@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,21 @@
1
+ import { List } from './List.js';
2
+
3
+ export function clone(node) {
4
+ const result = {};
5
+
6
+ for (const key of Object.keys(node)) {
7
+ let value = node[key];
8
+
9
+ if (value) {
10
+ if (Array.isArray(value) || value instanceof List) {
11
+ value = value.map(clone);
12
+ } else if (value.constructor === Object) {
13
+ value = clone(value);
14
+ }
15
+ }
16
+
17
+ result[key] = value;
18
+ }
19
+
20
+ return result;
21
+ }
@@ -0,0 +1,14 @@
1
+ export function createCustomError(name, message) {
2
+ // use Object.create(), because some VMs prevent setting line/column otherwise
3
+ // (iOS Safari 10 even throws an exception)
4
+ const error = Object.create(SyntaxError.prototype);
5
+ const errorStack = new Error();
6
+
7
+ return Object.assign(error, {
8
+ name,
9
+ message,
10
+ get stack() {
11
+ return (errorStack.stack || '').replace(/^(.+\n){1,3}/, `${name}: ${message}\n`);
12
+ }
13
+ });
14
+ };
@@ -0,0 +1,101 @@
1
+ import {
2
+ isName,
3
+ isValidEscape,
4
+ consumeEscaped,
5
+ decodeEscaped
6
+ } from '../tokenizer/index.js';
7
+
8
+ const REVERSE_SOLIDUS = 0x005c; // U+005C REVERSE SOLIDUS (\)
9
+
10
+ export function decode(str) {
11
+ const end = str.length - 1;
12
+ let decoded = '';
13
+
14
+ for (let i = 0; i < str.length; i++) {
15
+ let code = str.charCodeAt(i);
16
+
17
+ if (code === REVERSE_SOLIDUS) {
18
+ // special case at the ending
19
+ if (i === end) {
20
+ // if the next input code point is EOF, do nothing
21
+ break;
22
+ }
23
+
24
+ code = str.charCodeAt(++i);
25
+
26
+ // consume escaped
27
+ if (isValidEscape(REVERSE_SOLIDUS, code)) {
28
+ const escapeStart = i - 1;
29
+ const escapeEnd = consumeEscaped(str, escapeStart);
30
+
31
+ i = escapeEnd - 1;
32
+ decoded += decodeEscaped(str.substring(escapeStart + 1, escapeEnd));
33
+ } else {
34
+ // \r\n
35
+ if (code === 0x000d && str.charCodeAt(i + 1) === 0x000a) {
36
+ i++;
37
+ }
38
+ }
39
+ } else {
40
+ decoded += str[i];
41
+ }
42
+ }
43
+
44
+ return decoded;
45
+ }
46
+
47
+ // https://drafts.csswg.org/cssom/#serialize-an-identifier
48
+ // § 2.1. Common Serializing Idioms
49
+ export function encode(str) {
50
+ let encoded = '';
51
+
52
+ // If the character is the first character and is a "-" (U+002D),
53
+ // and there is no second character, then the escaped character.
54
+ // Note: That's means a single dash string "-" return as escaped dash,
55
+ // so move the condition out of the main loop
56
+ if (str.length === 1 && str.charCodeAt(0) === 0x002D) {
57
+ return '\\-';
58
+ }
59
+
60
+ // To serialize an identifier means to create a string represented
61
+ // by the concatenation of, for each character of the identifier:
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 (
72
+ // If the character is in the range [\1-\1f] (U+0001 to U+001F) or is U+007F ...
73
+ // Note: Do not compare with 0x0001 since 0x0000 is precessed before
74
+ code <= 0x001F || code === 0x007F ||
75
+ // [or] ... is in the range [0-9] (U+0030 to U+0039),
76
+ (code >= 0x0030 && code <= 0x0039 && (
77
+ // If the character is the first character ...
78
+ i === 0 ||
79
+ // If the character is the second character ... and the first character is a "-" (U+002D)
80
+ i === 1 && str.charCodeAt(0) === 0x002D
81
+ ))
82
+ ) {
83
+ // ... then the character escaped as code point.
84
+ encoded += '\\' + code.toString(16) + ' ';
85
+ continue;
86
+ }
87
+
88
+ // If the character is not handled by one of the above rules and is greater
89
+ // than or equal to U+0080, is "-" (U+002D) or "_" (U+005F), or is in one
90
+ // of the ranges [0-9] (U+0030 to U+0039), [A-Z] (U+0041 to U+005A),
91
+ // or \[a-z] (U+0061 to U+007A), then the character itself.
92
+ if (isName(code)) {
93
+ encoded += str.charAt(i);
94
+ } else {
95
+ // Otherwise, the escaped character.
96
+ encoded += '\\' + str.charAt(i);
97
+ }
98
+ }
99
+
100
+ return encoded;
101
+ }
@@ -0,0 +1,6 @@
1
+ export * from './clone.js';
2
+ export * as ident from './ident.js';
3
+ export * from './List.js';
4
+ export * from './names.js';
5
+ export * as string from './string.js';
6
+ export * as url from './url.js';
@@ -0,0 +1,106 @@
1
+ const keywords = new Map();
2
+ const properties = new Map();
3
+ const HYPHENMINUS = 45; // '-'.charCodeAt()
4
+
5
+ export const keyword = getKeywordDescriptor;
6
+ export const property = getPropertyDescriptor;
7
+ export const vendorPrefix = getVendorPrefix;
8
+ export function isCustomProperty(str, offset) {
9
+ offset = offset || 0;
10
+
11
+ return str.length - offset >= 2 &&
12
+ str.charCodeAt(offset) === HYPHENMINUS &&
13
+ str.charCodeAt(offset + 1) === HYPHENMINUS;
14
+ }
15
+
16
+ function getVendorPrefix(str, offset) {
17
+ offset = offset || 0;
18
+
19
+ // verdor prefix should be at least 3 chars length
20
+ if (str.length - offset >= 3) {
21
+ // vendor prefix starts with hyper minus following non-hyper minus
22
+ if (str.charCodeAt(offset) === HYPHENMINUS &&
23
+ str.charCodeAt(offset + 1) !== HYPHENMINUS) {
24
+ // vendor prefix should contain a hyper minus at the ending
25
+ const secondDashIndex = str.indexOf('-', offset + 2);
26
+
27
+ if (secondDashIndex !== -1) {
28
+ return str.substring(offset, secondDashIndex + 1);
29
+ }
30
+ }
31
+ }
32
+
33
+ return '';
34
+ }
35
+
36
+ function getKeywordDescriptor(keyword) {
37
+ if (keywords.has(keyword)) {
38
+ return keywords.get(keyword);
39
+ }
40
+
41
+ const name = keyword.toLowerCase();
42
+ let descriptor = keywords.get(name);
43
+
44
+ if (descriptor === undefined) {
45
+ const custom = isCustomProperty(name, 0);
46
+ const vendor = !custom ? getVendorPrefix(name, 0) : '';
47
+ descriptor = Object.freeze({
48
+ basename: name.substr(vendor.length),
49
+ name,
50
+ prefix: vendor,
51
+ vendor,
52
+ custom
53
+ });
54
+ }
55
+
56
+ keywords.set(keyword, descriptor);
57
+
58
+ return descriptor;
59
+ }
60
+
61
+ function getPropertyDescriptor(property) {
62
+ if (properties.has(property)) {
63
+ return properties.get(property);
64
+ }
65
+
66
+ let name = property;
67
+ let hack = property[0];
68
+
69
+ if (hack === '/') {
70
+ hack = property[1] === '/' ? '//' : '/';
71
+ } else if (hack !== '_' &&
72
+ hack !== '*' &&
73
+ hack !== '$' &&
74
+ hack !== '#' &&
75
+ hack !== '+' &&
76
+ hack !== '&') {
77
+ hack = '';
78
+ }
79
+
80
+ const custom = isCustomProperty(name, hack.length);
81
+
82
+ // re-use result when possible (the same as for lower case)
83
+ if (!custom) {
84
+ name = name.toLowerCase();
85
+ if (properties.has(name)) {
86
+ const descriptor = properties.get(name);
87
+ properties.set(property, descriptor);
88
+ return descriptor;
89
+ }
90
+ }
91
+
92
+ const vendor = !custom ? getVendorPrefix(name, hack.length) : '';
93
+ const prefix = name.substr(0, hack.length + vendor.length);
94
+ const descriptor = Object.freeze({
95
+ basename: name.substr(prefix.length),
96
+ name: name.substr(hack.length),
97
+ hack,
98
+ vendor,
99
+ prefix,
100
+ custom
101
+ });
102
+
103
+ properties.set(property, descriptor);
104
+
105
+ return descriptor;
106
+ }
@@ -0,0 +1,99 @@
1
+ import {
2
+ isHexDigit,
3
+ isWhiteSpace,
4
+ isValidEscape,
5
+ consumeEscaped,
6
+ decodeEscaped
7
+ } from '../tokenizer/index.js';
8
+
9
+ const REVERSE_SOLIDUS = 0x005c; // U+005C REVERSE SOLIDUS (\)
10
+ const QUOTATION_MARK = 0x0022; // "
11
+ const APOSTROPHE = 0x0027; // '
12
+
13
+ export function decode(str) {
14
+ const len = str.length;
15
+ const firstChar = str.charCodeAt(0);
16
+ const start = firstChar === QUOTATION_MARK || firstChar === APOSTROPHE ? 1 : 0;
17
+ const end = start === 1 && len > 1 && str.charCodeAt(len - 1) === firstChar ? len - 2 : len - 1;
18
+ let decoded = '';
19
+
20
+ for (let i = start; i <= end; i++) {
21
+ let code = str.charCodeAt(i);
22
+
23
+ if (code === REVERSE_SOLIDUS) {
24
+ // special case at the ending
25
+ if (i === end) {
26
+ // if the next input code point is EOF, do nothing
27
+ // otherwise include last quote as escaped
28
+ if (i !== len - 1) {
29
+ decoded = str.substr(i + 1);
30
+ }
31
+ break;
32
+ }
33
+
34
+ code = str.charCodeAt(++i);
35
+
36
+ // consume escaped
37
+ if (isValidEscape(REVERSE_SOLIDUS, code)) {
38
+ const escapeStart = i - 1;
39
+ const escapeEnd = consumeEscaped(str, escapeStart);
40
+
41
+ i = escapeEnd - 1;
42
+ decoded += decodeEscaped(str.substring(escapeStart + 1, escapeEnd));
43
+ } else {
44
+ // \r\n
45
+ if (code === 0x000d && str.charCodeAt(i + 1) === 0x000a) {
46
+ i++;
47
+ }
48
+ }
49
+ } else {
50
+ decoded += str[i];
51
+ }
52
+ }
53
+
54
+ return decoded;
55
+ }
56
+
57
+ // https://drafts.csswg.org/cssom/#serialize-a-string
58
+ // § 2.1. Common Serializing Idioms
59
+ export function encode(str, apostrophe) {
60
+ const quote = apostrophe ? '\'' : '"';
61
+ const quoteCode = apostrophe ? APOSTROPHE : QUOTATION_MARK;
62
+ let encoded = '';
63
+ let wsBeforeHexIsNeeded = false;
64
+
65
+ for (let i = 0; i < str.length; i++) {
66
+ const code = str.charCodeAt(i);
67
+
68
+ // If the character is NULL (U+0000), then the REPLACEMENT CHARACTER (U+FFFD).
69
+ if (code === 0x0000) {
70
+ encoded += '\uFFFD';
71
+ continue;
72
+ }
73
+
74
+ // If the character is in the range [\1-\1f] (U+0001 to U+001F) or is U+007F,
75
+ // the character escaped as code point.
76
+ // Note: Do not compare with 0x0001 since 0x0000 is precessed before
77
+ if (code <= 0x001f || code === 0x007F) {
78
+ encoded += '\\' + code.toString(16);
79
+ wsBeforeHexIsNeeded = true;
80
+ continue;
81
+ }
82
+
83
+ // If the character is '"' (U+0022) or "\" (U+005C), the escaped character.
84
+ if (code === quoteCode || code === REVERSE_SOLIDUS) {
85
+ encoded += '\\' + str.charAt(i);
86
+ wsBeforeHexIsNeeded = false;
87
+ } else {
88
+ if (wsBeforeHexIsNeeded && (isHexDigit(code) || isWhiteSpace(code))) {
89
+ encoded += ' ';
90
+ }
91
+
92
+ // Otherwise, the character itself.
93
+ encoded += str.charAt(i);
94
+ wsBeforeHexIsNeeded = false;
95
+ }
96
+ }
97
+
98
+ return quote + encoded + quote;
99
+ }
@@ -0,0 +1,108 @@
1
+ import {
2
+ isHexDigit,
3
+ isWhiteSpace,
4
+ isValidEscape,
5
+ consumeEscaped,
6
+ decodeEscaped
7
+ } from '../tokenizer/index.js';
8
+
9
+ const SPACE = 0x0020; // U+0020 SPACE
10
+ const REVERSE_SOLIDUS = 0x005c; // U+005C REVERSE SOLIDUS (\)
11
+ const QUOTATION_MARK = 0x0022; // "
12
+ const APOSTROPHE = 0x0027; // '
13
+ const LEFTPARENTHESIS = 0x0028; // U+0028 LEFT PARENTHESIS (()
14
+ const RIGHTPARENTHESIS = 0x0029; // U+0029 RIGHT PARENTHESIS ())
15
+
16
+ export function decode(str) {
17
+ const len = str.length;
18
+ let start = 4; // length of "url("
19
+ let end = str.charCodeAt(len - 1) === RIGHTPARENTHESIS ? len - 2 : len - 1;
20
+ let decoded = '';
21
+
22
+ while (start < end && isWhiteSpace(str.charCodeAt(start))) {
23
+ start++;
24
+ }
25
+
26
+ while (start < end && isWhiteSpace(str.charCodeAt(end))) {
27
+ end--;
28
+ }
29
+
30
+ for (let i = start; i <= end; i++) {
31
+ let code = str.charCodeAt(i);
32
+
33
+ if (code === REVERSE_SOLIDUS) {
34
+ // special case at the ending
35
+ if (i === end) {
36
+ // if the next input code point is EOF, do nothing
37
+ // otherwise include last left parenthesis as escaped
38
+ if (i !== len - 1) {
39
+ decoded = str.substr(i + 1);
40
+ }
41
+ break;
42
+ }
43
+
44
+ code = str.charCodeAt(++i);
45
+
46
+ // consume escaped
47
+ if (isValidEscape(REVERSE_SOLIDUS, code)) {
48
+ const escapeStart = i - 1;
49
+ const escapeEnd = consumeEscaped(str, escapeStart);
50
+
51
+ i = escapeEnd - 1;
52
+ decoded += decodeEscaped(str.substring(escapeStart + 1, escapeEnd));
53
+ } else {
54
+ // \r\n
55
+ if (code === 0x000d && str.charCodeAt(i + 1) === 0x000a) {
56
+ i++;
57
+ }
58
+ }
59
+ } else {
60
+ decoded += str[i];
61
+ }
62
+ }
63
+
64
+ return decoded;
65
+ }
66
+
67
+ export function encode(str) {
68
+ let encoded = '';
69
+ let wsBeforeHexIsNeeded = false;
70
+
71
+ for (let i = 0; i < str.length; i++) {
72
+ const code = str.charCodeAt(i);
73
+
74
+ // If the character is NULL (U+0000), then the REPLACEMENT CHARACTER (U+FFFD).
75
+ if (code === 0x0000) {
76
+ encoded += '\uFFFD';
77
+ continue;
78
+ }
79
+
80
+ // If the character is in the range [\1-\1f] (U+0001 to U+001F) or is U+007F,
81
+ // the character escaped as code point.
82
+ // Note: Do not compare with 0x0001 since 0x0000 is precessed before
83
+ if (code <= 0x001f || code === 0x007F) {
84
+ encoded += '\\' + code.toString(16);
85
+ wsBeforeHexIsNeeded = true;
86
+ continue;
87
+ }
88
+
89
+ if (code === SPACE ||
90
+ code === REVERSE_SOLIDUS ||
91
+ code === QUOTATION_MARK ||
92
+ code === APOSTROPHE ||
93
+ code === LEFTPARENTHESIS ||
94
+ code === RIGHTPARENTHESIS) {
95
+ encoded += '\\' + str.charAt(i);
96
+ wsBeforeHexIsNeeded = false;
97
+ } else {
98
+ if (wsBeforeHexIsNeeded && isHexDigit(code)) {
99
+ encoded += ' ';
100
+ }
101
+
102
+ encoded += str.charAt(i);
103
+ wsBeforeHexIsNeeded = false;
104
+ }
105
+ }
106
+
107
+ return 'url(' + encoded + ')';
108
+ }
package/lib/version.js ADDED
@@ -0,0 +1,5 @@
1
+ import { createRequire } from 'module';
2
+
3
+ const require = createRequire(import.meta.url);
4
+
5
+ export const { version } = require('../package.json');