141 lines
2.9 KiB
JavaScript
141 lines
2.9 KiB
JavaScript
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
|
|
};
|
|
};
|