@stylable/core
Version:
CSS for Components
195 lines • 7.86 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.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