UNPKG

reboost

Version:

A super fast dev server for rapid web development

141 lines (140 loc) 6.53 kB
"use strict"; // Heavily inspired by (kinda copy of) these // - https://github.com/webpack-contrib/css-loader/blob/master/src/plugins/postcss-import-parser.js // - https://github.com/webpack-contrib/css-loader/blob/master/src/plugins/postcss-url-parser.js Object.defineProperty(exports, "__esModule", { value: true }); exports.urlParser = exports.hasURLsIn = exports.importParser = exports.hasImportsIn = void 0; const tslib_1 = require("tslib"); const postcss_value_parser_1 = (0, tslib_1.__importDefault)(require("postcss-value-parser")); const shouldHandleURL = (url, testerFn) => { if (/^[a-z][a-z0-9+.-]*:/i.test(url)) return false; return testerFn(url); }; const importRE = /@import/i; const hasImportsIn = (css) => importRE.test(css); exports.hasImportsIn = hasImportsIn; const importParser = (imports, testerFn) => ({ postcssPlugin: 'import-parser', prepare: (result) => ({ AtRule: { import(node) { if (node.parent.type !== 'root') return; if (node.nodes) { result.warn('Import statement should not contain child nodes. Please fix your import statement (check for missing semicolons)', { node, word: '@import' }); return; } const [firstNode, ...mediaNodes] = (0, postcss_value_parser_1.default)(node.params).nodes; if ((!firstNode && !mediaNodes.length) || !['string', 'function'].includes(firstNode.type)) { result.warn('Unable to resolve URL of the import statement', { node }); return; } let importPath; if (firstNode.type === 'string') { importPath = firstNode.value; } else { if (firstNode.value.toLowerCase() !== 'url') { result.warn('Unable to resolve URL of the import statement', { node }); return; } const { nodes } = firstNode; const isString = nodes.length !== 0 && nodes[0].type === 'string'; importPath = isString ? nodes[0].value : postcss_value_parser_1.default.stringify(nodes); } if (!importPath.trim().length) { result.warn('The import statement imports nothing', { node }); return; } if (shouldHandleURL(importPath, testerFn)) { imports.push({ url: importPath, media: postcss_value_parser_1.default.stringify(mediaNodes).trim().toLowerCase() }); node.remove(); } } } }) }); exports.importParser = importParser; const urlRE = /url/i; const imageSetRE = /(-webkit-)?image-set/i; const hasURLOrImageSet = /(url|(-webkit-)?image-set)\(/i; const getFirstNodeOf = ({ nodes }) => nodes && nodes[0]; const getURL = ({ nodes }) => { const isString = nodes.length !== 0 && nodes[0].type === 'string'; const url = isString ? nodes[0].value : postcss_value_parser_1.default.stringify(nodes); return url; }; const isBlankURL = (url, result, node) => { if (url.trim()) return false; result.warn('The url is blank', { node }); return true; }; const hasURLsIn = (css) => hasURLOrImageSet.test(css); exports.hasURLsIn = hasURLsIn; const urlParser = (urls, testerFn) => ({ postcssPlugin: 'url-parser', prepare: (result) => { const replacements = []; let idx = 0; const makeReplacement = (decl, parsedValue, node, quoted) => { const replacement = `__URL_REPLACEMENT_${idx++}__`; node.type = 'word'; node.value = quoted ? `"${replacement}"` : replacement; replacements.push([decl, parsedValue.toString()]); return replacement; }; return { Declaration(decl) { if (!hasURLOrImageSet.test(decl.value)) return; const parsedValue = (0, postcss_value_parser_1.default)(decl.value); parsedValue.walk((node) => { if (node.type !== 'function') return; if (urlRE.test(node.value)) { const url = getURL(node); if (!isBlankURL(url, result, decl) && shouldHandleURL(url, testerFn)) { urls.push({ url, replacement: makeReplacement(decl, parsedValue, getFirstNodeOf(node), false) }); } return false; } else if (imageSetRE.test(node.value)) { node.nodes.forEach((nestedNode) => { if (nestedNode.type === 'function' && urlRE.test(nestedNode.value)) { const url = getURL(nestedNode); if (!isBlankURL(url, result, decl) && shouldHandleURL(url, testerFn)) { urls.push({ url, replacement: makeReplacement(decl, parsedValue, getFirstNodeOf(nestedNode), false) }); } } else if (nestedNode.type === 'string') { const url = nestedNode.value; if (!isBlankURL(url, result, decl) && shouldHandleURL(url, testerFn)) { urls.push({ url, replacement: makeReplacement(decl, parsedValue, nestedNode, true) }); } } }); return false; } }); }, OnceExit() { replacements.forEach(([decl, replacement]) => decl.value = replacement); } }; } }); exports.urlParser = urlParser;