1 | "use strict";
|
2 | var __importDefault = (this && this.__importDefault) || function (mod) {
|
3 | return (mod && mod.__esModule) ? mod : { "default": mod };
|
4 | };
|
5 | Object.defineProperty(exports, "__esModule", { value: true });
|
6 | exports.evalDeclarationValue = exports.processDeclarationValue = exports.resolveArgumentsValue = exports.functionWarnings = void 0;
|
7 | const path_1 = require("path");
|
8 | const postcss_value_parser_1 = __importDefault(require("postcss-value-parser"));
|
9 | const custom_values_1 = require("./custom-values");
|
10 | const native_reserved_lists_1 = require("./native-reserved-lists");
|
11 | const stylable_assets_1 = require("./stylable-assets");
|
12 | const stylable_utils_1 = require("./stylable-utils");
|
13 | const stylable_value_parsers_1 = require("./stylable-value-parsers");
|
14 | const utils_1 = require("./utils");
|
15 | exports.functionWarnings = {
|
16 | FAIL_TO_EXECUTE_FORMATTER: (resolvedValue, message) => `failed to execute formatter "${resolvedValue}" with error: "${message}"`,
|
17 | CYCLIC_VALUE: (cyclicChain) => `Cyclic value definition detected: "${cyclicChain
|
18 | .map((s, i) => (i === cyclicChain.length - 1 ? '↻ ' : i === 0 ? '→ ' : '↪ ') + s)
|
19 | .join('\n')}"`,
|
20 | CANNOT_USE_AS_VALUE: (type, varName) => `${type} "${varName}" cannot be used as a variable`,
|
21 | CANNOT_USE_JS_AS_VALUE: (varName) => `JavaScript import "${varName}" cannot be used as a variable`,
|
22 | CANNOT_FIND_IMPORTED_VAR: (varName) => `cannot use unknown imported "${varName}"`,
|
23 | MULTI_ARGS_IN_VALUE: (args) => `value function accepts only a single argument: "value(${args})"`,
|
24 | COULD_NOT_RESOLVE_VALUE: (args) => `cannot resolve value function using the arguments provided: "${args}"`,
|
25 | UNKNOWN_FORMATTER: (name) => `cannot find native function or custom formatter called ${name}`,
|
26 | UNKNOWN_VAR: (name) => `unknown var "${name}"`,
|
27 | };
|
28 | function resolveArgumentsValue(options, transformer, meta, diagnostics, node, variableOverride, path, cssVarsMapping) {
|
29 | const resolvedArgs = {};
|
30 | for (const k in options) {
|
31 | resolvedArgs[k] = evalDeclarationValue(transformer.resolver, options[k], meta, node, variableOverride, transformer.replaceValueHook, diagnostics, path, cssVarsMapping, undefined);
|
32 | }
|
33 | return resolvedArgs;
|
34 | }
|
35 | exports.resolveArgumentsValue = resolveArgumentsValue;
|
36 | function processDeclarationValue(resolver, value, meta, node, variableOverride, valueHook, diagnostics, passedThrough = [], cssVarsMapping, args = []) {
|
37 | diagnostics = node ? diagnostics : undefined;
|
38 | const customValues = custom_values_1.resolveCustomValues(meta, resolver);
|
39 | const parsedValue = postcss_value_parser_1.default(value);
|
40 | parsedValue.walk((parsedNode) => {
|
41 | const { type, value } = parsedNode;
|
42 | switch (type) {
|
43 | case 'function':
|
44 | if (value === 'value') {
|
45 | const parsedArgs = stylable_value_parsers_1.strategies.args(parsedNode).map((x) => x.value);
|
46 | if (parsedArgs.length >= 1) {
|
47 | const varName = parsedArgs[0];
|
48 | const getArgs = parsedArgs
|
49 | .slice(1)
|
50 | .map((arg) => evalDeclarationValue(resolver, arg, meta, node, variableOverride, valueHook, diagnostics, passedThrough.concat(createUniqID(meta.source, varName)), cssVarsMapping, undefined));
|
51 | if (variableOverride && variableOverride[varName]) {
|
52 | return (parsedNode.resolvedValue = variableOverride[varName]);
|
53 | }
|
54 | const refUniqID = createUniqID(meta.source, varName);
|
55 | if (passedThrough.includes(refUniqID)) {
|
56 |
|
57 | return handleCyclicValues(passedThrough, refUniqID, diagnostics, node, value, parsedNode);
|
58 | }
|
59 | const varSymbol = meta.mappedSymbols[varName];
|
60 | if (varSymbol && varSymbol._kind === 'var') {
|
61 | const resolved = processDeclarationValue(resolver, utils_1.stripQuotation(varSymbol.text), meta, varSymbol.node, variableOverride, valueHook, diagnostics, passedThrough.concat(createUniqID(meta.source, varName)), cssVarsMapping, getArgs);
|
62 | const { outputValue, topLevelType, typeError } = resolved;
|
63 | if (diagnostics && node) {
|
64 | const argsAsString = parsedArgs.join(', ');
|
65 | if (typeError) {
|
66 | diagnostics.warn(node, exports.functionWarnings.COULD_NOT_RESOLVE_VALUE(argsAsString));
|
67 | }
|
68 | else if (!topLevelType && parsedArgs.length > 1) {
|
69 | diagnostics.warn(node, exports.functionWarnings.MULTI_ARGS_IN_VALUE(argsAsString));
|
70 | }
|
71 | }
|
72 | parsedNode.resolvedValue = valueHook
|
73 | ? valueHook(outputValue, varName, true, passedThrough)
|
74 | : outputValue;
|
75 | }
|
76 | else if (varSymbol && varSymbol._kind === 'import') {
|
77 | const resolvedVar = resolver.deepResolve(varSymbol);
|
78 | if (resolvedVar && resolvedVar.symbol) {
|
79 | const resolvedVarSymbol = resolvedVar.symbol;
|
80 | if (resolvedVar._kind === 'css') {
|
81 | if (resolvedVarSymbol._kind === 'var') {
|
82 | const resolvedValue = evalDeclarationValue(resolver, utils_1.stripQuotation(resolvedVarSymbol.text), resolvedVar.meta, resolvedVarSymbol.node, variableOverride, valueHook, diagnostics, passedThrough.concat(createUniqID(meta.source, varName)), cssVarsMapping, getArgs);
|
83 | parsedNode.resolvedValue = valueHook
|
84 | ? valueHook(resolvedValue, varName, false, passedThrough)
|
85 | : resolvedValue;
|
86 | }
|
87 | else {
|
88 | const errorKind = resolvedVarSymbol._kind === 'class' &&
|
89 | resolvedVarSymbol[stylable_value_parsers_1.valueMapping.root]
|
90 | ? 'stylesheet'
|
91 | : resolvedVarSymbol._kind;
|
92 | if (diagnostics && node) {
|
93 | diagnostics.warn(node, exports.functionWarnings.CANNOT_USE_AS_VALUE(errorKind, varName), { word: varName });
|
94 | }
|
95 | }
|
96 | }
|
97 | else if (resolvedVar._kind === 'js' &&
|
98 | typeof resolvedVar.symbol === 'string') {
|
99 | parsedNode.resolvedValue = valueHook
|
100 | ? valueHook(resolvedVar.symbol, varName, false, passedThrough)
|
101 | : resolvedVar.symbol;
|
102 | }
|
103 | else if (resolvedVar._kind === 'js' && diagnostics && node) {
|
104 |
|
105 | diagnostics.warn(node, exports.functionWarnings.CANNOT_USE_JS_AS_VALUE(varName), {
|
106 | word: varName,
|
107 | });
|
108 | }
|
109 | }
|
110 | else {
|
111 | const namedDecl = varSymbol.import.rule.nodes.find((node) => {
|
112 | return node.type === 'decl' && node.prop === stylable_value_parsers_1.valueMapping.named;
|
113 | });
|
114 | if (namedDecl && diagnostics && node) {
|
115 |
|
116 | diagnostics.error(node, exports.functionWarnings.CANNOT_FIND_IMPORTED_VAR(varName), { word: varName });
|
117 | }
|
118 | }
|
119 | }
|
120 | else if (diagnostics && node) {
|
121 | diagnostics.warn(node, exports.functionWarnings.UNKNOWN_VAR(varName), {
|
122 | word: varName,
|
123 | });
|
124 | }
|
125 | }
|
126 | }
|
127 | else if (value === '') {
|
128 | parsedNode.resolvedValue = stringifyFunction(value, parsedNode);
|
129 | }
|
130 | else {
|
131 | if (customValues[value]) {
|
132 |
|
133 | }
|
134 | else if (value === 'url') {
|
135 |
|
136 |
|
137 | const url = parsedNode.nodes[0];
|
138 | if ((url.type === 'word' || url.type === 'string') &&
|
139 | url.value.startsWith('~')) {
|
140 | const sourceDir = path_1.dirname(meta.source);
|
141 | url.value = stylable_assets_1.assureRelativeUrlPrefix(path_1.relative(sourceDir, resolver.resolvePath(url.value.slice(1), sourceDir)).replace(/\\/gm, '/'));
|
142 | }
|
143 | }
|
144 | else if (value === 'format') {
|
145 |
|
146 | parsedNode.resolvedValue = stringifyFunction(value, parsedNode, true);
|
147 | }
|
148 | else {
|
149 | const formatterRef = meta.mappedSymbols[value];
|
150 | const formatter = resolver.deepResolve(formatterRef);
|
151 | const formatterArgs = stylable_value_parsers_1.getFormatterArgs(parsedNode);
|
152 | if (formatter && formatter._kind === 'js') {
|
153 | try {
|
154 | parsedNode.resolvedValue = formatter.symbol.apply(null, formatterArgs);
|
155 | if (valueHook && typeof parsedNode.resolvedValue === 'string') {
|
156 | parsedNode.resolvedValue = valueHook(parsedNode.resolvedValue, { name: parsedNode.value, args: formatterArgs }, true, passedThrough);
|
157 | }
|
158 | }
|
159 | catch (error) {
|
160 | parsedNode.resolvedValue = stringifyFunction(value, parsedNode);
|
161 | if (diagnostics && node) {
|
162 | diagnostics.warn(node, exports.functionWarnings.FAIL_TO_EXECUTE_FORMATTER(parsedNode.resolvedValue, error.message), { word: node.value });
|
163 | }
|
164 | }
|
165 | }
|
166 | else if (value === 'var') {
|
167 | const varWithPrefix = parsedNode.nodes[0].value;
|
168 | if (stylable_utils_1.isCSSVarProp(varWithPrefix)) {
|
169 | if (cssVarsMapping && cssVarsMapping[varWithPrefix]) {
|
170 | parsedNode.nodes[0].value = cssVarsMapping[varWithPrefix];
|
171 | }
|
172 | }
|
173 |
|
174 | if (parsedNode.nodes.length > 2) {
|
175 | parsedNode.resolvedValue = stringifyFunction(value, parsedNode);
|
176 | }
|
177 | }
|
178 | else if (native_reserved_lists_1.isCssNativeFunction(value)) {
|
179 | parsedNode.resolvedValue = stringifyFunction(value, parsedNode);
|
180 | }
|
181 | else if (diagnostics && node) {
|
182 | parsedNode.resolvedValue = stringifyFunction(value, parsedNode);
|
183 | diagnostics.warn(node, exports.functionWarnings.UNKNOWN_FORMATTER(value), {
|
184 | word: value,
|
185 | });
|
186 | }
|
187 | }
|
188 | }
|
189 | break;
|
190 | default: {
|
191 | return postcss_value_parser_1.default.stringify(parsedNode);
|
192 | }
|
193 | }
|
194 | return;
|
195 | }, true);
|
196 | let outputValue = '';
|
197 | let topLevelType = null;
|
198 | let typeError = null;
|
199 | for (const n of parsedValue.nodes) {
|
200 | if (n.type === 'function') {
|
201 | const matchingType = customValues[n.value];
|
202 | if (matchingType) {
|
203 | topLevelType = matchingType.evalVarAst(n, customValues);
|
204 | try {
|
205 | outputValue += matchingType.getValue(args, topLevelType, n, customValues);
|
206 | }
|
207 | catch (e) {
|
208 | typeError = e;
|
209 |
|
210 | }
|
211 | }
|
212 | else {
|
213 | outputValue += stylable_value_parsers_1.getStringValue([n]);
|
214 | }
|
215 | }
|
216 | else {
|
217 | outputValue += stylable_value_parsers_1.getStringValue([n]);
|
218 | }
|
219 | }
|
220 | return { outputValue, topLevelType, typeError };
|
221 |
|
222 |
|
223 |
|
224 |
|
225 | }
|
226 | exports.processDeclarationValue = processDeclarationValue;
|
227 | function evalDeclarationValue(resolver, value, meta, node, variableOverride, valueHook, diagnostics, passedThrough = [], cssVarsMapping, args = []) {
|
228 | return processDeclarationValue(resolver, value, meta, node, variableOverride, valueHook, diagnostics, passedThrough, cssVarsMapping, args).outputValue;
|
229 | }
|
230 | exports.evalDeclarationValue = evalDeclarationValue;
|
231 | function handleCyclicValues(passedThrough, refUniqID, diagnostics, node, value, parsedNode) {
|
232 | const cyclicChain = passedThrough.map((variable) => variable || '');
|
233 | cyclicChain.push(refUniqID);
|
234 | if (diagnostics && node) {
|
235 | diagnostics.warn(node, exports.functionWarnings.CYCLIC_VALUE(cyclicChain), {
|
236 | word: refUniqID,
|
237 | });
|
238 | }
|
239 | return stringifyFunction(value, parsedNode);
|
240 | }
|
241 | function stringifyFunction(name, parsedNode, perserveQuotes = false) {
|
242 | return `${name}(${stylable_value_parsers_1.getFormatterArgs(parsedNode, false, undefined, perserveQuotes).join(', ')})`;
|
243 | }
|
244 | function createUniqID(source, varName) {
|
245 | return `${source}: ${varName}`;
|
246 | }
|
247 |
|
\ | No newline at end of file |