@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.
Files changed (279) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +194 -0
  3. package/cjs/convertor/create.cjs +32 -0
  4. package/cjs/convertor/index.cjs +8 -0
  5. package/cjs/data-patch.cjs +7 -0
  6. package/cjs/data.cjs +120 -0
  7. package/cjs/definition-syntax/SyntaxError.cjs +16 -0
  8. package/cjs/definition-syntax/generate.cjs +139 -0
  9. package/cjs/definition-syntax/index.cjs +13 -0
  10. package/cjs/definition-syntax/parse.cjs +556 -0
  11. package/cjs/definition-syntax/scanner.cjs +113 -0
  12. package/cjs/definition-syntax/walk.cjs +57 -0
  13. package/cjs/generator/create.cjs +102 -0
  14. package/cjs/generator/index.cjs +8 -0
  15. package/cjs/generator/sourceMap.cjs +96 -0
  16. package/cjs/generator/token-before.cjs +170 -0
  17. package/cjs/index.cjs +65 -0
  18. package/cjs/lexer/Lexer.cjs +517 -0
  19. package/cjs/lexer/error.cjs +128 -0
  20. package/cjs/lexer/generic-an-plus-b.cjs +235 -0
  21. package/cjs/lexer/generic-const.cjs +12 -0
  22. package/cjs/lexer/generic-urange.cjs +149 -0
  23. package/cjs/lexer/generic.cjs +589 -0
  24. package/cjs/lexer/index.cjs +7 -0
  25. package/cjs/lexer/match-graph.cjs +530 -0
  26. package/cjs/lexer/match.cjs +632 -0
  27. package/cjs/lexer/prepare-tokens.cjs +54 -0
  28. package/cjs/lexer/search.cjs +65 -0
  29. package/cjs/lexer/structure.cjs +173 -0
  30. package/cjs/lexer/trace.cjs +73 -0
  31. package/cjs/lexer/units.cjs +38 -0
  32. package/cjs/parser/SyntaxError.cjs +74 -0
  33. package/cjs/parser/create.cjs +378 -0
  34. package/cjs/parser/index.cjs +8 -0
  35. package/cjs/parser/parse-selector.cjs +8 -0
  36. package/cjs/parser/sequence.cjs +47 -0
  37. package/cjs/syntax/atrule/container.cjs +32 -0
  38. package/cjs/syntax/atrule/font-face.cjs +12 -0
  39. package/cjs/syntax/atrule/import.cjs +101 -0
  40. package/cjs/syntax/atrule/index.cjs +27 -0
  41. package/cjs/syntax/atrule/layer.cjs +16 -0
  42. package/cjs/syntax/atrule/media.cjs +16 -0
  43. package/cjs/syntax/atrule/nest.cjs +16 -0
  44. package/cjs/syntax/atrule/page.cjs +16 -0
  45. package/cjs/syntax/atrule/scope.cjs +16 -0
  46. package/cjs/syntax/atrule/starting-style.cjs +12 -0
  47. package/cjs/syntax/atrule/supports.cjs +16 -0
  48. package/cjs/syntax/config/generator.cjs +9 -0
  49. package/cjs/syntax/config/lexer.cjs +14 -0
  50. package/cjs/syntax/config/mix.cjs +126 -0
  51. package/cjs/syntax/config/parser-selector.cjs +19 -0
  52. package/cjs/syntax/config/parser.cjs +49 -0
  53. package/cjs/syntax/config/walker.cjs +9 -0
  54. package/cjs/syntax/create.cjs +58 -0
  55. package/cjs/syntax/function/expression.cjs +11 -0
  56. package/cjs/syntax/function/var.cjs +43 -0
  57. package/cjs/syntax/index.cjs +14 -0
  58. package/cjs/syntax/node/AnPlusB.cjs +293 -0
  59. package/cjs/syntax/node/Atrule.cjs +103 -0
  60. package/cjs/syntax/node/AtrulePrelude.cjs +52 -0
  61. package/cjs/syntax/node/AttributeSelector.cjs +148 -0
  62. package/cjs/syntax/node/Block.cjs +96 -0
  63. package/cjs/syntax/node/Brackets.cjs +38 -0
  64. package/cjs/syntax/node/CDC.cjs +26 -0
  65. package/cjs/syntax/node/CDO.cjs +26 -0
  66. package/cjs/syntax/node/ClassSelector.cjs +31 -0
  67. package/cjs/syntax/node/Combinator.cjs +61 -0
  68. package/cjs/syntax/node/Comment.cjs +40 -0
  69. package/cjs/syntax/node/Condition.cjs +120 -0
  70. package/cjs/syntax/node/Declaration.cjs +166 -0
  71. package/cjs/syntax/node/DeclarationList.cjs +62 -0
  72. package/cjs/syntax/node/Dimension.cjs +30 -0
  73. package/cjs/syntax/node/Feature.cjs +101 -0
  74. package/cjs/syntax/node/FeatureFunction.cjs +67 -0
  75. package/cjs/syntax/node/FeatureRange.cjs +133 -0
  76. package/cjs/syntax/node/Function.cjs +45 -0
  77. package/cjs/syntax/node/GeneralEnclosed.cjs +68 -0
  78. package/cjs/syntax/node/Hash.cjs +30 -0
  79. package/cjs/syntax/node/IdSelector.cjs +33 -0
  80. package/cjs/syntax/node/Identifier.cjs +25 -0
  81. package/cjs/syntax/node/Layer.cjs +35 -0
  82. package/cjs/syntax/node/LayerList.cjs +43 -0
  83. package/cjs/syntax/node/MediaQuery.cjs +100 -0
  84. package/cjs/syntax/node/MediaQueryList.cjs +41 -0
  85. package/cjs/syntax/node/NestingSelector.cjs +29 -0
  86. package/cjs/syntax/node/Nth.cjs +54 -0
  87. package/cjs/syntax/node/Number.cjs +25 -0
  88. package/cjs/syntax/node/Operator.cjs +28 -0
  89. package/cjs/syntax/node/Parentheses.cjs +38 -0
  90. package/cjs/syntax/node/Percentage.cjs +25 -0
  91. package/cjs/syntax/node/PseudoClassSelector.cjs +67 -0
  92. package/cjs/syntax/node/PseudoElementSelector.cjs +69 -0
  93. package/cjs/syntax/node/Ratio.cjs +71 -0
  94. package/cjs/syntax/node/Raw.cjs +48 -0
  95. package/cjs/syntax/node/Rule.cjs +58 -0
  96. package/cjs/syntax/node/Scope.cjs +69 -0
  97. package/cjs/syntax/node/Selector.cjs +38 -0
  98. package/cjs/syntax/node/SelectorList.cjs +43 -0
  99. package/cjs/syntax/node/String.cjs +26 -0
  100. package/cjs/syntax/node/StyleSheet.cjs +83 -0
  101. package/cjs/syntax/node/SupportsDeclaration.cjs +38 -0
  102. package/cjs/syntax/node/TypeSelector.cjs +59 -0
  103. package/cjs/syntax/node/UnicodeRange.cjs +158 -0
  104. package/cjs/syntax/node/Url.cjs +54 -0
  105. package/cjs/syntax/node/Value.cjs +26 -0
  106. package/cjs/syntax/node/WhiteSpace.cjs +34 -0
  107. package/cjs/syntax/node/index-generate.cjs +103 -0
  108. package/cjs/syntax/node/index-parse-selector.cjs +39 -0
  109. package/cjs/syntax/node/index-parse.cjs +103 -0
  110. package/cjs/syntax/node/index.cjs +103 -0
  111. package/cjs/syntax/pseudo/index.cjs +60 -0
  112. package/cjs/syntax/pseudo/lang.cjs +37 -0
  113. package/cjs/syntax/scope/atrulePrelude.cjs +9 -0
  114. package/cjs/syntax/scope/default.cjs +76 -0
  115. package/cjs/syntax/scope/index.cjs +11 -0
  116. package/cjs/syntax/scope/selector.cjs +88 -0
  117. package/cjs/syntax/scope/value.cjs +29 -0
  118. package/cjs/tokenizer/OffsetToLocation.cjs +91 -0
  119. package/cjs/tokenizer/TokenStream.cjs +358 -0
  120. package/cjs/tokenizer/adopt-buffer.cjs +13 -0
  121. package/cjs/tokenizer/char-code-definitions.cjs +236 -0
  122. package/cjs/tokenizer/index.cjs +554 -0
  123. package/cjs/tokenizer/names.cjs +32 -0
  124. package/cjs/tokenizer/types.cjs +57 -0
  125. package/cjs/tokenizer/utils.cjs +261 -0
  126. package/cjs/utils/List.cjs +473 -0
  127. package/cjs/utils/clone.cjs +25 -0
  128. package/cjs/utils/create-custom-error.cjs +18 -0
  129. package/cjs/utils/ident.cjs +102 -0
  130. package/cjs/utils/index.cjs +20 -0
  131. package/cjs/utils/names.cjs +113 -0
  132. package/cjs/utils/string.cjs +99 -0
  133. package/cjs/utils/url.cjs +108 -0
  134. package/cjs/version.cjs +5 -0
  135. package/cjs/walker/create.cjs +291 -0
  136. package/cjs/walker/index.cjs +8 -0
  137. package/data/patch.json +874 -0
  138. package/dist/csstree.esm.js +12 -0
  139. package/dist/csstree.js +12 -0
  140. package/dist/data.cjs +1341 -0
  141. package/dist/data.js +1341 -0
  142. package/dist/version.cjs +1 -0
  143. package/dist/version.js +1 -0
  144. package/lib/convertor/create.js +28 -0
  145. package/lib/convertor/index.js +4 -0
  146. package/lib/data-patch.js +6 -0
  147. package/lib/data.js +118 -0
  148. package/lib/definition-syntax/SyntaxError.js +12 -0
  149. package/lib/definition-syntax/generate.js +135 -0
  150. package/lib/definition-syntax/index.js +4 -0
  151. package/lib/definition-syntax/parse.js +552 -0
  152. package/lib/definition-syntax/scanner.js +109 -0
  153. package/lib/definition-syntax/walk.js +53 -0
  154. package/lib/generator/create.js +97 -0
  155. package/lib/generator/index.js +4 -0
  156. package/lib/generator/sourceMap.js +92 -0
  157. package/lib/generator/token-before.js +182 -0
  158. package/lib/index.d.ts +3016 -0
  159. package/lib/index.js +30 -0
  160. package/lib/lexer/Lexer.js +511 -0
  161. package/lib/lexer/error.js +123 -0
  162. package/lib/lexer/generic-an-plus-b.js +238 -0
  163. package/lib/lexer/generic-const.js +8 -0
  164. package/lib/lexer/generic-urange.js +151 -0
  165. package/lib/lexer/generic.js +622 -0
  166. package/lib/lexer/index.js +1 -0
  167. package/lib/lexer/match-graph.js +527 -0
  168. package/lib/lexer/match.js +630 -0
  169. package/lib/lexer/prepare-tokens.js +50 -0
  170. package/lib/lexer/search.js +61 -0
  171. package/lib/lexer/structure.js +169 -0
  172. package/lib/lexer/trace.js +66 -0
  173. package/lib/lexer/units.js +27 -0
  174. package/lib/parser/SyntaxError.js +70 -0
  175. package/lib/parser/create.js +388 -0
  176. package/lib/parser/index.js +4 -0
  177. package/lib/parser/parse-selector.js +4 -0
  178. package/lib/parser/sequence.js +43 -0
  179. package/lib/syntax/atrule/container.js +28 -0
  180. package/lib/syntax/atrule/font-face.js +8 -0
  181. package/lib/syntax/atrule/import.js +104 -0
  182. package/lib/syntax/atrule/index.js +23 -0
  183. package/lib/syntax/atrule/layer.js +12 -0
  184. package/lib/syntax/atrule/media.js +12 -0
  185. package/lib/syntax/atrule/nest.js +12 -0
  186. package/lib/syntax/atrule/page.js +12 -0
  187. package/lib/syntax/atrule/scope.js +12 -0
  188. package/lib/syntax/atrule/starting-style.js +8 -0
  189. package/lib/syntax/atrule/supports.js +12 -0
  190. package/lib/syntax/config/generator.js +5 -0
  191. package/lib/syntax/config/lexer.js +10 -0
  192. package/lib/syntax/config/mix.js +122 -0
  193. package/lib/syntax/config/parser-selector.js +15 -0
  194. package/lib/syntax/config/parser.js +45 -0
  195. package/lib/syntax/config/walker.js +5 -0
  196. package/lib/syntax/create.js +55 -0
  197. package/lib/syntax/function/expression.js +7 -0
  198. package/lib/syntax/function/var.js +39 -0
  199. package/lib/syntax/index.js +10 -0
  200. package/lib/syntax/node/AnPlusB.js +292 -0
  201. package/lib/syntax/node/Atrule.js +100 -0
  202. package/lib/syntax/node/AtrulePrelude.js +47 -0
  203. package/lib/syntax/node/AttributeSelector.js +147 -0
  204. package/lib/syntax/node/Block.js +95 -0
  205. package/lib/syntax/node/Brackets.js +35 -0
  206. package/lib/syntax/node/CDC.js +19 -0
  207. package/lib/syntax/node/CDO.js +19 -0
  208. package/lib/syntax/node/ClassSelector.js +24 -0
  209. package/lib/syntax/node/Combinator.js +54 -0
  210. package/lib/syntax/node/Comment.js +33 -0
  211. package/lib/syntax/node/Condition.js +123 -0
  212. package/lib/syntax/node/Declaration.js +165 -0
  213. package/lib/syntax/node/DeclarationList.js +62 -0
  214. package/lib/syntax/node/Dimension.js +23 -0
  215. package/lib/syntax/node/Feature.js +103 -0
  216. package/lib/syntax/node/FeatureFunction.js +63 -0
  217. package/lib/syntax/node/FeatureRange.js +133 -0
  218. package/lib/syntax/node/Function.js +41 -0
  219. package/lib/syntax/node/GeneralEnclosed.js +66 -0
  220. package/lib/syntax/node/Hash.js +23 -0
  221. package/lib/syntax/node/IdSelector.js +26 -0
  222. package/lib/syntax/node/Identifier.js +18 -0
  223. package/lib/syntax/node/Layer.js +28 -0
  224. package/lib/syntax/node/LayerList.js +36 -0
  225. package/lib/syntax/node/MediaQuery.js +102 -0
  226. package/lib/syntax/node/MediaQueryList.js +34 -0
  227. package/lib/syntax/node/NestingSelector.js +22 -0
  228. package/lib/syntax/node/Nth.js +47 -0
  229. package/lib/syntax/node/Number.js +18 -0
  230. package/lib/syntax/node/Operator.js +21 -0
  231. package/lib/syntax/node/Parentheses.js +34 -0
  232. package/lib/syntax/node/Percentage.js +18 -0
  233. package/lib/syntax/node/PseudoClassSelector.js +65 -0
  234. package/lib/syntax/node/PseudoElementSelector.js +66 -0
  235. package/lib/syntax/node/Ratio.js +68 -0
  236. package/lib/syntax/node/Raw.js +41 -0
  237. package/lib/syntax/node/Rule.js +51 -0
  238. package/lib/syntax/node/Scope.js +66 -0
  239. package/lib/syntax/node/Selector.js +31 -0
  240. package/lib/syntax/node/SelectorList.js +35 -0
  241. package/lib/syntax/node/String.js +19 -0
  242. package/lib/syntax/node/StyleSheet.js +82 -0
  243. package/lib/syntax/node/SupportsDeclaration.js +34 -0
  244. package/lib/syntax/node/TypeSelector.js +52 -0
  245. package/lib/syntax/node/UnicodeRange.js +156 -0
  246. package/lib/syntax/node/Url.js +52 -0
  247. package/lib/syntax/node/Value.js +19 -0
  248. package/lib/syntax/node/WhiteSpace.js +27 -0
  249. package/lib/syntax/node/index-generate.js +49 -0
  250. package/lib/syntax/node/index-parse-selector.js +17 -0
  251. package/lib/syntax/node/index-parse.js +49 -0
  252. package/lib/syntax/node/index.js +49 -0
  253. package/lib/syntax/pseudo/index.js +56 -0
  254. package/lib/syntax/pseudo/lang.js +33 -0
  255. package/lib/syntax/scope/atrulePrelude.js +5 -0
  256. package/lib/syntax/scope/default.js +85 -0
  257. package/lib/syntax/scope/index.js +3 -0
  258. package/lib/syntax/scope/selector.js +94 -0
  259. package/lib/syntax/scope/value.js +25 -0
  260. package/lib/tokenizer/OffsetToLocation.js +87 -0
  261. package/lib/tokenizer/TokenStream.js +366 -0
  262. package/lib/tokenizer/adopt-buffer.js +9 -0
  263. package/lib/tokenizer/char-code-definitions.js +212 -0
  264. package/lib/tokenizer/index.js +513 -0
  265. package/lib/tokenizer/names.js +28 -0
  266. package/lib/tokenizer/types.js +28 -0
  267. package/lib/tokenizer/utils.js +254 -0
  268. package/lib/utils/List.js +469 -0
  269. package/lib/utils/clone.js +21 -0
  270. package/lib/utils/create-custom-error.js +14 -0
  271. package/lib/utils/ident.js +101 -0
  272. package/lib/utils/index.js +6 -0
  273. package/lib/utils/names.js +106 -0
  274. package/lib/utils/string.js +99 -0
  275. package/lib/utils/url.js +108 -0
  276. package/lib/version.js +5 -0
  277. package/lib/walker/create.js +287 -0
  278. package/lib/walker/index.js +4 -0
  279. package/package.json +133 -0
@@ -0,0 +1,254 @@
1
+ import {
2
+ isDigit,
3
+ isHexDigit,
4
+ isUppercaseLetter,
5
+ isName,
6
+ isWhiteSpace,
7
+ isValidEscape
8
+ } from './char-code-definitions.js';
9
+
10
+ function getCharCode(source, offset) {
11
+ return offset < source.length ? source.charCodeAt(offset) : 0;
12
+ }
13
+
14
+ export function getNewlineLength(source, offset, code) {
15
+ if (code === 13 /* \r */ && getCharCode(source, offset + 1) === 10 /* \n */) {
16
+ return 2;
17
+ }
18
+
19
+ return 1;
20
+ }
21
+
22
+ export function cmpChar(testStr, offset, referenceCode) {
23
+ let code = testStr.charCodeAt(offset);
24
+
25
+ // code.toLowerCase() for A..Z
26
+ if (isUppercaseLetter(code)) {
27
+ code = code | 32;
28
+ }
29
+
30
+ return code === referenceCode;
31
+ }
32
+
33
+ export function cmpStr(testStr, start, end, referenceStr) {
34
+ if (end - start !== referenceStr.length) {
35
+ return false;
36
+ }
37
+
38
+ if (start < 0 || end > testStr.length) {
39
+ return false;
40
+ }
41
+
42
+ for (let i = start; i < end; i++) {
43
+ const referenceCode = referenceStr.charCodeAt(i - start);
44
+ let testCode = testStr.charCodeAt(i);
45
+
46
+ // testCode.toLowerCase() for A..Z
47
+ if (isUppercaseLetter(testCode)) {
48
+ testCode = testCode | 32;
49
+ }
50
+
51
+ if (testCode !== referenceCode) {
52
+ return false;
53
+ }
54
+ }
55
+
56
+ return true;
57
+ }
58
+
59
+ export function findWhiteSpaceStart(source, offset) {
60
+ for (; offset >= 0; offset--) {
61
+ if (!isWhiteSpace(source.charCodeAt(offset))) {
62
+ break;
63
+ }
64
+ }
65
+
66
+ return offset + 1;
67
+ }
68
+
69
+ export function findWhiteSpaceEnd(source, offset) {
70
+ for (; offset < source.length; offset++) {
71
+ if (!isWhiteSpace(source.charCodeAt(offset))) {
72
+ break;
73
+ }
74
+ }
75
+
76
+ return offset;
77
+ }
78
+
79
+ export function findDecimalNumberEnd(source, offset) {
80
+ for (; offset < source.length; offset++) {
81
+ if (!isDigit(source.charCodeAt(offset))) {
82
+ break;
83
+ }
84
+ }
85
+
86
+ return offset;
87
+ }
88
+
89
+ // § 4.3.7. Consume an escaped code point
90
+ export function consumeEscaped(source, offset) {
91
+ // It assumes that the U+005C REVERSE SOLIDUS (\) has already been consumed and
92
+ // that the next input code point has already been verified to be part of a valid escape.
93
+ offset += 2;
94
+
95
+ // hex digit
96
+ if (isHexDigit(getCharCode(source, offset - 1))) {
97
+ // Consume as many hex digits as possible, but no more than 5.
98
+ // Note that this means 1-6 hex digits have been consumed in total.
99
+ for (const maxOffset = Math.min(source.length, offset + 5); offset < maxOffset; offset++) {
100
+ if (!isHexDigit(getCharCode(source, offset))) {
101
+ break;
102
+ }
103
+ }
104
+
105
+ // If the next input code point is whitespace, consume it as well.
106
+ const code = getCharCode(source, offset);
107
+ if (isWhiteSpace(code)) {
108
+ offset += getNewlineLength(source, offset, code);
109
+ }
110
+ }
111
+
112
+ return offset;
113
+ }
114
+
115
+ // §4.3.11. Consume a name
116
+ // Note: This algorithm does not do the verification of the first few code points that are necessary
117
+ // to ensure the returned code points would constitute an <ident-token>. If that is the intended use,
118
+ // ensure that the stream starts with an identifier before calling this algorithm.
119
+ export function consumeName(source, offset) {
120
+ // Let result initially be an empty string.
121
+ // Repeatedly consume the next input code point from the stream:
122
+ for (; offset < source.length; offset++) {
123
+ const code = source.charCodeAt(offset);
124
+
125
+ // name code point
126
+ if (isName(code)) {
127
+ // Append the code point to result.
128
+ continue;
129
+ }
130
+
131
+ // the stream starts with a valid escape
132
+ if (isValidEscape(code, getCharCode(source, offset + 1))) {
133
+ // Consume an escaped code point. Append the returned code point to result.
134
+ offset = consumeEscaped(source, offset) - 1;
135
+ continue;
136
+ }
137
+
138
+ // anything else
139
+ // Reconsume the current input code point. Return result.
140
+ break;
141
+ }
142
+
143
+ return offset;
144
+ }
145
+
146
+ // §4.3.12. Consume a number
147
+ export function consumeNumber(source, offset) {
148
+ let code = source.charCodeAt(offset);
149
+
150
+ // 2. If the next input code point is U+002B PLUS SIGN (+) or U+002D HYPHEN-MINUS (-),
151
+ // consume it and append it to repr.
152
+ if (code === 0x002B || code === 0x002D) {
153
+ code = source.charCodeAt(offset += 1);
154
+ }
155
+
156
+ // 3. While the next input code point is a digit, consume it and append it to repr.
157
+ if (isDigit(code)) {
158
+ offset = findDecimalNumberEnd(source, offset + 1);
159
+ code = source.charCodeAt(offset);
160
+ }
161
+
162
+ // 4. If the next 2 input code points are U+002E FULL STOP (.) followed by a digit, then:
163
+ if (code === 0x002E && isDigit(source.charCodeAt(offset + 1))) {
164
+ // 4.1 Consume them.
165
+ // 4.2 Append them to repr.
166
+ offset += 2;
167
+
168
+ // 4.3 Set type to "number".
169
+ // TODO
170
+
171
+ // 4.4 While the next input code point is a digit, consume it and append it to repr.
172
+
173
+ offset = findDecimalNumberEnd(source, offset);
174
+ }
175
+
176
+ // 5. If the next 2 or 3 input code points are U+0045 LATIN CAPITAL LETTER E (E)
177
+ // or U+0065 LATIN SMALL LETTER E (e), ... , followed by a digit, then:
178
+ if (cmpChar(source, offset, 101 /* e */)) {
179
+ let sign = 0;
180
+ code = source.charCodeAt(offset + 1);
181
+
182
+ // ... optionally followed by U+002D HYPHEN-MINUS (-) or U+002B PLUS SIGN (+) ...
183
+ if (code === 0x002D || code === 0x002B) {
184
+ sign = 1;
185
+ code = source.charCodeAt(offset + 2);
186
+ }
187
+
188
+ // ... followed by a digit
189
+ if (isDigit(code)) {
190
+ // 5.1 Consume them.
191
+ // 5.2 Append them to repr.
192
+
193
+ // 5.3 Set type to "number".
194
+ // TODO
195
+
196
+ // 5.4 While the next input code point is a digit, consume it and append it to repr.
197
+ offset = findDecimalNumberEnd(source, offset + 1 + sign + 1);
198
+ }
199
+ }
200
+
201
+ return offset;
202
+ }
203
+
204
+ // § 4.3.14. Consume the remnants of a bad url
205
+ // ... its sole use is to consume enough of the input stream to reach a recovery point
206
+ // where normal tokenizing can resume.
207
+ export function consumeBadUrlRemnants(source, offset) {
208
+ // Repeatedly consume the next input code point from the stream:
209
+ for (; offset < source.length; offset++) {
210
+ const code = source.charCodeAt(offset);
211
+
212
+ // U+0029 RIGHT PARENTHESIS ())
213
+ // EOF
214
+ if (code === 0x0029) {
215
+ // Return.
216
+ offset++;
217
+ break;
218
+ }
219
+
220
+ if (isValidEscape(code, getCharCode(source, offset + 1))) {
221
+ // Consume an escaped code point.
222
+ // Note: This allows an escaped right parenthesis ("\)") to be encountered
223
+ // without ending the <bad-url-token>. This is otherwise identical to
224
+ // the "anything else" clause.
225
+ offset = consumeEscaped(source, offset);
226
+ }
227
+ }
228
+
229
+ return offset;
230
+ }
231
+
232
+ // § 4.3.7. Consume an escaped code point
233
+ // Note: This algorithm assumes that escaped is valid without leading U+005C REVERSE SOLIDUS (\)
234
+ export function decodeEscaped(escaped) {
235
+ // Single char escaped that's not a hex digit
236
+ if (escaped.length === 1 && !isHexDigit(escaped.charCodeAt(0))) {
237
+ return escaped[0];
238
+ }
239
+
240
+ // Interpret the hex digits as a hexadecimal number.
241
+ let code = parseInt(escaped, 16);
242
+
243
+ if (
244
+ (code === 0) || // If this number is zero,
245
+ (code >= 0xD800 && code <= 0xDFFF) || // or is for a surrogate,
246
+ (code > 0x10FFFF) // or is greater than the maximum allowed code point
247
+ ) {
248
+ // ... return U+FFFD REPLACEMENT CHARACTER
249
+ code = 0xFFFD;
250
+ }
251
+
252
+ // Otherwise, return the code point with that value.
253
+ return String.fromCodePoint(code);
254
+ }
@@ -0,0 +1,469 @@
1
+ //
2
+ // list
3
+ // ┌──────┐
4
+ // ┌──────────────┼─head │
5
+ // │ │ tail─┼──────────────┐
6
+ // │ └──────┘ │
7
+ // ▼ ▼
8
+ // item item item item
9
+ // ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐
10
+ // null ◀──┼─prev │◀───┼─prev │◀───┼─prev │◀───┼─prev │
11
+ // │ next─┼───▶│ next─┼───▶│ next─┼───▶│ next─┼──▶ null
12
+ // ├──────┤ ├──────┤ ├──────┤ ├──────┤
13
+ // │ data │ │ data │ │ data │ │ data │
14
+ // └──────┘ └──────┘ └──────┘ └──────┘
15
+ //
16
+
17
+ let releasedCursors = null;
18
+
19
+ export class List {
20
+ static createItem(data) {
21
+ return {
22
+ prev: null,
23
+ next: null,
24
+ data
25
+ };
26
+ }
27
+
28
+ constructor() {
29
+ this.head = null;
30
+ this.tail = null;
31
+ this.cursor = null;
32
+ }
33
+ createItem(data) {
34
+ return List.createItem(data);
35
+ }
36
+
37
+ // cursor helpers
38
+ allocateCursor(prev, next) {
39
+ let cursor;
40
+
41
+ if (releasedCursors !== null) {
42
+ cursor = releasedCursors;
43
+ releasedCursors = releasedCursors.cursor;
44
+ cursor.prev = prev;
45
+ cursor.next = next;
46
+ cursor.cursor = this.cursor;
47
+ } else {
48
+ cursor = {
49
+ prev,
50
+ next,
51
+ cursor: this.cursor
52
+ };
53
+ }
54
+
55
+ this.cursor = cursor;
56
+
57
+ return cursor;
58
+ }
59
+ releaseCursor() {
60
+ const { cursor } = this;
61
+
62
+ this.cursor = cursor.cursor;
63
+ cursor.prev = null;
64
+ cursor.next = null;
65
+ cursor.cursor = releasedCursors;
66
+ releasedCursors = cursor;
67
+ }
68
+ updateCursors(prevOld, prevNew, nextOld, nextNew) {
69
+ let { cursor } = this;
70
+
71
+ while (cursor !== null) {
72
+ if (cursor.prev === prevOld) {
73
+ cursor.prev = prevNew;
74
+ }
75
+
76
+ if (cursor.next === nextOld) {
77
+ cursor.next = nextNew;
78
+ }
79
+
80
+ cursor = cursor.cursor;
81
+ }
82
+ }
83
+ *[Symbol.iterator]() {
84
+ for (let cursor = this.head; cursor !== null; cursor = cursor.next) {
85
+ yield cursor.data;
86
+ }
87
+ }
88
+
89
+ // getters
90
+ get size() {
91
+ let size = 0;
92
+
93
+ for (let cursor = this.head; cursor !== null; cursor = cursor.next) {
94
+ size++;
95
+ }
96
+
97
+ return size;
98
+ }
99
+ get isEmpty() {
100
+ return this.head === null;
101
+ }
102
+ get first() {
103
+ return this.head && this.head.data;
104
+ }
105
+ get last() {
106
+ return this.tail && this.tail.data;
107
+ }
108
+
109
+ // convertors
110
+ fromArray(array) {
111
+ let cursor = null;
112
+ this.head = null;
113
+
114
+ for (let data of array) {
115
+ const item = List.createItem(data);
116
+
117
+ if (cursor !== null) {
118
+ cursor.next = item;
119
+ } else {
120
+ this.head = item;
121
+ }
122
+
123
+ item.prev = cursor;
124
+ cursor = item;
125
+ }
126
+
127
+ this.tail = cursor;
128
+ return this;
129
+ }
130
+ toArray() {
131
+ return [...this];
132
+ }
133
+ toJSON() {
134
+ return [...this];
135
+ }
136
+
137
+ // array-like methods
138
+ forEach(fn, thisArg = this) {
139
+ // push cursor
140
+ const cursor = this.allocateCursor(null, this.head);
141
+
142
+ while (cursor.next !== null) {
143
+ const item = cursor.next;
144
+ cursor.next = item.next;
145
+ fn.call(thisArg, item.data, item, this);
146
+ }
147
+
148
+ // pop cursor
149
+ this.releaseCursor();
150
+ }
151
+ forEachRight(fn, thisArg = this) {
152
+ // push cursor
153
+ const cursor = this.allocateCursor(this.tail, null);
154
+
155
+ while (cursor.prev !== null) {
156
+ const item = cursor.prev;
157
+ cursor.prev = item.prev;
158
+ fn.call(thisArg, item.data, item, this);
159
+ }
160
+
161
+ // pop cursor
162
+ this.releaseCursor();
163
+ }
164
+ reduce(fn, initialValue, thisArg = this) {
165
+ // push cursor
166
+ let cursor = this.allocateCursor(null, this.head);
167
+ let acc = initialValue;
168
+ let item;
169
+
170
+ while (cursor.next !== null) {
171
+ item = cursor.next;
172
+ cursor.next = item.next;
173
+
174
+ acc = fn.call(thisArg, acc, item.data, item, this);
175
+ }
176
+
177
+ // pop cursor
178
+ this.releaseCursor();
179
+
180
+ return acc;
181
+ }
182
+ reduceRight(fn, initialValue, thisArg = this) {
183
+ // push cursor
184
+ let cursor = this.allocateCursor(this.tail, null);
185
+ let acc = initialValue;
186
+ let item;
187
+
188
+ while (cursor.prev !== null) {
189
+ item = cursor.prev;
190
+ cursor.prev = item.prev;
191
+
192
+ acc = fn.call(thisArg, acc, item.data, item, this);
193
+ }
194
+
195
+ // pop cursor
196
+ this.releaseCursor();
197
+
198
+ return acc;
199
+ }
200
+ some(fn, thisArg = this) {
201
+ for (let cursor = this.head; cursor !== null; cursor = cursor.next) {
202
+ if (fn.call(thisArg, cursor.data, cursor, this)) {
203
+ return true;
204
+ }
205
+ }
206
+
207
+ return false;
208
+ }
209
+ map(fn, thisArg = this) {
210
+ const result = new List();
211
+
212
+ for (let cursor = this.head; cursor !== null; cursor = cursor.next) {
213
+ result.appendData(fn.call(thisArg, cursor.data, cursor, this));
214
+ }
215
+
216
+ return result;
217
+ }
218
+ filter(fn, thisArg = this) {
219
+ const result = new List();
220
+
221
+ for (let cursor = this.head; cursor !== null; cursor = cursor.next) {
222
+ if (fn.call(thisArg, cursor.data, cursor, this)) {
223
+ result.appendData(cursor.data);
224
+ }
225
+ }
226
+
227
+ return result;
228
+ }
229
+
230
+ nextUntil(start, fn, thisArg = this) {
231
+ if (start === null) {
232
+ return;
233
+ }
234
+
235
+ // push cursor
236
+ const cursor = this.allocateCursor(null, start);
237
+
238
+ while (cursor.next !== null) {
239
+ const item = cursor.next;
240
+ cursor.next = item.next;
241
+ if (fn.call(thisArg, item.data, item, this)) {
242
+ break;
243
+ }
244
+ }
245
+
246
+ // pop cursor
247
+ this.releaseCursor();
248
+ }
249
+ prevUntil(start, fn, thisArg = this) {
250
+ if (start === null) {
251
+ return;
252
+ }
253
+
254
+ // push cursor
255
+ const cursor = this.allocateCursor(start, null);
256
+
257
+ while (cursor.prev !== null) {
258
+ const item = cursor.prev;
259
+ cursor.prev = item.prev;
260
+ if (fn.call(thisArg, item.data, item, this)) {
261
+ break;
262
+ }
263
+ }
264
+
265
+ // pop cursor
266
+ this.releaseCursor();
267
+ }
268
+
269
+ // mutation
270
+ clear() {
271
+ this.head = null;
272
+ this.tail = null;
273
+ }
274
+ copy() {
275
+ const result = new List();
276
+
277
+ for (let data of this) {
278
+ result.appendData(data);
279
+ }
280
+
281
+ return result;
282
+ }
283
+ prepend(item) {
284
+ // head
285
+ // ^
286
+ // item
287
+ this.updateCursors(null, item, this.head, item);
288
+
289
+ // insert to the beginning of the list
290
+ if (this.head !== null) {
291
+ // new item <- first item
292
+ this.head.prev = item;
293
+ // new item -> first item
294
+ item.next = this.head;
295
+ } else {
296
+ // if list has no head, then it also has no tail
297
+ // in this case tail points to the new item
298
+ this.tail = item;
299
+ }
300
+
301
+ // head always points to new item
302
+ this.head = item;
303
+ return this;
304
+ }
305
+ prependData(data) {
306
+ return this.prepend(List.createItem(data));
307
+ }
308
+ append(item) {
309
+ return this.insert(item);
310
+ }
311
+ appendData(data) {
312
+ return this.insert(List.createItem(data));
313
+ }
314
+ insert(item, before = null) {
315
+ if (before !== null) {
316
+ // prev before
317
+ // ^
318
+ // item
319
+ this.updateCursors(before.prev, item, before, item);
320
+
321
+ if (before.prev === null) {
322
+ // insert to the beginning of list
323
+ if (this.head !== before) {
324
+ throw new Error('before doesn\'t belong to list');
325
+ }
326
+ // since head points to before therefore list doesn't empty
327
+ // no need to check tail
328
+ this.head = item;
329
+ before.prev = item;
330
+ item.next = before;
331
+ this.updateCursors(null, item);
332
+ } else {
333
+ // insert between two items
334
+ before.prev.next = item;
335
+ item.prev = before.prev;
336
+ before.prev = item;
337
+ item.next = before;
338
+ }
339
+ } else {
340
+ // tail
341
+ // ^
342
+ // item
343
+ this.updateCursors(this.tail, item, null, item);
344
+
345
+ // insert to the ending of the list
346
+ if (this.tail !== null) {
347
+ // last item -> new item
348
+ this.tail.next = item;
349
+ // last item <- new item
350
+ item.prev = this.tail;
351
+ } else {
352
+ // if list has no tail, then it also has no head
353
+ // in this case head points to new item
354
+ this.head = item;
355
+ }
356
+
357
+ // tail always points to new item
358
+ this.tail = item;
359
+ }
360
+
361
+ return this;
362
+ }
363
+ insertData(data, before) {
364
+ return this.insert(List.createItem(data), before);
365
+ }
366
+ remove(item) {
367
+ // item
368
+ // ^
369
+ // prev next
370
+ this.updateCursors(item, item.prev, item, item.next);
371
+
372
+ if (item.prev !== null) {
373
+ item.prev.next = item.next;
374
+ } else {
375
+ if (this.head !== item) {
376
+ throw new Error('item doesn\'t belong to list');
377
+ }
378
+
379
+ this.head = item.next;
380
+ }
381
+
382
+ if (item.next !== null) {
383
+ item.next.prev = item.prev;
384
+ } else {
385
+ if (this.tail !== item) {
386
+ throw new Error('item doesn\'t belong to list');
387
+ }
388
+
389
+ this.tail = item.prev;
390
+ }
391
+
392
+ item.prev = null;
393
+ item.next = null;
394
+
395
+ return item;
396
+ }
397
+ push(data) {
398
+ this.insert(List.createItem(data));
399
+ }
400
+ pop() {
401
+ return this.tail !== null ? this.remove(this.tail) : null;
402
+ }
403
+ unshift(data) {
404
+ this.prepend(List.createItem(data));
405
+ }
406
+ shift() {
407
+ return this.head !== null ? this.remove(this.head) : null;
408
+ }
409
+ prependList(list) {
410
+ return this.insertList(list, this.head);
411
+ }
412
+ appendList(list) {
413
+ return this.insertList(list);
414
+ }
415
+ insertList(list, before) {
416
+ // ignore empty lists
417
+ if (list.head === null) {
418
+ return this;
419
+ }
420
+
421
+ if (before !== undefined && before !== null) {
422
+ this.updateCursors(before.prev, list.tail, before, list.head);
423
+
424
+ // insert in the middle of dist list
425
+ if (before.prev !== null) {
426
+ // before.prev <-> list.head
427
+ before.prev.next = list.head;
428
+ list.head.prev = before.prev;
429
+ } else {
430
+ this.head = list.head;
431
+ }
432
+
433
+ before.prev = list.tail;
434
+ list.tail.next = before;
435
+ } else {
436
+ this.updateCursors(this.tail, list.tail, null, list.head);
437
+
438
+ // insert to end of the list
439
+ if (this.tail !== null) {
440
+ // if destination list has a tail, then it also has a head,
441
+ // but head doesn't change
442
+ // dest tail -> source head
443
+ this.tail.next = list.head;
444
+ // dest tail <- source head
445
+ list.head.prev = this.tail;
446
+ } else {
447
+ // if list has no a tail, then it also has no a head
448
+ // in this case points head to new item
449
+ this.head = list.head;
450
+ }
451
+
452
+ // tail always start point to new item
453
+ this.tail = list.tail;
454
+ }
455
+
456
+ list.head = null;
457
+ list.tail = null;
458
+ return this;
459
+ }
460
+ replace(oldItem, newItemOrList) {
461
+ if ('head' in newItemOrList) {
462
+ this.insertList(newItemOrList, oldItem);
463
+ } else {
464
+ this.insert(newItemOrList, oldItem);
465
+ }
466
+
467
+ this.remove(oldItem);
468
+ }
469
+ }