|
1 | | -import { EnumToken } from '../types.js'; |
| 1 | +import { EnumToken, SyntaxValidationResult } from '../types.js'; |
2 | 2 | import { getSyntaxConfig } from '../../validation/config.js'; |
3 | 3 | import '../../validation/parser/types.js'; |
4 | 4 | import '../../validation/parser/parse.js'; |
5 | | -import { splitRule } from '../minify.js'; |
| 5 | +import { splitRule, definedPropertySettings } from '../minify.js'; |
6 | 6 | import { walkValues } from '../walk.js'; |
7 | | -import '../../parser/parse.js'; |
| 7 | +import { parseAtRulePrelude, parseString } from '../../parser/parse.js'; |
8 | 8 | import '../../parser/tokenize.js'; |
9 | 9 | import '../../parser/utils/config.js'; |
10 | | -import { webkitPseudoAliasMap } from '../../syntax/syntax.js'; |
11 | | -import '../../renderer/color/utils/constants.js'; |
12 | | -import '../../renderer/sourcemap/lib/encode.js'; |
| 10 | +import { pseudoAliasMap } from '../../syntax/syntax.js'; |
| 11 | +import { renderToken } from '../../renderer/render.js'; |
| 12 | +import { funcLike } from '../../renderer/color/utils/constants.js'; |
13 | 13 | import '../../validation/syntaxes/complex-selector.js'; |
14 | | -import '../../validation/syntax.js'; |
| 14 | +import { evaluateSyntax } from '../../validation/syntax.js'; |
15 | 15 |
|
16 | 16 | const config = getSyntaxConfig(); |
17 | 17 | function replacePseudo(tokens) { |
18 | 18 | return tokens.map((raw) => raw.map(r => { |
19 | | - if (r.startsWith(':-')) { |
20 | | - const i = r.indexOf('('); |
21 | | - let key = i != -1 ? r.slice(1, i) + '()' : r.slice(1); |
22 | | - if (key in webkitPseudoAliasMap) { |
23 | | - return ':' + webkitPseudoAliasMap[key] + (i == -1 ? '' : r.slice(i)); |
| 19 | + if (r.includes('(')) { |
| 20 | + const index = r.indexOf('('); |
| 21 | + const name = r.slice(0, index) + '()'; |
| 22 | + if (name in pseudoAliasMap) { |
| 23 | + return pseudoAliasMap[name] + r.slice(index); |
24 | 24 | } |
| 25 | + return r; |
25 | 26 | } |
26 | | - return r; |
| 27 | + return r in pseudoAliasMap && pseudoAliasMap[r] in config["selectors" /* ValidationSyntaxGroupEnum.Selectors */] ? pseudoAliasMap[r] : r; |
27 | 28 | })); |
28 | 29 | } |
29 | | -function replaceAstNodes(tokens) { |
30 | | - for (const { value } of walkValues(tokens)) { |
31 | | - if (value.typ == EnumToken.PseudoClassFuncTokenType || value.typ == EnumToken.PseudoClassTokenType) { |
32 | | - if (value.val.startsWith(':-')) { |
33 | | - let key = value.val.slice(1) + (value.typ == EnumToken.PseudoClassFuncTokenType ? '()' : ''); |
34 | | - if (key in webkitPseudoAliasMap) { |
35 | | - value.val = ':' + webkitPseudoAliasMap[key]; |
| 30 | +function replaceAstNodes(tokens, root) { |
| 31 | + let result = false; |
| 32 | + for (const { value, parent } of walkValues(tokens, root)) { |
| 33 | + if (value.typ == EnumToken.IdenTokenType || value.typ == EnumToken.PseudoClassFuncTokenType || value.typ == EnumToken.PseudoClassTokenType || value.typ == EnumToken.PseudoElementTokenType) { |
| 34 | + let key = value.val + (value.typ == EnumToken.PseudoClassFuncTokenType ? '()' : ''); |
| 35 | + if (key in pseudoAliasMap) { |
| 36 | + const isPseudClass = pseudoAliasMap[key].startsWith('::'); |
| 37 | + value.val = pseudoAliasMap[key]; |
| 38 | + if (value.typ == EnumToken.IdenTokenType && |
| 39 | + ['min-resolution', 'max-resolution'].includes(value.val) && |
| 40 | + parent?.typ == EnumToken.MediaQueryConditionTokenType && |
| 41 | + parent.r?.[0]?.typ == EnumToken.NumberTokenType) { |
| 42 | + Object.assign(parent.r?.[0], { |
| 43 | + typ: EnumToken.ResolutionTokenType, |
| 44 | + unit: 'x', |
| 45 | + }); |
36 | 46 | } |
| 47 | + else if (isPseudClass && value.typ == EnumToken.PseudoElementTokenType) { |
| 48 | + // @ts-ignore |
| 49 | + value.typ = EnumToken.PseudoClassTokenType; |
| 50 | + } |
| 51 | + result = true; |
37 | 52 | } |
38 | 53 | } |
39 | 54 | } |
| 55 | + return result; |
40 | 56 | } |
41 | 57 | class ComputePrefixFeature { |
42 | 58 | get ordering() { |
@@ -71,13 +87,63 @@ class ComputePrefixFeature { |
71 | 87 | if (node.nam.charAt(0) == '-') { |
72 | 88 | const match = node.nam.match(/^-([^-]+)-(.+)$/); |
73 | 89 | if (match != null) { |
74 | | - const nam = match[2]; |
75 | | - if (nam.toLowerCase() in config.declarations) { |
| 90 | + let nam = match[2]; |
| 91 | + if (!(nam in config.declarations)) { |
| 92 | + if (node.nam in pseudoAliasMap) { |
| 93 | + nam = pseudoAliasMap[node.nam]; |
| 94 | + } |
| 95 | + } |
| 96 | + if (nam in config.declarations) { |
76 | 97 | node.nam = nam; |
77 | | - replaceAstNodes(node.val); |
78 | 98 | } |
79 | 99 | } |
80 | 100 | } |
| 101 | + let hasPrefix = false; |
| 102 | + for (const { value } of walkValues(node.val)) { |
| 103 | + if ((value.typ == EnumToken.IdenTokenType || funcLike.includes(value.typ)) && value.val.match(/^-([^-]+)-(.+)$/) != null) { |
| 104 | + if (value.val.endsWith('-gradient')) { |
| 105 | + // not supported yet |
| 106 | + break; |
| 107 | + } |
| 108 | + hasPrefix = true; |
| 109 | + break; |
| 110 | + } |
| 111 | + } |
| 112 | + if (hasPrefix) { |
| 113 | + const nodes = structuredClone(node.val); |
| 114 | + for (const { value } of walkValues(nodes)) { |
| 115 | + if ((value.typ == EnumToken.IdenTokenType || funcLike.includes(value.typ))) { |
| 116 | + const match = value.val.match(/^-([^-]+)-(.+)$/); |
| 117 | + if (match == null) { |
| 118 | + continue; |
| 119 | + } |
| 120 | + value.val = match[2]; |
| 121 | + } |
| 122 | + } |
| 123 | + if (SyntaxValidationResult.Valid == evaluateSyntax({ ...node, val: nodes }, {}).valid) { |
| 124 | + node.val = nodes; |
| 125 | + } |
| 126 | + } |
| 127 | + } |
| 128 | + else if (node.typ == EnumToken.AtRuleNodeType || node.typ == EnumToken.KeyframeAtRuleNodeType) { |
| 129 | + if (node.nam.startsWith('-')) { |
| 130 | + const match = node.nam.match(/^-([^-]+)-(.+)$/); |
| 131 | + if (match != null && '@' + match[2] in config.atRules) { |
| 132 | + node.nam = match[2]; |
| 133 | + } |
| 134 | + } |
| 135 | + if (node.typ == EnumToken.AtRuleNodeType && node.val !== '') { |
| 136 | + if (node.tokens == null) { |
| 137 | + Object.defineProperty(node, 'tokens', { |
| 138 | + // @ts-ignore |
| 139 | + ...definedPropertySettings, |
| 140 | + value: parseAtRulePrelude(parseString(node.val), node), |
| 141 | + }); |
| 142 | + } |
| 143 | + if (replaceAstNodes(node.tokens)) { |
| 144 | + node.val = node.tokens.reduce((acc, curr) => acc + renderToken(curr), ''); |
| 145 | + } |
| 146 | + } |
81 | 147 | } |
82 | 148 | return node; |
83 | 149 | } |
|
0 commit comments