@stylable/core
Version:
CSS for Components
437 lines • 17.4 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;
};
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