198 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			198 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
"use strict";
 | 
						|
 | 
						|
Object.defineProperty(exports, "__esModule", {
 | 
						|
  value: true
 | 
						|
});
 | 
						|
exports.default = loader;
 | 
						|
 | 
						|
var _path = _interopRequireDefault(require("path"));
 | 
						|
 | 
						|
var _semver = require("semver");
 | 
						|
 | 
						|
var _package = _interopRequireDefault(require("postcss/package.json"));
 | 
						|
 | 
						|
var _Warning = _interopRequireDefault(require("./Warning"));
 | 
						|
 | 
						|
var _Error = _interopRequireDefault(require("./Error"));
 | 
						|
 | 
						|
var _options = _interopRequireDefault(require("./options.json"));
 | 
						|
 | 
						|
var _utils = require("./utils");
 | 
						|
 | 
						|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 | 
						|
 | 
						|
let hasExplicitDependencyOnPostCSS = false;
 | 
						|
/**
 | 
						|
 * **PostCSS Loader**
 | 
						|
 *
 | 
						|
 * Loads && processes CSS with [PostCSS](https://github.com/postcss/postcss)
 | 
						|
 *
 | 
						|
 * @method loader
 | 
						|
 *
 | 
						|
 * @param {String} content Source
 | 
						|
 * @param {Object} sourceMap Source Map
 | 
						|
 * @param {Object} meta Meta
 | 
						|
 *
 | 
						|
 * @return {callback} callback Result
 | 
						|
 */
 | 
						|
 | 
						|
async function loader(content, sourceMap, meta) {
 | 
						|
  const options = this.getOptions(_options.default);
 | 
						|
  const callback = this.async();
 | 
						|
  const configOption = typeof options.postcssOptions === "undefined" || typeof options.postcssOptions.config === "undefined" ? true : options.postcssOptions.config;
 | 
						|
  const postcssFactory = (0, _utils.getPostcssImplementation)(this, options.implementation);
 | 
						|
 | 
						|
  if (!postcssFactory) {
 | 
						|
    callback(new Error(`The Postcss implementation "${options.implementation}" not found`));
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  let loadedConfig;
 | 
						|
 | 
						|
  if (configOption) {
 | 
						|
    try {
 | 
						|
      loadedConfig = await (0, _utils.loadConfig)(this, configOption, options.postcssOptions);
 | 
						|
    } catch (error) {
 | 
						|
      callback(error);
 | 
						|
      return;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  const useSourceMap = typeof options.sourceMap !== "undefined" ? options.sourceMap : this.sourceMap;
 | 
						|
  const {
 | 
						|
    plugins,
 | 
						|
    processOptions
 | 
						|
  } = await (0, _utils.getPostcssOptions)(this, loadedConfig, options.postcssOptions);
 | 
						|
 | 
						|
  if (useSourceMap) {
 | 
						|
    processOptions.map = {
 | 
						|
      inline: false,
 | 
						|
      annotation: false,
 | 
						|
      ...processOptions.map
 | 
						|
    };
 | 
						|
  }
 | 
						|
 | 
						|
  if (sourceMap && processOptions.map) {
 | 
						|
    processOptions.map.prev = (0, _utils.normalizeSourceMap)(sourceMap, this.context);
 | 
						|
  }
 | 
						|
 | 
						|
  let root; // Reuse PostCSS AST from other loaders
 | 
						|
 | 
						|
  if (meta && meta.ast && meta.ast.type === "postcss" && (0, _semver.satisfies)(meta.ast.version, `^${_package.default.version}`)) {
 | 
						|
    ({
 | 
						|
      root
 | 
						|
    } = meta.ast);
 | 
						|
  }
 | 
						|
 | 
						|
  if (!root && options.execute) {
 | 
						|
    // eslint-disable-next-line no-param-reassign
 | 
						|
    content = (0, _utils.exec)(content, this);
 | 
						|
  }
 | 
						|
 | 
						|
  let result;
 | 
						|
  let processor;
 | 
						|
 | 
						|
  try {
 | 
						|
    processor = postcssFactory(plugins);
 | 
						|
    result = await processor.process(root || content, processOptions);
 | 
						|
  } catch (error) {
 | 
						|
    // Check postcss versions to avoid using PostCSS 7.
 | 
						|
    // For caching reasons, we use the readFileSync and existsSync functions from the context,
 | 
						|
    // not the functions from the `fs` module.
 | 
						|
    if (!hasExplicitDependencyOnPostCSS && processor && processor.version && processor.version.startsWith("7.")) {
 | 
						|
      // The `findPackageJsonDir` function returns `string` or `null`.
 | 
						|
      // This is used to do for caching, that is, an explicit comparison with `undefined`
 | 
						|
      // is used to make the condition body run once.
 | 
						|
      const packageJSONDir = (0, _utils.findPackageJSONDir)(process.cwd(), this.fs.statSync);
 | 
						|
 | 
						|
      if (packageJSONDir) {
 | 
						|
        let bufferOfPackageJSON;
 | 
						|
 | 
						|
        try {
 | 
						|
          bufferOfPackageJSON = this.fs.readFileSync(_path.default.resolve(packageJSONDir, "package.json"), "utf8");
 | 
						|
        } catch (_error) {// Nothing
 | 
						|
        }
 | 
						|
 | 
						|
        if (bufferOfPackageJSON) {
 | 
						|
          let pkg;
 | 
						|
 | 
						|
          try {
 | 
						|
            pkg = JSON.parse(bufferOfPackageJSON);
 | 
						|
          } catch (_error) {// Nothing
 | 
						|
          }
 | 
						|
 | 
						|
          if (pkg) {
 | 
						|
            if (!pkg.dependencies.postcss && !pkg.devDependencies.postcss) {
 | 
						|
              this.emitWarning(new Error("Add postcss as project dependency. postcss is not a peer dependency for postcss-loader. " + "Use `npm install postcss` or `yarn add postcss`"));
 | 
						|
            } else {
 | 
						|
              hasExplicitDependencyOnPostCSS = true;
 | 
						|
            }
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    if (error.file) {
 | 
						|
      this.addDependency(error.file);
 | 
						|
    }
 | 
						|
 | 
						|
    if (error.name === "CssSyntaxError") {
 | 
						|
      callback(new _Error.default(error));
 | 
						|
    } else {
 | 
						|
      callback(error);
 | 
						|
    }
 | 
						|
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  for (const warning of result.warnings()) {
 | 
						|
    this.emitWarning(new _Warning.default(warning));
 | 
						|
  }
 | 
						|
 | 
						|
  for (const message of result.messages) {
 | 
						|
    // eslint-disable-next-line default-case
 | 
						|
    switch (message.type) {
 | 
						|
      case "dependency":
 | 
						|
        this.addDependency(message.file);
 | 
						|
        break;
 | 
						|
 | 
						|
      case "build-dependency":
 | 
						|
        this.addBuildDependency(message.file);
 | 
						|
        break;
 | 
						|
 | 
						|
      case "missing-dependency":
 | 
						|
        this.addMissingDependency(message.file);
 | 
						|
        break;
 | 
						|
 | 
						|
      case "context-dependency":
 | 
						|
        this.addContextDependency(message.file);
 | 
						|
        break;
 | 
						|
 | 
						|
      case "dir-dependency":
 | 
						|
        this.addContextDependency(message.dir);
 | 
						|
        break;
 | 
						|
 | 
						|
      case "asset":
 | 
						|
        if (message.content && message.file) {
 | 
						|
          this.emitFile(message.file, message.content, message.sourceMap, message.info);
 | 
						|
        }
 | 
						|
 | 
						|
    }
 | 
						|
  } // eslint-disable-next-line no-undefined
 | 
						|
 | 
						|
 | 
						|
  let map = result.map ? result.map.toJSON() : undefined;
 | 
						|
 | 
						|
  if (map && useSourceMap) {
 | 
						|
    map = (0, _utils.normalizeSourceMapAfterPostcss)(map, this.context);
 | 
						|
  }
 | 
						|
 | 
						|
  const ast = {
 | 
						|
    type: "postcss",
 | 
						|
    version: result.processor.version,
 | 
						|
    root: result.root
 | 
						|
  };
 | 
						|
  callback(null, result.css, map, {
 | 
						|
    ast
 | 
						|
  });
 | 
						|
} |