UNPKG

@stylable/core

Version:

CSS for Components

437 lines 17.4 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 CSSCustomProperty = __importStar(require("./css-custom-property")); const diagnostics_1 = require("../diagnostics"); const plugable_record_1 = require("../helpers/plugable-record"); const namespace_1 = require("../helpers/namespace"); const global_1 = require("../helpers/global"); const postcss_value_parser_1 = __importDefault(require("postcss-value-parser")); exports.diagnostics = { UNEXPECTED_DECL_VALUE: (0, diagnostics_1.createDiagnosticReporter)('20001', 'error', (value) => `unexpected value: ${value}`), UNKNOWN_DECL_TYPE: (0, diagnostics_1.createDiagnosticReporter)('20002', 'error', (value) => `unknown container type: ${value}`), MISSING_DECL_TYPE: (0, diagnostics_1.createDiagnosticReporter)('20003', 'error', () => `missing container shorthand type`), INVALID_CONTAINER_NAME: (0, diagnostics_1.createDiagnosticReporter)('20004', 'error', (value) => `invalid container name: ${value}`), UNRESOLVED_CONTAINER_NAME: (0, diagnostics_1.createDiagnosticReporter)('20005', 'error', (value) => `unresolved container name: ${value}`), UNKNOWN_IMPORTED_CONTAINER: (0, diagnostics_1.createDiagnosticReporter)('20006', 'error', (name, path) => `cannot resolve imported container name "${name}" from stylesheet "${path}"`), MISSING_CONTAINER_NAME_INSIDE_GLOBAL: (0, diagnostics_1.createDiagnosticReporter)('20007', 'warning', () => `Missing container name inside "${global_1.GLOBAL_FUNC}()"`), UNEXPECTED_DEFINITION: (0, diagnostics_1.createDiagnosticReporter)('20008', 'error', (def) => `Unexpected value in container definition: "${def}""`), }; const dataKey = plugable_record_1.plugableRecord.key('container'); // HOOKS STImport.ImportTypeHook.set(`container`, (context, localName, importName, importDef) => { addContainer({ context, name: localName, importName, ast: importDef.rule, global: false, importDef, forceDefinition: true, }); }); exports.hooks = (0, feature_1.createFeature)({ metaInit({ meta }) { plugable_record_1.plugableRecord.set(meta.data, dataKey, { 'container-name': {}, container: {}, definitions: {}, }); }, analyzeDeclaration({ context, decl }) { const prop = decl.prop.toLowerCase(); if (prop !== 'container-name' && prop !== 'container') { return; } const analyzed = plugable_record_1.plugableRecord.getUnsafe(context.meta.data, dataKey); const bucket = analyzed[prop]; const value = decl.value; if (bucket[value]) { return; } const parsed = (bucket[value] = parseContainerDecl(decl, context)); for (const { name, global } of parsed.containers) { addContainer({ context, ast: decl, name, importName: name, global, forceDefinition: false, }); } }, analyzeAtRule({ context, atRule }) { const ast = (0, postcss_value_parser_1.default)(atRule.params).nodes; let name = ''; let global = false; let searchForContainerName = true; let searchForLogicalOp = false; for (const node of ast) { if (node.type === 'comment' || node.type === 'space') { // do nothing continue; } else if (searchForContainerName && node.type === 'word') { searchForContainerName = false; searchForLogicalOp = true; name = node.value; } else if (searchForContainerName && node.type === 'function' && node.value === global_1.GLOBAL_FUNC) { searchForContainerName = false; searchForLogicalOp = true; name = (0, global_1.globalValueFromFunctionNode)(node) || ''; global = true; } else if (node.type === 'function' && node.value === 'style') { searchForContainerName = false; searchForLogicalOp = true; // check for custom properties for (const queryNode of node.nodes) { if (queryNode.type === 'word' && queryNode.value.startsWith('--')) { CSSCustomProperty.addCSSProperty({ context, node: atRule, name: queryNode.value, global: context.meta.type === 'css', final: false, }); } } } else if (node.type !== 'function' && (!searchForLogicalOp || (node.type === 'word' && !logicalOpNames[node.value]))) { const def = postcss_value_parser_1.default.stringify(node); context.diagnostics.report(exports.diagnostics.UNEXPECTED_DEFINITION(def), { node: atRule, word: def, }); break; } } if (name && !atRule.nodes) { // treat @container with no body as definition if (invalidContainerNames[name]) { context.diagnostics.report(exports.diagnostics.INVALID_CONTAINER_NAME(name), { node: atRule, word: name, }); } addContainer({ context, ast: atRule, name, importName: name, global, forceDefinition: true, }); } }, transformResolve({ context }) { const symbols = STSymbol.getAllByType(context.meta, `container`); const resolved = { record: {}, locals: new Set(), }; const resolvedSymbols = context.getResolvedSymbols(context.meta); for (const [name, symbol] of Object.entries(symbols)) { const res = resolvedSymbols.container[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_CONTAINER(symbol.name, symbol.import.request), { node: symbol.import.rule, word: symbol.name, }); } } return resolved; }, transformDeclaration({ context, decl, resolved }) { const prop = decl.prop.toLowerCase(); if (prop !== 'container-name' && prop !== 'container') { return; } const analyzed = plugable_record_1.plugableRecord.getUnsafe(context.meta.data, dataKey); const bucket = analyzed[prop]; const value = decl.value; decl.value = bucket[value].transformNames((name) => { const resolve = resolved.record[name]; return resolve ? getTransformedName(resolved.record[name]) : name; }); }, transformAtRuleNode({ context, atRule, resolved }) { if (!atRule.nodes) { // remove definition only @container atRule.remove(); return; } const ast = (0, postcss_value_parser_1.default)(atRule.params).nodes; let changed = false; let searchForContainerName = true; search: for (const node of ast) { if (node.type === 'comment' || node.type === 'space') { // do nothing } else if (node.type === 'word' && searchForContainerName) { const resolve = resolved.record[node.value]; if (resolve) { node.value = getTransformedName(resolve); changed = true; } else { context.diagnostics.report(exports.diagnostics.UNRESOLVED_CONTAINER_NAME(node.value), { node: atRule, word: node.value, }); } break search; } else if (node.type === 'function' && node.value === global_1.GLOBAL_FUNC && searchForContainerName) { const globalName = (0, global_1.globalValueFromFunctionNode)(node) || ''; if (globalName) { changed = true; const wordNode = node; wordNode.type = 'word'; wordNode.value = globalName; } } else if (node.type === 'function' && node.value === 'style') { // check for custom properties searchForContainerName = false; for (const queryNode of node.nodes) { if (queryNode.type === 'word' && queryNode.value.startsWith('--')) { changed = true; CSSCustomProperty.transformPropertyIdent(context.meta, queryNode, context.getResolvedSymbols); } } } } if (changed) { atRule.params = postcss_value_parser_1.default.stringify(ast); } atRule.params = context.evaluator.evaluateValue(context, { value: atRule.params, meta: context.meta, node: atRule, initialNode: atRule, }).outputValue; }, transformJSExports({ exports, resolved }) { for (const name of resolved.locals) { exports.containers[name] = getTransformedName(resolved.record[name]); } }, }); const invalidContainerNames = { none: true, and: true, not: true, or: true, }; const logicalOpNames = { and: true, not: true, or: true, }; function parseContainerDecl(decl, context) { const { prop, value } = decl; const containers = []; const namedNodeRefs = {}; const ast = (0, postcss_value_parser_1.default)(value).nodes; let noneFound = false; const checkNextName = (node) => { const { type, value } = node; if (type === 'comment' || type === 'space') { // do nothing } else if (type === 'word' || (type === 'function' && value === global_1.GLOBAL_FUNC)) { const global = type === 'function'; const name = global ? (0, global_1.globalValueFromFunctionNode)(node) || '' : node.value; if (global && !name) { context.diagnostics.report(exports.diagnostics.MISSING_CONTAINER_NAME_INSIDE_GLOBAL(), { node: decl, }); } if (name === 'none') { noneFound = true; return; } if (!global) { containers.push({ name, global }); namedNodeRefs[name] ?? (namedNodeRefs[name] = []); namedNodeRefs[name].push(node); } else { // mutate to word - this is safe since this node is not exposed node.type = 'word'; node.value = name; } if (invalidContainerNames[name]) { context.diagnostics.report(exports.diagnostics.INVALID_CONTAINER_NAME(name), { node: decl, word: name, }); } } else { const word = postcss_value_parser_1.default.stringify(node); context.diagnostics.report(exports.diagnostics.UNEXPECTED_DECL_VALUE(word), { node: decl, word, }); return false; } return true; }; if (prop.toLowerCase() === 'container-name') { for (const node of ast) { const continueParse = checkNextName(node); if (!continueParse) { break; } } } else { let nextExpected = 'name'; for (const node of ast) { const { type, value } = node; if (type === 'comment' || type === 'space') { // do nothing } else if (nextExpected === 'name') { if (type === 'div' && value === '/') { nextExpected = 'type'; } else { const continueParse = checkNextName(node); if (!continueParse) { break; } } } else if (type === 'word' && nextExpected === 'type') { if (value !== 'normal' && value !== 'size' && value !== 'inline-size') { context.diagnostics.report(exports.diagnostics.UNKNOWN_DECL_TYPE(value), { node: decl, word: value, }); } nextExpected = ''; } else { const word = postcss_value_parser_1.default.stringify(node); context.diagnostics.report(exports.diagnostics.UNEXPECTED_DECL_VALUE(word), { node: decl, word, }); } } if (nextExpected === 'type') { context.diagnostics.report(exports.diagnostics.MISSING_DECL_TYPE(), { node: decl, }); } } if (containers.length > 0 && noneFound) { context.diagnostics.report(exports.diagnostics.INVALID_CONTAINER_NAME('none'), { node: decl, word: 'none', }); } return { containers, 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); }, }; } // API function get(meta, name) { return STSymbol.get(meta, name, `container`); } exports.get = get; function getAll(meta) { return STSymbol.getAllByType(meta, `container`); } exports.getAll = getAll; function getDefinition(meta, name) { const { definitions } = plugable_record_1.plugableRecord.getUnsafe(meta.data, dataKey); return definitions[name]; } exports.getDefinition = getDefinition; function getTransformedName({ symbol, meta }) { return symbol.global ? symbol.alias : (0, namespace_1.namespace)(symbol.alias, meta.namespace); } function addContainer({ context, name, importName, ast, global, importDef, forceDefinition, }) { const { definitions } = plugable_record_1.plugableRecord.getUnsafe(context.meta.data, dataKey); const definedSymbol = STSymbol.get(context.meta, name, 'container'); const isFirst = !definedSymbol; if (forceDefinition || isFirst) { if (context.meta.type !== 'stylable') { global = true; } definitions[name] = ast; STSymbol.addSymbol({ context, node: ast, localName: name, symbol: { _kind: 'container', name: importName, alias: name, global, import: importDef, }, safeRedeclare: false, }); } } //# sourceMappingURL=css-contains.js.map