UNPKG

@stylable/core

Version:

CSS for Components

337 lines 13.7 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; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getDefinition = exports.getAll = exports.get = exports.hooks = exports.diagnostics = void 0; const feature_1 = require("./feature"); const STSymbol = __importStar(require("./st-symbol")); const STImport = __importStar(require("./st-import")); const plugable_record_1 = require("../helpers/plugable-record"); const namespace_1 = require("../helpers/namespace"); const global_1 = require("../helpers/global"); const native_reserved_lists_1 = require("../native-reserved-lists"); const postcss_value_parser_1 = __importDefault(require("postcss-value-parser")); const diagnostics_1 = require("../diagnostics"); exports.diagnostics = { MISSING_LAYER_NAME_INSIDE_GLOBAL: (0, diagnostics_1.createDiagnosticReporter)('19001', 'warning', () => `"@layer" missing parameter inside "${global_1.GLOBAL_FUNC}()"`), LAYER_SORT_STATEMENT_WITH_STYLE: (0, diagnostics_1.createDiagnosticReporter)('19002', 'error', () => `"@layer" ordering statement cannot have a style block`), RESERVED_KEYWORD: (0, diagnostics_1.createDiagnosticReporter)('19003', 'error', (name) => `"@layer" name cannot be reserved word "${name}"`), NOT_IDENT: (0, diagnostics_1.createDiagnosticReporter)('19004', 'error', (name) => `"@layer" expected ident, but got "${name}"`), RECONFIGURE_IMPORTED: (0, diagnostics_1.createDiagnosticReporter)('19005', 'error', (name) => `cannot reconfigure imported layer "${name}"`), UNKNOWN_IMPORTED_LAYER: (0, diagnostics_1.createDiagnosticReporter)('19006', 'error', (name, path) => `cannot resolve imported layer "${name}" from stylesheet "${path}"`), }; const dataKey = plugable_record_1.plugableRecord.key('layer'); // HOOKS STImport.ImportTypeHook.set(`layer`, (context, localName, importName, importDef) => { addLayer({ context, name: localName, importName, ast: importDef.rule, global: false, importDef, }); }); exports.hooks = (0, feature_1.createFeature)({ metaInit({ meta }) { plugable_record_1.plugableRecord.set(meta.data, dataKey, { analyzedParams: {}, layerDefs: {} }); }, analyzeAtRule({ context, atRule }) { if (!atRule.params) { return; } if (atRule.name === 'import') { // native css import analyzeCSSImportLayer(context, atRule); } else if (atRule.name === 'layer') { // layer atrule const analyzeMetaData = plugable_record_1.plugableRecord.getUnsafe(context.meta.data, dataKey); const analyzedParams = parseLayerParams(atRule.params, context.diagnostics, atRule, context.meta.type === 'stylable'); if (analyzedParams.multiple && atRule.nodes) { context.diagnostics.report(exports.diagnostics.LAYER_SORT_STATEMENT_WITH_STYLE(), { node: atRule, }); } // cache params analyzeMetaData.analyzedParams[atRule.params] = analyzedParams; // cache symbols for (const name of analyzedParams.names) { addLayer({ context, name, importName: name, global: !!analyzedParams.globals[name] || context.meta.type === 'css', ast: atRule, }); } } }, transformResolve({ context }) { const symbols = STSymbol.getAllByType(context.meta, `layer`); const resolved = { record: {}, locals: new Set(), }; const resolvedSymbols = context.getResolvedSymbols(context.meta); for (const [name, symbol] of Object.entries(symbols)) { const res = resolvedSymbols.layer[name]; if (res) { resolved.record[name] = res; if (res.meta === context.meta) { resolved.locals.add(name); } } else if (symbol.import) { context.diagnostics.report(exports.diagnostics.UNKNOWN_IMPORTED_LAYER(symbol.name, symbol.import.request), { node: symbol.import.rule, word: symbol.name, }); } } return resolved; }, transformAtRuleNode({ context, atRule, resolved }) { if (!atRule.params) { return; } if (atRule.name === 'import') { // native css import transformCSSImportLayer(context, atRule, resolved.record); } else if (atRule.name === 'layer') { // layer atrule const { analyzedParams } = plugable_record_1.plugableRecord.getUnsafe(context.meta.data, dataKey); const analyzed = analyzedParams[atRule.params]; if (analyzed) { atRule.params = analyzed.transformNames((name) => { const resolve = resolved.record[name]; return resolve ? getTransformedName(resolved.record[name]) : name; }); } } }, transformJSExports({ exports, resolved }) { for (const name of resolved.locals) { exports.layers[name] = getTransformedName(resolved.record[name]); } }, }); // API function get(meta, name) { return STSymbol.get(meta, name, `layer`); } exports.get = get; function getAll(meta) { return STSymbol.getAllByType(meta, `layer`); } exports.getAll = getAll; function getDefinition(meta, name) { const analyzeMetaData = plugable_record_1.plugableRecord.getUnsafe(meta.data, dataKey); return analyzeMetaData.layerDefs[name]; } exports.getDefinition = getDefinition; function parseLayerParams(params, report, atRule, isStylable) { const names = []; const globals = {}; let readyForName = true; let multiple = false; const ast = (0, postcss_value_parser_1.default)(params).nodes; const namedNodeRefs = {}; for (let i = 0; i < ast.length; ++i) { const node = ast[i]; const { type, value } = node; if (type === 'word') { if (readyForName) { const layers = []; for (const name of getDotSeparatedNames(value)) { // ToDo: handle name duplications const splittedLayer = { ...node, value: name }; if (layers.length) { layers.push({ ...node, value: '.' }); } layers.push(splittedLayer); namedNodeRefs[name] ?? (namedNodeRefs[name] = []); namedNodeRefs[name].push(splittedLayer); names.push(name); } readyForName = false; ast.splice(i, 1, ...layers); } } else if (type === 'function' && value === global_1.GLOBAL_FUNC && readyForName && isStylable) { const globalName = (0, global_1.globalValueFromFunctionNode)(node); if (globalName) { namedNodeRefs[globalName] ?? (namedNodeRefs[globalName] = []); namedNodeRefs[globalName].push(node); names.push(globalName); globals[globalName] = true; } else if (globalName === '') { report.report(exports.diagnostics.MISSING_LAYER_NAME_INSIDE_GLOBAL(), { node: atRule }); } readyForName = false; } else if (type === 'div' && value === ',') { readyForName = true; multiple = true; } else if (type === 'comment') { // doesn't change meaning: do nothing } else { readyForName = false; const source = postcss_value_parser_1.default.stringify(node); report.report(exports.diagnostics.NOT_IDENT(source), { node: atRule, word: source }); } } return { names, globals, multiple, transformNames(getTransformedName) { for (const [name, nodes] of Object.entries(namedNodeRefs)) { const transformedName = getTransformedName(name); for (const modifiedNode of nodes) { if (modifiedNode.type === 'function') { // mutate to word - this is safe since this node is not exposed modifiedNode.type = 'word'; } modifiedNode.value = transformedName; } } return postcss_value_parser_1.default.stringify(ast); }, }; } function getDotSeparatedNames(value) { if (!value.includes('.')) { return [value]; } const names = []; let lastIndex = 0; for (let index = 0; index < value.length; ++index) { const char = value[index]; switch (char) { case '.': { if (value[index - 1] !== '\\') { names.push(value.substring(lastIndex, index)); lastIndex = index + 1; } break; } } } if (lastIndex <= value.length - 1) { names.push(value.substring(lastIndex, value.length)); } return names; } function analyzeCSSImportLayer(context, importAtRule) { const ast = (0, postcss_value_parser_1.default)(importAtRule.params).nodes; for (let i = 0; i < ast.length; ++i) { const node = ast[i]; const { type, value } = node; if (type === 'function' && value === 'layer' && node.nodes.length) { for (const nestedNode of node.nodes) { if (nestedNode.type === 'word') { for (const name of getDotSeparatedNames(nestedNode.value)) { addLayer({ context, name, importName: name, ast: importAtRule, global: false, }); } } } } } } function transformCSSImportLayer(_context, importAtRule, resolved) { const ast = (0, postcss_value_parser_1.default)(importAtRule.params).nodes; for (let i = 0; i < ast.length; ++i) { const node = ast[i]; const { type, value } = node; if (type === 'function' && value === 'layer' && node.nodes.length) { for (const nestedNode of node.nodes) { const { type, value } = nestedNode; if (type === 'word') { nestedNode.value = getDotSeparatedNames(value) .map((name) => { const resolve = resolved[name]; return resolve ? getTransformedName(resolved[name]) : name; }) .join('.'); } } } } importAtRule.params = postcss_value_parser_1.default.stringify(ast); } function getTransformedName({ symbol, meta }) { return symbol.global ? symbol.alias : (0, namespace_1.namespace)(symbol.alias, meta.namespace); } function addLayer({ context, name, importName, ast, global, importDef, }) { const definedSymbol = STSymbol.get(context.meta, name, 'layer'); if (!definedSymbol) { if (native_reserved_lists_1.CSSWideKeywords.includes(name)) { // keep global = true; context.diagnostics.report(exports.diagnostics.RESERVED_KEYWORD(name), { node: ast, word: name, }); } const analyzeMetaData = plugable_record_1.plugableRecord.getUnsafe(context.meta.data, dataKey); analyzeMetaData.layerDefs[name] = ast; STSymbol.addSymbol({ context, node: ast, localName: name, symbol: { _kind: 'layer', name: importName, alias: name, global, import: importDef, }, safeRedeclare: false, }); } else if (!definedSymbol.import && global) { definedSymbol.global = true; } else if (definedSymbol.import && global) { context.diagnostics.report(exports.diagnostics.RECONFIGURE_IMPORTED(name), { node: ast, word: name, }); } } //# sourceMappingURL=css-layer.js.map