@gyral/core 0.2.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 (517) hide show
  1. package/CHANGELOG.md +129 -0
  2. package/NOTICE +19 -0
  3. package/README.md +35 -8
  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 +30 -5
  8. package/dist/children.js +26 -4
  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 +31 -11
  15. package/dist/command.js.map +1 -1
  16. package/dist/compiler/ast.d.ts +23 -0
  17. package/dist/compiler/ast.js +149 -0
  18. package/dist/compiler/ast.js.map +1 -0
  19. package/dist/compiler/compile.d.ts +41 -0
  20. package/dist/compiler/compile.js +148 -0
  21. package/dist/compiler/compile.js.map +1 -0
  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 +22 -0
  35. package/dist/compiler/hooks.js +241 -0
  36. package/dist/compiler/hooks.js.map +1 -0
  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 +21 -0
  44. package/dist/compiler/parse5-check.js +60 -0
  45. package/dist/compiler/parse5-check.js.map +1 -0
  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 +41 -0
  50. package/dist/compiler/scan.js +160 -0
  51. package/dist/compiler/scan.js.map +1 -0
  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/source.d.ts +34 -0
  56. package/dist/compiler/source.js +114 -0
  57. package/dist/compiler/source.js.map +1 -0
  58. package/dist/compiler/tag-map.d.ts +41 -0
  59. package/dist/compiler/tag-map.js +126 -0
  60. package/dist/compiler/tag-map.js.map +1 -0
  61. package/dist/components-ready.d.ts +7 -0
  62. package/dist/components-ready.js +19 -0
  63. package/dist/components-ready.js.map +1 -0
  64. package/dist/define.d.ts +13 -4
  65. package/dist/define.js +35 -331
  66. package/dist/define.js.map +1 -1
  67. package/dist/devtools-events.d.ts +13 -0
  68. package/dist/devtools-events.js.map +1 -1
  69. package/dist/devtools-off.d.ts +2 -0
  70. package/dist/devtools-off.js +2 -0
  71. package/dist/devtools-off.js.map +1 -1
  72. package/dist/devtools.d.ts +4 -0
  73. package/dist/devtools.js +17 -2
  74. package/dist/devtools.js.map +1 -1
  75. package/dist/drivers-scope.d.ts +1 -1
  76. package/dist/drivers-scope.js +1 -8
  77. package/dist/drivers-scope.js.map +1 -1
  78. package/dist/element-internals.d.ts +1 -0
  79. package/dist/element-internals.js +11 -0
  80. package/dist/element-internals.js.map +1 -0
  81. package/dist/element-types.d.ts +11 -5
  82. package/dist/element-types.js.map +1 -1
  83. package/dist/element.d.ts +3 -0
  84. package/dist/element.js +322 -0
  85. package/dist/element.js.map +1 -0
  86. package/dist/error-view.d.ts +10 -0
  87. package/dist/error-view.js +30 -0
  88. package/dist/error-view.js.map +1 -0
  89. package/dist/errors.d.ts +21 -0
  90. package/dist/errors.js +47 -0
  91. package/dist/errors.js.map +1 -0
  92. package/dist/errors.json +289 -0
  93. package/dist/eslint/imports.d.ts +26 -0
  94. package/dist/eslint/imports.js +78 -0
  95. package/dist/eslint/imports.js.map +1 -0
  96. package/dist/eslint/index.d.ts +16 -0
  97. package/dist/eslint/index.js +23 -0
  98. package/dist/eslint/index.js.map +1 -0
  99. package/dist/eslint/locate.d.ts +33 -0
  100. package/dist/eslint/locate.js +132 -0
  101. package/dist/eslint/locate.js.map +1 -0
  102. package/dist/eslint/row-purity-rule.d.ts +2 -0
  103. package/dist/eslint/row-purity-rule.js +103 -0
  104. package/dist/eslint/row-purity-rule.js.map +1 -0
  105. package/dist/eslint/template-rule.d.ts +6 -0
  106. package/dist/eslint/template-rule.js +76 -0
  107. package/dist/eslint/template-rule.js.map +1 -0
  108. package/dist/eslint/unused-intent-rule.d.ts +2 -0
  109. package/dist/eslint/unused-intent-rule.js +186 -0
  110. package/dist/eslint/unused-intent-rule.js.map +1 -0
  111. package/dist/features.d.ts +39 -0
  112. package/dist/features.js +2 -0
  113. package/dist/features.js.map +1 -0
  114. package/dist/focus.d.ts +13 -12
  115. package/dist/focus.js +44 -11
  116. package/dist/focus.js.map +1 -1
  117. package/dist/form-associated.d.ts +46 -0
  118. package/dist/form-associated.js +77 -0
  119. package/dist/form-associated.js.map +1 -0
  120. package/dist/forms.d.ts +42 -30
  121. package/dist/forms.js +85 -41
  122. package/dist/forms.js.map +1 -1
  123. package/dist/frame-lane.d.ts +11 -0
  124. package/dist/frame-lane.js +28 -0
  125. package/dist/frame-lane.js.map +1 -0
  126. package/dist/head.d.ts +61 -0
  127. package/dist/head.js +85 -0
  128. package/dist/head.js.map +1 -0
  129. package/dist/hooks/invalid.d.ts +14 -0
  130. package/dist/hooks/invalid.js +72 -0
  131. package/dist/hooks/invalid.js.map +1 -0
  132. package/dist/host-model.d.ts +77 -0
  133. package/dist/host-model.js +278 -0
  134. package/dist/host-model.js.map +1 -0
  135. package/dist/hydration-client.d.ts +9 -0
  136. package/dist/hydration-client.js +35 -0
  137. package/dist/hydration-client.js.map +1 -0
  138. package/dist/hydration-loader.d.ts +13 -0
  139. package/dist/hydration-loader.js +58 -0
  140. package/dist/hydration-loader.js.map +1 -0
  141. package/dist/hydration-off.d.ts +8 -0
  142. package/dist/hydration-off.js +25 -0
  143. package/dist/hydration-off.js.map +1 -0
  144. package/dist/hydration.d.ts +3 -21
  145. package/dist/hydration.js +14 -63
  146. package/dist/hydration.js.map +1 -1
  147. package/dist/index.d.ts +24 -36
  148. package/dist/index.js +14 -32
  149. package/dist/index.js.map +1 -1
  150. package/dist/indexeddb-types.d.ts +97 -0
  151. package/dist/indexeddb-types.js +2 -0
  152. package/dist/indexeddb-types.js.map +1 -0
  153. package/dist/indexeddb.d.ts +5 -0
  154. package/dist/indexeddb.js +118 -0
  155. package/dist/indexeddb.js.map +1 -0
  156. package/dist/intent.d.ts +62 -17
  157. package/dist/intent.js +193 -100
  158. package/dist/intent.js.map +1 -1
  159. package/dist/internal/indexeddb-open.d.ts +8 -0
  160. package/dist/internal/indexeddb-open.js +96 -0
  161. package/dist/internal/indexeddb-open.js.map +1 -0
  162. package/dist/internal/indexeddb-transaction.d.ts +4 -0
  163. package/dist/internal/indexeddb-transaction.js +134 -0
  164. package/dist/internal/indexeddb-transaction.js.map +1 -0
  165. package/dist/internal/interpreter.d.ts +15 -1
  166. package/dist/internal/interpreter.js +42 -47
  167. package/dist/internal/interpreter.js.map +1 -1
  168. package/dist/internal/token.d.ts +1 -0
  169. package/dist/internal/token.js +7 -0
  170. package/dist/internal/token.js.map +1 -0
  171. package/dist/internal.d.ts +20 -0
  172. package/dist/internal.js +22 -0
  173. package/dist/internal.js.map +1 -0
  174. package/dist/invoker-fallback-used.d.ts +4 -0
  175. package/dist/invoker-fallback-used.js +10 -0
  176. package/dist/invoker-fallback-used.js.map +1 -0
  177. package/dist/invoker-fallback.d.ts +4 -0
  178. package/dist/invoker-fallback.js +15 -0
  179. package/dist/invoker-fallback.js.map +1 -0
  180. package/dist/invokers-shim.d.ts +6 -0
  181. package/dist/invokers-shim.js +32 -0
  182. package/dist/invokers-shim.js.map +1 -0
  183. package/dist/invokers.d.ts +3 -5
  184. package/dist/invokers.js +11 -51
  185. package/dist/invokers.js.map +1 -1
  186. package/dist/islands.d.ts +0 -2
  187. package/dist/islands.js +4 -11
  188. package/dist/islands.js.map +1 -1
  189. package/dist/light-dom.d.ts +4 -53
  190. package/dist/light-dom.js +5 -100
  191. package/dist/light-dom.js.map +1 -1
  192. package/dist/prop.d.ts +89 -0
  193. package/dist/prop.js +41 -0
  194. package/dist/prop.js.map +1 -0
  195. package/dist/props.d.ts +57 -21
  196. package/dist/props.js +157 -34
  197. package/dist/props.js.map +1 -1
  198. package/dist/retry.d.ts +15 -0
  199. package/dist/retry.js +48 -0
  200. package/dist/retry.js.map +1 -0
  201. package/dist/scheduler.d.ts +43 -0
  202. package/dist/scheduler.js +212 -0
  203. package/dist/scheduler.js.map +1 -0
  204. package/dist/script-json.d.ts +2 -0
  205. package/dist/script-json.js +13 -0
  206. package/dist/script-json.js.map +1 -0
  207. package/dist/server-component.d.ts +10 -0
  208. package/dist/server-component.js +133 -0
  209. package/dist/server-component.js.map +1 -0
  210. package/dist/server-specs.d.ts +6 -0
  211. package/dist/server-specs.js +13 -0
  212. package/dist/server-specs.js.map +1 -0
  213. package/dist/server.d.ts +34 -0
  214. package/dist/server.js +59 -0
  215. package/dist/server.js.map +1 -0
  216. package/dist/settled.d.ts +11 -0
  217. package/dist/settled.js +62 -0
  218. package/dist/settled.js.map +1 -0
  219. package/dist/spec-features-used.d.ts +21 -0
  220. package/dist/spec-features-used.js +50 -0
  221. package/dist/spec-features-used.js.map +1 -0
  222. package/dist/spec-features.d.ts +28 -0
  223. package/dist/spec-features.js +42 -0
  224. package/dist/spec-features.js.map +1 -0
  225. package/dist/states.d.ts +3 -5
  226. package/dist/states.js +22 -11
  227. package/dist/states.js.map +1 -1
  228. package/dist/storage.d.ts +69 -0
  229. package/dist/storage.js +158 -0
  230. package/dist/storage.js.map +1 -0
  231. package/dist/store-binding.d.ts +6 -3
  232. package/dist/store-binding.js +7 -8
  233. package/dist/store-binding.js.map +1 -1
  234. package/dist/store-scope.d.ts +8 -11
  235. package/dist/store-scope.js +15 -40
  236. package/dist/store-scope.js.map +1 -1
  237. package/dist/store.d.ts +3 -0
  238. package/dist/store.js +45 -10
  239. package/dist/store.js.map +1 -1
  240. package/dist/stores-provider.d.ts +2 -6
  241. package/dist/stores-provider.js +21 -55
  242. package/dist/stores-provider.js.map +1 -1
  243. package/dist/subscription.d.ts +35 -0
  244. package/dist/subscription.js +74 -0
  245. package/dist/subscription.js.map +1 -0
  246. package/dist/subscriptions.d.ts +26 -0
  247. package/dist/subscriptions.js +98 -0
  248. package/dist/subscriptions.js.map +1 -0
  249. package/dist/transitions.d.ts +5 -7
  250. package/dist/transitions.js +17 -20
  251. package/dist/transitions.js.map +1 -1
  252. package/dist/types.d.ts +142 -49
  253. package/dist/types.js.map +1 -1
  254. package/dist/use-dialogs.d.ts +2 -0
  255. package/dist/use-dialogs.js +9 -0
  256. package/dist/use-dialogs.js.map +1 -0
  257. package/dist/use-disposal.d.ts +2 -0
  258. package/dist/use-disposal.js +9 -0
  259. package/dist/use-disposal.js.map +1 -0
  260. package/dist/use-error-view.d.ts +2 -0
  261. package/dist/use-error-view.js +9 -0
  262. package/dist/use-error-view.js.map +1 -0
  263. package/dist/use-errored.d.ts +2 -0
  264. package/dist/use-errored.js +9 -0
  265. package/dist/use-errored.js.map +1 -0
  266. package/dist/use-form-associated.d.ts +2 -0
  267. package/dist/use-form-associated.js +7 -0
  268. package/dist/use-form-associated.js.map +1 -0
  269. package/dist/use-frame-lane.d.ts +2 -0
  270. package/dist/use-frame-lane.js +10 -0
  271. package/dist/use-frame-lane.js.map +1 -0
  272. package/dist/use-invokers.d.ts +2 -0
  273. package/dist/use-invokers.js +10 -0
  274. package/dist/use-invokers.js.map +1 -0
  275. package/dist/use-states.d.ts +2 -0
  276. package/dist/use-states.js +10 -0
  277. package/dist/use-states.js.map +1 -0
  278. package/dist/use-subscriptions.d.ts +2 -0
  279. package/dist/use-subscriptions.js +10 -0
  280. package/dist/use-subscriptions.js.map +1 -0
  281. package/dist/use-transitions.d.ts +2 -0
  282. package/dist/use-transitions.js +10 -0
  283. package/dist/use-transitions.js.map +1 -0
  284. package/dist/view/attributes.d.ts +11 -0
  285. package/dist/view/attributes.js +15 -0
  286. package/dist/view/attributes.js.map +1 -0
  287. package/dist/view/compiled.d.ts +1 -0
  288. package/dist/view/compiled.js +6 -0
  289. package/dist/view/compiled.js.map +1 -0
  290. package/dist/view/dev-off.d.ts +1 -0
  291. package/dist/view/dev-off.js +4 -0
  292. package/dist/view/dev-off.js.map +1 -0
  293. package/dist/view/dev.d.ts +1 -0
  294. package/dist/view/dev.js +5 -0
  295. package/dist/view/dev.js.map +1 -0
  296. package/dist/view/flags.d.ts +1 -0
  297. package/dist/view/flags.js +4 -0
  298. package/dist/view/flags.js.map +1 -0
  299. package/dist/view/index.d.ts +26 -0
  300. package/dist/view/index.js +27 -0
  301. package/dist/view/index.js.map +1 -0
  302. package/dist/view/loc.d.ts +9 -0
  303. package/dist/view/loc.js +50 -0
  304. package/dist/view/loc.js.map +1 -0
  305. package/dist/view/message.d.ts +17 -0
  306. package/dist/view/message.js +40 -0
  307. package/dist/view/message.js.map +1 -0
  308. package/dist/view/messages.d.ts +43 -0
  309. package/dist/view/messages.js +84 -0
  310. package/dist/view/messages.js.map +1 -0
  311. package/dist/view/normalize/check.d.ts +23 -0
  312. package/dist/view/normalize/check.js +81 -0
  313. package/dist/view/normalize/check.js.map +1 -0
  314. package/dist/view/normalize/emit.d.ts +15 -0
  315. package/dist/view/normalize/emit.js +165 -0
  316. package/dist/view/normalize/emit.js.map +1 -0
  317. package/dist/view/normalize/entities.d.ts +4 -0
  318. package/dist/view/normalize/entities.js +38 -0
  319. package/dist/view/normalize/entities.js.map +1 -0
  320. package/dist/view/normalize/errors.d.ts +9 -0
  321. package/dist/view/normalize/errors.js +19 -0
  322. package/dist/view/normalize/errors.js.map +1 -0
  323. package/dist/view/normalize/id.d.ts +10 -0
  324. package/dist/view/normalize/id.js +55 -0
  325. package/dist/view/normalize/id.js.map +1 -0
  326. package/dist/view/normalize/normalize.d.ts +18 -0
  327. package/dist/view/normalize/normalize.js +42 -0
  328. package/dist/view/normalize/normalize.js.map +1 -0
  329. package/dist/view/normalize/repairs.d.ts +24 -0
  330. package/dist/view/normalize/repairs.js +166 -0
  331. package/dist/view/normalize/repairs.js.map +1 -0
  332. package/dist/view/normalize/rules.d.ts +39 -0
  333. package/dist/view/normalize/rules.js +120 -0
  334. package/dist/view/normalize/rules.js.map +1 -0
  335. package/dist/view/normalize/shape.d.ts +5 -0
  336. package/dist/view/normalize/shape.js +38 -0
  337. package/dist/view/normalize/shape.js.map +1 -0
  338. package/dist/view/normalize/source.d.ts +13 -0
  339. package/dist/view/normalize/source.js +34 -0
  340. package/dist/view/normalize/source.js.map +1 -0
  341. package/dist/view/normalize/svg.d.ts +14 -0
  342. package/dist/view/normalize/svg.js +40 -0
  343. package/dist/view/normalize/svg.js.map +1 -0
  344. package/dist/view/normalize/tag-states.d.ts +23 -0
  345. package/dist/view/normalize/tag-states.js +192 -0
  346. package/dist/view/normalize/tag-states.js.map +1 -0
  347. package/dist/view/normalize/tokenizer.d.ts +5 -0
  348. package/dist/view/normalize/tokenizer.js +233 -0
  349. package/dist/view/normalize/tokenizer.js.map +1 -0
  350. package/dist/view/normalize/tokens.d.ts +55 -0
  351. package/dist/view/normalize/tokens.js +24 -0
  352. package/dist/view/normalize/tokens.js.map +1 -0
  353. package/dist/view/normalize/tree.d.ts +65 -0
  354. package/dist/view/normalize/tree.js +235 -0
  355. package/dist/view/normalize/tree.js.map +1 -0
  356. package/dist/view/normalize/types.d.ts +146 -0
  357. package/dist/view/normalize/types.js +29 -0
  358. package/dist/view/normalize/types.js.map +1 -0
  359. package/dist/view/normalize/whitespace.d.ts +2 -0
  360. package/dist/{template-whitespace.js → view/normalize/whitespace.js} +27 -36
  361. package/dist/view/normalize/whitespace.js.map +1 -0
  362. package/dist/view/prepare-stub.d.ts +3 -0
  363. package/dist/view/prepare-stub.js +7 -0
  364. package/dist/view/prepare-stub.js.map +1 -0
  365. package/dist/view/prepare.d.ts +11 -0
  366. package/dist/view/prepare.js +63 -0
  367. package/dist/view/prepare.js.map +1 -0
  368. package/dist/view/registry.d.ts +78 -0
  369. package/dist/view/registry.js +27 -0
  370. package/dist/view/registry.js.map +1 -0
  371. package/dist/view/render/adopt-attr.d.ts +14 -0
  372. package/dist/view/render/adopt-attr.js +83 -0
  373. package/dist/view/render/adopt-attr.js.map +1 -0
  374. package/dist/view/render/adopt-plan.d.ts +10 -0
  375. package/dist/view/render/adopt-plan.js +26 -0
  376. package/dist/view/render/adopt-plan.js.map +1 -0
  377. package/dist/view/render/adopt.d.ts +3 -0
  378. package/dist/view/render/adopt.js +286 -0
  379. package/dist/view/render/adopt.js.map +1 -0
  380. package/dist/view/render/attr-parts.d.ts +72 -0
  381. package/dist/view/render/attr-parts.js +262 -0
  382. package/dist/view/render/attr-parts.js.map +1 -0
  383. package/dist/view/render/child-part.d.ts +51 -0
  384. package/dist/view/render/child-part.js +173 -0
  385. package/dist/view/render/child-part.js.map +1 -0
  386. package/dist/view/render/dev-check.d.ts +12 -0
  387. package/dist/view/render/dev-check.js +122 -0
  388. package/dist/view/render/dev-check.js.map +1 -0
  389. package/dist/view/render/dispose.d.ts +3 -0
  390. package/dist/view/render/dispose.js +76 -0
  391. package/dist/view/render/dispose.js.map +1 -0
  392. package/dist/view/render/hook-part.d.ts +5 -0
  393. package/dist/view/render/hook-part.js +36 -0
  394. package/dist/view/render/hook-part.js.map +1 -0
  395. package/dist/view/render/hook-run.d.ts +2 -0
  396. package/dist/view/render/hook-run.js +72 -0
  397. package/dist/view/render/hook-run.js.map +1 -0
  398. package/dist/view/render/hooks.d.ts +108 -0
  399. package/dist/view/render/hooks.js +108 -0
  400. package/dist/view/render/hooks.js.map +1 -0
  401. package/dist/view/render/hydrate.d.ts +10 -0
  402. package/dist/view/render/hydrate.js +33 -0
  403. package/dist/view/render/hydrate.js.map +1 -0
  404. package/dist/view/render/instance.d.ts +33 -0
  405. package/dist/view/render/instance.js +107 -0
  406. package/dist/view/render/instance.js.map +1 -0
  407. package/dist/view/render/keyed.d.ts +6 -0
  408. package/dist/view/render/keyed.js +15 -0
  409. package/dist/view/render/keyed.js.map +1 -0
  410. package/dist/view/render/list.d.ts +20 -0
  411. package/dist/view/render/list.js +156 -0
  412. package/dist/view/render/list.js.map +1 -0
  413. package/dist/view/render/mismatch.d.ts +10 -0
  414. package/dist/view/render/mismatch.js +55 -0
  415. package/dist/view/render/mismatch.js.map +1 -0
  416. package/dist/view/render/modal.d.ts +3 -0
  417. package/dist/view/render/modal.js +39 -0
  418. package/dist/view/render/modal.js.map +1 -0
  419. package/dist/view/render/nodes.d.ts +10 -0
  420. package/dist/view/render/nodes.js +37 -0
  421. package/dist/view/render/nodes.js.map +1 -0
  422. package/dist/view/render/place.d.ts +18 -0
  423. package/dist/view/render/place.js +69 -0
  424. package/dist/view/render/place.js.map +1 -0
  425. package/dist/view/render/plan.d.ts +26 -0
  426. package/dist/view/render/plan.js +124 -0
  427. package/dist/view/render/plan.js.map +1 -0
  428. package/dist/view/render/raw.d.ts +21 -0
  429. package/dist/view/render/raw.js +72 -0
  430. package/dist/view/render/raw.js.map +1 -0
  431. package/dist/view/render/render.d.ts +15 -0
  432. package/dist/view/render/render.js +65 -0
  433. package/dist/view/render/render.js.map +1 -0
  434. package/dist/view/render/reorder.d.ts +4 -0
  435. package/dist/view/render/reorder.js +101 -0
  436. package/dist/view/render/reorder.js.map +1 -0
  437. package/dist/view/render/rows.d.ts +23 -0
  438. package/dist/view/render/rows.js +95 -0
  439. package/dist/view/render/rows.js.map +1 -0
  440. package/dist/view/render/seen.d.ts +11 -0
  441. package/dist/view/render/seen.js +17 -0
  442. package/dist/view/render/seen.js.map +1 -0
  443. package/dist/view/render/toggles.d.ts +6 -0
  444. package/dist/view/render/toggles.js +6 -0
  445. package/dist/view/render/toggles.js.map +1 -0
  446. package/dist/view/render/values.d.ts +29 -0
  447. package/dist/view/render/values.js +13 -0
  448. package/dist/view/render/values.js.map +1 -0
  449. package/dist/view/render/warn.d.ts +28 -0
  450. package/dist/view/render/warn.js +114 -0
  451. package/dist/view/render/warn.js.map +1 -0
  452. package/dist/view/server/component.d.ts +12 -0
  453. package/dist/view/server/component.js +64 -0
  454. package/dist/view/server/component.js.map +1 -0
  455. package/dist/view/server/escape.d.ts +10 -0
  456. package/dist/view/server/escape.js +34 -0
  457. package/dist/view/server/escape.js.map +1 -0
  458. package/dist/view/server/index.d.ts +48 -0
  459. package/dist/view/server/index.js +80 -0
  460. package/dist/view/server/index.js.map +1 -0
  461. package/dist/view/server/sha256.d.ts +2 -0
  462. package/dist/view/server/sha256.js +75 -0
  463. package/dist/view/server/sha256.js.map +1 -0
  464. package/dist/view/server/tags.d.ts +68 -0
  465. package/dist/view/server/tags.js +132 -0
  466. package/dist/view/server/tags.js.map +1 -0
  467. package/dist/view/server/values.d.ts +18 -0
  468. package/dist/view/server/values.js +94 -0
  469. package/dist/view/server/values.js.map +1 -0
  470. package/dist/view/server/writer.d.ts +21 -0
  471. package/dist/view/server/writer.js +170 -0
  472. package/dist/view/server/writer.js.map +1 -0
  473. package/dist/view/styles.d.ts +25 -0
  474. package/dist/view/styles.js +58 -0
  475. package/dist/view/styles.js.map +1 -0
  476. package/dist/view/template-element.d.ts +10 -0
  477. package/dist/view/template-element.js +45 -0
  478. package/dist/view/template-element.js.map +1 -0
  479. package/dist/view/template.d.ts +29 -0
  480. package/dist/view/template.js +84 -0
  481. package/dist/view/template.js.map +1 -0
  482. package/dist/view/trusted-html.d.ts +6 -0
  483. package/dist/view/trusted-html.js +34 -0
  484. package/dist/view/trusted-html.js.map +1 -0
  485. package/dist/vite.d.ts +57 -11
  486. package/dist/vite.js +319 -27
  487. package/dist/vite.js.map +1 -1
  488. package/package.json +70 -4
  489. package/dist/accessible-name.d.ts +0 -19
  490. package/dist/accessible-name.js +0 -56
  491. package/dist/accessible-name.js.map +0 -1
  492. package/dist/element-directive.d.ts +0 -20
  493. package/dist/element-directive.js +0 -31
  494. package/dist/element-directive.js.map +0 -1
  495. package/dist/invalid.d.ts +0 -21
  496. package/dist/invalid.js +0 -70
  497. package/dist/invalid.js.map +0 -1
  498. package/dist/lit-html-check.d.ts +0 -6
  499. package/dist/lit-html-check.js +0 -48
  500. package/dist/lit-html-check.js.map +0 -1
  501. package/dist/live-boolean.d.ts +0 -22
  502. package/dist/live-boolean.js +0 -34
  503. package/dist/live-boolean.js.map +0 -1
  504. package/dist/random.d.ts +0 -13
  505. package/dist/random.js +0 -19
  506. package/dist/random.js.map +0 -1
  507. package/dist/styles.d.ts +0 -12
  508. package/dist/styles.js +0 -11
  509. package/dist/styles.js.map +0 -1
  510. package/dist/template-whitespace.d.ts +0 -7
  511. package/dist/template-whitespace.js.map +0 -1
  512. package/dist/templates.d.ts +0 -5
  513. package/dist/templates.js +0 -15
  514. package/dist/templates.js.map +0 -1
  515. package/dist/textarea.d.ts +0 -26
  516. package/dist/textarea.js +0 -85
  517. package/dist/textarea.js.map +0 -1
@@ -0,0 +1,2 @@
1
+ import type { Rule } from 'eslint';
2
+ export declare const rowPurityRule: Rule.RuleModule;
@@ -0,0 +1,103 @@
1
+ import { findVariable, isGyral, OPTIONS_SCHEMA } from './imports.js';
2
+ const isFn = (node) => node?.type === 'ArrowFunctionExpression' ||
3
+ node?.type === 'FunctionExpression' ||
4
+ node?.type === 'FunctionDeclaration';
5
+ /** The function a binding holds when that is static: `function F`, or `const F = (…) => …`. */
6
+ function boundFunction(variable) {
7
+ const def = variable?.defs.length === 1 ? variable.defs[0] : undefined;
8
+ if (def?.type === 'FunctionName')
9
+ return def.node;
10
+ if (def?.type !== 'Variable' || def.parent.kind !== 'const')
11
+ return undefined;
12
+ const init = def.node.init;
13
+ return isFn(init) ? init : undefined;
14
+ }
15
+ /**
16
+ * The function a `row` argument is: inline, or a name bound to one. Anything else (a call, a
17
+ * parameter, a `let`) can't be followed statically; the development check (view/03) covers it.
18
+ */
19
+ function rowFunction(context, row) {
20
+ if (isFn(row))
21
+ return row;
22
+ if (row.type !== 'Identifier')
23
+ return undefined;
24
+ return boundFunction(findVariable(context.sourceCode.getScope(row), row.name));
25
+ }
26
+ /**
27
+ * The references in `fn` (nested functions included) to bindings of enclosing functions. A
28
+ * helper beside the row (`const Cell = (…) => …` in the same function) is followed instead: it
29
+ * is fine when it reads nothing from an enclosing function itself. `seen` stops recursion.
30
+ */
31
+ function enclosingReads(context, fn, seen) {
32
+ seen.add(fn);
33
+ return context.sourceCode.getScope(fn).through.filter((ref) => {
34
+ if ('isValueReference' in ref && ref.isValueReference === false)
35
+ return false; // a type
36
+ const variable = ref.resolved;
37
+ if (variable === null)
38
+ return false; // a global
39
+ const type = variable.scope.variableScope.type;
40
+ if (type === 'module' || type === 'global')
41
+ return false;
42
+ const helper = boundFunction(variable);
43
+ if (helper === undefined)
44
+ return true;
45
+ return !seen.has(helper) && enclosingReads(context, helper, seen).length > 0;
46
+ });
47
+ }
48
+ /** `s`, or `s.selected` / `s.a.b` when the reference starts a property chain, and its node. */
49
+ function readOf(id) {
50
+ let name = id.type === 'Identifier' ? id.name : '';
51
+ let node = id;
52
+ for (let p = node.parent; p?.type === 'MemberExpression'; p = p.parent) {
53
+ if (p.object !== node || p.computed || p.property.type !== 'Identifier')
54
+ break;
55
+ name += `.${p.property.name}`;
56
+ node = p;
57
+ }
58
+ return { name, node };
59
+ }
60
+ const isMissing = (key) => (key.type === 'Identifier' && key.name === 'undefined') ||
61
+ (key.type === 'Literal' && key.value === null);
62
+ export const rowPurityRule = {
63
+ meta: {
64
+ type: 'problem',
65
+ docs: {
66
+ description: "each()'s row reads only its item, its picked value, module-level bindings and " +
67
+ 'imports; each() has a key function (view/03-lists.md, rules 8 and 9).',
68
+ recommended: true,
69
+ url: 'https://github.com/gyraljs/gyral/blob/main/docs/design-docs/view/03-lists.md',
70
+ },
71
+ schema: OPTIONS_SCHEMA,
72
+ messages: {
73
+ reads: '`row` reads `{{name}}`; return it from `pick` and take it as the second argument ' +
74
+ '(view/03-lists.md).',
75
+ key: 'each() needs a key function as its second argument: each(items, (x) => x.id, Row) ' +
76
+ '(docs/design-docs/view/03-lists.md "Keys", rule 9).',
77
+ },
78
+ },
79
+ create(context) {
80
+ const reported = new Set();
81
+ return {
82
+ CallExpression(node) {
83
+ if (!isGyral(context, node.callee, 'each'))
84
+ return;
85
+ const [, key, row] = node.arguments;
86
+ if (key === undefined || row === undefined || isMissing(key)) {
87
+ context.report({ node, messageId: 'key' });
88
+ }
89
+ const fn = row === undefined ? undefined : rowFunction(context, row);
90
+ if (fn === undefined)
91
+ return;
92
+ for (const ref of enclosingReads(context, fn, new Set())) {
93
+ const { name, node: read } = readOf(ref.identifier);
94
+ if (reported.has(read))
95
+ continue; // one row passed to several each() calls
96
+ reported.add(read);
97
+ context.report({ node: read, messageId: 'reads', data: { name } });
98
+ }
99
+ },
100
+ };
101
+ },
102
+ };
103
+ //# sourceMappingURL=row-purity-rule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"row-purity-rule.js","sourceRoot":"","sources":["../../src/eslint/row-purity-rule.ts"],"names":[],"mappings":"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","sourcesContent":["// gyral/each-row-purity: rules 8 and 9 of view/09-template-rules.md (view/03-lists.md \"Rows must\n// be pure\", \"Keys\"). A skipped row is only correct when its output depends on nothing but\n// (item, picked), so `each`'s row may read only its own parameters and locals, module-level\n// bindings, imports and globals; anything from an enclosing function (the view's `s`, `i`, `ctx`,\n// its locals) must come through `pick`. Helper functions declared beside the row are followed\n// (they may read only the same). And every `each` needs a key function.\nimport type { Rule, Scope } from 'eslint';\nimport { findVariable, isGyral, OPTIONS_SCHEMA, type Node, type NodeOf } from './imports.js';\n\ntype Fn =\n NodeOf<'ArrowFunctionExpression'> | NodeOf<'FunctionExpression'> | NodeOf<'FunctionDeclaration'>;\n\nconst isFn = (node: Node | null | undefined): node is Fn =>\n node?.type === 'ArrowFunctionExpression' ||\n node?.type === 'FunctionExpression' ||\n node?.type === 'FunctionDeclaration';\n\n/** The function a binding holds when that is static: `function F`, or `const F = (…) => …`. */\nfunction boundFunction(variable: Scope.Variable | null | undefined): Fn | undefined {\n const def = variable?.defs.length === 1 ? variable.defs[0] : undefined;\n if (def?.type === 'FunctionName') return def.node as Fn;\n if (def?.type !== 'Variable' || def.parent.kind !== 'const') return undefined;\n const init = def.node.init as Node | null | undefined;\n return isFn(init) ? init : undefined;\n}\n\n/**\n * The function a `row` argument is: inline, or a name bound to one. Anything else (a call, a\n * parameter, a `let`) can't be followed statically; the development check (view/03) covers it.\n */\nfunction rowFunction(context: Rule.RuleContext, row: Node): Fn | undefined {\n if (isFn(row)) return row;\n if (row.type !== 'Identifier') return undefined;\n return boundFunction(findVariable(context.sourceCode.getScope(row), row.name));\n}\n\n/**\n * The references in `fn` (nested functions included) to bindings of enclosing functions. A\n * helper beside the row (`const Cell = (…) => …` in the same function) is followed instead: it\n * is fine when it reads nothing from an enclosing function itself. `seen` stops recursion.\n */\nfunction enclosingReads(context: Rule.RuleContext, fn: Fn, seen: Set<Fn>): Scope.Reference[] {\n seen.add(fn);\n return context.sourceCode.getScope(fn).through.filter((ref) => {\n if ('isValueReference' in ref && ref.isValueReference === false) return false; // a type\n const variable = ref.resolved;\n if (variable === null) return false; // a global\n const type = variable.scope.variableScope.type;\n if (type === 'module' || type === 'global') return false;\n const helper = boundFunction(variable);\n if (helper === undefined) return true;\n return !seen.has(helper) && enclosingReads(context, helper, seen).length > 0;\n });\n}\n\n/** `s`, or `s.selected` / `s.a.b` when the reference starts a property chain, and its node. */\nfunction readOf(id: Node): { name: string; node: Node } {\n let name = id.type === 'Identifier' ? id.name : '';\n let node: Node = id;\n for (let p = node.parent; p?.type === 'MemberExpression'; p = p.parent) {\n if (p.object !== node || p.computed || p.property.type !== 'Identifier') break;\n name += `.${p.property.name}`;\n node = p;\n }\n return { name, node };\n}\n\nconst isMissing = (key: Node): boolean =>\n (key.type === 'Identifier' && key.name === 'undefined') ||\n (key.type === 'Literal' && key.value === null);\n\nexport const rowPurityRule: Rule.RuleModule = {\n meta: {\n type: 'problem',\n docs: {\n description:\n \"each()'s row reads only its item, its picked value, module-level bindings and \" +\n 'imports; each() has a key function (view/03-lists.md, rules 8 and 9).',\n recommended: true,\n url: 'https://github.com/gyraljs/gyral/blob/main/docs/design-docs/view/03-lists.md',\n },\n schema: OPTIONS_SCHEMA,\n messages: {\n reads:\n '`row` reads `{{name}}`; return it from `pick` and take it as the second argument ' +\n '(view/03-lists.md).',\n key:\n 'each() needs a key function as its second argument: each(items, (x) => x.id, Row) ' +\n '(docs/design-docs/view/03-lists.md \"Keys\", rule 9).',\n },\n },\n create(context) {\n const reported = new Set<Node>();\n return {\n CallExpression(node) {\n if (!isGyral(context, node.callee as Node, 'each')) return;\n const [, key, row] = node.arguments as Node[];\n if (key === undefined || row === undefined || isMissing(key)) {\n context.report({ node, messageId: 'key' });\n }\n const fn = row === undefined ? undefined : rowFunction(context, row);\n if (fn === undefined) return;\n for (const ref of enclosingReads(context, fn, new Set())) {\n const { name, node: read } = readOf(ref.identifier as Node);\n if (reported.has(read)) continue; // one row passed to several each() calls\n reported.add(read);\n context.report({ node: read, messageId: 'reads', data: { name } });\n }\n },\n };\n },\n};\n"]}
@@ -0,0 +1,6 @@
1
+ import type { Rule } from 'eslint';
2
+ import { TemplateError } from '../view/index.js';
3
+ /** The message ESLint shows: the TemplateError's first line (rule, fix and spec section). */
4
+ export declare const messageOf: (error: TemplateError) => string;
5
+ export declare const CLOSURE: string;
6
+ export declare const templateRule: Rule.RuleModule;
@@ -0,0 +1,76 @@
1
+ import { checkTemplate, TemplateError } from '../view/index.js';
2
+ import { isGyral, OPTIONS_SCHEMA } from './imports.js';
3
+ import { cookedMap, errorSpan } from './locate.js';
4
+ /** The message ESLint shows: the TemplateError's first line (rule, fix and spec section). */
5
+ export const messageOf = (error) => error.message.split('\n')[0] ?? '';
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. ' +
10
+ 'Fix the escape (write \\\\ for a backslash).';
11
+ function quasisOf(context, node) {
12
+ const text = context.sourceCode.text;
13
+ const quasis = [];
14
+ const cooked = [];
15
+ for (const q of node.quasis) {
16
+ const value = q.value.cooked;
17
+ if (typeof value !== 'string')
18
+ return undefined;
19
+ const [from, to] = q.range ?? [0, 0];
20
+ // Parsers include the delimiters (` or } before, ` or ${ after) in the element's range.
21
+ const start = text.charAt(from) === '`' || text.charAt(from) === '}' ? from + 1 : from;
22
+ const end = q.tail ? to - 1 : to - 2;
23
+ // Undecodable (it shouldn't be): point at the quasi's start.
24
+ const map = cookedMap(text.slice(start, end), value) ?? Array(value.length + 1).fill(0);
25
+ quasis.push({ start, end, map });
26
+ cooked.push(value);
27
+ }
28
+ return { quasis, cooked };
29
+ }
30
+ export const templateRule = {
31
+ meta: {
32
+ type: 'problem',
33
+ docs: {
34
+ description: 'Template rules for html`…` and svg`…` (view/09-template-rules.md): the same checks and messages ' +
35
+ 'as the template compiler and the development runtime.',
36
+ recommended: true,
37
+ url: 'https://github.com/gyraljs/gyral/blob/main/docs/design-docs/view/09-template-rules.md',
38
+ },
39
+ schema: OPTIONS_SCHEMA,
40
+ messages: { rule: '{{message}}', escape: INVALID_ESCAPE, closure: CLOSURE },
41
+ },
42
+ create(context) {
43
+ return {
44
+ TaggedTemplateExpression(node) {
45
+ const tag = node.tag;
46
+ const svg = isGyral(context, tag, 'svg');
47
+ if (!svg && !isGyral(context, tag, 'html'))
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
+ }
54
+ const parts = quasisOf(context, node.quasi);
55
+ if (parts === undefined) {
56
+ context.report({ node: node.quasi, messageId: 'escape' });
57
+ return;
58
+ }
59
+ const issue = checkTemplate(parts.cooked, svg);
60
+ if (issue === undefined)
61
+ return;
62
+ const span = errorSpan(parts.quasis, parts.cooked, issue.strings, issue.at, issue.from);
63
+ const { sourceCode } = context;
64
+ context.report({
65
+ loc: {
66
+ start: sourceCode.getLocFromIndex(span.start),
67
+ end: sourceCode.getLocFromIndex(Math.max(span.end, span.start)),
68
+ },
69
+ messageId: 'rule',
70
+ data: { message: messageOf(issue.error) },
71
+ });
72
+ },
73
+ };
74
+ },
75
+ };
76
+ //# sourceMappingURL=template-rule.js.map
@@ -0,0 +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// (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;
@@ -0,0 +1,186 @@
1
+ import { findVariable, importedAs, isGyral, OPTIONS_SCHEMA, } from './imports.js';
2
+ /**
3
+ * A static `data-intent` or `data-intent-<event>` value in template text (not `data-intent-on`,
4
+ * whose value is events).
5
+ */
6
+ const STATIC_INTENT = /\sdata-intent(?:-(?!on=)[\w-]+)?=["']?([^"'\s>]+)/g;
7
+ /** Template text that ends where a `data-intent` or `data-intent-<event>` hole starts. */
8
+ const INTENT_HOLE = /\sdata-intent(?:-(?!on=)[\w-]+)?=["']?$/;
9
+ const isFn = (node) => node?.type === 'ArrowFunctionExpression' ||
10
+ node?.type === 'FunctionExpression' ||
11
+ node?.type === 'FunctionDeclaration';
12
+ const keyName = (key) => key.type === 'Identifier'
13
+ ? key.name
14
+ : key.type === 'Literal' && typeof key.value === 'string'
15
+ ? key.value
16
+ : undefined;
17
+ /** `{ name: value }` entries of an object literal, without spreads or computed keys. */
18
+ function entries(object) {
19
+ if (object.type !== 'ObjectExpression')
20
+ return [];
21
+ return object.properties.flatMap((p) => {
22
+ if (p.type !== 'Property' || p.computed)
23
+ return [];
24
+ const name = keyName(p.key);
25
+ return name === undefined ? [] : [{ name, key: p.key, value: p.value }];
26
+ });
27
+ }
28
+ /** Whether a variable is bound in this module (not imported, not a global). */
29
+ const isLocal = (variable) => variable !== undefined && variable.defs.length > 0 && variable.defs[0]?.type !== 'ImportBinding';
30
+ /** The function a view is: inline, or a module binding to one; undefined when elsewhere. */
31
+ function viewFunction(context, view) {
32
+ if (isFn(view))
33
+ return view;
34
+ if (view.type !== 'Identifier')
35
+ return undefined;
36
+ const variable = findVariable(context.sourceCode.getScope(view), view.name);
37
+ const def = variable?.defs[0];
38
+ if (def?.type === 'FunctionName')
39
+ return def.node;
40
+ const init = def?.type === 'Variable' ? def.node.init : null;
41
+ return isFn(init) ? init : undefined;
42
+ }
43
+ /** Whether `tag` is Gyral's `html` or `svg` (an svg fragment can name intents too). */
44
+ const isTemplateTag = (context, tag) => isGyral(context, tag, 'html') || isGyral(context, tag, 'svg');
45
+ /** Whether `node` sits in a hole of a Gyral html or svg template. */
46
+ function inTemplateHole(context, node) {
47
+ for (let n = node; n !== null; n = n.parent) {
48
+ const parent = n.parent;
49
+ if (parent?.type !== 'TemplateLiteral' || parent.parent.type !== 'TaggedTemplateExpression') {
50
+ continue;
51
+ }
52
+ if (isTemplateTag(context, parent.parent.tag))
53
+ return true;
54
+ }
55
+ return false;
56
+ }
57
+ /**
58
+ * Whether a template in the module calls, or passes on, a function imported from a module that
59
+ * isn't a template source: its markup, which this rule can't see, may name intents.
60
+ */
61
+ function templatesCallImports(context, program) {
62
+ const global = context.sourceCode.getScope(program);
63
+ const module = global.childScopes.find((scope) => scope.type === 'module') ?? global;
64
+ return module.variables.some((v) => {
65
+ const def = v.defs[0];
66
+ if (def?.type !== 'ImportBinding')
67
+ return false;
68
+ if (importedAs(context, def.name) !== undefined)
69
+ return false; // core
70
+ return v.references.some((r) => {
71
+ const id = r.identifier;
72
+ return id.parent?.type === 'CallExpression' && inTemplateHole(context, id);
73
+ });
74
+ });
75
+ }
76
+ /** Whether `id`'s reference stays in the module: `id.Name`, or an argument to a local function. */
77
+ function staysLocal(context, id) {
78
+ const parent = id.parent;
79
+ if (parent === null)
80
+ return false;
81
+ if (parent.type === 'MemberExpression' && parent.object === id)
82
+ return true;
83
+ if (parent.type !== 'CallExpression' || parent.callee === id)
84
+ return false;
85
+ const callee = parent.callee;
86
+ if (callee.type !== 'Identifier')
87
+ return false;
88
+ return isLocal(findVariable(context.sourceCode.getScope(callee), callee.name));
89
+ }
90
+ /** Whether the view's intents parameter (its second) can reach code outside the module. */
91
+ function viewEscapes(context, fn) {
92
+ const param = fn.params[1];
93
+ if (param?.type !== 'Identifier')
94
+ return false; // absent, or destructured (counted as used)
95
+ const variable = context.sourceCode.getDeclaredVariables(fn).find((v) => v.name === param.name);
96
+ return (variable?.references ?? []).some((r) => !staysLocal(context, r.identifier));
97
+ }
98
+ export const unusedIntentRule = {
99
+ meta: {
100
+ type: 'suggestion',
101
+ docs: {
102
+ description: 'An intent parser that no template in the module names with data-intent: a renamed ' +
103
+ 'intent or dead code (view/09-template-rules.md "Warnings").',
104
+ recommended: true,
105
+ url: 'https://github.com/gyraljs/gyral/blob/main/docs/design-docs/view/09-template-rules.md',
106
+ },
107
+ schema: OPTIONS_SCHEMA,
108
+ messages: {
109
+ unused: 'The intent parser "{{name}}" is never named by data-intent in this module, so it never ' +
110
+ 'runs: name it in the view (data-intent=${i.{{name}}}), or remove the parser (messages ' +
111
+ 'that only come from commands need none) (view/09-template-rules.md "Warnings").',
112
+ },
113
+ },
114
+ create(context) {
115
+ const used = new Set();
116
+ const components = [];
117
+ let exportsIntents = false;
118
+ return {
119
+ MemberExpression(node) {
120
+ const name = node.computed ? keyName(node.property) : undefined;
121
+ if (!node.computed && node.property.type === 'Identifier')
122
+ used.add(node.property.name);
123
+ else if (name !== undefined)
124
+ used.add(name);
125
+ },
126
+ ObjectPattern(node) {
127
+ for (const p of node.properties) {
128
+ const name = p.type === 'Property' && !p.computed ? keyName(p.key) : undefined;
129
+ if (name !== undefined)
130
+ used.add(name);
131
+ }
132
+ },
133
+ TaggedTemplateExpression(node) {
134
+ if (!isTemplateTag(context, node.tag))
135
+ return;
136
+ const { quasis, expressions } = node.quasi;
137
+ quasis.forEach((q, k) => {
138
+ const text = q.value.cooked ?? '';
139
+ for (const m of text.matchAll(STATIC_INTENT))
140
+ used.add(m[1] ?? '');
141
+ const value = expressions[k];
142
+ if (INTENT_HOLE.test(text) && value?.type === 'Literal')
143
+ used.add(String(value.value));
144
+ });
145
+ },
146
+ CallExpression(node) {
147
+ const callee = node.callee;
148
+ if (isGyral(context, callee, 'intentsOf')) {
149
+ // `export const i = intentsOf<typeof C>()`: other modules may name the intents.
150
+ const declaration = node.parent.parent?.parent;
151
+ if (declaration?.type === 'ExportNamedDeclaration')
152
+ exportsIntents = true;
153
+ return;
154
+ }
155
+ // `define<S, M>()(tag, spec)`: the spec is the second argument of the second call.
156
+ if (callee.type !== 'CallExpression' ||
157
+ !isGyral(context, callee.callee, 'define')) {
158
+ return;
159
+ }
160
+ const spec = node.arguments[1];
161
+ const fields = spec === undefined ? [] : entries(spec);
162
+ const intent = fields.find((f) => f.name === 'intent')?.value;
163
+ const view = fields.find((f) => f.name === 'view')?.value;
164
+ if (intent === undefined)
165
+ return;
166
+ const parsers = entries(intent).map((e) => ({ name: e.name, node: e.key }));
167
+ components.push({ parsers, view: view && viewFunction(context, view) });
168
+ },
169
+ 'Program:exit'(program) {
170
+ if (exportsIntents || components.length === 0)
171
+ return;
172
+ if (templatesCallImports(context, program))
173
+ return;
174
+ for (const { parsers, view } of components) {
175
+ if (view === undefined || viewEscapes(context, view))
176
+ continue;
177
+ for (const { name, node } of parsers) {
178
+ if (!used.has(name))
179
+ context.report({ node, messageId: 'unused', data: { name } });
180
+ }
181
+ }
182
+ },
183
+ };
184
+ },
185
+ };
186
+ //# sourceMappingURL=unused-intent-rule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unused-intent-rule.js","sourceRoot":"","sources":["../../src/eslint/unused-intent-rule.ts"],"names":[],"mappings":"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","sourcesContent":["// gyral/unused-intent: the \"unused intent parser\" warning of view/09-template-rules.md. A parser\n// in `define<S, M>()(tag, { intent: { Name: … } })` runs only when an element names it with\n// `data-intent`, so a parser no template in the module names is a renamed intent, dead code, or\n// (since intent names are inferred from these keys, ADR 0023) a misspelled key.\n// Static, over the whole module, so intents rendered conditionally (a dialog's buttons, an\n// error state) count as used; that is why the warning lives here and not in the runtime, which\n// sees only the templates rendered so far. A name counts as used when the module mentions it as\n// a property (`i.Name`, `{ Name } = i`, `i['Name']`) or as a static or literal `data-intent` or\n// `data-intent-<event>` value in an html or svg template. A component is skipped when its intent\n// names may be used elsewhere: its view is not in the module (an imported function), the view\n// hands its intents to an imported function, the module exports an `intentsOf()` constant, or a\n// template in the module calls (or passes on) a function imported from another module, which\n// may render `data-intent=\"Name\"` itself (a shared table header, a row module).\nimport type { Rule, Scope } from 'eslint';\nimport {\n findVariable,\n importedAs,\n isGyral,\n OPTIONS_SCHEMA,\n type Node,\n type NodeOf,\n} from './imports.js';\n\n/**\n * A static `data-intent` or `data-intent-<event>` value in template text (not `data-intent-on`,\n * whose value is events).\n */\nconst STATIC_INTENT = /\\sdata-intent(?:-(?!on=)[\\w-]+)?=[\"']?([^\"'\\s>]+)/g;\n/** Template text that ends where a `data-intent` or `data-intent-<event>` hole starts. */\nconst INTENT_HOLE = /\\sdata-intent(?:-(?!on=)[\\w-]+)?=[\"']?$/;\n\ninterface Component {\n readonly parsers: readonly { readonly name: string; readonly node: Node }[];\n readonly view: Fn | undefined;\n}\n\ntype Fn =\n NodeOf<'ArrowFunctionExpression'> | NodeOf<'FunctionExpression'> | NodeOf<'FunctionDeclaration'>;\n\nconst isFn = (node: Node | null | undefined): node is Fn =>\n node?.type === 'ArrowFunctionExpression' ||\n node?.type === 'FunctionExpression' ||\n node?.type === 'FunctionDeclaration';\n\nconst keyName = (key: Node): string | undefined =>\n key.type === 'Identifier'\n ? key.name\n : key.type === 'Literal' && typeof key.value === 'string'\n ? key.value\n : undefined;\n\n/** `{ name: value }` entries of an object literal, without spreads or computed keys. */\nfunction entries(object: Node): { name: string; key: Node; value: Node }[] {\n if (object.type !== 'ObjectExpression') return [];\n return object.properties.flatMap((p) => {\n if (p.type !== 'Property' || p.computed) return [];\n const name = keyName(p.key as Node);\n return name === undefined ? [] : [{ name, key: p.key as Node, value: p.value as Node }];\n });\n}\n\n/** Whether a variable is bound in this module (not imported, not a global). */\nconst isLocal = (variable: Scope.Variable | undefined): boolean =>\n variable !== undefined && variable.defs.length > 0 && variable.defs[0]?.type !== 'ImportBinding';\n\n/** The function a view is: inline, or a module binding to one; undefined when elsewhere. */\nfunction viewFunction(context: Rule.RuleContext, view: Node): Fn | undefined {\n if (isFn(view)) return view;\n if (view.type !== 'Identifier') return undefined;\n const variable = findVariable(context.sourceCode.getScope(view), view.name);\n const def = variable?.defs[0];\n if (def?.type === 'FunctionName') return def.node as Fn;\n const init = def?.type === 'Variable' ? (def.node.init as Node | null) : null;\n return isFn(init) ? init : undefined;\n}\n\n/** Whether `tag` is Gyral's `html` or `svg` (an svg fragment can name intents too). */\nconst isTemplateTag = (context: Rule.RuleContext, tag: Node): boolean =>\n isGyral(context, tag, 'html') || isGyral(context, tag, 'svg');\n\n/** Whether `node` sits in a hole of a Gyral html or svg template. */\nfunction inTemplateHole(context: Rule.RuleContext, node: Node): boolean {\n for (let n: Node | null = node; n !== null; n = n.parent) {\n const parent = n.parent;\n if (parent?.type !== 'TemplateLiteral' || parent.parent.type !== 'TaggedTemplateExpression') {\n continue;\n }\n if (isTemplateTag(context, parent.parent.tag as Node)) return true;\n }\n return false;\n}\n\n/**\n * Whether a template in the module calls, or passes on, a function imported from a module that\n * isn't a template source: its markup, which this rule can't see, may name intents.\n */\nfunction templatesCallImports(context: Rule.RuleContext, program: Node): boolean {\n const global = context.sourceCode.getScope(program);\n const module = global.childScopes.find((scope) => scope.type === 'module') ?? global;\n return module.variables.some((v) => {\n const def = v.defs[0];\n if (def?.type !== 'ImportBinding') return false;\n if (importedAs(context, def.name as NodeOf<'Identifier'>) !== undefined) return false; // core\n return v.references.some((r) => {\n const id = r.identifier as Node;\n return id.parent?.type === 'CallExpression' && inTemplateHole(context, id);\n });\n });\n}\n\n/** Whether `id`'s reference stays in the module: `id.Name`, or an argument to a local function. */\nfunction staysLocal(context: Rule.RuleContext, id: Node): boolean {\n const parent = id.parent;\n if (parent === null) return false;\n if (parent.type === 'MemberExpression' && parent.object === id) return true;\n if (parent.type !== 'CallExpression' || parent.callee === id) return false;\n const callee = parent.callee as Node;\n if (callee.type !== 'Identifier') return false;\n return isLocal(findVariable(context.sourceCode.getScope(callee), callee.name));\n}\n\n/** Whether the view's intents parameter (its second) can reach code outside the module. */\nfunction viewEscapes(context: Rule.RuleContext, fn: Fn): boolean {\n const param = fn.params[1] as Node | undefined;\n if (param?.type !== 'Identifier') return false; // absent, or destructured (counted as used)\n const variable = context.sourceCode.getDeclaredVariables(fn).find((v) => v.name === param.name);\n return (variable?.references ?? []).some((r) => !staysLocal(context, r.identifier as Node));\n}\n\nexport const unusedIntentRule: Rule.RuleModule = {\n meta: {\n type: 'suggestion',\n docs: {\n description:\n 'An intent parser that no template in the module names with data-intent: a renamed ' +\n 'intent or dead code (view/09-template-rules.md \"Warnings\").',\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: {\n unused:\n 'The intent parser \"{{name}}\" is never named by data-intent in this module, so it never ' +\n 'runs: name it in the view (data-intent=${i.{{name}}}), or remove the parser (messages ' +\n 'that only come from commands need none) (view/09-template-rules.md \"Warnings\").',\n },\n },\n create(context) {\n const used = new Set<string>();\n const components: Component[] = [];\n let exportsIntents = false;\n return {\n MemberExpression(node) {\n const name = node.computed ? keyName(node.property as Node) : undefined;\n if (!node.computed && node.property.type === 'Identifier') used.add(node.property.name);\n else if (name !== undefined) used.add(name);\n },\n ObjectPattern(node) {\n for (const p of node.properties) {\n const name = p.type === 'Property' && !p.computed ? keyName(p.key as Node) : undefined;\n if (name !== undefined) used.add(name);\n }\n },\n TaggedTemplateExpression(node) {\n if (!isTemplateTag(context, node.tag as Node)) return;\n const { quasis, expressions } = node.quasi;\n quasis.forEach((q, k) => {\n const text = q.value.cooked ?? '';\n for (const m of text.matchAll(STATIC_INTENT)) used.add(m[1] ?? '');\n const value = expressions[k] as Node | undefined;\n if (INTENT_HOLE.test(text) && value?.type === 'Literal') used.add(String(value.value));\n });\n },\n CallExpression(node) {\n const callee = node.callee as Node;\n if (isGyral(context, callee, 'intentsOf')) {\n // `export const i = intentsOf<typeof C>()`: other modules may name the intents.\n const declaration = node.parent.parent?.parent;\n if (declaration?.type === 'ExportNamedDeclaration') exportsIntents = true;\n return;\n }\n // `define<S, M>()(tag, spec)`: the spec is the second argument of the second call.\n if (\n callee.type !== 'CallExpression' ||\n !isGyral(context, callee.callee as Node, 'define')\n ) {\n return;\n }\n const spec = node.arguments[1] as Node | undefined;\n const fields = spec === undefined ? [] : entries(spec);\n const intent = fields.find((f) => f.name === 'intent')?.value;\n const view = fields.find((f) => f.name === 'view')?.value;\n if (intent === undefined) return;\n const parsers = entries(intent).map((e) => ({ name: e.name, node: e.key }));\n components.push({ parsers, view: view && viewFunction(context, view) });\n },\n 'Program:exit'(program) {\n if (exportsIntents || components.length === 0) return;\n if (templatesCallImports(context, program as Node)) return;\n for (const { parsers, view } of components) {\n if (view === undefined || viewEscapes(context, view)) continue;\n for (const { name, node } of parsers) {\n if (!used.has(name)) context.report({ node, messageId: 'unused', data: { name } });\n }\n }\n },\n };\n },\n};\n"]}
@@ -0,0 +1,39 @@
1
+ import type { DriverOverrides } from './command.js';
2
+ import type { CommandFailure, Interpreter } from './internal/interpreter.js';
3
+ import type { PropFeature } from './props.js';
4
+ import type { AnyStore, StoreOverrides, StoreRef, StoreSendInput } from './store.js';
5
+ import type { CommandTrace } from './devtools-events.js';
6
+ import type { IntentRejected, Tagged } from './types.js';
7
+ /** A host's element, as features see it. */
8
+ export type FeatureHost = HTMLElement & {
9
+ drivers: DriverOverrides;
10
+ stores: StoreOverrides;
11
+ };
12
+ /** What a component's store binding offers its model (store-binding.ts). */
13
+ export interface StoreLink {
14
+ read<S>(ref: StoreRef<S>): S;
15
+ send(input: StoreSendInput): void;
16
+ connect(): boolean;
17
+ disconnect(): void;
18
+ }
19
+ /** The host a marker driver's `local` handler runs against (focus, emit, store send). */
20
+ export interface LocalHost {
21
+ readonly el: FeatureHost;
22
+ readonly tag: string;
23
+ readonly root: () => ParentNode | undefined;
24
+ readonly stores: () => StoreLink;
25
+ }
26
+ /** A marker driver core runs itself, synchronously, without the interpreter. */
27
+ export interface LocalDriver {
28
+ readonly local: (host: LocalHost, input: unknown) => void;
29
+ }
30
+ type Msg = Tagged | IntentRejected;
31
+ export declare const features: {
32
+ /** Set by `command()`: a host's command interpreter, resolving drivers by name (ADR 0006). */
33
+ commands?: (el: FeatureHost, dispatch: (msg: Msg) => void, trace: CommandTrace | undefined, failed: CommandFailure) => Interpreter<Msg>;
34
+ /** Set by `defineStore()`: binds a host to the stores it declares (ADR 0013). */
35
+ stores?: (el: FeatureHost, tag: string, declared: readonly AnyStore[], onChange: (store: AnyStore, state: unknown, prev: unknown) => void) => StoreLink;
36
+ /** Set by the prop builders: attribute parsing and validation (view/05 "Props"). */
37
+ props?: PropFeature;
38
+ };
39
+ export {};
@@ -0,0 +1,2 @@
1
+ export const features = {};
2
+ //# sourceMappingURL=features.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"features.js","sourceRoot":"","sources":["../src/features.ts"],"names":[],"mappings":"AAsCA,MAAM,CAAC,MAAM,QAAQ,GAiBjB,EAAE,CAAC","sourcesContent":["// Features that register themselves when their API is used (ADR 0018 \"Size\", gyral-g1r.18).\n// Core reaches them only through these slots, which the feature's own API fills when called:\n// `command()` the interpreter, `defineStore()` the store binding, a prop builder the prop\n// machinery. An app that never calls one doesn't bundle what it registers. No module does this\n// at load time: bundlers keep `sideEffects: false` and tree-shake as usual.\nimport type { DriverOverrides } from './command.js';\nimport type { CommandFailure, Interpreter } from './internal/interpreter.js';\nimport type { PropFeature } from './props.js';\nimport type { AnyStore, StoreOverrides, StoreRef, StoreSendInput } from './store.js';\nimport type { CommandTrace } from './devtools-events.js';\nimport type { IntentRejected, Tagged } from './types.js';\n\n/** A host's element, as features see it. */\nexport type FeatureHost = HTMLElement & { drivers: DriverOverrides; stores: StoreOverrides };\n\n/** What a component's store binding offers its model (store-binding.ts). */\nexport interface StoreLink {\n read<S>(ref: StoreRef<S>): S;\n send(input: StoreSendInput): void;\n connect(): boolean;\n disconnect(): void;\n}\n\n/** The host a marker driver's `local` handler runs against (focus, emit, store send). */\nexport interface LocalHost {\n readonly el: FeatureHost;\n readonly tag: string;\n readonly root: () => ParentNode | undefined;\n readonly stores: () => StoreLink;\n}\n\n/** A marker driver core runs itself, synchronously, without the interpreter. */\nexport interface LocalDriver {\n readonly local: (host: LocalHost, input: unknown) => void;\n}\n\ntype Msg = Tagged | IntentRejected;\n\nexport const features: {\n /** Set by `command()`: a host's command interpreter, resolving drivers by name (ADR 0006). */\n commands?: (\n el: FeatureHost,\n dispatch: (msg: Msg) => void,\n trace: CommandTrace | undefined,\n failed: CommandFailure,\n ) => Interpreter<Msg>;\n /** Set by `defineStore()`: binds a host to the stores it declares (ADR 0013). */\n stores?: (\n el: FeatureHost,\n tag: string,\n declared: readonly AnyStore[],\n onChange: (store: AnyStore, state: unknown, prev: unknown) => void,\n ) => StoreLink;\n /** Set by the prop builders: attribute parsing and validation (view/05 \"Props\"). */\n props?: PropFeature;\n} = {};\n"]}
package/dist/focus.d.ts CHANGED
@@ -1,14 +1,22 @@
1
1
  import type { Command } from './command.js';
2
- /** Marker driver: `define()` handles focus commands itself. */
2
+ import type { LocalHost } from './features.js';
3
+ /** Marker driver: the host runs focus commands itself (`local`). */
3
4
  export declare const FOCUS: {
4
5
  readonly name: "@gyral/focus";
5
6
  readonly run: () => undefined;
7
+ readonly local: (host: LocalHost, input: unknown) => void;
6
8
  };
7
9
  export interface FocusOptions {
8
10
  /** Don't scroll the element into view (default `false`: the browser scrolls if needed). */
9
11
  readonly preventScroll?: boolean;
10
12
  /** Also select the text of an input or textarea. */
11
13
  readonly select?: boolean;
14
+ /**
15
+ * If nothing matches after this render, keep the request and focus the target as soon as a
16
+ * later render of this component produces it; a newer `focus()` from the component replaces
17
+ * it, and after one second it gives up with the usual warning. `settled()` doesn't wait for it.
18
+ */
19
+ readonly wait?: boolean;
12
20
  }
13
21
  /** The input of a `focus()` command. */
14
22
  export interface FocusInput extends FocusOptions {
@@ -23,17 +31,10 @@ export interface FocusInput extends FocusOptions {
23
31
  * Non-focusable targets (a heading) need `tabindex="-1"` in the view.
24
32
  */
25
33
  export declare function focus(selector: string, options?: FocusOptions): Command<never>;
26
- /** Runs a focus command against `root` (called by define() after the update completes). */
34
+ /** Runs a focus command against `root` (the scheduler calls it after the render). */
27
35
  export declare function runFocus(root: ParentNode, tag: string, input: FocusInput): void;
28
- /** What focusAfterUpdate needs from a component: Lit's update promise and its render root. */
29
- export interface FocusHost {
30
- readonly updateComplete: Promise<boolean>;
31
- readonly isConnected: boolean;
32
- readonly renderRoot: ParentNode;
33
- }
34
36
  /**
35
- * Runs a focus command after the render the same update caused, view transition included:
36
- * define() runs commands before #dispatch registers that update's view transition, so wait a
37
- * microtask first, then for updateComplete, which waits for the transition (gyral-6zz).
37
+ * Runs a focus command after the flush that renders the same update, view transition
38
+ * included: it is post-render work, so the DOM already shows the new state.
38
39
  */
39
- export declare function focusAfterUpdate(host: FocusHost, tag: string, input: FocusInput): void;
40
+ export declare function queueFocus(host: Element, root: () => ParentNode | undefined, tag: string, input: FocusInput): void;