@react-x11/components 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (783) hide show
  1. package/README.md +979 -21
  2. package/dist/ansi/cast.d.ts +48 -0
  3. package/dist/ansi/cast.d.ts.map +1 -0
  4. package/dist/ansi/cast.js +135 -0
  5. package/dist/ansi/cast.js.map +1 -0
  6. package/dist/ansi/index.d.ts +10 -0
  7. package/dist/ansi/index.d.ts.map +1 -0
  8. package/dist/ansi/index.js +27 -0
  9. package/dist/ansi/index.js.map +1 -0
  10. package/dist/ansi/palette.d.ts +79 -0
  11. package/dist/ansi/palette.d.ts.map +1 -0
  12. package/dist/ansi/palette.js +155 -0
  13. package/dist/ansi/palette.js.map +1 -0
  14. package/dist/ansi/parse.d.ts +114 -0
  15. package/dist/ansi/parse.d.ts.map +1 -0
  16. package/dist/ansi/parse.js +687 -0
  17. package/dist/ansi/parse.js.map +1 -0
  18. package/dist/ansi/sgr.d.ts +87 -0
  19. package/dist/ansi/sgr.d.ts.map +1 -0
  20. package/dist/ansi/sgr.js +302 -0
  21. package/dist/ansi/sgr.js.map +1 -0
  22. package/dist/ansi/utf8.d.ts +15 -0
  23. package/dist/ansi/utf8.d.ts.map +1 -0
  24. package/dist/ansi/utf8.js +82 -0
  25. package/dist/ansi/utf8.js.map +1 -0
  26. package/dist/calendar/Calendar.d.ts +136 -0
  27. package/dist/calendar/Calendar.d.ts.map +1 -0
  28. package/dist/calendar/Calendar.js +460 -0
  29. package/dist/calendar/Calendar.js.map +1 -0
  30. package/dist/calendar/DatePicker.d.ts +52 -0
  31. package/dist/calendar/DatePicker.d.ts.map +1 -0
  32. package/dist/calendar/DatePicker.js +257 -0
  33. package/dist/calendar/DatePicker.js.map +1 -0
  34. package/dist/calendar/dates.d.ts +90 -0
  35. package/dist/calendar/dates.d.ts.map +1 -0
  36. package/dist/calendar/dates.js +236 -0
  37. package/dist/calendar/dates.js.map +1 -0
  38. package/dist/calendar/index.d.ts +8 -0
  39. package/dist/calendar/index.d.ts.map +1 -0
  40. package/dist/calendar/index.js +15 -0
  41. package/dist/calendar/index.js.map +1 -0
  42. package/dist/charts/components.d.ts +141 -0
  43. package/dist/charts/components.d.ts.map +1 -0
  44. package/dist/charts/components.js +580 -0
  45. package/dist/charts/components.js.map +1 -0
  46. package/dist/charts/data.d.ts +198 -0
  47. package/dist/charts/data.d.ts.map +1 -0
  48. package/dist/charts/data.js +616 -0
  49. package/dist/charts/data.js.map +1 -0
  50. package/dist/charts/hx.d.ts +21 -0
  51. package/dist/charts/hx.d.ts.map +1 -0
  52. package/dist/charts/hx.js +15 -0
  53. package/dist/charts/hx.js.map +1 -0
  54. package/dist/charts/index.d.ts +27 -0
  55. package/dist/charts/index.d.ts.map +1 -0
  56. package/dist/charts/index.js +38 -0
  57. package/dist/charts/index.js.map +1 -0
  58. package/dist/charts/node.d.ts +96 -0
  59. package/dist/charts/node.d.ts.map +1 -0
  60. package/dist/charts/node.js +720 -0
  61. package/dist/charts/node.js.map +1 -0
  62. package/dist/charts/render.d.ts +153 -0
  63. package/dist/charts/render.d.ts.map +1 -0
  64. package/dist/charts/render.js +762 -0
  65. package/dist/charts/render.js.map +1 -0
  66. package/dist/charts/scale.d.ts +42 -0
  67. package/dist/charts/scale.d.ts.map +1 -0
  68. package/dist/charts/scale.js +173 -0
  69. package/dist/charts/scale.js.map +1 -0
  70. package/dist/charts/spec.d.ts +91 -0
  71. package/dist/charts/spec.d.ts.map +1 -0
  72. package/dist/charts/spec.js +33 -0
  73. package/dist/charts/spec.js.map +1 -0
  74. package/dist/charts/timers.d.ts +6 -0
  75. package/dist/charts/timers.d.ts.map +1 -0
  76. package/dist/charts/timers.js +14 -0
  77. package/dist/charts/timers.js.map +1 -0
  78. package/dist/code/hx.d.ts +24 -0
  79. package/dist/code/hx.d.ts.map +1 -0
  80. package/dist/code/hx.js +25 -0
  81. package/dist/code/hx.js.map +1 -0
  82. package/dist/code/index.d.ts +45 -0
  83. package/dist/code/index.d.ts.map +1 -0
  84. package/dist/code/index.js +93 -0
  85. package/dist/code/index.js.map +1 -0
  86. package/dist/code-editor/completion.d.ts +26 -0
  87. package/dist/code-editor/completion.d.ts.map +1 -0
  88. package/dist/code-editor/completion.js +129 -0
  89. package/dist/code-editor/completion.js.map +1 -0
  90. package/dist/code-editor/doc.d.ts +35 -0
  91. package/dist/code-editor/doc.d.ts.map +1 -0
  92. package/dist/code-editor/doc.js +162 -0
  93. package/dist/code-editor/doc.js.map +1 -0
  94. package/dist/code-editor/hx.d.ts +13 -0
  95. package/dist/code-editor/hx.d.ts.map +1 -0
  96. package/dist/code-editor/hx.js +10 -0
  97. package/dist/code-editor/hx.js.map +1 -0
  98. package/dist/code-editor/index.d.ts +88 -0
  99. package/dist/code-editor/index.d.ts.map +1 -0
  100. package/dist/code-editor/index.js +401 -0
  101. package/dist/code-editor/index.js.map +1 -0
  102. package/dist/code-editor/node.d.ts +343 -0
  103. package/dist/code-editor/node.d.ts.map +1 -0
  104. package/dist/code-editor/node.js +1521 -0
  105. package/dist/code-editor/node.js.map +1 -0
  106. package/dist/code-language/hljs.d.ts +47 -0
  107. package/dist/code-language/hljs.d.ts.map +1 -0
  108. package/dist/code-language/hljs.js +211 -0
  109. package/dist/code-language/hljs.js.map +1 -0
  110. package/dist/code-language/index.d.ts +22 -0
  111. package/dist/code-language/index.d.ts.map +1 -0
  112. package/dist/code-language/index.js +20 -0
  113. package/dist/code-language/index.js.map +1 -0
  114. package/dist/code-language/languages/glsl.d.ts +4 -0
  115. package/dist/code-language/languages/glsl.d.ts.map +1 -0
  116. package/dist/code-language/languages/glsl.js +99 -0
  117. package/dist/code-language/languages/glsl.js.map +1 -0
  118. package/dist/code-language/languages/javascript.d.ts +10 -0
  119. package/dist/code-language/languages/javascript.d.ts.map +1 -0
  120. package/dist/code-language/languages/javascript.js +360 -0
  121. package/dist/code-language/languages/javascript.js.map +1 -0
  122. package/dist/code-language/languages/json.d.ts +4 -0
  123. package/dist/code-language/languages/json.d.ts.map +1 -0
  124. package/dist/code-language/languages/json.js +68 -0
  125. package/dist/code-language/languages/json.js.map +1 -0
  126. package/dist/code-language/languages/shell.d.ts +4 -0
  127. package/dist/code-language/languages/shell.d.ts.map +1 -0
  128. package/dist/code-language/languages/shell.js +189 -0
  129. package/dist/code-language/languages/shell.js.map +1 -0
  130. package/dist/code-language/languages/sql.d.ts +11 -0
  131. package/dist/code-language/languages/sql.d.ts.map +1 -0
  132. package/dist/code-language/languages/sql.js +133 -0
  133. package/dist/code-language/languages/sql.js.map +1 -0
  134. package/dist/code-language/lezer.d.ts +24 -0
  135. package/dist/code-language/lezer.d.ts.map +1 -0
  136. package/dist/code-language/lezer.js +148 -0
  137. package/dist/code-language/lezer.js.map +1 -0
  138. package/dist/code-language/registry.d.ts +19 -0
  139. package/dist/code-language/registry.d.ts.map +1 -0
  140. package/dist/code-language/registry.js +56 -0
  141. package/dist/code-language/registry.js.map +1 -0
  142. package/dist/code-language/runs.d.ts +35 -0
  143. package/dist/code-language/runs.d.ts.map +1 -0
  144. package/dist/code-language/runs.js +88 -0
  145. package/dist/code-language/runs.js.map +1 -0
  146. package/dist/code-language/stream.d.ts +70 -0
  147. package/dist/code-language/stream.d.ts.map +1 -0
  148. package/dist/code-language/stream.js +243 -0
  149. package/dist/code-language/stream.js.map +1 -0
  150. package/dist/code-language/textmate.d.ts +27 -0
  151. package/dist/code-language/textmate.d.ts.map +1 -0
  152. package/dist/code-language/textmate.js +86 -0
  153. package/dist/code-language/textmate.js.map +1 -0
  154. package/dist/code-language/theme.d.ts +26 -0
  155. package/dist/code-language/theme.d.ts.map +1 -0
  156. package/dist/code-language/theme.js +108 -0
  157. package/dist/code-language/theme.js.map +1 -0
  158. package/dist/code-language/timers.d.ts +7 -0
  159. package/dist/code-language/timers.d.ts.map +1 -0
  160. package/dist/code-language/timers.js +22 -0
  161. package/dist/code-language/timers.js.map +1 -0
  162. package/dist/code-language/types.d.ts +173 -0
  163. package/dist/code-language/types.d.ts.map +1 -0
  164. package/dist/code-language/types.js +41 -0
  165. package/dist/code-language/types.js.map +1 -0
  166. package/dist/codeblock/index.d.ts +69 -0
  167. package/dist/codeblock/index.d.ts.map +1 -0
  168. package/dist/codeblock/index.js +85 -0
  169. package/dist/codeblock/index.js.map +1 -0
  170. package/dist/color-picker/ColorField.d.ts +39 -0
  171. package/dist/color-picker/ColorField.d.ts.map +1 -0
  172. package/dist/color-picker/ColorField.js +239 -0
  173. package/dist/color-picker/ColorField.js.map +1 -0
  174. package/dist/color-picker/ColorPicker.d.ts +109 -0
  175. package/dist/color-picker/ColorPicker.d.ts.map +1 -0
  176. package/dist/color-picker/ColorPicker.js +757 -0
  177. package/dist/color-picker/ColorPicker.js.map +1 -0
  178. package/dist/color-picker/color.d.ts +105 -0
  179. package/dist/color-picker/color.d.ts.map +1 -0
  180. package/dist/color-picker/color.js +313 -0
  181. package/dist/color-picker/color.js.map +1 -0
  182. package/dist/color-picker/index.d.ts +8 -0
  183. package/dist/color-picker/index.d.ts.map +1 -0
  184. package/dist/color-picker/index.js +19 -0
  185. package/dist/color-picker/index.js.map +1 -0
  186. package/dist/desktop-calendar/eds.d.ts +102 -0
  187. package/dist/desktop-calendar/eds.d.ts.map +1 -0
  188. package/dist/desktop-calendar/eds.js +356 -0
  189. package/dist/desktop-calendar/eds.js.map +1 -0
  190. package/dist/desktop-calendar/ical.d.ts +63 -0
  191. package/dist/desktop-calendar/ical.d.ts.map +1 -0
  192. package/dist/desktop-calendar/ical.js +57 -0
  193. package/dist/desktop-calendar/ical.js.map +1 -0
  194. package/dist/desktop-calendar/index.d.ts +72 -0
  195. package/dist/desktop-calendar/index.d.ts.map +1 -0
  196. package/dist/desktop-calendar/index.js +213 -0
  197. package/dist/desktop-calendar/index.js.map +1 -0
  198. package/dist/embed/client.d.ts +121 -0
  199. package/dist/embed/client.d.ts.map +1 -0
  200. package/dist/embed/client.js +203 -0
  201. package/dist/embed/client.js.map +1 -0
  202. package/dist/embed/host.d.ts +96 -0
  203. package/dist/embed/host.d.ts.map +1 -0
  204. package/dist/embed/host.js +266 -0
  205. package/dist/embed/host.js.map +1 -0
  206. package/dist/embed/index.d.ts +5 -0
  207. package/dist/embed/index.d.ts.map +1 -0
  208. package/dist/embed/index.js +13 -0
  209. package/dist/embed/index.js.map +1 -0
  210. package/dist/embed/timers.d.ts +6 -0
  211. package/dist/embed/timers.d.ts.map +1 -0
  212. package/dist/embed/timers.js +16 -0
  213. package/dist/embed/timers.js.map +1 -0
  214. package/dist/flow/draw.d.ts +45 -0
  215. package/dist/flow/draw.d.ts.map +1 -0
  216. package/dist/flow/draw.js +295 -0
  217. package/dist/flow/draw.js.map +1 -0
  218. package/dist/flow/index.d.ts +64 -0
  219. package/dist/flow/index.d.ts.map +1 -0
  220. package/dist/flow/index.js +306 -0
  221. package/dist/flow/index.js.map +1 -0
  222. package/dist/flow/model.d.ts +158 -0
  223. package/dist/flow/model.d.ts.map +1 -0
  224. package/dist/flow/model.js +566 -0
  225. package/dist/flow/model.js.map +1 -0
  226. package/dist/flow/node.d.ts +429 -0
  227. package/dist/flow/node.d.ts.map +1 -0
  228. package/dist/flow/node.js +3025 -0
  229. package/dist/flow/node.js.map +1 -0
  230. package/dist/flow/paths.d.ts +43 -0
  231. package/dist/flow/paths.d.ts.map +1 -0
  232. package/dist/flow/paths.js +327 -0
  233. package/dist/flow/paths.js.map +1 -0
  234. package/dist/flow/types.d.ts +561 -0
  235. package/dist/flow/types.d.ts.map +1 -0
  236. package/dist/flow/types.js +2 -0
  237. package/dist/flow/types.js.map +1 -0
  238. package/dist/formula/hx.d.ts +24 -0
  239. package/dist/formula/hx.d.ts.map +1 -0
  240. package/dist/formula/hx.js +25 -0
  241. package/dist/formula/hx.js.map +1 -0
  242. package/dist/formula/index.d.ts +74 -0
  243. package/dist/formula/index.d.ts.map +1 -0
  244. package/dist/formula/index.js +155 -0
  245. package/dist/formula/index.js.map +1 -0
  246. package/dist/formula/katex.d.ts +78 -0
  247. package/dist/formula/katex.d.ts.map +1 -0
  248. package/dist/formula/katex.js +130 -0
  249. package/dist/formula/katex.js.map +1 -0
  250. package/dist/formula/layout.d.ts +103 -0
  251. package/dist/formula/layout.d.ts.map +1 -0
  252. package/dist/formula/layout.js +716 -0
  253. package/dist/formula/layout.js.map +1 -0
  254. package/dist/formula/node.d.ts +50 -0
  255. package/dist/formula/node.d.ts.map +1 -0
  256. package/dist/formula/node.js +351 -0
  257. package/dist/formula/node.js.map +1 -0
  258. package/dist/html/controls.d.ts +48 -0
  259. package/dist/html/controls.d.ts.map +1 -0
  260. package/dist/html/controls.js +195 -0
  261. package/dist/html/controls.js.map +1 -0
  262. package/dist/html/css/cascade.d.ts +51 -0
  263. package/dist/html/css/cascade.d.ts.map +1 -0
  264. package/dist/html/css/cascade.js +552 -0
  265. package/dist/html/css/cascade.js.map +1 -0
  266. package/dist/html/css/parse.d.ts +74 -0
  267. package/dist/html/css/parse.d.ts.map +1 -0
  268. package/dist/html/css/parse.js +464 -0
  269. package/dist/html/css/parse.js.map +1 -0
  270. package/dist/html/css/style.d.ts +142 -0
  271. package/dist/html/css/style.d.ts.map +1 -0
  272. package/dist/html/css/style.js +1145 -0
  273. package/dist/html/css/style.js.map +1 -0
  274. package/dist/html/css/ua.d.ts +5 -0
  275. package/dist/html/css/ua.d.ts.map +1 -0
  276. package/dist/html/css/ua.js +171 -0
  277. package/dist/html/css/ua.js.map +1 -0
  278. package/dist/html/css/values.d.ts +78 -0
  279. package/dist/html/css/values.d.ts.map +1 -0
  280. package/dist/html/css/values.js +330 -0
  281. package/dist/html/css/values.js.map +1 -0
  282. package/dist/html/dom.d.ts +112 -0
  283. package/dist/html/dom.d.ts.map +1 -0
  284. package/dist/html/dom.js +374 -0
  285. package/dist/html/dom.js.map +1 -0
  286. package/dist/html/hx.d.ts +24 -0
  287. package/dist/html/hx.d.ts.map +1 -0
  288. package/dist/html/hx.js +29 -0
  289. package/dist/html/hx.js.map +1 -0
  290. package/dist/html/index.d.ts +137 -0
  291. package/dist/html/index.d.ts.map +1 -0
  292. package/dist/html/index.js +339 -0
  293. package/dist/html/index.js.map +1 -0
  294. package/dist/html/layout/block.d.ts +58 -0
  295. package/dist/html/layout/block.d.ts.map +1 -0
  296. package/dist/html/layout/block.js +724 -0
  297. package/dist/html/layout/block.js.map +1 -0
  298. package/dist/html/layout/boxes.d.ts +261 -0
  299. package/dist/html/layout/boxes.d.ts.map +1 -0
  300. package/dist/html/layout/boxes.js +725 -0
  301. package/dist/html/layout/boxes.js.map +1 -0
  302. package/dist/html/layout/flex.d.ts +16 -0
  303. package/dist/html/layout/flex.d.ts.map +1 -0
  304. package/dist/html/layout/flex.js +242 -0
  305. package/dist/html/layout/flex.js.map +1 -0
  306. package/dist/html/layout/floats.d.ts +50 -0
  307. package/dist/html/layout/floats.d.ts.map +1 -0
  308. package/dist/html/layout/floats.js +110 -0
  309. package/dist/html/layout/floats.js.map +1 -0
  310. package/dist/html/layout/inline.d.ts +44 -0
  311. package/dist/html/layout/inline.d.ts.map +1 -0
  312. package/dist/html/layout/inline.js +700 -0
  313. package/dist/html/layout/inline.js.map +1 -0
  314. package/dist/html/layout/table.d.ts +5 -0
  315. package/dist/html/layout/table.d.ts.map +1 -0
  316. package/dist/html/layout/table.js +340 -0
  317. package/dist/html/layout/table.js.map +1 -0
  318. package/dist/html/node.d.ts +149 -0
  319. package/dist/html/node.d.ts.map +1 -0
  320. package/dist/html/node.js +861 -0
  321. package/dist/html/node.js.map +1 -0
  322. package/dist/html/paint.d.ts +48 -0
  323. package/dist/html/paint.d.ts.map +1 -0
  324. package/dist/html/paint.js +495 -0
  325. package/dist/html/paint.js.map +1 -0
  326. package/dist/html/resources.d.ts +48 -0
  327. package/dist/html/resources.d.ts.map +1 -0
  328. package/dist/html/resources.js +156 -0
  329. package/dist/html/resources.js.map +1 -0
  330. package/dist/index.d.ts +48 -0
  331. package/dist/index.d.ts.map +1 -0
  332. package/dist/index.js +92 -0
  333. package/dist/index.js.map +1 -0
  334. package/dist/internal/heights.d.ts +81 -0
  335. package/dist/internal/heights.d.ts.map +1 -0
  336. package/dist/internal/heights.js +193 -0
  337. package/dist/internal/heights.js.map +1 -0
  338. package/dist/internal/hx.d.ts +24 -0
  339. package/dist/internal/hx.d.ts.map +1 -0
  340. package/dist/internal/hx.js +27 -0
  341. package/dist/internal/hx.js.map +1 -0
  342. package/dist/internal/text.d.ts +6 -0
  343. package/dist/internal/text.d.ts.map +1 -0
  344. package/dist/internal/text.js +44 -0
  345. package/dist/internal/text.js.map +1 -0
  346. package/dist/internal/timers.d.ts +8 -0
  347. package/dist/internal/timers.d.ts.map +1 -0
  348. package/dist/internal/timers.js +22 -0
  349. package/dist/internal/timers.js.map +1 -0
  350. package/dist/internal/widget.d.ts +40 -0
  351. package/dist/internal/widget.d.ts.map +1 -0
  352. package/dist/internal/widget.js +44 -0
  353. package/dist/internal/widget.js.map +1 -0
  354. package/dist/markdown/ast.d.ts +126 -0
  355. package/dist/markdown/ast.d.ts.map +1 -0
  356. package/dist/markdown/ast.js +8 -0
  357. package/dist/markdown/ast.js.map +1 -0
  358. package/dist/markdown/hx.d.ts +24 -0
  359. package/dist/markdown/hx.d.ts.map +1 -0
  360. package/dist/markdown/hx.js +25 -0
  361. package/dist/markdown/hx.js.map +1 -0
  362. package/dist/markdown/index.d.ts +90 -0
  363. package/dist/markdown/index.d.ts.map +1 -0
  364. package/dist/markdown/index.js +413 -0
  365. package/dist/markdown/index.js.map +1 -0
  366. package/dist/markdown/parse.d.ts +8 -0
  367. package/dist/markdown/parse.d.ts.map +1 -0
  368. package/dist/markdown/parse.js +911 -0
  369. package/dist/markdown/parse.js.map +1 -0
  370. package/dist/markdown/spans.d.ts +20 -0
  371. package/dist/markdown/spans.d.ts.map +1 -0
  372. package/dist/markdown/spans.js +96 -0
  373. package/dist/markdown/spans.js.map +1 -0
  374. package/dist/media-player/backends.d.ts +64 -0
  375. package/dist/media-player/backends.d.ts.map +1 -0
  376. package/dist/media-player/backends.js +110 -0
  377. package/dist/media-player/backends.js.map +1 -0
  378. package/dist/media-player/control.d.ts +40 -0
  379. package/dist/media-player/control.d.ts.map +1 -0
  380. package/dist/media-player/control.js +44 -0
  381. package/dist/media-player/control.js.map +1 -0
  382. package/dist/media-player/hx.d.ts +24 -0
  383. package/dist/media-player/hx.d.ts.map +1 -0
  384. package/dist/media-player/hx.js +25 -0
  385. package/dist/media-player/hx.js.map +1 -0
  386. package/dist/media-player/index.d.ts +107 -0
  387. package/dist/media-player/index.d.ts.map +1 -0
  388. package/dist/media-player/index.js +219 -0
  389. package/dist/media-player/index.js.map +1 -0
  390. package/dist/media-player/mpv.d.ts +4 -0
  391. package/dist/media-player/mpv.d.ts.map +1 -0
  392. package/dist/media-player/mpv.js +120 -0
  393. package/dist/media-player/mpv.js.map +1 -0
  394. package/dist/media-player/vlc.d.ts +8 -0
  395. package/dist/media-player/vlc.d.ts.map +1 -0
  396. package/dist/media-player/vlc.js +83 -0
  397. package/dist/media-player/vlc.js.map +1 -0
  398. package/dist/richtext/index.d.ts +19 -0
  399. package/dist/richtext/index.d.ts.map +1 -0
  400. package/dist/richtext/index.js +4 -0
  401. package/dist/richtext/index.js.map +1 -0
  402. package/dist/richtext/links.d.ts +12 -0
  403. package/dist/richtext/links.d.ts.map +1 -0
  404. package/dist/richtext/links.js +64 -0
  405. package/dist/richtext/links.js.map +1 -0
  406. package/dist/richtext/menu.d.ts +11 -0
  407. package/dist/richtext/menu.d.ts.map +1 -0
  408. package/dist/richtext/menu.js +43 -0
  409. package/dist/richtext/menu.js.map +1 -0
  410. package/dist/richtext/node.d.ts +151 -0
  411. package/dist/richtext/node.d.ts.map +1 -0
  412. package/dist/richtext/node.js +255 -0
  413. package/dist/richtext/node.js.map +1 -0
  414. package/dist/richtext/runs.d.ts +92 -0
  415. package/dist/richtext/runs.d.ts.map +1 -0
  416. package/dist/richtext/runs.js +158 -0
  417. package/dist/richtext/runs.js.map +1 -0
  418. package/dist/table/hx.d.ts +24 -0
  419. package/dist/table/hx.d.ts.map +1 -0
  420. package/dist/table/hx.js +25 -0
  421. package/dist/table/hx.js.map +1 -0
  422. package/dist/table/index.d.ts +169 -0
  423. package/dist/table/index.d.ts.map +1 -0
  424. package/dist/table/index.js +844 -0
  425. package/dist/table/index.js.map +1 -0
  426. package/dist/table/rows.d.ts +136 -0
  427. package/dist/table/rows.d.ts.map +1 -0
  428. package/dist/table/rows.js +146 -0
  429. package/dist/table/rows.js.map +1 -0
  430. package/dist/terminal/backends.d.ts +105 -0
  431. package/dist/terminal/backends.d.ts.map +1 -0
  432. package/dist/terminal/backends.js +185 -0
  433. package/dist/terminal/backends.js.map +1 -0
  434. package/dist/terminal/hx.d.ts +24 -0
  435. package/dist/terminal/hx.d.ts.map +1 -0
  436. package/dist/terminal/hx.js +25 -0
  437. package/dist/terminal/hx.js.map +1 -0
  438. package/dist/terminal/index.d.ts +160 -0
  439. package/dist/terminal/index.d.ts.map +1 -0
  440. package/dist/terminal/index.js +344 -0
  441. package/dist/terminal/index.js.map +1 -0
  442. package/dist/terminal/title.d.ts +24 -0
  443. package/dist/terminal/title.d.ts.map +1 -0
  444. package/dist/terminal/title.js +129 -0
  445. package/dist/terminal/title.js.map +1 -0
  446. package/dist/terminal/vt/colors.d.ts +63 -0
  447. package/dist/terminal/vt/colors.d.ts.map +1 -0
  448. package/dist/terminal/vt/colors.js +203 -0
  449. package/dist/terminal/vt/colors.js.map +1 -0
  450. package/dist/terminal/vt/diff.d.ts +117 -0
  451. package/dist/terminal/vt/diff.d.ts.map +1 -0
  452. package/dist/terminal/vt/diff.js +358 -0
  453. package/dist/terminal/vt/diff.js.map +1 -0
  454. package/dist/terminal/vt/fonts.d.ts +92 -0
  455. package/dist/terminal/vt/fonts.d.ts.map +1 -0
  456. package/dist/terminal/vt/fonts.js +178 -0
  457. package/dist/terminal/vt/fonts.js.map +1 -0
  458. package/dist/terminal/vt/index.d.ts +78 -0
  459. package/dist/terminal/vt/index.d.ts.map +1 -0
  460. package/dist/terminal/vt/index.js +312 -0
  461. package/dist/terminal/vt/index.js.map +1 -0
  462. package/dist/terminal/vt/keys.d.ts +74 -0
  463. package/dist/terminal/vt/keys.d.ts.map +1 -0
  464. package/dist/terminal/vt/keys.js +309 -0
  465. package/dist/terminal/vt/keys.js.map +1 -0
  466. package/dist/terminal/vt/mouse.d.ts +44 -0
  467. package/dist/terminal/vt/mouse.d.ts.map +1 -0
  468. package/dist/terminal/vt/mouse.js +106 -0
  469. package/dist/terminal/vt/mouse.js.map +1 -0
  470. package/dist/terminal/vt/node.d.ts +246 -0
  471. package/dist/terminal/vt/node.d.ts.map +1 -0
  472. package/dist/terminal/vt/node.js +1068 -0
  473. package/dist/terminal/vt/node.js.map +1 -0
  474. package/dist/terminal/vt/pty.d.ts +81 -0
  475. package/dist/terminal/vt/pty.d.ts.map +1 -0
  476. package/dist/terminal/vt/pty.js +201 -0
  477. package/dist/terminal/vt/pty.js.map +1 -0
  478. package/dist/terminal/vt/renderer.d.ts +179 -0
  479. package/dist/terminal/vt/renderer.d.ts.map +1 -0
  480. package/dist/terminal/vt/renderer.js +357 -0
  481. package/dist/terminal/vt/renderer.js.map +1 -0
  482. package/dist/terminal/vt/timers.d.ts +6 -0
  483. package/dist/terminal/vt/timers.d.ts.map +1 -0
  484. package/dist/terminal/vt/timers.js +16 -0
  485. package/dist/terminal/vt/timers.js.map +1 -0
  486. package/dist/terminal/vt/xterm.d.ts +142 -0
  487. package/dist/terminal/vt/xterm.d.ts.map +1 -0
  488. package/dist/terminal/vt/xterm.js +32 -0
  489. package/dist/terminal/vt/xterm.js.map +1 -0
  490. package/dist/terminal-output/hx.d.ts +24 -0
  491. package/dist/terminal-output/hx.d.ts.map +1 -0
  492. package/dist/terminal-output/hx.js +25 -0
  493. package/dist/terminal-output/hx.js.map +1 -0
  494. package/dist/terminal-output/index.d.ts +92 -0
  495. package/dist/terminal-output/index.d.ts.map +1 -0
  496. package/dist/terminal-output/index.js +179 -0
  497. package/dist/terminal-output/index.js.map +1 -0
  498. package/dist/terminal-output/runs.d.ts +27 -0
  499. package/dist/terminal-output/runs.d.ts.map +1 -0
  500. package/dist/terminal-output/runs.js +66 -0
  501. package/dist/terminal-output/runs.js.map +1 -0
  502. package/dist/three/canvas.d.ts +46 -0
  503. package/dist/three/canvas.d.ts.map +1 -0
  504. package/dist/three/canvas.js +305 -0
  505. package/dist/three/canvas.js.map +1 -0
  506. package/dist/three/events.d.ts +64 -0
  507. package/dist/three/events.d.ts.map +1 -0
  508. package/dist/three/events.js +146 -0
  509. package/dist/three/events.js.map +1 -0
  510. package/dist/three/geometries.d.ts +89 -0
  511. package/dist/three/geometries.d.ts.map +1 -0
  512. package/dist/three/geometries.js +345 -0
  513. package/dist/three/geometries.js.map +1 -0
  514. package/dist/three/globals.d.ts +7 -0
  515. package/dist/three/globals.d.ts.map +1 -0
  516. package/dist/three/globals.js +20 -0
  517. package/dist/three/globals.js.map +1 -0
  518. package/dist/three/hx.d.ts +9 -0
  519. package/dist/three/hx.d.ts.map +1 -0
  520. package/dist/three/hx.js +10 -0
  521. package/dist/three/hx.js.map +1 -0
  522. package/dist/three/index.d.ts +22 -0
  523. package/dist/three/index.d.ts.map +1 -0
  524. package/dist/three/index.js +24 -0
  525. package/dist/three/index.js.map +1 -0
  526. package/dist/three/jsx-dev-runtime.d.ts +19 -0
  527. package/dist/three/jsx-dev-runtime.d.ts.map +1 -0
  528. package/dist/three/jsx-dev-runtime.js +2 -0
  529. package/dist/three/jsx-dev-runtime.js.map +1 -0
  530. package/dist/three/jsx-runtime.d.ts +19 -0
  531. package/dist/three/jsx-runtime.d.ts.map +1 -0
  532. package/dist/three/jsx-runtime.js +2 -0
  533. package/dist/three/jsx-runtime.js.map +1 -0
  534. package/dist/three/jsx.d.ts +198 -0
  535. package/dist/three/jsx.d.ts.map +1 -0
  536. package/dist/three/jsx.js +2 -0
  537. package/dist/three/jsx.js.map +1 -0
  538. package/dist/three/materials.d.ts +125 -0
  539. package/dist/three/materials.d.ts.map +1 -0
  540. package/dist/three/materials.js +229 -0
  541. package/dist/three/materials.js.map +1 -0
  542. package/dist/three/math.d.ts +146 -0
  543. package/dist/three/math.d.ts.map +1 -0
  544. package/dist/three/math.js +464 -0
  545. package/dist/three/math.js.map +1 -0
  546. package/dist/three/objects.d.ts +185 -0
  547. package/dist/three/objects.d.ts.map +1 -0
  548. package/dist/three/objects.js +309 -0
  549. package/dist/three/objects.js.map +1 -0
  550. package/dist/three/passes.d.ts +54 -0
  551. package/dist/three/passes.d.ts.map +1 -0
  552. package/dist/three/passes.js +78 -0
  553. package/dist/three/passes.js.map +1 -0
  554. package/dist/three/postprocess.d.ts +85 -0
  555. package/dist/three/postprocess.d.ts.map +1 -0
  556. package/dist/three/postprocess.js +503 -0
  557. package/dist/three/postprocess.js.map +1 -0
  558. package/dist/three/raycast.d.ts +24 -0
  559. package/dist/three/raycast.d.ts.map +1 -0
  560. package/dist/three/raycast.js +138 -0
  561. package/dist/three/raycast.js.map +1 -0
  562. package/dist/three/reconciler.d.ts +48 -0
  563. package/dist/three/reconciler.d.ts.map +1 -0
  564. package/dist/three/reconciler.js +416 -0
  565. package/dist/three/reconciler.js.map +1 -0
  566. package/dist/three/renderer-direct.d.ts +102 -0
  567. package/dist/three/renderer-direct.d.ts.map +1 -0
  568. package/dist/three/renderer-direct.js +782 -0
  569. package/dist/three/renderer-direct.js.map +1 -0
  570. package/dist/three/renderer-indirect.d.ts +68 -0
  571. package/dist/three/renderer-indirect.d.ts.map +1 -0
  572. package/dist/three/renderer-indirect.js +438 -0
  573. package/dist/three/renderer-indirect.js.map +1 -0
  574. package/dist/three/store.d.ts +81 -0
  575. package/dist/three/store.d.ts.map +1 -0
  576. package/dist/three/store.js +110 -0
  577. package/dist/three/store.js.map +1 -0
  578. package/dist/timeline/hx.d.ts +18 -0
  579. package/dist/timeline/hx.d.ts.map +1 -0
  580. package/dist/timeline/hx.js +10 -0
  581. package/dist/timeline/hx.js.map +1 -0
  582. package/dist/timeline/index.d.ts +152 -0
  583. package/dist/timeline/index.d.ts.map +1 -0
  584. package/dist/timeline/index.js +383 -0
  585. package/dist/timeline/index.js.map +1 -0
  586. package/dist/tray-host/hx.d.ts +24 -0
  587. package/dist/tray-host/hx.d.ts.map +1 -0
  588. package/dist/tray-host/hx.js +25 -0
  589. package/dist/tray-host/hx.js.map +1 -0
  590. package/dist/tray-host/index.d.ts +110 -0
  591. package/dist/tray-host/index.d.ts.map +1 -0
  592. package/dist/tray-host/index.js +191 -0
  593. package/dist/tray-host/index.js.map +1 -0
  594. package/dist/tray-host/manager.d.ts +137 -0
  595. package/dist/tray-host/manager.d.ts.map +1 -0
  596. package/dist/tray-host/manager.js +462 -0
  597. package/dist/tray-host/manager.js.map +1 -0
  598. package/dist/tray-host/notify.d.ts +22 -0
  599. package/dist/tray-host/notify.d.ts.map +1 -0
  600. package/dist/tray-host/notify.js +74 -0
  601. package/dist/tray-host/notify.js.map +1 -0
  602. package/dist/tray-host/protocol.d.ts +106 -0
  603. package/dist/tray-host/protocol.d.ts.map +1 -0
  604. package/dist/tray-host/protocol.js +191 -0
  605. package/dist/tray-host/protocol.js.map +1 -0
  606. package/dist/tree/hx.d.ts +24 -0
  607. package/dist/tree/hx.d.ts.map +1 -0
  608. package/dist/tree/hx.js +25 -0
  609. package/dist/tree/hx.js.map +1 -0
  610. package/dist/tree/index.d.ts +221 -0
  611. package/dist/tree/index.d.ts.map +1 -0
  612. package/dist/tree/index.js +716 -0
  613. package/dist/tree/index.js.map +1 -0
  614. package/dist/tree/internal.d.ts +18 -0
  615. package/dist/tree/internal.d.ts.map +1 -0
  616. package/dist/tree/internal.js +66 -0
  617. package/dist/tree/internal.js.map +1 -0
  618. package/dist/tree/rows.d.ts +177 -0
  619. package/dist/tree/rows.d.ts.map +1 -0
  620. package/dist/tree/rows.js +179 -0
  621. package/dist/tree/rows.js.map +1 -0
  622. package/package.json +166 -12
  623. package/src/ansi/cast.ts +159 -0
  624. package/src/ansi/index.ts +53 -0
  625. package/src/ansi/palette.ts +226 -0
  626. package/src/ansi/parse.ts +780 -0
  627. package/src/ansi/sgr.ts +380 -0
  628. package/src/ansi/utf8.ts +84 -0
  629. package/src/calendar/Calendar.ts +744 -0
  630. package/src/calendar/DatePicker.ts +368 -0
  631. package/src/calendar/dates.ts +307 -0
  632. package/src/calendar/index.ts +51 -0
  633. package/src/charts/components.ts +864 -0
  634. package/src/charts/data.ts +776 -0
  635. package/src/charts/hx.ts +39 -0
  636. package/src/charts/index.ts +99 -0
  637. package/src/charts/node.ts +932 -0
  638. package/src/charts/render.ts +982 -0
  639. package/src/charts/scale.ts +214 -0
  640. package/src/charts/spec.ts +122 -0
  641. package/src/charts/timers.ts +24 -0
  642. package/src/code/hx.ts +51 -0
  643. package/src/code/index.ts +174 -0
  644. package/src/code-editor/completion.ts +161 -0
  645. package/src/code-editor/doc.ts +198 -0
  646. package/src/code-editor/hx.ts +26 -0
  647. package/src/code-editor/index.ts +615 -0
  648. package/src/code-editor/node.ts +1926 -0
  649. package/src/code-language/hljs.ts +302 -0
  650. package/src/code-language/index.ts +51 -0
  651. package/src/code-language/languages/glsl.ts +120 -0
  652. package/src/code-language/languages/javascript.ts +419 -0
  653. package/src/code-language/languages/json.ts +72 -0
  654. package/src/code-language/languages/shell.ts +221 -0
  655. package/src/code-language/languages/sql.ts +165 -0
  656. package/src/code-language/lezer.ts +190 -0
  657. package/src/code-language/registry.ts +66 -0
  658. package/src/code-language/runs.ts +128 -0
  659. package/src/code-language/stream.ts +306 -0
  660. package/src/code-language/textmate.ts +134 -0
  661. package/src/code-language/theme.ts +124 -0
  662. package/src/code-language/timers.ts +36 -0
  663. package/src/code-language/types.ts +252 -0
  664. package/src/codeblock/index.ts +146 -0
  665. package/src/color-picker/ColorField.ts +333 -0
  666. package/src/color-picker/ColorPicker.ts +1069 -0
  667. package/src/color-picker/color.ts +399 -0
  668. package/src/color-picker/index.ts +50 -0
  669. package/src/desktop-calendar/eds.ts +484 -0
  670. package/src/desktop-calendar/ical.ts +119 -0
  671. package/src/desktop-calendar/index.ts +287 -0
  672. package/src/embed/client.ts +311 -0
  673. package/src/embed/host.ts +432 -0
  674. package/src/embed/index.ts +33 -0
  675. package/src/embed/timers.ts +32 -0
  676. package/src/flow/draw.ts +418 -0
  677. package/src/flow/index.ts +473 -0
  678. package/src/flow/model.ts +687 -0
  679. package/src/flow/node.ts +3694 -0
  680. package/src/flow/paths.ts +403 -0
  681. package/src/flow/types.ts +634 -0
  682. package/src/formula/hx.ts +51 -0
  683. package/src/formula/index.ts +243 -0
  684. package/src/formula/katex.ts +209 -0
  685. package/src/formula/layout.ts +876 -0
  686. package/src/formula/node.ts +467 -0
  687. package/src/html/controls.ts +244 -0
  688. package/src/html/css/cascade.ts +606 -0
  689. package/src/html/css/parse.ts +500 -0
  690. package/src/html/css/style.ts +1371 -0
  691. package/src/html/css/ua.ts +174 -0
  692. package/src/html/css/values.ts +358 -0
  693. package/src/html/dom.ts +410 -0
  694. package/src/html/hx.ts +55 -0
  695. package/src/html/index.ts +545 -0
  696. package/src/html/layout/block.ts +876 -0
  697. package/src/html/layout/boxes.ts +981 -0
  698. package/src/html/layout/flex.ts +297 -0
  699. package/src/html/layout/floats.ts +125 -0
  700. package/src/html/layout/inline.ts +870 -0
  701. package/src/html/layout/table.ts +380 -0
  702. package/src/html/node.ts +967 -0
  703. package/src/html/paint.ts +605 -0
  704. package/src/html/resources.ts +214 -0
  705. package/src/index.ts +638 -0
  706. package/src/internal/heights.ts +211 -0
  707. package/src/internal/hx.ts +53 -0
  708. package/src/internal/text.ts +44 -0
  709. package/src/internal/timers.ts +44 -0
  710. package/src/internal/widget.ts +92 -0
  711. package/src/markdown/ast.ts +163 -0
  712. package/src/markdown/hx.ts +51 -0
  713. package/src/markdown/index.ts +686 -0
  714. package/src/markdown/parse.ts +1037 -0
  715. package/src/markdown/spans.ts +143 -0
  716. package/src/media-player/backends.ts +155 -0
  717. package/src/media-player/control.ts +70 -0
  718. package/src/media-player/hx.ts +51 -0
  719. package/src/media-player/index.ts +378 -0
  720. package/src/media-player/mpv.ts +146 -0
  721. package/src/media-player/vlc.ts +97 -0
  722. package/src/richtext/index.ts +42 -0
  723. package/src/richtext/links.ts +78 -0
  724. package/src/richtext/menu.ts +49 -0
  725. package/src/richtext/node.ts +406 -0
  726. package/src/richtext/runs.ts +253 -0
  727. package/src/table/hx.ts +51 -0
  728. package/src/table/index.ts +1219 -0
  729. package/src/table/rows.ts +275 -0
  730. package/src/terminal/backends.ts +242 -0
  731. package/src/terminal/hx.ts +51 -0
  732. package/src/terminal/index.ts +574 -0
  733. package/src/terminal/title.ts +172 -0
  734. package/src/terminal/vt/colors.ts +247 -0
  735. package/src/terminal/vt/diff.ts +467 -0
  736. package/src/terminal/vt/fonts.ts +233 -0
  737. package/src/terminal/vt/index.ts +443 -0
  738. package/src/terminal/vt/keys.ts +369 -0
  739. package/src/terminal/vt/mouse.ts +144 -0
  740. package/src/terminal/vt/node.ts +1242 -0
  741. package/src/terminal/vt/pty.ts +334 -0
  742. package/src/terminal/vt/renderer.ts +555 -0
  743. package/src/terminal/vt/timers.ts +31 -0
  744. package/src/terminal/vt/xterm.ts +193 -0
  745. package/src/terminal-output/hx.ts +51 -0
  746. package/src/terminal-output/index.ts +340 -0
  747. package/src/terminal-output/runs.ts +79 -0
  748. package/src/three/canvas.ts +451 -0
  749. package/src/three/events.ts +197 -0
  750. package/src/three/geometries.ts +429 -0
  751. package/src/three/globals.ts +34 -0
  752. package/src/three/hx.ts +22 -0
  753. package/src/three/index.ts +98 -0
  754. package/src/three/jsx-dev-runtime.ts +27 -0
  755. package/src/three/jsx-runtime.ts +38 -0
  756. package/src/three/jsx.ts +275 -0
  757. package/src/three/materials.ts +270 -0
  758. package/src/three/math.ts +585 -0
  759. package/src/three/objects.ts +397 -0
  760. package/src/three/passes.ts +90 -0
  761. package/src/three/postprocess.ts +677 -0
  762. package/src/three/raycast.ts +189 -0
  763. package/src/three/react-reconciler.d.ts +50 -0
  764. package/src/three/reconciler.ts +624 -0
  765. package/src/three/renderer-direct.ts +1055 -0
  766. package/src/three/renderer-indirect.ts +570 -0
  767. package/src/three/store.ts +207 -0
  768. package/src/timeline/hx.ts +31 -0
  769. package/src/timeline/index.ts +603 -0
  770. package/src/tray-host/hx.ts +51 -0
  771. package/src/tray-host/index.ts +331 -0
  772. package/src/tray-host/manager.ts +639 -0
  773. package/src/tray-host/notify.ts +102 -0
  774. package/src/tray-host/protocol.ts +235 -0
  775. package/src/tree/hx.ts +51 -0
  776. package/src/tree/index.ts +1087 -0
  777. package/src/tree/internal.ts +87 -0
  778. package/src/tree/rows.ts +334 -0
  779. package/src/index.d.ts +0 -2
  780. package/src/index.js +0 -9
  781. package/src/sparkline/index.d.ts +0 -29
  782. package/src/sparkline/index.js +0 -50
  783. package/src/sparkline/node.js +0 -72
@@ -0,0 +1,981 @@
1
+ // The box tree: what the DOM and the cascade become before layout runs.
2
+ //
3
+ // This is the phase that pays for itself twice. Building it is where the
4
+ // cascade is driven, where whitespace is collapsed, where anonymous boxes
5
+ // are generated and where every element's text is given its slice of the
6
+ // document-wide index the selection uses — all of which depend on the DOM
7
+ // and the stylesheets and **none of which depend on the width**. So a
8
+ // resize re-runs layout over this tree and skips all of it, and a repaint
9
+ // skips layout too. Three phases, three invalidation reasons:
10
+ //
11
+ // DOM or CSS changed → rebuild boxes, lay out, paint
12
+ // width changed → lay out, paint
13
+ // damage only → paint
14
+ //
15
+ // The document text is assembled here rather than by a later walk, for the
16
+ // reason richtext's node gives for answering from what it draws: an index
17
+ // built by a second traversal can disagree with the boxes, and a selection
18
+ // that disagrees with the glyphs is worse than no selection.
19
+ import type { Element } from 'domhandler';
20
+
21
+ import type { TextRun } from '../../richtext/index.js';
22
+ import {
23
+ attr,
24
+ childrenOf,
25
+ isElement,
26
+ isText,
27
+ NON_RENDERED,
28
+ tagOf,
29
+ } from '../dom.js';
30
+ import type { Cascade } from '../css/cascade.js';
31
+ import type { ComputedStyle } from '../css/style.js';
32
+
33
+ export type BoxKind =
34
+ | 'block'
35
+ | 'inline'
36
+ | 'text'
37
+ | 'replaced'
38
+ | 'flex'
39
+ | 'table'
40
+ | 'table-row-group'
41
+ | 'table-row'
42
+ | 'table-cell'
43
+ | 'table-caption'
44
+ | 'marker'
45
+ | 'break';
46
+
47
+ /** A laid-out line inside an inline formatting context. */
48
+ export interface LineBox {
49
+ /** Content-box relative, resolved to document coordinates at paint. */
50
+ x: number;
51
+ y: number;
52
+ width: number;
53
+ height: number;
54
+ baseline: number;
55
+ /**
56
+ * The text on this line, as one or more fragments.
57
+ *
58
+ * More than one whenever an atomic splits the text — `a <img> b` is two
59
+ * fragments of two different `TextLayout`s on one line — which is why this
60
+ * is a list rather than the single layout the common case would suggest.
61
+ */
62
+ texts: LineText[];
63
+ /** Where this line's text sits in the document index, in **code units**. */
64
+ textStart: number;
65
+ textEnd: number;
66
+ /** Atomic items sitting on this line — images, inline-blocks, controls. */
67
+ atomics: AtomicPlacement[];
68
+ }
69
+
70
+ /**
71
+ * One `TextLayout` line, placed on a line box.
72
+ *
73
+ * `drawX`/`drawY` are where the **layout's origin** sits in document
74
+ * coordinates — not where this line sits — because ntk draws a layout, not a
75
+ * line: `layout.draw(ctx, drawX, drawY)` emits every line it holds in one
76
+ * glyph batch, which is exactly the batching that makes a paragraph one
77
+ * composite instead of one per line. So the whole-paragraph case gives every
78
+ * one of its lines the same `drawX`/`drawY` and paint draws it once; the
79
+ * fragment case (text broken around an inline image) gives each fragment a
80
+ * layout holding one line, and each is drawn where it was placed.
81
+ */
82
+ export interface LineText {
83
+ layout: TextLayoutLike;
84
+ /** Which of `layout.lines` this fragment is. */
85
+ layoutLine: number;
86
+ /** Where the layout's origin lands, in document coordinates. */
87
+ drawX: number;
88
+ drawY: number;
89
+ /** Document index of this fragment's first and last character, in code
90
+ * units. */
91
+ textStart: number;
92
+ textEnd: number;
93
+ /** Code-unit offset within the layout's own text that `textStart` maps to,
94
+ * so a document index can be turned into a caret index in this layout. */
95
+ layoutStart: number;
96
+ }
97
+
98
+ export interface AtomicPlacement {
99
+ box: Box;
100
+ x: number;
101
+ y: number;
102
+ }
103
+
104
+ /** The slice of ntk's `TextLayout` this renderer reads. Structural for the
105
+ * reason every other element here types ntk structurally: ntk ships no
106
+ * declarations and this says what it needs and nothing more. */
107
+ export interface TextLayoutLike {
108
+ width: number;
109
+ height: number;
110
+ lines: {
111
+ x: number;
112
+ y: number;
113
+ height: number;
114
+ baseline: number;
115
+ width: number;
116
+ ascent: number;
117
+ descent: number;
118
+ start: number;
119
+ end: number;
120
+ runs: {
121
+ x: number;
122
+ width: number;
123
+ start: number;
124
+ end: number;
125
+ /** The span as handed in — a richtext `TextRun`, which is how the
126
+ * decoration a `<span>` carried reaches the paint pass on the same
127
+ * object the glyphs did. */
128
+ span: TextRun;
129
+ run: {
130
+ font: { metrics(size: number): { ascent: number; descent: number } };
131
+ size: number;
132
+ direction?: 'ltr' | 'rtl';
133
+ };
134
+ }[];
135
+ }[];
136
+ draw(ctx: unknown, x?: number, y?: number): void;
137
+ caretPosition(index: number): {
138
+ x: number;
139
+ y: number;
140
+ height: number;
141
+ line: number;
142
+ };
143
+ indexAt(x: number, y: number): number;
144
+ /** Whether `maxLines` dropped content — the slow inline path's "did this
145
+ * segment wrap" question, answered without laying the tail out. */
146
+ truncated?: boolean;
147
+ }
148
+
149
+ /**
150
+ * One box. Fields are assigned rather than passed so the shape stays
151
+ * monomorphic — every box has every field, which is what keeps the property
152
+ * access in the layout and paint loops a fixed offset rather than a
153
+ * megamorphic lookup.
154
+ */
155
+ export class Box {
156
+ kind: BoxKind;
157
+ el: Element | null;
158
+ style: ComputedStyle;
159
+ parent: Box | null = null;
160
+ children: Box[] = [];
161
+
162
+ /** Border-box, in document coordinates, after layout. */
163
+ x = 0;
164
+ y = 0;
165
+ width = 0;
166
+ height = 0;
167
+
168
+ /** Resolved edges — border + padding, per side. */
169
+ borderTop = 0;
170
+ borderRight = 0;
171
+ borderBottom = 0;
172
+ borderLeft = 0;
173
+ padTop = 0;
174
+ padRight = 0;
175
+ padBottom = 0;
176
+ padLeft = 0;
177
+ marginTop = 0;
178
+ marginRight = 0;
179
+ marginBottom = 0;
180
+ marginLeft = 0;
181
+
182
+ /** Text, for a `text` box: already whitespace-processed and transformed. */
183
+ text = '';
184
+ /** This box's slice of the document text index. */
185
+ textStart = 0;
186
+ textEnd = 0;
187
+
188
+ /** Lines, for a box that established an inline formatting context. */
189
+ lines: LineBox[] | null = null;
190
+
191
+ /** Intrinsic size, for a replaced box that knows one. */
192
+ intrinsicWidth = 0;
193
+ intrinsicHeight = 0;
194
+ /**
195
+ * Cached min-/max-content widths, for a table cell. -1 until measured.
196
+ *
197
+ * Intrinsic widths are width-independent by definition, so measuring them
198
+ * per layout pass was this engine breaking its own phase rule — a resize
199
+ * re-probed every cell twice and cost as much as the first layout. The
200
+ * cache lives on the box because the box's lifetime is exactly the
201
+ * invalidation rule: any DOM or style change rebuilds the tree, and a new
202
+ * box starts unmeasured.
203
+ */
204
+ intrinsicMinContent = -1;
205
+ intrinsicMaxContent = -1;
206
+ /** What a replaced box is: the resource seam and the control host both
207
+ * key on this rather than re-reading the tag. */
208
+ replaced: ReplacedKind = 'none';
209
+
210
+ /** The marker text of a `list-item`, if it generated one, and where it
211
+ * was laid out. The marker is not a box: it is not in the flow, nothing
212
+ * can select it (CSS spells that `::marker`, and no author styles it
213
+ * here), and giving it one would put a bullet in every copied list. */
214
+ markerText = '';
215
+ markerLayout: TextLayoutLike | null = null;
216
+ markerX = 0;
217
+ markerY = 0;
218
+
219
+ /**
220
+ * The bounds of everything this box and its descendants draw, in document
221
+ * coordinates — **ink** bounds, not the border box, because `overflow:
222
+ * visible` lets a child draw outside its parent and a box-rect test would
223
+ * then cull something still on screen. Filled by `computePaintBounds`
224
+ * after layout; the paint pass culls against it.
225
+ */
226
+ boundsX = 0;
227
+ boundsY = 0;
228
+ boundsWidth = 0;
229
+ boundsHeight = 0;
230
+
231
+ /**
232
+ * The viewport query over a wide child list, built by `computePaintBounds`
233
+ * past a size threshold: the paintable in-flow children sorted by ink top,
234
+ * with each entry's document-order position and a running maximum of ink
235
+ * bottoms. What it buys is the promise this component makes about tall
236
+ * documents — the cost of a paint is the viewport's, not the document's —
237
+ * because without it every expose walked all N children of a flat
238
+ * document to reject N−20 of them.
239
+ */
240
+ paintIndex: {
241
+ boxes: Box[];
242
+ order: number[];
243
+ prefixBottom: number[];
244
+ } | null = null;
245
+ /** Out-of-flow children in paint order (z-index, then document order),
246
+ * precomputed so a paint does not filter and sort per box per frame. */
247
+ positionedPaint: Box[] | null = null;
248
+ /** The tallest line box under this box — the slack a binary search over
249
+ * the y-sorted lines needs, since a line's bottom is not monotone. */
250
+ maxLineHeight = 0;
251
+
252
+ /**
253
+ * The document range this box's *subtree* covers, in code units. `[0, 0)`
254
+ * for a subtree with no text. Assigned once per build; the selection
255
+ * walks prune on it, which is what keeps "which pixels does this range
256
+ * cover" from touching the ninety-nine paragraphs a selection is not in.
257
+ */
258
+ subtreeTextStart = 0;
259
+ subtreeTextEnd = 0;
260
+
261
+ /** Set on a box whose `position` takes it out of flow, so the block pass
262
+ * can skip it and the positioned pass can find it. */
263
+ outOfFlow = false;
264
+ /** Set on a float, for the same reason. */
265
+ isFloat = false;
266
+
267
+ constructor(kind: BoxKind, el: Element | null, style: ComputedStyle) {
268
+ this.kind = kind;
269
+ this.el = el;
270
+ this.style = style;
271
+ }
272
+
273
+ append(child: Box): void {
274
+ child.parent = this;
275
+ this.children.push(child);
276
+ }
277
+
278
+ /** Content-box left edge, in document coordinates. */
279
+ get contentX(): number {
280
+ return this.x + this.borderLeft + this.padLeft;
281
+ }
282
+ get contentY(): number {
283
+ return this.y + this.borderTop + this.padTop;
284
+ }
285
+ get contentWidth(): number {
286
+ return Math.max(
287
+ 0,
288
+ this.width -
289
+ this.borderLeft -
290
+ this.borderRight -
291
+ this.padLeft -
292
+ this.padRight,
293
+ );
294
+ }
295
+ get contentHeight(): number {
296
+ return Math.max(
297
+ 0,
298
+ this.height -
299
+ this.borderTop -
300
+ this.borderBottom -
301
+ this.padTop -
302
+ this.padBottom,
303
+ );
304
+ }
305
+ /** Border + padding across, which is what a `border-box` width already
306
+ * contains and a `content-box` width does not. */
307
+ get horizontalExtra(): number {
308
+ return this.borderLeft + this.borderRight + this.padLeft + this.padRight;
309
+ }
310
+ get verticalExtra(): number {
311
+ return this.borderTop + this.borderBottom + this.padTop + this.padBottom;
312
+ }
313
+ }
314
+
315
+ export type ReplacedKind =
316
+ | 'none'
317
+ | 'image'
318
+ | 'input'
319
+ | 'textarea'
320
+ | 'select'
321
+ | 'button'
322
+ | 'checkbox'
323
+ | 'radio'
324
+ | 'hr';
325
+
326
+ /** What the builder produced, plus the document-wide text it indexed. */
327
+ export interface BoxTree {
328
+ root: Box;
329
+ /** The document's text as it will be drawn, which is what `textContent()`
330
+ * answers and what a copy puts on the clipboard. */
331
+ text: string;
332
+ /** Text boxes in document order — the selection binary-searches this. */
333
+ textBoxes: Box[];
334
+ /** Every replaced box that needs a real widget, in document order. */
335
+ controls: Box[];
336
+ /** Every box carrying an `href`, for click and hover. */
337
+ links: Box[];
338
+ }
339
+
340
+ export interface BuildOptions {
341
+ cascade: Cascade;
342
+ /** Intrinsic size for an image the host has already loaded. `null` when it
343
+ * has not: the box takes the attribute size, or a placeholder. */
344
+ imageSize(el: Element): { width: number; height: number } | null;
345
+ /** The size a real widget wants, so the box in the flow is the size the
346
+ * control will be drawn at. */
347
+ controlSize(
348
+ el: Element,
349
+ kind: ReplacedKind,
350
+ style: ComputedStyle,
351
+ ): {
352
+ width: number;
353
+ height: number;
354
+ };
355
+ }
356
+
357
+ /** Build the box tree for a document. */
358
+ export function buildBoxes(
359
+ root: Element | { children: unknown },
360
+ options: BuildOptions,
361
+ ): BoxTree {
362
+ const builder = new Builder(options);
363
+ return builder.run(root as Element);
364
+ }
365
+
366
+ /**
367
+ * How deep the box tree may go. Everything downstream of the builder — the
368
+ * fix-up pass, layout, paint, the accessor walks — recurses on box depth, so
369
+ * this is the one bound that keeps a degenerately nested document (fuzzer
370
+ * output, a runaway template) from a stack overflow five phases later.
371
+ * Blink's parser flattens at 512 for the same reason; content past the cap
372
+ * is dropped, which beats the alternative of crashing the application.
373
+ */
374
+ const MAX_DEPTH = 512;
375
+
376
+ class Builder {
377
+ private _options: BuildOptions;
378
+ private _text = '';
379
+ private _textBoxes: Box[] = [];
380
+ private _controls: Box[] = [];
381
+ private _links: Box[] = [];
382
+ /** Counter stack for `<ol>` numbering, one entry per open list. */
383
+ private _counters: number[] = [];
384
+ private _depth = 0;
385
+
386
+ constructor(options: BuildOptions) {
387
+ this._options = options;
388
+ }
389
+
390
+ run(root: Element): BoxTree {
391
+ const cascade = this._options.cascade;
392
+ const rootStyle = cascade.rootStyle(hasBody(root));
393
+ const rootBox = new Box('block', null, rootStyle);
394
+ // The DOM's `<html>`/`<body>` are ordinary elements with ordinary styles;
395
+ // the box above them exists only to be the initial containing block, so
396
+ // it carries no margins of its own and cannot collapse with anything.
397
+ this._children(root, rootBox, rootStyle, false);
398
+ fixUp(rootBox);
399
+ assignSubtreeRanges(rootBox);
400
+ return {
401
+ root: rootBox,
402
+ text: this._text,
403
+ textBoxes: this._textBoxes,
404
+ controls: this._controls,
405
+ links: this._links,
406
+ };
407
+ }
408
+
409
+ /** Build boxes for a parent's children into `into`. */
410
+ private _children(
411
+ node: Element | { children: unknown },
412
+ into: Box,
413
+ parentStyle: ComputedStyle,
414
+ inFlex: boolean,
415
+ owner: Element | null = null,
416
+ ): void {
417
+ for (const child of childrenOf(node as Element)) {
418
+ if (isText(child)) {
419
+ this._textNode(child.data, into, parentStyle, owner);
420
+ continue;
421
+ }
422
+ if (!isElement(child)) continue;
423
+ this._element(child, into, parentStyle, inFlex);
424
+ }
425
+ }
426
+
427
+ private _element(
428
+ el: Element,
429
+ into: Box,
430
+ parentStyle: ComputedStyle,
431
+ inFlex: boolean,
432
+ ): void {
433
+ const tag = tagOf(el);
434
+ if (NON_RENDERED.has(tag)) return;
435
+
436
+ const style = this._options.cascade.styleFor(el, parentStyle, inFlex);
437
+ if (style.display === 'none') return;
438
+
439
+ // `<br>` is a line break rather than a box, and it is the one element
440
+ // whose *absence* of a box still has to reach the inline layout.
441
+ if (tag === 'br') {
442
+ const box = new Box('break', el, style);
443
+ into.append(box);
444
+ this._push('\n', box);
445
+ return;
446
+ }
447
+
448
+ const replaced = replacedKind(el, tag);
449
+ if (replaced !== 'none') {
450
+ this._replaced(el, tag, replaced, style, into);
451
+ return;
452
+ }
453
+
454
+ if (this._depth >= MAX_DEPTH) return;
455
+ const kind = boxKindFor(style.display);
456
+ const box = new Box(kind, el, style);
457
+ into.append(box);
458
+ if (style.position === 'absolute' || style.position === 'fixed')
459
+ box.outOfFlow = true;
460
+ else if (style.float !== 'none') box.isFloat = true;
461
+
462
+ if (attr(el, 'href') && (tag === 'a' || tag === 'area'))
463
+ this._links.push(box);
464
+
465
+ if (style.display === 'list-item') {
466
+ box.markerText = markerFor(el, style, this._counters);
467
+ }
468
+ const opensCounter = tag === 'ol' || tag === 'ul';
469
+ if (opensCounter) {
470
+ const start = Number(attr(el, 'start') ?? '1');
471
+ this._counters.push(Number.isFinite(start) ? start : 1);
472
+ }
473
+
474
+ const childInFlex =
475
+ style.display === 'flex' || style.display === 'inline-flex';
476
+ this._depth += 1;
477
+ this._children(el, box, style, childInFlex, el);
478
+ this._depth -= 1;
479
+
480
+ if (opensCounter) this._counters.pop();
481
+ }
482
+
483
+ private _replaced(
484
+ el: Element,
485
+ tag: string,
486
+ replaced: ReplacedKind,
487
+ style: ComputedStyle,
488
+ into: Box,
489
+ ): void {
490
+ const box = new Box('replaced', el, style);
491
+ box.replaced = replaced;
492
+ into.append(box);
493
+ if (style.position === 'absolute' || style.position === 'fixed')
494
+ box.outOfFlow = true;
495
+ else if (style.float !== 'none') box.isFloat = true;
496
+
497
+ if (replaced === 'image') {
498
+ const loaded = this._options.imageSize(el);
499
+ if (loaded) {
500
+ box.intrinsicWidth = loaded.width;
501
+ box.intrinsicHeight = loaded.height;
502
+ } else {
503
+ // An image that has not arrived still needs a box, or the document
504
+ // reflows under the reader when it does. The attributes are the
505
+ // author telling us the size in advance; without them the box is a
506
+ // small placeholder rather than nothing.
507
+ box.intrinsicWidth = numberAttr(el, 'width') ?? 0;
508
+ box.intrinsicHeight = numberAttr(el, 'height') ?? 0;
509
+ }
510
+ // The alt text joins the document text, so a document read with the
511
+ // images blocked still copies as prose.
512
+ const alt = attr(el, 'alt');
513
+ if (alt) this._push(alt, box);
514
+ return;
515
+ }
516
+
517
+ if (replaced === 'hr') return;
518
+
519
+ const size = this._options.controlSize(el, replaced, style);
520
+ box.intrinsicWidth = size.width;
521
+ box.intrinsicHeight = size.height;
522
+ this._controls.push(box);
523
+ // A control's value is the widget's, not the document's: putting it in
524
+ // the selection index would make Ctrl+A copy the contents of every text
525
+ // field, which no document viewer does.
526
+ }
527
+
528
+ /** A text node, whitespace-processed per the inherited `white-space`. */
529
+ private _textNode(
530
+ data: string,
531
+ into: Box,
532
+ style: ComputedStyle,
533
+ owner: Element | null,
534
+ ): void {
535
+ const ws = style.whiteSpace;
536
+ let text: string;
537
+ if (ws === 'pre' || ws === 'pre-wrap') {
538
+ text = data;
539
+ } else if (ws === 'pre-line') {
540
+ text = data.replace(/[ \t]+/g, ' ').replace(/ *\n */g, '\n');
541
+ } else {
542
+ text = data.replace(/[\t\n\r\f ]+/g, ' ');
543
+ // A run of whitespace against the start of a block collapses away
544
+ // entirely; between two inline boxes it collapses to one space, which
545
+ // the replace above already did.
546
+ if (text === ' ' && !hasInlineContent(into)) return;
547
+ }
548
+ if (!text) return;
549
+ text = transformText(text, style.textTransform);
550
+ // The owning element rides on the text box, and from there onto the
551
+ // `TextRun`: hit testing inside a paragraph has no rectangle to test —
552
+ // an inline box is the runs on its lines — so the run is what has to
553
+ // know whose text it is.
554
+ const box = new Box('text', owner, style);
555
+ box.text = text;
556
+ into.append(box);
557
+ this._push(text, box);
558
+ }
559
+
560
+ /** Give a box its slice of the document text index. */
561
+ private _push(text: string, box: Box): void {
562
+ box.textStart = this._text.length;
563
+ this._text += text;
564
+ box.textEnd = this._text.length;
565
+ if (box.kind === 'text') this._textBoxes.push(box);
566
+ }
567
+ }
568
+
569
+ /** Whether the parsed document has a `<body>`. htmlparser2 does not
570
+ * synthesise one — it parses what it was given — so a fragment has none,
571
+ * and the root box stands in for it. */
572
+ function hasBody(root: Element | { children: unknown }): boolean {
573
+ for (const child of childrenOf(root as Element)) {
574
+ if (!isElement(child)) continue;
575
+ const tag = tagOf(child);
576
+ if (tag === 'body') return true;
577
+ if (tag === 'html' && hasBody(child)) return true;
578
+ }
579
+ return false;
580
+ }
581
+
582
+ function numberAttr(el: Element, name: string): number | null {
583
+ const raw = attr(el, name);
584
+ if (!raw) return null;
585
+ const n = parseFloat(raw);
586
+ return Number.isFinite(n) ? n : null;
587
+ }
588
+
589
+ function hasInlineContent(box: Box): boolean {
590
+ for (let i = box.children.length - 1; i >= 0; i -= 1) {
591
+ const kind = box.children[i].kind;
592
+ if (kind === 'text' || kind === 'inline' || kind === 'replaced')
593
+ return true;
594
+ if (kind === 'block' || kind === 'flex' || kind === 'table') return false;
595
+ }
596
+ return false;
597
+ }
598
+
599
+ function transformText(
600
+ text: string,
601
+ transform: ComputedStyle['textTransform'],
602
+ ): string {
603
+ switch (transform) {
604
+ case 'uppercase':
605
+ return text.toUpperCase();
606
+ case 'lowercase':
607
+ return text.toLowerCase();
608
+ case 'capitalize':
609
+ return text.replace(
610
+ /(^|\s)(\S)/g,
611
+ (_, sp: string, c: string) => sp + c.toUpperCase(),
612
+ );
613
+ default:
614
+ return text;
615
+ }
616
+ }
617
+
618
+ function boxKindFor(display: ComputedStyle['display']): BoxKind {
619
+ switch (display) {
620
+ case 'inline':
621
+ return 'inline';
622
+ case 'flex':
623
+ case 'inline-flex':
624
+ return 'flex';
625
+ case 'table':
626
+ case 'inline-table':
627
+ return 'table';
628
+ case 'table-row-group':
629
+ case 'table-header-group':
630
+ case 'table-footer-group':
631
+ return 'table-row-group';
632
+ case 'table-row':
633
+ return 'table-row';
634
+ case 'table-cell':
635
+ return 'table-cell';
636
+ case 'table-caption':
637
+ return 'table-caption';
638
+ case 'table-column':
639
+ case 'table-column-group':
640
+ // A column box paints nothing and lays out nothing; the table reads
641
+ // its style for the column width and skips the box.
642
+ return 'block';
643
+ default:
644
+ // `inline-block` and `list-item` are block *containers* that happen to
645
+ // be inline-level or to carry a marker; both lay out inside like a
646
+ // block, and the difference is what the parent does with them.
647
+ return 'block';
648
+ }
649
+ }
650
+
651
+ function replacedKind(el: Element, tag: string): ReplacedKind {
652
+ switch (tag) {
653
+ case 'img':
654
+ return 'image';
655
+ case 'hr':
656
+ return 'hr';
657
+ case 'textarea':
658
+ return 'textarea';
659
+ case 'select':
660
+ return 'select';
661
+ case 'button':
662
+ return 'button';
663
+ case 'input': {
664
+ const type = (attr(el, 'type') ?? 'text').toLowerCase();
665
+ if (type === 'checkbox') return 'checkbox';
666
+ if (type === 'radio') return 'radio';
667
+ if (type === 'button' || type === 'submit' || type === 'reset')
668
+ return 'button';
669
+ if (type === 'hidden') return 'none';
670
+ return 'input';
671
+ }
672
+ default:
673
+ return 'none';
674
+ }
675
+ }
676
+
677
+ const ROMAN: [number, string][] = [
678
+ [1000, 'm'],
679
+ [900, 'cm'],
680
+ [500, 'd'],
681
+ [400, 'cd'],
682
+ [100, 'c'],
683
+ [90, 'xc'],
684
+ [50, 'l'],
685
+ [40, 'xl'],
686
+ [10, 'x'],
687
+ [9, 'ix'],
688
+ [5, 'v'],
689
+ [4, 'iv'],
690
+ [1, 'i'],
691
+ ];
692
+
693
+ /**
694
+ * The marker a `list-item` draws. The counter is the *builder's*, not the
695
+ * element's, because `value` on an `<li>` restarts it and a nested list has
696
+ * its own — both of which are lost if the number is derived from the index
697
+ * of the child in its parent.
698
+ */
699
+ function markerFor(
700
+ el: Element,
701
+ style: ComputedStyle,
702
+ counters: number[],
703
+ ): string {
704
+ const type = style.listStyleType;
705
+ if (type === 'none') return '';
706
+ const depth = counters.length;
707
+ if (depth) {
708
+ const value = numberAttr(el, 'value');
709
+ if (value !== null) counters[depth - 1] = value;
710
+ }
711
+ const n = depth ? counters[depth - 1]++ : 1;
712
+ switch (type) {
713
+ case 'decimal':
714
+ return `${n}.`;
715
+ case 'decimal-leading-zero':
716
+ return `${n < 10 ? '0' : ''}${n}.`;
717
+ case 'lower-alpha':
718
+ case 'lower-latin':
719
+ return `${alpha(n).toLowerCase()}.`;
720
+ case 'upper-alpha':
721
+ case 'upper-latin':
722
+ return `${alpha(n)}.`;
723
+ case 'lower-roman':
724
+ return `${roman(n)}.`;
725
+ case 'upper-roman':
726
+ return `${roman(n).toUpperCase()}.`;
727
+ case 'circle':
728
+ return '◦';
729
+ case 'square':
730
+ return '▪';
731
+ case 'disc':
732
+ default:
733
+ return '•';
734
+ }
735
+ }
736
+
737
+ function alpha(n: number): string {
738
+ let out = '';
739
+ let v = Math.max(1, n);
740
+ while (v > 0) {
741
+ const rem = (v - 1) % 26;
742
+ out = String.fromCharCode(65 + rem) + out;
743
+ v = Math.floor((v - 1) / 26);
744
+ }
745
+ return out;
746
+ }
747
+
748
+ function roman(n: number): string {
749
+ let v = Math.max(1, Math.min(3999, n));
750
+ let out = '';
751
+ for (const [value, sym] of ROMAN) {
752
+ while (v >= value) {
753
+ out += sym;
754
+ v -= value;
755
+ }
756
+ }
757
+ return out;
758
+ }
759
+
760
+ /**
761
+ * Give every box the document range its subtree covers. Runs after `fixUp`,
762
+ * because fix-up reparents children into anonymous boxes and the ranges have
763
+ * to describe the tree the walks will actually traverse. Document order
764
+ * makes each subtree's range contiguous, so min/max over the children is
765
+ * exact rather than an approximation.
766
+ */
767
+ function assignSubtreeRanges(box: Box): { start: number; end: number } {
768
+ let start = box.textEnd > box.textStart ? box.textStart : Infinity;
769
+ let end = box.textEnd > box.textStart ? box.textEnd : -Infinity;
770
+ for (const child of box.children) {
771
+ const range = assignSubtreeRanges(child);
772
+ if (range.end > range.start) {
773
+ start = Math.min(start, range.start);
774
+ end = Math.max(end, range.end);
775
+ }
776
+ }
777
+ if (end <= start) {
778
+ box.subtreeTextStart = 0;
779
+ box.subtreeTextEnd = 0;
780
+ return { start: 0, end: 0 };
781
+ }
782
+ box.subtreeTextStart = start;
783
+ box.subtreeTextEnd = end;
784
+ return { start, end };
785
+ }
786
+
787
+ // --- anonymous boxes --------------------------------------------------------
788
+
789
+ /**
790
+ * The fix-up pass: CSS's anonymous box rules, applied bottom-up.
791
+ *
792
+ * Two of them, and both are the difference between a document that lays out
793
+ * and one that silently drops content:
794
+ *
795
+ * - **A block container with a mix of block-level and inline-level children
796
+ * wraps each run of inline children in an anonymous block.** Without it
797
+ * `<div>text<p>para</p></div>` has to decide whether the div is a block
798
+ * context or an inline one, and either answer loses something.
799
+ * - **A table's structure is completed.** Real documents write `<table>`
800
+ * straight to `<tr>`, and CSS says the missing row group is generated
801
+ * rather than the rows being dropped.
802
+ */
803
+ function fixUp(box: Box): void {
804
+ for (const child of box.children) fixUp(child);
805
+
806
+ if (box.kind === 'table') {
807
+ fixUpTable(box);
808
+ return;
809
+ }
810
+ if (box.kind === 'table-row-group') {
811
+ wrapOrphans(box, 'table-row', (k) => k === 'table-row');
812
+ return;
813
+ }
814
+ if (box.kind === 'table-row') {
815
+ wrapOrphans(box, 'table-cell', (k) => k === 'table-cell');
816
+ return;
817
+ }
818
+
819
+ if (!box.children.length) return;
820
+ let hasBlockLevel = false;
821
+ let hasInlineLevel = false;
822
+ for (const child of box.children) {
823
+ if (child.outOfFlow) continue;
824
+ if (isBlockLevel(child)) hasBlockLevel = true;
825
+ else hasInlineLevel = true;
826
+ }
827
+ // A flex container has no inline formatting context at all: every run of
828
+ // inline-level content becomes an anonymous flex *item*, whether or not a
829
+ // block-level sibling forced the question. `<div style="display:flex">some
830
+ // text</div>` is the case the mixed-content rule alone drops on the floor —
831
+ // all-inline children, so no wrapping, so the flex pass finds bare text
832
+ // boxes it cannot lay out and renders nothing.
833
+ const wrapAllInline = box.kind === 'flex';
834
+ if (!wrapAllInline && (!hasBlockLevel || !hasInlineLevel)) return;
835
+ if (wrapAllInline && !hasInlineLevel) return;
836
+
837
+ const next: Box[] = [];
838
+ let run: Box[] | null = null;
839
+ for (const child of box.children) {
840
+ // A float or an absolutely positioned box sits in whichever context it
841
+ // finds itself; it does not force an anonymous block on its own.
842
+ if (isBlockLevel(child) && !child.outOfFlow && !child.isFloat) {
843
+ if (run) {
844
+ next.push(anonymousBlock(box, run));
845
+ run = null;
846
+ }
847
+ next.push(child);
848
+ continue;
849
+ }
850
+ // Whitespace between two blocks is not content and must not generate a
851
+ // line box — `<div><p>a</p> <p>b</p></div>` has no blank line in it.
852
+ if (!run && child.kind === 'text' && !child.text.trim()) continue;
853
+ (run ??= []).push(child);
854
+ }
855
+ if (run) {
856
+ if (run.every((c) => c.kind === 'text' && !c.text.trim())) {
857
+ // trailing whitespace after the last block: same rule
858
+ } else {
859
+ next.push(anonymousBlock(box, run));
860
+ }
861
+ }
862
+ box.children = next;
863
+ }
864
+
865
+ function anonymousBlock(parent: Box, run: Box[]): Box {
866
+ const box = new Box('block', null, parent.style);
867
+ box.parent = parent;
868
+ for (const child of run) {
869
+ child.parent = box;
870
+ box.children.push(child);
871
+ }
872
+ return box;
873
+ }
874
+
875
+ function isBlockLevel(box: Box): boolean {
876
+ switch (box.kind) {
877
+ case 'block':
878
+ case 'flex':
879
+ case 'table':
880
+ case 'table-row':
881
+ case 'table-row-group':
882
+ case 'table-cell':
883
+ case 'table-caption':
884
+ // An `inline-block` or `inline-flex` is a block *container* with an
885
+ // inline-level outer role, so it belongs to the inline run around it.
886
+ return !isInlineLevelDisplay(box.style.display);
887
+ default:
888
+ return false;
889
+ }
890
+ }
891
+
892
+ function isInlineLevelDisplay(display: ComputedStyle['display']): boolean {
893
+ return (
894
+ display === 'inline-block' ||
895
+ display === 'inline-flex' ||
896
+ display === 'inline-table'
897
+ );
898
+ }
899
+
900
+ /** Wrap children that are not of `expect` in an anonymous box that is. */
901
+ function wrapOrphans(
902
+ box: Box,
903
+ kind: BoxKind,
904
+ accept: (k: BoxKind) => boolean,
905
+ ): void {
906
+ let needed = false;
907
+ for (const child of box.children) {
908
+ if (!accept(child.kind) && !isDroppableWhitespace(child)) {
909
+ needed = true;
910
+ break;
911
+ }
912
+ }
913
+ if (!needed) return;
914
+ const next: Box[] = [];
915
+ let run: Box[] | null = null;
916
+ for (const child of box.children) {
917
+ if (accept(child.kind)) {
918
+ if (run) {
919
+ next.push(anonymousOf(box, kind, run));
920
+ run = null;
921
+ }
922
+ next.push(child);
923
+ continue;
924
+ }
925
+ if (isDroppableWhitespace(child)) continue;
926
+ (run ??= []).push(child);
927
+ }
928
+ if (run) next.push(anonymousOf(box, kind, run));
929
+ box.children = next;
930
+ }
931
+
932
+ function anonymousOf(parent: Box, kind: BoxKind, run: Box[]): Box {
933
+ const box = new Box(kind, null, parent.style);
934
+ box.parent = parent;
935
+ for (const child of run) {
936
+ child.parent = box;
937
+ box.children.push(child);
938
+ }
939
+ return box;
940
+ }
941
+
942
+ function isDroppableWhitespace(box: Box): boolean {
943
+ return box.kind === 'text' && !box.text.trim();
944
+ }
945
+
946
+ function fixUpTable(table: Box): void {
947
+ const groups: Box[] = [];
948
+ const captions: Box[] = [];
949
+ let looseRows: Box[] | null = null;
950
+ for (const child of table.children) {
951
+ if (child.kind === 'table-row-group') {
952
+ if (looseRows) {
953
+ groups.push(anonymousOf(table, 'table-row-group', looseRows));
954
+ looseRows = null;
955
+ }
956
+ groups.push(child);
957
+ } else if (child.kind === 'table-caption') {
958
+ captions.push(child);
959
+ } else if (isDroppableWhitespace(child)) {
960
+ continue;
961
+ } else {
962
+ // A `<tr>`, or anything else that ended up here: rows go into an
963
+ // anonymous group, and anything that is not a row becomes a cell in
964
+ // one, which is how a browser rescues `<table>text</table>`.
965
+ const row =
966
+ child.kind === 'table-row'
967
+ ? child
968
+ : anonymousOf(table, 'table-row', [child]);
969
+ (looseRows ??= []).push(row);
970
+ }
971
+ }
972
+ if (looseRows) groups.push(anonymousOf(table, 'table-row-group', looseRows));
973
+ for (const group of groups) {
974
+ wrapOrphans(group, 'table-row', (k) => k === 'table-row');
975
+ for (const row of group.children) {
976
+ wrapOrphans(row, 'table-cell', (k) => k === 'table-cell');
977
+ }
978
+ }
979
+ table.children = [...captions, ...groups];
980
+ for (const child of table.children) child.parent = table;
981
+ }