@react-x11/components 0.8.0 → 0.10.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 (721) hide show
  1. package/README.md +105 -38
  2. package/dist/charts/node.d.ts +12 -2
  3. package/dist/charts/node.d.ts.map +1 -1
  4. package/dist/charts/node.js +50 -16
  5. package/dist/charts/node.js.map +1 -1
  6. package/dist/charts/render.d.ts +12 -3
  7. package/dist/charts/render.d.ts.map +1 -1
  8. package/dist/charts/render.js +94 -25
  9. package/dist/charts/render.js.map +1 -1
  10. package/dist/code/index.d.ts.map +1 -1
  11. package/dist/code/index.js +3 -1
  12. package/dist/code/index.js.map +1 -1
  13. package/dist/code-editor/completion.d.ts.map +1 -1
  14. package/dist/code-editor/completion.js +3 -2
  15. package/dist/code-editor/completion.js.map +1 -1
  16. package/dist/code-editor/index.d.ts.map +1 -1
  17. package/dist/code-editor/index.js +19 -0
  18. package/dist/code-editor/index.js.map +1 -1
  19. package/dist/code-editor/node.d.ts +177 -7
  20. package/dist/code-editor/node.d.ts.map +1 -1
  21. package/dist/code-editor/node.js +1329 -164
  22. package/dist/code-editor/node.js.map +1 -1
  23. package/dist/code-language/languages/glsl.d.ts.map +1 -1
  24. package/dist/code-language/languages/glsl.js +10 -2
  25. package/dist/code-language/languages/glsl.js.map +1 -1
  26. package/dist/code-language/languages/javascript.d.ts.map +1 -1
  27. package/dist/code-language/languages/javascript.js +18 -3
  28. package/dist/code-language/languages/javascript.js.map +1 -1
  29. package/dist/code-language/languages/json.d.ts.map +1 -1
  30. package/dist/code-language/languages/json.js +10 -2
  31. package/dist/code-language/languages/json.js.map +1 -1
  32. package/dist/code-language/languages/shell.d.ts.map +1 -1
  33. package/dist/code-language/languages/shell.js +10 -2
  34. package/dist/code-language/languages/shell.js.map +1 -1
  35. package/dist/code-language/languages/sql.d.ts.map +1 -1
  36. package/dist/code-language/languages/sql.js +20 -2
  37. package/dist/code-language/languages/sql.js.map +1 -1
  38. package/dist/code-language/stream.d.ts +22 -0
  39. package/dist/code-language/stream.d.ts.map +1 -1
  40. package/dist/code-language/stream.js +259 -9
  41. package/dist/code-language/stream.js.map +1 -1
  42. package/dist/code-language/types.d.ts +5 -4
  43. package/dist/code-language/types.d.ts.map +1 -1
  44. package/dist/codeblock/index.d.ts +13 -2
  45. package/dist/codeblock/index.d.ts.map +1 -1
  46. package/dist/codeblock/index.js +20 -3
  47. package/dist/codeblock/index.js.map +1 -1
  48. package/dist/embed/client.d.ts +48 -3
  49. package/dist/embed/client.d.ts.map +1 -1
  50. package/dist/embed/client.js +79 -5
  51. package/dist/embed/client.js.map +1 -1
  52. package/dist/embed/index.d.ts +1 -1
  53. package/dist/embed/index.d.ts.map +1 -1
  54. package/dist/embed/index.js +1 -1
  55. package/dist/embed/index.js.map +1 -1
  56. package/dist/flow/draw.d.ts +50 -0
  57. package/dist/flow/draw.d.ts.map +1 -1
  58. package/dist/flow/draw.js +132 -33
  59. package/dist/flow/draw.js.map +1 -1
  60. package/dist/flow/gl/color.d.ts +13 -0
  61. package/dist/flow/gl/color.d.ts.map +1 -0
  62. package/dist/flow/gl/color.js +82 -0
  63. package/dist/flow/gl/color.js.map +1 -0
  64. package/dist/flow/gl/index.d.ts +60 -0
  65. package/dist/flow/gl/index.d.ts.map +1 -0
  66. package/dist/flow/gl/index.js +283 -0
  67. package/dist/flow/gl/index.js.map +1 -0
  68. package/dist/flow/gl/pack.d.ts +133 -0
  69. package/dist/flow/gl/pack.d.ts.map +1 -0
  70. package/dist/flow/gl/pack.js +408 -0
  71. package/dist/flow/gl/pack.js.map +1 -0
  72. package/dist/flow/gl/renderer.d.ts +95 -0
  73. package/dist/flow/gl/renderer.d.ts.map +1 -0
  74. package/dist/flow/gl/renderer.js +459 -0
  75. package/dist/flow/gl/renderer.js.map +1 -0
  76. package/dist/flow/gl/shaders.d.ts +79 -0
  77. package/dist/flow/gl/shaders.d.ts.map +1 -0
  78. package/dist/flow/gl/shaders.js +346 -0
  79. package/dist/flow/gl/shaders.js.map +1 -0
  80. package/dist/flow/gl/text.d.ts +318 -0
  81. package/dist/flow/gl/text.d.ts.map +1 -0
  82. package/dist/flow/gl/text.js +1103 -0
  83. package/dist/flow/gl/text.js.map +1 -0
  84. package/dist/flow/index.d.ts +1 -1
  85. package/dist/flow/index.d.ts.map +1 -1
  86. package/dist/flow/index.js +619 -64
  87. package/dist/flow/index.js.map +1 -1
  88. package/dist/flow/node.d.ts +621 -72
  89. package/dist/flow/node.d.ts.map +1 -1
  90. package/dist/flow/node.js +2253 -1018
  91. package/dist/flow/node.js.map +1 -1
  92. package/dist/flow/paint.d.ts +35 -0
  93. package/dist/flow/paint.d.ts.map +1 -0
  94. package/dist/flow/paint.js +393 -0
  95. package/dist/flow/paint.js.map +1 -0
  96. package/dist/flow/paths.d.ts +14 -0
  97. package/dist/flow/paths.d.ts.map +1 -1
  98. package/dist/flow/paths.js +45 -19
  99. package/dist/flow/paths.js.map +1 -1
  100. package/dist/flow/scene.d.ts +584 -0
  101. package/dist/flow/scene.d.ts.map +1 -0
  102. package/dist/flow/scene.js +1453 -0
  103. package/dist/flow/scene.js.map +1 -0
  104. package/dist/flow/types.d.ts +111 -1
  105. package/dist/flow/types.d.ts.map +1 -1
  106. package/dist/html/controls.d.ts +28 -0
  107. package/dist/html/controls.d.ts.map +1 -1
  108. package/dist/html/controls.js +52 -2
  109. package/dist/html/controls.js.map +1 -1
  110. package/dist/html/css/calc.d.ts +14 -0
  111. package/dist/html/css/calc.d.ts.map +1 -0
  112. package/dist/html/css/calc.js +344 -0
  113. package/dist/html/css/calc.js.map +1 -0
  114. package/dist/html/css/cascade.d.ts +240 -6
  115. package/dist/html/css/cascade.d.ts.map +1 -1
  116. package/dist/html/css/cascade.js +1327 -66
  117. package/dist/html/css/cascade.js.map +1 -1
  118. package/dist/html/css/color.d.ts +23 -0
  119. package/dist/html/css/color.d.ts.map +1 -0
  120. package/dist/html/css/color.js +740 -0
  121. package/dist/html/css/color.js.map +1 -0
  122. package/dist/html/css/content.d.ts +92 -0
  123. package/dist/html/css/content.d.ts.map +1 -0
  124. package/dist/html/css/content.js +388 -0
  125. package/dist/html/css/content.js.map +1 -0
  126. package/dist/html/css/counter-styles.d.ts +76 -0
  127. package/dist/html/css/counter-styles.d.ts.map +1 -0
  128. package/dist/html/css/counter-styles.js +893 -0
  129. package/dist/html/css/counter-styles.js.map +1 -0
  130. package/dist/html/css/decode.d.ts +12 -0
  131. package/dist/html/css/decode.d.ts.map +1 -0
  132. package/dist/html/css/decode.js +116 -0
  133. package/dist/html/css/decode.js.map +1 -0
  134. package/dist/html/css/parse.d.ts +110 -10
  135. package/dist/html/css/parse.d.ts.map +1 -1
  136. package/dist/html/css/parse.js +1473 -180
  137. package/dist/html/css/parse.js.map +1 -1
  138. package/dist/html/css/style.d.ts +498 -15
  139. package/dist/html/css/style.d.ts.map +1 -1
  140. package/dist/html/css/style.js +3698 -206
  141. package/dist/html/css/style.js.map +1 -1
  142. package/dist/html/css/ua.d.ts.map +1 -1
  143. package/dist/html/css/ua.js +57 -11
  144. package/dist/html/css/ua.js.map +1 -1
  145. package/dist/html/css/values.d.ts +37 -3
  146. package/dist/html/css/values.d.ts.map +1 -1
  147. package/dist/html/css/values.js +122 -48
  148. package/dist/html/css/values.js.map +1 -1
  149. package/dist/html/css/vars.d.ts +52 -0
  150. package/dist/html/css/vars.d.ts.map +1 -0
  151. package/dist/html/css/vars.js +358 -0
  152. package/dist/html/css/vars.js.map +1 -0
  153. package/dist/html/dom.d.ts +30 -4
  154. package/dist/html/dom.d.ts.map +1 -1
  155. package/dist/html/dom.js +278 -17
  156. package/dist/html/dom.js.map +1 -1
  157. package/dist/html/fonts.d.ts +106 -0
  158. package/dist/html/fonts.d.ts.map +1 -0
  159. package/dist/html/fonts.js +565 -0
  160. package/dist/html/fonts.js.map +1 -0
  161. package/dist/html/gif.d.ts +15 -0
  162. package/dist/html/gif.d.ts.map +1 -0
  163. package/dist/html/gif.js +229 -0
  164. package/dist/html/gif.js.map +1 -0
  165. package/dist/html/index.d.ts +50 -11
  166. package/dist/html/index.d.ts.map +1 -1
  167. package/dist/html/index.js +115 -9
  168. package/dist/html/index.js.map +1 -1
  169. package/dist/html/layout/block.d.ts +226 -3
  170. package/dist/html/layout/block.d.ts.map +1 -1
  171. package/dist/html/layout/block.js +2937 -197
  172. package/dist/html/layout/block.js.map +1 -1
  173. package/dist/html/layout/boxes.d.ts +340 -17
  174. package/dist/html/layout/boxes.d.ts.map +1 -1
  175. package/dist/html/layout/boxes.js +1714 -182
  176. package/dist/html/layout/boxes.js.map +1 -1
  177. package/dist/html/layout/cache.d.ts +58 -0
  178. package/dist/html/layout/cache.d.ts.map +1 -0
  179. package/dist/html/layout/cache.js +224 -0
  180. package/dist/html/layout/cache.js.map +1 -0
  181. package/dist/html/layout/collapse.d.ts +45 -0
  182. package/dist/html/layout/collapse.d.ts.map +1 -0
  183. package/dist/html/layout/collapse.js +246 -0
  184. package/dist/html/layout/collapse.js.map +1 -0
  185. package/dist/html/layout/css-grid.d.ts +7 -0
  186. package/dist/html/layout/css-grid.d.ts.map +1 -0
  187. package/dist/html/layout/css-grid.js +900 -0
  188. package/dist/html/layout/css-grid.js.map +1 -0
  189. package/dist/html/layout/flex.d.ts.map +1 -1
  190. package/dist/html/layout/flex.js +1025 -89
  191. package/dist/html/layout/flex.js.map +1 -1
  192. package/dist/html/layout/floats.d.ts +45 -6
  193. package/dist/html/layout/floats.d.ts.map +1 -1
  194. package/dist/html/layout/floats.js +113 -14
  195. package/dist/html/layout/floats.js.map +1 -1
  196. package/dist/html/layout/grid-lines.d.ts +39 -0
  197. package/dist/html/layout/grid-lines.d.ts.map +1 -0
  198. package/dist/html/layout/grid-lines.js +119 -0
  199. package/dist/html/layout/grid-lines.js.map +1 -0
  200. package/dist/html/layout/grid.d.ts +53 -0
  201. package/dist/html/layout/grid.d.ts.map +1 -0
  202. package/dist/html/layout/grid.js +153 -0
  203. package/dist/html/layout/grid.js.map +1 -0
  204. package/dist/html/layout/inline.d.ts +151 -1
  205. package/dist/html/layout/inline.d.ts.map +1 -1
  206. package/dist/html/layout/inline.js +3375 -174
  207. package/dist/html/layout/inline.js.map +1 -1
  208. package/dist/html/layout/shaping.d.ts +6 -0
  209. package/dist/html/layout/shaping.d.ts.map +1 -0
  210. package/dist/html/layout/shaping.js +100 -0
  211. package/dist/html/layout/shaping.js.map +1 -0
  212. package/dist/html/layout/table.d.ts +3 -0
  213. package/dist/html/layout/table.d.ts.map +1 -1
  214. package/dist/html/layout/table.js +681 -175
  215. package/dist/html/layout/table.js.map +1 -1
  216. package/dist/html/layout/tracks.d.ts +44 -0
  217. package/dist/html/layout/tracks.d.ts.map +1 -0
  218. package/dist/html/layout/tracks.js +349 -0
  219. package/dist/html/layout/tracks.js.map +1 -0
  220. package/dist/html/node.d.ts +172 -5
  221. package/dist/html/node.d.ts.map +1 -1
  222. package/dist/html/node.js +1336 -103
  223. package/dist/html/node.js.map +1 -1
  224. package/dist/html/paint.d.ts +92 -3
  225. package/dist/html/paint.d.ts.map +1 -1
  226. package/dist/html/paint.js +3503 -141
  227. package/dist/html/paint.js.map +1 -1
  228. package/dist/html/resources.d.ts +60 -14
  229. package/dist/html/resources.d.ts.map +1 -1
  230. package/dist/html/resources.js +122 -36
  231. package/dist/html/resources.js.map +1 -1
  232. package/dist/html/surfaces.d.ts +23 -0
  233. package/dist/html/surfaces.d.ts.map +1 -0
  234. package/dist/html/surfaces.js +68 -0
  235. package/dist/html/surfaces.js.map +1 -0
  236. package/dist/html/svg.d.ts +80 -0
  237. package/dist/html/svg.d.ts.map +1 -0
  238. package/dist/html/svg.js +435 -0
  239. package/dist/html/svg.js.map +1 -0
  240. package/dist/html/url.d.ts +23 -0
  241. package/dist/html/url.d.ts.map +1 -0
  242. package/dist/html/url.js +80 -0
  243. package/dist/html/url.js.map +1 -0
  244. package/dist/index.d.ts +2 -2
  245. package/dist/index.d.ts.map +1 -1
  246. package/dist/index.js +1 -1
  247. package/dist/index.js.map +1 -1
  248. package/dist/internal/collate.d.ts +3 -0
  249. package/dist/internal/collate.d.ts.map +1 -0
  250. package/dist/internal/collate.js +11 -0
  251. package/dist/internal/collate.js.map +1 -0
  252. package/dist/{markdown → internal/markdown}/ast.d.ts +23 -0
  253. package/dist/internal/markdown/ast.d.ts.map +1 -0
  254. package/dist/internal/markdown/ast.js +22 -0
  255. package/dist/internal/markdown/ast.js.map +1 -0
  256. package/dist/internal/markdown/parse.d.ts.map +1 -0
  257. package/dist/{markdown → internal/markdown}/parse.js +221 -30
  258. package/dist/internal/markdown/parse.js.map +1 -0
  259. package/dist/internal/markdown/stringify.d.ts +4 -0
  260. package/dist/internal/markdown/stringify.d.ts.map +1 -0
  261. package/dist/internal/markdown/stringify.js +684 -0
  262. package/dist/internal/markdown/stringify.js.map +1 -0
  263. package/dist/internal/markdown/tags.d.ts.map +1 -0
  264. package/dist/internal/markdown/tags.js.map +1 -0
  265. package/dist/internal/prewarm.d.ts +18 -0
  266. package/dist/internal/prewarm.d.ts.map +1 -0
  267. package/dist/internal/prewarm.js +42 -0
  268. package/dist/internal/prewarm.js.map +1 -0
  269. package/dist/internal/scroll.d.ts +3 -2
  270. package/dist/internal/scroll.d.ts.map +1 -1
  271. package/dist/internal/scroll.js +1 -0
  272. package/dist/internal/scroll.js.map +1 -1
  273. package/dist/internal/sdf.d.ts +20 -0
  274. package/dist/internal/sdf.d.ts.map +1 -0
  275. package/dist/internal/sdf.js +216 -0
  276. package/dist/internal/sdf.js.map +1 -0
  277. package/dist/internal/splice.d.ts +12 -0
  278. package/dist/internal/splice.d.ts.map +1 -0
  279. package/dist/internal/splice.js +23 -0
  280. package/dist/internal/splice.js.map +1 -0
  281. package/dist/internal/window.d.ts +12 -0
  282. package/dist/internal/window.d.ts.map +1 -1
  283. package/dist/internal/window.js +23 -6
  284. package/dist/internal/window.js.map +1 -1
  285. package/dist/maps/anchors.d.ts +103 -0
  286. package/dist/maps/anchors.d.ts.map +1 -0
  287. package/dist/maps/anchors.js +790 -0
  288. package/dist/maps/anchors.js.map +1 -0
  289. package/dist/maps/controller.d.ts +340 -0
  290. package/dist/maps/controller.d.ts.map +1 -0
  291. package/dist/maps/controller.js +822 -0
  292. package/dist/maps/controller.js.map +1 -0
  293. package/dist/maps/gl/buckets.d.ts +99 -0
  294. package/dist/maps/gl/buckets.d.ts.map +1 -0
  295. package/dist/maps/gl/buckets.js +365 -0
  296. package/dist/maps/gl/buckets.js.map +1 -0
  297. package/dist/maps/gl/build-worker.d.ts +15 -0
  298. package/dist/maps/gl/build-worker.d.ts.map +1 -0
  299. package/dist/maps/gl/build-worker.js +44 -0
  300. package/dist/maps/gl/build-worker.js.map +1 -0
  301. package/dist/maps/gl/color.d.ts +8 -0
  302. package/dist/maps/gl/color.d.ts.map +1 -0
  303. package/dist/maps/gl/color.js +57 -0
  304. package/dist/maps/gl/color.js.map +1 -0
  305. package/dist/maps/gl/cover.d.ts +70 -0
  306. package/dist/maps/gl/cover.d.ts.map +1 -0
  307. package/dist/maps/gl/cover.js +137 -0
  308. package/dist/maps/gl/cover.js.map +1 -0
  309. package/dist/maps/gl/index.d.ts +3 -0
  310. package/dist/maps/gl/index.d.ts.map +1 -0
  311. package/dist/maps/gl/index.js +20 -0
  312. package/dist/maps/gl/index.js.map +1 -0
  313. package/dist/maps/gl/markers.d.ts +28 -0
  314. package/dist/maps/gl/markers.d.ts.map +1 -0
  315. package/dist/maps/gl/markers.js +60 -0
  316. package/dist/maps/gl/markers.js.map +1 -0
  317. package/dist/maps/gl/overlays.d.ts +68 -0
  318. package/dist/maps/gl/overlays.d.ts.map +1 -0
  319. package/dist/maps/gl/overlays.js +300 -0
  320. package/dist/maps/gl/overlays.js.map +1 -0
  321. package/dist/maps/gl/pane.d.ts +12 -0
  322. package/dist/maps/gl/pane.d.ts.map +1 -0
  323. package/dist/maps/gl/pane.js +37 -0
  324. package/dist/maps/gl/pane.js.map +1 -0
  325. package/dist/maps/gl/placement.d.ts +124 -0
  326. package/dist/maps/gl/placement.d.ts.map +1 -0
  327. package/dist/maps/gl/placement.js +642 -0
  328. package/dist/maps/gl/placement.js.map +1 -0
  329. package/dist/maps/gl/renderer.d.ts +384 -0
  330. package/dist/maps/gl/renderer.d.ts.map +1 -0
  331. package/dist/maps/gl/renderer.js +1184 -0
  332. package/dist/maps/gl/renderer.js.map +1 -0
  333. package/dist/maps/gl/shaders.d.ts +121 -0
  334. package/dist/maps/gl/shaders.d.ts.map +1 -0
  335. package/dist/maps/gl/shaders.js +453 -0
  336. package/dist/maps/gl/shaders.js.map +1 -0
  337. package/dist/maps/gl/store.d.ts +125 -0
  338. package/dist/maps/gl/store.d.ts.map +1 -0
  339. package/dist/maps/gl/store.js +512 -0
  340. package/dist/maps/gl/store.js.map +1 -0
  341. package/dist/maps/gl/text.d.ts +283 -0
  342. package/dist/maps/gl/text.d.ts.map +1 -0
  343. package/dist/maps/gl/text.js +698 -0
  344. package/dist/maps/gl/text.js.map +1 -0
  345. package/dist/maps/gl/view.d.ts +345 -0
  346. package/dist/maps/gl/view.d.ts.map +1 -0
  347. package/dist/maps/gl/view.js +1209 -0
  348. package/dist/maps/gl/view.js.map +1 -0
  349. package/dist/maps/icons.d.ts +32 -0
  350. package/dist/maps/icons.d.ts.map +1 -0
  351. package/dist/maps/icons.js +151 -0
  352. package/dist/maps/icons.js.map +1 -0
  353. package/dist/maps/index.d.ts +3 -1
  354. package/dist/maps/index.d.ts.map +1 -1
  355. package/dist/maps/index.js +218 -52
  356. package/dist/maps/index.js.map +1 -1
  357. package/dist/maps/labels.d.ts +91 -18
  358. package/dist/maps/labels.d.ts.map +1 -1
  359. package/dist/maps/labels.js +376 -140
  360. package/dist/maps/labels.js.map +1 -1
  361. package/dist/maps/node.d.ts +179 -56
  362. package/dist/maps/node.d.ts.map +1 -1
  363. package/dist/maps/node.js +663 -537
  364. package/dist/maps/node.js.map +1 -1
  365. package/dist/maps/overlay.d.ts +72 -9
  366. package/dist/maps/overlay.d.ts.map +1 -1
  367. package/dist/maps/overlay.js +108 -28
  368. package/dist/maps/overlay.js.map +1 -1
  369. package/dist/maps/paint.d.ts +3 -0
  370. package/dist/maps/paint.d.ts.map +1 -1
  371. package/dist/maps/paint.js.map +1 -1
  372. package/dist/maps/proj.d.ts +62 -0
  373. package/dist/maps/proj.d.ts.map +1 -1
  374. package/dist/maps/proj.js +101 -0
  375. package/dist/maps/proj.js.map +1 -1
  376. package/dist/maps/renderer.d.ts +69 -0
  377. package/dist/maps/renderer.d.ts.map +1 -0
  378. package/dist/maps/renderer.js +66 -0
  379. package/dist/maps/renderer.js.map +1 -0
  380. package/dist/maps/sources.d.ts +30 -6
  381. package/dist/maps/sources.d.ts.map +1 -1
  382. package/dist/maps/sources.js +22 -3
  383. package/dist/maps/sources.js.map +1 -1
  384. package/dist/maps/style.d.ts +35 -0
  385. package/dist/maps/style.d.ts.map +1 -1
  386. package/dist/maps/style.js.map +1 -1
  387. package/dist/maps/styles.d.ts +12 -0
  388. package/dist/maps/styles.d.ts.map +1 -1
  389. package/dist/maps/styles.js +120 -6
  390. package/dist/maps/styles.js.map +1 -1
  391. package/dist/maps/theme.d.ts +19 -0
  392. package/dist/maps/theme.d.ts.map +1 -0
  393. package/dist/maps/theme.js +44 -0
  394. package/dist/maps/theme.js.map +1 -0
  395. package/dist/maps/tiles.d.ts +147 -27
  396. package/dist/maps/tiles.d.ts.map +1 -1
  397. package/dist/maps/tiles.js +221 -54
  398. package/dist/maps/tiles.js.map +1 -1
  399. package/dist/maps/types.d.ts +213 -21
  400. package/dist/maps/types.d.ts.map +1 -1
  401. package/dist/markdown/expressions.d.ts +1 -1
  402. package/dist/markdown/expressions.d.ts.map +1 -1
  403. package/dist/markdown/expressions.js.map +1 -1
  404. package/dist/markdown/index.d.ts +7 -6
  405. package/dist/markdown/index.d.ts.map +1 -1
  406. package/dist/markdown/index.js +121 -50
  407. package/dist/markdown/index.js.map +1 -1
  408. package/dist/markdown/spans.d.ts +1 -1
  409. package/dist/markdown/spans.d.ts.map +1 -1
  410. package/dist/markdown/spans.js +6 -0
  411. package/dist/markdown/spans.js.map +1 -1
  412. package/dist/media-player/index.d.ts +11 -3
  413. package/dist/media-player/index.d.ts.map +1 -1
  414. package/dist/media-player/index.js +13 -2
  415. package/dist/media-player/index.js.map +1 -1
  416. package/dist/qml/containers.d.ts.map +1 -1
  417. package/dist/qml/containers.js +6 -1
  418. package/dist/qml/containers.js.map +1 -1
  419. package/dist/qml/interaction.d.ts.map +1 -1
  420. package/dist/qml/interaction.js +38 -5
  421. package/dist/qml/interaction.js.map +1 -1
  422. package/dist/qml/layouts.d.ts.map +1 -1
  423. package/dist/qml/layouts.js +21 -6
  424. package/dist/qml/layouts.js.map +1 -1
  425. package/dist/qml/qtquick.d.ts.map +1 -1
  426. package/dist/qml/qtquick.js +9 -2
  427. package/dist/qml/qtquick.js.map +1 -1
  428. package/dist/qml/react.d.ts.map +1 -1
  429. package/dist/qml/react.js +9 -7
  430. package/dist/qml/react.js.map +1 -1
  431. package/dist/reorder/clock.d.ts +7 -0
  432. package/dist/reorder/clock.d.ts.map +1 -0
  433. package/dist/reorder/clock.js +26 -0
  434. package/dist/reorder/clock.js.map +1 -0
  435. package/dist/reorder/index.d.ts +25 -3
  436. package/dist/reorder/index.d.ts.map +1 -1
  437. package/dist/reorder/index.js +64 -19
  438. package/dist/reorder/index.js.map +1 -1
  439. package/dist/rich-text-editor/clipboard.d.ts +23 -0
  440. package/dist/rich-text-editor/clipboard.d.ts.map +1 -0
  441. package/dist/rich-text-editor/clipboard.js +307 -0
  442. package/dist/rich-text-editor/clipboard.js.map +1 -0
  443. package/dist/rich-text-editor/collab.d.ts +32 -0
  444. package/dist/rich-text-editor/collab.d.ts.map +1 -0
  445. package/dist/rich-text-editor/collab.js +55 -0
  446. package/dist/rich-text-editor/collab.js.map +1 -0
  447. package/dist/rich-text-editor/commands.d.ts +50 -0
  448. package/dist/rich-text-editor/commands.d.ts.map +1 -0
  449. package/dist/rich-text-editor/commands.js +376 -0
  450. package/dist/rich-text-editor/commands.js.map +1 -0
  451. package/dist/rich-text-editor/drag.d.ts +68 -0
  452. package/dist/rich-text-editor/drag.d.ts.map +1 -0
  453. package/dist/rich-text-editor/drag.js +148 -0
  454. package/dist/rich-text-editor/drag.js.map +1 -0
  455. package/dist/rich-text-editor/html.d.ts +145 -0
  456. package/dist/rich-text-editor/html.d.ts.map +1 -0
  457. package/dist/rich-text-editor/html.js +516 -0
  458. package/dist/rich-text-editor/html.js.map +1 -0
  459. package/dist/rich-text-editor/index.d.ts +252 -0
  460. package/dist/rich-text-editor/index.d.ts.map +1 -0
  461. package/dist/rich-text-editor/index.js +856 -0
  462. package/dist/rich-text-editor/index.js.map +1 -0
  463. package/dist/rich-text-editor/inline.d.ts +94 -0
  464. package/dist/rich-text-editor/inline.d.ts.map +1 -0
  465. package/dist/rich-text-editor/inline.js +252 -0
  466. package/dist/rich-text-editor/inline.js.map +1 -0
  467. package/dist/rich-text-editor/keymap.d.ts +71 -0
  468. package/dist/rich-text-editor/keymap.d.ts.map +1 -0
  469. package/dist/rich-text-editor/keymap.js +394 -0
  470. package/dist/rich-text-editor/keymap.js.map +1 -0
  471. package/dist/rich-text-editor/keys.d.ts +40 -0
  472. package/dist/rich-text-editor/keys.d.ts.map +1 -0
  473. package/dist/rich-text-editor/keys.js +202 -0
  474. package/dist/rich-text-editor/keys.js.map +1 -0
  475. package/dist/rich-text-editor/look.d.ts +71 -0
  476. package/dist/rich-text-editor/look.d.ts.map +1 -0
  477. package/dist/rich-text-editor/look.js +342 -0
  478. package/dist/rich-text-editor/look.js.map +1 -0
  479. package/dist/rich-text-editor/markdown.d.ts +18 -0
  480. package/dist/rich-text-editor/markdown.d.ts.map +1 -0
  481. package/dist/rich-text-editor/markdown.js +496 -0
  482. package/dist/rich-text-editor/markdown.js.map +1 -0
  483. package/dist/rich-text-editor/marks.d.ts +9 -0
  484. package/dist/rich-text-editor/marks.d.ts.map +1 -0
  485. package/dist/rich-text-editor/marks.js +83 -0
  486. package/dist/rich-text-editor/marks.js.map +1 -0
  487. package/dist/rich-text-editor/nodes.d.ts +135 -0
  488. package/dist/rich-text-editor/nodes.d.ts.map +1 -0
  489. package/dist/rich-text-editor/nodes.js +397 -0
  490. package/dist/rich-text-editor/nodes.js.map +1 -0
  491. package/dist/rich-text-editor/render.d.ts +68 -0
  492. package/dist/rich-text-editor/render.d.ts.map +1 -0
  493. package/dist/rich-text-editor/render.js +518 -0
  494. package/dist/rich-text-editor/render.js.map +1 -0
  495. package/dist/rich-text-editor/schema.d.ts +16 -0
  496. package/dist/rich-text-editor/schema.d.ts.map +1 -0
  497. package/dist/rich-text-editor/schema.js +386 -0
  498. package/dist/rich-text-editor/schema.js.map +1 -0
  499. package/dist/rich-text-editor/store.d.ts +11 -0
  500. package/dist/rich-text-editor/store.d.ts.map +1 -0
  501. package/dist/rich-text-editor/store.js +43 -0
  502. package/dist/rich-text-editor/store.js.map +1 -0
  503. package/dist/rich-text-editor/suggest.d.ts +127 -0
  504. package/dist/rich-text-editor/suggest.d.ts.map +1 -0
  505. package/dist/rich-text-editor/suggest.js +0 -0
  506. package/dist/rich-text-editor/suggest.js.map +1 -0
  507. package/dist/rich-text-editor/tables.d.ts +41 -0
  508. package/dist/rich-text-editor/tables.d.ts.map +1 -0
  509. package/dist/rich-text-editor/tables.js +204 -0
  510. package/dist/rich-text-editor/tables.js.map +1 -0
  511. package/dist/rich-text-editor/toolbar.d.ts +58 -0
  512. package/dist/rich-text-editor/toolbar.d.ts.map +1 -0
  513. package/dist/rich-text-editor/toolbar.js +548 -0
  514. package/dist/rich-text-editor/toolbar.js.map +1 -0
  515. package/dist/rich-text-editor/view.d.ts +368 -0
  516. package/dist/rich-text-editor/view.d.ts.map +1 -0
  517. package/dist/rich-text-editor/view.js +1968 -0
  518. package/dist/rich-text-editor/view.js.map +1 -0
  519. package/dist/rich-text-editor/virtual.d.ts +54 -0
  520. package/dist/rich-text-editor/virtual.d.ts.map +1 -0
  521. package/dist/rich-text-editor/virtual.js +279 -0
  522. package/dist/rich-text-editor/virtual.js.map +1 -0
  523. package/dist/richtext/node.d.ts +71 -4
  524. package/dist/richtext/node.d.ts.map +1 -1
  525. package/dist/richtext/node.js +233 -28
  526. package/dist/richtext/node.js.map +1 -1
  527. package/dist/richtext/runs.d.ts +13 -8
  528. package/dist/richtext/runs.d.ts.map +1 -1
  529. package/dist/richtext/runs.js +18 -8
  530. package/dist/richtext/runs.js.map +1 -1
  531. package/dist/table/index.d.ts.map +1 -1
  532. package/dist/table/index.js +23 -0
  533. package/dist/table/index.js.map +1 -1
  534. package/dist/table/rows.d.ts +3 -2
  535. package/dist/table/rows.d.ts.map +1 -1
  536. package/dist/table/rows.js +20 -6
  537. package/dist/table/rows.js.map +1 -1
  538. package/dist/terminal/backends.d.ts +4 -1
  539. package/dist/terminal/backends.d.ts.map +1 -1
  540. package/dist/terminal/backends.js.map +1 -1
  541. package/dist/terminal/index.d.ts +18 -7
  542. package/dist/terminal/index.d.ts.map +1 -1
  543. package/dist/terminal/index.js +32 -11
  544. package/dist/terminal/index.js.map +1 -1
  545. package/dist/terminal/vt/pty.d.ts +13 -2
  546. package/dist/terminal/vt/pty.d.ts.map +1 -1
  547. package/dist/terminal/vt/pty.js +18 -3
  548. package/dist/terminal/vt/pty.js.map +1 -1
  549. package/dist/terminal-output/index.d.ts.map +1 -1
  550. package/dist/terminal-output/index.js +6 -1
  551. package/dist/terminal-output/index.js.map +1 -1
  552. package/dist/three/canvas.d.ts.map +1 -1
  553. package/dist/three/canvas.js +85 -7
  554. package/dist/three/canvas.js.map +1 -1
  555. package/dist/three/events.d.ts +22 -4
  556. package/dist/three/events.d.ts.map +1 -1
  557. package/dist/three/events.js +34 -4
  558. package/dist/three/events.js.map +1 -1
  559. package/dist/tree/index.d.ts.map +1 -1
  560. package/dist/tree/index.js +17 -0
  561. package/dist/tree/index.js.map +1 -1
  562. package/package.json +59 -31
  563. package/src/charts/node.ts +68 -28
  564. package/src/charts/render.ts +120 -30
  565. package/src/code/index.ts +3 -1
  566. package/src/code-editor/completion.ts +3 -2
  567. package/src/code-editor/index.ts +19 -0
  568. package/src/code-editor/node.ts +1574 -184
  569. package/src/code-language/languages/glsl.ts +12 -2
  570. package/src/code-language/languages/javascript.ts +21 -4
  571. package/src/code-language/languages/json.ts +12 -2
  572. package/src/code-language/languages/shell.ts +12 -2
  573. package/src/code-language/languages/sql.ts +22 -2
  574. package/src/code-language/stream.ts +257 -17
  575. package/src/code-language/types.ts +5 -4
  576. package/src/codeblock/index.ts +20 -3
  577. package/src/embed/client.ts +102 -8
  578. package/src/embed/index.ts +2 -0
  579. package/src/flow/draw.ts +167 -41
  580. package/src/flow/gl/color.ts +85 -0
  581. package/src/flow/gl/index.ts +342 -0
  582. package/src/flow/gl/pack.ts +585 -0
  583. package/src/flow/gl/renderer.ts +679 -0
  584. package/src/flow/gl/shaders.ts +371 -0
  585. package/src/flow/gl/text.ts +1295 -0
  586. package/src/flow/index.ts +794 -67
  587. package/src/flow/node.ts +2496 -1256
  588. package/src/flow/paint.ts +511 -0
  589. package/src/flow/paths.ts +80 -15
  590. package/src/flow/scene.ts +2199 -0
  591. package/src/flow/types.ts +113 -1
  592. package/src/html/controls.ts +73 -2
  593. package/src/html/css/calc.ts +385 -0
  594. package/src/html/css/cascade.ts +1403 -62
  595. package/src/html/css/color.ts +755 -0
  596. package/src/html/css/content.ts +417 -0
  597. package/src/html/css/counter-styles.ts +973 -0
  598. package/src/html/css/decode.ts +130 -0
  599. package/src/html/css/parse.ts +1514 -160
  600. package/src/html/css/style.ts +4102 -222
  601. package/src/html/css/ua.ts +58 -12
  602. package/src/html/css/values.ts +150 -50
  603. package/src/html/css/vars.ts +348 -0
  604. package/src/html/dom.ts +284 -17
  605. package/src/html/fonts.ts +641 -0
  606. package/src/html/gif.ts +233 -0
  607. package/src/html/index.ts +180 -20
  608. package/src/html/layout/block.ts +3456 -230
  609. package/src/html/layout/boxes.ts +2100 -190
  610. package/src/html/layout/cache.ts +289 -0
  611. package/src/html/layout/collapse.ts +317 -0
  612. package/src/html/layout/css-grid.ts +1063 -0
  613. package/src/html/layout/flex.ts +1115 -106
  614. package/src/html/layout/floats.ts +128 -14
  615. package/src/html/layout/grid-lines.ts +141 -0
  616. package/src/html/layout/grid.ts +181 -0
  617. package/src/html/layout/inline.ts +3943 -192
  618. package/src/html/layout/shaping.ts +140 -0
  619. package/src/html/layout/table.ts +696 -186
  620. package/src/html/layout/tracks.ts +437 -0
  621. package/src/html/node.ts +1486 -121
  622. package/src/html/paint.ts +4293 -169
  623. package/src/html/resources.ts +161 -50
  624. package/src/html/surfaces.ts +81 -0
  625. package/src/html/svg.ts +493 -0
  626. package/src/html/url.ts +86 -0
  627. package/src/index.ts +4 -0
  628. package/src/internal/collate.ts +12 -0
  629. package/src/{markdown → internal/markdown}/ast.ts +35 -7
  630. package/src/{markdown → internal/markdown}/parse.ts +288 -35
  631. package/src/internal/markdown/stringify.ts +772 -0
  632. package/src/internal/prewarm.ts +45 -0
  633. package/src/internal/scroll.ts +5 -3
  634. package/src/internal/sdf.ts +227 -0
  635. package/src/internal/splice.ts +25 -0
  636. package/src/internal/window.ts +36 -5
  637. package/src/maps/anchors.ts +913 -0
  638. package/src/maps/controller.ts +1084 -0
  639. package/src/maps/gl/buckets.ts +461 -0
  640. package/src/maps/gl/build-worker.ts +66 -0
  641. package/src/maps/gl/color.ts +62 -0
  642. package/src/maps/gl/cover.ts +205 -0
  643. package/src/maps/gl/index.ts +23 -0
  644. package/src/maps/gl/markers.ts +83 -0
  645. package/src/maps/gl/overlays.ts +379 -0
  646. package/src/maps/gl/pane.ts +42 -0
  647. package/src/maps/gl/placement.ts +968 -0
  648. package/src/maps/gl/renderer.ts +1660 -0
  649. package/src/maps/gl/shaders.ts +489 -0
  650. package/src/maps/gl/store.ts +615 -0
  651. package/src/maps/gl/text.ts +868 -0
  652. package/src/maps/gl/view.ts +1489 -0
  653. package/src/maps/icons.ts +183 -0
  654. package/src/maps/index.ts +274 -81
  655. package/src/maps/labels.ts +457 -144
  656. package/src/maps/node.ts +832 -665
  657. package/src/maps/overlay.ts +148 -43
  658. package/src/maps/paint.ts +3 -0
  659. package/src/maps/proj.ts +118 -0
  660. package/src/maps/renderer.ts +155 -0
  661. package/src/maps/sources.ts +43 -6
  662. package/src/maps/style.ts +32 -0
  663. package/src/maps/styles.ts +215 -4
  664. package/src/maps/theme.ts +51 -0
  665. package/src/maps/tiles.ts +253 -62
  666. package/src/maps/types.ts +213 -21
  667. package/src/markdown/expressions.ts +5 -1
  668. package/src/markdown/index.ts +163 -78
  669. package/src/markdown/spans.ts +6 -1
  670. package/src/media-player/index.ts +18 -4
  671. package/src/qml/containers.tsx +6 -1
  672. package/src/qml/interaction.tsx +42 -5
  673. package/src/qml/layouts.tsx +21 -6
  674. package/src/qml/qtquick.tsx +9 -2
  675. package/src/qml/react.tsx +7 -5
  676. package/src/reorder/clock.ts +27 -0
  677. package/src/reorder/index.ts +100 -27
  678. package/src/rich-text-editor/clipboard.ts +439 -0
  679. package/src/rich-text-editor/collab.ts +91 -0
  680. package/src/rich-text-editor/commands.ts +448 -0
  681. package/src/rich-text-editor/dom-globals.d.ts +23 -0
  682. package/src/rich-text-editor/drag.ts +211 -0
  683. package/src/rich-text-editor/html.ts +619 -0
  684. package/src/rich-text-editor/index.ts +1364 -0
  685. package/src/rich-text-editor/inline.ts +345 -0
  686. package/src/rich-text-editor/keymap.ts +510 -0
  687. package/src/rich-text-editor/keys.ts +228 -0
  688. package/src/rich-text-editor/look.ts +427 -0
  689. package/src/rich-text-editor/markdown.ts +653 -0
  690. package/src/rich-text-editor/marks.ts +101 -0
  691. package/src/rich-text-editor/nodes.ts +497 -0
  692. package/src/rich-text-editor/render.ts +837 -0
  693. package/src/rich-text-editor/schema.ts +431 -0
  694. package/src/rich-text-editor/store.ts +39 -0
  695. package/src/rich-text-editor/suggest.ts +597 -0
  696. package/src/rich-text-editor/tables.ts +272 -0
  697. package/src/rich-text-editor/toolbar.ts +724 -0
  698. package/src/rich-text-editor/view.ts +2287 -0
  699. package/src/rich-text-editor/virtual.ts +372 -0
  700. package/src/richtext/node.ts +294 -44
  701. package/src/richtext/runs.ts +23 -12
  702. package/src/table/index.ts +29 -0
  703. package/src/table/rows.ts +18 -8
  704. package/src/terminal/backends.ts +4 -1
  705. package/src/terminal/index.ts +47 -15
  706. package/src/terminal/vt/pty.ts +16 -2
  707. package/src/terminal-output/index.ts +6 -1
  708. package/src/three/canvas.ts +102 -8
  709. package/src/three/events.ts +49 -9
  710. package/src/tree/index.ts +19 -0
  711. package/dist/markdown/ast.d.ts.map +0 -1
  712. package/dist/markdown/ast.js +0 -17
  713. package/dist/markdown/ast.js.map +0 -1
  714. package/dist/markdown/parse.d.ts.map +0 -1
  715. package/dist/markdown/parse.js.map +0 -1
  716. package/dist/markdown/tags.d.ts.map +0 -1
  717. package/dist/markdown/tags.js.map +0 -1
  718. /package/dist/{markdown → internal/markdown}/parse.d.ts +0 -0
  719. /package/dist/{markdown → internal/markdown}/tags.d.ts +0 -0
  720. /package/dist/{markdown → internal/markdown}/tags.js +0 -0
  721. /package/src/{markdown → internal/markdown}/tags.ts +0 -0
@@ -19,9 +19,12 @@ import { compile } from 'css-select';
19
19
  import * as DomUtils from 'domutils';
20
20
  import { Element as DomElement, isTag } from 'domhandler';
21
21
  import { attr, tagOf } from '../dom.js';
22
- import { mediaMatches } from './parse.js';
23
- import { applyDeclaration, blockify, inherit, initialStyle } from './style.js';
22
+ import { svgSizeHint } from '../svg.js';
23
+ import { asciiLower, escapeEnd, mediaMatches, readIdent, startsIdent, } from './parse.js';
24
+ import { applyDeclaration, blockify, settleContentVisibility, settleOverflow, settleClamp, copyStyle, decorate, inherit, initialOne, initialStyle, isInherited, } from './style.js';
24
25
  import { parseDeclarations } from './parse.js';
26
+ import { CounterStyles, counterStyleRule } from './counter-styles.js';
27
+ import { customProperties, substituteIn } from './vars.js';
25
28
  /** Where a declaration came from. Higher wins before specificity is asked. */
26
29
  var Origin;
27
30
  (function (Origin) {
@@ -32,6 +35,20 @@ var Origin;
32
35
  Origin[Origin["AuthorImportant"] = 4] = "AuthorImportant";
33
36
  Origin[Origin["InlineImportant"] = 5] = "InlineImportant";
34
37
  })(Origin || (Origin = {}));
38
+ /**
39
+ * What makes a selector's match depend on more than the element's own tag and
40
+ * attributes and its ancestors' — its siblings, where it sits among them,
41
+ * what it contains, or where the document is scrolled to. Two elements that
42
+ * look alike from the root down can still differ under a rule with one of
43
+ * these, so an element such a rule could reach does not share its style
44
+ * (`Cascade.sharedStyleFor`). css-select spells some of them under other
45
+ * names, and those count too: `:checked` and `:selected` read which option
46
+ * comes first, `:disabled` and `:enabled` which legend does, and `:parent`
47
+ * and `:contains()` the element's contents. Over-broad on purpose: a `+` or
48
+ * `~` inside an attribute value, or the `~=` operator, costs sharing and
49
+ * nothing else.
50
+ */
51
+ const UNSHAREABLE = /[+~]|:(?:first|last|only)-(?:child|of-type)|:nth-|:empty|:blank|:has\(|:focus-within|:target|:scope|:(?:checked|selected|disabled|enabled|parent)\b|:i?contains\(/;
35
52
  /**
36
53
  * Rules bucketed by the key of their rightmost compound selector. An element
37
54
  * only ever tries `id`, its classes, its tag and the universal bucket.
@@ -44,12 +61,64 @@ class RuleIndex {
44
61
  /** Whether any rule in here is pointer-sensitive, so the renderer knows
45
62
  * whether a pointer move can change the cascade at all. */
46
63
  hoverSensitive = false;
64
+ /** The buckets holding a rule an element cannot share its style under
65
+ * (`UNSHAREABLE`): the ids, classes and tags whose elements compute
66
+ * their own, and whether the universal bucket makes every element do so. */
67
+ ownStyleIds = new Set();
68
+ ownStyleClasses = new Set();
69
+ ownStyleTags = new Set();
70
+ ownStyleEverywhere = false;
71
+ /** How many rules are in here, so an empty index costs one comparison. */
72
+ size = 0;
73
+ _nextId = 0;
74
+ /**
75
+ * Whether a bucket here could hold a rule for `el`, by its tag, id and
76
+ * classes and without matching anything: an index of a rule or two is
77
+ * asked of every element — the user-agent sheet's `q::before` and
78
+ * `q::after` made every element of a document split its `class` twice —
79
+ * and almost none of them has a rule in it.
80
+ */
81
+ reaches(el) {
82
+ if (this.universal.length || this.byTag.has(tagOf(el)))
83
+ return true;
84
+ if (this.byId.size) {
85
+ const id = attr(el, 'id');
86
+ if (id && this.byId.has(id))
87
+ return true;
88
+ }
89
+ if (this.byClass.size) {
90
+ const className = attr(el, 'class');
91
+ if (className) {
92
+ for (const name of className.split(/\s+/)) {
93
+ if (name && this.byClass.has(name))
94
+ return true;
95
+ }
96
+ }
97
+ }
98
+ return false;
99
+ }
47
100
  add(rule) {
48
- const indexed = { rule, match: null, compiled: false };
101
+ this.size += 1;
102
+ const indexed = {
103
+ rule,
104
+ match: null,
105
+ compiled: false,
106
+ id: this._nextId++,
107
+ };
49
108
  if (rule.selector.includes(':hover') || rule.selector.includes(':active')) {
50
109
  this.hoverSensitive = true;
51
110
  }
52
111
  const key = rightmostKey(rule.selector);
112
+ if (UNSHAREABLE.test(rule.selector)) {
113
+ if (key.kind === 'id')
114
+ this.ownStyleIds.add(key.name);
115
+ else if (key.kind === 'class')
116
+ this.ownStyleClasses.add(key.name);
117
+ else if (key.kind === 'tag')
118
+ this.ownStyleTags.add(key.name);
119
+ else
120
+ this.ownStyleEverywhere = true;
121
+ }
53
122
  const bucket = key.kind === 'id'
54
123
  ? mapBucket(this.byId, key.name)
55
124
  : key.kind === 'class'
@@ -60,6 +129,200 @@ class RuleIndex {
60
129
  bucket.push(indexed);
61
130
  }
62
131
  }
132
+ /** A selector's trailing `::before`, `::after`, `::first-letter`,
133
+ * `::first-line` or `::marker`, or CSS 2's single-colon spelling of any of
134
+ * its four. */
135
+ const PSEUDO_ELEMENT = /::?(before|after|first-letter|first-line)$|::marker$/i;
136
+ /**
137
+ * A rule for a pseudo-element, as the pseudo-element it styles and a rule
138
+ * for the element it hangs off, which is what gets matched. The specificity
139
+ * is the whole selector's, the pseudo-element counted in. `p::before`
140
+ * matches `p`; `p ::before` and `p > ::before` have nothing left of their
141
+ * last compound and match any child, `p *` and `p > *`.
142
+ */
143
+ function splitPseudoElement(rule) {
144
+ const m = PSEUDO_ELEMENT.exec(rule.selector);
145
+ if (!m)
146
+ return null;
147
+ const head = rule.selector.slice(0, m.index);
148
+ const trimmed = head.trimEnd();
149
+ const selector = !trimmed
150
+ ? '*'
151
+ : head !== trimmed || /[>+~]$/.test(trimmed)
152
+ ? `${trimmed} *`
153
+ : trimmed;
154
+ return {
155
+ which: (m[1] ?? 'marker').toLowerCase(),
156
+ rule: { ...rule, selector },
157
+ };
158
+ }
159
+ /**
160
+ * The compounds of a selector that test `:hover`, each without it (and
161
+ * without an `:active` beside it), and whether one is followed by a sibling
162
+ * combinator, which reaches the element's later siblings. `nested` where a
163
+ * `:hover` sits inside a functional pseudo-class — `:not(:hover)`,
164
+ * `:is(:hover)` — and reaches elements no compound names.
165
+ *
166
+ * A `:hover` in a compound's `:has()` is the one exception, since what it
167
+ * reaches is known: the compound, without its `:has()`, is an ancestor of
168
+ * the element the pointer is over — or an earlier sibling of it or of an
169
+ * ancestor, where the argument starts at a sibling (Selectors 4, 4.5). So
170
+ * it is given as an anchor (`has`) rather than making the rule `nested`.
171
+ *
172
+ * `:active` is not the pointer's here: nothing sets it (`setPointer` is
173
+ * handed none), so a selector that tests only it never changes as the
174
+ * pointer moves — Wikipedia's buttons' `:focus:not(:active)` among them.
175
+ * A press that sets it would have to be counted here too.
176
+ */
177
+ export function pointerCompounds(selector) {
178
+ const out = {
179
+ compounds: [],
180
+ siblings: false,
181
+ nested: false,
182
+ has: [],
183
+ };
184
+ // the compounds at the top level, each with the combinator after it
185
+ const parts = [];
186
+ let start = 0;
187
+ let depth = 0;
188
+ let quote = '';
189
+ const split = (end, next) => {
190
+ const text = selector.slice(start, end).trim();
191
+ if (text)
192
+ parts.push({ text, next });
193
+ else if (parts.length && next !== ' ')
194
+ parts[parts.length - 1].next = next;
195
+ };
196
+ for (let i = 0; i < selector.length; i += 1) {
197
+ const c = selector[i];
198
+ if (quote) {
199
+ if (c === quote && selector[i - 1] !== '\\')
200
+ quote = '';
201
+ continue;
202
+ }
203
+ if (c === '\\')
204
+ i = escapeEnd(selector, i) - 1;
205
+ else if (c === '"' || c === "'")
206
+ quote = c;
207
+ else if (c === '(' || c === '[')
208
+ depth += 1;
209
+ else if (c === ')' || c === ']')
210
+ depth = Math.max(0, depth - 1);
211
+ else if (depth === 0 && /[\s>+~]/.test(c)) {
212
+ split(i, c === '+' || c === '~' || c === '>' ? c : ' ');
213
+ start = i + 1;
214
+ }
215
+ }
216
+ split(selector.length, '');
217
+ for (const { text, next } of parts) {
218
+ let bare = '';
219
+ let pointer = false;
220
+ depth = 0;
221
+ quote = '';
222
+ /** Where a top-level `:has(` starts in `bare`, and its argument in
223
+ * `text`, while one is open. */
224
+ let hasAt = -1;
225
+ let argAt = -1;
226
+ let hasPointer = false;
227
+ let anchored = false;
228
+ const args = [];
229
+ for (let i = 0; i < text.length; i += 1) {
230
+ const c = text[i];
231
+ if (quote) {
232
+ if (c === quote && text[i - 1] !== '\\')
233
+ quote = '';
234
+ bare += c;
235
+ continue;
236
+ }
237
+ if (c === '\\') {
238
+ const end = escapeEnd(text, i);
239
+ bare += text.slice(i, end);
240
+ i = end - 1;
241
+ continue;
242
+ }
243
+ if (c === '"' || c === "'")
244
+ quote = c;
245
+ else if (c === '(' || c === '[') {
246
+ if (depth === 0 && c === '(' && /:has$/i.test(bare)) {
247
+ hasAt = bare.length - 4;
248
+ argAt = i + 1;
249
+ hasPointer = false;
250
+ }
251
+ depth += 1;
252
+ }
253
+ else if (c === ')' || c === ']') {
254
+ depth = Math.max(0, depth - 1);
255
+ if (depth === 0 && hasAt >= 0 && c === ')') {
256
+ // the compound is kept without it: its argument is what the
257
+ // pointer changes
258
+ if (hasPointer) {
259
+ anchored = true;
260
+ args.push(text.slice(argAt, i));
261
+ bare = bare.slice(0, hasAt);
262
+ }
263
+ else
264
+ bare += c;
265
+ hasAt = -1;
266
+ continue;
267
+ }
268
+ }
269
+ else if (c === ':' && text[i + 1] !== ':') {
270
+ const m = POINTER_PSEUDO_AT.exec(text.slice(i));
271
+ if (m) {
272
+ const hover = m[0].length === 6;
273
+ if (depth > 0) {
274
+ // whatever holds it in the argument, the element it tests is
275
+ // in the anchor's subtree or a later sibling's
276
+ if (hover && hasAt >= 0)
277
+ hasPointer = true;
278
+ else if (hover)
279
+ out.nested = true;
280
+ }
281
+ else {
282
+ if (hover)
283
+ pointer = true;
284
+ i += m[0].length - 1;
285
+ continue;
286
+ }
287
+ }
288
+ }
289
+ bare += c;
290
+ }
291
+ if (anchored) {
292
+ out.has.push({
293
+ anchor: bare.trim() || '*',
294
+ siblings: args.some((arg) => arg.split(',').some((one) => /^\s*[+~]/.test(one))),
295
+ });
296
+ }
297
+ if (!pointer)
298
+ continue;
299
+ out.compounds.push(bare.trim() || '*');
300
+ if (next === '+' || next === '~')
301
+ out.siblings = true;
302
+ }
303
+ return out;
304
+ }
305
+ /** `:hover` or `:active` at the start of a string, and nothing longer. */
306
+ const POINTER_PSEUDO_AT = /^:(?:hover|active)(?![\w-])/i;
307
+ /** `:hover` or `:active` anywhere in a selector. */
308
+ const POINTER_PSEUDO = /:(?:hover|active)(?![\w-])/i;
309
+ /**
310
+ * A selector compiled to a matcher over this adapter. css-select keeps the
311
+ * answers of a `:has()` above the subject, or of the ancestors a
312
+ * descendant combinator tried under one, for as long as the matcher lives
313
+ * (`cacheResults`) — which is the cascade's life, and a pointer move is no
314
+ * new cascade. So a selector that tests the pointer keeps none: with them,
315
+ * `#box:has(a:hover) .m` answered what it did before the first move, for
316
+ * good.
317
+ */
318
+ function compileSelector(selector, adapter) {
319
+ return compile(noEmptyWords(selector), {
320
+ adapter,
321
+ xmlMode: false,
322
+ pseudos: PSEUDOS,
323
+ cacheResults: !POINTER_PSEUDO.test(selector),
324
+ });
325
+ }
63
326
  function mapBucket(map, key) {
64
327
  let bucket = map.get(key);
65
328
  if (!bucket) {
@@ -87,14 +350,26 @@ function rightmostKey(selector) {
87
350
  quote = '';
88
351
  continue;
89
352
  }
90
- if (c === '"' || c === "'")
353
+ // an escaped character is part of a name, whatever it is — and a hex
354
+ // escape takes the space after it: `.c\6c ass` is the class `class`
355
+ if (c === '\\')
356
+ i = escapeEnd(selector, i) - 1;
357
+ else if (c === '"' || c === "'")
91
358
  quote = c;
92
359
  else if (c === '(' || c === '[')
93
360
  depth += 1;
94
361
  else if (c === ')' || c === ']')
95
362
  depth = Math.max(0, depth - 1);
96
363
  else if (depth === 0 &&
97
- (c === ' ' || c === '>' || c === '+' || c === '~')) {
364
+ (c === ' ' ||
365
+ c === '>' ||
366
+ c === '+' ||
367
+ c === '~' ||
368
+ // CSS's other white space: `div\fp` is a descendant too
369
+ c === '\t' ||
370
+ c === '\n' ||
371
+ c === '\r' ||
372
+ c === '\f')) {
98
373
  start = i + 1;
99
374
  }
100
375
  }
@@ -105,31 +380,29 @@ function rightmostKey(selector) {
105
380
  let i = 0;
106
381
  while (i < compound.length) {
107
382
  const c = compound[i];
108
- if (c === '#') {
109
- const end = identEnd(compound, i + 1);
110
- if (!id)
111
- id = compound.slice(i + 1, end);
112
- i = end;
113
- }
114
- else if (c === '.') {
115
- const end = identEnd(compound, i + 1);
116
- if (!cls)
117
- cls = compound.slice(i + 1, end);
118
- i = end;
383
+ // Names as the matcher reads them, escapes resolved: `.md\:flex` is
384
+ // the class `md:flex`, and filed under its first half it never matched.
385
+ if (c === '#' || c === '.') {
386
+ const name = readIdent(compound, i + 1);
387
+ if (c === '#' && !id)
388
+ id = name.value;
389
+ if (c === '.' && !cls)
390
+ cls = name.value;
391
+ i = Math.max(name.end, i + 1);
119
392
  }
120
393
  else if (c === '[') {
121
394
  i = balancedEnd(compound, i, '[', ']');
122
395
  }
123
396
  else if (c === ':') {
124
397
  const skip = compound[i + 1] === ':' ? 2 : 1;
125
- const end = identEnd(compound, i + skip);
398
+ const end = Math.max(readIdent(compound, i + skip).end, i + skip);
126
399
  i = compound[end] === '(' ? balancedEnd(compound, end, '(', ')') : end;
127
400
  }
128
- else if (/[a-zA-Z]/.test(c)) {
129
- const end = identEnd(compound, i);
401
+ else if (startsIdent(compound, i)) {
402
+ const name = readIdent(compound, i);
130
403
  if (!tag)
131
- tag = compound.slice(i, end).toLowerCase();
132
- i = end;
404
+ tag = name.value.toLowerCase();
405
+ i = name.end;
133
406
  }
134
407
  else {
135
408
  i += 1;
@@ -143,12 +416,6 @@ function rightmostKey(selector) {
143
416
  return { kind: 'tag', name: tag };
144
417
  return { kind: 'any', name: '' };
145
418
  }
146
- function identEnd(text, from) {
147
- let i = from;
148
- while (i < text.length && /[a-zA-Z0-9_\-\\]/.test(text[i]))
149
- i += 1;
150
- return i;
151
- }
152
419
  function balancedEnd(text, from, open, close) {
153
420
  let depth = 0;
154
421
  for (let i = from; i < text.length; i += 1) {
@@ -169,7 +436,33 @@ const NO_POINTER = { hovered: new Set(), active: new Set() };
169
436
  */
170
437
  export class Cascade {
171
438
  _index = new RuleIndex();
439
+ /** The rules for pseudo-elements, kept apart: they never style the
440
+ * element itself, and a document with none of them asks nothing. */
441
+ _pseudo = {
442
+ before: new RuleIndex(),
443
+ after: new RuleIndex(),
444
+ 'first-letter': new RuleIndex(),
445
+ 'first-line': new RuleIndex(),
446
+ marker: new RuleIndex(),
447
+ };
172
448
  _adapter;
449
+ /** The compounds of the selectors that test the pointer, each without
450
+ * its `:hover` or `:active` (`pointerCompounds`), and their matchers,
451
+ * compiled when a pointer move first asks (`hoverTouches`). */
452
+ _hoverCompounds = new Set();
453
+ _hoverMatchers = null;
454
+ /** Whether a pointer move can be restyled where it happened
455
+ * (`HtmlViewNode._hoverInPlace`): false where a selector tests the
456
+ * pointer inside a functional pseudo-class, which reaches elements no
457
+ * compound names. */
458
+ hoverLocal = true;
459
+ /** Whether a compound that tests the pointer is followed by a sibling
460
+ * combinator, so an element's later siblings restyle with it. */
461
+ hoverSiblings = false;
462
+ /** The compounds whose `:has()` tests the pointer, each without it, and
463
+ * whether its argument starts at a sibling (`hoverAnchors`). */
464
+ _hoverAnchors = new Map();
465
+ _anchorMatchers = null;
173
466
  _pointer = NO_POINTER;
174
467
  initial;
175
468
  look;
@@ -183,20 +476,74 @@ export class Cascade {
183
476
  /** Every width at which some `@media` rule changes its mind, in CSS
184
477
  * pixels — the unit the author wrote them in. */
185
478
  breakpoints;
186
- constructor(sheets, look, viewportWidth, viewportHeight, scale = 1) {
479
+ /** The counter styles the sheets define, over the predefined ones. */
480
+ counterStyles;
481
+ /** A font's x-height at a size, for `ex`, where the fonts can say. */
482
+ _xHeightOf;
483
+ _xHeights = new Map();
484
+ /** The advance of a font's "0" at a size, for `ch`, likewise. */
485
+ _zeroWidthOf;
486
+ _zeroWidths = new Map();
487
+ /** A font's own line height at a size, for `lh` where `line-height` is
488
+ * `normal`, likewise. */
489
+ _normalLineOf;
490
+ _normalLines = new Map();
491
+ /** Whether any declaration sets a custom property or reads one: without
492
+ * one, no element's style asks about them. */
493
+ _vars = false;
494
+ /** Whether any declaration is in a unit of the viewport's width — `vw`,
495
+ * `vmin`, `vmax` — or of its height, `vh` and the same two: a style
496
+ * holds such a length as a number, so it is computed again when that
497
+ * side of the viewport moves (`HtmlViewNode._update`). */
498
+ readsViewportWidth = false;
499
+ readsViewportHeight = false;
500
+ /** The families the document loads itself (`fonts.ts`), or null for a
501
+ * document with no `@font-face`. */
502
+ _families;
503
+ _mapFamilies;
504
+ /** Whether any declaration has a length in `lh` or `rlh`: only then is
505
+ * the line height settled ahead of the declarations that read it. */
506
+ _lh = false;
507
+ constructor(sheets, look, viewportWidth, viewportHeight, scale = 1, xHeight = null, zeroWidth = null, normalLine = null, families = null) {
508
+ this._xHeightOf = xHeight;
509
+ this._zeroWidthOf = zeroWidth;
510
+ this._normalLineOf = normalLine;
511
+ this._families = families;
512
+ this._mapFamilies = families
513
+ ? (list) => families.map(list)
514
+ : undefined;
187
515
  this.look = look;
188
- this.initial = initialStyle(look);
516
+ this.initial = initialStyle(look, scale);
189
517
  this.viewportWidth = viewportWidth;
190
518
  this.viewportHeight = viewportHeight;
191
519
  this.scale = scale;
192
520
  const breakpoints = new Set();
521
+ const counterStyles = new Map();
193
522
  for (const sheet of sheets) {
194
- for (const rule of sheet.rules)
195
- this._index.add(rule);
523
+ // a counter style's rule whole over any before it of its name
524
+ for (const { prelude, declarations } of sheet.counterStyles ?? []) {
525
+ const style = counterStyleRule(prelude, declarations);
526
+ if (style)
527
+ counterStyles.set(style.name, style.rule);
528
+ }
529
+ for (const rule of sheet.rules) {
530
+ if (!this._vars && usesVars(rule.declarations))
531
+ this._vars = true;
532
+ this._noteViewportUnits(rule.declarations);
533
+ if (!this._lh && usesLh(rule.declarations))
534
+ this._lh = true;
535
+ const pseudo = splitPseudoElement(rule);
536
+ if (pseudo)
537
+ this._pseudo[pseudo.which].add(pseudo.rule);
538
+ else
539
+ this._index.add(rule);
540
+ this._noteHover((pseudo?.rule ?? rule).selector);
541
+ }
196
542
  for (const bp of sheet.breakpoints)
197
543
  breakpoints.add(bp);
198
544
  }
199
545
  this.breakpoints = [...breakpoints].sort((a, b) => a - b);
546
+ this.counterStyles = new CounterStyles(counterStyles);
200
547
  // css-select's default adapter is domutils; `isHovered` and `isActive`
201
548
  // are its documented hooks for exactly this, so `:hover` costs an
202
549
  // adapter field rather than a fork of the matcher.
@@ -207,18 +554,124 @@ export class Cascade {
207
554
  this._adapter = {
208
555
  ...DomUtils,
209
556
  isTag,
557
+ // a type selector sees `tagOf`'s name — XHTML's `<svg:svg>` is an
558
+ // `svg` — asked only of a name that could be one: this runs for every
559
+ // type selector tried, and the parser has lowercased the rest
560
+ getName: (el) => el.name.endsWith(':svg') ? tagOf(el) : el.name,
210
561
  isHovered: (el) => this._pointer.hovered.has(el),
211
562
  isActive: (el) => this._pointer.active.has(el),
212
563
  isVisited: () => false,
213
564
  };
214
565
  }
566
+ /** Whether declarations read the viewport's width or height (`vw`,
567
+ * `vh`, `vmin`, `vmax`), noted on the cascade. */
568
+ _noteViewportUnits(declarations) {
569
+ if (this.readsViewportWidth && this.readsViewportHeight)
570
+ return;
571
+ for (const d of declarations) {
572
+ if (!VIEWPORT_UNIT.test(d.value))
573
+ continue;
574
+ for (const m of d.value.matchAll(VIEWPORT_UNITS)) {
575
+ const unit = m[1].toLowerCase();
576
+ if (unit !== 'vh')
577
+ this.readsViewportWidth = true;
578
+ if (unit !== 'vw')
579
+ this.readsViewportHeight = true;
580
+ }
581
+ }
582
+ }
215
583
  /** Whether a pointer move can change what this cascade produces. */
216
584
  get hoverSensitive() {
217
- return this._index.hoverSensitive;
585
+ return (this._index.hoverSensitive ||
586
+ this._pseudo.before.hoverSensitive ||
587
+ this._pseudo.after.hoverSensitive ||
588
+ this._pseudo['first-letter'].hoverSensitive ||
589
+ this._pseudo['first-line'].hoverSensitive ||
590
+ this._pseudo.marker.hoverSensitive);
218
591
  }
219
592
  setPointer(pointer) {
220
593
  this._pointer = pointer;
221
594
  }
595
+ /**
596
+ * Whether the pointer entering or leaving `el` can change a style: one of
597
+ * the compounds a selector tests the pointer in matches it, the pointer
598
+ * aside. A move between two paragraphs of a page whose only such rule is
599
+ * `a:hover` touches nothing, and restyles nothing.
600
+ */
601
+ hoverTouches(el) {
602
+ this._hoverMatchers ??= [...this._hoverCompounds].flatMap((c) => {
603
+ const match = this._compile(c);
604
+ return match ? [match] : [];
605
+ });
606
+ for (const match of this._hoverMatchers)
607
+ if (match(el))
608
+ return true;
609
+ return false;
610
+ }
611
+ /**
612
+ * The elements whose `:has()` may have changed its answer as `el` was
613
+ * hovered or left: the ancestors of it a compound whose `:has()` tests
614
+ * the pointer names, and their earlier siblings and its own where the
615
+ * argument starts at a sibling — a superset, which is restyled and found
616
+ * the same where it did not. Into `into`.
617
+ */
618
+ hoverAnchors(el, into) {
619
+ if (!this._hoverAnchors.size)
620
+ return;
621
+ this._anchorMatchers ??= [...this._hoverAnchors].flatMap(([anchor, siblings]) => {
622
+ const match = this._compile(anchor);
623
+ return match ? [{ match, siblings }] : [];
624
+ });
625
+ const siblings = this._anchorMatchers.some((m) => m.siblings);
626
+ for (let at = el; at;) {
627
+ if (at !== el) {
628
+ for (const { match } of this._anchorMatchers) {
629
+ if (match(at)) {
630
+ into.push(at);
631
+ break;
632
+ }
633
+ }
634
+ }
635
+ if (siblings) {
636
+ for (let s = at.prev; s; s = s.prev) {
637
+ if (!isTag(s))
638
+ continue;
639
+ for (const { match, siblings: apart } of this._anchorMatchers) {
640
+ if (apart && match(s)) {
641
+ into.push(s);
642
+ break;
643
+ }
644
+ }
645
+ }
646
+ }
647
+ const parent = at.parent;
648
+ at = parent && isTag(parent) ? parent : null;
649
+ }
650
+ }
651
+ _noteHover(selector) {
652
+ if (!/:(?:hover|active)/i.test(selector))
653
+ return;
654
+ const found = pointerCompounds(selector);
655
+ if (found.nested)
656
+ this.hoverLocal = false;
657
+ if (found.siblings)
658
+ this.hoverSiblings = true;
659
+ for (const c of found.compounds)
660
+ this._hoverCompounds.add(c);
661
+ for (const { anchor, siblings } of found.has) {
662
+ this._hoverAnchors.set(anchor, siblings || (this._hoverAnchors.get(anchor) ?? false));
663
+ }
664
+ }
665
+ /** A selector compiled as a rule's is, or null where css-select refuses
666
+ * it, as a rule it refuses drops out of the cascade. */
667
+ _compile(selector) {
668
+ try {
669
+ return compileSelector(selector, this._adapter);
670
+ }
671
+ catch {
672
+ return null;
673
+ }
674
+ }
222
675
  /** Which media band a device-pixel width falls in. Two widths in the same
223
676
  * band produce identical styles, which is what lets a resize skip
224
677
  * restyling. */
@@ -233,14 +686,323 @@ export class Cascade {
233
686
  }
234
687
  return band;
235
688
  }
689
+ /** Computed styles by sharing key, for one build (`sharedStyleFor`): one
690
+ * map for the elements shared without matching, one for the elements
691
+ * shared by what they matched. */
692
+ _shared = new Map();
693
+ _sharedByMatch = new Map();
694
+ _nextShareKey = 1;
695
+ /** Custom property sets by what made them, for one build (`_customFor`). */
696
+ _customs = new Map();
697
+ _ids = new WeakMap();
698
+ _nextId = 1;
699
+ /** A box tree is about to be built: the styles shared in the last build
700
+ * were computed against a pointer and a viewport that may have moved. */
701
+ beginSharing() {
702
+ this._shared.clear();
703
+ this._sharedByMatch.clear();
704
+ this._customs.clear();
705
+ }
236
706
  /**
237
- * The computed style for one element, given its parent's. Called once per
238
- * element per style pass, in document order — the box builder drives it,
239
- * so there is no second traversal and no map of styles to allocate.
707
+ * An element's custom properties: its parent's, or its own over them —
708
+ * shared by every element whose parent has the same ones and whose own
709
+ * come from the same declarations. Tailwind 4 sets thirty-five of them on
710
+ * every element (`*, ::before, ::after { --tw-shadow: 0 0 #0000; … }`),
711
+ * and a set per element was a fifth of building the boxes; it also kept
712
+ * each element's `var()`s from being replaced once for its siblings,
713
+ * which `substituteIn` remembers by the set they were read against.
714
+ */
715
+ _customFor(parentStyle, candidates) {
716
+ let key = '';
717
+ for (const c of candidates) {
718
+ if (!this._hasCustom(c))
719
+ continue;
720
+ key += `${this._idOf(c.declarations)}:${c.only},`;
721
+ }
722
+ const parent = parentStyle.custom;
723
+ if (!key)
724
+ return parent;
725
+ key = `${parent ? this._idOf(parent) : 0}|${key}`;
726
+ const hit = this._customs.get(key);
727
+ if (hit)
728
+ return hit;
729
+ const own = new Map();
730
+ for (const c of candidates) {
731
+ for (const d of pick(c))
732
+ if (d.custom)
733
+ own.set(d.prop, d.value);
734
+ }
735
+ const made = customProperties(own, parent);
736
+ this._customs.set(key, made);
737
+ return made;
738
+ }
739
+ /** Whether a candidate sets a custom property. */
740
+ _hasCustom(c) {
741
+ if (c.only >= 0)
742
+ return !!c.declarations[c.only].custom;
743
+ let has = CUSTOM_IN.get(c.declarations);
744
+ if (has === undefined) {
745
+ has = c.declarations.some((d) => !!d.custom);
746
+ CUSTOM_IN.set(c.declarations, has);
747
+ }
748
+ return has;
749
+ }
750
+ /** A number for an object, to key a string by. */
751
+ _idOf(of) {
752
+ let id = this._ids.get(of);
753
+ if (id === undefined) {
754
+ id = this._nextId++;
755
+ this._ids.set(of, id);
756
+ }
757
+ return id;
758
+ }
759
+ /**
760
+ * `styleFor`, shared between the elements that must compute the same
761
+ * style, with the key this element's children share under.
762
+ *
763
+ * A style is a function of the parent's style, the rules that match, the
764
+ * presentational attributes, the inline style and whether the parent is a
765
+ * flex container. Outside the rules `UNSHAREABLE` names, what matches
766
+ * depends only on the element's tag and attributes and its ancestors', and
767
+ * the hints read nothing else either. So the key is the parent's key, the
768
+ * flex flag, the tag and every attribute — plus the pointer state where a
769
+ * rule asks for it — and an element whose key has been computed in this
770
+ * build takes that style object, matching nothing. A long document is a
771
+ * few kinds of element many times over: the benchmark's 600 KB report is
772
+ * 9,039 elements and 110 keys, and computing every style again was a third
773
+ * of an edit.
774
+ *
775
+ * An element a rule `UNSHAREABLE` could reach is matched, since where it
776
+ * sits decides what matches — and then shared by what matched: the same
777
+ * parent, attributes and rules make the same style. That is what keeps a
778
+ * striped table from being a style per row, and it keeps the key its
779
+ * children share under, which an element-per-key would have taken from the
780
+ * whole subtree.
781
+ *
782
+ * The style is handed out shared, so nothing may write to it — nothing
783
+ * does after the cascade, and `rootStyle` does not go through here.
784
+ */
785
+ sharedStyleFor(el, parentStyle, parentKey, inFlexContainer) {
786
+ let key = `${parentKey}\u0001${inFlexContainer ? 1 : 0}`;
787
+ const tag = tagOf(el);
788
+ key += `\u0001${tag.length}:${tag}`;
789
+ if (this._index.hoverSensitive) {
790
+ if (this._pointer.hovered.has(el))
791
+ key += '\u0001:hover';
792
+ if (this._pointer.active.has(el))
793
+ key += '\u0001:active';
794
+ }
795
+ const attribs = el.attribs;
796
+ for (const name in attribs) {
797
+ const value = attribs[name];
798
+ key += `\u0001${name.length}:${name}=${value.length}:${value}`;
799
+ }
800
+ if (!this._shareable(el)) {
801
+ const matched = [];
802
+ const candidates = this._candidates(el, matched);
803
+ key += `\u0001${matched.join(',')}`;
804
+ let shared = this._sharedByMatch.get(key);
805
+ if (shared === undefined) {
806
+ shared = {
807
+ style: this._computeStyle(el, parentStyle, inFlexContainer, candidates),
808
+ key: this._nextShareKey++,
809
+ };
810
+ this._sharedByMatch.set(key, shared);
811
+ }
812
+ return shared;
813
+ }
814
+ let shared = this._shared.get(key);
815
+ if (shared === undefined) {
816
+ shared = {
817
+ style: this.styleFor(el, parentStyle, inFlexContainer),
818
+ key: this._nextShareKey++,
819
+ };
820
+ this._shared.set(key, shared);
821
+ }
822
+ return shared;
823
+ }
824
+ /** Whether no rule `UNSHAREABLE` names could reach this element: the same
825
+ * buckets `_candidates` looks in. */
826
+ _shareable(el) {
827
+ const index = this._index;
828
+ if (index.ownStyleEverywhere)
829
+ return false;
830
+ if (index.ownStyleTags.size && index.ownStyleTags.has(tagOf(el))) {
831
+ return false;
832
+ }
833
+ if (index.ownStyleIds.size) {
834
+ const id = attr(el, 'id');
835
+ if (id && index.ownStyleIds.has(id))
836
+ return false;
837
+ }
838
+ if (index.ownStyleClasses.size) {
839
+ const className = attr(el, 'class');
840
+ if (className) {
841
+ for (const name of className.split(/\s+/)) {
842
+ if (name && index.ownStyleClasses.has(name))
843
+ return false;
844
+ }
845
+ }
846
+ }
847
+ return true;
848
+ }
849
+ /**
850
+ * The computed style for one element, given its parent's. The box builder
851
+ * asks for every element in document order, through `sharedStyleFor`, so
852
+ * a style is computed only for the elements with none to share.
240
853
  */
241
854
  styleFor(el, parentStyle, inFlexContainer) {
855
+ return this._computeStyle(el, parentStyle, inFlexContainer, this._candidates(el));
856
+ }
857
+ /**
858
+ * The style of an element's `::before` or `::after`, or null when it has
859
+ * none: no rule reaches it, or the rules that do leave `content` at
860
+ * `normal` or `none`, which make no box (CSS 2.1 12.2). It inherits from
861
+ * the element's own style, as a pseudo-element does, and a flex
862
+ * container's are flex items. Not shared: few elements have one, and where
863
+ * a rule gives every element one — a clearfix — the style is the cost of
864
+ * the box it makes.
865
+ */
866
+ pseudoStyleFor(el, which, elementStyle) {
867
+ const index = this._pseudo[which];
868
+ if (!index.size || !index.reaches(el))
869
+ return null;
870
+ const candidates = [];
871
+ this._matchInto(index, el, candidates);
872
+ if (!candidates.length)
873
+ return null;
874
+ // One that no rule gives a `content` is none, whatever else reaches it —
875
+ // `content` is not inherited, and its initial `normal` is nothing here.
876
+ // Tailwind's `*, ::before, ::after` reaches both of every element's.
877
+ if (!candidates.some(setsContent))
878
+ return null;
879
+ candidates.sort(byCascade);
880
+ const style = this._computeStyle(el, elementStyle, elementStyle.display === 'flex' || elementStyle.display === 'inline-flex', candidates);
881
+ return style.content === 'normal' || style.content === 'none'
882
+ ? null
883
+ : style;
884
+ }
885
+ /**
886
+ * The rules for an element's `::first-letter`, or null when none reaches
887
+ * it. They are matched against the element here, and its style computed
888
+ * later by `firstLetterStyle`, because the pseudo-element inherits from
889
+ * the box its letter turns out to be in — a `<span>` the block opens with,
890
+ * a `::before` — which the builder has not reached yet.
891
+ */
892
+ firstLetterRules(el) {
893
+ const index = this._pseudo['first-letter'];
894
+ if (!index.size || !index.reaches(el))
895
+ return null;
896
+ const candidates = [];
897
+ this._matchInto(index, el, candidates);
898
+ if (!candidates.length)
899
+ return null;
900
+ candidates.sort(byCascade);
901
+ return { el, candidates };
902
+ }
903
+ /** Whether any rule styles a `::first-line`: a document with none asks
904
+ * nothing more of its blocks. */
905
+ get hasFirstLine() {
906
+ return this._pseudo['first-line'].size > 0;
907
+ }
908
+ /**
909
+ * A list item's `::marker` style, inheriting from its own, or null when no
910
+ * rule reaches it (CSS Lists 3, 3.1): the colour and the font a bullet or
911
+ * a number is set in, and a `content` it is set as instead.
912
+ */
913
+ markerStyle(el, style) {
914
+ const index = this._pseudo.marker;
915
+ if (!index.size || !index.reaches(el))
916
+ return null;
917
+ const candidates = [];
918
+ this._matchInto(index, el, candidates);
919
+ if (!candidates.length)
920
+ return null;
921
+ candidates.sort(byCascade);
922
+ const out = this._computeStyle(el, style, false, candidates);
923
+ // a marker's direction is its own unless a rule says otherwise (the
924
+ // HTML style sheet's `::marker { unicode-bidi: isolate }`)
925
+ const set = candidates.some((c) => c.declarations.some((d) => d.prop === 'unicode-bidi'));
926
+ if (!set)
927
+ out.unicodeBidi = 'isolate';
928
+ return out;
929
+ }
930
+ /**
931
+ * An element's `::first-line` style, inheriting from its own, or null
932
+ * when no rule reaches it (CSS 2.1 5.12.1).
933
+ */
934
+ firstLineStyle(el, style) {
935
+ const index = this._pseudo['first-line'];
936
+ if (!index.size)
937
+ return null;
938
+ const candidates = [];
939
+ this._matchInto(index, el, candidates);
940
+ if (!candidates.length)
941
+ return null;
942
+ candidates.sort(byCascade);
943
+ return this._computeStyle(el, style, false, candidates);
944
+ }
945
+ /**
946
+ * The style of a `::first-letter` inside a box of `parentStyle`. It is an
947
+ * inline box, or a float where it floats, whatever the rules say of its
948
+ * `display` or its `position` (CSS 2.1 5.12.2).
949
+ */
950
+ firstLetterStyle(rules, parentStyle) {
951
+ const style = this._computeStyle(rules.el, parentStyle, false, rules.candidates);
952
+ style.display = style.float === 'none' ? 'inline' : 'block';
953
+ style.position = 'static';
954
+ return style;
955
+ }
956
+ /** The x-height of a style's font: the font's own, asked once per face
957
+ * and size, or half an em. */
958
+ _exOf(style) {
959
+ const key = `${style.fontFamily}\u0001${style.fontSize}`;
960
+ let ex = this._xHeights.get(key);
961
+ if (ex === undefined) {
962
+ ex = this._xHeightOf?.(style.fontFamily, style.fontSize) ?? NaN;
963
+ if (!(ex > 0))
964
+ ex = style.fontSize * 0.5;
965
+ this._xHeights.set(key, ex);
966
+ }
967
+ return ex;
968
+ }
969
+ /** The advance of a style's font's "0": the font's own, asked once per
970
+ * face and size, or half an em. */
971
+ _chOf(style) {
972
+ const key = `${style.fontFamily}\u0001${style.fontSize}`;
973
+ let ch = this._zeroWidths.get(key);
974
+ if (ch === undefined) {
975
+ ch = this._zeroWidthOf?.(style.fontFamily, style.fontSize) ?? NaN;
976
+ if (!(ch > 0))
977
+ ch = style.fontSize * 0.5;
978
+ this._zeroWidths.set(key, ch);
979
+ }
980
+ return ch;
981
+ }
982
+ /** A style's computed line height as a length, for `lh`: `normal` as
983
+ * its font's own, asked once per face and size, or 1.2em. */
984
+ _lineHeightOf(style) {
985
+ const set = style.lineHeight;
986
+ if (set !== 'normal') {
987
+ return style.lineHeightIsLength ? set : set * style.fontSize;
988
+ }
989
+ const key = `${style.fontFamily}\u0001${style.fontSize}`;
990
+ let line = this._normalLines.get(key);
991
+ if (line === undefined) {
992
+ line = this._normalLineOf?.(style.fontFamily, style.fontSize) ?? NaN;
993
+ if (!(line > 0))
994
+ line = style.fontSize * 1.2;
995
+ this._normalLines.set(key, line);
996
+ }
997
+ return line;
998
+ }
999
+ /** `styleFor`, from the rules and hints already gathered for `el`. */
1000
+ _computeStyle(el, parentStyle, inFlexContainer, candidates) {
242
1001
  const style = inherit(parentStyle, this.initial);
243
- const candidates = this._candidates(el);
1002
+ // custom properties first, in cascade order, so every `var()` in the
1003
+ // declarations below finds the one that wins
1004
+ if (this._vars)
1005
+ style.custom = this._customFor(parentStyle, candidates);
244
1006
  // The unit context has to be built twice: once with the parent's font
245
1007
  // size, so a `font-size: 1.2em` in the cascade resolves against the
246
1008
  // right em, and again after the font size is settled so every *other*
@@ -248,28 +1010,123 @@ export class Cascade {
248
1010
  const ctxParent = {
249
1011
  em: parentStyle.fontSize,
250
1012
  rem: this.initial.fontSize,
1013
+ initial: this.initial,
251
1014
  vw: this.viewportWidth,
252
1015
  vh: this.viewportHeight,
253
1016
  scale: this.scale,
1017
+ ex: () => this._exOf(parentStyle),
1018
+ ch: () => this._chOf(parentStyle),
1019
+ families: this._mapFamilies,
1020
+ lh: () => this._lineHeightOf(parentStyle),
1021
+ rlh: () => this._lineHeightOf(this.initial),
254
1022
  };
1023
+ // the family goes with the size, so an `ex` after it is its font's
1024
+ let sized = false;
1025
+ let keyword = false;
255
1026
  for (const c of candidates) {
256
1027
  for (const d of pick(c)) {
257
- if (d.prop === 'font-size' || d.prop === 'font') {
258
- applyDeclaration(style, parentStyle, d.prop, d.value, ctxParent);
1028
+ if (d.prop === 'font-family') {
1029
+ this._apply(style, parentStyle, d, ctxParent);
1030
+ }
1031
+ else if (d.prop === 'font-size' || d.prop === 'font') {
1032
+ // NaN until a size is set, so one the declaration did not take
1033
+ // leaves the size where it was, and says nothing of it
1034
+ const was = style.fontSize;
1035
+ style.fontSize = NaN;
1036
+ this._apply(style, parentStyle, d, ctxParent);
1037
+ if (Number.isNaN(style.fontSize)) {
1038
+ style.fontSize = was;
1039
+ }
1040
+ else {
1041
+ sized = true;
1042
+ keyword = !d.vars && sizeKeyword(d.prop, d.value);
1043
+ }
259
1044
  }
260
1045
  }
261
1046
  }
262
- const ctx = { ...ctxParent, em: style.fontSize };
1047
+ // The generic `monospace` on its own has a smaller size than the rest,
1048
+ // 13 pixels to their 16 (the "fixed" font size every browser keeps):
1049
+ // an element whose family becomes it, or stops being it, scales the
1050
+ // size it inherits by that, and a keyword size is read from the
1051
+ // smaller scale — the size it sets itself stays its own. Blink's
1052
+ // CheckForGenericFamilyChange, and why a `<pre>` in a browser is 13px.
1053
+ const mono = monospaceOnly(style.fontFamily);
1054
+ if (sized ? keyword && mono : mono !== monospaceOnly(parentStyle.fontFamily)) {
1055
+ style.fontSize *= mono ? FIXED_SIZE : 1 / FIXED_SIZE;
1056
+ }
1057
+ const ctx = {
1058
+ ...ctxParent,
1059
+ em: style.fontSize,
1060
+ ex: () => this._exOf(style),
1061
+ ch: () => this._chOf(style),
1062
+ lh: () => this._lineHeightOf(style),
1063
+ };
1064
+ // the line height, which an `lh` in any other declaration reads, ahead
1065
+ // of them: set again with the rest, in its place among them
1066
+ if (this._lh) {
1067
+ for (const c of candidates) {
1068
+ for (const d of pick(c)) {
1069
+ if (d.prop === 'line-height')
1070
+ this._apply(style, parentStyle, d, ctx);
1071
+ }
1072
+ }
1073
+ }
1074
+ const settled = style.fontSize;
263
1075
  for (const c of candidates) {
264
1076
  for (const d of pick(c)) {
265
- if (d.prop === 'font-size')
1077
+ if (d.prop === 'font-size' || d.custom)
266
1078
  continue;
267
- applyDeclaration(style, parentStyle, d.prop, d.value, ctx);
1079
+ this._apply(style, parentStyle, d, ctx);
268
1080
  }
269
1081
  }
1082
+ // A `font` is applied again, to keep its other longhands in cascade
1083
+ // order, and it sets the size it names as well: the size is the first
1084
+ // pass's, which the declarations that outrank the `font` had their say
1085
+ // in, and the scale after them. `span { font: 15px/1 Ahem }` under
1086
+ // `.b > span { font-size: 3.75em }` was 15px, its `em`s 3.75 of its
1087
+ // parent's.
1088
+ style.fontSize = settled;
1089
+ // A table never keeps HTML's alignment, `-webkit-center` and its kin:
1090
+ // the `<td align="center">` every mail centres its body table in
1091
+ // centres the table, and the text in its cells stays at their start —
1092
+ // as Blink resets it ("tables never support the -webkit-* values for
1093
+ // text-align"). An author's own `text-align: center` is not HTML's, and
1094
+ // is inherited into the table as it always was.
1095
+ if (style.alignBlocks !== null && tagOf(el) === 'table') {
1096
+ style.textAlign = 'start';
1097
+ style.alignBlocks = null;
1098
+ }
1099
+ settleClamp(style, parentStyle);
1100
+ settleOverflow(style);
1101
+ settleContentVisibility(style);
270
1102
  blockify(style, inFlexContainer);
1103
+ decorate(style);
1104
+ // which faces of the document's own families this family, weight and
1105
+ // slant ask for — known only now, with all three computed
1106
+ this._families?.note(style);
271
1107
  return style;
272
1108
  }
1109
+ /** One declaration, its `var()`s replaced first. One that names a
1110
+ * custom property with no value, and has no fallback, is invalid at
1111
+ * computed-value time, and the property is as though `unset`. */
1112
+ _apply(style, parentStyle, d, ctx) {
1113
+ if (!d.vars) {
1114
+ applyDeclaration(style, parentStyle, d.prop, d.value, ctx);
1115
+ return;
1116
+ }
1117
+ // unset first: a value that does not parse once it is substituted is
1118
+ // invalid at computed-value time, and does not leave the property what
1119
+ // an earlier declaration gave it
1120
+ if (isInherited(d.prop)) {
1121
+ applyDeclaration(style, parentStyle, d.prop, 'inherit', ctx);
1122
+ }
1123
+ else {
1124
+ initialOne(style, this.initial, d.prop);
1125
+ }
1126
+ const value = substituteIn(d.value, style.custom);
1127
+ if (value !== null)
1128
+ applyDeclaration(style, parentStyle, d.prop, value, ctx);
1129
+ }
273
1130
  /**
274
1131
  * The root's style — nothing above it to inherit from.
275
1132
  *
@@ -278,24 +1135,37 @@ export class Cascade {
278
1135
  * a `<body>` would have had: the UA sheet's margin and font, and any
279
1136
  * author `body { … }` rule. Without it a fragment renders hard against the
280
1137
  * left edge while the same markup inside `<html><body>` does not, which
281
- * reads as a bug in the renderer rather than as a missing element.
1138
+ * reads as a bug in the renderer rather than as a missing element. With
1139
+ * no `<html>` either, the body inherits from an `<html>` that author
1140
+ * `html { … }` rules have styled, as the one a browser implies would be.
1141
+ *
1142
+ * A document with a `<body>` and no `<html>` — the usual shape of a page
1143
+ * that starts `<!DOCTYPE html><title>` — has the root box standing in for
1144
+ * that implied `<html>` instead, so an `html { font-size }` still reaches
1145
+ * the body. Taken as the initial style, the rule matched nothing and the
1146
+ * whole page came out at the theme's size.
282
1147
  */
283
- rootStyle(hasBody) {
284
- const style = { ...this.initial };
1148
+ rootStyle(hasBody, hasHtml = true) {
1149
+ const style = copyStyle(this.initial);
285
1150
  style.display = 'block';
286
- if (hasBody)
1151
+ if (hasBody && hasHtml)
287
1152
  return style;
288
1153
  const synthetic = new DomElement('body', {}, []);
289
- const bodyStyle = this.styleFor(synthetic, style, false);
1154
+ let parent = style;
1155
+ if (!hasHtml) {
1156
+ const html = new DomElement('html', {}, hasBody ? [] : [synthetic]);
1157
+ synthetic.parent = html;
1158
+ parent = this.styleFor(html, style, false);
1159
+ if (hasBody)
1160
+ return asRoot(parent);
1161
+ }
290
1162
  // Only the box the body would have drawn is taken, not its layout role:
291
1163
  // the root is still the initial containing block.
292
- bodyStyle.display = 'block';
293
- bodyStyle.position = 'static';
294
- bodyStyle.float = 'none';
295
- return bodyStyle;
1164
+ return asRoot(this.styleFor(synthetic, parent, false));
296
1165
  }
297
- _candidates(el) {
298
- const out = [];
1166
+ /** The rules of `index` that match `el`, pushed onto `out` as candidates,
1167
+ * and their ids onto `matched` in the order they were tried. */
1168
+ _matchInto(index, el, out, matched) {
299
1169
  // A media query's width is CSS pixels; the viewport is kept in device.
300
1170
  const width = this.viewportWidth / this.scale;
301
1171
  const consider = (bucket) => {
@@ -308,10 +1178,7 @@ export class Cascade {
308
1178
  if (!indexed.compiled) {
309
1179
  indexed.compiled = true;
310
1180
  try {
311
- indexed.match = compile(rule.selector, {
312
- adapter: this._adapter,
313
- xmlMode: false,
314
- });
1181
+ indexed.match = compileSelector(rule.selector, this._adapter);
315
1182
  }
316
1183
  catch {
317
1184
  // A selector this matcher does not know (`::-moz-…`, a CSS4 form
@@ -322,26 +1189,35 @@ export class Cascade {
322
1189
  }
323
1190
  if (!indexed.match || !indexed.match(el))
324
1191
  continue;
1192
+ matched?.push(indexed.id);
325
1193
  const origin = rule.order < 0 ? Origin.UserAgent : Origin.Author;
326
1194
  pushRule(out, rule, origin);
327
1195
  }
328
1196
  };
329
1197
  const id = attr(el, 'id');
330
1198
  if (id)
331
- consider(this._index.byId.get(id));
1199
+ consider(index.byId.get(id));
332
1200
  const className = attr(el, 'class');
333
1201
  if (className) {
334
1202
  for (const name of className.split(/\s+/)) {
335
1203
  if (name)
336
- consider(this._index.byClass.get(name));
1204
+ consider(index.byClass.get(name));
337
1205
  }
338
1206
  }
339
- consider(this._index.byTag.get(tagOf(el)));
340
- consider(this._index.universal);
1207
+ consider(index.byTag.get(tagOf(el)));
1208
+ consider(index.universal);
1209
+ }
1210
+ /** Every rule and hint that applies to `el`, in cascade order — and, into
1211
+ * `matched` when it is passed, the ids of the rules, in the order they
1212
+ * were tried. */
1213
+ _candidates(el, matched) {
1214
+ const out = [];
1215
+ this._matchInto(this._index, el, out, matched);
341
1216
  const hints = presentationHints(el);
342
1217
  if (hints.length) {
343
1218
  out.push({
344
1219
  origin: Origin.Presentation,
1220
+ layer: null,
345
1221
  specificity: 0,
346
1222
  order: 0,
347
1223
  declarations: hints,
@@ -351,11 +1227,17 @@ export class Cascade {
351
1227
  const inline = attr(el, 'style');
352
1228
  if (inline) {
353
1229
  const declarations = parseDeclarations(inline);
1230
+ if (!this._vars && usesVars(declarations))
1231
+ this._vars = true;
1232
+ this._noteViewportUnits(declarations);
1233
+ if (!this._lh && usesLh(declarations))
1234
+ this._lh = true;
354
1235
  const normal = declarations.filter((d) => !d.important);
355
1236
  const important = declarations.filter((d) => d.important);
356
1237
  if (normal.length) {
357
1238
  out.push({
358
1239
  origin: Origin.Inline,
1240
+ layer: null,
359
1241
  specificity: 0,
360
1242
  order: 0,
361
1243
  declarations: normal,
@@ -365,6 +1247,7 @@ export class Cascade {
365
1247
  if (important.length) {
366
1248
  out.push({
367
1249
  origin: Origin.InlineImportant,
1250
+ layer: null,
368
1251
  specificity: 0,
369
1252
  order: 0,
370
1253
  declarations: important,
@@ -376,6 +1259,144 @@ export class Cascade {
376
1259
  return out;
377
1260
  }
378
1261
  }
1262
+ /** An implied element's style as the root box's: its look, not its role —
1263
+ * the root is still a block, in flow, and the initial containing block. */
1264
+ function asRoot(style) {
1265
+ style.display = 'block';
1266
+ style.position = 'static';
1267
+ style.float = 'none';
1268
+ return style;
1269
+ }
1270
+ /** `:root` is the `<html>` element: the one a browser implies around a
1271
+ * fragment, whose style the root box takes (`rootStyle`), and never a
1272
+ * fragment's top-level elements, which css-select would take for it. */
1273
+ const PSEUDOS = {
1274
+ root: (el) => el.name === 'html' && !(el.parent && isTag(el.parent)),
1275
+ // css-select's, but its ranges and tags lower-cased as ASCII has it, and
1276
+ // no other script (CSS 2.1 4.1.3): Unicode's took `:lang(\u212Al)`, a
1277
+ // Kelvin sign for the K, for `:lang(kl)`
1278
+ lang: (el, code) => {
1279
+ const ranges = (code ?? '')
1280
+ .split(',')
1281
+ .map((range) => range.trim().replace(/^['"]|['"]$/g, ''))
1282
+ .filter((range) => range.length > 0)
1283
+ .map((range) => asciiLower(range).split('-'));
1284
+ let root = el;
1285
+ for (let node = el; node;) {
1286
+ const value = node.attribs['xml:lang'] ?? node.attribs.lang;
1287
+ if (value != null) {
1288
+ if (!value)
1289
+ return ranges.some((range) => range[0] === '');
1290
+ const tag = asciiLower(value).split('-');
1291
+ return ranges.some((range) => langRangeMatches(tag, range));
1292
+ }
1293
+ root = node;
1294
+ const parent = node.parent;
1295
+ node = parent && isTag(parent) ? parent : null;
1296
+ }
1297
+ // with no element saying, the document's, as its `<meta>` sets it —
1298
+ // searched from the document, where a fragment's `<meta>` is a
1299
+ // sibling of what it covers
1300
+ const pragma = pragmaLanguage(root.parent ?? root);
1301
+ if (!pragma)
1302
+ return ranges.some((range) => range[0] === '');
1303
+ const tag = asciiLower(pragma).split('-');
1304
+ return ranges.some((range) => langRangeMatches(tag, range));
1305
+ },
1306
+ };
1307
+ /** A length in a unit of the viewport: a number, then the unit, and no
1308
+ * more of a name after it. */
1309
+ const VIEWPORT_UNIT = /\d(?:vw|vh|vmin|vmax)(?![\w-])/i;
1310
+ const VIEWPORT_UNITS = /\d(vw|vh|vmin|vmax)(?![\w-])/gi;
1311
+ /**
1312
+ * A selector with its `[attr~=""]` made one that matches nothing: an empty
1313
+ * string is no word of a list, and such a selector represents nothing
1314
+ * (Selectors 3, 6.3.1) — which the matcher's `~=` is not told, taking the
1315
+ * empty word for one between two spaces, or at either end of none.
1316
+ */
1317
+ function noEmptyWords(selector) {
1318
+ if (!selector.includes('~='))
1319
+ return selector;
1320
+ return selector.replace(/\[[^\]"']*~=\s*(?:""|'')\s*(?:[is]\s*)?\]/gi, ':not(*)');
1321
+ }
1322
+ /**
1323
+ * A document's language as a `<meta http-equiv="content-language">` sets
1324
+ * it — HTML's pragma-set default language, the last such `<meta>`'s
1325
+ * `content` up to its first white space, and none where it lists more
1326
+ * than one — by the document's root element, found once.
1327
+ */
1328
+ function pragmaLanguage(root) {
1329
+ let lang = PRAGMA_LANGUAGE.get(root);
1330
+ if (lang !== undefined)
1331
+ return lang;
1332
+ lang = '';
1333
+ const stack = [root];
1334
+ while (stack.length) {
1335
+ const node = stack.pop();
1336
+ if (isTag(node) &&
1337
+ node.name === 'meta' &&
1338
+ node.attribs['http-equiv']?.trim().toLowerCase() === 'content-language') {
1339
+ const content = node.attribs.content;
1340
+ if (content !== undefined && !content.includes(',')) {
1341
+ const candidate = content.trim().split(/[\t\n\f\r ]/)[0];
1342
+ if (candidate)
1343
+ lang = candidate;
1344
+ }
1345
+ }
1346
+ // in document order: the last one pushed is taken first
1347
+ for (let i = node.children.length - 1; i >= 0; i -= 1) {
1348
+ const child = node.children[i];
1349
+ if (isTag(child))
1350
+ stack.push(child);
1351
+ }
1352
+ }
1353
+ PRAGMA_LANGUAGE.set(root, lang);
1354
+ return lang;
1355
+ }
1356
+ const PRAGMA_LANGUAGE = new WeakMap();
1357
+ /** RFC 4647's extended filtering, of a tag's subtags by a range's, as
1358
+ * css-select does it. */
1359
+ function langRangeMatches(tag, range) {
1360
+ if (range[0] !== '*' && range[0] !== tag[0])
1361
+ return false;
1362
+ let at = 1;
1363
+ for (let r = 1; r < range.length; r += 1) {
1364
+ if (range[r] === '*')
1365
+ continue;
1366
+ while (at < tag.length && tag[at] !== range[r]) {
1367
+ if (tag[at++].length <= 1)
1368
+ return false;
1369
+ }
1370
+ if (at >= tag.length)
1371
+ return false;
1372
+ at += 1;
1373
+ }
1374
+ return true;
1375
+ }
1376
+ /** Whether any of these declarations sets a custom property or reads one. */
1377
+ function usesVars(declarations) {
1378
+ for (const d of declarations)
1379
+ if (d.custom || d.vars)
1380
+ return true;
1381
+ return false;
1382
+ }
1383
+ /** Whether any of the declarations has a length in `lh` or `rlh`. */
1384
+ function usesLh(declarations) {
1385
+ for (const d of declarations)
1386
+ if (LH.test(d.value))
1387
+ return true;
1388
+ return false;
1389
+ }
1390
+ const LH = /\d\.?r?lh\b/i;
1391
+ /** Whether a candidate declares `content`. */
1392
+ function setsContent(c) {
1393
+ for (const d of pick(c))
1394
+ if (d.prop === 'content')
1395
+ return true;
1396
+ return false;
1397
+ }
1398
+ /** Whether a rule's declarations set a custom property, by the array. */
1399
+ const CUSTOM_IN = new WeakMap();
379
1400
  function pick(c) {
380
1401
  return c.only < 0 ? c.declarations : [c.declarations[c.only]];
381
1402
  }
@@ -390,6 +1411,7 @@ function pushRule(out, rule, origin) {
390
1411
  if (!hasImportant) {
391
1412
  out.push({
392
1413
  origin,
1414
+ layer: rule.layer,
393
1415
  specificity: rule.specificity,
394
1416
  order: rule.order,
395
1417
  declarations: rule.declarations,
@@ -407,6 +1429,7 @@ function pushRule(out, rule, origin) {
407
1429
  ? Origin.UserAgent
408
1430
  : Origin.AuthorImportant
409
1431
  : origin,
1432
+ layer: rule.layer,
410
1433
  specificity: rule.specificity,
411
1434
  order: rule.order,
412
1435
  declarations: rule.declarations,
@@ -417,10 +1440,34 @@ function pushRule(out, rule, origin) {
417
1440
  function byCascade(a, b) {
418
1441
  if (a.origin !== b.origin)
419
1442
  return a.origin - b.origin;
1443
+ if (a.layer !== b.layer) {
1444
+ // a later layer wins over an earlier one whatever the specificity, and
1445
+ // for `!important` an earlier one does (CSS Cascade 5, 6.4)
1446
+ const by = compareLayers(a.layer, b.layer);
1447
+ if (by !== 0)
1448
+ return a.origin >= Origin.AuthorImportant ? -by : by;
1449
+ }
420
1450
  if (a.specificity !== b.specificity)
421
1451
  return a.specificity - b.specificity;
422
1452
  return a.order - b.order;
423
1453
  }
1454
+ /**
1455
+ * Which of two layers wins for a normal declaration: a later one over an
1456
+ * earlier one, and a rule in no layer over any, as a rule directly in a
1457
+ * layer is over the layers inside it.
1458
+ */
1459
+ function compareLayers(a, b) {
1460
+ if (a === null)
1461
+ return b === null ? 0 : 1;
1462
+ if (b === null)
1463
+ return -1;
1464
+ const n = Math.min(a.length, b.length);
1465
+ for (let i = 0; i < n; i += 1) {
1466
+ if (a[i] !== b[i])
1467
+ return a[i] - b[i];
1468
+ }
1469
+ return b.length - a.length;
1470
+ }
424
1471
  /**
425
1472
  * The presentational attributes, as declarations. They sit above the UA
426
1473
  * sheet and below every author rule, which is where HTML says they go — and
@@ -437,9 +1484,44 @@ function presentationHints(el) {
437
1484
  const align = attr(el, 'align');
438
1485
  if (align) {
439
1486
  const v = align.toLowerCase();
440
- if (tag === 'img' && (v === 'left' || v === 'right'))
1487
+ const side = v === 'middle' ? 'center' : v;
1488
+ if ((tag === 'img' || tag === 'table') && (v === 'left' || v === 'right')) {
441
1489
  push('float', v);
442
- else if (v === 'center' || v === 'middle')
1490
+ }
1491
+ else if (tag === 'img') {
1492
+ // an image's other alignments are its line's
1493
+ const va = IMAGE_ALIGN[v];
1494
+ if (va)
1495
+ push('vertical-align', va);
1496
+ }
1497
+ else if (tag === 'hr') {
1498
+ // a rule narrower than its line stands where it is aligned
1499
+ if (v === 'left') {
1500
+ push('margin-left', '0');
1501
+ push('margin-right', 'auto');
1502
+ }
1503
+ else if (v === 'right') {
1504
+ push('margin-left', 'auto');
1505
+ push('margin-right', '0');
1506
+ }
1507
+ }
1508
+ else if (tag === 'table') {
1509
+ // a table's `align` places the table and leaves its text alone: set
1510
+ // as its text's, `<table align="center">` — the frame of nearly
1511
+ // every mail — stood at the left with its cells' text centred
1512
+ if (side === 'center') {
1513
+ push('margin-left', 'auto');
1514
+ push('margin-right', 'auto');
1515
+ }
1516
+ }
1517
+ else if (ALIGNS_BLOCKS.has(tag) &&
1518
+ (side === 'center' || side === 'left' || side === 'right')) {
1519
+ // these align the blocks in them as well as their text (HTML's
1520
+ // rendering, "align descendants"): the table a `<td align="center">`
1521
+ // or a `<div align="center">` holds is centred in it
1522
+ push('text-align', `-webkit-${side}`);
1523
+ }
1524
+ else if (side === 'center')
443
1525
  push('text-align', 'center');
444
1526
  else if (v === 'left' || v === 'right' || v === 'justify')
445
1527
  push('text-align', v);
@@ -447,9 +1529,42 @@ function presentationHints(el) {
447
1529
  const valign = attr(el, 'valign');
448
1530
  if (valign)
449
1531
  push('vertical-align', valign.toLowerCase());
1532
+ // HTML's `dir` is its element's `direction`: `<table dir="rtl">` starts
1533
+ // at the right, and a Hebrew or an Arabic message is written this way
1534
+ const dir = attr(el, 'dir')?.toLowerCase();
1535
+ if (dir === 'rtl' || dir === 'ltr')
1536
+ push('direction', dir);
1537
+ // and it isolates the element from the text around it, or with `auto`
1538
+ // takes its first strong letter's direction (HTML's UA sheet: `[dir]`,
1539
+ // `[dir=auto i]`, `bdo[dir]`)
1540
+ if (dir !== undefined) {
1541
+ push('unicode-bidi', tag === 'bdo'
1542
+ ? 'isolate-override'
1543
+ : dir === 'auto'
1544
+ ? 'plaintext'
1545
+ : 'isolate');
1546
+ }
450
1547
  const bgcolor = attr(el, 'bgcolor');
451
1548
  if (bgcolor)
452
1549
  push('background-color', bgcolor);
1550
+ if (BACKGROUNDS.has(tag)) {
1551
+ const background = attr(el, 'background')?.trim();
1552
+ if (background) {
1553
+ push('background-image', `url("${background.replace(/["\\\n]/g, '')}")`);
1554
+ }
1555
+ }
1556
+ if (tag === 'body') {
1557
+ // the text's colour, and the links'
1558
+ const text = attr(el, 'text');
1559
+ if (text)
1560
+ push('color', text);
1561
+ }
1562
+ else if (tag === 'a' && attr(el, 'href') !== undefined) {
1563
+ const body = closestBody(el);
1564
+ const link = body ? attr(body, 'link') : undefined;
1565
+ if (link)
1566
+ push('color', link);
1567
+ }
453
1568
  const color = attr(el, 'color');
454
1569
  if (color && (tag === 'font' || tag === 'basefont'))
455
1570
  push('color', color);
@@ -472,6 +1587,27 @@ function presentationHints(el) {
472
1587
  const height = attr(el, 'height');
473
1588
  if (height)
474
1589
  push('height', lengthAttr(height));
1590
+ // and, both numbers, an image's the ratio it has before it loads, or
1591
+ // where it has none of its own (HTML 15.4.3, "map to the aspect-ratio
1592
+ // property")
1593
+ if (width && height && RATIO_SIZED.has(tag)) {
1594
+ const w = parseFloat(width);
1595
+ const h = parseFloat(height);
1596
+ if (w > 0 && h > 0 && !/%/.test(width + height)) {
1597
+ push('aspect-ratio', `auto ${w} / ${h}`);
1598
+ }
1599
+ }
1600
+ }
1601
+ else if (tag === 'svg') {
1602
+ // an SVG's are CSS lengths of their own, units and all (SVG 2, 5.1.1)
1603
+ const width = attr(el, 'width');
1604
+ const w = width ? svgSizeHint(width) : null;
1605
+ if (w)
1606
+ push('width', w);
1607
+ const height = attr(el, 'height');
1608
+ const h = height ? svgSizeHint(height) : null;
1609
+ if (h)
1610
+ push('height', h);
475
1611
  }
476
1612
  if (tag === 'table') {
477
1613
  const border = attr(el, 'border');
@@ -496,15 +1632,54 @@ function presentationHints(el) {
496
1632
  const noshade = attr(el, 'noshade');
497
1633
  if (noshade !== undefined)
498
1634
  push('border-top-width', '2px');
1635
+ // the rule's colour and its thickness
1636
+ const color = attr(el, 'color');
1637
+ if (color)
1638
+ push('border-top-color', color);
1639
+ const size = attr(el, 'size');
1640
+ if (size && Number(size) > 0)
1641
+ push('border-top-width', `${Number(size)}px`);
1642
+ }
1643
+ if ((tag === 'td' || tag === 'th') && attr(el, 'nowrap') !== undefined) {
1644
+ push('white-space', 'nowrap');
1645
+ }
1646
+ if (tag === 'br') {
1647
+ // below the floats: `<br clear="all">` after a floated image
1648
+ const clear = attr(el, 'clear')?.toLowerCase();
1649
+ if (clear === 'all' || clear === 'both')
1650
+ push('clear', 'both');
1651
+ else if (clear === 'left' || clear === 'right')
1652
+ push('clear', clear);
499
1653
  }
500
1654
  if (tag === 'ol') {
501
1655
  const type = attr(el, 'type');
502
1656
  const mapped = OL_TYPES[type ?? ''];
503
1657
  if (mapped)
504
1658
  push('list-style-type', mapped);
505
- const start = attr(el, 'start');
506
- if (start)
507
- push('counter-reset', start);
1659
+ // the number a list starts at is its `list-item` counter's, one before
1660
+ // it, or counting down one after it (HTML's rendering, "Lists")
1661
+ const start = htmlInteger(attr(el, 'start'));
1662
+ if (start !== null) {
1663
+ push('counter-reset', attr(el, 'reversed') !== undefined
1664
+ ? `reversed(list-item) ${start + 1}`
1665
+ : `list-item ${start - 1}`);
1666
+ }
1667
+ }
1668
+ if (tag === 'ul') {
1669
+ const type = attr(el, 'type')?.toLowerCase();
1670
+ if (type && BULLETS.has(type))
1671
+ push('list-style-type', type);
1672
+ }
1673
+ if (tag === 'li') {
1674
+ // an item's `value` is the number it goes on from
1675
+ const value = htmlInteger(attr(el, 'value'));
1676
+ if (value !== null)
1677
+ push('counter-set', `list-item ${value}`);
1678
+ const type = attr(el, 'type');
1679
+ const mapped = OL_TYPES[type ?? ''] ??
1680
+ (type && BULLETS.has(type.toLowerCase()) ? type.toLowerCase() : null);
1681
+ if (mapped)
1682
+ push('list-style-type', mapped);
508
1683
  }
509
1684
  if (tag === 'img' || tag === 'object') {
510
1685
  const hspace = attr(el, 'hspace');
@@ -520,6 +1695,51 @@ function presentationHints(el) {
520
1695
  }
521
1696
  return out;
522
1697
  }
1698
+ /** An image's `align` other than a side, as its `vertical-align`. */
1699
+ const IMAGE_ALIGN = {
1700
+ top: 'top',
1701
+ texttop: 'text-top',
1702
+ middle: 'middle',
1703
+ absmiddle: 'middle',
1704
+ center: 'middle',
1705
+ bottom: 'baseline',
1706
+ baseline: 'baseline',
1707
+ absbottom: 'bottom',
1708
+ };
1709
+ /** The elements whose `align` aligns the blocks in them too. */
1710
+ const ALIGNS_BLOCKS = new Set([
1711
+ 'div',
1712
+ 'caption',
1713
+ 'thead',
1714
+ 'tbody',
1715
+ 'tfoot',
1716
+ 'tr',
1717
+ 'td',
1718
+ 'th',
1719
+ ]);
1720
+ /** The elements a `background` attribute gives a background image. */
1721
+ const BACKGROUNDS = new Set([
1722
+ 'body',
1723
+ 'table',
1724
+ 'thead',
1725
+ 'tbody',
1726
+ 'tfoot',
1727
+ 'tr',
1728
+ 'td',
1729
+ 'th',
1730
+ ]);
1731
+ function closestBody(el) {
1732
+ let node = el.parent;
1733
+ while (node) {
1734
+ if (node.type === 'tag' && node.name === 'body') {
1735
+ return node;
1736
+ }
1737
+ node = node.parent;
1738
+ }
1739
+ return null;
1740
+ }
1741
+ /** What the `width` and `height` attributes give a ratio as well. */
1742
+ const RATIO_SIZED = new Set(['img', 'video']);
523
1743
  const SIZED = new Set([
524
1744
  'img',
525
1745
  'table',
@@ -529,7 +1749,6 @@ const SIZED = new Set([
529
1749
  'colgroup',
530
1750
  'iframe',
531
1751
  'video',
532
- 'canvas',
533
1752
  'object',
534
1753
  'embed',
535
1754
  'hr',
@@ -541,6 +1760,17 @@ const OL_TYPES = {
541
1760
  i: 'lower-roman',
542
1761
  I: 'upper-roman',
543
1762
  };
1763
+ /** What a `<ul type>` or an `<li type>` names that is not a number. */
1764
+ const BULLETS = new Set(['disc', 'circle', 'square', 'none']);
1765
+ /** An attribute read as HTML reads an integer: its leading digits, signed,
1766
+ * whatever follows them; null where it has none. A counter is a 32-bit
1767
+ * integer in a browser, and one past that is kept to it. */
1768
+ function htmlInteger(value) {
1769
+ const match = value === undefined ? null : /^\s*([+-]?\d+)/.exec(value);
1770
+ if (!match)
1771
+ return null;
1772
+ return Math.max(-2147483648, Math.min(2147483647, Number(match[1])));
1773
+ }
544
1774
  const FONT_SIZE_STEPS = [1, 0.63, 0.82, 1, 1.13, 1.5, 2, 3];
545
1775
  /** A presentational length: bare numbers are pixels, `50%` stays a percent. */
546
1776
  function lengthAttr(value) {
@@ -559,4 +1789,35 @@ function closestTable(el) {
559
1789
  }
560
1790
  return null;
561
1791
  }
1792
+ /** The generic fixed-width family's size to everyone else's: 13 to 16. */
1793
+ const FIXED_SIZE = 13 / 16;
1794
+ /** Whether a family list is the generic `monospace` and nothing else,
1795
+ * which has the smaller size; a list with a fallback after it does not,
1796
+ * so `monospace, monospace` keeps the size it had. */
1797
+ function monospaceOnly(family) {
1798
+ return family.length === 9 && family.toLowerCase() === 'monospace';
1799
+ }
1800
+ /** Whether a `font-size`, or the size in a `font`, is an absolute-size
1801
+ * keyword, or `initial`, which is `medium`. */
1802
+ function sizeKeyword(prop, value) {
1803
+ const words = value.trim().toLowerCase();
1804
+ if (prop === 'font-size')
1805
+ return ABSOLUTE_SIZES.has(words);
1806
+ for (const word of words.split(/[\s/]+/)) {
1807
+ if (ABSOLUTE_SIZES.has(word))
1808
+ return true;
1809
+ }
1810
+ return false;
1811
+ }
1812
+ const ABSOLUTE_SIZES = new Set([
1813
+ 'xx-small',
1814
+ 'x-small',
1815
+ 'small',
1816
+ 'medium',
1817
+ 'large',
1818
+ 'x-large',
1819
+ 'xx-large',
1820
+ 'xxx-large',
1821
+ 'initial',
1822
+ ]);
562
1823
  //# sourceMappingURL=cascade.js.map