@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
@@ -2,6 +2,8 @@
2
2
  // included), for the template compiler's scanner (scan.ts): generic child iteration, the
3
3
  // names a binding pattern declares, and the names each scope declares, so a local variable
4
4
  // that shadows the imported `html` is never mistaken for it.
5
+ /** The `lang` to parse a module with, from its id (`this.parse(code, { lang })`). */
6
+ export const langOf = (id) => /\.[cm]?tsx$/.test(id) ? 'tsx' : /\.[cm]?ts$/.test(id) ? 'ts' : id.endsWith('x') ? 'jsx' : 'js';
5
7
  export const isNode = (value) => typeof value === 'object' &&
6
8
  value !== null &&
7
9
  typeof value.type === 'string';
@@ -32,9 +34,11 @@ const TS_VALUE = new Set([
32
34
  'TSInstantiationExpression',
33
35
  'TSExportAssignment',
34
36
  ]);
37
+ /** TS declarations whose members are runtime values (`enum E { A = 'a' }`). */
38
+ const TS_RUNTIME = new Set(['TSEnumDeclaration', 'TSEnumBody', 'TSEnumMember']);
35
39
  /** The child nodes of `node` that can contain runtime code, in source order. */
36
40
  export function children(node) {
37
- if (node.type.startsWith('TS')) {
41
+ if (node.type.startsWith('TS') && !TS_RUNTIME.has(node.type)) {
38
42
  if (TS_VALUE.has(node.type))
39
43
  return nodesAt(node, 'expression');
40
44
  if (node.type === 'TSParameterProperty')
@@ -1 +1 @@
1
- {"version":3,"file":"ast.js","sourceRoot":"","sources":["../../src/compiler/ast.ts"],"names":[],"mappings":"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","sourcesContent":["// A minimal view of the ESTree AST that Rolldown's `this.parse` returns (oxc, TypeScript\n// included), for the template compiler's scanner (scan.ts): generic child iteration, the\n// names a binding pattern declares, and the names each scope declares, so a local variable\n// that shadows the imported `html` is never mistaken for it.\n\n/** An ESTree node: `start`/`end` are UTF-16 offsets into the module's code. */\nexport interface Node {\n readonly type: string;\n readonly start: number;\n readonly end: number;\n readonly [key: string]: unknown;\n}\n\nexport const isNode = (value: unknown): value is Node =>\n typeof value === 'object' &&\n value !== null &&\n typeof (value as { type?: unknown }).type === 'string';\n\nexport const nodeAt = (node: Node, key: string): Node | undefined => {\n const value = node[key];\n return isNode(value) ? value : undefined;\n};\n\n/** The node or nodes at `key` (an array, or a single node). */\nexport const nodesAt = (node: Node, key: string): Node[] => {\n const value = node[key];\n return Array.isArray(value) ? value.filter(isNode) : isNode(value) ? [value] : [];\n};\n\n/** TypeScript-only keys: type annotations never reference a value. */\nconst TYPE_KEYS = new Set([\n 'typeAnnotation',\n 'typeArguments',\n 'typeParameters',\n 'returnType',\n 'superTypeArguments',\n 'implements',\n]);\n\n/** TS nodes that wrap a runtime expression; every other `TS*` node is type-only. */\nconst TS_VALUE = new Set([\n 'TSAsExpression',\n 'TSSatisfiesExpression',\n 'TSNonNullExpression',\n 'TSTypeAssertion',\n 'TSInstantiationExpression',\n 'TSExportAssignment',\n]);\n\n/** The child nodes of `node` that can contain runtime code, in source order. */\nexport function children(node: Node): Node[] {\n if (node.type.startsWith('TS')) {\n if (TS_VALUE.has(node.type)) return nodesAt(node, 'expression');\n if (node.type === 'TSParameterProperty') return nodesAt(node, 'parameter');\n if (node.type === 'TSModuleDeclaration') return nodesAt(node, 'body');\n if (node.type === 'TSModuleBlock') return nodesAt(node, 'body');\n return [];\n }\n const out: Node[] = [];\n for (const key in node) {\n if (key === 'type' || key === 'start' || key === 'end' || TYPE_KEYS.has(key)) continue;\n const value = node[key];\n if (Array.isArray(value)) out.push(...value.filter(isNode));\n else if (isNode(value)) out.push(value);\n }\n return out.sort((a, b) => a.start - b.start);\n}\n\n/** The names a binding pattern declares (`a`, `{ a, b: [c] }`, `...d`, `e = 1`). */\nexport function patternNames(pattern: Node | undefined): string[] {\n if (pattern === undefined) return [];\n switch (pattern.type) {\n case 'Identifier':\n return [pattern['name'] as string];\n case 'ObjectPattern':\n return nodesAt(pattern, 'properties').flatMap((p) =>\n p.type === 'RestElement'\n ? patternNames(nodeAt(p, 'argument'))\n : patternNames(nodeAt(p, 'value')),\n );\n case 'ArrayPattern':\n return nodesAt(pattern, 'elements').flatMap(patternNames);\n case 'RestElement':\n return patternNames(nodeAt(pattern, 'argument'));\n case 'AssignmentPattern':\n return patternNames(nodeAt(pattern, 'left'));\n case 'TSParameterProperty':\n return patternNames(nodeAt(pattern, 'parameter'));\n default:\n return [];\n }\n}\n\nconst FUNCTIONS = new Set(['FunctionDeclaration', 'FunctionExpression', 'ArrowFunctionExpression']);\n\nexport const isFunction = (node: Node): boolean => FUNCTIONS.has(node.type);\n\n/** `var` names declared anywhere in a function body (hoisted), not crossing nested functions. */\nfunction varNames(node: Node, out: string[]): void {\n if (node.type === 'VariableDeclaration' && node['kind'] === 'var') {\n for (const d of nodesAt(node, 'declarations')) out.push(...patternNames(nodeAt(d, 'id')));\n }\n for (const child of children(node)) if (!isFunction(child)) varNames(child, out);\n}\n\n/** Block-scoped names declared directly in a list of statements. */\nfunction lexicalNames(statements: readonly Node[]): string[] {\n return statements.flatMap((s) => {\n if (s.type === 'VariableDeclaration' && s['kind'] !== 'var') {\n return nodesAt(s, 'declarations').flatMap((d) => patternNames(nodeAt(d, 'id')));\n }\n if (s.type === 'FunctionDeclaration' || s.type === 'ClassDeclaration') {\n return patternNames(nodeAt(s, 'id'));\n }\n return [];\n });\n}\n\n/**\n * The names `node` declares for its own scope, or undefined when it opens no scope. The\n * Program scope is left out: the imported binding lives there.\n */\nexport function scopeNames(node: Node): string[] | undefined {\n switch (node.type) {\n case 'FunctionDeclaration':\n case 'FunctionExpression':\n case 'ArrowFunctionExpression': {\n const names = nodesAt(node, 'params').flatMap(patternNames);\n if (node.type === 'FunctionExpression') names.push(...patternNames(nodeAt(node, 'id')));\n const body = nodeAt(node, 'body');\n if (body?.type === 'BlockStatement') {\n varNames(body, names);\n names.push(...lexicalNames(nodesAt(body, 'body')));\n }\n return names;\n }\n case 'BlockStatement':\n case 'StaticBlock':\n return lexicalNames(nodesAt(node, 'body'));\n case 'SwitchStatement':\n return lexicalNames(nodesAt(node, 'cases').flatMap((c) => nodesAt(c, 'consequent')));\n case 'ForStatement':\n case 'ForInStatement':\n case 'ForOfStatement': {\n const head = nodeAt(node, node.type === 'ForStatement' ? 'init' : 'left');\n return head === undefined ? [] : lexicalNames([head]);\n }\n case 'CatchClause':\n return patternNames(nodeAt(node, 'param'));\n case 'ClassExpression':\n return patternNames(nodeAt(node, 'id'));\n default:\n return undefined;\n }\n}\n"]}
1
+ {"version":3,"file":"ast.js","sourceRoot":"","sources":["../../src/compiler/ast.ts"],"names":[],"mappings":"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","sourcesContent":["// A minimal view of the ESTree AST that Rolldown's `this.parse` returns (oxc, TypeScript\n// included), for the template compiler's scanner (scan.ts): generic child iteration, the\n// names a binding pattern declares, and the names each scope declares, so a local variable\n// that shadows the imported `html` is never mistaken for it.\n\n/** The `lang` to parse a module with, from its id (`this.parse(code, { lang })`). */\nexport const langOf = (id: string): 'js' | 'jsx' | 'ts' | 'tsx' =>\n /\\.[cm]?tsx$/.test(id) ? 'tsx' : /\\.[cm]?ts$/.test(id) ? 'ts' : id.endsWith('x') ? 'jsx' : 'js';\n\n/** An ESTree node: `start`/`end` are UTF-16 offsets into the module's code. */\nexport interface Node {\n readonly type: string;\n readonly start: number;\n readonly end: number;\n readonly [key: string]: unknown;\n}\n\nexport const isNode = (value: unknown): value is Node =>\n typeof value === 'object' &&\n value !== null &&\n typeof (value as { type?: unknown }).type === 'string';\n\nexport const nodeAt = (node: Node, key: string): Node | undefined => {\n const value = node[key];\n return isNode(value) ? value : undefined;\n};\n\n/** The node or nodes at `key` (an array, or a single node). */\nexport const nodesAt = (node: Node, key: string): Node[] => {\n const value = node[key];\n return Array.isArray(value) ? value.filter(isNode) : isNode(value) ? [value] : [];\n};\n\n/** TypeScript-only keys: type annotations never reference a value. */\nconst TYPE_KEYS = new Set([\n 'typeAnnotation',\n 'typeArguments',\n 'typeParameters',\n 'returnType',\n 'superTypeArguments',\n 'implements',\n]);\n\n/** TS nodes that wrap a runtime expression; every other `TS*` node is type-only. */\nconst TS_VALUE = new Set([\n 'TSAsExpression',\n 'TSSatisfiesExpression',\n 'TSNonNullExpression',\n 'TSTypeAssertion',\n 'TSInstantiationExpression',\n 'TSExportAssignment',\n]);\n\n/** TS declarations whose members are runtime values (`enum E { A = 'a' }`). */\nconst TS_RUNTIME = new Set(['TSEnumDeclaration', 'TSEnumBody', 'TSEnumMember']);\n\n/** The child nodes of `node` that can contain runtime code, in source order. */\nexport function children(node: Node): Node[] {\n if (node.type.startsWith('TS') && !TS_RUNTIME.has(node.type)) {\n if (TS_VALUE.has(node.type)) return nodesAt(node, 'expression');\n if (node.type === 'TSParameterProperty') return nodesAt(node, 'parameter');\n if (node.type === 'TSModuleDeclaration') return nodesAt(node, 'body');\n if (node.type === 'TSModuleBlock') return nodesAt(node, 'body');\n return [];\n }\n const out: Node[] = [];\n for (const key in node) {\n if (key === 'type' || key === 'start' || key === 'end' || TYPE_KEYS.has(key)) continue;\n const value = node[key];\n if (Array.isArray(value)) out.push(...value.filter(isNode));\n else if (isNode(value)) out.push(value);\n }\n return out.sort((a, b) => a.start - b.start);\n}\n\n/** The names a binding pattern declares (`a`, `{ a, b: [c] }`, `...d`, `e = 1`). */\nexport function patternNames(pattern: Node | undefined): string[] {\n if (pattern === undefined) return [];\n switch (pattern.type) {\n case 'Identifier':\n return [pattern['name'] as string];\n case 'ObjectPattern':\n return nodesAt(pattern, 'properties').flatMap((p) =>\n p.type === 'RestElement'\n ? patternNames(nodeAt(p, 'argument'))\n : patternNames(nodeAt(p, 'value')),\n );\n case 'ArrayPattern':\n return nodesAt(pattern, 'elements').flatMap(patternNames);\n case 'RestElement':\n return patternNames(nodeAt(pattern, 'argument'));\n case 'AssignmentPattern':\n return patternNames(nodeAt(pattern, 'left'));\n case 'TSParameterProperty':\n return patternNames(nodeAt(pattern, 'parameter'));\n default:\n return [];\n }\n}\n\nconst FUNCTIONS = new Set(['FunctionDeclaration', 'FunctionExpression', 'ArrowFunctionExpression']);\n\nexport const isFunction = (node: Node): boolean => FUNCTIONS.has(node.type);\n\n/** `var` names declared anywhere in a function body (hoisted), not crossing nested functions. */\nfunction varNames(node: Node, out: string[]): void {\n if (node.type === 'VariableDeclaration' && node['kind'] === 'var') {\n for (const d of nodesAt(node, 'declarations')) out.push(...patternNames(nodeAt(d, 'id')));\n }\n for (const child of children(node)) if (!isFunction(child)) varNames(child, out);\n}\n\n/** Block-scoped names declared directly in a list of statements. */\nfunction lexicalNames(statements: readonly Node[]): string[] {\n return statements.flatMap((s) => {\n if (s.type === 'VariableDeclaration' && s['kind'] !== 'var') {\n return nodesAt(s, 'declarations').flatMap((d) => patternNames(nodeAt(d, 'id')));\n }\n if (s.type === 'FunctionDeclaration' || s.type === 'ClassDeclaration') {\n return patternNames(nodeAt(s, 'id'));\n }\n return [];\n });\n}\n\n/**\n * The names `node` declares for its own scope, or undefined when it opens no scope. The\n * Program scope is left out: the imported binding lives there.\n */\nexport function scopeNames(node: Node): string[] | undefined {\n switch (node.type) {\n case 'FunctionDeclaration':\n case 'FunctionExpression':\n case 'ArrowFunctionExpression': {\n const names = nodesAt(node, 'params').flatMap(patternNames);\n if (node.type === 'FunctionExpression') names.push(...patternNames(nodeAt(node, 'id')));\n const body = nodeAt(node, 'body');\n if (body?.type === 'BlockStatement') {\n varNames(body, names);\n names.push(...lexicalNames(nodesAt(body, 'body')));\n }\n return names;\n }\n case 'BlockStatement':\n case 'StaticBlock':\n return lexicalNames(nodesAt(node, 'body'));\n case 'SwitchStatement':\n return lexicalNames(nodesAt(node, 'cases').flatMap((c) => nodesAt(c, 'consequent')));\n case 'ForStatement':\n case 'ForInStatement':\n case 'ForOfStatement': {\n const head = nodeAt(node, node.type === 'ForStatement' ? 'init' : 'left');\n return head === undefined ? [] : lexicalNames([head]);\n }\n case 'CatchClause':\n return patternNames(nodeAt(node, 'param'));\n case 'ClassExpression':\n return patternNames(nodeAt(node, 'id'));\n default:\n return undefined;\n }\n}\n"]}
@@ -1,7 +1,7 @@
1
1
  import type { Node } from './ast.js';
2
2
  import { type Parse5 } from './parse5-check.js';
3
- import type { HtmlImport } from './scan.js';
4
- import { type Lines, type SourceMap } from './source.js';
3
+ import type { HtmlImport, Tag } from './scan.js';
4
+ import { type Edit, type Lines, type SourceMap } from './source.js';
5
5
  /** A build error at `start`–`end` of the module (the plugin adds the code frame). */
6
6
  export declare class CompileError extends Error {
7
7
  readonly start: number;
@@ -16,6 +16,7 @@ export interface CompileInput {
16
16
  readonly sites: readonly {
17
17
  readonly node: Node;
18
18
  readonly binding: HtmlImport;
19
+ readonly tag: Tag;
19
20
  }[];
20
21
  /** Server build: keep the server segments. */
21
22
  readonly ssr: boolean;
@@ -25,6 +26,8 @@ export interface CompileInput {
25
26
  */
26
27
  readonly ids: boolean;
27
28
  readonly parse5: Parse5 | undefined;
29
+ /** Other edits to apply in the same pass (prop-schemas.ts); dropped inside a call site. */
30
+ readonly extra?: readonly Edit[];
28
31
  /** Template id → normalized strings and call site, for the whole build (collisions). */
29
32
  readonly seen: Map<string, {
30
33
  readonly strings: string;
@@ -1,9 +1,10 @@
1
- // Compiles one module's `html` call sites (view/01-templates.md "Compiled"): each call site's
2
- // cooked strings go through the same normalizer as the runtime path (so ids match), parse5
3
- // double-checks rule 7, one module-level constant is hoisted per template object (without its
4
- // id in production client builds: the renderer compares those by identity), and the call
5
- // becomes `compiled(<const>, [values…])`. Line breaks inside a rewritten template are
6
- // kept, so every following line keeps its number; the source map covers columns.
1
+ // Compiles one module's `html` and `svg` call sites (view/01-templates.md "Compiled"): each
2
+ // call site's cooked strings go through the same normalizer as the runtime path (so ids match),
3
+ // parse5 double-checks rule 7, one module-level constant is hoisted per template object
4
+ // (without its id in production client builds: the renderer compares those by identity), and
5
+ // the call becomes `compiled(<const>, [values…])`, or `compiledSvg(…)` for an svg template.
6
+ // Line breaks inside a rewritten template are kept, so every following line keeps its number;
7
+ // the source map covers columns.
7
8
  import { analyze, TemplateError } from '../view/index.js';
8
9
  import { nodeAt, nodesAt } from './ast.js';
9
10
  import { checkWithParse5 } from './parse5-check.js';
@@ -27,9 +28,19 @@ export class CompileError extends Error {
27
28
  * needs no decoding.
28
29
  */
29
30
  function emitted(template, ssr, ids) {
30
- const { id, html, parts, server, segments } = template;
31
- const client = { ...(ids ? { id } : {}), html, parts, ...(server === true ? { server } : {}) };
32
- return ssr ? { ...client, segments } : client;
31
+ const { id, html, parts, server, svg, segments, staticStyles } = template;
32
+ const client = {
33
+ ...(ids ? { id } : {}),
34
+ html,
35
+ parts,
36
+ ...(server === true ? { server } : {}),
37
+ ...(svg === true ? { svg } : {}),
38
+ };
39
+ if (!ssr)
40
+ return client;
41
+ return staticStyles === undefined
42
+ ? { ...client, segments }
43
+ : { ...client, segments, staticStyles };
33
44
  }
34
45
  const newlines = (text) => '\n'.repeat(text.split('\n').length - 1);
35
46
  /** Edits turning html`a${x}b${y}c` into `callee(name, [x, y])`, keeping line breaks. */
@@ -61,11 +72,11 @@ function siteEdits(code, node, callee, name) {
61
72
  return edits;
62
73
  }
63
74
  /** The cooked strings of a tagged template (what the tag receives at runtime). */
64
- function cookedStrings(node) {
75
+ function cookedStrings(node, tag) {
65
76
  return nodesAt(nodeAt(node, 'quasi') ?? node, 'quasis').map((q) => {
66
77
  const cooked = q['value']?.cooked;
67
78
  if (typeof cooked !== 'string') {
68
- throw new CompileError(q.start, q.end, 'This html template has an invalid escape sequence, so it has no string value at ' +
79
+ throw new CompileError(q.start, q.end, `This ${tag} template has an invalid escape sequence, so it has no string value at ` +
69
80
  'runtime. Fix the escape (write \\\\ for a backslash).');
70
81
  }
71
82
  return cooked;
@@ -78,16 +89,18 @@ export function compileModule(input) {
78
89
  let prefix = '_gyral$';
79
90
  for (let n = 1; code.includes(prefix); n++)
80
91
  prefix = `_gyral${String(n)}$`;
92
+ /** `compiled from "entry"` → the import's local name, per tag function and entry. */
81
93
  const callees = new Map();
94
+ const imports = [];
82
95
  const consts = new Map();
83
96
  const decls = [];
84
97
  const edits = [];
85
- for (const { node, binding } of sites) {
98
+ for (const { node, binding, tag } of sites) {
86
99
  const { line, column } = lines.position(node.start);
87
100
  const loc = `${input.file}:${String(line)}:${String(column + 1)}`;
88
101
  let analysis;
89
102
  try {
90
- analysis = analyze(cookedStrings(node), loc);
103
+ analysis = analyze(cookedStrings(node, tag), loc, tag === 'svg');
91
104
  }
92
105
  catch (error) {
93
106
  if (error instanceof TemplateError)
@@ -113,14 +126,20 @@ export function compileModule(input) {
113
126
  decls.push(`const ${name} = ${JSON.stringify(emitted(template, input.ssr, input.ids))};`);
114
127
  }
115
128
  const entry = COMPILED_ENTRIES[binding.specifier] ?? binding.specifier;
116
- let callee = callees.get(entry);
129
+ const exported = tag === 'svg' ? 'compiledSvg' : 'compiled';
130
+ const from = `${exported} from ${JSON.stringify(entry)}`;
131
+ let callee = callees.get(from);
117
132
  if (callee === undefined) {
118
- callee = `${prefix}compiled${callees.size === 0 ? '' : String(callees.size)}`;
119
- callees.set(entry, callee);
133
+ callee = `${prefix}${exported}${callees.size === 0 ? '' : String(callees.size)}`;
134
+ callees.set(from, callee);
135
+ imports.push(`import { ${exported} as ${callee} } from ${JSON.stringify(entry)};`);
120
136
  }
121
137
  edits.push(...siteEdits(code, node, callee, name));
122
138
  }
123
- const imports = [...callees].map(([entry, local]) => `import { compiled as ${local} } from ${JSON.stringify(entry)};`);
139
+ for (const e of input.extra ?? []) {
140
+ if (!sites.some(({ node }) => e.start < node.end && e.end > node.start))
141
+ edits.push(e);
142
+ }
124
143
  // Prepended to the first line (after a hashbang), so no line moves.
125
144
  const at = code.startsWith('#!') ? code.indexOf('\n') + 1 : 0;
126
145
  edits.unshift({ start: at, end: at, text: [...imports, ...decls].join('') });
@@ -1 +1 @@
1
- {"version":3,"file":"compile.js","sourceRoot":"","sources":["../../src/compiler/compile.ts"],"names":[],"mappings":"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","sourcesContent":["// Compiles one module's `html` call sites (view/01-templates.md \"Compiled\"): each call site's\n// cooked strings go through the same normalizer as the runtime path (so ids match), parse5\n// double-checks rule 7, one module-level constant is hoisted per template object (without its\n// id in production client builds: the renderer compares those by identity), and the call\n// becomes `compiled(<const>, [values…])`. Line breaks inside a rewritten template are\n// kept, so every following line keeps its number; the source map covers columns.\nimport { analyze, TemplateError, type TemplateObject } from '../view/index.js';\nimport type { Node } from './ast.js';\nimport { nodeAt, nodesAt } from './ast.js';\nimport { checkWithParse5, type Parse5 } from './parse5-check.js';\nimport type { HtmlImport } from './scan.js';\nimport { splice, type Edit, type Lines, type SourceMap } from './source.js';\n\n/** Where a source's `compiled` lives when its `html` module isn't the one to import it from. */\nconst COMPILED_ENTRIES: Readonly<Record<string, string>> = {\n '@gyral/core': '@gyral/core/compiled',\n};\n\n/** A build error at `start`–`end` of the module (the plugin adds the code frame). */\nexport class CompileError extends Error {\n constructor(\n readonly start: number,\n readonly end: number,\n message: string,\n ) {\n super(message);\n }\n}\n\nexport interface CompileInput {\n readonly lines: Lines;\n /** Module id, and its path relative to the root (for messages). */\n readonly id: string;\n readonly file: string;\n readonly sites: readonly { readonly node: Node; readonly binding: HtmlImport }[];\n /** Server build: keep the server segments. */\n readonly ssr: boolean;\n /**\n * Keep template ids: SSR and development builds (development markers, the hydration id\n * check). A production client compares templates by identity, so its objects go without.\n */\n readonly ids: boolean;\n readonly parse5: Parse5 | undefined;\n /** Template id → normalized strings and call site, for the whole build (collisions). */\n readonly seen: Map<string, { readonly strings: string; readonly loc: string }>;\n}\n\n/**\n * The template object as emitted: no `loc` (production), no `segments` in client builds, no\n * `id` unless `ids` (01 \"Template ids\": random base-36 text that gzip can't shrink). Its fields\n * are already compact (numeric part kinds, tuples, `server` only when true; 01), so the code\n * needs no decoding.\n */\nfunction emitted(template: TemplateObject, ssr: boolean, ids: boolean): object {\n const { id, html, parts, server, segments } = template;\n const client = { ...(ids ? { id } : {}), html, parts, ...(server === true ? { server } : {}) };\n return ssr ? { ...client, segments } : client;\n}\n\nconst newlines = (text: string): string => '\\n'.repeat(text.split('\\n').length - 1);\n\n/** Edits turning html`a${x}b${y}c` into `callee(name, [x, y])`, keeping line breaks. */\nfunction siteEdits(code: string, node: Node, callee: string, name: string): Edit[] {\n const values = nodesAt(nodeAt(node, 'quasi') ?? node, 'expressions');\n const first = values[0];\n const last = values.at(-1);\n if (first === undefined || last === undefined) {\n const nl = newlines(code.slice(node.start, node.end));\n return [{ start: node.start, end: node.end, text: `${callee}(${name}, [${nl}])` }];\n }\n const edit = (start: number, end: number, text: string): Edit => ({\n start,\n end,\n text: text + newlines(code.slice(start, end)),\n });\n const edits = [edit(node.start, first.start, `${callee}(${name}, [`)];\n for (let k = 1; k < values.length; k++) {\n const prev = values[k - 1];\n const next = values[k];\n if (prev !== undefined && next !== undefined) edits.push(edit(prev.end, next.start, ', '));\n }\n edits.push({\n start: last.end,\n end: node.end,\n text: `${newlines(code.slice(last.end, node.end))}])`,\n });\n return edits;\n}\n\n/** The cooked strings of a tagged template (what the tag receives at runtime). */\nfunction cookedStrings(node: Node): string[] {\n return nodesAt(nodeAt(node, 'quasi') ?? node, 'quasis').map((q) => {\n const cooked = (q['value'] as { cooked?: unknown } | undefined)?.cooked;\n if (typeof cooked !== 'string') {\n throw new CompileError(\n q.start,\n q.end,\n 'This html template has an invalid escape sequence, so it has no string value at ' +\n 'runtime. Fix the escape (write \\\\\\\\ for a backslash).',\n );\n }\n return cooked;\n });\n}\n\n/** Rewrites every call site in the module; nested templates inside values are included. */\nexport function compileModule(input: CompileInput): { code: string; map: SourceMap } {\n const { lines, sites, seen } = input;\n const { code } = lines;\n let prefix = '_gyral$';\n for (let n = 1; code.includes(prefix); n++) prefix = `_gyral${String(n)}$`;\n const callees = new Map<string, string>();\n const consts = new Map<string, string>();\n const decls: string[] = [];\n const edits: Edit[] = [];\n for (const { node, binding } of sites) {\n const { line, column } = lines.position(node.start);\n const loc = `${input.file}:${String(line)}:${String(column + 1)}`;\n let analysis;\n try {\n analysis = analyze(cookedStrings(node), loc);\n } catch (error) {\n if (error instanceof TemplateError)\n throw new CompileError(node.start, node.end, error.message);\n throw error;\n }\n const { template, shape } = analysis;\n const strings = JSON.stringify(analysis.strings);\n const known = seen.get(template.id);\n if (known !== undefined && known.strings !== strings) {\n throw new CompileError(\n node.start,\n node.end,\n `Two different templates share the id ${template.id} (this one and ${known.loc}), so ` +\n `server output and hydration could confuse them. Change one slightly (for example add ` +\n `a class) and report the collision (view/01-templates.md \"Template ids\").`,\n );\n }\n seen.set(template.id, { strings, loc });\n const repaired = input.parse5 && checkWithParse5(input.parse5, template, shape);\n if (repaired) throw new CompileError(node.start, node.end, repaired.message);\n let name = consts.get(template.id);\n if (name === undefined) {\n name = `${prefix}t${String(consts.size)}`;\n consts.set(template.id, name);\n decls.push(`const ${name} = ${JSON.stringify(emitted(template, input.ssr, input.ids))};`);\n }\n const entry = COMPILED_ENTRIES[binding.specifier] ?? binding.specifier;\n let callee = callees.get(entry);\n if (callee === undefined) {\n callee = `${prefix}compiled${callees.size === 0 ? '' : String(callees.size)}`;\n callees.set(entry, callee);\n }\n edits.push(...siteEdits(code, node, callee, name));\n }\n const imports = [...callees].map(\n ([entry, local]) => `import { compiled as ${local} } from ${JSON.stringify(entry)};`,\n );\n // Prepended to the first line (after a hashbang), so no line moves.\n const at = code.startsWith('#!') ? code.indexOf('\\n') + 1 : 0;\n edits.unshift({ start: at, end: at, text: [...imports, ...decls].join('') });\n return splice(lines, edits, input.id);\n}\n"]}
1
+ {"version":3,"file":"compile.js","sourceRoot":"","sources":["../../src/compiler/compile.ts"],"names":[],"mappings":"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","sourcesContent":["// Compiles one module's `html` and `svg` call sites (view/01-templates.md \"Compiled\"): each\n// call site's cooked strings go through the same normalizer as the runtime path (so ids match),\n// parse5 double-checks rule 7, one module-level constant is hoisted per template object\n// (without its id in production client builds: the renderer compares those by identity), and\n// the call becomes `compiled(<const>, [values…])`, or `compiledSvg(…)` for an svg template.\n// Line breaks inside a rewritten template are kept, so every following line keeps its number;\n// the source map covers columns.\nimport { analyze, TemplateError, type TemplateObject } from '../view/index.js';\nimport type { Node } from './ast.js';\nimport { nodeAt, nodesAt } from './ast.js';\nimport { checkWithParse5, type Parse5 } from './parse5-check.js';\nimport type { HtmlImport, Tag } from './scan.js';\nimport { splice, type Edit, type Lines, type SourceMap } from './source.js';\n\n/** Where a source's `compiled` lives when its `html` module isn't the one to import it from. */\nconst COMPILED_ENTRIES: Readonly<Record<string, string>> = {\n '@gyral/core': '@gyral/core/compiled',\n};\n\n/** A build error at `start`–`end` of the module (the plugin adds the code frame). */\nexport class CompileError extends Error {\n constructor(\n readonly start: number,\n readonly end: number,\n message: string,\n ) {\n super(message);\n }\n}\n\nexport interface CompileInput {\n readonly lines: Lines;\n /** Module id, and its path relative to the root (for messages). */\n readonly id: string;\n readonly file: string;\n readonly sites: readonly {\n readonly node: Node;\n readonly binding: HtmlImport;\n readonly tag: Tag;\n }[];\n /** Server build: keep the server segments. */\n readonly ssr: boolean;\n /**\n * Keep template ids: SSR and development builds (development markers, the hydration id\n * check). A production client compares templates by identity, so its objects go without.\n */\n readonly ids: boolean;\n readonly parse5: Parse5 | undefined;\n /** Other edits to apply in the same pass (prop-schemas.ts); dropped inside a call site. */\n readonly extra?: readonly Edit[];\n /** Template id → normalized strings and call site, for the whole build (collisions). */\n readonly seen: Map<string, { readonly strings: string; readonly loc: string }>;\n}\n\n/**\n * The template object as emitted: no `loc` (production), no `segments` in client builds, no\n * `id` unless `ids` (01 \"Template ids\": random base-36 text that gzip can't shrink). Its fields\n * are already compact (numeric part kinds, tuples, `server` only when true; 01), so the code\n * needs no decoding.\n */\nfunction emitted(template: TemplateObject, ssr: boolean, ids: boolean): object {\n const { id, html, parts, server, svg, segments, staticStyles } = template;\n const client = {\n ...(ids ? { id } : {}),\n html,\n parts,\n ...(server === true ? { server } : {}),\n ...(svg === true ? { svg } : {}),\n };\n if (!ssr) return client;\n return staticStyles === undefined\n ? { ...client, segments }\n : { ...client, segments, staticStyles };\n}\n\nconst newlines = (text: string): string => '\\n'.repeat(text.split('\\n').length - 1);\n\n/** Edits turning html`a${x}b${y}c` into `callee(name, [x, y])`, keeping line breaks. */\nfunction siteEdits(code: string, node: Node, callee: string, name: string): Edit[] {\n const values = nodesAt(nodeAt(node, 'quasi') ?? node, 'expressions');\n const first = values[0];\n const last = values.at(-1);\n if (first === undefined || last === undefined) {\n const nl = newlines(code.slice(node.start, node.end));\n return [{ start: node.start, end: node.end, text: `${callee}(${name}, [${nl}])` }];\n }\n const edit = (start: number, end: number, text: string): Edit => ({\n start,\n end,\n text: text + newlines(code.slice(start, end)),\n });\n const edits = [edit(node.start, first.start, `${callee}(${name}, [`)];\n for (let k = 1; k < values.length; k++) {\n const prev = values[k - 1];\n const next = values[k];\n if (prev !== undefined && next !== undefined) edits.push(edit(prev.end, next.start, ', '));\n }\n edits.push({\n start: last.end,\n end: node.end,\n text: `${newlines(code.slice(last.end, node.end))}])`,\n });\n return edits;\n}\n\n/** The cooked strings of a tagged template (what the tag receives at runtime). */\nfunction cookedStrings(node: Node, tag: Tag): string[] {\n return nodesAt(nodeAt(node, 'quasi') ?? node, 'quasis').map((q) => {\n const cooked = (q['value'] as { cooked?: unknown } | undefined)?.cooked;\n if (typeof cooked !== 'string') {\n throw new CompileError(\n q.start,\n q.end,\n `This ${tag} template has an invalid escape sequence, so it has no string value at ` +\n 'runtime. Fix the escape (write \\\\\\\\ for a backslash).',\n );\n }\n return cooked;\n });\n}\n\n/** Rewrites every call site in the module; nested templates inside values are included. */\nexport function compileModule(input: CompileInput): { code: string; map: SourceMap } {\n const { lines, sites, seen } = input;\n const { code } = lines;\n let prefix = '_gyral$';\n for (let n = 1; code.includes(prefix); n++) prefix = `_gyral${String(n)}$`;\n /** `compiled from \"entry\"` → the import's local name, per tag function and entry. */\n const callees = new Map<string, string>();\n const imports: string[] = [];\n const consts = new Map<string, string>();\n const decls: string[] = [];\n const edits: Edit[] = [];\n for (const { node, binding, tag } of sites) {\n const { line, column } = lines.position(node.start);\n const loc = `${input.file}:${String(line)}:${String(column + 1)}`;\n let analysis;\n try {\n analysis = analyze(cookedStrings(node, tag), loc, tag === 'svg');\n } catch (error) {\n if (error instanceof TemplateError)\n throw new CompileError(node.start, node.end, error.message);\n throw error;\n }\n const { template, shape } = analysis;\n const strings = JSON.stringify(analysis.strings);\n const known = seen.get(template.id);\n if (known !== undefined && known.strings !== strings) {\n throw new CompileError(\n node.start,\n node.end,\n `Two different templates share the id ${template.id} (this one and ${known.loc}), so ` +\n `server output and hydration could confuse them. Change one slightly (for example add ` +\n `a class) and report the collision (view/01-templates.md \"Template ids\").`,\n );\n }\n seen.set(template.id, { strings, loc });\n const repaired = input.parse5 && checkWithParse5(input.parse5, template, shape);\n if (repaired) throw new CompileError(node.start, node.end, repaired.message);\n let name = consts.get(template.id);\n if (name === undefined) {\n name = `${prefix}t${String(consts.size)}`;\n consts.set(template.id, name);\n decls.push(`const ${name} = ${JSON.stringify(emitted(template, input.ssr, input.ids))};`);\n }\n const entry = COMPILED_ENTRIES[binding.specifier] ?? binding.specifier;\n const exported = tag === 'svg' ? 'compiledSvg' : 'compiled';\n const from = `${exported} from ${JSON.stringify(entry)}`;\n let callee = callees.get(from);\n if (callee === undefined) {\n callee = `${prefix}${exported}${callees.size === 0 ? '' : String(callees.size)}`;\n callees.set(from, callee);\n imports.push(`import { ${exported} as ${callee} } from ${JSON.stringify(entry)};`);\n }\n edits.push(...siteEdits(code, node, callee, name));\n }\n for (const e of input.extra ?? []) {\n if (!sites.some(({ node }) => e.start < node.end && e.end > node.start)) edits.push(e);\n }\n // Prepended to the first line (after a hashbang), so no line moves.\n const at = code.startsWith('#!') ? code.indexOf('\\n') + 1 : 0;\n edits.unshift({ start: at, end: at, text: [...imports, ...decls].join('') });\n return splice(lines, edits, input.id);\n}\n"]}
@@ -0,0 +1,7 @@
1
+ import type { Rollup } from 'vite';
2
+ /**
3
+ * Modules statically retained by the app's inputs (transitively). A component among them is
4
+ * defined at startup by the app's own entry; giving it to the loader as well would make the
5
+ * bundler split it out of the entry into a chunk of its own.
6
+ */
7
+ export declare function staticallyReachable(ctx: Rollup.PluginContext, inputs: readonly string[]): Promise<Set<string>>;
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Modules statically retained by the app's inputs (transitively). A component among them is
3
+ * defined at startup by the app's own entry; giving it to the loader as well would make the
4
+ * bundler split it out of the entry into a chunk of its own.
5
+ */
6
+ export async function staticallyReachable(ctx, inputs) {
7
+ const seen = new Set();
8
+ const reachable = new Set();
9
+ const entries = new Set();
10
+ const queue = [];
11
+ for (const input of inputs) {
12
+ const resolved = await ctx.resolve(input, undefined, { isEntry: true });
13
+ if (resolved !== null && !resolved.external) {
14
+ entries.add(resolved.id);
15
+ queue.push(resolved);
16
+ }
17
+ }
18
+ while (queue.length > 0) {
19
+ const resolved = queue.pop();
20
+ if (resolved === undefined)
21
+ break;
22
+ const { id } = resolved;
23
+ if (seen.has(id) || id === '\0virtual:gyral/components')
24
+ continue;
25
+ seen.add(id);
26
+ const info = await ctx.load({ ...resolved, resolveDependencies: true });
27
+ // A side-effect-only import can be dropped by tree shaking. Keep such components in
28
+ // the loader rather than assuming the entry registered them (including through barrels).
29
+ if ((info.moduleSideEffects ?? resolved.moduleSideEffects) === false && !entries.has(id))
30
+ continue;
31
+ reachable.add(id);
32
+ for (const next of info.importedIds) {
33
+ if (seen.has(next))
34
+ continue;
35
+ const dependency = await ctx.resolve(next, id);
36
+ if (dependency !== null && !dependency.external)
37
+ queue.push(dependency);
38
+ }
39
+ }
40
+ return reachable;
41
+ }
42
+ //# sourceMappingURL=component-entries.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"component-entries.js","sourceRoot":"","sources":["../../src/compiler/component-entries.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,GAAyB,EACzB,MAAyB;IAEzB,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,SAAS,GAAG,IAAI,GAAG,EAAU,CAAC;IACpC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,MAAM,KAAK,GAAwB,EAAE,CAAC;IACtC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QACxE,IAAI,QAAQ,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;YAC5C,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;YACzB,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC;QAC7B,IAAI,QAAQ,KAAK,SAAS;YAAE,MAAM;QAClC,MAAM,EAAE,EAAE,EAAE,GAAG,QAAQ,CAAC;QACxB,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,4BAA4B;YAAE,SAAS;QAClE,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACb,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,QAAQ,EAAE,mBAAmB,EAAE,IAAI,EAAE,CAAC,CAAC;QACxE,oFAAoF;QACpF,yFAAyF;QACzF,IAAI,CAAC,IAAI,CAAC,iBAAiB,IAAI,QAAQ,CAAC,iBAAiB,CAAC,KAAK,KAAK,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YACtF,SAAS;QACX,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAClB,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACpC,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;gBAAE,SAAS;YAC7B,MAAM,UAAU,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAC/C,IAAI,UAAU,KAAK,IAAI,IAAI,CAAC,UAAU,CAAC,QAAQ;gBAAE,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC1E,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC","sourcesContent":["// Preserve components statically retained by the app entry instead of forcing another\n// dynamic-import entry for them (ADR 0016, gyral-1zd.31).\nimport type { Rollup } from 'vite';\n\n/**\n * Modules statically retained by the app's inputs (transitively). A component among them is\n * defined at startup by the app's own entry; giving it to the loader as well would make the\n * bundler split it out of the entry into a chunk of its own.\n */\nexport async function staticallyReachable(\n ctx: Rollup.PluginContext,\n inputs: readonly string[],\n): Promise<Set<string>> {\n const seen = new Set<string>();\n const reachable = new Set<string>();\n const entries = new Set<string>();\n const queue: Rollup.ResolvedId[] = [];\n for (const input of inputs) {\n const resolved = await ctx.resolve(input, undefined, { isEntry: true });\n if (resolved !== null && !resolved.external) {\n entries.add(resolved.id);\n queue.push(resolved);\n }\n }\n while (queue.length > 0) {\n const resolved = queue.pop();\n if (resolved === undefined) break;\n const { id } = resolved;\n if (seen.has(id) || id === '\\0virtual:gyral/components') continue;\n seen.add(id);\n const info = await ctx.load({ ...resolved, resolveDependencies: true });\n // A side-effect-only import can be dropped by tree shaking. Keep such components in\n // the loader rather than assuming the entry registered them (including through barrels).\n if ((info.moduleSideEffects ?? resolved.moduleSideEffects) === false && !entries.has(id))\n continue;\n reachable.add(id);\n for (const next of info.importedIds) {\n if (seen.has(next)) continue;\n const dependency = await ctx.resolve(next, id);\n if (dependency !== null && !dependency.external) queue.push(dependency);\n }\n }\n return reachable;\n}\n"]}
@@ -0,0 +1,4 @@
1
+ import type { Plugin } from 'vite';
2
+ import type { ComponentsOptions } from '../vite.js';
3
+ /** Automatic component loading (`gyralVitePreset({ components })`). */
4
+ export declare function createComponents(options: ComponentsOptions): Plugin;
@@ -0,0 +1,182 @@
1
+ // Automatic component loading (`gyralVitePreset({ components })`, ADR 0016 addendum "Automatic
2
+ // component loading"): finds the app's components, adds a loader to the client build that
3
+ // imports a tag's module once the tag is in the page, and writes the manifest
4
+ // `@gyral/ssr/static`'s `componentsFromManifest` reads. ../vite.ts loads it on the plugin's
5
+ // first hook, as it loads the compiler.
6
+ import { relative, resolve, sep } from 'node:path';
7
+ import { staticallyReachable } from './component-entries.js';
8
+ import { loaderSource } from './loader-source.js';
9
+ import { discoverComponents } from './tag-map.js';
10
+ /** The loader module's id, and Vite's id for it (a virtual module). */
11
+ const COMPONENTS_ID = 'virtual:gyral/components';
12
+ const COMPONENTS_RESOLVED = `\0${COMPONENTS_ID}`;
13
+ /** The file the build writes next to `.vite/manifest.json` (read by `@gyral/ssr/static`). */
14
+ const COMPONENTS_MANIFEST = '.vite/gyral-components.json';
15
+ const SOURCE_FILE = /\.[cm]?[jt]sx?$/;
16
+ /**
17
+ * Tag → root-relative URL (`/src/…`) of the module defining it: ./tag-map.ts's scan, then the
18
+ * `modules` the app lists for components the scan can't see (defined through a wrapper).
19
+ */
20
+ function scanComponents(root, include, listed = {}) {
21
+ const tags = new Map();
22
+ for (const [tag, path] of Object.entries(listed)) {
23
+ tags.set(tag, `/${relative(root, resolve(root, path)).split(sep).join('/')}`);
24
+ }
25
+ for (const { tag, file } of discoverComponents(root, include)) {
26
+ const url = `/${relative(root, file).split(sep).join('/')}`;
27
+ const known = tags.get(tag);
28
+ if (known === undefined)
29
+ tags.set(tag, url);
30
+ else if (known !== url && listed[tag] === undefined) {
31
+ console.warn(`gyral: <${tag}> is defined in ${known} and ${url}; loading ${known}`);
32
+ }
33
+ }
34
+ return tags;
35
+ }
36
+ /** The app's own inputs (everything but the loader), as module specifiers. */
37
+ function inputsOf(input) {
38
+ if (input === undefined)
39
+ return [];
40
+ if (typeof input === 'string')
41
+ return [input];
42
+ if (Array.isArray(input))
43
+ return [...input];
44
+ return Object.values(input);
45
+ }
46
+ /** The client build's input with the loader added. */
47
+ function withLoader(input) {
48
+ if (input === undefined)
49
+ return { components: COMPONENTS_ID };
50
+ if (typeof input === 'string') {
51
+ const name = input.replace(/^.*\//, '').replace(/\.[^.]*$/, '');
52
+ return withLoader({ [name]: input });
53
+ }
54
+ if (Array.isArray(input))
55
+ return [...input, COMPONENTS_ID];
56
+ const entries = input;
57
+ let name = 'components';
58
+ while (name in entries)
59
+ name += '-loader';
60
+ return { ...entries, [name]: COMPONENTS_ID };
61
+ }
62
+ /** Automatic component loading (`gyralVitePreset({ components })`). */
63
+ export function createComponents(options) {
64
+ const include = options.include ?? ['src'];
65
+ let root = process.cwd();
66
+ let tags = new Map();
67
+ /** The app's own build inputs, recorded before the loader is added. */
68
+ let appInputs = [];
69
+ /** Tags the app's entry defines itself (statically imported): not loaded by the loader. */
70
+ let entryTags = [];
71
+ let loaderFile = '';
72
+ const scan = () => (tags = scanComponents(root, include, options.modules));
73
+ const api = { tags: scan };
74
+ return {
75
+ name: 'gyral:components',
76
+ api,
77
+ config(config, env) {
78
+ root = resolve(config.root ?? process.cwd());
79
+ if (env.command !== 'build' || env.isSsrBuild === true)
80
+ return;
81
+ const build = (config.build ??= {});
82
+ const key = build.rolldownOptions !== undefined ? 'rolldownOptions' : 'rollupOptions';
83
+ const bundler = (build[key] ??= {});
84
+ const input = bundler.input ?? config.input;
85
+ appInputs = inputsOf(input);
86
+ bundler.input = withLoader(input);
87
+ build.manifest ??= true;
88
+ },
89
+ configResolved(config) {
90
+ root = config.root;
91
+ if (config.command !== 'build' || config.build.ssr !== false)
92
+ return;
93
+ const preload = config.build.modulePreload;
94
+ if (preload === false)
95
+ return;
96
+ const previous = preload.resolveDependencies;
97
+ preload.resolveDependencies = (file, deps, context) => context.hostType === 'js' && context.hostId === loaderFile
98
+ ? []
99
+ : (previous?.(file, deps, context) ?? deps);
100
+ },
101
+ buildStart() {
102
+ scan();
103
+ },
104
+ resolveId(source) {
105
+ return source === COMPONENTS_ID ? COMPONENTS_RESOLVED : null;
106
+ },
107
+ async load(id) {
108
+ if (id !== COMPONENTS_RESOLVED)
109
+ return null;
110
+ if (this.environment.config.command === 'serve') {
111
+ scan();
112
+ return loaderSource(tags);
113
+ }
114
+ // A production build: components the app's entry imports are already defined at startup,
115
+ // and every other one becomes a dynamic import. The dependency filter removes repeated
116
+ // JS preload lists (renderPage already preloads them); Vite still loads their CSS.
117
+ const inEntry = await staticallyReachable(this, appInputs);
118
+ entryTags = [];
119
+ const lazy = new Map();
120
+ for (const [tag, url] of tags) {
121
+ const file = resolve(root, url.slice(1));
122
+ if (inEntry.has(file)) {
123
+ entryTags.push(tag);
124
+ continue;
125
+ }
126
+ lazy.set(tag, url);
127
+ }
128
+ return loaderSource(lazy, { known: entryTags });
129
+ },
130
+ configureServer(server) {
131
+ // A new or edited component module changes the loader's table.
132
+ const refresh = (file) => {
133
+ if (!SOURCE_FILE.test(file))
134
+ return;
135
+ const module = server.environments.client.moduleGraph.getModuleById(COMPONENTS_RESOLVED);
136
+ if (module !== undefined)
137
+ server.environments.client.moduleGraph.invalidateModule(module);
138
+ };
139
+ server.watcher.on('add', refresh);
140
+ server.watcher.on('unlink', refresh);
141
+ server.watcher.on('change', refresh);
142
+ },
143
+ generateBundle(_output, bundle) {
144
+ if (this.environment.config.consumer !== 'client')
145
+ return;
146
+ const loader = Object.values(bundle).find((chunk) => chunk.type === 'chunk' && chunk.facadeModuleId === COMPONENTS_RESOLVED);
147
+ if (loader?.type !== 'chunk')
148
+ return;
149
+ loaderFile = loader.fileName;
150
+ const modules = Object.fromEntries([...tags].map(([tag, url]) => [tag, url.slice(1)]));
151
+ // Each tag's chunk by file. A module another chunk imports statically is bundled into
152
+ // that chunk (often the entry), so Vite's manifest has no key for it; the server finds
153
+ // the chunk by file instead (`componentAssets`).
154
+ const chunkOf = new Map();
155
+ for (const chunk of Object.values(bundle)) {
156
+ if (chunk.type !== 'chunk')
157
+ continue;
158
+ for (const id of chunk.moduleIds)
159
+ chunkOf.set(id, chunk.fileName);
160
+ }
161
+ const chunks = {};
162
+ for (const [tag, url] of tags) {
163
+ const file = chunkOf.get(resolve(root, url.slice(1)));
164
+ if (file !== undefined)
165
+ chunks[tag] = file;
166
+ }
167
+ const written = {
168
+ loader: loader.fileName,
169
+ loaderImports: loader.imports,
170
+ modules,
171
+ chunks,
172
+ entryTags,
173
+ };
174
+ this.emitFile({
175
+ type: 'asset',
176
+ fileName: COMPONENTS_MANIFEST,
177
+ source: `${JSON.stringify(written, null, 2)}\n`,
178
+ });
179
+ },
180
+ };
181
+ }
182
+ //# sourceMappingURL=components.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"components.js","sourceRoot":"","sources":["../../src/compiler/components.ts"],"names":[],"mappings":"AAAA,+FAA+F;AAC/F,0FAA0F;AAC1F,8EAA8E;AAC9E,4FAA4F;AAC5F,wCAAwC;AACxC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAEnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAE7D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAElD,uEAAuE;AACvE,MAAM,aAAa,GAAG,0BAA0B,CAAC;AACjD,MAAM,mBAAmB,GAAG,KAAK,aAAa,EAAE,CAAC;AACjD,6FAA6F;AAC7F,MAAM,mBAAmB,GAAG,6BAA6B,CAAC;AAE1D,MAAM,WAAW,GAAG,iBAAiB,CAAC;AAEtC;;;GAGG;AACH,SAAS,cAAc,CACrB,IAAY,EACZ,OAA0B,EAC1B,SAA2C,EAAE;IAE7C,MAAM,IAAI,GAAG,IAAI,GAAG,EAAkB,CAAC;IACvC,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACjD,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChF,CAAC;IACD,KAAK,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,kBAAkB,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC;QAC9D,MAAM,GAAG,GAAG,IAAI,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QAC5D,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAI,KAAK,KAAK,SAAS;YAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;aACvC,IAAI,KAAK,KAAK,GAAG,IAAI,MAAM,CAAC,GAAG,CAAC,KAAK,SAAS,EAAE,CAAC;YACpD,OAAO,CAAC,IAAI,CAAC,WAAW,GAAG,mBAAmB,KAAK,QAAQ,GAAG,aAAa,KAAK,EAAE,CAAC,CAAC;QACtF,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAID,8EAA8E;AAC9E,SAAS,QAAQ,CAAC,KAAY;IAC5B,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,EAAE,CAAC;IACnC,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IAC9C,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,CAAC,GAAI,KAA2B,CAAC,CAAC;IACnE,OAAO,MAAM,CAAC,MAAM,CAAC,KAAyC,CAAC,CAAC;AAClE,CAAC;AAED,sDAAsD;AACtD,SAAS,UAAU,CAAC,KAAY;IAC9B,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,CAAC;IAC9D,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;QAChE,OAAO,UAAU,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IACvC,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,CAAC,GAAI,KAA2B,EAAE,aAAa,CAAC,CAAC;IAClF,MAAM,OAAO,GAAG,KAAyC,CAAC;IAC1D,IAAI,IAAI,GAAG,YAAY,CAAC;IACxB,OAAO,IAAI,IAAI,OAAO;QAAE,IAAI,IAAI,SAAS,CAAC;IAC1C,OAAO,EAAE,GAAG,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE,aAAa,EAAE,CAAC;AAC/C,CAAC;AAOD,uEAAuE;AACvE,MAAM,UAAU,gBAAgB,CAAC,OAA0B;IACzD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC;IAC3C,IAAI,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IACzB,IAAI,IAAI,GAAG,IAAI,GAAG,EAAkB,CAAC;IACrC,uEAAuE;IACvE,IAAI,SAAS,GAAa,EAAE,CAAC;IAC7B,2FAA2F;IAC3F,IAAI,SAAS,GAAa,EAAE,CAAC;IAC7B,IAAI,UAAU,GAAG,EAAE,CAAC;IACpB,MAAM,IAAI,GAAG,GAAwB,EAAE,CAAC,CAAC,IAAI,GAAG,cAAc,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;IAChG,MAAM,GAAG,GAAwB,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAChD,OAAO;QACL,IAAI,EAAE,kBAAkB;QACxB,GAAG;QACH,MAAM,CAAC,MAAM,EAAE,GAAG;YAChB,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;YAC7C,IAAI,GAAG,CAAC,OAAO,KAAK,OAAO,IAAI,GAAG,CAAC,UAAU,KAAK,IAAI;gBAAE,OAAO;YAM/D,MAAM,KAAK,GAAG,CAAE,MAA4B,CAAC,KAAK,KAAK,EAAE,CAAC,CAAC;YAC3D,MAAM,GAAG,GAAG,KAAK,CAAC,eAAe,KAAK,SAAS,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,eAAe,CAAC;YACtF,MAAM,OAAO,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC;YACpC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC;YAC5C,SAAS,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;YAC5B,OAAO,CAAC,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;YAClC,KAAK,CAAC,QAAQ,KAAK,IAAI,CAAC;QAC1B,CAAC;QACD,cAAc,CAAC,MAAM;YACnB,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;YACnB,IAAI,MAAM,CAAC,OAAO,KAAK,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC,GAAG,KAAK,KAAK;gBAAE,OAAO;YACrE,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC;YAC3C,IAAI,OAAO,KAAK,KAAK;gBAAE,OAAO;YAC9B,MAAM,QAAQ,GAAG,OAAO,CAAC,mBAAmB,CAAC;YAC7C,OAAO,CAAC,mBAAmB,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,CACpD,OAAO,CAAC,QAAQ,KAAK,IAAI,IAAI,OAAO,CAAC,MAAM,KAAK,UAAU;gBACxD,CAAC,CAAC,EAAE;gBACJ,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC;QAClD,CAAC;QACD,UAAU;YACR,IAAI,EAAE,CAAC;QACT,CAAC;QACD,SAAS,CAAC,MAAM;YACd,OAAO,MAAM,KAAK,aAAa,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,IAAI,CAAC;QAC/D,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,EAAE;YACX,IAAI,EAAE,KAAK,mBAAmB;gBAAE,OAAO,IAAI,CAAC;YAC5C,IAAI,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,KAAK,OAAO,EAAE,CAAC;gBAChD,IAAI,EAAE,CAAC;gBACP,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC;YAC5B,CAAC;YACD,yFAAyF;YACzF,uFAAuF;YACvF,mFAAmF;YACnF,MAAM,OAAO,GAAG,MAAM,mBAAmB,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;YAC3D,SAAS,GAAG,EAAE,CAAC;YACf,MAAM,IAAI,GAAG,IAAI,GAAG,EAAkB,CAAC;YACvC,KAAK,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;gBAC9B,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;gBACzC,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;oBACtB,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;oBACpB,SAAS;gBACX,CAAC;gBACD,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACrB,CAAC;YACD,OAAO,YAAY,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;QAClD,CAAC;QACD,eAAe,CAAC,MAAM;YACpB,+DAA+D;YAC/D,MAAM,OAAO,GAAG,CAAC,IAAY,EAAQ,EAAE;gBACrC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC;oBAAE,OAAO;gBACpC,MAAM,MAAM,GAAG,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,WAAW,CAAC,aAAa,CAAC,mBAAmB,CAAC,CAAC;gBACzF,IAAI,MAAM,KAAK,SAAS;oBAAE,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC;YAC5F,CAAC,CAAC;YACF,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;YAClC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YACrC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACvC,CAAC;QACD,cAAc,CAAC,OAAO,EAAE,MAAM;YAC5B,IAAI,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,QAAQ,KAAK,QAAQ;gBAAE,OAAO;YAC1D,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CACvC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,OAAO,IAAI,KAAK,CAAC,cAAc,KAAK,mBAAmB,CAClF,CAAC;YACF,IAAI,MAAM,EAAE,IAAI,KAAK,OAAO;gBAAE,OAAO;YACrC,UAAU,GAAG,MAAM,CAAC,QAAQ,CAAC;YAC7B,MAAM,OAAO,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACvF,sFAAsF;YACtF,uFAAuF;YACvF,iDAAiD;YACjD,MAAM,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAC;YAC1C,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC1C,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO;oBAAE,SAAS;gBACrC,KAAK,MAAM,EAAE,IAAI,KAAK,CAAC,SAAS;oBAAE,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;YACpE,CAAC;YACD,MAAM,MAAM,GAA2B,EAAE,CAAC;YAC1C,KAAK,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;gBAC9B,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBACtD,IAAI,IAAI,KAAK,SAAS;oBAAE,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;YAC7C,CAAC;YACD,MAAM,OAAO,GAAG;gBACd,MAAM,EAAE,MAAM,CAAC,QAAQ;gBACvB,aAAa,EAAE,MAAM,CAAC,OAAO;gBAC7B,OAAO;gBACP,MAAM;gBACN,SAAS;aACV,CAAC;YACF,IAAI,CAAC,QAAQ,CAAC;gBACZ,IAAI,EAAE,OAAO;gBACb,QAAQ,EAAE,mBAAmB;gBAC7B,MAAM,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI;aAChD,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["// Automatic component loading (`gyralVitePreset({ components })`, ADR 0016 addendum \"Automatic\n// component loading\"): finds the app's components, adds a loader to the client build that\n// imports a tag's module once the tag is in the page, and writes the manifest\n// `@gyral/ssr/static`'s `componentsFromManifest` reads. ../vite.ts loads it on the plugin's\n// first hook, as it loads the compiler.\nimport { relative, resolve, sep } from 'node:path';\nimport type { Plugin } from 'vite';\nimport { staticallyReachable } from './component-entries.js';\nimport type { ComponentsOptions } from '../vite.js';\nimport { loaderSource } from './loader-source.js';\nimport { discoverComponents } from './tag-map.js';\n\n/** The loader module's id, and Vite's id for it (a virtual module). */\nconst COMPONENTS_ID = 'virtual:gyral/components';\nconst COMPONENTS_RESOLVED = `\\0${COMPONENTS_ID}`;\n/** The file the build writes next to `.vite/manifest.json` (read by `@gyral/ssr/static`). */\nconst COMPONENTS_MANIFEST = '.vite/gyral-components.json';\n\nconst SOURCE_FILE = /\\.[cm]?[jt]sx?$/;\n\n/**\n * Tag → root-relative URL (`/src/…`) of the module defining it: ./tag-map.ts's scan, then the\n * `modules` the app lists for components the scan can't see (defined through a wrapper).\n */\nfunction scanComponents(\n root: string,\n include: readonly string[],\n listed: Readonly<Record<string, string>> = {},\n): Map<string, string> {\n const tags = new Map<string, string>();\n for (const [tag, path] of Object.entries(listed)) {\n tags.set(tag, `/${relative(root, resolve(root, path)).split(sep).join('/')}`);\n }\n for (const { tag, file } of discoverComponents(root, include)) {\n const url = `/${relative(root, file).split(sep).join('/')}`;\n const known = tags.get(tag);\n if (known === undefined) tags.set(tag, url);\n else if (known !== url && listed[tag] === undefined) {\n console.warn(`gyral: <${tag}> is defined in ${known} and ${url}; loading ${known}`);\n }\n }\n return tags;\n}\n\ntype Input = string | readonly string[] | Readonly<Record<string, string>> | undefined;\n\n/** The app's own inputs (everything but the loader), as module specifiers. */\nfunction inputsOf(input: Input): string[] {\n if (input === undefined) return [];\n if (typeof input === 'string') return [input];\n if (Array.isArray(input)) return [...(input as readonly string[])];\n return Object.values(input as Readonly<Record<string, string>>);\n}\n\n/** The client build's input with the loader added. */\nfunction withLoader(input: Input): string[] | Record<string, string> {\n if (input === undefined) return { components: COMPONENTS_ID };\n if (typeof input === 'string') {\n const name = input.replace(/^.*\\//, '').replace(/\\.[^.]*$/, '');\n return withLoader({ [name]: input });\n }\n if (Array.isArray(input)) return [...(input as readonly string[]), COMPONENTS_ID];\n const entries = input as Readonly<Record<string, string>>;\n let name = 'components';\n while (name in entries) name += '-loader';\n return { ...entries, [name]: COMPONENTS_ID };\n}\n\n/** The API `gyralDevServer` reads from this plugin (the tags it found, fresh). */\ninterface ComponentsPluginApi {\n readonly tags: () => ReadonlyMap<string, string>;\n}\n\n/** Automatic component loading (`gyralVitePreset({ components })`). */\nexport function createComponents(options: ComponentsOptions): Plugin {\n const include = options.include ?? ['src'];\n let root = process.cwd();\n let tags = new Map<string, string>();\n /** The app's own build inputs, recorded before the loader is added. */\n let appInputs: string[] = [];\n /** Tags the app's entry defines itself (statically imported): not loaded by the loader. */\n let entryTags: string[] = [];\n let loaderFile = '';\n const scan = (): Map<string, string> => (tags = scanComponents(root, include, options.modules));\n const api: ComponentsPluginApi = { tags: scan };\n return {\n name: 'gyral:components',\n api,\n config(config, env) {\n root = resolve(config.root ?? process.cwd());\n if (env.command !== 'build' || env.isSsrBuild === true) return;\n type Build = {\n manifest?: boolean | string;\n rollupOptions?: { input?: Input };\n rolldownOptions?: { input?: Input };\n };\n const build = ((config as { build?: Build }).build ??= {});\n const key = build.rolldownOptions !== undefined ? 'rolldownOptions' : 'rollupOptions';\n const bundler = (build[key] ??= {});\n const input = bundler.input ?? config.input;\n appInputs = inputsOf(input);\n bundler.input = withLoader(input);\n build.manifest ??= true;\n },\n configResolved(config) {\n root = config.root;\n if (config.command !== 'build' || config.build.ssr !== false) return;\n const preload = config.build.modulePreload;\n if (preload === false) return;\n const previous = preload.resolveDependencies;\n preload.resolveDependencies = (file, deps, context) =>\n context.hostType === 'js' && context.hostId === loaderFile\n ? []\n : (previous?.(file, deps, context) ?? deps);\n },\n buildStart() {\n scan();\n },\n resolveId(source) {\n return source === COMPONENTS_ID ? COMPONENTS_RESOLVED : null;\n },\n async load(id) {\n if (id !== COMPONENTS_RESOLVED) return null;\n if (this.environment.config.command === 'serve') {\n scan();\n return loaderSource(tags);\n }\n // A production build: components the app's entry imports are already defined at startup,\n // and every other one becomes a dynamic import. The dependency filter removes repeated\n // JS preload lists (renderPage already preloads them); Vite still loads their CSS.\n const inEntry = await staticallyReachable(this, appInputs);\n entryTags = [];\n const lazy = new Map<string, string>();\n for (const [tag, url] of tags) {\n const file = resolve(root, url.slice(1));\n if (inEntry.has(file)) {\n entryTags.push(tag);\n continue;\n }\n lazy.set(tag, url);\n }\n return loaderSource(lazy, { known: entryTags });\n },\n configureServer(server) {\n // A new or edited component module changes the loader's table.\n const refresh = (file: string): void => {\n if (!SOURCE_FILE.test(file)) return;\n const module = server.environments.client.moduleGraph.getModuleById(COMPONENTS_RESOLVED);\n if (module !== undefined) server.environments.client.moduleGraph.invalidateModule(module);\n };\n server.watcher.on('add', refresh);\n server.watcher.on('unlink', refresh);\n server.watcher.on('change', refresh);\n },\n generateBundle(_output, bundle) {\n if (this.environment.config.consumer !== 'client') return;\n const loader = Object.values(bundle).find(\n (chunk) => chunk.type === 'chunk' && chunk.facadeModuleId === COMPONENTS_RESOLVED,\n );\n if (loader?.type !== 'chunk') return;\n loaderFile = loader.fileName;\n const modules = Object.fromEntries([...tags].map(([tag, url]) => [tag, url.slice(1)]));\n // Each tag's chunk by file. A module another chunk imports statically is bundled into\n // that chunk (often the entry), so Vite's manifest has no key for it; the server finds\n // the chunk by file instead (`componentAssets`).\n const chunkOf = new Map<string, string>();\n for (const chunk of Object.values(bundle)) {\n if (chunk.type !== 'chunk') continue;\n for (const id of chunk.moduleIds) chunkOf.set(id, chunk.fileName);\n }\n const chunks: Record<string, string> = {};\n for (const [tag, url] of tags) {\n const file = chunkOf.get(resolve(root, url.slice(1)));\n if (file !== undefined) chunks[tag] = file;\n }\n const written = {\n loader: loader.fileName,\n loaderImports: loader.imports,\n modules,\n chunks,\n entryTags,\n };\n this.emitFile({\n type: 'asset',\n fileName: COMPONENTS_MANIFEST,\n source: `${JSON.stringify(written, null, 2)}\\n`,\n });\n },\n };\n}\n"]}
@@ -0,0 +1,31 @@
1
+ import { type Node } from './ast.js';
2
+ /** Optional machinery the build adds when a module may use it. */
3
+ export type Feature = 'invokers' | 'transitions' | 'frame' | 'states' | 'forms' | 'subscriptions' | 'dialogs' | 'disposal' | 'errorView' | 'errored';
4
+ /** The spec field each spec-field feature is reached through (04, 05). */
5
+ export declare const FIELDS: {
6
+ readonly transitions: "viewTransition";
7
+ readonly frame: "renderOnFrame";
8
+ readonly states: "states";
9
+ readonly forms: "formAssociated";
10
+ readonly subscriptions: "subscriptions";
11
+ readonly disposal: "dispose";
12
+ readonly errorView: "error";
13
+ readonly errored: "Errored";
14
+ };
15
+ export interface ModuleFacts {
16
+ /** Identifier names in runtime code, import declarations left out. */
17
+ readonly names: ReadonlySet<string>;
18
+ /** String literal values, and template literal texts with `${}` for each expression. */
19
+ readonly texts: readonly string[];
20
+ /** Specifiers through which the module may reach a `raw` export (see the header). */
21
+ readonly rawSources: readonly string[];
22
+ /** Whether the module may give a component an error view (see `specError`). */
23
+ readonly errorView: boolean;
24
+ }
25
+ /** The facts the scan needs about a module (`program`, from `this.parse`). */
26
+ export declare function factsOf(program: Node): ModuleFacts;
27
+ /**
28
+ * Whether the module may use `feature` by what it writes itself. For `invokers` that is the
29
+ * markup and strings; `raw` needs resolving `rawSources` (features.ts).
30
+ */
31
+ export declare function writes(facts: ModuleFacts, feature: Feature): boolean;