@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
@@ -13,17 +13,22 @@
13
13
  // algorithm is too slow — which, on a table with a thousand rows, it is.
14
14
  import { AUTO, isPct, resolveOrNull } from '../css/values.js';
15
15
  import type { Len } from '../css/values.js';
16
- import { Box } from './boxes.js';
17
- import { measureIntrinsicWidth, moveTo, resolveEdges } from './block.js';
16
+ import { Box, CLIPPED_CELLS, COLLAPSED_CELLS, isBlank } from './boxes.js';
17
+ import {
18
+ CELL_CONTENT,
19
+ MIN_CONTENT_PROBE,
20
+ clampHeight,
21
+ exactMinContent,
22
+ layoutBlockIn,
23
+ measureIntrinsicWidth,
24
+ moveContent,
25
+ moveTo,
26
+ resolveEdges,
27
+ } from './block.js';
18
28
  import type { LayoutContext } from './block.js';
19
-
20
- interface Cell {
21
- box: Box;
22
- row: number;
23
- column: number;
24
- colSpan: number;
25
- rowSpan: number;
26
- }
29
+ import { firstBaselineIn } from './inline.js';
30
+ import { tableGrid } from './grid.js';
31
+ import type { Cell } from './grid.js';
27
32
 
28
33
  /** Lay out a table's insides. Returns the content height. */
29
34
  export function layoutTable(
@@ -31,67 +36,146 @@ export function layoutTable(
31
36
  ctx: LayoutContext,
32
37
  contentWidth: number,
33
38
  ): number {
34
- const rows: Box[] = [];
35
- const captions: Box[] = [];
36
- for (const child of table.children) {
37
- if (child.kind === 'table-caption') captions.push(child);
38
- else if (child.kind === 'table-row-group') {
39
- for (const row of child.children) {
40
- if (row.kind === 'table-row') rows.push(row);
39
+ const { rows, captions, cells, columnCount, columnBoxes, columnGroups } =
40
+ tableGrid(table);
41
+ table.captionTop = 0;
42
+ table.captionBottom = 0;
43
+ if (!columnCount) {
44
+ // With no columns, an auto table is as wide as its widest caption can
45
+ // be and its `min-width` asks, as one with columns is at the least
46
+ // (17.5.2), rather than as the room on offer: a caption over no cells
47
+ // was centred in the width of the page.
48
+ if (table.style.width === AUTO) {
49
+ let inner = captions.length
50
+ ? captionMinimum(captions, ctx) - table.horizontalExtra
51
+ : 0;
52
+ const min = resolveOrNull(table.style.minWidth, contentWidth);
53
+ if (min !== null) {
54
+ inner = Math.max(
55
+ inner,
56
+ table.style.boxSizing === 'border-box'
57
+ ? min - table.horizontalExtra
58
+ : min,
59
+ );
41
60
  }
42
- } else if (child.kind === 'table-row') rows.push(child);
61
+ table.width = Math.max(0, inner) + table.horizontalExtra;
62
+ }
63
+ layoutCaptions(captions, ctx, table);
64
+ return 0;
43
65
  }
44
66
 
45
- const { cells, columnCount } = gridOf(rows);
46
- if (!columnCount)
47
- return layoutCaptionsOnly(captions, ctx, table, contentWidth);
48
-
49
67
  const style = table.style;
50
- const spacing = style.borderCollapse === 'collapse' ? 0 : style.borderSpacing;
68
+ // between the columns, and between the rows (CSS 2.1 17.6.1)
69
+ const apart = style.borderCollapse !== 'collapse';
70
+ const spacing = apart ? style.borderSpacing : 0;
71
+ const rowSpacing = apart ? style.borderSpacingY : 0;
51
72
  const gaps = spacing * (columnCount + 1);
52
73
  const available = Math.max(0, contentWidth - gaps);
53
74
 
54
75
  for (const cell of cells) resolveEdges(cell.box, contentWidth);
55
76
 
56
- const widths =
57
- style.tableLayout === 'fixed'
58
- ? fixedColumns(table, cells, columnCount, available)
59
- : autoColumns(cells, columnCount, available, ctx, contentWidth);
77
+ // a fixed layout needs a width to be fixed to; with `auto` a table is laid
78
+ // out by its contents after all (CSS 2.1 17.5.2.1)
79
+ const fixed = style.tableLayout === 'fixed' && style.width !== AUTO;
80
+ // a percentage of the table's width less its spacing (CSS 2.1 17.5.2.1)
81
+ const set = columnWidths(columnBoxes, columnGroups, available);
82
+ const widths = fixed
83
+ ? fixedColumns(cells, set, columnCount, available, spacing)
84
+ : autoColumns(
85
+ cells,
86
+ set,
87
+ columnCount,
88
+ available,
89
+ ctx,
90
+ contentWidth,
91
+ style.width !== AUTO,
92
+ spacing,
93
+ );
60
94
 
61
95
  // --- place ---------------------------------------------------------------
62
- let y = table.contentY;
63
- for (const caption of captions) {
64
- resolveEdges(caption, contentWidth);
65
- ctx.layoutSubtree(caption, contentWidth);
66
- moveTo(caption, table.contentX, y);
67
- y += caption.height;
96
+ // An auto table is at least as wide as its widest caption can be (CSS 2.1
97
+ // 17.5.2), and as its `min-width` asks; the columns share what that adds.
98
+ if (style.width === AUTO) {
99
+ let room = 0;
100
+ if (captions.length) {
101
+ room = captionMinimum(captions, ctx) - table.horizontalExtra - gaps;
102
+ }
103
+ const min = resolveOrNull(style.minWidth, contentWidth);
104
+ if (min !== null) {
105
+ const inner =
106
+ style.boxSizing === 'border-box' ? min - table.horizontalExtra : min;
107
+ room = Math.max(room, inner - gaps);
108
+ }
109
+ const sum = widths.reduce((a, b) => a + b, 0);
110
+ if (room > sum) {
111
+ for (let c = 0; c < columnCount; c += 1) {
112
+ widths[c] +=
113
+ sum > 0
114
+ ? (widths[c] / sum) * (room - sum)
115
+ : (room - sum) / columnCount;
116
+ }
117
+ }
68
118
  }
69
119
 
120
+ // A column that `visibility: collapse` takes out of the table has been
121
+ // sized with the rest, and is no room at all where they are placed (CSS
122
+ // 2.1 17.5.5): no width, and no spacing after it. Its cells are still
123
+ // laid out at the width they would have had, so that taking it out
124
+ // changes no row's height.
70
125
  const columnX: number[] = new Array<number>(columnCount);
126
+ const gone: boolean[] = new Array<boolean>(columnCount);
127
+ let anyGone = false;
71
128
  let x = table.contentX + spacing;
72
129
  for (let c = 0; c < columnCount; c += 1) {
73
130
  columnX[c] = x;
74
- x += widths[c] + spacing;
131
+ gone[c] = collapsedColumn(columnBoxes[c], columnGroups[c]);
132
+ if (gone[c]) anyGone = true;
133
+ else x += widths[c] + spacing;
75
134
  }
76
135
  // A table with `width: auto` is as wide as its columns need, not as wide as
77
136
  // its container — it shrinks to fit, which is what makes a two-column table
78
137
  // in a wide document a small table rather than a pair of columns stranded
79
138
  // at the left of a full-width box. The columns were sized against the space
80
- // on offer, so this only ever narrows.
81
- const used = Math.min(x - table.contentX, contentWidth);
82
- const tableContentWidth = style.width === AUTO ? used : contentWidth;
83
- if (style.width === AUTO)
139
+ // on offer, so this narrows it — but never past the least its columns can
140
+ // be (CSS 2.1 17.5.2.2): a table whose words do not fit is wider than the
141
+ // room, as a word is, and one beside a float goes below it.
142
+ //
143
+ // A table set to a width is as wide as it or its columns, whichever is the
144
+ // wider: columns set wider than the table widen it. A column taken out
145
+ // gives its room back either way, set width or not.
146
+ const used = x - table.contentX;
147
+ let tableContentWidth = contentWidth;
148
+ if (style.width === AUTO) {
149
+ tableContentWidth = used;
84
150
  table.width = tableContentWidth + table.horizontalExtra;
151
+ } else if (used > contentWidth || anyGone) {
152
+ tableContentWidth = used;
153
+ table.width = used + table.horizontalExtra;
154
+ }
155
+ layoutCaptions(captions, ctx, table);
85
156
 
157
+ const top = table.contentY + table.captionTop;
158
+ let y = top;
86
159
  const rowTop: number[] = new Array<number>(rows.length);
87
160
  const rowHeight: number[] = new Array<number>(rows.length).fill(0);
88
- y += spacing;
161
+ y += rowSpacing;
89
162
 
90
163
  // Size every cell at its column width first, so a row's height is the
91
- // tallest cell in it rather than the first one that was measured.
92
- for (const cell of cells) {
164
+ // tallest cell in it rather than the first one that was measured. What
165
+ // its content came to is kept apart from a height the cell sets: it is
166
+ // that content `vertical-align` moves in the cell.
167
+ const natural: number[] = new Array<number>(cells.length);
168
+ for (let i = 0; i < cells.length; i += 1) {
169
+ const cell = cells[i];
93
170
  const width = spannedWidth(widths, cell, spacing);
94
171
  ctx.layoutSubtree(cell.box, width);
172
+ natural[i] = CELL_CONTENT.get(cell.box) ?? cell.box.height;
173
+ // A height a cell sets is a least one: its content is laid out as a
174
+ // block's, which keeps a height it sets and lets the content run out of
175
+ // it, and a cell does not. `<td height="10">` with a line in it is as
176
+ // tall as the line (CSS 2.1 17.5.3), where it was 10px with the line
177
+ // hanging out of it.
178
+ if (natural[i] > cell.box.height) cell.box.height = natural[i];
95
179
  const specified = resolveOrNull(cell.box.style.height, NaN);
96
180
  if (specified !== null) {
97
181
  cell.box.height = Math.max(
@@ -100,9 +184,18 @@ export function layoutTable(
100
184
  );
101
185
  }
102
186
  }
103
- for (const cell of cells) {
187
+ // A cell aligned on the baseline — every value but `top`, `middle` and
188
+ // `bottom` — hangs its first line on its first row's baseline, the lowest
189
+ // of theirs from the row's top (CSS 2.1 17.5.3), and the row is as tall as
190
+ // the cells hung from it need.
191
+ const lift = baselineLifts(cells, rows.length);
192
+ for (let i = 0; i < cells.length; i += 1) {
193
+ const cell = cells[i];
104
194
  if (cell.rowSpan > 1) continue;
105
- rowHeight[cell.row] = Math.max(rowHeight[cell.row], cell.box.height);
195
+ rowHeight[cell.row] = Math.max(
196
+ rowHeight[cell.row],
197
+ lift[i] + cell.box.height,
198
+ );
106
199
  }
107
200
  for (let r = 0; r < rows.length; r += 1) {
108
201
  const specified = resolveOrNull(rows[r].style.height, NaN);
@@ -111,76 +204,229 @@ export function layoutTable(
111
204
  // A row-spanning cell only forces height when the rows it covers do not
112
205
  // already provide it — otherwise a `rowspan="3"` cell would make each of
113
206
  // its three rows as tall as all of it.
114
- for (const cell of cells) {
207
+ for (let i = 0; i < cells.length; i += 1) {
208
+ const cell = cells[i];
115
209
  if (cell.rowSpan <= 1) continue;
116
210
  const last = Math.min(rows.length - 1, cell.row + cell.rowSpan - 1);
117
211
  let covered = 0;
118
212
  for (let r = cell.row; r <= last; r += 1) covered += rowHeight[r];
119
- covered += spacing * (last - cell.row);
120
- const missing = cell.box.height - covered;
213
+ covered += rowSpacing * (last - cell.row);
214
+ const missing = lift[i] + cell.box.height - covered;
121
215
  if (missing > 0) rowHeight[last] += missing;
122
216
  }
123
217
 
218
+ // A table's own height, within its least and greatest, is a least
219
+ // height: what its rows come short of it goes to them (CSS 2.1 17.5.3,
220
+ // which leaves how to its user agents: `growRows`)
221
+ const wanted = resolveOrNull(style.height, table.percentHeightBase);
222
+ if (rows.length) {
223
+ const extraBox = table.verticalExtra;
224
+ const set =
225
+ wanted === null
226
+ ? 0
227
+ : style.boxSizing === 'border-box'
228
+ ? wanted
229
+ : wanted + extraBox;
230
+ const inner = clampHeight(table, set) - extraBox;
231
+ let total = 0;
232
+ for (const h of rowHeight) total += h;
233
+ const extra = inner - total - rowSpacing * (rows.length + 1);
234
+ if (extra > 0) growRows(rowHeight, rowSizing(rows, cells), extra, inner);
235
+ }
236
+
237
+ // And a row it takes out has sized the columns with the rest, and is as
238
+ // tall as nothing, with no spacing after it; its cells inherit the value,
239
+ // and are not drawn.
240
+ const rowGone: boolean[] = new Array<boolean>(rows.length);
124
241
  for (let r = 0; r < rows.length; r += 1) {
125
242
  rowTop[r] = y;
126
- y += rowHeight[r] + spacing;
243
+ rowGone[r] = rows[r].style.visibility === 'collapse';
244
+ if (rowGone[r]) rowHeight[r] = 0;
245
+ else y += rowHeight[r] + rowSpacing;
127
246
  }
128
247
 
129
- for (const cell of cells) {
248
+ for (let i = 0; i < cells.length; i += 1) {
249
+ const cell = cells[i];
130
250
  const last = Math.min(rows.length - 1, cell.row + cell.rowSpan - 1);
131
251
  let height = 0;
132
- for (let r = cell.row; r <= last; r += 1) height += rowHeight[r];
133
- height += spacing * (last - cell.row);
134
- const width = spannedWidth(widths, cell, spacing);
252
+ let clip = false;
253
+ for (let r = cell.row; r <= last; r += 1) {
254
+ height += rowHeight[r];
255
+ if (r > cell.row && rowGone[r]) clip = true;
256
+ }
257
+ height += rowSpacing * (last - cell.row);
258
+ if (clip) {
259
+ // down to the last of its rows left in the table, whose spacing went
260
+ // with the rows taken out
261
+ let bottom = rowTop[cell.row] + rowHeight[cell.row];
262
+ for (let r = cell.row + 1; r <= last; r += 1) {
263
+ if (!rowGone[r]) bottom = rowTop[r] + rowHeight[r];
264
+ }
265
+ height = bottom - rowTop[cell.row];
266
+ }
267
+ let width = spannedWidth(widths, cell, spacing);
268
+ // Where its columns are: a cell spanning a column taken out is laid out
269
+ // across all of them, moved left by the width of the ones before the
270
+ // first left in, and clipped to the ones left, which cuts out what was
271
+ // in those (CSS 2.1 17.5.5). The spacing after them goes from the end
272
+ // of its content, which does not line up with the columns it spans.
273
+ // One wholly in them is not drawn.
274
+ let placeX = columnX[cell.column];
275
+ let boxX = placeX;
276
+ if (anyGone) {
277
+ const lastColumn = Math.min(
278
+ columnCount - 1,
279
+ cell.column + cell.colSpan - 1,
280
+ );
281
+ let first = -1;
282
+ let end = -1;
283
+ let before = 0;
284
+ let some = false;
285
+ for (let c = cell.column; c <= lastColumn; c += 1) {
286
+ if (!gone[c]) {
287
+ if (first < 0) first = c;
288
+ end = c;
289
+ } else {
290
+ if (first < 0) before += (some ? spacing : 0) + widths[c];
291
+ some = true;
292
+ }
293
+ }
294
+ if (first < 0) COLLAPSED_CELLS.add(cell.box);
295
+ else if (some) {
296
+ clip = true;
297
+ boxX = columnX[first];
298
+ placeX = boxX - before;
299
+ width = columnX[end] + widths[end] - boxX;
300
+ }
301
+ }
135
302
  const inner = cell.box.height;
136
303
  // `vertical-align` inside a cell moves the *content*, not the box: the
137
- // box fills the row, and the content sits top, middle or bottom in it.
138
- let offset = 0;
304
+ // box fills the row, background and all, and the content sits top,
305
+ // middle, bottom or on the row's baseline in it — in the box a height
306
+ // of its own makes too, which is no content to be moved
307
+ let offset = lift[i];
139
308
  const va = cell.box.style.verticalAlign;
140
- if (va === 'middle') offset = Math.max(0, (height - inner) / 2);
141
- else if (va === 'bottom') offset = Math.max(0, height - inner);
142
- moveTo(cell.box, columnX[cell.column], rowTop[cell.row] + offset);
309
+ const content = natural[i];
310
+ const room = Math.max(height, inner);
311
+ if (va === 'middle') offset = Math.max(0, (room - content) / 2);
312
+ else if (va === 'bottom') offset = Math.max(0, room - content);
313
+ moveTo(cell.box, placeX, rowTop[cell.row]);
314
+ moveContent(cell.box, offset);
315
+ cell.box.x = boxX;
143
316
  cell.box.width = width;
144
- cell.box.height = Math.max(inner, height - offset);
317
+ if (clip) {
318
+ cell.box.height = height;
319
+ CLIPPED_CELLS.add(cell.box);
320
+ } else {
321
+ cell.box.height = Math.max(inner, height);
322
+ }
145
323
  }
146
324
 
325
+ // where the grid lines fell, for the collapsed borders drawn along them
326
+ const collapsed = table.collapsed;
327
+ if (collapsed && collapsed.columns === columnCount) {
328
+ const last = columnCount - 1;
329
+ collapsed.lineX = columnX.map((cx) => cx - table.x);
330
+ collapsed.lineX.push(columnX[last] + widths[last] - table.x);
331
+ collapsed.lineY = rowTop.map((ry) => ry - table.y);
332
+ const bottom = rows.length - 1;
333
+ collapsed.lineY.push(rowTop[bottom] + rowHeight[bottom] - table.y);
334
+ }
335
+
336
+ // A row, and a group of them, spans the columns: from the first one's
337
+ // left edge to the last one's right, the spacing around them outside it
338
+ // (CSS 2.1 17.5.1), as it is above and below.
339
+ const gridX = table.contentX + spacing;
340
+ const gridWidth = Math.max(0, x - spacing - gridX);
147
341
  for (let r = 0; r < rows.length; r += 1) {
148
342
  const row = rows[r];
149
- row.x = table.contentX;
343
+ row.x = gridX;
150
344
  row.y = rowTop[r];
151
- row.width = tableContentWidth;
345
+ row.width = gridWidth;
152
346
  row.height = rowHeight[r];
153
347
  }
154
348
  for (const child of table.children) {
155
349
  if (child.kind !== 'table-row-group') continue;
156
350
  const groupRows = child.children.filter((row) => row.kind === 'table-row');
157
351
  if (!groupRows.length) continue;
158
- child.x = table.contentX;
352
+ child.x = gridX;
159
353
  child.y = groupRows[0].y;
160
- child.width = tableContentWidth;
354
+ child.width = gridWidth;
161
355
  child.height =
162
356
  groupRows[groupRows.length - 1].y +
163
357
  groupRows[groupRows.length - 1].height -
164
358
  child.y;
165
359
  }
166
360
 
167
- return y - table.contentY;
361
+ return y - top;
168
362
  }
169
363
 
170
- function layoutCaptionsOnly(
171
- captions: Box[],
172
- ctx: LayoutContext,
173
- table: Box,
174
- contentWidth: number,
175
- ): number {
176
- let y = table.contentY;
364
+ /** Whether `visibility: collapse` takes a column out: its own, or the
365
+ * column group's that holds it with no column box of its own. */
366
+ function collapsedColumn(column: Box | null, group: Box | null): boolean {
367
+ return (column ?? group)?.style.visibility === 'collapse';
368
+ }
369
+
370
+ /**
371
+ * A table's captions, which are outside the table box (CSS 2.1 17.4): as
372
+ * wide as its border box, the ones on top above its border, and the ones
373
+ * at the bottom laid out here and placed below it by `finishCaptions`,
374
+ * once the table's height is known.
375
+ */
376
+ function layoutCaptions(captions: Box[], ctx: LayoutContext, table: Box): void {
377
+ let y = table.y;
177
378
  for (const caption of captions) {
178
- resolveEdges(caption, contentWidth);
179
- ctx.layoutSubtree(caption, contentWidth);
180
- moveTo(caption, table.contentX, y);
181
- y += caption.height;
379
+ // laid out at the offset its margins give it across the table, which
380
+ // is where it stays across
381
+ layoutBlockIn(caption, ctx, table.width);
382
+ const height = caption.marginTop + caption.height + caption.marginBottom;
383
+ if (caption.style.captionSide === 'bottom') {
384
+ table.captionBottom += height;
385
+ continue;
386
+ }
387
+ moveTo(caption, table.x + caption.x, y + caption.marginTop);
388
+ y += height;
389
+ table.captionTop += height;
182
390
  }
183
- return y - table.contentY;
391
+ }
392
+
393
+ /** The narrowest the widest caption can be, margins in: its own width
394
+ * where it has one, and its longest word where it has not. */
395
+ function captionMinimum(captions: Box[], ctx: LayoutContext): number {
396
+ let widest = 0;
397
+ for (const caption of captions) {
398
+ let width = measureIntrinsicWidth(caption, ctx, MIN_CONTENT_PROBE);
399
+ // and as wide as a length its own `width` sets: the probe lays it out
400
+ // at none, so an empty caption set to 100px measured nothing, and the
401
+ // table under it was as narrow as its cells
402
+ const set = caption.style.width;
403
+ if (set !== AUTO && !isPct(set)) {
404
+ const length = resolveOrNull(set, 0);
405
+ if (length !== null) {
406
+ const extra =
407
+ caption.style.boxSizing === 'border-box'
408
+ ? 0
409
+ : caption.horizontalExtra;
410
+ width = Math.max(width, length + extra);
411
+ }
412
+ }
413
+ widest = Math.max(widest, width + caption.marginLeft + caption.marginRight);
414
+ }
415
+ return widest;
416
+ }
417
+
418
+ /** The table box has its height: the captions go around it, the bottom
419
+ * ones below it, and the box grows to hold them. */
420
+ export function finishCaptions(table: Box): void {
421
+ if (!table.captionTop && !table.captionBottom) return;
422
+ let y = table.y + table.captionTop + table.height;
423
+ for (const caption of table.children) {
424
+ if (caption.kind !== 'table-caption') continue;
425
+ if (caption.style.captionSide !== 'bottom') continue;
426
+ moveTo(caption, table.x + caption.x, y + caption.marginTop);
427
+ y += caption.marginTop + caption.height + caption.marginBottom;
428
+ }
429
+ table.height += table.captionTop + table.captionBottom;
184
430
  }
185
431
 
186
432
  function spannedWidth(widths: number[], cell: Cell, spacing: number): number {
@@ -191,84 +437,69 @@ function spannedWidth(widths: number[], cell: Cell, spacing: number): number {
191
437
  }
192
438
 
193
439
  /**
194
- * Assign every cell a row and a column, honouring `colspan` and `rowspan`.
195
- * The occupancy grid is what makes a `rowspan` in an earlier row push a
196
- * later row's cells to the right, which is the bug every naive table
197
- * renderer ships with.
440
+ * `table-layout: fixed`: the columns and the first row decide, and the rest
441
+ * of the table is not measured at all, which is the whole point of it (CSS
442
+ * 2.1 17.5.2.1). A column with a `width` sets its own; failing that, a cell
443
+ * of the first row with one sets the columns it spans, by its border box and
444
+ * less the spacing between them; the columns left share what remains, and
445
+ * where nothing remains, what is left of a table wider than its columns is
446
+ * shared among all of them.
198
447
  */
199
- function gridOf(rows: Box[]): { cells: Cell[]; columnCount: number } {
200
- const cells: Cell[] = [];
201
- const occupied: boolean[][] = [];
202
- let columnCount = 0;
203
-
204
- const mark = (r: number, c: number): void => {
205
- (occupied[r] ??= [])[c] = true;
206
- };
207
- const taken = (r: number, c: number): boolean => occupied[r]?.[c] === true;
208
-
209
- for (let r = 0; r < rows.length; r += 1) {
210
- let c = 0;
211
- for (const box of rows[r].children) {
212
- if (box.kind !== 'table-cell') continue;
213
- while (taken(r, c)) c += 1;
214
- const colSpan = Math.max(1, spanAttr(box, 'colspan'));
215
- const rowSpan = Math.max(1, spanAttr(box, 'rowspan'));
216
- cells.push({ box, row: r, column: c, colSpan, rowSpan });
217
- for (let dr = 0; dr < rowSpan; dr += 1) {
218
- for (let dc = 0; dc < colSpan; dc += 1) mark(r + dr, c + dc);
219
- }
220
- c += colSpan;
221
- columnCount = Math.max(columnCount, c);
222
- }
223
- }
224
- return { cells, columnCount };
225
- }
226
-
227
- function spanAttr(box: Box, name: string): number {
228
- const raw = box.el?.attribs?.[name];
229
- if (!raw) return 1;
230
- const n = parseInt(raw, 10);
231
- return Number.isFinite(n) && n > 0 ? Math.min(n, 1000) : 1;
232
- }
233
-
234
- /** `table-layout: fixed` — the first row and any `width` decide, and the
235
- * rest of the table is not measured at all. That is the whole point of it. */
236
448
  function fixedColumns(
237
- table: Box,
238
449
  cells: Cell[],
450
+ columnWidths: (number | null)[],
239
451
  columnCount: number,
240
452
  available: number,
453
+ spacing: number,
241
454
  ): number[] {
242
455
  const widths: number[] = new Array<number>(columnCount).fill(0);
243
- const fixed: boolean[] = new Array<boolean>(columnCount).fill(false);
456
+ const set: boolean[] = new Array<boolean>(columnCount).fill(false);
457
+ for (let c = 0; c < columnCount; c += 1) {
458
+ const px = columnWidths[c];
459
+ if (px === null) continue;
460
+ widths[c] = px;
461
+ set[c] = true;
462
+ }
244
463
  for (const cell of cells) {
245
464
  if (cell.row > 0) break;
246
- const len = cell.box.style.width;
247
- if (len === AUTO) continue;
248
- const px = lengthAgainst(len, available);
465
+ const px = tableWidth(cell.box.style.width, available);
249
466
  if (px === null) continue;
250
- const per = px / cell.colSpan;
251
- for (
252
- let c = cell.column;
253
- c < cell.column + cell.colSpan && c < columnCount;
254
- c += 1
255
- ) {
256
- widths[c] = per;
257
- fixed[c] = true;
467
+ const box = cell.box;
468
+ const outer =
469
+ box.style.boxSizing === 'border-box'
470
+ ? Math.max(px, box.horizontalExtra)
471
+ : px + box.horizontalExtra;
472
+ const last = Math.min(columnCount, cell.column + cell.colSpan);
473
+ let taken = spacing * (last - cell.column - 1);
474
+ let open = 0;
475
+ for (let c = cell.column; c < last; c += 1) {
476
+ if (set[c]) taken += widths[c];
477
+ else open += 1;
258
478
  }
479
+ if (!open) continue;
480
+ const each = Math.max(0, outer - taken) / open;
481
+ for (let c = cell.column; c < last; c += 1) {
482
+ if (set[c]) continue;
483
+ widths[c] = each;
484
+ set[c] = true;
485
+ }
486
+ }
487
+ let used = 0;
488
+ let unset = 0;
489
+ for (let c = 0; c < columnCount; c += 1) {
490
+ if (set[c]) used += widths[c];
491
+ else unset += 1;
259
492
  }
260
- const used = widths.reduce((a, b) => a + b, 0);
261
493
  const remaining = Math.max(0, available - used);
262
- const autoCount = fixed.filter((f) => !f).length;
263
- const each = autoCount ? remaining / autoCount : 0;
264
- for (let c = 0; c < columnCount; c += 1) if (!fixed[c]) widths[c] = each;
265
- // A table narrower than its container keeps the width it asked for; one
266
- // wider than it is left wide and overflows, which is what a browser does
267
- // and what makes an oversized table scrollable rather than crushed.
268
- const total = widths.reduce((a, b) => a + b, 0);
269
- if (total < available && table.style.width !== AUTO) {
270
- const scale = available / (total || 1);
271
- for (let c = 0; c < columnCount; c += 1) widths[c] *= scale;
494
+ if (unset) {
495
+ for (let c = 0; c < columnCount; c += 1) {
496
+ if (!set[c]) widths[c] = remaining / unset;
497
+ }
498
+ } else if (remaining > 0 && columnCount) {
499
+ for (let c = 0; c < columnCount; c += 1) {
500
+ widths[c] +=
501
+ used > 0 ? (widths[c] / used) * remaining : remaining / columnCount;
502
+ }
272
503
  }
273
504
  return widths;
274
505
  }
@@ -285,22 +516,26 @@ function fixedColumns(
285
516
  */
286
517
  function autoColumns(
287
518
  cells: Cell[],
519
+ columnWidths: (number | null)[],
288
520
  columnCount: number,
289
521
  available: number,
290
522
  ctx: LayoutContext,
291
523
  containingWidth: number,
524
+ fill: boolean,
525
+ spacing: number,
292
526
  ): number[] {
293
527
  const max: number[] = new Array<number>(columnCount).fill(0);
294
528
  const min: number[] = new Array<number>(columnCount).fill(0);
295
529
  const explicit: (number | null)[] = new Array<number | null>(
296
530
  columnCount,
297
531
  ).fill(null);
532
+ const spanning: Cell[] = [];
298
533
 
299
534
  for (const cell of cells) {
300
- // Two probe layouts per cell: unconstrained for max-content, and at a
301
- // width of 1 for min-content — which the line breaker answers by
302
- // breaking at every opportunity, so the widest line is the longest
303
- // unbreakable word.
535
+ // Two probe layouts per cell: unconstrained for max-content, and at no
536
+ // width for min-content (`MIN_CONTENT_PROBE`) — which the line breaker
537
+ // answers by breaking at every opportunity, so the widest line is the
538
+ // longest unbreakable word.
304
539
  //
305
540
  // Cached on the box, because intrinsic widths are width-independent by
306
541
  // definition — measuring them per layout pass made a *resize* of a
@@ -313,68 +548,343 @@ function autoColumns(
313
548
  ctx,
314
549
  Infinity,
315
550
  );
316
- cell.box.intrinsicMinContent = measureIntrinsicWidth(cell.box, ctx, 1);
551
+ // where its words say it exactly, read from the layout just made
552
+ cell.box.intrinsicMinContent =
553
+ (ctx.fonts && exactMinContent(cell.box, ctx.fonts)) ??
554
+ measureIntrinsicWidth(cell.box, ctx, MIN_CONTENT_PROBE, true);
317
555
  }
318
- const cellMax = cell.box.intrinsicMaxContent;
319
- const cellMin = cell.box.intrinsicMinContent;
320
-
321
- const len = cell.box.style.width;
322
- const width = len === AUTO ? null : lengthAgainst(len, containingWidth);
323
- if (cell.colSpan === 1) {
324
- max[cell.column] = Math.max(max[cell.column], cellMax);
325
- min[cell.column] = Math.max(min[cell.column], cellMin);
326
- if (width !== null) {
327
- explicit[cell.column] = Math.max(
328
- explicit[cell.column] ?? 0,
329
- width + cell.box.horizontalExtra,
330
- );
331
- }
332
- } else {
333
- // A spanning cell contributes to its columns only when they cannot
334
- // already hold it, spread evenly — which is the spec's rule reduced to
335
- // the part that matters visually.
336
- const last = Math.min(columnCount - 1, cell.column + cell.colSpan - 1);
337
- let currentMax = 0;
338
- let currentMin = 0;
339
- for (let c = cell.column; c <= last; c += 1) {
340
- currentMax += max[c];
341
- currentMin += min[c];
342
- }
343
- const spread = last - cell.column + 1;
344
- if (cellMax > currentMax) {
345
- const each = (cellMax - currentMax) / spread;
346
- for (let c = cell.column; c <= last; c += 1) max[c] += each;
347
- }
348
- if (cellMin > currentMin) {
349
- const each = (cellMin - currentMin) / spread;
350
- for (let c = cell.column; c <= last; c += 1) min[c] += each;
351
- }
556
+ if (cell.colSpan > 1) {
557
+ spanning.push(cell);
558
+ continue;
559
+ }
560
+ max[cell.column] = Math.max(max[cell.column], cell.box.intrinsicMaxContent);
561
+ min[cell.column] = Math.max(min[cell.column], cell.box.intrinsicMinContent);
562
+ const width = cellWidth(cell, containingWidth);
563
+ if (width !== null) {
564
+ explicit[cell.column] = Math.max(explicit[cell.column] ?? 0, width);
352
565
  }
353
566
  }
354
567
 
568
+ // a column's own width counts as its cells' do: at least that, and its
569
+ // content's max where that is wider (CSS 2.1 17.5.2.2, step 2)
570
+ for (let c = 0; c < columnCount; c += 1) {
571
+ const own = columnWidths[c];
572
+ if (own !== null) explicit[c] = Math.max(explicit[c] ?? 0, own);
573
+ }
574
+
575
+ // A spanning cell comes after the cells of one column, the narrower
576
+ // spans first, and adds to its columns only what they come short of it
577
+ // (CSS 2.1 17.5.2.2, step 3). It holds the spacing between them too,
578
+ // room the columns need not find. What it adds goes to those of them
579
+ // with no width set, in proportion to their content, and evenly where
580
+ // they have none. Taken in document order and spread evenly, a spanning
581
+ // cell in a first row was shared out before the cells of one column
582
+ // under it were seen, and a column one of them set to 5px took half.
583
+ spanning.sort((a, b) => a.colSpan - b.colSpan);
584
+ const grow = (into: number[], want: number, cell: Cell): void => {
585
+ const last = Math.min(columnCount - 1, cell.column + cell.colSpan - 1);
586
+ let have = spacing * (last - cell.column);
587
+ for (let c = cell.column; c <= last; c += 1) have += into[c];
588
+ if (!(want > have)) return;
589
+ let free = false;
590
+ for (let c = cell.column; c <= last && !free; c += 1) {
591
+ free = explicit[c] === null;
592
+ }
593
+ let weight = 0;
594
+ let count = 0;
595
+ for (let c = cell.column; c <= last; c += 1) {
596
+ if (free && explicit[c] !== null) continue;
597
+ weight += max[c];
598
+ count += 1;
599
+ }
600
+ for (let c = cell.column; c <= last; c += 1) {
601
+ if (free && explicit[c] !== null) continue;
602
+ into[c] +=
603
+ weight > 0 ? ((want - have) * max[c]) / weight : (want - have) / count;
604
+ }
605
+ };
606
+
607
+ // what the columns' content alone asks, before their set widths: the
608
+ // least a column gives way to when the table has less room than its
609
+ // cells' widths want, as beside a float
610
+ const least = min.slice();
611
+ for (const cell of spanning) grow(least, cell.box.intrinsicMinContent, cell);
355
612
  for (let c = 0; c < columnCount; c += 1) {
356
613
  if (explicit[c] !== null) {
357
- max[c] = Math.max(max[c], explicit[c] as number);
614
+ max[c] = Math.max(min[c], explicit[c] as number);
358
615
  min[c] = Math.max(min[c], Math.min(explicit[c] as number, max[c]));
359
616
  }
360
- min[c] = Math.min(min[c], max[c]);
361
617
  }
618
+ // and with them: a spanning cell's own width is the least it is, as a
619
+ // single cell's is (step 1), so a cell over three columns set to 100px,
620
+ // with 20px between them, has 60 to share, where it had none
621
+ for (const cell of spanning) {
622
+ const own = cellWidth(cell, containingWidth) ?? 0;
623
+ grow(min, Math.max(cell.box.intrinsicMinContent, own), cell);
624
+ grow(max, Math.max(cell.box.intrinsicMaxContent, own), cell);
625
+ }
626
+ for (let c = 0; c < columnCount; c += 1) min[c] = Math.min(min[c], max[c]);
362
627
 
363
628
  const totalMax = max.reduce((a, b) => a + b, 0);
364
629
  if (totalMax <= available) {
365
- // Everything fits. A table with an explicit width still fills it, by
366
- // growing the columns in proportion to what they asked for.
367
- return max;
630
+ // Everything fits. A table with a width of its own still fills it (CSS
631
+ // 2.1 17.5.2.2): the columns not set to a width take the rest in
632
+ // proportion to what they asked for, or every column does where all are
633
+ // set. Returned as asked, `<table width="600">` drew its cells at their
634
+ // content's width and left the rest of its 600 empty.
635
+ if (!fill || available <= totalMax) return max;
636
+ const set = explicit.every((w) => w !== null);
637
+ let weight = 0;
638
+ let count = 0;
639
+ for (let c = 0; c < columnCount; c += 1) {
640
+ if (!set && explicit[c] !== null) continue;
641
+ weight += max[c];
642
+ count += 1;
643
+ }
644
+ const extra = available - totalMax;
645
+ return max.map((m, c) =>
646
+ !set && explicit[c] !== null
647
+ ? m
648
+ : m + (weight > 0 ? (extra * m) / weight : extra / count),
649
+ );
368
650
  }
369
651
  const totalMin = min.reduce((a, b) => a + b, 0);
370
- if (totalMin >= available) return min;
652
+ if (totalMin >= available) {
653
+ // Less room than the cells' widths want: a width a cell was set to
654
+ // gives way first, down to what its content asks, and a table never
655
+ // goes narrower than its words (CSS 2.1 17.5.2.2), which it overflows.
656
+ const totalLeast = least.reduce((a, b) => a + b, 0);
657
+ if (totalLeast >= available) return least;
658
+ const give = totalMin - totalLeast;
659
+ return min.map(
660
+ (m, c) => m - ((m - least[c]) / give) * (totalMin - available),
661
+ );
662
+ }
371
663
  const slack = available - totalMin;
372
664
  const surplus = totalMax - totalMin;
373
665
  return max.map((m, c) => min[c] + ((m - min[c]) / surplus) * slack);
374
666
  }
375
667
 
668
+ /**
669
+ * The width each column is set to, or null: a column's own `width`, or its
670
+ * group's shared among the columns of a group that has none of its own
671
+ * (HTML's `<colgroup span>`); and a group's `width` spread over its columns
672
+ * where theirs come to less (CSS 2.1 17.5.2.2, step 4). Each within its
673
+ * `min-width` and `max-width`, which apply to columns and column groups as
674
+ * to any block (10.4), so `min-width` alone sets one.
675
+ */
676
+ function columnWidths(
677
+ columnBoxes: (Box | null)[],
678
+ columnGroups: (Box | null)[],
679
+ base: number,
680
+ ): (number | null)[] {
681
+ const widths = columnBoxes.map((column) =>
682
+ column ? partWidth(column, base) : null,
683
+ );
684
+ let group: Box | null = null;
685
+ for (let c = 0; c <= columnGroups.length; c += 1) {
686
+ if (c < columnGroups.length && columnGroups[c] === group) continue;
687
+ // the group that ends here, over its columns from `start`
688
+ if (group) {
689
+ const width = partWidth(group, base);
690
+ let start = c - 1;
691
+ while (start > 0 && columnGroups[start - 1] === group) start -= 1;
692
+ if (width !== null) {
693
+ let have = 0;
694
+ for (let i = start; i < c; i += 1) have += widths[i] ?? 0;
695
+ if (have < width) {
696
+ const each = (width - have) / (c - start);
697
+ for (let i = start; i < c; i += 1) {
698
+ widths[i] = (widths[i] ?? 0) + each;
699
+ }
700
+ }
701
+ }
702
+ }
703
+ group = c < columnGroups.length ? columnGroups[c] : null;
704
+ }
705
+ return widths;
706
+ }
707
+
708
+ /** A column's or a column group's width, within its limits, or null where
709
+ * it sets none. */
710
+ function partWidth(box: Box, base: number): number | null {
711
+ const style = box.style;
712
+ const width = tableWidth(style.width, base);
713
+ const min = lengthAgainst(style.minWidth, base) ?? 0;
714
+ if (width === null && !(min > 0)) return null;
715
+ const max =
716
+ style.maxWidth === 'none' ? null : lengthAgainst(style.maxWidth, base);
717
+ let out = width ?? 0;
718
+ if (max !== null) out = Math.min(out, max);
719
+ return Math.max(0, out, min);
720
+ }
721
+
722
+ /** A cell's own `width`, its padding and borders in, or null. A
723
+ * percentage is a share of the table its padding and borders are part
724
+ * of, as browsers read it: added on, a 90% cell and a 10% one came to
725
+ * more than the table, which then took it back from both. Held within its
726
+ * `min-width` and `max-width` as a column's is (`partWidth`), which CSS
727
+ * 2.1 leaves undefined and every browser does: a cell set `width: 3in;
728
+ * max-width: 1in` is an inch wide, and one with `min-width` alone is as
729
+ * wide as that. */
730
+ function cellWidth(cell: Cell, base: number): number | null {
731
+ const style = cell.box.style;
732
+ const len = style.width;
733
+ const width = len === AUTO ? null : tableWidth(len, base);
734
+ const min = lengthAgainst(style.minWidth, base) ?? 0;
735
+ if (width === null && !(min > 0)) return null;
736
+ const max =
737
+ style.maxWidth === 'none' ? null : lengthAgainst(style.maxWidth, base);
738
+ let own = width ?? 0;
739
+ if (max !== null) own = Math.min(own, max);
740
+ own = Math.max(0, own, min);
741
+ if (isPct(len) && own === width) {
742
+ return Math.max(width, cell.box.horizontalExtra);
743
+ }
744
+ return own + cell.box.horizontalExtra;
745
+ }
746
+
747
+ /** A cell's or a column's width. One that adds a percentage to a length,
748
+ * a `calc()`, is `auto` in a table, as browsers read it: a column cannot be
749
+ * both a share of the table and a size of its own. */
750
+ function tableWidth(len: Len, base: number): number | null {
751
+ if (isPct(len) && (len.px || len.of)) return null;
752
+ return lengthAgainst(len, base);
753
+ }
754
+
376
755
  function lengthAgainst(len: Len, base: number): number | null {
377
756
  if (len === AUTO) return null;
378
- if (isPct(len)) return Number.isFinite(base) ? (len.pct / 100) * base : null;
379
- return len;
757
+ return resolveOrNull(len, base);
758
+ }
759
+
760
+ /**
761
+ * How far each cell's content moves down to put its baseline on its first
762
+ * row's: 0 for a cell aligned `top`, `middle` or `bottom`, which is placed
763
+ * once the row's height is known. A cell's baseline is its first line box's,
764
+ * at any depth, or the bottom of its content where it has none (CSS 2.1
765
+ * 17.5.3); it is taken as laid out, from the cell's top. An empty cell has
766
+ * nothing to align and says nothing about the row's, as in a browser: its
767
+ * content's bottom is its height, which would hang every other cell in the
768
+ * row from the bottom of a cell given a height and nothing in it.
769
+ */
770
+ function baselineLifts(cells: Cell[], rowCount: number): number[] {
771
+ const lift = new Array<number>(cells.length).fill(0);
772
+ let any = false;
773
+ for (const cell of cells) {
774
+ const va = cell.box.style.verticalAlign;
775
+ if (va !== 'top' && va !== 'middle' && va !== 'bottom') any = true;
776
+ }
777
+ if (!any) return lift;
778
+ const own = new Array<number>(cells.length).fill(NaN);
779
+ const row = new Array<number>(rowCount).fill(-Infinity);
780
+ for (let i = 0; i < cells.length; i += 1) {
781
+ const box = cells[i].box;
782
+ const va = box.style.verticalAlign;
783
+ if (va === 'top' || va === 'middle' || va === 'bottom') continue;
784
+ const first = firstBaselineIn(box);
785
+ if (first === null && !holdsFlow(box)) continue;
786
+ own[i] =
787
+ first !== null
788
+ ? first - box.y
789
+ : box.height - box.padBottom - box.borderBottom;
790
+ row[cells[i].row] = Math.max(row[cells[i].row], own[i]);
791
+ }
792
+ for (let i = 0; i < cells.length; i += 1) {
793
+ if (own[i] === own[i]) lift[i] = row[cells[i].row] - own[i];
794
+ }
795
+ return lift;
796
+ }
797
+
798
+ /** Whether a cell has anything in flow in it. */
799
+ function holdsFlow(box: Box): boolean {
800
+ for (const child of box.children) {
801
+ if (child.outOfFlow || child.isFloat) continue;
802
+ if (child.kind === 'text' && isBlank(child.text)) continue;
803
+ return true;
804
+ }
805
+ return false;
806
+ }
807
+
808
+ /** What a row's height is set as: a length its own or a cell's in it
809
+ * sets, which makes it constrained, and a percentage one does. */
810
+ interface RowSizing {
811
+ constrained: boolean;
812
+ percent: number | null;
813
+ }
814
+
815
+ function rowSizing(rows: Box[], cells: Cell[]): RowSizing[] {
816
+ const sizing = rows.map((row): RowSizing => {
817
+ const height = row.style.height;
818
+ return {
819
+ constrained: typeof height === 'number',
820
+ percent: height !== AUTO && isPct(height) ? height.pct : null,
821
+ };
822
+ });
823
+ for (const cell of cells) {
824
+ if (cell.rowSpan > 1 || !sizing[cell.row]) continue;
825
+ const height = cell.box.style.height;
826
+ const row = sizing[cell.row];
827
+ if (typeof height === 'number') row.constrained = true;
828
+ else if (height !== AUTO && isPct(height)) {
829
+ row.percent = Math.max(row.percent ?? 0, height.pct);
830
+ }
831
+ }
832
+ return sizing;
833
+ }
834
+
835
+ /**
836
+ * The height a table has past its rows' given out among them, as browsers
837
+ * give it (the CSS Tables 3 draft leaves it open, csswg-drafts#4418): first
838
+ * to the rows a percentage sets, up to it; then to the rows nothing sets
839
+ * that have content, in proportion to their heights; then, where every row
840
+ * with content is set, to the empty rows, those nothing sets first, evenly;
841
+ * and else to every row with content, in proportion. A row whose cells set
842
+ * its height keeps it while an empty row beside it takes the rest.
843
+ */
844
+ function growRows(
845
+ heights: number[],
846
+ sizing: RowSizing[],
847
+ extra: number,
848
+ base: number,
849
+ ): void {
850
+ const n = heights.length;
851
+ const deficit = heights.map((h, r) => {
852
+ const pct = sizing[r].percent;
853
+ return pct ? Math.max(0, (pct / 100) * base - h) : 0;
854
+ });
855
+ const empty: number[] = [];
856
+ const nothingSetEmpty: number[] = [];
857
+ const full: number[] = [];
858
+ const nothingSetFull: number[] = [];
859
+ let setFull = 0;
860
+ for (let r = 0; r < n; r += 1) {
861
+ const set = sizing[r].constrained || sizing[r].percent !== null;
862
+ if (heights[r] === 0 && deficit[r] === 0) {
863
+ empty.push(r);
864
+ if (!set) nothingSetEmpty.push(r);
865
+ } else {
866
+ full.push(r);
867
+ if (set) setFull += 1;
868
+ else nothingSetFull.push(r);
869
+ }
870
+ }
871
+ const owed = deficit.reduce((a, b) => a + b, 0);
872
+ if (owed > 0) {
873
+ const give = Math.min(owed, extra);
874
+ for (let r = 0; r < n; r += 1) heights[r] += (give * deficit[r]) / owed;
875
+ extra -= give;
876
+ if (!(extra > 0)) return;
877
+ }
878
+ const grow = (which: number[], even: boolean) => {
879
+ let sum = 0;
880
+ for (const r of which) sum += heights[r];
881
+ for (const r of which) {
882
+ heights[r] +=
883
+ even || !(sum > 0) ? extra / which.length : (extra * heights[r]) / sum;
884
+ }
885
+ };
886
+ if (nothingSetFull.length) grow(nothingSetFull, false);
887
+ else if (empty.length && empty.length + setFull === n) {
888
+ grow(nothingSetEmpty.length ? nothingSetEmpty : empty, true);
889
+ } else grow(full, false);
380
890
  }