@gyral/core 0.3.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (381) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/NOTICE +19 -0
  3. package/README.md +30 -5
  4. package/dist/call.d.ts +32 -0
  5. package/dist/call.js +63 -0
  6. package/dist/call.js.map +1 -0
  7. package/dist/children.d.ts +25 -3
  8. package/dist/children.js +18 -1
  9. package/dist/children.js.map +1 -1
  10. package/dist/cli/gyral-types.d.ts +2 -0
  11. package/dist/cli/gyral-types.js +23 -0
  12. package/dist/cli/gyral-types.js.map +1 -0
  13. package/dist/command.d.ts +54 -12
  14. package/dist/command.js +25 -11
  15. package/dist/command.js.map +1 -1
  16. package/dist/compiler/ast.d.ts +2 -0
  17. package/dist/compiler/ast.js +5 -1
  18. package/dist/compiler/ast.js.map +1 -1
  19. package/dist/compiler/compile.d.ts +5 -2
  20. package/dist/compiler/compile.js +36 -17
  21. package/dist/compiler/compile.js.map +1 -1
  22. package/dist/compiler/component-entries.d.ts +7 -0
  23. package/dist/compiler/component-entries.js +42 -0
  24. package/dist/compiler/component-entries.js.map +1 -0
  25. package/dist/compiler/components.d.ts +4 -0
  26. package/dist/compiler/components.js +182 -0
  27. package/dist/compiler/components.js.map +1 -0
  28. package/dist/compiler/facts.d.ts +31 -0
  29. package/dist/compiler/facts.js +285 -0
  30. package/dist/compiler/facts.js.map +1 -0
  31. package/dist/compiler/features.d.ts +34 -0
  32. package/dist/compiler/features.js +158 -0
  33. package/dist/compiler/features.js.map +1 -0
  34. package/dist/compiler/hooks.d.ts +4 -0
  35. package/dist/compiler/hooks.js +144 -89
  36. package/dist/compiler/hooks.js.map +1 -1
  37. package/dist/compiler/loader-source.d.ts +14 -0
  38. package/dist/compiler/loader-source.js +86 -0
  39. package/dist/compiler/loader-source.js.map +1 -0
  40. package/dist/compiler/locate.d.ts +14 -0
  41. package/dist/compiler/locate.js +78 -0
  42. package/dist/compiler/locate.js.map +1 -0
  43. package/dist/compiler/parse5-check.d.ts +1 -1
  44. package/dist/compiler/parse5-check.js +8 -3
  45. package/dist/compiler/parse5-check.js.map +1 -1
  46. package/dist/compiler/prop-schemas.d.ts +4 -0
  47. package/dist/compiler/prop-schemas.js +108 -0
  48. package/dist/compiler/prop-schemas.js.map +1 -0
  49. package/dist/compiler/scan.d.ts +13 -3
  50. package/dist/compiler/scan.js +21 -13
  51. package/dist/compiler/scan.js.map +1 -1
  52. package/dist/compiler/scope.d.ts +8 -0
  53. package/dist/compiler/scope.js +116 -0
  54. package/dist/compiler/scope.js.map +1 -0
  55. package/dist/compiler/tag-map.d.ts +41 -0
  56. package/dist/compiler/tag-map.js +126 -0
  57. package/dist/compiler/tag-map.js.map +1 -0
  58. package/dist/components-ready.d.ts +7 -0
  59. package/dist/components-ready.js +19 -0
  60. package/dist/components-ready.js.map +1 -0
  61. package/dist/define.d.ts +13 -4
  62. package/dist/define.js +8 -12
  63. package/dist/define.js.map +1 -1
  64. package/dist/devtools-events.d.ts +8 -0
  65. package/dist/devtools-events.js.map +1 -1
  66. package/dist/devtools-off.d.ts +1 -0
  67. package/dist/devtools-off.js +1 -0
  68. package/dist/devtools-off.js.map +1 -1
  69. package/dist/devtools.d.ts +3 -0
  70. package/dist/devtools.js +14 -0
  71. package/dist/devtools.js.map +1 -1
  72. package/dist/drivers-scope.js.map +1 -1
  73. package/dist/element-internals.d.ts +1 -0
  74. package/dist/element-internals.js +11 -0
  75. package/dist/element-internals.js.map +1 -0
  76. package/dist/element-types.d.ts +6 -2
  77. package/dist/element-types.js.map +1 -1
  78. package/dist/element.js +80 -27
  79. package/dist/element.js.map +1 -1
  80. package/dist/error-view.d.ts +10 -0
  81. package/dist/error-view.js +30 -0
  82. package/dist/error-view.js.map +1 -0
  83. package/dist/errors.d.ts +21 -0
  84. package/dist/errors.js +47 -0
  85. package/dist/errors.js.map +1 -0
  86. package/dist/errors.json +289 -0
  87. package/dist/eslint/imports.d.ts +2 -0
  88. package/dist/eslint/imports.js +2 -2
  89. package/dist/eslint/imports.js.map +1 -1
  90. package/dist/eslint/index.d.ts +2 -1
  91. package/dist/eslint/index.js +11 -3
  92. package/dist/eslint/index.js.map +1 -1
  93. package/dist/eslint/template-rule.d.ts +1 -0
  94. package/dist/eslint/template-rule.js +15 -5
  95. package/dist/eslint/template-rule.js.map +1 -1
  96. package/dist/eslint/unused-intent-rule.d.ts +2 -0
  97. package/dist/eslint/unused-intent-rule.js +186 -0
  98. package/dist/eslint/unused-intent-rule.js.map +1 -0
  99. package/dist/features.d.ts +2 -2
  100. package/dist/features.js.map +1 -1
  101. package/dist/focus.d.ts +6 -0
  102. package/dist/focus.js +32 -2
  103. package/dist/focus.js.map +1 -1
  104. package/dist/form-associated.d.ts +46 -0
  105. package/dist/form-associated.js +77 -0
  106. package/dist/form-associated.js.map +1 -0
  107. package/dist/forms.d.ts +42 -30
  108. package/dist/forms.js +85 -41
  109. package/dist/forms.js.map +1 -1
  110. package/dist/frame-lane.d.ts +11 -0
  111. package/dist/frame-lane.js +28 -0
  112. package/dist/frame-lane.js.map +1 -0
  113. package/dist/head.d.ts +61 -0
  114. package/dist/head.js +85 -0
  115. package/dist/head.js.map +1 -0
  116. package/dist/host-model.d.ts +34 -5
  117. package/dist/host-model.js +146 -23
  118. package/dist/host-model.js.map +1 -1
  119. package/dist/hydration-client.js +2 -2
  120. package/dist/hydration-client.js.map +1 -1
  121. package/dist/hydration-loader.d.ts +13 -0
  122. package/dist/hydration-loader.js +58 -0
  123. package/dist/hydration-loader.js.map +1 -0
  124. package/dist/hydration-off.d.ts +8 -0
  125. package/dist/hydration-off.js +25 -0
  126. package/dist/hydration-off.js.map +1 -0
  127. package/dist/hydration.d.ts +0 -12
  128. package/dist/hydration.js +3 -52
  129. package/dist/hydration.js.map +1 -1
  130. package/dist/index.d.ts +20 -24
  131. package/dist/index.js +10 -19
  132. package/dist/index.js.map +1 -1
  133. package/dist/indexeddb-types.d.ts +97 -0
  134. package/dist/indexeddb-types.js +2 -0
  135. package/dist/indexeddb-types.js.map +1 -0
  136. package/dist/indexeddb.d.ts +5 -0
  137. package/dist/indexeddb.js +118 -0
  138. package/dist/indexeddb.js.map +1 -0
  139. package/dist/intent.d.ts +41 -19
  140. package/dist/intent.js +144 -106
  141. package/dist/intent.js.map +1 -1
  142. package/dist/internal/indexeddb-open.d.ts +8 -0
  143. package/dist/internal/indexeddb-open.js +96 -0
  144. package/dist/internal/indexeddb-open.js.map +1 -0
  145. package/dist/internal/indexeddb-transaction.d.ts +4 -0
  146. package/dist/internal/indexeddb-transaction.js +134 -0
  147. package/dist/internal/indexeddb-transaction.js.map +1 -0
  148. package/dist/internal/interpreter.d.ts +12 -4
  149. package/dist/internal/interpreter.js +36 -48
  150. package/dist/internal/interpreter.js.map +1 -1
  151. package/dist/internal/token.d.ts +1 -0
  152. package/dist/internal/token.js +7 -0
  153. package/dist/internal/token.js.map +1 -0
  154. package/dist/internal.d.ts +20 -0
  155. package/dist/internal.js +22 -0
  156. package/dist/internal.js.map +1 -0
  157. package/dist/invoker-fallback-used.d.ts +4 -0
  158. package/dist/invoker-fallback-used.js +10 -0
  159. package/dist/invoker-fallback-used.js.map +1 -0
  160. package/dist/invoker-fallback.d.ts +4 -0
  161. package/dist/invoker-fallback.js +15 -0
  162. package/dist/invoker-fallback.js.map +1 -0
  163. package/dist/light-dom.d.ts +1 -1
  164. package/dist/light-dom.js.map +1 -1
  165. package/dist/prop.d.ts +30 -7
  166. package/dist/prop.js +19 -0
  167. package/dist/prop.js.map +1 -1
  168. package/dist/props.d.ts +8 -3
  169. package/dist/props.js +22 -15
  170. package/dist/props.js.map +1 -1
  171. package/dist/retry.d.ts +15 -0
  172. package/dist/retry.js +48 -0
  173. package/dist/retry.js.map +1 -0
  174. package/dist/scheduler.d.ts +7 -3
  175. package/dist/scheduler.js +38 -56
  176. package/dist/scheduler.js.map +1 -1
  177. package/dist/script-json.d.ts +2 -0
  178. package/dist/script-json.js +13 -0
  179. package/dist/script-json.js.map +1 -0
  180. package/dist/server-component.d.ts +1 -1
  181. package/dist/server-component.js +45 -14
  182. package/dist/server-component.js.map +1 -1
  183. package/dist/server.d.ts +8 -2
  184. package/dist/server.js +11 -2
  185. package/dist/server.js.map +1 -1
  186. package/dist/settled.d.ts +4 -3
  187. package/dist/settled.js +48 -26
  188. package/dist/settled.js.map +1 -1
  189. package/dist/spec-features-used.d.ts +21 -0
  190. package/dist/spec-features-used.js +50 -0
  191. package/dist/spec-features-used.js.map +1 -0
  192. package/dist/spec-features.d.ts +28 -0
  193. package/dist/spec-features.js +42 -0
  194. package/dist/spec-features.js.map +1 -0
  195. package/dist/states.d.ts +3 -5
  196. package/dist/states.js +22 -8
  197. package/dist/states.js.map +1 -1
  198. package/dist/storage.d.ts +69 -0
  199. package/dist/storage.js +158 -0
  200. package/dist/storage.js.map +1 -0
  201. package/dist/store-binding.js +2 -2
  202. package/dist/store-binding.js.map +1 -1
  203. package/dist/store-scope.d.ts +2 -4
  204. package/dist/store-scope.js +6 -16
  205. package/dist/store-scope.js.map +1 -1
  206. package/dist/store.js +36 -8
  207. package/dist/store.js.map +1 -1
  208. package/dist/subscription.d.ts +35 -0
  209. package/dist/subscription.js +74 -0
  210. package/dist/subscription.js.map +1 -0
  211. package/dist/subscriptions.d.ts +26 -0
  212. package/dist/subscriptions.js +98 -0
  213. package/dist/subscriptions.js.map +1 -0
  214. package/dist/transitions.d.ts +4 -5
  215. package/dist/transitions.js +10 -4
  216. package/dist/transitions.js.map +1 -1
  217. package/dist/types.d.ts +124 -27
  218. package/dist/types.js.map +1 -1
  219. package/dist/use-dialogs.d.ts +2 -0
  220. package/dist/use-dialogs.js +9 -0
  221. package/dist/use-dialogs.js.map +1 -0
  222. package/dist/use-disposal.d.ts +2 -0
  223. package/dist/use-disposal.js +9 -0
  224. package/dist/use-disposal.js.map +1 -0
  225. package/dist/use-error-view.d.ts +2 -0
  226. package/dist/use-error-view.js +9 -0
  227. package/dist/use-error-view.js.map +1 -0
  228. package/dist/use-errored.d.ts +2 -0
  229. package/dist/use-errored.js +9 -0
  230. package/dist/use-errored.js.map +1 -0
  231. package/dist/use-form-associated.d.ts +2 -0
  232. package/dist/use-form-associated.js +7 -0
  233. package/dist/use-form-associated.js.map +1 -0
  234. package/dist/use-frame-lane.d.ts +2 -0
  235. package/dist/use-frame-lane.js +10 -0
  236. package/dist/use-frame-lane.js.map +1 -0
  237. package/dist/use-invokers.d.ts +2 -0
  238. package/dist/use-invokers.js +10 -0
  239. package/dist/use-invokers.js.map +1 -0
  240. package/dist/use-states.d.ts +2 -0
  241. package/dist/use-states.js +10 -0
  242. package/dist/use-states.js.map +1 -0
  243. package/dist/use-subscriptions.d.ts +2 -0
  244. package/dist/use-subscriptions.js +10 -0
  245. package/dist/use-subscriptions.js.map +1 -0
  246. package/dist/use-transitions.d.ts +2 -0
  247. package/dist/use-transitions.js +10 -0
  248. package/dist/use-transitions.js.map +1 -0
  249. package/dist/view/attributes.d.ts +5 -0
  250. package/dist/view/attributes.js +5 -0
  251. package/dist/view/attributes.js.map +1 -1
  252. package/dist/view/compiled.d.ts +1 -1
  253. package/dist/view/compiled.js +1 -1
  254. package/dist/view/compiled.js.map +1 -1
  255. package/dist/view/index.d.ts +9 -4
  256. package/dist/view/index.js +9 -3
  257. package/dist/view/index.js.map +1 -1
  258. package/dist/view/loc.d.ts +9 -0
  259. package/dist/view/loc.js +50 -0
  260. package/dist/view/loc.js.map +1 -0
  261. package/dist/view/message.d.ts +17 -0
  262. package/dist/view/message.js +40 -0
  263. package/dist/view/message.js.map +1 -0
  264. package/dist/view/messages.d.ts +43 -0
  265. package/dist/view/messages.js +84 -0
  266. package/dist/view/messages.js.map +1 -0
  267. package/dist/view/normalize/check.d.ts +5 -2
  268. package/dist/view/normalize/check.js +6 -3
  269. package/dist/view/normalize/check.js.map +1 -1
  270. package/dist/view/normalize/emit.d.ts +2 -0
  271. package/dist/view/normalize/emit.js +40 -11
  272. package/dist/view/normalize/emit.js.map +1 -1
  273. package/dist/view/normalize/errors.js +1 -1
  274. package/dist/view/normalize/errors.js.map +1 -1
  275. package/dist/view/normalize/id.d.ts +5 -2
  276. package/dist/view/normalize/id.js +9 -2
  277. package/dist/view/normalize/id.js.map +1 -1
  278. package/dist/view/normalize/normalize.d.ts +7 -4
  279. package/dist/view/normalize/normalize.js +15 -9
  280. package/dist/view/normalize/normalize.js.map +1 -1
  281. package/dist/view/normalize/rules.d.ts +9 -0
  282. package/dist/view/normalize/rules.js +35 -5
  283. package/dist/view/normalize/rules.js.map +1 -1
  284. package/dist/view/normalize/svg.d.ts +14 -0
  285. package/dist/view/normalize/svg.js +40 -0
  286. package/dist/view/normalize/svg.js.map +1 -0
  287. package/dist/view/normalize/tokens.d.ts +5 -1
  288. package/dist/view/normalize/tokens.js.map +1 -1
  289. package/dist/view/normalize/tree.d.ts +8 -2
  290. package/dist/view/normalize/tree.js +58 -13
  291. package/dist/view/normalize/tree.js.map +1 -1
  292. package/dist/view/normalize/types.d.ts +24 -4
  293. package/dist/view/normalize/types.js +4 -1
  294. package/dist/view/normalize/types.js.map +1 -1
  295. package/dist/view/normalize/whitespace.js +4 -3
  296. package/dist/view/normalize/whitespace.js.map +1 -1
  297. package/dist/view/prepare-stub.js +2 -2
  298. package/dist/view/prepare-stub.js.map +1 -1
  299. package/dist/view/prepare.d.ts +5 -2
  300. package/dist/view/prepare.js +9 -3
  301. package/dist/view/prepare.js.map +1 -1
  302. package/dist/view/registry.d.ts +15 -0
  303. package/dist/view/registry.js +10 -2
  304. package/dist/view/registry.js.map +1 -1
  305. package/dist/view/render/adopt-attr.js +7 -1
  306. package/dist/view/render/adopt-attr.js.map +1 -1
  307. package/dist/view/render/adopt.js +21 -4
  308. package/dist/view/render/adopt.js.map +1 -1
  309. package/dist/view/render/attr-parts.d.ts +12 -1
  310. package/dist/view/render/attr-parts.js +38 -5
  311. package/dist/view/render/attr-parts.js.map +1 -1
  312. package/dist/view/render/child-part.js +5 -2
  313. package/dist/view/render/child-part.js.map +1 -1
  314. package/dist/view/render/dispose.d.ts +3 -0
  315. package/dist/view/render/dispose.js +76 -0
  316. package/dist/view/render/dispose.js.map +1 -0
  317. package/dist/view/render/hook-part.d.ts +3 -1
  318. package/dist/view/render/hook-part.js +21 -5
  319. package/dist/view/render/hook-part.js.map +1 -1
  320. package/dist/view/render/hook-run.d.ts +2 -0
  321. package/dist/view/render/hook-run.js +72 -0
  322. package/dist/view/render/hook-run.js.map +1 -0
  323. package/dist/view/render/hooks.d.ts +73 -5
  324. package/dist/view/render/hooks.js +79 -17
  325. package/dist/view/render/hooks.js.map +1 -1
  326. package/dist/view/render/hydrate.js +2 -2
  327. package/dist/view/render/hydrate.js.map +1 -1
  328. package/dist/view/render/keyed.d.ts +6 -0
  329. package/dist/view/render/keyed.js +15 -0
  330. package/dist/view/render/keyed.js.map +1 -0
  331. package/dist/view/render/mismatch.js +5 -3
  332. package/dist/view/render/mismatch.js.map +1 -1
  333. package/dist/view/render/modal.d.ts +3 -0
  334. package/dist/view/render/modal.js +39 -0
  335. package/dist/view/render/modal.js.map +1 -0
  336. package/dist/view/render/raw.d.ts +4 -1
  337. package/dist/view/render/raw.js +6 -2
  338. package/dist/view/render/raw.js.map +1 -1
  339. package/dist/view/render/render.d.ts +4 -1
  340. package/dist/view/render/render.js +17 -12
  341. package/dist/view/render/render.js.map +1 -1
  342. package/dist/view/render/toggles.d.ts +6 -0
  343. package/dist/view/render/toggles.js +6 -0
  344. package/dist/view/render/toggles.js.map +1 -0
  345. package/dist/view/render/warn.d.ts +14 -0
  346. package/dist/view/render/warn.js +45 -0
  347. package/dist/view/render/warn.js.map +1 -1
  348. package/dist/view/server/component.d.ts +6 -3
  349. package/dist/view/server/component.js +29 -7
  350. package/dist/view/server/component.js.map +1 -1
  351. package/dist/view/server/index.d.ts +20 -0
  352. package/dist/view/server/index.js +12 -4
  353. package/dist/view/server/index.js.map +1 -1
  354. package/dist/view/server/tags.d.ts +13 -2
  355. package/dist/view/server/tags.js +13 -2
  356. package/dist/view/server/tags.js.map +1 -1
  357. package/dist/view/server/values.d.ts +2 -0
  358. package/dist/view/server/values.js +8 -0
  359. package/dist/view/server/values.js.map +1 -1
  360. package/dist/view/server/writer.d.ts +9 -4
  361. package/dist/view/server/writer.js +33 -18
  362. package/dist/view/server/writer.js.map +1 -1
  363. package/dist/view/template-element.d.ts +7 -0
  364. package/dist/view/template-element.js +25 -5
  365. package/dist/view/template-element.js.map +1 -1
  366. package/dist/view/template.d.ts +10 -2
  367. package/dist/view/template.js +62 -8
  368. package/dist/view/template.js.map +1 -1
  369. package/dist/view/trusted-html.d.ts +6 -0
  370. package/dist/view/trusted-html.js +34 -0
  371. package/dist/view/trusted-html.js.map +1 -0
  372. package/dist/vite.d.ts +38 -31
  373. package/dist/vite.js +198 -31
  374. package/dist/vite.js.map +1 -1
  375. package/package.json +34 -3
  376. package/dist/hooks/labelled-by.d.ts +0 -13
  377. package/dist/hooks/labelled-by.js +0 -51
  378. package/dist/hooks/labelled-by.js.map +0 -1
  379. package/dist/random.d.ts +0 -13
  380. package/dist/random.js +0 -19
  381. package/dist/random.js.map +0 -1
@@ -0,0 +1,289 @@
1
+ [
2
+ {
3
+ "code": "G0001",
4
+ "group": "Components",
5
+ "message": "<{tag}> is a browser element (render it on the server with @gyral/ssr).",
6
+ "arguments": ["tag"],
7
+ "url": "https://gyral.dev/errors/#G0001"
8
+ },
9
+ {
10
+ "code": "G0010",
11
+ "group": "Components",
12
+ "message": "<{tag}> has no update for message \"{message}\".",
13
+ "arguments": ["tag", "message"],
14
+ "url": "https://gyral.dev/errors/#G0010"
15
+ },
16
+ {
17
+ "code": "G0011",
18
+ "group": "Components",
19
+ "message": "<{tag}> has no intent parser for data-intent=\"{intent}\".",
20
+ "arguments": ["tag", "intent"],
21
+ "url": "https://gyral.dev/errors/#G0011"
22
+ },
23
+ {
24
+ "code": "G0012",
25
+ "group": "Components",
26
+ "message": "<{tag}> intent parser for \"{intent}\" failed",
27
+ "arguments": ["tag", "intent"],
28
+ "url": "https://gyral.dev/errors/#G0012"
29
+ },
30
+ {
31
+ "code": "G0013",
32
+ "group": "Components",
33
+ "message": "<{tag}> focus(\"{selector}\") matched no focusable element.",
34
+ "arguments": ["tag", "selector"],
35
+ "url": "https://gyral.dev/errors/#G0013"
36
+ },
37
+ {
38
+ "code": "G0020",
39
+ "group": "Props",
40
+ "message": "<{tag}> prop \"{prop}\" has an asynchronous schema; it must be synchronous.",
41
+ "arguments": ["tag", "prop"],
42
+ "url": "https://gyral.dev/errors/#G0020"
43
+ },
44
+ {
45
+ "code": "G0021",
46
+ "group": "Props",
47
+ "message": "<{tag}> prop \"{prop}\" got an invalid value from {source}, so it is treated as missing: {issues}",
48
+ "arguments": ["tag", "prop", "source", "issues"],
49
+ "url": "https://gyral.dev/errors/#G0021"
50
+ },
51
+ {
52
+ "code": "G0022",
53
+ "group": "Props",
54
+ "message": "<{tag}> is missing required prop(s): {props}.",
55
+ "arguments": ["tag", "props"],
56
+ "url": "https://gyral.dev/errors/#G0022"
57
+ },
58
+ {
59
+ "code": "G0023",
60
+ "group": "Props",
61
+ "message": "<{tag}> declares prop(s) that shadow built-in element properties: {props}. Setting them changes platform behaviour (a prop named \"hidden\" hides the element). Rename them (view/05-element.md).",
62
+ "arguments": ["tag", "props"],
63
+ "url": "https://gyral.dev/errors/#G0023"
64
+ },
65
+ {
66
+ "code": "G0030",
67
+ "group": "Scheduling",
68
+ "message": "gyral: a deferred callback failed",
69
+ "arguments": [],
70
+ "url": "https://gyral.dev/errors/#G0030"
71
+ },
72
+ {
73
+ "code": "G0031",
74
+ "group": "Scheduling",
75
+ "message": "<{tag}> view failed; it shows its error view, or its previous DOM stays.",
76
+ "arguments": ["tag"],
77
+ "url": "https://gyral.dev/errors/#G0031"
78
+ },
79
+ {
80
+ "code": "G0032",
81
+ "group": "Scheduling",
82
+ "message": "gyral: post-render work failed",
83
+ "arguments": [],
84
+ "url": "https://gyral.dev/errors/#G0032"
85
+ },
86
+ {
87
+ "code": "G0033",
88
+ "group": "Scheduling",
89
+ "message": "gyral: rendering did not settle in one flush (a cycle between {tags}). Components are probably feeding each other props or messages; break the cycle with a condition in update (docs/design-docs/view/04-scheduler.md \"Loop guard\").",
90
+ "arguments": ["tags"],
91
+ "url": "https://gyral.dev/errors/#G0033"
92
+ },
93
+ {
94
+ "code": "G0034",
95
+ "group": "Scheduling",
96
+ "message": "settled(): the page did not settle after {rounds} flushes or busy turns. A stream is emitting without pause, or components (or drivers) are feeding each other messages in a cycle.",
97
+ "arguments": ["rounds"],
98
+ "url": "https://gyral.dev/errors/#G0034"
99
+ },
100
+ {
101
+ "code": "G0040",
102
+ "group": "Commands",
103
+ "message": "{owner}: the onSuccess or onFailure mapper for driver \"{driver}\" threw; no message was sent.",
104
+ "arguments": ["owner", "driver"],
105
+ "url": "https://gyral.dev/errors/#G0040"
106
+ },
107
+ {
108
+ "code": "G0041",
109
+ "group": "Commands",
110
+ "message": "{owner}: driver \"{driver}\" failed and the command has no onFailure.",
111
+ "arguments": ["owner", "driver"],
112
+ "url": "https://gyral.dev/errors/#G0041"
113
+ },
114
+ {
115
+ "code": "G0042",
116
+ "group": "Commands",
117
+ "message": "gyral: subscription \"{name}\" failed to unsubscribe",
118
+ "arguments": ["name"],
119
+ "url": "https://gyral.dev/errors/#G0042"
120
+ },
121
+ {
122
+ "code": "G0043",
123
+ "group": "Commands",
124
+ "message": "{owner}: no driver provides \"{driver}\". It is a driver token: provide an implementation by name with provideDrivers(root, { {driver}: … }) or el.drivers (ADR 0006 \"Driver tokens\").",
125
+ "arguments": ["owner", "driver"],
126
+ "url": "https://gyral.dev/errors/#G0043"
127
+ },
128
+ {
129
+ "code": "G0050",
130
+ "group": "Stores",
131
+ "message": "<{tag}> uses store \"{store}\" without declaring it. Add it to the spec: stores: [{store}] (ADR 0013), so the component subscribes to its changes.",
132
+ "arguments": ["tag", "store"],
133
+ "url": "https://gyral.dev/errors/#G0050"
134
+ },
135
+ {
136
+ "code": "G0051",
137
+ "group": "Stores",
138
+ "message": "store \"{store}\": the server's seed failed its schema, so it starts from init. Issues: {issues}",
139
+ "arguments": ["store", "issues"],
140
+ "url": "https://gyral.dev/errors/#G0051"
141
+ },
142
+ {
143
+ "code": "G0052",
144
+ "group": "Stores",
145
+ "message": "unreadable {attribute} seed on {where}",
146
+ "arguments": ["attribute", "where"],
147
+ "url": "https://gyral.dev/errors/#G0052"
148
+ },
149
+ {
150
+ "code": "G0053",
151
+ "group": "Stores",
152
+ "message": "<{tag}> reads store \"{store}\" during a server render without a store scope. Pass the request's store instances to renderPage({ stores }) or renderToString(value, { stores }).",
153
+ "arguments": ["tag", "store"],
154
+ "url": "https://gyral.dev/errors/#G0053"
155
+ },
156
+ {
157
+ "code": "G0054",
158
+ "group": "Stores",
159
+ "message": "store \"{store}\" sends to \"{target}\" but is not held by a store scope (a registry, <gyral-stores> or the page default), so the message is dropped.",
160
+ "arguments": ["store", "target"],
161
+ "url": "https://gyral.dev/errors/#G0054"
162
+ },
163
+ {
164
+ "code": "G0055",
165
+ "group": "Stores",
166
+ "message": "store \"{store}\" has no update for message \"{message}\".",
167
+ "arguments": ["store", "message"],
168
+ "url": "https://gyral.dev/errors/#G0055"
169
+ },
170
+ {
171
+ "code": "G0060",
172
+ "group": "Hydration",
173
+ "message": "<{tag}> has an unreadable {attribute}",
174
+ "arguments": ["tag", "attribute"],
175
+ "url": "https://gyral.dev/errors/#G0060"
176
+ },
177
+ {
178
+ "code": "G0061",
179
+ "group": "Hydration",
180
+ "message": "gyral: hydration code failed to load; rendering fresh",
181
+ "arguments": [],
182
+ "url": "https://gyral.dev/errors/#G0061"
183
+ },
184
+ {
185
+ "code": "G0062",
186
+ "group": "Hydration",
187
+ "message": "gyral: hydration mismatch in {host} at {path}: expected {expected}, found {found}. The server's HTML differs from the first client render: a view that isn't deterministic (Date.now(), locale), a third party that changed the DOM before scripts ran, or a stale cached page (docs/design-docs/view/07-hydration.md \"Mismatches\").",
188
+ "arguments": ["host", "path", "expected", "found"],
189
+ "url": "https://gyral.dev/errors/#G0062"
190
+ },
191
+ {
192
+ "code": "G0063",
193
+ "group": "Hydration",
194
+ "message": "<{tag}> was rendered fresh after a hydration mismatch:",
195
+ "arguments": ["tag"],
196
+ "url": "https://gyral.dev/errors/#G0063"
197
+ },
198
+ {
199
+ "code": "G0070",
200
+ "group": "Templates",
201
+ "message": "gyral: an html template was not compiled: `{start}`. Under the gyral-compiled condition every html`…` must be compiled by the Gyral Vite preset (view/01-templates.md).",
202
+ "arguments": ["start"],
203
+ "url": "https://gyral.dev/errors/#G0070"
204
+ },
205
+ {
206
+ "code": "G0071",
207
+ "group": "Templates",
208
+ "message": "gyral: template rule 11: a page shell rendered in the browser.",
209
+ "arguments": [],
210
+ "url": "https://gyral.dev/errors/#G0071"
211
+ },
212
+ {
213
+ "code": "G0072",
214
+ "group": "Templates",
215
+ "message": "gyral: this page's Trusted Types policy list does not allow the policy \"gyral\", so templates are parsed from plain strings, which works only while Trusted Types are not enforced. Add `trusted-types gyral` to the Content-Security-Policy.",
216
+ "arguments": [],
217
+ "url": "https://gyral.dev/errors/#G0072"
218
+ },
219
+ {
220
+ "code": "G0073",
221
+ "group": "Errors (ADR 0024)",
222
+ "message": "<{tag}> update for \"{message}\" failed; the state is unchanged.",
223
+ "arguments": ["tag", "message"],
224
+ "url": "https://gyral.dev/errors/#G0073"
225
+ },
226
+ {
227
+ "code": "G0074",
228
+ "group": "Errors (ADR 0024)",
229
+ "message": "<{tag}> init failed; it shows its error view, or stays empty.",
230
+ "arguments": ["tag"],
231
+ "url": "https://gyral.dev/errors/#G0074"
232
+ },
233
+ {
234
+ "code": "G0075",
235
+ "group": "Errors (ADR 0024)",
236
+ "message": "<{tag}> element hook failed; the other hooks still ran.",
237
+ "arguments": ["tag"],
238
+ "url": "https://gyral.dev/errors/#G0075"
239
+ },
240
+ {
241
+ "code": "G0076",
242
+ "group": "Errors (ADR 0024)",
243
+ "message": "store \"{store}\": update for \"{message}\" failed; the state is unchanged.",
244
+ "arguments": ["store", "message"],
245
+ "url": "https://gyral.dev/errors/#G0076"
246
+ },
247
+ {
248
+ "code": "G0077",
249
+ "group": "Errors (ADR 0024)",
250
+ "message": "store \"{store}\": a subscriber failed; the other subscribers were still notified.",
251
+ "arguments": ["store"],
252
+ "url": "https://gyral.dev/errors/#G0077"
253
+ },
254
+ {
255
+ "code": "G0078",
256
+ "group": "Errors (ADR 0024)",
257
+ "message": "<{tag}> failed to render on the server; it renders its error view (or nothing) and starts fresh in the browser.",
258
+ "arguments": ["tag"],
259
+ "url": "https://gyral.dev/errors/#G0078"
260
+ },
261
+ {
262
+ "code": "G0079",
263
+ "group": "Subscriptions (ADR 0025)",
264
+ "message": "<{tag}> subscriptions returned two commands for lane \"{lane}\"; only the first runs. Give each its own `key`.",
265
+ "arguments": ["tag", "lane"],
266
+ "url": "https://gyral.dev/errors/#G0079"
267
+ },
268
+ {
269
+ "code": "G0080",
270
+ "group": "Subscriptions (ADR 0025)",
271
+ "message": "<{tag}> subscriptions kept restarting: a subscription's input data changes with every message it sends (for example a timestamp or a counter in the input). Keep inputs to what should restart it; functions are ignored, so to restart on a new selector, change the key.",
272
+ "arguments": ["tag"],
273
+ "url": "https://gyral.dev/errors/#G0080"
274
+ },
275
+ {
276
+ "code": "G0085",
277
+ "group": "Element calls (gyral-1zd.27)",
278
+ "message": "<{tag}> call(\"{selector}\", \"{method}\") failed",
279
+ "arguments": ["tag", "selector", "method"],
280
+ "url": "https://gyral.dev/errors/#G0085"
281
+ },
282
+ {
283
+ "code": "G0086",
284
+ "group": "Element calls (gyral-1zd.27)",
285
+ "message": "call(\"{selector}\", \"{method}\"): arguments must be plain data.",
286
+ "arguments": ["selector", "method"],
287
+ "url": "https://gyral.dev/errors/#G0086"
288
+ }
289
+ ]
@@ -20,5 +20,7 @@ export declare const OPTIONS_SCHEMA: {
20
20
  }[];
21
21
  export declare function sourcesOf(context: Rule.RuleContext): readonly string[];
22
22
  export declare function findVariable(scope: Scope.Scope | null, name: string): Scope.Variable | undefined;
23
+ /** How `id` was imported from a template source: the export's name, or `*`. */
24
+ export declare function importedAs(context: Rule.RuleContext, id: NodeOf<'Identifier'>): string | undefined;
23
25
  /** Whether `node` (a tag or callee) is the template sources' `name` export. */
24
26
  export declare function isGyral(context: Rule.RuleContext, node: Node, name: string): boolean;
@@ -1,4 +1,4 @@
1
- // Which identifiers are Gyral's `html` and `each` (@gyral/core/eslint). Like the template
1
+ // Which identifiers are Gyral's `html`, `svg` and `each` (@gyral/core/eslint). Like the template
2
2
  // compiler (compiler/scan.ts), a binding counts only when it is imported from a template
3
3
  // source: `import { html } from '@gyral/core'` (any local name) or `import * as g` used as
4
4
  // `g.html`. ESLint's scope analysis resolves the name, so shadowing is handled. Core's own code
@@ -46,7 +46,7 @@ export function findVariable(scope, name) {
46
46
  return undefined;
47
47
  }
48
48
  /** How `id` was imported from a template source: the export's name, or `*`. */
49
- function importedAs(context, id) {
49
+ export function importedAs(context, id) {
50
50
  const variable = findVariable(context.sourceCode.getScope(id), id.name);
51
51
  const def = variable?.defs[0];
52
52
  if (def?.type !== 'ImportBinding')
@@ -1 +1 @@
1
- {"version":3,"file":"imports.js","sourceRoot":"","sources":["../../src/eslint/imports.ts"],"names":[],"mappings":"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","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"]}
1
+ {"version":3,"file":"imports.js","sourceRoot":"","sources":["../../src/eslint/imports.ts"],"names":[],"mappings":"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","sourcesContent":["// Which identifiers are Gyral's `html`, `svg` 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 `*`. */\nexport function importedAs(\n context: Rule.RuleContext,\n id: NodeOf<'Identifier'>,\n): 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"]}
@@ -1,10 +1,12 @@
1
1
  import type { ESLint, Linter } from 'eslint';
2
2
  import { rowPurityRule } from './row-purity-rule.js';
3
3
  import { templateRule } from './template-rule.js';
4
+ import { unusedIntentRule } from './unused-intent-rule.js';
4
5
  export interface GyralPlugin extends ESLint.Plugin {
5
6
  readonly rules: {
6
7
  readonly template: typeof templateRule;
7
8
  readonly 'each-row-purity': typeof rowPurityRule;
9
+ readonly 'unused-intent': typeof unusedIntentRule;
8
10
  };
9
11
  readonly configs: {
10
12
  readonly recommended: Linter.Config;
@@ -12,4 +14,3 @@ export interface GyralPlugin extends ESLint.Plugin {
12
14
  }
13
15
  declare const plugin: GyralPlugin;
14
16
  export default plugin;
15
- export { rowPurityRule, templateRule };
@@ -1,6 +1,11 @@
1
1
  import { rowPurityRule } from './row-purity-rule.js';
2
2
  import { templateRule } from './template-rule.js';
3
- const rules = { template: templateRule, 'each-row-purity': rowPurityRule };
3
+ import { unusedIntentRule } from './unused-intent-rule.js';
4
+ const rules = {
5
+ template: templateRule,
6
+ 'each-row-purity': rowPurityRule,
7
+ 'unused-intent': unusedIntentRule,
8
+ };
4
9
  const configs = { recommended: {} };
5
10
  const plugin = { meta: { name: '@gyral/core/eslint' }, rules, configs };
6
11
  // The config names the plugin object itself, so it can be combined with configs that register
@@ -8,8 +13,11 @@ const plugin = { meta: { name: '@gyral/core/eslint' }, rules, configs };
8
13
  configs.recommended = {
9
14
  name: 'gyral/recommended',
10
15
  plugins: { gyral: plugin },
11
- rules: { 'gyral/template': 'error', 'gyral/each-row-purity': 'error' },
16
+ rules: {
17
+ 'gyral/template': 'error',
18
+ 'gyral/each-row-purity': 'error',
19
+ 'gyral/unused-intent': 'warn',
20
+ },
12
21
  };
13
22
  export default plugin;
14
- export { rowPurityRule, templateRule };
15
23
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/eslint/index.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAUlD,MAAM,KAAK,GAAG,EAAE,QAAQ,EAAE,YAAY,EAAE,iBAAiB,EAAE,aAAa,EAAE,CAAC;AAC3E,MAAM,OAAO,GAAmC,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC;AAEpE,MAAM,MAAM,GAAgB,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,oBAAoB,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AAErF,8FAA8F;AAC9F,4EAA4E;AAC5E,OAAO,CAAC,WAAW,GAAG;IACpB,IAAI,EAAE,mBAAmB;IACzB,OAAO,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE;IAC1B,KAAK,EAAE,EAAE,gBAAgB,EAAE,OAAO,EAAE,uBAAuB,EAAE,OAAO,EAAE;CACvE,CAAC;AAEF,eAAe,MAAM,CAAC;AACtB,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,CAAC","sourcesContent":["// @gyral/core/eslint: the template rules (view/09-template-rules.md) in the editor, as an\n// ESLint flat-config plugin. ESLint is an optional peer dependency; nothing here reaches a\n// browser or server bundle.\n//\n// import gyral from '@gyral/core/eslint';\n// export default [gyral.configs.recommended];\nimport type { ESLint, Linter } from 'eslint';\nimport { rowPurityRule } from './row-purity-rule.js';\nimport { templateRule } from './template-rule.js';\n\nexport interface GyralPlugin extends ESLint.Plugin {\n readonly rules: {\n readonly template: typeof templateRule;\n readonly 'each-row-purity': typeof rowPurityRule;\n };\n readonly configs: { readonly recommended: Linter.Config };\n}\n\nconst rules = { template: templateRule, 'each-row-purity': rowPurityRule };\nconst configs: { recommended: Linter.Config } = { recommended: {} };\n\nconst plugin: GyralPlugin = { meta: { name: '@gyral/core/eslint' }, rules, configs };\n\n// The config names the plugin object itself, so it can be combined with configs that register\n// `gyral` too (ESLint rejects two different objects under one plugin name).\nconfigs.recommended = {\n name: 'gyral/recommended',\n plugins: { gyral: plugin },\n rules: { 'gyral/template': 'error', 'gyral/each-row-purity': 'error' },\n};\n\nexport default plugin;\nexport { rowPurityRule, templateRule };\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/eslint/index.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAW3D,MAAM,KAAK,GAAG;IACZ,QAAQ,EAAE,YAAY;IACtB,iBAAiB,EAAE,aAAa;IAChC,eAAe,EAAE,gBAAgB;CAClC,CAAC;AACF,MAAM,OAAO,GAAmC,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC;AAEpE,MAAM,MAAM,GAAgB,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,oBAAoB,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AAErF,8FAA8F;AAC9F,4EAA4E;AAC5E,OAAO,CAAC,WAAW,GAAG;IACpB,IAAI,EAAE,mBAAmB;IACzB,OAAO,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE;IAC1B,KAAK,EAAE;QACL,gBAAgB,EAAE,OAAO;QACzB,uBAAuB,EAAE,OAAO;QAChC,qBAAqB,EAAE,MAAM;KAC9B;CACF,CAAC;AAEF,eAAe,MAAM,CAAC","sourcesContent":["// @gyral/core/eslint: the template rules (view/09-template-rules.md) in the editor, as an\n// ESLint flat-config plugin. ESLint is an optional peer dependency; nothing here reaches a\n// browser or server bundle.\n//\n// import gyral from '@gyral/core/eslint';\n// export default [gyral.configs.recommended];\nimport type { ESLint, Linter } from 'eslint';\nimport { rowPurityRule } from './row-purity-rule.js';\nimport { templateRule } from './template-rule.js';\nimport { unusedIntentRule } from './unused-intent-rule.js';\n\nexport interface GyralPlugin extends ESLint.Plugin {\n readonly rules: {\n readonly template: typeof templateRule;\n readonly 'each-row-purity': typeof rowPurityRule;\n readonly 'unused-intent': typeof unusedIntentRule;\n };\n readonly configs: { readonly recommended: Linter.Config };\n}\n\nconst rules = {\n template: templateRule,\n 'each-row-purity': rowPurityRule,\n 'unused-intent': unusedIntentRule,\n};\nconst configs: { recommended: Linter.Config } = { recommended: {} };\n\nconst plugin: GyralPlugin = { meta: { name: '@gyral/core/eslint' }, rules, configs };\n\n// The config names the plugin object itself, so it can be combined with configs that register\n// `gyral` too (ESLint rejects two different objects under one plugin name).\nconfigs.recommended = {\n name: 'gyral/recommended',\n plugins: { gyral: plugin },\n rules: {\n 'gyral/template': 'error',\n 'gyral/each-row-purity': 'error',\n 'gyral/unused-intent': 'warn',\n },\n};\n\nexport default plugin;\n"]}
@@ -2,4 +2,5 @@ import type { Rule } from 'eslint';
2
2
  import { TemplateError } from '../view/index.js';
3
3
  /** The message ESLint shows: the TemplateError's first line (rule, fix and spec section). */
4
4
  export declare const messageOf: (error: TemplateError) => string;
5
+ export declare const CLOSURE: string;
5
6
  export declare const templateRule: Rule.RuleModule;
@@ -3,7 +3,10 @@ import { isGyral, OPTIONS_SCHEMA } from './imports.js';
3
3
  import { cookedMap, errorSpan } from './locate.js';
4
4
  /** The message ESLint shows: the TemplateError's first line (rule, fix and spec section). */
5
5
  export const messageOf = (error) => error.message.split('\n')[0] ?? '';
6
- const INVALID_ESCAPE = 'This html template has an invalid escape sequence, so it has no string value at runtime. ' +
6
+ export const CLOSURE = 'Views attach no closures: a function in a template hole is an event handler or a callback. ' +
7
+ 'Name an intent with data-intent=${i.Name} for events, pass data to components (they answer ' +
8
+ 'with outputs), and put behaviour on an element in a hook (view/02-bindings.md "Properties").';
9
+ const INVALID_ESCAPE = 'This template has an invalid escape sequence, so it has no string value at runtime. ' +
7
10
  'Fix the escape (write \\\\ for a backslash).';
8
11
  function quasisOf(context, node) {
9
12
  const text = context.sourceCode.text;
@@ -28,25 +31,32 @@ export const templateRule = {
28
31
  meta: {
29
32
  type: 'problem',
30
33
  docs: {
31
- description: 'Template rules for html`…` (view/09-template-rules.md): the same checks and messages ' +
34
+ description: 'Template rules for html`…` and svg`…` (view/09-template-rules.md): the same checks and messages ' +
32
35
  'as the template compiler and the development runtime.',
33
36
  recommended: true,
34
37
  url: 'https://github.com/gyraljs/gyral/blob/main/docs/design-docs/view/09-template-rules.md',
35
38
  },
36
39
  schema: OPTIONS_SCHEMA,
37
- messages: { rule: '{{message}}', escape: INVALID_ESCAPE },
40
+ messages: { rule: '{{message}}', escape: INVALID_ESCAPE, closure: CLOSURE },
38
41
  },
39
42
  create(context) {
40
43
  return {
41
44
  TaggedTemplateExpression(node) {
42
- if (!isGyral(context, node.tag, 'html'))
45
+ const tag = node.tag;
46
+ const svg = isGyral(context, tag, 'svg');
47
+ if (!svg && !isGyral(context, tag, 'html'))
43
48
  return;
49
+ for (const value of node.quasi.expressions) {
50
+ if (value.type === 'ArrowFunctionExpression' || value.type === 'FunctionExpression') {
51
+ context.report({ node: value, messageId: 'closure' });
52
+ }
53
+ }
44
54
  const parts = quasisOf(context, node.quasi);
45
55
  if (parts === undefined) {
46
56
  context.report({ node: node.quasi, messageId: 'escape' });
47
57
  return;
48
58
  }
49
- const issue = checkTemplate(parts.cooked);
59
+ const issue = checkTemplate(parts.cooked, svg);
50
60
  if (issue === undefined)
51
61
  return;
52
62
  const span = errorSpan(parts.quasis, parts.cooked, issue.strings, issue.at, issue.from);
@@ -1 +1 @@
1
- {"version":3,"file":"template-rule.js","sourceRoot":"","sources":["../../src/eslint/template-rule.ts"],"names":[],"mappings":"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","sourcesContent":["// gyral/template: the template rules of view/09-template-rules.md, in the editor. Every html`…`\n// whose tag is imported from a template source goes through the normalizer's own check\n// (view/normalize/check.ts), the one rule set the compiler and the development runtime use, so\n// the message is the same TemplateError message (minus the `near:`/`at` context, which the\n// editor's location replaces). Not checked here: rule 7's parse5 comparison (compiler only) and\n// the browser's own parse (runtime only); rule 11 (a page shell is fine on the server).\nimport type { Rule } from 'eslint';\nimport { checkTemplate, TemplateError } from '../view/index.js';\nimport { isGyral, OPTIONS_SCHEMA } from './imports.js';\nimport { cookedMap, errorSpan, type Quasi } from './locate.js';\n\n/** The message ESLint shows: the TemplateError's first line (rule, fix and spec section). */\nexport const messageOf = (error: TemplateError): string => error.message.split('\\n')[0] ?? '';\n\nconst INVALID_ESCAPE =\n 'This html template has an invalid escape sequence, so it has no string value at runtime. ' +\n 'Fix the escape (write \\\\\\\\ for a backslash).';\n\n/** What this rule reads of a TemplateElement (ESTree's, or typescript-eslint's). */\ninterface QuasiNode {\n readonly value: { readonly cooked?: string | null | undefined };\n readonly range?: [number, number] | undefined;\n readonly tail: boolean;\n}\n\nfunction quasisOf(\n context: Rule.RuleContext,\n node: { readonly quasis: readonly QuasiNode[] },\n): { quasis: Quasi[]; cooked: string[] } | undefined {\n const text = context.sourceCode.text;\n const quasis: Quasi[] = [];\n const cooked: string[] = [];\n for (const q of node.quasis) {\n const value = q.value.cooked;\n if (typeof value !== 'string') return undefined;\n const [from, to] = q.range ?? [0, 0];\n // Parsers include the delimiters (` or } before, ` or ${ after) in the element's range.\n const start = text.charAt(from) === '`' || text.charAt(from) === '}' ? from + 1 : from;\n const end = q.tail ? to - 1 : to - 2;\n // Undecodable (it shouldn't be): point at the quasi's start.\n const map = cookedMap(text.slice(start, end), value) ?? Array<number>(value.length + 1).fill(0);\n quasis.push({ start, end, map });\n cooked.push(value);\n }\n return { quasis, cooked };\n}\n\nexport const templateRule: Rule.RuleModule = {\n meta: {\n type: 'problem',\n docs: {\n description:\n 'Template rules for html`…` (view/09-template-rules.md): the same checks and messages ' +\n 'as the template compiler and the development runtime.',\n recommended: true,\n url: 'https://github.com/gyraljs/gyral/blob/main/docs/design-docs/view/09-template-rules.md',\n },\n schema: OPTIONS_SCHEMA,\n messages: { rule: '{{message}}', escape: INVALID_ESCAPE },\n },\n create(context) {\n return {\n TaggedTemplateExpression(node) {\n if (!isGyral(context, node.tag as Rule.Node, 'html')) return;\n const parts = quasisOf(context, node.quasi);\n if (parts === undefined) {\n context.report({ node: node.quasi, messageId: 'escape' });\n return;\n }\n const issue = checkTemplate(parts.cooked);\n if (issue === undefined) return;\n const span = errorSpan(parts.quasis, parts.cooked, issue.strings, issue.at, issue.from);\n const { sourceCode } = context;\n context.report({\n loc: {\n start: sourceCode.getLocFromIndex(span.start),\n end: sourceCode.getLocFromIndex(Math.max(span.end, span.start)),\n },\n messageId: 'rule',\n data: { message: messageOf(issue.error) },\n });\n },\n };\n },\n};\n"]}
1
+ {"version":3,"file":"template-rule.js","sourceRoot":"","sources":["../../src/eslint/template-rule.ts"],"names":[],"mappings":"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","sourcesContent":["// gyral/template: the template rules of view/09-template-rules.md, in the editor. Every html`…`\n// (and svg`…`) whose tag is imported from a template source goes through the normalizer's own check\n// (view/normalize/check.ts), the one rule set the compiler and the development runtime use, so\n// the message is the same TemplateError message (minus the `near:`/`at` context, which the\n// editor's location replaces). Not checked here: rule 7's parse5 comparison (compiler only) and\n// the browser's own parse (runtime only); rule 11 (a page shell is fine on the server). Also\n// reported: a function written directly in a hole (`.onclick=${() => …}`), since views attach\n// no closures (view/02-bindings.md \"Properties\"; the runtime warns for property bindings).\nimport type { Rule } from 'eslint';\nimport { checkTemplate, TemplateError } from '../view/index.js';\nimport { isGyral, OPTIONS_SCHEMA } from './imports.js';\nimport { cookedMap, errorSpan, type Quasi } from './locate.js';\n\n/** The message ESLint shows: the TemplateError's first line (rule, fix and spec section). */\nexport const messageOf = (error: TemplateError): string => error.message.split('\\n')[0] ?? '';\n\nexport const CLOSURE =\n 'Views attach no closures: a function in a template hole is an event handler or a callback. ' +\n 'Name an intent with data-intent=${i.Name} for events, pass data to components (they answer ' +\n 'with outputs), and put behaviour on an element in a hook (view/02-bindings.md \"Properties\").';\n\nconst INVALID_ESCAPE =\n 'This template has an invalid escape sequence, so it has no string value at runtime. ' +\n 'Fix the escape (write \\\\\\\\ for a backslash).';\n\n/** What this rule reads of a TemplateElement (ESTree's, or typescript-eslint's). */\ninterface QuasiNode {\n readonly value: { readonly cooked?: string | null | undefined };\n readonly range?: [number, number] | undefined;\n readonly tail: boolean;\n}\n\nfunction quasisOf(\n context: Rule.RuleContext,\n node: { readonly quasis: readonly QuasiNode[] },\n): { quasis: Quasi[]; cooked: string[] } | undefined {\n const text = context.sourceCode.text;\n const quasis: Quasi[] = [];\n const cooked: string[] = [];\n for (const q of node.quasis) {\n const value = q.value.cooked;\n if (typeof value !== 'string') return undefined;\n const [from, to] = q.range ?? [0, 0];\n // Parsers include the delimiters (` or } before, ` or ${ after) in the element's range.\n const start = text.charAt(from) === '`' || text.charAt(from) === '}' ? from + 1 : from;\n const end = q.tail ? to - 1 : to - 2;\n // Undecodable (it shouldn't be): point at the quasi's start.\n const map = cookedMap(text.slice(start, end), value) ?? Array<number>(value.length + 1).fill(0);\n quasis.push({ start, end, map });\n cooked.push(value);\n }\n return { quasis, cooked };\n}\n\nexport const templateRule: Rule.RuleModule = {\n meta: {\n type: 'problem',\n docs: {\n description:\n 'Template rules for html`…` and svg`…` (view/09-template-rules.md): the same checks and messages ' +\n 'as the template compiler and the development runtime.',\n recommended: true,\n url: 'https://github.com/gyraljs/gyral/blob/main/docs/design-docs/view/09-template-rules.md',\n },\n schema: OPTIONS_SCHEMA,\n messages: { rule: '{{message}}', escape: INVALID_ESCAPE, closure: CLOSURE },\n },\n create(context) {\n return {\n TaggedTemplateExpression(node) {\n const tag = node.tag as Rule.Node;\n const svg = isGyral(context, tag, 'svg');\n if (!svg && !isGyral(context, tag, 'html')) return;\n for (const value of node.quasi.expressions) {\n if (value.type === 'ArrowFunctionExpression' || value.type === 'FunctionExpression') {\n context.report({ node: value, messageId: 'closure' });\n }\n }\n const parts = quasisOf(context, node.quasi);\n if (parts === undefined) {\n context.report({ node: node.quasi, messageId: 'escape' });\n return;\n }\n const issue = checkTemplate(parts.cooked, svg);\n if (issue === undefined) return;\n const span = errorSpan(parts.quasis, parts.cooked, issue.strings, issue.at, issue.from);\n const { sourceCode } = context;\n context.report({\n loc: {\n start: sourceCode.getLocFromIndex(span.start),\n end: sourceCode.getLocFromIndex(Math.max(span.end, span.start)),\n },\n messageId: 'rule',\n data: { message: messageOf(issue.error) },\n });\n },\n };\n },\n};\n"]}
@@ -0,0 +1,2 @@
1
+ import type { Rule } from 'eslint';
2
+ export declare const unusedIntentRule: Rule.RuleModule;