@gyral/core 0.2.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 (343) hide show
  1. package/CHANGELOG.md +87 -0
  2. package/README.md +7 -5
  3. package/dist/children.d.ts +5 -2
  4. package/dist/children.js +8 -3
  5. package/dist/children.js.map +1 -1
  6. package/dist/command.js +6 -0
  7. package/dist/command.js.map +1 -1
  8. package/dist/compiler/ast.d.ts +21 -0
  9. package/dist/compiler/ast.js +145 -0
  10. package/dist/compiler/ast.js.map +1 -0
  11. package/dist/compiler/compile.d.ts +38 -0
  12. package/dist/compiler/compile.js +129 -0
  13. package/dist/compiler/compile.js.map +1 -0
  14. package/dist/compiler/hooks.d.ts +18 -0
  15. package/dist/compiler/hooks.js +186 -0
  16. package/dist/compiler/hooks.js.map +1 -0
  17. package/dist/compiler/parse5-check.d.ts +21 -0
  18. package/dist/compiler/parse5-check.js +55 -0
  19. package/dist/compiler/parse5-check.js.map +1 -0
  20. package/dist/compiler/scan.d.ts +31 -0
  21. package/dist/compiler/scan.js +152 -0
  22. package/dist/compiler/scan.js.map +1 -0
  23. package/dist/compiler/source.d.ts +34 -0
  24. package/dist/compiler/source.js +114 -0
  25. package/dist/compiler/source.js.map +1 -0
  26. package/dist/define.d.ts +2 -2
  27. package/dist/define.js +35 -327
  28. package/dist/define.js.map +1 -1
  29. package/dist/devtools-events.d.ts +5 -0
  30. package/dist/devtools-events.js.map +1 -1
  31. package/dist/devtools-off.d.ts +1 -0
  32. package/dist/devtools-off.js +1 -0
  33. package/dist/devtools-off.js.map +1 -1
  34. package/dist/devtools.d.ts +1 -0
  35. package/dist/devtools.js +3 -2
  36. package/dist/devtools.js.map +1 -1
  37. package/dist/drivers-scope.d.ts +1 -1
  38. package/dist/drivers-scope.js +1 -8
  39. package/dist/drivers-scope.js.map +1 -1
  40. package/dist/element-types.d.ts +5 -3
  41. package/dist/element-types.js.map +1 -1
  42. package/dist/element.d.ts +3 -0
  43. package/dist/element.js +269 -0
  44. package/dist/element.js.map +1 -0
  45. package/dist/eslint/imports.d.ts +24 -0
  46. package/dist/eslint/imports.js +78 -0
  47. package/dist/eslint/imports.js.map +1 -0
  48. package/dist/eslint/index.d.ts +15 -0
  49. package/dist/eslint/index.js +15 -0
  50. package/dist/eslint/index.js.map +1 -0
  51. package/dist/eslint/locate.d.ts +33 -0
  52. package/dist/eslint/locate.js +132 -0
  53. package/dist/eslint/locate.js.map +1 -0
  54. package/dist/eslint/row-purity-rule.d.ts +2 -0
  55. package/dist/eslint/row-purity-rule.js +103 -0
  56. package/dist/eslint/row-purity-rule.js.map +1 -0
  57. package/dist/eslint/template-rule.d.ts +5 -0
  58. package/dist/eslint/template-rule.js +66 -0
  59. package/dist/eslint/template-rule.js.map +1 -0
  60. package/dist/features.d.ts +39 -0
  61. package/dist/features.js +2 -0
  62. package/dist/features.js.map +1 -0
  63. package/dist/focus.d.ts +7 -12
  64. package/dist/focus.js +13 -10
  65. package/dist/focus.js.map +1 -1
  66. package/dist/hooks/invalid.d.ts +14 -0
  67. package/dist/hooks/invalid.js +72 -0
  68. package/dist/hooks/invalid.js.map +1 -0
  69. package/dist/hooks/labelled-by.d.ts +13 -0
  70. package/dist/hooks/labelled-by.js +51 -0
  71. package/dist/hooks/labelled-by.js.map +1 -0
  72. package/dist/host-model.d.ts +48 -0
  73. package/dist/host-model.js +155 -0
  74. package/dist/host-model.js.map +1 -0
  75. package/dist/hydration-client.d.ts +9 -0
  76. package/dist/hydration-client.js +35 -0
  77. package/dist/hydration-client.js.map +1 -0
  78. package/dist/hydration.d.ts +13 -19
  79. package/dist/hydration.js +45 -45
  80. package/dist/hydration.js.map +1 -1
  81. package/dist/index.d.ts +9 -17
  82. package/dist/index.js +9 -18
  83. package/dist/index.js.map +1 -1
  84. package/dist/intent.d.ts +31 -8
  85. package/dist/intent.js +82 -27
  86. package/dist/intent.js.map +1 -1
  87. package/dist/internal/interpreter.d.ts +7 -1
  88. package/dist/internal/interpreter.js +11 -4
  89. package/dist/internal/interpreter.js.map +1 -1
  90. package/dist/invokers-shim.d.ts +6 -0
  91. package/dist/invokers-shim.js +32 -0
  92. package/dist/invokers-shim.js.map +1 -0
  93. package/dist/invokers.d.ts +3 -5
  94. package/dist/invokers.js +11 -51
  95. package/dist/invokers.js.map +1 -1
  96. package/dist/islands.d.ts +0 -2
  97. package/dist/islands.js +4 -11
  98. package/dist/islands.js.map +1 -1
  99. package/dist/light-dom.d.ts +3 -52
  100. package/dist/light-dom.js +5 -100
  101. package/dist/light-dom.js.map +1 -1
  102. package/dist/prop.d.ts +66 -0
  103. package/dist/prop.js +22 -0
  104. package/dist/prop.js.map +1 -0
  105. package/dist/props.d.ts +52 -21
  106. package/dist/props.js +150 -34
  107. package/dist/props.js.map +1 -1
  108. package/dist/scheduler.d.ts +39 -0
  109. package/dist/scheduler.js +230 -0
  110. package/dist/scheduler.js.map +1 -0
  111. package/dist/server-component.d.ts +10 -0
  112. package/dist/server-component.js +102 -0
  113. package/dist/server-component.js.map +1 -0
  114. package/dist/server-specs.d.ts +6 -0
  115. package/dist/server-specs.js +13 -0
  116. package/dist/server-specs.js.map +1 -0
  117. package/dist/server.d.ts +28 -0
  118. package/dist/server.js +50 -0
  119. package/dist/server.js.map +1 -0
  120. package/dist/settled.d.ts +10 -0
  121. package/dist/settled.js +40 -0
  122. package/dist/settled.js.map +1 -0
  123. package/dist/states.d.ts +3 -3
  124. package/dist/states.js +4 -7
  125. package/dist/states.js.map +1 -1
  126. package/dist/store-binding.d.ts +6 -3
  127. package/dist/store-binding.js +5 -6
  128. package/dist/store-binding.js.map +1 -1
  129. package/dist/store-scope.d.ts +6 -7
  130. package/dist/store-scope.js +11 -26
  131. package/dist/store-scope.js.map +1 -1
  132. package/dist/store.d.ts +3 -0
  133. package/dist/store.js +9 -2
  134. package/dist/store.js.map +1 -1
  135. package/dist/stores-provider.d.ts +2 -6
  136. package/dist/stores-provider.js +21 -55
  137. package/dist/stores-provider.js.map +1 -1
  138. package/dist/transitions.d.ts +5 -6
  139. package/dist/transitions.js +11 -20
  140. package/dist/transitions.js.map +1 -1
  141. package/dist/types.d.ts +19 -23
  142. package/dist/types.js.map +1 -1
  143. package/dist/view/attributes.d.ts +6 -0
  144. package/dist/view/attributes.js +10 -0
  145. package/dist/view/attributes.js.map +1 -0
  146. package/dist/view/compiled.d.ts +1 -0
  147. package/dist/view/compiled.js +6 -0
  148. package/dist/view/compiled.js.map +1 -0
  149. package/dist/view/dev-off.d.ts +1 -0
  150. package/dist/view/dev-off.js +4 -0
  151. package/dist/view/dev-off.js.map +1 -0
  152. package/dist/view/dev.d.ts +1 -0
  153. package/dist/view/dev.js +5 -0
  154. package/dist/view/dev.js.map +1 -0
  155. package/dist/view/flags.d.ts +1 -0
  156. package/dist/view/flags.js +4 -0
  157. package/dist/view/flags.js.map +1 -0
  158. package/dist/view/index.d.ts +21 -0
  159. package/dist/view/index.js +21 -0
  160. package/dist/view/index.js.map +1 -0
  161. package/dist/view/normalize/check.d.ts +20 -0
  162. package/dist/view/normalize/check.js +78 -0
  163. package/dist/view/normalize/check.js.map +1 -0
  164. package/dist/view/normalize/emit.d.ts +13 -0
  165. package/dist/view/normalize/emit.js +136 -0
  166. package/dist/view/normalize/emit.js.map +1 -0
  167. package/dist/view/normalize/entities.d.ts +4 -0
  168. package/dist/view/normalize/entities.js +38 -0
  169. package/dist/view/normalize/entities.js.map +1 -0
  170. package/dist/view/normalize/errors.d.ts +9 -0
  171. package/dist/view/normalize/errors.js +19 -0
  172. package/dist/view/normalize/errors.js.map +1 -0
  173. package/dist/view/normalize/id.d.ts +7 -0
  174. package/dist/view/normalize/id.js +48 -0
  175. package/dist/view/normalize/id.js.map +1 -0
  176. package/dist/view/normalize/normalize.d.ts +15 -0
  177. package/dist/view/normalize/normalize.js +36 -0
  178. package/dist/view/normalize/normalize.js.map +1 -0
  179. package/dist/view/normalize/repairs.d.ts +24 -0
  180. package/dist/view/normalize/repairs.js +166 -0
  181. package/dist/view/normalize/repairs.js.map +1 -0
  182. package/dist/view/normalize/rules.d.ts +30 -0
  183. package/dist/view/normalize/rules.js +90 -0
  184. package/dist/view/normalize/rules.js.map +1 -0
  185. package/dist/view/normalize/shape.d.ts +5 -0
  186. package/dist/view/normalize/shape.js +38 -0
  187. package/dist/view/normalize/shape.js.map +1 -0
  188. package/dist/view/normalize/source.d.ts +13 -0
  189. package/dist/view/normalize/source.js +34 -0
  190. package/dist/view/normalize/source.js.map +1 -0
  191. package/dist/view/normalize/tag-states.d.ts +23 -0
  192. package/dist/view/normalize/tag-states.js +192 -0
  193. package/dist/view/normalize/tag-states.js.map +1 -0
  194. package/dist/view/normalize/tokenizer.d.ts +5 -0
  195. package/dist/view/normalize/tokenizer.js +233 -0
  196. package/dist/view/normalize/tokenizer.js.map +1 -0
  197. package/dist/view/normalize/tokens.d.ts +51 -0
  198. package/dist/view/normalize/tokens.js +24 -0
  199. package/dist/view/normalize/tokens.js.map +1 -0
  200. package/dist/view/normalize/tree.d.ts +59 -0
  201. package/dist/view/normalize/tree.js +190 -0
  202. package/dist/view/normalize/tree.js.map +1 -0
  203. package/dist/view/normalize/types.d.ts +126 -0
  204. package/dist/view/normalize/types.js +26 -0
  205. package/dist/view/normalize/types.js.map +1 -0
  206. package/dist/view/normalize/whitespace.d.ts +2 -0
  207. package/dist/{template-whitespace.js → view/normalize/whitespace.js} +24 -34
  208. package/dist/view/normalize/whitespace.js.map +1 -0
  209. package/dist/view/prepare-stub.d.ts +3 -0
  210. package/dist/view/prepare-stub.js +7 -0
  211. package/dist/view/prepare-stub.js.map +1 -0
  212. package/dist/view/prepare.d.ts +8 -0
  213. package/dist/view/prepare.js +57 -0
  214. package/dist/view/prepare.js.map +1 -0
  215. package/dist/view/registry.d.ts +63 -0
  216. package/dist/view/registry.js +19 -0
  217. package/dist/view/registry.js.map +1 -0
  218. package/dist/view/render/adopt-attr.d.ts +14 -0
  219. package/dist/view/render/adopt-attr.js +77 -0
  220. package/dist/view/render/adopt-attr.js.map +1 -0
  221. package/dist/view/render/adopt-plan.d.ts +10 -0
  222. package/dist/view/render/adopt-plan.js +26 -0
  223. package/dist/view/render/adopt-plan.js.map +1 -0
  224. package/dist/view/render/adopt.d.ts +3 -0
  225. package/dist/view/render/adopt.js +269 -0
  226. package/dist/view/render/adopt.js.map +1 -0
  227. package/dist/view/render/attr-parts.d.ts +61 -0
  228. package/dist/view/render/attr-parts.js +229 -0
  229. package/dist/view/render/attr-parts.js.map +1 -0
  230. package/dist/view/render/child-part.d.ts +51 -0
  231. package/dist/view/render/child-part.js +170 -0
  232. package/dist/view/render/child-part.js.map +1 -0
  233. package/dist/view/render/dev-check.d.ts +12 -0
  234. package/dist/view/render/dev-check.js +122 -0
  235. package/dist/view/render/dev-check.js.map +1 -0
  236. package/dist/view/render/hook-part.d.ts +3 -0
  237. package/dist/view/render/hook-part.js +20 -0
  238. package/dist/view/render/hook-part.js.map +1 -0
  239. package/dist/view/render/hooks.d.ts +40 -0
  240. package/dist/view/render/hooks.js +46 -0
  241. package/dist/view/render/hooks.js.map +1 -0
  242. package/dist/view/render/hydrate.d.ts +10 -0
  243. package/dist/view/render/hydrate.js +33 -0
  244. package/dist/view/render/hydrate.js.map +1 -0
  245. package/dist/view/render/instance.d.ts +33 -0
  246. package/dist/view/render/instance.js +107 -0
  247. package/dist/view/render/instance.js.map +1 -0
  248. package/dist/view/render/list.d.ts +20 -0
  249. package/dist/view/render/list.js +156 -0
  250. package/dist/view/render/list.js.map +1 -0
  251. package/dist/view/render/mismatch.d.ts +10 -0
  252. package/dist/view/render/mismatch.js +53 -0
  253. package/dist/view/render/mismatch.js.map +1 -0
  254. package/dist/view/render/nodes.d.ts +10 -0
  255. package/dist/view/render/nodes.js +37 -0
  256. package/dist/view/render/nodes.js.map +1 -0
  257. package/dist/view/render/place.d.ts +18 -0
  258. package/dist/view/render/place.js +69 -0
  259. package/dist/view/render/place.js.map +1 -0
  260. package/dist/view/render/plan.d.ts +26 -0
  261. package/dist/view/render/plan.js +124 -0
  262. package/dist/view/render/plan.js.map +1 -0
  263. package/dist/view/render/raw.d.ts +18 -0
  264. package/dist/view/render/raw.js +68 -0
  265. package/dist/view/render/raw.js.map +1 -0
  266. package/dist/view/render/render.d.ts +12 -0
  267. package/dist/view/render/render.js +60 -0
  268. package/dist/view/render/render.js.map +1 -0
  269. package/dist/view/render/reorder.d.ts +4 -0
  270. package/dist/view/render/reorder.js +101 -0
  271. package/dist/view/render/reorder.js.map +1 -0
  272. package/dist/view/render/rows.d.ts +23 -0
  273. package/dist/view/render/rows.js +95 -0
  274. package/dist/view/render/rows.js.map +1 -0
  275. package/dist/view/render/seen.d.ts +11 -0
  276. package/dist/view/render/seen.js +17 -0
  277. package/dist/view/render/seen.js.map +1 -0
  278. package/dist/view/render/values.d.ts +29 -0
  279. package/dist/view/render/values.js +13 -0
  280. package/dist/view/render/values.js.map +1 -0
  281. package/dist/view/render/warn.d.ts +14 -0
  282. package/dist/view/render/warn.js +69 -0
  283. package/dist/view/render/warn.js.map +1 -0
  284. package/dist/view/server/component.d.ts +9 -0
  285. package/dist/view/server/component.js +42 -0
  286. package/dist/view/server/component.js.map +1 -0
  287. package/dist/view/server/escape.d.ts +10 -0
  288. package/dist/view/server/escape.js +34 -0
  289. package/dist/view/server/escape.js.map +1 -0
  290. package/dist/view/server/index.d.ts +28 -0
  291. package/dist/view/server/index.js +72 -0
  292. package/dist/view/server/index.js.map +1 -0
  293. package/dist/view/server/sha256.d.ts +2 -0
  294. package/dist/view/server/sha256.js +75 -0
  295. package/dist/view/server/sha256.js.map +1 -0
  296. package/dist/view/server/tags.d.ts +57 -0
  297. package/dist/view/server/tags.js +121 -0
  298. package/dist/view/server/tags.js.map +1 -0
  299. package/dist/view/server/values.d.ts +16 -0
  300. package/dist/view/server/values.js +86 -0
  301. package/dist/view/server/values.js.map +1 -0
  302. package/dist/view/server/writer.d.ts +16 -0
  303. package/dist/view/server/writer.js +155 -0
  304. package/dist/view/server/writer.js.map +1 -0
  305. package/dist/view/styles.d.ts +25 -0
  306. package/dist/view/styles.js +58 -0
  307. package/dist/view/styles.js.map +1 -0
  308. package/dist/view/template-element.d.ts +3 -0
  309. package/dist/view/template-element.js +25 -0
  310. package/dist/view/template-element.js.map +1 -0
  311. package/dist/view/template.d.ts +21 -0
  312. package/dist/view/template.js +30 -0
  313. package/dist/view/template.js.map +1 -0
  314. package/dist/vite.d.ts +45 -6
  315. package/dist/vite.js +150 -25
  316. package/dist/vite.js.map +1 -1
  317. package/package.json +39 -4
  318. package/dist/accessible-name.d.ts +0 -19
  319. package/dist/accessible-name.js +0 -56
  320. package/dist/accessible-name.js.map +0 -1
  321. package/dist/element-directive.d.ts +0 -20
  322. package/dist/element-directive.js +0 -31
  323. package/dist/element-directive.js.map +0 -1
  324. package/dist/invalid.d.ts +0 -21
  325. package/dist/invalid.js +0 -70
  326. package/dist/invalid.js.map +0 -1
  327. package/dist/lit-html-check.d.ts +0 -6
  328. package/dist/lit-html-check.js +0 -48
  329. package/dist/lit-html-check.js.map +0 -1
  330. package/dist/live-boolean.d.ts +0 -22
  331. package/dist/live-boolean.js +0 -34
  332. package/dist/live-boolean.js.map +0 -1
  333. package/dist/styles.d.ts +0 -12
  334. package/dist/styles.js +0 -11
  335. package/dist/styles.js.map +0 -1
  336. package/dist/template-whitespace.d.ts +0 -7
  337. package/dist/template-whitespace.js.map +0 -1
  338. package/dist/templates.d.ts +0 -5
  339. package/dist/templates.js +0 -15
  340. package/dist/templates.js.map +0 -1
  341. package/dist/textarea.d.ts +0 -26
  342. package/dist/textarea.js +0 -85
  343. package/dist/textarea.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"devtools-off.js","sourceRoot":"","sources":["../src/devtools-off.ts"],"names":[],"mappings":"AAKA,MAAM,CAAC,MAAM,gBAAgB,GAAY,KAAK,CAAC;AAE/C,MAAM,IAAI,GAAG,GAAS,EAAE,CAAC,SAAS,CAAC;AAEnC,MAAM,CAAC,MAAM,UAAU,GAA0B,IAAI,CAAC;AACtD,MAAM,CAAC,MAAM,SAAS,GAAyB,IAAI,CAAC;AACpD,MAAM,CAAC,MAAM,WAAW,GAA2B,IAAI,CAAC;AACxD,MAAM,CAAC,MAAM,QAAQ,GAAwB,IAAI,CAAC;AAClD,MAAM,CAAC,MAAM,WAAW,GAA2B,GAAG,EAAE,CAAC,IAAI,CAAC;AAC9D,MAAM,CAAC,MAAM,QAAQ,GAAwB,GAAG,EAAE,CAAC,EAAE,CAAC;AACtD,MAAM,CAAC,MAAM,iBAAiB,GAAiC,GAAG,EAAE,CAAC,EAAE,CAAC","sourcesContent":["// Production build of the devtools hook (ADR 0017): the same names as devtools.ts, doing\n// nothing. Call sites guard with DEVTOOLS_ENABLED, a literal `false` here, so bundlers drop\n// them entirely. The `typeof Dev.x` annotations keep both modules' signatures in sync.\nimport type * as Dev from './devtools.js';\n\nexport const DEVTOOLS_ENABLED: boolean = false;\n\nconst noop = (): void => undefined;\n\nexport const devConnect: typeof Dev.devConnect = noop;\nexport const devUpdate: typeof Dev.devUpdate = noop;\nexport const devHydrated: typeof Dev.devHydrated = noop;\nexport const devStore: typeof Dev.devStore = noop;\nexport const devCommands: typeof Dev.devCommands = () => noop;\nexport const devOwner: typeof Dev.devOwner = () => '';\nexport const devLiveComponents: typeof Dev.devLiveComponents = () => [];\n"]}
1
+ {"version":3,"file":"devtools-off.js","sourceRoot":"","sources":["../src/devtools-off.ts"],"names":[],"mappings":"AAKA,MAAM,CAAC,MAAM,gBAAgB,GAAY,KAAK,CAAC;AAE/C,MAAM,IAAI,GAAG,GAAS,EAAE,CAAC,SAAS,CAAC;AAEnC,MAAM,CAAC,MAAM,UAAU,GAA0B,IAAI,CAAC;AACtD,MAAM,CAAC,MAAM,SAAS,GAAyB,IAAI,CAAC;AACpD,MAAM,CAAC,MAAM,WAAW,GAA2B,IAAI,CAAC;AACxD,MAAM,CAAC,MAAM,WAAW,GAA2B,IAAI,CAAC;AACxD,MAAM,CAAC,MAAM,QAAQ,GAAwB,IAAI,CAAC;AAClD,MAAM,CAAC,MAAM,WAAW,GAA2B,GAAG,EAAE,CAAC,IAAI,CAAC;AAC9D,MAAM,CAAC,MAAM,QAAQ,GAAwB,GAAG,EAAE,CAAC,EAAE,CAAC;AACtD,MAAM,CAAC,MAAM,iBAAiB,GAAiC,GAAG,EAAE,CAAC,EAAE,CAAC","sourcesContent":["// Production build of the devtools hook (ADR 0017): the same names as devtools.ts, doing\n// nothing. Call sites guard with DEVTOOLS_ENABLED, a literal `false` here, so bundlers drop\n// them entirely. The `typeof Dev.x` annotations keep both modules' signatures in sync.\nimport type * as Dev from './devtools.js';\n\nexport const DEVTOOLS_ENABLED: boolean = false;\n\nconst noop = (): void => undefined;\n\nexport const devConnect: typeof Dev.devConnect = noop;\nexport const devUpdate: typeof Dev.devUpdate = noop;\nexport const devHydrated: typeof Dev.devHydrated = noop;\nexport const devMismatch: typeof Dev.devMismatch = noop;\nexport const devStore: typeof Dev.devStore = noop;\nexport const devCommands: typeof Dev.devCommands = () => noop;\nexport const devOwner: typeof Dev.devOwner = () => '';\nexport const devLiveComponents: typeof Dev.devLiveComponents = () => [];\n"]}
@@ -6,6 +6,7 @@ export declare function devLiveComponents(): readonly DevComponentRef[];
6
6
  export declare function devConnect(element: Element, tag: string, connected: boolean): void;
7
7
  export declare function devUpdate(element: Element, tag: string, msg: Tagged, prev: unknown, next: unknown): void;
8
8
  export declare function devHydrated(element: Element, tag: string, serverRendered: boolean): void;
9
+ export declare function devMismatch(element: Element, tag: string, message: string): void;
9
10
  export declare function devStore(store: string, msg: Tagged, prev: unknown, next: unknown): void;
10
11
  /** A command tracer for one owner (`<tag>#id` or `store:name`). */
11
12
  export declare function devCommands(owner: () => string): CommandTrace;
package/dist/devtools.js CHANGED
@@ -2,7 +2,6 @@
2
2
  // with the `development` condition; production builds get devtools-off.ts instead, so the
3
3
  // guarded call sites (`if (DEVTOOLS_ENABLED) …`) disappear from the bundle.
4
4
  import { DEVTOOLS_GLOBAL, } from './devtools-events.js';
5
- import { warnLeakingLitHtmlOnce } from './lit-html-check.js';
6
5
  export const DEVTOOLS_ENABLED = true;
7
6
  const hook = () => globalThis[DEVTOOLS_GLOBAL];
8
7
  const ids = new WeakMap();
@@ -35,7 +34,6 @@ export function devLiveComponents() {
35
34
  return [...live].map(([element, tag]) => ref(element, tag));
36
35
  }
37
36
  export function devConnect(element, tag, connected) {
38
- warnLeakingLitHtmlOnce();
39
37
  if (connected)
40
38
  live.set(element, tag);
41
39
  else
@@ -52,6 +50,9 @@ export function devUpdate(element, tag, msg, prev, next) {
52
50
  export function devHydrated(element, tag, serverRendered) {
53
51
  emit(() => ({ kind: 'hydrated', component: ref(element, tag), serverRendered, at: now() }));
54
52
  }
53
+ export function devMismatch(element, tag, message) {
54
+ emit(() => ({ kind: 'mismatch', component: ref(element, tag), message, at: now() }));
55
+ }
55
56
  export function devStore(store, msg, prev, next) {
56
57
  emit(() => ({ kind: 'store', store, msg, prev, next, at: now() }));
57
58
  }
@@ -1 +1 @@
1
- {"version":3,"file":"devtools.js","sourceRoot":"","sources":["../src/devtools.ts"],"names":[],"mappings":"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","sourcesContent":["// Development build of the devtools hook (ADR 0017). Resolved through the `#devtools` import\n// with the `development` condition; production builds get devtools-off.ts instead, so the\n// guarded call sites (`if (DEVTOOLS_ENABLED) …`) disappear from the bundle.\nimport {\n DEVTOOLS_GLOBAL,\n type CommandTrace,\n type DevComponentRef,\n type DevEvent,\n type DevtoolsHook,\n} from './devtools-events.js';\nimport { warnLeakingLitHtmlOnce } from './lit-html-check.js';\nimport type { Tagged } from './types.js';\n\nexport const DEVTOOLS_ENABLED: boolean = true;\n\nconst hook = (): DevtoolsHook | undefined =>\n (globalThis as Record<string, unknown>)[DEVTOOLS_GLOBAL] as DevtoolsHook | undefined;\n\nconst ids = new WeakMap<Element, number>();\nlet nextId = 1;\n\nfunction ref(element: Element, tag: string): DevComponentRef {\n let id = ids.get(element);\n if (id === undefined) {\n id = nextId++;\n ids.set(element, id);\n }\n return { tag, id, element };\n}\n\n// Builds nothing unless a listener is installed: zero cost in dev without devtools.\nfunction emit(make: () => DevEvent): void {\n const listener = hook();\n if (listener === undefined) return;\n try {\n listener.emit(make());\n } catch (error) {\n console.error('gyral devtools listener threw', error);\n }\n}\n\nconst now = (): number => performance.now();\n\n/** Connected components, so a panel loaded later still lists them (dev builds only). */\nconst live = new Map<Element, string>();\n\n/** Components connected right now, for a panel that starts after they did. */\nexport function devLiveComponents(): readonly DevComponentRef[] {\n return [...live].map(([element, tag]) => ref(element, tag));\n}\n\nexport function devConnect(element: Element, tag: string, connected: boolean): void {\n warnLeakingLitHtmlOnce();\n if (connected) live.set(element, tag);\n else live.delete(element);\n emit(() => ({\n kind: connected ? 'connect' : 'disconnect',\n component: ref(element, tag),\n at: now(),\n }));\n}\n\nexport function devUpdate(\n element: Element,\n tag: string,\n msg: Tagged,\n prev: unknown,\n next: unknown,\n) {\n emit(() => ({ kind: 'update', component: ref(element, tag), msg, prev, next, at: now() }));\n}\n\nexport function devHydrated(element: Element, tag: string, serverRendered: boolean): void {\n emit(() => ({ kind: 'hydrated', component: ref(element, tag), serverRendered, at: now() }));\n}\n\nexport function devStore(store: string, msg: Tagged, prev: unknown, next: unknown): void {\n emit(() => ({ kind: 'store', store, msg, prev, next, at: now() }));\n}\n\n/** A command tracer for one owner (`<tag>#id` or `store:name`). */\nexport function devCommands(owner: () => string): CommandTrace {\n return (event) => {\n emit(() => ({ kind: 'command', owner: owner(), ...event, at: now() }));\n };\n}\n\n/** The label the panel shows for a component's commands. */\nexport function devOwner(element: Element, tag: string): string {\n return `<${tag}>#${String(ref(element, tag).id)}`;\n}\n"]}
1
+ {"version":3,"file":"devtools.js","sourceRoot":"","sources":["../src/devtools.ts"],"names":[],"mappings":"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","sourcesContent":["// Development build of the devtools hook (ADR 0017). Resolved through the `#devtools` import\n// with the `development` condition; production builds get devtools-off.ts instead, so the\n// guarded call sites (`if (DEVTOOLS_ENABLED) …`) disappear from the bundle.\nimport {\n DEVTOOLS_GLOBAL,\n type CommandTrace,\n type DevComponentRef,\n type DevEvent,\n type DevtoolsHook,\n} from './devtools-events.js';\nimport type { Tagged } from './types.js';\n\nexport const DEVTOOLS_ENABLED: boolean = true;\n\nconst hook = (): DevtoolsHook | undefined =>\n (globalThis as Record<string, unknown>)[DEVTOOLS_GLOBAL] as DevtoolsHook | undefined;\n\nconst ids = new WeakMap<Element, number>();\nlet nextId = 1;\n\nfunction ref(element: Element, tag: string): DevComponentRef {\n let id = ids.get(element);\n if (id === undefined) {\n id = nextId++;\n ids.set(element, id);\n }\n return { tag, id, element };\n}\n\n// Builds nothing unless a listener is installed: zero cost in dev without devtools.\nfunction emit(make: () => DevEvent): void {\n const listener = hook();\n if (listener === undefined) return;\n try {\n listener.emit(make());\n } catch (error) {\n console.error('gyral devtools listener threw', error);\n }\n}\n\nconst now = (): number => performance.now();\n\n/** Connected components, so a panel loaded later still lists them (dev builds only). */\nconst live = new Map<Element, string>();\n\n/** Components connected right now, for a panel that starts after they did. */\nexport function devLiveComponents(): readonly DevComponentRef[] {\n return [...live].map(([element, tag]) => ref(element, tag));\n}\n\nexport function devConnect(element: Element, tag: string, connected: boolean): void {\n if (connected) live.set(element, tag);\n else live.delete(element);\n emit(() => ({\n kind: connected ? 'connect' : 'disconnect',\n component: ref(element, tag),\n at: now(),\n }));\n}\n\nexport function devUpdate(\n element: Element,\n tag: string,\n msg: Tagged,\n prev: unknown,\n next: unknown,\n) {\n emit(() => ({ kind: 'update', component: ref(element, tag), msg, prev, next, at: now() }));\n}\n\nexport function devHydrated(element: Element, tag: string, serverRendered: boolean): void {\n emit(() => ({ kind: 'hydrated', component: ref(element, tag), serverRendered, at: now() }));\n}\n\nexport function devMismatch(element: Element, tag: string, message: string): void {\n emit(() => ({ kind: 'mismatch', component: ref(element, tag), message, at: now() }));\n}\n\nexport function devStore(store: string, msg: Tagged, prev: unknown, next: unknown): void {\n emit(() => ({ kind: 'store', store, msg, prev, next, at: now() }));\n}\n\n/** A command tracer for one owner (`<tag>#id` or `store:name`). */\nexport function devCommands(owner: () => string): CommandTrace {\n return (event) => {\n emit(() => ({ kind: 'command', owner: owner(), ...event, at: now() }));\n };\n}\n\n/** The label the panel shows for a component's commands. */\nexport function devOwner(element: Element, tag: string): string {\n return `<${tag}>#${String(ref(element, tag).id)}`;\n}\n"]}
@@ -10,6 +10,6 @@ export declare function provideDrivers(element: Element, drivers: DriverOverride
10
10
  /**
11
11
  * The override for `name` from the nearest provider that has one. Providers nest: an inner
12
12
  * provider without that driver lets an outer one supply it. Commands never run on the server,
13
- * so there is nothing to resolve there.
13
+ * so only the browser calls this.
14
14
  */
15
15
  export declare function providedDriver(host: Element, name: string): AnyDriver | undefined;
@@ -1,8 +1,3 @@
1
- // Tree-scoped driver overrides (gyral-czi.35, ADR 0006 addendum): which driver a command uses.
2
- // Resolution: el.drivers → nearest driver provider (across shadow roots) → spec.drivers →
3
- // the command's own driver. Mirrors <gyral-stores> (ADR 0013) for stores.
4
- import { isServer } from 'lit';
5
- const onServer = isServer;
6
1
  /** Provider element name: `<gyral-drivers .drivers=${{ http: fake }}>…</gyral-drivers>`. */
7
2
  export const DRIVERS_ELEMENT = 'gyral-drivers';
8
3
  // Elements registered with provideDrivers() (any element can act as a provider).
@@ -30,11 +25,9 @@ function overridesOf(node) {
30
25
  /**
31
26
  * The override for `name` from the nearest provider that has one. Providers nest: an inner
32
27
  * provider without that driver lets an outer one supply it. Commands never run on the server,
33
- * so there is nothing to resolve there.
28
+ * so only the browser calls this.
34
29
  */
35
30
  export function providedDriver(host, name) {
36
- if (onServer)
37
- return undefined;
38
31
  for (let node = host.parentNode; node !== null;) {
39
32
  if (node instanceof Element) {
40
33
  const driver = overridesOf(node)?.[name];
@@ -1 +1 @@
1
- {"version":3,"file":"drivers-scope.js","sourceRoot":"","sources":["../src/drivers-scope.ts"],"names":[],"mappings":"AAAA,+FAA+F;AAC/F,0FAA0F;AAC1F,0EAA0E;AAC1E,OAAO,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;AAG/B,MAAM,QAAQ,GAAY,QAAQ,CAAC;AAEnC,4FAA4F;AAC5F,MAAM,CAAC,MAAM,eAAe,GAAG,eAAe,CAAC;AAE/C,iFAAiF;AACjF,MAAM,QAAQ,GAAG,IAAI,OAAO,EAA4B,CAAC;AAEzD;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,OAAgB,EAAE,OAAwB;IACvE,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC/B,OAAO,GAAG,EAAE;QACV,IAAI,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,OAAO;YAAE,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAClE,CAAC,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAAC,IAAa;IAChC,MAAM,UAAU,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACtC,IAAI,UAAU,KAAK,SAAS;QAAE,OAAO,UAAU,CAAC;IAChD,IAAI,IAAI,CAAC,SAAS,KAAK,eAAe;QAAE,OAAO,SAAS,CAAC;IACzD,OAAQ,IAAgD,CAAC,OAAO,CAAC;AACnE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,IAAa,EAAE,IAAY;IACxD,IAAI,QAAQ;QAAE,OAAO,SAAS,CAAC;IAC/B,KAAK,IAAI,IAAI,GAAgB,IAAI,CAAC,UAAU,EAAE,IAAI,KAAK,IAAI,GAAG,CAAC;QAC7D,IAAI,IAAI,YAAY,OAAO,EAAE,CAAC;YAC5B,MAAM,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;YACzC,IAAI,MAAM,KAAK,SAAS;gBAAE,OAAO,MAAM,CAAC;QAC1C,CAAC;QACD,IAAI,GAAG,IAAI,YAAY,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC;IAClE,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC","sourcesContent":["// Tree-scoped driver overrides (gyral-czi.35, ADR 0006 addendum): which driver a command uses.\n// Resolution: el.drivers → nearest driver provider (across shadow roots) → spec.drivers →\n// the command's own driver. Mirrors <gyral-stores> (ADR 0013) for stores.\nimport { isServer } from 'lit';\nimport type { AnyDriver, DriverOverrides } from './command.js';\n\nconst onServer: boolean = isServer;\n\n/** Provider element name: `<gyral-drivers .drivers=${{ http: fake }}>…</gyral-drivers>`. */\nexport const DRIVERS_ELEMENT = 'gyral-drivers';\n\n// Elements registered with provideDrivers() (any element can act as a provider).\nconst provided = new WeakMap<Element, DriverOverrides>();\n\n/**\n * Makes `element` a driver provider for every Gyral component below it (including inside\n * shadow roots). Returns a function that removes the overrides. Use it on a test container\n * or an app root; a `<gyral-drivers>` element with a `.drivers` property works the same way.\n */\nexport function provideDrivers(element: Element, drivers: DriverOverrides): () => void {\n provided.set(element, drivers);\n return () => {\n if (provided.get(element) === drivers) provided.delete(element);\n };\n}\n\nfunction overridesOf(node: Element): DriverOverrides | undefined {\n const registered = provided.get(node);\n if (registered !== undefined) return registered;\n if (node.localName !== DRIVERS_ELEMENT) return undefined;\n return (node as Element & { drivers?: DriverOverrides }).drivers;\n}\n\n/**\n * The override for `name` from the nearest provider that has one. Providers nest: an inner\n * provider without that driver lets an outer one supply it. Commands never run on the server,\n * so there is nothing to resolve there.\n */\nexport function providedDriver(host: Element, name: string): AnyDriver | undefined {\n if (onServer) return undefined;\n for (let node: Node | null = host.parentNode; node !== null;) {\n if (node instanceof Element) {\n const driver = overridesOf(node)?.[name];\n if (driver !== undefined) return driver;\n }\n node = node instanceof ShadowRoot ? node.host : node.parentNode;\n }\n return undefined;\n}\n"]}
1
+ {"version":3,"file":"drivers-scope.js","sourceRoot":"","sources":["../src/drivers-scope.ts"],"names":[],"mappings":"AAKA,4FAA4F;AAC5F,MAAM,CAAC,MAAM,eAAe,GAAG,eAAe,CAAC;AAE/C,iFAAiF;AACjF,MAAM,QAAQ,GAAG,IAAI,OAAO,EAA4B,CAAC;AAEzD;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,OAAgB,EAAE,OAAwB;IACvE,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC/B,OAAO,GAAG,EAAE;QACV,IAAI,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,OAAO;YAAE,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAClE,CAAC,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAAC,IAAa;IAChC,MAAM,UAAU,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACtC,IAAI,UAAU,KAAK,SAAS;QAAE,OAAO,UAAU,CAAC;IAChD,IAAI,IAAI,CAAC,SAAS,KAAK,eAAe;QAAE,OAAO,SAAS,CAAC;IACzD,OAAQ,IAAgD,CAAC,OAAO,CAAC;AACnE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,IAAa,EAAE,IAAY;IACxD,KAAK,IAAI,IAAI,GAAgB,IAAI,CAAC,UAAU,EAAE,IAAI,KAAK,IAAI,GAAG,CAAC;QAC7D,IAAI,IAAI,YAAY,OAAO,EAAE,CAAC;YAC5B,MAAM,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;YACzC,IAAI,MAAM,KAAK,SAAS;gBAAE,OAAO,MAAM,CAAC;QAC1C,CAAC;QACD,IAAI,GAAG,IAAI,YAAY,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC;IAClE,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC","sourcesContent":["// Tree-scoped driver overrides (gyral-czi.35, ADR 0006 addendum): which driver a command uses.\n// Resolution: el.drivers → nearest driver provider (across shadow roots) → spec.drivers →\n// the command's own driver. Mirrors <gyral-stores> (ADR 0013) for stores.\nimport type { AnyDriver, DriverOverrides } from './command.js';\n\n/** Provider element name: `<gyral-drivers .drivers=${{ http: fake }}>…</gyral-drivers>`. */\nexport const DRIVERS_ELEMENT = 'gyral-drivers';\n\n// Elements registered with provideDrivers() (any element can act as a provider).\nconst provided = new WeakMap<Element, DriverOverrides>();\n\n/**\n * Makes `element` a driver provider for every Gyral component below it (including inside\n * shadow roots). Returns a function that removes the overrides. Use it on a test container\n * or an app root; a `<gyral-drivers>` element with a `.drivers` property works the same way.\n */\nexport function provideDrivers(element: Element, drivers: DriverOverrides): () => void {\n provided.set(element, drivers);\n return () => {\n if (provided.get(element) === drivers) provided.delete(element);\n };\n}\n\nfunction overridesOf(node: Element): DriverOverrides | undefined {\n const registered = provided.get(node);\n if (registered !== undefined) return registered;\n if (node.localName !== DRIVERS_ELEMENT) return undefined;\n return (node as Element & { drivers?: DriverOverrides }).drivers;\n}\n\n/**\n * The override for `name` from the nearest provider that has one. Providers nest: an inner\n * provider without that driver lets an outer one supply it. Commands never run on the server,\n * so only the browser calls this.\n */\nexport function providedDriver(host: Element, name: string): AnyDriver | undefined {\n for (let node: Node | null = host.parentNode; node !== null;) {\n if (node instanceof Element) {\n const driver = overridesOf(node)?.[name];\n if (driver !== undefined) return driver;\n }\n node = node instanceof ShadowRoot ? node.host : node.parentNode;\n }\n return undefined;\n}\n"]}
@@ -1,9 +1,11 @@
1
- import type { LitElement } from 'lit';
2
1
  import type { DriverOverrides } from './command.js';
3
2
  import type { StoreOverrides } from './store.js';
4
3
  import type { ComponentSpec, Tagged } from './types.js';
5
- /** The custom element class produced by `define()`. */
6
- export interface GyralElement<S, M extends Tagged> extends LitElement {
4
+ /**
5
+ * The custom element `define()` produces: a plain `HTMLElement` (view/05-element.md "Public
6
+ * instance API"). Tests wait for rendering with `settled()`.
7
+ */
8
+ export interface GyralElement<S, M extends Tagged> extends HTMLElement {
7
9
  /** Current model state. */
8
10
  readonly state: S;
9
11
  /** Feeds a message through `update`, as if an intent had produced it. */
@@ -1 +1 @@
1
- {"version":3,"file":"element-types.js","sourceRoot":"","sources":["../src/element-types.ts"],"names":[],"mappings":"","sourcesContent":["import type { LitElement } from 'lit';\nimport type { DriverOverrides } from './command.js';\nimport type { StoreOverrides } from './store.js';\nimport type { ComponentSpec, Tagged } from './types.js';\n\n/** The custom element class produced by `define()`. */\nexport interface GyralElement<S, M extends Tagged> extends LitElement {\n /** Current model state. */\n readonly state: S;\n /** Feeds a message through `update`, as if an intent had produced it. */\n send(msg: M): void;\n /** Per-instance driver substitutions by name (test fakes). Checked before the spec's. */\n drivers: DriverOverrides;\n /**\n * Per-instance store instances by store name (tests, islands). Checked before the nearest\n * `<gyral-stores>` provider and the document default (ADR 0013).\n */\n stores: StoreOverrides;\n /**\n * Messages applied through `update` right after `init`, before the first render. The server\n * uses it to render a rejected form with the same reducer as the JS path (ADR 0008). Ignored\n * when the element resumes from a hydration seed (the seed already contains their effect).\n */\n initialMessages: readonly Tagged[];\n}\n\nexport interface GyralElementClass<S, M extends Tagged, P, O extends Tagged = never> {\n /** Instances expose their declared props as settable properties. */\n new (): GyralElement<S, M> & { -readonly [K in keyof P]: P[K] };\n readonly spec: ComponentSpec<S, M, P>;\n readonly tagName: string;\n /** Type-only: the outputs this component emits (read by `child()`). */\n readonly outputs?: O;\n}\n"]}
1
+ {"version":3,"file":"element-types.js","sourceRoot":"","sources":["../src/element-types.ts"],"names":[],"mappings":"","sourcesContent":["import type { DriverOverrides } from './command.js';\nimport type { StoreOverrides } from './store.js';\nimport type { ComponentSpec, Tagged } from './types.js';\n\n/**\n * The custom element `define()` produces: a plain `HTMLElement` (view/05-element.md \"Public\n * instance API\"). Tests wait for rendering with `settled()`.\n */\nexport interface GyralElement<S, M extends Tagged> extends HTMLElement {\n /** Current model state. */\n readonly state: S;\n /** Feeds a message through `update`, as if an intent had produced it. */\n send(msg: M): void;\n /** Per-instance driver substitutions by name (test fakes). Checked before the spec's. */\n drivers: DriverOverrides;\n /**\n * Per-instance store instances by store name (tests, islands). Checked before the nearest\n * `<gyral-stores>` provider and the document default (ADR 0013).\n */\n stores: StoreOverrides;\n /**\n * Messages applied through `update` right after `init`, before the first render. The server\n * uses it to render a rejected form with the same reducer as the JS path (ADR 0008). Ignored\n * when the element resumes from a hydration seed (the seed already contains their effect).\n */\n initialMessages: readonly Tagged[];\n}\n\nexport interface GyralElementClass<S, M extends Tagged, P, O extends Tagged = never> {\n /** Instances expose their declared props as settable properties. */\n new (): GyralElement<S, M> & { -readonly [K in keyof P]: P[K] };\n readonly spec: ComponentSpec<S, M, P>;\n readonly tagName: string;\n /** Type-only: the outputs this component emits (read by `child()`). */\n readonly outputs?: O;\n}\n"]}
@@ -0,0 +1,3 @@
1
+ import type { ComponentSpec, Tagged } from './types.js';
2
+ /** The element class for `spec` (not yet registered); define() types it for the spec. */
3
+ export declare function elementClass<S, M extends Tagged, P>(tag: string, spec: ComponentSpec<S, M, P>): CustomElementConstructor;
@@ -0,0 +1,269 @@
1
+ // The element define() creates (docs/design-docs/view/05-element.md): a plain HTMLElement
2
+ // subclass. Declared props are prototype accessors over Standard Schema builders; renders go
3
+ // through the global scheduler (view/04-scheduler.md); intents are delegated listeners on the
4
+ // root (ADR 0001). The model side (state, commands, stores) is host-model.ts.
5
+ import { DEVTOOLS_ENABLED, devConnect, devHydrated } from '#devtools';
6
+ import { HostModel } from './host-model.js';
7
+ import { hydrationCode, takeSeed, whenHydrationLoads } from './hydration.js';
8
+ import { DEFAULT_EVENTS, eventsOf, handleIntent, hostDepth, intentNames, listenForIntents, } from './intent.js';
9
+ import { isLight } from './light-dom.js';
10
+ import { features } from './features.js';
11
+ import { afterRender, markDirty, POST_HYDRATED, POST_INIT, POST_STATES, } from './scheduler.js';
12
+ import { stateSync } from './states.js';
13
+ import { render, sheetsFor } from './view/index.js';
14
+ const DEFER = 'defer-hydration';
15
+ /** The element class for `spec` (not yet registered); define() types it for the spec. */
16
+ export function elementClass(tag, spec) {
17
+ const table = (spec.props ?? {});
18
+ const names = Object.keys(table);
19
+ // Registered by the prop builders (features.ts): set whenever a component declares props.
20
+ const props = features.props;
21
+ const attrs = new Map();
22
+ const light = isLight(spec);
23
+ let sheets;
24
+ const parsers = spec.intent;
25
+ const model = spec;
26
+ class Element extends HTMLElement {
27
+ static { this.spec = spec; }
28
+ static { this.tagName = tag; }
29
+ static get observedAttributes() {
30
+ return [...attrs.keys(), DEFER];
31
+ }
32
+ static {
33
+ for (const name of names) {
34
+ const def = table[name];
35
+ const attr = def === undefined ? undefined : props.attributeOf(name, def);
36
+ if (attr !== undefined)
37
+ attrs.set(attr, name);
38
+ Object.defineProperty(this.prototype, name, {
39
+ configurable: true,
40
+ enumerable: true,
41
+ get() {
42
+ return this.#values[name];
43
+ },
44
+ set(value) {
45
+ this.#write(name, props.propertyValue(tag, name, table[name], value));
46
+ },
47
+ });
48
+ }
49
+ }
50
+ #values = {};
51
+ #root;
52
+ #rendered = false;
53
+ /** Something changed while disconnected: render on reconnect. */
54
+ #stale = false;
55
+ #serverRendered = false;
56
+ /** The first render adopts the server's DOM (07): resumed from a seed, root not empty. */
57
+ #hydrating = false;
58
+ /** init's commands for a server-rendered host: started after its first render. */
59
+ #afterInit = [];
60
+ #states;
61
+ #task = {
62
+ tag,
63
+ depth: 0,
64
+ render: () => {
65
+ this.#render();
66
+ },
67
+ };
68
+ #model = new HostModel({
69
+ el: this,
70
+ tag,
71
+ props: () => (names.length > 0 ? props.readProps(this.#values, table) : {}),
72
+ root: () => this.#root,
73
+ invalidate: (onFrame) => {
74
+ this.#invalidate(onFrame);
75
+ },
76
+ }, model);
77
+ constructor() {
78
+ super();
79
+ const self = this;
80
+ self['drivers'] ??= {};
81
+ self['stores'] ??= {};
82
+ self['initialMessages'] ??= [];
83
+ // Upgrade capture: a property set before the class was defined hides the accessor.
84
+ for (const name of names) {
85
+ if (!Object.hasOwn(this, name))
86
+ continue;
87
+ const value = self[name];
88
+ Reflect.deleteProperty(this, name);
89
+ self[name] = value;
90
+ }
91
+ }
92
+ get state() {
93
+ return this.#state();
94
+ }
95
+ #state() {
96
+ if (!this.#model.ready && names.length > 0)
97
+ props.warnMissing(tag, this.#values, table);
98
+ return this.#model.state(this.initialMessages);
99
+ }
100
+ send(msg) {
101
+ this.#model.dispatch(msg);
102
+ }
103
+ connectedCallback() {
104
+ if (this.#root !== undefined) {
105
+ this.#connect();
106
+ return;
107
+ }
108
+ this.#resume();
109
+ this.#begin();
110
+ }
111
+ /** `moveBefore()` keeps everything: no disconnect, no re-resolution (view/03-lists.md). */
112
+ connectedMoveCallback() {
113
+ // Intentionally empty.
114
+ }
115
+ disconnectedCallback() {
116
+ this.#model.disconnect();
117
+ if (DEVTOOLS_ENABLED)
118
+ devConnect(this, tag, false);
119
+ }
120
+ attributeChangedCallback(name, _old, raw) {
121
+ if (name === DEFER) {
122
+ if (raw === null && this.isConnected && this.#root === undefined)
123
+ this.#begin();
124
+ return;
125
+ }
126
+ const prop = attrs.get(name);
127
+ if (prop !== undefined)
128
+ this.#write(prop, props.attributeValue(tag, prop, table[prop], name, raw));
129
+ }
130
+ #write(name, value) {
131
+ if (Object.is(this.#values[name], value))
132
+ return;
133
+ this.#values[name] = value;
134
+ if (this.#model.ready)
135
+ this.#invalidate();
136
+ }
137
+ /** Hydration seeds (ADR 0012): the server's state and the props no attribute carried. */
138
+ #resume() {
139
+ if (this.#model.ready)
140
+ return;
141
+ const seed = takeSeed(this);
142
+ if (seed === undefined)
143
+ return;
144
+ for (const [name, value] of Object.entries(seed.props)) {
145
+ const def = table[name];
146
+ if (def === undefined || this.#values[name] !== undefined)
147
+ continue;
148
+ this.#values[name] = props.propertyValue(tag, name, def, value, 'the seed');
149
+ }
150
+ this.#afterInit = this.#model.resume(seed);
151
+ this.#serverRendered = true;
152
+ }
153
+ /**
154
+ * Starts the host, or waits: for the hydration code (a server-rendered host or an island,
155
+ * view/07-hydration.md "Loading"), then for an island's trigger (released by
156
+ * attributeChangedCallback).
157
+ */
158
+ #begin() {
159
+ const defer = this.hasAttribute(DEFER);
160
+ if (hydrationCode === undefined && (this.#serverRendered || defer)) {
161
+ whenHydrationLoads(() => {
162
+ if (this.isConnected && this.#root === undefined)
163
+ this.#begin();
164
+ });
165
+ }
166
+ else if (defer && hydrationCode !== null)
167
+ hydrationCode?.scheduleIsland(this);
168
+ else
169
+ this.#start();
170
+ }
171
+ #start() {
172
+ const root = light ? this : (this.shadowRoot ?? this.attachShadow({ mode: 'open' }));
173
+ this.#root = root;
174
+ this.#hydrating = this.#serverRendered && hydrationCode != null && root.hasChildNodes();
175
+ sheets ??= light ? [] : sheetsFor(spec.styles);
176
+ // Rendering fresh: a shadow root without a seed (hand-written DSD) or a server-rendered
177
+ // host whose hydration code failed to load starts empty.
178
+ if (!this.#hydrating) {
179
+ if (!light || this.#serverRendered)
180
+ root.replaceChildren();
181
+ if (!light)
182
+ root.adoptedStyleSheets = sheets;
183
+ }
184
+ this.#listen(DEFAULT_EVENTS);
185
+ if (spec.events !== undefined)
186
+ this.#listen(spec.events);
187
+ this.#state(); // init, unless resumed from a seed
188
+ this.#connect();
189
+ }
190
+ #connect() {
191
+ this.#task.depth = hostDepth(this);
192
+ const rebound = this.#model.connect();
193
+ if (DEVTOOLS_ENABLED)
194
+ devConnect(this, tag, true);
195
+ if (!this.#rendered || this.#stale || rebound)
196
+ this.#invalidate();
197
+ }
198
+ #invalidate(onFrame = false) {
199
+ if (this.#root === undefined)
200
+ return;
201
+ if (this.isConnected)
202
+ markDirty(this.#task, onFrame);
203
+ else
204
+ this.#stale = true;
205
+ }
206
+ /** One render (the scheduler calls it): PropsChanged first, then the view and its commit. */
207
+ #render() {
208
+ const root = this.#root;
209
+ if (root === undefined || !this.isConnected) {
210
+ this.#stale = true;
211
+ return;
212
+ }
213
+ this.#stale = false;
214
+ this.#model.syncProps(names);
215
+ const view = spec.view(this.state, intentNames, this.#model.ctx());
216
+ if (this.#hydrating) {
217
+ hydrationCode?.hydrateRoot(this, tag, view, root, light ? undefined : sheets, this.#seen);
218
+ this.#hydrating = false;
219
+ }
220
+ else
221
+ render(view, root, this.#seen);
222
+ if (spec.states !== undefined)
223
+ afterRender(POST_STATES, this.#syncStates);
224
+ if (this.#rendered)
225
+ return;
226
+ this.#rendered = true;
227
+ if (DEVTOOLS_ENABLED)
228
+ devHydrated(this, tag, this.#serverRendered);
229
+ if (this.#model.hasReducer('Hydrated')) {
230
+ const msg = { _tag: 'Hydrated', serverRendered: this.#serverRendered };
231
+ afterRender(POST_HYDRATED, () => {
232
+ this.#model.dispatch(msg);
233
+ });
234
+ }
235
+ const commands = this.#afterInit;
236
+ this.#afterInit = [];
237
+ if (commands.length > 0) {
238
+ afterRender(POST_INIT, () => {
239
+ this.#model.run(commands);
240
+ });
241
+ }
242
+ }
243
+ #syncStates = () => {
244
+ // ElementInternals is attached lazily, once, when the first states sync needs it (05).
245
+ this.#states ??= stateSync(this.attachInternals());
246
+ if (this.#states !== false && spec.states !== undefined)
247
+ this.#states(spec.states(this.state));
248
+ };
249
+ /** Intent event types this host's root listens for (view/05-element.md "Intent events"). */
250
+ #listening = new Set();
251
+ #listen(types) {
252
+ listenForIntents(this.#root, this.#listening, types, this.#onEvent);
253
+ }
254
+ /** Told about each template a render instantiates: listen for what its markup names. */
255
+ #seen = (markup) => {
256
+ this.#listen(eventsOf(markup));
257
+ };
258
+ #onEvent = (event) => {
259
+ if (this.#root === undefined)
260
+ return;
261
+ handleIntent(event, this.#root, parsers, tag, (msg) => {
262
+ if (msg !== undefined && this.isConnected)
263
+ this.#model.dispatch(msg);
264
+ });
265
+ };
266
+ }
267
+ return Element;
268
+ }
269
+ //# sourceMappingURL=element.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"element.js","sourceRoot":"","sources":["../src/element.ts"],"names":[],"mappings":"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","sourcesContent":["// The element define() creates (docs/design-docs/view/05-element.md): a plain HTMLElement\n// subclass. Declared props are prototype accessors over Standard Schema builders; renders go\n// through the global scheduler (view/04-scheduler.md); intents are delegated listeners on the\n// root (ADR 0001). The model side (state, commands, stores) is host-model.ts.\nimport { DEVTOOLS_ENABLED, devConnect, devHydrated } from '#devtools';\nimport type { DriverOverrides } from './command.js';\nimport type { GyralElement } from './element-types.js';\nimport { HostModel, type ModelCommand } from './host-model.js';\nimport { hydrationCode, takeSeed, whenHydrationLoads } from './hydration.js';\nimport {\n DEFAULT_EVENTS,\n eventsOf,\n handleIntent,\n hostDepth,\n intentNames,\n listenForIntents,\n} from './intent.js';\nimport { isLight } from './light-dom.js';\nimport { features } from './features.js';\nimport type { PropFeature, PropTable } from './props.js';\nimport {\n afterRender,\n markDirty,\n POST_HYDRATED,\n POST_INIT,\n POST_STATES,\n type HostTask,\n} from './scheduler.js';\nimport { stateSync, type StateSync } from './states.js';\nimport type { StoreOverrides } from './store.js';\nimport type { ComponentSpec, IntentNames, IntentParser, Tagged } from './types.js';\nimport { render, sheetsFor, type Markup } from './view/index.js';\n\nconst DEFER = 'defer-hydration';\n\ntype Bag = Record<string, unknown>;\n/** The element class for `spec` (not yet registered); define() types it for the spec. */\nexport function elementClass<S, M extends Tagged, P>(\n tag: string,\n spec: ComponentSpec<S, M, P>,\n): CustomElementConstructor {\n const table = (spec.props ?? {}) as PropTable;\n const names = Object.keys(table);\n // Registered by the prop builders (features.ts): set whenever a component declares props.\n const props = features.props as PropFeature;\n const attrs = new Map<string, string>();\n const light = isLight(spec);\n let sheets: CSSStyleSheet[] | undefined;\n const parsers = spec.intent as Readonly<Record<string, IntentParser<M> | undefined>>;\n const model = spec as unknown as ComponentSpec<S, Tagged, P>;\n\n class Element extends HTMLElement implements GyralElement<S, M> {\n static readonly spec = spec;\n static readonly tagName = tag;\n static get observedAttributes(): string[] {\n return [...attrs.keys(), DEFER];\n }\n\n static {\n for (const name of names) {\n const def = table[name];\n const attr = def === undefined ? undefined : props.attributeOf(name, def);\n if (attr !== undefined) attrs.set(attr, name);\n Object.defineProperty(this.prototype, name, {\n configurable: true,\n enumerable: true,\n get(this: Element): unknown {\n return this.#values[name];\n },\n set(this: Element, value: unknown) {\n this.#write(name, props.propertyValue(tag, name, table[name], value));\n },\n });\n }\n }\n\n declare drivers: DriverOverrides;\n declare stores: StoreOverrides;\n declare initialMessages: readonly Tagged[];\n\n #values: Bag = {};\n #root: ShadowRoot | HTMLElement | undefined;\n #rendered = false;\n /** Something changed while disconnected: render on reconnect. */\n #stale = false;\n #serverRendered = false;\n /** The first render adopts the server's DOM (07): resumed from a seed, root not empty. */\n #hydrating = false;\n /** init's commands for a server-rendered host: started after its first render. */\n #afterInit: readonly ModelCommand[] = [];\n #states: StateSync | false | undefined;\n #task: HostTask = {\n tag,\n depth: 0,\n render: () => {\n this.#render();\n },\n };\n #model = new HostModel<S, P>(\n {\n el: this,\n tag,\n props: () => (names.length > 0 ? props.readProps(this.#values, table) : {}),\n root: () => this.#root,\n invalidate: (onFrame) => {\n this.#invalidate(onFrame);\n },\n },\n model,\n );\n\n constructor() {\n super();\n const self = this as unknown as Bag;\n self['drivers'] ??= {};\n self['stores'] ??= {};\n self['initialMessages'] ??= [];\n // Upgrade capture: a property set before the class was defined hides the accessor.\n for (const name of names) {\n if (!Object.hasOwn(this, name)) continue;\n const value = self[name];\n Reflect.deleteProperty(this, name);\n self[name] = value;\n }\n }\n\n get state(): S {\n return this.#state();\n }\n\n #state(): S {\n if (!this.#model.ready && names.length > 0) props.warnMissing(tag, this.#values, table);\n return this.#model.state(this.initialMessages);\n }\n\n send(msg: M): void {\n this.#model.dispatch(msg);\n }\n\n connectedCallback(): void {\n if (this.#root !== undefined) {\n this.#connect();\n return;\n }\n this.#resume();\n this.#begin();\n }\n\n /** `moveBefore()` keeps everything: no disconnect, no re-resolution (view/03-lists.md). */\n connectedMoveCallback(): void {\n // Intentionally empty.\n }\n\n disconnectedCallback(): void {\n this.#model.disconnect();\n if (DEVTOOLS_ENABLED) devConnect(this, tag, false);\n }\n\n attributeChangedCallback(name: string, _old: string | null, raw: string | null): void {\n if (name === DEFER) {\n if (raw === null && this.isConnected && this.#root === undefined) this.#begin();\n return;\n }\n const prop = attrs.get(name);\n if (prop !== undefined)\n this.#write(prop, props.attributeValue(tag, prop, table[prop], name, raw));\n }\n\n #write(name: string, value: unknown): void {\n if (Object.is(this.#values[name], value)) return;\n this.#values[name] = value;\n if (this.#model.ready) this.#invalidate();\n }\n\n /** Hydration seeds (ADR 0012): the server's state and the props no attribute carried. */\n #resume(): void {\n if (this.#model.ready) return;\n const seed = takeSeed(this);\n if (seed === undefined) return;\n for (const [name, value] of Object.entries(seed.props)) {\n const def = table[name];\n if (def === undefined || this.#values[name] !== undefined) continue;\n this.#values[name] = props.propertyValue(tag, name, def, value, 'the seed');\n }\n this.#afterInit = this.#model.resume(seed);\n this.#serverRendered = true;\n }\n\n /**\n * Starts the host, or waits: for the hydration code (a server-rendered host or an island,\n * view/07-hydration.md \"Loading\"), then for an island's trigger (released by\n * attributeChangedCallback).\n */\n #begin(): void {\n const defer = this.hasAttribute(DEFER);\n if (hydrationCode === undefined && (this.#serverRendered || defer)) {\n whenHydrationLoads(() => {\n if (this.isConnected && this.#root === undefined) this.#begin();\n });\n } else if (defer && hydrationCode !== null) hydrationCode?.scheduleIsland(this);\n else this.#start();\n }\n\n #start(): void {\n const root = light ? this : (this.shadowRoot ?? this.attachShadow({ mode: 'open' }));\n this.#root = root;\n this.#hydrating = this.#serverRendered && hydrationCode != null && root.hasChildNodes();\n sheets ??= light ? [] : sheetsFor(spec.styles);\n // Rendering fresh: a shadow root without a seed (hand-written DSD) or a server-rendered\n // host whose hydration code failed to load starts empty.\n if (!this.#hydrating) {\n if (!light || this.#serverRendered) root.replaceChildren();\n if (!light) (root as ShadowRoot).adoptedStyleSheets = sheets;\n }\n this.#listen(DEFAULT_EVENTS);\n if (spec.events !== undefined) this.#listen(spec.events);\n this.#state(); // init, unless resumed from a seed\n this.#connect();\n }\n\n #connect(): void {\n this.#task.depth = hostDepth(this);\n const rebound = this.#model.connect();\n if (DEVTOOLS_ENABLED) devConnect(this, tag, true);\n if (!this.#rendered || this.#stale || rebound) this.#invalidate();\n }\n\n #invalidate(onFrame = false): void {\n if (this.#root === undefined) return;\n if (this.isConnected) markDirty(this.#task, onFrame);\n else this.#stale = true;\n }\n\n /** One render (the scheduler calls it): PropsChanged first, then the view and its commit. */\n #render(): void {\n const root = this.#root;\n if (root === undefined || !this.isConnected) {\n this.#stale = true;\n return;\n }\n this.#stale = false;\n this.#model.syncProps(names);\n const view = spec.view(this.state, intentNames as IntentNames<M>, this.#model.ctx());\n if (this.#hydrating) {\n hydrationCode?.hydrateRoot(this, tag, view, root, light ? undefined : sheets, this.#seen);\n this.#hydrating = false;\n } else render(view, root, this.#seen);\n if (spec.states !== undefined) afterRender(POST_STATES, this.#syncStates);\n if (this.#rendered) return;\n this.#rendered = true;\n if (DEVTOOLS_ENABLED) devHydrated(this, tag, this.#serverRendered);\n if (this.#model.hasReducer('Hydrated')) {\n const msg = { _tag: 'Hydrated', serverRendered: this.#serverRendered } as Tagged;\n afterRender(POST_HYDRATED, () => {\n this.#model.dispatch(msg);\n });\n }\n const commands = this.#afterInit;\n this.#afterInit = [];\n if (commands.length > 0) {\n afterRender(POST_INIT, () => {\n this.#model.run(commands);\n });\n }\n }\n\n #syncStates = (): void => {\n // ElementInternals is attached lazily, once, when the first states sync needs it (05).\n this.#states ??= stateSync(this.attachInternals());\n if (this.#states !== false && spec.states !== undefined)\n this.#states(spec.states(this.state));\n };\n\n /** Intent event types this host's root listens for (view/05-element.md \"Intent events\"). */\n #listening = new Set<string>();\n\n #listen(types: readonly string[]): void {\n listenForIntents(this.#root as Node, this.#listening, types, this.#onEvent);\n }\n\n /** Told about each template a render instantiates: listen for what its markup names. */\n #seen = (markup: Markup): void => {\n this.#listen(eventsOf(markup));\n };\n\n #onEvent = (event: Event): void => {\n if (this.#root === undefined) return;\n handleIntent(event, this.#root, parsers, tag, (msg) => {\n if (msg !== undefined && this.isConnected) this.#model.dispatch(msg);\n });\n };\n }\n return Element;\n}\n"]}
@@ -0,0 +1,24 @@
1
+ import type { Rule, Scope } from 'eslint';
2
+ export type Node = Rule.Node;
3
+ export type NodeOf<T extends Node['type']> = Extract<Node, {
4
+ type: T;
5
+ }>;
6
+ /** The default template sources, as in the Vite preset's `sources` option. */
7
+ export declare const DEFAULT_SOURCES: readonly string[];
8
+ /** The options both rules take. */
9
+ export declare const OPTIONS_SCHEMA: {
10
+ type: string;
11
+ properties: {
12
+ sources: {
13
+ type: string;
14
+ items: {
15
+ type: string;
16
+ };
17
+ };
18
+ };
19
+ additionalProperties: boolean;
20
+ }[];
21
+ export declare function sourcesOf(context: Rule.RuleContext): readonly string[];
22
+ export declare function findVariable(scope: Scope.Scope | null, name: string): Scope.Variable | undefined;
23
+ /** Whether `node` (a tag or callee) is the template sources' `name` export. */
24
+ export declare function isGyral(context: Rule.RuleContext, node: Node, name: string): boolean;
@@ -0,0 +1,78 @@
1
+ // Which identifiers are Gyral's `html` and `each` (@gyral/core/eslint). Like the template
2
+ // compiler (compiler/scan.ts), a binding counts only when it is imported from a template
3
+ // source: `import { html } from '@gyral/core'` (any local name) or `import * as g` used as
4
+ // `g.html`. ESLint's scope analysis resolves the name, so shadowing is handled. Core's own code
5
+ // and tests import from core's modules by relative path; those count too.
6
+ import { dirname, resolve } from 'node:path';
7
+ import { fileURLToPath } from 'node:url';
8
+ /** The default template sources, as in the Vite preset's `sources` option. */
9
+ export const DEFAULT_SOURCES = ['@gyral/core'];
10
+ /** The options both rules take. */
11
+ export const OPTIONS_SCHEMA = [
12
+ {
13
+ type: 'object',
14
+ properties: { sources: { type: 'array', items: { type: 'string' } } },
15
+ additionalProperties: false,
16
+ },
17
+ ];
18
+ /** Core's modules that export `html` and `each` (this file is src/eslint/ or dist/eslint/). */
19
+ const CORE_MODULES = ['../index', '../view/index', '../view/template', '../view/render/values']
20
+ .flatMap((name) => ['.ts', '.js'].map((ext) => new URL(`${name}${ext}`, import.meta.url)))
21
+ .map((url) => fileURLToPath(url));
22
+ export function sourcesOf(context) {
23
+ const options = context.options[0];
24
+ const sources = typeof options === 'object' && options !== null && 'sources' in options
25
+ ? options.sources
26
+ : undefined;
27
+ return Array.isArray(sources)
28
+ ? sources.filter((s) => typeof s === 'string')
29
+ : DEFAULT_SOURCES;
30
+ }
31
+ function isSource(context, specifier) {
32
+ if (sourcesOf(context).includes(specifier))
33
+ return true;
34
+ if (!specifier.startsWith('.'))
35
+ return false;
36
+ return CORE_MODULES.includes(resolve(dirname(context.filename), specifier));
37
+ }
38
+ /** typescript-eslint's `import type` marker (not in ESTree). */
39
+ const typeOnly = (node) => 'importKind' in node && node.importKind === 'type';
40
+ export function findVariable(scope, name) {
41
+ for (let s = scope; s !== null; s = s.upper) {
42
+ const v = s.set.get(name);
43
+ if (v !== undefined)
44
+ return v;
45
+ }
46
+ return undefined;
47
+ }
48
+ /** How `id` was imported from a template source: the export's name, or `*`. */
49
+ function importedAs(context, id) {
50
+ const variable = findVariable(context.sourceCode.getScope(id), id.name);
51
+ const def = variable?.defs[0];
52
+ if (def?.type !== 'ImportBinding')
53
+ return undefined;
54
+ const declaration = def.parent;
55
+ if (typeOnly(declaration) || !isSource(context, String(declaration.source.value))) {
56
+ return undefined;
57
+ }
58
+ const spec = def.node;
59
+ if (spec.type === 'ImportNamespaceSpecifier')
60
+ return '*';
61
+ if (spec.type !== 'ImportSpecifier' || typeOnly(spec))
62
+ return undefined;
63
+ const { imported } = spec;
64
+ return imported.type === 'Identifier' ? imported.name : String(imported.value);
65
+ }
66
+ /** Whether `node` (a tag or callee) is the template sources' `name` export. */
67
+ export function isGyral(context, node, name) {
68
+ if (node.type === 'Identifier')
69
+ return importedAs(context, node) === name;
70
+ if (node.type !== 'MemberExpression' || node.computed || node.object.type !== 'Identifier') {
71
+ return false;
72
+ }
73
+ const { property } = node;
74
+ return (property.type === 'Identifier' &&
75
+ property.name === name &&
76
+ importedAs(context, node.object) === '*');
77
+ }
78
+ //# sourceMappingURL=imports.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"imports.js","sourceRoot":"","sources":["../../src/eslint/imports.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAC1F,yFAAyF;AACzF,2FAA2F;AAC3F,gGAAgG;AAChG,0EAA0E;AAC1E,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAMzC,8EAA8E;AAC9E,MAAM,CAAC,MAAM,eAAe,GAAsB,CAAC,aAAa,CAAC,CAAC;AAElE,mCAAmC;AACnC,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B;QACE,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE;QACrE,oBAAoB,EAAE,KAAK;KAC5B;CACF,CAAC;AAEF,+FAA+F;AAC/F,MAAM,YAAY,GAAG,CAAC,UAAU,EAAE,eAAe,EAAE,kBAAkB,EAAE,uBAAuB,CAAC;KAC5F,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,GAAG,IAAI,GAAG,GAAG,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;KACzF,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC;AAEpC,MAAM,UAAU,SAAS,CAAC,OAAyB;IACjD,MAAM,OAAO,GAAY,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAC5C,MAAM,OAAO,GACX,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,IAAI,SAAS,IAAI,OAAO;QACrE,CAAC,CAAC,OAAO,CAAC,OAAO;QACjB,CAAC,CAAC,SAAS,CAAC;IAChB,OAAO,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;QAC3B,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC;QAC3D,CAAC,CAAC,eAAe,CAAC;AACtB,CAAC;AAED,SAAS,QAAQ,CAAC,OAAyB,EAAE,SAAiB;IAC5D,IAAI,SAAS,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC;QAAE,OAAO,IAAI,CAAC;IACxD,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IAC7C,OAAO,YAAY,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC;AAC9E,CAAC;AAED,gEAAgE;AAChE,MAAM,QAAQ,GAAG,CAAC,IAAY,EAAW,EAAE,CAAC,YAAY,IAAI,IAAI,IAAI,IAAI,CAAC,UAAU,KAAK,MAAM,CAAC;AAE/F,MAAM,UAAU,YAAY,CAAC,KAAyB,EAAE,IAAY;IAClE,KAAK,IAAI,CAAC,GAAG,KAAK,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC;QAC5C,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC1B,IAAI,CAAC,KAAK,SAAS;YAAE,OAAO,CAAC,CAAC;IAChC,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,+EAA+E;AAC/E,SAAS,UAAU,CAAC,OAAyB,EAAE,EAAwB;IACrE,MAAM,QAAQ,GAAG,YAAY,CAAC,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;IACxE,MAAM,GAAG,GAAG,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;IAC9B,IAAI,GAAG,EAAE,IAAI,KAAK,eAAe;QAAE,OAAO,SAAS,CAAC;IACpD,MAAM,WAAW,GAAG,GAAG,CAAC,MAAM,CAAC;IAC/B,IAAI,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;QAClF,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC;IACtB,IAAI,IAAI,CAAC,IAAI,KAAK,0BAA0B;QAAE,OAAO,GAAG,CAAC;IACzD,IAAI,IAAI,CAAC,IAAI,KAAK,iBAAiB,IAAI,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,SAAS,CAAC;IACxE,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;IAC1B,OAAO,QAAQ,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACjF,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,OAAO,CAAC,OAAyB,EAAE,IAAU,EAAE,IAAY;IACzE,IAAI,IAAI,CAAC,IAAI,KAAK,YAAY;QAAE,OAAO,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,IAAI,CAAC;IAC1E,IAAI,IAAI,CAAC,IAAI,KAAK,kBAAkB,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;QAC3F,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;IAC1B,OAAO,CACL,QAAQ,CAAC,IAAI,KAAK,YAAY;QAC9B,QAAQ,CAAC,IAAI,KAAK,IAAI;QACtB,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,MAA8B,CAAC,KAAK,GAAG,CACjE,CAAC;AACJ,CAAC","sourcesContent":["// Which identifiers are Gyral's `html` and `each` (@gyral/core/eslint). Like the template\n// compiler (compiler/scan.ts), a binding counts only when it is imported from a template\n// source: `import { html } from '@gyral/core'` (any local name) or `import * as g` used as\n// `g.html`. ESLint's scope analysis resolves the name, so shadowing is handled. Core's own code\n// and tests import from core's modules by relative path; those count too.\nimport { dirname, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { Rule, Scope } from 'eslint';\n\nexport type Node = Rule.Node;\nexport type NodeOf<T extends Node['type']> = Extract<Node, { type: T }>;\n\n/** The default template sources, as in the Vite preset's `sources` option. */\nexport const DEFAULT_SOURCES: readonly string[] = ['@gyral/core'];\n\n/** The options both rules take. */\nexport const OPTIONS_SCHEMA = [\n {\n type: 'object',\n properties: { sources: { type: 'array', items: { type: 'string' } } },\n additionalProperties: false,\n },\n];\n\n/** Core's modules that export `html` and `each` (this file is src/eslint/ or dist/eslint/). */\nconst CORE_MODULES = ['../index', '../view/index', '../view/template', '../view/render/values']\n .flatMap((name) => ['.ts', '.js'].map((ext) => new URL(`${name}${ext}`, import.meta.url)))\n .map((url) => fileURLToPath(url));\n\nexport function sourcesOf(context: Rule.RuleContext): readonly string[] {\n const options: unknown = context.options[0];\n const sources =\n typeof options === 'object' && options !== null && 'sources' in options\n ? options.sources\n : undefined;\n return Array.isArray(sources)\n ? sources.filter((s): s is string => typeof s === 'string')\n : DEFAULT_SOURCES;\n}\n\nfunction isSource(context: Rule.RuleContext, specifier: string): boolean {\n if (sourcesOf(context).includes(specifier)) return true;\n if (!specifier.startsWith('.')) return false;\n return CORE_MODULES.includes(resolve(dirname(context.filename), specifier));\n}\n\n/** typescript-eslint's `import type` marker (not in ESTree). */\nconst typeOnly = (node: object): boolean => 'importKind' in node && node.importKind === 'type';\n\nexport function findVariable(scope: Scope.Scope | null, name: string): Scope.Variable | undefined {\n for (let s = scope; s !== null; s = s.upper) {\n const v = s.set.get(name);\n if (v !== undefined) return v;\n }\n return undefined;\n}\n\n/** How `id` was imported from a template source: the export's name, or `*`. */\nfunction importedAs(context: Rule.RuleContext, id: NodeOf<'Identifier'>): string | undefined {\n const variable = findVariable(context.sourceCode.getScope(id), id.name);\n const def = variable?.defs[0];\n if (def?.type !== 'ImportBinding') return undefined;\n const declaration = def.parent;\n if (typeOnly(declaration) || !isSource(context, String(declaration.source.value))) {\n return undefined;\n }\n const spec = def.node;\n if (spec.type === 'ImportNamespaceSpecifier') return '*';\n if (spec.type !== 'ImportSpecifier' || typeOnly(spec)) return undefined;\n const { imported } = spec;\n return imported.type === 'Identifier' ? imported.name : String(imported.value);\n}\n\n/** Whether `node` (a tag or callee) is the template sources' `name` export. */\nexport function isGyral(context: Rule.RuleContext, node: Node, name: string): boolean {\n if (node.type === 'Identifier') return importedAs(context, node) === name;\n if (node.type !== 'MemberExpression' || node.computed || node.object.type !== 'Identifier') {\n return false;\n }\n const { property } = node;\n return (\n property.type === 'Identifier' &&\n property.name === name &&\n importedAs(context, node.object as NodeOf<'Identifier'>) === '*'\n );\n}\n"]}
@@ -0,0 +1,15 @@
1
+ import type { ESLint, Linter } from 'eslint';
2
+ import { rowPurityRule } from './row-purity-rule.js';
3
+ import { templateRule } from './template-rule.js';
4
+ export interface GyralPlugin extends ESLint.Plugin {
5
+ readonly rules: {
6
+ readonly template: typeof templateRule;
7
+ readonly 'each-row-purity': typeof rowPurityRule;
8
+ };
9
+ readonly configs: {
10
+ readonly recommended: Linter.Config;
11
+ };
12
+ }
13
+ declare const plugin: GyralPlugin;
14
+ export default plugin;
15
+ export { rowPurityRule, templateRule };
@@ -0,0 +1,15 @@
1
+ import { rowPurityRule } from './row-purity-rule.js';
2
+ import { templateRule } from './template-rule.js';
3
+ const rules = { template: templateRule, 'each-row-purity': rowPurityRule };
4
+ const configs = { recommended: {} };
5
+ const plugin = { meta: { name: '@gyral/core/eslint' }, rules, configs };
6
+ // The config names the plugin object itself, so it can be combined with configs that register
7
+ // `gyral` too (ESLint rejects two different objects under one plugin name).
8
+ configs.recommended = {
9
+ name: 'gyral/recommended',
10
+ plugins: { gyral: plugin },
11
+ rules: { 'gyral/template': 'error', 'gyral/each-row-purity': 'error' },
12
+ };
13
+ export default plugin;
14
+ export { rowPurityRule, templateRule };
15
+ //# sourceMappingURL=index.js.map