@graview/guest 0.1.9 → 0.1.12

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 (173) hide show
  1. package/README.md +353 -3
  2. package/client.js +2 -0
  3. package/dist/channel.d.ts +11 -3
  4. package/dist/channel.d.ts.map +1 -1
  5. package/dist/channel.js +5 -1
  6. package/dist/channel.js.map +1 -1
  7. package/dist/cli.d.ts +16 -0
  8. package/dist/cli.d.ts.map +1 -0
  9. package/dist/cli.js +75 -0
  10. package/dist/cli.js.map +1 -0
  11. package/dist/client-script.d.ts +3 -0
  12. package/dist/client-script.d.ts.map +1 -0
  13. package/dist/client-script.js +21 -0
  14. package/dist/client-script.js.map +1 -0
  15. package/dist/client.d.ts +2 -0
  16. package/dist/client.d.ts.map +1 -0
  17. package/dist/client.generated.d.ts +4 -0
  18. package/dist/client.generated.d.ts.map +1 -0
  19. package/dist/client.generated.js +9 -0
  20. package/dist/client.generated.js.map +1 -0
  21. package/dist/client.js +12 -0
  22. package/dist/client.js.map +1 -0
  23. package/dist/headless/describe.d.ts +19 -0
  24. package/dist/headless/describe.d.ts.map +1 -0
  25. package/dist/headless/describe.js +255 -0
  26. package/dist/headless/describe.js.map +1 -0
  27. package/dist/headless/draw.d.ts +17 -0
  28. package/dist/headless/draw.d.ts.map +1 -0
  29. package/dist/headless/draw.js +25 -0
  30. package/dist/headless/draw.js.map +1 -0
  31. package/dist/headless/index.d.ts +99 -0
  32. package/dist/headless/index.d.ts.map +1 -0
  33. package/dist/headless/index.js +143 -0
  34. package/dist/headless/index.js.map +1 -0
  35. package/dist/headless/judge.d.ts +16 -0
  36. package/dist/headless/judge.d.ts.map +1 -0
  37. package/dist/headless/judge.js +52 -0
  38. package/dist/headless/judge.js.map +1 -0
  39. package/dist/headless/node.d.ts +8 -0
  40. package/dist/headless/node.d.ts.map +1 -0
  41. package/dist/headless/node.js +80 -0
  42. package/dist/headless/node.js.map +1 -0
  43. package/dist/headless/protocol.d.ts +75 -0
  44. package/dist/headless/protocol.d.ts.map +1 -0
  45. package/dist/headless/protocol.js +14 -0
  46. package/dist/headless/protocol.js.map +1 -0
  47. package/dist/headless/runtime.d.ts +2 -0
  48. package/dist/headless/runtime.d.ts.map +1 -0
  49. package/dist/headless/runtime.generated.d.ts +2 -0
  50. package/dist/headless/runtime.generated.d.ts.map +1 -0
  51. package/dist/headless/runtime.generated.js +8 -0
  52. package/dist/headless/runtime.generated.js.map +1 -0
  53. package/dist/headless/runtime.js +171 -0
  54. package/dist/headless/runtime.js.map +1 -0
  55. package/dist/headless/tree.d.ts +54 -0
  56. package/dist/headless/tree.d.ts.map +1 -0
  57. package/dist/headless/tree.js +128 -0
  58. package/dist/headless/tree.js.map +1 -0
  59. package/dist/host/css.d.ts +118 -0
  60. package/dist/host/css.d.ts.map +1 -0
  61. package/dist/host/css.js +963 -0
  62. package/dist/host/css.js.map +1 -0
  63. package/dist/host/draw-budget.d.ts +10 -0
  64. package/dist/host/draw-budget.d.ts.map +1 -0
  65. package/dist/host/draw-budget.js +29 -0
  66. package/dist/host/draw-budget.js.map +1 -0
  67. package/dist/host/frame.d.ts +19 -1
  68. package/dist/host/frame.d.ts.map +1 -1
  69. package/dist/host/frame.js +21 -2
  70. package/dist/host/frame.js.map +1 -1
  71. package/dist/host/index.d.ts +4 -3
  72. package/dist/host/index.d.ts.map +1 -1
  73. package/dist/host/index.js +7 -1
  74. package/dist/host/index.js.map +1 -1
  75. package/dist/host/kit.d.ts +6 -2
  76. package/dist/host/kit.d.ts.map +1 -1
  77. package/dist/host/kit.js +12 -5
  78. package/dist/host/kit.js.map +1 -1
  79. package/dist/host/links.d.ts +24 -0
  80. package/dist/host/links.d.ts.map +1 -0
  81. package/dist/host/links.js +35 -0
  82. package/dist/host/links.js.map +1 -0
  83. package/dist/host/manifest.d.ts +50 -0
  84. package/dist/host/manifest.d.ts.map +1 -0
  85. package/dist/host/manifest.js +103 -0
  86. package/dist/host/manifest.js.map +1 -0
  87. package/dist/host/open-draw.d.ts +44 -0
  88. package/dist/host/open-draw.d.ts.map +1 -0
  89. package/dist/host/open-draw.js +108 -0
  90. package/dist/host/open-draw.js.map +1 -0
  91. package/dist/host/open-judge.d.ts +53 -0
  92. package/dist/host/open-judge.d.ts.map +1 -0
  93. package/dist/host/open-judge.js +95 -0
  94. package/dist/host/open-judge.js.map +1 -0
  95. package/dist/host/open-render.d.ts +32 -0
  96. package/dist/host/open-render.d.ts.map +1 -0
  97. package/dist/host/open-render.js +262 -0
  98. package/dist/host/open-render.js.map +1 -0
  99. package/dist/host/press.d.ts +15 -0
  100. package/dist/host/press.d.ts.map +1 -0
  101. package/dist/host/press.js +156 -0
  102. package/dist/host/press.js.map +1 -0
  103. package/dist/host/react.d.ts +15 -2
  104. package/dist/host/react.d.ts.map +1 -1
  105. package/dist/host/react.js +13 -5
  106. package/dist/host/react.js.map +1 -1
  107. package/dist/host/session.d.ts +94 -1
  108. package/dist/host/session.d.ts.map +1 -1
  109. package/dist/host/session.js +103 -14
  110. package/dist/host/session.js.map +1 -1
  111. package/dist/host/theme.d.ts +14 -0
  112. package/dist/host/theme.d.ts.map +1 -0
  113. package/dist/host/theme.js +51 -0
  114. package/dist/host/theme.js.map +1 -0
  115. package/dist/host/view-runtime.generated.d.ts +2 -0
  116. package/dist/host/view-runtime.generated.d.ts.map +1 -0
  117. package/dist/host/view-runtime.generated.js +7 -0
  118. package/dist/host/view-runtime.generated.js.map +1 -0
  119. package/dist/host/view-source.d.ts +10 -0
  120. package/dist/host/view-source.d.ts.map +1 -0
  121. package/dist/host/view-source.js +44 -0
  122. package/dist/host/view-source.js.map +1 -0
  123. package/dist/host/view.d.ts +138 -0
  124. package/dist/host/view.d.ts.map +1 -0
  125. package/dist/host/view.js +381 -0
  126. package/dist/host/view.js.map +1 -0
  127. package/dist/host/views.d.ts +10 -0
  128. package/dist/host/views.d.ts.map +1 -0
  129. package/dist/host/views.js +15 -0
  130. package/dist/host/views.js.map +1 -0
  131. package/dist/host/worker-react.d.ts +57 -0
  132. package/dist/host/worker-react.d.ts.map +1 -0
  133. package/dist/host/worker-react.js +129 -0
  134. package/dist/host/worker-react.js.map +1 -0
  135. package/dist/host/worker-start.d.ts +66 -0
  136. package/dist/host/worker-start.d.ts.map +1 -0
  137. package/dist/host/worker-start.js +188 -0
  138. package/dist/host/worker-start.js.map +1 -0
  139. package/dist/host/worker.d.ts +28 -19
  140. package/dist/host/worker.d.ts.map +1 -1
  141. package/dist/host/worker.js +60 -119
  142. package/dist/host/worker.js.map +1 -1
  143. package/dist/host/writes.d.ts +49 -0
  144. package/dist/host/writes.d.ts.map +1 -0
  145. package/dist/host/writes.js +76 -0
  146. package/dist/host/writes.js.map +1 -0
  147. package/dist/index.d.ts +1 -1
  148. package/dist/index.d.ts.map +1 -1
  149. package/dist/open-kit.d.ts +148 -0
  150. package/dist/open-kit.d.ts.map +1 -0
  151. package/dist/open-kit.js +321 -0
  152. package/dist/open-kit.js.map +1 -0
  153. package/dist/protocol.d.ts +109 -3
  154. package/dist/protocol.d.ts.map +1 -1
  155. package/dist/protocol.js +13 -0
  156. package/dist/protocol.js.map +1 -1
  157. package/dist/worker/harden.d.ts +13 -2
  158. package/dist/worker/harden.d.ts.map +1 -1
  159. package/dist/worker/harden.js +10 -4
  160. package/dist/worker/harden.js.map +1 -1
  161. package/dist/worker/natives.d.ts +1 -0
  162. package/dist/worker/natives.d.ts.map +1 -1
  163. package/dist/worker/natives.js +4 -0
  164. package/dist/worker/natives.js.map +1 -1
  165. package/dist/worker/view-global.d.ts +70 -0
  166. package/dist/worker/view-global.d.ts.map +1 -0
  167. package/dist/worker/view-global.js +264 -0
  168. package/dist/worker/view-global.js.map +1 -0
  169. package/dist/worker/view.d.ts +14 -0
  170. package/dist/worker/view.d.ts.map +1 -0
  171. package/dist/worker/view.js +64 -0
  172. package/dist/worker/view.js.map +1 -0
  173. package/package.json +30 -4
@@ -0,0 +1,963 @@
1
+ import { CSS_AT_RULES, CSS_FRAGMENT_PROPERTIES, CSS_FUNCTIONS, CSS_KEYWORD_PROPERTIES, CSS_PROPERTIES, CSS_REFUSED_SELECTORS, HTML_DRAWN_AS, OPEN_MAX_STYLESHEET, } from "../open-kit.js";
2
+ const isDigit = (c) => c >= 0x30 && c <= 0x39;
3
+ const isHex = (c) => isDigit(c) || (c >= 0x41 && c <= 0x46) || (c >= 0x61 && c <= 0x66);
4
+ const isLetter = (c) => (c >= 0x41 && c <= 0x5a) || (c >= 0x61 && c <= 0x7a);
5
+ const isNonAscii = (c) => c >= 0x80;
6
+ const isIdentStart = (c) => isLetter(c) || isNonAscii(c) || c === 0x5f;
7
+ const isIdent = (c) => isIdentStart(c) || isDigit(c) || c === 0x2d;
8
+ const isNewline = (c) => c === 0x0a;
9
+ const isWhitespace = (c) => c === 0x0a || c === 0x09 || c === 0x20;
10
+ const isNonPrintable = (c) => (c >= 0 && c <= 8) || c === 0x0b || (c >= 0x0e && c <= 0x1f) || c === 0x7f;
11
+ const EOF = -1;
12
+ /** CSS Syntax §3.3: newlines made one, NUL and surrogates made U+FFFD. */
13
+ function preprocess(input) {
14
+ const out = [];
15
+ for (let i = 0; i < input.length; i += 1) {
16
+ let c = input.codePointAt(i);
17
+ if (c > 0xffff)
18
+ i += 1;
19
+ if (c === 0x0d) {
20
+ if (input.charCodeAt(i + 1) === 0x0a)
21
+ i += 1;
22
+ c = 0x0a;
23
+ }
24
+ else if (c === 0x0c)
25
+ c = 0x0a;
26
+ else if (c === 0 || (c >= 0xd800 && c <= 0xdfff))
27
+ c = 0xfffd;
28
+ out.push(c);
29
+ }
30
+ return out;
31
+ }
32
+ /** CSS Syntax §4: the tokens of a stylesheet, a declaration list or a value. Comments are consumed and dropped. */
33
+ export function tokenize(input) {
34
+ const s = preprocess(input);
35
+ let i = 0;
36
+ const at = (n = 0) => (i + n < s.length ? s[i + n] : EOF);
37
+ const tokens = [];
38
+ const validEscape = (a, b) => a === 0x5c && b !== 0x0a && b !== EOF;
39
+ const startsIdent = (a, b, c) => {
40
+ if (a === 0x2d)
41
+ return isIdentStart(b) || b === 0x2d || validEscape(b, c);
42
+ if (isIdentStart(a))
43
+ return true;
44
+ return validEscape(a, b);
45
+ };
46
+ const startsNumber = (a, b, c) => {
47
+ if (a === 0x2b || a === 0x2d)
48
+ return isDigit(b) || (b === 0x2e && isDigit(c));
49
+ if (a === 0x2e)
50
+ return isDigit(b);
51
+ return isDigit(a);
52
+ };
53
+ /* §4.3.7: after the backslash. */
54
+ const escape = () => {
55
+ const c = at();
56
+ i += 1;
57
+ if (c === EOF)
58
+ return 0xfffd;
59
+ if (isHex(c)) {
60
+ let hex = String.fromCodePoint(c);
61
+ while (hex.length < 6 && isHex(at())) {
62
+ hex += String.fromCodePoint(at());
63
+ i += 1;
64
+ }
65
+ if (isWhitespace(at()))
66
+ i += 1;
67
+ const value = parseInt(hex, 16);
68
+ return value === 0 || (value >= 0xd800 && value <= 0xdfff) || value > 0x10ffff ? 0xfffd : value;
69
+ }
70
+ return c;
71
+ };
72
+ const name = () => {
73
+ let result = "";
74
+ for (;;) {
75
+ const c = at();
76
+ if (isIdent(c)) {
77
+ result += String.fromCodePoint(c);
78
+ i += 1;
79
+ }
80
+ else if (validEscape(c, at(1))) {
81
+ i += 1;
82
+ result += String.fromCodePoint(escape());
83
+ }
84
+ else
85
+ return result;
86
+ }
87
+ };
88
+ const number = () => {
89
+ let repr = "";
90
+ if (at() === 0x2b || at() === 0x2d)
91
+ repr += String.fromCodePoint(s[i++]);
92
+ while (isDigit(at()))
93
+ repr += String.fromCodePoint(s[i++]);
94
+ if (at() === 0x2e && isDigit(at(1))) {
95
+ repr += String.fromCodePoint(s[i++], s[i++]);
96
+ while (isDigit(at()))
97
+ repr += String.fromCodePoint(s[i++]);
98
+ }
99
+ if ((at() === 0x45 || at() === 0x65) && (isDigit(at(1)) || ((at(1) === 0x2b || at(1) === 0x2d) && isDigit(at(2))))) {
100
+ repr += String.fromCodePoint(s[i++]);
101
+ if (!isDigit(at()))
102
+ repr += String.fromCodePoint(s[i++]);
103
+ while (isDigit(at()))
104
+ repr += String.fromCodePoint(s[i++]);
105
+ }
106
+ return repr;
107
+ };
108
+ const numeric = () => {
109
+ const repr = number();
110
+ if (startsIdent(at(), at(1), at(2)))
111
+ return { type: "dimension", repr, unit: name() };
112
+ if (at() === 0x25) {
113
+ i += 1;
114
+ return { type: "percentage", repr };
115
+ }
116
+ return { type: "number", repr };
117
+ };
118
+ const badUrlRemnants = () => {
119
+ for (;;) {
120
+ const c = at();
121
+ i += 1;
122
+ if (c === 0x29 || c === EOF)
123
+ return;
124
+ if (validEscape(c, at()))
125
+ escape();
126
+ }
127
+ };
128
+ const url = () => {
129
+ let value = "";
130
+ while (isWhitespace(at()))
131
+ i += 1;
132
+ for (;;) {
133
+ const c = at();
134
+ i += 1;
135
+ if (c === 0x29)
136
+ return { type: "url", value };
137
+ if (c === EOF)
138
+ return { type: "url", value };
139
+ if (isWhitespace(c)) {
140
+ while (isWhitespace(at()))
141
+ i += 1;
142
+ if (at() === 0x29 || at() === EOF) {
143
+ if (at() === 0x29)
144
+ i += 1;
145
+ return { type: "url", value };
146
+ }
147
+ badUrlRemnants();
148
+ return { type: "bad-url" };
149
+ }
150
+ if (c === 0x22 || c === 0x27 || c === 0x28 || isNonPrintable(c)) {
151
+ badUrlRemnants();
152
+ return { type: "bad-url" };
153
+ }
154
+ if (c === 0x5c) {
155
+ if (validEscape(c, at()))
156
+ value += String.fromCodePoint(escape());
157
+ else {
158
+ badUrlRemnants();
159
+ return { type: "bad-url" };
160
+ }
161
+ continue;
162
+ }
163
+ value += String.fromCodePoint(c);
164
+ }
165
+ };
166
+ const identLike = () => {
167
+ const value = name();
168
+ if (value.toLowerCase() === "url" && at() === 0x28) {
169
+ i += 1;
170
+ while (isWhitespace(at()) && isWhitespace(at(1)))
171
+ i += 1;
172
+ const next = isWhitespace(at()) ? at(1) : at();
173
+ if (next === 0x22 || next === 0x27)
174
+ return { type: "function", value };
175
+ return url();
176
+ }
177
+ if (at() === 0x28) {
178
+ i += 1;
179
+ return { type: "function", value };
180
+ }
181
+ return { type: "ident", value };
182
+ };
183
+ const string = (quote) => {
184
+ let value = "";
185
+ for (;;) {
186
+ const c = at();
187
+ i += 1;
188
+ if (c === quote || c === EOF)
189
+ return { type: "string", value };
190
+ if (isNewline(c)) {
191
+ i -= 1;
192
+ return { type: "bad-string" };
193
+ }
194
+ if (c === 0x5c) {
195
+ if (at() === EOF)
196
+ continue;
197
+ if (isNewline(at())) {
198
+ i += 1;
199
+ continue;
200
+ }
201
+ value += String.fromCodePoint(escape());
202
+ continue;
203
+ }
204
+ value += String.fromCodePoint(c);
205
+ }
206
+ };
207
+ for (;;) {
208
+ /* Comments, which a browser drops before it sees a token. */
209
+ while (at() === 0x2f && at(1) === 0x2a) {
210
+ i += 2;
211
+ while (at() !== EOF && !(at() === 0x2a && at(1) === 0x2f))
212
+ i += 1;
213
+ if (at() !== EOF)
214
+ i += 2;
215
+ }
216
+ const c = at();
217
+ if (c === EOF)
218
+ return tokens;
219
+ if (isWhitespace(c)) {
220
+ while (isWhitespace(at()))
221
+ i += 1;
222
+ tokens.push({ type: "whitespace" });
223
+ continue;
224
+ }
225
+ i += 1;
226
+ switch (c) {
227
+ case 0x22:
228
+ case 0x27:
229
+ tokens.push(string(c));
230
+ continue;
231
+ case 0x23:
232
+ if (isIdent(at()) || validEscape(at(), at(1))) {
233
+ const id = startsIdent(at(), at(1), at(2));
234
+ tokens.push({ type: "hash", value: name(), id });
235
+ }
236
+ else
237
+ tokens.push({ type: "delim", value: "#" });
238
+ continue;
239
+ case 0x28:
240
+ tokens.push({ type: "(" });
241
+ continue;
242
+ case 0x29:
243
+ tokens.push({ type: ")" });
244
+ continue;
245
+ case 0x2b:
246
+ case 0x2e:
247
+ if (startsNumber(c, at(), at(1))) {
248
+ i -= 1;
249
+ tokens.push(numeric());
250
+ }
251
+ else
252
+ tokens.push({ type: "delim", value: String.fromCodePoint(c) });
253
+ continue;
254
+ case 0x2c:
255
+ tokens.push({ type: "," });
256
+ continue;
257
+ case 0x2d:
258
+ if (startsNumber(c, at(), at(1))) {
259
+ i -= 1;
260
+ tokens.push(numeric());
261
+ }
262
+ else if (at() === 0x2d && at(1) === 0x3e) {
263
+ i += 2;
264
+ tokens.push({ type: "CDC" });
265
+ }
266
+ else if (startsIdent(c, at(), at(1))) {
267
+ i -= 1;
268
+ tokens.push(identLike());
269
+ }
270
+ else
271
+ tokens.push({ type: "delim", value: "-" });
272
+ continue;
273
+ case 0x3a:
274
+ tokens.push({ type: ":" });
275
+ continue;
276
+ case 0x3b:
277
+ tokens.push({ type: ";" });
278
+ continue;
279
+ case 0x3c:
280
+ if (at() === 0x21 && at(1) === 0x2d && at(2) === 0x2d) {
281
+ i += 3;
282
+ tokens.push({ type: "CDO" });
283
+ }
284
+ else
285
+ tokens.push({ type: "delim", value: "<" });
286
+ continue;
287
+ case 0x40:
288
+ if (startsIdent(at(), at(1), at(2)))
289
+ tokens.push({ type: "at-keyword", value: name() });
290
+ else
291
+ tokens.push({ type: "delim", value: "@" });
292
+ continue;
293
+ case 0x5b:
294
+ tokens.push({ type: "[" });
295
+ continue;
296
+ case 0x5c:
297
+ if (validEscape(c, at())) {
298
+ i -= 1;
299
+ tokens.push(identLike());
300
+ }
301
+ else
302
+ tokens.push({ type: "delim", value: "\\" });
303
+ continue;
304
+ case 0x5d:
305
+ tokens.push({ type: "]" });
306
+ continue;
307
+ case 0x7b:
308
+ tokens.push({ type: "{" });
309
+ continue;
310
+ case 0x7d:
311
+ tokens.push({ type: "}" });
312
+ continue;
313
+ default:
314
+ if (isDigit(c)) {
315
+ i -= 1;
316
+ tokens.push(numeric());
317
+ }
318
+ else if (isIdentStart(c)) {
319
+ i -= 1;
320
+ tokens.push(identLike());
321
+ }
322
+ else
323
+ tokens.push({ type: "delim", value: String.fromCodePoint(c) });
324
+ }
325
+ }
326
+ }
327
+ const CLOSE = { "{": "}", "[": "]", "(": ")" };
328
+ /** How deep blocks and functions may nest before the rest is read as unreadable. */
329
+ const MAX_DEPTH = 32;
330
+ class Stream {
331
+ tokens;
332
+ i = 0;
333
+ constructor(tokens) {
334
+ this.tokens = tokens;
335
+ }
336
+ peek() {
337
+ return this.tokens[this.i];
338
+ }
339
+ next() {
340
+ return this.tokens[this.i++];
341
+ }
342
+ }
343
+ /** §5.4.7: one component value. Past MAX_DEPTH a block is read flat, and judged unreadable by its caller. */
344
+ function componentValue(stream, depth) {
345
+ const token = stream.next();
346
+ if (token.type === "{" || token.type === "[" || token.type === "(")
347
+ return { type: "block", open: token.type, value: blockContents(stream, CLOSE[token.type], depth + 1) };
348
+ if (token.type === "function")
349
+ return { type: "func", name: token.value, value: blockContents(stream, ")", depth + 1) };
350
+ return token;
351
+ }
352
+ function blockContents(stream, close, depth) {
353
+ const value = [];
354
+ for (;;) {
355
+ const token = stream.peek();
356
+ if (!token)
357
+ return value;
358
+ if (token.type === close) {
359
+ stream.next();
360
+ return value;
361
+ }
362
+ if (depth > MAX_DEPTH) {
363
+ /* Too deep to judge: consumed and dropped as a bad token, so the rule it is in fails. */
364
+ stream.next();
365
+ value.push({ type: "bad-string" });
366
+ continue;
367
+ }
368
+ value.push(componentValue(stream, depth));
369
+ }
370
+ }
371
+ /** §5.4.2–5.4.3: the rules of a stylesheet (or of a block that holds rules). */
372
+ function rules(values, topLevel) {
373
+ const out = [];
374
+ let at = 0;
375
+ while (at < values.length) {
376
+ const value = values[at];
377
+ if (value.type === "whitespace" || (topLevel && (value.type === "CDO" || value.type === "CDC"))) {
378
+ at += 1;
379
+ continue;
380
+ }
381
+ if (value.type === "at-keyword") {
382
+ const prelude = [];
383
+ at += 1;
384
+ let block;
385
+ while (at < values.length) {
386
+ const part = values[at];
387
+ at += 1;
388
+ if (part.type === ";")
389
+ break;
390
+ if (part.type === "block" && part.open === "{") {
391
+ block = part.value;
392
+ break;
393
+ }
394
+ prelude.push(part);
395
+ }
396
+ out.push({ type: "at-rule", name: value.value, prelude, ...(block ? { block } : {}) });
397
+ continue;
398
+ }
399
+ const prelude = [];
400
+ let block;
401
+ while (at < values.length) {
402
+ const part = values[at];
403
+ at += 1;
404
+ if (part.type === "block" && part.open === "{") {
405
+ block = part.value;
406
+ break;
407
+ }
408
+ prelude.push(part);
409
+ }
410
+ if (block)
411
+ out.push({ type: "qualified", prelude, block });
412
+ }
413
+ return out;
414
+ }
415
+ /** The parts of a block's contents (§5.4.5, with nesting): declarations, and rules nested among them. */
416
+ function blockItems(values) {
417
+ const out = [];
418
+ let at = 0;
419
+ while (at < values.length) {
420
+ const value = values[at];
421
+ if (value.type === "whitespace" || value.type === ";") {
422
+ at += 1;
423
+ continue;
424
+ }
425
+ if (value.type === "at-keyword") {
426
+ const end = (() => {
427
+ for (let j = at + 1; j < values.length; j += 1) {
428
+ const part = values[j];
429
+ if (part.type === ";")
430
+ return j + 1;
431
+ if (part.type === "block" && part.open === "{")
432
+ return j + 1;
433
+ }
434
+ return values.length;
435
+ })();
436
+ out.push(...rules(values.slice(at, end), false));
437
+ at = end;
438
+ continue;
439
+ }
440
+ if (value.type === "ident") {
441
+ /* A declaration: ident, colon, value, up to the next top-level ';'. */
442
+ let j = at + 1;
443
+ while (values[j]?.type === "whitespace")
444
+ j += 1;
445
+ if (values[j]?.type === ":") {
446
+ let end = j + 1;
447
+ while (end < values.length && values[end].type !== ";")
448
+ end += 1;
449
+ const declaration = toDeclaration(value.value, values.slice(j + 1, end));
450
+ /* A '{' block in it means it was a nested rule after all (`a:hover { … }`). */
451
+ if (declaration.value.some((part) => part.type === "block" && part.open === "{")) {
452
+ const ends = values.findIndex((part, index) => index > at && part.type === "block" && part.open === "{");
453
+ out.push(...rules(values.slice(at, ends + 1), false));
454
+ at = ends + 1;
455
+ continue;
456
+ }
457
+ out.push(declaration);
458
+ at = end + 1;
459
+ continue;
460
+ }
461
+ }
462
+ /* A nested rule (`& .child { … }`, `.child { … }`), up to its block. */
463
+ let end = at;
464
+ while (end < values.length && !(values[end].type === "block" && values[end].open === "{")) {
465
+ if (values[end].type === ";")
466
+ break;
467
+ end += 1;
468
+ }
469
+ if (end < values.length && values[end].type === "block") {
470
+ out.push(...rules(values.slice(at, end + 1), false));
471
+ at = end + 1;
472
+ }
473
+ else
474
+ at = end + 1;
475
+ }
476
+ return out;
477
+ }
478
+ function toDeclaration(name, raw) {
479
+ const value = [...raw];
480
+ while (value[0]?.type === "whitespace")
481
+ value.shift();
482
+ while (value.at(-1)?.type === "whitespace")
483
+ value.pop();
484
+ let important = false;
485
+ /* `! important`, with any whitespace and in any case, at the end. */
486
+ const last = value.length - 1;
487
+ let bang = last;
488
+ if (value[bang]?.type === "ident" && value[bang].value.toLowerCase() === "important") {
489
+ bang -= 1;
490
+ while (value[bang]?.type === "whitespace")
491
+ bang -= 1;
492
+ const mark = value[bang];
493
+ if (mark?.type === "delim" && mark.value === "!") {
494
+ important = true;
495
+ value.length = bang;
496
+ while (value.at(-1)?.type === "whitespace")
497
+ value.pop();
498
+ }
499
+ }
500
+ return { type: "declaration", name, value, important };
501
+ }
502
+ function parse(css) {
503
+ const stream = new Stream(tokenize(css));
504
+ const out = [];
505
+ while (stream.peek())
506
+ out.push(componentValue(stream, 0));
507
+ return out;
508
+ }
509
+ // ── serialisation ───────────────────────────────────────────────────────────
510
+ /** CSSOM's "serialize an identifier". */
511
+ export function serializeIdent(value) {
512
+ let out = "";
513
+ const codes = [...value].map((one) => one.codePointAt(0));
514
+ codes.forEach((c, index) => {
515
+ if (c === 0)
516
+ out += "�";
517
+ else if ((c >= 1 && c <= 0x1f) || c === 0x7f || (index === 0 && isDigit(c)) || (index === 1 && isDigit(c) && codes[0] === 0x2d))
518
+ out += `\\${c.toString(16)} `;
519
+ else if (index === 0 && c === 0x2d && codes.length === 1)
520
+ out += "\\-";
521
+ else if (isNonAscii(c) || c === 0x2d || c === 0x5f || isDigit(c) || isLetter(c))
522
+ out += String.fromCodePoint(c);
523
+ else
524
+ out += `\\${String.fromCodePoint(c)}`;
525
+ });
526
+ return out;
527
+ }
528
+ /** A name after `#` or in a unit: like an identifier, but it may start with a digit. */
529
+ function serializeName(value) {
530
+ let out = "";
531
+ for (const one of value) {
532
+ const c = one.codePointAt(0);
533
+ if (isNonAscii(c) || c === 0x2d || c === 0x5f || isDigit(c) || isLetter(c))
534
+ out += one;
535
+ else if ((c >= 1 && c <= 0x1f) || c === 0x7f)
536
+ out += `\\${c.toString(16)} `;
537
+ else
538
+ out += `\\${one}`;
539
+ }
540
+ return out;
541
+ }
542
+ /** A string, quoted, with nothing in it that could end the quote, the line or a `<style>`. */
543
+ export function serializeString(value) {
544
+ let out = '"';
545
+ for (const one of value) {
546
+ const c = one.codePointAt(0);
547
+ if (c === 0)
548
+ out += "�";
549
+ else if ((c >= 1 && c <= 0x1f) || c === 0x7f || c === 0x3c || c === 0x3e)
550
+ out += `\\${c.toString(16)} `;
551
+ else if (c === 0x22 || c === 0x5c)
552
+ out += `\\${one}`;
553
+ else
554
+ out += one;
555
+ }
556
+ return `${out}"`;
557
+ }
558
+ /** A unit, written so it does not read back as an exponent (`1\65 3x` is not `1e3x`). */
559
+ function serializeUnit(unit) {
560
+ const named = serializeName(unit);
561
+ return /^[eE]([0-9]|[+-][0-9])/.test(unit) ? `\\${unit.codePointAt(0).toString(16)} ${serializeName(unit.slice(1))}` : named;
562
+ }
563
+ const kindOf = (value) => {
564
+ switch (value.type) {
565
+ case "ident":
566
+ case "url":
567
+ case "bad-url":
568
+ case "number":
569
+ case "percentage":
570
+ case "dimension":
571
+ case "CDC":
572
+ case "hash":
573
+ case "at-keyword":
574
+ return value.type;
575
+ case "func":
576
+ case "function":
577
+ return "function";
578
+ case "block":
579
+ return value.open === "(" ? "(" : "other";
580
+ case "(":
581
+ return "(";
582
+ case "delim":
583
+ return `delim${value.value}`;
584
+ default:
585
+ return "other";
586
+ }
587
+ };
588
+ /** CSS Syntax §9: the pairs that would run together, which get a comment between them. */
589
+ function needsComment(a, b) {
590
+ const identish = ["ident", "function", "url", "bad-url", "delim-", "number", "percentage", "dimension", "CDC"];
591
+ if (a === "ident")
592
+ return [...identish, "("].includes(b);
593
+ if (a === "at-keyword" || a === "hash" || a === "dimension")
594
+ return identish.includes(b);
595
+ if (a === "delim#" || a === "delim-")
596
+ return identish.includes(b);
597
+ if (a === "number")
598
+ return ["ident", "function", "url", "bad-url", "number", "percentage", "dimension", "delim%"].includes(b);
599
+ if (a === "delim@")
600
+ return ["ident", "function", "url", "bad-url", "delim-", "CDC"].includes(b);
601
+ if (a === "delim." || a === "delim+")
602
+ return ["number", "percentage", "dimension"].includes(b);
603
+ if (a === "delim/")
604
+ return b === "delim*";
605
+ return false;
606
+ }
607
+ function serializeOne(value) {
608
+ switch (value.type) {
609
+ case "whitespace":
610
+ return " ";
611
+ case "ident":
612
+ return serializeIdent(value.value);
613
+ case "at-keyword":
614
+ return `@${serializeIdent(value.value)}`;
615
+ case "hash":
616
+ return `#${serializeName(value.value)}`;
617
+ case "string":
618
+ return serializeString(value.value);
619
+ case "url":
620
+ return `url(${serializeString(value.value)})`;
621
+ case "delim":
622
+ return value.value === "\\" ? "\\\n" : value.value;
623
+ /* Written back as they were: dropped, `:-->host` would read back as `:host`. */
624
+ case "CDO":
625
+ return "<!--";
626
+ case "CDC":
627
+ return "-->";
628
+ case "number":
629
+ return value.repr;
630
+ case "percentage":
631
+ return `${value.repr}%`;
632
+ case "dimension":
633
+ return `${value.repr}${serializeUnit(value.unit)}`;
634
+ case "func":
635
+ return `${serializeIdent(value.name)}(${serializeValues(value.value)})`;
636
+ case "block":
637
+ return `${value.open}${serializeValues(value.value)}${CLOSE[value.open]}`;
638
+ case ":":
639
+ case ";":
640
+ case ",":
641
+ case "[":
642
+ case "]":
643
+ case "(":
644
+ case ")":
645
+ case "{":
646
+ case "}":
647
+ return value.type;
648
+ default:
649
+ return "";
650
+ }
651
+ }
652
+ /** Component values as text, with whitespace runs made one space and a comment wherever two tokens would run together. */
653
+ export function serializeValues(values) {
654
+ let out = "";
655
+ let previous;
656
+ for (const value of values) {
657
+ if (value.type === "whitespace" && previous?.type === "whitespace")
658
+ continue;
659
+ if (previous && needsComment(kindOf(previous), kindOf(value)))
660
+ out += "/**/";
661
+ out += serializeOne(value);
662
+ previous = value;
663
+ }
664
+ return out;
665
+ }
666
+ const PROPERTIES = new Set(CSS_PROPERTIES);
667
+ const FUNCTIONS = new Set(CSS_FUNCTIONS);
668
+ const FRAGMENTS = new Set(CSS_FRAGMENT_PROPERTIES);
669
+ const AT_RULES = new Set(CSS_AT_RULES);
670
+ const REFUSED_SELECTORS = new Set(CSS_REFUSED_SELECTORS);
671
+ const FRAGMENT = /^#[A-Za-z_][A-Za-z0-9_.:-]*$/;
672
+ const lower = (value) => value.replace(/[A-Z]/g, (c) => c.toLowerCase());
673
+ /** A vendor prefix said in another case, or a property spelled with an escape, is the same property (`POSITION`, `po\73 ition`). */
674
+ const propertyName = (name) => lower(name);
675
+ /**
676
+ * A value as it may be drawn for `property`, or the reason it may not:
677
+ * every function on the allowlist, every `url()` a fragment on a paint,
678
+ * nothing unreadable. `var()` is wrapped in whitespace, so no browser that
679
+ * substitutes by text can glue it to its neighbour.
680
+ */
681
+ function judgeValue(property, values, refuse) {
682
+ const out = [];
683
+ for (const value of values) {
684
+ if (value.type === "bad-url" || value.type === "bad-string") {
685
+ refuse({ reason: "unreadable", ...(property ? { name: property } : {}) });
686
+ return undefined;
687
+ }
688
+ if (value.type === "url") {
689
+ if (property && FRAGMENTS.has(property) && FRAGMENT.test(value.value)) {
690
+ out.push({ type: "func", name: "url", value: [{ type: "string", value: value.value }] });
691
+ continue;
692
+ }
693
+ refuse({ reason: "url", ...(property ? { name: property } : {}) });
694
+ return undefined;
695
+ }
696
+ if (value.type === "func") {
697
+ const name = lower(value.name);
698
+ if (name === "url" || name === "src") {
699
+ const inner = value.value.filter((part) => part.type !== "whitespace");
700
+ const only = inner[0];
701
+ if (name === "url" && inner.length === 1 && only?.type === "string" && property && FRAGMENTS.has(property) && FRAGMENT.test(only.value)) {
702
+ out.push({ type: "func", name: "url", value: [{ type: "string", value: only.value }] });
703
+ continue;
704
+ }
705
+ refuse({ reason: "url", ...(property ? { name: property } : {}) });
706
+ return undefined;
707
+ }
708
+ if (!FUNCTIONS.has(name)) {
709
+ refuse({ reason: "function", name });
710
+ return undefined;
711
+ }
712
+ const inner = judgeValue(property, value.value, refuse);
713
+ if (!inner)
714
+ return undefined;
715
+ if (name === "var")
716
+ out.push({ type: "whitespace" }, { type: "func", name, value: inner }, { type: "whitespace" });
717
+ else
718
+ out.push({ type: "func", name, value: inner });
719
+ continue;
720
+ }
721
+ if (value.type === "block") {
722
+ /* A name and a bracket with something between them (`url/**\/(…)`) is a function nobody can call: not drawn, rather than judged harmless. */
723
+ if (value.open === "{" || (value.open === "(" && out.at(-1)?.type === "ident")) {
724
+ refuse({ reason: "unreadable", ...(property ? { name: property } : {}) });
725
+ return undefined;
726
+ }
727
+ const inner = judgeValue(property, value.value, refuse);
728
+ if (!inner)
729
+ return undefined;
730
+ out.push({ type: "block", open: value.open, value: inner });
731
+ continue;
732
+ }
733
+ if (value.type === "at-keyword" || value.type === "CDO" || value.type === "CDC" || value.type === "{" || value.type === "}" || value.type === ";" || (value.type === "delim" && value.value === "\\")) {
734
+ refuse({ reason: "unreadable", ...(property ? { name: property } : {}) });
735
+ return undefined;
736
+ }
737
+ out.push(value);
738
+ }
739
+ return out;
740
+ }
741
+ /** One declaration, judged: kept as text, or refused. */
742
+ function judgeDeclaration(declaration, refuse) {
743
+ const custom = declaration.name.startsWith("--");
744
+ const name = custom ? declaration.name : propertyName(declaration.name);
745
+ if (!custom && !PROPERTIES.has(name)) {
746
+ refuse({ reason: "property", name });
747
+ return undefined;
748
+ }
749
+ const keywords = CSS_KEYWORD_PROPERTIES[name];
750
+ if (keywords) {
751
+ /* Held to keywords: exactly one ident from the list, never var(), never an escape that reads as one. */
752
+ const parts = declaration.value.filter((part) => part.type !== "whitespace");
753
+ const only = parts[0];
754
+ const word = parts.length === 1 && only?.type === "ident" ? lower(only.value) : undefined;
755
+ if (!word || ![...keywords, "inherit", "initial", "unset", "revert"].includes(word)) {
756
+ refuse({ reason: "value", name });
757
+ return undefined;
758
+ }
759
+ return `${name}: ${word}${declaration.important ? " !important" : ""}`;
760
+ }
761
+ const value = judgeValue(custom ? undefined : name, declaration.value, refuse);
762
+ if (!value)
763
+ return undefined;
764
+ const said = serializeValues(value).trim();
765
+ return `${custom ? `--${serializeName(declaration.name.slice(2))}` : name}: ${said}${declaration.important ? " !important" : ""}`;
766
+ }
767
+ /** Whether a selector stays in the view's own tree: nothing on `CSS_REFUSED_SELECTORS`, nothing unreadable. */
768
+ function judgeSelector(prelude, refuse) {
769
+ const walk = (values) => {
770
+ for (let index = 0; index < values.length; index += 1) {
771
+ const value = values[index];
772
+ const colon = index > 0 && values[index - 1].type === ":";
773
+ if (colon && (value.type === "ident" || value.type === "func")) {
774
+ const name = lower(value.type === "ident" ? value.value : value.name);
775
+ if (REFUSED_SELECTORS.has(name) || name.startsWith("-webkit-") || name.startsWith("-moz-")) {
776
+ refuse({ reason: "selector", name });
777
+ return false;
778
+ }
779
+ }
780
+ /* `<!--` and `-->` mean nothing in a selector, and stand between a colon and the name it is judged by (`:-->host`). */
781
+ if (value.type === "url" || value.type === "bad-url" || value.type === "bad-string" || value.type === "at-keyword" || value.type === "CDO" || value.type === "CDC" || (value.type === "block" && value.open === "{")) {
782
+ refuse({ reason: "unreadable", name: "selector" });
783
+ return false;
784
+ }
785
+ if (value.type === "func" && !walk(value.value))
786
+ return false;
787
+ if (value.type === "block" && !walk(value.value))
788
+ return false;
789
+ }
790
+ return true;
791
+ };
792
+ return walk(prelude);
793
+ }
794
+ /** The contents of a style rule's block: declarations and nested rules. */
795
+ function judgeBlock(values, refuse, depth) {
796
+ const kept = [];
797
+ for (const item of blockItems(values)) {
798
+ if (item.type === "declaration") {
799
+ const said = judgeDeclaration(item, refuse);
800
+ if (said)
801
+ kept.push(`${said};`);
802
+ }
803
+ else {
804
+ const said = judgeRule(item, refuse, depth + 1, "style");
805
+ if (said)
806
+ kept.push(said);
807
+ }
808
+ }
809
+ return kept.join(" ");
810
+ }
811
+ /** A prelude of `@media`, `@supports` or `@container`: conditions, which fetch nothing, written with no url and no function outside the allowlist (but `selector()` in `@supports`). */
812
+ function judgeCondition(prelude, at, refuse) {
813
+ const walk = (values) => values.every((value) => {
814
+ if (value.type === "url" || value.type === "bad-url" || value.type === "bad-string" || (value.type === "block" && value.open === "{")) {
815
+ refuse({ reason: value.type === "url" ? "url" : "unreadable", name: `@${at}` });
816
+ return false;
817
+ }
818
+ if (value.type === "func") {
819
+ const name = lower(value.name);
820
+ if (at === "supports" && name === "selector")
821
+ return judgeSelector(value.value, refuse);
822
+ if (!FUNCTIONS.has(name)) {
823
+ refuse({ reason: "function", name });
824
+ return false;
825
+ }
826
+ return walk(value.value);
827
+ }
828
+ if (value.type === "block") {
829
+ /* `(display: grid)` in @supports is a declaration: judged as one. */
830
+ if (at === "supports") {
831
+ const items = blockItems(value.value);
832
+ if (items.length === 1 && items[0].type === "declaration")
833
+ return judgeDeclaration(items[0], refuse) !== undefined;
834
+ }
835
+ return walk(value.value);
836
+ }
837
+ return true;
838
+ });
839
+ return walk(prelude) ? serializeValues(prelude).trim() : undefined;
840
+ }
841
+ /**
842
+ * A selector with its type selectors for the elements the host draws as
843
+ * another (`HTML_DRAWN_AS`: `nav`, `header`, `output`, …) read as the
844
+ * attribute the host gives them: `.package header` is
845
+ * `.package [data-graview-as="header"]`, so a view styles them as it wrote.
846
+ * A type selector is an ident that no `:`, `.` or `|` stands before, outside
847
+ * an attribute's brackets.
848
+ */
849
+ function asDrawn(values) {
850
+ return values.map((value, index) => {
851
+ const before = values[index - 1];
852
+ const named = before?.type === ":" || (before?.type === "delim" && (before.value === "." || before.value === "|"));
853
+ if (value.type === "ident" && !named && Object.prototype.hasOwnProperty.call(HTML_DRAWN_AS, lower(value.value))) {
854
+ return { type: "block", open: "[", value: [{ type: "ident", value: "data-graview-as" }, { type: "delim", value: "=" }, { type: "string", value: lower(value.value) }] };
855
+ }
856
+ if (value.type === "func")
857
+ return { type: "func", name: value.name, value: asDrawn(value.value) };
858
+ if (value.type === "block" && value.open === "(")
859
+ return { type: "block", open: "(", value: asDrawn(value.value) };
860
+ return value;
861
+ });
862
+ }
863
+ function judgeRule(rule, refuse, depth, within) {
864
+ if (depth > MAX_DEPTH) {
865
+ refuse({ reason: "unreadable", name: "nesting" });
866
+ return undefined;
867
+ }
868
+ if (rule.type === "qualified") {
869
+ if (within === "keyframes") {
870
+ /* A keyframe's prelude is `from`, `to` or percentages. */
871
+ const ok = rule.prelude.every((part) => part.type === "whitespace" || part.type === "," || part.type === "percentage" || (part.type === "ident" && ["from", "to"].includes(lower(part.value))));
872
+ if (!ok) {
873
+ refuse({ reason: "unreadable", name: "keyframe" });
874
+ return undefined;
875
+ }
876
+ return `${serializeValues(rule.prelude).trim()} { ${judgeBlock(rule.block, refuse, depth)} }`;
877
+ }
878
+ if (!judgeSelector(rule.prelude, refuse))
879
+ return undefined;
880
+ const selector = serializeValues(asDrawn(rule.prelude)).trim();
881
+ if (selector === "") {
882
+ refuse({ reason: "unreadable", name: "selector" });
883
+ return undefined;
884
+ }
885
+ return `${selector} { ${judgeBlock(rule.block, refuse, depth)} }`;
886
+ }
887
+ const name = lower(rule.name);
888
+ const canonical = name === "-webkit-keyframes" ? "keyframes" : name;
889
+ if (!AT_RULES.has(canonical) || within === "keyframes") {
890
+ refuse({ reason: "at-rule", name: `@${name}` });
891
+ return undefined;
892
+ }
893
+ if (!rule.block) {
894
+ refuse({ reason: "unreadable", name: `@${name}` });
895
+ return undefined;
896
+ }
897
+ if (canonical === "keyframes") {
898
+ if (within !== "sheet") {
899
+ refuse({ reason: "at-rule", name: "@keyframes" });
900
+ return undefined;
901
+ }
902
+ const parts = rule.prelude.filter((part) => part.type !== "whitespace");
903
+ const only = parts[0];
904
+ if (parts.length !== 1 || !only || (only.type !== "ident" && only.type !== "string")) {
905
+ refuse({ reason: "unreadable", name: "@keyframes" });
906
+ return undefined;
907
+ }
908
+ const frames = rules(rule.block, false)
909
+ .map((frame) => judgeRule(frame, refuse, depth + 1, "keyframes"))
910
+ .filter((one) => one !== undefined);
911
+ const named = only.type === "ident" ? serializeIdent(only.value) : serializeString(only.value);
912
+ return `@keyframes ${named} { ${frames.join(" ")} }`;
913
+ }
914
+ const condition = judgeCondition(rule.prelude, canonical, refuse);
915
+ if (condition === undefined)
916
+ return undefined;
917
+ /* Inside a style rule a conditional rule holds declarations (nesting); at the top it holds rules. */
918
+ const body = within === "style"
919
+ ? judgeBlock(rule.block, refuse, depth)
920
+ : rules(rule.block, false)
921
+ .map((inner) => judgeRule(inner, refuse, depth + 1, "sheet"))
922
+ .filter((one) => one !== undefined)
923
+ .join(" ");
924
+ return `@${canonical} ${condition} { ${body} }`;
925
+ }
926
+ /** A VIEW'S STYLESHEET, judged: what may be drawn of it, and what was refused. */
927
+ export function sanitizeStylesheet(css, maxLength = OPEN_MAX_STYLESHEET) {
928
+ const refused = [];
929
+ if (css.length > maxLength)
930
+ return { css: "", refused: [{ reason: "size" }] };
931
+ const refuse = (refusal) => void refused.push(refusal);
932
+ const kept = rules(parse(css), true)
933
+ .map((rule) => judgeRule(rule, refuse, 0, "sheet"))
934
+ .filter((one) => one !== undefined);
935
+ return { css: kept.join("\n"), refused };
936
+ }
937
+ /** A `style` attribute, judged: declarations only. */
938
+ export function sanitizeDeclarations(css, maxLength = OPEN_MAX_STYLESHEET) {
939
+ const refused = [];
940
+ if (css.length > maxLength)
941
+ return { css: "", refused: [{ reason: "size" }] };
942
+ const refuse = (refusal) => void refused.push(refusal);
943
+ const kept = [];
944
+ for (const item of blockItems(parse(css))) {
945
+ if (item.type !== "declaration") {
946
+ refuse({ reason: "unreadable", name: "a rule in a style attribute" });
947
+ continue;
948
+ }
949
+ const said = judgeDeclaration(item, refuse);
950
+ if (said)
951
+ kept.push(said);
952
+ }
953
+ return { css: kept.join("; "), refused };
954
+ }
955
+ /** One value for one property (an SVG presentation attribute), judged. */
956
+ export function sanitizeValue(property, value) {
957
+ let refusal;
958
+ const said = judgeDeclaration(toDeclaration(property, parse(value)), (one) => (refusal ??= one));
959
+ if (said === undefined || refusal)
960
+ return { refused: refusal ?? { reason: "unreadable", name: property } };
961
+ return { value: said.slice(said.indexOf(":") + 1).trim() };
962
+ }
963
+ //# sourceMappingURL=css.js.map