parcel-bundler
Version:
<p align="center"> <a href="https://parceljs.org/" target="_blank"> <img alt="Parcel" src="https://user-images.githubusercontent.com/19409/31321658-f6aed0f2-ac3d-11e7-8100-1587e676e0ec.png" width="749"> </a> </p>
162 lines (127 loc) • 4.36 kB
JavaScript
function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
function _toArray(arr) { return Array.isArray(arr) ? arr : Array.from(arr); }
const Asset = require('../Asset');
const postcss = require('postcss');
const valueParser = require('postcss-value-parser');
const postcssTransform = require('../transforms/postcss');
const CssSyntaxError = require('postcss/lib/css-syntax-error');
const URL_RE = /url\s*\("?(?![a-z]+:)/;
const IMPORT_RE = /@import/;
const PROTOCOL_RE = /^[a-z]+:/;
class CSSAsset extends Asset {
constructor(name, pkg, options) {
super(name, pkg, options);
this.type = 'css';
}
mightHaveDependencies() {
return !/\.css$/.test(this.name) || IMPORT_RE.test(this.contents) || URL_RE.test(this.contents);
}
parse(code) {
let root = postcss.parse(code, { from: this.name, to: this.name });
return new CSSAst(code, root);
}
collectDependencies() {
this.ast.root.walkAtRules('import', rule => {
let params = valueParser(rule.params).nodes;
var _params = _toArray(params);
let name = _params[0],
media = _params.slice(1);
let dep;
if (name.type === 'string') {
dep = name.value;
} else if (name.type === 'function' && name.value === 'url' && name.nodes.length) {
dep = name.nodes[0].value;
}
if (!dep) {
throw new Error('Could not find import name for ' + rule);
}
if (PROTOCOL_RE.test(dep)) {
return;
}
media = valueParser.stringify(media).trim();
this.addDependency(dep, { media, loc: rule.source.start });
rule.remove();
this.ast.dirty = true;
});
this.ast.root.walkDecls(decl => {
if (URL_RE.test(decl.value)) {
let parsed = valueParser(decl.value);
let dirty = false;
parsed.walk(node => {
if (node.type === 'function' && node.value === 'url' && node.nodes.length) {
let url = this.addURLDependency(node.nodes[0].value, {
loc: decl.source.start
});
dirty = node.nodes[0].value !== url;
node.nodes[0].value = url;
}
});
if (dirty) {
decl.value = parsed.toString();
this.ast.dirty = true;
}
}
});
}
transform() {
var _this = this;
return _asyncToGenerator(function* () {
yield postcssTransform(_this);
})();
}
getCSSAst() {
// Converts the ast to a CSS ast if needed, so we can apply postcss transforms.
if (!(this.ast instanceof CSSAst)) {
this.ast = CSSAsset.prototype.parse.call(this, this.ast.render());
}
return this.ast.root;
}
generate() {
let css = this.ast ? this.ast.render() : this.contents;
let js = '';
if (this.options.hmr) {
this.addDependency('_css_loader');
js = `
var reloadCSS = require('_css_loader');
module.hot.dispose(reloadCSS);
module.hot.accept(reloadCSS);
`;
}
if (this.cssModules) {
js += 'module.exports = ' + JSON.stringify(this.cssModules, false, 2) + ';';
}
return { css, js };
}
generateErrorMessage(err) {
// Wrap the error in a CssSyntaxError if needed so we can generate a code frame
if (err.loc && !err.showSourceCode) {
err = new CssSyntaxError(err.message, err.loc.line, err.loc.column, this.contents);
}
err.message = err.reason || err.message;
err.loc = {
line: err.line,
column: err.column
};
if (err.showSourceCode) {
err.codeFrame = err.showSourceCode();
err.highlightedCodeFrame = err.showSourceCode(true);
}
return err;
}
}
class CSSAst {
constructor(css, root) {
this.css = css;
this.root = root;
this.dirty = false;
}
render() {
if (this.dirty) {
this.css = '';
postcss.stringify(this.root, c => this.css += c);
}
return this.css;
}
}
module.exports = CSSAsset;
;