@gyral/core 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (340) hide show
  1. package/CHANGELOG.md +112 -0
  2. package/LICENSE +1 -1
  3. package/NOTICE +1 -1
  4. package/README.md +9 -7
  5. package/dist/children.d.ts +5 -2
  6. package/dist/children.js +8 -3
  7. package/dist/children.js.map +1 -1
  8. package/dist/command.js +6 -0
  9. package/dist/command.js.map +1 -1
  10. package/dist/compiler/ast.d.ts +21 -0
  11. package/dist/compiler/ast.js +145 -0
  12. package/dist/compiler/ast.js.map +1 -0
  13. package/dist/compiler/compile.d.ts +38 -0
  14. package/dist/compiler/compile.js +129 -0
  15. package/dist/compiler/compile.js.map +1 -0
  16. package/dist/compiler/hooks.d.ts +18 -0
  17. package/dist/compiler/hooks.js +186 -0
  18. package/dist/compiler/hooks.js.map +1 -0
  19. package/dist/compiler/parse5-check.d.ts +21 -0
  20. package/dist/compiler/parse5-check.js +55 -0
  21. package/dist/compiler/parse5-check.js.map +1 -0
  22. package/dist/compiler/scan.d.ts +31 -0
  23. package/dist/compiler/scan.js +152 -0
  24. package/dist/compiler/scan.js.map +1 -0
  25. package/dist/compiler/source.d.ts +34 -0
  26. package/dist/compiler/source.js +114 -0
  27. package/dist/compiler/source.js.map +1 -0
  28. package/dist/define.d.ts +2 -2
  29. package/dist/define.js +35 -334
  30. package/dist/define.js.map +1 -1
  31. package/dist/devtools-events.d.ts +5 -0
  32. package/dist/devtools-events.js.map +1 -1
  33. package/dist/devtools-off.d.ts +1 -0
  34. package/dist/devtools-off.js +1 -0
  35. package/dist/devtools-off.js.map +1 -1
  36. package/dist/devtools.d.ts +1 -0
  37. package/dist/devtools.js +3 -0
  38. package/dist/devtools.js.map +1 -1
  39. package/dist/drivers-scope.d.ts +1 -1
  40. package/dist/drivers-scope.js +1 -8
  41. package/dist/drivers-scope.js.map +1 -1
  42. package/dist/element-types.d.ts +5 -3
  43. package/dist/element-types.js.map +1 -1
  44. package/dist/element.d.ts +3 -0
  45. package/dist/element.js +269 -0
  46. package/dist/element.js.map +1 -0
  47. package/dist/eslint/imports.d.ts +24 -0
  48. package/dist/eslint/imports.js +78 -0
  49. package/dist/eslint/imports.js.map +1 -0
  50. package/dist/eslint/index.d.ts +15 -0
  51. package/dist/eslint/index.js +15 -0
  52. package/dist/eslint/index.js.map +1 -0
  53. package/dist/eslint/locate.d.ts +33 -0
  54. package/dist/eslint/locate.js +132 -0
  55. package/dist/eslint/locate.js.map +1 -0
  56. package/dist/eslint/row-purity-rule.d.ts +2 -0
  57. package/dist/eslint/row-purity-rule.js +103 -0
  58. package/dist/eslint/row-purity-rule.js.map +1 -0
  59. package/dist/eslint/template-rule.d.ts +5 -0
  60. package/dist/eslint/template-rule.js +66 -0
  61. package/dist/eslint/template-rule.js.map +1 -0
  62. package/dist/features.d.ts +39 -0
  63. package/dist/features.js +2 -0
  64. package/dist/features.js.map +1 -0
  65. package/dist/focus.d.ts +9 -2
  66. package/dist/focus.js +17 -2
  67. package/dist/focus.js.map +1 -1
  68. package/dist/hooks/invalid.d.ts +14 -0
  69. package/dist/hooks/invalid.js +72 -0
  70. package/dist/hooks/invalid.js.map +1 -0
  71. package/dist/hooks/labelled-by.d.ts +13 -0
  72. package/dist/hooks/labelled-by.js +51 -0
  73. package/dist/hooks/labelled-by.js.map +1 -0
  74. package/dist/host-model.d.ts +48 -0
  75. package/dist/host-model.js +155 -0
  76. package/dist/host-model.js.map +1 -0
  77. package/dist/hydration-client.d.ts +9 -0
  78. package/dist/hydration-client.js +35 -0
  79. package/dist/hydration-client.js.map +1 -0
  80. package/dist/hydration.d.ts +13 -19
  81. package/dist/hydration.js +45 -45
  82. package/dist/hydration.js.map +1 -1
  83. package/dist/index.d.ts +9 -16
  84. package/dist/index.js +9 -16
  85. package/dist/index.js.map +1 -1
  86. package/dist/intent.d.ts +31 -8
  87. package/dist/intent.js +82 -27
  88. package/dist/intent.js.map +1 -1
  89. package/dist/internal/interpreter.d.ts +7 -1
  90. package/dist/internal/interpreter.js +118 -73
  91. package/dist/internal/interpreter.js.map +1 -1
  92. package/dist/invokers-shim.d.ts +6 -0
  93. package/dist/invokers-shim.js +32 -0
  94. package/dist/invokers-shim.js.map +1 -0
  95. package/dist/invokers.d.ts +3 -5
  96. package/dist/invokers.js +11 -51
  97. package/dist/invokers.js.map +1 -1
  98. package/dist/islands.d.ts +0 -2
  99. package/dist/islands.js +4 -11
  100. package/dist/islands.js.map +1 -1
  101. package/dist/light-dom.d.ts +3 -52
  102. package/dist/light-dom.js +5 -100
  103. package/dist/light-dom.js.map +1 -1
  104. package/dist/prop.d.ts +66 -0
  105. package/dist/prop.js +22 -0
  106. package/dist/prop.js.map +1 -0
  107. package/dist/props.d.ts +52 -21
  108. package/dist/props.js +150 -34
  109. package/dist/props.js.map +1 -1
  110. package/dist/scheduler.d.ts +39 -0
  111. package/dist/scheduler.js +230 -0
  112. package/dist/scheduler.js.map +1 -0
  113. package/dist/server-component.d.ts +10 -0
  114. package/dist/server-component.js +102 -0
  115. package/dist/server-component.js.map +1 -0
  116. package/dist/server-specs.d.ts +6 -0
  117. package/dist/server-specs.js +13 -0
  118. package/dist/server-specs.js.map +1 -0
  119. package/dist/server.d.ts +28 -0
  120. package/dist/server.js +50 -0
  121. package/dist/server.js.map +1 -0
  122. package/dist/settled.d.ts +10 -0
  123. package/dist/settled.js +40 -0
  124. package/dist/settled.js.map +1 -0
  125. package/dist/states.d.ts +3 -3
  126. package/dist/states.js +4 -7
  127. package/dist/states.js.map +1 -1
  128. package/dist/store-binding.d.ts +6 -3
  129. package/dist/store-binding.js +5 -6
  130. package/dist/store-binding.js.map +1 -1
  131. package/dist/store-scope.d.ts +6 -7
  132. package/dist/store-scope.js +11 -26
  133. package/dist/store-scope.js.map +1 -1
  134. package/dist/store.d.ts +3 -0
  135. package/dist/store.js +9 -2
  136. package/dist/store.js.map +1 -1
  137. package/dist/stores-provider.d.ts +2 -6
  138. package/dist/stores-provider.js +21 -55
  139. package/dist/stores-provider.js.map +1 -1
  140. package/dist/transitions.d.ts +5 -6
  141. package/dist/transitions.js +11 -20
  142. package/dist/transitions.js.map +1 -1
  143. package/dist/types.d.ts +19 -23
  144. package/dist/types.js.map +1 -1
  145. package/dist/view/attributes.d.ts +6 -0
  146. package/dist/view/attributes.js +10 -0
  147. package/dist/view/attributes.js.map +1 -0
  148. package/dist/view/compiled.d.ts +1 -0
  149. package/dist/view/compiled.js +6 -0
  150. package/dist/view/compiled.js.map +1 -0
  151. package/dist/view/dev-off.d.ts +1 -0
  152. package/dist/view/dev-off.js +4 -0
  153. package/dist/view/dev-off.js.map +1 -0
  154. package/dist/view/dev.d.ts +1 -0
  155. package/dist/view/dev.js +5 -0
  156. package/dist/view/dev.js.map +1 -0
  157. package/dist/view/flags.d.ts +1 -0
  158. package/dist/view/flags.js +4 -0
  159. package/dist/view/flags.js.map +1 -0
  160. package/dist/view/index.d.ts +21 -0
  161. package/dist/view/index.js +21 -0
  162. package/dist/view/index.js.map +1 -0
  163. package/dist/view/normalize/check.d.ts +20 -0
  164. package/dist/view/normalize/check.js +78 -0
  165. package/dist/view/normalize/check.js.map +1 -0
  166. package/dist/view/normalize/emit.d.ts +13 -0
  167. package/dist/view/normalize/emit.js +136 -0
  168. package/dist/view/normalize/emit.js.map +1 -0
  169. package/dist/view/normalize/entities.d.ts +4 -0
  170. package/dist/view/normalize/entities.js +38 -0
  171. package/dist/view/normalize/entities.js.map +1 -0
  172. package/dist/view/normalize/errors.d.ts +9 -0
  173. package/dist/view/normalize/errors.js +19 -0
  174. package/dist/view/normalize/errors.js.map +1 -0
  175. package/dist/view/normalize/id.d.ts +7 -0
  176. package/dist/view/normalize/id.js +48 -0
  177. package/dist/view/normalize/id.js.map +1 -0
  178. package/dist/view/normalize/normalize.d.ts +15 -0
  179. package/dist/view/normalize/normalize.js +36 -0
  180. package/dist/view/normalize/normalize.js.map +1 -0
  181. package/dist/view/normalize/repairs.d.ts +24 -0
  182. package/dist/view/normalize/repairs.js +166 -0
  183. package/dist/view/normalize/repairs.js.map +1 -0
  184. package/dist/view/normalize/rules.d.ts +30 -0
  185. package/dist/view/normalize/rules.js +90 -0
  186. package/dist/view/normalize/rules.js.map +1 -0
  187. package/dist/view/normalize/shape.d.ts +5 -0
  188. package/dist/view/normalize/shape.js +38 -0
  189. package/dist/view/normalize/shape.js.map +1 -0
  190. package/dist/view/normalize/source.d.ts +13 -0
  191. package/dist/view/normalize/source.js +34 -0
  192. package/dist/view/normalize/source.js.map +1 -0
  193. package/dist/view/normalize/tag-states.d.ts +23 -0
  194. package/dist/view/normalize/tag-states.js +192 -0
  195. package/dist/view/normalize/tag-states.js.map +1 -0
  196. package/dist/view/normalize/tokenizer.d.ts +5 -0
  197. package/dist/view/normalize/tokenizer.js +233 -0
  198. package/dist/view/normalize/tokenizer.js.map +1 -0
  199. package/dist/view/normalize/tokens.d.ts +51 -0
  200. package/dist/view/normalize/tokens.js +24 -0
  201. package/dist/view/normalize/tokens.js.map +1 -0
  202. package/dist/view/normalize/tree.d.ts +59 -0
  203. package/dist/view/normalize/tree.js +190 -0
  204. package/dist/view/normalize/tree.js.map +1 -0
  205. package/dist/view/normalize/types.d.ts +126 -0
  206. package/dist/view/normalize/types.js +26 -0
  207. package/dist/view/normalize/types.js.map +1 -0
  208. package/dist/view/normalize/whitespace.d.ts +2 -0
  209. package/dist/view/normalize/whitespace.js +182 -0
  210. package/dist/view/normalize/whitespace.js.map +1 -0
  211. package/dist/view/prepare-stub.d.ts +3 -0
  212. package/dist/view/prepare-stub.js +7 -0
  213. package/dist/view/prepare-stub.js.map +1 -0
  214. package/dist/view/prepare.d.ts +8 -0
  215. package/dist/view/prepare.js +57 -0
  216. package/dist/view/prepare.js.map +1 -0
  217. package/dist/view/registry.d.ts +63 -0
  218. package/dist/view/registry.js +19 -0
  219. package/dist/view/registry.js.map +1 -0
  220. package/dist/view/render/adopt-attr.d.ts +14 -0
  221. package/dist/view/render/adopt-attr.js +77 -0
  222. package/dist/view/render/adopt-attr.js.map +1 -0
  223. package/dist/view/render/adopt-plan.d.ts +10 -0
  224. package/dist/view/render/adopt-plan.js +26 -0
  225. package/dist/view/render/adopt-plan.js.map +1 -0
  226. package/dist/view/render/adopt.d.ts +3 -0
  227. package/dist/view/render/adopt.js +269 -0
  228. package/dist/view/render/adopt.js.map +1 -0
  229. package/dist/view/render/attr-parts.d.ts +61 -0
  230. package/dist/view/render/attr-parts.js +229 -0
  231. package/dist/view/render/attr-parts.js.map +1 -0
  232. package/dist/view/render/child-part.d.ts +51 -0
  233. package/dist/view/render/child-part.js +170 -0
  234. package/dist/view/render/child-part.js.map +1 -0
  235. package/dist/view/render/dev-check.d.ts +12 -0
  236. package/dist/view/render/dev-check.js +122 -0
  237. package/dist/view/render/dev-check.js.map +1 -0
  238. package/dist/view/render/hook-part.d.ts +3 -0
  239. package/dist/view/render/hook-part.js +20 -0
  240. package/dist/view/render/hook-part.js.map +1 -0
  241. package/dist/view/render/hooks.d.ts +40 -0
  242. package/dist/view/render/hooks.js +46 -0
  243. package/dist/view/render/hooks.js.map +1 -0
  244. package/dist/view/render/hydrate.d.ts +10 -0
  245. package/dist/view/render/hydrate.js +33 -0
  246. package/dist/view/render/hydrate.js.map +1 -0
  247. package/dist/view/render/instance.d.ts +33 -0
  248. package/dist/view/render/instance.js +107 -0
  249. package/dist/view/render/instance.js.map +1 -0
  250. package/dist/view/render/list.d.ts +20 -0
  251. package/dist/view/render/list.js +156 -0
  252. package/dist/view/render/list.js.map +1 -0
  253. package/dist/view/render/mismatch.d.ts +10 -0
  254. package/dist/view/render/mismatch.js +53 -0
  255. package/dist/view/render/mismatch.js.map +1 -0
  256. package/dist/view/render/nodes.d.ts +10 -0
  257. package/dist/view/render/nodes.js +37 -0
  258. package/dist/view/render/nodes.js.map +1 -0
  259. package/dist/view/render/place.d.ts +18 -0
  260. package/dist/view/render/place.js +69 -0
  261. package/dist/view/render/place.js.map +1 -0
  262. package/dist/view/render/plan.d.ts +26 -0
  263. package/dist/view/render/plan.js +124 -0
  264. package/dist/view/render/plan.js.map +1 -0
  265. package/dist/view/render/raw.d.ts +18 -0
  266. package/dist/view/render/raw.js +68 -0
  267. package/dist/view/render/raw.js.map +1 -0
  268. package/dist/view/render/render.d.ts +12 -0
  269. package/dist/view/render/render.js +60 -0
  270. package/dist/view/render/render.js.map +1 -0
  271. package/dist/view/render/reorder.d.ts +4 -0
  272. package/dist/view/render/reorder.js +101 -0
  273. package/dist/view/render/reorder.js.map +1 -0
  274. package/dist/view/render/rows.d.ts +23 -0
  275. package/dist/view/render/rows.js +95 -0
  276. package/dist/view/render/rows.js.map +1 -0
  277. package/dist/view/render/seen.d.ts +11 -0
  278. package/dist/view/render/seen.js +17 -0
  279. package/dist/view/render/seen.js.map +1 -0
  280. package/dist/view/render/values.d.ts +29 -0
  281. package/dist/view/render/values.js +13 -0
  282. package/dist/view/render/values.js.map +1 -0
  283. package/dist/view/render/warn.d.ts +14 -0
  284. package/dist/view/render/warn.js +69 -0
  285. package/dist/view/render/warn.js.map +1 -0
  286. package/dist/view/server/component.d.ts +9 -0
  287. package/dist/view/server/component.js +42 -0
  288. package/dist/view/server/component.js.map +1 -0
  289. package/dist/view/server/escape.d.ts +10 -0
  290. package/dist/view/server/escape.js +34 -0
  291. package/dist/view/server/escape.js.map +1 -0
  292. package/dist/view/server/index.d.ts +28 -0
  293. package/dist/view/server/index.js +72 -0
  294. package/dist/view/server/index.js.map +1 -0
  295. package/dist/view/server/sha256.d.ts +2 -0
  296. package/dist/view/server/sha256.js +75 -0
  297. package/dist/view/server/sha256.js.map +1 -0
  298. package/dist/view/server/tags.d.ts +57 -0
  299. package/dist/view/server/tags.js +121 -0
  300. package/dist/view/server/tags.js.map +1 -0
  301. package/dist/view/server/values.d.ts +16 -0
  302. package/dist/view/server/values.js +86 -0
  303. package/dist/view/server/values.js.map +1 -0
  304. package/dist/view/server/writer.d.ts +16 -0
  305. package/dist/view/server/writer.js +155 -0
  306. package/dist/view/server/writer.js.map +1 -0
  307. package/dist/view/styles.d.ts +25 -0
  308. package/dist/view/styles.js +58 -0
  309. package/dist/view/styles.js.map +1 -0
  310. package/dist/view/template-element.d.ts +3 -0
  311. package/dist/view/template-element.js +25 -0
  312. package/dist/view/template-element.js.map +1 -0
  313. package/dist/view/template.d.ts +21 -0
  314. package/dist/view/template.js +30 -0
  315. package/dist/view/template.js.map +1 -0
  316. package/dist/vite.d.ts +45 -6
  317. package/dist/vite.js +150 -25
  318. package/dist/vite.js.map +1 -1
  319. package/package.json +41 -7
  320. package/dist/accessible-name.d.ts +0 -19
  321. package/dist/accessible-name.js +0 -56
  322. package/dist/accessible-name.js.map +0 -1
  323. package/dist/element-directive.d.ts +0 -20
  324. package/dist/element-directive.js +0 -31
  325. package/dist/element-directive.js.map +0 -1
  326. package/dist/internal/runtime.d.ts +0 -7
  327. package/dist/internal/runtime.js +0 -8
  328. package/dist/internal/runtime.js.map +0 -1
  329. package/dist/invalid.d.ts +0 -21
  330. package/dist/invalid.js +0 -70
  331. package/dist/invalid.js.map +0 -1
  332. package/dist/live-boolean.d.ts +0 -22
  333. package/dist/live-boolean.js +0 -34
  334. package/dist/live-boolean.js.map +0 -1
  335. package/dist/styles.d.ts +0 -12
  336. package/dist/styles.js +0 -11
  337. package/dist/styles.js.map +0 -1
  338. package/dist/textarea.d.ts +0 -26
  339. package/dist/textarea.js +0 -85
  340. package/dist/textarea.js.map +0 -1
@@ -0,0 +1,8 @@
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;
4
+ /**
5
+ * Throws rule 7 when the browser's parse of `template.html` (in `el`) differs from the tree
6
+ * the normalizer computed paths for. Templates that didn't come from `prepare` are skipped.
7
+ */
8
+ export declare function verify(template: TemplateObject, el: HTMLTemplateElement): void;
@@ -0,0 +1,57 @@
1
+ // The runtime template preparer (view/01-templates.md "Runtime"), resolved through core's
2
+ // `#prepare` import by default. It runs the normalizer once per call site (template.ts caches
3
+ // the result) and, when the browser first parses a template's HTML (template-element.ts),
4
+ // checks that the parse built exactly the DOM the normalizer's paths assume. A difference
5
+ // means the parser repaired the markup: rule 7 (view/09-template-rules.md). Builds made with
6
+ // the `gyral-compiled` condition get prepare-stub.ts instead.
7
+ import { recordTemplateId } from './normalize/id.js';
8
+ import { analyze } from './normalize/normalize.js';
9
+ import { repairError, shapeMismatch } from './normalize/shape.js';
10
+ const shapes = new WeakMap();
11
+ const prepared = new WeakMap();
12
+ // One-entry cache in front of the WeakMap: list rows ask for the same call site in a row.
13
+ let lastSource;
14
+ let lastTemplate;
15
+ /** The template object of a call site's strings, normalized (with development checks) once. */
16
+ export function prepare(strings) {
17
+ if (strings === lastSource)
18
+ return lastTemplate;
19
+ let template = prepared.get(strings);
20
+ if (template === undefined) {
21
+ const analysis = analyze(strings);
22
+ template = analysis.template;
23
+ recordTemplateId(analysis.template.id, analysis.strings);
24
+ shapes.set(template, analysis.shape);
25
+ prepared.set(strings, template);
26
+ }
27
+ lastSource = strings;
28
+ lastTemplate = template;
29
+ return template;
30
+ }
31
+ /** The DOM the browser built, as a Shape (lower-case names, <template> content inlined). */
32
+ function domShape(nodes) {
33
+ return [...nodes].map((node) => {
34
+ if (node.nodeType === 3)
35
+ return '#text';
36
+ if (node.nodeType === 8)
37
+ return '#comment';
38
+ if (node.nodeType !== 1)
39
+ return [node.nodeName.toLowerCase(), []];
40
+ const el = node;
41
+ const children = el.localName === 'template' ? el.content.childNodes : el.childNodes;
42
+ return [el.localName.toLowerCase(), domShape(children)];
43
+ });
44
+ }
45
+ /**
46
+ * Throws rule 7 when the browser's parse of `template.html` (in `el`) differs from the tree
47
+ * the normalizer computed paths for. Templates that didn't come from `prepare` are skipped.
48
+ */
49
+ export function verify(template, el) {
50
+ const shape = shapes.get(template);
51
+ if (shape === undefined)
52
+ return;
53
+ const problem = shapeMismatch(shape, domShape(el.content.childNodes));
54
+ if (problem !== undefined)
55
+ throw repairError(template, "The browser's HTML parser", problem);
56
+ }
57
+ //# sourceMappingURL=prepare.js.map
@@ -0,0 +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"]}
@@ -0,0 +1,63 @@
1
+ import type { ChildValue } from './render/values.js';
2
+ /** What a server render of one component returns: its view and what its seed must carry. */
3
+ export interface ServerRendering {
4
+ /** `view(state, intents, ctx)` for the resolved props and state. */
5
+ readonly view: ChildValue;
6
+ /**
7
+ * The `data-gyral-seed` payload (ADR 0012): `props` that no attribute carries, and `state`
8
+ * unless it equals `init(props)`'s state. JSON-serializable.
9
+ */
10
+ readonly seed: {
11
+ readonly state?: unknown;
12
+ readonly props: Readonly<Record<string, unknown>>;
13
+ };
14
+ }
15
+ /** The input of one server render, gathered from the start tag (06 "Components"). */
16
+ export interface ServerRenderInput {
17
+ /** Static attributes plus attribute/boolean holes, as strings (`''` for a present boolean). */
18
+ readonly attributes: Readonly<Record<string, string>>;
19
+ /** Property holes: values as is. */
20
+ readonly properties: Readonly<Record<string, unknown>>;
21
+ /** Messages run through their reducers after `init` (ADR 0008's rejected-form re-render). */
22
+ readonly initialMessages?: readonly unknown[] | undefined;
23
+ /**
24
+ * The nearest provider's scope (opaque to view/), or undefined for the request's own scope.
25
+ * The renderer passes it down: a provider's subtree can span several streamed chunks, so a
26
+ * global set around the subtree would not survive between pulls.
27
+ */
28
+ readonly scope?: unknown;
29
+ }
30
+ /** One registered component, as the server renderer sees it. */
31
+ export interface ServerComponent {
32
+ readonly tag: string;
33
+ /** `shadow: false` (ADR 0014): render as light-DOM children, not `<template shadowrootmode>`. */
34
+ readonly light: boolean;
35
+ /** CSS texts for the declarative shadow root's `<style>` (08). Empty for light components. */
36
+ readonly styles: readonly string[];
37
+ /** The island strategy (07): anything but `load` adds `defer-hydration` and `data-gyral-hydrate`. */
38
+ readonly hydrate: 'load' | 'idle' | 'visible' | 'interaction';
39
+ /** Parses props (validated as in the browser), runs `init` (commands dropped) and the view. */
40
+ render(input: ServerRenderInput): ServerRendering;
41
+ }
42
+ /** Records a component. A tag registered twice keeps its first entry, as `customElements` does. */
43
+ export declare function registerServerComponent(component: ServerComponent): void;
44
+ /** The component registered under `tag`, if any. */
45
+ export declare const serverComponent: (tag: string) => ServerComponent | undefined;
46
+ /** Every registered component (for `styleHashes()`, 06 "CSP"). */
47
+ export declare const serverComponents: () => readonly ServerComponent[];
48
+ /**
49
+ * A server-side provider element (`<gyral-stores>`, ADR 0013): written as a plain element, it
50
+ * gives its subtree a scope (passed to components as `ServerRenderInput.scope`) and may add
51
+ * attributes to its start tag (its seed).
52
+ */
53
+ export interface ServerProvider {
54
+ readonly tag: string;
55
+ open(input: ServerRenderInput): {
56
+ readonly scope: unknown;
57
+ readonly attributes: Readonly<Record<string, string>>;
58
+ };
59
+ }
60
+ /** Records a provider element. A tag registered twice keeps its first entry. */
61
+ export declare function registerServerProvider(provider: ServerProvider): void;
62
+ /** The provider registered under `tag`, if any. */
63
+ export declare const serverProvider: (tag: string) => ServerProvider | undefined;
@@ -0,0 +1,19 @@
1
+ const components = new Map();
2
+ /** Records a component. A tag registered twice keeps its first entry, as `customElements` does. */
3
+ export function registerServerComponent(component) {
4
+ if (!components.has(component.tag))
5
+ components.set(component.tag, component);
6
+ }
7
+ /** The component registered under `tag`, if any. */
8
+ export const serverComponent = (tag) => components.get(tag);
9
+ /** Every registered component (for `styleHashes()`, 06 "CSP"). */
10
+ export const serverComponents = () => [...components.values()];
11
+ const providers = new Map();
12
+ /** Records a provider element. A tag registered twice keeps its first entry. */
13
+ export function registerServerProvider(provider) {
14
+ if (!providers.has(provider.tag))
15
+ providers.set(provider.tag, provider);
16
+ }
17
+ /** The provider registered under `tag`, if any. */
18
+ export const serverProvider = (tag) => providers.get(tag);
19
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +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"]}
@@ -0,0 +1,14 @@
1
+ import { type AttrPart } from './attr-parts.js';
2
+ /**
3
+ * Takes this render's values as committed without writing (the server wrote them). Form state
4
+ * the user changed before scripts ran stays: like every part, it writes only when the model's
5
+ * value changes (07 "Form state"). `?indeterminate`, which no attribute carries, is set; a
6
+ * property is set unless a nested component already has it from its own seed.
7
+ */
8
+ export declare function adoptAttr(part: AttrPart, values: readonly unknown[]): void;
9
+ /**
10
+ * Development: the element shows what `part` adopted. Form state the user edits is compared
11
+ * by its attribute or default text, which edits don't change; `?open` isn't compared. `fail`
12
+ * throws the walk's mismatch.
13
+ */
14
+ export declare function checkAttr(part: AttrPart, fail: (expected: string, found: string, at: Node) => never): void;
@@ -0,0 +1,77 @@
1
+ // Element parts in hydration (view/07-hydration.md "The parallel walk", "Form state"): an
2
+ // attribute, property, hook or text part built over server DOM takes this render's values as
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';
5
+ /**
6
+ * Takes this render's values as committed without writing (the server wrote them). Form state
7
+ * the user changed before scripts ran stays: like every part, it writes only when the model's
8
+ * value changes (07 "Form state"). `?indeterminate`, which no attribute carries, is set; a
9
+ * property is set unless a nested component already has it from its own seed.
10
+ */
11
+ export function adoptAttr(part, values) {
12
+ const v = values[part.at];
13
+ const el = part.el;
14
+ const live = el;
15
+ const name = part.name;
16
+ const kind = part.kind;
17
+ if (kind === HOOK)
18
+ part.hook(v);
19
+ else if (kind === PROP) {
20
+ part.value = v;
21
+ const own = live[name] !== undefined && el.localName.includes('-');
22
+ if (!own && !Object.is(live[name], v))
23
+ live[name] = v;
24
+ }
25
+ else if (kind === MULTI) {
26
+ const pieces = part.pieces;
27
+ for (let i = 0; i < pieces.length; i++)
28
+ pieces[i] = values[part.at + i];
29
+ part.value = part.join(pieces);
30
+ }
31
+ else if (kind === ATTR || kind === VALUE) {
32
+ part.value = v;
33
+ if (kind === VALUE && PLAIN.test(el.type))
34
+ part.kind = ATTR;
35
+ }
36
+ else if (kind === TITLE || kind === TEXTAREA)
37
+ part.value = textOf(part, v);
38
+ else {
39
+ part.value = truthy(v);
40
+ if (kind === STATE && live[name] !== part.value)
41
+ live[name] = part.value;
42
+ }
43
+ }
44
+ /**
45
+ * Development: the element shows what `part` adopted. Form state the user edits is compared
46
+ * by its attribute or default text, which edits don't change; `?open` isn't compared. `fail`
47
+ * throws the walk's mismatch.
48
+ */
49
+ export function checkAttr(part, fail) {
50
+ const { el, name, value } = part;
51
+ let want = value;
52
+ let got;
53
+ switch (part.kind) {
54
+ case ATTR:
55
+ case VALUE:
56
+ case MULTI:
57
+ if (part.kind !== MULTI)
58
+ want = absent(value) ? null : String(value);
59
+ got = el.getAttribute(name);
60
+ break;
61
+ case BOOL:
62
+ case CHECKED:
63
+ got = el.hasAttribute(name);
64
+ break;
65
+ case TITLE:
66
+ case TEXTAREA:
67
+ got = el.textContent;
68
+ break;
69
+ default:
70
+ return;
71
+ }
72
+ if (got !== want) {
73
+ const what = name === '' ? 'content' : name;
74
+ fail(`${what} ${JSON.stringify(want)}`, `${JSON.stringify(got)} on <${el.localName}>`, el);
75
+ }
76
+ }
77
+ //# sourceMappingURL=adopt-attr.js.map
@@ -0,0 +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"]}
@@ -0,0 +1,10 @@
1
+ import type { PartSpec, TemplateObject } from '../normalize/types.js';
2
+ import { type Plan } from './plan.js';
3
+ /** Per template: its element parts per static element, its child holes per parent node. */
4
+ export interface Adoption {
5
+ readonly plan: Plan;
6
+ readonly specs: readonly PartSpec[];
7
+ readonly attrs: Map<Node, number[]>;
8
+ readonly holes: Map<Node, number[]>;
9
+ }
10
+ export declare function adoptionOf(template: TemplateObject): Adoption;
@@ -0,0 +1,26 @@
1
+ import { nodes, planOf, stack, walk } from './plan.js';
2
+ const adoptions = new WeakMap();
3
+ export function adoptionOf(template) {
4
+ let a = adoptions.get(template);
5
+ if (a !== undefined)
6
+ return a;
7
+ const plan = planOf(template);
8
+ // The plan's targets in the template's own content: where each part sits.
9
+ stack[0] = plan.content;
10
+ if (plan.single)
11
+ stack[1] = plan.content.firstChild;
12
+ walk(plan);
13
+ a = { plan, specs: template.parts, attrs: new Map(), holes: new Map() };
14
+ for (let i = 0; i < plan.kinds.length; i++) {
15
+ const node = nodes[plan.a[i]];
16
+ const map = plan.kinds[i] >= 0 ? a.attrs : a.holes;
17
+ const list = map.get(node);
18
+ if (list === undefined)
19
+ map.set(node, [i]);
20
+ else
21
+ list.push(i);
22
+ }
23
+ adoptions.set(template, a);
24
+ return a;
25
+ }
26
+ //# sourceMappingURL=adopt-plan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adopt-plan.js","sourceRoot":"","sources":["../../../src/view/render/adopt-plan.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAa,MAAM,WAAW,CAAC;AAUlE,MAAM,SAAS,GAAG,IAAI,OAAO,EAA4B,CAAC;AAE1D,MAAM,UAAU,UAAU,CAAC,QAAwB;IACjD,IAAI,CAAC,GAAG,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAChC,IAAI,CAAC,KAAK,SAAS;QAAE,OAAO,CAAC,CAAC;IAC9B,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC9B,0EAA0E;IAC1E,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC;IACxB,IAAI,IAAI,CAAC,MAAM;QAAE,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,UAAkB,CAAC;IAC5D,IAAI,CAAC,IAAI,CAAC,CAAC;IACX,CAAC,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,GAAG,EAAE,EAAE,KAAK,EAAE,IAAI,GAAG,EAAE,EAAE,CAAC;IACxE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3C,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAW,CAAS,CAAC;QAChD,MAAM,GAAG,GAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAY,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;QAC/D,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC3B,IAAI,IAAI,KAAK,SAAS;YAAE,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;;YACtC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;IACD,SAAS,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;IAC3B,OAAO,CAAC,CAAC;AACX,CAAC","sourcesContent":["// Per-template data for the hydration walk (adopt.ts, view/07-hydration.md \"The parallel\n// walk\"): which parts sit on each static element of the template's parsed content, and which\n// child holes sit in each parent node, in order. Computed once per template from its plan.\nimport type { PartSpec, TemplateObject } from '../normalize/types.js';\nimport { nodes, planOf, stack, walk, type Plan } from './plan.js';\n\n/** Per template: its element parts per static element, its child holes per parent node. */\nexport interface Adoption {\n readonly plan: Plan;\n readonly specs: readonly PartSpec[];\n readonly attrs: Map<Node, number[]>;\n readonly holes: Map<Node, number[]>;\n}\n\nconst adoptions = new WeakMap<TemplateObject, Adoption>();\n\nexport function adoptionOf(template: TemplateObject): Adoption {\n let a = adoptions.get(template);\n if (a !== undefined) return a;\n const plan = planOf(template);\n // The plan's targets in the template's own content: where each part sits.\n stack[0] = plan.content;\n if (plan.single) stack[1] = plan.content.firstChild as Node;\n walk(plan);\n a = { plan, specs: template.parts, attrs: new Map(), holes: new Map() };\n for (let i = 0; i < plan.kinds.length; i++) {\n const node = nodes[plan.a[i] as number] as Node;\n const map = (plan.kinds[i] as number) >= 0 ? a.attrs : a.holes;\n const list = map.get(node);\n if (list === undefined) map.set(node, [i]);\n else list.push(i);\n }\n adoptions.set(template, a);\n return a;\n}\n"]}
@@ -0,0 +1,3 @@
1
+ import { ChildPart } from './child-part.js';
2
+ /** Adopts the server DOM in `root` (a host's root) as `part`'s content for `value`. */
3
+ export declare function adopt(part: ChildPart, value: unknown, root: Node, label: string): void;
@@ -0,0 +1,269 @@
1
+ // The parallel walk (view/07-hydration.md "The parallel walk"): visits a template's static
2
+ // structure (its parsed content) and the server DOM together, and builds the same parts the
3
+ // client renderer would, with this render's values as committed values. It writes nothing,
4
+ // except splitting merged text at known lengths (`splitText`), creating the empty Text node of
5
+ // an `''` value, joining text the parser split, and removing development markers. Nested
6
+ // templates, lists (rows one after another, no markers), arrays and `raw()` are walked in
7
+ // turn. Nested Gyral hosts: a shadow host's light children are the parent's content (slotted)
8
+ // and are walked; its shadow root never is; a light host (`data-gyral-light`) is opaque.
9
+ // Development checks every node, text and bound attribute, and the `<!--gyral:ID-->` markers
10
+ // when present; production checks node types, local names and text lengths.
11
+ import { DEV } from '#view-dev';
12
+ import { LIGHT_ATTRIBUTE } from '../attributes.js';
13
+ import { CHILD_BEFORE } from '../normalize/types.js';
14
+ import { isTemplateResult, sourceOf, templateOf } from '../template.js';
15
+ import { adoptionOf } from './adopt-plan.js';
16
+ import { adoptAttr, checkAttr } from './adopt-attr.js';
17
+ import { attrPart, TEXTAREA, TITLE } from './attr-parts.js';
18
+ import { ChildPart, INSTANCE, ITEMS, LIST, RAW, TEXT } from './child-part.js';
19
+ import { checkKeys } from './dev-check.js';
20
+ import { Instance } from './instance.js';
21
+ import { mismatch } from './mismatch.js';
22
+ import { ROOT, SOLE } from './plan.js';
23
+ import { parse, RawRange } from './raw.js';
24
+ import { report } from './seen.js';
25
+ import { List } from './rows.js';
26
+ import { isList, rawHtml } from './values.js';
27
+ /** The walk's position: the next DOM node; null at the end of `parent`'s children. */
28
+ let cur = null;
29
+ let parent;
30
+ /** For mismatch messages: the host's root, the component, the template being walked. */
31
+ let top;
32
+ let host = '';
33
+ let current;
34
+ const fail = (expected, found = cur, at = parent) => mismatch(expected, found, at, top, host, current?.loc);
35
+ /** Adopts the server DOM in `root` (a host's root) as `part`'s content for `value`. */
36
+ export function adopt(part, value, root, label) {
37
+ top = parent = root;
38
+ cur = root.firstChild;
39
+ host = label;
40
+ current = undefined;
41
+ content(part, value);
42
+ if (cur !== null)
43
+ fail('the end of the view');
44
+ }
45
+ /** A child value at the walk's position (view/02-bindings.md "Child values"). */
46
+ function content(part, v) {
47
+ switch (typeof v) {
48
+ case 'string':
49
+ case 'number': {
50
+ const data = typeof v === 'string' ? v : String(v);
51
+ part.kind = TEXT;
52
+ part.value = v;
53
+ if (data !== '')
54
+ part.content = text(data);
55
+ else
56
+ parent.insertBefore((part.content = document.createTextNode('')), cur);
57
+ return;
58
+ }
59
+ case 'object':
60
+ if (v === null)
61
+ return;
62
+ if (isTemplateResult(v)) {
63
+ part.kind = INSTANCE;
64
+ part.content = instance(v, part);
65
+ }
66
+ else if (isList(v))
67
+ rows(part, v.items, v);
68
+ else if (Array.isArray(v))
69
+ rows(part, v, undefined);
70
+ else {
71
+ const markup = rawHtml(v);
72
+ if (markup !== undefined)
73
+ raw(part, markup);
74
+ else if (DEV)
75
+ part.commit(v);
76
+ }
77
+ return;
78
+ default:
79
+ // Development: a value no hole renders throws (or warns, for `true`) as on the client.
80
+ // Called through the part, so this chunk imports no development-only function.
81
+ if (DEV)
82
+ part.commit(v);
83
+ }
84
+ }
85
+ /** Static text or a text value: exactly `want`'s length, split off a longer Text node. */
86
+ function text(want) {
87
+ // The parser turns CR and CRLF into LF.
88
+ const data = want.includes('\r') ? want.replace(/\r\n?/g, '\n') : want;
89
+ const t = cur;
90
+ if (t !== null && t.nodeType === 3) {
91
+ // Join text the parser split (very long runs).
92
+ for (let n = t.nextSibling; t.length < data.length && n !== null && n.nodeType === 3;) {
93
+ t.appendData(n.data);
94
+ n.remove();
95
+ n = t.nextSibling;
96
+ }
97
+ if (t.length >= data.length && (!DEV || t.data.startsWith(data))) {
98
+ if (t.length > data.length)
99
+ t.splitText(data.length);
100
+ cur = t.nextSibling;
101
+ return t;
102
+ }
103
+ }
104
+ return fail(`text ${JSON.stringify(data.slice(0, 40))}`);
105
+ }
106
+ function instance(result, holder) {
107
+ const template = templateOf(result);
108
+ const a = adoptionOf(template);
109
+ // A development server's marker: checked when present (a production server writes none),
110
+ // against the id when the template has one (production client objects don't, 01).
111
+ const marker = cur;
112
+ if (marker !== null && marker.nodeType === 8 && marker.data.startsWith('gyral:')) {
113
+ const id = template.id;
114
+ if (DEV && id !== undefined && marker.data !== `gyral:${id}`)
115
+ fail(`<!--gyral:${id}-->`);
116
+ cur = marker.nextSibling;
117
+ marker.remove();
118
+ }
119
+ const outer = current;
120
+ current = template;
121
+ const inst = new Instance(template, sourceOf(result), holder, true);
122
+ children(a.plan.content, a, inst, result.values);
123
+ current = outer;
124
+ return inst;
125
+ }
126
+ /** The children of template node `t`, with the child holes between them. */
127
+ function children(t, a, inst, values) {
128
+ const holes = a.holes.get(t);
129
+ const root = t === a.plan.content;
130
+ let h = 0;
131
+ for (let n = t.firstChild, j = 0;; n = n.nextSibling, j++) {
132
+ if (holes !== undefined && h < holes.length) {
133
+ const i = holes[h];
134
+ const spec = a.specs[i];
135
+ const ref = spec[0] === CHILD_BEFORE ? spec[2] : null;
136
+ if (n === null ? ref === null : ref === j) {
137
+ hole(i, ref, a, inst, values);
138
+ h++;
139
+ }
140
+ }
141
+ if (n === null)
142
+ return;
143
+ const dom = node(n, a, inst, values);
144
+ if (root) {
145
+ if (j === 0)
146
+ inst.start = dom;
147
+ inst.end = dom;
148
+ }
149
+ }
150
+ }
151
+ /** A child hole: its content, then its reference node (the DOM node the walk reached). */
152
+ function hole(i, ref, a, inst, values) {
153
+ const kind = a.plan.kinds[i];
154
+ const at = a.plan.at[i];
155
+ const part = kind === ROOT
156
+ ? new ChildPart(null, null, null, 0, false, at)
157
+ : new ChildPart(parent, null, null, 0, kind === SOLE, at);
158
+ inst.parts[i] = part;
159
+ content(part, values[at]);
160
+ if (ref !== null) {
161
+ part.ref = cur;
162
+ if (kind === ROOT && ref === 0)
163
+ inst.head = part;
164
+ }
165
+ else if (kind === ROOT) {
166
+ part.owner = inst;
167
+ inst.tail = part;
168
+ }
169
+ }
170
+ function node(t, a, inst, values) {
171
+ if (t.nodeType === 3)
172
+ return text(t.data);
173
+ if (t.nodeType !== 8)
174
+ return element(t, a, inst, values);
175
+ const c = cur;
176
+ if (c === null || c.nodeType !== 8 || (DEV && c.data !== t.data)) {
177
+ return fail(`<!--${t.data}-->`);
178
+ }
179
+ cur = c.nextSibling;
180
+ return c;
181
+ }
182
+ const WHITESPACE_ONLY = /^[\t\n\f\r ]*$/;
183
+ function element(t, a, inst, values) {
184
+ const el = cur;
185
+ if (el === null || el.localName !== t.localName)
186
+ return fail(`<${t.localName}>`);
187
+ cur = el.nextSibling;
188
+ let whole = false;
189
+ for (const i of a.attrs.get(t) ?? []) {
190
+ const kind = a.plan.kinds[i];
191
+ const part = attrPart(el, kind, a.specs[i], a.plan.at[i]);
192
+ inst.parts[i] = part;
193
+ adoptAttr(part, values);
194
+ if (DEV)
195
+ checkAttr(part, fail);
196
+ if (kind === TEXTAREA || kind === TITLE)
197
+ whole = true; // the part owns the content
198
+ }
199
+ let holes = a.holes.has(t);
200
+ if (whole)
201
+ return el;
202
+ if (el.hasAttribute(LIGHT_ATTRIBUTE)) {
203
+ // A light host owns its children (ADR 0014): its parent writes none (06 "Components").
204
+ for (let c = t.firstChild; c !== null; c = c.nextSibling) {
205
+ if (c.nodeType !== 3 || !WHITESPACE_ONLY.test(c.data))
206
+ holes = true;
207
+ }
208
+ if (holes)
209
+ fail(`no children from the parent in light host <${t.localName}>`, el, el);
210
+ return el;
211
+ }
212
+ // A custom element without children in the template: what it holds is its own.
213
+ if (!holes && t.firstChild === null && t.localName.includes('-'))
214
+ return el;
215
+ const outer = cur;
216
+ const outerParent = parent;
217
+ parent = el;
218
+ cur = el.firstChild;
219
+ children(t, a, inst, values);
220
+ if (cur !== null)
221
+ fail(`the end of <${t.localName}>`);
222
+ cur = outer;
223
+ parent = outerParent;
224
+ return el;
225
+ }
226
+ /** Rows of `each` (keyed) or items of an array (`l` undefined), one after another. */
227
+ function rows(part, values, l) {
228
+ const list = new List(part);
229
+ part.kind = l === undefined ? ITEMS : LIST;
230
+ part.content = list;
231
+ if (DEV && l !== undefined)
232
+ checkKeys(values, l.key);
233
+ for (let i = 0; i < values.length; i++) {
234
+ const row = new ChildPart(null, null, list, i, false, -1);
235
+ list.rows.push(row);
236
+ if (l === undefined) {
237
+ content(row, values[i]);
238
+ continue;
239
+ }
240
+ const item = values[i];
241
+ row.key = l.key(item);
242
+ row.item = item;
243
+ row.picked = l.pick === undefined ? undefined : l.pick(item);
244
+ content(row, l.row(item, row.picked));
245
+ }
246
+ }
247
+ /** `raw()`: its start anchor, then the nodes its markup parses to (texts by length). */
248
+ function raw(part, markup) {
249
+ report({ html: markup });
250
+ const start = cur;
251
+ if (start === null || start.nodeType !== 8)
252
+ return fail('the raw() start anchor <!---->');
253
+ cur = start.nextSibling;
254
+ let end = start;
255
+ for (let n = parse(markup).firstChild; n !== null; n = n.nextSibling) {
256
+ if (n.nodeType === 3)
257
+ end = text(n.data);
258
+ else {
259
+ const dom = cur;
260
+ if (dom === null || dom.nodeName !== n.nodeName)
261
+ return fail(`raw() markup's ${n.nodeName}`);
262
+ end = dom;
263
+ cur = dom.nextSibling;
264
+ }
265
+ }
266
+ part.kind = RAW;
267
+ part.content = new RawRange(start, end, markup);
268
+ }
269
+ //# sourceMappingURL=adopt.js.map