Skip to content

Commit

Permalink
refactor: loader
Browse files Browse the repository at this point in the history
* refactor: placeholder regex

* refactor: utils

* refactor: loader
  • Loading branch information
evilebottnawi committed Nov 29, 2018
1 parent e9327c0 commit ee409c5
Show file tree
Hide file tree
Showing 3 changed files with 161 additions and 173 deletions.
184 changes: 139 additions & 45 deletions lib/loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,23 @@
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
const postcss = require('postcss');
const localByDefault = require('postcss-modules-local-by-default');
const extractImports = require('postcss-modules-extract-imports');
const modulesScope = require('postcss-modules-scope');
const modulesValues = require('postcss-modules-values');
const loaderUtils = require('loader-utils');

const processCss = require('./processCss');
const { importParser, icssParser, urlParser } = require('./plugins');
const {
getLocalIdent,
getImportPrefix,
placeholderImportItemReplacer,
compileExports,
placholderRegExps,
} = require('./utils');
const Warning = require('./Warning');
const CssSyntaxError = require('./CssSyntaxError');

module.exports = function loader(content, map) {
const callback = this.async();
Expand All @@ -34,27 +43,92 @@ module.exports = function loader(content, map) {
}
/* eslint-enable no-param-reassign */

processCss(
content,
map,
{
loaderContext: this,
loaderOptions: options,
sourceMap,
},
(err, result) => {
if (err) {
return callback(err);
}
const loaderContext = this;
const localIdentName = options.localIdentName || '[hash:base64]';
const customGetLocalIdent = options.getLocalIdent || getLocalIdent;

const parserOptions = {
url: options.url !== false,
import: options.import !== false,
};

const plugins = [
modulesValues,
localByDefault({
mode: options.modules ? 'local' : 'global',
rewriteUrl(global, url) {
if (parserOptions.url) {
// eslint-disable-next-line no-param-reassign
url = url.trim();

if (
!url.replace(/\s/g, '').length ||
!loaderUtils.isUrlRequest(url)
) {
return url;
}
if (global) {
return loaderUtils.urlToRequest(url);
}
}
return url;
},
}),
extractImports(),
modulesScope({
generateScopedName: function generateScopedName(exportName) {
return customGetLocalIdent(loaderContext, localIdentName, exportName, {
regExp: options.localIdentRegExp,
hashPrefix: options.hashPrefix || '',
context: options.context,
});
},
}),
];

if (options.import !== false) {
plugins.push(importParser(parserOptions));
}

if (options.url !== false) {
plugins.push(urlParser(parserOptions));
}

plugins.push(icssParser(parserOptions));

postcss(plugins)
.process(content, {
// we need a prefix to avoid path rewriting of PostCSS
from: `/css-loader!${loaderUtils
.getRemainingRequest(this)
.split('!')
.pop()}`,
to: loaderUtils
.getCurrentRequest(this)
.split('!')
.pop(),
map: options.sourceMap
? {
prev: map,
sourcesContent: true,
inline: false,
annotation: false,
}
: null,
})
.then((result) => {
result
.warnings()
.forEach((warning) => this.emitWarning(new Warning(warning)));

// for importing CSS
const importUrlPrefix = getImportPrefix(this, options);

let exportJs = compileExports(
result,
parserOptions.exports,
placeholderImportItemReplacer(
this,
result,
parserOptions.importItems,
importUrlPrefix,
options.exportOnlyLocals
),
Expand All @@ -69,10 +143,10 @@ module.exports = function loader(content, map) {
return callback(null, exportJs);
}

let cssAsString = JSON.stringify(result.source);
let cssAsString = JSON.stringify(result.css);

const alreadyImported = {};
const importJs = result.importItems
const importJs = parserOptions.importItems
.filter((imp) => {
if (!imp.media) {
if (alreadyImported[imp.url]) {
Expand Down Expand Up @@ -102,48 +176,61 @@ module.exports = function loader(content, map) {
.join('\n');

cssAsString = cssAsString.replace(
result.importItemRegExpG,
placeholderImportItemReplacer(this, result, importUrlPrefix)
placholderRegExps.importItemG,
placeholderImportItemReplacer(
this,
parserOptions.importItems,
importUrlPrefix
)
);

// helper for ensuring valid CSS strings from requires
let urlEscapeHelper = '';

if (
options.url !== false &&
result.urlItems &&
result.urlItems.length > 0
parserOptions.urlItems &&
parserOptions.urlItems.length > 0
) {
urlEscapeHelper = `var escape = require(${loaderUtils.stringifyRequest(
this,
require.resolve('./runtime/escape.js')
)});\n`;

cssAsString = cssAsString.replace(result.urlItemRegExpG, (item) => {
const match = result.urlItemRegExp.exec(item);
let idx = +match[1];
const urlItem = result.urlItems[idx];
const { url } = urlItem;
idx = url.indexOf('?#');
if (idx < 0) {
idx = url.indexOf('#');
}
let urlRequest;
if (idx > 0) {
// idx === 0 is catched by isUrlRequest
// in cases like url('webfont.eot?#iefix')
urlRequest = url.substr(0, idx);
cssAsString = cssAsString.replace(
placholderRegExps.urlItemG,
(item) => {
const match = placholderRegExps.urlItem.exec(item);
let idx = +match[1];
const urlItem = parserOptions.urlItems[idx];
const { url } = urlItem;

idx = url.indexOf('?#');

if (idx < 0) {
idx = url.indexOf('#');
}

let urlRequest;

if (idx > 0) {
// idx === 0 is catched by isUrlRequest
// in cases like url('webfont.eot?#iefix')
urlRequest = url.substr(0, idx);
return `" + escape(require(${loaderUtils.stringifyRequest(
this,
urlRequest
)}) + "${url.substr(idx)}") + "`;
}

urlRequest = url;

return `" + escape(require(${loaderUtils.stringifyRequest(
this,
urlRequest
)}) + "${url.substr(idx)}") + "`;
)})) + "`;
}
urlRequest = url;
return `" + escape(require(${loaderUtils.stringifyRequest(
this,
urlRequest
)})) + "`;
});
);
}

if (exportJs) {
Expand All @@ -154,7 +241,8 @@ module.exports = function loader(content, map) {
if (sourceMap && result.map) {
/* eslint-disable no-param-reassign */
// Add a SourceMap
({ map } = result);
map = result.map.toJSON();

if (map.sources) {
map.sources = map.sources.map(
(source) =>
Expand All @@ -166,12 +254,14 @@ module.exports = function loader(content, map) {
);
map.sourceRoot = '';
}

map.file = map.file
.split('!')
.pop()
.replace(/\\/g, '/');
map = JSON.stringify(map);
/* eslint-enable no-param-reassign */

moduleJs = `exports.push([module.id, ${cssAsString}, "", ${map}]);`;
} else {
moduleJs = `exports.push([module.id, ${cssAsString}, ""]);`;
Expand All @@ -188,6 +278,10 @@ module.exports = function loader(content, map) {
`// module\n${moduleJs}\n\n` +
`// exports\n${exportJs}`
);
}
);
})
.catch((error) => {
callback(
error.name === 'CssSyntaxError' ? new CssSyntaxError(error) : error
);
});
};
120 changes: 0 additions & 120 deletions lib/processCss.js

This file was deleted.

0 comments on commit ee409c5

Please sign in to comment.