From fc93965e15eb24496d4cd88ffd405881b852cc67 Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Mon, 26 Nov 2018 15:00:50 +0300 Subject: [PATCH] refactor: move value parser plugin to own file --- lib/postcss-css-loader-parser.js | 139 +++++++++++++++++++++++++++++++ lib/processCss.js | 138 +----------------------------- 2 files changed, 142 insertions(+), 135 deletions(-) create mode 100644 lib/postcss-css-loader-parser.js diff --git a/lib/postcss-css-loader-parser.js b/lib/postcss-css-loader-parser.js new file mode 100644 index 00000000..f7ff14b5 --- /dev/null +++ b/lib/postcss-css-loader-parser.js @@ -0,0 +1,139 @@ +const postcss = require('postcss'); +const valueParser = require('postcss-value-parser'); +const icssUtils = require('icss-utils'); +const Tokenizer = require('css-selector-tokenizer'); +const loaderUtils = require('loader-utils'); + +module.exports = postcss.plugin( + 'postcss-css-loader-parser', + (options) => (css) => { + const imports = {}; + let exports = {}; + const importItems = []; + const urlItems = []; + + function replaceImportsInString(str) { + if (options.import) { + const tokens = valueParser(str); + tokens.walk((node) => { + if (node.type !== 'word') { + return; + } + const token = node.value; + const importIndex = imports[`$${token}`]; + if (typeof importIndex === 'number') { + // eslint-disable-next-line no-param-reassign + node.value = `___CSS_LOADER_IMPORT___${importIndex}___`; + } + }); + return tokens.toString(); + } + return str; + } + + if (options.import) { + css.walkAtRules(/^import$/i, (rule) => { + const values = Tokenizer.parseValues(rule.params); + let [url] = values.nodes[0].nodes; + if (url && url.type === 'url') { + ({ url } = url); + } else if (url && url.type === 'string') { + url = url.value; + } else throw rule.error(`Unexpected format ${rule.params}`); + if (!url.replace(/\s/g, '').length) { + return; + } + values.nodes[0].nodes.shift(); + const mediaQuery = Tokenizer.stringifyValues(values); + + if (loaderUtils.isUrlRequest(url)) { + url = loaderUtils.urlToRequest(url); + } + + importItems.push({ + url, + mediaQuery, + }); + rule.remove(); + }); + } + + const icss = icssUtils.extractICSS(css); + exports = icss.icssExports; + Object.keys(icss.icssImports).forEach((key) => { + const url = loaderUtils.parseString(key); + Object.keys(icss.icssImports[key]).forEach((prop) => { + imports[`$${prop}`] = importItems.length; + importItems.push({ + url, + export: icss.icssImports[key][prop], + }); + }); + }); + + Object.keys(exports).forEach((exportName) => { + exports[exportName] = replaceImportsInString(exports[exportName]); + }); + + function processNode(item) { + switch (item.type) { + case 'value': + item.nodes.forEach(processNode); + break; + case 'nested-item': + item.nodes.forEach(processNode); + break; + case 'item': { + const importIndex = imports[`$${item.name}`]; + if (typeof importIndex === 'number') { + // eslint-disable-next-line no-param-reassign + item.name = `___CSS_LOADER_IMPORT___${importIndex}___`; + } + break; + } + case 'url': + if ( + options.url && + item.url.replace(/\s/g, '').length && + !/^#/.test(item.url) && + loaderUtils.isUrlRequest(item.url) + ) { + // Strip quotes, they will be re-added if the module needs them + /* eslint-disable no-param-reassign */ + item.stringType = ''; + delete item.innerSpacingBefore; + delete item.innerSpacingAfter; + const { url } = item; + item.url = `___CSS_LOADER_URL___${urlItems.length}___`; + /* eslint-enable no-param-reassign */ + urlItems.push({ + url, + }); + } + break; + // no default + } + } + + css.walkDecls((decl) => { + const values = Tokenizer.parseValues(decl.value); + values.nodes.forEach((value) => { + value.nodes.forEach(processNode); + }); + // eslint-disable-next-line no-param-reassign + decl.value = Tokenizer.stringifyValues(values); + }); + css.walkAtRules((atrule) => { + if (typeof atrule.params === 'string') { + // eslint-disable-next-line no-param-reassign + atrule.params = replaceImportsInString(atrule.params); + } + }); + + /* eslint-disable no-param-reassign */ + options.importItems = importItems; + options.urlItems = urlItems; + options.exports = exports; + /* eslint-enable no-param-reassign */ + } +); diff --git a/lib/processCss.js b/lib/processCss.js index 1f665f4d..f21ca025 100644 --- a/lib/processCss.js +++ b/lib/processCss.js @@ -2,151 +2,19 @@ MIT License http://www.opensource.org/licenses/mit-license.php Author Tobias Koppers @sokra */ -const Tokenizer = require('css-selector-tokenizer'); const postcss = require('postcss'); const loaderUtils = require('loader-utils'); -const icssUtils = require('icss-utils'); 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 valueParser = require('postcss-value-parser'); + +const cssLoaderParser = require('./postcss-css-loader-parser'); const CssSyntaxError = require('./CssSyntaxError'); const getLocalIdent = require('./getLocalIdent'); -const parserPlugin = postcss.plugin('css-loader-parser', (options) => (css) => { - const imports = {}; - let exports = {}; - const importItems = []; - const urlItems = []; - - function replaceImportsInString(str) { - if (options.import) { - const tokens = valueParser(str); - tokens.walk((node) => { - if (node.type !== 'word') { - return; - } - const token = node.value; - const importIndex = imports[`$${token}`]; - if (typeof importIndex === 'number') { - // eslint-disable-next-line no-param-reassign - node.value = `___CSS_LOADER_IMPORT___${importIndex}___`; - } - }); - return tokens.toString(); - } - return str; - } - - if (options.import) { - css.walkAtRules(/^import$/i, (rule) => { - const values = Tokenizer.parseValues(rule.params); - let [url] = values.nodes[0].nodes; - if (url && url.type === 'url') { - ({ url } = url); - } else if (url && url.type === 'string') { - url = url.value; - } else throw rule.error(`Unexpected format ${rule.params}`); - if (!url.replace(/\s/g, '').length) { - return; - } - values.nodes[0].nodes.shift(); - const mediaQuery = Tokenizer.stringifyValues(values); - - if (loaderUtils.isUrlRequest(url)) { - url = loaderUtils.urlToRequest(url); - } - - importItems.push({ - url, - mediaQuery, - }); - rule.remove(); - }); - } - - const icss = icssUtils.extractICSS(css); - exports = icss.icssExports; - Object.keys(icss.icssImports).forEach((key) => { - const url = loaderUtils.parseString(key); - Object.keys(icss.icssImports[key]).forEach((prop) => { - imports[`$${prop}`] = importItems.length; - importItems.push({ - url, - export: icss.icssImports[key][prop], - }); - }); - }); - - Object.keys(exports).forEach((exportName) => { - exports[exportName] = replaceImportsInString(exports[exportName]); - }); - - function processNode(item) { - switch (item.type) { - case 'value': - item.nodes.forEach(processNode); - break; - case 'nested-item': - item.nodes.forEach(processNode); - break; - case 'item': { - const importIndex = imports[`$${item.name}`]; - if (typeof importIndex === 'number') { - // eslint-disable-next-line no-param-reassign - item.name = `___CSS_LOADER_IMPORT___${importIndex}___`; - } - break; - } - case 'url': - if ( - options.url && - item.url.replace(/\s/g, '').length && - !/^#/.test(item.url) && - loaderUtils.isUrlRequest(item.url) - ) { - // Strip quotes, they will be re-added if the module needs them - /* eslint-disable no-param-reassign */ - item.stringType = ''; - delete item.innerSpacingBefore; - delete item.innerSpacingAfter; - const { url } = item; - item.url = `___CSS_LOADER_URL___${urlItems.length}___`; - /* eslint-enable no-param-reassign */ - urlItems.push({ - url, - }); - } - break; - // no default - } - } - - css.walkDecls((decl) => { - const values = Tokenizer.parseValues(decl.value); - values.nodes.forEach((value) => { - value.nodes.forEach(processNode); - }); - // eslint-disable-next-line no-param-reassign - decl.value = Tokenizer.stringifyValues(values); - }); - css.walkAtRules((atrule) => { - if (typeof atrule.params === 'string') { - // eslint-disable-next-line no-param-reassign - atrule.params = replaceImportsInString(atrule.params); - } - }); - - /* eslint-disable no-param-reassign */ - options.importItems = importItems; - options.urlItems = urlItems; - options.exports = exports; - /* eslint-enable no-param-reassign */ -}); - module.exports = function processCss(inputSource, inputMap, options, callback) { const { query } = options; const { context, localIdentRegExp } = query; @@ -197,7 +65,7 @@ module.exports = function processCss(inputSource, inputMap, options, callback) { ); }, }), - parserPlugin(parserOptions), + cssLoaderParser(parserOptions), ]); pipeline