@stylable/core
Version:
CSS for Components
165 lines • 7.98 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.transformCustomSelectorInline = exports.getCustomSelectorNames = exports.getCustomSelectorExpended = exports.getCustomSelectors = exports.getCustomSelector = exports.isScoped = exports.hooks = exports.CUSTOM_SELECTOR_RE = exports.diagnostics = void 0;
const plugable_record_1 = require("../helpers/plugable-record");
const feature_1 = require("./feature");
const custom_selector_1 = require("../helpers/custom-selector");
const selector_1 = require("../helpers/selector");
const postcss = __importStar(require("postcss"));
const css_selector_parser_1 = require("@tokey/css-selector-parser");
const diagnostics_1 = require("../diagnostics");
exports.diagnostics = {
UNKNOWN_CUSTOM_SELECTOR: (0, diagnostics_1.createDiagnosticReporter)('18001', 'error', (selector) => `The selector '${selector}' is undefined`),
};
const dataKey = plugable_record_1.plugableRecord.key('st-custom-selector');
exports.CUSTOM_SELECTOR_RE = /:--[\w-]+/g;
// HOOKS
exports.hooks = (0, feature_1.createFeature)({
metaInit({ meta }) {
plugable_record_1.plugableRecord.set(meta.data, dataKey, {});
},
analyzeAtRule({ context, atRule, analyzeRule }) {
const params = atRule.params.split(/\s/);
const customSelector = params.shift();
if (customSelector && customSelector.match(exports.CUSTOM_SELECTOR_RE)) {
const selector = atRule.params.replace(customSelector, '').trim();
const ast = (0, selector_1.parseSelectorWithCache)(selector, { clone: true });
const isScoped = analyzeRule(postcss.rule({ selector, source: atRule.source }), {
isScoped: false,
originalNode: atRule,
});
const analyzed = plugable_record_1.plugableRecord.getUnsafe(context.meta.data, dataKey);
const name = customSelector.slice(3);
analyzed[name] = { selector, ast, isScoped, def: atRule };
}
else {
// TODO: add warn there are two types one is not valid name and the other is empty name.
}
},
analyzeDone(context) {
const analyzed = plugable_record_1.plugableRecord.getUnsafe(context.meta.data, dataKey);
const customSelectors = {};
for (const [name, data] of Object.entries(analyzed)) {
customSelectors[name] = data.ast;
}
const inlined = (0, custom_selector_1.transformInlineCustomSelectorMap)(customSelectors, (report) => {
if (report.type === 'unknown' && analyzed[report.origin]) {
const unknownSelector = `:--${report.unknown}`;
context.diagnostics.report(exports.diagnostics.UNKNOWN_CUSTOM_SELECTOR(unknownSelector), {
node: analyzed[report.origin].def,
word: unknownSelector,
});
}
else if (report.type === 'circular') {
// ToDo: report error
}
});
// cache inlined selector
for (const [name, ast] of Object.entries(inlined)) {
analyzed[name].ast = ast;
analyzed[name].selector = (0, css_selector_parser_1.stringifySelectorAst)(ast);
}
},
prepareAST({ context, node, toRemove }) {
// called with experimentalSelectorInference=false
// split selectors & remove definitions
if (node.type === 'rule' && node.selector.match(exports.CUSTOM_SELECTOR_RE)) {
node.selector = transformCustomSelectorInline(context.meta, node.selector, {
diagnostics: context.diagnostics,
node,
});
}
else if (node.type === 'atrule' && node.name === 'custom-selector') {
toRemove.push(node);
}
},
transformSelectorNode({ context, selectorContext, node }) {
const customSelector = node.value.startsWith('--') &&
getCustomSelectorExpended(context.meta, node.value.slice(2));
if (customSelector) {
const mappedSelectorAst = (0, selector_1.parseSelectorWithCache)(customSelector, { clone: true });
const mappedContext = selectorContext.createNestedContext(mappedSelectorAst);
selectorContext.scopeSelectorAst(mappedContext);
const inferredSelector = selectorContext.experimentalSelectorInference
? mappedContext.inferredMultipleSelectors
: mappedContext.inferredSelector;
selectorContext.setNextSelectorScope(inferredSelector, node); // doesn't add to the resolved elements
if (selectorContext.transform) {
selectorContext.transformIntoMultiSelector(node, mappedSelectorAst);
}
}
return !!customSelector;
},
transformAtRuleNode({ atRule }) {
if (atRule.name === 'custom-selector') {
atRule.remove();
}
},
});
// API
function isScoped(meta, name) {
const analyzed = plugable_record_1.plugableRecord.getUnsafe(meta.data, dataKey);
return analyzed[name]?.isScoped;
}
exports.isScoped = isScoped;
function getCustomSelector(meta, name) {
return plugable_record_1.plugableRecord.getUnsafe(meta.data, dataKey)[name]?.ast;
}
exports.getCustomSelector = getCustomSelector;
function getCustomSelectors(meta) {
const analyzed = plugable_record_1.plugableRecord.getUnsafe(meta.data, dataKey);
return Object.entries(analyzed).reduce((acc, [name, { ast }]) => {
acc[name] = ast;
return acc;
}, {});
}
exports.getCustomSelectors = getCustomSelectors;
function getCustomSelectorExpended(meta, name) {
const analyzed = plugable_record_1.plugableRecord.getUnsafe(meta.data, dataKey);
return analyzed[name]?.selector;
}
exports.getCustomSelectorExpended = getCustomSelectorExpended;
function getCustomSelectorNames(meta) {
const analyzed = plugable_record_1.plugableRecord.getUnsafe(meta.data, dataKey);
return Object.keys(analyzed).map((name) => `:--${name}`);
}
exports.getCustomSelectorNames = getCustomSelectorNames;
function transformCustomSelectorInline(meta, selector, options = {}) {
const ast = (0, selector_1.parseSelectorWithCache)(selector, { clone: true });
const analyzed = plugable_record_1.plugableRecord.getUnsafe(meta.data, dataKey);
const inlined = (0, custom_selector_1.transformInlineCustomSelectors)(ast, (name) => analyzed[name]?.ast, (report) => {
if (options.diagnostics && options.node) {
const unknownSelector = `:--${report.unknown}`;
options.diagnostics.report(exports.diagnostics.UNKNOWN_CUSTOM_SELECTOR(unknownSelector), {
node: options.node,
word: unknownSelector,
});
}
});
return (0, css_selector_parser_1.stringifySelectorAst)(inlined);
}
exports.transformCustomSelectorInline = transformCustomSelectorInline;
//# sourceMappingURL=st-custom-selector.js.map