@gyral/core 0.3.0 → 0.3.1

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 (381) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/NOTICE +19 -0
  3. package/README.md +30 -5
  4. package/dist/call.d.ts +32 -0
  5. package/dist/call.js +63 -0
  6. package/dist/call.js.map +1 -0
  7. package/dist/children.d.ts +25 -3
  8. package/dist/children.js +18 -1
  9. package/dist/children.js.map +1 -1
  10. package/dist/cli/gyral-types.d.ts +2 -0
  11. package/dist/cli/gyral-types.js +23 -0
  12. package/dist/cli/gyral-types.js.map +1 -0
  13. package/dist/command.d.ts +54 -12
  14. package/dist/command.js +25 -11
  15. package/dist/command.js.map +1 -1
  16. package/dist/compiler/ast.d.ts +2 -0
  17. package/dist/compiler/ast.js +5 -1
  18. package/dist/compiler/ast.js.map +1 -1
  19. package/dist/compiler/compile.d.ts +5 -2
  20. package/dist/compiler/compile.js +36 -17
  21. package/dist/compiler/compile.js.map +1 -1
  22. package/dist/compiler/component-entries.d.ts +7 -0
  23. package/dist/compiler/component-entries.js +42 -0
  24. package/dist/compiler/component-entries.js.map +1 -0
  25. package/dist/compiler/components.d.ts +4 -0
  26. package/dist/compiler/components.js +182 -0
  27. package/dist/compiler/components.js.map +1 -0
  28. package/dist/compiler/facts.d.ts +31 -0
  29. package/dist/compiler/facts.js +285 -0
  30. package/dist/compiler/facts.js.map +1 -0
  31. package/dist/compiler/features.d.ts +34 -0
  32. package/dist/compiler/features.js +158 -0
  33. package/dist/compiler/features.js.map +1 -0
  34. package/dist/compiler/hooks.d.ts +4 -0
  35. package/dist/compiler/hooks.js +144 -89
  36. package/dist/compiler/hooks.js.map +1 -1
  37. package/dist/compiler/loader-source.d.ts +14 -0
  38. package/dist/compiler/loader-source.js +86 -0
  39. package/dist/compiler/loader-source.js.map +1 -0
  40. package/dist/compiler/locate.d.ts +14 -0
  41. package/dist/compiler/locate.js +78 -0
  42. package/dist/compiler/locate.js.map +1 -0
  43. package/dist/compiler/parse5-check.d.ts +1 -1
  44. package/dist/compiler/parse5-check.js +8 -3
  45. package/dist/compiler/parse5-check.js.map +1 -1
  46. package/dist/compiler/prop-schemas.d.ts +4 -0
  47. package/dist/compiler/prop-schemas.js +108 -0
  48. package/dist/compiler/prop-schemas.js.map +1 -0
  49. package/dist/compiler/scan.d.ts +13 -3
  50. package/dist/compiler/scan.js +21 -13
  51. package/dist/compiler/scan.js.map +1 -1
  52. package/dist/compiler/scope.d.ts +8 -0
  53. package/dist/compiler/scope.js +116 -0
  54. package/dist/compiler/scope.js.map +1 -0
  55. package/dist/compiler/tag-map.d.ts +41 -0
  56. package/dist/compiler/tag-map.js +126 -0
  57. package/dist/compiler/tag-map.js.map +1 -0
  58. package/dist/components-ready.d.ts +7 -0
  59. package/dist/components-ready.js +19 -0
  60. package/dist/components-ready.js.map +1 -0
  61. package/dist/define.d.ts +13 -4
  62. package/dist/define.js +8 -12
  63. package/dist/define.js.map +1 -1
  64. package/dist/devtools-events.d.ts +8 -0
  65. package/dist/devtools-events.js.map +1 -1
  66. package/dist/devtools-off.d.ts +1 -0
  67. package/dist/devtools-off.js +1 -0
  68. package/dist/devtools-off.js.map +1 -1
  69. package/dist/devtools.d.ts +3 -0
  70. package/dist/devtools.js +14 -0
  71. package/dist/devtools.js.map +1 -1
  72. package/dist/drivers-scope.js.map +1 -1
  73. package/dist/element-internals.d.ts +1 -0
  74. package/dist/element-internals.js +11 -0
  75. package/dist/element-internals.js.map +1 -0
  76. package/dist/element-types.d.ts +6 -2
  77. package/dist/element-types.js.map +1 -1
  78. package/dist/element.js +80 -27
  79. package/dist/element.js.map +1 -1
  80. package/dist/error-view.d.ts +10 -0
  81. package/dist/error-view.js +30 -0
  82. package/dist/error-view.js.map +1 -0
  83. package/dist/errors.d.ts +21 -0
  84. package/dist/errors.js +47 -0
  85. package/dist/errors.js.map +1 -0
  86. package/dist/errors.json +289 -0
  87. package/dist/eslint/imports.d.ts +2 -0
  88. package/dist/eslint/imports.js +2 -2
  89. package/dist/eslint/imports.js.map +1 -1
  90. package/dist/eslint/index.d.ts +2 -1
  91. package/dist/eslint/index.js +11 -3
  92. package/dist/eslint/index.js.map +1 -1
  93. package/dist/eslint/template-rule.d.ts +1 -0
  94. package/dist/eslint/template-rule.js +15 -5
  95. package/dist/eslint/template-rule.js.map +1 -1
  96. package/dist/eslint/unused-intent-rule.d.ts +2 -0
  97. package/dist/eslint/unused-intent-rule.js +186 -0
  98. package/dist/eslint/unused-intent-rule.js.map +1 -0
  99. package/dist/features.d.ts +2 -2
  100. package/dist/features.js.map +1 -1
  101. package/dist/focus.d.ts +6 -0
  102. package/dist/focus.js +32 -2
  103. package/dist/focus.js.map +1 -1
  104. package/dist/form-associated.d.ts +46 -0
  105. package/dist/form-associated.js +77 -0
  106. package/dist/form-associated.js.map +1 -0
  107. package/dist/forms.d.ts +42 -30
  108. package/dist/forms.js +85 -41
  109. package/dist/forms.js.map +1 -1
  110. package/dist/frame-lane.d.ts +11 -0
  111. package/dist/frame-lane.js +28 -0
  112. package/dist/frame-lane.js.map +1 -0
  113. package/dist/head.d.ts +61 -0
  114. package/dist/head.js +85 -0
  115. package/dist/head.js.map +1 -0
  116. package/dist/host-model.d.ts +34 -5
  117. package/dist/host-model.js +146 -23
  118. package/dist/host-model.js.map +1 -1
  119. package/dist/hydration-client.js +2 -2
  120. package/dist/hydration-client.js.map +1 -1
  121. package/dist/hydration-loader.d.ts +13 -0
  122. package/dist/hydration-loader.js +58 -0
  123. package/dist/hydration-loader.js.map +1 -0
  124. package/dist/hydration-off.d.ts +8 -0
  125. package/dist/hydration-off.js +25 -0
  126. package/dist/hydration-off.js.map +1 -0
  127. package/dist/hydration.d.ts +0 -12
  128. package/dist/hydration.js +3 -52
  129. package/dist/hydration.js.map +1 -1
  130. package/dist/index.d.ts +20 -24
  131. package/dist/index.js +10 -19
  132. package/dist/index.js.map +1 -1
  133. package/dist/indexeddb-types.d.ts +97 -0
  134. package/dist/indexeddb-types.js +2 -0
  135. package/dist/indexeddb-types.js.map +1 -0
  136. package/dist/indexeddb.d.ts +5 -0
  137. package/dist/indexeddb.js +118 -0
  138. package/dist/indexeddb.js.map +1 -0
  139. package/dist/intent.d.ts +41 -19
  140. package/dist/intent.js +144 -106
  141. package/dist/intent.js.map +1 -1
  142. package/dist/internal/indexeddb-open.d.ts +8 -0
  143. package/dist/internal/indexeddb-open.js +96 -0
  144. package/dist/internal/indexeddb-open.js.map +1 -0
  145. package/dist/internal/indexeddb-transaction.d.ts +4 -0
  146. package/dist/internal/indexeddb-transaction.js +134 -0
  147. package/dist/internal/indexeddb-transaction.js.map +1 -0
  148. package/dist/internal/interpreter.d.ts +12 -4
  149. package/dist/internal/interpreter.js +36 -48
  150. package/dist/internal/interpreter.js.map +1 -1
  151. package/dist/internal/token.d.ts +1 -0
  152. package/dist/internal/token.js +7 -0
  153. package/dist/internal/token.js.map +1 -0
  154. package/dist/internal.d.ts +20 -0
  155. package/dist/internal.js +22 -0
  156. package/dist/internal.js.map +1 -0
  157. package/dist/invoker-fallback-used.d.ts +4 -0
  158. package/dist/invoker-fallback-used.js +10 -0
  159. package/dist/invoker-fallback-used.js.map +1 -0
  160. package/dist/invoker-fallback.d.ts +4 -0
  161. package/dist/invoker-fallback.js +15 -0
  162. package/dist/invoker-fallback.js.map +1 -0
  163. package/dist/light-dom.d.ts +1 -1
  164. package/dist/light-dom.js.map +1 -1
  165. package/dist/prop.d.ts +30 -7
  166. package/dist/prop.js +19 -0
  167. package/dist/prop.js.map +1 -1
  168. package/dist/props.d.ts +8 -3
  169. package/dist/props.js +22 -15
  170. package/dist/props.js.map +1 -1
  171. package/dist/retry.d.ts +15 -0
  172. package/dist/retry.js +48 -0
  173. package/dist/retry.js.map +1 -0
  174. package/dist/scheduler.d.ts +7 -3
  175. package/dist/scheduler.js +38 -56
  176. package/dist/scheduler.js.map +1 -1
  177. package/dist/script-json.d.ts +2 -0
  178. package/dist/script-json.js +13 -0
  179. package/dist/script-json.js.map +1 -0
  180. package/dist/server-component.d.ts +1 -1
  181. package/dist/server-component.js +45 -14
  182. package/dist/server-component.js.map +1 -1
  183. package/dist/server.d.ts +8 -2
  184. package/dist/server.js +11 -2
  185. package/dist/server.js.map +1 -1
  186. package/dist/settled.d.ts +4 -3
  187. package/dist/settled.js +48 -26
  188. package/dist/settled.js.map +1 -1
  189. package/dist/spec-features-used.d.ts +21 -0
  190. package/dist/spec-features-used.js +50 -0
  191. package/dist/spec-features-used.js.map +1 -0
  192. package/dist/spec-features.d.ts +28 -0
  193. package/dist/spec-features.js +42 -0
  194. package/dist/spec-features.js.map +1 -0
  195. package/dist/states.d.ts +3 -5
  196. package/dist/states.js +22 -8
  197. package/dist/states.js.map +1 -1
  198. package/dist/storage.d.ts +69 -0
  199. package/dist/storage.js +158 -0
  200. package/dist/storage.js.map +1 -0
  201. package/dist/store-binding.js +2 -2
  202. package/dist/store-binding.js.map +1 -1
  203. package/dist/store-scope.d.ts +2 -4
  204. package/dist/store-scope.js +6 -16
  205. package/dist/store-scope.js.map +1 -1
  206. package/dist/store.js +36 -8
  207. package/dist/store.js.map +1 -1
  208. package/dist/subscription.d.ts +35 -0
  209. package/dist/subscription.js +74 -0
  210. package/dist/subscription.js.map +1 -0
  211. package/dist/subscriptions.d.ts +26 -0
  212. package/dist/subscriptions.js +98 -0
  213. package/dist/subscriptions.js.map +1 -0
  214. package/dist/transitions.d.ts +4 -5
  215. package/dist/transitions.js +10 -4
  216. package/dist/transitions.js.map +1 -1
  217. package/dist/types.d.ts +124 -27
  218. package/dist/types.js.map +1 -1
  219. package/dist/use-dialogs.d.ts +2 -0
  220. package/dist/use-dialogs.js +9 -0
  221. package/dist/use-dialogs.js.map +1 -0
  222. package/dist/use-disposal.d.ts +2 -0
  223. package/dist/use-disposal.js +9 -0
  224. package/dist/use-disposal.js.map +1 -0
  225. package/dist/use-error-view.d.ts +2 -0
  226. package/dist/use-error-view.js +9 -0
  227. package/dist/use-error-view.js.map +1 -0
  228. package/dist/use-errored.d.ts +2 -0
  229. package/dist/use-errored.js +9 -0
  230. package/dist/use-errored.js.map +1 -0
  231. package/dist/use-form-associated.d.ts +2 -0
  232. package/dist/use-form-associated.js +7 -0
  233. package/dist/use-form-associated.js.map +1 -0
  234. package/dist/use-frame-lane.d.ts +2 -0
  235. package/dist/use-frame-lane.js +10 -0
  236. package/dist/use-frame-lane.js.map +1 -0
  237. package/dist/use-invokers.d.ts +2 -0
  238. package/dist/use-invokers.js +10 -0
  239. package/dist/use-invokers.js.map +1 -0
  240. package/dist/use-states.d.ts +2 -0
  241. package/dist/use-states.js +10 -0
  242. package/dist/use-states.js.map +1 -0
  243. package/dist/use-subscriptions.d.ts +2 -0
  244. package/dist/use-subscriptions.js +10 -0
  245. package/dist/use-subscriptions.js.map +1 -0
  246. package/dist/use-transitions.d.ts +2 -0
  247. package/dist/use-transitions.js +10 -0
  248. package/dist/use-transitions.js.map +1 -0
  249. package/dist/view/attributes.d.ts +5 -0
  250. package/dist/view/attributes.js +5 -0
  251. package/dist/view/attributes.js.map +1 -1
  252. package/dist/view/compiled.d.ts +1 -1
  253. package/dist/view/compiled.js +1 -1
  254. package/dist/view/compiled.js.map +1 -1
  255. package/dist/view/index.d.ts +9 -4
  256. package/dist/view/index.js +9 -3
  257. package/dist/view/index.js.map +1 -1
  258. package/dist/view/loc.d.ts +9 -0
  259. package/dist/view/loc.js +50 -0
  260. package/dist/view/loc.js.map +1 -0
  261. package/dist/view/message.d.ts +17 -0
  262. package/dist/view/message.js +40 -0
  263. package/dist/view/message.js.map +1 -0
  264. package/dist/view/messages.d.ts +43 -0
  265. package/dist/view/messages.js +84 -0
  266. package/dist/view/messages.js.map +1 -0
  267. package/dist/view/normalize/check.d.ts +5 -2
  268. package/dist/view/normalize/check.js +6 -3
  269. package/dist/view/normalize/check.js.map +1 -1
  270. package/dist/view/normalize/emit.d.ts +2 -0
  271. package/dist/view/normalize/emit.js +40 -11
  272. package/dist/view/normalize/emit.js.map +1 -1
  273. package/dist/view/normalize/errors.js +1 -1
  274. package/dist/view/normalize/errors.js.map +1 -1
  275. package/dist/view/normalize/id.d.ts +5 -2
  276. package/dist/view/normalize/id.js +9 -2
  277. package/dist/view/normalize/id.js.map +1 -1
  278. package/dist/view/normalize/normalize.d.ts +7 -4
  279. package/dist/view/normalize/normalize.js +15 -9
  280. package/dist/view/normalize/normalize.js.map +1 -1
  281. package/dist/view/normalize/rules.d.ts +9 -0
  282. package/dist/view/normalize/rules.js +35 -5
  283. package/dist/view/normalize/rules.js.map +1 -1
  284. package/dist/view/normalize/svg.d.ts +14 -0
  285. package/dist/view/normalize/svg.js +40 -0
  286. package/dist/view/normalize/svg.js.map +1 -0
  287. package/dist/view/normalize/tokens.d.ts +5 -1
  288. package/dist/view/normalize/tokens.js.map +1 -1
  289. package/dist/view/normalize/tree.d.ts +8 -2
  290. package/dist/view/normalize/tree.js +58 -13
  291. package/dist/view/normalize/tree.js.map +1 -1
  292. package/dist/view/normalize/types.d.ts +24 -4
  293. package/dist/view/normalize/types.js +4 -1
  294. package/dist/view/normalize/types.js.map +1 -1
  295. package/dist/view/normalize/whitespace.js +4 -3
  296. package/dist/view/normalize/whitespace.js.map +1 -1
  297. package/dist/view/prepare-stub.js +2 -2
  298. package/dist/view/prepare-stub.js.map +1 -1
  299. package/dist/view/prepare.d.ts +5 -2
  300. package/dist/view/prepare.js +9 -3
  301. package/dist/view/prepare.js.map +1 -1
  302. package/dist/view/registry.d.ts +15 -0
  303. package/dist/view/registry.js +10 -2
  304. package/dist/view/registry.js.map +1 -1
  305. package/dist/view/render/adopt-attr.js +7 -1
  306. package/dist/view/render/adopt-attr.js.map +1 -1
  307. package/dist/view/render/adopt.js +21 -4
  308. package/dist/view/render/adopt.js.map +1 -1
  309. package/dist/view/render/attr-parts.d.ts +12 -1
  310. package/dist/view/render/attr-parts.js +38 -5
  311. package/dist/view/render/attr-parts.js.map +1 -1
  312. package/dist/view/render/child-part.js +5 -2
  313. package/dist/view/render/child-part.js.map +1 -1
  314. package/dist/view/render/dispose.d.ts +3 -0
  315. package/dist/view/render/dispose.js +76 -0
  316. package/dist/view/render/dispose.js.map +1 -0
  317. package/dist/view/render/hook-part.d.ts +3 -1
  318. package/dist/view/render/hook-part.js +21 -5
  319. package/dist/view/render/hook-part.js.map +1 -1
  320. package/dist/view/render/hook-run.d.ts +2 -0
  321. package/dist/view/render/hook-run.js +72 -0
  322. package/dist/view/render/hook-run.js.map +1 -0
  323. package/dist/view/render/hooks.d.ts +73 -5
  324. package/dist/view/render/hooks.js +79 -17
  325. package/dist/view/render/hooks.js.map +1 -1
  326. package/dist/view/render/hydrate.js +2 -2
  327. package/dist/view/render/hydrate.js.map +1 -1
  328. package/dist/view/render/keyed.d.ts +6 -0
  329. package/dist/view/render/keyed.js +15 -0
  330. package/dist/view/render/keyed.js.map +1 -0
  331. package/dist/view/render/mismatch.js +5 -3
  332. package/dist/view/render/mismatch.js.map +1 -1
  333. package/dist/view/render/modal.d.ts +3 -0
  334. package/dist/view/render/modal.js +39 -0
  335. package/dist/view/render/modal.js.map +1 -0
  336. package/dist/view/render/raw.d.ts +4 -1
  337. package/dist/view/render/raw.js +6 -2
  338. package/dist/view/render/raw.js.map +1 -1
  339. package/dist/view/render/render.d.ts +4 -1
  340. package/dist/view/render/render.js +17 -12
  341. package/dist/view/render/render.js.map +1 -1
  342. package/dist/view/render/toggles.d.ts +6 -0
  343. package/dist/view/render/toggles.js +6 -0
  344. package/dist/view/render/toggles.js.map +1 -0
  345. package/dist/view/render/warn.d.ts +14 -0
  346. package/dist/view/render/warn.js +45 -0
  347. package/dist/view/render/warn.js.map +1 -1
  348. package/dist/view/server/component.d.ts +6 -3
  349. package/dist/view/server/component.js +29 -7
  350. package/dist/view/server/component.js.map +1 -1
  351. package/dist/view/server/index.d.ts +20 -0
  352. package/dist/view/server/index.js +12 -4
  353. package/dist/view/server/index.js.map +1 -1
  354. package/dist/view/server/tags.d.ts +13 -2
  355. package/dist/view/server/tags.js +13 -2
  356. package/dist/view/server/tags.js.map +1 -1
  357. package/dist/view/server/values.d.ts +2 -0
  358. package/dist/view/server/values.js +8 -0
  359. package/dist/view/server/values.js.map +1 -1
  360. package/dist/view/server/writer.d.ts +9 -4
  361. package/dist/view/server/writer.js +33 -18
  362. package/dist/view/server/writer.js.map +1 -1
  363. package/dist/view/template-element.d.ts +7 -0
  364. package/dist/view/template-element.js +25 -5
  365. package/dist/view/template-element.js.map +1 -1
  366. package/dist/view/template.d.ts +10 -2
  367. package/dist/view/template.js +62 -8
  368. package/dist/view/template.js.map +1 -1
  369. package/dist/view/trusted-html.d.ts +6 -0
  370. package/dist/view/trusted-html.js +34 -0
  371. package/dist/view/trusted-html.js.map +1 -0
  372. package/dist/vite.d.ts +38 -31
  373. package/dist/vite.js +198 -31
  374. package/dist/vite.js.map +1 -1
  375. package/package.json +34 -3
  376. package/dist/hooks/labelled-by.d.ts +0 -13
  377. package/dist/hooks/labelled-by.js +0 -51
  378. package/dist/hooks/labelled-by.js.map +0 -1
  379. package/dist/random.d.ts +0 -13
  380. package/dist/random.js +0 -19
  381. package/dist/random.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"tree.js","sourceRoot":"","sources":["../../../src/view/normalize/tree.ts"],"names":[],"mappings":"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","sourcesContent":["// Tree builder for the normalizer (view/01-templates.md \"Normalization\"): turns the tokenizer's\n// tokens into the tree the HTML parser builds for valid markup (WHATWG \"tree construction\":\n// namespaces, void elements, raw text, the leading newline of <pre>/<listing>/<textarea>), so\n// part paths match the browser's DOM. Markup the parser would repair is an error instead of\n// being modelled (rule 7, repairs.ts), as are rules 3, 4, 6, 10, 12 and 13.\nimport { decodeRefs, unquote } from './entities.js';\nimport {\n breaksOutOfForeign,\n contextOf,\n rootContext,\n startRepair,\n textRepair,\n type Context,\n type Ns,\n} from './repairs.js';\nimport { formStateFix, msg, SVG_ONLY, VOID } from './rules.js';\nimport type { Source } from './source.js';\nimport type { AttrToken, ContentMode, Sink, StartTag } from './tokenizer.js';\n\nexport interface ElementNode {\n readonly type: 'el';\n /** Lower-case name, and the name as written. */\n readonly name: string;\n readonly raw: string;\n readonly ns: Ns;\n /** Static and bound attributes; bound names normalized, multi strings decoded. */\n readonly attrs: readonly AttrToken[];\n /** A custom element's static attributes, decoded (server props); undefined otherwise. */\n readonly props: readonly (readonly [string, string])[] | undefined;\n /** No end tag: a void element, or a self-closed SVG/MathML element. */\n readonly empty: boolean;\n readonly children: TreeNode[];\n /** For <template>: the context its first start tag chose. */\n inner?: Context;\n}\n\nexport type TreeNode =\n | ElementNode\n | { readonly type: 'text'; readonly raw: string }\n | { readonly type: 'comment'; readonly raw: string }\n | { readonly type: 'doctype'; readonly raw: string }\n | { readonly type: 'hole'; readonly kind: 'child' | 'text' };\n\nconst RAWTEXT = new Set('script style xmp iframe noembed noframes noscript plaintext'.split(' '));\nconst RCDATA = new Set(['textarea', 'title']);\nconst LEADING_NEWLINE = new Set(['pre', 'listing', 'textarea']);\nconst DOCUMENT = new Set(['html', 'head', 'body']);\n\nfunction integrationPoint(el: ElementNode): boolean {\n if (el.ns === 'svg') return /^(foreignobject|desc|title)$/.test(el.name);\n return el.ns === 'math' && /^(mi|mo|mn|ms|mtext)$/.test(el.name);\n}\n\nexport class TreeBuilder implements Sink {\n readonly root: TreeNode[] = [];\n server = false;\n private readonly stack: ElementNode[] = [];\n private rootCtx: Context | undefined;\n /** The <pre>/<listing>/<textarea> whose first newline the parser drops, if just opened. */\n private fresh: ElementNode | undefined;\n\n constructor(private readonly src: Source) {}\n\n private get children(): TreeNode[] {\n return this.stack.at(-1)?.children ?? this.root;\n }\n\n private context(): { ctx: Context; atRoot: boolean } {\n const top = this.stack.at(-1);\n if (top === undefined) return { ctx: this.rootCtx ?? 'body', atRoot: true };\n if (top.ns !== 'html') return { ctx: 'body', atRoot: false };\n if (top.name === 'template') return { ctx: top.inner ?? 'body', atRoot: true };\n return { ctx: contextOf(top.name), atRoot: false };\n }\n\n private inTemplate(): boolean {\n return this.stack.some((el) => el.ns === 'html' && el.name === 'template');\n }\n\n text(raw: string): void {\n const text = this.fresh !== undefined && raw.startsWith('\\n') ? raw.slice(1) : raw;\n this.fresh = undefined;\n if (text === '') return;\n const { ctx, atRoot } = this.context();\n const repair = textRepair(text, ctx, atRoot);\n if (repair !== undefined) this.src.fail(7, repair);\n this.children.push({ type: 'text', raw: text });\n }\n\n comment(raw: string): void {\n this.fresh = undefined;\n this.children.push({ type: 'comment', raw });\n }\n\n doctype(raw: string): void {\n this.fresh = undefined;\n this.server = true;\n this.children.push({ type: 'doctype', raw });\n }\n\n hole(kind: 'child' | 'text'): void {\n this.fresh = undefined;\n if (this.inTemplate()) this.src.fail(3, msg.inTemplate());\n this.children.push({ type: 'hole', kind });\n }\n\n start(tag: StartTag): ContentMode {\n this.fresh = undefined;\n const { name } = tag;\n const ns = this.namespace(tag);\n if (ns === 'html') this.checkHtml(tag);\n if (this.inTemplate() && tag.attrs.some((a) => a.kind !== 'static')) {\n this.src.fail(3, msg.inTemplate());\n }\n const empty = ns === 'html' ? VOID.has(name) : tag.selfClosing;\n const custom = ns === 'html' && name.includes('-');\n const el: ElementNode = {\n type: 'el',\n name,\n raw: tag.raw,\n ns,\n attrs: this.attributes(tag, ns),\n props: custom ? this.props(tag) : undefined,\n empty,\n children: [],\n };\n this.children.push(el);\n if (empty) return 'data';\n this.stack.push(el);\n if (ns !== 'html') return 'data';\n if (LEADING_NEWLINE.has(name)) this.fresh = el;\n return RAWTEXT.has(name) ? 'rawtext' : RCDATA.has(name) ? 'rcdata' : 'data';\n }\n\n private namespace(tag: StartTag): Ns {\n const parent = this.stack.at(-1);\n if (parent === undefined || parent.ns === 'html' || integrationPoint(parent)) {\n return tag.name === 'svg' ? 'svg' : tag.name === 'math' ? 'math' : 'html';\n }\n if (parent.name === 'annotation-xml' && tag.name === 'svg') return 'svg';\n const fontAttr = tag.attrs.some((a) => /^(color|face|size)$/i.test(a.name));\n if (breaksOutOfForeign(tag.name, fontAttr)) {\n this.src.fail(\n 7,\n msg.repaired(\n `<${tag.name}> inside <${parent.ns}> ends the <${parent.ns}> element`,\n `Put HTML inside <foreignObject>, or move it out of the <${parent.ns}>.`,\n ),\n );\n }\n return parent.ns;\n }\n\n private checkHtml(tag: StartTag): void {\n const { name } = tag;\n if (SVG_ONLY.has(name)) this.src.fail(10, msg.svgOnly(tag.raw));\n if (DOCUMENT.has(name)) this.server = true;\n if (tag.selfClosing && !VOID.has(name)) this.src.fail(6, msg.selfClosing(tag.raw));\n const top = this.stack.at(-1);\n if (top === undefined) this.rootCtx ??= rootContext(name);\n else if (top.ns === 'html' && top.name === 'template') top.inner ??= rootContext(name);\n const { ctx, atRoot } = this.context();\n const hidden = tag.attrs.some(\n (a) =>\n a.kind === 'static' &&\n a.name.toLowerCase() === 'type' &&\n /^[\"']?hidden[\"']?$/i.test(a.value ?? ''),\n );\n const repair = startRepair(name, ctx, atRoot, this.stack, hidden);\n if (repair !== undefined) this.src.fail(7, repair);\n }\n\n /** Bound names lower-cased on HTML elements (not properties); rules 4, 7 (duplicates), 13. */\n private attributes(tag: StartTag, ns: Ns): AttrToken[] {\n const seen = new Set<string>();\n return tag.attrs.map((a) => {\n const lower = ns === 'html' && a.kind !== 'prop' ? a.name.toLowerCase() : a.name;\n if (a.kind === 'prop' && ns === 'html') {\n const fix = formStateFix(tag.name, a.name);\n if (fix !== undefined) this.src.fail(4, msg.formState(tag.name, a.name, fix));\n }\n if (a.kind !== 'prop' && a.kind !== 'hook') {\n const key = ns === 'html' ? lower : a.name;\n if (seen.has(key)) {\n this.src.fail(\n 7,\n msg.repaired(\n `${key} appears twice on <${tag.raw}>, and the parser keeps only the first`,\n `Write it once; to mix static and dynamic text, quote one value: ${key}=\"a \\${…}\".`,\n ),\n );\n }\n seen.add(key);\n }\n if (a.kind === 'static') return a;\n const strings = a.strings?.map((s) => this.decode(s));\n return strings === undefined\n ? { kind: a.kind, name: lower }\n : { kind: a.kind, name: lower, strings };\n });\n }\n\n private props(tag: StartTag): [string, string][] {\n return tag.attrs.flatMap((a) =>\n a.kind === 'static'\n ? [[a.name.toLowerCase(), a.value === null ? '' : this.decode(unquote(a.value))]]\n : [],\n );\n }\n\n private decode(raw: string): string {\n return decodeRefs(raw, (ref) => this.src.fail(13, msg.charRef(ref)));\n }\n\n end(name: string): void {\n this.fresh = undefined;\n const top = this.stack.at(-1);\n if (top?.name === name) {\n this.close(top);\n return;\n }\n if (VOID.has(name) && name !== 'br') return; // ignored by the parser\n const open = this.stack.some((el) => el.name === name);\n this.src.fail(\n 7,\n open && top !== undefined\n ? msg.repaired(\n `</${name}> while <${top.raw}> is still open`,\n `Close </${top.raw}> first (end tags must match their start tags).`,\n )\n : msg.repaired(\n `</${name}> has no matching start tag${name === 'br' || name === 'p' ? `, so the parser creates an empty <${name}>` : ''}`,\n name === 'br' ? 'Write <br>.' : 'Remove it.',\n ),\n );\n }\n\n private close(el: ElementNode): void {\n this.stack.pop();\n const hasText = el.children.some((c) => c.type === 'hole' && c.kind === 'text');\n if (hasText && el.children.length !== 1) this.src.fail(12, msg.textContent(el.raw));\n }\n\n finish(): void {\n for (let el = this.stack.at(-1); el !== undefined; el = this.stack.at(-1)) this.close(el);\n }\n}\n"]}
1
+ {"version":3,"file":"tree.js","sourceRoot":"","sources":["../../../src/view/normalize/tree.ts"],"names":[],"mappings":"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","sourcesContent":["// Tree builder for the normalizer (view/01-templates.md \"Normalization\"): turns the tokenizer's\n// tokens into the tree the HTML parser builds for valid markup (WHATWG \"tree construction\":\n// namespaces, void elements, raw text, the leading newline of <pre>/<listing>/<textarea>), so\n// part paths match the browser's DOM. Markup the parser would repair is an error instead of\n// being modelled (rule 7, repairs.ts), as are rules 3, 4, 6, 10, 12 and 13. An svg template's\n// top level is SVG content, as if inside an <svg> (01 \"svg templates\", svg.ts).\nimport { decodeRefs, unquote } from './entities.js';\nimport {\n breaksOutOfForeign,\n contextOf,\n rootContext,\n startRepair,\n textRepair,\n type Context,\n type Ns,\n} from './repairs.js';\nimport { BOOLEAN_ATTRS, formStateFix, msg, SVG_ONLY, VOID } from './rules.js';\nimport type { Source } from './source.js';\nimport { HTML_ONLY, namespacedAttr, SVG_HTML_POINT, svgAttr } from './svg.js';\nimport type { AttrToken, ContentMode, Sink, StartTag } from './tokenizer.js';\n\nexport interface ElementNode {\n readonly type: 'el';\n /** Lower-case name, and the name as written. */\n readonly name: string;\n readonly raw: string;\n readonly ns: Ns;\n /** Static and bound attributes; bound names normalized, multi strings decoded. */\n readonly attrs: readonly AttrToken[];\n /** A custom element's static attributes, decoded (server props); undefined otherwise. */\n readonly props: readonly (readonly [string, string])[] | undefined;\n /** No end tag: a void element, or a self-closed SVG/MathML element. */\n readonly empty: boolean;\n readonly children: TreeNode[];\n /** For <template>: the context its first start tag chose. */\n inner?: Context;\n}\n\nexport type TreeNode =\n | ElementNode\n | { readonly type: 'text'; readonly raw: string }\n | { readonly type: 'comment'; readonly raw: string }\n | { readonly type: 'doctype'; readonly raw: string }\n | { readonly type: 'hole'; readonly kind: 'child' | 'text' };\n\nconst RAWTEXT = new Set('script style xmp iframe noembed noframes noscript plaintext'.split(' '));\nconst RCDATA = new Set(['textarea', 'title']);\nconst LEADING_NEWLINE = new Set(['pre', 'listing', 'textarea']);\nconst DOCUMENT = new Set(['html', 'head', 'body']);\n\nfunction integrationPoint(el: ElementNode): boolean {\n if (el.ns === 'svg') return SVG_HTML_POINT.test(el.name);\n return el.ns === 'math' && /^(mi|mo|mn|ms|mtext)$/.test(el.name);\n}\n\nexport class TreeBuilder implements Sink {\n readonly root: TreeNode[] = [];\n server = false;\n private readonly stack: ElementNode[] = [];\n private rootCtx: Context | undefined;\n /** The <pre>/<listing>/<textarea> whose first newline the parser drops, if just opened. */\n private fresh: ElementNode | undefined;\n\n /** `svg`: an svg template, whose top level is SVG content (01 \"svg templates\"). */\n constructor(\n private readonly src: Source,\n private readonly svg = false,\n ) {}\n\n private get children(): TreeNode[] {\n return this.stack.at(-1)?.children ?? this.root;\n }\n\n private context(): { ctx: Context; atRoot: boolean } {\n const top = this.stack.at(-1);\n if (top === undefined) return { ctx: this.rootCtx ?? 'body', atRoot: true };\n if (top.ns !== 'html') return { ctx: 'body', atRoot: false };\n if (top.name === 'template') return { ctx: top.inner ?? 'body', atRoot: true };\n return { ctx: contextOf(top.name), atRoot: false };\n }\n\n private inTemplate(): boolean {\n return this.stack.some((el) => el.ns === 'html' && el.name === 'template');\n }\n\n text(raw: string): void {\n const text = this.fresh !== undefined && raw.startsWith('\\n') ? raw.slice(1) : raw;\n this.fresh = undefined;\n if (text === '') return;\n const { ctx, atRoot } = this.context();\n const repair = textRepair(text, ctx, atRoot);\n if (repair !== undefined) this.src.fail(7, repair);\n this.children.push({ type: 'text', raw: text });\n }\n\n comment(raw: string): void {\n this.fresh = undefined;\n this.children.push({ type: 'comment', raw });\n }\n\n doctype(raw: string): void {\n this.fresh = undefined;\n if (this.svg) this.src.fail(10, msg.htmlInSvg('!doctype', true));\n this.server = true;\n this.children.push({ type: 'doctype', raw });\n }\n\n hole(kind: 'child' | 'text'): void {\n this.fresh = undefined;\n if (this.inTemplate()) this.src.fail(3, msg.inTemplate());\n this.children.push({ type: 'hole', kind });\n }\n\n start(tag: StartTag): ContentMode {\n this.fresh = undefined;\n const { name } = tag;\n const ns = this.namespace(tag);\n if (ns === 'html') this.checkHtml(tag);\n if (this.inTemplate() && tag.attrs.some((a) => a.kind !== 'static')) {\n this.src.fail(3, msg.inTemplate());\n }\n const empty = ns === 'html' ? VOID.has(name) : tag.selfClosing;\n const custom = ns === 'html' && name.includes('-');\n const el: ElementNode = {\n type: 'el',\n name,\n raw: tag.raw,\n ns,\n attrs: this.attributes(tag, ns),\n props: custom ? this.props(tag) : undefined,\n empty,\n children: [],\n };\n this.children.push(el);\n if (empty) return 'data';\n this.stack.push(el);\n if (ns !== 'html') return 'data';\n if (LEADING_NEWLINE.has(name)) this.fresh = el;\n return RAWTEXT.has(name) ? 'rawtext' : RCDATA.has(name) ? 'rcdata' : 'data';\n }\n\n private namespace(tag: StartTag): Ns {\n const parent = this.stack.at(-1);\n if (parent === undefined ? !this.svg : parent.ns === 'html' || integrationPoint(parent)) {\n return tag.name === 'svg' ? 'svg' : tag.name === 'math' ? 'math' : 'html';\n }\n // An svg template's top level: SVG content, as inside the <svg> it renders in.\n if (parent === undefined) {\n const fontAttr = tag.attrs.some((a) => /^(color|face|size)$/i.test(a.name));\n if (breaksOutOfForeign(tag.name, fontAttr) || HTML_ONLY.has(tag.name)) {\n this.src.fail(10, msg.htmlInSvg(tag.raw, true));\n }\n return 'svg';\n }\n if (parent.name === 'annotation-xml' && tag.name === 'svg') return 'svg';\n if (parent.ns === 'svg' && HTML_ONLY.has(tag.name)) {\n this.src.fail(10, msg.htmlInSvg(tag.raw, false));\n }\n const fontAttr = tag.attrs.some((a) => /^(color|face|size)$/i.test(a.name));\n if (breaksOutOfForeign(tag.name, fontAttr)) {\n this.src.fail(\n 7,\n msg.repaired(\n `<${tag.name}> inside <${parent.ns}> ends the <${parent.ns}> element`,\n `Put HTML inside <foreignObject>, or move it out of the <${parent.ns}>.`,\n ),\n );\n }\n return parent.ns;\n }\n\n private checkHtml(tag: StartTag): void {\n const { name } = tag;\n if (SVG_ONLY.has(name)) this.src.fail(10, msg.svgOnly(tag.raw));\n if (DOCUMENT.has(name)) this.server = true;\n if (tag.selfClosing && !VOID.has(name)) this.src.fail(6, msg.selfClosing(tag.raw));\n const top = this.stack.at(-1);\n if (top === undefined) this.rootCtx ??= rootContext(name);\n else if (top.ns === 'html' && top.name === 'template') top.inner ??= rootContext(name);\n const { ctx, atRoot } = this.context();\n const hidden = tag.attrs.some(\n (a) =>\n a.kind === 'static' &&\n a.name.toLowerCase() === 'type' &&\n /^[\"']?hidden[\"']?$/i.test(a.value ?? ''),\n );\n const repair = startRepair(name, ctx, atRoot, this.stack, hidden);\n if (repair !== undefined) this.src.fail(7, repair);\n }\n\n /**\n * Bound names as the parser spells them (not properties): lower case on HTML elements, SVG's\n * camelCase on SVG elements (svg.ts); rules 4, 7 (duplicates), 10 (namespaced), 13, 14 (boolean attributes). A\n * static `style` gets its decoded value (`css`): the client applies it as a part (emit.ts).\n */\n private attributes(tag: StartTag, ns: Ns): AttrToken[] {\n const seen = new Set<string>();\n // A nested <template>'s content is out of the parts' reach: its static styles stay.\n const reach = !this.inTemplate();\n return tag.attrs.map((a) => {\n const name =\n a.kind === 'prop' || ns === 'math'\n ? a.name\n : ns === 'html'\n ? a.name.toLowerCase()\n : svgAttr(a.name);\n if (a.kind === 'prop' && ns === 'html') {\n const fix = formStateFix(tag.name, a.name);\n if (fix !== undefined) this.src.fail(4, msg.formState(tag.name, a.name, fix));\n }\n // Dialog and popover state is bound with `?`, on the element that can open (02).\n if (ns === 'html' && (name === 'modal' || name === 'popover-open') && a.kind !== 'prop') {\n const fits =\n name === 'modal'\n ? tag.name === 'dialog'\n : tag.attrs.some((b) => b.name.toLowerCase() === 'popover');\n if (a.kind !== 'bool' || !fits) this.src.fail(4, msg.toggle(tag.name, name));\n }\n if (\n a.kind === 'attr' &&\n ns === 'html' &&\n !tag.name.includes('-') &&\n BOOLEAN_ATTRS.has(name)\n ) {\n this.src.fail(14, msg.booleanAttr(tag.name, name));\n }\n if ((a.kind === 'attr' || a.kind === 'bool') && ns !== 'html' && namespacedAttr(a.name)) {\n this.src.fail(10, msg.namespacedAttr(a.name));\n }\n if (a.kind !== 'prop' && a.kind !== 'hook') {\n const key = ns === 'math' ? a.name : a.name.toLowerCase();\n if (seen.has(key)) {\n this.src.fail(\n 7,\n msg.repaired(\n `${key} appears twice on <${tag.raw}>, and the parser keeps only the first`,\n `Write it once; to mix static and dynamic text, quote one value: ${key}=\"a \\${…}\".`,\n ),\n );\n }\n seen.add(key);\n }\n if (a.kind === 'static') {\n if (!reach || a.name.toLowerCase() !== 'style') return a;\n return { ...a, css: a.value === null ? '' : this.decode(unquote(a.value)) };\n }\n const strings = a.strings?.map((s) => this.decode(s));\n return strings === undefined ? { kind: a.kind, name } : { kind: a.kind, name, strings };\n });\n }\n\n private props(tag: StartTag): [string, string][] {\n return tag.attrs.flatMap((a) =>\n a.kind === 'static'\n ? [[a.name.toLowerCase(), a.value === null ? '' : this.decode(unquote(a.value))]]\n : [],\n );\n }\n\n private decode(raw: string): string {\n return decodeRefs(raw, (ref) => this.src.fail(13, msg.charRef(ref)));\n }\n\n end(name: string): void {\n this.fresh = undefined;\n const top = this.stack.at(-1);\n if (top?.name === name) {\n this.close(top);\n return;\n }\n if (VOID.has(name) && name !== 'br') return; // ignored by the parser\n const open = this.stack.some((el) => el.name === name);\n this.src.fail(\n 7,\n open && top !== undefined\n ? msg.repaired(\n `</${name}> while <${top.raw}> is still open`,\n `Close </${top.raw}> first (end tags must match their start tags).`,\n )\n : msg.repaired(\n `</${name}> has no matching start tag${name === 'br' || name === 'p' ? `, so the parser creates an empty <${name}>` : ''}`,\n name === 'br' ? 'Write <br>.' : 'Remove it.',\n ),\n );\n }\n\n private close(el: ElementNode): void {\n this.stack.pop();\n const hasText = el.children.some((c) => c.type === 'hole' && c.kind === 'text');\n if (hasText && el.children.length !== 1) this.src.fail(12, msg.textContent(el.raw));\n }\n\n finish(): void {\n for (let el = this.stack.at(-1); el !== undefined; el = this.stack.at(-1)) this.close(el);\n }\n}\n"]}
@@ -8,7 +8,10 @@ export declare const CHILD_SOLE = 1;
8
8
  export declare const CHILD_BEFORE = 2;
9
9
  /** `[ATTR_PART, path, name]`: `name=${v}`. */
10
10
  export declare const ATTR_PART = 3;
11
- /** `[MULTI_PART, path, name, strings]`: `name="a ${x} b"`. */
11
+ /**
12
+ * `[MULTI_PART, path, name, strings]`: `name="a ${x} b"`; with one string and no values, a
13
+ * static `style` attribute the client applies through the CSSOM (01 "Normalization").
14
+ */
12
15
  export declare const MULTI_PART = 4;
13
16
  /** `[BOOL_PART, path, name]`: `?name=${v}`. */
14
17
  export declare const BOOL_PART = 5;
@@ -47,7 +50,8 @@ export type PartSpec = readonly [
47
50
  * - `child`: the value per 02's child table. Anchors are already in the next static string.
48
51
  * `in` is the parent element's local name (absent at the template root, where the parent is
49
52
  * wherever the instance is written): the development check for text the parser would move
50
- * out of table structure needs it.
53
+ * out of table structure needs it. `svg` is set when the parent is SVG content (an SVG
54
+ * element other than <foreignObject>, <desc>, <title>), where svg templates may render.
51
55
  * - `text`: the value as escaped text (`<textarea>`, `<title>` content).
52
56
  * - `attr`: ` name="escaped"`, or nothing for null/undefined/nothing. With `strings`, the
53
57
  * pieces and `strings.length - 1` values are joined first (`nothing` in any piece: nothing).
@@ -62,11 +66,13 @@ export type PartSpec = readonly [
62
66
  * - `close`: write `</tag>`. Everything between `openEnd` and `close` is the element's children.
63
67
  *
64
68
  * Joining the strings with every op written empty (`open` as `html`, `openEnd` as `>`, `close`
65
- * as `</tag>`) gives exactly the template's `html`.
69
+ * as `</tag>`) gives exactly the template's `html`, plus its static `style` attributes, which
70
+ * the client's `html` leaves to the part table.
66
71
  */
67
72
  export type Segment = string | {
68
73
  readonly k: 'child';
69
74
  readonly in?: string;
75
+ readonly svg?: true;
70
76
  } | {
71
77
  readonly k: 'text';
72
78
  } | {
@@ -98,7 +104,10 @@ export interface TemplateObject {
98
104
  * production client (01 "Template ids"): there the renderer compares templates by identity.
99
105
  */
100
106
  readonly id?: string;
101
- /** Normalized template HTML for the client: bound attributes removed, anchors added. */
107
+ /**
108
+ * Normalized template HTML for the client: bound attributes and static `style` attributes
109
+ * (zero-hole multi-attribute parts) removed, anchors added.
110
+ */
102
111
  readonly html: string;
103
112
  readonly parts: readonly PartSpec[];
104
113
  /**
@@ -106,11 +115,22 @@ export interface TemplateObject {
106
115
  * server-only. Absent otherwise.
107
116
  */
108
117
  readonly server?: true;
118
+ /**
119
+ * `true` for an svg template (`` svg`…` ``, 01 "svg templates"): its HTML is SVG content,
120
+ * parsed inside an <svg>. Absent otherwise.
121
+ */
122
+ readonly svg?: true;
109
123
  /**
110
124
  * Server writing plan. Absent from client-compiled template objects (the compiler drops it),
111
125
  * so the client renderer never reads it; the runtime preparer and server builds keep it.
112
126
  */
113
127
  readonly segments?: readonly Segment[];
128
+ /**
129
+ * Server only, like `segments`: the decoded values of the template's non-empty static
130
+ * `style` attributes, deduplicated, so a server render can collect every `style` value it
131
+ * writes for a CSP (ADR 0020) without parsing its string segments. Absent when there are none.
132
+ */
133
+ readonly staticStyles?: readonly string[];
114
134
  /** Development only: file:line:column of the call site. */
115
135
  readonly loc?: string;
116
136
  }
@@ -13,7 +13,10 @@ export const CHILD_SOLE = 1;
13
13
  export const CHILD_BEFORE = 2;
14
14
  /** `[ATTR_PART, path, name]`: `name=${v}`. */
15
15
  export const ATTR_PART = 3;
16
- /** `[MULTI_PART, path, name, strings]`: `name="a ${x} b"`. */
16
+ /**
17
+ * `[MULTI_PART, path, name, strings]`: `name="a ${x} b"`; with one string and no values, a
18
+ * static `style` attribute the client applies through the CSSOM (01 "Normalization").
19
+ */
17
20
  export const MULTI_PART = 4;
18
21
  /** `[BOOL_PART, path, name]`: `?name=${v}`. */
19
22
  export const BOOL_PART = 5;
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/view/normalize/types.ts"],"names":[],"mappings":"AAAA,sFAAsF;AACtF,iGAAiG;AACjG,6FAA6F;AAC7F,yFAAyF;AACzF,0DAA0D;AAK1D,0FAA0F;AAC1F,sFAAsF;AACtF,+EAA+E;AAC/E,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAC;AAC3B,+FAA+F;AAC/F,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,CAAC;AAC5B,8FAA8F;AAC9F,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC;AAC9B,8CAA8C;AAC9C,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAC;AAC3B,8DAA8D;AAC9D,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,CAAC;AAC5B,+CAA+C;AAC/C,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAC;AAC3B,+CAA+C;AAC/C,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAC;AAC3B,wDAAwD;AACxD,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAC;AAC3B,6EAA6E;AAC7E,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAC","sourcesContent":["// The template object (view/01-templates.md \"The template object\") and its part table\n// (view/02-bindings.md \"Hole kinds\"). Plain JSON data, no functions: the Vite compiler (Phase 6)\n// emits it as code, the browser instantiates from it, and the server writes from it. Compact\n// on purpose (numeric part kinds, tuples, `server` only when true), so the code compiled\n// client builds carry stays small with nothing to decode.\n\n/** Child-index path from the template's content root (`[]` is the root itself). */\nexport type Path = readonly number[];\n\n// Part kinds: the first entry of a PartSpec tuple. Small numbers, because compiled client\n// builds carry every template's part table as code (view/01-templates.md \"Compiled\").\n/** `[CHILD_END, path]`: a child hole that inserts at the end of its parent. */\nexport const CHILD_END = 0;\n/** `[CHILD_SOLE, path]`: a child hole that is its parent's only child node (so at its end). */\nexport const CHILD_SOLE = 1;\n/** `[CHILD_BEFORE, path, ref]`: a child hole that inserts before the parent's child `ref`. */\nexport const CHILD_BEFORE = 2;\n/** `[ATTR_PART, path, name]`: `name=${v}`. */\nexport const ATTR_PART = 3;\n/** `[MULTI_PART, path, name, strings]`: `name=\"a ${x} b\"`. */\nexport const MULTI_PART = 4;\n/** `[BOOL_PART, path, name]`: `?name=${v}`. */\nexport const BOOL_PART = 5;\n/** `[PROP_PART, path, name]`: `.name=${v}`. */\nexport const PROP_PART = 6;\n/** `[HOOK_PART, path]`: `${hook(…)}` in a start tag. */\nexport const HOOK_PART = 7;\n/** `[TEXT_PART, path]`: the whole content of a `<textarea>` or `<title>`. */\nexport const TEXT_PART = 8;\n\n/**\n * One entry per binding, in source order: a tuple whose first entry is its kind (above), whose\n * second is a path, then the kind's own fields. Multi-attributes take several values.\n *\n * - Child holes: `path` leads to the parent element (`[]`: the template root). `ref` is the\n * index, among the parent's child nodes in the template DOM, of the node the part inserts\n * before: the next static element or comment, or the anchor comment the normalizer emitted.\n * Without `ref` the hole inserts at the end of the parent (CHILD_END, CHILD_SOLE).\n * - Attributes, booleans, properties: `path` leads to the element; `name` is the attribute or\n * property name. A multi-attribute's `strings` are its static pieces (character references\n * already decoded): `strings.length - 1` values are joined with them.\n * - Hooks: `path` leads to the element. Text: `path` leads to the `<textarea>`/`<title>`.\n */\nexport type PartSpec =\n | readonly [\n kind: typeof CHILD_END | typeof CHILD_SOLE | typeof HOOK_PART | typeof TEXT_PART,\n path: Path,\n ]\n | readonly [kind: typeof CHILD_BEFORE, path: Path, ref: number]\n | readonly [\n kind: typeof ATTR_PART | typeof BOOL_PART | typeof PROP_PART,\n path: Path,\n name: string,\n ]\n | readonly [kind: typeof MULTI_PART, path: Path, name: string, strings: readonly string[]];\n\n/**\n * What the server renderer writes (view/06-server.md), in order, with no tokenizing. Strings\n * are static markup, written verbatim. Each hole op takes the next value(s); the custom-element\n * ops take none and mark where a component's start tag ends and its end tag begins.\n *\n * - `child`: the value per 02's child table. Anchors are already in the next static string.\n * `in` is the parent element's local name (absent at the template root, where the parent is\n * wherever the instance is written): the development check for text the parser would move\n * out of table structure needs it.\n * - `text`: the value as escaped text (`<textarea>`, `<title>` content).\n * - `attr`: ` name=\"escaped\"`, or nothing for null/undefined/nothing. With `strings`, the\n * pieces and `strings.length - 1` values are joined first (`nothing` in any piece: nothing).\n * - `bool`: ` name` when the value is truthy.\n * - `prop`: nothing in markup; a prop when the element is a Gyral component.\n * - `hook`: the hook's `server(args)` attributes.\n * - `open`: a custom element's start tag begins. `html` is `<tag` plus its static attributes,\n * written verbatim; `attrs` are the same static attributes, decoded (props for a component).\n * The element's attribute ops follow.\n * - `openEnd`: write `>`. A component writes its seed attribute first, and its shadow root\n * after.\n * - `close`: write `</tag>`. Everything between `openEnd` and `close` is the element's children.\n *\n * Joining the strings with every op written empty (`open` as `html`, `openEnd` as `>`, `close`\n * as `</tag>`) gives exactly the template's `html`.\n */\nexport type Segment =\n | string\n | { readonly k: 'child'; readonly in?: string }\n | { readonly k: 'text' }\n | { readonly k: 'attr'; readonly name: string; readonly strings?: readonly string[] }\n | { readonly k: 'bool'; readonly name: string }\n | { readonly k: 'prop'; readonly name: string }\n | { readonly k: 'hook' }\n | {\n readonly k: 'open';\n readonly tag: string;\n readonly html: string;\n readonly attrs: readonly (readonly [name: string, value: string])[];\n }\n | { readonly k: 'openEnd' }\n | { readonly k: 'close'; readonly tag: string };\n\nexport interface TemplateObject {\n /**\n * Deterministic id of the normalized strings (id.ts). Absent from objects compiled for a\n * production client (01 \"Template ids\"): there the renderer compares templates by identity.\n */\n readonly id?: string;\n /** Normalized template HTML for the client: bound attributes removed, anchors added. */\n readonly html: string;\n readonly parts: readonly PartSpec[];\n /**\n * `true` when it contains document-level tags (<!doctype>, <html>, <head>, <body>):\n * server-only. Absent otherwise.\n */\n readonly server?: true;\n /**\n * Server writing plan. Absent from client-compiled template objects (the compiler drops it),\n * so the client renderer never reads it; the runtime preparer and server builds keep it.\n */\n readonly segments?: readonly Segment[];\n /** Development only: file:line:column of the call site. */\n readonly loc?: string;\n}\n\n/** What the normalizer returns: a template object that always has its id. */\nexport type NormalizedTemplate = TemplateObject & { readonly id: string };\n\n/**\n * The DOM the browser must build from `html`, for the runtime preparer's check (prepare.ts):\n * `'#text'`, `'#comment'`, or `[localName (lower case), children]`.\n */\nexport type ShapeNode = '#text' | '#comment' | readonly [name: string, children: Shape];\nexport type Shape = readonly ShapeNode[];\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/view/normalize/types.ts"],"names":[],"mappings":"AAAA,sFAAsF;AACtF,iGAAiG;AACjG,6FAA6F;AAC7F,yFAAyF;AACzF,0DAA0D;AAK1D,0FAA0F;AAC1F,sFAAsF;AACtF,+EAA+E;AAC/E,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAC;AAC3B,+FAA+F;AAC/F,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,CAAC;AAC5B,8FAA8F;AAC9F,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC;AAC9B,8CAA8C;AAC9C,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAC;AAC3B;;;GAGG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,CAAC;AAC5B,+CAA+C;AAC/C,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAC;AAC3B,+CAA+C;AAC/C,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAC;AAC3B,wDAAwD;AACxD,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAC;AAC3B,6EAA6E;AAC7E,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAC","sourcesContent":["// The template object (view/01-templates.md \"The template object\") and its part table\n// (view/02-bindings.md \"Hole kinds\"). Plain JSON data, no functions: the Vite compiler (Phase 6)\n// emits it as code, the browser instantiates from it, and the server writes from it. Compact\n// on purpose (numeric part kinds, tuples, `server` only when true), so the code compiled\n// client builds carry stays small with nothing to decode.\n\n/** Child-index path from the template's content root (`[]` is the root itself). */\nexport type Path = readonly number[];\n\n// Part kinds: the first entry of a PartSpec tuple. Small numbers, because compiled client\n// builds carry every template's part table as code (view/01-templates.md \"Compiled\").\n/** `[CHILD_END, path]`: a child hole that inserts at the end of its parent. */\nexport const CHILD_END = 0;\n/** `[CHILD_SOLE, path]`: a child hole that is its parent's only child node (so at its end). */\nexport const CHILD_SOLE = 1;\n/** `[CHILD_BEFORE, path, ref]`: a child hole that inserts before the parent's child `ref`. */\nexport const CHILD_BEFORE = 2;\n/** `[ATTR_PART, path, name]`: `name=${v}`. */\nexport const ATTR_PART = 3;\n/**\n * `[MULTI_PART, path, name, strings]`: `name=\"a ${x} b\"`; with one string and no values, a\n * static `style` attribute the client applies through the CSSOM (01 \"Normalization\").\n */\nexport const MULTI_PART = 4;\n/** `[BOOL_PART, path, name]`: `?name=${v}`. */\nexport const BOOL_PART = 5;\n/** `[PROP_PART, path, name]`: `.name=${v}`. */\nexport const PROP_PART = 6;\n/** `[HOOK_PART, path]`: `${hook(…)}` in a start tag. */\nexport const HOOK_PART = 7;\n/** `[TEXT_PART, path]`: the whole content of a `<textarea>` or `<title>`. */\nexport const TEXT_PART = 8;\n\n/**\n * One entry per binding, in source order: a tuple whose first entry is its kind (above), whose\n * second is a path, then the kind's own fields. Multi-attributes take several values.\n *\n * - Child holes: `path` leads to the parent element (`[]`: the template root). `ref` is the\n * index, among the parent's child nodes in the template DOM, of the node the part inserts\n * before: the next static element or comment, or the anchor comment the normalizer emitted.\n * Without `ref` the hole inserts at the end of the parent (CHILD_END, CHILD_SOLE).\n * - Attributes, booleans, properties: `path` leads to the element; `name` is the attribute or\n * property name. A multi-attribute's `strings` are its static pieces (character references\n * already decoded): `strings.length - 1` values are joined with them.\n * - Hooks: `path` leads to the element. Text: `path` leads to the `<textarea>`/`<title>`.\n */\nexport type PartSpec =\n | readonly [\n kind: typeof CHILD_END | typeof CHILD_SOLE | typeof HOOK_PART | typeof TEXT_PART,\n path: Path,\n ]\n | readonly [kind: typeof CHILD_BEFORE, path: Path, ref: number]\n | readonly [\n kind: typeof ATTR_PART | typeof BOOL_PART | typeof PROP_PART,\n path: Path,\n name: string,\n ]\n | readonly [kind: typeof MULTI_PART, path: Path, name: string, strings: readonly string[]];\n\n/**\n * What the server renderer writes (view/06-server.md), in order, with no tokenizing. Strings\n * are static markup, written verbatim. Each hole op takes the next value(s); the custom-element\n * ops take none and mark where a component's start tag ends and its end tag begins.\n *\n * - `child`: the value per 02's child table. Anchors are already in the next static string.\n * `in` is the parent element's local name (absent at the template root, where the parent is\n * wherever the instance is written): the development check for text the parser would move\n * out of table structure needs it. `svg` is set when the parent is SVG content (an SVG\n * element other than <foreignObject>, <desc>, <title>), where svg templates may render.\n * - `text`: the value as escaped text (`<textarea>`, `<title>` content).\n * - `attr`: ` name=\"escaped\"`, or nothing for null/undefined/nothing. With `strings`, the\n * pieces and `strings.length - 1` values are joined first (`nothing` in any piece: nothing).\n * - `bool`: ` name` when the value is truthy.\n * - `prop`: nothing in markup; a prop when the element is a Gyral component.\n * - `hook`: the hook's `server(args)` attributes.\n * - `open`: a custom element's start tag begins. `html` is `<tag` plus its static attributes,\n * written verbatim; `attrs` are the same static attributes, decoded (props for a component).\n * The element's attribute ops follow.\n * - `openEnd`: write `>`. A component writes its seed attribute first, and its shadow root\n * after.\n * - `close`: write `</tag>`. Everything between `openEnd` and `close` is the element's children.\n *\n * Joining the strings with every op written empty (`open` as `html`, `openEnd` as `>`, `close`\n * as `</tag>`) gives exactly the template's `html`, plus its static `style` attributes, which\n * the client's `html` leaves to the part table.\n */\nexport type Segment =\n | string\n | { readonly k: 'child'; readonly in?: string; readonly svg?: true }\n | { readonly k: 'text' }\n | { readonly k: 'attr'; readonly name: string; readonly strings?: readonly string[] }\n | { readonly k: 'bool'; readonly name: string }\n | { readonly k: 'prop'; readonly name: string }\n | { readonly k: 'hook' }\n | {\n readonly k: 'open';\n readonly tag: string;\n readonly html: string;\n readonly attrs: readonly (readonly [name: string, value: string])[];\n }\n | { readonly k: 'openEnd' }\n | { readonly k: 'close'; readonly tag: string };\n\nexport interface TemplateObject {\n /**\n * Deterministic id of the normalized strings (id.ts). Absent from objects compiled for a\n * production client (01 \"Template ids\"): there the renderer compares templates by identity.\n */\n readonly id?: string;\n /**\n * Normalized template HTML for the client: bound attributes and static `style` attributes\n * (zero-hole multi-attribute parts) removed, anchors added.\n */\n readonly html: string;\n readonly parts: readonly PartSpec[];\n /**\n * `true` when it contains document-level tags (<!doctype>, <html>, <head>, <body>):\n * server-only. Absent otherwise.\n */\n readonly server?: true;\n /**\n * `true` for an svg template (`` svg`…` ``, 01 \"svg templates\"): its HTML is SVG content,\n * parsed inside an <svg>. Absent otherwise.\n */\n readonly svg?: true;\n /**\n * Server writing plan. Absent from client-compiled template objects (the compiler drops it),\n * so the client renderer never reads it; the runtime preparer and server builds keep it.\n */\n readonly segments?: readonly Segment[];\n /**\n * Server only, like `segments`: the decoded values of the template's non-empty static\n * `style` attributes, deduplicated, so a server render can collect every `style` value it\n * writes for a CSP (ADR 0020) without parsing its string segments. Absent when there are none.\n */\n readonly staticStyles?: readonly string[];\n /** Development only: file:line:column of the call site. */\n readonly loc?: string;\n}\n\n/** What the normalizer returns: a template object that always has its id. */\nexport type NormalizedTemplate = TemplateObject & { readonly id: string };\n\n/**\n * The DOM the browser must build from `html`, for the runtime preparer's check (prepare.ts):\n * `'#text'`, `'#comment'`, or `[localName (lower case), children]`.\n */\nexport type ShapeNode = '#text' | '#comment' | readonly [name: string, children: Shape];\nexport type Shape = readonly ShapeNode[];\n"]}
@@ -5,7 +5,7 @@
5
5
  // Rules:
6
6
  // - Whitespace-only text that contains a newline is removed when it sits next to a template
7
7
  // edge, a block-level tag (head-only tags count: <head>, <meta>, <link>, <base>, <title>),
8
- // or the inside edge of a <button>/<select> (CSS never renders it there). Inside <head>,
8
+ // or the inside edge of a <button>/<select>/<svg> (never rendered there). Inside <head>,
9
9
  // whitespace-only text is always removed, newline or not, between holes too: nothing there
10
10
  // renders. Between two inline neighbours (phrasing elements, custom elements, holes,
11
11
  // comments) it collapses to one space.
@@ -30,9 +30,10 @@ const RAW_TEXT = new Set(['script', 'style', 'textarea', 'title']);
30
30
  const PRESERVE = 'pre';
31
31
  /**
32
32
  * Inline-block controls: they sit inline among their neighbours, but whitespace at the start or
33
- * end of their own content is never rendered (it is at the edge of their own line box).
33
+ * end of their own content is never rendered (it is at the edge of their own line box). Same
34
+ * for <svg>: SVG content renders no text outside its text elements.
34
35
  */
35
- const INLINE_BOX = new Set(['button', 'select']);
36
+ const INLINE_BOX = new Set(['button', 'select', 'svg']);
36
37
  /**
37
38
  * The edge a tag makes for the text next to it. `inside` is true when the text is inside the
38
39
  * element (after its start tag, or before its end tag).
@@ -1 +1 @@
1
- {"version":3,"file":"whitespace.js","sourceRoot":"","sources":["../../../src/view/normalize/whitespace.ts"],"names":[],"mappings":"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","sourcesContent":["// Whitespace minification for templates (view/01-templates.md \"Whitespace\", ADR 0016 addendum).\n// Moved from core's template-whitespace.ts (Gyral's own design) into the view layer's\n// normalizer, so the compiler, the runtime preparer and the server minify identically.\n//\n// Rules:\n// - Whitespace-only text that contains a newline is removed when it sits next to a template\n// edge, a block-level tag (head-only tags count: <head>, <meta>, <link>, <base>, <title>),\n// or the inside edge of a <button>/<select> (CSS never renders it there). Inside <head>,\n// whitespace-only text is always removed, newline or not, between holes too: nothing there\n// renders. Between two inline neighbours (phrasing elements, custom elements, holes,\n// comments) it collapses to one space.\n// - Other runs of whitespace in text collapse to one space; a leading or trailing run with a\n// newline next to one of those edges is removed.\n// - <pre>, <textarea>, <script>, <style> and <title> contents, tags and attribute values,\n// and comments are copied unchanged. Holes never move: the result has the same number of\n// strings.\n// The function is idempotent: minifying minified strings changes nothing.\n\n/** Elements whose box is block-level (or never laid out inline) by default. */\nconst BLOCK = new Set(\n (\n 'address article aside blockquote body caption col colgroup datalist dd details dialog div ' +\n 'dl dt fieldset figcaption figure footer form h1 h2 h3 h4 h5 h6 head header hgroup hr html ' +\n 'legend li main menu nav ol optgroup option p pre search section select summary table tbody ' +\n 'td tfoot th thead tr ul ' +\n // Head-only elements: never rendered at all, so never inline.\n 'base link meta title ' +\n // SVG containers and shapes: whitespace between them is never rendered.\n 'circle clippath defs ellipse g line lineargradient marker mask path pattern polygon ' +\n 'polyline radialgradient rect stop symbol use'\n ).split(' '),\n);\n\n/** Elements whose text content is copied verbatim (whitespace is meaningful or raw text). */\nconst RAW_TEXT = new Set(['script', 'style', 'textarea', 'title']);\nconst PRESERVE = 'pre';\n\n/** What sits on one side of a text chunk. */\ntype Edge = 'template' | 'inline' | 'block';\n\n/**\n * Inline-block controls: they sit inline among their neighbours, but whitespace at the start or\n * end of their own content is never rendered (it is at the edge of their own line box).\n */\nconst INLINE_BOX = new Set(['button', 'select']);\n\n/**\n * The edge a tag makes for the text next to it. `inside` is true when the text is inside the\n * element (after its start tag, or before its end tag).\n */\nfunction edgeOfTag(name: string, inside: boolean): Edge {\n const lower = name.toLowerCase();\n if (BLOCK.has(lower)) return 'block';\n return inside && INLINE_BOX.has(lower) ? 'block' : 'inline';\n}\n\nconst WS = /^[ \\t\\n\\r\\f]*$/;\nconst RUN = /[ \\t\\n\\r\\f]+/g;\n\n/** `head`: the text is inside `<head>`, which is never rendered. */\nfunction minifyChunk(text: string, left: Edge, right: Edge, head: boolean): string {\n if (text === '') return text;\n if (WS.test(text)) {\n const removable =\n head ||\n (/[\\n\\r]/.test(text) &&\n (left === 'template' || right === 'template' || left === 'block' || right === 'block'));\n return removable ? '' : ' ';\n }\n // Mixed text: a leading or trailing run with a newline next to a removable edge goes too.\n const dropStart = left !== 'inline' && /^[ \\t\\f]*[\\n\\r]/.test(text);\n const dropEnd = right !== 'inline' && /[\\n\\r][ \\t\\n\\r\\f]*$/.test(text);\n let body = text.replace(RUN, ' ');\n if (dropStart) body = body.replace(/^ /, '');\n if (dropEnd) body = body.replace(/ $/, '');\n return body;\n}\n\nconst Mode = { Text: 0, Tag: 1, Comment: 2, RawText: 3 } as const;\ntype Mode = (typeof Mode)[keyof typeof Mode];\n\ninterface Scan {\n mode: Mode;\n /** Quote char while inside an attribute value in a tag, else ''. */\n quote: string;\n /** Name of the tag being read (lower case), and whether it is a closing tag. */\n tagName: string;\n closing: boolean;\n /** Raw-text element we are inside (its contents are copied verbatim). */\n rawName: string;\n /** Depth of open <pre> elements: text is copied verbatim while > 0. */\n preDepth: number;\n /** Inside <head> (until </head> or <body>). */\n head: boolean;\n /** Edge type of the boundary before the current text chunk. */\n left: Edge;\n}\n\nconst TAG_START = /^<(\\/?)([A-Za-z!?][^\\s/>]*)/;\n\n/** Minify one segment, carrying the HTML scan state across bindings. */\nfunction minifySegment(segment: string, state: Scan, last: boolean): string {\n let out = '';\n let chunk = '';\n const flushText = (right: Edge): void => {\n out += state.preDepth > 0 ? chunk : minifyChunk(chunk, state.left, right, state.head);\n chunk = '';\n };\n let i = 0;\n while (i < segment.length) {\n const ch = segment.charAt(i);\n if (state.mode === Mode.Comment) {\n if (segment.startsWith('-->', i)) {\n out += '-->';\n i += 3;\n state.mode = Mode.Text;\n state.left = 'inline';\n } else {\n out += ch;\n i += 1;\n }\n continue;\n }\n if (state.mode === Mode.RawText) {\n const close = `</${state.rawName}`;\n if (segment.slice(i, i + close.length).toLowerCase() === close) {\n state.mode = Mode.Text;\n state.left = 'inline';\n continue; // the closing tag is read in Text mode\n }\n out += ch;\n i += 1;\n continue;\n }\n if (state.mode === Mode.Tag) {\n out += ch;\n i += 1;\n if (state.quote !== '') {\n if (ch === state.quote) state.quote = '';\n } else if (ch === '\"' || ch === \"'\") {\n state.quote = ch;\n } else if (ch === '>') {\n endTag(state, out.endsWith('/>'));\n }\n continue;\n }\n // Text mode.\n if (ch === '<' && segment.startsWith('<!--', i)) {\n flushText('inline');\n state.mode = Mode.Comment;\n out += '<!--';\n i += 4;\n continue;\n }\n const tag = ch === '<' ? TAG_START.exec(segment.slice(i)) : null;\n if (tag !== null) {\n const name = (tag[2] ?? '').toLowerCase();\n const closing = tag[1] === '/';\n flushText(edgeOfTag(name, closing));\n state.closing = closing;\n state.tagName = name;\n state.mode = Mode.Tag;\n out += tag[0];\n i += tag[0].length;\n continue;\n }\n chunk += ch;\n i += 1;\n }\n if (state.mode === Mode.Text) {\n flushText(last ? 'template' : 'inline');\n state.left = 'inline'; // the next segment starts after a binding\n }\n return out;\n}\n\nfunction endTag(state: Scan, selfClosing: boolean): void {\n const name = state.tagName;\n state.mode = Mode.Text;\n state.left = edgeOfTag(name, !state.closing && !selfClosing);\n if (name === 'head' && !selfClosing) state.head = !state.closing;\n if (name === 'body') state.head = false;\n if (name === PRESERVE) {\n if (state.closing) state.preDepth = Math.max(0, state.preDepth - 1);\n else if (!selfClosing) state.preDepth += 1;\n }\n if (!state.closing && !selfClosing && RAW_TEXT.has(name)) {\n state.mode = Mode.RawText;\n state.rawName = name;\n }\n}\n\n/** Minified copy of template strings (same length, bindings unmoved). Idempotent. */\nexport function minifyStrings(strings: readonly string[]): string[] {\n const state: Scan = {\n mode: Mode.Text,\n quote: '',\n tagName: '',\n closing: false,\n rawName: '',\n preDepth: 0,\n head: false,\n left: 'template',\n };\n return strings.map((segment, index) =>\n minifySegment(segment, state, index === strings.length - 1),\n );\n}\n"]}
1
+ {"version":3,"file":"whitespace.js","sourceRoot":"","sources":["../../../src/view/normalize/whitespace.ts"],"names":[],"mappings":"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","sourcesContent":["// Whitespace minification for templates (view/01-templates.md \"Whitespace\", ADR 0016 addendum).\n// Moved from core's template-whitespace.ts (Gyral's own design) into the view layer's\n// normalizer, so the compiler, the runtime preparer and the server minify identically.\n//\n// Rules:\n// - Whitespace-only text that contains a newline is removed when it sits next to a template\n// edge, a block-level tag (head-only tags count: <head>, <meta>, <link>, <base>, <title>),\n// or the inside edge of a <button>/<select>/<svg> (never rendered there). Inside <head>,\n// whitespace-only text is always removed, newline or not, between holes too: nothing there\n// renders. Between two inline neighbours (phrasing elements, custom elements, holes,\n// comments) it collapses to one space.\n// - Other runs of whitespace in text collapse to one space; a leading or trailing run with a\n// newline next to one of those edges is removed.\n// - <pre>, <textarea>, <script>, <style> and <title> contents, tags and attribute values,\n// and comments are copied unchanged. Holes never move: the result has the same number of\n// strings.\n// The function is idempotent: minifying minified strings changes nothing.\n\n/** Elements whose box is block-level (or never laid out inline) by default. */\nconst BLOCK = new Set(\n (\n 'address article aside blockquote body caption col colgroup datalist dd details dialog div ' +\n 'dl dt fieldset figcaption figure footer form h1 h2 h3 h4 h5 h6 head header hgroup hr html ' +\n 'legend li main menu nav ol optgroup option p pre search section select summary table tbody ' +\n 'td tfoot th thead tr ul ' +\n // Head-only elements: never rendered at all, so never inline.\n 'base link meta title ' +\n // SVG containers and shapes: whitespace between them is never rendered.\n 'circle clippath defs ellipse g line lineargradient marker mask path pattern polygon ' +\n 'polyline radialgradient rect stop symbol use'\n ).split(' '),\n);\n\n/** Elements whose text content is copied verbatim (whitespace is meaningful or raw text). */\nconst RAW_TEXT = new Set(['script', 'style', 'textarea', 'title']);\nconst PRESERVE = 'pre';\n\n/** What sits on one side of a text chunk. */\ntype Edge = 'template' | 'inline' | 'block';\n\n/**\n * Inline-block controls: they sit inline among their neighbours, but whitespace at the start or\n * end of their own content is never rendered (it is at the edge of their own line box). Same\n * for <svg>: SVG content renders no text outside its text elements.\n */\nconst INLINE_BOX = new Set(['button', 'select', 'svg']);\n\n/**\n * The edge a tag makes for the text next to it. `inside` is true when the text is inside the\n * element (after its start tag, or before its end tag).\n */\nfunction edgeOfTag(name: string, inside: boolean): Edge {\n const lower = name.toLowerCase();\n if (BLOCK.has(lower)) return 'block';\n return inside && INLINE_BOX.has(lower) ? 'block' : 'inline';\n}\n\nconst WS = /^[ \\t\\n\\r\\f]*$/;\nconst RUN = /[ \\t\\n\\r\\f]+/g;\n\n/** `head`: the text is inside `<head>`, which is never rendered. */\nfunction minifyChunk(text: string, left: Edge, right: Edge, head: boolean): string {\n if (text === '') return text;\n if (WS.test(text)) {\n const removable =\n head ||\n (/[\\n\\r]/.test(text) &&\n (left === 'template' || right === 'template' || left === 'block' || right === 'block'));\n return removable ? '' : ' ';\n }\n // Mixed text: a leading or trailing run with a newline next to a removable edge goes too.\n const dropStart = left !== 'inline' && /^[ \\t\\f]*[\\n\\r]/.test(text);\n const dropEnd = right !== 'inline' && /[\\n\\r][ \\t\\n\\r\\f]*$/.test(text);\n let body = text.replace(RUN, ' ');\n if (dropStart) body = body.replace(/^ /, '');\n if (dropEnd) body = body.replace(/ $/, '');\n return body;\n}\n\nconst Mode = { Text: 0, Tag: 1, Comment: 2, RawText: 3 } as const;\ntype Mode = (typeof Mode)[keyof typeof Mode];\n\ninterface Scan {\n mode: Mode;\n /** Quote char while inside an attribute value in a tag, else ''. */\n quote: string;\n /** Name of the tag being read (lower case), and whether it is a closing tag. */\n tagName: string;\n closing: boolean;\n /** Raw-text element we are inside (its contents are copied verbatim). */\n rawName: string;\n /** Depth of open <pre> elements: text is copied verbatim while > 0. */\n preDepth: number;\n /** Inside <head> (until </head> or <body>). */\n head: boolean;\n /** Edge type of the boundary before the current text chunk. */\n left: Edge;\n}\n\nconst TAG_START = /^<(\\/?)([A-Za-z!?][^\\s/>]*)/;\n\n/** Minify one segment, carrying the HTML scan state across bindings. */\nfunction minifySegment(segment: string, state: Scan, last: boolean): string {\n let out = '';\n let chunk = '';\n const flushText = (right: Edge): void => {\n out += state.preDepth > 0 ? chunk : minifyChunk(chunk, state.left, right, state.head);\n chunk = '';\n };\n let i = 0;\n while (i < segment.length) {\n const ch = segment.charAt(i);\n if (state.mode === Mode.Comment) {\n if (segment.startsWith('-->', i)) {\n out += '-->';\n i += 3;\n state.mode = Mode.Text;\n state.left = 'inline';\n } else {\n out += ch;\n i += 1;\n }\n continue;\n }\n if (state.mode === Mode.RawText) {\n const close = `</${state.rawName}`;\n if (segment.slice(i, i + close.length).toLowerCase() === close) {\n state.mode = Mode.Text;\n state.left = 'inline';\n continue; // the closing tag is read in Text mode\n }\n out += ch;\n i += 1;\n continue;\n }\n if (state.mode === Mode.Tag) {\n out += ch;\n i += 1;\n if (state.quote !== '') {\n if (ch === state.quote) state.quote = '';\n } else if (ch === '\"' || ch === \"'\") {\n state.quote = ch;\n } else if (ch === '>') {\n endTag(state, out.endsWith('/>'));\n }\n continue;\n }\n // Text mode.\n if (ch === '<' && segment.startsWith('<!--', i)) {\n flushText('inline');\n state.mode = Mode.Comment;\n out += '<!--';\n i += 4;\n continue;\n }\n const tag = ch === '<' ? TAG_START.exec(segment.slice(i)) : null;\n if (tag !== null) {\n const name = (tag[2] ?? '').toLowerCase();\n const closing = tag[1] === '/';\n flushText(edgeOfTag(name, closing));\n state.closing = closing;\n state.tagName = name;\n state.mode = Mode.Tag;\n out += tag[0];\n i += tag[0].length;\n continue;\n }\n chunk += ch;\n i += 1;\n }\n if (state.mode === Mode.Text) {\n flushText(last ? 'template' : 'inline');\n state.left = 'inline'; // the next segment starts after a binding\n }\n return out;\n}\n\nfunction endTag(state: Scan, selfClosing: boolean): void {\n const name = state.tagName;\n state.mode = Mode.Text;\n state.left = edgeOfTag(name, !state.closing && !selfClosing);\n if (name === 'head' && !selfClosing) state.head = !state.closing;\n if (name === 'body') state.head = false;\n if (name === PRESERVE) {\n if (state.closing) state.preDepth = Math.max(0, state.preDepth - 1);\n else if (!selfClosing) state.preDepth += 1;\n }\n if (!state.closing && !selfClosing && RAW_TEXT.has(name)) {\n state.mode = Mode.RawText;\n state.rawName = name;\n }\n}\n\n/** Minified copy of template strings (same length, bindings unmoved). Idempotent. */\nexport function minifyStrings(strings: readonly string[]): string[] {\n const state: Scan = {\n mode: Mode.Text,\n quote: '',\n tagName: '',\n closing: false,\n rawName: '',\n preDepth: 0,\n head: false,\n left: 'template',\n };\n return strings.map((segment, index) =>\n minifySegment(segment, state, index === strings.length - 1),\n );\n}\n"]}
@@ -1,7 +1,7 @@
1
+ import { message } from './message.js';
1
2
  export const prepare = (strings) => {
2
3
  const start = strings.join('${…}').trim().slice(0, 80);
3
- throw new Error(`gyral: an html template was not compiled: \`${start}\`. Under the gyral-compiled condition ` +
4
- `every html\`…\` must be compiled by the Gyral Vite preset (view/01-templates.md).`);
4
+ throw new Error(message(70, start));
5
5
  };
6
6
  export const verify = () => undefined;
7
7
  //# sourceMappingURL=prepare-stub.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"prepare-stub.js","sourceRoot":"","sources":["../../src/view/prepare-stub.ts"],"names":[],"mappings":"AAKA,MAAM,CAAC,MAAM,OAAO,GAA2B,CAAC,OAAO,EAAE,EAAE;IACzD,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACvD,MAAM,IAAI,KAAK,CACb,+CAA+C,KAAK,yCAAyC;QAC3F,mFAAmF,CACtF,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,MAAM,GAA0B,GAAG,EAAE,CAAC,SAAS,CAAC","sourcesContent":["// The `gyral-compiled` build of core's `#prepare` import (view/01-templates.md \"Compiled\"):\n// with the Vite preset's template compiler every `html` template is precompiled, so the\n// runtime preparer is left out of the bundle. Reaching this means one template was not.\nimport type * as Prepare from './prepare.js';\n\nexport const prepare: typeof Prepare.prepare = (strings) => {\n const start = strings.join('${…}').trim().slice(0, 80);\n throw new Error(\n `gyral: an html template was not compiled: \\`${start}\\`. Under the gyral-compiled condition ` +\n `every html\\`…\\` must be compiled by the Gyral Vite preset (view/01-templates.md).`,\n );\n};\n\nexport const verify: typeof Prepare.verify = () => undefined;\n"]}
1
+ {"version":3,"file":"prepare-stub.js","sourceRoot":"","sources":["../../src/view/prepare-stub.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,MAAM,CAAC,MAAM,OAAO,GAA2B,CAAC,OAAO,EAAE,EAAE;IACzD,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACvD,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC;AACtC,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,MAAM,GAA0B,GAAG,EAAE,CAAC,SAAS,CAAC","sourcesContent":["// The `gyral-compiled` build of core's `#prepare` import (view/01-templates.md \"Compiled\"):\n// with the Vite preset's template compiler every `html` template is precompiled, so the\n// runtime preparer is left out of the bundle. Reaching this means one template was not.\nimport type * as Prepare from './prepare.js';\nimport { message } from './message.js';\n\nexport const prepare: typeof Prepare.prepare = (strings) => {\n const start = strings.join('${…}').trim().slice(0, 80);\n throw new Error(message(70, start));\n};\n\nexport const verify: typeof Prepare.verify = () => undefined;\n"]}
@@ -1,6 +1,9 @@
1
1
  import type { TemplateObject } from './normalize/types.js';
2
- /** The template object of a call site's strings, normalized (with development checks) once. */
3
- export declare function prepare(strings: readonly string[]): TemplateObject;
2
+ /**
3
+ * The template object of a call site's strings, normalized (with development checks) once.
4
+ * `svg`: the call site is an svg template (template.ts `svg`), whose first call prepares it.
5
+ */
6
+ export declare function prepare(strings: readonly string[], svg?: boolean): TemplateObject;
4
7
  /**
5
8
  * Throws rule 7 when the browser's parse of `template.html` (in `el`) differs from the tree
6
9
  * the normalizer computed paths for. Templates that didn't come from `prepare` are skipped.
@@ -4,6 +4,8 @@
4
4
  // checks that the parse built exactly the DOM the normalizer's paths assume. A difference
5
5
  // means the parser repaired the markup: rule 7 (view/09-template-rules.md). Builds made with
6
6
  // the `gyral-compiled` condition get prepare-stub.ts instead.
7
+ import { DEV } from '#view-dev';
8
+ import { locOf } from './loc.js';
7
9
  import { recordTemplateId } from './normalize/id.js';
8
10
  import { analyze } from './normalize/normalize.js';
9
11
  import { repairError, shapeMismatch } from './normalize/shape.js';
@@ -12,13 +14,17 @@ const prepared = new WeakMap();
12
14
  // One-entry cache in front of the WeakMap: list rows ask for the same call site in a row.
13
15
  let lastSource;
14
16
  let lastTemplate;
15
- /** The template object of a call site's strings, normalized (with development checks) once. */
16
- export function prepare(strings) {
17
+ /**
18
+ * The template object of a call site's strings, normalized (with development checks) once.
19
+ * `svg`: the call site is an svg template (template.ts `svg`), whose first call prepares it.
20
+ */
21
+ export function prepare(strings, svg) {
17
22
  if (strings === lastSource)
18
23
  return lastTemplate;
19
24
  let template = prepared.get(strings);
20
25
  if (template === undefined) {
21
- const analysis = analyze(strings);
26
+ // Development: the call site (loc.ts), so rule errors and hydration mismatches name it.
27
+ const analysis = analyze(strings, DEV ? locOf(strings) : undefined, svg);
22
28
  template = analysis.template;
23
29
  recordTemplateId(analysis.template.id, analysis.strings);
24
30
  shapes.set(template, analysis.shape);
@@ -1 +1 @@
1
- {"version":3,"file":"prepare.js","sourceRoot":"","sources":["../../src/view/prepare.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAC1F,8FAA8F;AAC9F,0FAA0F;AAC1F,0FAA0F;AAC1F,6FAA6F;AAC7F,8DAA8D;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAGlE,MAAM,MAAM,GAAG,IAAI,OAAO,EAAyB,CAAC;AACpD,MAAM,QAAQ,GAAG,IAAI,OAAO,EAAqC,CAAC;AAClE,0FAA0F;AAC1F,IAAI,UAAyC,CAAC;AAC9C,IAAI,YAAwC,CAAC;AAE7C,+FAA+F;AAC/F,MAAM,UAAU,OAAO,CAAC,OAA0B;IAChD,IAAI,OAAO,KAAK,UAAU;QAAE,OAAO,YAA8B,CAAC;IAClE,IAAI,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACrC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QAClC,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAC;QAC7B,gBAAgB,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;QACzD,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;QACrC,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IAClC,CAAC;IACD,UAAU,GAAG,OAAO,CAAC;IACrB,YAAY,GAAG,QAAQ,CAAC;IACxB,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,4FAA4F;AAC5F,SAAS,QAAQ,CAAC,KAA4B;IAC5C,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAa,EAAE;QACxC,IAAI,IAAI,CAAC,QAAQ,KAAK,CAAC;YAAE,OAAO,OAAO,CAAC;QACxC,IAAI,IAAI,CAAC,QAAQ,KAAK,CAAC;YAAE,OAAO,UAAU,CAAC;QAC3C,IAAI,IAAI,CAAC,QAAQ,KAAK,CAAC;YAAE,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,EAAE,EAAE,CAAC,CAAC;QAClE,MAAM,EAAE,GAAG,IAAe,CAAC;QAC3B,MAAM,QAAQ,GACZ,EAAE,CAAC,SAAS,KAAK,UAAU,CAAC,CAAC,CAAE,EAA0B,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC;QAC/F,OAAO,CAAC,EAAE,CAAC,SAAS,CAAC,WAAW,EAAE,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,MAAM,CAAC,QAAwB,EAAE,EAAuB;IACtE,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACnC,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO;IAChC,MAAM,OAAO,GAAG,aAAa,CAAC,KAAK,EAAE,QAAQ,CAAC,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC;IACtE,IAAI,OAAO,KAAK,SAAS;QAAE,MAAM,WAAW,CAAC,QAAQ,EAAE,2BAA2B,EAAE,OAAO,CAAC,CAAC;AAC/F,CAAC","sourcesContent":["// The runtime template preparer (view/01-templates.md \"Runtime\"), resolved through core's\n// `#prepare` import by default. It runs the normalizer once per call site (template.ts caches\n// the result) and, when the browser first parses a template's HTML (template-element.ts),\n// checks that the parse built exactly the DOM the normalizer's paths assume. A difference\n// means the parser repaired the markup: rule 7 (view/09-template-rules.md). Builds made with\n// the `gyral-compiled` condition get prepare-stub.ts instead.\nimport { recordTemplateId } from './normalize/id.js';\nimport { analyze } from './normalize/normalize.js';\nimport { repairError, shapeMismatch } from './normalize/shape.js';\nimport type { Shape, ShapeNode, TemplateObject } from './normalize/types.js';\n\nconst shapes = new WeakMap<TemplateObject, Shape>();\nconst prepared = new WeakMap<readonly string[], TemplateObject>();\n// One-entry cache in front of the WeakMap: list rows ask for the same call site in a row.\nlet lastSource: readonly string[] | undefined;\nlet lastTemplate: TemplateObject | undefined;\n\n/** The template object of a call site's strings, normalized (with development checks) once. */\nexport function prepare(strings: readonly string[]): TemplateObject {\n if (strings === lastSource) return lastTemplate as TemplateObject;\n let template = prepared.get(strings);\n if (template === undefined) {\n const analysis = analyze(strings);\n template = analysis.template;\n recordTemplateId(analysis.template.id, analysis.strings);\n shapes.set(template, analysis.shape);\n prepared.set(strings, template);\n }\n lastSource = strings;\n lastTemplate = template;\n return template;\n}\n\n/** The DOM the browser built, as a Shape (lower-case names, <template> content inlined). */\nfunction domShape(nodes: NodeListOf<ChildNode>): Shape {\n return [...nodes].map((node): ShapeNode => {\n if (node.nodeType === 3) return '#text';\n if (node.nodeType === 8) return '#comment';\n if (node.nodeType !== 1) return [node.nodeName.toLowerCase(), []];\n const el = node as Element;\n const children =\n el.localName === 'template' ? (el as HTMLTemplateElement).content.childNodes : el.childNodes;\n return [el.localName.toLowerCase(), domShape(children)];\n });\n}\n\n/**\n * Throws rule 7 when the browser's parse of `template.html` (in `el`) differs from the tree\n * the normalizer computed paths for. Templates that didn't come from `prepare` are skipped.\n */\nexport function verify(template: TemplateObject, el: HTMLTemplateElement): void {\n const shape = shapes.get(template);\n if (shape === undefined) return;\n const problem = shapeMismatch(shape, domShape(el.content.childNodes));\n if (problem !== undefined) throw repairError(template, \"The browser's HTML parser\", problem);\n}\n"]}
1
+ {"version":3,"file":"prepare.js","sourceRoot":"","sources":["../../src/view/prepare.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAC1F,8FAA8F;AAC9F,0FAA0F;AAC1F,0FAA0F;AAC1F,6FAA6F;AAC7F,8DAA8D;AAC9D,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAChC,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AACjC,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAGlE,MAAM,MAAM,GAAG,IAAI,OAAO,EAAyB,CAAC;AACpD,MAAM,QAAQ,GAAG,IAAI,OAAO,EAAqC,CAAC;AAClE,0FAA0F;AAC1F,IAAI,UAAyC,CAAC;AAC9C,IAAI,YAAwC,CAAC;AAE7C;;;GAGG;AACH,MAAM,UAAU,OAAO,CAAC,OAA0B,EAAE,GAAa;IAC/D,IAAI,OAAO,KAAK,UAAU;QAAE,OAAO,YAA8B,CAAC;IAClE,IAAI,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACrC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,wFAAwF;QACxF,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QACzE,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAC;QAC7B,gBAAgB,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;QACzD,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;QACrC,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IAClC,CAAC;IACD,UAAU,GAAG,OAAO,CAAC;IACrB,YAAY,GAAG,QAAQ,CAAC;IACxB,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,4FAA4F;AAC5F,SAAS,QAAQ,CAAC,KAA4B;IAC5C,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAa,EAAE;QACxC,IAAI,IAAI,CAAC,QAAQ,KAAK,CAAC;YAAE,OAAO,OAAO,CAAC;QACxC,IAAI,IAAI,CAAC,QAAQ,KAAK,CAAC;YAAE,OAAO,UAAU,CAAC;QAC3C,IAAI,IAAI,CAAC,QAAQ,KAAK,CAAC;YAAE,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,EAAE,EAAE,CAAC,CAAC;QAClE,MAAM,EAAE,GAAG,IAAe,CAAC;QAC3B,MAAM,QAAQ,GACZ,EAAE,CAAC,SAAS,KAAK,UAAU,CAAC,CAAC,CAAE,EAA0B,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC;QAC/F,OAAO,CAAC,EAAE,CAAC,SAAS,CAAC,WAAW,EAAE,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,MAAM,CAAC,QAAwB,EAAE,EAAuB;IACtE,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACnC,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO;IAChC,MAAM,OAAO,GAAG,aAAa,CAAC,KAAK,EAAE,QAAQ,CAAC,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC;IACtE,IAAI,OAAO,KAAK,SAAS;QAAE,MAAM,WAAW,CAAC,QAAQ,EAAE,2BAA2B,EAAE,OAAO,CAAC,CAAC;AAC/F,CAAC","sourcesContent":["// The runtime template preparer (view/01-templates.md \"Runtime\"), resolved through core's\n// `#prepare` import by default. It runs the normalizer once per call site (template.ts caches\n// the result) and, when the browser first parses a template's HTML (template-element.ts),\n// checks that the parse built exactly the DOM the normalizer's paths assume. A difference\n// means the parser repaired the markup: rule 7 (view/09-template-rules.md). Builds made with\n// the `gyral-compiled` condition get prepare-stub.ts instead.\nimport { DEV } from '#view-dev';\nimport { locOf } from './loc.js';\nimport { recordTemplateId } from './normalize/id.js';\nimport { analyze } from './normalize/normalize.js';\nimport { repairError, shapeMismatch } from './normalize/shape.js';\nimport type { Shape, ShapeNode, TemplateObject } from './normalize/types.js';\n\nconst shapes = new WeakMap<TemplateObject, Shape>();\nconst prepared = new WeakMap<readonly string[], TemplateObject>();\n// One-entry cache in front of the WeakMap: list rows ask for the same call site in a row.\nlet lastSource: readonly string[] | undefined;\nlet lastTemplate: TemplateObject | undefined;\n\n/**\n * The template object of a call site's strings, normalized (with development checks) once.\n * `svg`: the call site is an svg template (template.ts `svg`), whose first call prepares it.\n */\nexport function prepare(strings: readonly string[], svg?: boolean): TemplateObject {\n if (strings === lastSource) return lastTemplate as TemplateObject;\n let template = prepared.get(strings);\n if (template === undefined) {\n // Development: the call site (loc.ts), so rule errors and hydration mismatches name it.\n const analysis = analyze(strings, DEV ? locOf(strings) : undefined, svg);\n template = analysis.template;\n recordTemplateId(analysis.template.id, analysis.strings);\n shapes.set(template, analysis.shape);\n prepared.set(strings, template);\n }\n lastSource = strings;\n lastTemplate = template;\n return template;\n}\n\n/** The DOM the browser built, as a Shape (lower-case names, <template> content inlined). */\nfunction domShape(nodes: NodeListOf<ChildNode>): Shape {\n return [...nodes].map((node): ShapeNode => {\n if (node.nodeType === 3) return '#text';\n if (node.nodeType === 8) return '#comment';\n if (node.nodeType !== 1) return [node.nodeName.toLowerCase(), []];\n const el = node as Element;\n const children =\n el.localName === 'template' ? (el as HTMLTemplateElement).content.childNodes : el.childNodes;\n return [el.localName.toLowerCase(), domShape(children)];\n });\n}\n\n/**\n * Throws rule 7 when the browser's parse of `template.html` (in `el`) differs from the tree\n * the normalizer computed paths for. Templates that didn't come from `prepare` are skipped.\n */\nexport function verify(template: TemplateObject, el: HTMLTemplateElement): void {\n const shape = shapes.get(template);\n if (shape === undefined) return;\n const problem = shapeMismatch(shape, domShape(el.content.childNodes));\n if (problem !== undefined) throw repairError(template, \"The browser's HTML parser\", problem);\n}\n"]}
@@ -11,6 +11,12 @@ export interface ServerRendering {
11
11
  readonly state?: unknown;
12
12
  readonly props: Readonly<Record<string, unknown>>;
13
13
  };
14
+ /**
15
+ * Set when `init` or the view threw (ADR 0024): `view` is the component's error view (or
16
+ * nothing), the host is marked `data-gyral-error` with no seed, and the renderer reports this
17
+ * value (core's `GyralError`, opaque here) through its `onError` option.
18
+ */
19
+ readonly failed?: unknown;
14
20
  }
15
21
  /** The input of one server render, gathered from the start tag (06 "Components"). */
16
22
  export interface ServerRenderInput {
@@ -32,15 +38,24 @@ export interface ServerComponent {
32
38
  readonly tag: string;
33
39
  /** `shadow: false` (ADR 0014): render as light-DOM children, not `<template shadowrootmode>`. */
34
40
  readonly light: boolean;
41
+ /** `shadow: { delegatesFocus: true }`: the declarative root gets `shadowrootdelegatesfocus`. */
42
+ readonly delegatesFocus?: boolean;
35
43
  /** CSS texts for the declarative shadow root's `<style>` (08). Empty for light components. */
36
44
  readonly styles: readonly string[];
37
45
  /** The island strategy (07): anything but `load` adds `defer-hydration` and `data-gyral-hydrate`. */
38
46
  readonly hydrate: 'load' | 'idle' | 'visible' | 'interaction';
39
47
  /** Parses props (validated as in the browser), runs `init` (commands dropped) and the view. */
40
48
  render(input: ServerRenderInput): ServerRendering;
49
+ /** The error rendering for a view value that failed while being written (ADR 0024). */
50
+ fallback?(cause: unknown): ServerRendering;
41
51
  }
42
52
  /** Records a component. A tag registered twice keeps its first entry, as `customElements` does. */
43
53
  export declare function registerServerComponent(component: ServerComponent): void;
54
+ /**
55
+ * Changes whenever the registry does (a component, and so its CSS, is added): caches derived
56
+ * from the registry (the CSP header of `@gyral/ssr`'s `renderPage`) key on it.
57
+ */
58
+ export declare const serverRegistryVersion: () => number;
44
59
  /** The component registered under `tag`, if any. */
45
60
  export declare const serverComponent: (tag: string) => ServerComponent | undefined;
46
61
  /** Every registered component (for `styleHashes()`, 06 "CSP"). */
@@ -1,9 +1,17 @@
1
1
  const components = new Map();
2
+ let version = 0;
2
3
  /** Records a component. A tag registered twice keeps its first entry, as `customElements` does. */
3
4
  export function registerServerComponent(component) {
4
- if (!components.has(component.tag))
5
- components.set(component.tag, component);
5
+ if (components.has(component.tag))
6
+ return;
7
+ components.set(component.tag, component);
8
+ version++;
6
9
  }
10
+ /**
11
+ * Changes whenever the registry does (a component, and so its CSS, is added): caches derived
12
+ * from the registry (the CSP header of `@gyral/ssr`'s `renderPage`) key on it.
13
+ */
14
+ export const serverRegistryVersion = () => version;
7
15
  /** The component registered under `tag`, if any. */
8
16
  export const serverComponent = (tag) => components.get(tag);
9
17
  /** Every registered component (for `styleHashes()`, 06 "CSP"). */
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/view/registry.ts"],"names":[],"mappings":"AAgDA,MAAM,UAAU,GAAG,IAAI,GAAG,EAA2B,CAAC;AAEtD,mGAAmG;AACnG,MAAM,UAAU,uBAAuB,CAAC,SAA0B;IAChE,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC;QAAE,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;AAC/E,CAAC;AAED,oDAAoD;AACpD,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,GAAW,EAA+B,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAEjG,kEAAkE;AAClE,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAA+B,EAAE,CAAC,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;AAe3F,MAAM,SAAS,GAAG,IAAI,GAAG,EAA0B,CAAC;AAEpD,gFAAgF;AAChF,MAAM,UAAU,sBAAsB,CAAC,QAAwB;IAC7D,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;AAC1E,CAAC;AAED,mDAAmD;AACnD,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,GAAW,EAA8B,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC","sourcesContent":["// The server registry (view/05-element.md \"Registration\", view/06-server.md \"Components\").\n// Outside the browser `define()` records each spec (server-specs.ts); `@gyral/core/server`\n// turns them into entries here (server-component.ts `registerRecordedSpecs`) before each\n// render, and its renderer (view/server/) looks start tags up and renders the component in\n// place. Providers (`<gyral-stores>`, ADR 0013) register a scope for their subtree. Plain data\n// and functions, no DOM: it lives in view/ so view/server/ can read it.\nimport type { ChildValue } from './render/values.js';\n\n/** What a server render of one component returns: its view and what its seed must carry. */\nexport interface ServerRendering {\n /** `view(state, intents, ctx)` for the resolved props and state. */\n readonly view: ChildValue;\n /**\n * The `data-gyral-seed` payload (ADR 0012): `props` that no attribute carries, and `state`\n * unless it equals `init(props)`'s state. JSON-serializable.\n */\n readonly seed: { readonly state?: unknown; readonly props: Readonly<Record<string, unknown>> };\n}\n\n/** The input of one server render, gathered from the start tag (06 \"Components\"). */\nexport interface ServerRenderInput {\n /** Static attributes plus attribute/boolean holes, as strings (`''` for a present boolean). */\n readonly attributes: Readonly<Record<string, string>>;\n /** Property holes: values as is. */\n readonly properties: Readonly<Record<string, unknown>>;\n /** Messages run through their reducers after `init` (ADR 0008's rejected-form re-render). */\n readonly initialMessages?: readonly unknown[] | undefined;\n /**\n * The nearest provider's scope (opaque to view/), or undefined for the request's own scope.\n * The renderer passes it down: a provider's subtree can span several streamed chunks, so a\n * global set around the subtree would not survive between pulls.\n */\n readonly scope?: unknown;\n}\n\n/** One registered component, as the server renderer sees it. */\nexport interface ServerComponent {\n readonly tag: string;\n /** `shadow: false` (ADR 0014): render as light-DOM children, not `<template shadowrootmode>`. */\n readonly light: boolean;\n /** CSS texts for the declarative shadow root's `<style>` (08). Empty for light components. */\n readonly styles: readonly string[];\n /** The island strategy (07): anything but `load` adds `defer-hydration` and `data-gyral-hydrate`. */\n readonly hydrate: 'load' | 'idle' | 'visible' | 'interaction';\n /** Parses props (validated as in the browser), runs `init` (commands dropped) and the view. */\n render(input: ServerRenderInput): ServerRendering;\n}\n\nconst components = new Map<string, ServerComponent>();\n\n/** Records a component. A tag registered twice keeps its first entry, as `customElements` does. */\nexport function registerServerComponent(component: ServerComponent): void {\n if (!components.has(component.tag)) components.set(component.tag, component);\n}\n\n/** The component registered under `tag`, if any. */\nexport const serverComponent = (tag: string): ServerComponent | undefined => components.get(tag);\n\n/** Every registered component (for `styleHashes()`, 06 \"CSP\"). */\nexport const serverComponents = (): readonly ServerComponent[] => [...components.values()];\n\n/**\n * A server-side provider element (`<gyral-stores>`, ADR 0013): written as a plain element, it\n * gives its subtree a scope (passed to components as `ServerRenderInput.scope`) and may add\n * attributes to its start tag (its seed).\n */\nexport interface ServerProvider {\n readonly tag: string;\n open(input: ServerRenderInput): {\n readonly scope: unknown;\n readonly attributes: Readonly<Record<string, string>>;\n };\n}\n\nconst providers = new Map<string, ServerProvider>();\n\n/** Records a provider element. A tag registered twice keeps its first entry. */\nexport function registerServerProvider(provider: ServerProvider): void {\n if (!providers.has(provider.tag)) providers.set(provider.tag, provider);\n}\n\n/** The provider registered under `tag`, if any. */\nexport const serverProvider = (tag: string): ServerProvider | undefined => providers.get(tag);\n"]}
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/view/registry.ts"],"names":[],"mappings":"AA0DA,MAAM,UAAU,GAAG,IAAI,GAAG,EAA2B,CAAC;AACtD,IAAI,OAAO,GAAG,CAAC,CAAC;AAEhB,mGAAmG;AACnG,MAAM,UAAU,uBAAuB,CAAC,SAA0B;IAChE,IAAI,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC;QAAE,OAAO;IAC1C,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IACzC,OAAO,EAAE,CAAC;AACZ,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,GAAW,EAAE,CAAC,OAAO,CAAC;AAE3D,oDAAoD;AACpD,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,GAAW,EAA+B,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAEjG,kEAAkE;AAClE,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAA+B,EAAE,CAAC,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;AAe3F,MAAM,SAAS,GAAG,IAAI,GAAG,EAA0B,CAAC;AAEpD,gFAAgF;AAChF,MAAM,UAAU,sBAAsB,CAAC,QAAwB;IAC7D,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;AAC1E,CAAC;AAED,mDAAmD;AACnD,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,GAAW,EAA8B,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC","sourcesContent":["// The server registry (view/05-element.md \"Registration\", view/06-server.md \"Components\").\n// Outside the browser `define()` records each spec (server-specs.ts); `@gyral/core/internal/server`\n// turns them into entries here (server-component.ts `registerRecordedSpecs`) before each\n// render, and its renderer (view/server/) looks start tags up and renders the component in\n// place. Providers (`<gyral-stores>`, ADR 0013) register a scope for their subtree. Plain data\n// and functions, no DOM: it lives in view/ so view/server/ can read it.\nimport type { ChildValue } from './render/values.js';\n\n/** What a server render of one component returns: its view and what its seed must carry. */\nexport interface ServerRendering {\n /** `view(state, intents, ctx)` for the resolved props and state. */\n readonly view: ChildValue;\n /**\n * The `data-gyral-seed` payload (ADR 0012): `props` that no attribute carries, and `state`\n * unless it equals `init(props)`'s state. JSON-serializable.\n */\n readonly seed: { readonly state?: unknown; readonly props: Readonly<Record<string, unknown>> };\n /**\n * Set when `init` or the view threw (ADR 0024): `view` is the component's error view (or\n * nothing), the host is marked `data-gyral-error` with no seed, and the renderer reports this\n * value (core's `GyralError`, opaque here) through its `onError` option.\n */\n readonly failed?: unknown;\n}\n\n/** The input of one server render, gathered from the start tag (06 \"Components\"). */\nexport interface ServerRenderInput {\n /** Static attributes plus attribute/boolean holes, as strings (`''` for a present boolean). */\n readonly attributes: Readonly<Record<string, string>>;\n /** Property holes: values as is. */\n readonly properties: Readonly<Record<string, unknown>>;\n /** Messages run through their reducers after `init` (ADR 0008's rejected-form re-render). */\n readonly initialMessages?: readonly unknown[] | undefined;\n /**\n * The nearest provider's scope (opaque to view/), or undefined for the request's own scope.\n * The renderer passes it down: a provider's subtree can span several streamed chunks, so a\n * global set around the subtree would not survive between pulls.\n */\n readonly scope?: unknown;\n}\n\n/** One registered component, as the server renderer sees it. */\nexport interface ServerComponent {\n readonly tag: string;\n /** `shadow: false` (ADR 0014): render as light-DOM children, not `<template shadowrootmode>`. */\n readonly light: boolean;\n /** `shadow: { delegatesFocus: true }`: the declarative root gets `shadowrootdelegatesfocus`. */\n readonly delegatesFocus?: boolean;\n /** CSS texts for the declarative shadow root's `<style>` (08). Empty for light components. */\n readonly styles: readonly string[];\n /** The island strategy (07): anything but `load` adds `defer-hydration` and `data-gyral-hydrate`. */\n readonly hydrate: 'load' | 'idle' | 'visible' | 'interaction';\n /** Parses props (validated as in the browser), runs `init` (commands dropped) and the view. */\n render(input: ServerRenderInput): ServerRendering;\n /** The error rendering for a view value that failed while being written (ADR 0024). */\n fallback?(cause: unknown): ServerRendering;\n}\n\nconst components = new Map<string, ServerComponent>();\nlet version = 0;\n\n/** Records a component. A tag registered twice keeps its first entry, as `customElements` does. */\nexport function registerServerComponent(component: ServerComponent): void {\n if (components.has(component.tag)) return;\n components.set(component.tag, component);\n version++;\n}\n\n/**\n * Changes whenever the registry does (a component, and so its CSS, is added): caches derived\n * from the registry (the CSP header of `@gyral/ssr`'s `renderPage`) key on it.\n */\nexport const serverRegistryVersion = (): number => version;\n\n/** The component registered under `tag`, if any. */\nexport const serverComponent = (tag: string): ServerComponent | undefined => components.get(tag);\n\n/** Every registered component (for `styleHashes()`, 06 \"CSP\"). */\nexport const serverComponents = (): readonly ServerComponent[] => [...components.values()];\n\n/**\n * A server-side provider element (`<gyral-stores>`, ADR 0013): written as a plain element, it\n * gives its subtree a scope (passed to components as `ServerRenderInput.scope`) and may add\n * attributes to its start tag (its seed).\n */\nexport interface ServerProvider {\n readonly tag: string;\n open(input: ServerRenderInput): {\n readonly scope: unknown;\n readonly attributes: Readonly<Record<string, string>>;\n };\n}\n\nconst providers = new Map<string, ServerProvider>();\n\n/** Records a provider element. A tag registered twice keeps its first entry. */\nexport function registerServerProvider(provider: ServerProvider): void {\n if (!providers.has(provider.tag)) providers.set(provider.tag, provider);\n}\n\n/** The provider registered under `tag`, if any. */\nexport const serverProvider = (tag: string): ServerProvider | undefined => providers.get(tag);\n"]}
@@ -1,7 +1,7 @@
1
1
  // Element parts in hydration (view/07-hydration.md "The parallel walk", "Form state"): an
2
2
  // attribute, property, hook or text part built over server DOM takes this render's values as
3
3
  // committed. Lives with the walk, in the lazily loaded hydration code, not in attr-parts.ts.
4
- import { absent, ATTR, BOOL, CHECKED, HOOK, MULTI, PLAIN, PROP, STATE, TEXTAREA, textOf, TITLE, truthy, VALUE, } from './attr-parts.js';
4
+ import { absent, ATTR, BOOL, CHECKED, HOOK, MULTI, PLAIN, PROP, STATE, TEXTAREA, textOf, TITLE, TOGGLE, truthy, VALUE, } from './attr-parts.js';
5
5
  /**
6
6
  * Takes this render's values as committed without writing (the server wrote them). Form state
7
7
  * the user changed before scripts ran stays: like every part, it writes only when the model's
@@ -35,6 +35,8 @@ export function adoptAttr(part, values) {
35
35
  }
36
36
  else if (kind === TITLE || kind === TEXTAREA)
37
37
  part.value = textOf(part, v);
38
+ else if (kind === TOGGLE)
39
+ part.set(values); // the server can't open a modal: open it now
38
40
  else {
39
41
  part.value = truthy(v);
40
42
  if (kind === STATE && live[name] !== part.value)
@@ -54,6 +56,10 @@ export function checkAttr(part, fail) {
54
56
  case ATTR:
55
57
  case VALUE:
56
58
  case MULTI:
59
+ // A style the CSP blocked can't be compared: Firefox empties the attribute.
60
+ if (name === 'style' && el.hasAttribute(name) && el.style.length === 0) {
61
+ return;
62
+ }
57
63
  if (part.kind !== MULTI)
58
64
  want = absent(value) ? null : String(value);
59
65
  got = el.getAttribute(name);
@@ -1 +1 @@
1
- {"version":3,"file":"adopt-attr.js","sourceRoot":"","sources":["../../../src/view/render/adopt-attr.ts"],"names":[],"mappings":"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","sourcesContent":["// Element parts in hydration (view/07-hydration.md \"The parallel walk\", \"Form state\"): an\n// attribute, property, hook or text part built over server DOM takes this render's values as\n// committed. Lives with the walk, in the lazily loaded hydration code, not in attr-parts.ts.\nimport {\n absent,\n ATTR,\n BOOL,\n CHECKED,\n HOOK,\n MULTI,\n PLAIN,\n PROP,\n STATE,\n TEXTAREA,\n textOf,\n TITLE,\n truthy,\n VALUE,\n type AttrPart,\n} from './attr-parts.js';\n\n/**\n * Takes this render's values as committed without writing (the server wrote them). Form state\n * the user changed before scripts ran stays: like every part, it writes only when the model's\n * value changes (07 \"Form state\"). `?indeterminate`, which no attribute carries, is set; a\n * property is set unless a nested component already has it from its own seed.\n */\nexport function adoptAttr(part: AttrPart, values: readonly unknown[]): void {\n const v = values[part.at];\n const el = part.el;\n const live = el as unknown as Record<string, unknown>;\n const name = part.name;\n const kind = part.kind;\n if (kind === HOOK) part.hook(v);\n else if (kind === PROP) {\n part.value = v;\n const own = live[name] !== undefined && el.localName.includes('-');\n if (!own && !Object.is(live[name], v)) live[name] = v;\n } else if (kind === MULTI) {\n const pieces = part.pieces as unknown[];\n for (let i = 0; i < pieces.length; i++) pieces[i] = values[part.at + i];\n part.value = part.join(pieces);\n } else if (kind === ATTR || kind === VALUE) {\n part.value = v;\n if (kind === VALUE && PLAIN.test((el as HTMLInputElement).type)) part.kind = ATTR;\n } else if (kind === TITLE || kind === TEXTAREA) part.value = textOf(part, v);\n else {\n part.value = truthy(v);\n if (kind === STATE && live[name] !== part.value) live[name] = part.value;\n }\n}\n\n/**\n * Development: the element shows what `part` adopted. Form state the user edits is compared\n * by its attribute or default text, which edits don't change; `?open` isn't compared. `fail`\n * throws the walk's mismatch.\n */\nexport function checkAttr(\n part: AttrPart,\n fail: (expected: string, found: string, at: Node) => never,\n): void {\n const { el, name, value } = part;\n let want: unknown = value;\n let got: unknown;\n switch (part.kind) {\n case ATTR:\n case VALUE:\n case MULTI:\n if (part.kind !== MULTI) want = absent(value) ? null : String(value);\n got = el.getAttribute(name);\n break;\n case BOOL:\n case CHECKED:\n got = el.hasAttribute(name);\n break;\n case TITLE:\n case TEXTAREA:\n got = el.textContent;\n break;\n default:\n return;\n }\n if (got !== want) {\n const what = name === '' ? 'content' : name;\n fail(`${what} ${JSON.stringify(want)}`, `${JSON.stringify(got)} on <${el.localName}>`, el);\n }\n}\n"]}
1
+ {"version":3,"file":"adopt-attr.js","sourceRoot":"","sources":["../../../src/view/render/adopt-attr.ts"],"names":[],"mappings":"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","sourcesContent":["// Element parts in hydration (view/07-hydration.md \"The parallel walk\", \"Form state\"): an\n// attribute, property, hook or text part built over server DOM takes this render's values as\n// committed. Lives with the walk, in the lazily loaded hydration code, not in attr-parts.ts.\nimport {\n absent,\n ATTR,\n BOOL,\n CHECKED,\n HOOK,\n MULTI,\n PLAIN,\n PROP,\n STATE,\n TEXTAREA,\n textOf,\n TITLE,\n TOGGLE,\n truthy,\n VALUE,\n type AttrPart,\n} from './attr-parts.js';\n\n/**\n * Takes this render's values as committed without writing (the server wrote them). Form state\n * the user changed before scripts ran stays: like every part, it writes only when the model's\n * value changes (07 \"Form state\"). `?indeterminate`, which no attribute carries, is set; a\n * property is set unless a nested component already has it from its own seed.\n */\nexport function adoptAttr(part: AttrPart, values: readonly unknown[]): void {\n const v = values[part.at];\n const el = part.el;\n const live = el as unknown as Record<string, unknown>;\n const name = part.name;\n const kind = part.kind;\n if (kind === HOOK) part.hook(v);\n else if (kind === PROP) {\n part.value = v;\n const own = live[name] !== undefined && el.localName.includes('-');\n if (!own && !Object.is(live[name], v)) live[name] = v;\n } else if (kind === MULTI) {\n const pieces = part.pieces as unknown[];\n for (let i = 0; i < pieces.length; i++) pieces[i] = values[part.at + i];\n part.value = part.join(pieces);\n } else if (kind === ATTR || kind === VALUE) {\n part.value = v;\n if (kind === VALUE && PLAIN.test((el as HTMLInputElement).type)) part.kind = ATTR;\n } else if (kind === TITLE || kind === TEXTAREA) part.value = textOf(part, v);\n else if (kind === TOGGLE)\n part.set(values); // the server can't open a modal: open it now\n else {\n part.value = truthy(v);\n if (kind === STATE && live[name] !== part.value) live[name] = part.value;\n }\n}\n\n/**\n * Development: the element shows what `part` adopted. Form state the user edits is compared\n * by its attribute or default text, which edits don't change; `?open` isn't compared. `fail`\n * throws the walk's mismatch.\n */\nexport function checkAttr(\n part: AttrPart,\n fail: (expected: string, found: string, at: Node) => never,\n): void {\n const { el, name, value } = part;\n let want: unknown = value;\n let got: unknown;\n switch (part.kind) {\n case ATTR:\n case VALUE:\n case MULTI:\n // A style the CSP blocked can't be compared: Firefox empties the attribute.\n if (name === 'style' && el.hasAttribute(name) && (el as HTMLElement).style.length === 0) {\n return;\n }\n if (part.kind !== MULTI) want = absent(value) ? null : String(value);\n got = el.getAttribute(name);\n break;\n case BOOL:\n case CHECKED:\n got = el.hasAttribute(name);\n break;\n case TITLE:\n case TEXTAREA:\n got = el.textContent;\n break;\n default:\n return;\n }\n if (got !== want) {\n const what = name === '' ? 'content' : name;\n fail(`${what} ${JSON.stringify(want)}`, `${JSON.stringify(got)} on <${el.localName}>`, el);\n }\n}\n"]}