Add rollup-plugin-minify-html-template-literals to node_modules

R=jacktfranklin@chromium.org

Bug: 1213034
Change-Id: I5da8225f60b53870a1c67d6b5d02a464c08f4eb2
Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/2917088
Commit-Queue: Tim van der Lippe <tvanderlippe@chromium.org>
Reviewed-by: Jack Franklin <jacktfranklin@chromium.org>
diff --git a/node_modules/clean-css/lib/reader/apply-source-maps.js b/node_modules/clean-css/lib/reader/apply-source-maps.js
new file mode 100644
index 0000000..7c5a928
--- /dev/null
+++ b/node_modules/clean-css/lib/reader/apply-source-maps.js
@@ -0,0 +1,245 @@
+var fs = require('fs');
+var path = require('path');
+
+var isAllowedResource = require('./is-allowed-resource');
+var matchDataUri = require('./match-data-uri');
+var rebaseLocalMap = require('./rebase-local-map');
+var rebaseRemoteMap = require('./rebase-remote-map');
+
+var Token = require('../tokenizer/token');
+var hasProtocol = require('../utils/has-protocol');
+var isDataUriResource = require('../utils/is-data-uri-resource');
+var isRemoteResource = require('../utils/is-remote-resource');
+
+var MAP_MARKER_PATTERN = /^\/\*# sourceMappingURL=(\S+) \*\/$/;
+
+function applySourceMaps(tokens, context, callback) {
+  var applyContext = {
+    callback: callback,
+    fetch: context.options.fetch,
+    index: 0,
+    inline: context.options.inline,
+    inlineRequest: context.options.inlineRequest,
+    inlineTimeout: context.options.inlineTimeout,
+    inputSourceMapTracker: context.inputSourceMapTracker,
+    localOnly: context.localOnly,
+    processedTokens: [],
+    rebaseTo: context.options.rebaseTo,
+    sourceTokens: tokens,
+    warnings: context.warnings
+  };
+
+  return context.options.sourceMap && tokens.length > 0 ?
+    doApplySourceMaps(applyContext) :
+    callback(tokens);
+}
+
+function doApplySourceMaps(applyContext) {
+  var singleSourceTokens = [];
+  var lastSource = findTokenSource(applyContext.sourceTokens[0]);
+  var source;
+  var token;
+  var l;
+
+  for (l = applyContext.sourceTokens.length; applyContext.index < l; applyContext.index++) {
+    token = applyContext.sourceTokens[applyContext.index];
+    source = findTokenSource(token);
+
+    if (source != lastSource) {
+      singleSourceTokens = [];
+      lastSource = source;
+    }
+
+    singleSourceTokens.push(token);
+    applyContext.processedTokens.push(token);
+
+    if (token[0] == Token.COMMENT && MAP_MARKER_PATTERN.test(token[1])) {
+      return fetchAndApplySourceMap(token[1], source, singleSourceTokens, applyContext);
+    }
+  }
+
+  return applyContext.callback(applyContext.processedTokens);
+}
+
+function findTokenSource(token) {
+  var scope;
+  var metadata;
+
+  if (token[0] == Token.AT_RULE || token[0] == Token.COMMENT) {
+    metadata = token[2][0];
+  } else {
+    scope = token[1][0];
+    metadata = scope[2][0];
+  }
+
+  return metadata[2];
+}
+
+function fetchAndApplySourceMap(sourceMapComment, source, singleSourceTokens, applyContext) {
+  return extractInputSourceMapFrom(sourceMapComment, applyContext, function (inputSourceMap) {
+    if (inputSourceMap) {
+      applyContext.inputSourceMapTracker.track(source, inputSourceMap);
+      applySourceMapRecursively(singleSourceTokens, applyContext.inputSourceMapTracker);
+    }
+
+    applyContext.index++;
+    return doApplySourceMaps(applyContext);
+  });
+}
+
+function extractInputSourceMapFrom(sourceMapComment, applyContext, whenSourceMapReady) {
+  var uri = MAP_MARKER_PATTERN.exec(sourceMapComment)[1];
+  var absoluteUri;
+  var sourceMap;
+  var rebasedMap;
+
+  if (isDataUriResource(uri)) {
+    sourceMap = extractInputSourceMapFromDataUri(uri);
+    return whenSourceMapReady(sourceMap);
+  } else if (isRemoteResource(uri)) {
+    return loadInputSourceMapFromRemoteUri(uri, applyContext, function (sourceMap) {
+      var parsedMap;
+
+      if (sourceMap) {
+        parsedMap = JSON.parse(sourceMap);
+        rebasedMap = rebaseRemoteMap(parsedMap, uri);
+        whenSourceMapReady(rebasedMap);
+      } else {
+        whenSourceMapReady(null);
+      }
+    });
+  } else {
+    // at this point `uri` is already rebased, see lib/reader/rebase.js#rebaseSourceMapComment
+    // it is rebased to be consistent with rebasing other URIs
+    // however here we need to resolve it back to read it from disk
+    absoluteUri = path.resolve(applyContext.rebaseTo, uri);
+    sourceMap = loadInputSourceMapFromLocalUri(absoluteUri, applyContext);
+
+    if (sourceMap) {
+      rebasedMap = rebaseLocalMap(sourceMap, absoluteUri, applyContext.rebaseTo);
+      return whenSourceMapReady(rebasedMap);
+    } else {
+      return whenSourceMapReady(null);
+    }
+  }
+}
+
+function extractInputSourceMapFromDataUri(uri) {
+  var dataUriMatch = matchDataUri(uri);
+  var charset = dataUriMatch[2] ? dataUriMatch[2].split(/[=;]/)[2] : 'us-ascii';
+  var encoding = dataUriMatch[3] ? dataUriMatch[3].split(';')[1] : 'utf8';
+  var data = encoding == 'utf8' ? global.unescape(dataUriMatch[4]) : dataUriMatch[4];
+
+  var buffer = new Buffer(data, encoding);
+  buffer.charset = charset;
+
+  return JSON.parse(buffer.toString());
+}
+
+function loadInputSourceMapFromRemoteUri(uri, applyContext, whenLoaded) {
+  var isAllowed = isAllowedResource(uri, true, applyContext.inline);
+  var isRuntimeResource = !hasProtocol(uri);
+
+  if (applyContext.localOnly) {
+    applyContext.warnings.push('Cannot fetch remote resource from "' + uri + '" as no callback given.');
+    return whenLoaded(null);
+  } else if (isRuntimeResource) {
+    applyContext.warnings.push('Cannot fetch "' + uri + '" as no protocol given.');
+    return whenLoaded(null);
+  } else if (!isAllowed) {
+    applyContext.warnings.push('Cannot fetch "' + uri + '" as resource is not allowed.');
+    return whenLoaded(null);
+  }
+
+  applyContext.fetch(uri, applyContext.inlineRequest, applyContext.inlineTimeout, function (error, body) {
+    if (error) {
+      applyContext.warnings.push('Missing source map at "' + uri + '" - ' + error);
+      return whenLoaded(null);
+    }
+
+    whenLoaded(body);
+  });
+}
+
+function loadInputSourceMapFromLocalUri(uri, applyContext) {
+  var isAllowed = isAllowedResource(uri, false, applyContext.inline);
+  var sourceMap;
+
+  if (!fs.existsSync(uri) || !fs.statSync(uri).isFile()) {
+    applyContext.warnings.push('Ignoring local source map at "' + uri + '" as resource is missing.');
+    return null;
+  } else if (!isAllowed) {
+    applyContext.warnings.push('Cannot fetch "' + uri + '" as resource is not allowed.');
+    return null;
+  }
+
+  sourceMap = fs.readFileSync(uri, 'utf-8');
+  return JSON.parse(sourceMap);
+}
+
+function applySourceMapRecursively(tokens, inputSourceMapTracker) {
+  var token;
+  var i, l;
+
+  for (i = 0, l = tokens.length; i < l; i++) {
+    token = tokens[i];
+
+    switch (token[0]) {
+      case Token.AT_RULE:
+        applySourceMapTo(token, inputSourceMapTracker);
+        break;
+      case Token.AT_RULE_BLOCK:
+        applySourceMapRecursively(token[1], inputSourceMapTracker);
+        applySourceMapRecursively(token[2], inputSourceMapTracker);
+        break;
+      case Token.AT_RULE_BLOCK_SCOPE:
+        applySourceMapTo(token, inputSourceMapTracker);
+        break;
+      case Token.NESTED_BLOCK:
+        applySourceMapRecursively(token[1], inputSourceMapTracker);
+        applySourceMapRecursively(token[2], inputSourceMapTracker);
+        break;
+      case Token.NESTED_BLOCK_SCOPE:
+        applySourceMapTo(token, inputSourceMapTracker);
+        break;
+      case Token.COMMENT:
+        applySourceMapTo(token, inputSourceMapTracker);
+        break;
+      case Token.PROPERTY:
+        applySourceMapRecursively(token, inputSourceMapTracker);
+        break;
+      case Token.PROPERTY_BLOCK:
+        applySourceMapRecursively(token[1], inputSourceMapTracker);
+        break;
+      case Token.PROPERTY_NAME:
+        applySourceMapTo(token, inputSourceMapTracker);
+        break;
+      case Token.PROPERTY_VALUE:
+        applySourceMapTo(token, inputSourceMapTracker);
+        break;
+      case Token.RULE:
+        applySourceMapRecursively(token[1], inputSourceMapTracker);
+        applySourceMapRecursively(token[2], inputSourceMapTracker);
+        break;
+      case Token.RULE_SCOPE:
+        applySourceMapTo(token, inputSourceMapTracker);
+    }
+  }
+
+  return tokens;
+}
+
+function applySourceMapTo(token, inputSourceMapTracker) {
+  var value = token[1];
+  var metadata = token[2];
+  var newMetadata = [];
+  var i, l;
+
+  for (i = 0, l = metadata.length; i < l; i++) {
+    newMetadata.push(inputSourceMapTracker.originalPositionFor(metadata[i], value.length));
+  }
+
+  token[2] = newMetadata;
+}
+
+module.exports = applySourceMaps;
diff --git a/node_modules/clean-css/lib/reader/extract-import-url-and-media.js b/node_modules/clean-css/lib/reader/extract-import-url-and-media.js
new file mode 100644
index 0000000..e309c2f
--- /dev/null
+++ b/node_modules/clean-css/lib/reader/extract-import-url-and-media.js
@@ -0,0 +1,35 @@
+var split = require('../utils/split');
+
+var BRACE_PREFIX = /^\(/;
+var BRACE_SUFFIX = /\)$/;
+var IMPORT_PREFIX_PATTERN = /^@import/i;
+var QUOTE_PREFIX_PATTERN = /['"]\s*/;
+var QUOTE_SUFFIX_PATTERN = /\s*['"]/;
+var URL_PREFIX_PATTERN = /^url\(\s*/i;
+var URL_SUFFIX_PATTERN = /\s*\)/i;
+
+function extractImportUrlAndMedia(atRuleValue) {
+  var uri;
+  var mediaQuery;
+  var stripped;
+  var parts;
+
+  stripped = atRuleValue
+    .replace(IMPORT_PREFIX_PATTERN, '')
+    .trim()
+    .replace(URL_PREFIX_PATTERN, '(')
+    .replace(URL_SUFFIX_PATTERN, ')')
+    .replace(QUOTE_PREFIX_PATTERN, '')
+    .replace(QUOTE_SUFFIX_PATTERN, '');
+
+  parts = split(stripped, ' ');
+
+  uri = parts[0]
+    .replace(BRACE_PREFIX, '')
+    .replace(BRACE_SUFFIX, '');
+  mediaQuery = parts.slice(1).join(' ');
+
+  return [uri, mediaQuery];
+}
+
+module.exports = extractImportUrlAndMedia;
diff --git a/node_modules/clean-css/lib/reader/input-source-map-tracker.js b/node_modules/clean-css/lib/reader/input-source-map-tracker.js
new file mode 100644
index 0000000..4b8730c
--- /dev/null
+++ b/node_modules/clean-css/lib/reader/input-source-map-tracker.js
@@ -0,0 +1,58 @@
+var SourceMapConsumer = require('source-map').SourceMapConsumer;
+
+function inputSourceMapTracker() {
+  var maps = {};
+
+  return {
+    all: all.bind(null, maps),
+    isTracking: isTracking.bind(null, maps),
+    originalPositionFor: originalPositionFor.bind(null, maps),
+    track: track.bind(null, maps)
+  };
+}
+
+function all(maps) {
+  return maps;
+}
+
+function isTracking(maps, source) {
+  return source in maps;
+}
+
+function originalPositionFor(maps, metadata, range, selectorFallbacks) {
+  var line = metadata[0];
+  var column = metadata[1];
+  var source = metadata[2];
+  var position = {
+    line: line,
+    column: column + range
+  };
+  var originalPosition;
+
+  while (!originalPosition && position.column > column) {
+    position.column--;
+    originalPosition = maps[source].originalPositionFor(position);
+  }
+
+  if (!originalPosition || originalPosition.column < 0) {
+    return metadata;
+  }
+
+  if (originalPosition.line === null && line > 1 && selectorFallbacks > 0) {
+    return originalPositionFor(maps, [line - 1, column, source], range, selectorFallbacks - 1);
+  }
+
+  return originalPosition.line !== null ?
+    toMetadata(originalPosition) :
+    metadata;
+}
+
+function toMetadata(asHash) {
+  return [asHash.line, asHash.column, asHash.source];
+}
+
+function track(maps, source, data) {
+  maps[source] = new SourceMapConsumer(data);
+}
+
+module.exports = inputSourceMapTracker;
diff --git a/node_modules/clean-css/lib/reader/is-allowed-resource.js b/node_modules/clean-css/lib/reader/is-allowed-resource.js
new file mode 100644
index 0000000..043066e
--- /dev/null
+++ b/node_modules/clean-css/lib/reader/is-allowed-resource.js
@@ -0,0 +1,77 @@
+var path = require('path');
+var url = require('url');
+
+var isRemoteResource = require('../utils/is-remote-resource');
+var hasProtocol = require('../utils/has-protocol');
+
+var HTTP_PROTOCOL = 'http:';
+
+function isAllowedResource(uri, isRemote, rules) {
+  var match;
+  var absoluteUri;
+  var allowed = isRemote ? false : true;
+  var rule;
+  var isNegated;
+  var normalizedRule;
+  var i;
+
+  if (rules.length === 0) {
+    return false;
+  }
+
+  if (isRemote && !hasProtocol(uri)) {
+    uri = HTTP_PROTOCOL + uri;
+  }
+
+  match = isRemote ?
+    url.parse(uri).host :
+    uri;
+
+  absoluteUri = isRemote ?
+    uri :
+    path.resolve(uri);
+
+  for (i = 0; i < rules.length; i++) {
+    rule = rules[i];
+    isNegated = rule[0] == '!';
+    normalizedRule = rule.substring(1);
+
+    if (isNegated && isRemote && isRemoteRule(normalizedRule)) {
+      allowed = allowed && !isAllowedResource(uri, true, [normalizedRule]);
+    } else if (isNegated && !isRemote && !isRemoteRule(normalizedRule)) {
+      allowed = allowed && !isAllowedResource(uri, false, [normalizedRule]);
+    } else if (isNegated) {
+      allowed = allowed && true;
+    } else if (rule == 'all') {
+      allowed = true;
+    } else if (isRemote && rule == 'local') {
+      allowed = allowed || false;
+    } else if (isRemote && rule == 'remote') {
+      allowed = true;
+    } else if (!isRemote && rule == 'remote') {
+      allowed = false;
+    } else if (!isRemote && rule == 'local') {
+      allowed = true;
+    } else if (rule === match) {
+      allowed = true;
+    } else if (rule === uri) {
+      allowed = true;
+    } else if (isRemote && absoluteUri.indexOf(rule) === 0) {
+      allowed = true;
+    } else if (!isRemote && absoluteUri.indexOf(path.resolve(rule)) === 0) {
+      allowed = true;
+    } else if (isRemote != isRemoteRule(normalizedRule)) {
+      allowed = allowed && true;
+    } else {
+      allowed = false;
+    }
+  }
+
+  return allowed;
+}
+
+function isRemoteRule(rule) {
+  return isRemoteResource(rule) || url.parse(HTTP_PROTOCOL + '//' + rule).host == rule;
+}
+
+module.exports = isAllowedResource;
diff --git a/node_modules/clean-css/lib/reader/load-original-sources.js b/node_modules/clean-css/lib/reader/load-original-sources.js
new file mode 100644
index 0000000..465035d
--- /dev/null
+++ b/node_modules/clean-css/lib/reader/load-original-sources.js
@@ -0,0 +1,126 @@
+var fs = require('fs');
+var path = require('path');
+
+var isAllowedResource = require('./is-allowed-resource');
+
+var hasProtocol = require('../utils/has-protocol');
+var isRemoteResource = require('../utils/is-remote-resource');
+
+function loadOriginalSources(context, callback) {
+  var loadContext = {
+    callback: callback,
+    fetch: context.options.fetch,
+    index: 0,
+    inline: context.options.inline,
+    inlineRequest: context.options.inlineRequest,
+    inlineTimeout: context.options.inlineTimeout,
+    localOnly: context.localOnly,
+    rebaseTo: context.options.rebaseTo,
+    sourcesContent: context.sourcesContent,
+    uriToSource: uriToSourceMapping(context.inputSourceMapTracker.all()),
+    warnings: context.warnings
+  };
+
+  return context.options.sourceMap && context.options.sourceMapInlineSources ?
+    doLoadOriginalSources(loadContext) :
+    callback();
+}
+
+function uriToSourceMapping(allSourceMapConsumers) {
+  var mapping = {};
+  var consumer;
+  var uri;
+  var source;
+  var i, l;
+
+  for (source in allSourceMapConsumers) {
+    consumer = allSourceMapConsumers[source];
+
+    for (i = 0, l = consumer.sources.length; i < l; i++) {
+      uri = consumer.sources[i];
+      source = consumer.sourceContentFor(uri, true);
+
+      mapping[uri] = source;
+    }
+  }
+
+  return mapping;
+}
+
+function doLoadOriginalSources(loadContext) {
+  var uris = Object.keys(loadContext.uriToSource);
+  var uri;
+  var source;
+  var total;
+
+  for (total = uris.length; loadContext.index < total; loadContext.index++) {
+    uri = uris[loadContext.index];
+    source = loadContext.uriToSource[uri];
+
+    if (source) {
+      loadContext.sourcesContent[uri] = source;
+    } else {
+      return loadOriginalSource(uri, loadContext);
+    }
+  }
+
+  return loadContext.callback();
+}
+
+function loadOriginalSource(uri, loadContext) {
+  var content;
+
+  if (isRemoteResource(uri)) {
+    return loadOriginalSourceFromRemoteUri(uri, loadContext, function (content) {
+      loadContext.index++;
+      loadContext.sourcesContent[uri] = content;
+      return doLoadOriginalSources(loadContext);
+    });
+  } else {
+    content = loadOriginalSourceFromLocalUri(uri, loadContext);
+    loadContext.index++;
+    loadContext.sourcesContent[uri] = content;
+    return doLoadOriginalSources(loadContext);
+  }
+}
+
+function loadOriginalSourceFromRemoteUri(uri, loadContext, whenLoaded) {
+  var isAllowed = isAllowedResource(uri, true, loadContext.inline);
+  var isRuntimeResource = !hasProtocol(uri);
+
+  if (loadContext.localOnly) {
+    loadContext.warnings.push('Cannot fetch remote resource from "' + uri + '" as no callback given.');
+    return whenLoaded(null);
+  } else if (isRuntimeResource) {
+    loadContext.warnings.push('Cannot fetch "' + uri + '" as no protocol given.');
+    return whenLoaded(null);
+  } else if (!isAllowed) {
+    loadContext.warnings.push('Cannot fetch "' + uri + '" as resource is not allowed.');
+    return whenLoaded(null);
+  }
+
+  loadContext.fetch(uri, loadContext.inlineRequest, loadContext.inlineTimeout, function (error, content) {
+    if (error) {
+      loadContext.warnings.push('Missing original source at "' + uri + '" - ' + error);
+    }
+
+    whenLoaded(content);
+  });
+}
+
+function loadOriginalSourceFromLocalUri(relativeUri, loadContext) {
+  var isAllowed = isAllowedResource(relativeUri, false, loadContext.inline);
+  var absoluteUri = path.resolve(loadContext.rebaseTo, relativeUri);
+
+  if (!fs.existsSync(absoluteUri) || !fs.statSync(absoluteUri).isFile()) {
+    loadContext.warnings.push('Ignoring local source map at "' + absoluteUri + '" as resource is missing.');
+    return null;
+  } else if (!isAllowed) {
+    loadContext.warnings.push('Cannot fetch "' + absoluteUri + '" as resource is not allowed.');
+    return null;
+  }
+
+  return fs.readFileSync(absoluteUri, 'utf8');
+}
+
+module.exports = loadOriginalSources;
diff --git a/node_modules/clean-css/lib/reader/load-remote-resource.js b/node_modules/clean-css/lib/reader/load-remote-resource.js
new file mode 100644
index 0000000..0133c78
--- /dev/null
+++ b/node_modules/clean-css/lib/reader/load-remote-resource.js
@@ -0,0 +1,74 @@
+var http = require('http');
+var https = require('https');
+var url = require('url');
+
+var isHttpResource = require('../utils/is-http-resource');
+var isHttpsResource = require('../utils/is-https-resource');
+var override = require('../utils/override');
+
+var HTTP_PROTOCOL = 'http:';
+
+function loadRemoteResource(uri, inlineRequest, inlineTimeout, callback) {
+  var proxyProtocol = inlineRequest.protocol || inlineRequest.hostname;
+  var errorHandled = false;
+  var requestOptions;
+  var fetch;
+
+  requestOptions = override(
+    url.parse(uri),
+    inlineRequest || {}
+  );
+
+  if (inlineRequest.hostname !== undefined) {
+    // overwrite as we always expect a http proxy currently
+    requestOptions.protocol = inlineRequest.protocol || HTTP_PROTOCOL;
+    requestOptions.path = requestOptions.href;
+  }
+
+  fetch = (proxyProtocol && !isHttpsResource(proxyProtocol)) || isHttpResource(uri) ?
+    http.get :
+    https.get;
+
+  fetch(requestOptions, function (res) {
+    var chunks = [];
+    var movedUri;
+
+    if (errorHandled) {
+      return;
+    }
+
+    if (res.statusCode < 200 || res.statusCode > 399) {
+      return callback(res.statusCode, null);
+    } else if (res.statusCode > 299) {
+      movedUri = url.resolve(uri, res.headers.location);
+      return loadRemoteResource(movedUri, inlineRequest, inlineTimeout, callback);
+    }
+
+    res.on('data', function (chunk) {
+      chunks.push(chunk.toString());
+    });
+    res.on('end', function () {
+      var body = chunks.join('');
+      callback(null, body);
+    });
+  })
+  .on('error', function (res) {
+    if (errorHandled) {
+      return;
+    }
+
+    errorHandled = true;
+    callback(res.message, null);
+  })
+  .on('timeout', function () {
+    if (errorHandled) {
+      return;
+    }
+
+    errorHandled = true;
+    callback('timeout', null);
+  })
+  .setTimeout(inlineTimeout);
+}
+
+module.exports = loadRemoteResource;
diff --git a/node_modules/clean-css/lib/reader/match-data-uri.js b/node_modules/clean-css/lib/reader/match-data-uri.js
new file mode 100644
index 0000000..d0d5a4c
--- /dev/null
+++ b/node_modules/clean-css/lib/reader/match-data-uri.js
@@ -0,0 +1,7 @@
+var DATA_URI_PATTERN = /^data:(\S*?)?(;charset=[^;]+)?(;[^,]+?)?,(.+)/;
+
+function matchDataUri(uri) {
+  return DATA_URI_PATTERN.exec(uri);
+}
+
+module.exports = matchDataUri;
diff --git a/node_modules/clean-css/lib/reader/normalize-path.js b/node_modules/clean-css/lib/reader/normalize-path.js
new file mode 100644
index 0000000..a9eca38
--- /dev/null
+++ b/node_modules/clean-css/lib/reader/normalize-path.js
@@ -0,0 +1,8 @@
+var UNIX_SEPARATOR = '/';
+var WINDOWS_SEPARATOR_PATTERN = /\\/g;
+
+function normalizePath(path) {
+  return path.replace(WINDOWS_SEPARATOR_PATTERN, UNIX_SEPARATOR);
+}
+
+module.exports = normalizePath;
diff --git a/node_modules/clean-css/lib/reader/read-sources.js b/node_modules/clean-css/lib/reader/read-sources.js
new file mode 100644
index 0000000..1338f6a
--- /dev/null
+++ b/node_modules/clean-css/lib/reader/read-sources.js
@@ -0,0 +1,341 @@
+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;
diff --git a/node_modules/clean-css/lib/reader/rebase-local-map.js b/node_modules/clean-css/lib/reader/rebase-local-map.js
new file mode 100644
index 0000000..aec8d23
--- /dev/null
+++ b/node_modules/clean-css/lib/reader/rebase-local-map.js
@@ -0,0 +1,15 @@
+var path = require('path');
+
+function rebaseLocalMap(sourceMap, sourceUri, rebaseTo) {
+  var currentPath = path.resolve('');
+  var absoluteUri = path.resolve(currentPath, sourceUri);
+  var absoluteUriDirectory = path.dirname(absoluteUri);
+
+  sourceMap.sources = sourceMap.sources.map(function(source) {
+    return path.relative(rebaseTo, path.resolve(absoluteUriDirectory, source));
+  });
+
+  return sourceMap;
+}
+
+module.exports = rebaseLocalMap;
diff --git a/node_modules/clean-css/lib/reader/rebase-remote-map.js b/node_modules/clean-css/lib/reader/rebase-remote-map.js
new file mode 100644
index 0000000..7b6bb7a
--- /dev/null
+++ b/node_modules/clean-css/lib/reader/rebase-remote-map.js
@@ -0,0 +1,14 @@
+var path = require('path');
+var url = require('url');
+
+function rebaseRemoteMap(sourceMap, sourceUri) {
+  var sourceDirectory = path.dirname(sourceUri);
+
+  sourceMap.sources = sourceMap.sources.map(function(source) {
+    return url.resolve(sourceDirectory, source);
+  });
+
+  return sourceMap;
+}
+
+module.exports = rebaseRemoteMap;
diff --git a/node_modules/clean-css/lib/reader/rebase.js b/node_modules/clean-css/lib/reader/rebase.js
new file mode 100644
index 0000000..181b319
--- /dev/null
+++ b/node_modules/clean-css/lib/reader/rebase.js
@@ -0,0 +1,101 @@
+var extractImportUrlAndMedia = require('./extract-import-url-and-media');
+var restoreImport = require('./restore-import');
+var rewriteUrl = require('./rewrite-url');
+
+var Token = require('../tokenizer/token');
+var isImport = require('../utils/is-import');
+
+var SOURCE_MAP_COMMENT_PATTERN = /^\/\*# sourceMappingURL=(\S+) \*\/$/;
+
+function rebase(tokens, rebaseAll, validator, rebaseConfig) {
+  return rebaseAll ?
+    rebaseEverything(tokens, validator, rebaseConfig) :
+    rebaseAtRules(tokens, validator, rebaseConfig);
+}
+
+function rebaseEverything(tokens, validator, rebaseConfig) {
+  var token;
+  var i, l;
+
+  for (i = 0, l = tokens.length; i < l; i++) {
+    token = tokens[i];
+
+    switch (token[0]) {
+      case Token.AT_RULE:
+        rebaseAtRule(token, validator, rebaseConfig);
+        break;
+      case Token.AT_RULE_BLOCK:
+        rebaseProperties(token[2], validator, rebaseConfig);
+        break;
+      case Token.COMMENT:
+        rebaseSourceMapComment(token, rebaseConfig);
+        break;
+      case Token.NESTED_BLOCK:
+        rebaseEverything(token[2], validator, rebaseConfig);
+        break;
+      case Token.RULE:
+        rebaseProperties(token[2], validator, rebaseConfig);
+        break;
+    }
+  }
+
+  return tokens;
+}
+
+function rebaseAtRules(tokens, validator, rebaseConfig) {
+  var token;
+  var i, l;
+
+  for (i = 0, l = tokens.length; i < l; i++) {
+    token = tokens[i];
+
+    switch (token[0]) {
+      case Token.AT_RULE:
+        rebaseAtRule(token, validator, rebaseConfig);
+        break;
+    }
+  }
+
+  return tokens;
+}
+
+function rebaseAtRule(token, validator, rebaseConfig) {
+  if (!isImport(token[1])) {
+    return;
+  }
+
+  var uriAndMediaQuery = extractImportUrlAndMedia(token[1]);
+  var newUrl = rewriteUrl(uriAndMediaQuery[0], rebaseConfig);
+  var mediaQuery = uriAndMediaQuery[1];
+
+  token[1] = restoreImport(newUrl, mediaQuery);
+}
+
+function rebaseSourceMapComment(token, rebaseConfig) {
+  var matches = SOURCE_MAP_COMMENT_PATTERN.exec(token[1]);
+
+  if (matches && matches[1].indexOf('data:') === -1) {
+    token[1] = token[1].replace(matches[1], rewriteUrl(matches[1], rebaseConfig, true));
+  }
+}
+
+function rebaseProperties(properties, validator, rebaseConfig) {
+  var property;
+  var value;
+  var i, l;
+  var j, m;
+
+  for (i = 0, l = properties.length; i < l; i++) {
+    property = properties[i];
+
+    for (j = 2 /* 0 is Token.PROPERTY, 1 is name */, m = property.length; j < m; j++) {
+      value = property[j][1];
+
+      if (validator.isUrl(value)) {
+        property[j][1] = rewriteUrl(value, rebaseConfig);
+      }
+    }
+  }
+}
+
+module.exports = rebase;
diff --git a/node_modules/clean-css/lib/reader/restore-import.js b/node_modules/clean-css/lib/reader/restore-import.js
new file mode 100644
index 0000000..5bdbd92
--- /dev/null
+++ b/node_modules/clean-css/lib/reader/restore-import.js
@@ -0,0 +1,5 @@
+function restoreImport(uri, mediaQuery) {
+  return ('@import ' + uri + ' ' + mediaQuery).trim();
+}
+
+module.exports = restoreImport;
diff --git a/node_modules/clean-css/lib/reader/rewrite-url.js b/node_modules/clean-css/lib/reader/rewrite-url.js
new file mode 100644
index 0000000..a4793fd
--- /dev/null
+++ b/node_modules/clean-css/lib/reader/rewrite-url.js
@@ -0,0 +1,118 @@
+var path = require('path');
+var url = require('url');
+
+var DOUBLE_QUOTE = '"';
+var SINGLE_QUOTE = '\'';
+var URL_PREFIX = 'url(';
+var URL_SUFFIX = ')';
+
+var QUOTE_PREFIX_PATTERN = /^["']/;
+var QUOTE_SUFFIX_PATTERN = /["']$/;
+var ROUND_BRACKETS_PATTERN = /[\(\)]/;
+var URL_PREFIX_PATTERN = /^url\(/i;
+var URL_SUFFIX_PATTERN = /\)$/;
+var WHITESPACE_PATTERN = /\s/;
+
+var isWindows = process.platform == 'win32';
+
+function rebase(uri, rebaseConfig) {
+  if (!rebaseConfig) {
+    return uri;
+  }
+
+  if (isAbsolute(uri) && !isRemote(rebaseConfig.toBase)) {
+    return uri;
+  }
+
+  if (isRemote(uri) || isSVGMarker(uri) || isInternal(uri)) {
+    return uri;
+  }
+
+  if (isData(uri)) {
+    return '\'' + uri + '\'';
+  }
+
+  if (isRemote(rebaseConfig.toBase)) {
+    return url.resolve(rebaseConfig.toBase, uri);
+  }
+
+  return rebaseConfig.absolute ?
+    normalize(absolute(uri, rebaseConfig)) :
+    normalize(relative(uri, rebaseConfig));
+}
+
+function isAbsolute(uri) {
+  return path.isAbsolute(uri);
+}
+
+function isSVGMarker(uri) {
+  return uri[0] == '#';
+}
+
+function isInternal(uri) {
+  return /^\w+:\w+/.test(uri);
+}
+
+function isRemote(uri) {
+  return /^[^:]+?:\/\//.test(uri) || uri.indexOf('//') === 0;
+}
+
+function isData(uri) {
+  return uri.indexOf('data:') === 0;
+}
+
+function absolute(uri, rebaseConfig) {
+  return path
+    .resolve(path.join(rebaseConfig.fromBase || '', uri))
+    .replace(rebaseConfig.toBase, '');
+}
+
+function relative(uri, rebaseConfig) {
+  return path.relative(rebaseConfig.toBase, path.join(rebaseConfig.fromBase || '', uri));
+}
+
+function normalize(uri) {
+  return isWindows ? uri.replace(/\\/g, '/') : uri;
+}
+
+function quoteFor(unquotedUrl) {
+  if (unquotedUrl.indexOf(SINGLE_QUOTE) > -1) {
+    return DOUBLE_QUOTE;
+  } else if (unquotedUrl.indexOf(DOUBLE_QUOTE) > -1) {
+    return SINGLE_QUOTE;
+  } else if (hasWhitespace(unquotedUrl) || hasRoundBrackets(unquotedUrl)) {
+    return SINGLE_QUOTE;
+  } else {
+    return '';
+  }
+}
+
+function hasWhitespace(url) {
+  return WHITESPACE_PATTERN.test(url);
+}
+
+function hasRoundBrackets(url) {
+  return ROUND_BRACKETS_PATTERN.test(url);
+}
+
+function rewriteUrl(originalUrl, rebaseConfig, pathOnly) {
+  var strippedUrl = originalUrl
+    .replace(URL_PREFIX_PATTERN, '')
+    .replace(URL_SUFFIX_PATTERN, '')
+    .trim();
+
+  var unquotedUrl = strippedUrl
+    .replace(QUOTE_PREFIX_PATTERN, '')
+    .replace(QUOTE_SUFFIX_PATTERN, '')
+    .trim();
+
+  var quote = strippedUrl[0] == SINGLE_QUOTE || strippedUrl[0] == DOUBLE_QUOTE ?
+    strippedUrl[0] :
+    quoteFor(unquotedUrl);
+
+  return pathOnly ?
+    rebase(unquotedUrl, rebaseConfig) :
+    URL_PREFIX + quote + rebase(unquotedUrl, rebaseConfig) + quote + URL_SUFFIX;
+}
+
+module.exports = rewriteUrl;