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.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.mixinDeclRegExp = exports.valueMapping = exports.rootValueMapping = exports.valueParserWarnings = void 0;
|
7 | const postcss_value_parser_1 = __importDefault(require("postcss-value-parser"));
|
8 | const pseudo_states_1 = require("./pseudo-states");
|
9 | const selector_utils_1 = require("./selector-utils");
|
10 | exports.valueParserWarnings = {
|
11 | VALUE_CANNOT_BE_STRING() {
|
12 | return 'value can not be a string (remove quotes?)';
|
13 | },
|
14 | CSS_MIXIN_FORCE_NAMED_PARAMS() {
|
15 | return 'CSS mixins must use named parameters (e.g. "func(name value, [name value, ...])")';
|
16 | },
|
17 | INVALID_NAMED_IMPORT_AS(name) {
|
18 | return `Invalid named import "as" with name "${name}"`;
|
19 | },
|
20 | INVALID_NESTED_KEYFRAMES(name) {
|
21 | return `Invalid nested keyframes import "${name}"`;
|
22 | },
|
23 | };
|
24 | exports.rootValueMapping = {
|
25 | vars: ':vars',
|
26 | import: ':import',
|
27 | stScope: 'st-scope',
|
28 | namespace: 'namespace',
|
29 | };
|
30 | exports.valueMapping = {
|
31 | from: '-st-from',
|
32 | named: '-st-named',
|
33 | default: '-st-default',
|
34 | root: '-st-root',
|
35 | states: '-st-states',
|
36 | extends: '-st-extends',
|
37 | mixin: '-st-mixin',
|
38 | partialMixin: '-st-partial-mixin',
|
39 | global: '-st-global',
|
40 | };
|
41 | exports.mixinDeclRegExp = new RegExp(`(${exports.valueMapping.mixin})|(${exports.valueMapping.partialMixin})`);
|
42 | exports.stValues = Object.keys(exports.valueMapping).map((key) => exports.valueMapping[key]);
|
43 | exports.stValuesMap = Object.keys(exports.valueMapping).reduce((acc, key) => {
|
44 | acc[exports.valueMapping[key]] = true;
|
45 | return acc;
|
46 | }, {});
|
47 | exports.STYLABLE_VALUE_MATCHER = /^-st-/;
|
48 | exports.STYLABLE_NAMED_MATCHER = new RegExp(`^${exports.valueMapping.named}-(.+)`);
|
49 | exports.SBTypesParsers = {
|
50 | '-st-root'(value) {
|
51 | return value === 'false' ? false : true;
|
52 | },
|
53 | '-st-global'(decl, _diagnostics) {
|
54 |
|
55 | const selector = selector_utils_1.parseSelector(decl.value.replace(/^['"]/, '').replace(/['"]$/, ''));
|
56 | return selector.nodes[0].nodes;
|
57 | },
|
58 | '-st-states'(value, decl, diagnostics) {
|
59 | if (!value) {
|
60 | return {};
|
61 | }
|
62 | return pseudo_states_1.processPseudoStates(value, decl, diagnostics);
|
63 | },
|
64 | '-st-extends'(value) {
|
65 | const ast = postcss_value_parser_1.default(value);
|
66 | const types = [];
|
67 | ast.walk((node) => {
|
68 | if (node.type === 'function') {
|
69 | const args = getNamedArgs(node);
|
70 | types.push({
|
71 | symbolName: node.value,
|
72 | args,
|
73 | });
|
74 | return false;
|
75 | }
|
76 | else if (node.type === 'word') {
|
77 | types.push({
|
78 | symbolName: node.value,
|
79 | args: null,
|
80 | });
|
81 | }
|
82 | return undefined;
|
83 | }, false);
|
84 | return {
|
85 | ast,
|
86 | types,
|
87 | };
|
88 | },
|
89 | '-st-named'(value, node, diagnostics) {
|
90 | const namedMap = {};
|
91 | const keyframesMap = {};
|
92 | if (value) {
|
93 | handleNamedTokens(postcss_value_parser_1.default(value), { namedMap, keyframesMap }, 'namedMap', node, diagnostics);
|
94 | }
|
95 | return { namedMap, keyframesMap };
|
96 | },
|
97 | '-st-mixin'(mixinNode, strategy, diagnostics) {
|
98 | const ast = postcss_value_parser_1.default(mixinNode.value);
|
99 | const mixins = [];
|
100 | function reportWarning(message, options) {
|
101 | if (diagnostics) {
|
102 | diagnostics.warn(mixinNode, message, options);
|
103 | }
|
104 | }
|
105 | ast.nodes.forEach((node) => {
|
106 | const strat = strategy(node.value);
|
107 | if (node.type === 'function') {
|
108 | mixins.push({
|
109 | type: node.value,
|
110 | options: exports.strategies[strat](node, reportWarning),
|
111 | });
|
112 | }
|
113 | else if (node.type === 'word') {
|
114 | mixins.push({
|
115 | type: node.value,
|
116 | options: strat === 'named' ? {} : [],
|
117 | });
|
118 | }
|
119 | else if (node.type === 'string' && diagnostics) {
|
120 | diagnostics.error(mixinNode, exports.valueParserWarnings.VALUE_CANNOT_BE_STRING(), {
|
121 | word: mixinNode.value,
|
122 | });
|
123 | }
|
124 | });
|
125 | return mixins;
|
126 | },
|
127 | '-st-partial-mixin'(mixinNode, strategy, diagnostics) {
|
128 | return exports.SBTypesParsers['-st-mixin'](mixinNode, strategy, diagnostics).map((mixin) => {
|
129 | mixin.partial = true;
|
130 | return mixin;
|
131 | });
|
132 | },
|
133 | };
|
134 | function handleNamedTokens(tokens, buckets, key = 'namedMap', node, diagnostics) {
|
135 | const { nodes } = tokens;
|
136 | for (let i = 0; i < nodes.length; i++) {
|
137 | const token = nodes[i];
|
138 | if (token.type === 'word') {
|
139 | const space = nodes[i + 1];
|
140 | const as = nodes[i + 2];
|
141 | const spaceAfter = nodes[i + 3];
|
142 | const asName = nodes[i + 4];
|
143 | if (isImportAs(space, as)) {
|
144 | if ((spaceAfter === null || spaceAfter === void 0 ? void 0 : spaceAfter.type) === 'space' && (asName === null || asName === void 0 ? void 0 : asName.type) === 'word') {
|
145 | buckets[key][asName.value] = token.value;
|
146 | i += 4;
|
147 | }
|
148 | else {
|
149 | i += !asName ? 3 : 2;
|
150 | diagnostics.warn(node, exports.valueParserWarnings.INVALID_NAMED_IMPORT_AS(token.value));
|
151 | continue;
|
152 | }
|
153 | }
|
154 | else {
|
155 | buckets[key][token.value] = token.value;
|
156 | }
|
157 | }
|
158 | else if (token.type === 'function' && token.value === 'keyframes') {
|
159 | if (key === 'keyframesMap') {
|
160 | diagnostics.warn(node, exports.valueParserWarnings.INVALID_NESTED_KEYFRAMES(postcss_value_parser_1.default.stringify(token)));
|
161 | }
|
162 | handleNamedTokens(token, buckets, 'keyframesMap', node, diagnostics);
|
163 | }
|
164 | }
|
165 | }
|
166 | function isImportAs(space, as) {
|
167 | return (space === null || space === void 0 ? void 0 : space.type) === 'space' && (as === null || as === void 0 ? void 0 : as.type) === 'word' && (as === null || as === void 0 ? void 0 : as.value) === 'as';
|
168 | }
|
169 | function getNamedArgs(node) {
|
170 | const args = [];
|
171 | if (node.nodes.length) {
|
172 | args.push([]);
|
173 | node.nodes.forEach((node) => {
|
174 | if (node.type === 'div') {
|
175 | args.push([]);
|
176 | }
|
177 | else {
|
178 | const { sourceIndex, ...clone } = node;
|
179 | args[args.length - 1].push(clone);
|
180 | }
|
181 | });
|
182 | }
|
183 |
|
184 | return args.length && args[args.length - 1].length === 0 ? args.slice(0, -1) : args;
|
185 | }
|
186 | exports.getNamedArgs = getNamedArgs;
|
187 | function getFormatterArgs(node, allowComments = false, _reportWarning, perserveQuotes = false) {
|
188 | const argsResult = [];
|
189 | let currentArg = '';
|
190 | let argIndex = 0;
|
191 | for (const currentNode of node.nodes) {
|
192 | if (currentNode.type === 'div' && currentNode.value === ',') {
|
193 | checkEmptyArg();
|
194 | argIndex++;
|
195 | argsResult.push(currentArg.trim());
|
196 | currentArg = '';
|
197 | }
|
198 | else if (currentNode.type === 'comment') {
|
199 | if (allowComments) {
|
200 | currentArg +=
|
201 | currentNode.resolvedValue || postcss_value_parser_1.default.stringify(currentNode);
|
202 | }
|
203 | }
|
204 | else if (currentNode.type === 'string') {
|
205 | currentArg += perserveQuotes
|
206 | ? postcss_value_parser_1.default.stringify(currentNode)
|
207 | : currentNode.value;
|
208 | }
|
209 | else {
|
210 | currentArg += currentNode.resolvedValue || postcss_value_parser_1.default.stringify(currentNode);
|
211 | }
|
212 | }
|
213 | checkEmptyArg();
|
214 | argsResult.push(currentArg.trim());
|
215 | let i = argsResult.length;
|
216 | while (i--) {
|
217 | if (argsResult[i] === '') {
|
218 | argsResult.pop();
|
219 | }
|
220 | else {
|
221 | return argsResult;
|
222 | }
|
223 | }
|
224 | return argsResult;
|
225 | function checkEmptyArg() {
|
226 | if (currentArg.trim() === '' && _reportWarning) {
|
227 | _reportWarning(`${postcss_value_parser_1.default.stringify(node)}: argument at index ${argIndex} is empty`);
|
228 | }
|
229 | }
|
230 | }
|
231 | exports.getFormatterArgs = getFormatterArgs;
|
232 | function getStringValue(nodes) {
|
233 | return postcss_value_parser_1.default.stringify(nodes, (node) => {
|
234 | if (node.resolvedValue !== undefined) {
|
235 | return node.resolvedValue;
|
236 | }
|
237 | else {
|
238 |
|
239 | return undefined;
|
240 | }
|
241 | });
|
242 | }
|
243 | exports.getStringValue = getStringValue;
|
244 | function groupValues(nodes, divType = 'div') {
|
245 | const grouped = [];
|
246 | let current = [];
|
247 | nodes.forEach((n) => {
|
248 | if (n.type === divType) {
|
249 | grouped.push(current);
|
250 | current = [];
|
251 | }
|
252 | else {
|
253 | current.push(n);
|
254 | }
|
255 | });
|
256 | const last = grouped[grouped.length - 1];
|
257 | if ((last && last !== current && current.length) || (!last && current.length)) {
|
258 | grouped.push(current);
|
259 | }
|
260 | return grouped;
|
261 | }
|
262 | exports.groupValues = groupValues;
|
263 | exports.strategies = {
|
264 | named: (node, reportWarning) => {
|
265 | const named = {};
|
266 | getNamedArgs(node).forEach((mixinArgsGroup) => {
|
267 | const argsDivider = mixinArgsGroup[1];
|
268 | if (mixinArgsGroup.length < 3 || (argsDivider && argsDivider.type !== 'space')) {
|
269 | if (reportWarning) {
|
270 | const argValue = mixinArgsGroup[0];
|
271 | reportWarning(exports.valueParserWarnings.CSS_MIXIN_FORCE_NAMED_PARAMS(), {
|
272 | word: argValue.value,
|
273 | });
|
274 | }
|
275 | return;
|
276 | }
|
277 | named[mixinArgsGroup[0].value] = stringifyParam(mixinArgsGroup.slice(2));
|
278 | });
|
279 | return named;
|
280 | },
|
281 | args: (node, reportWarning) => {
|
282 | return getFormatterArgs(node, true, reportWarning).map((value) => ({ value }));
|
283 | },
|
284 | };
|
285 | function stringifyParam(nodes) {
|
286 | return postcss_value_parser_1.default.stringify(nodes, (n) => {
|
287 | if (n.type === 'function') {
|
288 | return postcss_value_parser_1.default.stringify(n);
|
289 | }
|
290 | else if (n.type === 'div') {
|
291 | return null;
|
292 | }
|
293 | else if (n.type === 'string') {
|
294 | return n.value;
|
295 | }
|
296 | else {
|
297 | return undefined;
|
298 | }
|
299 | });
|
300 | }
|
301 | function listOptions(node) {
|
302 | return groupValues(node.nodes)
|
303 | .map((nodes) => postcss_value_parser_1.default.stringify(nodes, (n) => {
|
304 | if (n.type === 'div') {
|
305 | return null;
|
306 | }
|
307 | else if (n.type === 'string') {
|
308 | return n.value;
|
309 | }
|
310 | else {
|
311 | return undefined;
|
312 | }
|
313 | }))
|
314 | .filter((x) => typeof x === 'string');
|
315 | }
|
316 | exports.listOptions = listOptions;
|
317 | function validateAllowedNodesUntil(node, i, untilType = 'div', allowed = ['comment']) {
|
318 | i = 1;
|
319 | let current = node.nodes[i];
|
320 | while (current && current.type !== untilType) {
|
321 | if (!allowed.includes(current.type)) {
|
322 | return false;
|
323 | }
|
324 | i++;
|
325 | current = node.nodes[i];
|
326 | }
|
327 | return true;
|
328 | }
|
329 | exports.validateAllowedNodesUntil = validateAllowedNodesUntil;
|
330 |
|
\ | No newline at end of file |