94 lines
3.0 KiB
JavaScript
Raw Normal View History

2024-01-29 09:26:07 +08:00
function ampCount(selector) {
let cnt = 0;
for (let i = 0; i < selector.length; ++i) {
if (selector[i] === '&')
++cnt;
}
return cnt;
}
/**
* Don't just use ',' to separate css selector. For example:
* x:(a, b) {} will be split into 'x:(a' and 'b)', which is not expected.
* Make sure comma doesn't exist inside parentheses.
*/
const separatorRegex = /\s*,(?![^(]*\))\s*/g;
const extraSpaceRegex = /\s+/g;
/**
* selector must includes '&'
* selector is trimmed
* every part of amp is trimmed
*/
function resolveSelectorWithAmp(amp, selector) {
const nextAmp = [];
selector.split(separatorRegex).forEach(partialSelector => {
let round = ampCount(partialSelector);
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
if (!round) {
amp.forEach(partialAmp => {
nextAmp.push(
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
(partialAmp && partialAmp + ' ') + partialSelector);
});
return;
}
else if (round === 1) {
amp.forEach(partialAmp => {
nextAmp.push(partialSelector.replace('&', partialAmp));
});
return;
}
let partialNextAmp = [
partialSelector
];
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
while (round--) {
const nextPartialNextAmp = [];
partialNextAmp.forEach(selectorItr => {
amp.forEach(partialAmp => {
nextPartialNextAmp.push(selectorItr.replace('&', partialAmp));
});
});
partialNextAmp = nextPartialNextAmp;
}
partialNextAmp.forEach(part => nextAmp.push(part));
});
return nextAmp;
}
/**
* selector mustn't includes '&'
* selector is trimmed
*/
function resolveSelector(amp, selector) {
const nextAmp = [];
selector.split(separatorRegex).forEach(partialSelector => {
amp.forEach(partialAmp => {
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
nextAmp.push(((partialAmp && partialAmp + ' ') + partialSelector));
});
});
return nextAmp;
}
export function parseSelectorPath(selectorPaths) {
let amp = [''];
selectorPaths.forEach(selector => {
// eslint-disable-next-line
selector = selector && selector.trim();
if (
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
!selector) {
/**
* if it's a empty selector, do nothing
*/
return;
}
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
if (selector.includes('&')) {
amp = resolveSelectorWithAmp(amp, selector);
}
else {
amp = resolveSelector(amp, selector);
}
});
return amp.join(', ').replace(extraSpaceRegex, ' ');
}