UNPKG

@stylable/core

Version:

CSS for Components

195 lines 7.86 kB
"use strict"; 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.getAlias = exports.getSourcePath = exports.sourcePathDiagnostics = exports.mergeRules = exports.utilDiagnostics = exports.isValidDeclaration = void 0; const path_1 = require("path"); const postcss = __importStar(require("postcss")); const diagnostics_1 = require("./diagnostics"); const rule_1 = require("./helpers/rule"); const selector_1 = require("./helpers/selector"); function isValidDeclaration(decl) { return typeof decl.value === 'string'; } exports.isValidDeclaration = isValidDeclaration; exports.utilDiagnostics = { INVALID_MERGE_OF: (0, diagnostics_1.createDiagnosticReporter)('14001', 'error', (mergeValue) => `invalid merge of: \n"${mergeValue}"`), INVALID_RECURSIVE_MIXIN: (0, diagnostics_1.createDiagnosticReporter)('10010', 'error', () => `invalid recursive mixin`), }; // ToDo: move to helpers/mixin function mergeRules(mixinAst, rule, mixinDecl, report, useNestingAsAnchor) { let mixinRoot = null; const nestedInKeyframes = (0, rule_1.isChildOfAtRule)(rule, `keyframes`); const anchorSelector = useNestingAsAnchor ? '&' : '[' + rule_1.stMixinMarker + ']'; const anchorNodeCheck = useNestingAsAnchor ? undefined : rule_1.isStMixinMarker; mixinAst.walkRules((mixinRule) => { if ((0, rule_1.isChildOfAtRule)(mixinRule, 'keyframes')) { return; } if (mixinRule.selector === anchorSelector && !mixinRoot) { if (mixinRule.parent === mixinAst) { mixinRoot = mixinRule; } else { const { selector } = (0, selector_1.scopeNestedSelector)((0, selector_1.parseSelectorWithCache)(rule.selector), (0, selector_1.parseSelectorWithCache)(mixinRule.selector), false, anchorNodeCheck); mixinRoot = 'NoRoot'; mixinRule.selector = selector; } } else if (!isChildOfMixinRoot(mixinRule, mixinRoot)) { // scope to mixin target if not already scoped by parent const { selector } = (0, selector_1.scopeNestedSelector)((0, selector_1.parseSelectorWithCache)(rule.selector), (0, selector_1.parseSelectorWithCache)(mixinRule.selector), false, anchorNodeCheck); mixinRule.selector = selector; } else if (mixinRule.selector.includes(anchorSelector)) { // report invalid nested mixin mixinRule.selector = mixinRule.selector.split(anchorSelector).join('&'); report?.report(exports.utilDiagnostics.INVALID_RECURSIVE_MIXIN(), { node: rule, }); } }); if (mixinAst.nodes) { let nextRule = rule; // TODO: handle rules before and after decl on entry const inlineMixin = !hasNonDeclsBeforeDecl(mixinDecl); const mixInto = inlineMixin ? rule : postcss.rule({ selector: '&' }); const mixIntoRule = (node) => { // mix node into rule if (inlineMixin) { mixInto.insertBefore(mixinDecl, node); } else { // indent first level - doesn't change deep nested node.raws.before = (node.raws.before || '') + ' '; mixInto.append(node); } // mark following decls for nesting if (!nestFollowingDecls && node.type !== 'decl' && hasAnyDeclsAfter(mixinDecl)) { nestFollowingDecls = true; } }; let nestFollowingDecls = false; mixinAst.nodes.slice().forEach((node) => { if (node === mixinRoot) { for (const nested of [...node.nodes]) { mixIntoRule(nested); } } else if (node.type === 'decl') { // stand alone decl - most likely from js mixin mixIntoRule(node); } else if (node.type === 'rule' || node.type === 'atrule') { const valid = !nestedInKeyframes; if (valid) { if (rule.parent.last === nextRule) { rule.parent.append(node); } else { rule.parent.insertAfter(nextRule, node); } nextRule = node; } else { report?.report(exports.utilDiagnostics.INVALID_MERGE_OF(node.toString()), { node: rule, }); } } }); // add nested mixin to rule body if (mixInto !== rule && mixInto.nodes.length) { mixinDecl.before(mixInto); } // nest following decls if needed if (nestFollowingDecls) { const nestFollowingDecls = postcss.rule({ selector: '&' }); while (mixinDecl.next()) { const nextNode = mixinDecl.next(); nextNode.raws.before = (nextNode.raws.before || '') + ' '; nestFollowingDecls.append(nextNode); } mixinDecl.after(nestFollowingDecls); } } return rule; } exports.mergeRules = mergeRules; function hasNonDeclsBeforeDecl(decl) { let current = decl.prev(); while (current) { if (current.type !== 'decl' && current.type !== 'comment') { return true; } current = current.prev(); } return false; } function hasAnyDeclsAfter(decl) { let current = decl.next(); while (current) { if (current.type === 'decl') { return true; } current = current.prev(); } return false; } const isChildOfMixinRoot = (rule, mixinRoot) => { let current = rule.parent; while (current) { if (current === mixinRoot) { return true; } current = current.parent; } return false; }; exports.sourcePathDiagnostics = { MISSING_SOURCE_FILENAME: (0, diagnostics_1.createDiagnosticReporter)('17001', 'error', () => 'missing source filename'), }; function getSourcePath(root, diagnostics) { const source = (root.source && root.source.input.file) || ''; if (!source) { diagnostics.report(exports.sourcePathDiagnostics.MISSING_SOURCE_FILENAME(), { node: root, }); } else if (!(0, path_1.isAbsolute)(source)) { throw new Error('source filename is not absolute path: "' + source + '"'); } return source; } exports.getSourcePath = getSourcePath; function getAlias(symbol) { if (symbol._kind === 'class' || symbol._kind === 'element') { if (!symbol[`-st-extends`]) { return symbol.alias; } } return undefined; } exports.getAlias = getAlias; //# sourceMappingURL=stylable-utils.js.map