buninu-browser 0.0.2

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 (830) hide show
  1. package/AGENTS.md +13 -0
  2. package/Architecture.md +601 -0
  3. package/LICENSE +21 -0
  4. package/LICENSES/Apache-2.0.txt +202 -0
  5. package/LICENSES/BSD-3-Clause-Skia.txt +29 -0
  6. package/LICENSES/Bitstream-Vera.txt +44 -0
  7. package/LICENSES/CC-BY-4.0.txt +396 -0
  8. package/LICENSES/OFL-1.1.txt +91 -0
  9. package/LICENSES/README.md +9 -0
  10. package/LICENSES/acorn.txt +21 -0
  11. package/LICENSES/chromium.txt +27 -0
  12. package/LICENSES/dropflow.txt +19 -0
  13. package/LICENSES/emscripten.txt +102 -0
  14. package/LICENSES/freetype.txt +169 -0
  15. package/LICENSES/happy-dom.txt +22 -0
  16. package/LICENSES/harfbuzz.txt +42 -0
  17. package/LICENSES/icu.txt +512 -0
  18. package/LICENSES/libjpeg-ijg.txt +260 -0
  19. package/LICENSES/libjpeg-turbo.txt +147 -0
  20. package/LICENSES/libpng.txt +134 -0
  21. package/LICENSES/libwebp.txt +30 -0
  22. package/LICENSES/ses-aura.txt +16 -0
  23. package/LICENSES/ses-caja.txt +13 -0
  24. package/LICENSES/ses-corejs.txt +19 -0
  25. package/LICENSES/ses-v8.txt +9 -0
  26. package/LICENSES/ses.txt +201 -0
  27. package/LICENSES/termdom.txt +21 -0
  28. package/LICENSES/wasmpeg.txt +501 -0
  29. package/LICENSES/woff2.txt +19 -0
  30. package/LICENSES/wuffs.txt +211 -0
  31. package/LICENSES/zlib.txt +22 -0
  32. package/Linux +0 -0
  33. package/PORTING.md +825 -0
  34. package/README.md +283 -0
  35. package/THIRD_PARTY_NOTICES.md +224 -0
  36. package/bunfig.toml +2 -0
  37. package/buninu-browser.js +65 -0
  38. package/index.js +149 -0
  39. package/lib/cdp-server.js +1424 -0
  40. package/lib/cdp.js +203 -0
  41. package/lib/happy-dom/entities-adapter.js +51 -0
  42. package/lib/happy-dom/image-size-adapter.js +8 -0
  43. package/lib/happy-dom/mime-type-adapter.js +27 -0
  44. package/lib/happy-dom/parser.js +53 -0
  45. package/lib/happy-dom/websocket-adapter.js +62 -0
  46. package/lib/headless-shell.js +362 -0
  47. package/lib/input/hit-test.js +78 -0
  48. package/lib/layout/scroll-viewport.js +53 -0
  49. package/lib/layout/text-layout.js +2236 -0
  50. package/lib/log.js +85 -0
  51. package/lib/network/cookie-jar.js +178 -0
  52. package/lib/network/network-service.js +268 -0
  53. package/lib/network/resolver.js +97 -0
  54. package/lib/paint/display-list.js +359 -0
  55. package/lib/paint/frame.js +88 -0
  56. package/lib/paint/gradient.js +207 -0
  57. package/lib/render-tree/index.js +263 -0
  58. package/lib/render-tree/svg.js +210 -0
  59. package/lib/renderer/bindings.js +1291 -0
  60. package/lib/renderer/compositor.js +123 -0
  61. package/lib/renderer/flags.js +20 -0
  62. package/lib/renderer/host.js +503 -0
  63. package/lib/renderer/main.js +234 -0
  64. package/lib/renderer/module-transform.js +399 -0
  65. package/lib/renderer/page-realm.js +1471 -0
  66. package/lib/renderer/page-renderer.js +1691 -0
  67. package/lib/renderer/script-rewrite.js +232 -0
  68. package/lib/renderer/seccomp.js +215 -0
  69. package/lib/renderer/syscall-numbers.js +139 -0
  70. package/lib/style/computed-style.js +2053 -0
  71. package/package.json +39 -0
  72. package/patches/happy-dom/0001-use-bun-entity-adapter.patch +15 -0
  73. package/patches/happy-dom/0002-use-bun-platform-adapters.patch +69 -0
  74. package/patches/happy-dom/README.md +38 -0
  75. package/test/chromium-headless-shell +5 -0
  76. package/test/compositor.test.js +154 -0
  77. package/test/computed-style.test.js +434 -0
  78. package/test/display-list.test.js +128 -0
  79. package/test/entities-adapter.test.js +43 -0
  80. package/test/fixtures/fake-renderer.js +26 -0
  81. package/test/fixtures/seccomp-child.js +32 -0
  82. package/test/fixtures/video.mp4 +0 -0
  83. package/test/flex.test.js +150 -0
  84. package/test/gradient.test.js +56 -0
  85. package/test/grid.test.js +253 -0
  86. package/test/happy-dom-platform-adapters.test.js +18 -0
  87. package/test/headless-shell.test.js +318 -0
  88. package/test/hit-test.test.js +49 -0
  89. package/test/html-parser.test.js +40 -0
  90. package/test/index.test.js +29 -0
  91. package/test/log.test.js +40 -0
  92. package/test/mobile.test.js +85 -0
  93. package/test/network-service.test.js +214 -0
  94. package/test/page-scripts.test.js +552 -0
  95. package/test/poc-backend.js +189 -0
  96. package/test/poc-backend.test.js +154 -0
  97. package/test/positioning.test.js +112 -0
  98. package/test/render-tree.test.js +103 -0
  99. package/test/renderer-host.test.js +69 -0
  100. package/test/resolver.test.js +51 -0
  101. package/test/script-rewrite.test.js +31 -0
  102. package/test/scroll-viewport.test.js +25 -0
  103. package/test/seccomp.test.js +71 -0
  104. package/test/site-isolation.test.js +74 -0
  105. package/test/svg.test.js +61 -0
  106. package/test/text-layout.test.js +419 -0
  107. package/usr/README.md +20 -0
  108. package/usr/lib/canvaskit/LICENSE +29 -0
  109. package/usr/lib/canvaskit/canvaskit.js +264 -0
  110. package/usr/lib/canvaskit/canvaskit.wasm +0 -0
  111. package/usr/share/fonts/DejaVuSansMono-Bold.ttf +0 -0
  112. package/usr/share/fonts/DejaVuSansMono.ttf +0 -0
  113. package/usr/share/fonts/LICENSE-Apache-2.0.txt +202 -0
  114. package/usr/share/fonts/LICENSE-DejaVu.txt +44 -0
  115. package/usr/share/fonts/LICENSE-OFL-1.1.txt +91 -0
  116. package/usr/share/fonts/NotoColorEmoji.ttf +0 -0
  117. package/usr/share/fonts/NotoColorEmojiFlags.ttf +0 -0
  118. package/usr/share/fonts/NotoSansCJK-Regular.ttc +0 -0
  119. package/usr/share/fonts/NotoSansSymbols-Regular-Subsetted.ttf +0 -0
  120. package/usr/share/fonts/NotoSansSymbols-Regular-Subsetted2.ttf +0 -0
  121. package/usr/share/fonts/Roboto-Regular.ttf +0 -0
  122. package/usr/share/fonts/fonts.json +28 -0
  123. package/vendor/acorn/LICENSE +21 -0
  124. package/vendor/acorn/README.md +309 -0
  125. package/vendor/acorn/dist/acorn.mjs +6313 -0
  126. package/vendor/acorn/package.json +50 -0
  127. package/vendor/happy-dom/.editorconfig +8 -0
  128. package/vendor/happy-dom/.eslintignore +6 -0
  129. package/vendor/happy-dom/.eslintrc.cjs +188 -0
  130. package/vendor/happy-dom/.github/CODEOWNERS +2 -0
  131. package/vendor/happy-dom/.github/FUNDING.yml +1 -0
  132. package/vendor/happy-dom/.github/ISSUE_TEMPLATE/bug_report.md +32 -0
  133. package/vendor/happy-dom/.github/ISSUE_TEMPLATE/custom.md +10 -0
  134. package/vendor/happy-dom/.github/ISSUE_TEMPLATE/feature_request.md +19 -0
  135. package/vendor/happy-dom/.github/PULL_REQUEST_TEMPLATE.md +27 -0
  136. package/vendor/happy-dom/.github/workflows/auto-assign.yml +23 -0
  137. package/vendor/happy-dom/.github/workflows/pull_request.yml +53 -0
  138. package/vendor/happy-dom/.github/workflows/release.yml +143 -0
  139. package/vendor/happy-dom/.husky/pre-commit +1 -0
  140. package/vendor/happy-dom/.prettierignore +1 -0
  141. package/vendor/happy-dom/.prettierrc.cjs +6 -0
  142. package/vendor/happy-dom/.vscode/extensions.json +3 -0
  143. package/vendor/happy-dom/CODE_OF_CONDUCT.md +128 -0
  144. package/vendor/happy-dom/CONTRIBUTING.md +147 -0
  145. package/vendor/happy-dom/LICENSE +21 -0
  146. package/vendor/happy-dom/README.md +62 -0
  147. package/vendor/happy-dom/SECURITY.md +12 -0
  148. package/vendor/happy-dom/cspell.json +34 -0
  149. package/vendor/happy-dom/docs/happy-dom-logo.jpg +0 -0
  150. package/vendor/happy-dom/integration-test/.editorconfig +8 -0
  151. package/vendor/happy-dom/integration-test/LICENSE +21 -0
  152. package/vendor/happy-dom/integration-test/README.md +1 -0
  153. package/vendor/happy-dom/integration-test/package.json +24 -0
  154. package/vendor/happy-dom/package-lock.json +15520 -0
  155. package/vendor/happy-dom/package.json +55 -0
  156. package/vendor/happy-dom/packages/@happy-dom/global-registrator/LICENSE +21 -0
  157. package/vendor/happy-dom/packages/@happy-dom/global-registrator/README.md +60 -0
  158. package/vendor/happy-dom/packages/@happy-dom/global-registrator/package.json +52 -0
  159. package/vendor/happy-dom/packages/@happy-dom/global-registrator/register.js +2 -0
  160. package/vendor/happy-dom/packages/@happy-dom/global-registrator/src/GlobalRegistrator.ts +121 -0
  161. package/vendor/happy-dom/packages/@happy-dom/global-registrator/src/index.ts +3 -0
  162. package/vendor/happy-dom/packages/@happy-dom/global-registrator/tsconfig.json +30 -0
  163. package/vendor/happy-dom/packages/@happy-dom/jest-environment/LICENSE +21 -0
  164. package/vendor/happy-dom/packages/@happy-dom/jest-environment/README.md +71 -0
  165. package/vendor/happy-dom/packages/@happy-dom/jest-environment/package.json +93 -0
  166. package/vendor/happy-dom/packages/@happy-dom/jest-environment/src/index.ts +192 -0
  167. package/vendor/happy-dom/packages/@happy-dom/jest-environment/tsconfig.json +30 -0
  168. package/vendor/happy-dom/packages/@happy-dom/node-canvas-adapter/README.md +48 -0
  169. package/vendor/happy-dom/packages/@happy-dom/node-canvas-adapter/package.json +41 -0
  170. package/vendor/happy-dom/packages/@happy-dom/node-canvas-adapter/src/CanvasAdapter.ts +275 -0
  171. package/vendor/happy-dom/packages/@happy-dom/node-canvas-adapter/src/index.ts +1 -0
  172. package/vendor/happy-dom/packages/@happy-dom/server-renderer/LICENSE +21 -0
  173. package/vendor/happy-dom/packages/@happy-dom/server-renderer/README.md +100 -0
  174. package/vendor/happy-dom/packages/@happy-dom/server-renderer/bin/src/happy-dom-sr.ts +30 -0
  175. package/vendor/happy-dom/packages/@happy-dom/server-renderer/package.json +62 -0
  176. package/vendor/happy-dom/packages/@happy-dom/server-renderer/src/ServerRenderer.ts +368 -0
  177. package/vendor/happy-dom/packages/@happy-dom/server-renderer/src/ServerRendererBrowser.ts +142 -0
  178. package/vendor/happy-dom/packages/@happy-dom/server-renderer/src/ServerRendererBrowserWorker.ts +29 -0
  179. package/vendor/happy-dom/packages/@happy-dom/server-renderer/src/ServerRendererPage.ts +305 -0
  180. package/vendor/happy-dom/packages/@happy-dom/server-renderer/src/ServerRendererPageWorker.ts +55 -0
  181. package/vendor/happy-dom/packages/@happy-dom/server-renderer/src/ServerRendererServer.ts +332 -0
  182. package/vendor/happy-dom/packages/@happy-dom/server-renderer/src/config/DefaultServerRendererConfiguration.ts +47 -0
  183. package/vendor/happy-dom/packages/@happy-dom/server-renderer/src/enums/ServerRendererLogLevelEnum.ts +9 -0
  184. package/vendor/happy-dom/packages/@happy-dom/server-renderer/src/enums/ServerRendererModeEnum.ts +8 -0
  185. package/vendor/happy-dom/packages/@happy-dom/server-renderer/src/index.ts +19 -0
  186. package/vendor/happy-dom/packages/@happy-dom/server-renderer/src/types/IOptionalServerRendererConfiguration.ts +127 -0
  187. package/vendor/happy-dom/packages/@happy-dom/server-renderer/src/types/IServerRendererConfiguration.ts +126 -0
  188. package/vendor/happy-dom/packages/@happy-dom/server-renderer/src/types/IServerRendererItem.ts +6 -0
  189. package/vendor/happy-dom/packages/@happy-dom/server-renderer/src/types/IServerRendererResult.ts +11 -0
  190. package/vendor/happy-dom/packages/@happy-dom/server-renderer/src/utilities/BrowserWindowPolyfill.ts +138 -0
  191. package/vendor/happy-dom/packages/@happy-dom/server-renderer/src/utilities/HelpPrinter.ts +36 -0
  192. package/vendor/happy-dom/packages/@happy-dom/server-renderer/src/utilities/HelpPrinterRows.ts +288 -0
  193. package/vendor/happy-dom/packages/@happy-dom/server-renderer/src/utilities/PackageVersion.ts +12 -0
  194. package/vendor/happy-dom/packages/@happy-dom/server-renderer/src/utilities/ProcessArgumentsParser.ts +387 -0
  195. package/vendor/happy-dom/packages/@happy-dom/server-renderer/src/utilities/ServerRendererConfigurationFactory.ts +91 -0
  196. package/vendor/happy-dom/packages/happy-dom/LICENSE +21 -0
  197. package/vendor/happy-dom/packages/happy-dom/README.md +42 -0
  198. package/vendor/happy-dom/packages/happy-dom/package.json +58 -0
  199. package/vendor/happy-dom/packages/happy-dom/src/PropertySymbol.ts +431 -0
  200. package/vendor/happy-dom/packages/happy-dom/src/animation/Animation.ts +273 -0
  201. package/vendor/happy-dom/packages/happy-dom/src/animation/AnimationTimeline.ts +15 -0
  202. package/vendor/happy-dom/packages/happy-dom/src/animation/DocumentTimeline.ts +33 -0
  203. package/vendor/happy-dom/packages/happy-dom/src/animation/KeyframeEffect.ts +295 -0
  204. package/vendor/happy-dom/packages/happy-dom/src/async-task-manager/AsyncTaskManager.ts +340 -0
  205. package/vendor/happy-dom/packages/happy-dom/src/async-task-manager/AsyncTaskManagerDebugError.ts +14 -0
  206. package/vendor/happy-dom/packages/happy-dom/src/base64/Base64.ts +97 -0
  207. package/vendor/happy-dom/packages/happy-dom/src/browser/Browser.ts +123 -0
  208. package/vendor/happy-dom/packages/happy-dom/src/browser/BrowserContext.ts +100 -0
  209. package/vendor/happy-dom/packages/happy-dom/src/browser/BrowserFrame.ts +232 -0
  210. package/vendor/happy-dom/packages/happy-dom/src/browser/BrowserPage.ts +205 -0
  211. package/vendor/happy-dom/packages/happy-dom/src/browser/BrowserSettingsFactory.ts +96 -0
  212. package/vendor/happy-dom/packages/happy-dom/src/browser/DefaultBrowserSettings.ts +67 -0
  213. package/vendor/happy-dom/packages/happy-dom/src/browser/detached-browser/DetachedBrowser.ts +129 -0
  214. package/vendor/happy-dom/packages/happy-dom/src/browser/detached-browser/DetachedBrowserContext.ts +103 -0
  215. package/vendor/happy-dom/packages/happy-dom/src/browser/detached-browser/DetachedBrowserFrame.ts +250 -0
  216. package/vendor/happy-dom/packages/happy-dom/src/browser/detached-browser/DetachedBrowserPage.ts +218 -0
  217. package/vendor/happy-dom/packages/happy-dom/src/browser/enums/BrowserErrorCaptureEnum.ts +10 -0
  218. package/vendor/happy-dom/packages/happy-dom/src/browser/enums/BrowserNavigationCrossOriginPolicyEnum.ts +10 -0
  219. package/vendor/happy-dom/packages/happy-dom/src/browser/types/IBrowser.ts +51 -0
  220. package/vendor/happy-dom/packages/happy-dom/src/browser/types/IBrowserContext.ts +44 -0
  221. package/vendor/happy-dom/packages/happy-dom/src/browser/types/IBrowserFrame.ts +112 -0
  222. package/vendor/happy-dom/packages/happy-dom/src/browser/types/IBrowserPage.ts +110 -0
  223. package/vendor/happy-dom/packages/happy-dom/src/browser/types/IBrowserPageViewport.ts +5 -0
  224. package/vendor/happy-dom/packages/happy-dom/src/browser/types/IBrowserSettings.ts +194 -0
  225. package/vendor/happy-dom/packages/happy-dom/src/browser/types/IGoToOptions.ts +17 -0
  226. package/vendor/happy-dom/packages/happy-dom/src/browser/types/IOptionalBrowserPageViewport.ts +5 -0
  227. package/vendor/happy-dom/packages/happy-dom/src/browser/types/IOptionalBrowserSettings.ts +190 -0
  228. package/vendor/happy-dom/packages/happy-dom/src/browser/types/IReloadOptions.ts +27 -0
  229. package/vendor/happy-dom/packages/happy-dom/src/browser/utilities/BrowserExceptionObserver.ts +123 -0
  230. package/vendor/happy-dom/packages/happy-dom/src/browser/utilities/BrowserFrameFactory.ts +106 -0
  231. package/vendor/happy-dom/packages/happy-dom/src/browser/utilities/BrowserFrameNavigator.ts +574 -0
  232. package/vendor/happy-dom/packages/happy-dom/src/browser/utilities/BrowserFrameScriptEvaluator.ts +71 -0
  233. package/vendor/happy-dom/packages/happy-dom/src/browser/utilities/BrowserFrameURL.ts +30 -0
  234. package/vendor/happy-dom/packages/happy-dom/src/browser/utilities/BrowserFrameValidator.ts +84 -0
  235. package/vendor/happy-dom/packages/happy-dom/src/browser/utilities/BrowserPageUtility.ts +56 -0
  236. package/vendor/happy-dom/packages/happy-dom/src/canvas/ICanvasAdapter.ts +63 -0
  237. package/vendor/happy-dom/packages/happy-dom/src/canvas/ICanvasAdapterCaller.ts +9 -0
  238. package/vendor/happy-dom/packages/happy-dom/src/canvas/ICanvasGradient.ts +8 -0
  239. package/vendor/happy-dom/packages/happy-dom/src/canvas/ICanvasPattern.ts +10 -0
  240. package/vendor/happy-dom/packages/happy-dom/src/canvas/ICanvasRenderingContext2D.ts +162 -0
  241. package/vendor/happy-dom/packages/happy-dom/src/canvas/ICanvasShape.ts +7 -0
  242. package/vendor/happy-dom/packages/happy-dom/src/canvas/IImageBitmapOptions.ts +8 -0
  243. package/vendor/happy-dom/packages/happy-dom/src/canvas/ITextMetrics.ts +12 -0
  244. package/vendor/happy-dom/packages/happy-dom/src/canvas/ImageBitmap.ts +162 -0
  245. package/vendor/happy-dom/packages/happy-dom/src/canvas/ImageData.ts +83 -0
  246. package/vendor/happy-dom/packages/happy-dom/src/canvas/OffscreenCanvas.ts +162 -0
  247. package/vendor/happy-dom/packages/happy-dom/src/canvas/TCanvasImage.ts +14 -0
  248. package/vendor/happy-dom/packages/happy-dom/src/canvas/TImageBitmapSource.ts +12 -0
  249. package/vendor/happy-dom/packages/happy-dom/src/clipboard/Clipboard.ts +108 -0
  250. package/vendor/happy-dom/packages/happy-dom/src/clipboard/ClipboardItem.ts +57 -0
  251. package/vendor/happy-dom/packages/happy-dom/src/config/HTMLElementConfig.ts +536 -0
  252. package/vendor/happy-dom/packages/happy-dom/src/config/HTMLElementConfigContentModelEnum.ts +12 -0
  253. package/vendor/happy-dom/packages/happy-dom/src/config/IHTMLElementTagNameMap.ts +181 -0
  254. package/vendor/happy-dom/packages/happy-dom/src/config/ISVGElementTagNameMap.ts +127 -0
  255. package/vendor/happy-dom/packages/happy-dom/src/config/NamespaceURI.ts +8 -0
  256. package/vendor/happy-dom/packages/happy-dom/src/config/SVGElementConfig.ts +70 -0
  257. package/vendor/happy-dom/packages/happy-dom/src/console/IConsole.ts +161 -0
  258. package/vendor/happy-dom/packages/happy-dom/src/console/IVirtualConsoleLogEntry.ts +10 -0
  259. package/vendor/happy-dom/packages/happy-dom/src/console/IVirtualConsoleLogGroup.ts +6 -0
  260. package/vendor/happy-dom/packages/happy-dom/src/console/IVirtualConsolePrinter.ts +58 -0
  261. package/vendor/happy-dom/packages/happy-dom/src/console/VirtualConsole.ts +363 -0
  262. package/vendor/happy-dom/packages/happy-dom/src/console/VirtualConsolePrinter.ts +148 -0
  263. package/vendor/happy-dom/packages/happy-dom/src/console/enums/VirtualConsoleLogLevelEnum.ts +12 -0
  264. package/vendor/happy-dom/packages/happy-dom/src/console/enums/VirtualConsoleLogTypeEnum.ts +29 -0
  265. package/vendor/happy-dom/packages/happy-dom/src/console/utilities/VirtualConsoleLogEntryStringifier.ts +100 -0
  266. package/vendor/happy-dom/packages/happy-dom/src/cookie/CookieContainer.ts +91 -0
  267. package/vendor/happy-dom/packages/happy-dom/src/cookie/DefaultCookie.ts +17 -0
  268. package/vendor/happy-dom/packages/happy-dom/src/cookie/ICookie.ts +14 -0
  269. package/vendor/happy-dom/packages/happy-dom/src/cookie/ICookieContainer.ts +33 -0
  270. package/vendor/happy-dom/packages/happy-dom/src/cookie/IOptionalCookie.ts +16 -0
  271. package/vendor/happy-dom/packages/happy-dom/src/cookie/enums/CookieSameSiteEnum.ts +6 -0
  272. package/vendor/happy-dom/packages/happy-dom/src/cookie/urilities/CookieExpireUtility.ts +16 -0
  273. package/vendor/happy-dom/packages/happy-dom/src/cookie/urilities/CookieStringUtility.ts +119 -0
  274. package/vendor/happy-dom/packages/happy-dom/src/cookie/urilities/CookieURLUtility.ts +27 -0
  275. package/vendor/happy-dom/packages/happy-dom/src/cookie-store/CookieStore.ts +226 -0
  276. package/vendor/happy-dom/packages/happy-dom/src/cookie-store/ICookieStoreDeleteOptions.ts +9 -0
  277. package/vendor/happy-dom/packages/happy-dom/src/cookie-store/ICookieStoreGetOptions.ts +7 -0
  278. package/vendor/happy-dom/packages/happy-dom/src/cookie-store/ICookieStoreItem.ts +13 -0
  279. package/vendor/happy-dom/packages/happy-dom/src/cookie-store/ICookieStoreSetOptions.ts +12 -0
  280. package/vendor/happy-dom/packages/happy-dom/src/css/CSS.ts +63 -0
  281. package/vendor/happy-dom/packages/happy-dom/src/css/CSSRule.ts +84 -0
  282. package/vendor/happy-dom/packages/happy-dom/src/css/CSSRuleTypeEnum.ts +18 -0
  283. package/vendor/happy-dom/packages/happy-dom/src/css/CSSStyleSheet.ts +141 -0
  284. package/vendor/happy-dom/packages/happy-dom/src/css/CSSUnitValue.ts +26 -0
  285. package/vendor/happy-dom/packages/happy-dom/src/css/CSSUnits.ts +31 -0
  286. package/vendor/happy-dom/packages/happy-dom/src/css/MediaList.ts +177 -0
  287. package/vendor/happy-dom/packages/happy-dom/src/css/declaration/CSSPropertyList.ts +1273 -0
  288. package/vendor/happy-dom/packages/happy-dom/src/css/declaration/CSSStyleDeclaration.ts +355 -0
  289. package/vendor/happy-dom/packages/happy-dom/src/css/declaration/ICSSStyleDeclaration.ts +1178 -0
  290. package/vendor/happy-dom/packages/happy-dom/src/css/declaration/computed-style/CSSComputedStyle.ts +502 -0
  291. package/vendor/happy-dom/packages/happy-dom/src/css/declaration/computed-style/config/CSSComputedStyleElementDefault.ts +133 -0
  292. package/vendor/happy-dom/packages/happy-dom/src/css/declaration/computed-style/config/CSSComputedStyleInheritedProperties.ts +39 -0
  293. package/vendor/happy-dom/packages/happy-dom/src/css/declaration/computed-style/config/CSSComputedStyleMeasurementProperties.ts +41 -0
  294. package/vendor/happy-dom/packages/happy-dom/src/css/declaration/property-manager/CSSPropertyManager.ts +641 -0
  295. package/vendor/happy-dom/packages/happy-dom/src/css/declaration/property-manager/parsers/CSSPropertyGetParser.ts +741 -0
  296. package/vendor/happy-dom/packages/happy-dom/src/css/declaration/property-manager/parsers/CSSPropertySetParser.ts +2955 -0
  297. package/vendor/happy-dom/packages/happy-dom/src/css/declaration/property-manager/types/ICSSPropertyMap.ts +5 -0
  298. package/vendor/happy-dom/packages/happy-dom/src/css/declaration/property-manager/types/ICSSPropertyValue.ts +4 -0
  299. package/vendor/happy-dom/packages/happy-dom/src/css/declaration/property-manager/utilities/CSSStringUtility.ts +90 -0
  300. package/vendor/happy-dom/packages/happy-dom/src/css/declaration/property-manager/utilities/CSSValueFormatter.ts +447 -0
  301. package/vendor/happy-dom/packages/happy-dom/src/css/declaration/property-manager/utilities/CSSVariableFormatter.ts +76 -0
  302. package/vendor/happy-dom/packages/happy-dom/src/css/declaration/utilities/CSSMeasurementConverter.ts +79 -0
  303. package/vendor/happy-dom/packages/happy-dom/src/css/declaration/utilities/CSSTextParser.ts +44 -0
  304. package/vendor/happy-dom/packages/happy-dom/src/css/rules/CSSConditionRule.ts +20 -0
  305. package/vendor/happy-dom/packages/happy-dom/src/css/rules/CSSContainerRule.ts +34 -0
  306. package/vendor/happy-dom/packages/happy-dom/src/css/rules/CSSFontFaceRule.ts +45 -0
  307. package/vendor/happy-dom/packages/happy-dom/src/css/rules/CSSGroupingRule.ts +84 -0
  308. package/vendor/happy-dom/packages/happy-dom/src/css/rules/CSSKeyframeRule.ts +53 -0
  309. package/vendor/happy-dom/packages/happy-dom/src/css/rules/CSSKeyframesRule.ts +147 -0
  310. package/vendor/happy-dom/packages/happy-dom/src/css/rules/CSSMediaRule.ts +50 -0
  311. package/vendor/happy-dom/packages/happy-dom/src/css/rules/CSSScopeRule.ts +53 -0
  312. package/vendor/happy-dom/packages/happy-dom/src/css/rules/CSSStyleRule.ts +73 -0
  313. package/vendor/happy-dom/packages/happy-dom/src/css/rules/CSSSupportsRule.ts +30 -0
  314. package/vendor/happy-dom/packages/happy-dom/src/css/style-property-map/CSSKeywordValue.ts +35 -0
  315. package/vendor/happy-dom/packages/happy-dom/src/css/style-property-map/CSSStyleValue.ts +37 -0
  316. package/vendor/happy-dom/packages/happy-dom/src/css/style-property-map/StylePropertyMap.ts +45 -0
  317. package/vendor/happy-dom/packages/happy-dom/src/css/style-property-map/StylePropertyMapReadOnly.ts +128 -0
  318. package/vendor/happy-dom/packages/happy-dom/src/css/utilities/CSSEscaper.ts +87 -0
  319. package/vendor/happy-dom/packages/happy-dom/src/css/utilities/CSSRuleParser.ts +315 -0
  320. package/vendor/happy-dom/packages/happy-dom/src/custom-element/CustomElementReactionStack.ts +91 -0
  321. package/vendor/happy-dom/packages/happy-dom/src/custom-element/CustomElementRegistry.ts +186 -0
  322. package/vendor/happy-dom/packages/happy-dom/src/custom-element/CustomElementUtility.ts +34 -0
  323. package/vendor/happy-dom/packages/happy-dom/src/custom-element/ICustomElementDefinition.ts +16 -0
  324. package/vendor/happy-dom/packages/happy-dom/src/dom/DOMPoint.ts +84 -0
  325. package/vendor/happy-dom/packages/happy-dom/src/dom/DOMPointReadOnly.ts +117 -0
  326. package/vendor/happy-dom/packages/happy-dom/src/dom/DOMRect.ts +92 -0
  327. package/vendor/happy-dom/packages/happy-dom/src/dom/DOMRectList.ts +34 -0
  328. package/vendor/happy-dom/packages/happy-dom/src/dom/DOMRectReadOnly.ts +129 -0
  329. package/vendor/happy-dom/packages/happy-dom/src/dom/DOMStringMap.ts +93 -0
  330. package/vendor/happy-dom/packages/happy-dom/src/dom/DOMStringMapUtility.ts +33 -0
  331. package/vendor/happy-dom/packages/happy-dom/src/dom/DOMTokenList.ts +363 -0
  332. package/vendor/happy-dom/packages/happy-dom/src/dom/IDOMPointInit.ts +6 -0
  333. package/vendor/happy-dom/packages/happy-dom/src/dom/IDOMRectInit.ts +6 -0
  334. package/vendor/happy-dom/packages/happy-dom/src/dom/dom-matrix/DOMMatrix.ts +526 -0
  335. package/vendor/happy-dom/packages/happy-dom/src/dom/dom-matrix/DOMMatrixReadOnly.ts +1608 -0
  336. package/vendor/happy-dom/packages/happy-dom/src/dom/dom-matrix/IDOMMatrixCompatibleObject.ts +24 -0
  337. package/vendor/happy-dom/packages/happy-dom/src/dom/dom-matrix/IDOMMatrixJSON.ts +26 -0
  338. package/vendor/happy-dom/packages/happy-dom/src/dom/dom-matrix/TDOMMatrix2DArray.ts +3 -0
  339. package/vendor/happy-dom/packages/happy-dom/src/dom/dom-matrix/TDOMMatrix3DArray.ts +20 -0
  340. package/vendor/happy-dom/packages/happy-dom/src/dom/dom-matrix/TDOMMatrixInit.ts +8 -0
  341. package/vendor/happy-dom/packages/happy-dom/src/dom-implementation/DOMImplementation.ts +81 -0
  342. package/vendor/happy-dom/packages/happy-dom/src/dom-parser/DOMParser.ts +47 -0
  343. package/vendor/happy-dom/packages/happy-dom/src/event/DataTransfer.ts +128 -0
  344. package/vendor/happy-dom/packages/happy-dom/src/event/DataTransferItem.ts +47 -0
  345. package/vendor/happy-dom/packages/happy-dom/src/event/DataTransferItemList.ts +44 -0
  346. package/vendor/happy-dom/packages/happy-dom/src/event/Event.ts +222 -0
  347. package/vendor/happy-dom/packages/happy-dom/src/event/EventPhaseEnum.ts +7 -0
  348. package/vendor/happy-dom/packages/happy-dom/src/event/EventTarget.ts +396 -0
  349. package/vendor/happy-dom/packages/happy-dom/src/event/IEventInit.ts +5 -0
  350. package/vendor/happy-dom/packages/happy-dom/src/event/IEventListenerOptions.ts +10 -0
  351. package/vendor/happy-dom/packages/happy-dom/src/event/ITouchInit.ts +16 -0
  352. package/vendor/happy-dom/packages/happy-dom/src/event/IUIEventInit.ts +7 -0
  353. package/vendor/happy-dom/packages/happy-dom/src/event/MessagePort.ts +32 -0
  354. package/vendor/happy-dom/packages/happy-dom/src/event/TEventListener.ts +4 -0
  355. package/vendor/happy-dom/packages/happy-dom/src/event/TEventListenerFunction.ts +3 -0
  356. package/vendor/happy-dom/packages/happy-dom/src/event/TEventListenerObject.ts +5 -0
  357. package/vendor/happy-dom/packages/happy-dom/src/event/Touch.ts +40 -0
  358. package/vendor/happy-dom/packages/happy-dom/src/event/UIEvent.ts +32 -0
  359. package/vendor/happy-dom/packages/happy-dom/src/event/events/AnimationEvent.ts +25 -0
  360. package/vendor/happy-dom/packages/happy-dom/src/event/events/ClipboardEvent.ts +22 -0
  361. package/vendor/happy-dom/packages/happy-dom/src/event/events/CloseEvent.ts +25 -0
  362. package/vendor/happy-dom/packages/happy-dom/src/event/events/CookieChangeEvent.ts +25 -0
  363. package/vendor/happy-dom/packages/happy-dom/src/event/events/CustomEvent.ts +53 -0
  364. package/vendor/happy-dom/packages/happy-dom/src/event/events/ErrorEvent.ts +29 -0
  365. package/vendor/happy-dom/packages/happy-dom/src/event/events/FocusEvent.ts +22 -0
  366. package/vendor/happy-dom/packages/happy-dom/src/event/events/HashChangeEvent.ts +25 -0
  367. package/vendor/happy-dom/packages/happy-dom/src/event/events/IAnimationEventInit.ts +7 -0
  368. package/vendor/happy-dom/packages/happy-dom/src/event/events/IClipboardEventInit.ts +6 -0
  369. package/vendor/happy-dom/packages/happy-dom/src/event/events/ICloseEventInit.ts +7 -0
  370. package/vendor/happy-dom/packages/happy-dom/src/event/events/ICookieChangeEventInit.ts +10 -0
  371. package/vendor/happy-dom/packages/happy-dom/src/event/events/ICustomEventInit.ts +5 -0
  372. package/vendor/happy-dom/packages/happy-dom/src/event/events/IErrorEventInit.ts +8 -0
  373. package/vendor/happy-dom/packages/happy-dom/src/event/events/IFocusEventInit.ts +6 -0
  374. package/vendor/happy-dom/packages/happy-dom/src/event/events/IHashChangeEventInit.ts +6 -0
  375. package/vendor/happy-dom/packages/happy-dom/src/event/events/IInputEventInit.ts +9 -0
  376. package/vendor/happy-dom/packages/happy-dom/src/event/events/IKeyboardEventInit.ts +23 -0
  377. package/vendor/happy-dom/packages/happy-dom/src/event/events/IMediaQueryListEventInit.ts +6 -0
  378. package/vendor/happy-dom/packages/happy-dom/src/event/events/IMediaQueryListInit.ts +6 -0
  379. package/vendor/happy-dom/packages/happy-dom/src/event/events/IMessageEventInit.ts +11 -0
  380. package/vendor/happy-dom/packages/happy-dom/src/event/events/IMouseEventInit.ts +21 -0
  381. package/vendor/happy-dom/packages/happy-dom/src/event/events/IPointerEventInit.ts +19 -0
  382. package/vendor/happy-dom/packages/happy-dom/src/event/events/IPopStateEventInit.ts +6 -0
  383. package/vendor/happy-dom/packages/happy-dom/src/event/events/IProgressEventInit.ts +7 -0
  384. package/vendor/happy-dom/packages/happy-dom/src/event/events/IStorageEventInit.ts +10 -0
  385. package/vendor/happy-dom/packages/happy-dom/src/event/events/ISubmitEventInit.ts +6 -0
  386. package/vendor/happy-dom/packages/happy-dom/src/event/events/ITouchEventInit.ts +12 -0
  387. package/vendor/happy-dom/packages/happy-dom/src/event/events/IWheelEventInit.ts +8 -0
  388. package/vendor/happy-dom/packages/happy-dom/src/event/events/InputEvent.ts +28 -0
  389. package/vendor/happy-dom/packages/happy-dom/src/event/events/KeyboardEvent.ts +80 -0
  390. package/vendor/happy-dom/packages/happy-dom/src/event/events/MediaQueryListEvent.ts +23 -0
  391. package/vendor/happy-dom/packages/happy-dom/src/event/events/MediaStreamTrackEvent.ts +22 -0
  392. package/vendor/happy-dom/packages/happy-dom/src/event/events/MessageEvent.ts +33 -0
  393. package/vendor/happy-dom/packages/happy-dom/src/event/events/MouseEvent.ts +52 -0
  394. package/vendor/happy-dom/packages/happy-dom/src/event/events/PointerEvent.ts +51 -0
  395. package/vendor/happy-dom/packages/happy-dom/src/event/events/PopStateEvent.ts +23 -0
  396. package/vendor/happy-dom/packages/happy-dom/src/event/events/ProgressEvent.ts +25 -0
  397. package/vendor/happy-dom/packages/happy-dom/src/event/events/StorageEvent.ts +30 -0
  398. package/vendor/happy-dom/packages/happy-dom/src/event/events/SubmitEvent.ts +22 -0
  399. package/vendor/happy-dom/packages/happy-dom/src/event/events/TouchEvent.ts +34 -0
  400. package/vendor/happy-dom/packages/happy-dom/src/event/events/WheelEvent.ts +30 -0
  401. package/vendor/happy-dom/packages/happy-dom/src/exception/DOMException.ts +21 -0
  402. package/vendor/happy-dom/packages/happy-dom/src/exception/DOMExceptionNameEnum.ts +23 -0
  403. package/vendor/happy-dom/packages/happy-dom/src/fetch/AbortController.ts +25 -0
  404. package/vendor/happy-dom/packages/happy-dom/src/fetch/AbortSignal.ts +182 -0
  405. package/vendor/happy-dom/packages/happy-dom/src/fetch/Fetch.ts +1072 -0
  406. package/vendor/happy-dom/packages/happy-dom/src/fetch/Headers.ts +177 -0
  407. package/vendor/happy-dom/packages/happy-dom/src/fetch/ReadableStreamWrapper.ts +30 -0
  408. package/vendor/happy-dom/packages/happy-dom/src/fetch/Request.ts +492 -0
  409. package/vendor/happy-dom/packages/happy-dom/src/fetch/ResourceFetch.ts +190 -0
  410. package/vendor/happy-dom/packages/happy-dom/src/fetch/Response.ts +439 -0
  411. package/vendor/happy-dom/packages/happy-dom/src/fetch/SyncFetch.ts +717 -0
  412. package/vendor/happy-dom/packages/happy-dom/src/fetch/cache/preflight/ICacheablePreflightRequest.ts +7 -0
  413. package/vendor/happy-dom/packages/happy-dom/src/fetch/cache/preflight/ICacheablePreflightResponse.ts +7 -0
  414. package/vendor/happy-dom/packages/happy-dom/src/fetch/cache/preflight/ICachedPreflightResponse.ts +5 -0
  415. package/vendor/happy-dom/packages/happy-dom/src/fetch/cache/preflight/IPreflightResponseCache.ts +33 -0
  416. package/vendor/happy-dom/packages/happy-dom/src/fetch/cache/preflight/PreflightResponseCache.ts +94 -0
  417. package/vendor/happy-dom/packages/happy-dom/src/fetch/cache/response/CachedResponseStateEnum.ts +5 -0
  418. package/vendor/happy-dom/packages/happy-dom/src/fetch/cache/response/ICacheableRequest.ts +7 -0
  419. package/vendor/happy-dom/packages/happy-dom/src/fetch/cache/response/ICacheableResponse.ts +11 -0
  420. package/vendor/happy-dom/packages/happy-dom/src/fetch/cache/response/ICachedResponse.ts +40 -0
  421. package/vendor/happy-dom/packages/happy-dom/src/fetch/cache/response/IResponseCache.ts +37 -0
  422. package/vendor/happy-dom/packages/happy-dom/src/fetch/cache/response/IResponseCacheFileSystem.ts +18 -0
  423. package/vendor/happy-dom/packages/happy-dom/src/fetch/cache/response/ResponseCache.ts +248 -0
  424. package/vendor/happy-dom/packages/happy-dom/src/fetch/cache/response/ResponseCacheFileSystem.ts +175 -0
  425. package/vendor/happy-dom/packages/happy-dom/src/fetch/certificate/FetchHTTPSCertificate.ts +52 -0
  426. package/vendor/happy-dom/packages/happy-dom/src/fetch/data-uri/DataURIParser.ts +66 -0
  427. package/vendor/happy-dom/packages/happy-dom/src/fetch/multipart/MultipartFormDataParser.ts +174 -0
  428. package/vendor/happy-dom/packages/happy-dom/src/fetch/multipart/MultipartReader.ts +216 -0
  429. package/vendor/happy-dom/packages/happy-dom/src/fetch/preload/PreloadEntry.ts +50 -0
  430. package/vendor/happy-dom/packages/happy-dom/src/fetch/preload/PreloadUtility.ts +33 -0
  431. package/vendor/happy-dom/packages/happy-dom/src/fetch/types/IFetchInterceptor.ts +60 -0
  432. package/vendor/happy-dom/packages/happy-dom/src/fetch/types/IFetchRequestHeaders.ts +9 -0
  433. package/vendor/happy-dom/packages/happy-dom/src/fetch/types/IRequestInit.ts +23 -0
  434. package/vendor/happy-dom/packages/happy-dom/src/fetch/types/IResourceFetchResponse.ts +4 -0
  435. package/vendor/happy-dom/packages/happy-dom/src/fetch/types/IResponseInit.ts +10 -0
  436. package/vendor/happy-dom/packages/happy-dom/src/fetch/types/ISyncResponse.ts +18 -0
  437. package/vendor/happy-dom/packages/happy-dom/src/fetch/types/IVirtualServer.ts +7 -0
  438. package/vendor/happy-dom/packages/happy-dom/src/fetch/types/THeadersInit.ts +3 -0
  439. package/vendor/happy-dom/packages/happy-dom/src/fetch/types/TRequestBody.ts +14 -0
  440. package/vendor/happy-dom/packages/happy-dom/src/fetch/types/TRequestCredentials.ts +1 -0
  441. package/vendor/happy-dom/packages/happy-dom/src/fetch/types/TRequestInfo.ts +4 -0
  442. package/vendor/happy-dom/packages/happy-dom/src/fetch/types/TRequestMode.ts +1 -0
  443. package/vendor/happy-dom/packages/happy-dom/src/fetch/types/TRequestRedirect.ts +1 -0
  444. package/vendor/happy-dom/packages/happy-dom/src/fetch/types/TRequestReferrerPolicy.ts +10 -0
  445. package/vendor/happy-dom/packages/happy-dom/src/fetch/types/TResponseBody.ts +14 -0
  446. package/vendor/happy-dom/packages/happy-dom/src/fetch/utilities/FetchBodyUtility.ts +284 -0
  447. package/vendor/happy-dom/packages/happy-dom/src/fetch/utilities/FetchCORSUtility.ts +23 -0
  448. package/vendor/happy-dom/packages/happy-dom/src/fetch/utilities/FetchRequestHeaderUtility.ts +141 -0
  449. package/vendor/happy-dom/packages/happy-dom/src/fetch/utilities/FetchRequestReferrerUtility.ts +259 -0
  450. package/vendor/happy-dom/packages/happy-dom/src/fetch/utilities/FetchRequestValidationUtility.ts +128 -0
  451. package/vendor/happy-dom/packages/happy-dom/src/fetch/utilities/FetchResponseHeaderUtility.ts +48 -0
  452. package/vendor/happy-dom/packages/happy-dom/src/fetch/utilities/FetchResponseRedirectUtility.ts +27 -0
  453. package/vendor/happy-dom/packages/happy-dom/src/fetch/utilities/SyncFetchScriptBuilder.ts +77 -0
  454. package/vendor/happy-dom/packages/happy-dom/src/fetch/utilities/VirtualServerUtility.ts +114 -0
  455. package/vendor/happy-dom/packages/happy-dom/src/file/Blob.ts +163 -0
  456. package/vendor/happy-dom/packages/happy-dom/src/file/File.ts +43 -0
  457. package/vendor/happy-dom/packages/happy-dom/src/file/FileReader.ts +211 -0
  458. package/vendor/happy-dom/packages/happy-dom/src/file/FileReaderEventTypeEnum.ts +9 -0
  459. package/vendor/happy-dom/packages/happy-dom/src/file/FileReaderFormatEnum.ts +7 -0
  460. package/vendor/happy-dom/packages/happy-dom/src/file/FileReaderReadyStateEnum.ts +6 -0
  461. package/vendor/happy-dom/packages/happy-dom/src/form-data/FormData.ts +291 -0
  462. package/vendor/happy-dom/packages/happy-dom/src/history/History.ts +220 -0
  463. package/vendor/happy-dom/packages/happy-dom/src/history/HistoryItemList.ts +72 -0
  464. package/vendor/happy-dom/packages/happy-dom/src/history/HistoryScrollRestorationEnum.ts +5 -0
  465. package/vendor/happy-dom/packages/happy-dom/src/history/IHistoryItem.ts +12 -0
  466. package/vendor/happy-dom/packages/happy-dom/src/html-parser/HTMLParser.ts +920 -0
  467. package/vendor/happy-dom/packages/happy-dom/src/html-serializer/HTMLSerializer.ts +172 -0
  468. package/vendor/happy-dom/packages/happy-dom/src/index.ts +495 -0
  469. package/vendor/happy-dom/packages/happy-dom/src/intersection-observer/IIntersectionObserverInit.ts +16 -0
  470. package/vendor/happy-dom/packages/happy-dom/src/intersection-observer/IntersectionObserver.ts +64 -0
  471. package/vendor/happy-dom/packages/happy-dom/src/intersection-observer/IntersectionObserverEntry.ts +26 -0
  472. package/vendor/happy-dom/packages/happy-dom/src/javascript/IJavaScriptCompiledResult.ts +9 -0
  473. package/vendor/happy-dom/packages/happy-dom/src/javascript/JavaScriptCompiler.ts +381 -0
  474. package/vendor/happy-dom/packages/happy-dom/src/location/Location.ts +319 -0
  475. package/vendor/happy-dom/packages/happy-dom/src/match-media/IMediaQueryRange.ts +5 -0
  476. package/vendor/happy-dom/packages/happy-dom/src/match-media/IMediaQueryRule.ts +4 -0
  477. package/vendor/happy-dom/packages/happy-dom/src/match-media/MediaQueryItem.ts +354 -0
  478. package/vendor/happy-dom/packages/happy-dom/src/match-media/MediaQueryList.ts +133 -0
  479. package/vendor/happy-dom/packages/happy-dom/src/match-media/MediaQueryParser.ts +113 -0
  480. package/vendor/happy-dom/packages/happy-dom/src/match-media/MediaQueryTypeEnum.ts +7 -0
  481. package/vendor/happy-dom/packages/happy-dom/src/module/CSSModule.ts +53 -0
  482. package/vendor/happy-dom/packages/happy-dom/src/module/ECMAScriptModule.ts +194 -0
  483. package/vendor/happy-dom/packages/happy-dom/src/module/ECMAScriptModuleCompiler.ts +961 -0
  484. package/vendor/happy-dom/packages/happy-dom/src/module/JSONModule.ts +58 -0
  485. package/vendor/happy-dom/packages/happy-dom/src/module/ModuleFactory.ts +148 -0
  486. package/vendor/happy-dom/packages/happy-dom/src/module/ModuleURLUtility.ts +199 -0
  487. package/vendor/happy-dom/packages/happy-dom/src/module/UnresolvedModule.ts +81 -0
  488. package/vendor/happy-dom/packages/happy-dom/src/module/enums/ECMAScriptModuleEvaluateStateEnum.ts +7 -0
  489. package/vendor/happy-dom/packages/happy-dom/src/module/types/IECMAScriptModuleCachedResult.ts +9 -0
  490. package/vendor/happy-dom/packages/happy-dom/src/module/types/IECMAScriptModuleCompiledResult.ts +19 -0
  491. package/vendor/happy-dom/packages/happy-dom/src/module/types/IECMAScriptModuleImport.ts +4 -0
  492. package/vendor/happy-dom/packages/happy-dom/src/module/types/IECMAScriptModuleInit.ts +10 -0
  493. package/vendor/happy-dom/packages/happy-dom/src/module/types/IModule.ts +20 -0
  494. package/vendor/happy-dom/packages/happy-dom/src/module/types/IModuleImportMap.ts +10 -0
  495. package/vendor/happy-dom/packages/happy-dom/src/module/types/IModuleImportMapRule.ts +4 -0
  496. package/vendor/happy-dom/packages/happy-dom/src/module/types/IModuleImportMapScope.ts +6 -0
  497. package/vendor/happy-dom/packages/happy-dom/src/module/types/IModuleInit.ts +12 -0
  498. package/vendor/happy-dom/packages/happy-dom/src/module/types/IResolveNodeModules.ts +8 -0
  499. package/vendor/happy-dom/packages/happy-dom/src/mutation-observer/IMutationListener.ts +7 -0
  500. package/vendor/happy-dom/packages/happy-dom/src/mutation-observer/IMutationObserverInit.ts +14 -0
  501. package/vendor/happy-dom/packages/happy-dom/src/mutation-observer/MutationObserver.ts +175 -0
  502. package/vendor/happy-dom/packages/happy-dom/src/mutation-observer/MutationObserverListener.ts +115 -0
  503. package/vendor/happy-dom/packages/happy-dom/src/mutation-observer/MutationRecord.ts +55 -0
  504. package/vendor/happy-dom/packages/happy-dom/src/mutation-observer/MutationTypeEnum.ts +7 -0
  505. package/vendor/happy-dom/packages/happy-dom/src/navigator/MimeType.ts +35 -0
  506. package/vendor/happy-dom/packages/happy-dom/src/navigator/MimeTypeArray.ts +48 -0
  507. package/vendor/happy-dom/packages/happy-dom/src/navigator/Navigator.ts +247 -0
  508. package/vendor/happy-dom/packages/happy-dom/src/navigator/Plugin.ts +61 -0
  509. package/vendor/happy-dom/packages/happy-dom/src/navigator/PluginArray.ts +58 -0
  510. package/vendor/happy-dom/packages/happy-dom/src/nodes/NodeFactory.ts +38 -0
  511. package/vendor/happy-dom/packages/happy-dom/src/nodes/attr/Attr.ts +119 -0
  512. package/vendor/happy-dom/packages/happy-dom/src/nodes/character-data/CharacterData.ts +218 -0
  513. package/vendor/happy-dom/packages/happy-dom/src/nodes/character-data/CharacterDataUtility.ts +68 -0
  514. package/vendor/happy-dom/packages/happy-dom/src/nodes/child-node/ChildNodeUtility.ts +100 -0
  515. package/vendor/happy-dom/packages/happy-dom/src/nodes/child-node/IChildNode.ts +29 -0
  516. package/vendor/happy-dom/packages/happy-dom/src/nodes/child-node/INonDocumentTypeChildNode.ts +7 -0
  517. package/vendor/happy-dom/packages/happy-dom/src/nodes/child-node/NonDocumentChildNodeUtility.ts +37 -0
  518. package/vendor/happy-dom/packages/happy-dom/src/nodes/comment/Comment.ts +36 -0
  519. package/vendor/happy-dom/packages/happy-dom/src/nodes/document/Document.ts +2310 -0
  520. package/vendor/happy-dom/packages/happy-dom/src/nodes/document/DocumentReadyStateEnum.ts +6 -0
  521. package/vendor/happy-dom/packages/happy-dom/src/nodes/document/DocumentReadyStateManager.ts +52 -0
  522. package/vendor/happy-dom/packages/happy-dom/src/nodes/document/VisibilityStateEnum.ts +6 -0
  523. package/vendor/happy-dom/packages/happy-dom/src/nodes/document-fragment/DocumentFragment.ts +208 -0
  524. package/vendor/happy-dom/packages/happy-dom/src/nodes/document-type/DocumentType.ts +70 -0
  525. package/vendor/happy-dom/packages/happy-dom/src/nodes/element/Element.ts +1842 -0
  526. package/vendor/happy-dom/packages/happy-dom/src/nodes/element/ElementEventAttributeUtility.ts +96 -0
  527. package/vendor/happy-dom/packages/happy-dom/src/nodes/element/HTMLCollection.ts +228 -0
  528. package/vendor/happy-dom/packages/happy-dom/src/nodes/element/NamedNodeMap.ts +274 -0
  529. package/vendor/happy-dom/packages/happy-dom/src/nodes/element/NamedNodeMapProxyFactory.ts +127 -0
  530. package/vendor/happy-dom/packages/happy-dom/src/nodes/element/THTMLCollectionListener.ts +6 -0
  531. package/vendor/happy-dom/packages/happy-dom/src/nodes/element/TNamedNodeMapListener.ts +3 -0
  532. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-anchor-element/HTMLAnchorElement.ts +439 -0
  533. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-area-element/HTMLAreaElement.ts +426 -0
  534. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-audio-element/Audio.ts +28 -0
  535. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-audio-element/HTMLAudioElement.ts +10 -0
  536. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-base-element/HTMLBaseElement.ts +64 -0
  537. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-body-element/HTMLBodyElement.ts +161 -0
  538. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-br-element/HTMLBRElement.ts +7 -0
  539. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-button-element/HTMLButtonElement.ts +406 -0
  540. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-canvas-element/CanvasCaptureMediaStreamTrack.ts +51 -0
  541. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-canvas-element/HTMLCanvasElement.ts +304 -0
  542. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-d-list-element/HTMLDListElement.ts +7 -0
  543. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-data-element/HTMLDataElement.ts +25 -0
  544. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-data-list-element/HTMLDataListElement.ts +28 -0
  545. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-details-element/HTMLDetailsElement.ts +112 -0
  546. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-dialog-element/HTMLDialogElement.ts +104 -0
  547. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-div-element/HTMLDivElement.ts +7 -0
  548. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-document/HTMLDocument.ts +82 -0
  549. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-element/HTMLElement.ts +1149 -0
  550. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-element/HTMLElementUtility.ts +119 -0
  551. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-embed-element/HTMLEmbedElement.ts +90 -0
  552. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-field-set-element/HTMLFieldSetElement.ts +165 -0
  553. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-form-element/HTMLFormControlsCollection.ts +35 -0
  554. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-form-element/HTMLFormElement.ts +675 -0
  555. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-form-element/RadioNodeList.ts +25 -0
  556. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-form-element/THTMLFormControlElement.ts +16 -0
  557. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-head-element/HTMLHeadElement.ts +7 -0
  558. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-heading-element/HTMLHeadingElement.ts +7 -0
  559. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-hr-element/HTMLHRElement.ts +7 -0
  560. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-html-element/HTMLHtmlElement.ts +7 -0
  561. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-hyperlink-element/HTMLHyperlinkElementUtility.ts +329 -0
  562. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-hyperlink-element/IHTMLHyperlinkElement.ts +19 -0
  563. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-iframe-element/HTMLIFrameElement.ts +460 -0
  564. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-image-element/HTMLImageElement.ts +500 -0
  565. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-image-element/Image.ts +33 -0
  566. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-input-element/FileList.ts +34 -0
  567. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-input-element/HTMLInputElement.ts +1550 -0
  568. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-input-element/HTMLInputElementDateUtility.ts +50 -0
  569. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-input-element/HTMLInputElementSelectionDirectionEnum.ts +6 -0
  570. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-input-element/HTMLInputElementSelectionModeEnum.ts +7 -0
  571. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-input-element/HTMLInputElementValueSanitizer.ts +211 -0
  572. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-input-element/HTMLInputElementValueStepping.ts +92 -0
  573. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-label-element/HTMLLabelElement.ts +128 -0
  574. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-label-element/HTMLLabelElementUtility.ts +45 -0
  575. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-legend-element/HTMLLegendElement.ts +27 -0
  576. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-li-element/HTMLLIElement.ts +31 -0
  577. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-link-element/HTMLLinkElement.ts +501 -0
  578. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-map-element/HTMLMapElement.ts +47 -0
  579. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-media-element/HTMLMediaElement.ts +906 -0
  580. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-media-element/IMediaTrackCapabilities.ts +21 -0
  581. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-media-element/IMediaTrackSettings.ts +5 -0
  582. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-media-element/MediaStream.ts +114 -0
  583. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-media-element/MediaStreamTrack.ts +182 -0
  584. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-media-element/RemotePlayback.ts +47 -0
  585. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-media-element/TextTrack.ts +156 -0
  586. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-media-element/TextTrackCue.ts +51 -0
  587. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-media-element/TextTrackCueList.ts +37 -0
  588. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-media-element/TextTrackKindEnum.ts +9 -0
  589. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-media-element/TextTrackList.ts +182 -0
  590. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-media-element/TimeRanges.ts +73 -0
  591. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-media-element/VTTCue.ts +80 -0
  592. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-media-element/VTTRegion.ts +15 -0
  593. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-menu-element/HTMLMenuElement.ts +7 -0
  594. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-meta-element/HTMLMetaElement.ts +80 -0
  595. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-meter-element/HTMLMeterElement.ts +216 -0
  596. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-mod-element/HTMLModElement.ts +54 -0
  597. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-o-list-element/HTMLOListElement.ts +83 -0
  598. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-object-element/HTMLObjectElement.ts +223 -0
  599. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-opt-group-element/HTMLOptGroupElement.ts +53 -0
  600. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-option-element/HTMLOptionElement.ts +192 -0
  601. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-output-element/HTMLOutputElement.ts +179 -0
  602. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-paragraph-element/HTMLParagraphElement.ts +7 -0
  603. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-param-element/HTMLParamElement.ts +7 -0
  604. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-picture-element/HTMLPictureElement.ts +7 -0
  605. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-pre-element/HTMLPreElement.ts +7 -0
  606. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-progress-element/HTMLProgressElement.ts +100 -0
  607. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-quote-element/HTMLQuoteElement.ts +36 -0
  608. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-script-element/HTMLScriptElement.ts +735 -0
  609. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-select-element/HTMLOptionsCollection.ts +69 -0
  610. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-select-element/HTMLSelectElement.ts +779 -0
  611. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-slot-element/HTMLSlotElement.ts +249 -0
  612. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-source-element/HTMLSourceElement.ts +148 -0
  613. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-span-element/HTMLSpanElement.ts +7 -0
  614. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-style-element/HTMLStyleElement.ts +125 -0
  615. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-table-caption-element/HTMLTableCaptionElement.ts +7 -0
  616. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-table-cell-element/HTMLTableCellElement.ts +125 -0
  617. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-table-col-element/HTMLTableColElement.ts +7 -0
  618. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-table-element/HTMLTableElement.ts +343 -0
  619. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-table-row-element/HTMLTableRowElement.ts +149 -0
  620. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-table-section-element/HTMLTableSectionElement.ts +88 -0
  621. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-template-element/HTMLTemplateElement.ts +154 -0
  622. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-text-area-element/HTMLTextAreaElement.ts +649 -0
  623. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-time-element/HTMLTimeElement.ts +27 -0
  624. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-title-element/HTMLTitleElement.ts +48 -0
  625. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-track-element/HTMLTrackElement.ts +164 -0
  626. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-u-list-element/HTMLUListElement.ts +7 -0
  627. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-unknown-element/HTMLUnknownElement.ts +9 -0
  628. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-video-element/HTMLVideoElement.ts +10 -0
  629. package/vendor/happy-dom/packages/happy-dom/src/nodes/node/ICachedComputedStyleResult.ts +6 -0
  630. package/vendor/happy-dom/packages/happy-dom/src/nodes/node/ICachedElementByIdResult.ts +6 -0
  631. package/vendor/happy-dom/packages/happy-dom/src/nodes/node/ICachedElementByTagNameResult.ts +6 -0
  632. package/vendor/happy-dom/packages/happy-dom/src/nodes/node/ICachedElementsByTagNameResult.ts +6 -0
  633. package/vendor/happy-dom/packages/happy-dom/src/nodes/node/ICachedMatchesResult.ts +6 -0
  634. package/vendor/happy-dom/packages/happy-dom/src/nodes/node/ICachedQuerySelectorAllResult.ts +7 -0
  635. package/vendor/happy-dom/packages/happy-dom/src/nodes/node/ICachedQuerySelectorResult.ts +6 -0
  636. package/vendor/happy-dom/packages/happy-dom/src/nodes/node/ICachedResult.ts +3 -0
  637. package/vendor/happy-dom/packages/happy-dom/src/nodes/node/ICachedStyleResult.ts +6 -0
  638. package/vendor/happy-dom/packages/happy-dom/src/nodes/node/Node.ts +1373 -0
  639. package/vendor/happy-dom/packages/happy-dom/src/nodes/node/NodeDocumentPositionEnum.ts +10 -0
  640. package/vendor/happy-dom/packages/happy-dom/src/nodes/node/NodeList.ts +224 -0
  641. package/vendor/happy-dom/packages/happy-dom/src/nodes/node/NodeTypeEnum.ts +13 -0
  642. package/vendor/happy-dom/packages/happy-dom/src/nodes/node/NodeUtility.ts +330 -0
  643. package/vendor/happy-dom/packages/happy-dom/src/nodes/node/TNodeListListener.ts +1 -0
  644. package/vendor/happy-dom/packages/happy-dom/src/nodes/parent-node/IParentNode.ts +109 -0
  645. package/vendor/happy-dom/packages/happy-dom/src/nodes/parent-node/ParentNodeUtility.ts +334 -0
  646. package/vendor/happy-dom/packages/happy-dom/src/nodes/processing-instruction/ProcessingInstruction.ts +22 -0
  647. package/vendor/happy-dom/packages/happy-dom/src/nodes/shadow-root/ShadowRoot.ts +290 -0
  648. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-animate-element/SVGAnimateElement.ts +8 -0
  649. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-animate-motion-element/SVGAnimateMotionElement.ts +8 -0
  650. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-animate-transform-element/SVGAnimateTransformElement.ts +8 -0
  651. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-animation-element/SVGAnimationElement.ts +94 -0
  652. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-circle-element/SVGCircleElement.ts +72 -0
  653. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-clip-path-element/SVGClipPathElement.ts +34 -0
  654. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-component-transfer-function-element/SVGComponentTransferFunctionElement.ts +167 -0
  655. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-defs-element/SVGDefsElement.ts +8 -0
  656. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-desc-element/SVGDescElement.ts +8 -0
  657. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-element/SVGElement.ts +828 -0
  658. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-ellipse-element/SVGEllipseElement.ts +92 -0
  659. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-fe-blend-element/SVGFEBlendElement.ts +192 -0
  660. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-fe-color-matrix-element/SVGFEColorMatrixElement.ts +204 -0
  661. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-fe-component-transfer-element/SVGFEComponentTransferElement.ts +133 -0
  662. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-fe-composite-element/SVGFECompositeElement.ts +186 -0
  663. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-fe-convolve-matrix-element/SVGFEConvolveMatrixElement.ts +366 -0
  664. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-fe-diffuse-lighting-element/SVGFEDiffuseLightingElement.ts +214 -0
  665. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-fe-displacement-map-element/SVGFEDisplacementMapElement.ts +226 -0
  666. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-fe-distant-light-element/SVGFEDistantLightElement.ts +52 -0
  667. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-fe-drop-shadow-element/SVGFEDropShadowElement.ts +227 -0
  668. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-fe-flood-element/SVGFEFloodElement.ts +113 -0
  669. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-fe-func-a-element/SVGFEFuncAElement.ts +8 -0
  670. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-fe-func-b-element/SVGFEFuncBElement.ts +8 -0
  671. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-fe-func-g-element/SVGFEFuncGElement.ts +8 -0
  672. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-fe-func-r-element/SVGFEFuncRElement.ts +8 -0
  673. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-fe-gaussian-blur-element/SVGFEGaussianBlurElement.ts +214 -0
  674. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-fe-image-element/SVGFEImageElement.ts +173 -0
  675. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-fe-merge-element/SVGFEMergeElement.ts +113 -0
  676. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-fe-merge-node-element/SVGFEMergeNodeElement.ts +32 -0
  677. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-fe-morphology-element/SVGFEMorphologyElement.ts +202 -0
  678. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-fe-offset-element/SVGFEOffsetElement.ts +174 -0
  679. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-fe-point-light-element/SVGFEPointLightElement.ts +72 -0
  680. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-fe-specular-lighting-element/SVGFESpecularLightingElement.ts +237 -0
  681. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-fe-spot-light-element/SVGFESpotLightElement.ts +173 -0
  682. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-fe-tile-element/SVGFETileElement.ts +133 -0
  683. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-fe-turbulence-element/SVGFETurbulenceElement.ts +249 -0
  684. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-filter-element/SVGFilterElement.ts +158 -0
  685. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-foreign-object-element/SVGForeignObjectElement.ts +92 -0
  686. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-g-element/SVGGElement.ts +8 -0
  687. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-geometry-element/SVGGeometryElement.ts +94 -0
  688. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-gradient-element/SVGGradientElement.ts +104 -0
  689. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-graphics-element/SVGGraphicsElement.ts +134 -0
  690. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-image-element/SVGImageElement.ts +188 -0
  691. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-line-element/SVGLineElement.ts +92 -0
  692. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-linear-gradient-element/SVGLinearGradientElement.ts +92 -0
  693. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-m-path-element/SVGMPathElement.ts +32 -0
  694. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-marker-element/SVGMarkerElement.ts +230 -0
  695. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-mask-element/SVGMaskElement.ts +137 -0
  696. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-metadata-element/SVGMetadataElement.ts +8 -0
  697. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-path-element/SVGPathElement.ts +8 -0
  698. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-pattern-element/SVGPatternElement.ts +179 -0
  699. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-polygon-element/SVGPolygonElement.ts +53 -0
  700. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-polyline-element/SVGPolylineElement.ts +53 -0
  701. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-radial-gradient-element/SVGRadialGradientElement.ts +112 -0
  702. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-rect-element/SVGRectElement.ts +132 -0
  703. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-script-element/SVGScriptElement.ts +50 -0
  704. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-set-element/SVGSetElement.ts +8 -0
  705. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-stop-element/SVGStopElement.ts +32 -0
  706. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-style-element/SVGStyleElement.ts +143 -0
  707. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-svg-element/SVGSVGElement.ts +601 -0
  708. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-switch-element/SVGSwitchElement.ts +8 -0
  709. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-symbol-element/SVGSymbolElement.ts +8 -0
  710. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-t-span-element/SVGTSpanElement.ts +8 -0
  711. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-text-content-element/SVGTextContentElement.ts +143 -0
  712. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-text-element/SVGTextElement.ts +8 -0
  713. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-text-path-element/SVGTextPathElement.ts +106 -0
  714. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-text-positioning-element/SVGTextPositioningElement.ts +113 -0
  715. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-title-element/SVGTitleElement.ts +8 -0
  716. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-use-element/SVGUseElement.ts +113 -0
  717. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-view-element/SVGViewElement.ts +8 -0
  718. package/vendor/happy-dom/packages/happy-dom/src/nodes/text/Text.ts +154 -0
  719. package/vendor/happy-dom/packages/happy-dom/src/nodes/xml-document/XMLDocument.ts +10 -0
  720. package/vendor/happy-dom/packages/happy-dom/src/permissions/PermissionNameEnum.ts +32 -0
  721. package/vendor/happy-dom/packages/happy-dom/src/permissions/PermissionStatus.ts +23 -0
  722. package/vendor/happy-dom/packages/happy-dom/src/permissions/Permissions.ts +59 -0
  723. package/vendor/happy-dom/packages/happy-dom/src/query-selector/ISelectorAttribute.ts +7 -0
  724. package/vendor/happy-dom/packages/happy-dom/src/query-selector/ISelectorMatch.ts +3 -0
  725. package/vendor/happy-dom/packages/happy-dom/src/query-selector/ISelectorPseudo.ts +8 -0
  726. package/vendor/happy-dom/packages/happy-dom/src/query-selector/QuerySelector.ts +849 -0
  727. package/vendor/happy-dom/packages/happy-dom/src/query-selector/SelectorCombinatorEnum.ts +9 -0
  728. package/vendor/happy-dom/packages/happy-dom/src/query-selector/SelectorItem.ts +575 -0
  729. package/vendor/happy-dom/packages/happy-dom/src/query-selector/SelectorParser.ts +699 -0
  730. package/vendor/happy-dom/packages/happy-dom/src/query-selector/TGlobalMatchFunction.ts +12 -0
  731. package/vendor/happy-dom/packages/happy-dom/src/range/IRangeBoundaryPoint.ts +9 -0
  732. package/vendor/happy-dom/packages/happy-dom/src/range/Range.ts +1161 -0
  733. package/vendor/happy-dom/packages/happy-dom/src/range/RangeHowEnum.ts +8 -0
  734. package/vendor/happy-dom/packages/happy-dom/src/range/RangeUtility.ts +118 -0
  735. package/vendor/happy-dom/packages/happy-dom/src/resize-observer/ResizeObserver.ts +33 -0
  736. package/vendor/happy-dom/packages/happy-dom/src/screen/Screen.ts +19 -0
  737. package/vendor/happy-dom/packages/happy-dom/src/screen/ScreenDetailed.ts +17 -0
  738. package/vendor/happy-dom/packages/happy-dom/src/screen/ScreenDetails.ts +27 -0
  739. package/vendor/happy-dom/packages/happy-dom/src/selection/Selection.ts +556 -0
  740. package/vendor/happy-dom/packages/happy-dom/src/selection/SelectionDirectionEnum.ts +7 -0
  741. package/vendor/happy-dom/packages/happy-dom/src/storage/Storage.ts +149 -0
  742. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGAngle.ts +310 -0
  743. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGAngleTypeEnum.ts +9 -0
  744. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGAnimatedAngle.ts +100 -0
  745. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGAnimatedBoolean.ts +80 -0
  746. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGAnimatedEnumeration.ts +119 -0
  747. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGAnimatedInteger.ts +97 -0
  748. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGAnimatedLength.ts +100 -0
  749. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGAnimatedLengthList.ts +101 -0
  750. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGAnimatedNumber.ts +101 -0
  751. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGAnimatedNumberList.ts +101 -0
  752. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGAnimatedPreserveAspectRatio.ts +100 -0
  753. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGAnimatedRect.ts +100 -0
  754. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGAnimatedString.ts +83 -0
  755. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGAnimatedTransformList.ts +101 -0
  756. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGLength.ts +375 -0
  757. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGLengthList.ts +489 -0
  758. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGLengthTypeEnum.ts +15 -0
  759. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGMatrix.ts +429 -0
  760. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGNumber.ts +83 -0
  761. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGNumberList.ts +522 -0
  762. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGPoint.ts +114 -0
  763. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGPointList.ts +526 -0
  764. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGPreserveAspectRatio.ts +176 -0
  765. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGPreserveAspectRatioAlignEnum.ts +15 -0
  766. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGPreserveAspectRatioMeetOrSliceEnum.ts +7 -0
  767. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGRect.ts +200 -0
  768. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGStringList.ts +422 -0
  769. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGTransform.ts +369 -0
  770. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGTransformList.ts +531 -0
  771. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGTransformTypeEnum.ts +11 -0
  772. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGUnitTypes.ts +26 -0
  773. package/vendor/happy-dom/packages/happy-dom/src/tree-walker/NodeFilter.ts +18 -0
  774. package/vendor/happy-dom/packages/happy-dom/src/tree-walker/NodeFilterMask.ts +28 -0
  775. package/vendor/happy-dom/packages/happy-dom/src/tree-walker/NodeIterator.ts +85 -0
  776. package/vendor/happy-dom/packages/happy-dom/src/tree-walker/TNodeFilter.ts +3 -0
  777. package/vendor/happy-dom/packages/happy-dom/src/tree-walker/TreeWalker.ts +339 -0
  778. package/vendor/happy-dom/packages/happy-dom/src/url/URL.ts +45 -0
  779. package/vendor/happy-dom/packages/happy-dom/src/utilities/AttributeUtility.ts +43 -0
  780. package/vendor/happy-dom/packages/happy-dom/src/utilities/ClassMethodBinder.ts +71 -0
  781. package/vendor/happy-dom/packages/happy-dom/src/utilities/StringUtility.ts +47 -0
  782. package/vendor/happy-dom/packages/happy-dom/src/utilities/XMLEncodeUtility.ts +166 -0
  783. package/vendor/happy-dom/packages/happy-dom/src/validity-state/ValidityState.ts +234 -0
  784. package/vendor/happy-dom/packages/happy-dom/src/version.ts +1 -0
  785. package/vendor/happy-dom/packages/happy-dom/src/web-socket/WebSocket.ts +408 -0
  786. package/vendor/happy-dom/packages/happy-dom/src/web-socket/WebSocketReadyStateEnum.ts +8 -0
  787. package/vendor/happy-dom/packages/happy-dom/src/window/BrowserWindow.ts +3074 -0
  788. package/vendor/happy-dom/packages/happy-dom/src/window/CrossOriginBrowserWindow.ts +152 -0
  789. package/vendor/happy-dom/packages/happy-dom/src/window/DetachedWindowAPI.ts +133 -0
  790. package/vendor/happy-dom/packages/happy-dom/src/window/GlobalWindow.ts +90 -0
  791. package/vendor/happy-dom/packages/happy-dom/src/window/INodeJSGlobal.ts +76 -0
  792. package/vendor/happy-dom/packages/happy-dom/src/window/IOptionalTimerLoopsLimit.ts +4 -0
  793. package/vendor/happy-dom/packages/happy-dom/src/window/IScrollToOptions.ts +5 -0
  794. package/vendor/happy-dom/packages/happy-dom/src/window/ITimerLoopsLimit.ts +4 -0
  795. package/vendor/happy-dom/packages/happy-dom/src/window/VMGlobalPropertyScript.ts +59 -0
  796. package/vendor/happy-dom/packages/happy-dom/src/window/Window.ts +67 -0
  797. package/vendor/happy-dom/packages/happy-dom/src/window/WindowBrowserContext.ts +117 -0
  798. package/vendor/happy-dom/packages/happy-dom/src/window/WindowContextClassExtender.ts +288 -0
  799. package/vendor/happy-dom/packages/happy-dom/src/window/WindowPageOpenUtility.ts +200 -0
  800. package/vendor/happy-dom/packages/happy-dom/src/xml-http-request/XMLHttpRequest.ts +577 -0
  801. package/vendor/happy-dom/packages/happy-dom/src/xml-http-request/XMLHttpRequestEventTarget.ts +88 -0
  802. package/vendor/happy-dom/packages/happy-dom/src/xml-http-request/XMLHttpRequestReadyStateEnum.ts +9 -0
  803. package/vendor/happy-dom/packages/happy-dom/src/xml-http-request/XMLHttpRequestResponseDataParser.ts +70 -0
  804. package/vendor/happy-dom/packages/happy-dom/src/xml-http-request/XMLHttpRequestUpload.ts +6 -0
  805. package/vendor/happy-dom/packages/happy-dom/src/xml-http-request/XMLHttpResponseTypeEnum.ts +9 -0
  806. package/vendor/happy-dom/packages/happy-dom/src/xml-parser/XMLParser.ts +744 -0
  807. package/vendor/happy-dom/packages/happy-dom/src/xml-serializer/XMLSerializer.ts +280 -0
  808. package/vendor/happy-dom/turbo.json +52 -0
  809. package/vendor/ses/LICENSE +201 -0
  810. package/vendor/ses/LICENSE-aura +16 -0
  811. package/vendor/ses/LICENSE-caja +13 -0
  812. package/vendor/ses/LICENSE-corejs +19 -0
  813. package/vendor/ses/LICENSE-v8 +9 -0
  814. package/vendor/ses/README.md +968 -0
  815. package/vendor/ses/dist/ses.mjs +15219 -0
  816. package/vendor/ses/package.json +142 -0
  817. package/vendor/wasmpeg/LICENSE +501 -0
  818. package/vendor/wasmpeg/NOTICE +30 -0
  819. package/vendor/wasmpeg/VENDORING.md +35 -0
  820. package/vendor/wasmpeg/dist/cpu.js +2 -0
  821. package/vendor/wasmpeg/dist/cpu.wasm +0 -0
  822. package/vendor/wasmpeg/package.json +45 -0
  823. package/vendor/wasmpeg/source-v1.0.1.tar.gz +0 -0
  824. package/vendor/wasmpeg/src/js/exec.mjs +478 -0
  825. package/vendor/wasmpeg/src/js/ffmpeg.js +94 -0
  826. package/vendor/wasmpeg/src/js/formats.js +84 -0
  827. package/vendor/wasmpeg/src/js/gpu.js +480 -0
  828. package/vendor/wasmpeg/src/js/index.d.ts +154 -0
  829. package/vendor/wasmpeg/src/js/index.js +7 -0
  830. package/vendor/wasmpeg/src/js/wasmpeg.mjs +221 -0
@@ -0,0 +1,2236 @@
1
+ /**
2
+ * Box-tree layout: block formatting contexts with margin collapsing, inline
3
+ * formatting contexts with line boxes, atomic inlines, and flex layout
4
+ * (CSS Flexbox §9: flexible length resolution, wrapping, alignment; column
5
+ * containers currently stack items without main-axis flexing), and grid
6
+ * layout (CSS Grid 2 §8 placement and §12 track sizing, without named lines,
7
+ * areas, or column auto-flow). Relative, absolute and fixed positioning
8
+ * place boxes after flow layout; positioned boxes get their own paint layer.
9
+ *
10
+ * The block/inline structure follows concepts from Dropflow
11
+ * (chearon/dropflow@13552695d3446ac68f39952ea89dc69c4499dde2, MIT,
12
+ * src/layout-flow.ts): block containers hold either block-level boxes or one
13
+ * inline formatting context, anonymous block boxes wrap inline runs between
14
+ * blocks, and adjacent/parent-child margins collapse through margin struts.
15
+ * The code is a project-owned implementation over RenderNode input.
16
+ *
17
+ * Output stays flat for painting and hit testing: `boxes` in paint (pre-)order
18
+ * and `fragments` as positioned line boxes sorted by y.
19
+ */
20
+ const ZERO_BOX = Object.freeze([0, 0, 0, 0]);
21
+ const ZERO_STRUT = Object.freeze({ positive: 0, negative: 0 });
22
+ const DEFAULT_ASCENT = 0.93;
23
+ const DEFAULT_CONTENT_HEIGHT = 1.17;
24
+
25
+ const ROOT_LAYER = Object.freeze({ z: 0, order: 0, context: true, parent: null });
26
+
27
+ export function layoutText(tree, options = {}) {
28
+ const columns = positiveInteger(options.columns, 40);
29
+ const x = finiteNumber(options.x, 16);
30
+ const y = finiteNumber(options.y, 12);
31
+ const columnWidth = positiveNumber(options.columnWidth, 13);
32
+ const viewportWidth = positiveNumber(options.width, 0);
33
+ const measureText = typeof options.measureText === "function"
34
+ ? options.measureText
35
+ : (text) => Bun.stringWidth(text) * columnWidth;
36
+ const ctx = {
37
+ tree,
38
+ fragments: [],
39
+ boxes: [],
40
+ lineHeight: options.lineHeight == null ? null : positiveNumber(options.lineHeight, 31),
41
+ fallbackLineHeight: 31,
42
+ measure: cachedMeasure(measureText),
43
+ metrics: cachedMetrics(options.fontMetrics),
44
+ maxContent: new WeakMap(),
45
+ minContent: new WeakMap(),
46
+ // Paint layers: the root layer holds in-flow content; positioned boxes add
47
+ // more. A layer with an integer z-index is a stacking context; `parent` is
48
+ // the stacking context a layer is painted in (CSS 2 Appendix E).
49
+ layer: ROOT_LAYER,
50
+ stackingContext: ROOT_LAYER,
51
+ layerCount: 1,
52
+ initialContainingBlock: null,
53
+ };
54
+
55
+ containingBlocks = [];
56
+ let root;
57
+ try {
58
+ root = buildBox(tree.root, inheritedFlags(tree.root, { preserve: false, wrap: true }));
59
+ } finally {
60
+ containingBlocks = null;
61
+ }
62
+ const containingWidth = options.measureText || viewportWidth
63
+ ? Math.max(1, (viewportWidth || columns * columnWidth) - x * 2)
64
+ : columns * columnWidth;
65
+ ctx.initialContainingBlock = {
66
+ x: 0,
67
+ y: 0,
68
+ width: viewportWidth || containingWidth + x * 2,
69
+ height: positiveNumber(options.viewportHeight, 0),
70
+ };
71
+ // The root render node is <body>; the initial containing block (html)
72
+ // establishes the BFC, so body margins collapse with its children's.
73
+ const horizontal = resolveHorizontal(ctx, root, x, containingWidth, false);
74
+ const rootY = y + strutValue(topStrut(root));
75
+ const result = layoutBlock(ctx, root, horizontal.x, horizontal.width, rootY, collapsesThroughTop(root));
76
+ const height = rootY + result.height + strutValue(bottomStrut(root));
77
+
78
+ const fragments = ctx.fragments
79
+ .map((fragment, order) => ({ fragment, order }))
80
+ .sort((left, right) => left.fragment.y - right.fragment.y || left.order - right.order)
81
+ .map(({ fragment }, index) => Object.freeze({ id: `${tree.generation}:${index}`, ...fragment }));
82
+ const boxes = ctx.boxes.map((box) => Object.freeze(box));
83
+ return Object.freeze({
84
+ generation: tree.generation,
85
+ columns,
86
+ columnWidth,
87
+ width: Math.max(viewportWidth, x + Math.max(0, ...boxes.map((box) => box.x + box.width))),
88
+ height,
89
+ boxes: Object.freeze(boxes),
90
+ fragments: Object.freeze(fragments),
91
+ });
92
+ }
93
+
94
+ // ---------------------------------------------------------------------------
95
+ // Box tree construction
96
+
97
+ // Absolutely positioned boxes register with their containing block while the
98
+ // box tree is built. Building is synchronous and scoped to layoutText.
99
+ let containingBlocks = null;
100
+
101
+ // Text nodes carry their parent's style, so only element boxes can be positioned.
102
+ const UNPOSITIONABLE = new Set(["root", "text", "line-break"]);
103
+
104
+ function isPositioned(node) {
105
+ return !UNPOSITIONABLE.has(node.type) && ["relative", "absolute", "fixed", "sticky"].includes(node.style?.position);
106
+ }
107
+
108
+ function isOutOfFlow(node) {
109
+ return !UNPOSITIONABLE.has(node.type) && ["absolute", "fixed"].includes(node.style?.position);
110
+ }
111
+
112
+ /** Builds an absolutely positioned box and hands it to its containing block. */
113
+ function outOfFlowBox(node, flags) {
114
+ const holder = node.style.position === "fixed" ? containingBlocks[0] : containingBlocks.at(-1);
115
+ const box = buildBox(node, inheritedFlags(node, flags), true);
116
+ box.outOfFlow = true;
117
+ holder.absolutes.push(box);
118
+ return box;
119
+ }
120
+
121
+ function buildBox(node, flags, blockified = false) {
122
+ const style = node.style ?? null;
123
+ if (node.type === "image") {
124
+ return { kind: "block", node, style, replaced: true, bfc: true, children: [], absolutes: [] };
125
+ }
126
+ const flex = ["flex", "inline-flex"].includes(node.type)
127
+ ? style?.flexDirection === "column" ? "column" : "row"
128
+ : null;
129
+ const grid = ["grid", "inline-grid"].includes(node.type);
130
+ const table = ["table", "inline-table"].includes(node.type);
131
+ const box = {
132
+ kind: "block",
133
+ node,
134
+ style,
135
+ flex,
136
+ grid,
137
+ table: null,
138
+ bfc: blockified || flex !== null || grid || table || isAtomic(node),
139
+ // Atomic inlines are sized shrink-to-fit, so their main size is indefinite.
140
+ shrinkToFit: isAtomic(node),
141
+ children: [],
142
+ absolutes: [],
143
+ };
144
+ const containing = node.type === "root" || isPositioned(node);
145
+ if (containing) containingBlocks?.push(box);
146
+ try {
147
+ if (table) box.table = tableStructure(node, flags);
148
+ else box.children = flex || grid ? flexItems(node, flags) : blockChildren(node, flags);
149
+ } finally {
150
+ if (containing) containingBlocks?.pop();
151
+ }
152
+ return box;
153
+ }
154
+
155
+ function blockChildren(node, flags) {
156
+ const children = [];
157
+ const openInlines = [];
158
+ let items = [];
159
+ const flush = () => {
160
+ if (hasInlineContent(items)) children.push({ kind: "ifc", node, style: node.style ?? null, items });
161
+ items = [];
162
+ };
163
+
164
+ function walk(child, childFlags) {
165
+ if (isOutOfFlow(child)) {
166
+ const box = outOfFlowBox(child, childFlags);
167
+ // Between blocks the placeholder records the static position; inline
168
+ // placeholders fall back to the containing block's origin.
169
+ if (!openInlines.length && !hasInlineContent(items)) children.push({ kind: "placeholder", box });
170
+ } else if (child.type === "text") {
171
+ items.push(textItem(child, childFlags));
172
+ } else if (child.type === "line-break") {
173
+ items.push({ kind: "break", node: child });
174
+ } else if (isBlockLevel(child)) {
175
+ // A block inside an inline splits the inline around the block.
176
+ for (const open of [...openInlines].reverse()) items.push({ kind: "close", node: open });
177
+ flush();
178
+ children.push(buildBox(child, inheritedFlags(child, childFlags)));
179
+ for (const open of openInlines) items.push({ kind: "open", node: open, style: open.style ?? null });
180
+ } else if (child.type === "image") {
181
+ items.push({ kind: "image", node: child });
182
+ } else if (isAtomic(child)) {
183
+ items.push({ kind: "atomic", node: child, box: buildBox(child, inheritedFlags(child, childFlags)) });
184
+ } else {
185
+ items.push({ kind: "open", node: child, style: child.style ?? null });
186
+ openInlines.push(child);
187
+ const grandchildFlags = inheritedFlags(child, childFlags);
188
+ for (const grandchild of child.children) walk(grandchild, grandchildFlags);
189
+ openInlines.pop();
190
+ items.push({ kind: "close", node: child });
191
+ }
192
+ }
193
+
194
+ for (const child of node.children) walk(child, flags);
195
+ flush();
196
+ return children;
197
+ }
198
+
199
+ /**
200
+ * Flex and grid items: every in-flow child element is blockified; each
201
+ * contiguous run of non-white-space text becomes an anonymous item.
202
+ */
203
+ function flexItems(node, flags) {
204
+ const items = [];
205
+ let text = [];
206
+ const flush = () => {
207
+ if (text.length) {
208
+ items.push({
209
+ kind: "block",
210
+ node,
211
+ style: null,
212
+ anonymous: true,
213
+ bfc: true,
214
+ children: [{ kind: "ifc", node, style: node.style ?? null, items: text }],
215
+ });
216
+ }
217
+ text = [];
218
+ };
219
+ for (const child of node.children) {
220
+ if (child.type === "line-break") continue;
221
+ if (child.type === "text") {
222
+ if (child.text.trim()) text.push(textItem(child, flags));
223
+ continue;
224
+ }
225
+ if (isOutOfFlow(child)) {
226
+ outOfFlowBox(child, flags);
227
+ continue;
228
+ }
229
+ flush();
230
+ items.push(buildBox(child, inheritedFlags(child, flags), true));
231
+ }
232
+ flush();
233
+ return items;
234
+ }
235
+
236
+ function textItem(node, flags) {
237
+ return { kind: "text", node, style: node.style ?? null, text: node.text, preserve: flags.preserve, wrap: flags.wrap };
238
+ }
239
+
240
+ function inheritedFlags(node, flags) {
241
+ const whiteSpace = node.style?.whiteSpace;
242
+ if (whiteSpace) {
243
+ return { preserve: ["pre", "pre-wrap"].includes(whiteSpace), wrap: !["pre", "nowrap"].includes(whiteSpace) };
244
+ }
245
+ if (node.tagName === "PRE") return { preserve: true, wrap: false };
246
+ return flags;
247
+ }
248
+
249
+ // Table parts found outside a table are laid out as blocks.
250
+ const TABLE_PARTS = new Set([
251
+ "table-row-group", "table-header-group", "table-footer-group", "table-row", "table-cell", "table-caption",
252
+ "table-column", "table-column-group",
253
+ ]);
254
+
255
+ function isBlockLevel(node) {
256
+ return ["block", "flex", "grid", "table"].includes(node.type) || TABLE_PARTS.has(node.type)
257
+ || (node.type === "image" && node.style?.display === "block");
258
+ }
259
+
260
+ function isAtomic(node) {
261
+ return ["inline-block", "inline-flex", "inline-grid", "inline-table"].includes(node.type);
262
+ }
263
+
264
+ function hasInlineContent(items) {
265
+ return items.some((item) => item.kind === "text"
266
+ ? item.preserve ? item.text.length > 0 : /[^\t\n\f\r ]/.test(item.text)
267
+ : ["break", "image", "atomic"].includes(item.kind));
268
+ }
269
+
270
+ // ---------------------------------------------------------------------------
271
+ // Block layout
272
+
273
+ /**
274
+ * Lays out a block-level box, then its absolutely positioned descendants,
275
+ * then applies relative offsets and translations to everything it produced.
276
+ */
277
+ function layoutBlock(ctx, box, x, width, y, absorbTop = false, forcedHeight = null) {
278
+ const style = box.style;
279
+ const boxStart = ctx.boxes.length;
280
+ const fragmentStart = ctx.fragments.length;
281
+ const previousLayer = ctx.layer;
282
+ const previousContext = ctx.stackingContext;
283
+ // Anonymous boxes reuse their container's node but are never positioned themselves.
284
+ if (!box.anonymous && isPositioned(box.node)) {
285
+ const context = Number.isInteger(style.zIndex);
286
+ ctx.layer = Object.freeze({
287
+ z: context ? style.zIndex : 0,
288
+ order: ctx.layerCount++,
289
+ context,
290
+ parent: ctx.stackingContext,
291
+ });
292
+ // z-index: auto paints in the parent context and does not group its descendants.
293
+ if (context) ctx.stackingContext = ctx.layer;
294
+ }
295
+ const result = layoutBlockContent(ctx, box, x, width, y, absorbTop, forcedHeight);
296
+ const record = ctx.boxes[boxStart];
297
+ if (box.absolutes?.length) layoutAbsolutes(ctx, box, record);
298
+ let dx = 0;
299
+ let dy = 0;
300
+ if (style?.position === "relative") {
301
+ const [top, right, bottom, left] = style.inset.map((value) => numberOrNull(value));
302
+ dx = left ?? (right != null ? -right : 0);
303
+ dy = top ?? (bottom != null ? -bottom : 0);
304
+ }
305
+ if (style?.transform) {
306
+ dx += numberOrZero(resolveLength(style.transform.x, record.width));
307
+ dy += numberOrZero(resolveLength(style.transform.y, record.height));
308
+ }
309
+ for (let index = boxStart; index < ctx.boxes.length; index++) ctx.boxes[index].layer ??= ctx.layer;
310
+ for (let index = fragmentStart; index < ctx.fragments.length; index++) ctx.fragments[index].layer ??= ctx.layer;
311
+ if (dx || dy) shiftOutput(ctx, boxStart, fragmentStart, dx, dy);
312
+ ctx.layer = previousLayer;
313
+ ctx.stackingContext = previousContext;
314
+ return result;
315
+ }
316
+
317
+ /** CSS 2 §10.3.7/§10.6.4 absolute placement against the padding box. */
318
+ function layoutAbsolutes(ctx, box, record) {
319
+ const border = borderWidths(box.style);
320
+ const icb = ctx.initialContainingBlock;
321
+ const block = box.node.type === "root"
322
+ ? { ...icb, height: icb.height || record.y + record.height }
323
+ : {
324
+ x: record.x + border[3],
325
+ y: record.y + border[0],
326
+ width: record.width - border[1] - border[3],
327
+ height: record.height - border[0] - border[2],
328
+ };
329
+ for (const absolute of box.absolutes) {
330
+ const style = absolute.style;
331
+ const containing = style?.position === "fixed" ? { ...icb, height: icb.height || block.height } : block;
332
+ const [top, right, bottom, left] = (style?.inset ?? ["auto", "auto", "auto", "auto"])
333
+ .map((value, index) => value === "auto" ? null : resolveLength(value, index % 2 ? containing.width : containing.height));
334
+ const margin = style?.margin ?? ZERO_BOX;
335
+ const [marginTop, marginRight, marginBottom, marginLeft] = margin.map(numberOrZero);
336
+ const specifiedWidth = numberOrNull(resolveLength(style?.width, containing.width));
337
+ let width;
338
+ if (specifiedWidth == null && left != null && right != null) {
339
+ width = Math.max(0, containing.width - left - right - marginLeft - marginRight);
340
+ } else {
341
+ width = resolveHorizontal(ctx, absolute, 0, containing.width - (left ?? 0) - (right ?? 0), true).width;
342
+ }
343
+ const staticPosition = absolute.staticPosition ?? containing;
344
+ const x = left != null ? containing.x + left + marginLeft
345
+ : right != null ? containing.x + containing.width - right - marginRight - width
346
+ : staticPosition.x + marginLeft;
347
+ const specifiedHeight = numberOrNull(resolveLength(style?.height, containing.height));
348
+ const forcedHeight = specifiedHeight == null && top != null && bottom != null
349
+ ? Math.max(0, containing.height - top - bottom - marginTop - marginBottom)
350
+ : null;
351
+ let height = forcedHeight;
352
+ if (height == null && top == null && bottom != null) height = dryLayout(ctx, absolute, width).height;
353
+ const y = top != null ? containing.y + top + marginTop
354
+ : bottom != null ? containing.y + containing.height - bottom - marginBottom - height
355
+ : staticPosition.y + marginTop;
356
+ layoutBlock(ctx, absolute, x, width, y, false, forcedHeight);
357
+ }
358
+ }
359
+
360
+ function shiftOutput(ctx, boxStart, fragmentStart, dx, dy) {
361
+ for (let index = boxStart; index < ctx.boxes.length; index++) {
362
+ ctx.boxes[index].x += dx;
363
+ ctx.boxes[index].y += dy;
364
+ }
365
+ for (let index = fragmentStart; index < ctx.fragments.length; index++) {
366
+ const fragment = ctx.fragments[index];
367
+ ctx.fragments[index] = {
368
+ ...fragment,
369
+ x: fragment.x + dx,
370
+ y: fragment.y + dy,
371
+ baseline: fragment.baseline == null ? null : fragment.baseline + dy,
372
+ runs: Object.freeze(fragment.runs.map((run) => Object.freeze({
373
+ ...run,
374
+ x: run.x + dx,
375
+ y: run.y == null ? run.y : run.y + dy,
376
+ }))),
377
+ };
378
+ }
379
+ }
380
+
381
+ function layoutBlockContent(ctx, box, x, width, y, absorbTop = false, forcedHeight = null) {
382
+ const style = box.style;
383
+ const border = borderWidths(style);
384
+ const padding = style?.padding ?? ZERO_BOX;
385
+ const record = { nodeId: box.node.id, x, y, width, height: 0, style };
386
+ ctx.boxes.push(record);
387
+ if (box.replaced) {
388
+ const dimensions = imageDimensions(box.node, width);
389
+ const imageX = x + border[3] + padding[3];
390
+ const imageY = y + border[0] + padding[0];
391
+ ctx.fragments.push(lineFragment(box.style, "", [box.node.id], [{
392
+ nodeId: box.node.id,
393
+ type: "image",
394
+ text: "",
395
+ start: 0,
396
+ end: 1,
397
+ style,
398
+ x: imageX,
399
+ y: imageY,
400
+ width: dimensions.width,
401
+ height: dimensions.height,
402
+ resource: box.node.resource,
403
+ video: box.node.tagName === "VIDEO",
404
+ svg: box.node.svg ?? null,
405
+ }], imageX, imageY, dimensions.width, dimensions.height));
406
+ record.height = dimensions.height + padding[0] + padding[2] + border[0] + border[2];
407
+ return { height: record.height, baseline: null };
408
+ }
409
+
410
+ const contentX = x + border[3] + padding[3];
411
+ const contentWidth = Math.max(1, width - border[1] - border[3] - padding[1] - padding[3]);
412
+ const contentTop = y + border[0] + padding[0];
413
+ const firstFragment = ctx.fragments.length;
414
+ let contentBottom = contentTop;
415
+ let baseline = null;
416
+
417
+ if (box.table) {
418
+ const result = layoutTable(ctx, box, contentX, contentWidth, contentTop);
419
+ contentBottom = result.bottom;
420
+ baseline = result.baseline;
421
+ } else if (box.grid) {
422
+ const result = layoutGrid(ctx, box, contentX, contentWidth, contentTop);
423
+ contentBottom = result.bottom;
424
+ baseline = result.baseline;
425
+ } else if (box.flex === "row") {
426
+ const result = layoutFlexRow(ctx, box, contentX, contentWidth, contentTop);
427
+ contentBottom = result.bottom;
428
+ baseline = result.baseline;
429
+ } else if (box.flex === "column") {
430
+ const gap = style?.rowGap ?? style?.gap ?? 0;
431
+ let cursor = contentTop;
432
+ box.children.forEach((child, index) => {
433
+ if (index > 0) cursor += gap;
434
+ if (child.kind === "ifc") {
435
+ const result = layoutInline(ctx, child, contentX, contentWidth, cursor);
436
+ cursor = result.bottom;
437
+ baseline = result.baseline ?? baseline;
438
+ return;
439
+ }
440
+ const alignment = ["auto", "normal", undefined].includes(child.style?.alignSelf)
441
+ ? style?.alignItems ?? "normal"
442
+ : child.style.alignSelf;
443
+ const shrink = !["normal", "stretch"].includes(alignment);
444
+ const placed = resolveHorizontal(ctx, child, contentX, contentWidth, shrink);
445
+ const autoMargins = (child.style?.margin ?? ZERO_BOX).some((value) => value === "auto");
446
+ let childX = placed.x;
447
+ if (shrink && !autoMargins) {
448
+ const free = contentWidth - placed.width - placed.marginLeft - placed.marginRight;
449
+ if (alignment === "center") childX = contentX + placed.marginLeft + free / 2;
450
+ else if (alignment === "end") childX = contentX + placed.marginLeft + free;
451
+ }
452
+ const margin = verticalMargins(child.style);
453
+ const result = layoutBlock(ctx, child, childX, placed.width, cursor + margin.top);
454
+ cursor += margin.top + result.height + margin.bottom;
455
+ baseline = result.baseline ?? baseline;
456
+ });
457
+ contentBottom = cursor;
458
+ } else {
459
+ let cursor = contentTop;
460
+ let pending = null;
461
+ let firstInFlow = true;
462
+ box.children.forEach((child) => {
463
+ if (child.kind === "placeholder") {
464
+ child.box.staticPosition = { x: contentX, y: cursor + strutValue(pending ?? ZERO_STRUT) };
465
+ return;
466
+ }
467
+ const first = firstInFlow;
468
+ firstInFlow = false;
469
+ if (child.kind === "ifc") {
470
+ cursor += strutValue(pending ?? ZERO_STRUT);
471
+ pending = ZERO_STRUT;
472
+ const result = layoutInline(ctx, child, contentX, contentWidth, cursor);
473
+ cursor = result.bottom;
474
+ baseline = result.baseline ?? baseline;
475
+ return;
476
+ }
477
+ const combined = first && absorbTop
478
+ ? ZERO_STRUT
479
+ : combineStruts(pending ?? ZERO_STRUT, topStrut(child));
480
+ const childY = cursor + strutValue(combined);
481
+ // Tables with width: auto are sized to their contents (CSS 2 §17.5.2).
482
+ const placed = resolveHorizontal(ctx, child, contentX, contentWidth, Boolean(child.table));
483
+ const result = layoutBlock(ctx, child, placed.x, placed.width, childY, collapsesThroughTop(child));
484
+ cursor = childY + result.height;
485
+ pending = bottomStrut(child);
486
+ baseline = result.baseline ?? baseline;
487
+ });
488
+ contentBottom = collapsesThroughBottom(box) ? cursor : cursor + strutValue(pending ?? ZERO_STRUT);
489
+ }
490
+
491
+ let contentHeight = Math.max(0, contentBottom - contentTop);
492
+ const toContentHeight = (value) => style.boxSizing === "border-box"
493
+ ? Math.max(0, value - border[0] - border[2] - padding[0] - padding[2])
494
+ : value;
495
+ const specifiedHeight = numberOrNull(style?.height);
496
+ if (specifiedHeight != null) contentHeight = toContentHeight(specifiedHeight);
497
+ // min-height and max-height (percentages need a definite containing height; not modelled).
498
+ const maxHeight = numberOrNull(style?.maxHeight);
499
+ if (maxHeight != null) contentHeight = Math.min(contentHeight, toContentHeight(maxHeight));
500
+ const minHeight = numberOrNull(style?.minHeight);
501
+ if (minHeight != null) contentHeight = Math.max(contentHeight, toContentHeight(minHeight));
502
+ record.height = forcedHeight ?? contentHeight + padding[0] + padding[2] + border[0] + border[2];
503
+ if (style?.display === "list-item") placeListMarker(ctx, box, contentX, contentTop, firstFragment);
504
+ return { height: record.height, baseline };
505
+ }
506
+
507
+ /**
508
+ * Outside list markers (CSS Lists 3): the marker's inline end touches the
509
+ * principal box's content edge, on the baseline of the item's first line.
510
+ */
511
+ function placeListMarker(ctx, box, contentX, contentTop, firstFragment) {
512
+ const style = box.style;
513
+ const text = markerText(style.listStyleType, listOrdinal(box.node));
514
+ if (!text) return;
515
+ const width = ctx.measure(text, style);
516
+ const metrics = textMetrics(ctx, style);
517
+ const firstLine = ctx.fragments.slice(firstFragment).find((fragment) => fragment.baseline != null);
518
+ const baseline = firstLine?.baseline ?? contentTop + metrics.ascent;
519
+ const x = contentX - width;
520
+ ctx.fragments.push(lineFragment(style, text, [box.node.id], [{
521
+ nodeId: box.node.id,
522
+ type: "marker",
523
+ text,
524
+ start: 0,
525
+ end: text.length,
526
+ style,
527
+ x,
528
+ y: baseline - metrics.contentAscent,
529
+ width,
530
+ height: null,
531
+ }], x, baseline - metrics.ascent, width, metrics.ascent + metrics.descent, baseline));
532
+ }
533
+
534
+ function listOrdinal(node) {
535
+ const element = node.domNode;
536
+ const list = element?.parentElement;
537
+ let ordinal = list?.tagName === "OL" && Number.isInteger(Number(list.getAttribute("start")))
538
+ && list.hasAttribute("start") ? Number(list.getAttribute("start")) : 1;
539
+ for (let sibling = element?.previousElementSibling; sibling; sibling = sibling.previousElementSibling) {
540
+ if (sibling.tagName === "LI") ordinal++;
541
+ }
542
+ const value = Number(element?.getAttribute?.("value"));
543
+ return element?.hasAttribute?.("value") && Number.isInteger(value) ? value : ordinal;
544
+ }
545
+
546
+ function markerText(type, ordinal) {
547
+ switch (type) {
548
+ case "disc": return "\u2022 ";
549
+ case "circle": return "\u25E6 ";
550
+ case "square": return "\u25AA ";
551
+ case "decimal": return `${ordinal}. `;
552
+ case "decimal-leading-zero": return `${String(ordinal).padStart(2, "0")}. `;
553
+ case "lower-alpha":
554
+ case "lower-latin": return `${alphabetic(ordinal)}. `;
555
+ case "upper-alpha":
556
+ case "upper-latin": return `${alphabetic(ordinal).toUpperCase()}. `;
557
+ case "lower-roman": return `${roman(ordinal)}. `;
558
+ case "upper-roman": return `${roman(ordinal).toUpperCase()}. `;
559
+ default: return "";
560
+ }
561
+ }
562
+
563
+ function alphabetic(value) {
564
+ let text = "";
565
+ for (let rest = value; rest > 0; rest = Math.floor((rest - 1) / 26)) {
566
+ text = String.fromCharCode(97 + (rest - 1) % 26) + text;
567
+ }
568
+ return text || String(value);
569
+ }
570
+
571
+ function roman(value) {
572
+ if (value <= 0 || value >= 4000) return String(value);
573
+ const numerals = [[1000, "m"], [900, "cm"], [500, "d"], [400, "cd"], [100, "c"], [90, "xc"],
574
+ [50, "l"], [40, "xl"], [10, "x"], [9, "ix"], [5, "v"], [4, "iv"], [1, "i"]];
575
+ let text = "";
576
+ for (const [amount, numeral] of numerals) {
577
+ while (value >= amount) {
578
+ text += numeral;
579
+ value -= amount;
580
+ }
581
+ }
582
+ return text;
583
+ }
584
+
585
+ // ---------------------------------------------------------------------------
586
+ // Flex row layout (CSS Flexbox §9)
587
+
588
+ function layoutFlexRow(ctx, box, x, width, y) {
589
+ const style = box.style;
590
+ const columnGap = style?.columnGap ?? style?.gap ?? 0;
591
+ const rowGap = style?.rowGap ?? style?.gap ?? 0;
592
+ const items = box.children.map((child) => flexItem(ctx, child, width));
593
+
594
+ const lines = [];
595
+ let line = [];
596
+ let used = 0;
597
+ for (const item of items) {
598
+ const outer = item.hypothetical + item.extra + item.marginLeft + item.marginRight;
599
+ if (style?.flexWrap === "wrap" && line.length && used + columnGap + outer > width + 0.01) {
600
+ lines.push(line);
601
+ line = [];
602
+ used = 0;
603
+ }
604
+ used += (line.length ? columnGap : 0) + outer;
605
+ line.push(item);
606
+ }
607
+ if (line.length) lines.push(line);
608
+
609
+ let cursor = y;
610
+ let baseline = null;
611
+ lines.forEach((lineItems, lineIndex) => {
612
+ if (lineIndex > 0) cursor += rowGap;
613
+ const gaps = columnGap * (lineItems.length - 1);
614
+ resolveFlexibleLengths(lineItems, width - gaps, !box.shrinkToFit);
615
+ for (const item of lineItems) {
616
+ item.target += item.extra;
617
+ Object.assign(item, dryLayout(ctx, item.box, item.target));
618
+ }
619
+ let crossSize = Math.max(0, ...lineItems.map((item) => item.height + item.marginTop + item.marginBottom));
620
+ // A single-line container with a definite height gives its line that cross size (§9.4.15).
621
+ const definiteHeight = numberOrNull(style?.height);
622
+ if (lines.length === 1 && definiteHeight != null) {
623
+ const padding = style.padding ?? ZERO_BOX;
624
+ crossSize = style.boxSizing === "border-box"
625
+ ? Math.max(0, definiteHeight - padding[0] - padding[2] - borderWidths(style)[0] - borderWidths(style)[2])
626
+ : definiteHeight;
627
+ }
628
+
629
+ // Main axis: auto margins absorb free space first, then justify-content.
630
+ let free = width - gaps - lineItems.reduce((sum, item) => sum + item.target + item.marginLeft + item.marginRight, 0);
631
+ const autoMargins = lineItems.reduce((sum, item) => sum + Number(item.autoLeft) + Number(item.autoRight), 0);
632
+ const autoShare = autoMargins && free > 0 ? free / autoMargins : 0;
633
+ if (autoMargins && free > 0) free = 0;
634
+ const justify = style?.justifyContent ?? "normal";
635
+ const count = lineItems.length;
636
+ let offset = 0;
637
+ let between = 0;
638
+ if (justify === "end") offset = free;
639
+ else if (justify === "center") offset = free / 2;
640
+ else if (free > 0 && justify === "space-between" && count > 1) between = free / (count - 1);
641
+ else if (free > 0 && justify === "space-around") {
642
+ between = free / count;
643
+ offset = between / 2;
644
+ } else if (free > 0 && justify === "space-evenly") {
645
+ between = free / (count + 1);
646
+ offset = between;
647
+ }
648
+
649
+ let mainX = x + offset;
650
+ for (const item of lineItems) {
651
+ mainX += item.marginLeft + (item.autoLeft ? autoShare : 0);
652
+ const alignment = ["auto", "normal", undefined].includes(item.box.style?.alignSelf)
653
+ ? style?.alignItems ?? "normal"
654
+ : item.box.style.alignSelf;
655
+ const outerHeight = item.height + item.marginTop + item.marginBottom;
656
+ let itemY = cursor + item.marginTop;
657
+ let forcedHeight = null;
658
+ if (item.autoCross) {
659
+ // Auto cross margins absorb the free cross space (§8.1).
660
+ const margin = item.box.style.margin;
661
+ const free = Math.max(0, crossSize - outerHeight);
662
+ const autos = Number(margin[0] === "auto") + Number(margin[2] === "auto");
663
+ if (margin[0] === "auto") itemY += free / autos;
664
+ } else if (["normal", "stretch"].includes(alignment) && numberOrNull(item.box.style?.height) == null) {
665
+ forcedHeight = Math.max(item.height, crossSize - item.marginTop - item.marginBottom);
666
+ } else if (alignment === "center") {
667
+ itemY += (crossSize - outerHeight) / 2;
668
+ } else if (alignment === "end") {
669
+ itemY += crossSize - outerHeight;
670
+ }
671
+ const result = layoutBlock(ctx, item.box, mainX, item.target, itemY, false, forcedHeight);
672
+ baseline ??= result.baseline;
673
+ mainX += item.target + item.marginRight + (item.autoRight ? autoShare : 0) + columnGap + between;
674
+ }
675
+ cursor += crossSize;
676
+ });
677
+ return { bottom: cursor, baseline };
678
+ }
679
+
680
+ function flexItem(ctx, box, containerWidth) {
681
+ // Sizes below are content-box sizes, as in Blink's FlexItem
682
+ // (base_content_size, hypothetical_content_size); `extra` is padding+border.
683
+ const style = box.style;
684
+ const padding = style?.padding ?? ZERO_BOX;
685
+ const extra = padding[1] + padding[3] + borderWidths(style)[1] + borderWidths(style)[3];
686
+ const contentBox = (value) => Math.max(0, style?.boxSizing === "border-box" ? value - extra : value);
687
+ const margin = style?.margin ?? ZERO_BOX;
688
+ const specifiedWidth = numberOrNull(resolveLength(style?.width, containerWidth));
689
+ const basis = style?.flexBasis ?? "auto";
690
+ const definiteBasis = numberOrNull(resolveLength(basis, containerWidth));
691
+ let base;
692
+ if (definiteBasis != null) base = contentBox(definiteBasis);
693
+ else if (basis === "auto" && specifiedWidth != null && !box.replaced) base = contentBox(specifiedWidth);
694
+ else base = Math.max(0, maxContentWidth(ctx, box) - extra);
695
+
696
+ const minWidth = numberOrNull(resolveLength(style?.minWidth, containerWidth));
697
+ // Automatic minimum size (§4.5): the content size suggestion, capped by the
698
+ // specified size suggestion. It floors every clamp, not only the hypothetical size.
699
+ let min = minWidth != null
700
+ ? contentBox(minWidth)
701
+ : Math.min(Math.max(0, minContentWidth(ctx, box) - extra),
702
+ specifiedWidth != null ? contentBox(specifiedWidth) : Infinity);
703
+ const maxWidth = numberOrNull(resolveLength(style?.maxWidth, containerWidth));
704
+ const max = maxWidth != null ? contentBox(maxWidth) : Infinity;
705
+ min = Math.min(min, max);
706
+ return {
707
+ box,
708
+ extra,
709
+ grow: style?.flexGrow ?? 0,
710
+ shrink: style?.flexShrink ?? 1,
711
+ base,
712
+ min,
713
+ max,
714
+ hypothetical: Math.min(max, Math.max(min, base)),
715
+ marginLeft: numberOrZero(margin[3]),
716
+ marginRight: numberOrZero(margin[1]),
717
+ marginTop: numberOrZero(margin[0]),
718
+ marginBottom: numberOrZero(margin[2]),
719
+ autoLeft: margin[3] === "auto",
720
+ autoRight: margin[1] === "auto",
721
+ autoCross: margin[0] === "auto" || margin[2] === "auto",
722
+ };
723
+ }
724
+
725
+ /**
726
+ * CSS Flexbox §9.7, following Blink's LineFlexer (line_flexer.cc): decide grow
727
+ * vs. shrink once, freeze inflexible items, then repeatedly distribute free
728
+ * space and freeze min/max violators. `available` excludes gaps; sizes are
729
+ * content-box. Growing requires a definite main size (TermDOM layoutsolver).
730
+ */
731
+ function resolveFlexibleLengths(items, available, definite = true) {
732
+ const outer = (item, size) => size + item.extra + item.marginLeft + item.marginRight;
733
+ const growing = items.reduce((sum, item) => sum + outer(item, item.hypothetical), 0) < available;
734
+ for (const item of items) {
735
+ item.target = item.hypothetical;
736
+ const factor = growing ? item.grow : item.shrink;
737
+ item.frozen = factor === 0 || (growing && !definite)
738
+ || (growing ? item.base > item.hypothetical : item.base < item.hypothetical);
739
+ }
740
+ const freeSpace = () => available
741
+ - items.reduce((sum, item) => sum + outer(item, item.frozen ? item.target : item.base), 0);
742
+ const initialFree = freeSpace();
743
+
744
+ for (let iteration = 0; iteration <= items.length; iteration++) {
745
+ const unfrozen = items.filter((item) => !item.frozen);
746
+ if (!unfrozen.length) break;
747
+ for (const item of unfrozen) item.target = item.hypothetical;
748
+ let free = freeSpace();
749
+ const factors = unfrozen.reduce((sum, item) => sum + (growing ? item.grow : item.shrink), 0);
750
+ if (factors > 0 && factors < 1 && Math.abs(initialFree * factors) < Math.abs(free)) free = initialFree * factors;
751
+ // No free space in the flexing direction: items keep their hypothetical sizes.
752
+ if (growing ? free <= 0 : free >= 0) break;
753
+ const scaledShrink = unfrozen.reduce((sum, item) => sum + item.shrink * item.base, 0);
754
+ let violation = 0;
755
+ for (const item of unfrozen) {
756
+ const size = growing
757
+ ? item.base + free * item.grow / factors
758
+ : item.base + (scaledShrink > 0 ? free * item.shrink * item.base / scaledShrink : 0);
759
+ const clamped = Math.max(0, Math.min(item.max, Math.max(item.min, size)));
760
+ item.violation = clamped - size;
761
+ item.target = clamped;
762
+ violation += item.violation;
763
+ }
764
+ if (Math.abs(violation) < 1e-9) break;
765
+ for (const item of unfrozen) {
766
+ if (violation > 0 ? item.violation > 0 : item.violation < 0) item.frozen = true;
767
+ }
768
+ }
769
+ }
770
+
771
+ // ---------------------------------------------------------------------------
772
+ // Grid layout (CSS Grid 2). Structure follows the spec's algorithm steps;
773
+ // behaviour is checked against TermDOM's hand-derived grid tests.
774
+
775
+ function layoutGrid(ctx, box, x, width, y) {
776
+ const style = box.style;
777
+ const columnGap = style?.columnGap ?? 0;
778
+ const rowGap = style?.rowGap ?? 0;
779
+ const grid = gridStructure(ctx, box, width, columnGap, true);
780
+ const columns = sizeGridColumns(ctx, box, grid, width, columnGap, true);
781
+ // justify-content distributes space left over after track sizing (css-align-3 §5.3).
782
+ const visibleColumns = columns.filter((_, index) => !grid.columnCollapsed[index]).length;
783
+ const used = columns.reduce((sum, size) => sum + size, 0) + columnGap * Math.max(0, visibleColumns - 1);
784
+ const free = Math.max(0, width - used);
785
+ const justify = style?.justifyContent ?? "normal";
786
+ let offset = 0;
787
+ let between = 0;
788
+ if (justify === "center") offset = free / 2;
789
+ else if (justify === "end") offset = free;
790
+ else if (justify === "space-between" && visibleColumns > 1) between = free / (visibleColumns - 1);
791
+ else if (justify === "space-around") {
792
+ between = free / visibleColumns;
793
+ offset = between / 2;
794
+ } else if (justify === "space-evenly") {
795
+ between = free / (visibleColumns + 1);
796
+ offset = between;
797
+ }
798
+ const effectiveGap = columnGap + between;
799
+ const columnStarts = trackStarts(columns, grid.columnCollapsed, effectiveGap, x + offset);
800
+
801
+ // Row sizing: item heights at their column-area widths (§12.5 simplified).
802
+ const areaWidth = (item) => spanSize(columns, grid.columnCollapsed, effectiveGap, item.column, item.columnSpan);
803
+ for (const item of grid.items) {
804
+ item.width = areaWidth(item);
805
+ const margin = item.box.style?.margin ?? ZERO_BOX;
806
+ const horizontal = gridHorizontal(ctx, style, item, columnStarts[item.column], item.width);
807
+ item.horizontal = horizontal;
808
+ const measured = dryLayout(ctx, item.box, horizontal.width);
809
+ item.height = measured.height + numberOrZero(margin[0]) + numberOrZero(margin[2]);
810
+ }
811
+ const rows = sizeGridRows(grid, rowGap);
812
+ const rowStarts = trackStarts(rows, [], rowGap, y);
813
+
814
+ let baseline = null;
815
+ for (const item of grid.items) {
816
+ const areaY = rowStarts[item.row];
817
+ const areaHeight = spanSize(rows, [], rowGap, item.row, item.rowSpan);
818
+ const itemStyle = item.box.style;
819
+ const margin = verticalMargins(itemStyle);
820
+ const alignment = ["auto", "normal", undefined].includes(itemStyle?.alignSelf)
821
+ ? style?.alignItems ?? "normal"
822
+ : itemStyle.alignSelf;
823
+ const contentHeight = item.height - margin.top - margin.bottom;
824
+ let itemY = areaY + margin.top;
825
+ let forcedHeight = null;
826
+ if (["normal", "stretch"].includes(alignment) && numberOrNull(itemStyle?.height) == null) {
827
+ forcedHeight = Math.max(contentHeight, areaHeight - margin.top - margin.bottom);
828
+ } else if (alignment === "center") {
829
+ itemY += (areaHeight - item.height) / 2;
830
+ } else if (alignment === "end") {
831
+ itemY += areaHeight - item.height;
832
+ }
833
+ const result = layoutBlock(ctx, item.box, item.horizontal.x, item.horizontal.width, itemY, false, forcedHeight);
834
+ baseline ??= result.baseline;
835
+ }
836
+ const height = rows.reduce((sum, size) => sum + size, 0) + rowGap * Math.max(0, rows.length - 1);
837
+ return { bottom: y + height, baseline };
838
+ }
839
+
840
+ // ---------------------------------------------------------------------------
841
+ // Tables (CSS 2 §17; column widths as in the HTML/CSS automatic table layout)
842
+
843
+ /**
844
+ * Rows in display order (header groups, body rows, footer groups) with their
845
+ * cells, plus captions. Cells directly in a table or group get an anonymous
846
+ * row; other stray content is not rendered.
847
+ */
848
+ function tableStructure(node, flags) {
849
+ const header = [];
850
+ const body = [];
851
+ const footer = [];
852
+ const captions = [];
853
+ const addRows = (target, children, childFlags) => {
854
+ let anonymous = null;
855
+ for (const child of children) {
856
+ if (child.type === "table-row") {
857
+ anonymous = null;
858
+ const rowFlags = inheritedFlags(child, childFlags);
859
+ target.push({
860
+ node: child,
861
+ style: child.style ?? null,
862
+ cells: child.children.filter((cell) => cell.type === "table-cell").map((cell) => tableCell(cell, rowFlags)),
863
+ });
864
+ } else if (child.type === "table-cell") {
865
+ if (!anonymous) target.push(anonymous = { node: null, style: null, cells: [] });
866
+ anonymous.cells.push(tableCell(child, childFlags));
867
+ }
868
+ }
869
+ };
870
+ let loose = [];
871
+ const flushLoose = () => {
872
+ addRows(body, loose, flags);
873
+ loose = [];
874
+ };
875
+ for (const child of node.children) {
876
+ if (child.type === "table-row" || child.type === "table-cell") {
877
+ loose.push(child);
878
+ continue;
879
+ }
880
+ flushLoose();
881
+ if (child.type === "table-caption") captions.push(buildBox(child, inheritedFlags(child, flags), true));
882
+ else if (child.type === "table-header-group") addRows(header, child.children, inheritedFlags(child, flags));
883
+ else if (child.type === "table-footer-group") addRows(footer, child.children, inheritedFlags(child, flags));
884
+ else if (child.type === "table-row-group") addRows(body, child.children, inheritedFlags(child, flags));
885
+ }
886
+ flushLoose();
887
+ return { rows: [...header, ...body, ...footer], captions, grid: null };
888
+ }
889
+
890
+ function tableCell(node, flags) {
891
+ const span = (name) => Math.max(1, Math.min(1000, Number.parseInt(node.domNode?.getAttribute?.(name) ?? "1", 10) || 1));
892
+ return { box: buildBox(node, inheritedFlags(node, flags), true), colspan: span("colspan"), rowspan: span("rowspan") };
893
+ }
894
+
895
+ /** Places cells on the row/column grid, skipping slots taken by earlier rowspans. */
896
+ function tableGrid(table) {
897
+ if (table.grid) return table.grid;
898
+ const occupied = [];
899
+ const cells = [];
900
+ let columns = 0;
901
+ table.rows.forEach((row, rowIndex) => {
902
+ let column = 0;
903
+ for (const cell of row.cells) {
904
+ while (occupied[rowIndex]?.has(column)) column++;
905
+ const rowspan = Math.min(cell.rowspan, table.rows.length - rowIndex);
906
+ for (let dr = 0; dr < rowspan; dr++) {
907
+ for (let dc = 0; dc < cell.colspan; dc++) (occupied[rowIndex + dr] ??= new Set()).add(column + dc);
908
+ }
909
+ cells.push({ ...cell, row: rowIndex, column, rowspan });
910
+ column += cell.colspan;
911
+ columns = Math.max(columns, column);
912
+ }
913
+ });
914
+ table.grid = { cells, columns, rows: table.rows.length };
915
+ return table.grid;
916
+ }
917
+
918
+ function tableSpacing(style) {
919
+ return style?.borderCollapse === "collapse" ? [0, 0] : style?.borderSpacing ?? [0, 0];
920
+ }
921
+
922
+ /** Minimum and maximum widths of every column; spanning cells spread their excess evenly. */
923
+ function tableColumnSizes(ctx, grid, spacingX) {
924
+ const mins = new Array(grid.columns).fill(0);
925
+ const maxes = new Array(grid.columns).fill(0);
926
+ const bySpan = [...grid.cells].sort((left, right) => left.colspan - right.colspan);
927
+ for (const cell of bySpan) {
928
+ const min = minContentWidth(ctx, cell.box);
929
+ const max = Math.max(min, maxContentWidth(ctx, cell.box));
930
+ const span = [...Array(cell.colspan).keys()].map((offset) => cell.column + offset);
931
+ const spread = (sizes, need) => {
932
+ const have = span.reduce((sum, column) => sum + sizes[column], 0) + spacingX * (cell.colspan - 1);
933
+ if (need > have) for (const column of span) sizes[column] += (need - have) / cell.colspan;
934
+ };
935
+ spread(mins, min);
936
+ spread(maxes, max);
937
+ }
938
+ for (let column = 0; column < grid.columns; column++) maxes[column] = Math.max(maxes[column], mins[column]);
939
+ return { mins, maxes };
940
+ }
941
+
942
+ /**
943
+ * table-layout: fixed (CSS 2 §17.5.2.1): widths come from the first row's
944
+ * specified cell widths; the other columns share the rest equally. Cell
945
+ * contents do not affect them.
946
+ */
947
+ function fixedColumnSizes(grid, table, available) {
948
+ const widths = new Array(grid.columns).fill(null);
949
+ for (const cell of grid.cells) {
950
+ if (cell.row !== 0) continue;
951
+ const specified = numberOrNull(resolveLength(cell.box.style?.width, available));
952
+ if (specified == null) continue;
953
+ for (let offset = 0; offset < cell.colspan; offset++) widths[cell.column + offset] = specified / cell.colspan;
954
+ }
955
+ const assigned = widths.reduce((sum, size) => sum + (size ?? 0), 0);
956
+ const open = widths.filter((size) => size == null).length;
957
+ const share = open ? Math.max(0, available - assigned) / open : 0;
958
+ const sizes = widths.map((size) => size ?? share);
959
+ return { mins: sizes, maxes: sizes };
960
+ }
961
+
962
+ function tableIntrinsicWidth(ctx, box, kind) {
963
+ const grid = tableGrid(box.table);
964
+ const [spacingX] = tableSpacing(box.style);
965
+ const { mins, maxes } = tableColumnSizes(ctx, grid, spacingX);
966
+ const columns = (kind === "min" ? mins : maxes).reduce((sum, size) => sum + size, 0);
967
+ const captions = Math.max(0, ...box.table.captions.map((caption) =>
968
+ kind === "min" ? minContentWidth(ctx, caption) : maxContentWidth(ctx, caption)));
969
+ return Math.max(captions, grid.columns ? columns + spacingX * (grid.columns + 1) : 0);
970
+ }
971
+
972
+ function layoutTable(ctx, box, x, width, y) {
973
+ const table = box.table;
974
+ const [spacingX, spacingY] = tableSpacing(box.style);
975
+ let cursor = y;
976
+ for (const caption of table.captions) {
977
+ const placed = resolveHorizontal(ctx, caption, x, width, false);
978
+ const margin = verticalMargins(caption.style);
979
+ cursor += margin.top + layoutBlock(ctx, caption, placed.x, placed.width, cursor + margin.top).height + margin.bottom;
980
+ }
981
+ const grid = tableGrid(table);
982
+ if (!grid.columns) return { bottom: cursor, baseline: null };
983
+
984
+ // Column widths: maximum widths when they fit, else interpolate from the
985
+ // minimums; any remaining space is shared in proportion to the maximums.
986
+ const available = Math.max(0, width - spacingX * (grid.columns + 1));
987
+ const fixed = box.style?.tableLayout === "fixed" && numberOrNull(resolveLength(box.style?.width, width)) != null;
988
+ const { mins, maxes } = fixed ? fixedColumnSizes(grid, table, available) : tableColumnSizes(ctx, grid, spacingX);
989
+ const sumMin = mins.reduce((sum, size) => sum + size, 0);
990
+ const sumMax = maxes.reduce((sum, size) => sum + size, 0);
991
+ let widths;
992
+ if (fixed) widths = maxes;
993
+ else if (sumMin >= available) widths = mins;
994
+ else if (sumMax <= available) {
995
+ const extra = available - sumMax;
996
+ widths = maxes.map((size) => size + (sumMax > 0 ? extra * size / sumMax : extra / grid.columns));
997
+ } else {
998
+ const ratio = (available - sumMin) / (sumMax - sumMin);
999
+ widths = mins.map((min, column) => min + (maxes[column] - min) * ratio);
1000
+ }
1001
+ const starts = [];
1002
+ let columnX = x + spacingX;
1003
+ for (const size of widths) {
1004
+ starts.push(columnX);
1005
+ columnX += size + spacingX;
1006
+ }
1007
+ const spanWidth = (cell) =>
1008
+ widths.slice(cell.column, cell.column + cell.colspan).reduce((sum, size) => sum + size, 0) + spacingX * (cell.colspan - 1);
1009
+
1010
+ // Row heights: the tallest single-row cell (or a specified height); rowspans
1011
+ // add whatever they still need to their last row.
1012
+ const rowHeights = table.rows.map((row) => numberOrZero(numberOrNull(row.style?.height)));
1013
+ for (const cell of grid.cells) {
1014
+ cell.width = spanWidth(cell);
1015
+ cell.measured = dryLayout(ctx, cell.box, cell.width).height;
1016
+ if (cell.rowspan === 1) rowHeights[cell.row] = Math.max(rowHeights[cell.row], cell.measured);
1017
+ }
1018
+ for (const cell of grid.cells) {
1019
+ if (cell.rowspan === 1) continue;
1020
+ const last = cell.row + cell.rowspan - 1;
1021
+ const have = rowHeights.slice(cell.row, last + 1).reduce((sum, size) => sum + size, 0) + spacingY * (cell.rowspan - 1);
1022
+ if (cell.measured > have) rowHeights[last] += cell.measured - have;
1023
+ }
1024
+ const rowTops = [];
1025
+ cursor += spacingY;
1026
+ for (const size of rowHeights) {
1027
+ rowTops.push(cursor);
1028
+ cursor += size + spacingY;
1029
+ }
1030
+
1031
+ // Row backgrounds, then cells.
1032
+ table.rows.forEach((row, index) => {
1033
+ if (!row.node) return;
1034
+ ctx.boxes.push({
1035
+ nodeId: row.node.id,
1036
+ x: x + spacingX,
1037
+ y: rowTops[index],
1038
+ width: Math.max(0, width - spacingX * 2),
1039
+ height: rowHeights[index],
1040
+ style: row.style,
1041
+ });
1042
+ });
1043
+ let baseline = null;
1044
+ for (const cell of grid.cells) {
1045
+ const top = rowTops[cell.row];
1046
+ const height = rowHeights.slice(cell.row, cell.row + cell.rowspan).reduce((sum, size) => sum + size, 0)
1047
+ + spacingY * (cell.rowspan - 1);
1048
+ const boxStart = ctx.boxes.length;
1049
+ const fragmentStart = ctx.fragments.length;
1050
+ const result = layoutBlock(ctx, cell.box, starts[cell.column], cell.width, top, false, height);
1051
+ // vertical-align moves the cell's content, not the cell box.
1052
+ const align = cell.box.style?.verticalAlign;
1053
+ const offset = align === "middle" ? (height - cell.measured) / 2
1054
+ : align === "bottom" ? height - cell.measured
1055
+ : 0;
1056
+ if (offset > 0) shiftOutput(ctx, boxStart + 1, fragmentStart, 0, offset);
1057
+ if (cell.row === 0) baseline ??= result.baseline == null ? null : result.baseline + offset;
1058
+ }
1059
+ return { bottom: cursor, baseline };
1060
+ }
1061
+
1062
+ /** justify-self within the grid area: stretch unless a width or alignment says otherwise. */
1063
+ function gridHorizontal(ctx, containerStyle, item, areaX, areaWidth) {
1064
+ const style = item.box.style;
1065
+ const alignment = ["auto", undefined].includes(style?.justifySelf)
1066
+ ? containerStyle?.justifyItems ?? "normal"
1067
+ : style.justifySelf;
1068
+ const shrink = ["start", "end", "center"].includes(alignment);
1069
+ const placed = resolveHorizontal(ctx, item.box, areaX, areaWidth, shrink);
1070
+ const free = areaWidth - placed.width - placed.marginLeft - placed.marginRight;
1071
+ if (alignment === "center") placed.x += free / 2;
1072
+ else if (alignment === "end") placed.x += free;
1073
+ return placed;
1074
+ }
1075
+
1076
+ /** Expands track lists and places items (§7.2, §8.5 row auto-flow). */
1077
+ function gridStructure(ctx, box, availableWidth, columnGap, definite) {
1078
+ const style = box.style;
1079
+ const explicitColumns = expandTrackList(style?.gridTemplateColumns, definite ? availableWidth : null, columnGap);
1080
+ const explicitRows = expandTrackList(style?.gridTemplateRows, null, style?.rowGap ?? 0);
1081
+ const items = box.children.map((child) => ({ box: child, ...gridLines(child.style, explicitColumns.tracks.length, "Column"),
1082
+ ...rowLines(child.style, explicitRows.tracks.length) }));
1083
+
1084
+ let columnCount = Math.max(1, explicitColumns.tracks.length);
1085
+ for (const item of items) {
1086
+ if (item.column != null) columnCount = Math.max(columnCount, item.column + item.columnSpan);
1087
+ else columnCount = Math.max(columnCount, item.columnSpan);
1088
+ }
1089
+ const occupied = [];
1090
+ const isFree = (row, column, rowSpan, columnSpan) => {
1091
+ for (let r = row; r < row + rowSpan; r++) {
1092
+ for (let c = column; c < column + columnSpan; c++) if (occupied[r]?.[c]) return false;
1093
+ }
1094
+ return true;
1095
+ };
1096
+ const occupy = (item) => {
1097
+ for (let r = item.row; r < item.row + item.rowSpan; r++) {
1098
+ occupied[r] ??= [];
1099
+ for (let c = item.column; c < item.column + item.columnSpan; c++) occupied[r][c] = true;
1100
+ }
1101
+ };
1102
+
1103
+ // 1. Items locked to both axes; 2. items locked to a row.
1104
+ for (const item of items) if (item.row != null && item.column != null) occupy(item);
1105
+ for (const item of items) {
1106
+ if (item.row == null || item.column != null) continue;
1107
+ let column = 0;
1108
+ while (column + item.columnSpan <= columnCount && !isFree(item.row, column, item.rowSpan, item.columnSpan)) column++;
1109
+ item.column = column;
1110
+ columnCount = Math.max(columnCount, column + item.columnSpan);
1111
+ occupy(item);
1112
+ }
1113
+ // 3. Auto-placed items walk a cursor forward (sparse) or restart (dense).
1114
+ const dense = style?.gridAutoFlow?.dense === true;
1115
+ let cursorRow = 0;
1116
+ let cursorColumn = 0;
1117
+ for (const item of items) {
1118
+ if (item.row != null) continue;
1119
+ if (dense) {
1120
+ cursorRow = 0;
1121
+ cursorColumn = 0;
1122
+ }
1123
+ if (item.column != null) {
1124
+ if (item.column < cursorColumn) cursorRow++;
1125
+ cursorColumn = item.column;
1126
+ while (!isFree(cursorRow, item.column, item.rowSpan, item.columnSpan)) cursorRow++;
1127
+ item.row = cursorRow;
1128
+ } else {
1129
+ for (;;) {
1130
+ if (cursorColumn + item.columnSpan > columnCount) {
1131
+ cursorRow++;
1132
+ cursorColumn = 0;
1133
+ }
1134
+ if (isFree(cursorRow, cursorColumn, item.rowSpan, item.columnSpan)) break;
1135
+ cursorColumn++;
1136
+ }
1137
+ item.row = cursorRow;
1138
+ item.column = cursorColumn;
1139
+ cursorColumn += item.columnSpan;
1140
+ }
1141
+ occupy(item);
1142
+ }
1143
+
1144
+ const rowCount = Math.max(explicitRows.tracks.length, ...items.map((item) => item.row + item.rowSpan), 0);
1145
+ const columnTracks = Array.from({ length: columnCount }, (_, index) =>
1146
+ explicitColumns.tracks[index] ?? cycle(style?.gridAutoColumns, index - explicitColumns.tracks.length));
1147
+ const rowTracks = Array.from({ length: rowCount }, (_, index) =>
1148
+ explicitRows.tracks[index] ?? cycle(style?.gridAutoRows, index - explicitRows.tracks.length));
1149
+ // auto-fit: repeated tracks nobody occupies collapse (§7.2.3.2).
1150
+ const columnCollapsed = columnTracks.map((_, index) => explicitColumns.autoFit.has(index)
1151
+ && !items.some((item) => index >= item.column && index < item.column + item.columnSpan));
1152
+ return { items, columnTracks, rowTracks, columnCollapsed };
1153
+ }
1154
+
1155
+ function cycle(tracks, index) {
1156
+ const list = tracks?.length ? tracks : [{ min: "auto", max: "auto" }];
1157
+ return list[((index % list.length) + list.length) % list.length];
1158
+ }
1159
+
1160
+ function gridLines(style, explicitCount, axis) {
1161
+ const start = style?.[`grid${axis}Start`] ?? "auto";
1162
+ const end = style?.[`grid${axis}End`] ?? "auto";
1163
+ // Line numbers are 1-based; negatives count back from the explicit end line.
1164
+ const index = (line) => line > 0 ? line - 1 : Math.max(0, explicitCount + 1 + line);
1165
+ let from = start.line != null ? index(start.line) : null;
1166
+ let to = end.line != null ? index(end.line) : null;
1167
+ let span = 1;
1168
+ if (from != null && to != null) {
1169
+ if (to < from) [from, to] = [to, from];
1170
+ span = Math.max(1, to - from);
1171
+ } else if (from != null) {
1172
+ span = end.span ?? 1;
1173
+ } else if (to != null) {
1174
+ span = start.span ?? 1;
1175
+ from = Math.max(0, to - span);
1176
+ } else {
1177
+ // Two spans: the end span is discarded (§8.3.1).
1178
+ span = start.span ?? end.span ?? 1;
1179
+ }
1180
+ return axis === "Column" ? { column: from, columnSpan: span } : { row: from, rowSpan: span };
1181
+ }
1182
+
1183
+ function rowLines(style, explicitCount) {
1184
+ return gridLines(style, explicitCount, "Row");
1185
+ }
1186
+
1187
+ /** Expands repeat() and resolves auto-fill/auto-fit repetitions (§7.2.3.2). */
1188
+ function expandTrackList(list, available, gap) {
1189
+ const tracks = [];
1190
+ const autoFit = new Set();
1191
+ if (!list) return { tracks, autoFit };
1192
+ const autoEntry = list.find((entry) => typeof entry.repeat === "string");
1193
+ let repetitions = 1;
1194
+ if (autoEntry && available != null) {
1195
+ const fixedSize = (track) => {
1196
+ const max = numberOrNull(resolveLength(track.max, available));
1197
+ const min = numberOrNull(resolveLength(track.min, available));
1198
+ return max ?? min;
1199
+ };
1200
+ const other = list.filter((entry) => entry !== autoEntry)
1201
+ .flatMap((entry) => entry.repeat ? Array(entry.repeat).fill(entry.tracks).flat() : [entry]);
1202
+ const repeated = autoEntry.tracks.map(fixedSize);
1203
+ if (repeated.every((size) => size != null)) {
1204
+ const otherSize = other.reduce((sum, track) => sum + (fixedSize(track) ?? 0), 0);
1205
+ const repetitionSize = repeated.reduce((sum, size) => sum + size, 0);
1206
+ const count = (n) => other.length + n * autoEntry.tracks.length;
1207
+ repetitions = 1;
1208
+ while (otherSize + (repetitions + 1) * repetitionSize + gap * (count(repetitions + 1) - 1) <= available + 0.01) {
1209
+ repetitions++;
1210
+ }
1211
+ }
1212
+ }
1213
+ for (const entry of list) {
1214
+ if (!entry.repeat) {
1215
+ tracks.push(entry);
1216
+ continue;
1217
+ }
1218
+ const count = typeof entry.repeat === "number" ? entry.repeat : repetitions;
1219
+ for (let index = 0; index < count; index++) {
1220
+ for (const track of entry.tracks) {
1221
+ if (entry.repeat === "auto-fit") autoFit.add(tracks.length);
1222
+ tracks.push(track);
1223
+ }
1224
+ }
1225
+ }
1226
+ return { tracks, autoFit };
1227
+ }
1228
+
1229
+ /** Track sizing for columns (§12.3–§12.8, span-1 contributions, simplified spanning). */
1230
+ /**
1231
+ * An item's minimum contribution for an auto track minimum (CSS Grid 2
1232
+ * §6.6/§12.5): a specified min-width, else 0 for scroll containers (overflow
1233
+ * other than visible), else its min-content contribution.
1234
+ */
1235
+ function minimumContribution(box, minContent, available) {
1236
+ const style = box.style;
1237
+ const margin = style?.margin ?? ZERO_BOX;
1238
+ const margins = numberOrZero(margin[1]) + numberOrZero(margin[3]);
1239
+ const specified = numberOrNull(resolveLength(style?.minWidth, available));
1240
+ if (specified != null) {
1241
+ const padding = style?.padding ?? ZERO_BOX;
1242
+ const extra = padding[1] + padding[3] + borderWidths(style)[1] + borderWidths(style)[3];
1243
+ return (style.boxSizing === "border-box" ? Math.max(specified, extra) : specified + extra) + margins;
1244
+ }
1245
+ if (style?.overflowX === "clip" || style?.overflowY === "clip") return margins;
1246
+ return minContent;
1247
+ }
1248
+
1249
+ function sizeGridColumns(ctx, box, grid, available, gap, definite, intrinsic = "max") {
1250
+ const tracks = grid.columnTracks.map((track, index) => {
1251
+ const collapsed = grid.columnCollapsed[index];
1252
+ const min = collapsed ? 0 : resolveBreadth(track.min, definite ? available : null);
1253
+ const max = collapsed ? 0 : resolveBreadth(track.max, definite ? available : null);
1254
+ return {
1255
+ min,
1256
+ max,
1257
+ base: typeof min === "number" ? min : 0,
1258
+ growth: typeof max === "number" ? max : max?.fr != null ? null : Infinity,
1259
+ };
1260
+ });
1261
+ const contributions = (item) => {
1262
+ const margin = item.box.style?.margin ?? ZERO_BOX;
1263
+ const margins = numberOrZero(margin[1]) + numberOrZero(margin[3]);
1264
+ return { min: minContentWidth(ctx, item.box) + margins, max: maxContentWidth(ctx, item.box) + margins };
1265
+ };
1266
+
1267
+ // Intrinsic sizes from items spanning one track (§12.5 step 2).
1268
+ for (const item of grid.items.filter((candidate) => candidate.columnSpan === 1)) {
1269
+ const track = tracks[item.column];
1270
+ if (grid.columnCollapsed[item.column]) continue;
1271
+ const contribution = contributions(item);
1272
+ if (track.min === "min-content") track.base = Math.max(track.base, contribution.min);
1273
+ else if (track.min === "auto") track.base = Math.max(track.base, minimumContribution(item.box, contribution.min, available));
1274
+ else if (track.min === "max-content") track.base = Math.max(track.base, contribution.max);
1275
+ if (track.max === "min-content") track.growth = updateGrowth(track, contribution.min);
1276
+ else if (track.max === "max-content" || track.max === "auto") track.growth = updateGrowth(track, contribution.max);
1277
+ else if (track.max?.fitContent != null) {
1278
+ const limit = resolveLength(track.max.fitContent, available);
1279
+ track.growth = updateGrowth(track, Math.min(contribution.max, Math.max(contribution.min, limit)));
1280
+ }
1281
+ }
1282
+ for (const track of tracks) {
1283
+ if (track.growth === Infinity) track.growth = track.base;
1284
+ if (track.growth != null) track.growth = Math.max(track.growth, track.base);
1285
+ }
1286
+ // Items spanning several tracks grow the intrinsic ones they cross (§12.5 step 3, simplified).
1287
+ for (const item of grid.items.filter((candidate) => candidate.columnSpan > 1)) {
1288
+ const spanned = tracks.slice(item.column, item.column + item.columnSpan);
1289
+ const intrinsic = spanned.filter((track) => typeof track.min !== "number");
1290
+ if (!intrinsic.length) continue;
1291
+ const current = spanned.reduce((sum, track) => sum + track.base, 0) + gap * (item.columnSpan - 1);
1292
+ const extra = contributions(item).min - current;
1293
+ if (extra > 0) for (const track of intrinsic) track.base += extra / intrinsic.length;
1294
+ for (const track of spanned) if (track.growth != null) track.growth = Math.max(track.growth, track.base);
1295
+ }
1296
+
1297
+ const visible = tracks.filter((_, index) => !grid.columnCollapsed[index]);
1298
+ const gaps = gap * Math.max(0, visible.length - 1);
1299
+ const sizes = () => tracks.reduce((sum, track) => sum + track.base, 0) + gaps;
1300
+
1301
+ // Maximize tracks (§12.6): grow bases toward growth limits equally.
1302
+ if (definite) {
1303
+ for (let guard = 0; guard < tracks.length + 1; guard++) {
1304
+ const growable = tracks.filter((track) => track.growth != null && track.growth > track.base + 1e-9);
1305
+ const free = available - sizes();
1306
+ if (!growable.length || free <= 1e-9) break;
1307
+ const share = free / growable.length;
1308
+ for (const track of growable) track.base = Math.min(track.growth, track.base + share);
1309
+ }
1310
+ } else if (intrinsic === "max") {
1311
+ // Max-content sizing: every track takes its growth limit.
1312
+ for (const track of tracks) if (track.growth != null) track.base = track.growth;
1313
+ }
1314
+
1315
+ // Expand flexible tracks (§12.7).
1316
+ const flexible = tracks.filter((track) => track.max?.fr != null);
1317
+ if (flexible.length) {
1318
+ let frSize;
1319
+ if (definite) {
1320
+ const leftover = available - gaps - tracks.filter((track) => track.max?.fr == null)
1321
+ .reduce((sum, track) => sum + track.base, 0);
1322
+ const inflexible = new Set();
1323
+ for (let guard = 0; guard <= flexible.length; guard++) {
1324
+ const active = flexible.filter((track) => !inflexible.has(track));
1325
+ const factors = Math.max(1, active.reduce((sum, track) => sum + track.max.fr, 0));
1326
+ const space = leftover - [...inflexible].reduce((sum, track) => sum + track.base, 0);
1327
+ frSize = Math.max(0, space / factors);
1328
+ const violators = active.filter((track) => track.base > frSize * track.max.fr);
1329
+ if (!violators.length) break;
1330
+ for (const track of violators) inflexible.add(track);
1331
+ }
1332
+ } else if (intrinsic === "min") {
1333
+ frSize = 0;
1334
+ } else {
1335
+ // Indefinite: the fr size that fits every track's max-content contribution (§12.7.2).
1336
+ frSize = 0;
1337
+ for (const item of grid.items.filter((candidate) => candidate.columnSpan === 1)) {
1338
+ const track = tracks[item.column];
1339
+ if (track.max?.fr > 0) frSize = Math.max(frSize, contributions(item).max / Math.max(1, track.max.fr));
1340
+ }
1341
+ }
1342
+ for (const track of flexible) track.base = Math.max(track.base, frSize * track.max.fr);
1343
+ }
1344
+
1345
+ // Stretch auto tracks into leftover space (§12.8, justify-content: normal).
1346
+ if (definite && ["normal", "stretch"].includes(box.style?.justifyContent ?? "normal")) {
1347
+ const stretchable = tracks.filter((track, index) => track.max === "auto" && !grid.columnCollapsed[index]);
1348
+ const free = available - sizes();
1349
+ if (stretchable.length && free > 0) for (const track of stretchable) track.base += free / stretchable.length;
1350
+ }
1351
+ return tracks.map((track) => track.base);
1352
+ }
1353
+
1354
+ /** An infinite growth limit takes the first contribution, then the largest. */
1355
+ function updateGrowth(track, value) {
1356
+ return track.growth === Infinity ? value : Math.max(track.growth, value);
1357
+ }
1358
+
1359
+ /** Row sizing: explicit lengths are fixed; other rows fit their tallest item. */
1360
+ function sizeGridRows(grid, gap) {
1361
+ const rows = grid.rowTracks.map((track) => {
1362
+ const fixed = numberOrNull(resolveBreadth(track.min, null));
1363
+ const fixedMax = numberOrNull(resolveBreadth(track.max, null));
1364
+ return fixed != null && fixedMax != null ? { size: fixedMax, fixed: true } : { size: fixed ?? 0, fixed: false };
1365
+ });
1366
+ for (const item of grid.items.filter((candidate) => candidate.rowSpan === 1)) {
1367
+ const row = rows[item.row];
1368
+ if (!row.fixed) row.size = Math.max(row.size, item.height);
1369
+ }
1370
+ for (const item of grid.items.filter((candidate) => candidate.rowSpan > 1)) {
1371
+ const spanned = rows.slice(item.row, item.row + item.rowSpan);
1372
+ const current = spanned.reduce((sum, row) => sum + row.size, 0) + gap * (item.rowSpan - 1);
1373
+ const flexible = spanned.filter((row) => !row.fixed);
1374
+ if (item.height > current && flexible.length) flexible.at(-1).size += item.height - current;
1375
+ }
1376
+ return rows.map((row) => row.size);
1377
+ }
1378
+
1379
+ function resolveBreadth(breadth, available) {
1380
+ if (typeof breadth === "string" || breadth?.fr != null || breadth?.fitContent != null) return breadth;
1381
+ const value = available == null && breadth?.unit ? null : resolveLength(breadth, available);
1382
+ return Number.isFinite(value) ? value : "auto";
1383
+ }
1384
+
1385
+ function trackStarts(sizes, collapsed, gap, origin) {
1386
+ const starts = [];
1387
+ let cursor = origin;
1388
+ let placedAny = false;
1389
+ sizes.forEach((size, index) => {
1390
+ if (!collapsed[index] && placedAny) cursor += gap;
1391
+ starts.push(cursor);
1392
+ cursor += size;
1393
+ if (!collapsed[index]) placedAny = true;
1394
+ });
1395
+ return starts;
1396
+ }
1397
+
1398
+ function spanSize(sizes, collapsed, gap, start, span) {
1399
+ let total = 0;
1400
+ let visible = 0;
1401
+ for (let index = start; index < start + span; index++) {
1402
+ total += sizes[index] ?? 0;
1403
+ if (!collapsed[index]) visible++;
1404
+ }
1405
+ return total + gap * Math.max(0, visible - 1);
1406
+ }
1407
+
1408
+ function gridIntrinsicWidth(ctx, box, kind) {
1409
+ const gap = box.style?.columnGap ?? 0;
1410
+ const grid = gridStructure(ctx, box, null, gap, false);
1411
+ const columns = sizeGridColumns(ctx, box, grid, 0, gap, false, kind);
1412
+ const visible = columns.filter((_, index) => !grid.columnCollapsed[index]);
1413
+ return columns.reduce((sum, size) => sum + size, 0) + gap * Math.max(0, visible.length - 1);
1414
+ }
1415
+
1416
+ /** Lays a box out off-screen to learn its height and baseline at a given width. */
1417
+ function dryLayout(ctx, box, width) {
1418
+ const fragments = ctx.fragments;
1419
+ const boxes = ctx.boxes;
1420
+ ctx.fragments = [];
1421
+ ctx.boxes = [];
1422
+ const result = layoutBlock(ctx, box, 0, width, 0);
1423
+ ctx.fragments = fragments;
1424
+ ctx.boxes = boxes;
1425
+ return { height: result.height, baselineOffset: result.baseline };
1426
+ }
1427
+
1428
+ /** Resolves the used border-box width and horizontal margins of a block-level box. */
1429
+ function resolveHorizontal(ctx, box, containingX, containingWidth, shrink) {
1430
+ const style = box.style;
1431
+ const padding = style?.padding ?? ZERO_BOX;
1432
+ const extra = padding[1] + padding[3] + borderWidths(style)[1] + borderWidths(style)[3];
1433
+ const borderBox = (value) => style?.boxSizing === "border-box" ? value : value + extra;
1434
+ const margin = style?.margin ?? ZERO_BOX;
1435
+ let marginLeft = numberOrZero(margin[3]);
1436
+ let marginRight = numberOrZero(margin[1]);
1437
+ const available = Math.max(0, containingWidth - marginLeft - marginRight);
1438
+ const specified = numberOrNull(resolveLength(style?.width, containingWidth));
1439
+ let width;
1440
+ if (box.replaced) width = imageDimensions(box.node, containingWidth).width + extra;
1441
+ else if (specified != null) width = borderBox(specified);
1442
+ else if (shrink) width = Math.min(maxContentWidth(ctx, box), available);
1443
+ else width = available;
1444
+ const maxWidth = numberOrNull(resolveLength(style?.maxWidth, containingWidth));
1445
+ if (maxWidth != null) width = Math.min(width, borderBox(maxWidth));
1446
+ const minWidth = numberOrNull(resolveLength(style?.minWidth, containingWidth));
1447
+ if (minWidth != null) width = Math.max(width, borderBox(minWidth));
1448
+ width = Math.max(width, extra);
1449
+
1450
+ const remaining = Math.max(0, containingWidth - width - marginLeft - marginRight);
1451
+ if (margin[3] === "auto" && margin[1] === "auto") {
1452
+ marginLeft += remaining / 2;
1453
+ marginRight += remaining / 2;
1454
+ } else if (margin[3] === "auto") {
1455
+ marginLeft += remaining;
1456
+ } else if (margin[1] === "auto") {
1457
+ marginRight += remaining;
1458
+ }
1459
+ return { x: containingX + marginLeft, width, marginLeft, marginRight };
1460
+ }
1461
+
1462
+ function maxContentWidth(ctx, box) {
1463
+ const cached = ctx.maxContent.get(box);
1464
+ if (cached != null) return cached;
1465
+ const style = box.style;
1466
+ const padding = style?.padding ?? ZERO_BOX;
1467
+ const extra = padding[1] + padding[3] + borderWidths(style)[1] + borderWidths(style)[3];
1468
+ let width;
1469
+ const specified = numberOrNull(style?.width);
1470
+ if (box.replaced) {
1471
+ width = imageDimensions(box.node, Infinity).width + extra;
1472
+ } else if (specified != null) {
1473
+ width = style.boxSizing === "border-box" ? specified : specified + extra;
1474
+ } else if (box.table) {
1475
+ width = tableIntrinsicWidth(ctx, box, "max") + extra;
1476
+ } else if (box.grid) {
1477
+ width = gridIntrinsicWidth(ctx, box, "max") + extra;
1478
+ } else if (box.flex === "row") {
1479
+ const gap = style?.columnGap ?? style?.gap ?? 0;
1480
+ const content = box.children.reduce((sum, child, index) => {
1481
+ const margin = child.style?.margin ?? ZERO_BOX;
1482
+ return sum + (index ? gap : 0) + maxContentWidth(ctx, child) + numberOrZero(margin[1]) + numberOrZero(margin[3]);
1483
+ }, 0);
1484
+ width = content + extra;
1485
+ } else {
1486
+ let content = 0;
1487
+ for (const child of inFlowChildren(box)) {
1488
+ if (child.kind === "ifc") {
1489
+ content = Math.max(content, inlineMaxContentWidth(ctx, child));
1490
+ } else {
1491
+ const margin = child.style?.margin ?? ZERO_BOX;
1492
+ content = Math.max(content, maxContentWidth(ctx, child) + numberOrZero(margin[1]) + numberOrZero(margin[3]));
1493
+ }
1494
+ }
1495
+ width = content + extra;
1496
+ }
1497
+ const maxWidth = numberOrNull(style?.maxWidth);
1498
+ if (maxWidth != null) width = Math.min(width, style.boxSizing === "border-box" ? maxWidth : maxWidth + extra);
1499
+ ctx.maxContent.set(box, width);
1500
+ return width;
1501
+ }
1502
+
1503
+ function minContentWidth(ctx, box) {
1504
+ const cached = ctx.minContent.get(box);
1505
+ if (cached != null) return cached;
1506
+ const style = box.style;
1507
+ const padding = style?.padding ?? ZERO_BOX;
1508
+ const extra = padding[1] + padding[3] + borderWidths(style)[1] + borderWidths(style)[3];
1509
+ const specified = numberOrNull(style?.width);
1510
+ const outer = (child) => {
1511
+ const margin = child.style?.margin ?? ZERO_BOX;
1512
+ return minContentWidth(ctx, child) + numberOrZero(margin[1]) + numberOrZero(margin[3]);
1513
+ };
1514
+ let width;
1515
+ if (box.replaced) {
1516
+ width = imageDimensions(box.node, Infinity).width + extra;
1517
+ } else if (specified != null) {
1518
+ width = style.boxSizing === "border-box" ? specified : specified + extra;
1519
+ } else if (box.table) {
1520
+ width = tableIntrinsicWidth(ctx, box, "min") + extra;
1521
+ } else if (box.grid) {
1522
+ width = gridIntrinsicWidth(ctx, box, "min") + extra;
1523
+ } else if (box.flex === "row" && style?.flexWrap !== "wrap") {
1524
+ const gap = style?.columnGap ?? style?.gap ?? 0;
1525
+ width = box.children.reduce((sum, child, index) => sum + (index ? gap : 0) + outer(child), 0) + extra;
1526
+ } else {
1527
+ width = Math.max(0, ...inFlowChildren(box).map((child) => child.kind === "ifc"
1528
+ ? inlineMinContentWidth(ctx, child)
1529
+ : outer(child))) + extra;
1530
+ }
1531
+ ctx.minContent.set(box, width);
1532
+ return width;
1533
+ }
1534
+
1535
+ function verticalMargins(style) {
1536
+ const margin = style?.margin ?? ZERO_BOX;
1537
+ return { top: numberOrZero(margin[0]), bottom: numberOrZero(margin[2]) };
1538
+ }
1539
+
1540
+ // Margin collapsing. A box collapses with its first/last in-flow child when
1541
+ // it does not establish a BFC and has no border or padding on that side.
1542
+
1543
+ function collapsesThroughTop(box) {
1544
+ return !box.bfc && box.kind === "block" && !box.replaced
1545
+ && borderWidths(box.style)[0] === 0 && (box.style?.padding ?? ZERO_BOX)[0] === 0
1546
+ && inFlowChildren(box)[0]?.kind === "block";
1547
+ }
1548
+
1549
+ function collapsesThroughBottom(box) {
1550
+ return !box.bfc && box.kind === "block" && !box.replaced
1551
+ && borderWidths(box.style)[2] === 0 && (box.style?.padding ?? ZERO_BOX)[2] === 0
1552
+ && numberOrNull(box.style?.height) == null
1553
+ && inFlowChildren(box).at(-1)?.kind === "block";
1554
+ }
1555
+
1556
+ function topStrut(box) {
1557
+ const own = marginStrut(verticalMargins(box.style).top);
1558
+ return collapsesThroughTop(box) ? combineStruts(own, topStrut(inFlowChildren(box)[0])) : own;
1559
+ }
1560
+
1561
+ function bottomStrut(box) {
1562
+ const own = marginStrut(verticalMargins(box.style).bottom);
1563
+ return collapsesThroughBottom(box) ? combineStruts(own, bottomStrut(inFlowChildren(box).at(-1))) : own;
1564
+ }
1565
+
1566
+ function inFlowChildren(box) {
1567
+ return box.children.filter((child) => child.kind !== "placeholder");
1568
+ }
1569
+
1570
+ function marginStrut(value) {
1571
+ return value >= 0 ? { positive: value, negative: 0 } : { positive: 0, negative: value };
1572
+ }
1573
+
1574
+ function combineStruts(left, right) {
1575
+ return {
1576
+ positive: Math.max(left.positive, right.positive),
1577
+ negative: Math.min(left.negative, right.negative),
1578
+ };
1579
+ }
1580
+
1581
+ function strutValue(strut) {
1582
+ return strut.positive + strut.negative;
1583
+ }
1584
+
1585
+ // ---------------------------------------------------------------------------
1586
+ // Inline formatting context
1587
+
1588
+ function layoutInline(ctx, ifc, x, width, y) {
1589
+ const paragraph = buildParagraph(ctx, ifc);
1590
+ const atoms = new Map();
1591
+ const atomFor = (run) => {
1592
+ let atom = atoms.get(run);
1593
+ if (!atom) {
1594
+ atom = measureAtomic(ctx, run.box, width);
1595
+ atoms.set(run, atom);
1596
+ }
1597
+ return atom;
1598
+ };
1599
+ const lines = breakLines(ctx, paragraph, width, atomFor);
1600
+ let cursor = y;
1601
+ let baseline = null;
1602
+ for (const line of lines) {
1603
+ const placed = placeLine(ctx, ifc, paragraph, line, x, width, cursor, atomFor);
1604
+ cursor += placed.height;
1605
+ baseline = placed.baseline;
1606
+ }
1607
+ return { bottom: cursor, baseline };
1608
+ }
1609
+
1610
+ function inlineMaxContentWidth(ctx, ifc) {
1611
+ const paragraph = buildParagraph(ctx, ifc);
1612
+ const atomFor = (run) => {
1613
+ const margin = run.box.style?.margin ?? ZERO_BOX;
1614
+ return {
1615
+ width: maxContentWidth(ctx, run.box),
1616
+ marginLeft: numberOrZero(margin[3]),
1617
+ marginRight: numberOrZero(margin[1]),
1618
+ };
1619
+ };
1620
+ const lines = breakLines(ctx, paragraph, Infinity, atomFor);
1621
+ return Math.max(0, ...lines.map((line) => line.width));
1622
+ }
1623
+
1624
+ /** The widest unbreakable piece: the narrowest width without overflow. */
1625
+ function inlineMinContentWidth(ctx, ifc) {
1626
+ const paragraph = buildParagraph(ctx, ifc);
1627
+ const atomFor = (run) => {
1628
+ const margin = run.box.style?.margin ?? ZERO_BOX;
1629
+ return {
1630
+ width: minContentWidth(ctx, run.box),
1631
+ marginLeft: numberOrZero(margin[3]),
1632
+ marginRight: numberOrZero(margin[1]),
1633
+ };
1634
+ };
1635
+ return Math.max(0, ...paragraph.pieces.map((piece) =>
1636
+ rangeWidth(ctx, paragraph, piece.start, piece.end, atomFor)
1637
+ - trailingHangWidth(ctx, paragraph, piece.end, atomFor)));
1638
+ }
1639
+
1640
+ /**
1641
+ * Converts inline items into one paragraph string plus runs. Collapsible white
1642
+ * space is collapsed across element boundaries; atomic inlines become U+FFFC.
1643
+ */
1644
+ function buildParagraph(ctx, ifc) {
1645
+ if (ifc.paragraph) return ifc.paragraph;
1646
+ let text = "";
1647
+ const runs = [];
1648
+ const forced = new Map();
1649
+ const stack = [];
1650
+ const inlineState = new Map();
1651
+ let pendingOpens = [];
1652
+ let afterSpace = true;
1653
+
1654
+ const lastCollapsibleRun = () => {
1655
+ const run = runs.at(-1);
1656
+ return run && run.end > run.start && run.collapsible && text[run.end - 1] === " " ? run : null;
1657
+ };
1658
+ const trimTrailingSpace = () => {
1659
+ const run = lastCollapsibleRun();
1660
+ if (run && run.end === text.length) {
1661
+ run.end--;
1662
+ text = text.slice(0, -1);
1663
+ }
1664
+ };
1665
+ const pushRun = (run, value) => {
1666
+ run.start = text.length;
1667
+ text += value;
1668
+ run.end = text.length;
1669
+ run.inlines = [...stack];
1670
+ run.opens = pendingOpens;
1671
+ run.closes = [];
1672
+ for (const open of pendingOpens) inlineState.get(open).firstRun = run;
1673
+ pendingOpens = [];
1674
+ for (const inline of stack) inlineState.get(inline).lastRun = run;
1675
+ runs.push(run);
1676
+ };
1677
+
1678
+ for (const item of ifc.items) {
1679
+ if (item.kind === "open") {
1680
+ stack.push(item.node);
1681
+ inlineState.set(item.node, { style: item.style, firstRun: null, lastRun: null });
1682
+ pendingOpens.push(item.node);
1683
+ } else if (item.kind === "close") {
1684
+ const index = stack.lastIndexOf(item.node);
1685
+ if (index >= 0) stack.splice(index, 1);
1686
+ pendingOpens = pendingOpens.filter((node) => node !== item.node);
1687
+ inlineState.get(item.node)?.lastRun?.closes.unshift(item.node);
1688
+ } else if (item.kind === "text") {
1689
+ let value = String(item.text).replace(/\r\n?/g, "\n");
1690
+ if (item.preserve) {
1691
+ const pieces = value.split("\n");
1692
+ pieces.forEach((piece, index) => {
1693
+ if (index > 0) forced.set(text.length, (forced.get(text.length) ?? 0) + 1);
1694
+ if (piece) {
1695
+ pushRun({ kind: "text", nodeId: item.node.id, style: item.style, collapsible: false, wrap: item.wrap }, piece);
1696
+ }
1697
+ });
1698
+ afterSpace = false;
1699
+ } else {
1700
+ value = value.replace(/[\t\n\f\r ]+/g, " ");
1701
+ if (afterSpace) value = value.replace(/^ /, "");
1702
+ if (value) {
1703
+ pushRun({ kind: "text", nodeId: item.node.id, style: item.style, collapsible: true, wrap: item.wrap }, value);
1704
+ afterSpace = value.endsWith(" ");
1705
+ }
1706
+ }
1707
+ } else if (item.kind === "break") {
1708
+ trimTrailingSpace();
1709
+ forced.set(text.length, (forced.get(text.length) ?? 0) + 1);
1710
+ afterSpace = true;
1711
+ } else if (item.kind === "image" || item.kind === "atomic") {
1712
+ pushRun({ kind: item.kind, nodeId: item.node.id, style: item.node.style ?? null, node: item.node, box: item.box, wrap: true }, "");
1713
+ afterSpace = false;
1714
+ }
1715
+ }
1716
+ trimTrailingSpace();
1717
+
1718
+ const visibleRuns = runs;
1719
+ for (const run of visibleRuns) {
1720
+ run.startInset = run.opens.reduce((sum, node) => sum + inlineInsets(inlineState.get(node).style).left, 0);
1721
+ run.endInset = run.closes.reduce((sum, node) => sum + inlineInsets(inlineState.get(node).style).right, 0);
1722
+ }
1723
+
1724
+ const runAt = new Array(text.length);
1725
+ for (const run of visibleRuns) for (let index = run.start; index < run.end; index++) runAt[index] = run;
1726
+ const opportunities = new Set();
1727
+ const graphemes = [...new Intl.Segmenter(undefined, { granularity: "grapheme" }).segment(text)];
1728
+ for (const { segment, index } of graphemes) {
1729
+ const run = runAt[index];
1730
+ const end = index + segment.length;
1731
+ if (!run) continue;
1732
+ if (run.collapsible && run.wrap && segment === " ") opportunities.add(end);
1733
+ else if (run.kind === "image" || run.kind === "atomic") {
1734
+ opportunities.add(index);
1735
+ opportunities.add(end);
1736
+ } else if (run.wrap && run.kind === "text" && (Bun.stringWidth(segment) > 1 || (!run.collapsible && segment === " "))) {
1737
+ if (Bun.stringWidth(segment) > 1) opportunities.add(index);
1738
+ opportunities.add(end);
1739
+ }
1740
+ }
1741
+
1742
+ const pieces = [];
1743
+ let start = 0;
1744
+ const pushPiece = (end, forcedCount) => {
1745
+ pieces.push({ start, end, forced: forcedCount > 0 });
1746
+ for (let count = 1; count < forcedCount; count++) pieces.push({ start: end, end, forced: true });
1747
+ start = end;
1748
+ };
1749
+ for (let position = 0; position <= text.length; position++) {
1750
+ const forcedCount = forced.get(position) ?? 0;
1751
+ if (forcedCount > 0) pushPiece(position, forcedCount);
1752
+ else if (position > start && (opportunities.has(position) || position === text.length)) pushPiece(position, 0);
1753
+ }
1754
+
1755
+ ifc.paragraph = { text, runs: visibleRuns, runAt, pieces, inlineState, graphemes };
1756
+ return ifc.paragraph;
1757
+ }
1758
+
1759
+ /** CSS Text 3 §5.2/§5.5: breaking inside a word needs overflow-wrap or word-break. */
1760
+ function mayBreakWithinWords(paragraph, piece) {
1761
+ const run = paragraph.runAt[piece.start];
1762
+ const style = run?.style;
1763
+ // white-space: nowrap / pre never wrap, whatever overflow-wrap says.
1764
+ if (!style || run.wrap === false) return false;
1765
+ return (style.overflowWrap ?? "normal") !== "normal" || style.wordBreak === "break-all" || style.wordBreak === "break-word";
1766
+ }
1767
+
1768
+ /**
1769
+ * text-overflow: ellipsis (CSS Overflow 3 §3): a line wider than a clipping
1770
+ * block container loses content from its end, at grapheme boundaries, to make
1771
+ * room for "…". Mutates `segments`; returns the ellipsis to append, or null.
1772
+ */
1773
+ function truncateForEllipsis(ctx, style, paragraph, segments, line, width) {
1774
+ if (style?.textOverflow !== "ellipsis" || style.overflowX !== "clip" || line.width <= width + 0.5) return null;
1775
+ const lastText = [...segments].reverse().find((segment) => segment.run.kind === "text");
1776
+ if (!lastText) return null;
1777
+ const text = "\u2026";
1778
+ const ellipsisWidth = ctx.measure(text, lastText.run.style);
1779
+ let budget = width - ellipsisWidth;
1780
+ let keep = 0;
1781
+ for (; keep < segments.length; keep++) {
1782
+ const segment = segments[keep];
1783
+ if (segment.width <= budget) {
1784
+ budget -= segment.width;
1785
+ continue;
1786
+ }
1787
+ if (segment.run.kind === "text") {
1788
+ // The longest grapheme-aligned prefix that fits.
1789
+ let end = segment.start;
1790
+ let used = 0;
1791
+ for (const { index, segment: grapheme } of paragraph.graphemes) {
1792
+ if (index < segment.start || index >= segment.end) continue;
1793
+ const next = ctx.measure(paragraph.text.slice(segment.start, index + grapheme.length), segment.run.style);
1794
+ if (next > budget) break;
1795
+ end = index + grapheme.length;
1796
+ used = next;
1797
+ }
1798
+ if (end > segment.start) {
1799
+ segments[keep] = { ...segment, end, width: used };
1800
+ keep++;
1801
+ }
1802
+ }
1803
+ break;
1804
+ }
1805
+ segments.splice(keep);
1806
+ line.width = segments.reduce((sum, segment) => sum + segment.width, 0) + ellipsisWidth;
1807
+ return { text, width: ellipsisWidth, run: lastText.run, metrics: textMetrics(ctx, lastText.run.style) };
1808
+ }
1809
+
1810
+ function inlineImageMargins(node) {
1811
+ const margin = node.style?.margin ?? ZERO_BOX;
1812
+ return { left: numberOrZero(margin[3]), right: numberOrZero(margin[1]) };
1813
+ }
1814
+
1815
+ /**
1816
+ * The top of an inline image relative to the baseline (CSS 2 §10.8.1
1817
+ * vertical-align), with the line's text metrics for text-top/text-bottom.
1818
+ */
1819
+ function inlineImageTop(style, height, metrics) {
1820
+ switch (style?.verticalAlign) {
1821
+ case "text-bottom":
1822
+ case "bottom":
1823
+ return metrics.descent - height;
1824
+ case "text-top":
1825
+ case "top":
1826
+ return -metrics.ascent;
1827
+ case "middle":
1828
+ // Centred on the baseline plus half the x-height (about 0.25em).
1829
+ return -(style.fontSize ?? 16) * 0.25 - height / 2;
1830
+ default:
1831
+ return -height;
1832
+ }
1833
+ }
1834
+
1835
+ function inlineInsets(style) {
1836
+ const margin = style?.margin ?? ZERO_BOX;
1837
+ const padding = style?.padding ?? ZERO_BOX;
1838
+ const border = borderWidths(style);
1839
+ return {
1840
+ left: numberOrZero(margin[3]) + border[3] + padding[3],
1841
+ right: numberOrZero(margin[1]) + border[1] + padding[1],
1842
+ };
1843
+ }
1844
+
1845
+ function rangeWidth(ctx, paragraph, start, end, atomFor) {
1846
+ let width = 0;
1847
+ for (const run of paragraph.runs) {
1848
+ if (run.end <= start || run.start >= end) continue;
1849
+ if (run.start >= start) width += run.startInset;
1850
+ if (run.end <= end) width += run.endInset;
1851
+ width += runSliceWidth(ctx, run, Math.max(start, run.start), Math.min(end, run.end), paragraph.text, atomFor);
1852
+ }
1853
+ return width;
1854
+ }
1855
+
1856
+ function runSliceWidth(ctx, run, start, end, text, atomFor) {
1857
+ if (end <= start) return 0;
1858
+ if (run.kind === "image") {
1859
+ const margins = inlineImageMargins(run.node);
1860
+ return imageDimensions(run.node, Infinity).width + margins.left + margins.right;
1861
+ }
1862
+ if (run.kind === "atomic") {
1863
+ const atom = atomFor(run);
1864
+ return atom.width + atom.marginLeft + atom.marginRight;
1865
+ }
1866
+ return ctx.measure(text.slice(start, end), run.style);
1867
+ }
1868
+
1869
+ function trailingHangWidth(ctx, paragraph, end, atomFor) {
1870
+ const run = paragraph.runAt[end - 1];
1871
+ if (!run?.collapsible || paragraph.text[end - 1] !== " ") return 0;
1872
+ return runSliceWidth(ctx, run, end - 1, end, paragraph.text, atomFor);
1873
+ }
1874
+
1875
+ function breakLines(ctx, paragraph, maxWidth, atomFor) {
1876
+ const lines = [];
1877
+ let line = null;
1878
+ const finish = () => {
1879
+ if (!line) return;
1880
+ let end = line.end;
1881
+ while (end > line.start && paragraph.runAt[end - 1]?.collapsible && paragraph.text[end - 1] === " ") end--;
1882
+ // Use the same piece-wise sum the break decision used, so a max-content
1883
+ // width measured here never wraps when laid out at exactly that width.
1884
+ lines.push({ start: line.start, end, width: line.width - (line.hang ?? 0) });
1885
+ line = null;
1886
+ };
1887
+
1888
+ for (const piece of paragraph.pieces) {
1889
+ const width = rangeWidth(ctx, paragraph, piece.start, piece.end, atomFor);
1890
+ const hang = trailingHangWidth(ctx, paragraph, piece.end, atomFor);
1891
+ if (line && line.width + width - hang > maxWidth + 0.01) finish();
1892
+ if (!line && width - hang > maxWidth + 0.01 && piece.end - piece.start > 1 && mayBreakWithinWords(paragraph, piece)) {
1893
+ // Emergency break inside an unbreakable piece, one grapheme at a time
1894
+ // (only where overflow-wrap or word-break allow it; otherwise it overflows).
1895
+ let start = piece.start;
1896
+ let used = 0;
1897
+ for (const { segment, index } of paragraph.graphemes) {
1898
+ if (index < piece.start || index >= piece.end) continue;
1899
+ const graphemeWidth = rangeWidth(ctx, paragraph, index, index + segment.length, atomFor);
1900
+ if (index > start && used + graphemeWidth > maxWidth + 0.01) {
1901
+ line = { start, end: index, width: used, hang: 0 };
1902
+ finish();
1903
+ start = index;
1904
+ used = 0;
1905
+ }
1906
+ used += graphemeWidth;
1907
+ }
1908
+ line = { start, end: piece.end, width: used, hang: 0 };
1909
+ } else if (line) {
1910
+ line.end = piece.end;
1911
+ line.width += width;
1912
+ line.hang = hang;
1913
+ } else {
1914
+ line = { start: piece.start, end: piece.end, width, hang };
1915
+ }
1916
+ if (piece.forced) {
1917
+ line ??= { start: piece.end, end: piece.end, width: 0, hang: 0 };
1918
+ finish();
1919
+ }
1920
+ }
1921
+ finish();
1922
+ return lines;
1923
+ }
1924
+
1925
+ function placeLine(ctx, ifc, paragraph, line, x, width, y, atomFor) {
1926
+ const style = ifc.style;
1927
+ const segments = [];
1928
+ for (const run of paragraph.runs) {
1929
+ const start = Math.max(line.start, run.start);
1930
+ const end = Math.min(line.end, run.end);
1931
+ if (end <= start) continue;
1932
+ segments.push({ run, start, end, width: runSliceWidth(ctx, run, start, end, paragraph.text, atomFor) });
1933
+ }
1934
+
1935
+ // Vertical metrics: align every item on a shared baseline, including the
1936
+ // container's strut.
1937
+ const strut = textMetrics(ctx, style);
1938
+ let ascent = strut.ascent;
1939
+ let descent = strut.descent;
1940
+ for (const segment of segments) {
1941
+ const { run } = segment;
1942
+ if (run.kind === "image") {
1943
+ segment.dimensions = imageDimensions(run.node, width);
1944
+ segment.imageTop = inlineImageTop(run.node.style, segment.dimensions.height, strut);
1945
+ ascent = Math.max(ascent, -segment.imageTop);
1946
+ descent = Math.max(descent, segment.imageTop + segment.dimensions.height);
1947
+ } else if (run.kind === "atomic") {
1948
+ const atom = atomFor(run);
1949
+ const atomAscent = atom.marginTop + (atom.baseline ?? atom.height) ;
1950
+ segment.atomAscent = atomAscent;
1951
+ ascent = Math.max(ascent, atomAscent);
1952
+ descent = Math.max(descent, atom.marginTop + atom.height + atom.marginBottom - atomAscent);
1953
+ } else {
1954
+ segment.metrics = textMetrics(ctx, run.style);
1955
+ ascent = Math.max(ascent, segment.metrics.ascent);
1956
+ descent = Math.max(descent, segment.metrics.descent);
1957
+ }
1958
+ }
1959
+ const baselineY = y + ascent;
1960
+ const lineHeight = ascent + descent;
1961
+
1962
+ // Horizontal alignment.
1963
+ const alignment = style?.textAlign;
1964
+ const free = Math.max(0, width - line.width);
1965
+ const lineX = x + (alignment === "center" ? free / 2 : alignment === "end" ? free : 0);
1966
+
1967
+ const ellipsis = truncateForEllipsis(ctx, style, paragraph, segments, line, width);
1968
+
1969
+ let cursor = lineX;
1970
+ const edges = new Map();
1971
+ const runs = [];
1972
+ const atomsToPlace = [];
1973
+ // Right floats (approximated as atomic inlines) go to the end of the line.
1974
+ const rightFloats = segments.filter((segment) => segment.run.kind === "atomic" && segment.run.style?.float === "right");
1975
+ const rightFloatWidth = rightFloats.reduce((sum, segment) => sum + segment.width, 0);
1976
+ const ordered = rightFloats.length
1977
+ ? [...segments.filter((segment) => !rightFloats.includes(segment)), ...rightFloats]
1978
+ : segments;
1979
+ for (const segment of ordered) {
1980
+ const { run } = segment;
1981
+ if (segment === rightFloats[0]) cursor = Math.max(cursor, x + width - rightFloatWidth);
1982
+ if (segment.start === run.start) {
1983
+ for (const node of run.opens) {
1984
+ const insets = inlineInsets(paragraph.inlineState.get(node).style);
1985
+ const margin = paragraph.inlineState.get(node).style?.margin ?? ZERO_BOX;
1986
+ edges.set(node, { ...edges.get(node), left: cursor + numberOrZero(margin[3]) });
1987
+ cursor += insets.left;
1988
+ }
1989
+ }
1990
+ const segmentWidth = segment.width;
1991
+ const common = {
1992
+ nodeId: run.nodeId,
1993
+ text: run.kind === "text" ? paragraph.text.slice(segment.start, segment.end) : "",
1994
+ start: segment.start - line.start,
1995
+ end: segment.end - line.start,
1996
+ style: run.style ?? style,
1997
+ };
1998
+ if (run.kind === "image") {
1999
+ runs.push({
2000
+ ...common,
2001
+ type: "image",
2002
+ x: cursor + inlineImageMargins(run.node).left,
2003
+ y: baselineY + segment.imageTop,
2004
+ width: segment.dimensions.width,
2005
+ height: segment.dimensions.height,
2006
+ resource: run.node.resource,
2007
+ video: run.node.tagName === "VIDEO",
2008
+ svg: run.node.svg ?? null,
2009
+ });
2010
+ } else if (run.kind === "atomic") {
2011
+ const atom = atomFor(run);
2012
+ const atomY = baselineY - segment.atomAscent + atom.marginTop;
2013
+ runs.push({ ...common, type: "atomic", x: cursor, y: atomY, width: segmentWidth, height: atom.height });
2014
+ atomsToPlace.push({ box: run.box, x: cursor + atom.marginLeft, y: atomY, width: atom.width });
2015
+ } else {
2016
+ runs.push({
2017
+ ...common,
2018
+ x: cursor,
2019
+ y: baselineY - segment.metrics.contentAscent,
2020
+ width: Math.max(1, segmentWidth),
2021
+ height: null,
2022
+ });
2023
+ }
2024
+ for (const node of run.inlines) {
2025
+ const edge = edges.get(node) ?? {};
2026
+ edge.first ??= cursor;
2027
+ edge.last = cursor + segmentWidth;
2028
+ edges.set(node, edge);
2029
+ }
2030
+ cursor += segmentWidth;
2031
+ if (segment.end === run.end) {
2032
+ for (const node of run.closes) {
2033
+ const state = paragraph.inlineState.get(node);
2034
+ const insets = inlineInsets(state.style);
2035
+ const margin = state.style?.margin ?? ZERO_BOX;
2036
+ cursor += insets.right;
2037
+ const edge = edges.get(node) ?? {};
2038
+ edge.right = cursor - numberOrZero(margin[1]);
2039
+ edges.set(node, edge);
2040
+ }
2041
+ }
2042
+ }
2043
+ if (ellipsis) {
2044
+ const end = segments.at(-1)?.end ?? line.start;
2045
+ runs.push({
2046
+ nodeId: ellipsis.run.nodeId,
2047
+ text: ellipsis.text,
2048
+ start: end - line.start,
2049
+ end: end - line.start,
2050
+ style: ellipsis.run.style ?? style,
2051
+ x: cursor,
2052
+ y: baselineY - ellipsis.metrics.contentAscent,
2053
+ width: ellipsis.width,
2054
+ height: null,
2055
+ });
2056
+ cursor += ellipsis.width;
2057
+ }
2058
+
2059
+ // Decorated inline boxes (background/border) for this line.
2060
+ for (const [node, edge] of edges) {
2061
+ const nodeStyle = paragraph.inlineState.get(node)?.style;
2062
+ if (!isDecorated(nodeStyle) || edge.first == null) continue;
2063
+ const padding = nodeStyle.padding ?? ZERO_BOX;
2064
+ const border = borderWidths(nodeStyle);
2065
+ const metrics = textMetrics(ctx, nodeStyle);
2066
+ const left = edge.left ?? edge.first;
2067
+ const right = edge.right ?? edge.last;
2068
+ ctx.boxes.push({
2069
+ nodeId: node.id,
2070
+ x: left,
2071
+ y: baselineY - metrics.contentAscent - padding[0] - border[0],
2072
+ width: right - left,
2073
+ height: metrics.contentHeight + padding[0] + padding[2] + border[0] + border[2],
2074
+ style: nodeStyle,
2075
+ inline: true,
2076
+ });
2077
+ }
2078
+
2079
+ ctx.fragments.push(lineFragment(
2080
+ style,
2081
+ paragraph.text.slice(line.start, line.end),
2082
+ [...new Set(runs.map((run) => run.nodeId))],
2083
+ runs,
2084
+ lineX,
2085
+ y,
2086
+ line.width,
2087
+ lineHeight,
2088
+ baselineY,
2089
+ ));
2090
+ for (const atom of atomsToPlace) layoutBlock(ctx, atom.box, atom.x, atom.width, atom.y);
2091
+ return { height: lineHeight, baseline: baselineY };
2092
+ }
2093
+
2094
+ function measureAtomic(ctx, box, availableWidth) {
2095
+ const placed = resolveHorizontal(ctx, box, 0, availableWidth, true);
2096
+ const result = dryLayout(ctx, box, placed.width);
2097
+ const margin = verticalMargins(box.style);
2098
+ return {
2099
+ width: placed.width,
2100
+ height: result.height,
2101
+ baseline: result.baselineOffset,
2102
+ marginLeft: placed.marginLeft,
2103
+ marginRight: placed.marginRight,
2104
+ marginTop: margin.top,
2105
+ marginBottom: margin.bottom,
2106
+ };
2107
+ }
2108
+
2109
+ function textMetrics(ctx, style) {
2110
+ const font = ctx.metrics(style);
2111
+ // `line-height: normal` (null) uses the font's own content height.
2112
+ const lineHeight = ctx.lineHeight ?? (style ? style.lineHeight ?? font.height : ctx.fallbackLineHeight);
2113
+ const halfLeading = (lineHeight - font.height) / 2;
2114
+ const ascent = halfLeading + font.ascent;
2115
+ return { ascent, descent: lineHeight - ascent, contentAscent: font.ascent, contentHeight: font.height };
2116
+ }
2117
+
2118
+ function isDecorated(style) {
2119
+ return Boolean(style && ((style.backgroundColor && style.backgroundColor !== "rgba(0, 0, 0, 0)")
2120
+ || borderWidths(style).some((width) => width > 0)));
2121
+ }
2122
+
2123
+ function borderWidths(style) {
2124
+ return style?.borderWidths ?? ZERO_BOX;
2125
+ }
2126
+
2127
+ function lineFragment(style, text, nodeIds, runs, x, y, width, height, baseline = null) {
2128
+ return {
2129
+ type: "line",
2130
+ baseline,
2131
+ text,
2132
+ nodeIds: Object.freeze(nodeIds),
2133
+ runs: Object.freeze(runs.map((run) => Object.freeze(run))),
2134
+ x,
2135
+ y,
2136
+ width,
2137
+ height: Math.max(height, ...runs.map((run) => run.height ?? 0)),
2138
+ style,
2139
+ };
2140
+ }
2141
+
2142
+ // ---------------------------------------------------------------------------
2143
+ // Shared helpers
2144
+
2145
+ function cachedMeasure(measureText) {
2146
+ const byStyle = new Map();
2147
+ return (text, style) => {
2148
+ if (!text) return 0;
2149
+ let cache = byStyle.get(style ?? null);
2150
+ if (!cache) byStyle.set(style ?? null, cache = new Map());
2151
+ let width = cache.get(text);
2152
+ if (width === undefined) cache.set(text, width = measureText(text, style ?? null));
2153
+ return width;
2154
+ };
2155
+ }
2156
+
2157
+ function cachedMetrics(fontMetrics) {
2158
+ const cache = new Map();
2159
+ return (style) => {
2160
+ const fontSize = style?.fontSize ?? 16;
2161
+ const key = `${fontSize}/${style?.fontWeight ?? 400}/${style?.fontFamily?.join(",")}`;
2162
+ let metrics = cache.get(key);
2163
+ if (!metrics) {
2164
+ metrics = typeof fontMetrics === "function" ? fontMetrics(style ?? null) : null;
2165
+ if (!(metrics?.height > 0)) {
2166
+ metrics = { ascent: fontSize * DEFAULT_ASCENT, height: fontSize * DEFAULT_CONTENT_HEIGHT };
2167
+ }
2168
+ cache.set(key, metrics);
2169
+ }
2170
+ return metrics;
2171
+ };
2172
+ }
2173
+
2174
+ function imageDimensions(node, referenceWidth) {
2175
+ const intrinsicWidth = node.resource?.width ?? node.widthAttribute ?? 300;
2176
+ const intrinsicHeight = node.resource?.height ?? node.heightAttribute ?? 150;
2177
+ const ratio = intrinsicWidth / intrinsicHeight;
2178
+ const cssWidth = node.style?.width;
2179
+ const cssHeight = node.style?.height;
2180
+ let width = cssWidth !== "auto" && cssWidth != null
2181
+ ? resolveLength(cssWidth, referenceWidth)
2182
+ : node.widthAttribute;
2183
+ let height = cssHeight !== "auto" && cssHeight != null
2184
+ ? resolveLength(cssHeight, referenceWidth)
2185
+ : node.heightAttribute;
2186
+ if (!Number.isFinite(width)) width = null;
2187
+ if (!Number.isFinite(height)) height = null;
2188
+ if (width == null && height == null) [width, height] = [intrinsicWidth, intrinsicHeight];
2189
+ else if (width == null) width = height * ratio;
2190
+ else if (height == null) height = width / ratio;
2191
+ if (node.style?.maxWidth !== "none" && node.style?.maxWidth != null) {
2192
+ const maximum = resolveLength(node.style.maxWidth, referenceWidth);
2193
+ if (Number.isFinite(maximum) && width > maximum) [width, height] = [maximum, maximum / ratio];
2194
+ }
2195
+ if (node.tagName === "VIDEO") {
2196
+ if (Number.isFinite(referenceWidth) && width > referenceWidth) [width, height] = [referenceWidth, referenceWidth / ratio];
2197
+ const minHeight = resolveLength(node.style?.minHeight, referenceWidth);
2198
+ const maxHeight = resolveLength(node.style?.maxHeight, referenceWidth);
2199
+ if (Number.isFinite(minHeight) && height < minHeight) height = minHeight;
2200
+ if (Number.isFinite(maxHeight) && height > maxHeight) [width, height] = [maxHeight * ratio, maxHeight];
2201
+ }
2202
+ return { width: Math.max(1, width), height: Math.max(1, height) };
2203
+ }
2204
+
2205
+ function positiveInteger(value, fallback) {
2206
+ return Number.isInteger(value) && value > 0 ? value : fallback;
2207
+ }
2208
+
2209
+ function positiveNumber(value, fallback) {
2210
+ return Number.isFinite(value) && value > 0 ? value : fallback;
2211
+ }
2212
+
2213
+ function finiteNumber(value, fallback) {
2214
+ return Number.isFinite(value) ? value : fallback;
2215
+ }
2216
+
2217
+ function numberOrZero(value) {
2218
+ return Number.isFinite(value) ? value : 0;
2219
+ }
2220
+
2221
+ function numberOrNull(value) {
2222
+ return Number.isFinite(value) ? value : null;
2223
+ }
2224
+
2225
+ function resolveLength(value, reference) {
2226
+ if (!value || typeof value !== "object") return value;
2227
+ if (value.unit === "%") return reference * value.value / 100;
2228
+ if (value.unit === "math" && value.kind === "calc") return value.px + reference * value.percent / 100;
2229
+ if (value.unit === "math") {
2230
+ const values = value.values.map((part) => resolveLength(part, reference));
2231
+ if (value.kind === "min") return Math.min(...values);
2232
+ if (value.kind === "max") return Math.max(...values);
2233
+ return Math.max(values[0], Math.min(values[1], values[2]));
2234
+ }
2235
+ return value;
2236
+ }