@eslint/css-tree 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +20 -0
- package/README.md +194 -0
- package/cjs/convertor/create.cjs +32 -0
- package/cjs/convertor/index.cjs +8 -0
- package/cjs/data-patch.cjs +7 -0
- package/cjs/data.cjs +120 -0
- package/cjs/definition-syntax/SyntaxError.cjs +16 -0
- package/cjs/definition-syntax/generate.cjs +139 -0
- package/cjs/definition-syntax/index.cjs +13 -0
- package/cjs/definition-syntax/parse.cjs +556 -0
- package/cjs/definition-syntax/scanner.cjs +113 -0
- package/cjs/definition-syntax/walk.cjs +57 -0
- package/cjs/generator/create.cjs +102 -0
- package/cjs/generator/index.cjs +8 -0
- package/cjs/generator/sourceMap.cjs +96 -0
- package/cjs/generator/token-before.cjs +170 -0
- package/cjs/index.cjs +65 -0
- package/cjs/lexer/Lexer.cjs +517 -0
- package/cjs/lexer/error.cjs +128 -0
- package/cjs/lexer/generic-an-plus-b.cjs +235 -0
- package/cjs/lexer/generic-const.cjs +12 -0
- package/cjs/lexer/generic-urange.cjs +149 -0
- package/cjs/lexer/generic.cjs +589 -0
- package/cjs/lexer/index.cjs +7 -0
- package/cjs/lexer/match-graph.cjs +530 -0
- package/cjs/lexer/match.cjs +632 -0
- package/cjs/lexer/prepare-tokens.cjs +54 -0
- package/cjs/lexer/search.cjs +65 -0
- package/cjs/lexer/structure.cjs +173 -0
- package/cjs/lexer/trace.cjs +73 -0
- package/cjs/lexer/units.cjs +38 -0
- package/cjs/parser/SyntaxError.cjs +74 -0
- package/cjs/parser/create.cjs +378 -0
- package/cjs/parser/index.cjs +8 -0
- package/cjs/parser/parse-selector.cjs +8 -0
- package/cjs/parser/sequence.cjs +47 -0
- package/cjs/syntax/atrule/container.cjs +32 -0
- package/cjs/syntax/atrule/font-face.cjs +12 -0
- package/cjs/syntax/atrule/import.cjs +101 -0
- package/cjs/syntax/atrule/index.cjs +27 -0
- package/cjs/syntax/atrule/layer.cjs +16 -0
- package/cjs/syntax/atrule/media.cjs +16 -0
- package/cjs/syntax/atrule/nest.cjs +16 -0
- package/cjs/syntax/atrule/page.cjs +16 -0
- package/cjs/syntax/atrule/scope.cjs +16 -0
- package/cjs/syntax/atrule/starting-style.cjs +12 -0
- package/cjs/syntax/atrule/supports.cjs +16 -0
- package/cjs/syntax/config/generator.cjs +9 -0
- package/cjs/syntax/config/lexer.cjs +14 -0
- package/cjs/syntax/config/mix.cjs +126 -0
- package/cjs/syntax/config/parser-selector.cjs +19 -0
- package/cjs/syntax/config/parser.cjs +49 -0
- package/cjs/syntax/config/walker.cjs +9 -0
- package/cjs/syntax/create.cjs +58 -0
- package/cjs/syntax/function/expression.cjs +11 -0
- package/cjs/syntax/function/var.cjs +43 -0
- package/cjs/syntax/index.cjs +14 -0
- package/cjs/syntax/node/AnPlusB.cjs +293 -0
- package/cjs/syntax/node/Atrule.cjs +103 -0
- package/cjs/syntax/node/AtrulePrelude.cjs +52 -0
- package/cjs/syntax/node/AttributeSelector.cjs +148 -0
- package/cjs/syntax/node/Block.cjs +96 -0
- package/cjs/syntax/node/Brackets.cjs +38 -0
- package/cjs/syntax/node/CDC.cjs +26 -0
- package/cjs/syntax/node/CDO.cjs +26 -0
- package/cjs/syntax/node/ClassSelector.cjs +31 -0
- package/cjs/syntax/node/Combinator.cjs +61 -0
- package/cjs/syntax/node/Comment.cjs +40 -0
- package/cjs/syntax/node/Condition.cjs +120 -0
- package/cjs/syntax/node/Declaration.cjs +166 -0
- package/cjs/syntax/node/DeclarationList.cjs +62 -0
- package/cjs/syntax/node/Dimension.cjs +30 -0
- package/cjs/syntax/node/Feature.cjs +101 -0
- package/cjs/syntax/node/FeatureFunction.cjs +67 -0
- package/cjs/syntax/node/FeatureRange.cjs +133 -0
- package/cjs/syntax/node/Function.cjs +45 -0
- package/cjs/syntax/node/GeneralEnclosed.cjs +68 -0
- package/cjs/syntax/node/Hash.cjs +30 -0
- package/cjs/syntax/node/IdSelector.cjs +33 -0
- package/cjs/syntax/node/Identifier.cjs +25 -0
- package/cjs/syntax/node/Layer.cjs +35 -0
- package/cjs/syntax/node/LayerList.cjs +43 -0
- package/cjs/syntax/node/MediaQuery.cjs +100 -0
- package/cjs/syntax/node/MediaQueryList.cjs +41 -0
- package/cjs/syntax/node/NestingSelector.cjs +29 -0
- package/cjs/syntax/node/Nth.cjs +54 -0
- package/cjs/syntax/node/Number.cjs +25 -0
- package/cjs/syntax/node/Operator.cjs +28 -0
- package/cjs/syntax/node/Parentheses.cjs +38 -0
- package/cjs/syntax/node/Percentage.cjs +25 -0
- package/cjs/syntax/node/PseudoClassSelector.cjs +67 -0
- package/cjs/syntax/node/PseudoElementSelector.cjs +69 -0
- package/cjs/syntax/node/Ratio.cjs +71 -0
- package/cjs/syntax/node/Raw.cjs +48 -0
- package/cjs/syntax/node/Rule.cjs +58 -0
- package/cjs/syntax/node/Scope.cjs +69 -0
- package/cjs/syntax/node/Selector.cjs +38 -0
- package/cjs/syntax/node/SelectorList.cjs +43 -0
- package/cjs/syntax/node/String.cjs +26 -0
- package/cjs/syntax/node/StyleSheet.cjs +83 -0
- package/cjs/syntax/node/SupportsDeclaration.cjs +38 -0
- package/cjs/syntax/node/TypeSelector.cjs +59 -0
- package/cjs/syntax/node/UnicodeRange.cjs +158 -0
- package/cjs/syntax/node/Url.cjs +54 -0
- package/cjs/syntax/node/Value.cjs +26 -0
- package/cjs/syntax/node/WhiteSpace.cjs +34 -0
- package/cjs/syntax/node/index-generate.cjs +103 -0
- package/cjs/syntax/node/index-parse-selector.cjs +39 -0
- package/cjs/syntax/node/index-parse.cjs +103 -0
- package/cjs/syntax/node/index.cjs +103 -0
- package/cjs/syntax/pseudo/index.cjs +60 -0
- package/cjs/syntax/pseudo/lang.cjs +37 -0
- package/cjs/syntax/scope/atrulePrelude.cjs +9 -0
- package/cjs/syntax/scope/default.cjs +76 -0
- package/cjs/syntax/scope/index.cjs +11 -0
- package/cjs/syntax/scope/selector.cjs +88 -0
- package/cjs/syntax/scope/value.cjs +29 -0
- package/cjs/tokenizer/OffsetToLocation.cjs +91 -0
- package/cjs/tokenizer/TokenStream.cjs +358 -0
- package/cjs/tokenizer/adopt-buffer.cjs +13 -0
- package/cjs/tokenizer/char-code-definitions.cjs +236 -0
- package/cjs/tokenizer/index.cjs +554 -0
- package/cjs/tokenizer/names.cjs +32 -0
- package/cjs/tokenizer/types.cjs +57 -0
- package/cjs/tokenizer/utils.cjs +261 -0
- package/cjs/utils/List.cjs +473 -0
- package/cjs/utils/clone.cjs +25 -0
- package/cjs/utils/create-custom-error.cjs +18 -0
- package/cjs/utils/ident.cjs +102 -0
- package/cjs/utils/index.cjs +20 -0
- package/cjs/utils/names.cjs +113 -0
- package/cjs/utils/string.cjs +99 -0
- package/cjs/utils/url.cjs +108 -0
- package/cjs/version.cjs +5 -0
- package/cjs/walker/create.cjs +291 -0
- package/cjs/walker/index.cjs +8 -0
- package/data/patch.json +874 -0
- package/dist/csstree.esm.js +12 -0
- package/dist/csstree.js +12 -0
- package/dist/data.cjs +1341 -0
- package/dist/data.js +1341 -0
- package/dist/version.cjs +1 -0
- package/dist/version.js +1 -0
- package/lib/convertor/create.js +28 -0
- package/lib/convertor/index.js +4 -0
- package/lib/data-patch.js +6 -0
- package/lib/data.js +118 -0
- package/lib/definition-syntax/SyntaxError.js +12 -0
- package/lib/definition-syntax/generate.js +135 -0
- package/lib/definition-syntax/index.js +4 -0
- package/lib/definition-syntax/parse.js +552 -0
- package/lib/definition-syntax/scanner.js +109 -0
- package/lib/definition-syntax/walk.js +53 -0
- package/lib/generator/create.js +97 -0
- package/lib/generator/index.js +4 -0
- package/lib/generator/sourceMap.js +92 -0
- package/lib/generator/token-before.js +182 -0
- package/lib/index.d.ts +3016 -0
- package/lib/index.js +30 -0
- package/lib/lexer/Lexer.js +511 -0
- package/lib/lexer/error.js +123 -0
- package/lib/lexer/generic-an-plus-b.js +238 -0
- package/lib/lexer/generic-const.js +8 -0
- package/lib/lexer/generic-urange.js +151 -0
- package/lib/lexer/generic.js +622 -0
- package/lib/lexer/index.js +1 -0
- package/lib/lexer/match-graph.js +527 -0
- package/lib/lexer/match.js +630 -0
- package/lib/lexer/prepare-tokens.js +50 -0
- package/lib/lexer/search.js +61 -0
- package/lib/lexer/structure.js +169 -0
- package/lib/lexer/trace.js +66 -0
- package/lib/lexer/units.js +27 -0
- package/lib/parser/SyntaxError.js +70 -0
- package/lib/parser/create.js +388 -0
- package/lib/parser/index.js +4 -0
- package/lib/parser/parse-selector.js +4 -0
- package/lib/parser/sequence.js +43 -0
- package/lib/syntax/atrule/container.js +28 -0
- package/lib/syntax/atrule/font-face.js +8 -0
- package/lib/syntax/atrule/import.js +104 -0
- package/lib/syntax/atrule/index.js +23 -0
- package/lib/syntax/atrule/layer.js +12 -0
- package/lib/syntax/atrule/media.js +12 -0
- package/lib/syntax/atrule/nest.js +12 -0
- package/lib/syntax/atrule/page.js +12 -0
- package/lib/syntax/atrule/scope.js +12 -0
- package/lib/syntax/atrule/starting-style.js +8 -0
- package/lib/syntax/atrule/supports.js +12 -0
- package/lib/syntax/config/generator.js +5 -0
- package/lib/syntax/config/lexer.js +10 -0
- package/lib/syntax/config/mix.js +122 -0
- package/lib/syntax/config/parser-selector.js +15 -0
- package/lib/syntax/config/parser.js +45 -0
- package/lib/syntax/config/walker.js +5 -0
- package/lib/syntax/create.js +55 -0
- package/lib/syntax/function/expression.js +7 -0
- package/lib/syntax/function/var.js +39 -0
- package/lib/syntax/index.js +10 -0
- package/lib/syntax/node/AnPlusB.js +292 -0
- package/lib/syntax/node/Atrule.js +100 -0
- package/lib/syntax/node/AtrulePrelude.js +47 -0
- package/lib/syntax/node/AttributeSelector.js +147 -0
- package/lib/syntax/node/Block.js +95 -0
- package/lib/syntax/node/Brackets.js +35 -0
- package/lib/syntax/node/CDC.js +19 -0
- package/lib/syntax/node/CDO.js +19 -0
- package/lib/syntax/node/ClassSelector.js +24 -0
- package/lib/syntax/node/Combinator.js +54 -0
- package/lib/syntax/node/Comment.js +33 -0
- package/lib/syntax/node/Condition.js +123 -0
- package/lib/syntax/node/Declaration.js +165 -0
- package/lib/syntax/node/DeclarationList.js +62 -0
- package/lib/syntax/node/Dimension.js +23 -0
- package/lib/syntax/node/Feature.js +103 -0
- package/lib/syntax/node/FeatureFunction.js +63 -0
- package/lib/syntax/node/FeatureRange.js +133 -0
- package/lib/syntax/node/Function.js +41 -0
- package/lib/syntax/node/GeneralEnclosed.js +66 -0
- package/lib/syntax/node/Hash.js +23 -0
- package/lib/syntax/node/IdSelector.js +26 -0
- package/lib/syntax/node/Identifier.js +18 -0
- package/lib/syntax/node/Layer.js +28 -0
- package/lib/syntax/node/LayerList.js +36 -0
- package/lib/syntax/node/MediaQuery.js +102 -0
- package/lib/syntax/node/MediaQueryList.js +34 -0
- package/lib/syntax/node/NestingSelector.js +22 -0
- package/lib/syntax/node/Nth.js +47 -0
- package/lib/syntax/node/Number.js +18 -0
- package/lib/syntax/node/Operator.js +21 -0
- package/lib/syntax/node/Parentheses.js +34 -0
- package/lib/syntax/node/Percentage.js +18 -0
- package/lib/syntax/node/PseudoClassSelector.js +65 -0
- package/lib/syntax/node/PseudoElementSelector.js +66 -0
- package/lib/syntax/node/Ratio.js +68 -0
- package/lib/syntax/node/Raw.js +41 -0
- package/lib/syntax/node/Rule.js +51 -0
- package/lib/syntax/node/Scope.js +66 -0
- package/lib/syntax/node/Selector.js +31 -0
- package/lib/syntax/node/SelectorList.js +35 -0
- package/lib/syntax/node/String.js +19 -0
- package/lib/syntax/node/StyleSheet.js +82 -0
- package/lib/syntax/node/SupportsDeclaration.js +34 -0
- package/lib/syntax/node/TypeSelector.js +52 -0
- package/lib/syntax/node/UnicodeRange.js +156 -0
- package/lib/syntax/node/Url.js +52 -0
- package/lib/syntax/node/Value.js +19 -0
- package/lib/syntax/node/WhiteSpace.js +27 -0
- package/lib/syntax/node/index-generate.js +49 -0
- package/lib/syntax/node/index-parse-selector.js +17 -0
- package/lib/syntax/node/index-parse.js +49 -0
- package/lib/syntax/node/index.js +49 -0
- package/lib/syntax/pseudo/index.js +56 -0
- package/lib/syntax/pseudo/lang.js +33 -0
- package/lib/syntax/scope/atrulePrelude.js +5 -0
- package/lib/syntax/scope/default.js +85 -0
- package/lib/syntax/scope/index.js +3 -0
- package/lib/syntax/scope/selector.js +94 -0
- package/lib/syntax/scope/value.js +25 -0
- package/lib/tokenizer/OffsetToLocation.js +87 -0
- package/lib/tokenizer/TokenStream.js +366 -0
- package/lib/tokenizer/adopt-buffer.js +9 -0
- package/lib/tokenizer/char-code-definitions.js +212 -0
- package/lib/tokenizer/index.js +513 -0
- package/lib/tokenizer/names.js +28 -0
- package/lib/tokenizer/types.js +28 -0
- package/lib/tokenizer/utils.js +254 -0
- package/lib/utils/List.js +469 -0
- package/lib/utils/clone.js +21 -0
- package/lib/utils/create-custom-error.js +14 -0
- package/lib/utils/ident.js +101 -0
- package/lib/utils/index.js +6 -0
- package/lib/utils/names.js +106 -0
- package/lib/utils/string.js +99 -0
- package/lib/utils/url.js +108 -0
- package/lib/version.js +5 -0
- package/lib/walker/create.js +287 -0
- package/lib/walker/index.js +4 -0
- package/package.json +133 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const keywords = new Map();
|
|
4
|
+
const properties = new Map();
|
|
5
|
+
const HYPHENMINUS = 45; // '-'.charCodeAt()
|
|
6
|
+
|
|
7
|
+
const keyword = getKeywordDescriptor;
|
|
8
|
+
const property = getPropertyDescriptor;
|
|
9
|
+
const vendorPrefix = getVendorPrefix;
|
|
10
|
+
function isCustomProperty(str, offset) {
|
|
11
|
+
offset = offset || 0;
|
|
12
|
+
|
|
13
|
+
return str.length - offset >= 2 &&
|
|
14
|
+
str.charCodeAt(offset) === HYPHENMINUS &&
|
|
15
|
+
str.charCodeAt(offset + 1) === HYPHENMINUS;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function getVendorPrefix(str, offset) {
|
|
19
|
+
offset = offset || 0;
|
|
20
|
+
|
|
21
|
+
// verdor prefix should be at least 3 chars length
|
|
22
|
+
if (str.length - offset >= 3) {
|
|
23
|
+
// vendor prefix starts with hyper minus following non-hyper minus
|
|
24
|
+
if (str.charCodeAt(offset) === HYPHENMINUS &&
|
|
25
|
+
str.charCodeAt(offset + 1) !== HYPHENMINUS) {
|
|
26
|
+
// vendor prefix should contain a hyper minus at the ending
|
|
27
|
+
const secondDashIndex = str.indexOf('-', offset + 2);
|
|
28
|
+
|
|
29
|
+
if (secondDashIndex !== -1) {
|
|
30
|
+
return str.substring(offset, secondDashIndex + 1);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return '';
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function getKeywordDescriptor(keyword) {
|
|
39
|
+
if (keywords.has(keyword)) {
|
|
40
|
+
return keywords.get(keyword);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const name = keyword.toLowerCase();
|
|
44
|
+
let descriptor = keywords.get(name);
|
|
45
|
+
|
|
46
|
+
if (descriptor === undefined) {
|
|
47
|
+
const custom = isCustomProperty(name, 0);
|
|
48
|
+
const vendor = !custom ? getVendorPrefix(name, 0) : '';
|
|
49
|
+
descriptor = Object.freeze({
|
|
50
|
+
basename: name.substr(vendor.length),
|
|
51
|
+
name,
|
|
52
|
+
prefix: vendor,
|
|
53
|
+
vendor,
|
|
54
|
+
custom
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
keywords.set(keyword, descriptor);
|
|
59
|
+
|
|
60
|
+
return descriptor;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function getPropertyDescriptor(property) {
|
|
64
|
+
if (properties.has(property)) {
|
|
65
|
+
return properties.get(property);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
let name = property;
|
|
69
|
+
let hack = property[0];
|
|
70
|
+
|
|
71
|
+
if (hack === '/') {
|
|
72
|
+
hack = property[1] === '/' ? '//' : '/';
|
|
73
|
+
} else if (hack !== '_' &&
|
|
74
|
+
hack !== '*' &&
|
|
75
|
+
hack !== '$' &&
|
|
76
|
+
hack !== '#' &&
|
|
77
|
+
hack !== '+' &&
|
|
78
|
+
hack !== '&') {
|
|
79
|
+
hack = '';
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const custom = isCustomProperty(name, hack.length);
|
|
83
|
+
|
|
84
|
+
// re-use result when possible (the same as for lower case)
|
|
85
|
+
if (!custom) {
|
|
86
|
+
name = name.toLowerCase();
|
|
87
|
+
if (properties.has(name)) {
|
|
88
|
+
const descriptor = properties.get(name);
|
|
89
|
+
properties.set(property, descriptor);
|
|
90
|
+
return descriptor;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const vendor = !custom ? getVendorPrefix(name, hack.length) : '';
|
|
95
|
+
const prefix = name.substr(0, hack.length + vendor.length);
|
|
96
|
+
const descriptor = Object.freeze({
|
|
97
|
+
basename: name.substr(prefix.length),
|
|
98
|
+
name: name.substr(hack.length),
|
|
99
|
+
hack,
|
|
100
|
+
vendor,
|
|
101
|
+
prefix,
|
|
102
|
+
custom
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
properties.set(property, descriptor);
|
|
106
|
+
|
|
107
|
+
return descriptor;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
exports.isCustomProperty = isCustomProperty;
|
|
111
|
+
exports.keyword = keyword;
|
|
112
|
+
exports.property = property;
|
|
113
|
+
exports.vendorPrefix = vendorPrefix;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const charCodeDefinitions = require('../tokenizer/char-code-definitions.cjs');
|
|
4
|
+
const utils = require('../tokenizer/utils.cjs');
|
|
5
|
+
|
|
6
|
+
const REVERSE_SOLIDUS = 0x005c; // U+005C REVERSE SOLIDUS (\)
|
|
7
|
+
const QUOTATION_MARK = 0x0022; // "
|
|
8
|
+
const APOSTROPHE = 0x0027; // '
|
|
9
|
+
|
|
10
|
+
function decode(str) {
|
|
11
|
+
const len = str.length;
|
|
12
|
+
const firstChar = str.charCodeAt(0);
|
|
13
|
+
const start = firstChar === QUOTATION_MARK || firstChar === APOSTROPHE ? 1 : 0;
|
|
14
|
+
const end = start === 1 && len > 1 && str.charCodeAt(len - 1) === firstChar ? len - 2 : len - 1;
|
|
15
|
+
let decoded = '';
|
|
16
|
+
|
|
17
|
+
for (let i = start; i <= end; i++) {
|
|
18
|
+
let code = str.charCodeAt(i);
|
|
19
|
+
|
|
20
|
+
if (code === REVERSE_SOLIDUS) {
|
|
21
|
+
// special case at the ending
|
|
22
|
+
if (i === end) {
|
|
23
|
+
// if the next input code point is EOF, do nothing
|
|
24
|
+
// otherwise include last quote as escaped
|
|
25
|
+
if (i !== len - 1) {
|
|
26
|
+
decoded = str.substr(i + 1);
|
|
27
|
+
}
|
|
28
|
+
break;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
code = str.charCodeAt(++i);
|
|
32
|
+
|
|
33
|
+
// consume escaped
|
|
34
|
+
if (charCodeDefinitions.isValidEscape(REVERSE_SOLIDUS, code)) {
|
|
35
|
+
const escapeStart = i - 1;
|
|
36
|
+
const escapeEnd = utils.consumeEscaped(str, escapeStart);
|
|
37
|
+
|
|
38
|
+
i = escapeEnd - 1;
|
|
39
|
+
decoded += utils.decodeEscaped(str.substring(escapeStart + 1, escapeEnd));
|
|
40
|
+
} else {
|
|
41
|
+
// \r\n
|
|
42
|
+
if (code === 0x000d && str.charCodeAt(i + 1) === 0x000a) {
|
|
43
|
+
i++;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
} else {
|
|
47
|
+
decoded += str[i];
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return decoded;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// https://drafts.csswg.org/cssom/#serialize-a-string
|
|
55
|
+
// § 2.1. Common Serializing Idioms
|
|
56
|
+
function encode(str, apostrophe) {
|
|
57
|
+
const quote = apostrophe ? '\'' : '"';
|
|
58
|
+
const quoteCode = apostrophe ? APOSTROPHE : QUOTATION_MARK;
|
|
59
|
+
let encoded = '';
|
|
60
|
+
let wsBeforeHexIsNeeded = false;
|
|
61
|
+
|
|
62
|
+
for (let i = 0; i < str.length; i++) {
|
|
63
|
+
const code = str.charCodeAt(i);
|
|
64
|
+
|
|
65
|
+
// If the character is NULL (U+0000), then the REPLACEMENT CHARACTER (U+FFFD).
|
|
66
|
+
if (code === 0x0000) {
|
|
67
|
+
encoded += '\uFFFD';
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// If the character is in the range [\1-\1f] (U+0001 to U+001F) or is U+007F,
|
|
72
|
+
// the character escaped as code point.
|
|
73
|
+
// Note: Do not compare with 0x0001 since 0x0000 is precessed before
|
|
74
|
+
if (code <= 0x001f || code === 0x007F) {
|
|
75
|
+
encoded += '\\' + code.toString(16);
|
|
76
|
+
wsBeforeHexIsNeeded = true;
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// If the character is '"' (U+0022) or "\" (U+005C), the escaped character.
|
|
81
|
+
if (code === quoteCode || code === REVERSE_SOLIDUS) {
|
|
82
|
+
encoded += '\\' + str.charAt(i);
|
|
83
|
+
wsBeforeHexIsNeeded = false;
|
|
84
|
+
} else {
|
|
85
|
+
if (wsBeforeHexIsNeeded && (charCodeDefinitions.isHexDigit(code) || charCodeDefinitions.isWhiteSpace(code))) {
|
|
86
|
+
encoded += ' ';
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Otherwise, the character itself.
|
|
90
|
+
encoded += str.charAt(i);
|
|
91
|
+
wsBeforeHexIsNeeded = false;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return quote + encoded + quote;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
exports.decode = decode;
|
|
99
|
+
exports.encode = encode;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const charCodeDefinitions = require('../tokenizer/char-code-definitions.cjs');
|
|
4
|
+
const utils = require('../tokenizer/utils.cjs');
|
|
5
|
+
|
|
6
|
+
const SPACE = 0x0020; // U+0020 SPACE
|
|
7
|
+
const REVERSE_SOLIDUS = 0x005c; // U+005C REVERSE SOLIDUS (\)
|
|
8
|
+
const QUOTATION_MARK = 0x0022; // "
|
|
9
|
+
const APOSTROPHE = 0x0027; // '
|
|
10
|
+
const LEFTPARENTHESIS = 0x0028; // U+0028 LEFT PARENTHESIS (()
|
|
11
|
+
const RIGHTPARENTHESIS = 0x0029; // U+0029 RIGHT PARENTHESIS ())
|
|
12
|
+
|
|
13
|
+
function decode(str) {
|
|
14
|
+
const len = str.length;
|
|
15
|
+
let start = 4; // length of "url("
|
|
16
|
+
let end = str.charCodeAt(len - 1) === RIGHTPARENTHESIS ? len - 2 : len - 1;
|
|
17
|
+
let decoded = '';
|
|
18
|
+
|
|
19
|
+
while (start < end && charCodeDefinitions.isWhiteSpace(str.charCodeAt(start))) {
|
|
20
|
+
start++;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
while (start < end && charCodeDefinitions.isWhiteSpace(str.charCodeAt(end))) {
|
|
24
|
+
end--;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
for (let i = start; i <= end; i++) {
|
|
28
|
+
let code = str.charCodeAt(i);
|
|
29
|
+
|
|
30
|
+
if (code === REVERSE_SOLIDUS) {
|
|
31
|
+
// special case at the ending
|
|
32
|
+
if (i === end) {
|
|
33
|
+
// if the next input code point is EOF, do nothing
|
|
34
|
+
// otherwise include last left parenthesis as escaped
|
|
35
|
+
if (i !== len - 1) {
|
|
36
|
+
decoded = str.substr(i + 1);
|
|
37
|
+
}
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
code = str.charCodeAt(++i);
|
|
42
|
+
|
|
43
|
+
// consume escaped
|
|
44
|
+
if (charCodeDefinitions.isValidEscape(REVERSE_SOLIDUS, code)) {
|
|
45
|
+
const escapeStart = i - 1;
|
|
46
|
+
const escapeEnd = utils.consumeEscaped(str, escapeStart);
|
|
47
|
+
|
|
48
|
+
i = escapeEnd - 1;
|
|
49
|
+
decoded += utils.decodeEscaped(str.substring(escapeStart + 1, escapeEnd));
|
|
50
|
+
} else {
|
|
51
|
+
// \r\n
|
|
52
|
+
if (code === 0x000d && str.charCodeAt(i + 1) === 0x000a) {
|
|
53
|
+
i++;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
} else {
|
|
57
|
+
decoded += str[i];
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return decoded;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function encode(str) {
|
|
65
|
+
let encoded = '';
|
|
66
|
+
let wsBeforeHexIsNeeded = false;
|
|
67
|
+
|
|
68
|
+
for (let i = 0; i < str.length; i++) {
|
|
69
|
+
const code = str.charCodeAt(i);
|
|
70
|
+
|
|
71
|
+
// If the character is NULL (U+0000), then the REPLACEMENT CHARACTER (U+FFFD).
|
|
72
|
+
if (code === 0x0000) {
|
|
73
|
+
encoded += '\uFFFD';
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// If the character is in the range [\1-\1f] (U+0001 to U+001F) or is U+007F,
|
|
78
|
+
// the character escaped as code point.
|
|
79
|
+
// Note: Do not compare with 0x0001 since 0x0000 is precessed before
|
|
80
|
+
if (code <= 0x001f || code === 0x007F) {
|
|
81
|
+
encoded += '\\' + code.toString(16);
|
|
82
|
+
wsBeforeHexIsNeeded = true;
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (code === SPACE ||
|
|
87
|
+
code === REVERSE_SOLIDUS ||
|
|
88
|
+
code === QUOTATION_MARK ||
|
|
89
|
+
code === APOSTROPHE ||
|
|
90
|
+
code === LEFTPARENTHESIS ||
|
|
91
|
+
code === RIGHTPARENTHESIS) {
|
|
92
|
+
encoded += '\\' + str.charAt(i);
|
|
93
|
+
wsBeforeHexIsNeeded = false;
|
|
94
|
+
} else {
|
|
95
|
+
if (wsBeforeHexIsNeeded && charCodeDefinitions.isHexDigit(code)) {
|
|
96
|
+
encoded += ' ';
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
encoded += str.charAt(i);
|
|
100
|
+
wsBeforeHexIsNeeded = false;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return 'url(' + encoded + ')';
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
exports.decode = decode;
|
|
108
|
+
exports.encode = encode;
|
package/cjs/version.cjs
ADDED
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { hasOwnProperty } = Object.prototype;
|
|
4
|
+
const noop = function() {};
|
|
5
|
+
|
|
6
|
+
function ensureFunction(value) {
|
|
7
|
+
return typeof value === 'function' ? value : noop;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function invokeForType(fn, type) {
|
|
11
|
+
return function(node, item, list) {
|
|
12
|
+
if (node.type === type) {
|
|
13
|
+
fn.call(this, node, item, list);
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function getWalkersFromStructure(name, nodeType) {
|
|
19
|
+
const structure = nodeType.structure;
|
|
20
|
+
const walkers = [];
|
|
21
|
+
|
|
22
|
+
for (const key in structure) {
|
|
23
|
+
if (hasOwnProperty.call(structure, key) === false) {
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
let fieldTypes = structure[key];
|
|
28
|
+
const walker = {
|
|
29
|
+
name: key,
|
|
30
|
+
type: false,
|
|
31
|
+
nullable: false
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
if (!Array.isArray(fieldTypes)) {
|
|
35
|
+
fieldTypes = [fieldTypes];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
for (const fieldType of fieldTypes) {
|
|
39
|
+
if (fieldType === null) {
|
|
40
|
+
walker.nullable = true;
|
|
41
|
+
} else if (typeof fieldType === 'string') {
|
|
42
|
+
walker.type = 'node';
|
|
43
|
+
} else if (Array.isArray(fieldType)) {
|
|
44
|
+
walker.type = 'list';
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (walker.type) {
|
|
49
|
+
walkers.push(walker);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (walkers.length) {
|
|
54
|
+
return {
|
|
55
|
+
context: nodeType.walkContext,
|
|
56
|
+
fields: walkers
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function getTypesFromConfig(config) {
|
|
64
|
+
const types = {};
|
|
65
|
+
|
|
66
|
+
for (const name in config.node) {
|
|
67
|
+
if (hasOwnProperty.call(config.node, name)) {
|
|
68
|
+
const nodeType = config.node[name];
|
|
69
|
+
|
|
70
|
+
if (!nodeType.structure) {
|
|
71
|
+
throw new Error('Missed `structure` field in `' + name + '` node type definition');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
types[name] = getWalkersFromStructure(name, nodeType);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return types;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function createTypeIterator(config, reverse) {
|
|
82
|
+
const fields = config.fields.slice();
|
|
83
|
+
const contextName = config.context;
|
|
84
|
+
const useContext = typeof contextName === 'string';
|
|
85
|
+
|
|
86
|
+
if (reverse) {
|
|
87
|
+
fields.reverse();
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return function(node, context, walk, walkReducer) {
|
|
91
|
+
let prevContextValue;
|
|
92
|
+
|
|
93
|
+
if (useContext) {
|
|
94
|
+
prevContextValue = context[contextName];
|
|
95
|
+
context[contextName] = node;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
for (const field of fields) {
|
|
99
|
+
const ref = node[field.name];
|
|
100
|
+
|
|
101
|
+
if (!field.nullable || ref) {
|
|
102
|
+
if (field.type === 'list') {
|
|
103
|
+
const breakWalk = reverse
|
|
104
|
+
? ref.reduceRight(walkReducer, false)
|
|
105
|
+
: ref.reduce(walkReducer, false);
|
|
106
|
+
|
|
107
|
+
if (breakWalk) {
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
} else if (walk(ref)) {
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (useContext) {
|
|
117
|
+
context[contextName] = prevContextValue;
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function createFastTraveralMap({
|
|
123
|
+
StyleSheet,
|
|
124
|
+
Atrule,
|
|
125
|
+
Rule,
|
|
126
|
+
Block,
|
|
127
|
+
DeclarationList
|
|
128
|
+
}) {
|
|
129
|
+
return {
|
|
130
|
+
Atrule: {
|
|
131
|
+
StyleSheet,
|
|
132
|
+
Atrule,
|
|
133
|
+
Rule,
|
|
134
|
+
Block
|
|
135
|
+
},
|
|
136
|
+
Rule: {
|
|
137
|
+
StyleSheet,
|
|
138
|
+
Atrule,
|
|
139
|
+
Rule,
|
|
140
|
+
Block
|
|
141
|
+
},
|
|
142
|
+
Declaration: {
|
|
143
|
+
StyleSheet,
|
|
144
|
+
Atrule,
|
|
145
|
+
Rule,
|
|
146
|
+
Block,
|
|
147
|
+
DeclarationList
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function createWalker(config) {
|
|
153
|
+
const types = getTypesFromConfig(config);
|
|
154
|
+
const iteratorsNatural = {};
|
|
155
|
+
const iteratorsReverse = {};
|
|
156
|
+
const breakWalk = Symbol('break-walk');
|
|
157
|
+
const skipNode = Symbol('skip-node');
|
|
158
|
+
|
|
159
|
+
for (const name in types) {
|
|
160
|
+
if (hasOwnProperty.call(types, name) && types[name] !== null) {
|
|
161
|
+
iteratorsNatural[name] = createTypeIterator(types[name], false);
|
|
162
|
+
iteratorsReverse[name] = createTypeIterator(types[name], true);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const fastTraversalIteratorsNatural = createFastTraveralMap(iteratorsNatural);
|
|
167
|
+
const fastTraversalIteratorsReverse = createFastTraveralMap(iteratorsReverse);
|
|
168
|
+
|
|
169
|
+
const walk = function(root, options) {
|
|
170
|
+
function walkNode(node, item, list) {
|
|
171
|
+
const enterRet = enter.call(context, node, item, list);
|
|
172
|
+
|
|
173
|
+
if (enterRet === breakWalk) {
|
|
174
|
+
return true;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (enterRet === skipNode) {
|
|
178
|
+
return false;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (iterators.hasOwnProperty(node.type)) {
|
|
182
|
+
if (iterators[node.type](node, context, walkNode, walkReducer)) {
|
|
183
|
+
return true;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (leave.call(context, node, item, list) === breakWalk) {
|
|
188
|
+
return true;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return false;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
let enter = noop;
|
|
195
|
+
let leave = noop;
|
|
196
|
+
let iterators = iteratorsNatural;
|
|
197
|
+
let walkReducer = (ret, data, item, list) => ret || walkNode(data, item, list);
|
|
198
|
+
const context = {
|
|
199
|
+
break: breakWalk,
|
|
200
|
+
skip: skipNode,
|
|
201
|
+
|
|
202
|
+
root,
|
|
203
|
+
stylesheet: null,
|
|
204
|
+
atrule: null,
|
|
205
|
+
atrulePrelude: null,
|
|
206
|
+
rule: null,
|
|
207
|
+
selector: null,
|
|
208
|
+
block: null,
|
|
209
|
+
declaration: null,
|
|
210
|
+
function: null
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
if (typeof options === 'function') {
|
|
214
|
+
enter = options;
|
|
215
|
+
} else if (options) {
|
|
216
|
+
enter = ensureFunction(options.enter);
|
|
217
|
+
leave = ensureFunction(options.leave);
|
|
218
|
+
|
|
219
|
+
if (options.reverse) {
|
|
220
|
+
iterators = iteratorsReverse;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
if (options.visit) {
|
|
224
|
+
if (fastTraversalIteratorsNatural.hasOwnProperty(options.visit)) {
|
|
225
|
+
iterators = options.reverse
|
|
226
|
+
? fastTraversalIteratorsReverse[options.visit]
|
|
227
|
+
: fastTraversalIteratorsNatural[options.visit];
|
|
228
|
+
} else if (!types.hasOwnProperty(options.visit)) {
|
|
229
|
+
throw new Error('Bad value `' + options.visit + '` for `visit` option (should be: ' + Object.keys(types).sort().join(', ') + ')');
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
enter = invokeForType(enter, options.visit);
|
|
233
|
+
leave = invokeForType(leave, options.visit);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
if (enter === noop && leave === noop) {
|
|
238
|
+
throw new Error('Neither `enter` nor `leave` walker handler is set or both aren\'t a function');
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
walkNode(root);
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
walk.break = breakWalk;
|
|
245
|
+
walk.skip = skipNode;
|
|
246
|
+
|
|
247
|
+
walk.find = function(ast, fn) {
|
|
248
|
+
let found = null;
|
|
249
|
+
|
|
250
|
+
walk(ast, function(node, item, list) {
|
|
251
|
+
if (fn.call(this, node, item, list)) {
|
|
252
|
+
found = node;
|
|
253
|
+
return breakWalk;
|
|
254
|
+
}
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
return found;
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
walk.findLast = function(ast, fn) {
|
|
261
|
+
let found = null;
|
|
262
|
+
|
|
263
|
+
walk(ast, {
|
|
264
|
+
reverse: true,
|
|
265
|
+
enter(node, item, list) {
|
|
266
|
+
if (fn.call(this, node, item, list)) {
|
|
267
|
+
found = node;
|
|
268
|
+
return breakWalk;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
return found;
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
walk.findAll = function(ast, fn) {
|
|
277
|
+
const found = [];
|
|
278
|
+
|
|
279
|
+
walk(ast, function(node, item, list) {
|
|
280
|
+
if (fn.call(this, node, item, list)) {
|
|
281
|
+
found.push(node);
|
|
282
|
+
}
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
return found;
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
return walk;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
exports.createWalker = createWalker;
|