Skip to content

refactor: url parser #852

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 37 additions & 46 deletions src/plugins/postcss-url-parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,52 +3,31 @@ import valueParser from 'postcss-value-parser';

const pluginName = 'postcss-url-parser';

function getArg(nodes) {
return nodes.length !== 0 && nodes[0].type === 'string'
? nodes[0].value
: valueParser.stringify(nodes);
}

function walkUrls(parsed, callback) {
parsed.walk((node) => {
if (node.type !== 'function' || node.value.toLowerCase() !== 'url') {
return;
}

const url =
node.nodes.length !== 0 && node.nodes[0].type === 'string'
? node.nodes[0].value
: valueParser.stringify(node.nodes);

/* eslint-disable */
node.before = '';
node.after = '';
/* eslint-enable */

callback(node, url);
callback(node, getArg(node.nodes));

// Do not traverse inside url
// eslint-disable-next-line consistent-return
return false;
});
}

function filterUrls(parsed, result, decl, filter) {
const urls = [];

walkUrls(parsed, (node, url) => {
if (url.trim().replace(/\\[\r\n]/g, '').length === 0) {
result.warn(`Unable to find uri in '${decl.toString()}'`, {
node: decl,
});

return;
}

if (filter && !filter(url)) {
return;
}

urls.push(url);
});

return urls;
}

function walkDeclsWithUrl(css, result, filter) {
const items = [];

Expand All @@ -58,13 +37,29 @@ function walkDeclsWithUrl(css, result, filter) {
}

const parsed = valueParser(decl.value);
const values = filterUrls(parsed, result, decl, filter);
const urls = [];

walkUrls(parsed, (node, url) => {
if (url.trim().replace(/\\[\r\n]/g, '').length === 0) {
result.warn(`Unable to find uri in '${decl.toString()}'`, {
node: decl,
});

if (values.length === 0) {
return;
}

if (filter && !filter(url)) {
return;
}

urls.push(url);
});

if (urls.length === 0) {
return;
}

items.push({ decl, parsed, values });
items.push({ decl, parsed, urls });
});

return items;
Expand All @@ -74,19 +69,6 @@ function flatten(array) {
return array.reduce((acc, d) => [...acc, ...d], []);
}

function mapUrls(parsed, map) {
walkUrls(parsed, (node, content) => {
const placeholder = map(content);

if (!placeholder) {
return;
}

// eslint-disable-next-line no-param-reassign
node.nodes = [{ type: 'word', value: map(content) }];
});
}

function uniq(array) {
return array.reduce(
(acc, d) => (acc.indexOf(d) === -1 ? [...acc, d] : acc),
Expand All @@ -99,7 +81,7 @@ export default postcss.plugin(
(options = {}) =>
function process(css, result) {
const traversed = walkDeclsWithUrl(css, result, options.filter);
const paths = uniq(flatten(traversed.map((item) => item.values)));
const paths = uniq(flatten(traversed.map((item) => item.urls)));

if (paths.length === 0) {
return;
Expand All @@ -120,7 +102,16 @@ export default postcss.plugin(
});

traversed.forEach((item) => {
mapUrls(item.parsed, (value) => urls[value]);
walkUrls(item.parsed, (node, url) => {
const value = urls[url];

if (!value) {
return;
}

// eslint-disable-next-line no-param-reassign
node.nodes = [{ type: 'word', value }];
});

// eslint-disable-next-line no-param-reassign
item.decl.value = item.parsed.toString();
Expand Down