| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341 | var fs = require('fs');var path = require('path');var applySourceMaps = require('./apply-source-maps');var extractImportUrlAndMedia = require('./extract-import-url-and-media');var isAllowedResource = require('./is-allowed-resource');var loadOriginalSources = require('./load-original-sources');var normalizePath = require('./normalize-path');var rebase = require('./rebase');var rebaseLocalMap = require('./rebase-local-map');var rebaseRemoteMap = require('./rebase-remote-map');var restoreImport = require('./restore-import');var tokenize = require('../tokenizer/tokenize');var Token = require('../tokenizer/token');var Marker = require('../tokenizer/marker');var hasProtocol = require('../utils/has-protocol');var isImport = require('../utils/is-import');var isRemoteResource = require('../utils/is-remote-resource');var UNKNOWN_URI = 'uri:unknown';function readSources(input, context, callback) {  return doReadSources(input, context, function (tokens) {    return applySourceMaps(tokens, context, function () {      return loadOriginalSources(context, function () { return callback(tokens); });    });  });}function doReadSources(input, context, callback) {  if (typeof input == 'string') {    return fromString(input, context, callback);  } else if (Buffer.isBuffer(input)) {    return fromString(input.toString(), context, callback);  } else if (Array.isArray(input)) {    return fromArray(input, context, callback);  } else if (typeof input == 'object') {    return fromHash(input, context, callback);  }}function fromString(input, context, callback) {  context.source = undefined;  context.sourcesContent[undefined] = input;  context.stats.originalSize += input.length;  return fromStyles(input, context, { inline: context.options.inline }, callback);}function fromArray(input, context, callback) {  var inputAsImports = input.reduce(function (accumulator, uriOrHash) {    if (typeof uriOrHash === 'string') {      return addStringSource(uriOrHash, accumulator);    } else {      return addHashSource(uriOrHash, context, accumulator);    }  }, []);  return fromStyles(inputAsImports.join(''), context, { inline: ['all'] }, callback);}function fromHash(input, context, callback) {  var inputAsImports = addHashSource(input, context, []);  return fromStyles(inputAsImports.join(''), context, { inline: ['all'] }, callback);}function addStringSource(input, imports) {  imports.push(restoreAsImport(normalizeUri(input)));  return imports;}function addHashSource(input, context, imports) {  var uri;  var normalizedUri;  var source;  for (uri in input) {    source = input[uri];    normalizedUri = normalizeUri(uri);    imports.push(restoreAsImport(normalizedUri));    context.sourcesContent[normalizedUri] = source.styles;    if (source.sourceMap) {      trackSourceMap(source.sourceMap, normalizedUri, context);    }  }  return imports;}function normalizeUri(uri) {  var currentPath = path.resolve('');  var absoluteUri;  var relativeToCurrentPath;  var normalizedUri;  if (isRemoteResource(uri)) {    return uri;  }  absoluteUri = path.isAbsolute(uri) ?    uri :    path.resolve(uri);  relativeToCurrentPath = path.relative(currentPath, absoluteUri);  normalizedUri = normalizePath(relativeToCurrentPath);  return normalizedUri;}function trackSourceMap(sourceMap, uri, context) {  var parsedMap = typeof sourceMap == 'string' ?      JSON.parse(sourceMap) :      sourceMap;  var rebasedMap = isRemoteResource(uri) ?    rebaseRemoteMap(parsedMap, uri) :    rebaseLocalMap(parsedMap, uri || UNKNOWN_URI, context.options.rebaseTo);  context.inputSourceMapTracker.track(uri, rebasedMap);}function restoreAsImport(uri) {  return restoreImport('url(' + uri + ')', '') + Marker.SEMICOLON;}function fromStyles(styles, context, parentInlinerContext, callback) {  var tokens;  var rebaseConfig = {};  if (!context.source) {    rebaseConfig.fromBase = path.resolve('');    rebaseConfig.toBase = context.options.rebaseTo;  } else if (isRemoteResource(context.source)) {    rebaseConfig.fromBase = context.source;    rebaseConfig.toBase = context.source;  } else if (path.isAbsolute(context.source)) {    rebaseConfig.fromBase = path.dirname(context.source);    rebaseConfig.toBase = context.options.rebaseTo;  } else {    rebaseConfig.fromBase = path.dirname(path.resolve(context.source));    rebaseConfig.toBase = context.options.rebaseTo;  }  tokens = tokenize(styles, context);  tokens = rebase(tokens, context.options.rebase, context.validator, rebaseConfig);  return allowsAnyImports(parentInlinerContext.inline) ?    inline(tokens, context, parentInlinerContext, callback) :    callback(tokens);}function allowsAnyImports(inline) {  return !(inline.length == 1 && inline[0] == 'none');}function inline(tokens, externalContext, parentInlinerContext, callback) {  var inlinerContext = {    afterContent: false,    callback: callback,    errors: externalContext.errors,    externalContext: externalContext,    fetch: externalContext.options.fetch,    inlinedStylesheets: parentInlinerContext.inlinedStylesheets || externalContext.inlinedStylesheets,    inline: parentInlinerContext.inline,    inlineRequest: externalContext.options.inlineRequest,    inlineTimeout: externalContext.options.inlineTimeout,    isRemote: parentInlinerContext.isRemote || false,    localOnly: externalContext.localOnly,    outputTokens: [],    rebaseTo: externalContext.options.rebaseTo,    sourceTokens: tokens,    warnings: externalContext.warnings  };  return doInlineImports(inlinerContext);}function doInlineImports(inlinerContext) {  var token;  var i, l;  for (i = 0, l = inlinerContext.sourceTokens.length; i < l; i++) {    token = inlinerContext.sourceTokens[i];    if (token[0] == Token.AT_RULE && isImport(token[1])) {      inlinerContext.sourceTokens.splice(0, i);      return inlineStylesheet(token, inlinerContext);    } else if (token[0] == Token.AT_RULE || token[0] == Token.COMMENT) {      inlinerContext.outputTokens.push(token);    } else {      inlinerContext.outputTokens.push(token);      inlinerContext.afterContent = true;    }  }  inlinerContext.sourceTokens = [];  return inlinerContext.callback(inlinerContext.outputTokens);}function inlineStylesheet(token, inlinerContext) {  var uriAndMediaQuery = extractImportUrlAndMedia(token[1]);  var uri = uriAndMediaQuery[0];  var mediaQuery = uriAndMediaQuery[1];  var metadata = token[2];  return isRemoteResource(uri) ?    inlineRemoteStylesheet(uri, mediaQuery, metadata, inlinerContext) :    inlineLocalStylesheet(uri, mediaQuery, metadata, inlinerContext);}function inlineRemoteStylesheet(uri, mediaQuery, metadata, inlinerContext) {  var isAllowed = isAllowedResource(uri, true, inlinerContext.inline);  var originalUri = uri;  var isLoaded = uri in inlinerContext.externalContext.sourcesContent;  var isRuntimeResource = !hasProtocol(uri);  if (inlinerContext.inlinedStylesheets.indexOf(uri) > -1) {    inlinerContext.warnings.push('Ignoring remote @import of "' + uri + '" as it has already been imported.');    inlinerContext.sourceTokens = inlinerContext.sourceTokens.slice(1);    return doInlineImports(inlinerContext);  } else if (inlinerContext.localOnly && inlinerContext.afterContent) {    inlinerContext.warnings.push('Ignoring remote @import of "' + uri + '" as no callback given and after other content.');    inlinerContext.sourceTokens = inlinerContext.sourceTokens.slice(1);    return doInlineImports(inlinerContext);  } else if (isRuntimeResource) {    inlinerContext.warnings.push('Skipping remote @import of "' + uri + '" as no protocol given.');    inlinerContext.outputTokens = inlinerContext.outputTokens.concat(inlinerContext.sourceTokens.slice(0, 1));    inlinerContext.sourceTokens = inlinerContext.sourceTokens.slice(1);    return doInlineImports(inlinerContext);  } else if (inlinerContext.localOnly && !isLoaded) {    inlinerContext.warnings.push('Skipping remote @import of "' + uri + '" as no callback given.');    inlinerContext.outputTokens = inlinerContext.outputTokens.concat(inlinerContext.sourceTokens.slice(0, 1));    inlinerContext.sourceTokens = inlinerContext.sourceTokens.slice(1);    return doInlineImports(inlinerContext);  } else if (!isAllowed && inlinerContext.afterContent) {    inlinerContext.warnings.push('Ignoring remote @import of "' + uri + '" as resource is not allowed and after other content.');    inlinerContext.sourceTokens = inlinerContext.sourceTokens.slice(1);    return doInlineImports(inlinerContext);  } else if (!isAllowed) {    inlinerContext.warnings.push('Skipping remote @import of "' + uri + '" as resource is not allowed.');    inlinerContext.outputTokens = inlinerContext.outputTokens.concat(inlinerContext.sourceTokens.slice(0, 1));    inlinerContext.sourceTokens = inlinerContext.sourceTokens.slice(1);    return doInlineImports(inlinerContext);  }  inlinerContext.inlinedStylesheets.push(uri);  function whenLoaded(error, importedStyles) {    if (error) {      inlinerContext.errors.push('Broken @import declaration of "' + uri + '" - ' + error);      return process.nextTick(function () {        inlinerContext.outputTokens = inlinerContext.outputTokens.concat(inlinerContext.sourceTokens.slice(0, 1));        inlinerContext.sourceTokens = inlinerContext.sourceTokens.slice(1);        doInlineImports(inlinerContext);      });    }    inlinerContext.inline = inlinerContext.externalContext.options.inline;    inlinerContext.isRemote = true;    inlinerContext.externalContext.source = originalUri;    inlinerContext.externalContext.sourcesContent[uri] = importedStyles;    inlinerContext.externalContext.stats.originalSize += importedStyles.length;    return fromStyles(importedStyles, inlinerContext.externalContext, inlinerContext, function (importedTokens) {      importedTokens = wrapInMedia(importedTokens, mediaQuery, metadata);      inlinerContext.outputTokens = inlinerContext.outputTokens.concat(importedTokens);      inlinerContext.sourceTokens = inlinerContext.sourceTokens.slice(1);      return doInlineImports(inlinerContext);    });  }  return isLoaded ?    whenLoaded(null, inlinerContext.externalContext.sourcesContent[uri]) :    inlinerContext.fetch(uri, inlinerContext.inlineRequest, inlinerContext.inlineTimeout, whenLoaded);}function inlineLocalStylesheet(uri, mediaQuery, metadata, inlinerContext) {  var currentPath = path.resolve('');  var absoluteUri = path.isAbsolute(uri) ?    path.resolve(currentPath, uri[0] == '/' ? uri.substring(1) : uri) :    path.resolve(inlinerContext.rebaseTo, uri);  var relativeToCurrentPath = path.relative(currentPath, absoluteUri);  var importedStyles;  var isAllowed = isAllowedResource(uri, false, inlinerContext.inline);  var normalizedPath = normalizePath(relativeToCurrentPath);  var isLoaded = normalizedPath in inlinerContext.externalContext.sourcesContent;  if (inlinerContext.inlinedStylesheets.indexOf(absoluteUri) > -1) {    inlinerContext.warnings.push('Ignoring local @import of "' + uri + '" as it has already been imported.');  } else if (!isLoaded && (!fs.existsSync(absoluteUri) || !fs.statSync(absoluteUri).isFile())) {    inlinerContext.errors.push('Ignoring local @import of "' + uri + '" as resource is missing.');  } else if (!isAllowed && inlinerContext.afterContent) {    inlinerContext.warnings.push('Ignoring local @import of "' + uri + '" as resource is not allowed and after other content.');  } else if (inlinerContext.afterContent) {    inlinerContext.warnings.push('Ignoring local @import of "' + uri + '" as after other content.');  } else if (!isAllowed) {    inlinerContext.warnings.push('Skipping local @import of "' + uri + '" as resource is not allowed.');    inlinerContext.outputTokens = inlinerContext.outputTokens.concat(inlinerContext.sourceTokens.slice(0, 1));  } else {    importedStyles = isLoaded ?      inlinerContext.externalContext.sourcesContent[normalizedPath] :      fs.readFileSync(absoluteUri, 'utf-8');    inlinerContext.inlinedStylesheets.push(absoluteUri);    inlinerContext.inline = inlinerContext.externalContext.options.inline;    inlinerContext.externalContext.source = normalizedPath;    inlinerContext.externalContext.sourcesContent[normalizedPath] = importedStyles;    inlinerContext.externalContext.stats.originalSize += importedStyles.length;    return fromStyles(importedStyles, inlinerContext.externalContext, inlinerContext, function (importedTokens) {      importedTokens = wrapInMedia(importedTokens, mediaQuery, metadata);      inlinerContext.outputTokens = inlinerContext.outputTokens.concat(importedTokens);      inlinerContext.sourceTokens = inlinerContext.sourceTokens.slice(1);      return doInlineImports(inlinerContext);    });  }  inlinerContext.sourceTokens = inlinerContext.sourceTokens.slice(1);  return doInlineImports(inlinerContext);}function wrapInMedia(tokens, mediaQuery, metadata) {  if (mediaQuery) {    return [[Token.NESTED_BLOCK, [[Token.NESTED_BLOCK_SCOPE, '@media ' + mediaQuery, metadata]], tokens]];  } else {    return tokens;  }}module.exports = readSources;
 |