You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
141 lines
2.9 KiB
141 lines
2.9 KiB
2 years ago
|
const valueParser = require("postcss-value-parser");
|
||
|
|
||
|
const { stringify } = valueParser;
|
||
|
|
||
|
function getUrl(nodes) {
|
||
|
let url = "";
|
||
|
let urlEnd = 0;
|
||
|
|
||
|
for (let i = 0; i < nodes.length; i += 1) {
|
||
|
const node = nodes[i];
|
||
|
if (node.type === "string") {
|
||
|
if (i !== 0) {
|
||
|
throw Error(`Invalid "svg-load(${stringify(nodes)})" definition`);
|
||
|
}
|
||
|
url = node.value;
|
||
|
urlEnd = i + 1;
|
||
|
break;
|
||
|
}
|
||
|
if (node.type === "div" && node.value === ",") {
|
||
|
if (i === 0) {
|
||
|
throw Error(`Invalid "svg-load(${stringify(nodes)})" definition`);
|
||
|
}
|
||
|
urlEnd = i;
|
||
|
break;
|
||
|
}
|
||
|
url += stringify(node);
|
||
|
urlEnd += 1;
|
||
|
}
|
||
|
|
||
|
return {
|
||
|
url,
|
||
|
urlEnd
|
||
|
};
|
||
|
}
|
||
|
|
||
|
function getParamChunks(nodes) {
|
||
|
const list = [];
|
||
|
const lastArg = nodes.reduce((arg, node) => {
|
||
|
if (node.type === "word" || node.type === "string") {
|
||
|
return arg + node.value;
|
||
|
}
|
||
|
if (node.type === "space") {
|
||
|
return arg + " ";
|
||
|
}
|
||
|
if (node.type === "div" && node.value === ",") {
|
||
|
list.push(arg);
|
||
|
return "";
|
||
|
}
|
||
|
return arg + stringify(node);
|
||
|
}, "");
|
||
|
|
||
|
return list.concat(lastArg);
|
||
|
}
|
||
|
|
||
|
function splitParams(list) {
|
||
|
const params = {};
|
||
|
|
||
|
list.reduce((sep, arg) => {
|
||
|
if (!arg) {
|
||
|
throw Error(`Expected parameter`);
|
||
|
}
|
||
|
|
||
|
if (!sep) {
|
||
|
if (arg.indexOf(":") !== -1) {
|
||
|
sep = ":";
|
||
|
} else if (arg.indexOf("=") !== -1) {
|
||
|
sep = "=";
|
||
|
} else {
|
||
|
throw Error(`Expected ":" or "=" separator in "${arg}"`);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
const pair = arg.split(sep);
|
||
|
if (pair.length !== 2) {
|
||
|
throw Error(`Expected "${sep}" separator in "${arg}"`);
|
||
|
}
|
||
|
params[pair[0].trim()] = pair[1].trim();
|
||
|
|
||
|
return sep;
|
||
|
}, null);
|
||
|
|
||
|
return params;
|
||
|
}
|
||
|
|
||
|
function getLoader(parsedValue, valueNode) {
|
||
|
if (!valueNode.nodes.length) {
|
||
|
throw Error(`Invalid "svg-load()" statement`);
|
||
|
}
|
||
|
|
||
|
// parse url
|
||
|
const { url, urlEnd } = getUrl(valueNode.nodes);
|
||
|
|
||
|
// parse params
|
||
|
const paramsNodes = valueNode.nodes.slice(urlEnd + 1);
|
||
|
const params =
|
||
|
urlEnd !== valueNode.nodes.length
|
||
|
? splitParams(getParamChunks(paramsNodes))
|
||
|
: {};
|
||
|
|
||
|
return {
|
||
|
url,
|
||
|
params,
|
||
|
valueNode,
|
||
|
parsedValue
|
||
|
};
|
||
|
}
|
||
|
|
||
|
function getInliner(parsedValue, valueNode) {
|
||
|
if (!valueNode.nodes.length) {
|
||
|
throw Error(`Invalid "svg-inline()" statement`);
|
||
|
}
|
||
|
const name = valueNode.nodes[0].value;
|
||
|
|
||
|
return {
|
||
|
name,
|
||
|
valueNode,
|
||
|
parsedValue
|
||
|
};
|
||
|
}
|
||
|
|
||
|
module.exports = function parseDeclValue(value) {
|
||
|
const loaders = [];
|
||
|
const inliners = [];
|
||
|
const parsedValue = valueParser(value);
|
||
|
|
||
|
parsedValue.walk(valueNode => {
|
||
|
if (valueNode.type === "function") {
|
||
|
if (valueNode.value === "svg-load") {
|
||
|
loaders.push(getLoader(parsedValue, valueNode));
|
||
|
} else if (valueNode.value === "svg-inline") {
|
||
|
inliners.push(getInliner(parsedValue, valueNode));
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
|
||
|
return {
|
||
|
loaders,
|
||
|
inliners
|
||
|
};
|
||
|
};
|