UNPKG

@stylable/core

Version:

CSS for Components

277 lines 11.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.processNamespace = exports.StylableProcessor = void 0; const diagnostics_1 = require("./diagnostics"); const native_reserved_lists_1 = require("./native-reserved-lists"); const stylable_meta_1 = require("./stylable-meta"); const features_1 = require("./features"); const diagnostics_2 = require("./features/diagnostics"); const features_2 = require("./features"); const process_declaration_functions_1 = require("./process-declaration-functions"); const selector_1 = require("./helpers/selector"); const rule_1 = require("./helpers/rule"); const feature_1 = require("./features/feature"); class StylableProcessor { constructor(diagnostics = new diagnostics_1.Diagnostics(), resolveNamespace = features_2.STNamespace.defaultProcessNamespace, flags = { ...feature_1.defaultFeatureFlags }) { this.diagnostics = diagnostics; this.resolveNamespace = resolveNamespace; this.flags = flags; } process(root) { this.meta = new stylable_meta_1.StylableMeta(root, this.diagnostics, this.flags); features_2.STStructure.hooks.analyzeInit(this); features_2.STImport.hooks.analyzeInit(this); features_1.CSSCustomProperty.hooks.analyzeInit(this); this.handleAtRules(root); root.walkRules((rule) => { if (!(0, rule_1.isChildOfAtRule)(rule, 'keyframes')) { this.handleRule(rule, { isScoped: (0, rule_1.isChildOfAtRule)(rule, `st-scope`), reportUnscoped: true, }); } }); root.walkDecls((decl) => { features_2.CSSClass.hooks.analyzeDeclaration({ context: this, decl }); features_1.CSSCustomProperty.hooks.analyzeDeclaration({ context: this, decl }); features_2.CSSContains.hooks.analyzeDeclaration({ context: this, decl }); this.collectUrls(decl); }); features_2.STNamespace.hooks.analyzeDone(this); features_1.STCustomSelector.hooks.analyzeDone(this); features_2.STStructure.hooks.analyzeDone(this); features_2.STNamespace.setMetaNamespace(this, this.resolveNamespace); features_2.STSymbol.reportRedeclare(this); return this.meta; } handleAtRules(root) { const analyzeRule = (rule, { isScoped, originalNode, }) => { return this.handleRule(rule, { isScoped, originalNode, reportUnscoped: false, }); }; root.walkAtRules((atRule) => { switch (atRule.name) { case 'st-import': { features_2.STImport.hooks.analyzeAtRule({ context: this, atRule, analyzeRule, }); break; } case 'namespace': case 'st-namespace': { features_2.STNamespace.hooks.analyzeAtRule({ context: this, atRule, analyzeRule, }); break; } case 'keyframes': features_2.CSSKeyframes.hooks.analyzeAtRule({ context: this, atRule, analyzeRule, }); break; case 'layer': features_2.CSSLayer.hooks.analyzeAtRule({ context: this, atRule, analyzeRule, }); break; case 'import': features_2.STImport.hooks.analyzeAtRule({ context: this, atRule, analyzeRule, }); features_2.CSSLayer.hooks.analyzeAtRule({ context: this, atRule, analyzeRule, }); break; case 'custom-selector': { features_1.STCustomSelector.hooks.analyzeAtRule({ context: this, atRule, analyzeRule, }); break; } case 'st-scope': features_2.STScope.hooks.analyzeAtRule({ context: this, atRule, analyzeRule }); break; case 'property': case 'st-global-custom-property': { features_1.CSSCustomProperty.hooks.analyzeAtRule({ context: this, atRule, analyzeRule, }); break; } case 'container': { features_2.CSSContains.hooks.analyzeAtRule({ context: this, atRule, analyzeRule, }); break; } case 'st': { features_2.STStructure.hooks.analyzeAtRule({ context: this, atRule, analyzeRule, }); break; } } }); } collectUrls(decl) { (0, process_declaration_functions_1.processDeclarationFunctions)(decl, (node) => { if (node.type === 'url') { this.meta.urls.push(node.url); } }, false); } handleRule(rule, { isScoped, reportUnscoped, originalNode = rule, }) { const selectorAst = (0, selector_1.parseSelectorWithCache)(rule.selector); let locallyScoped = isScoped; let topSelectorIndex = -1; (0, selector_1.walkSelector)(selectorAst, (node, ...nodeContext) => { const [index, nodes, parents] = nodeContext; const type = node.type; if (type === 'selector' && !(0, selector_1.isInPseudoClassContext)(parents)) { // reset scope check between top level selectors locallyScoped = isScoped; topSelectorIndex++; } const walkSkip = features_2.STGlobal.hooks.analyzeSelectorNode({ context: this, node, topSelectorIndex, rule, originalNode, walkContext: nodeContext, }); if (walkSkip !== undefined) { return walkSkip; } if (node.type === 'pseudo_class') { if (node.value === 'import') { features_2.STImport.hooks.analyzeSelectorNode({ context: this, node, topSelectorIndex, rule, originalNode, walkContext: nodeContext, }); } else if (node.value === 'vars') { return features_1.STVar.hooks.analyzeSelectorNode({ context: this, node, topSelectorIndex, rule, originalNode, walkContext: nodeContext, }); } else if (node.value.startsWith('--')) { // ToDo: move to css-class feature locallyScoped = locallyScoped || features_1.STCustomSelector.isScoped(this.meta, node.value.slice(2)) || false; } else if (!native_reserved_lists_1.knownPseudoClassesWithNestedSelectors.includes(node.value)) { return selector_1.walkSelector.skipNested; } } else if (node.type === 'class') { features_2.CSSClass.hooks.analyzeSelectorNode({ context: this, node, topSelectorIndex, rule, originalNode, walkContext: nodeContext, }); locallyScoped = features_2.CSSClass.validateClassScoping({ context: this, classSymbol: features_2.CSSClass.get(this.meta, node.value), locallyScoped, reportUnscoped, node, nodes, index, rule, }); } else if (node.type === 'type') { features_2.CSSType.hooks.analyzeSelectorNode({ context: this, node, topSelectorIndex, rule, originalNode, walkContext: nodeContext, }); locallyScoped = features_2.CSSType.validateTypeScoping({ context: this, locallyScoped, reportUnscoped, node, nodes, index, rule, }); } else if (node.type === `id`) { if (node.nodes) { this.diagnostics.report(diagnostics_2.generalDiagnostics.INVALID_FUNCTIONAL_SELECTOR(`#` + node.value, `id`), { node: rule, word: (0, selector_1.stringifySelector)(node), }); } } else if (node.type === `attribute`) { if (node.nodes) { this.diagnostics.report(diagnostics_2.generalDiagnostics.INVALID_FUNCTIONAL_SELECTOR(`[${node.value}]`, `attribute`), { node: rule, word: (0, selector_1.stringifySelector)(node), }); } } else if (node.type === `nesting`) { if (node.nodes) { this.diagnostics.report(diagnostics_2.generalDiagnostics.INVALID_FUNCTIONAL_SELECTOR(node.value, `nesting`), { node: rule, word: (0, selector_1.stringifySelector)(node), }); } } return; }); features_2.STGlobal.hooks.analyzeSelectorDone({ context: this, rule, originalNode, }); return locallyScoped; } } exports.StylableProcessor = StylableProcessor; // ToDo: remove export and reroute import from feature exports.processNamespace = features_2.STNamespace.defaultProcessNamespace; //# sourceMappingURL=stylable-processor.js.map