@gyral/core 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (343) hide show
  1. package/CHANGELOG.md +87 -0
  2. package/README.md +7 -5
  3. package/dist/children.d.ts +5 -2
  4. package/dist/children.js +8 -3
  5. package/dist/children.js.map +1 -1
  6. package/dist/command.js +6 -0
  7. package/dist/command.js.map +1 -1
  8. package/dist/compiler/ast.d.ts +21 -0
  9. package/dist/compiler/ast.js +145 -0
  10. package/dist/compiler/ast.js.map +1 -0
  11. package/dist/compiler/compile.d.ts +38 -0
  12. package/dist/compiler/compile.js +129 -0
  13. package/dist/compiler/compile.js.map +1 -0
  14. package/dist/compiler/hooks.d.ts +18 -0
  15. package/dist/compiler/hooks.js +186 -0
  16. package/dist/compiler/hooks.js.map +1 -0
  17. package/dist/compiler/parse5-check.d.ts +21 -0
  18. package/dist/compiler/parse5-check.js +55 -0
  19. package/dist/compiler/parse5-check.js.map +1 -0
  20. package/dist/compiler/scan.d.ts +31 -0
  21. package/dist/compiler/scan.js +152 -0
  22. package/dist/compiler/scan.js.map +1 -0
  23. package/dist/compiler/source.d.ts +34 -0
  24. package/dist/compiler/source.js +114 -0
  25. package/dist/compiler/source.js.map +1 -0
  26. package/dist/define.d.ts +2 -2
  27. package/dist/define.js +35 -327
  28. package/dist/define.js.map +1 -1
  29. package/dist/devtools-events.d.ts +5 -0
  30. package/dist/devtools-events.js.map +1 -1
  31. package/dist/devtools-off.d.ts +1 -0
  32. package/dist/devtools-off.js +1 -0
  33. package/dist/devtools-off.js.map +1 -1
  34. package/dist/devtools.d.ts +1 -0
  35. package/dist/devtools.js +3 -2
  36. package/dist/devtools.js.map +1 -1
  37. package/dist/drivers-scope.d.ts +1 -1
  38. package/dist/drivers-scope.js +1 -8
  39. package/dist/drivers-scope.js.map +1 -1
  40. package/dist/element-types.d.ts +5 -3
  41. package/dist/element-types.js.map +1 -1
  42. package/dist/element.d.ts +3 -0
  43. package/dist/element.js +269 -0
  44. package/dist/element.js.map +1 -0
  45. package/dist/eslint/imports.d.ts +24 -0
  46. package/dist/eslint/imports.js +78 -0
  47. package/dist/eslint/imports.js.map +1 -0
  48. package/dist/eslint/index.d.ts +15 -0
  49. package/dist/eslint/index.js +15 -0
  50. package/dist/eslint/index.js.map +1 -0
  51. package/dist/eslint/locate.d.ts +33 -0
  52. package/dist/eslint/locate.js +132 -0
  53. package/dist/eslint/locate.js.map +1 -0
  54. package/dist/eslint/row-purity-rule.d.ts +2 -0
  55. package/dist/eslint/row-purity-rule.js +103 -0
  56. package/dist/eslint/row-purity-rule.js.map +1 -0
  57. package/dist/eslint/template-rule.d.ts +5 -0
  58. package/dist/eslint/template-rule.js +66 -0
  59. package/dist/eslint/template-rule.js.map +1 -0
  60. package/dist/features.d.ts +39 -0
  61. package/dist/features.js +2 -0
  62. package/dist/features.js.map +1 -0
  63. package/dist/focus.d.ts +7 -12
  64. package/dist/focus.js +13 -10
  65. package/dist/focus.js.map +1 -1
  66. package/dist/hooks/invalid.d.ts +14 -0
  67. package/dist/hooks/invalid.js +72 -0
  68. package/dist/hooks/invalid.js.map +1 -0
  69. package/dist/hooks/labelled-by.d.ts +13 -0
  70. package/dist/hooks/labelled-by.js +51 -0
  71. package/dist/hooks/labelled-by.js.map +1 -0
  72. package/dist/host-model.d.ts +48 -0
  73. package/dist/host-model.js +155 -0
  74. package/dist/host-model.js.map +1 -0
  75. package/dist/hydration-client.d.ts +9 -0
  76. package/dist/hydration-client.js +35 -0
  77. package/dist/hydration-client.js.map +1 -0
  78. package/dist/hydration.d.ts +13 -19
  79. package/dist/hydration.js +45 -45
  80. package/dist/hydration.js.map +1 -1
  81. package/dist/index.d.ts +9 -17
  82. package/dist/index.js +9 -18
  83. package/dist/index.js.map +1 -1
  84. package/dist/intent.d.ts +31 -8
  85. package/dist/intent.js +82 -27
  86. package/dist/intent.js.map +1 -1
  87. package/dist/internal/interpreter.d.ts +7 -1
  88. package/dist/internal/interpreter.js +11 -4
  89. package/dist/internal/interpreter.js.map +1 -1
  90. package/dist/invokers-shim.d.ts +6 -0
  91. package/dist/invokers-shim.js +32 -0
  92. package/dist/invokers-shim.js.map +1 -0
  93. package/dist/invokers.d.ts +3 -5
  94. package/dist/invokers.js +11 -51
  95. package/dist/invokers.js.map +1 -1
  96. package/dist/islands.d.ts +0 -2
  97. package/dist/islands.js +4 -11
  98. package/dist/islands.js.map +1 -1
  99. package/dist/light-dom.d.ts +3 -52
  100. package/dist/light-dom.js +5 -100
  101. package/dist/light-dom.js.map +1 -1
  102. package/dist/prop.d.ts +66 -0
  103. package/dist/prop.js +22 -0
  104. package/dist/prop.js.map +1 -0
  105. package/dist/props.d.ts +52 -21
  106. package/dist/props.js +150 -34
  107. package/dist/props.js.map +1 -1
  108. package/dist/scheduler.d.ts +39 -0
  109. package/dist/scheduler.js +230 -0
  110. package/dist/scheduler.js.map +1 -0
  111. package/dist/server-component.d.ts +10 -0
  112. package/dist/server-component.js +102 -0
  113. package/dist/server-component.js.map +1 -0
  114. package/dist/server-specs.d.ts +6 -0
  115. package/dist/server-specs.js +13 -0
  116. package/dist/server-specs.js.map +1 -0
  117. package/dist/server.d.ts +28 -0
  118. package/dist/server.js +50 -0
  119. package/dist/server.js.map +1 -0
  120. package/dist/settled.d.ts +10 -0
  121. package/dist/settled.js +40 -0
  122. package/dist/settled.js.map +1 -0
  123. package/dist/states.d.ts +3 -3
  124. package/dist/states.js +4 -7
  125. package/dist/states.js.map +1 -1
  126. package/dist/store-binding.d.ts +6 -3
  127. package/dist/store-binding.js +5 -6
  128. package/dist/store-binding.js.map +1 -1
  129. package/dist/store-scope.d.ts +6 -7
  130. package/dist/store-scope.js +11 -26
  131. package/dist/store-scope.js.map +1 -1
  132. package/dist/store.d.ts +3 -0
  133. package/dist/store.js +9 -2
  134. package/dist/store.js.map +1 -1
  135. package/dist/stores-provider.d.ts +2 -6
  136. package/dist/stores-provider.js +21 -55
  137. package/dist/stores-provider.js.map +1 -1
  138. package/dist/transitions.d.ts +5 -6
  139. package/dist/transitions.js +11 -20
  140. package/dist/transitions.js.map +1 -1
  141. package/dist/types.d.ts +19 -23
  142. package/dist/types.js.map +1 -1
  143. package/dist/view/attributes.d.ts +6 -0
  144. package/dist/view/attributes.js +10 -0
  145. package/dist/view/attributes.js.map +1 -0
  146. package/dist/view/compiled.d.ts +1 -0
  147. package/dist/view/compiled.js +6 -0
  148. package/dist/view/compiled.js.map +1 -0
  149. package/dist/view/dev-off.d.ts +1 -0
  150. package/dist/view/dev-off.js +4 -0
  151. package/dist/view/dev-off.js.map +1 -0
  152. package/dist/view/dev.d.ts +1 -0
  153. package/dist/view/dev.js +5 -0
  154. package/dist/view/dev.js.map +1 -0
  155. package/dist/view/flags.d.ts +1 -0
  156. package/dist/view/flags.js +4 -0
  157. package/dist/view/flags.js.map +1 -0
  158. package/dist/view/index.d.ts +21 -0
  159. package/dist/view/index.js +21 -0
  160. package/dist/view/index.js.map +1 -0
  161. package/dist/view/normalize/check.d.ts +20 -0
  162. package/dist/view/normalize/check.js +78 -0
  163. package/dist/view/normalize/check.js.map +1 -0
  164. package/dist/view/normalize/emit.d.ts +13 -0
  165. package/dist/view/normalize/emit.js +136 -0
  166. package/dist/view/normalize/emit.js.map +1 -0
  167. package/dist/view/normalize/entities.d.ts +4 -0
  168. package/dist/view/normalize/entities.js +38 -0
  169. package/dist/view/normalize/entities.js.map +1 -0
  170. package/dist/view/normalize/errors.d.ts +9 -0
  171. package/dist/view/normalize/errors.js +19 -0
  172. package/dist/view/normalize/errors.js.map +1 -0
  173. package/dist/view/normalize/id.d.ts +7 -0
  174. package/dist/view/normalize/id.js +48 -0
  175. package/dist/view/normalize/id.js.map +1 -0
  176. package/dist/view/normalize/normalize.d.ts +15 -0
  177. package/dist/view/normalize/normalize.js +36 -0
  178. package/dist/view/normalize/normalize.js.map +1 -0
  179. package/dist/view/normalize/repairs.d.ts +24 -0
  180. package/dist/view/normalize/repairs.js +166 -0
  181. package/dist/view/normalize/repairs.js.map +1 -0
  182. package/dist/view/normalize/rules.d.ts +30 -0
  183. package/dist/view/normalize/rules.js +90 -0
  184. package/dist/view/normalize/rules.js.map +1 -0
  185. package/dist/view/normalize/shape.d.ts +5 -0
  186. package/dist/view/normalize/shape.js +38 -0
  187. package/dist/view/normalize/shape.js.map +1 -0
  188. package/dist/view/normalize/source.d.ts +13 -0
  189. package/dist/view/normalize/source.js +34 -0
  190. package/dist/view/normalize/source.js.map +1 -0
  191. package/dist/view/normalize/tag-states.d.ts +23 -0
  192. package/dist/view/normalize/tag-states.js +192 -0
  193. package/dist/view/normalize/tag-states.js.map +1 -0
  194. package/dist/view/normalize/tokenizer.d.ts +5 -0
  195. package/dist/view/normalize/tokenizer.js +233 -0
  196. package/dist/view/normalize/tokenizer.js.map +1 -0
  197. package/dist/view/normalize/tokens.d.ts +51 -0
  198. package/dist/view/normalize/tokens.js +24 -0
  199. package/dist/view/normalize/tokens.js.map +1 -0
  200. package/dist/view/normalize/tree.d.ts +59 -0
  201. package/dist/view/normalize/tree.js +190 -0
  202. package/dist/view/normalize/tree.js.map +1 -0
  203. package/dist/view/normalize/types.d.ts +126 -0
  204. package/dist/view/normalize/types.js +26 -0
  205. package/dist/view/normalize/types.js.map +1 -0
  206. package/dist/view/normalize/whitespace.d.ts +2 -0
  207. package/dist/{template-whitespace.js → view/normalize/whitespace.js} +24 -34
  208. package/dist/view/normalize/whitespace.js.map +1 -0
  209. package/dist/view/prepare-stub.d.ts +3 -0
  210. package/dist/view/prepare-stub.js +7 -0
  211. package/dist/view/prepare-stub.js.map +1 -0
  212. package/dist/view/prepare.d.ts +8 -0
  213. package/dist/view/prepare.js +57 -0
  214. package/dist/view/prepare.js.map +1 -0
  215. package/dist/view/registry.d.ts +63 -0
  216. package/dist/view/registry.js +19 -0
  217. package/dist/view/registry.js.map +1 -0
  218. package/dist/view/render/adopt-attr.d.ts +14 -0
  219. package/dist/view/render/adopt-attr.js +77 -0
  220. package/dist/view/render/adopt-attr.js.map +1 -0
  221. package/dist/view/render/adopt-plan.d.ts +10 -0
  222. package/dist/view/render/adopt-plan.js +26 -0
  223. package/dist/view/render/adopt-plan.js.map +1 -0
  224. package/dist/view/render/adopt.d.ts +3 -0
  225. package/dist/view/render/adopt.js +269 -0
  226. package/dist/view/render/adopt.js.map +1 -0
  227. package/dist/view/render/attr-parts.d.ts +61 -0
  228. package/dist/view/render/attr-parts.js +229 -0
  229. package/dist/view/render/attr-parts.js.map +1 -0
  230. package/dist/view/render/child-part.d.ts +51 -0
  231. package/dist/view/render/child-part.js +170 -0
  232. package/dist/view/render/child-part.js.map +1 -0
  233. package/dist/view/render/dev-check.d.ts +12 -0
  234. package/dist/view/render/dev-check.js +122 -0
  235. package/dist/view/render/dev-check.js.map +1 -0
  236. package/dist/view/render/hook-part.d.ts +3 -0
  237. package/dist/view/render/hook-part.js +20 -0
  238. package/dist/view/render/hook-part.js.map +1 -0
  239. package/dist/view/render/hooks.d.ts +40 -0
  240. package/dist/view/render/hooks.js +46 -0
  241. package/dist/view/render/hooks.js.map +1 -0
  242. package/dist/view/render/hydrate.d.ts +10 -0
  243. package/dist/view/render/hydrate.js +33 -0
  244. package/dist/view/render/hydrate.js.map +1 -0
  245. package/dist/view/render/instance.d.ts +33 -0
  246. package/dist/view/render/instance.js +107 -0
  247. package/dist/view/render/instance.js.map +1 -0
  248. package/dist/view/render/list.d.ts +20 -0
  249. package/dist/view/render/list.js +156 -0
  250. package/dist/view/render/list.js.map +1 -0
  251. package/dist/view/render/mismatch.d.ts +10 -0
  252. package/dist/view/render/mismatch.js +53 -0
  253. package/dist/view/render/mismatch.js.map +1 -0
  254. package/dist/view/render/nodes.d.ts +10 -0
  255. package/dist/view/render/nodes.js +37 -0
  256. package/dist/view/render/nodes.js.map +1 -0
  257. package/dist/view/render/place.d.ts +18 -0
  258. package/dist/view/render/place.js +69 -0
  259. package/dist/view/render/place.js.map +1 -0
  260. package/dist/view/render/plan.d.ts +26 -0
  261. package/dist/view/render/plan.js +124 -0
  262. package/dist/view/render/plan.js.map +1 -0
  263. package/dist/view/render/raw.d.ts +18 -0
  264. package/dist/view/render/raw.js +68 -0
  265. package/dist/view/render/raw.js.map +1 -0
  266. package/dist/view/render/render.d.ts +12 -0
  267. package/dist/view/render/render.js +60 -0
  268. package/dist/view/render/render.js.map +1 -0
  269. package/dist/view/render/reorder.d.ts +4 -0
  270. package/dist/view/render/reorder.js +101 -0
  271. package/dist/view/render/reorder.js.map +1 -0
  272. package/dist/view/render/rows.d.ts +23 -0
  273. package/dist/view/render/rows.js +95 -0
  274. package/dist/view/render/rows.js.map +1 -0
  275. package/dist/view/render/seen.d.ts +11 -0
  276. package/dist/view/render/seen.js +17 -0
  277. package/dist/view/render/seen.js.map +1 -0
  278. package/dist/view/render/values.d.ts +29 -0
  279. package/dist/view/render/values.js +13 -0
  280. package/dist/view/render/values.js.map +1 -0
  281. package/dist/view/render/warn.d.ts +14 -0
  282. package/dist/view/render/warn.js +69 -0
  283. package/dist/view/render/warn.js.map +1 -0
  284. package/dist/view/server/component.d.ts +9 -0
  285. package/dist/view/server/component.js +42 -0
  286. package/dist/view/server/component.js.map +1 -0
  287. package/dist/view/server/escape.d.ts +10 -0
  288. package/dist/view/server/escape.js +34 -0
  289. package/dist/view/server/escape.js.map +1 -0
  290. package/dist/view/server/index.d.ts +28 -0
  291. package/dist/view/server/index.js +72 -0
  292. package/dist/view/server/index.js.map +1 -0
  293. package/dist/view/server/sha256.d.ts +2 -0
  294. package/dist/view/server/sha256.js +75 -0
  295. package/dist/view/server/sha256.js.map +1 -0
  296. package/dist/view/server/tags.d.ts +57 -0
  297. package/dist/view/server/tags.js +121 -0
  298. package/dist/view/server/tags.js.map +1 -0
  299. package/dist/view/server/values.d.ts +16 -0
  300. package/dist/view/server/values.js +86 -0
  301. package/dist/view/server/values.js.map +1 -0
  302. package/dist/view/server/writer.d.ts +16 -0
  303. package/dist/view/server/writer.js +155 -0
  304. package/dist/view/server/writer.js.map +1 -0
  305. package/dist/view/styles.d.ts +25 -0
  306. package/dist/view/styles.js +58 -0
  307. package/dist/view/styles.js.map +1 -0
  308. package/dist/view/template-element.d.ts +3 -0
  309. package/dist/view/template-element.js +25 -0
  310. package/dist/view/template-element.js.map +1 -0
  311. package/dist/view/template.d.ts +21 -0
  312. package/dist/view/template.js +30 -0
  313. package/dist/view/template.js.map +1 -0
  314. package/dist/vite.d.ts +45 -6
  315. package/dist/vite.js +150 -25
  316. package/dist/vite.js.map +1 -1
  317. package/package.json +39 -4
  318. package/dist/accessible-name.d.ts +0 -19
  319. package/dist/accessible-name.js +0 -56
  320. package/dist/accessible-name.js.map +0 -1
  321. package/dist/element-directive.d.ts +0 -20
  322. package/dist/element-directive.js +0 -31
  323. package/dist/element-directive.js.map +0 -1
  324. package/dist/invalid.d.ts +0 -21
  325. package/dist/invalid.js +0 -70
  326. package/dist/invalid.js.map +0 -1
  327. package/dist/lit-html-check.d.ts +0 -6
  328. package/dist/lit-html-check.js +0 -48
  329. package/dist/lit-html-check.js.map +0 -1
  330. package/dist/live-boolean.d.ts +0 -22
  331. package/dist/live-boolean.js +0 -34
  332. package/dist/live-boolean.js.map +0 -1
  333. package/dist/styles.d.ts +0 -12
  334. package/dist/styles.js +0 -11
  335. package/dist/styles.js.map +0 -1
  336. package/dist/template-whitespace.d.ts +0 -7
  337. package/dist/template-whitespace.js.map +0 -1
  338. package/dist/templates.d.ts +0 -5
  339. package/dist/templates.js +0 -15
  340. package/dist/templates.js.map +0 -1
  341. package/dist/textarea.d.ts +0 -26
  342. package/dist/textarea.js +0 -85
  343. package/dist/textarea.js.map +0 -1
@@ -0,0 +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"]}
@@ -0,0 +1,18 @@
1
+ import type { Plugin } from 'vite';
2
+ type Fn<H> = H extends {
3
+ handler: infer F;
4
+ } ? F : H;
5
+ type HookFn<K extends keyof Plugin> = Fn<NonNullable<Plugin[K]>>;
6
+ export interface CompilerHooks {
7
+ readonly configResolved: HookFn<'configResolved'>;
8
+ readonly buildStart: HookFn<'buildStart'>;
9
+ readonly transform: HookFn<'transform'>;
10
+ readonly generateBundle: HookFn<'generateBundle'>;
11
+ }
12
+ export interface CompilerSettings {
13
+ readonly sources: readonly string[];
14
+ /** The module to load parse5 from; undefined skips the parse5 check. */
15
+ readonly parse5: string | undefined;
16
+ }
17
+ export declare function createCompiler(settings: CompilerSettings): CompilerHooks;
18
+ export {};
@@ -0,0 +1,186 @@
1
+ // The template compiler's build hooks (view/01-templates.md "Compiled",
2
+ // view/09-template-rules.md), loaded lazily by the plugin shell in ../vite.ts on the first
3
+ // `vite build` hook, so the preset stays loadable from any vite.config.ts:
4
+ // - `transform` (the shell is enforce: 'pre', so positions are the author's own source,
5
+ // TypeScript included, parsed by Rolldown's `this.parse`): rewrites each `html` call site
6
+ // of the configured sources into `compiled(<hoisted template object>, [values…])`,
7
+ // dependencies in node_modules included. Template rule violations, and references it
8
+ // can't follow, fail the build with a code frame.
9
+ // - `generateBundle`: fails when an uncompiled `html` survived in a chunk anyway (re-exports
10
+ // across modules, dynamic imports): the guarantee that the `#prepare` stub is never hit.
11
+ import { join, relative } from 'node:path';
12
+ import { fileURLToPath } from 'node:url';
13
+ import { CompileError, compileModule } from './compile.js';
14
+ import { loadParse5 } from './parse5-check.js';
15
+ import { findUses, htmlImports } from './scan.js';
16
+ import { Lines } from './source.js';
17
+ /** Core's own view modules: always sources (core-internal templates, tests). */
18
+ const VIEW = ['index', 'template'].flatMap((name) => ['.ts', '.js'].map((ext) => fileURLToPath(new URL(`../view/${name}${ext}`, import.meta.url))));
19
+ /** template.ts's symbol description: the module defining `html`, in any copy of core. */
20
+ const DEFINES_HTML = /Symbol\(['"]gyral\.template['"]\)/;
21
+ const SCRIPT = /\.[cm]?[jt]sx?$/;
22
+ const langOf = (id) => /\.[cm]?tsx$/.test(id) ? 'tsx' : /\.[cm]?ts$/.test(id) ? 'ts' : id.endsWith('x') ? 'jsx' : 'js';
23
+ /**
24
+ * Whether an environment resolves core's `#view-dev` to its development module: the
25
+ * `development` condition is listed, or Vite's `development|production` placeholder is and
26
+ * the build isn't a production one. Exactly then the client keeps template ids (01).
27
+ */
28
+ function developmentBuild(config) {
29
+ const { conditions } = config.resolve;
30
+ return (conditions.includes('development') ||
31
+ (!config.isProduction && conditions.includes('development|production')));
32
+ }
33
+ const CANT_FOLLOW = `This use of html can't be compiled: the template compiler rewrites only html\`…\` tagged ` +
34
+ `templates whose tag is the imported html itself (or ns.html for import * as ns). ` +
35
+ `Aliasing it, passing it around or calling it as a function would reach the runtime ` +
36
+ `template preparer, which builds made with the Gyral preset leave out. Write html\`…\` at ` +
37
+ `the call site (view/01-templates.md "Compiled").`;
38
+ export function createCompiler(settings) {
39
+ const { sources } = settings;
40
+ /** Per environment (client, ssr, …): Vite may build them with one plugin instance. */
41
+ const states = new WeakMap();
42
+ const global = {};
43
+ let root = '';
44
+ let treeshake = true;
45
+ let info = () => undefined;
46
+ let parse5;
47
+ function stateOf(env) {
48
+ const key = env ?? global;
49
+ let state = states.get(key);
50
+ if (state === undefined) {
51
+ state = { sourceIds: new Set(VIEW), definers: new Set(), seen: new Map() };
52
+ states.set(key, state);
53
+ }
54
+ return state;
55
+ }
56
+ /** parse5, loaded once; the notice when it is missing is printed once too. */
57
+ function loadOnce() {
58
+ const specifier = settings.parse5;
59
+ if (specifier === undefined)
60
+ return undefined;
61
+ if (parse5 === undefined) {
62
+ parse5 = { module: loadParse5(specifier, root) };
63
+ if (parse5.module === undefined) {
64
+ info(`gyral: ${specifier} is not installed, so the template compiler skips its extra ` +
65
+ `rule 7 check (the normalizer's own check still runs). To get it: pnpm add -D ` +
66
+ `parse5 (view/09-template-rules.md).`);
67
+ }
68
+ }
69
+ return parse5.module;
70
+ }
71
+ return {
72
+ configResolved(config) {
73
+ root = config.root;
74
+ treeshake = config.build.rolldownOptions.treeshake !== false;
75
+ info = (message) => {
76
+ config.logger.info(message);
77
+ };
78
+ },
79
+ async buildStart() {
80
+ states.delete(this.environment);
81
+ const state = stateOf(this.environment);
82
+ for (const source of sources) {
83
+ const resolved = await this.resolve(source, join(root, 'index.html'));
84
+ if (resolved !== null)
85
+ state.sourceIds.add(resolved.id);
86
+ }
87
+ loadOnce();
88
+ },
89
+ async transform(code, id, opts) {
90
+ if (id.startsWith('\0') || !SCRIPT.test(id))
91
+ return null;
92
+ const env = this.environment;
93
+ const state = stateOf(env);
94
+ if (DEFINES_HTML.test(code))
95
+ state.definers.add(id);
96
+ if (state.sourceIds.has(id))
97
+ return null;
98
+ let program;
99
+ try {
100
+ program = this.parse(code, { lang: langOf(id) });
101
+ }
102
+ catch {
103
+ return null; // not ours to report: the bundler fails on it with a better message
104
+ }
105
+ const { imports, reexports } = htmlImports(program);
106
+ if (imports.length === 0 && reexports.length === 0)
107
+ return null;
108
+ const isSource = async (specifier) => {
109
+ if (sources.includes(specifier))
110
+ return true;
111
+ const resolved = await this.resolve(specifier, id);
112
+ return resolved !== null && state.sourceIds.has(resolved.id);
113
+ };
114
+ const lines = new Lines(code);
115
+ const file = relative(root, id);
116
+ const where = (node) => `${file}:${String(lines.position(node.start).line)}`;
117
+ for (const r of reexports) {
118
+ if (!(await isSource(r.specifier)))
119
+ continue;
120
+ this.warn(`${where(r.node)}: re-exporting html. The template compiler only follows html ` +
121
+ `imported straight from ${r.specifier}: templates written with this re-export stay ` +
122
+ `uncompiled and fail the build. Import html from ${r.specifier} instead.`);
123
+ }
124
+ const matched = [];
125
+ for (const binding of imports)
126
+ if (await isSource(binding.specifier))
127
+ matched.push(binding);
128
+ if (matched.length === 0)
129
+ return null;
130
+ const fail = (start, end, message) => this.error({
131
+ message,
132
+ id,
133
+ loc: { file: id, ...lines.position(start) },
134
+ frame: lines.frame(start, end),
135
+ });
136
+ const { sites, leftovers } = findUses(program, matched);
137
+ for (const l of leftovers) {
138
+ if (l.exported)
139
+ this.warn(`${where(l.node)}: re-exporting html; its users stay uncompiled.`);
140
+ else
141
+ fail(l.node.start, l.node.end, CANT_FOLLOW);
142
+ }
143
+ if (sites.length === 0)
144
+ return null;
145
+ const ssr = opts?.ssr === true || env.config.consumer === 'server';
146
+ try {
147
+ return compileModule({
148
+ lines,
149
+ id,
150
+ file,
151
+ sites,
152
+ ssr,
153
+ ids: ssr || developmentBuild(env.config),
154
+ parse5: loadOnce(),
155
+ seen: state.seen,
156
+ });
157
+ }
158
+ catch (error) {
159
+ if (error instanceof CompileError)
160
+ return fail(error.start, error.end, error.message);
161
+ throw error;
162
+ }
163
+ },
164
+ generateBundle(_, bundle) {
165
+ const state = stateOf(this.environment);
166
+ // Without tree-shaking every export is rendered, used or not.
167
+ if (state.definers.size === 0 || !treeshake)
168
+ return;
169
+ for (const chunk of Object.values(bundle)) {
170
+ if (chunk.type !== 'chunk')
171
+ continue;
172
+ for (const [id, module] of Object.entries(chunk.modules)) {
173
+ if (!state.definers.has(id) || !module.renderedExports.includes('html'))
174
+ continue;
175
+ this.error(`gyral: an uncompiled html template remains in ${chunk.fileName}: something uses ` +
176
+ `html from ${relative(root, id)} in a way the template compiler can't see (a ` +
177
+ `re-export, a dynamic import, or a module it doesn't process). With the ` +
178
+ `gyral-compiled condition the runtime preparer is left out, so that template ` +
179
+ `would throw. Import html straight from '@gyral/core' where you write templates ` +
180
+ `(view/01-templates.md "Compiled").`);
181
+ }
182
+ }
183
+ },
184
+ };
185
+ }
186
+ //# sourceMappingURL=hooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../src/compiler/hooks.ts"],"names":[],"mappings":"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","sourcesContent":["// The template compiler's build hooks (view/01-templates.md \"Compiled\",\n// view/09-template-rules.md), loaded lazily by the plugin shell in ../vite.ts on the first\n// `vite build` hook, so the preset stays loadable from any vite.config.ts:\n// - `transform` (the shell is enforce: 'pre', so positions are the author's own source,\n// TypeScript included, parsed by Rolldown's `this.parse`): rewrites each `html` call site\n// of the configured sources into `compiled(<hoisted template object>, [values…])`,\n// dependencies in node_modules included. Template rule violations, and references it\n// can't follow, fail the build with a code frame.\n// - `generateBundle`: fails when an uncompiled `html` survived in a chunk anyway (re-exports\n// across modules, dynamic imports): the guarantee that the `#prepare` stub is never hit.\nimport { join, relative } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { Plugin } from 'vite';\nimport type { Node } from './ast.js';\nimport { CompileError, compileModule } from './compile.js';\nimport { loadParse5, type Parse5 } from './parse5-check.js';\nimport { findUses, htmlImports } from './scan.js';\nimport { Lines } from './source.js';\n\ntype Fn<H> = H extends { handler: infer F } ? F : H;\ntype HookFn<K extends keyof Plugin> = Fn<NonNullable<Plugin[K]>>;\n\nexport interface CompilerHooks {\n readonly configResolved: HookFn<'configResolved'>;\n readonly buildStart: HookFn<'buildStart'>;\n readonly transform: HookFn<'transform'>;\n readonly generateBundle: HookFn<'generateBundle'>;\n}\n\nexport interface CompilerSettings {\n readonly sources: readonly string[];\n /** The module to load parse5 from; undefined skips the parse5 check. */\n readonly parse5: string | undefined;\n}\n\n/** Core's own view modules: always sources (core-internal templates, tests). */\nconst VIEW = ['index', 'template'].flatMap((name) =>\n ['.ts', '.js'].map((ext) => fileURLToPath(new URL(`../view/${name}${ext}`, import.meta.url))),\n);\n/** template.ts's symbol description: the module defining `html`, in any copy of core. */\nconst DEFINES_HTML = /Symbol\\(['\"]gyral\\.template['\"]\\)/;\nconst SCRIPT = /\\.[cm]?[jt]sx?$/;\n\ninterface BuildState {\n readonly sourceIds: Set<string>;\n readonly definers: Set<string>;\n readonly seen: Map<string, { readonly strings: string; readonly loc: string }>;\n}\n\nconst 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/**\n * Whether an environment resolves core's `#view-dev` to its development module: the\n * `development` condition is listed, or Vite's `development|production` placeholder is and\n * the build isn't a production one. Exactly then the client keeps template ids (01).\n */\nfunction developmentBuild(config: {\n readonly isProduction: boolean;\n readonly resolve: { readonly conditions: readonly string[] };\n}): boolean {\n const { conditions } = config.resolve;\n return (\n conditions.includes('development') ||\n (!config.isProduction && conditions.includes('development|production'))\n );\n}\n\nconst CANT_FOLLOW =\n `This use of html can't be compiled: the template compiler rewrites only html\\`…\\` tagged ` +\n `templates whose tag is the imported html itself (or ns.html for import * as ns). ` +\n `Aliasing it, passing it around or calling it as a function would reach the runtime ` +\n `template preparer, which builds made with the Gyral preset leave out. Write html\\`…\\` at ` +\n `the call site (view/01-templates.md \"Compiled\").`;\n\nexport function createCompiler(settings: CompilerSettings): CompilerHooks {\n const { sources } = settings;\n /** Per environment (client, ssr, …): Vite may build them with one plugin instance. */\n const states = new WeakMap<object, BuildState>();\n const global = {};\n let root = '';\n let treeshake = true;\n let info: (message: string) => void = () => undefined;\n let parse5: { readonly module: Parse5 | undefined } | undefined;\n\n function stateOf(env: object | undefined): BuildState {\n const key = env ?? global;\n let state = states.get(key);\n if (state === undefined) {\n state = { sourceIds: new Set(VIEW), definers: new Set(), seen: new Map() };\n states.set(key, state);\n }\n return state;\n }\n\n /** parse5, loaded once; the notice when it is missing is printed once too. */\n function loadOnce(): Parse5 | undefined {\n const specifier = settings.parse5;\n if (specifier === undefined) return undefined;\n if (parse5 === undefined) {\n parse5 = { module: loadParse5(specifier, root) };\n if (parse5.module === undefined) {\n info(\n `gyral: ${specifier} is not installed, so the template compiler skips its extra ` +\n `rule 7 check (the normalizer's own check still runs). To get it: pnpm add -D ` +\n `parse5 (view/09-template-rules.md).`,\n );\n }\n }\n return parse5.module;\n }\n\n return {\n configResolved(config) {\n root = config.root;\n treeshake = config.build.rolldownOptions.treeshake !== false;\n info = (message) => {\n config.logger.info(message);\n };\n },\n\n async buildStart() {\n states.delete(this.environment);\n const state = stateOf(this.environment);\n for (const source of sources) {\n const resolved = await this.resolve(source, join(root, 'index.html'));\n if (resolved !== null) state.sourceIds.add(resolved.id);\n }\n loadOnce();\n },\n\n async transform(code, id, opts) {\n if (id.startsWith('\\0') || !SCRIPT.test(id)) return null;\n const env = this.environment;\n const state = stateOf(env);\n if (DEFINES_HTML.test(code)) state.definers.add(id);\n if (state.sourceIds.has(id)) return null;\n let program: Node;\n try {\n program = this.parse(code, { lang: langOf(id) }) as unknown as Node;\n } catch {\n return null; // not ours to report: the bundler fails on it with a better message\n }\n const { imports, reexports } = htmlImports(program);\n if (imports.length === 0 && reexports.length === 0) return null;\n const isSource = async (specifier: string): Promise<boolean> => {\n if (sources.includes(specifier)) return true;\n const resolved = await this.resolve(specifier, id);\n return resolved !== null && state.sourceIds.has(resolved.id);\n };\n const lines = new Lines(code);\n const file = relative(root, id);\n const where = (node: Node): string => `${file}:${String(lines.position(node.start).line)}`;\n for (const r of reexports) {\n if (!(await isSource(r.specifier))) continue;\n this.warn(\n `${where(r.node)}: re-exporting html. The template compiler only follows html ` +\n `imported straight from ${r.specifier}: templates written with this re-export stay ` +\n `uncompiled and fail the build. Import html from ${r.specifier} instead.`,\n );\n }\n const matched = [];\n for (const binding of imports) if (await isSource(binding.specifier)) matched.push(binding);\n if (matched.length === 0) return null;\n const fail = (start: number, end: number, message: string): never =>\n this.error({\n message,\n id,\n loc: { file: id, ...lines.position(start) },\n frame: lines.frame(start, end),\n });\n const { sites, leftovers } = findUses(program, matched);\n for (const l of leftovers) {\n if (l.exported)\n this.warn(`${where(l.node)}: re-exporting html; its users stay uncompiled.`);\n else fail(l.node.start, l.node.end, CANT_FOLLOW);\n }\n if (sites.length === 0) return null;\n const ssr = opts?.ssr === true || env.config.consumer === 'server';\n try {\n return compileModule({\n lines,\n id,\n file,\n sites,\n ssr,\n ids: ssr || developmentBuild(env.config),\n parse5: loadOnce(),\n seen: state.seen,\n });\n } catch (error) {\n if (error instanceof CompileError) return fail(error.start, error.end, error.message);\n throw error;\n }\n },\n\n generateBundle(_, bundle) {\n const state = stateOf(this.environment);\n // Without tree-shaking every export is rendered, used or not.\n if (state.definers.size === 0 || !treeshake) return;\n for (const chunk of Object.values(bundle)) {\n if (chunk.type !== 'chunk') continue;\n for (const [id, module] of Object.entries(chunk.modules)) {\n if (!state.definers.has(id) || !module.renderedExports.includes('html')) continue;\n this.error(\n `gyral: an uncompiled html template remains in ${chunk.fileName}: something uses ` +\n `html from ${relative(root, id)} in a way the template compiler can't see (a ` +\n `re-export, a dynamic import, or a module it doesn't process). With the ` +\n `gyral-compiled condition the runtime preparer is left out, so that template ` +\n `would throw. Import html straight from '@gyral/core' where you write templates ` +\n `(view/01-templates.md \"Compiled\").`,\n );\n }\n }\n },\n };\n}\n"]}
@@ -0,0 +1,21 @@
1
+ import { type Shape, type TemplateObject } from '../view/index.js';
2
+ /** The slice of parse5's API the check uses (default tree adapter). */
3
+ export interface Parse5 {
4
+ parseFragment(html: string): Parse5Node;
5
+ }
6
+ interface Parse5Node {
7
+ readonly nodeName: string;
8
+ readonly tagName?: string;
9
+ readonly childNodes?: readonly Parse5Node[];
10
+ readonly content?: Parse5Node;
11
+ }
12
+ /**
13
+ * Loads parse5 (`specifier`) as resolved from @gyral/core, else from the app's `root`;
14
+ * undefined when neither has it. `require` (Node loads ES modules with it too) rather than
15
+ * `import()`: when core runs from source, this module is loaded by a Vite module runner that
16
+ * is closed by the time the build starts.
17
+ */
18
+ export declare function loadParse5(specifier: string, root: string): Parse5 | undefined;
19
+ /** Rule 7's error when parse5 builds a different tree than `shape`; undefined if it agrees. */
20
+ export declare function checkWithParse5(parse5: Parse5, template: TemplateObject, shape: Shape): Error | undefined;
21
+ export {};
@@ -0,0 +1,55 @@
1
+ // Rule 7 at build time with parse5 (view/09-template-rules.md "How rule 7 is checked"): a
2
+ // spec-compliant HTML parser parses each template's HTML as <template> content, exactly like
3
+ // the runtime path's `<template>.innerHTML`, and its tree is compared with the shape the
4
+ // normalizer computed paths for (view/normalize/shape.ts, shared with the browser check).
5
+ //
6
+ // parse5 is an optional peer dependency of @gyral/core, loaded at build time by the compiler
7
+ // only: it never reaches browser or server bundles. Without it the build still runs
8
+ // the normalizer's structural rule 7 check and skips this one.
9
+ import { createRequire } from 'node:module';
10
+ import { join } from 'node:path';
11
+ import { repairError, shapeMismatch, } from '../view/index.js';
12
+ const isParse5 = (value) => typeof value === 'object' &&
13
+ value !== null &&
14
+ typeof value.parseFragment === 'function';
15
+ /**
16
+ * Loads parse5 (`specifier`) as resolved from @gyral/core, else from the app's `root`;
17
+ * undefined when neither has it. `require` (Node loads ES modules with it too) rather than
18
+ * `import()`: when core runs from source, this module is loaded by a Vite module runner that
19
+ * is closed by the time the build starts.
20
+ */
21
+ export function loadParse5(specifier, root) {
22
+ for (const base of [import.meta.url, join(root, 'package.json')]) {
23
+ try {
24
+ const module = createRequire(base)(specifier);
25
+ if (isParse5(module))
26
+ return module;
27
+ }
28
+ catch {
29
+ // not resolvable from here
30
+ }
31
+ }
32
+ return undefined;
33
+ }
34
+ function toShape(nodes) {
35
+ return nodes.map((node) => {
36
+ if (node.nodeName === '#text')
37
+ return '#text';
38
+ if (node.nodeName === '#comment')
39
+ return '#comment';
40
+ const inner = node.tagName === 'template' ? node.content?.childNodes : node.childNodes;
41
+ return [(node.tagName ?? node.nodeName).toLowerCase(), toShape(inner ?? [])];
42
+ });
43
+ }
44
+ /** Rule 7's error when parse5 builds a different tree than `shape`; undefined if it agrees. */
45
+ export function checkWithParse5(parse5, template, shape) {
46
+ // Page shells (document-level tags) are written by the server and never parsed as a
47
+ // fragment; fragment parsing would drop their <html>/<head>/<body> tags.
48
+ if (template.server)
49
+ return undefined;
50
+ const problem = shapeMismatch(shape, toShape(parse5.parseFragment(template.html).childNodes ?? []));
51
+ return problem === undefined
52
+ ? undefined
53
+ : repairError(template, 'The HTML parser (parse5)', problem);
54
+ }
55
+ //# sourceMappingURL=parse5-check.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse5-check.js","sourceRoot":"","sources":["../../src/compiler/parse5-check.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAC1F,6FAA6F;AAC7F,yFAAyF;AACzF,0FAA0F;AAC1F,EAAE;AACF,6FAA6F;AAC7F,oFAAoF;AACpF,+DAA+D;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EACL,WAAW,EACX,aAAa,GAId,MAAM,kBAAkB,CAAC;AAc1B,MAAM,QAAQ,GAAG,CAAC,KAAc,EAAmB,EAAE,CACnD,OAAO,KAAK,KAAK,QAAQ;IACzB,KAAK,KAAK,IAAI;IACd,OAAQ,KAAqC,CAAC,aAAa,KAAK,UAAU,CAAC;AAE7E;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,SAAiB,EAAE,IAAY;IACxD,KAAK,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC,EAAE,CAAC;QACjE,IAAI,CAAC;YACH,MAAM,MAAM,GAAY,aAAa,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC;YACvD,IAAI,QAAQ,CAAC,MAAM,CAAC;gBAAE,OAAO,MAAM,CAAC;QACtC,CAAC;QAAC,MAAM,CAAC;YACP,2BAA2B;QAC7B,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,OAAO,CAAC,KAA4B;IAC3C,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAa,EAAE;QACnC,IAAI,IAAI,CAAC,QAAQ,KAAK,OAAO;YAAE,OAAO,OAAO,CAAC;QAC9C,IAAI,IAAI,CAAC,QAAQ,KAAK,UAAU;YAAE,OAAO,UAAU,CAAC;QACpD,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,KAAK,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC;QACvF,OAAO,CAAC,CAAC,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,EAAE,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC;IAC/E,CAAC,CAAC,CAAC;AACL,CAAC;AAED,+FAA+F;AAC/F,MAAM,UAAU,eAAe,CAC7B,MAAc,EACd,QAAwB,EACxB,KAAY;IAEZ,oFAAoF;IACpF,yEAAyE;IACzE,IAAI,QAAQ,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IACtC,MAAM,OAAO,GAAG,aAAa,CAC3B,KAAK,EACL,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,UAAU,IAAI,EAAE,CAAC,CAC9D,CAAC;IACF,OAAO,OAAO,KAAK,SAAS;QAC1B,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,WAAW,CAAC,QAAQ,EAAE,0BAA0B,EAAE,OAAO,CAAC,CAAC;AACjE,CAAC","sourcesContent":["// Rule 7 at build time with parse5 (view/09-template-rules.md \"How rule 7 is checked\"): a\n// spec-compliant HTML parser parses each template's HTML as <template> content, exactly like\n// the runtime path's `<template>.innerHTML`, and its tree is compared with the shape the\n// normalizer computed paths for (view/normalize/shape.ts, shared with the browser check).\n//\n// parse5 is an optional peer dependency of @gyral/core, loaded at build time by the compiler\n// only: it never reaches browser or server bundles. Without it the build still runs\n// the normalizer's structural rule 7 check and skips this one.\nimport { createRequire } from 'node:module';\nimport { join } from 'node:path';\nimport {\n repairError,\n shapeMismatch,\n type Shape,\n type ShapeNode,\n type TemplateObject,\n} from '../view/index.js';\n\n/** The slice of parse5's API the check uses (default tree adapter). */\nexport interface Parse5 {\n parseFragment(html: string): Parse5Node;\n}\n\ninterface Parse5Node {\n readonly nodeName: string;\n readonly tagName?: string;\n readonly childNodes?: readonly Parse5Node[];\n readonly content?: Parse5Node;\n}\n\nconst isParse5 = (value: unknown): value is Parse5 =>\n typeof value === 'object' &&\n value !== null &&\n typeof (value as { parseFragment?: unknown }).parseFragment === 'function';\n\n/**\n * Loads parse5 (`specifier`) as resolved from @gyral/core, else from the app's `root`;\n * undefined when neither has it. `require` (Node loads ES modules with it too) rather than\n * `import()`: when core runs from source, this module is loaded by a Vite module runner that\n * is closed by the time the build starts.\n */\nexport function loadParse5(specifier: string, root: string): Parse5 | undefined {\n for (const base of [import.meta.url, join(root, 'package.json')]) {\n try {\n const module: unknown = createRequire(base)(specifier);\n if (isParse5(module)) return module;\n } catch {\n // not resolvable from here\n }\n }\n return undefined;\n}\n\nfunction toShape(nodes: readonly Parse5Node[]): Shape {\n return nodes.map((node): ShapeNode => {\n if (node.nodeName === '#text') return '#text';\n if (node.nodeName === '#comment') return '#comment';\n const inner = node.tagName === 'template' ? node.content?.childNodes : node.childNodes;\n return [(node.tagName ?? node.nodeName).toLowerCase(), toShape(inner ?? [])];\n });\n}\n\n/** Rule 7's error when parse5 builds a different tree than `shape`; undefined if it agrees. */\nexport function checkWithParse5(\n parse5: Parse5,\n template: TemplateObject,\n shape: Shape,\n): Error | undefined {\n // Page shells (document-level tags) are written by the server and never parsed as a\n // fragment; fragment parsing would drop their <html>/<head>/<body> tags.\n if (template.server) return undefined;\n const problem = shapeMismatch(\n shape,\n toShape(parse5.parseFragment(template.html).childNodes ?? []),\n );\n return problem === undefined\n ? undefined\n : repairError(template, 'The HTML parser (parse5)', problem);\n}\n"]}
@@ -0,0 +1,31 @@
1
+ import { type Node } from './ast.js';
2
+ /** `import { html as local } from 'specifier'`, or `import * as local from 'specifier'`. */
3
+ export interface HtmlImport {
4
+ readonly local: string;
5
+ readonly namespace: boolean;
6
+ readonly specifier: string;
7
+ }
8
+ export interface Imports {
9
+ readonly imports: readonly HtmlImport[];
10
+ /** `export { html } from 'specifier'` (its node, for a code frame). */
11
+ readonly reexports: readonly {
12
+ readonly node: Node;
13
+ readonly specifier: string;
14
+ }[];
15
+ }
16
+ export interface Uses {
17
+ /** TaggedTemplateExpression nodes whose tag is a matching binding. */
18
+ readonly sites: readonly {
19
+ readonly node: Node;
20
+ readonly binding: HtmlImport;
21
+ }[];
22
+ /** Other references; `exported`: an `export { html }` specifier. */
23
+ readonly leftovers: readonly {
24
+ readonly node: Node;
25
+ readonly exported: boolean;
26
+ }[];
27
+ }
28
+ /** Imports of `html` (named) and namespace imports, plus `export { html } from` re-exports. */
29
+ export declare function htmlImports(program: Node): Imports;
30
+ /** Every use of `bindings` in `program`, skipping names that a nested scope redeclares. */
31
+ export declare function findUses(program: Node, bindings: readonly HtmlImport[]): Uses;
@@ -0,0 +1,152 @@
1
+ // Finds a module's `html` call sites for the template compiler (view/01-templates.md
2
+ // "Compiled"). Two steps, because matching an import against the configured sources may need
3
+ // module resolution (async, in the plugin): `htmlImports` lists the candidate imports, and
4
+ // `findUses` walks the module, scope-aware, for every reference to the matching bindings:
5
+ // - html`…` (or ns.html`…` for `import * as ns`) is a call site;
6
+ // - any other reference (`const h = html`, `html(strings)`, `ns[x]`, `{ html } = ns`) is a
7
+ // leftover the compiler can't follow: an error, since it would reach the runtime preparer;
8
+ // - `export { html }` re-exports it: a warning here, an error in generateBundle when an
9
+ // uncompiled `html` survives in the bundle.
10
+ import { children, nodeAt, nodesAt, scopeNames } from './ast.js';
11
+ const nameOf = (node) => node === undefined
12
+ ? undefined
13
+ : node.type === 'Identifier'
14
+ ? node['name']
15
+ : node.type === 'Literal' && typeof node['value'] === 'string'
16
+ ? node['value']
17
+ : undefined;
18
+ const specifierOf = (node) => nameOf(nodeAt(node, 'source'));
19
+ const isValue = (node) => node['importKind'] !== 'type' && node['exportKind'] !== 'type';
20
+ /** Imports of `html` (named) and namespace imports, plus `export { html } from` re-exports. */
21
+ export function htmlImports(program) {
22
+ const imports = [];
23
+ const reexports = [];
24
+ for (const statement of nodesAt(program, 'body')) {
25
+ const specifier = specifierOf(statement);
26
+ if (specifier === undefined || !isValue(statement))
27
+ continue;
28
+ if (statement.type === 'ImportDeclaration') {
29
+ for (const s of nodesAt(statement, 'specifiers')) {
30
+ const local = nameOf(nodeAt(s, 'local'));
31
+ if (local === undefined || !isValue(s))
32
+ continue;
33
+ if (s.type === 'ImportNamespaceSpecifier') {
34
+ imports.push({ local, namespace: true, specifier });
35
+ }
36
+ else if (s.type === 'ImportSpecifier' && nameOf(nodeAt(s, 'imported')) === 'html') {
37
+ imports.push({ local, namespace: false, specifier });
38
+ }
39
+ }
40
+ }
41
+ else if (statement.type === 'ExportNamedDeclaration') {
42
+ const html = nodesAt(statement, 'specifiers').find((s) => isValue(s) && nameOf(nodeAt(s, 'local')) === 'html');
43
+ if (html !== undefined)
44
+ reexports.push({ node: html, specifier });
45
+ }
46
+ }
47
+ return { imports, reexports };
48
+ }
49
+ const unparen = (node) => node?.type === 'ParenthesizedExpression' ? unparen(nodeAt(node, 'expression')) : node;
50
+ /** Every use of `bindings` in `program`, skipping names that a nested scope redeclares. */
51
+ export function findUses(program, bindings) {
52
+ const byName = new Map(bindings.map((b) => [b.local, b]));
53
+ const sites = [];
54
+ const leftovers = [];
55
+ const scopes = [];
56
+ const binding = (node) => {
57
+ const name = node?.type === 'Identifier' ? node['name'] : undefined;
58
+ if (name === undefined || scopes.some((s) => s.has(name)))
59
+ return undefined;
60
+ return byName.get(name);
61
+ };
62
+ /** The binding a tag refers to: `html` itself, or `ns.html`. */
63
+ const tagBinding = (tag) => {
64
+ if (tag?.type === 'Identifier') {
65
+ const b = binding(tag);
66
+ return b?.namespace === false ? b : undefined;
67
+ }
68
+ if (tag?.type !== 'MemberExpression' || tag['computed'] === true)
69
+ return undefined;
70
+ const b = binding(nodeAt(tag, 'object'));
71
+ return b?.namespace === true && nameOf(nodeAt(tag, 'property')) === 'html' ? b : undefined;
72
+ };
73
+ const walkAll = (nodes) => {
74
+ for (const n of nodes)
75
+ walk(n);
76
+ };
77
+ function visit(node) {
78
+ switch (node.type) {
79
+ case 'ImportDeclaration':
80
+ case 'ExportAllDeclaration':
81
+ case 'MetaProperty':
82
+ case 'BreakStatement':
83
+ case 'ContinueStatement':
84
+ return;
85
+ case 'ExportNamedDeclaration':
86
+ if (nodeAt(node, 'source') === undefined) {
87
+ for (const s of nodesAt(node, 'specifiers')) {
88
+ if (binding(nodeAt(s, 'local')) !== undefined)
89
+ leftovers.push({ node: s, exported: true });
90
+ }
91
+ }
92
+ walkAll(nodesAt(node, 'declaration'));
93
+ return;
94
+ case 'TaggedTemplateExpression': {
95
+ const tag = unparen(nodeAt(node, 'tag'));
96
+ const b = tagBinding(tag);
97
+ if (b === undefined)
98
+ break;
99
+ sites.push({ node, binding: b });
100
+ walkAll(nodesAt(nodeAt(node, 'quasi') ?? node, 'expressions'));
101
+ return;
102
+ }
103
+ case 'MemberExpression': {
104
+ const object = nodeAt(node, 'object');
105
+ const b = binding(object);
106
+ const computed = node['computed'] === true;
107
+ if (b !== undefined) {
108
+ // ns.other is fine; ns.html outside a tag, or ns[expr], can't be followed.
109
+ if (!b.namespace || computed || nameOf(nodeAt(node, 'property')) === 'html') {
110
+ leftovers.push({ node, exported: false });
111
+ }
112
+ }
113
+ else
114
+ walkAll(nodesAt(node, 'object'));
115
+ if (computed)
116
+ walkAll(nodesAt(node, 'property'));
117
+ return;
118
+ }
119
+ case 'Property':
120
+ case 'MethodDefinition':
121
+ case 'PropertyDefinition':
122
+ case 'AccessorProperty':
123
+ if (node['computed'] === true)
124
+ walkAll(nodesAt(node, 'key'));
125
+ walkAll(nodesAt(node, 'decorators'));
126
+ walkAll(nodesAt(node, 'value'));
127
+ return;
128
+ case 'LabeledStatement':
129
+ walkAll(nodesAt(node, 'body'));
130
+ return;
131
+ case 'Identifier':
132
+ if (binding(node) !== undefined)
133
+ leftovers.push({ node, exported: false });
134
+ return;
135
+ }
136
+ walkAll(children(node));
137
+ }
138
+ function walk(node) {
139
+ const declared = scopeNames(node)?.filter((name) => byName.has(name));
140
+ if (declared === undefined || declared.length === 0) {
141
+ visit(node);
142
+ return;
143
+ }
144
+ scopes.push(new Set(declared));
145
+ visit(node);
146
+ scopes.pop();
147
+ }
148
+ if (byName.size > 0)
149
+ walkAll(nodesAt(program, 'body'));
150
+ return { sites, leftovers };
151
+ }
152
+ //# sourceMappingURL=scan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan.js","sourceRoot":"","sources":["../../src/compiler/scan.ts"],"names":[],"mappings":"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","sourcesContent":["// Finds a module's `html` call sites for the template compiler (view/01-templates.md\n// \"Compiled\"). Two steps, because matching an import against the configured sources may need\n// module resolution (async, in the plugin): `htmlImports` lists the candidate imports, and\n// `findUses` walks the module, scope-aware, for every reference to the matching bindings:\n// - html`…` (or ns.html`…` for `import * as ns`) is a call site;\n// - any other reference (`const h = html`, `html(strings)`, `ns[x]`, `{ html } = ns`) is a\n// leftover the compiler can't follow: an error, since it would reach the runtime preparer;\n// - `export { html }` re-exports it: a warning here, an error in generateBundle when an\n// uncompiled `html` survives in the bundle.\nimport { children, nodeAt, nodesAt, scopeNames, type Node } from './ast.js';\n\n/** `import { html as local } from 'specifier'`, or `import * as local from 'specifier'`. */\nexport interface HtmlImport {\n readonly local: string;\n readonly namespace: boolean;\n readonly specifier: string;\n}\n\nexport interface Imports {\n readonly imports: readonly HtmlImport[];\n /** `export { html } from 'specifier'` (its node, for a code frame). */\n readonly reexports: readonly { readonly node: Node; readonly specifier: string }[];\n}\n\nexport interface Uses {\n /** TaggedTemplateExpression nodes whose tag is a matching binding. */\n readonly sites: readonly { readonly node: Node; readonly binding: HtmlImport }[];\n /** Other references; `exported`: an `export { html }` specifier. */\n readonly leftovers: readonly { readonly node: Node; readonly exported: boolean }[];\n}\n\nconst nameOf = (node: Node | undefined): string | undefined =>\n node === undefined\n ? undefined\n : node.type === 'Identifier'\n ? (node['name'] as string)\n : node.type === 'Literal' && typeof node['value'] === 'string'\n ? node['value']\n : undefined;\n\nconst specifierOf = (node: Node): string | undefined => nameOf(nodeAt(node, 'source'));\n\nconst isValue = (node: Node): boolean =>\n node['importKind'] !== 'type' && node['exportKind'] !== 'type';\n\n/** Imports of `html` (named) and namespace imports, plus `export { html } from` re-exports. */\nexport function htmlImports(program: Node): Imports {\n const imports: HtmlImport[] = [];\n const reexports: { node: Node; specifier: string }[] = [];\n for (const statement of nodesAt(program, 'body')) {\n const specifier = specifierOf(statement);\n if (specifier === undefined || !isValue(statement)) continue;\n if (statement.type === 'ImportDeclaration') {\n for (const s of nodesAt(statement, 'specifiers')) {\n const local = nameOf(nodeAt(s, 'local'));\n if (local === undefined || !isValue(s)) continue;\n if (s.type === 'ImportNamespaceSpecifier') {\n imports.push({ local, namespace: true, specifier });\n } else if (s.type === 'ImportSpecifier' && nameOf(nodeAt(s, 'imported')) === 'html') {\n imports.push({ local, namespace: false, specifier });\n }\n }\n } else if (statement.type === 'ExportNamedDeclaration') {\n const html = nodesAt(statement, 'specifiers').find(\n (s) => isValue(s) && nameOf(nodeAt(s, 'local')) === 'html',\n );\n if (html !== undefined) reexports.push({ node: html, specifier });\n }\n }\n return { imports, reexports };\n}\n\nconst unparen = (node: Node | undefined): Node | undefined =>\n node?.type === 'ParenthesizedExpression' ? unparen(nodeAt(node, 'expression')) : node;\n\n/** Every use of `bindings` in `program`, skipping names that a nested scope redeclares. */\nexport function findUses(program: Node, bindings: readonly HtmlImport[]): Uses {\n const byName = new Map(bindings.map((b) => [b.local, b]));\n const sites: { node: Node; binding: HtmlImport }[] = [];\n const leftovers: { node: Node; exported: boolean }[] = [];\n const scopes: Set<string>[] = [];\n\n const binding = (node: Node | undefined): HtmlImport | undefined => {\n const name = node?.type === 'Identifier' ? (node['name'] as string) : undefined;\n if (name === undefined || scopes.some((s) => s.has(name))) return undefined;\n return byName.get(name);\n };\n\n /** The binding a tag refers to: `html` itself, or `ns.html`. */\n const tagBinding = (tag: Node | undefined): HtmlImport | undefined => {\n if (tag?.type === 'Identifier') {\n const b = binding(tag);\n return b?.namespace === false ? b : undefined;\n }\n if (tag?.type !== 'MemberExpression' || tag['computed'] === true) return undefined;\n const b = binding(nodeAt(tag, 'object'));\n return b?.namespace === true && nameOf(nodeAt(tag, 'property')) === 'html' ? b : undefined;\n };\n\n const walkAll = (nodes: readonly Node[]): void => {\n for (const n of nodes) walk(n);\n };\n\n function visit(node: Node): void {\n switch (node.type) {\n case 'ImportDeclaration':\n case 'ExportAllDeclaration':\n case 'MetaProperty':\n case 'BreakStatement':\n case 'ContinueStatement':\n return;\n case 'ExportNamedDeclaration':\n if (nodeAt(node, 'source') === undefined) {\n for (const s of nodesAt(node, 'specifiers')) {\n if (binding(nodeAt(s, 'local')) !== undefined)\n leftovers.push({ node: s, exported: true });\n }\n }\n walkAll(nodesAt(node, 'declaration'));\n return;\n case 'TaggedTemplateExpression': {\n const tag = unparen(nodeAt(node, 'tag'));\n const b = tagBinding(tag);\n if (b === undefined) break;\n sites.push({ node, binding: b });\n walkAll(nodesAt(nodeAt(node, 'quasi') ?? node, 'expressions'));\n return;\n }\n case 'MemberExpression': {\n const object = nodeAt(node, 'object');\n const b = binding(object);\n const computed = node['computed'] === true;\n if (b !== undefined) {\n // ns.other is fine; ns.html outside a tag, or ns[expr], can't be followed.\n if (!b.namespace || computed || nameOf(nodeAt(node, 'property')) === 'html') {\n leftovers.push({ node, exported: false });\n }\n } else walkAll(nodesAt(node, 'object'));\n if (computed) walkAll(nodesAt(node, 'property'));\n return;\n }\n case 'Property':\n case 'MethodDefinition':\n case 'PropertyDefinition':\n case 'AccessorProperty':\n if (node['computed'] === true) walkAll(nodesAt(node, 'key'));\n walkAll(nodesAt(node, 'decorators'));\n walkAll(nodesAt(node, 'value'));\n return;\n case 'LabeledStatement':\n walkAll(nodesAt(node, 'body'));\n return;\n case 'Identifier':\n if (binding(node) !== undefined) leftovers.push({ node, exported: false });\n return;\n }\n walkAll(children(node));\n }\n\n function walk(node: Node): void {\n const declared = scopeNames(node)?.filter((name) => byName.has(name));\n if (declared === undefined || declared.length === 0) {\n visit(node);\n return;\n }\n scopes.push(new Set(declared));\n visit(node);\n scopes.pop();\n }\n\n if (byName.size > 0) walkAll(nodesAt(program, 'body'));\n return { sites, leftovers };\n}\n"]}
@@ -0,0 +1,34 @@
1
+ export interface Position {
2
+ /** 1-based. */
3
+ readonly line: number;
4
+ /** 0-based. */
5
+ readonly column: number;
6
+ }
7
+ export declare class Lines {
8
+ readonly code: string;
9
+ private readonly starts;
10
+ constructor(code: string);
11
+ position(offset: number): Position;
12
+ /** Two lines of context around `offset`, with a caret under it (Vite prints it). */
13
+ frame(offset: number, end?: number): string;
14
+ }
15
+ export interface Edit {
16
+ readonly start: number;
17
+ readonly end: number;
18
+ readonly text: string;
19
+ }
20
+ export interface SourceMap {
21
+ readonly version: 3;
22
+ readonly sources: string[];
23
+ readonly names: string[];
24
+ readonly mappings: string;
25
+ }
26
+ /**
27
+ * Applies non-overlapping `edits` to `lines.code` and maps the result back to it: a segment at
28
+ * the start of every output line and at every edit boundary (line-level precision, like
29
+ * magic-string without `hires`).
30
+ */
31
+ export declare function splice(lines: Lines, edits: readonly Edit[], file: string): {
32
+ code: string;
33
+ map: SourceMap;
34
+ };