@wuchale/svelte 0.16.0 → 0.16.2

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.d.ts CHANGED
@@ -1,2 +1,6 @@
1
- import type { Adapter, AdapterArgs } from 'wuchale';
1
+ import type { HeuristicFunc, Adapter, AdapterArgs } from 'wuchale';
2
+ /** Default Svelte heuristic which extracts top level variable assignments as well, leading to `$derived` being auto added when needed */
3
+ export declare const svelteDefaultHeuristic: HeuristicFunc;
4
+ /** Default Svelte heuristic which requires `$derived` or `$derived.by` for top level variable assignments */
5
+ export declare const svelteDefaultHeuristicDerivedReq: HeuristicFunc;
2
6
  export declare const adapter: (args?: AdapterArgs) => Adapter;
package/dist/index.js CHANGED
@@ -2,7 +2,8 @@ import { defaultGenerateLoadID, defaultHeuristic, deepMergeObjects } from 'wucha
2
2
  import { SvelteTransformer } from "./transformer.js";
3
3
  import { getDependencies, loaderPathResolver } from 'wuchale/adapter-utils';
4
4
  import { pluralPattern } from 'wuchale/adapter-vanilla';
5
- const svelteHeuristic = msg => {
5
+ /** Default Svelte heuristic which extracts top level variable assignments as well, leading to `$derived` being auto added when needed */
6
+ export const svelteDefaultHeuristic = msg => {
6
7
  if (!defaultHeuristic(msg)) {
7
8
  return false;
8
9
  }
@@ -14,11 +15,24 @@ const svelteHeuristic = msg => {
14
15
  }
15
16
  return true;
16
17
  };
18
+ /** Default Svelte heuristic which requires `$derived` or `$derived.by` for top level variable assignments */
19
+ export const svelteDefaultHeuristicDerivedReq = msg => {
20
+ if (!svelteDefaultHeuristic(msg)) {
21
+ return false;
22
+ }
23
+ if (msg.details.scope !== 'script' || msg.details.declaring !== 'variable') {
24
+ return true;
25
+ }
26
+ if (!msg.details.topLevelCall) {
27
+ return false;
28
+ }
29
+ return ['$derived', '$derived.by'].includes(msg.details.topLevelCall);
30
+ };
17
31
  const defaultArgs = {
18
32
  files: ['src/**/*.svelte', 'src/**/*.svelte.{js,ts}'],
19
33
  catalog: './src/locales/{locale}',
20
34
  patterns: [pluralPattern],
21
- heuristic: svelteHeuristic,
35
+ heuristic: svelteDefaultHeuristic,
22
36
  granularLoad: false,
23
37
  bundleLoad: false,
24
38
  generateLoadID: defaultGenerateLoadID,
@@ -11,6 +11,7 @@ export declare class SvelteTransformer extends Transformer {
11
11
  commentDirectivesStack: CommentDirectives[];
12
12
  lastVisitIsComment: boolean;
13
13
  currentSnippet: number;
14
+ moduleExportRanges: [number, number][];
14
15
  mixedVisitor: MixedVisitor<MixedNodesTypes>;
15
16
  constructor(content: string, filename: string, index: IndexTracker, heuristic: HeuristicFunc, patterns: CodePattern[], catalogExpr: CatalogExpr, rtConf: RuntimeConf);
16
17
  visitExpressionTag: (node: AST.ExpressionTag) => Message[];
@@ -36,6 +37,8 @@ export declare class SvelteTransformer extends Transformer {
36
37
  visitSvelteWindow: (node: AST.SvelteWindow) => Message[];
37
38
  visitRoot: (node: AST.Root) => Message[];
38
39
  visitSv: (node: AST.SvelteNode | AnyNode) => Message[];
40
+ /** collects the ranges that will be checked if a snippet identifier is exported using RegExp test to simplify */
41
+ collectModuleExportRanges: (script: AST.Script) => void;
39
42
  transformSv: () => TransformOutput;
40
43
  }
41
44
  export {};
@@ -14,6 +14,7 @@ export class SvelteTransformer extends Transformer {
14
14
  commentDirectivesStack = [];
15
15
  lastVisitIsComment = false;
16
16
  currentSnippet = 0;
17
+ moduleExportRanges = []; // to choose which runtime var to use for snippets
17
18
  mixedVisitor;
18
19
  constructor(content, filename, index, heuristic, patterns, catalogExpr, rtConf) {
19
20
  super(content, filename, index, heuristic, patterns, catalogExpr, rtConf, [varNames.rt, rtModuleVar]);
@@ -25,7 +26,7 @@ export class SvelteTransformer extends Transformer {
25
26
  return msgs;
26
27
  }
27
28
  const needsWrapping = msgs.some(msg => {
28
- if (['$derived', '$derived.by'].includes(msg.details.topLevelCall)) {
29
+ if (['$props', '$derived', '$derived.by'].includes(msg.details.topLevelCall)) {
29
30
  return false;
30
31
  }
31
32
  if (msg.details.declaring !== 'variable') {
@@ -165,7 +166,17 @@ export class SvelteTransformer extends Transformer {
165
166
  }
166
167
  return [msgInfo];
167
168
  };
168
- visitSnippetBlock = (node) => this.visitFragment(node.body);
169
+ visitSnippetBlock = (node) => {
170
+ // use module runtime var because the snippet may be exported from the module
171
+ const prevRtVar = this.currentRtVar;
172
+ const pattern = new RegExp(`\\b${node.expression.name}\\b`);
173
+ if (this.moduleExportRanges.some(([start, end]) => pattern.test(this.content.slice(start, end)))) {
174
+ this.currentRtVar = rtModuleVar;
175
+ }
176
+ const msgs = this.visitFragment(node.body);
177
+ this.currentRtVar = prevRtVar;
178
+ return msgs;
179
+ };
169
180
  visitIfBlock = (node) => {
170
181
  const msgs = this.visit(node.test);
171
182
  msgs.push(...this.visitSv(node.consequent));
@@ -218,7 +229,6 @@ export class SvelteTransformer extends Transformer {
218
229
  visitSvelteWindow = (node) => node.attributes.map(this.visitSv).flat();
219
230
  visitRoot = (node) => {
220
231
  const msgs = [];
221
- // @ts-ignore: module is a reserved keyword, not sure how to specify the type
222
232
  if (node.module) {
223
233
  const prevRtVar = this.currentRtVar;
224
234
  this.currentRtVar = rtModuleVar;
@@ -269,6 +279,34 @@ export class SvelteTransformer extends Transformer {
269
279
  this.commentDirectives = commentDirectivesPrev;
270
280
  return msgs;
271
281
  };
282
+ /** collects the ranges that will be checked if a snippet identifier is exported using RegExp test to simplify */
283
+ collectModuleExportRanges = (script) => {
284
+ for (const stmt of script.content.body) {
285
+ if (stmt.type !== 'ExportNamedDeclaration') {
286
+ continue;
287
+ }
288
+ for (const spec of stmt.specifiers) {
289
+ if (spec.local.type === 'Identifier') {
290
+ const local = spec.local;
291
+ this.moduleExportRanges.push([local.start, local.end]);
292
+ }
293
+ }
294
+ const declaration = stmt.declaration;
295
+ if (!declaration) {
296
+ continue;
297
+ }
298
+ if (declaration.type === 'FunctionDeclaration' || declaration.type === 'ClassDeclaration') {
299
+ this.moduleExportRanges.push([declaration.start, declaration.end]);
300
+ continue;
301
+ }
302
+ for (const decl of declaration.declarations) {
303
+ if (!decl.init) {
304
+ continue;
305
+ }
306
+ this.moduleExportRanges.push([decl.init.start, decl.init.end]);
307
+ }
308
+ }
309
+ };
272
310
  transformSv = () => {
273
311
  const isComponent = this.filename.endsWith('.svelte');
274
312
  let ast;
@@ -282,6 +320,9 @@ export class SvelteTransformer extends Transformer {
282
320
  }
283
321
  this.mstr = new MagicString(this.content);
284
322
  this.mixedVisitor = this.initMixedVisitor();
323
+ if (ast.type === 'Root' && ast.module) {
324
+ this.collectModuleExportRanges(ast.module);
325
+ }
285
326
  const msgs = this.visitSv(ast);
286
327
  const initRuntime = this.initRuntime(this.filename, null, null, {});
287
328
  if (ast.type === 'Program') {
@@ -291,7 +332,7 @@ export class SvelteTransformer extends Transformer {
291
332
  }
292
333
  let headerIndex = 0;
293
334
  if (ast.module) {
294
- // @ts-ignore
335
+ // @ts-expect-error
295
336
  headerIndex = this.getRealBodyStart(ast.module.content.body) ?? ast.module.content.start;
296
337
  }
297
338
  if (ast.instance) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wuchale/svelte",
3
- "version": "0.16.0",
3
+ "version": "0.16.2",
4
4
  "description": "Protobuf-like i18n from plain code: Svelte adapter",
5
5
  "scripts": {
6
6
  "dev": "tsc --watch",
@@ -52,11 +52,11 @@
52
52
  "license": "MIT",
53
53
  "dependencies": {
54
54
  "svelte": "^5.37.0",
55
- "wuchale": "^0.17.0"
55
+ "wuchale": "^0.17.1"
56
56
  },
57
57
  "devDependencies": {
58
58
  "acorn": "^8.15.0",
59
- "typescript": "^5.8.3"
59
+ "typescript": "^5.9.3"
60
60
  },
61
61
  "type": "module"
62
62
  }