1025 lines
29 KiB
JavaScript
1025 lines
29 KiB
JavaScript
'use strict';
|
|
|
|
var path = require('path');
|
|
var rollupPluginutils = require('rollup-pluginutils');
|
|
var Concat = require('concat-with-sourcemaps');
|
|
var series = require('promise.series');
|
|
var importCwd = require('import-cwd');
|
|
var postcss = require('postcss');
|
|
var findPostcssConfig = require('postcss-load-config');
|
|
var safeIdentifier = require('safe-identifier');
|
|
var pify = require('pify');
|
|
var resolve = require('resolve');
|
|
var PQueue = require('p-queue');
|
|
|
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
|
|
var path__default = /*#__PURE__*/_interopDefaultLegacy(path);
|
|
var Concat__default = /*#__PURE__*/_interopDefaultLegacy(Concat);
|
|
var series__default = /*#__PURE__*/_interopDefaultLegacy(series);
|
|
var importCwd__default = /*#__PURE__*/_interopDefaultLegacy(importCwd);
|
|
var postcss__default = /*#__PURE__*/_interopDefaultLegacy(postcss);
|
|
var findPostcssConfig__default = /*#__PURE__*/_interopDefaultLegacy(findPostcssConfig);
|
|
var pify__default = /*#__PURE__*/_interopDefaultLegacy(pify);
|
|
var resolve__default = /*#__PURE__*/_interopDefaultLegacy(resolve);
|
|
var PQueue__default = /*#__PURE__*/_interopDefaultLegacy(PQueue);
|
|
|
|
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
|
|
try {
|
|
var info = gen[key](arg);
|
|
var value = info.value;
|
|
} catch (error) {
|
|
reject(error);
|
|
return;
|
|
}
|
|
|
|
if (info.done) {
|
|
resolve(value);
|
|
} else {
|
|
Promise.resolve(value).then(_next, _throw);
|
|
}
|
|
}
|
|
|
|
function _asyncToGenerator(fn) {
|
|
return function () {
|
|
var self = this,
|
|
args = arguments;
|
|
return new Promise(function (resolve, reject) {
|
|
var gen = fn.apply(self, args);
|
|
|
|
function _next(value) {
|
|
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
|
|
}
|
|
|
|
function _throw(err) {
|
|
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
|
|
}
|
|
|
|
_next(undefined);
|
|
});
|
|
};
|
|
}
|
|
|
|
function _defineProperty(obj, key, value) {
|
|
if (key in obj) {
|
|
Object.defineProperty(obj, key, {
|
|
value: value,
|
|
enumerable: true,
|
|
configurable: true,
|
|
writable: true
|
|
});
|
|
} else {
|
|
obj[key] = value;
|
|
}
|
|
|
|
return obj;
|
|
}
|
|
|
|
function ownKeys(object, enumerableOnly) {
|
|
var keys = Object.keys(object);
|
|
|
|
if (Object.getOwnPropertySymbols) {
|
|
var symbols = Object.getOwnPropertySymbols(object);
|
|
if (enumerableOnly) symbols = symbols.filter(function (sym) {
|
|
return Object.getOwnPropertyDescriptor(object, sym).enumerable;
|
|
});
|
|
keys.push.apply(keys, symbols);
|
|
}
|
|
|
|
return keys;
|
|
}
|
|
|
|
function _objectSpread2(target) {
|
|
for (var i = 1; i < arguments.length; i++) {
|
|
var source = arguments[i] != null ? arguments[i] : {};
|
|
|
|
if (i % 2) {
|
|
ownKeys(Object(source), true).forEach(function (key) {
|
|
_defineProperty(target, key, source[key]);
|
|
});
|
|
} else if (Object.getOwnPropertyDescriptors) {
|
|
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
|
|
} else {
|
|
ownKeys(Object(source)).forEach(function (key) {
|
|
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
|
|
});
|
|
}
|
|
}
|
|
|
|
return target;
|
|
}
|
|
|
|
function _unsupportedIterableToArray(o, minLen) {
|
|
if (!o) return;
|
|
if (typeof o === "string") return _arrayLikeToArray(o, minLen);
|
|
var n = Object.prototype.toString.call(o).slice(8, -1);
|
|
if (n === "Object" && o.constructor) n = o.constructor.name;
|
|
if (n === "Map" || n === "Set") return Array.from(o);
|
|
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
|
|
}
|
|
|
|
function _arrayLikeToArray(arr, len) {
|
|
if (len == null || len > arr.length) len = arr.length;
|
|
|
|
for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
|
|
|
|
return arr2;
|
|
}
|
|
|
|
function _createForOfIteratorHelper(o, allowArrayLike) {
|
|
var it;
|
|
|
|
if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) {
|
|
if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
|
|
if (it) o = it;
|
|
var i = 0;
|
|
|
|
var F = function () {};
|
|
|
|
return {
|
|
s: F,
|
|
n: function () {
|
|
if (i >= o.length) return {
|
|
done: true
|
|
};
|
|
return {
|
|
done: false,
|
|
value: o[i++]
|
|
};
|
|
},
|
|
e: function (e) {
|
|
throw e;
|
|
},
|
|
f: F
|
|
};
|
|
}
|
|
|
|
throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
}
|
|
|
|
var normalCompletion = true,
|
|
didErr = false,
|
|
err;
|
|
return {
|
|
s: function () {
|
|
it = o[Symbol.iterator]();
|
|
},
|
|
n: function () {
|
|
var step = it.next();
|
|
normalCompletion = step.done;
|
|
return step;
|
|
},
|
|
e: function (e) {
|
|
didErr = true;
|
|
err = e;
|
|
},
|
|
f: function () {
|
|
try {
|
|
if (!normalCompletion && it.return != null) it.return();
|
|
} finally {
|
|
if (didErr) throw err;
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
/* eslint import/no-anonymous-default-export: [2, {"allowArrowFunction": true}] */
|
|
var normalizePath = (path => path && path.replace(/\\+/g, '/'));
|
|
|
|
const humanlizePath = filepath => normalizePath(path__default['default'].relative(process.cwd(), filepath));
|
|
|
|
const styleInjectPath = require.resolve('style-inject/dist/style-inject.es').replace(/[\\/]+/g, '/');
|
|
|
|
function loadConfig(id, {
|
|
ctx: configOptions,
|
|
path: configPath
|
|
}) {
|
|
const handleError = err => {
|
|
if (!err.message.includes('No PostCSS Config found')) {
|
|
throw err;
|
|
} // Return empty options for PostCSS
|
|
|
|
|
|
return {};
|
|
};
|
|
|
|
configPath = configPath ? path__default['default'].resolve(configPath) : path__default['default'].dirname(id);
|
|
const ctx = {
|
|
file: {
|
|
extname: path__default['default'].extname(id),
|
|
dirname: path__default['default'].dirname(id),
|
|
basename: path__default['default'].basename(id)
|
|
},
|
|
options: configOptions || {}
|
|
};
|
|
return findPostcssConfig__default['default'](ctx, configPath).catch(handleError);
|
|
}
|
|
|
|
function escapeClassNameDashes(string) {
|
|
return string.replace(/-+/g, match => {
|
|
return `$${match.replace(/-/g, '_')}$`;
|
|
});
|
|
}
|
|
|
|
function ensureClassName(name) {
|
|
name = escapeClassNameDashes(name);
|
|
return safeIdentifier.identifier(name, false);
|
|
}
|
|
|
|
function ensurePostCSSOption(option) {
|
|
return typeof option === 'string' ? importCwd__default['default'](option) : option;
|
|
}
|
|
|
|
function isModuleFile(file) {
|
|
return /\.module\.[a-z]{2,6}$/.test(file);
|
|
}
|
|
/* eslint import/no-anonymous-default-export: [2, {"allowObject": true}] */
|
|
|
|
|
|
var postcssLoader = {
|
|
name: 'postcss',
|
|
alwaysProcess: true,
|
|
|
|
// `test` option is dynamically set in ./loaders
|
|
// eslint-disable-next-line complexity
|
|
process({
|
|
code,
|
|
map
|
|
}) {
|
|
var _this = this;
|
|
|
|
return _asyncToGenerator(function* () {
|
|
const config = _this.options.config ? yield loadConfig(_this.id, _this.options.config) : {};
|
|
const options = _this.options;
|
|
const plugins = [...(options.postcss.plugins || []), ...(config.plugins || [])];
|
|
const shouldExtract = options.extract;
|
|
const shouldInject = options.inject;
|
|
const modulesExported = {};
|
|
const autoModules = options.autoModules !== false && options.onlyModules !== true;
|
|
const isAutoModule = autoModules && isModuleFile(_this.id);
|
|
const supportModules = autoModules ? isAutoModule : options.modules;
|
|
|
|
if (supportModules) {
|
|
plugins.unshift(require('postcss-modules')(_objectSpread2(_objectSpread2({
|
|
// In tests
|
|
// Skip hash in names since css content on windows and linux would differ because of `new line` (\r?\n)
|
|
generateScopedName: process.env.ROLLUP_POSTCSS_TEST ? '[name]_[local]' : '[name]_[local]__[hash:base64:5]'
|
|
}, options.modules), {}, {
|
|
getJSON(filepath, json, outpath) {
|
|
modulesExported[filepath] = json;
|
|
|
|
if (typeof options.modules === 'object' && typeof options.modules.getJSON === 'function') {
|
|
return options.modules.getJSON(filepath, json, outpath);
|
|
}
|
|
}
|
|
|
|
})));
|
|
} // If shouldExtract, minimize is done after all CSS are extracted to a file
|
|
|
|
|
|
if (!shouldExtract && options.minimize) {
|
|
plugins.push(require('cssnano')(options.minimize));
|
|
}
|
|
|
|
const postcssOptions = _objectSpread2(_objectSpread2(_objectSpread2({}, _this.options.postcss), config.options), {}, {
|
|
// Allow overriding `to` for some plugins that are relying on this value
|
|
to: options.to || _this.id,
|
|
// Followings are never modified by user config config
|
|
from: _this.id,
|
|
map: _this.sourceMap ? shouldExtract ? {
|
|
inline: false,
|
|
annotation: false
|
|
} : {
|
|
inline: true,
|
|
annotation: false
|
|
} : false
|
|
});
|
|
|
|
delete postcssOptions.plugins;
|
|
postcssOptions.parser = ensurePostCSSOption(postcssOptions.parser);
|
|
postcssOptions.syntax = ensurePostCSSOption(postcssOptions.syntax);
|
|
postcssOptions.stringifier = ensurePostCSSOption(postcssOptions.stringifier);
|
|
|
|
if (map && postcssOptions.map) {
|
|
postcssOptions.map.prev = typeof map === 'string' ? JSON.parse(map) : map;
|
|
}
|
|
|
|
if (plugins.length === 0) {
|
|
// Prevent from postcss warning:
|
|
// You did not set any plugins, parser, or stringifier. Right now, PostCSS does nothing. Pick plugins for your case on https://www.postcss.parts/ and use them in postcss.config.js
|
|
const noopPlugin = () => {
|
|
return {
|
|
postcssPlugin: 'postcss-noop-plugin',
|
|
|
|
Once() {}
|
|
|
|
};
|
|
};
|
|
|
|
plugins.push(noopPlugin());
|
|
}
|
|
|
|
const result = yield postcss__default['default'](plugins).process(code, postcssOptions);
|
|
|
|
var _iterator = _createForOfIteratorHelper(result.messages),
|
|
_step;
|
|
|
|
try {
|
|
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
const message = _step.value;
|
|
|
|
if (message.type === 'dependency') {
|
|
_this.dependencies.add(message.file);
|
|
}
|
|
}
|
|
} catch (err) {
|
|
_iterator.e(err);
|
|
} finally {
|
|
_iterator.f();
|
|
}
|
|
|
|
var _iterator2 = _createForOfIteratorHelper(result.warnings()),
|
|
_step2;
|
|
|
|
try {
|
|
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
const warning = _step2.value;
|
|
|
|
if (!warning.message) {
|
|
warning.message = warning.text;
|
|
}
|
|
|
|
_this.warn(warning);
|
|
}
|
|
} catch (err) {
|
|
_iterator2.e(err);
|
|
} finally {
|
|
_iterator2.f();
|
|
}
|
|
|
|
const outputMap = result.map && JSON.parse(result.map.toString());
|
|
|
|
if (outputMap && outputMap.sources) {
|
|
outputMap.sources = outputMap.sources.map(v => normalizePath(v));
|
|
}
|
|
|
|
let output = '';
|
|
let extracted;
|
|
|
|
if (options.namedExports) {
|
|
const json = modulesExported[_this.id];
|
|
const getClassName = typeof options.namedExports === 'function' ? options.namedExports : ensureClassName; // eslint-disable-next-line guard-for-in
|
|
|
|
for (const name in json) {
|
|
const newName = getClassName(name); // Log transformed class names
|
|
// But skip this when namedExports is a function
|
|
// Since a user like you can manually log that if you want
|
|
|
|
if (name !== newName && typeof options.namedExports !== 'function') {
|
|
_this.warn(`Exported "${name}" as "${newName}" in ${humanlizePath(_this.id)}`);
|
|
}
|
|
|
|
if (!json[newName]) {
|
|
json[newName] = json[name];
|
|
}
|
|
|
|
output += `export var ${newName} = ${JSON.stringify(json[name])};\n`;
|
|
}
|
|
}
|
|
|
|
const cssVariableName = safeIdentifier.identifier('css', true);
|
|
|
|
if (shouldExtract) {
|
|
output += `export default ${JSON.stringify(modulesExported[_this.id])};`;
|
|
extracted = {
|
|
id: _this.id,
|
|
code: result.css,
|
|
map: outputMap
|
|
};
|
|
} else {
|
|
const module = supportModules ? JSON.stringify(modulesExported[_this.id]) : cssVariableName;
|
|
output += `var ${cssVariableName} = ${JSON.stringify(result.css)};\n` + `export default ${module};\n` + `export var stylesheet=${JSON.stringify(result.css)};`;
|
|
}
|
|
|
|
if (!shouldExtract && shouldInject) {
|
|
output += typeof options.inject === 'function' ? options.inject(cssVariableName, _this.id) : '\n' + `import styleInject from '${styleInjectPath}';\n` + `styleInject(${cssVariableName}${Object.keys(options.inject).length > 0 ? `,${JSON.stringify(options.inject)}` : ''});`;
|
|
}
|
|
|
|
return {
|
|
code: output,
|
|
map: outputMap,
|
|
extracted
|
|
};
|
|
})();
|
|
}
|
|
|
|
};
|
|
|
|
function loadModule(moduleId) {
|
|
// Trying to load module normally (relative to plugin directory)
|
|
try {
|
|
return require(moduleId);
|
|
} catch (_unused) {// Ignore error
|
|
} // Then, trying to load it relative to CWD
|
|
|
|
|
|
return importCwd__default['default'].silent(moduleId);
|
|
}
|
|
|
|
// See: https://github.com/sass/node-sass/issues/857
|
|
|
|
const threadPoolSize = process.env.UV_THREADPOOL_SIZE || 4;
|
|
const workQueue = new PQueue__default['default']({
|
|
concurrency: threadPoolSize - 1
|
|
});
|
|
const moduleRe = /^~([a-z\d]|@).+/i;
|
|
|
|
const getUrlOfPartial = url => {
|
|
const parsedUrl = path__default['default'].parse(url);
|
|
return `${parsedUrl.dir}${path__default['default'].sep}_${parsedUrl.base}`;
|
|
};
|
|
|
|
const resolvePromise = pify__default['default'](resolve__default['default']); // List of supported SASS modules in the order of preference
|
|
|
|
const sassModuleIds = ['sass', 'node-sass'];
|
|
/* eslint import/no-anonymous-default-export: [2, {"allowObject": true}] */
|
|
|
|
var sassLoader = {
|
|
name: 'sass',
|
|
test: /\.(sass|scss)$/,
|
|
|
|
process({
|
|
code
|
|
}) {
|
|
return new Promise((resolve, reject) => {
|
|
const sass = loadSassOrThrow();
|
|
const render = pify__default['default'](sass.render.bind(sass));
|
|
const data = this.options.data || '';
|
|
workQueue.add(() => render(_objectSpread2(_objectSpread2({}, this.options), {}, {
|
|
file: this.id,
|
|
data: data + code,
|
|
indentedSyntax: /\.sass$/.test(this.id),
|
|
sourceMap: this.sourceMap,
|
|
importer: [(url, importer, done) => {
|
|
if (!moduleRe.test(url)) return done({
|
|
file: url
|
|
});
|
|
const moduleUrl = url.slice(1);
|
|
const partialUrl = getUrlOfPartial(moduleUrl);
|
|
const options = {
|
|
basedir: path__default['default'].dirname(importer),
|
|
extensions: ['.scss', '.sass', '.css']
|
|
};
|
|
|
|
const finishImport = id => {
|
|
done({
|
|
// Do not add `.css` extension in order to inline the file
|
|
file: id.endsWith('.css') ? id.replace(/\.css$/, '') : id
|
|
});
|
|
};
|
|
|
|
const next = () => {
|
|
// Catch all resolving errors, return the original file and pass responsibility back to other custom importers
|
|
done({
|
|
file: url
|
|
});
|
|
}; // Give precedence to importing a partial
|
|
|
|
|
|
resolvePromise(partialUrl, options).then(finishImport).catch(error => {
|
|
if (error.code === 'MODULE_NOT_FOUND' || error.code === 'ENOENT') {
|
|
resolvePromise(moduleUrl, options).then(finishImport).catch(next);
|
|
} else {
|
|
next();
|
|
}
|
|
});
|
|
}].concat(this.options.importer || [])
|
|
})).then(result => {
|
|
var _iterator = _createForOfIteratorHelper(result.stats.includedFiles),
|
|
_step;
|
|
|
|
try {
|
|
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
const file = _step.value;
|
|
this.dependencies.add(file);
|
|
}
|
|
} catch (err) {
|
|
_iterator.e(err);
|
|
} finally {
|
|
_iterator.f();
|
|
}
|
|
|
|
resolve({
|
|
code: result.css.toString(),
|
|
map: result.map && result.map.toString()
|
|
});
|
|
}).catch(reject));
|
|
});
|
|
}
|
|
|
|
};
|
|
|
|
function loadSassOrThrow() {
|
|
// Loading one of the supported modules
|
|
var _iterator2 = _createForOfIteratorHelper(sassModuleIds),
|
|
_step2;
|
|
|
|
try {
|
|
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
const moduleId = _step2.value;
|
|
const module = loadModule(moduleId);
|
|
|
|
if (module) {
|
|
return module;
|
|
}
|
|
} // Throwing exception if module can't be loaded
|
|
|
|
} catch (err) {
|
|
_iterator2.e(err);
|
|
} finally {
|
|
_iterator2.f();
|
|
}
|
|
|
|
throw new Error('You need to install one of the following packages: ' + sassModuleIds.map(moduleId => `"${moduleId}"`).join(', ') + ' ' + 'in order to process SASS files');
|
|
}
|
|
|
|
/* eslint import/no-anonymous-default-export: [2, {"allowObject": true}] */
|
|
|
|
var stylusLoader = {
|
|
name: 'stylus',
|
|
test: /\.(styl|stylus)$/,
|
|
|
|
process({
|
|
code
|
|
}) {
|
|
var _this = this;
|
|
|
|
return _asyncToGenerator(function* () {
|
|
const stylus = loadModule('stylus');
|
|
|
|
if (!stylus) {
|
|
throw new Error('You need to install "stylus" packages in order to process Stylus files');
|
|
}
|
|
|
|
const style = stylus(code, _objectSpread2(_objectSpread2({}, _this.options), {}, {
|
|
filename: _this.id,
|
|
sourcemap: _this.sourceMap && {}
|
|
}));
|
|
const css = yield pify__default['default'](style.render.bind(style))();
|
|
const deps = style.deps();
|
|
|
|
var _iterator = _createForOfIteratorHelper(deps),
|
|
_step;
|
|
|
|
try {
|
|
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
const dep = _step.value;
|
|
|
|
_this.dependencies.add(dep);
|
|
}
|
|
} catch (err) {
|
|
_iterator.e(err);
|
|
} finally {
|
|
_iterator.f();
|
|
}
|
|
|
|
return {
|
|
code: css,
|
|
map: style.sourcemap
|
|
};
|
|
})();
|
|
}
|
|
|
|
};
|
|
|
|
/* eslint import/no-anonymous-default-export: [2, {"allowObject": true}] */
|
|
|
|
var lessLoader = {
|
|
name: 'less',
|
|
test: /\.less$/,
|
|
|
|
process({
|
|
code
|
|
}) {
|
|
var _this = this;
|
|
|
|
return _asyncToGenerator(function* () {
|
|
const less = loadModule('less');
|
|
|
|
if (!less) {
|
|
throw new Error('You need to install "less" packages in order to process Less files');
|
|
}
|
|
|
|
let _yield$pify = yield pify__default['default'](less.render.bind(less))(code, _objectSpread2(_objectSpread2({}, _this.options), {}, {
|
|
sourceMap: _this.sourceMap && {},
|
|
filename: _this.id
|
|
})),
|
|
css = _yield$pify.css,
|
|
map = _yield$pify.map,
|
|
imports = _yield$pify.imports;
|
|
|
|
var _iterator = _createForOfIteratorHelper(imports),
|
|
_step;
|
|
|
|
try {
|
|
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
const dep = _step.value;
|
|
|
|
_this.dependencies.add(dep);
|
|
}
|
|
} catch (err) {
|
|
_iterator.e(err);
|
|
} finally {
|
|
_iterator.f();
|
|
}
|
|
|
|
if (map) {
|
|
map = JSON.parse(map);
|
|
map.sources = map.sources.map(source => humanlizePath(source));
|
|
}
|
|
|
|
return {
|
|
code: css,
|
|
map
|
|
};
|
|
})();
|
|
}
|
|
|
|
};
|
|
|
|
const matchFile = (filepath, condition) => {
|
|
if (typeof condition === 'function') {
|
|
return condition(filepath);
|
|
}
|
|
|
|
return condition && condition.test(filepath);
|
|
};
|
|
|
|
class Loaders {
|
|
constructor(options = {}) {
|
|
this.use = options.use.map(rule => {
|
|
if (typeof rule === 'string') {
|
|
return [rule];
|
|
}
|
|
|
|
if (Array.isArray(rule)) {
|
|
return rule;
|
|
}
|
|
|
|
throw new TypeError('The rule in `use` option must be string or Array!');
|
|
});
|
|
this.loaders = [];
|
|
const extensions = options.extensions || ['.css', '.sss', '.pcss'];
|
|
|
|
const customPostcssLoader = _objectSpread2(_objectSpread2({}, postcssLoader), {}, {
|
|
test: filepath => extensions.some(ext => path__default['default'].extname(filepath) === ext)
|
|
});
|
|
|
|
this.registerLoader(customPostcssLoader);
|
|
this.registerLoader(sassLoader);
|
|
this.registerLoader(stylusLoader);
|
|
this.registerLoader(lessLoader);
|
|
|
|
if (options.loaders) {
|
|
options.loaders.forEach(loader => this.registerLoader(loader));
|
|
}
|
|
}
|
|
|
|
registerLoader(loader) {
|
|
const existing = this.getLoader(loader.name);
|
|
|
|
if (existing) {
|
|
this.removeLoader(loader.name);
|
|
}
|
|
|
|
this.loaders.push(loader);
|
|
return this;
|
|
}
|
|
|
|
removeLoader(name) {
|
|
this.loaders = this.loaders.filter(loader => loader.name !== name);
|
|
return this;
|
|
}
|
|
|
|
isSupported(filepath) {
|
|
return this.loaders.some(loader => {
|
|
return matchFile(filepath, loader.test);
|
|
});
|
|
}
|
|
/**
|
|
* Process the resource with loaders in serial
|
|
* @param {object} resource
|
|
* @param {string} resource.code
|
|
* @param {any} resource.map
|
|
* @param {object} context
|
|
* @param {string} context.id The absolute path to resource
|
|
* @param {boolean | 'inline'} context.sourceMap
|
|
* @param {Set<string>} context.dependencies A set of dependencies to watch
|
|
* @returns {{code: string, map?: any}}
|
|
*/
|
|
|
|
|
|
process({
|
|
code,
|
|
map
|
|
}, context) {
|
|
return series__default['default'](this.use.slice().reverse().map(([name, options]) => {
|
|
const loader = this.getLoader(name);
|
|
|
|
const loaderContext = _objectSpread2({
|
|
options: options || {}
|
|
}, context);
|
|
|
|
return v => {
|
|
if (loader.alwaysProcess || matchFile(loaderContext.id, loader.test)) {
|
|
return loader.process.call(loaderContext, v);
|
|
} // Otherwise directly return input value
|
|
|
|
|
|
return v;
|
|
};
|
|
}), {
|
|
code,
|
|
map
|
|
});
|
|
}
|
|
|
|
getLoader(name) {
|
|
return this.loaders.find(loader => loader.name === name);
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* The options that could be `boolean` or `object`
|
|
* We convert it to an object when it's truthy
|
|
* Otherwise fallback to default value
|
|
*/
|
|
|
|
function inferOption(option, defaultValue) {
|
|
if (option === false) return false;
|
|
if (option && typeof option === 'object') return option;
|
|
return option ? {} : defaultValue;
|
|
}
|
|
/**
|
|
* Recursively get the correct import order from rollup
|
|
* We only process a file once
|
|
*
|
|
* @param {string} id
|
|
* @param {Function} getModuleInfo
|
|
* @param {Set<string>} seen
|
|
*/
|
|
|
|
|
|
function getRecursiveImportOrder(id, getModuleInfo, seen = new Set()) {
|
|
if (seen.has(id)) {
|
|
return [];
|
|
}
|
|
|
|
seen.add(id);
|
|
const result = [id];
|
|
getModuleInfo(id).importedIds.forEach(importFile => {
|
|
result.push(...getRecursiveImportOrder(importFile, getModuleInfo, seen));
|
|
});
|
|
return result;
|
|
}
|
|
/* eslint import/no-anonymous-default-export: [2, {"allowArrowFunction": true}] */
|
|
|
|
|
|
var index = ((options = {}) => {
|
|
const filter = rollupPluginutils.createFilter(options.include, options.exclude);
|
|
const postcssPlugins = Array.isArray(options.plugins) ? options.plugins.filter(Boolean) : options.plugins;
|
|
const sourceMap = options.sourceMap;
|
|
const postcssLoaderOptions = {
|
|
/** Inject CSS as `<style>` to `<head>` */
|
|
inject: typeof options.inject === 'function' ? options.inject : inferOption(options.inject, {}),
|
|
|
|
/** Extract CSS */
|
|
extract: typeof options.extract === 'undefined' ? false : options.extract,
|
|
|
|
/** CSS modules */
|
|
onlyModules: options.modules === true,
|
|
modules: inferOption(options.modules, false),
|
|
namedExports: options.namedExports,
|
|
|
|
/** Automatically CSS modules for .module.xxx files */
|
|
autoModules: options.autoModules,
|
|
|
|
/** Options for cssnano */
|
|
minimize: inferOption(options.minimize, false),
|
|
|
|
/** Postcss config file */
|
|
config: inferOption(options.config, {}),
|
|
|
|
/** PostCSS target filename hint, for plugins that are relying on it */
|
|
to: options.to,
|
|
|
|
/** PostCSS options */
|
|
postcss: {
|
|
parser: options.parser,
|
|
plugins: postcssPlugins,
|
|
syntax: options.syntax,
|
|
stringifier: options.stringifier,
|
|
exec: options.exec
|
|
}
|
|
};
|
|
let use = ['sass', 'stylus', 'less'];
|
|
|
|
if (Array.isArray(options.use)) {
|
|
use = options.use;
|
|
} else if (options.use !== null && typeof options.use === 'object') {
|
|
use = [['sass', options.use.sass || {}], ['stylus', options.use.stylus || {}], ['less', options.use.less || {}]];
|
|
}
|
|
|
|
use.unshift(['postcss', postcssLoaderOptions]);
|
|
const loaders = new Loaders({
|
|
use,
|
|
loaders: options.loaders,
|
|
extensions: options.extensions
|
|
});
|
|
const extracted = new Map();
|
|
return {
|
|
name: 'postcss',
|
|
|
|
transform(code, id) {
|
|
var _this = this;
|
|
|
|
return _asyncToGenerator(function* () {
|
|
if (!filter(id) || !loaders.isSupported(id)) {
|
|
return null;
|
|
}
|
|
|
|
if (typeof options.onImport === 'function') {
|
|
options.onImport(id);
|
|
}
|
|
|
|
const loaderContext = {
|
|
id,
|
|
sourceMap,
|
|
dependencies: new Set(),
|
|
warn: _this.warn.bind(_this),
|
|
plugin: _this
|
|
};
|
|
const result = yield loaders.process({
|
|
code,
|
|
map: undefined
|
|
}, loaderContext);
|
|
|
|
var _iterator = _createForOfIteratorHelper(loaderContext.dependencies),
|
|
_step;
|
|
|
|
try {
|
|
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
const dep = _step.value;
|
|
|
|
_this.addWatchFile(dep);
|
|
}
|
|
} catch (err) {
|
|
_iterator.e(err);
|
|
} finally {
|
|
_iterator.f();
|
|
}
|
|
|
|
if (postcssLoaderOptions.extract) {
|
|
extracted.set(id, result.extracted);
|
|
return {
|
|
code: result.code,
|
|
map: {
|
|
mappings: ''
|
|
}
|
|
};
|
|
}
|
|
|
|
return {
|
|
code: result.code,
|
|
map: result.map || {
|
|
mappings: ''
|
|
}
|
|
};
|
|
})();
|
|
},
|
|
|
|
augmentChunkHash() {
|
|
if (extracted.size === 0) return; // eslint-disable-next-line unicorn/no-reduce
|
|
|
|
const extractedValue = [...extracted].reduce((object, [key, value]) => _objectSpread2(_objectSpread2({}, object), {}, {
|
|
[key]: value
|
|
}), {});
|
|
return JSON.stringify(extractedValue);
|
|
},
|
|
|
|
generateBundle(options_, bundle) {
|
|
var _this2 = this;
|
|
|
|
return _asyncToGenerator(function* () {
|
|
if (extracted.size === 0 || !(options_.dir || options_.file)) return; // eslint-disable-next-line no-warning-comments
|
|
// TODO: support `[hash]`
|
|
|
|
const dir = options_.dir || path__default['default'].dirname(options_.file);
|
|
const file = options_.file || path__default['default'].join(options_.dir, Object.keys(bundle).find(fileName => bundle[fileName].isEntry));
|
|
|
|
const getExtracted = () => {
|
|
let fileName = `${path__default['default'].basename(file, path__default['default'].extname(file))}.css`;
|
|
|
|
if (typeof postcssLoaderOptions.extract === 'string') {
|
|
fileName = path__default['default'].isAbsolute(postcssLoaderOptions.extract) ? normalizePath(path__default['default'].relative(dir, postcssLoaderOptions.extract)) : normalizePath(postcssLoaderOptions.extract);
|
|
}
|
|
|
|
const concat = new Concat__default['default'](true, fileName, '\n');
|
|
const entries = [...extracted.values()];
|
|
const _bundle$normalizePath = bundle[normalizePath(path__default['default'].relative(dir, file))],
|
|
modules = _bundle$normalizePath.modules,
|
|
facadeModuleId = _bundle$normalizePath.facadeModuleId;
|
|
|
|
if (modules) {
|
|
const moduleIds = getRecursiveImportOrder(facadeModuleId, _this2.getModuleInfo);
|
|
entries.sort((a, b) => moduleIds.indexOf(a.id) - moduleIds.indexOf(b.id));
|
|
}
|
|
|
|
for (var _i = 0, _entries = entries; _i < _entries.length; _i++) {
|
|
const result = _entries[_i];
|
|
const relative = normalizePath(path__default['default'].relative(dir, result.id));
|
|
const map = result.map || null;
|
|
|
|
if (map) {
|
|
map.file = fileName;
|
|
}
|
|
|
|
concat.add(relative, result.code, map);
|
|
}
|
|
|
|
let code = concat.content;
|
|
|
|
if (sourceMap === 'inline') {
|
|
code += `\n/*# sourceMappingURL=data:application/json;base64,${Buffer.from(concat.sourceMap, 'utf8').toString('base64')}*/`;
|
|
} else if (sourceMap === true) {
|
|
code += `\n/*# sourceMappingURL=${path__default['default'].basename(fileName)}.map */`;
|
|
}
|
|
|
|
return {
|
|
code,
|
|
map: sourceMap === true && concat.sourceMap,
|
|
codeFileName: fileName,
|
|
mapFileName: fileName + '.map'
|
|
};
|
|
};
|
|
|
|
if (options.onExtract) {
|
|
const shouldExtract = yield options.onExtract(getExtracted);
|
|
|
|
if (shouldExtract === false) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
let _getExtracted = getExtracted(),
|
|
code = _getExtracted.code,
|
|
codeFileName = _getExtracted.codeFileName,
|
|
map = _getExtracted.map,
|
|
mapFileName = _getExtracted.mapFileName; // Perform cssnano on the extracted file
|
|
|
|
|
|
if (postcssLoaderOptions.minimize) {
|
|
const cssOptions = {};
|
|
cssOptions.from = codeFileName;
|
|
|
|
if (sourceMap === 'inline') {
|
|
cssOptions.map = {
|
|
inline: true
|
|
};
|
|
} else if (sourceMap === true && map) {
|
|
cssOptions.map = {
|
|
prev: map
|
|
};
|
|
cssOptions.to = codeFileName;
|
|
}
|
|
|
|
const result = yield require('cssnano')(postcssLoaderOptions.minimize).process(code, cssOptions);
|
|
code = result.css;
|
|
|
|
if (sourceMap === true && result.map && result.map.toString) {
|
|
map = result.map.toString();
|
|
}
|
|
}
|
|
|
|
_this2.emitFile({
|
|
fileName: codeFileName,
|
|
type: 'asset',
|
|
source: code
|
|
});
|
|
|
|
if (map) {
|
|
_this2.emitFile({
|
|
fileName: mapFileName,
|
|
type: 'asset',
|
|
source: map
|
|
});
|
|
}
|
|
})();
|
|
}
|
|
|
|
};
|
|
});
|
|
|
|
module.exports = index;
|