@wuchale/svelte 0.19.4 → 0.20.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.
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { createHeuristic, defaultGenerateLoadID, defaultHeuristicOpts, fillDefaults, pofile } from 'wuchale';
1
+ import { createHeuristic, defaultHeuristicOpts, fillDefaults, pofile } from 'wuchale';
2
2
  import { loaderPathResolver } from 'wuchale/adapter-utils';
3
3
  import { pluralPattern } from 'wuchale/adapter-vanilla';
4
4
  import { SvelteTransformer } from './transformer.js';
@@ -46,9 +46,11 @@ export const defaultArgs = {
46
46
  storage: pofile(),
47
47
  patterns: [pluralPattern],
48
48
  heuristic: svelteDefaultHeuristic,
49
- granularLoad: false,
50
- bundleLoad: false,
51
- generateLoadID: defaultGenerateLoadID,
49
+ loading: {
50
+ direct: false,
51
+ granular: false,
52
+ group: [],
53
+ },
52
54
  loader: 'svelte',
53
55
  runtime: {
54
56
  initReactive: ({ file, funcName, ctx: { module } }) => {
@@ -91,11 +93,9 @@ export const adapter = (args = defaultArgs) => {
91
93
  }
92
94
  const { heuristic, patterns, runtime, loader, ...rest } = fillDefaults(args, defaultArgs);
93
95
  return {
94
- transform: ({ content, filename, index, expr, matchUrl }) => {
95
- return new SvelteTransformer(content, filename, index, heuristic, patterns, expr, runtime, matchUrl).transformSv();
96
- },
96
+ transform: ctx => new SvelteTransformer(ctx, heuristic, patterns, runtime).transformSv(),
97
97
  loaderExts: ['.svelte.js', '.svelte.ts', '.js', '.ts'],
98
- defaultLoaderPath: getDefaultLoaderPath(loader, rest.bundleLoad),
98
+ defaultLoaderPath: getDefaultLoaderPath(loader, rest.loading.direct),
99
99
  runtime,
100
100
  ...rest,
101
101
  };
@@ -1,50 +1,54 @@
1
1
  import type { AnyNode, VariableDeclarator } from 'acorn';
2
2
  import { type AST } from 'svelte/compiler';
3
- import type { CatalogExpr, CodePattern, HeuristicFunc, IndexTracker, Message, RuntimeConf, TransformOutput, UrlMatcher } from 'wuchale';
3
+ import type { CodePattern, HeuristicFunc, Message, RuntimeConf, TransformCtx, TransformOutput } from 'wuchale';
4
4
  import { MixedVisitor } from 'wuchale/adapter-utils';
5
5
  import { Transformer } from 'wuchale/adapter-vanilla';
6
- type MixedNodesTypes = AST.Text | AST.Tag | AST.ElementLike | AST.Block | AST.Comment;
7
- type MixedVisitorSvelte = MixedVisitor<MixedNodesTypes, AST.Text, AST.Comment, AST.ExpressionTag>;
6
+ type MixedNodesTypes = AST.Text | AST.Tag | AST.ElementLike | AST.SvelteElement | AST.Block | AST.Comment;
7
+ type AddCtx = {
8
+ currentSnippet: number;
9
+ };
10
+ type MixedVisitorSvelte = MixedVisitor<MixedNodesTypes, AddCtx, AST.Text, AST.Comment, AST.ExpressionTag>;
8
11
  export type RuntimeCtxSv = {
9
12
  module: boolean;
10
13
  };
11
14
  export declare class SvelteTransformer extends Transformer {
12
15
  currentElement?: string | undefined;
13
16
  inCompoundText: boolean;
14
- currentSnippet: number;
17
+ addCtx: AddCtx;
15
18
  moduleExportExprs: AnyNode[];
16
19
  mixedVisitor: MixedVisitorSvelte;
17
- constructor(content: string, filename: string, index: IndexTracker, heuristic: HeuristicFunc, patterns: CodePattern[], catalogExpr: CatalogExpr, rtConf: RuntimeConf, matchUrl: UrlMatcher);
18
- visitExpressionTag: (node: AST.ExpressionTag) => Message[];
19
- visitVariableDeclarator: (node: VariableDeclarator) => Message[];
20
- initMixedVisitor: () => MixedVisitorSvelte;
21
- visitFragment: (node: AST.Fragment) => Message[];
22
- visitRegularElement: (node: AST.ElementLike) => Message[];
23
- visitComponent: (node: AST.ElementLike) => Message[];
24
- visitText: (node: AST.Text) => Message[];
25
- visitSpreadAttribute: (node: AST.SpreadAttribute) => Message[];
26
- visitAttribute: (node: AST.Attribute) => Message[];
27
- visitConstTag: (node: AST.ConstTag) => Message[];
28
- visitRenderTag: (node: AST.RenderTag) => Message[];
29
- visitHtmlTag: (node: AST.HtmlTag) => Message[];
30
- visitOnDirective: (node: AST.OnDirective) => Message[];
31
- hasIdentifier: (node: AnyNode | AnyNode[], name: string) => boolean;
32
- visitSnippetBlock: (node: AST.SnippetBlock) => Message[];
33
- visitIfBlock: (node: AST.IfBlock) => Message[];
34
- visitEachBlock: (node: AST.EachBlock) => Message[];
35
- visitKeyBlock: (node: AST.KeyBlock) => Message[];
36
- visitAwaitBlock: (node: AST.AwaitBlock) => Message[];
37
- visitSvelteBody: (node: AST.SvelteBody) => Message[];
38
- visitSvelteDocument: (node: AST.SvelteDocument) => Message[];
39
- visitSvelteElement: (node: AST.SvelteElement) => Message[];
40
- visitSvelteBoundary: (node: AST.SvelteBoundary) => Message[];
41
- visitSvelteHead: (node: AST.SvelteHead) => Message[];
42
- visitTitleElement: (node: AST.TitleElement) => Message[];
43
- visitSvelteWindow: (node: AST.SvelteWindow) => Message[];
44
- visitRoot: (node: AST.Root) => Message[];
45
- visitSv: (node: AST.SvelteNode | AnyNode) => Message[];
20
+ constructor(ctx: TransformCtx, heuristic: HeuristicFunc, patterns: CodePattern[], rtConf: RuntimeConf);
21
+ visitExpressionTag(node: AST.ExpressionTag): Message[];
22
+ visitVariableDeclarator(node: VariableDeclarator): Message[];
23
+ initMixedVisitor(): MixedVisitorSvelte;
24
+ visitFragment(node: AST.Fragment): Message[];
25
+ visitRegularElement(node: AST.ElementLike): Message[];
26
+ visitComponent(node: AST.Component): Message[];
27
+ visitText(node: AST.Text): Message[];
28
+ visitSpreadAttribute(node: AST.SpreadAttribute): Message[];
29
+ visitAttribute(node: AST.Attribute): Message[];
30
+ visitConstTag(node: AST.ConstTag): Message[];
31
+ visitDeclarationTag(node: AST.DeclarationTag): Message[];
32
+ visitRenderTag(node: AST.RenderTag): Message[];
33
+ visitHtmlTag(node: AST.HtmlTag): Message[];
34
+ visitOnDirective(node: AST.OnDirective): Message[];
35
+ hasIdentifier(node: AnyNode | AnyNode[], name: string): boolean;
36
+ visitSnippetBlock(node: AST.SnippetBlock): Message[];
37
+ visitIfBlock(node: AST.IfBlock): Message[];
38
+ visitEachBlock(node: AST.EachBlock): Message[];
39
+ visitKeyBlock(node: AST.KeyBlock): Message[];
40
+ visitAwaitBlock(node: AST.AwaitBlock): Message[];
41
+ visitSvelteBody(node: AST.SvelteBody): Message[];
42
+ visitSvelteDocument(node: AST.SvelteDocument): Message[];
43
+ visitSvelteElement(node: AST.SvelteElement): Message[];
44
+ visitSvelteBoundary(node: AST.SvelteBoundary): Message[];
45
+ visitSvelteHead(node: AST.SvelteHead): Message[];
46
+ visitTitleElement(node: AST.TitleElement): Message[];
47
+ visitSvelteWindow(node: AST.SvelteWindow): Message[];
48
+ visitRoot(node: AST.Root): Message[];
49
+ visitSv(node: AST.SvelteNode | AnyNode): Message[];
46
50
  /** collects the ranges that will be checked if a snippet identifier is exported using RegExp test to simplify */
47
- collectModuleExportExprs: (script: AST.Script) => void;
48
- transformSv: () => Promise<TransformOutput>;
51
+ collectModuleExportExprs(script: AST.Script): void;
52
+ transformSv(): Promise<TransformOutput>;
49
53
  }
50
54
  export {};
@@ -2,7 +2,7 @@ import { parse, preprocess } from 'svelte/compiler';
2
2
  import { getKey } from 'wuchale';
3
3
  import { MixedVisitor, nonWhitespaceText, varNames } from 'wuchale/adapter-utils';
4
4
  import { parseScript, Transformer } from 'wuchale/adapter-vanilla';
5
- const nodesWithChildren = ['RegularElement', 'Component'];
5
+ const nodesWithChildren = ['RegularElement', 'Component', 'SvelteElement'];
6
6
  const noWrapTopCalls = ['$props', '$state', '$derived', '$effect'];
7
7
  const rtComponent = 'W_tx_';
8
8
  const headerAdd = `\nimport ${rtComponent} from "@wuchale/svelte/runtime.svelte"`;
@@ -18,22 +18,25 @@ export class SvelteTransformer extends Transformer {
18
18
  // state
19
19
  currentElement;
20
20
  inCompoundText = false;
21
- currentSnippet = 0;
21
+ addCtx = { currentSnippet: 0 };
22
22
  moduleExportExprs = []; // to choose which runtime var to use for snippets
23
23
  mixedVisitor;
24
- constructor(content, filename, index, heuristic, patterns, catalogExpr, rtConf, matchUrl) {
25
- super(content, filename, index, heuristic, patterns, catalogExpr, rtConf, matchUrl, [varNames.rt, rtModuleVar]);
24
+ constructor(ctx, heuristic, patterns, rtConf) {
25
+ super(ctx, heuristic, patterns, rtConf, [varNames.rt, rtModuleVar]);
26
26
  this.heuristciDetails.insideProgram = false;
27
27
  this.mixedVisitor = this.initMixedVisitor();
28
28
  }
29
- visitExpressionTag = (node) => this.visit(node.expression);
30
- visitVariableDeclarator = (node) => {
31
- const msgs = this.defaultVisitVariableDeclarator(node);
29
+ visitExpressionTag(node) {
30
+ return this.visit(node.expression);
31
+ }
32
+ visitVariableDeclarator(node) {
33
+ const msgs = super.visitVariableDeclarator(node);
32
34
  const init = node.init;
33
35
  if (!msgs.length ||
34
- this.heuristciDetails.declaring != null ||
36
+ (this.heuristciDetails.declaring != null && this.heuristciDetails.declaring !== 'variable') ||
35
37
  init == null ||
36
- ['ArrowFunctionExpression', 'FunctionExpression'].includes(init.type)) {
38
+ init.type === 'ArrowFunctionExpression' ||
39
+ init.type === 'FunctionExpression') {
37
40
  return msgs;
38
41
  }
39
42
  const needsWrapping = msgs.some(msg => {
@@ -53,75 +56,74 @@ export class SvelteTransformer extends Transformer {
53
56
  return msgs;
54
57
  }
55
58
  const isExported = this.moduleExportExprs.some(node => init.start >= node.start && init.end <= node.end);
56
- if (!isExported) {
59
+ if (!isExported && this.initReactive()) {
57
60
  this.mstr.appendLeft(init.start, '$derived(');
58
61
  this.mstr.appendRight(init.end, ')');
59
62
  }
60
63
  return msgs;
61
- };
62
- initMixedVisitor = () => new MixedVisitor({
63
- mstr: this.mstr,
64
- vars: this.vars,
65
- getRange: node => ({ start: node.start, end: node.end }),
66
- isText: node => node.type === 'Text',
67
- isComment: node => node.type === 'Comment',
68
- leaveInPlace: node => ['ConstTag', 'SnippetBlock'].includes(node.type),
69
- isExpression: node => node.type === 'ExpressionTag',
70
- getTextContent: node => node.data,
71
- getCommentData: node => node.data.trim(),
72
- canHaveChildren: node => nodesWithChildren.includes(node.type),
73
- visitFunc: (child, inCompoundText) => {
74
- const inCompoundTextPrev = this.inCompoundText;
75
- this.inCompoundText = inCompoundText;
76
- const childTxts = this.visitSv(child);
77
- this.inCompoundText = inCompoundTextPrev; // restore
78
- return childTxts;
79
- },
80
- visitExpressionTag: this.visitExpressionTag,
81
- fullHeuristicDetails: this.fullHeuristicDetails,
82
- checkHeuristic: this.getHeuristicMessageType,
83
- index: this.index,
84
- wrapNested: (msgInfo, hasExprs, nestedRanges, lastChildEnd) => {
85
- const snippets = [];
86
- // create and reference snippets
87
- for (const [childStart, childEnd, haveCtx] of nestedRanges) {
88
- const snippetName = `${snipPrefix}${this.currentSnippet}`;
89
- snippets.push(snippetName);
90
- this.currentSnippet++;
91
- const snippetBegin = `\n{#snippet ${snippetName}(${haveCtx ? this.vars().nestCtx : ''})}\n`;
92
- this.mstr.appendRight(childStart, snippetBegin);
93
- this.mstr.prependLeft(childEnd, '\n{/snippet}\n');
94
- }
95
- let begin = `\n<${rtComponent}`;
96
- if (snippets.length) {
97
- begin += ` t={[${snippets.join(', ')}]}`;
98
- }
99
- begin += ' x=';
100
- if (this.inCompoundText) {
101
- begin += `{${this.vars().nestCtx}} n`;
102
- }
103
- else {
104
- const index = this.index.get(getKey(msgInfo.msgStr, msgInfo.context));
105
- begin += `{${this.vars().rtCtx}(${index})}`;
106
- }
107
- let end = ' />\n';
108
- if (hasExprs) {
109
- begin += ' a={[';
110
- end = `]}${end}`;
111
- }
112
- this.mstr.appendLeft(lastChildEnd, begin);
113
- this.mstr.appendRight(lastChildEnd, end);
114
- },
115
- });
116
- visitFragment = (node) => this.mixedVisitor.visit({
117
- children: node.nodes,
118
- commentDirectives: this.commentDirectives,
119
- inCompoundText: this.inCompoundText,
120
- scope: 'markup',
121
- element: this.currentElement,
122
- useComponent: this.currentElement !== 'title',
123
- });
124
- visitRegularElement = (node) => {
64
+ }
65
+ initMixedVisitor() {
66
+ return new MixedVisitor({
67
+ vars: this.vars.bind(this),
68
+ content: this.content,
69
+ getRange: node => ({ start: node.start, end: node.end }),
70
+ isText: node => node.type === 'Text',
71
+ isComment: node => node.type === 'Comment',
72
+ leaveInPlace: node => ['ConstTag', 'SnippetBlock'].includes(node.type),
73
+ isExpression: node => node.type === 'ExpressionTag',
74
+ getTextContent: node => node.data,
75
+ getCommentData: node => node.data.trim(),
76
+ canHaveChildren: node => nodesWithChildren.includes(node.type),
77
+ visitFunc: MixedVisitor.withCtxRestore(this, this.visitSv.bind(this)),
78
+ fullHeuristicDetails: this.fullHeuristicDetails.bind(this),
79
+ checkHeuristic: this.getHeuristicMessageType.bind(this),
80
+ wrapNested: (msgInfo, hasExprs, nestedRanges, lastChildEnd) => {
81
+ const snippets = [];
82
+ // create and reference snippets
83
+ for (const [childStart, childEnd, haveCtx] of nestedRanges) {
84
+ const snippetName = `${snipPrefix}${this.addCtx.currentSnippet}`;
85
+ snippets.push(snippetName);
86
+ this.addCtx.currentSnippet++;
87
+ const snippetBegin = `\n{#snippet ${snippetName}(${haveCtx ? this.vars().nestCtx : ''})}\n`;
88
+ this.mstr.appendRight(childStart, snippetBegin);
89
+ this.mstr.prependLeft(childEnd, '\n{/snippet}\n');
90
+ }
91
+ let begin = `\n<${rtComponent}`;
92
+ if (snippets.length) {
93
+ begin += ` t={[${snippets.join(', ')}]}`;
94
+ }
95
+ begin += ' x=';
96
+ if (this.inCompoundText) {
97
+ begin += `{${this.vars().nestCtx}} n`;
98
+ }
99
+ else {
100
+ const index = this.index.get(getKey(msgInfo.msgStr, msgInfo.context));
101
+ begin += `{${this.vars().rtCtx}(${index})}`;
102
+ }
103
+ let end = ' />\n';
104
+ if (hasExprs) {
105
+ begin += ' a={[';
106
+ end = `]}${end}`;
107
+ }
108
+ this.mstr.appendLeft(lastChildEnd, begin);
109
+ this.mstr.appendRight(lastChildEnd, end);
110
+ },
111
+ });
112
+ }
113
+ visitFragment(node) {
114
+ return this.mixedVisitor.visit({
115
+ mstr: this.mstr,
116
+ index: this.index,
117
+ addCtx: this.addCtx,
118
+ children: node.nodes,
119
+ commentDirectives: this.commentDirectives,
120
+ inCompoundText: this.inCompoundText,
121
+ scope: 'markup',
122
+ element: this.currentElement,
123
+ useComponent: this.currentElement !== 'title',
124
+ });
125
+ }
126
+ visitRegularElement(node) {
125
127
  const currentElement = this.currentElement;
126
128
  this.currentElement = node.name;
127
129
  const msgs = [];
@@ -131,9 +133,11 @@ export class SvelteTransformer extends Transformer {
131
133
  msgs.push(...this.visitFragment(node.fragment));
132
134
  this.currentElement = currentElement;
133
135
  return msgs;
134
- };
135
- visitComponent = this.visitRegularElement;
136
- visitText = (node) => {
136
+ }
137
+ visitComponent(node) {
138
+ return this.visitRegularElement(node);
139
+ }
140
+ visitText(node) {
137
141
  const [startWh, trimmed, endWh] = nonWhitespaceText(node.data);
138
142
  const [pass, msgInfo] = this.checkHeuristic(trimmed, {
139
143
  scope: 'markup',
@@ -144,9 +148,11 @@ export class SvelteTransformer extends Transformer {
144
148
  }
145
149
  this.mstr.update(node.start + startWh, node.end - endWh, `{${this.literalRepl(msgInfo)}}`);
146
150
  return [msgInfo];
147
- };
148
- visitSpreadAttribute = (node) => this.visit(node.expression);
149
- visitAttribute = (node) => {
151
+ }
152
+ visitSpreadAttribute(node) {
153
+ return this.visit(node.expression);
154
+ }
155
+ visitAttribute(node) {
150
156
  if (node.value === true) {
151
157
  return [];
152
158
  }
@@ -159,6 +165,9 @@ export class SvelteTransformer extends Transformer {
159
165
  }
160
166
  if (values.length > 1) {
161
167
  return this.mixedVisitor.visit({
168
+ mstr: this.mstr,
169
+ index: this.index,
170
+ addCtx: this.addCtx,
162
171
  children: values,
163
172
  commentDirectives: this.commentDirectives,
164
173
  inCompoundText: false,
@@ -195,15 +204,29 @@ export class SvelteTransformer extends Transformer {
195
204
  this.mstr.remove(value.end, value.end + 1);
196
205
  }
197
206
  return [msgInfo];
198
- };
199
- visitConstTag = (node) => {
207
+ }
208
+ visitConstTag(node) {
200
209
  // @ts-expect-error
201
210
  return this.visitVariableDeclaration(node.declaration);
202
- };
203
- visitRenderTag = (node) => this.visit(node.expression);
204
- visitHtmlTag = (node) => this.visit(node.expression);
205
- visitOnDirective = (node) => this.visit(node.expression);
206
- hasIdentifier = (node, name) => {
211
+ }
212
+ visitDeclarationTag(node) {
213
+ const prevDeclaring = this.heuristciDetails.declaring;
214
+ this.heuristciDetails.declaring = 'variable';
215
+ // @ts-expect-error
216
+ const msgs = this.visitVariableDeclaration(node.declaration);
217
+ this.heuristciDetails.declaring = prevDeclaring;
218
+ return msgs;
219
+ }
220
+ visitRenderTag(node) {
221
+ return this.visit(node.expression);
222
+ }
223
+ visitHtmlTag(node) {
224
+ return this.visit(node.expression);
225
+ }
226
+ visitOnDirective(node) {
227
+ return this.visit(node.expression);
228
+ }
229
+ hasIdentifier(node, name) {
207
230
  if (!node || typeof node !== 'object') {
208
231
  return false;
209
232
  }
@@ -214,8 +237,8 @@ export class SvelteTransformer extends Transformer {
214
237
  return node.name === name;
215
238
  }
216
239
  return Object.values(node).some(value => this.hasIdentifier(value, name));
217
- };
218
- visitSnippetBlock = (node) => {
240
+ }
241
+ visitSnippetBlock(node) {
219
242
  // use module runtime var because the snippet may be exported from the module
220
243
  const prevRtVar = this.currentRtVar;
221
244
  if (this.hasIdentifier(this.moduleExportExprs, node.expression.name)) {
@@ -224,16 +247,16 @@ export class SvelteTransformer extends Transformer {
224
247
  const msgs = this.visitFragment(node.body);
225
248
  this.currentRtVar = prevRtVar;
226
249
  return msgs;
227
- };
228
- visitIfBlock = (node) => {
250
+ }
251
+ visitIfBlock(node) {
229
252
  const msgs = this.visit(node.test);
230
253
  msgs.push(...this.visitSv(node.consequent));
231
254
  if (node.alternate) {
232
255
  msgs.push(...this.visitSv(node.alternate));
233
256
  }
234
257
  return msgs;
235
- };
236
- visitEachBlock = (node) => {
258
+ }
259
+ visitEachBlock(node) {
237
260
  const msgs = [...this.visit(node.expression), ...this.visitSv(node.body)];
238
261
  if (node.key) {
239
262
  msgs.push(...this.visit(node.key));
@@ -242,11 +265,11 @@ export class SvelteTransformer extends Transformer {
242
265
  msgs.push(...this.visitSv(node.fallback));
243
266
  }
244
267
  return msgs;
245
- };
246
- visitKeyBlock = (node) => {
268
+ }
269
+ visitKeyBlock(node) {
247
270
  return [...this.visit(node.expression), ...this.visitSv(node.fragment)];
248
- };
249
- visitAwaitBlock = (node) => {
271
+ }
272
+ visitAwaitBlock(node) {
250
273
  const msgs = this.visit(node.expression);
251
274
  if (node.then) {
252
275
  msgs.push(...this.visitFragment(node.then));
@@ -258,18 +281,38 @@ export class SvelteTransformer extends Transformer {
258
281
  msgs.push(...this.visitFragment(node.catch));
259
282
  }
260
283
  return msgs;
261
- };
262
- visitSvelteBody = (node) => node.attributes.flatMap(this.visitSv);
263
- visitSvelteDocument = (node) => node.attributes.flatMap(this.visitSv);
264
- visitSvelteElement = (node) => node.attributes.flatMap(this.visitSv);
265
- visitSvelteBoundary = (node) => [
266
- ...node.attributes.flatMap(this.visitSv),
267
- ...this.visitSv(node.fragment),
268
- ];
269
- visitSvelteHead = (node) => this.visitSv(node.fragment);
270
- visitTitleElement = (node) => this.visitRegularElement(node);
271
- visitSvelteWindow = (node) => node.attributes.flatMap(this.visitSv);
272
- visitRoot = (node) => {
284
+ }
285
+ visitSvelteBody(node) {
286
+ return node.attributes.flatMap(n => this.visitSv(n));
287
+ }
288
+ visitSvelteDocument(node) {
289
+ return node.attributes.flatMap(n => this.visitSv(n));
290
+ }
291
+ visitSvelteElement(node) {
292
+ const currentElement = this.currentElement;
293
+ if (node.tag.type === 'Literal' && typeof node.tag.value === 'string') {
294
+ this.currentElement = node.tag.value;
295
+ }
296
+ else {
297
+ this.currentElement = 'svelte:element';
298
+ }
299
+ const msgs = [...node.attributes.flatMap(n => this.visitSv(n)), ...this.visitFragment(node.fragment)];
300
+ this.currentElement = currentElement;
301
+ return msgs;
302
+ }
303
+ visitSvelteBoundary(node) {
304
+ return [...node.attributes.flatMap(n => this.visitSv(n)), ...this.visitSv(node.fragment)];
305
+ }
306
+ visitSvelteHead(node) {
307
+ return this.visitSv(node.fragment);
308
+ }
309
+ visitTitleElement(node) {
310
+ return this.visitRegularElement(node);
311
+ }
312
+ visitSvelteWindow(node) {
313
+ return node.attributes.flatMap(n => this.visitSv(n));
314
+ }
315
+ visitRoot(node) {
273
316
  const msgs = [];
274
317
  if (node.module) {
275
318
  const prevRtVar = this.currentRtVar;
@@ -293,10 +336,12 @@ export class SvelteTransformer extends Transformer {
293
336
  }
294
337
  msgs.push(...this.visitFragment(node.fragment));
295
338
  return msgs;
296
- };
297
- visitSv = (node) => this.visit(node);
339
+ }
340
+ visitSv(node) {
341
+ return this.visit(node);
342
+ }
298
343
  /** collects the ranges that will be checked if a snippet identifier is exported using RegExp test to simplify */
299
- collectModuleExportExprs = (script) => {
344
+ collectModuleExportExprs(script) {
300
345
  for (const stmt of script.content.body) {
301
346
  if (stmt.type !== 'ExportNamedDeclaration') {
302
347
  continue;
@@ -322,8 +367,8 @@ export class SvelteTransformer extends Transformer {
322
367
  this.moduleExportExprs.push(decl.init);
323
368
  }
324
369
  }
325
- };
326
- transformSv = async () => {
370
+ }
371
+ async transformSv() {
327
372
  const isComponent = this.heuristciDetails.file.endsWith('.svelte');
328
373
  let ast;
329
374
  if (isComponent) {
@@ -369,5 +414,5 @@ export class SvelteTransformer extends Transformer {
369
414
  // now hmr data can be prependRight(0, ...)
370
415
  }
371
416
  return this.finalize(msgs, headerIndex, headerAdd);
372
- };
417
+ }
373
418
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wuchale/svelte",
3
- "version": "0.19.4",
3
+ "version": "0.20.0",
4
4
  "description": "Protobuf-like i18n from plain code: Svelte adapter",
5
5
  "scripts": {
6
6
  "dev": "tsc --watch",
@@ -50,13 +50,15 @@
50
50
  "bugs": "https://github.com/wuchalejs/wuchale/issues",
51
51
  "author": "K1DV5",
52
52
  "license": "MIT",
53
+ "peerDependencies": {
54
+ "svelte": "^5"
55
+ },
53
56
  "dependencies": {
54
- "magic-string": "^0.30.21",
55
- "svelte": "^5",
56
- "wuchale": "^0.23.0"
57
+ "wuchale": "^0.24.0"
57
58
  },
58
59
  "devDependencies": {
59
- "@types/node": "~24.12.2",
60
+ "@types/node": "~24.13.1",
61
+ "svelte": "^5.56.3",
60
62
  "acorn": "^8.16.0",
61
63
  "typescript": "^6.0.3"
62
64
  },
@@ -12,7 +12,7 @@ export function setLocale(newLocale) {
12
12
 
13
13
  // for non-reactive
14
14
  /**
15
- * @param {{ [locale: string]: import("wuchale/runtime").CatalogModule }} catalogs
15
+ * @param {{ [locale in import('${DATA}').Locale]: import("wuchale/runtime").CatalogModule }} catalogs
16
16
  */
17
17
  export const getRuntime = catalogs => toRuntime(catalogs[locale], locale)
18
18
 
@@ -1,12 +1,13 @@
1
1
  import { defaultCollection, registerLoaders } from 'wuchale/load-utils'
2
- import { loadCatalog, loadIDs } from '${PROXY}'
2
+ import { loadCatalog, loadCount } from '${PROXY}'
3
3
 
4
4
  const key = '${KEY}'
5
5
 
6
- const runtimes = $state({})
6
+ /** @type import('wuchale/runtime').Runtime[] */
7
+ const runtimes = $state([])
7
8
 
8
9
  // for non-reactive
9
- export const getRuntime = registerLoaders(key, loadCatalog, loadIDs, defaultCollection(runtimes))
10
+ export const getRuntime = registerLoaders(key, loadCatalog, loadCount, defaultCollection(runtimes))
10
11
 
11
12
  // same function, only will be inside $derived when used
12
13
  export const getRuntimeRx = getRuntime
@@ -1,12 +1,12 @@
1
1
  import { currentRuntime } from 'wuchale/load-utils/server'
2
- import { loadCatalog, loadIDs } from '${PROXY_SYNC}'
2
+ import { loadCatalog, loadCount } from '${PROXY_SYNC}'
3
3
 
4
4
  const key = '${KEY}'
5
5
 
6
- export { key, loadCatalog, loadIDs } // for hooks.server.{js,ts}
6
+ export { key, loadCatalog, loadCount } // for hooks.server.{js,ts}
7
7
 
8
8
  // for non-reactive
9
- export const getRuntime = (/** @type {string} */ loadID) => currentRuntime(key, loadID)
9
+ export const getRuntime = (loadID = 0) => currentRuntime(key, loadID)
10
10
 
11
11
  // same function, only will be inside $derived when used
12
12
  export const getRuntimeRx = getRuntime