@stylable/core
Version:
CSS for Components
119 lines • 4.9 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.transformInlineCustomSelectors = exports.transformInlineCustomSelectorMap = void 0;
const css_selector_parser_1 = require("@tokey/css-selector-parser");
const lodash_clonedeep_1 = __importDefault(require("lodash.clonedeep"));
function transformInlineCustomSelectorMap(customSelectors, report) {
const result = {};
const link = (name, path) => {
const ast = customSelectors[name];
if (!ast) {
return;
}
result[name] = transformInlineCustomSelectors(ast, (nestedName) => {
const selector = `:--${nestedName}`;
if (path.includes(selector)) {
// loop!: report & preserve source selector
report({ type: 'circular', path });
return (0, css_selector_parser_1.parseCssSelector)(selector);
}
if (!result[nestedName]) {
link(nestedName, [...path, selector]);
}
return result[nestedName];
}, ({ type, unknown }) => report({ type, origin: name, unknown }));
};
for (const name of Object.keys(customSelectors)) {
link(name, [`:--${name}`]);
}
return result;
}
exports.transformInlineCustomSelectorMap = transformInlineCustomSelectorMap;
function isCustomSelectorNode(node) {
return node.type === 'pseudo_class' && node.value.startsWith('--');
}
/**
* Takes a list of selectors and a function that returns a selector
* against a custom selector name.
*
* Then search for inline custom selectors (e.g. ":--custom") and
* replaces them with the retrieved selectors it receives
*/
function transformInlineCustomSelectors(inputSelectors, getCustomSelector, report) {
const result = [];
for (const selector of inputSelectors) {
result.push(...transformInlineCustomSelector(selector, getCustomSelector, report));
}
return result;
}
exports.transformInlineCustomSelectors = transformInlineCustomSelectors;
function transformInlineCustomSelector(inputSelector, getCustomSelector, report) {
const insertions = [];
// get insertion points
(0, css_selector_parser_1.walk)(inputSelector, (node, index, _nodes, parents) => {
if (isCustomSelectorNode(node)) {
const name = node.value.slice(2);
const targetSelectors = getCustomSelector(name);
if (!targetSelectors) {
report({ type: 'unknown', origin: '', unknown: name });
}
else if (targetSelectors.length !== 0) {
const parent = parents[parents.length - 1];
if (parent && 'nodes' in parent && parent.nodes) {
let selectorIndex = 0;
insertions.push((progress) => {
if (progress) {
selectorIndex++;
}
const overflow = selectorIndex === targetSelectors.length;
if (overflow) {
selectorIndex = 0;
}
const currentSelector = targetSelectors[selectorIndex];
currentSelector.before = currentSelector.after = '';
parent.nodes[index] = currentSelector;
return overflow;
});
}
}
}
});
// permute selectors
const output = [];
if (insertions.length) {
// save first permutation
insertions.forEach((updateSelector) => updateSelector(false));
output.push((0, lodash_clonedeep_1.default)(inputSelector));
// collect rest of permutations
let run = true;
while (run) {
let progressIdx = 0;
for (let i = 0; i < insertions.length; ++i) {
const updateSelector = insertions[i];
const moveToNext = i === progressIdx;
const overflow = updateSelector(moveToNext);
if (overflow) {
if (progressIdx < insertions.length - 1) {
// advance next insertion point
progressIdx++;
}
else {
// finish run over all permutations
run = false;
return output;
}
}
else {
// no need to update any farther this round
break;
}
}
output.push((0, lodash_clonedeep_1.default)(inputSelector));
}
}
return [inputSelector];
}
//# sourceMappingURL=custom-selector.js.map