|
|
"use strict";
Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0;
var _util = require("util");
var _postcss = _interopRequireDefault(require("postcss"));
var _postcssValueParser = _interopRequireDefault(require("postcss-value-parser"));
var _utils = require("../utils");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const pluginName = 'postcss-url-parser'; const isUrlFunc = /url/i; const isImageSetFunc = /^(?:-webkit-)?image-set$/i; const needParseDecl = /(?:url|(?:-webkit-)?image-set)\(/i;
function getNodeFromUrlFunc(node) { return node.nodes && node.nodes[0]; }
function shouldHandleRule(rule, decl, result) { // https://www.w3.org/TR/css-syntax-3/#typedef-url-token
if (rule.url.replace(/^[\s]+|[\s]+$/g, '').length === 0) { result.warn(`Unable to find uri in '${decl.toString()}'`, { node: decl }); return false; }
if (!(0, _utils.isUrlRequestable)(rule.url)) { return false; }
return true; }
function walkCss(css, result, options, callback) { const accumulator = []; css.walkDecls(decl => { if (!needParseDecl.test(decl.value)) { return; }
const parsed = (0, _postcssValueParser.default)(decl.value); parsed.walk(node => { if (node.type !== 'function') { return; }
if (isUrlFunc.test(node.value)) { const { nodes } = node; const isStringValue = nodes.length !== 0 && nodes[0].type === 'string'; const url = isStringValue ? nodes[0].value : _postcssValueParser.default.stringify(nodes); const rule = { node: getNodeFromUrlFunc(node), url, needQuotes: false, isStringValue };
if (shouldHandleRule(rule, decl, result)) { accumulator.push({ decl, rule, parsed }); } // Do not traverse inside `url`
// eslint-disable-next-line consistent-return
return false; } else if (isImageSetFunc.test(node.value)) { for (const nNode of node.nodes) { const { type, value } = nNode;
if (type === 'function' && isUrlFunc.test(value)) { const { nodes } = nNode; const isStringValue = nodes.length !== 0 && nodes[0].type === 'string'; const url = isStringValue ? nodes[0].value : _postcssValueParser.default.stringify(nodes); const rule = { node: getNodeFromUrlFunc(nNode), url, needQuotes: false, isStringValue };
if (shouldHandleRule(rule, decl, result)) { accumulator.push({ decl, rule, parsed }); } } else if (type === 'string') { const rule = { node: nNode, url: value, needQuotes: true, isStringValue: true };
if (shouldHandleRule(rule, decl, result)) { accumulator.push({ decl, rule, parsed }); } } } // Do not traverse inside `image-set`
// eslint-disable-next-line consistent-return
return false; } }); }); callback(null, accumulator); }
const asyncWalkCss = (0, _util.promisify)(walkCss);
var _default = _postcss.default.plugin(pluginName, options => async (css, result) => { const parsedResults = await asyncWalkCss(css, result, options);
if (parsedResults.length === 0) { return Promise.resolve(); }
const tasks = []; const imports = new Map(); const replacements = new Map(); let hasUrlImportHelper = false;
for (const parsedResult of parsedResults) { const { url, isStringValue } = parsedResult.rule; let normalizedUrl = url; let prefix = ''; const queryParts = normalizedUrl.split('!');
if (queryParts.length > 1) { normalizedUrl = queryParts.pop(); prefix = queryParts.join('!'); }
normalizedUrl = (0, _utils.normalizeUrl)(normalizedUrl, isStringValue);
if (!options.filter(normalizedUrl)) { // eslint-disable-next-line no-continue
continue; }
if (!hasUrlImportHelper) { options.imports.push({ importName: '___CSS_LOADER_GET_URL_IMPORT___', url: options.urlHandler(require.resolve('../runtime/getUrl.js')), index: -1 }); hasUrlImportHelper = true; }
const splittedUrl = normalizedUrl.split(/(\?)?#/); const [pathname, query, hashOrQuery] = splittedUrl; let hash = query ? '?' : ''; hash += hashOrQuery ? `#${hashOrQuery}` : ''; const request = (0, _utils.requestify)(pathname, options.rootContext); tasks.push((async () => { const { resolver, context } = options; const resolvedUrl = await (0, _utils.resolveRequests)(resolver, context, [...new Set([request, normalizedUrl])]); return { url: resolvedUrl, prefix, hash, parsedResult }; })()); }
const results = await Promise.all(tasks);
for (let index = 0; index <= results.length - 1; index++) { const { url, prefix, hash, parsedResult: { decl, rule, parsed } } = results[index]; const newUrl = prefix ? `${prefix}!${url}` : url; const importKey = newUrl; let importName = imports.get(importKey);
if (!importName) { importName = `___CSS_LOADER_URL_IMPORT_${imports.size}___`; imports.set(importKey, importName); options.imports.push({ importName, url: options.urlHandler(newUrl), index }); }
const { needQuotes } = rule; const replacementKey = JSON.stringify({ newUrl, hash, needQuotes }); let replacementName = replacements.get(replacementKey);
if (!replacementName) { replacementName = `___CSS_LOADER_URL_REPLACEMENT_${replacements.size}___`; replacements.set(replacementKey, replacementName); options.replacements.push({ replacementName, importName, hash, needQuotes }); } // eslint-disable-next-line no-param-reassign
rule.node.type = 'word'; // eslint-disable-next-line no-param-reassign
rule.node.value = replacementName; // eslint-disable-next-line no-param-reassign
decl.value = parsed.toString(); }
return Promise.resolve(); });
exports.default = _default;
|