@vigla/svelte 0.0.0-stage → 5.57.3

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 (373) hide show
  1. package/action.d.ts +2 -0
  2. package/animate.d.ts +2 -0
  3. package/compiler/index.js +43266 -0
  4. package/compiler/index.js.map +1 -0
  5. package/compiler/package.json +3 -0
  6. package/compiler.d.ts +2 -0
  7. package/dist/compiler/diagnostics.d.ts +70 -0
  8. package/dist/compiler/diagnostics.d.ts.map +1 -0
  9. package/dist/compiler/diagnostics.js +166 -0
  10. package/dist/compiler/diagnostics.js.map +1 -0
  11. package/dist/compiler/index.d.ts +72 -0
  12. package/dist/compiler/index.d.ts.map +1 -0
  13. package/dist/compiler/index.js +178 -0
  14. package/dist/compiler/index.js.map +1 -0
  15. package/dist/compiler/options.d.ts +7 -0
  16. package/dist/compiler/options.d.ts.map +1 -0
  17. package/dist/compiler/options.js +126 -0
  18. package/dist/compiler/options.js.map +1 -0
  19. package/dist/compiler/preprocess/decode.d.ts +3 -0
  20. package/dist/compiler/preprocess/decode.d.ts.map +1 -0
  21. package/dist/compiler/preprocess/decode.js +60 -0
  22. package/dist/compiler/preprocess/decode.js.map +1 -0
  23. package/dist/compiler/preprocess/index.d.ts +27 -0
  24. package/dist/compiler/preprocess/index.d.ts.map +1 -0
  25. package/dist/compiler/preprocess/index.js +208 -0
  26. package/dist/compiler/preprocess/index.js.map +1 -0
  27. package/dist/compiler/preprocess/mapped.d.ts +25 -0
  28. package/dist/compiler/preprocess/mapped.d.ts.map +1 -0
  29. package/dist/compiler/preprocess/mapped.js +129 -0
  30. package/dist/compiler/preprocess/mapped.js.map +1 -0
  31. package/dist/compiler/proxy.d.ts +3 -0
  32. package/dist/compiler/proxy.d.ts.map +1 -0
  33. package/dist/compiler/proxy.js +133 -0
  34. package/dist/compiler/proxy.js.map +1 -0
  35. package/dist/entries/action.d.ts +2 -0
  36. package/dist/entries/action.d.ts.map +1 -0
  37. package/dist/entries/action.js +1 -0
  38. package/dist/entries/action.js.map +1 -0
  39. package/dist/entries/animate.d.ts +2 -0
  40. package/dist/entries/animate.d.ts.map +1 -0
  41. package/dist/entries/animate.js +2 -0
  42. package/dist/entries/animate.js.map +1 -0
  43. package/dist/entries/attachments.d.ts +2 -0
  44. package/dist/entries/attachments.d.ts.map +1 -0
  45. package/dist/entries/attachments.js +2 -0
  46. package/dist/entries/attachments.js.map +1 -0
  47. package/dist/entries/context.d.ts +15 -0
  48. package/dist/entries/context.d.ts.map +1 -0
  49. package/dist/entries/context.js +32 -0
  50. package/dist/entries/context.js.map +1 -0
  51. package/dist/entries/easing.d.ts +2 -0
  52. package/dist/entries/easing.d.ts.map +1 -0
  53. package/dist/entries/easing.js +2 -0
  54. package/dist/entries/easing.js.map +1 -0
  55. package/dist/entries/events.d.ts +2 -0
  56. package/dist/entries/events.d.ts.map +1 -0
  57. package/dist/entries/events.js +2 -0
  58. package/dist/entries/events.js.map +1 -0
  59. package/dist/entries/index-server.d.ts +4 -0
  60. package/dist/entries/index-server.d.ts.map +1 -0
  61. package/dist/entries/index-server.js +11 -0
  62. package/dist/entries/index-server.js.map +1 -0
  63. package/dist/entries/index.d.ts +10 -0
  64. package/dist/entries/index.d.ts.map +1 -0
  65. package/dist/entries/index.js +24 -0
  66. package/dist/entries/index.js.map +1 -0
  67. package/dist/entries/internal/client.d.ts +4 -0
  68. package/dist/entries/internal/client.d.ts.map +1 -0
  69. package/dist/entries/internal/client.js +9 -0
  70. package/dist/entries/internal/client.js.map +1 -0
  71. package/dist/entries/internal/disclose-version.d.ts +2 -0
  72. package/dist/entries/internal/disclose-version.d.ts.map +1 -0
  73. package/dist/entries/internal/disclose-version.js +4 -0
  74. package/dist/entries/internal/disclose-version.js.map +1 -0
  75. package/dist/entries/internal/index.d.ts +2 -0
  76. package/dist/entries/internal/index.d.ts.map +1 -0
  77. package/dist/entries/internal/index.js +2 -0
  78. package/dist/entries/internal/index.js.map +1 -0
  79. package/dist/entries/internal/server.d.ts +2 -0
  80. package/dist/entries/internal/server.d.ts.map +1 -0
  81. package/dist/entries/internal/server.js +7 -0
  82. package/dist/entries/internal/server.js.map +1 -0
  83. package/dist/entries/internal/tracing.d.ts +2 -0
  84. package/dist/entries/internal/tracing.d.ts.map +1 -0
  85. package/dist/entries/internal/tracing.js +2 -0
  86. package/dist/entries/internal/tracing.js.map +1 -0
  87. package/dist/entries/motion-server.d.ts +2 -0
  88. package/dist/entries/motion-server.d.ts.map +1 -0
  89. package/dist/entries/motion-server.js +2 -0
  90. package/dist/entries/motion-server.js.map +1 -0
  91. package/dist/entries/motion.d.ts +2 -0
  92. package/dist/entries/motion.d.ts.map +1 -0
  93. package/dist/entries/motion.js +2 -0
  94. package/dist/entries/motion.js.map +1 -0
  95. package/dist/entries/proxy.d.ts +6 -0
  96. package/dist/entries/proxy.d.ts.map +1 -0
  97. package/dist/entries/proxy.js +77 -0
  98. package/dist/entries/proxy.js.map +1 -0
  99. package/dist/entries/reactivity-server.d.ts +2 -0
  100. package/dist/entries/reactivity-server.d.ts.map +1 -0
  101. package/dist/entries/reactivity-server.js +2 -0
  102. package/dist/entries/reactivity-server.js.map +1 -0
  103. package/dist/entries/reactivity.d.ts +2 -0
  104. package/dist/entries/reactivity.d.ts.map +1 -0
  105. package/dist/entries/reactivity.js +2 -0
  106. package/dist/entries/reactivity.js.map +1 -0
  107. package/dist/entries/report.d.ts +3 -0
  108. package/dist/entries/report.d.ts.map +1 -0
  109. package/dist/entries/report.js +66 -0
  110. package/dist/entries/report.js.map +1 -0
  111. package/dist/entries/server.d.ts +8 -0
  112. package/dist/entries/server.d.ts.map +1 -0
  113. package/dist/entries/server.js +48 -0
  114. package/dist/entries/server.js.map +1 -0
  115. package/dist/entries/store-client.d.ts +12 -0
  116. package/dist/entries/store-client.d.ts.map +1 -0
  117. package/dist/entries/store-client.js +63 -0
  118. package/dist/entries/store-client.js.map +1 -0
  119. package/dist/entries/store-server.d.ts +12 -0
  120. package/dist/entries/store-server.d.ts.map +1 -0
  121. package/dist/entries/store-server.js +30 -0
  122. package/dist/entries/store-server.js.map +1 -0
  123. package/dist/entries/store.d.ts +25 -0
  124. package/dist/entries/store.d.ts.map +1 -0
  125. package/dist/entries/store.js +139 -0
  126. package/dist/entries/store.js.map +1 -0
  127. package/dist/entries/transition.d.ts +2 -0
  128. package/dist/entries/transition.d.ts.map +1 -0
  129. package/dist/entries/transition.js +2 -0
  130. package/dist/entries/transition.js.map +1 -0
  131. package/dist/entries/window-server.d.ts +2 -0
  132. package/dist/entries/window-server.d.ts.map +1 -0
  133. package/dist/entries/window-server.js +2 -0
  134. package/dist/entries/window-server.js.map +1 -0
  135. package/dist/entries/window.d.ts +2 -0
  136. package/dist/entries/window.d.ts.map +1 -0
  137. package/dist/entries/window.js +2 -0
  138. package/dist/entries/window.js.map +1 -0
  139. package/dist/front/ast.d.ts +290 -0
  140. package/dist/front/ast.d.ts.map +1 -0
  141. package/dist/front/ast.js +1 -0
  142. package/dist/front/ast.js.map +1 -0
  143. package/dist/front/diagnostics.d.ts +13 -0
  144. package/dist/front/diagnostics.d.ts.map +1 -0
  145. package/dist/front/diagnostics.js +38 -0
  146. package/dist/front/diagnostics.js.map +1 -0
  147. package/dist/front/ignores.d.ts +12 -0
  148. package/dist/front/ignores.d.ts.map +1 -0
  149. package/dist/front/ignores.js +75 -0
  150. package/dist/front/ignores.js.map +1 -0
  151. package/dist/front/index.d.ts +17 -0
  152. package/dist/front/index.d.ts.map +1 -0
  153. package/dist/front/index.js +65 -0
  154. package/dist/front/index.js.map +1 -0
  155. package/dist/front/legacy.d.ts +5 -0
  156. package/dist/front/legacy.d.ts.map +1 -0
  157. package/dist/front/legacy.js +408 -0
  158. package/dist/front/legacy.js.map +1 -0
  159. package/dist/front/locate.d.ts +4 -0
  160. package/dist/front/locate.d.ts.map +1 -0
  161. package/dist/front/locate.js +19 -0
  162. package/dist/front/locate.js.map +1 -0
  163. package/dist/front/lower.d.ts +39 -0
  164. package/dist/front/lower.d.ts.map +1 -0
  165. package/dist/front/lower.js +470 -0
  166. package/dist/front/lower.js.map +1 -0
  167. package/dist/front/parse/attribute.d.ts +12 -0
  168. package/dist/front/parse/attribute.d.ts.map +1 -0
  169. package/dist/front/parse/attribute.js +288 -0
  170. package/dist/front/parse/attribute.js.map +1 -0
  171. package/dist/front/parse/bracket.d.ts +3 -0
  172. package/dist/front/parse/bracket.d.ts.map +1 -0
  173. package/dist/front/parse/bracket.js +102 -0
  174. package/dist/front/parse/bracket.js.map +1 -0
  175. package/dist/front/parse/characters.d.ts +4 -0
  176. package/dist/front/parse/characters.d.ts.map +1 -0
  177. package/dist/front/parse/characters.js +6 -0
  178. package/dist/front/parse/characters.js.map +1 -0
  179. package/dist/front/parse/decode.d.ts +2 -0
  180. package/dist/front/parse/decode.d.ts.map +1 -0
  181. package/dist/front/parse/decode.js +89 -0
  182. package/dist/front/parse/decode.js.map +1 -0
  183. package/dist/front/parse/element.d.ts +3 -0
  184. package/dist/front/parse/element.d.ts.map +1 -0
  185. package/dist/front/parse/element.js +311 -0
  186. package/dist/front/parse/element.js.map +1 -0
  187. package/dist/front/parse/entities.d.ts +2 -0
  188. package/dist/front/parse/entities.d.ts.map +1 -0
  189. package/dist/front/parse/entities.js +2234 -0
  190. package/dist/front/parse/entities.js.map +1 -0
  191. package/dist/front/parse/expression.d.ts +5 -0
  192. package/dist/front/parse/expression.d.ts.map +1 -0
  193. package/dist/front/parse/expression.js +86 -0
  194. package/dist/front/parse/expression.js.map +1 -0
  195. package/dist/front/parse/html.d.ts +8 -0
  196. package/dist/front/parse/html.d.ts.map +1 -0
  197. package/dist/front/parse/html.js +146 -0
  198. package/dist/front/parse/html.js.map +1 -0
  199. package/dist/front/parse/identifier.d.ts +4 -0
  200. package/dist/front/parse/identifier.d.ts.map +1 -0
  201. package/dist/front/parse/identifier.js +24 -0
  202. package/dist/front/parse/identifier.js.map +1 -0
  203. package/dist/front/parse/index.d.ts +13 -0
  204. package/dist/front/parse/index.d.ts.map +1 -0
  205. package/dist/front/parse/index.js +74 -0
  206. package/dist/front/parse/index.js.map +1 -0
  207. package/dist/front/parse/js.d.ts +27 -0
  208. package/dist/front/parse/js.d.ts.map +1 -0
  209. package/dist/front/parse/js.js +241 -0
  210. package/dist/front/parse/js.js.map +1 -0
  211. package/dist/front/parse/options.d.ts +3 -0
  212. package/dist/front/parse/options.d.ts.map +1 -0
  213. package/dist/front/parse/options.js +198 -0
  214. package/dist/front/parse/options.js.map +1 -0
  215. package/dist/front/parse/parser.d.ts +50 -0
  216. package/dist/front/parse/parser.d.ts.map +1 -0
  217. package/dist/front/parse/parser.js +157 -0
  218. package/dist/front/parse/parser.js.map +1 -0
  219. package/dist/front/parse/pattern.d.ts +4 -0
  220. package/dist/front/parse/pattern.d.ts.map +1 -0
  221. package/dist/front/parse/pattern.js +53 -0
  222. package/dist/front/parse/pattern.js.map +1 -0
  223. package/dist/front/parse/script.d.ts +4 -0
  224. package/dist/front/parse/script.d.ts.map +1 -0
  225. package/dist/front/parse/script.js +60 -0
  226. package/dist/front/parse/script.js.map +1 -0
  227. package/dist/front/parse/style.d.ts +7 -0
  228. package/dist/front/parse/style.d.ts.map +1 -0
  229. package/dist/front/parse/style.js +397 -0
  230. package/dist/front/parse/style.js.map +1 -0
  231. package/dist/front/parse/tag.d.ts +3 -0
  232. package/dist/front/parse/tag.d.ts.map +1 -0
  233. package/dist/front/parse/tag.js +591 -0
  234. package/dist/front/parse/tag.js.map +1 -0
  235. package/dist/front/print/css.d.ts +5 -0
  236. package/dist/front/print/css.d.ts.map +1 -0
  237. package/dist/front/print/css.js +234 -0
  238. package/dist/front/print/css.js.map +1 -0
  239. package/dist/front/print/index.d.ts +18 -0
  240. package/dist/front/print/index.d.ts.map +1 -0
  241. package/dist/front/print/index.js +24 -0
  242. package/dist/front/print/index.js.map +1 -0
  243. package/dist/front/print/layout.d.ts +11 -0
  244. package/dist/front/print/layout.d.ts.map +1 -0
  245. package/dist/front/print/layout.js +73 -0
  246. package/dist/front/print/layout.js.map +1 -0
  247. package/dist/front/print/template.d.ts +5 -0
  248. package/dist/front/print/template.d.ts.map +1 -0
  249. package/dist/front/print/template.js +455 -0
  250. package/dist/front/print/template.js.map +1 -0
  251. package/dist/front/runes.d.ts +13 -0
  252. package/dist/front/runes.d.ts.map +1 -0
  253. package/dist/front/runes.js +253 -0
  254. package/dist/front/runes.js.map +1 -0
  255. package/dist/front/stores.d.ts +5 -0
  256. package/dist/front/stores.d.ts.map +1 -0
  257. package/dist/front/stores.js +84 -0
  258. package/dist/front/stores.js.map +1 -0
  259. package/dist/front/typescript.d.ts +2 -0
  260. package/dist/front/typescript.d.ts.map +1 -0
  261. package/dist/front/typescript.js +182 -0
  262. package/dist/front/typescript.js.map +1 -0
  263. package/dist/front/validate/anchors.d.ts +15 -0
  264. package/dist/front/validate/anchors.d.ts.map +1 -0
  265. package/dist/front/validate/anchors.js +43 -0
  266. package/dist/front/validate/anchors.js.map +1 -0
  267. package/dist/front/validate/index.d.ts +16 -0
  268. package/dist/front/validate/index.d.ts.map +1 -0
  269. package/dist/front/validate/index.js +139 -0
  270. package/dist/front/validate/index.js.map +1 -0
  271. package/dist/front/validate/legacy.d.ts +9 -0
  272. package/dist/front/validate/legacy.d.ts.map +1 -0
  273. package/dist/front/validate/legacy.js +102 -0
  274. package/dist/front/validate/legacy.js.map +1 -0
  275. package/dist/front/validate/report.d.ts +14 -0
  276. package/dist/front/validate/report.d.ts.map +1 -0
  277. package/dist/front/validate/report.js +29 -0
  278. package/dist/front/validate/report.js.map +1 -0
  279. package/dist/front/validate/template.d.ts +31 -0
  280. package/dist/front/validate/template.d.ts.map +1 -0
  281. package/dist/front/validate/template.js +507 -0
  282. package/dist/front/validate/template.js.map +1 -0
  283. package/dist/front/wording.d.ts +4 -0
  284. package/dist/front/wording.d.ts.map +1 -0
  285. package/dist/front/wording.js +110 -0
  286. package/dist/front/wording.js.map +1 -0
  287. package/dist/shared/format.d.ts +3 -0
  288. package/dist/shared/format.d.ts.map +1 -0
  289. package/dist/shared/format.js +7 -0
  290. package/dist/shared/format.js.map +1 -0
  291. package/easing.d.ts +2 -0
  292. package/elements.d.ts +1220 -0
  293. package/index.d.ts +2 -0
  294. package/motion.d.ts +2 -0
  295. package/package.json +123 -5
  296. package/src/compiler/diagnostics.ts +233 -0
  297. package/src/compiler/index.ts +292 -0
  298. package/src/compiler/options.ts +140 -0
  299. package/src/compiler/preprocess/decode.ts +85 -0
  300. package/src/compiler/preprocess/index.ts +299 -0
  301. package/src/compiler/preprocess/mapped.ts +146 -0
  302. package/src/compiler/proxy.ts +154 -0
  303. package/src/entries/action.ts +1 -0
  304. package/src/entries/animate.ts +1 -0
  305. package/src/entries/attachments.ts +1 -0
  306. package/src/entries/context.ts +50 -0
  307. package/src/entries/easing.ts +1 -0
  308. package/src/entries/events.ts +1 -0
  309. package/src/entries/index-server.ts +17 -0
  310. package/src/entries/index.ts +41 -0
  311. package/src/entries/internal/client.ts +15 -0
  312. package/src/entries/internal/disclose-version.ts +4 -0
  313. package/src/entries/internal/index.ts +3 -0
  314. package/src/entries/internal/server.ts +8 -0
  315. package/src/entries/internal/tracing.ts +1 -0
  316. package/src/entries/motion-server.ts +1 -0
  317. package/src/entries/motion.ts +1 -0
  318. package/src/entries/proxy.ts +86 -0
  319. package/src/entries/reactivity-server.ts +9 -0
  320. package/src/entries/reactivity.ts +9 -0
  321. package/src/entries/report.ts +81 -0
  322. package/src/entries/server.ts +76 -0
  323. package/src/entries/store-client.ts +80 -0
  324. package/src/entries/store-server.ts +44 -0
  325. package/src/entries/store.ts +201 -0
  326. package/src/entries/transition.ts +1 -0
  327. package/src/entries/window-server.ts +1 -0
  328. package/src/entries/window.ts +1 -0
  329. package/src/front/ast.ts +369 -0
  330. package/src/front/diagnostics.ts +53 -0
  331. package/src/front/ignores.ts +84 -0
  332. package/src/front/index.ts +86 -0
  333. package/src/front/legacy.ts +414 -0
  334. package/src/front/locate.ts +20 -0
  335. package/src/front/lower.ts +509 -0
  336. package/src/front/parse/attribute.ts +319 -0
  337. package/src/front/parse/bracket.ts +99 -0
  338. package/src/front/parse/characters.ts +19 -0
  339. package/src/front/parse/decode.ts +87 -0
  340. package/src/front/parse/element.ts +354 -0
  341. package/src/front/parse/entities.ts +2233 -0
  342. package/src/front/parse/expression.ts +85 -0
  343. package/src/front/parse/html.ts +158 -0
  344. package/src/front/parse/identifier.ts +29 -0
  345. package/src/front/parse/index.ts +88 -0
  346. package/src/front/parse/js.ts +284 -0
  347. package/src/front/parse/options.ts +194 -0
  348. package/src/front/parse/parser.ts +189 -0
  349. package/src/front/parse/pattern.ts +57 -0
  350. package/src/front/parse/script.ts +74 -0
  351. package/src/front/parse/style.ts +399 -0
  352. package/src/front/parse/tag.ts +601 -0
  353. package/src/front/print/css.ts +239 -0
  354. package/src/front/print/index.ts +40 -0
  355. package/src/front/print/layout.ts +87 -0
  356. package/src/front/print/template.ts +448 -0
  357. package/src/front/runes.ts +267 -0
  358. package/src/front/stores.ts +98 -0
  359. package/src/front/typescript.ts +178 -0
  360. package/src/front/validate/anchors.ts +54 -0
  361. package/src/front/validate/index.ts +174 -0
  362. package/src/front/validate/legacy.ts +119 -0
  363. package/src/front/validate/report.ts +38 -0
  364. package/src/front/validate/template.ts +549 -0
  365. package/src/front/wording.ts +112 -0
  366. package/src/shared/format.ts +8 -0
  367. package/store.d.ts +2 -0
  368. package/svelte-html.d.ts +53 -0
  369. package/transition.d.ts +2 -0
  370. package/types/compiler/interfaces.d.ts +2 -0
  371. package/types/compiler/preprocess.d.ts +2 -0
  372. package/types/index.d.ts +1453 -0
  373. package/README.md +0 -3
@@ -0,0 +1,98 @@
1
+ import type * as ES from 'estree';
2
+ import type { ExternalBinding, Rune } from 'vigla/compiler';
3
+ import type { Resolution } from './runes.ts';
4
+
5
+ function names(pattern: ES.Pattern): ES.Identifier[] {
6
+ switch (pattern.type) {
7
+ case 'Identifier':
8
+ return [pattern];
9
+ case 'ObjectPattern':
10
+ return pattern.properties.flatMap((property) =>
11
+ names(property.type === 'RestElement' ? property.argument : property.value)
12
+ );
13
+ case 'ArrayPattern':
14
+ return pattern.elements.flatMap((element) => (element === null ? [] : names(element)));
15
+ case 'AssignmentPattern':
16
+ return names(pattern.left);
17
+ case 'RestElement':
18
+ return names(pattern.argument);
19
+ default:
20
+ return [];
21
+ }
22
+ }
23
+
24
+ function declarations(program: ES.Program | null, into: Map<string, ES.Node | null>): void {
25
+ for (const item of program?.body ?? []) {
26
+ const statement = item.type === 'ExportNamedDeclaration' ? item.declaration : item;
27
+ if (statement?.type === 'ImportDeclaration') {
28
+ for (const specifier of statement.specifiers) into.set(specifier.local.name, statement);
29
+ } else if (statement?.type === 'VariableDeclaration') {
30
+ for (const declarator of statement.declarations) {
31
+ for (const name of names(declarator.id)) into.set(name.name, declarator.init ?? null);
32
+ }
33
+ } else if (
34
+ (statement?.type === 'FunctionDeclaration' || statement?.type === 'ClassDeclaration') &&
35
+ statement.id !== null
36
+ ) {
37
+ into.set(statement.id.name, statement);
38
+ }
39
+ }
40
+ }
41
+
42
+ interface StoreBinding extends ExternalBinding {
43
+ readonly source: ES.Identifier;
44
+ readonly references: Set<ES.Identifier>;
45
+ }
46
+
47
+ const runeNames = new Set([
48
+ '$state',
49
+ '$derived',
50
+ '$effect',
51
+ '$props',
52
+ '$bindable',
53
+ '$inspect',
54
+ '$host'
55
+ ]);
56
+
57
+ export function stores(
58
+ resolution: Resolution,
59
+ module: ES.Program | null,
60
+ instance: ES.Program | null
61
+ ): ExternalBinding[] {
62
+ const moduleDeclarations = new Map<string, ES.Node | null>();
63
+ declarations(module, moduleDeclarations);
64
+ const declared = new Map(moduleDeclarations);
65
+ declarations(instance, declared);
66
+ const bindings = new Map<string, StoreBinding>();
67
+ for (const [reference, name] of resolution.references) {
68
+ if (name === '$' || name.startsWith('$$')) continue;
69
+ const source = name.slice(1);
70
+ const at = (reference as ES.Identifier & { start?: number }).start ?? -1;
71
+ const span = module as (ES.Program & { start?: number; end?: number }) | null;
72
+ if (span !== null && at >= (span.start ?? 0) && at < (span.end ?? 0)) continue;
73
+ const initial = declared.get(source);
74
+ if (runeNames.has(name)) {
75
+ if (initial === undefined) continue;
76
+ const rune: Rune | undefined =
77
+ initial?.type === 'CallExpression' ? resolution.runes.get(initial.callee) : undefined;
78
+ if (rune !== undefined && (rune !== '$props' || source === 'props')) continue;
79
+ if (
80
+ name === '$derived' &&
81
+ initial?.type === 'ImportDeclaration' &&
82
+ initial.source.value === 'svelte/store'
83
+ )
84
+ continue;
85
+ }
86
+ let binding = bindings.get(name);
87
+ if (binding === undefined) {
88
+ binding = {
89
+ source: { type: 'Identifier', name: source },
90
+ name: source,
91
+ references: new Set()
92
+ };
93
+ bindings.set(name, binding);
94
+ }
95
+ binding.references.add(reference);
96
+ }
97
+ return [...bindings.values()];
98
+ }
@@ -0,0 +1,178 @@
1
+ import { fail } from './diagnostics.ts';
2
+
3
+ type Node = { type: string; [key: string]: unknown };
4
+
5
+ const erasedStatements = new WeakSet<Node>();
6
+
7
+ const empty = (): Node => {
8
+ const statement: Node = { type: 'EmptyStatement' };
9
+ erasedStatements.add(statement);
10
+ return statement;
11
+ };
12
+
13
+ const unwrapped = new Set([
14
+ 'TSAsExpression',
15
+ 'TSSatisfiesExpression',
16
+ 'TSNonNullExpression',
17
+ 'TSTypeAssertion',
18
+ 'TSInstantiationExpression'
19
+ ]);
20
+
21
+ const erased = new Set(['TSInterfaceDeclaration', 'TSTypeAliasDeclaration', 'TSDeclareFunction']);
22
+
23
+ const typeFields = [
24
+ 'typeAnnotation',
25
+ 'typeParameters',
26
+ 'typeArguments',
27
+ 'returnType',
28
+ 'accessibility',
29
+ 'readonly',
30
+ 'definite',
31
+ 'override'
32
+ ];
33
+
34
+ function isNode(value: unknown): value is Node {
35
+ return value !== null && typeof value === 'object' && typeof (value as Node).type === 'string';
36
+ }
37
+
38
+ class Stripper {
39
+ readonly path: Node[] = [];
40
+
41
+ children(node: Node): void {
42
+ this.path.push(node);
43
+ for (const key in node) {
44
+ if (key === 'type') continue;
45
+ const value = node[key];
46
+ if (Array.isArray(value)) {
47
+ for (let index = 0; index < value.length; index++) {
48
+ if (isNode(value[index])) value[index] = this.visit(value[index] as Node);
49
+ }
50
+ } else if (isNode(value)) {
51
+ node[key] = this.visit(value);
52
+ }
53
+ }
54
+ this.path.pop();
55
+ }
56
+
57
+ clean(node: Node): Node {
58
+ for (const field of typeFields) delete node[field];
59
+ if (node.type !== 'MemberExpression' && node.type !== 'CallExpression') delete node.optional;
60
+ return node;
61
+ }
62
+
63
+ visit(node: Node): Node {
64
+ return this.clean(this.special(node));
65
+ }
66
+
67
+ special(node: Node): Node {
68
+ if (unwrapped.has(node.type)) return this.visit(node.expression as Node);
69
+ if (erased.has(node.type)) return empty();
70
+ switch (node.type) {
71
+ case 'Decorator':
72
+ fail('typescript_invalid_feature', node as never, {
73
+ feature: 'decorators (related TSC proposal is not stage 4 yet)'
74
+ });
75
+ case 'TSEnumDeclaration':
76
+ fail('typescript_invalid_feature', node as never, { feature: 'enums' });
77
+ case 'ImportDeclaration': {
78
+ if (node.importKind === 'type') return empty();
79
+ const specifiers = node.specifiers as Node[] | undefined;
80
+ if (specifiers !== undefined && specifiers.length > 0) {
81
+ const kept = specifiers.filter((specifier) => specifier.importKind !== 'type');
82
+ if (kept.length === 0) return empty();
83
+ node.specifiers = kept;
84
+ }
85
+ return node;
86
+ }
87
+ case 'ExportNamedDeclaration': {
88
+ if (node.exportKind === 'type') return empty();
89
+ if (node.declaration) {
90
+ this.children(node);
91
+ return (node.declaration as Node).type === 'EmptyStatement' ? empty() : node;
92
+ }
93
+ const specifiers = node.specifiers as Node[] | undefined;
94
+ if (specifiers) {
95
+ const kept = specifiers.filter((specifier) => specifier.exportKind !== 'type');
96
+ if (kept.length === 0) return empty();
97
+ node.specifiers = kept;
98
+ }
99
+ return node;
100
+ }
101
+ case 'ExportDefaultDeclaration':
102
+ case 'ExportAllDeclaration':
103
+ return node.exportKind === 'type' ? empty() : node;
104
+ case 'PropertyDefinition':
105
+ if (node.accessor) {
106
+ fail('typescript_invalid_feature', node as never, {
107
+ feature: 'accessor fields (related TSC proposal is not stage 4 yet)'
108
+ });
109
+ }
110
+ break;
111
+ case 'TSParameterProperty': {
112
+ if ((node.readonly || node.accessibility) && this.path.at(-2)?.kind === 'constructor') {
113
+ fail('typescript_invalid_feature', node as never, {
114
+ feature: 'accessibility modifiers on constructor parameters'
115
+ });
116
+ }
117
+ return this.visit(node.parameter as Node);
118
+ }
119
+ case 'FunctionExpression':
120
+ case 'FunctionDeclaration': {
121
+ const params = node.params as Node[];
122
+ const first = params[0];
123
+ if (first?.type === 'Identifier' && first.name === 'this') params.shift();
124
+ break;
125
+ }
126
+ case 'ClassBody': {
127
+ const body: Node[] = [];
128
+ this.path.push(node);
129
+ for (const member of node.body as Node[]) {
130
+ const child = this.visit(member);
131
+ if (child.type !== 'PropertyDefinition' || !child.declare) body.push(child);
132
+ }
133
+ this.path.pop();
134
+ node.body = body;
135
+ return node;
136
+ }
137
+ case 'ClassDeclaration':
138
+ if (node.declare) return empty();
139
+ delete node.abstract;
140
+ delete node.implements;
141
+ delete node.superTypeArguments;
142
+ delete node.superTypeParameters;
143
+ break;
144
+ case 'ClassExpression':
145
+ delete node.implements;
146
+ delete node.superTypeArguments;
147
+ delete node.superTypeParameters;
148
+ break;
149
+ case 'MethodDefinition':
150
+ if (node.abstract) return empty();
151
+ break;
152
+ case 'VariableDeclaration':
153
+ if (node.declare) return empty();
154
+ break;
155
+ case 'TSModuleDeclaration': {
156
+ const body = node.body as Node | undefined;
157
+ if (!body) return empty();
158
+ this.path.push(node);
159
+ const cleaned = (body.body as Node[]).map((entry) => this.visit(entry));
160
+ this.path.pop();
161
+ if (cleaned.some((entry) => !erasedStatements.has(entry))) {
162
+ fail('typescript_invalid_feature', node as never, {
163
+ feature: 'namespaces with non-type nodes'
164
+ });
165
+ }
166
+ return empty();
167
+ }
168
+ default:
169
+ break;
170
+ }
171
+ this.children(node);
172
+ return node;
173
+ }
174
+ }
175
+
176
+ export function stripTypes<T>(node: T): T {
177
+ return new Stripper().visit(node as unknown as Node) as unknown as T;
178
+ }
@@ -0,0 +1,54 @@
1
+ import type { Diagnostic } from 'vigla/compiler';
2
+
3
+ export const stopped: unique symbol = Symbol('stopped');
4
+
5
+ export interface Anchor {
6
+ warnings: Diagnostic[];
7
+ error?: Diagnostic;
8
+ }
9
+
10
+ export class Anchors {
11
+ readonly map = new Map<object, Anchor>();
12
+ failed = false;
13
+
14
+ #entry(node: object): Anchor {
15
+ let entry = this.map.get(node);
16
+ if (entry === undefined) {
17
+ entry = { warnings: [] };
18
+ this.map.set(node, entry);
19
+ }
20
+ return entry;
21
+ }
22
+
23
+ warn(node: object, warnings: readonly Diagnostic[]): void {
24
+ if (warnings.length > 0) this.#entry(node).warnings.push(...warnings);
25
+ }
26
+
27
+ fail(node: object, error: Diagnostic): void {
28
+ const entry = this.#entry(node);
29
+ entry.error ??= error;
30
+ this.failed = true;
31
+ }
32
+
33
+ translated(
34
+ lowered: ReadonlyMap<object, object>,
35
+ first: ReadonlyMap<object, readonly Diagnostic[]>
36
+ ): Map<object, Anchor> {
37
+ const out = new Map<object, Anchor>();
38
+ const entry = (key: object): Anchor => {
39
+ let found = out.get(key);
40
+ if (found === undefined) {
41
+ found = { warnings: [] };
42
+ out.set(key, found);
43
+ }
44
+ return found;
45
+ };
46
+ for (const [node, warnings] of first) entry(node).warnings.push(...warnings);
47
+ for (const [node, anchor] of this.map) {
48
+ const target = entry(lowered.get(node) ?? node);
49
+ target.warnings.push(...anchor.warnings);
50
+ if (anchor.error !== undefined) target.error ??= anchor.error;
51
+ }
52
+ return out;
53
+ }
54
+ }
@@ -0,0 +1,174 @@
1
+ import type { Diagnostic } from 'vigla/compiler';
2
+ import type * as AST from '../ast.ts';
3
+ import { bidirectionalChar } from '../parse/characters.ts';
4
+ import type { Parsed } from '../parse/index.ts';
5
+ import type * as ES from 'estree';
6
+ import { diagnostic, fail } from '../diagnostics.ts';
7
+ import { Anchors } from './anchors.ts';
8
+ import { rejectLegacy } from './legacy.ts';
9
+ import { Report } from './report.ts';
10
+ import { Template } from './template.ts';
11
+
12
+ export interface ValidateOptions {
13
+ readonly customElement: boolean;
14
+ readonly filename: string | undefined;
15
+ }
16
+
17
+ const bidirectional = bidirectionalChar;
18
+
19
+ type Node = { type: string; [key: string]: unknown };
20
+
21
+ function literals(node: unknown, report: Report, anchors: Anchors): void {
22
+ if (node === null || typeof node !== 'object') return;
23
+ if (Array.isArray(node)) {
24
+ for (const item of node) literals(item, report, anchors);
25
+ return;
26
+ }
27
+ const record = node as Node;
28
+ if (typeof record.type !== 'string') return;
29
+ const text =
30
+ record.type === 'Literal' && typeof record.value === 'string'
31
+ ? record.value
32
+ : record.type === 'TemplateElement'
33
+ ? ((record.value as { cooked?: string | null }).cooked ?? '')
34
+ : null;
35
+ if (text !== null && bidirectional.test(text)) {
36
+ const before = report.warnings.length;
37
+ report.warn('bidirectional_control_characters', record as never);
38
+ anchors.warn(record, report.warnings.slice(before));
39
+ }
40
+ for (const key in record) {
41
+ if (
42
+ key !== 'type' &&
43
+ key !== 'loc' &&
44
+ key !== 'leadingComments' &&
45
+ key !== 'trailingComments'
46
+ ) {
47
+ literals(record[key], report, anchors);
48
+ }
49
+ }
50
+ }
51
+
52
+ const forbiddenUpdates = new Set(['beforeUpdate', 'afterUpdate']);
53
+
54
+ function imports(
55
+ program: AST.Script['content'] | ES.Program | null | undefined,
56
+ anchors: Anchors
57
+ ): void {
58
+ for (const statement of program?.body ?? []) {
59
+ if (statement.type !== 'ImportDeclaration') continue;
60
+ const source = String(statement.source.value);
61
+ const at = statement as unknown as AST.Located;
62
+ if (source.startsWith('svelte/internal')) {
63
+ anchors.fail(statement, diagnostic('import_svelte_internal_forbidden', at));
64
+ continue;
65
+ }
66
+ if (source !== 'svelte') continue;
67
+ for (const specifier of statement.specifiers) {
68
+ if (specifier.type !== 'ImportSpecifier' || specifier.imported.type !== 'Identifier')
69
+ continue;
70
+ const name = specifier.imported.name;
71
+ if (forbiddenUpdates.has(name)) {
72
+ anchors.fail(
73
+ statement,
74
+ diagnostic('runes_mode_invalid_import', specifier as unknown as AST.Located, { name })
75
+ );
76
+ break;
77
+ }
78
+ }
79
+ }
80
+ }
81
+
82
+ export function validateModuleSyntax(program: ES.Program): Anchors {
83
+ const anchors = new Anchors();
84
+ imports(program, anchors);
85
+ return anchors;
86
+ }
87
+
88
+ function firstReference(node: unknown, name: string, parent: Node | null): Node | null {
89
+ if (node === null || typeof node !== 'object') return null;
90
+ if (Array.isArray(node)) {
91
+ for (const item of node) {
92
+ const found = firstReference(item, name, parent);
93
+ if (found !== null) return found;
94
+ }
95
+ return null;
96
+ }
97
+ const record = node as Node;
98
+ if (typeof record.type !== 'string') return null;
99
+ if (record.type === 'Identifier' && record.name === name) {
100
+ const property =
101
+ (parent?.type === 'MemberExpression' && parent.property === record && !parent.computed) ||
102
+ (parent?.type === 'Property' && parent.key === record && !parent.computed);
103
+ if (!property) return record;
104
+ }
105
+ for (const key in record) {
106
+ if (
107
+ key === 'type' ||
108
+ key === 'loc' ||
109
+ key === 'leadingComments' ||
110
+ key === 'trailingComments'
111
+ ) {
112
+ continue;
113
+ }
114
+ const found = firstReference(record[key], name, record);
115
+ if (found !== null) return found;
116
+ }
117
+ return null;
118
+ }
119
+
120
+ function rejectLegacyProps(root: AST.Root): void {
121
+ for (const [name, code] of [
122
+ ['$$props', 'legacy_props_invalid'],
123
+ ['$$restProps', 'legacy_rest_props_invalid']
124
+ ] as const) {
125
+ const found =
126
+ firstReference(root.module, name, null) ??
127
+ firstReference(root.instance, name, null) ??
128
+ firstReference(root.fragment, name, null);
129
+ if (found !== null) fail(code, found as unknown as AST.Located);
130
+ }
131
+ }
132
+
133
+ export interface Validated {
134
+ readonly parse: readonly Diagnostic[];
135
+ readonly before: readonly Diagnostic[];
136
+ readonly anchors: Anchors;
137
+ }
138
+
139
+ export function validateComponent(
140
+ parsed: Parsed,
141
+ source: string,
142
+ options: ValidateOptions
143
+ ): Validated {
144
+ const root = parsed.root;
145
+ const anchors = new Anchors();
146
+ rejectLegacy(root, { ...options, anchors });
147
+ const early = new Report();
148
+ for (const attribute of root.options?.attributes ?? []) {
149
+ if (
150
+ attribute.type === 'Attribute' &&
151
+ attribute.name === 'customElement' &&
152
+ !options.customElement
153
+ ) {
154
+ early.warn('options_missing_custom_element', attribute);
155
+ }
156
+ }
157
+ rejectLegacyProps(root);
158
+ imports(root.module?.content, anchors);
159
+ imports(root.instance?.content, anchors);
160
+ for (const statement of root.instance?.content.body ?? []) {
161
+ if (statement.type === 'LabeledStatement' && statement.label.name === '$') {
162
+ anchors.fail(
163
+ statement,
164
+ diagnostic('legacy_reactive_statement_invalid', statement as unknown as AST.Located)
165
+ );
166
+ }
167
+ }
168
+ const scripts = new Report();
169
+ literals(root.module, scripts, anchors);
170
+ literals(root.instance, scripts, anchors);
171
+ new Template(source, new Report(), anchors).walk(root);
172
+ literals(root.fragment, new Report(), anchors);
173
+ return { parse: parsed.warnings, before: early.warnings, anchors };
174
+ }
@@ -0,0 +1,119 @@
1
+ import type * as AST from '../ast.ts';
2
+ import { CompileError } from 'vigla/compiler';
3
+ import { fail, legacy } from '../diagnostics.ts';
4
+ import { stopped, type Anchors } from './anchors.ts';
5
+
6
+ export interface LegacyContext {
7
+ readonly customElement: boolean;
8
+ readonly filename: string | undefined;
9
+ readonly anchors: Anchors;
10
+ }
11
+
12
+ const components = new Set(['Component', 'SvelteComponent', 'SvelteSelf']);
13
+
14
+ function selfName(filename: string | undefined): { name: string; basename: string } {
15
+ const basename =
16
+ filename === undefined ? 'Self.svelte' : (filename.split(/[/\\]/).pop() as string);
17
+ const stem = basename.replace(/\.svelte$/, '');
18
+ return { name: stem.charAt(0).toUpperCase() + stem.slice(1), basename };
19
+ }
20
+
21
+ function children(node: AST.TemplateNode): (AST.Fragment | null | undefined)[] {
22
+ switch (node.type) {
23
+ case 'IfBlock':
24
+ return [node.consequent, node.alternate];
25
+ case 'EachBlock':
26
+ return [node.body, node.fallback];
27
+ case 'AwaitBlock':
28
+ return [node.pending, node.then, node.catch];
29
+ case 'KeyBlock':
30
+ return [node.fragment];
31
+ case 'SnippetBlock':
32
+ return [node.body];
33
+ default:
34
+ return 'fragment' in node ? [node.fragment] : [];
35
+ }
36
+ }
37
+
38
+ function element(
39
+ node: AST.ElementLike,
40
+ parent: AST.ElementLike | null,
41
+ inSnippet: boolean,
42
+ context: LegacyContext
43
+ ): void {
44
+ if (node.type === 'SvelteComponent') legacy('svelte_component_deprecated', node);
45
+ if (node.type === 'SvelteSelf')
46
+ legacy('svelte_self_deprecated', node, selfName(context.filename));
47
+ if (node.type === 'SvelteFragment') legacy('svelte_fragment_invalid', node);
48
+ if (node.type === 'SlotElement' && !context.customElement)
49
+ legacy('slot_element_deprecated', node);
50
+ for (const attribute of node.attributes) {
51
+ if (attribute.type === 'LetDirective') legacy('let_directive_invalid', attribute);
52
+ if (attribute.type === 'OnDirective') {
53
+ legacy(
54
+ components.has(node.type)
55
+ ? 'component_event_directive_invalid'
56
+ : 'event_directive_deprecated',
57
+ attribute,
58
+ { name: attribute.name }
59
+ );
60
+ }
61
+ if (attribute.type !== 'Attribute' || attribute.name !== 'slot') continue;
62
+ if (inSnippet) {
63
+ const value = attribute.value;
64
+ if (!Array.isArray(value) || value.length !== 1 || value[0]?.type !== 'Text')
65
+ fail('slot_attribute_invalid', attribute);
66
+ } else if (parent !== null && components.has(parent.type)) {
67
+ legacy('slot_attribute_unsupported', attribute);
68
+ }
69
+ }
70
+ }
71
+
72
+ function fragment(
73
+ nodes: AST.Fragment | null | undefined,
74
+ parent: AST.ElementLike | null,
75
+ context: LegacyContext,
76
+ container: AST.TemplateNode | null = null
77
+ ): void {
78
+ for (const node of nodes?.nodes ?? []) {
79
+ const isElement = 'attributes' in node && 'name_loc' in node;
80
+ if (isElement) {
81
+ try {
82
+ element(node, parent, container?.type === 'SnippetBlock', context);
83
+ } catch (error) {
84
+ if (!(error instanceof CompileError)) throw error;
85
+ context.anchors.fail(node, error.diagnostic);
86
+ throw stopped;
87
+ }
88
+ }
89
+ const owner = isElement ? node : parent;
90
+ for (const child of children(node)) fragment(child, owner, context, node);
91
+ }
92
+ }
93
+
94
+ export function rejectLegacy(root: AST.Root, context: LegacyContext): void {
95
+ const options = root.options;
96
+ if (options?.runes === false) {
97
+ const at = options.attributes.find(
98
+ (attribute) => attribute.type === 'Attribute' && attribute.name === 'runes'
99
+ );
100
+ legacy('runes_mode_required', at ?? options);
101
+ }
102
+ for (const attribute of options?.attributes ?? []) {
103
+ if (attribute.type !== 'Attribute') continue;
104
+ if (attribute.name === 'accessors') legacy('options_deprecated_accessors', attribute);
105
+ if (attribute.name === 'immutable') legacy('options_deprecated_immutable', attribute);
106
+ }
107
+ const contextAttribute = root.module?.attributes.find(
108
+ (attribute) => attribute.type === 'Attribute' && attribute.name === 'context'
109
+ );
110
+ if (contextAttribute !== undefined) legacy('script_context_deprecated', contextAttribute);
111
+ try {
112
+ fragment(root.fragment, null, {
113
+ ...context,
114
+ customElement: context.customElement || options?.customElement !== undefined
115
+ });
116
+ } catch (error) {
117
+ if (error !== stopped) throw error;
118
+ }
119
+ }
@@ -0,0 +1,38 @@
1
+ import type { Diagnostic } from 'vigla/compiler';
2
+ import { warning, type Args, type At } from '../diagnostics.ts';
3
+
4
+ export class Report {
5
+ readonly warnings: Diagnostic[] = [];
6
+ readonly #stack: ReadonlySet<string>[] = [];
7
+ readonly #snapshots = new Map<object, ReadonlySet<string> | undefined>();
8
+
9
+ push(codes: readonly string[]): void {
10
+ const inherited = this.#stack.at(-1);
11
+ this.#stack.push(new Set([...(inherited ?? []), ...codes]));
12
+ }
13
+
14
+ pop(): void {
15
+ this.#stack.pop();
16
+ }
17
+
18
+ mark(node: object): void {
19
+ this.#snapshots.set(node, this.#stack.at(-1));
20
+ }
21
+
22
+ ignored(code: string, at?: object): boolean {
23
+ const codes =
24
+ at !== undefined && this.#snapshots.has(at) ? this.#snapshots.get(at) : this.#stack.at(-1);
25
+ return codes?.has(code) ?? false;
26
+ }
27
+
28
+ warn(code: string, at: At & object, args?: Args): void;
29
+ warn(code: string, at: At, args?: Args): void;
30
+ warn(code: string, at: At, args: Args = {}): void {
31
+ if (this.ignored(code, typeof at === 'object' ? at : undefined)) return;
32
+ this.warnings.push(warning(code, at, args));
33
+ }
34
+
35
+ add(diagnostics: readonly Diagnostic[]): void {
36
+ this.warnings.push(...diagnostics);
37
+ }
38
+ }