@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,156 @@
1
+ // Lists in child holes: `each` (view/03-lists.md "Reconciliation", "Fast paths") and
2
+ // positional arrays (view/02-bindings.md "Child values"). Rows are child parts tracked by their
3
+ // node range, with no markers. Fast paths: create into empty (one fragment), clear
4
+ // (replaceChildren when the list is its parent's only content), the common prefix and suffix,
5
+ // insert-only (append, prepend, insert) and remove-only. What remains is reordered by
6
+ // reorder.ts. Rows commit in document order. `each` is here: its result carries `commitList`,
7
+ // so the keyed path (this, rows.ts, reorder.ts, place.ts) is bundled only by apps that call it.
8
+ import { DEV } from '#view-dev';
9
+ import { ChildPart, EMPTY, ITEMS, LIST } from './child-part.js';
10
+ import { checkKeys, recheckRows } from './dev-check.js';
11
+ import { reorder } from './reorder.js';
12
+ import { firstFrom, List, newRow, updateRow } from './rows.js';
13
+ import { EACH } from './values.js';
14
+ export { List } from './rows.js';
15
+ function listOf(part, kind) {
16
+ if (part.kind === kind)
17
+ return part.content;
18
+ if (part.kind !== EMPTY)
19
+ part.clear();
20
+ const list = new List(part);
21
+ part.kind = kind;
22
+ part.content = list;
23
+ return list;
24
+ }
25
+ /** Removes every row; the list's part keeps its (now empty) list. */
26
+ export function clearList(part, list) {
27
+ if (part.sole && part.parentNode !== null)
28
+ part.parentNode.replaceChildren();
29
+ else
30
+ for (const row of list.rows)
31
+ row.clear();
32
+ list.rows = [];
33
+ }
34
+ /**
35
+ * Creates rows for `l.items[from…to]` (keys from `keys[i - from]` when given) into one
36
+ * fragment, pushes them onto `rows` and inserts the fragment before `end`.
37
+ */
38
+ export function createRows(part, list, l, rows, from, to, end, keys) {
39
+ const frag = document.createDocumentFragment();
40
+ list.building = frag;
41
+ try {
42
+ for (let i = from; i <= to; i++) {
43
+ const item = l.items[i];
44
+ const key = keys === undefined ? l.key(item) : keys[i - from];
45
+ rows.push(newRow(list, null, l, item, key, i));
46
+ }
47
+ }
48
+ finally {
49
+ list.building = null;
50
+ }
51
+ part.parent().insertBefore(frag, end);
52
+ }
53
+ export function each(items, key, row, pick) {
54
+ if (DEV && typeof key !== 'function') {
55
+ throw new TypeError('gyral: each() needs a key function as its second argument: ' +
56
+ 'each(items, (x) => x.id, Row) (docs/design-docs/view/03-lists.md "Keys", rule 9).');
57
+ }
58
+ return {
59
+ [EACH]: commitList,
60
+ items,
61
+ key: key,
62
+ row: row,
63
+ pick: pick,
64
+ };
65
+ }
66
+ function commitList(part, l) {
67
+ const list = listOf(part, LIST);
68
+ const n = l.items.length;
69
+ if (DEV)
70
+ checkKeys(l.items, l.key);
71
+ if (list.rows.length === 0) {
72
+ if (n > 0) {
73
+ const rows = [];
74
+ createRows(part, list, l, rows, 0, n - 1, part.end());
75
+ list.rows = rows;
76
+ }
77
+ }
78
+ else if (n === 0)
79
+ clearList(part, list);
80
+ else
81
+ reconcile(part, list, l);
82
+ if (DEV)
83
+ recheckRows(list, l);
84
+ }
85
+ function reconcile(part, list, l) {
86
+ const { items, key } = l;
87
+ const old = list.rows;
88
+ const n = items.length;
89
+ const on = old.length;
90
+ const m = n < on ? n : on;
91
+ let s = 0;
92
+ for (; s < m; s++) {
93
+ const item = items[s];
94
+ const row = old[s];
95
+ if (key(item) !== row.key)
96
+ break;
97
+ updateRow(row, item, l);
98
+ }
99
+ if (s === n && s === on)
100
+ return;
101
+ let oe = on - 1;
102
+ let ne = n - 1;
103
+ while (oe >= s && ne >= s && key(items[ne]) === old[oe].key) {
104
+ oe--;
105
+ ne--;
106
+ }
107
+ const rows = old.slice(0, s);
108
+ if (s > oe)
109
+ createRows(part, list, l, rows, s, ne, firstFrom(old, oe + 1, part));
110
+ else if (s > ne)
111
+ for (let j = s; j <= oe; j++)
112
+ old[j].clear();
113
+ else
114
+ reorder(part, list, l, rows, s, oe, ne);
115
+ for (let j = oe + 1; j < on; j++)
116
+ rows.push(old[j]);
117
+ list.rows = rows;
118
+ for (let i = s; i < n; i++)
119
+ rows[i].index = i;
120
+ for (let i = ne + 1; i < n; i++)
121
+ updateRow(rows[i], items[i], l);
122
+ }
123
+ /** A positional array: items reused by index (view/02-bindings.md "Child values"). */
124
+ export function commitItems(part, values) {
125
+ const list = listOf(part, ITEMS);
126
+ const rows = list.rows;
127
+ const n = values.length;
128
+ if (n === 0) {
129
+ if (rows.length > 0)
130
+ clearList(part, list);
131
+ return;
132
+ }
133
+ const common = n < rows.length ? n : rows.length;
134
+ for (let i = 0; i < common; i++)
135
+ rows[i].commit(values[i]);
136
+ if (n > rows.length) {
137
+ const end = part.end();
138
+ const frag = document.createDocumentFragment();
139
+ list.building = frag;
140
+ try {
141
+ for (let i = rows.length; i < n; i++) {
142
+ const row = new ChildPart(null, null, list, i, false, -1);
143
+ rows.push(row);
144
+ row.commit(values[i]);
145
+ }
146
+ }
147
+ finally {
148
+ list.building = null;
149
+ }
150
+ part.parent().insertBefore(frag, end);
151
+ }
152
+ else
153
+ while (rows.length > n)
154
+ rows.pop().clear();
155
+ }
156
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../../src/view/render/list.ts"],"names":[],"mappings":"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","sourcesContent":["// Lists in child holes: `each` (view/03-lists.md \"Reconciliation\", \"Fast paths\") and\n// positional arrays (view/02-bindings.md \"Child values\"). Rows are child parts tracked by their\n// node range, with no markers. Fast paths: create into empty (one fragment), clear\n// (replaceChildren when the list is its parent's only content), the common prefix and suffix,\n// insert-only (append, prepend, insert) and remove-only. What remains is reordered by\n// reorder.ts. Rows commit in document order. `each` is here: its result carries `commitList`,\n// so the keyed path (this, rows.ts, reorder.ts, place.ts) is bundled only by apps that call it.\nimport { DEV } from '#view-dev';\nimport { ChildPart, EMPTY, ITEMS, LIST } from './child-part.js';\nimport { checkKeys, recheckRows } from './dev-check.js';\nimport { reorder } from './reorder.js';\nimport { firstFrom, List, newRow, updateRow } from './rows.js';\nimport { EACH, type ChildValue, type ListResult } from './values.js';\n\nexport { List } from './rows.js';\n\nfunction listOf(part: ChildPart, kind: number): List {\n if (part.kind === kind) return part.content as List;\n if (part.kind !== EMPTY) part.clear();\n const list = new List(part);\n part.kind = kind;\n part.content = list;\n return list;\n}\n\n/** Removes every row; the list's part keeps its (now empty) list. */\nexport function clearList(part: ChildPart, list: List): void {\n if (part.sole && part.parentNode !== null) (part.parentNode as Element).replaceChildren();\n else for (const row of list.rows) row.clear();\n list.rows = [];\n}\n\n/**\n * Creates rows for `l.items[from…to]` (keys from `keys[i - from]` when given) into one\n * fragment, pushes them onto `rows` and inserts the fragment before `end`.\n */\nexport function createRows(\n part: ChildPart,\n list: List,\n l: ListResult,\n rows: ChildPart[],\n from: number,\n to: number,\n end: Node | null,\n keys?: readonly unknown[],\n): void {\n const frag = document.createDocumentFragment();\n list.building = frag;\n try {\n for (let i = from; i <= to; i++) {\n const item = l.items[i];\n const key = keys === undefined ? l.key(item) : keys[i - from];\n rows.push(newRow(list, null, l, item, key, i));\n }\n } finally {\n list.building = null;\n }\n part.parent().insertBefore(frag, end);\n}\n\n/**\n * A keyed list (view/03-lists.md). `key` must give each item a unique string or number; `row`\n * must depend only on its arguments: a row re-renders only when its item object or its `pick`\n * result changes.\n */\nexport function each<T>(\n items: readonly T[],\n key: (item: T) => string | number,\n row: (item: T) => ChildValue,\n): ListResult;\nexport function each<T, P>(\n items: readonly T[],\n key: (item: T) => string | number,\n row: (item: T, picked: P) => ChildValue,\n pick: (item: T) => P,\n): ListResult;\nexport function each<T, P>(\n items: readonly T[],\n key: (item: T) => string | number,\n row: (item: T, picked: P) => ChildValue,\n pick?: (item: T) => P,\n): ListResult {\n if (DEV && typeof key !== 'function') {\n throw new TypeError(\n 'gyral: each() needs a key function as its second argument: ' +\n 'each(items, (x) => x.id, Row) (docs/design-docs/view/03-lists.md \"Keys\", rule 9).',\n );\n }\n return {\n [EACH]: commitList,\n items,\n key: key as (item: unknown) => unknown,\n row: row as (item: unknown, picked: unknown) => unknown,\n pick: pick as ((item: unknown) => unknown) | undefined,\n };\n}\n\nfunction commitList(part: ChildPart, l: ListResult): void {\n const list = listOf(part, LIST);\n const n = l.items.length;\n if (DEV) checkKeys(l.items, l.key);\n if (list.rows.length === 0) {\n if (n > 0) {\n const rows: ChildPart[] = [];\n createRows(part, list, l, rows, 0, n - 1, part.end());\n list.rows = rows;\n }\n } else if (n === 0) clearList(part, list);\n else reconcile(part, list, l);\n if (DEV) recheckRows(list, l);\n}\n\nfunction reconcile(part: ChildPart, list: List, l: ListResult): void {\n const { items, key } = l;\n const old = list.rows;\n const n = items.length;\n const on = old.length;\n const m = n < on ? n : on;\n let s = 0;\n for (; s < m; s++) {\n const item = items[s];\n const row = old[s] as ChildPart;\n if (key(item) !== row.key) break;\n updateRow(row, item, l);\n }\n if (s === n && s === on) return;\n let oe = on - 1;\n let ne = n - 1;\n while (oe >= s && ne >= s && key(items[ne]) === (old[oe] as ChildPart).key) {\n oe--;\n ne--;\n }\n const rows = old.slice(0, s);\n if (s > oe) createRows(part, list, l, rows, s, ne, firstFrom(old, oe + 1, part));\n else if (s > ne) for (let j = s; j <= oe; j++) (old[j] as ChildPart).clear();\n else reorder(part, list, l, rows, s, oe, ne);\n for (let j = oe + 1; j < on; j++) rows.push(old[j] as ChildPart);\n list.rows = rows;\n for (let i = s; i < n; i++) (rows[i] as ChildPart).index = i;\n for (let i = ne + 1; i < n; i++) updateRow(rows[i] as ChildPart, items[i], l);\n}\n\n/** A positional array: items reused by index (view/02-bindings.md \"Child values\"). */\nexport function commitItems(part: ChildPart, values: readonly unknown[]): void {\n const list = listOf(part, ITEMS);\n const rows = list.rows;\n const n = values.length;\n if (n === 0) {\n if (rows.length > 0) clearList(part, list);\n return;\n }\n const common = n < rows.length ? n : rows.length;\n for (let i = 0; i < common; i++) (rows[i] as ChildPart).commit(values[i]);\n if (n > rows.length) {\n const end = part.end();\n const frag = document.createDocumentFragment();\n list.building = frag;\n try {\n for (let i = rows.length; i < n; i++) {\n const row = new ChildPart(null, null, list, i, false, -1);\n rows.push(row);\n row.commit(values[i]);\n }\n } finally {\n list.building = null;\n }\n part.parent().insertBefore(frag, end);\n } else while (rows.length > n) (rows.pop() as ChildPart).clear();\n}\n"]}
@@ -0,0 +1,10 @@
1
+ /** The server's DOM doesn't match the component's first client render. */
2
+ export declare class HydrationMismatch extends Error {
3
+ constructor(message: string);
4
+ }
5
+ /**
6
+ * Throws a mismatch. `expected` describes what the walk needed; `found` is the DOM node there,
7
+ * a description, or null when `at` (the parent) had no more children. `host` names the
8
+ * component and `loc` the template's call site.
9
+ */
10
+ export declare function mismatch(expected: string, found: Node | string | null, at: Node, root: Node, host: string, loc: string | undefined): never;
@@ -0,0 +1,53 @@
1
+ // Hydration mismatches (view/07-hydration.md "Mismatches"): the server DOM differs from what
2
+ // the first client render needs. The message names the component, the template's call site
3
+ // (development builds know it), the path from the root to the node, and what was expected
4
+ // and found. Development throws it; production recovers the one component (core's caller).
5
+ import { DEV } from '#view-dev';
6
+ /** The server's DOM doesn't match the component's first client render. */
7
+ export class HydrationMismatch extends Error {
8
+ constructor(message) {
9
+ super(message);
10
+ this.name = 'HydrationMismatch';
11
+ }
12
+ }
13
+ /** A short description of a DOM node. */
14
+ function describe(node) {
15
+ if (node.nodeType === 3)
16
+ return `text ${JSON.stringify(node.data.slice(0, 40))}`;
17
+ if (node.nodeType === 8)
18
+ return `<!--${node.data}-->`;
19
+ return node.nodeType === 1 ? `<${node.localName}>` : 'the root';
20
+ }
21
+ /** `div[0] › ul[2] › li[1]`: local names and child indexes from `root` down to `node`. */
22
+ function pathOf(node, root) {
23
+ const steps = [];
24
+ for (let n = node; n !== null && n !== root; n = n.parentNode) {
25
+ let index = 0;
26
+ for (let s = n.previousSibling; s !== null; s = s.previousSibling)
27
+ index++;
28
+ steps.unshift(`${n.nodeType === 1 ? n.localName : n.nodeName}[${String(index)}]`);
29
+ }
30
+ return steps.length === 0 ? 'the root' : steps.join(' › ');
31
+ }
32
+ /**
33
+ * Throws a mismatch. `expected` describes what the walk needed; `found` is the DOM node there,
34
+ * a description, or null when `at` (the parent) had no more children. `host` names the
35
+ * component and `loc` the template's call site.
36
+ */
37
+ export function mismatch(expected, found, at, root, host, loc) {
38
+ const where = typeof found === 'object' && found !== null ? found : at;
39
+ const what = found === null
40
+ ? `the end of ${describe(at)}`
41
+ : typeof found === 'string'
42
+ ? found
43
+ : describe(found);
44
+ throw new HydrationMismatch(`gyral: hydration mismatch in ${host}${loc === undefined ? '' : ` (template at ${loc})`} ` +
45
+ `at ${pathOf(where, root)}: expected ${expected}, found ${what}.` +
46
+ (DEV
47
+ ? " The server's HTML differs from the first client render: a view that isn't " +
48
+ 'deterministic (Date.now(), locale), a third party that changed the DOM before ' +
49
+ 'scripts ran, or a stale cached page (docs/design-docs/view/07-hydration.md ' +
50
+ '"Mismatches").'
51
+ : ''));
52
+ }
53
+ //# sourceMappingURL=mismatch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mismatch.js","sourceRoot":"","sources":["../../../src/view/render/mismatch.ts"],"names":[],"mappings":"AAAA,6FAA6F;AAC7F,2FAA2F;AAC3F,0FAA0F;AAC1F,2FAA2F;AAC3F,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAEhC,0EAA0E;AAC1E,MAAM,OAAO,iBAAkB,SAAQ,KAAK;IAC1C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;IAClC,CAAC;CACF;AAED,yCAAyC;AACzC,SAAS,QAAQ,CAAC,IAAU;IAC1B,IAAI,IAAI,CAAC,QAAQ,KAAK,CAAC;QAAE,OAAO,QAAQ,IAAI,CAAC,SAAS,CAAE,IAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC;IAC3F,IAAI,IAAI,CAAC,QAAQ,KAAK,CAAC;QAAE,OAAO,OAAQ,IAAgB,CAAC,IAAI,KAAK,CAAC;IACnE,OAAO,IAAI,CAAC,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAC,IAAK,IAAgB,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC;AAC/E,CAAC;AAED,0FAA0F;AAC1F,SAAS,MAAM,CAAC,IAAU,EAAE,IAAU;IACpC,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,IAAI,CAAC,GAAgB,IAAI,EAAE,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,CAAC;QAC3E,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,KAAK,IAAI,CAAC,GAAG,CAAC,CAAC,eAAe,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,eAAe;YAAE,KAAK,EAAE,CAAC;QAC3E,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAE,CAAa,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,IAAI,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACjG,CAAC;IACD,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC7D,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CACtB,QAAgB,EAChB,KAA2B,EAC3B,EAAQ,EACR,IAAU,EACV,IAAY,EACZ,GAAuB;IAEvB,MAAM,KAAK,GAAG,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IACvE,MAAM,IAAI,GACR,KAAK,KAAK,IAAI;QACZ,CAAC,CAAC,cAAc,QAAQ,CAAC,EAAE,CAAC,EAAE;QAC9B,CAAC,CAAC,OAAO,KAAK,KAAK,QAAQ;YACzB,CAAC,CAAC,KAAK;YACP,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACxB,MAAM,IAAI,iBAAiB,CACzB,gCAAgC,IAAI,GAAG,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,iBAAiB,GAAG,GAAG,GAAG;QACxF,MAAM,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,cAAc,QAAQ,WAAW,IAAI,GAAG;QACjE,CAAC,GAAG;YACF,CAAC,CAAC,6EAA6E;gBAC7E,gFAAgF;gBAChF,6EAA6E;gBAC7E,gBAAgB;YAClB,CAAC,CAAC,EAAE,CAAC,CACV,CAAC;AACJ,CAAC","sourcesContent":["// Hydration mismatches (view/07-hydration.md \"Mismatches\"): the server DOM differs from what\n// the first client render needs. The message names the component, the template's call site\n// (development builds know it), the path from the root to the node, and what was expected\n// and found. Development throws it; production recovers the one component (core's caller).\nimport { DEV } from '#view-dev';\n\n/** The server's DOM doesn't match the component's first client render. */\nexport class HydrationMismatch extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'HydrationMismatch';\n }\n}\n\n/** A short description of a DOM node. */\nfunction describe(node: Node): string {\n if (node.nodeType === 3) return `text ${JSON.stringify((node as Text).data.slice(0, 40))}`;\n if (node.nodeType === 8) return `<!--${(node as Comment).data}-->`;\n return node.nodeType === 1 ? `<${(node as Element).localName}>` : 'the root';\n}\n\n/** `div[0] › ul[2] › li[1]`: local names and child indexes from `root` down to `node`. */\nfunction pathOf(node: Node, root: Node): string {\n const steps: string[] = [];\n for (let n: Node | null = node; n !== null && n !== root; n = n.parentNode) {\n let index = 0;\n for (let s = n.previousSibling; s !== null; s = s.previousSibling) index++;\n steps.unshift(`${n.nodeType === 1 ? (n as Element).localName : n.nodeName}[${String(index)}]`);\n }\n return steps.length === 0 ? 'the root' : steps.join(' › ');\n}\n\n/**\n * Throws a mismatch. `expected` describes what the walk needed; `found` is the DOM node there,\n * a description, or null when `at` (the parent) had no more children. `host` names the\n * component and `loc` the template's call site.\n */\nexport function mismatch(\n expected: string,\n found: Node | string | null,\n at: Node,\n root: Node,\n host: string,\n loc: string | undefined,\n): never {\n const where = typeof found === 'object' && found !== null ? found : at;\n const what =\n found === null\n ? `the end of ${describe(at)}`\n : typeof found === 'string'\n ? found\n : describe(found);\n throw new HydrationMismatch(\n `gyral: hydration mismatch in ${host}${loc === undefined ? '' : ` (template at ${loc})`} ` +\n `at ${pathOf(where, root)}: expected ${expected}, found ${what}.` +\n (DEV\n ? \" The server's HTML differs from the first client render: a view that isn't \" +\n 'deterministic (Date.now(), locale), a third party that changed the DOM before ' +\n 'scripts ran, or a stale cached page (docs/design-docs/view/07-hydration.md ' +\n '\"Mismatches\").'\n : ''),\n );\n}\n"]}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Whether moves into `parent` can use `moveBefore` (not Baseline yet: detected on the parent,
3
+ * once per reorder): the browser has it and the parent is in a document (state worth keeping
4
+ * only exists there, and both ends share a root).
5
+ */
6
+ export declare const canMove: (parent: Node) => boolean;
7
+ /** Moves the nodes `first`…`last` (siblings, in order) before `ref` in `parent`. */
8
+ export declare function moveRange(parent: Node, first: Node, last: Node, ref: Node | null, move: boolean): void;
9
+ /** Removes the nodes `first`…`last` (siblings, in order). */
10
+ export declare function removeRange(first: Node, last: Node): void;
@@ -0,0 +1,37 @@
1
+ // Moving and removing node ranges (view/03-lists.md "Row boundaries", reconciliation step 4).
2
+ // A row or instance is tracked by its first and last node, with no markers. Moves use
3
+ // `moveBefore()` where the browser has it (it keeps focus, selection, animations, iframe and
4
+ // media state); elsewhere `insertBefore` (ADR 0003 tier 2: an inline fallback).
5
+ /**
6
+ * Whether moves into `parent` can use `moveBefore` (not Baseline yet: detected on the parent,
7
+ * once per reorder): the browser has it and the parent is in a document (state worth keeping
8
+ * only exists there, and both ends share a root).
9
+ */
10
+ export const canMove = (parent) => 'moveBefore' in parent && parent.isConnected;
11
+ /** Moves the nodes `first`…`last` (siblings, in order) before `ref` in `parent`. */
12
+ export function moveRange(parent, first, last, ref, move) {
13
+ for (let node = first;;) {
14
+ const next = node.nextSibling;
15
+ if (move)
16
+ parent.moveBefore(node, ref);
17
+ else
18
+ parent.insertBefore(node, ref);
19
+ if (node === last || next === null)
20
+ return;
21
+ node = next;
22
+ }
23
+ }
24
+ /** Removes the nodes `first`…`last` (siblings, in order). */
25
+ export function removeRange(first, last) {
26
+ const parent = first.parentNode;
27
+ if (parent === null)
28
+ return;
29
+ for (let node = first;;) {
30
+ const next = node.nextSibling;
31
+ parent.removeChild(node);
32
+ if (node === last || next === null)
33
+ return;
34
+ node = next;
35
+ }
36
+ }
37
+ //# sourceMappingURL=nodes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nodes.js","sourceRoot":"","sources":["../../../src/view/render/nodes.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAC9F,sFAAsF;AACtF,6FAA6F;AAC7F,gFAAgF;AAMhF;;;;GAIG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,MAAY,EAAW,EAAE,CAAC,YAAY,IAAI,MAAM,IAAI,MAAM,CAAC,WAAW,CAAC;AAE/F,oFAAoF;AACpF,MAAM,UAAU,SAAS,CACvB,MAAY,EACZ,KAAW,EACX,IAAU,EACV,GAAgB,EAChB,IAAa;IAEb,KAAK,IAAI,IAAI,GAAG,KAAK,IAAK,CAAC;QACzB,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC;QAC9B,IAAI,IAAI;YAAG,MAAkC,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;;YAC/D,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QACpC,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI;YAAE,OAAO;QAC3C,IAAI,GAAG,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,6DAA6D;AAC7D,MAAM,UAAU,WAAW,CAAC,KAAW,EAAE,IAAU;IACjD,MAAM,MAAM,GAAG,KAAK,CAAC,UAAU,CAAC;IAChC,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO;IAC5B,KAAK,IAAI,IAAI,GAAG,KAAK,IAAK,CAAC;QACzB,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC;QAC9B,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QACzB,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI;YAAE,OAAO;QAC3C,IAAI,GAAG,IAAI,CAAC;IACd,CAAC;AACH,CAAC","sourcesContent":["// Moving and removing node ranges (view/03-lists.md \"Row boundaries\", reconciliation step 4).\n// A row or instance is tracked by its first and last node, with no markers. Moves use\n// `moveBefore()` where the browser has it (it keeps focus, selection, animations, iframe and\n// media state); elsewhere `insertBefore` (ADR 0003 tier 2: an inline fallback).\n\ninterface MovingParent {\n moveBefore(node: Node, child: Node | null): void;\n}\n\n/**\n * Whether moves into `parent` can use `moveBefore` (not Baseline yet: detected on the parent,\n * once per reorder): the browser has it and the parent is in a document (state worth keeping\n * only exists there, and both ends share a root).\n */\nexport const canMove = (parent: Node): boolean => 'moveBefore' in parent && parent.isConnected;\n\n/** Moves the nodes `first`…`last` (siblings, in order) before `ref` in `parent`. */\nexport function moveRange(\n parent: Node,\n first: Node,\n last: Node,\n ref: Node | null,\n move: boolean,\n): void {\n for (let node = first; ;) {\n const next = node.nextSibling;\n if (move) (parent as unknown as MovingParent).moveBefore(node, ref);\n else parent.insertBefore(node, ref);\n if (node === last || next === null) return;\n node = next;\n }\n}\n\n/** Removes the nodes `first`…`last` (siblings, in order). */\nexport function removeRange(first: Node, last: Node): void {\n const parent = first.parentNode;\n if (parent === null) return;\n for (let node = first; ;) {\n const next = node.nextSibling;\n parent.removeChild(node);\n if (node === last || next === null) return;\n node = next;\n }\n}\n"]}
@@ -0,0 +1,18 @@
1
+ /** A row, as far as placing it goes. */
2
+ export interface Placeable {
3
+ first(): Node | null;
4
+ last(): Node | null;
5
+ }
6
+ /**
7
+ * Marks (1) the positions of one longest strictly increasing subsequence of `src`, ignoring
8
+ * negative entries (new rows). O(n log n).
9
+ */
10
+ export declare function lis(src: Int32Array): Uint8Array;
11
+ /**
12
+ * Places `rows[from..to]` before `end` in `parent`, back to front. `src[i - from]` is the old
13
+ * position of a reused row, or -1 for a new row (its nodes wait in a fragment). Reused rows
14
+ * marked in `keep` stay (all of them when `keep` is undefined: they are already in order); the
15
+ * others move. Rows that stay cost two array reads; only a row that moves looks up its
16
+ * reference node.
17
+ */
18
+ export declare function placeRows(parent: Node, rows: readonly Placeable[], from: number, to: number, src: Int32Array, keep: Uint8Array | undefined, end: Node | null): void;
@@ -0,0 +1,69 @@
1
+ // Putting a list's reordered rows in place with the fewest DOM moves (view/03-lists.md
2
+ // "Reconciliation", step 3): the rows whose old positions form a longest increasing
3
+ // subsequence (or that a two-ended scan matched in place) stay; every other reused row moves,
4
+ // and new rows are inserted. The benchmark behind the plan is recorded in the spec.
5
+ import { canMove, moveRange } from './nodes.js';
6
+ /**
7
+ * Marks (1) the positions of one longest strictly increasing subsequence of `src`, ignoring
8
+ * negative entries (new rows). O(n log n).
9
+ */
10
+ export function lis(src) {
11
+ const n = src.length;
12
+ const tails = new Int32Array(n);
13
+ const prev = new Int32Array(n);
14
+ let len = 0;
15
+ for (let i = 0; i < n; i++) {
16
+ const v = src[i];
17
+ if (v < 0)
18
+ continue;
19
+ let lo = 0;
20
+ let hi = len;
21
+ while (lo < hi) {
22
+ const mid = (lo + hi) >> 1;
23
+ if (src[tails[mid]] < v)
24
+ lo = mid + 1;
25
+ else
26
+ hi = mid;
27
+ }
28
+ prev[i] = lo > 0 ? tails[lo - 1] : -1;
29
+ tails[lo] = i;
30
+ if (lo === len)
31
+ len++;
32
+ }
33
+ const keep = new Uint8Array(n);
34
+ for (let k = len > 0 ? tails[len - 1] : -1; k >= 0; k = prev[k]) {
35
+ keep[k] = 1;
36
+ }
37
+ return keep;
38
+ }
39
+ /** The first node of `rows[from…to]` (already placed), or `end`. */
40
+ function nodeAfter(rows, from, to, end) {
41
+ for (let i = from; i <= to; i++) {
42
+ const node = rows[i].first();
43
+ if (node !== null)
44
+ return node;
45
+ }
46
+ return end;
47
+ }
48
+ /**
49
+ * Places `rows[from..to]` before `end` in `parent`, back to front. `src[i - from]` is the old
50
+ * position of a reused row, or -1 for a new row (its nodes wait in a fragment). Reused rows
51
+ * marked in `keep` stay (all of them when `keep` is undefined: they are already in order); the
52
+ * others move. Rows that stay cost two array reads; only a row that moves looks up its
53
+ * reference node.
54
+ */
55
+ export function placeRows(parent, rows, from, to, src, keep, end) {
56
+ const move = canMove(parent);
57
+ for (let i = to; i >= from; i--) {
58
+ const fresh = src[i - from] < 0;
59
+ if (!fresh && (keep === undefined || keep[i - from] === 1))
60
+ continue;
61
+ const row = rows[i];
62
+ const first = row.first();
63
+ if (first === null)
64
+ continue;
65
+ const ref = nodeAfter(rows, i + 1, to, end);
66
+ moveRange(parent, first, row.last(), ref, !fresh && move);
67
+ }
68
+ }
69
+ //# sourceMappingURL=place.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"place.js","sourceRoot":"","sources":["../../../src/view/render/place.ts"],"names":[],"mappings":"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","sourcesContent":["// Putting a list's reordered rows in place with the fewest DOM moves (view/03-lists.md\n// \"Reconciliation\", step 3): the rows whose old positions form a longest increasing\n// subsequence (or that a two-ended scan matched in place) stay; every other reused row moves,\n// and new rows are inserted. The benchmark behind the plan is recorded in the spec.\nimport { canMove, moveRange } from './nodes.js';\n\n/** A row, as far as placing it goes. */\nexport interface Placeable {\n first(): Node | null;\n last(): Node | null;\n}\n\n/**\n * Marks (1) the positions of one longest strictly increasing subsequence of `src`, ignoring\n * negative entries (new rows). O(n log n).\n */\nexport function lis(src: Int32Array): Uint8Array {\n const n = src.length;\n const tails = new Int32Array(n);\n const prev = new Int32Array(n);\n let len = 0;\n for (let i = 0; i < n; i++) {\n const v = src[i] as number;\n if (v < 0) continue;\n let lo = 0;\n let hi = len;\n while (lo < hi) {\n const mid = (lo + hi) >> 1;\n if ((src[tails[mid] as number] as number) < v) lo = mid + 1;\n else hi = mid;\n }\n prev[i] = lo > 0 ? (tails[lo - 1] as number) : -1;\n tails[lo] = i;\n if (lo === len) len++;\n }\n const keep = new Uint8Array(n);\n for (let k = len > 0 ? (tails[len - 1] as number) : -1; k >= 0; k = prev[k] as number) {\n keep[k] = 1;\n }\n return keep;\n}\n\n/** The first node of `rows[from…to]` (already placed), or `end`. */\nfunction nodeAfter(\n rows: readonly Placeable[],\n from: number,\n to: number,\n end: Node | null,\n): Node | null {\n for (let i = from; i <= to; i++) {\n const node = (rows[i] as Placeable).first();\n if (node !== null) return node;\n }\n return end;\n}\n\n/**\n * Places `rows[from..to]` before `end` in `parent`, back to front. `src[i - from]` is the old\n * position of a reused row, or -1 for a new row (its nodes wait in a fragment). Reused rows\n * marked in `keep` stay (all of them when `keep` is undefined: they are already in order); the\n * others move. Rows that stay cost two array reads; only a row that moves looks up its\n * reference node.\n */\nexport function placeRows(\n parent: Node,\n rows: readonly Placeable[],\n from: number,\n to: number,\n src: Int32Array,\n keep: Uint8Array | undefined,\n end: Node | null,\n): void {\n const move = canMove(parent);\n for (let i = to; i >= from; i--) {\n const fresh = (src[i - from] as number) < 0;\n if (!fresh && (keep === undefined || keep[i - from] === 1)) continue;\n const row = rows[i] as Placeable;\n const first = row.first();\n if (first === null) continue;\n const ref = nodeAfter(rows, i + 1, to, end);\n moveRange(parent, first, row.last() as Node, ref, !fresh && move);\n }\n}\n"]}
@@ -0,0 +1,26 @@
1
+ import { type TemplateObject } from '../normalize/types.js';
2
+ /** Plan kinds of child parts (element parts use their attr-parts.ts kind, ≥ 0). */
3
+ export declare const CHILD = -1;
4
+ export declare const SOLE = -2;
5
+ export declare const ROOT = -3;
6
+ export interface Plan {
7
+ readonly content: DocumentFragment;
8
+ /** One root node and no root-level holes: clone that node instead of the fragment. */
9
+ readonly single: boolean;
10
+ /** Per target node, in document order: keep depth, sibling skip (-1: none), n, n indexes. */
11
+ readonly ops: readonly number[];
12
+ readonly targets: number;
13
+ /** Per part: its element's (or child part's parent's) target, its reference node's target. */
14
+ readonly a: readonly number[];
15
+ readonly b: readonly number[];
16
+ /** Per part: the index of its (first) value, and its kind. */
17
+ readonly at: readonly number[];
18
+ readonly kinds: readonly number[];
19
+ }
20
+ /** Scratch space for walks (never re-entrant: nested instances are created after the walk). */
21
+ export declare const stack: Node[];
22
+ export declare const nodes: Node[];
23
+ /** Fills `nodes` with each target of `plan`, walking from `stack[0]` (or `stack[1]`). */
24
+ export declare function walk(plan: Plan): void;
25
+ /** The plan of `template` (one-entry cache in front of the WeakMap: rows repeat a template). */
26
+ export declare function planOf(template: TemplateObject): Plan;
@@ -0,0 +1,124 @@
1
+ // Instantiation plans (view/01-templates.md "Instantiation"): computed once per template object,
2
+ // they say how to reach every part's nodes in a clone by child-index paths, following
3
+ // firstChild/nextSibling and sharing prefixes (no TreeWalker, no marker search), and what each
4
+ // part is. Part kinds that depend on the element (live form state) are decided here, from the
5
+ // template's own parsed content, so creating an instance only walks and allocates.
6
+ import { ATTR_PART, BOOL_PART, CHILD_BEFORE, CHILD_SOLE, MULTI_PART, PROP_PART, HOOK_PART, TEXT_PART, } from '../normalize/types.js';
7
+ import { templateElement } from '../template-element.js';
8
+ import { attrKind, HOOK, MULTI, PROP, TEXTAREA, TITLE } from './attr-parts.js';
9
+ /** Plan kinds of child parts (element parts use their attr-parts.ts kind, ≥ 0). */
10
+ export const CHILD = -1;
11
+ export const SOLE = -2;
12
+ export const ROOT = -3;
13
+ /** Scratch space for walks (never re-entrant: nested instances are created after the walk). */
14
+ export const stack = [];
15
+ export const nodes = [];
16
+ /** Fills `nodes` with each target of `plan`, walking from `stack[0]` (or `stack[1]`). */
17
+ export function walk(plan) {
18
+ const ops = plan.ops;
19
+ let k = 0;
20
+ for (let t = 0; t < plan.targets; t++) {
21
+ const keep = ops[k];
22
+ const skip = ops[k + 1];
23
+ const n = ops[k + 2];
24
+ k += 3;
25
+ let depth = keep;
26
+ let node = stack[keep];
27
+ if (skip >= 0) {
28
+ node = stack[++depth];
29
+ for (let s = 0; s < skip; s++)
30
+ node = node.nextSibling;
31
+ stack[depth] = node;
32
+ }
33
+ for (let j = 0; j < n; j++) {
34
+ node = node.firstChild;
35
+ for (let s = ops[k++]; s > 0; s--)
36
+ node = node.nextSibling;
37
+ stack[++depth] = node;
38
+ }
39
+ nodes[t] = node;
40
+ }
41
+ }
42
+ function build(template) {
43
+ const content = templateElement(template).content;
44
+ const single = content.childNodes.length === 1 && template.parts.every((p) => p[1].length > 0);
45
+ const ids = new Map();
46
+ const ops = [];
47
+ let cursor = single ? [0] : [];
48
+ const target = (path) => {
49
+ const id = path.join();
50
+ const known = ids.get(id);
51
+ if (known !== undefined)
52
+ return known;
53
+ let keep = 0;
54
+ while (keep < path.length && path[keep] === cursor[keep])
55
+ keep++;
56
+ if (keep === path.length) {
57
+ ops.push(keep, -1, 0); // an ancestor of the cursor (or the cursor itself)
58
+ }
59
+ else {
60
+ const from = (cursor[keep] ?? Infinity) < path[keep] ? keep + 1 : keep;
61
+ const skip = from > keep ? path[keep] - cursor[keep] : -1;
62
+ ops.push(keep, skip, path.length - from, ...path.slice(from));
63
+ cursor = path;
64
+ }
65
+ ids.set(id, ids.size);
66
+ return ids.size - 1;
67
+ };
68
+ const a = [];
69
+ const b = [];
70
+ const at = [];
71
+ let value = 0;
72
+ for (const spec of template.parts) {
73
+ a.push(target(spec[1]));
74
+ b.push(spec[0] === CHILD_BEFORE ? target([...spec[1], spec[2]]) : -1);
75
+ at.push(value);
76
+ value += spec[0] === MULTI_PART ? spec[3].length - 1 : 1;
77
+ }
78
+ const kinds = [];
79
+ const plan = { content, single, ops, targets: ids.size, a, b, at, kinds };
80
+ // Walk the template's own content once to decide the element-dependent kinds.
81
+ stack[0] = content;
82
+ if (single)
83
+ stack[1] = content.firstChild;
84
+ walk(plan);
85
+ template.parts.forEach((spec, i) => {
86
+ kinds.push(kindOf(spec, nodes[a[i]]));
87
+ });
88
+ return plan;
89
+ }
90
+ function kindOf(spec, el) {
91
+ switch (spec[0]) {
92
+ case ATTR_PART:
93
+ return attrKind(el, spec[2], false);
94
+ case MULTI_PART:
95
+ return MULTI;
96
+ case BOOL_PART:
97
+ return attrKind(el, spec[2], true);
98
+ case PROP_PART:
99
+ return PROP;
100
+ case HOOK_PART:
101
+ return HOOK;
102
+ case TEXT_PART:
103
+ return el.localName === 'textarea' ? TEXTAREA : TITLE;
104
+ default:
105
+ return spec[1].length === 0 ? ROOT : spec[0] === CHILD_SOLE ? SOLE : CHILD;
106
+ }
107
+ }
108
+ const plans = new WeakMap();
109
+ let lastTemplate;
110
+ let lastPlan;
111
+ /** The plan of `template` (one-entry cache in front of the WeakMap: rows repeat a template). */
112
+ export function planOf(template) {
113
+ if (template === lastTemplate)
114
+ return lastPlan;
115
+ let plan = plans.get(template);
116
+ if (plan === undefined) {
117
+ plan = build(template);
118
+ plans.set(template, plan);
119
+ }
120
+ lastTemplate = template;
121
+ lastPlan = plan;
122
+ return plan;
123
+ }
124
+ //# sourceMappingURL=plan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan.js","sourceRoot":"","sources":["../../../src/view/render/plan.ts"],"names":[],"mappings":"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","sourcesContent":["// Instantiation plans (view/01-templates.md \"Instantiation\"): computed once per template object,\n// they say how to reach every part's nodes in a clone by child-index paths, following\n// firstChild/nextSibling and sharing prefixes (no TreeWalker, no marker search), and what each\n// part is. Part kinds that depend on the element (live form state) are decided here, from the\n// template's own parsed content, so creating an instance only walks and allocates.\nimport {\n ATTR_PART,\n BOOL_PART,\n CHILD_BEFORE,\n CHILD_SOLE,\n MULTI_PART,\n PROP_PART,\n HOOK_PART,\n TEXT_PART,\n type PartSpec,\n type TemplateObject,\n} from '../normalize/types.js';\nimport { templateElement } from '../template-element.js';\nimport { attrKind, HOOK, MULTI, PROP, TEXTAREA, TITLE } from './attr-parts.js';\n\n/** Plan kinds of child parts (element parts use their attr-parts.ts kind, ≥ 0). */\nexport const CHILD = -1;\nexport const SOLE = -2;\nexport const ROOT = -3;\n\nexport interface Plan {\n readonly content: DocumentFragment;\n /** One root node and no root-level holes: clone that node instead of the fragment. */\n readonly single: boolean;\n /** Per target node, in document order: keep depth, sibling skip (-1: none), n, n indexes. */\n readonly ops: readonly number[];\n readonly targets: number;\n /** Per part: its element's (or child part's parent's) target, its reference node's target. */\n readonly a: readonly number[];\n readonly b: readonly number[];\n /** Per part: the index of its (first) value, and its kind. */\n readonly at: readonly number[];\n readonly kinds: readonly number[];\n}\n\n/** Scratch space for walks (never re-entrant: nested instances are created after the walk). */\nexport const stack: Node[] = [];\nexport const nodes: Node[] = [];\n\n/** Fills `nodes` with each target of `plan`, walking from `stack[0]` (or `stack[1]`). */\nexport function walk(plan: Plan): void {\n const ops = plan.ops;\n let k = 0;\n for (let t = 0; t < plan.targets; t++) {\n const keep = ops[k] as number;\n const skip = ops[k + 1] as number;\n const n = ops[k + 2] as number;\n k += 3;\n let depth = keep;\n let node = stack[keep] as Node;\n if (skip >= 0) {\n node = stack[++depth] as Node;\n for (let s = 0; s < skip; s++) node = node.nextSibling as Node;\n stack[depth] = node;\n }\n for (let j = 0; j < n; j++) {\n node = node.firstChild as Node;\n for (let s = ops[k++] as number; s > 0; s--) node = node.nextSibling as Node;\n stack[++depth] = node;\n }\n nodes[t] = node;\n }\n}\n\nfunction build(template: TemplateObject): Plan {\n const content = templateElement(template).content;\n const single = content.childNodes.length === 1 && template.parts.every((p) => p[1].length > 0);\n const ids = new Map<string, number>();\n const ops: number[] = [];\n let cursor: readonly number[] = single ? [0] : [];\n const target = (path: readonly number[]): number => {\n const id = path.join();\n const known = ids.get(id);\n if (known !== undefined) return known;\n let keep = 0;\n while (keep < path.length && path[keep] === cursor[keep]) keep++;\n if (keep === path.length) {\n ops.push(keep, -1, 0); // an ancestor of the cursor (or the cursor itself)\n } else {\n const from = (cursor[keep] ?? Infinity) < (path[keep] as number) ? keep + 1 : keep;\n const skip = from > keep ? (path[keep] as number) - (cursor[keep] as number) : -1;\n ops.push(keep, skip, path.length - from, ...path.slice(from));\n cursor = path;\n }\n ids.set(id, ids.size);\n return ids.size - 1;\n };\n const a: number[] = [];\n const b: number[] = [];\n const at: number[] = [];\n let value = 0;\n for (const spec of template.parts) {\n a.push(target(spec[1]));\n b.push(spec[0] === CHILD_BEFORE ? target([...spec[1], spec[2]]) : -1);\n at.push(value);\n value += spec[0] === MULTI_PART ? spec[3].length - 1 : 1;\n }\n const kinds: number[] = [];\n const plan: Plan = { content, single, ops, targets: ids.size, a, b, at, kinds };\n // Walk the template's own content once to decide the element-dependent kinds.\n stack[0] = content;\n if (single) stack[1] = content.firstChild as Node;\n walk(plan);\n template.parts.forEach((spec, i) => {\n kinds.push(kindOf(spec, nodes[a[i] as number] as Element));\n });\n return plan;\n}\n\nfunction kindOf(spec: PartSpec, el: Element): number {\n switch (spec[0]) {\n case ATTR_PART:\n return attrKind(el, spec[2], false);\n case MULTI_PART:\n return MULTI;\n case BOOL_PART:\n return attrKind(el, spec[2], true);\n case PROP_PART:\n return PROP;\n case HOOK_PART:\n return HOOK;\n case TEXT_PART:\n return el.localName === 'textarea' ? TEXTAREA : TITLE;\n default:\n return spec[1].length === 0 ? ROOT : spec[0] === CHILD_SOLE ? SOLE : CHILD;\n }\n}\n\nconst plans = new WeakMap<TemplateObject, Plan>();\nlet lastTemplate: TemplateObject | undefined;\nlet lastPlan: Plan | undefined;\n\n/** The plan of `template` (one-entry cache in front of the WeakMap: rows repeat a template). */\nexport function planOf(template: TemplateObject): Plan {\n if (template === lastTemplate) return lastPlan as Plan;\n let plan = plans.get(template);\n if (plan === undefined) {\n plan = build(template);\n plans.set(template, plan);\n }\n lastTemplate = template;\n lastPlan = plan;\n return plan;\n}\n"]}
@@ -0,0 +1,18 @@
1
+ import { type RawResult } from './values.js';
2
+ /** Parsed `raw()` markup: the start anchor, the last node, and the string. */
3
+ export declare class RawRange {
4
+ readonly start: Comment;
5
+ end: Node;
6
+ html: string;
7
+ constructor(start: Comment, end: Node, html: string);
8
+ first(): Node;
9
+ last(): Node;
10
+ remove(): void;
11
+ }
12
+ /** `html` parsed by a <template> (its content is reused: read it before the next call). */
13
+ export declare function parse(html: string): DocumentFragment;
14
+ /**
15
+ * Trusted markup from your own code (Markdown output, JSON-LD), parsed in a child hole and
16
+ * re-parsed only when the string changes. Never pass user input.
17
+ */
18
+ export declare function raw(html: string): RawResult;