@stylable/core
Version:
CSS for Components
285 lines • 9.45 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.validateAllowedNodesUntil = exports.listOptions = exports.strategies = exports.groupValues = exports.getStringValue = exports.getFormatterArgs = exports.getNamedArgs = exports.SBTypesParsers = exports.STYLABLE_NAMED_MATCHER = exports.STYLABLE_VALUE_MATCHER = exports.stValuesMap = exports.stValues = exports.valueMapping = exports.rootValueMapping = exports.valueParserWarnings = void 0;
const pseudo_states_1 = require("./pseudo-states");
const selector_utils_1 = require("./selector-utils");
const postcssValueParser = require('postcss-value-parser');
exports.valueParserWarnings = {
VALUE_CANNOT_BE_STRING() {
return 'value can not be a string (remove quotes?)';
},
CSS_MIXIN_FORCE_NAMED_PARAMS() {
return 'CSS mixins must use named parameters (e.g. "func(name value, [name value, ...])")';
},
};
exports.rootValueMapping = {
vars: ':vars',
import: ':import',
stScope: 'st-scope',
namespace: 'namespace',
};
exports.valueMapping = {
from: '-st-from',
named: '-st-named',
default: '-st-default',
root: '-st-root',
states: '-st-states',
extends: '-st-extends',
mixin: '-st-mixin',
global: '-st-global',
};
exports.stValues = Object.keys(exports.valueMapping).map((key) => exports.valueMapping[key]);
exports.stValuesMap = Object.keys(exports.valueMapping).reduce((acc, key) => {
acc[exports.valueMapping[key]] = true;
return acc;
}, {});
exports.STYLABLE_VALUE_MATCHER = /^-st-/;
exports.STYLABLE_NAMED_MATCHER = new RegExp(`^${exports.valueMapping.named}-(.+)`);
exports.SBTypesParsers = {
'-st-root'(value) {
return value === 'false' ? false : true;
},
'-st-global'(decl, _diagnostics) {
// Experimental
const selector = selector_utils_1.parseSelector(decl.value.replace(/^['"]/, '').replace(/['"]$/, ''));
return selector.nodes[0].nodes;
},
'-st-states'(value, decl, diagnostics) {
if (!value) {
return {};
}
return pseudo_states_1.processPseudoStates(value, decl, diagnostics);
},
'-st-extends'(value) {
const ast = postcssValueParser(value);
const types = [];
ast.walk((node) => {
if (node.type === 'function') {
const args = getNamedArgs(node);
types.push({
symbolName: node.value,
args,
});
return false;
}
else if (node.type === 'word') {
types.push({
symbolName: node.value,
args: null,
});
}
return undefined;
}, false);
return {
ast,
types,
};
},
'-st-named'(value) {
const namedMap = {};
if (value) {
value.split(',').forEach((name) => {
const parts = name.trim().split(/\s+as\s+/);
if (parts.length === 1) {
namedMap[parts[0]] = parts[0];
}
else if (parts.length === 2) {
namedMap[parts[1]] = parts[0];
}
});
}
return namedMap;
},
'-st-mixin'(mixinNode, strategy, diagnostics) {
const ast = postcssValueParser(mixinNode.value);
const mixins = [];
function reportWarning(message, options) {
if (diagnostics) {
diagnostics.warn(mixinNode, message, options);
}
}
ast.nodes.forEach((node) => {
const strat = strategy(node.value);
if (node.type === 'function') {
mixins.push({
type: node.value,
options: exports.strategies[strat](node, reportWarning),
});
}
else if (node.type === 'word') {
mixins.push({
type: node.value,
options: strat === 'named' ? {} : [],
});
}
else if (node.type === 'string' && diagnostics) {
diagnostics.error(mixinNode, exports.valueParserWarnings.VALUE_CANNOT_BE_STRING(), {
word: mixinNode.value,
});
}
});
return mixins;
},
};
function getNamedArgs(node) {
const args = [];
if (node.nodes.length) {
args.push([]);
node.nodes.forEach((node) => {
if (node.type === 'div') {
args.push([]);
}
else {
const { sourceIndex, ...clone } = node;
args[args.length - 1].push(clone);
}
});
}
// handle trailing comma
return args.length && args[args.length - 1].length === 0 ? args.slice(0, -1) : args;
}
exports.getNamedArgs = getNamedArgs;
function getFormatterArgs(node, allowComments = false, _reportWarning, perserveQuotes = false) {
const argsResult = [];
let currentArg = '';
let argIndex = 0;
for (const currentNode of node.nodes) {
if (currentNode.type === 'div' && currentNode.value === ',') {
checkEmptyArg();
argIndex++;
argsResult.push(currentArg.trim());
currentArg = '';
}
else if (currentNode.type === 'comment') {
if (allowComments) {
currentArg +=
currentNode.resolvedValue || postcssValueParser.stringify(currentNode);
}
}
else if (currentNode.type === 'string') {
currentArg += perserveQuotes
? postcssValueParser.stringify(currentNode)
: currentNode.value;
}
else {
currentArg += currentNode.resolvedValue || postcssValueParser.stringify(currentNode);
}
}
checkEmptyArg();
argsResult.push(currentArg.trim());
let i = argsResult.length;
while (i--) {
if (argsResult[i] === '') {
argsResult.pop();
}
else {
return argsResult;
}
}
return argsResult;
function checkEmptyArg() {
if (currentArg.trim() === '' && _reportWarning) {
_reportWarning(`${postcssValueParser.stringify(node)}: argument at index ${argIndex} is empty`);
}
}
}
exports.getFormatterArgs = getFormatterArgs;
function getStringValue(nodes) {
return postcssValueParser.stringify(nodes, (node) => {
if (node.resolvedValue !== undefined) {
return node.resolvedValue;
}
else {
// TODO: warn
return undefined;
}
});
}
exports.getStringValue = getStringValue;
function groupValues(nodes, divType = 'div') {
const grouped = [];
let current = [];
nodes.forEach((n) => {
if (n.type === divType) {
grouped.push(current);
current = [];
}
else {
current.push(n);
}
});
const last = grouped[grouped.length - 1];
if ((last && last !== current && current.length) || (!last && current.length)) {
grouped.push(current);
}
return grouped;
}
exports.groupValues = groupValues;
exports.strategies = {
named: (node, reportWarning) => {
const named = {};
getNamedArgs(node).forEach((mixinArgsGroup) => {
const argsDivider = mixinArgsGroup[1];
if (mixinArgsGroup.length < 3 || (argsDivider && argsDivider.type !== 'space')) {
if (reportWarning) {
const argValue = mixinArgsGroup[0];
reportWarning(exports.valueParserWarnings.CSS_MIXIN_FORCE_NAMED_PARAMS(), {
word: argValue.value,
});
}
return;
}
named[mixinArgsGroup[0].value] = stringifyParam(mixinArgsGroup.slice(2));
});
return named;
},
args: (node, reportWarning) => {
return getFormatterArgs(node, true, reportWarning).map((value) => ({ value }));
},
};
function stringifyParam(nodes) {
return postcssValueParser.stringify(nodes, (n) => {
if (n.type === 'function') {
return postcssValueParser.stringify(n);
}
else if (n.type === 'div') {
return null;
}
else if (n.type === 'string') {
return n.value;
}
else {
return undefined;
}
});
}
function listOptions(node) {
return groupValues(node.nodes)
.map((nodes) => postcssValueParser.stringify(nodes, (n) => {
if (n.type === 'div') {
return null;
}
else if (n.type === 'string') {
return n.value;
}
else {
return undefined;
}
}))
.filter((x) => typeof x === 'string');
}
exports.listOptions = listOptions;
function validateAllowedNodesUntil(node, i, untilType = 'div', allowed = ['comment']) {
i = 1;
let current = node.nodes[i];
while (current && current.type !== untilType) {
if (!allowed.includes(current.type)) {
return false;
}
i++;
current = node.nodes[i];
}
return true;
}
exports.validateAllowedNodesUntil = validateAllowedNodesUntil;
//# sourceMappingURL=stylable-value-parsers.js.map