@wuchale/svelte 0.13.4 → 0.14.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,5 +1,4 @@
1
1
  import { defaultGenerateLoadID, defaultHeuristic, deepMergeObjects } from 'wuchale';
2
- import { initRuntimeStmt, adapter as vanillaAdapter } from 'wuchale/adapter-vanilla';
3
2
  import { SvelteTransformer } from "./transformer.js";
4
3
  import { getDependencies } from 'wuchale/adapter-utils';
5
4
  const topLevelDeclarationsInside = ['$derived', '$derived.by'];
@@ -31,12 +30,32 @@ const defaultArgs = {
31
30
  bundleLoad: false,
32
31
  generateLoadID: defaultGenerateLoadID,
33
32
  writeFiles: {},
33
+ runtime: {
34
+ useReactive: ({ file, funcName, additional }) => {
35
+ const inTopLevel = funcName == null;
36
+ const inModule = file.endsWith('.svelte.js') || additional.module;
37
+ return {
38
+ init: inModule ? inTopLevel : (inTopLevel ? true : null),
39
+ use: inModule ? inTopLevel : true,
40
+ };
41
+ },
42
+ reactive: {
43
+ importName: 'default',
44
+ wrapInit: expr => `$derived(${expr})`,
45
+ wrapUse: expr => expr,
46
+ },
47
+ plain: {
48
+ importName: 'get',
49
+ wrapInit: expr => expr,
50
+ wrapUse: expr => expr,
51
+ },
52
+ },
34
53
  };
35
54
  export const adapter = (args = defaultArgs) => {
36
- const { heuristic, pluralsFunc, ...rest } = deepMergeObjects(args, defaultArgs);
55
+ const { heuristic, pluralsFunc, runtime, ...rest } = deepMergeObjects(args, defaultArgs);
37
56
  return {
38
57
  transform: ({ content, filename, index, header }) => {
39
- return new SvelteTransformer(content, filename, index, heuristic, pluralsFunc, initRuntimeStmt(header.expr)).transformSv(header.head, header.expr);
58
+ return new SvelteTransformer(content, filename, index, heuristic, pluralsFunc, header.expr, runtime).transformSv(header.head);
40
59
  },
41
60
  loaderExts: ['.svelte.js', '.svelte.ts', '.js', '.ts'],
42
61
  defaultLoaders: async () => {
@@ -44,18 +63,22 @@ export const adapter = (args = defaultArgs) => {
44
63
  return ['bundle'];
45
64
  }
46
65
  const deps = await getDependencies();
47
- const available = ['reactive', 'vanilla'];
66
+ const available = ['svelte'];
48
67
  if (deps.has('@sveltejs/kit')) {
49
68
  available.unshift('sveltekit');
50
69
  }
51
70
  return available;
52
71
  },
53
- defaultLoaderPath: (loader) => {
54
- if (loader === 'vanilla') {
55
- return vanillaAdapter().defaultLoaderPath('vite');
72
+ defaultLoaderPath: loader => {
73
+ if (loader === 'sveltekit') {
74
+ return {
75
+ client: new URL(`../src/loaders/svelte.svelte.js`, import.meta.url).pathname,
76
+ ssr: new URL(`../src/loaders/sveltekit.ssr.svelte.js`, import.meta.url).pathname
77
+ };
56
78
  }
57
79
  return new URL(`../src/loaders/${loader}.svelte.js`, import.meta.url).pathname;
58
80
  },
81
+ runtime,
59
82
  ...rest,
60
83
  docsUrl: 'https://wuchale.dev/adapters/svelte'
61
84
  };
@@ -2,7 +2,7 @@ import type { AnyNode } from "acorn";
2
2
  import { type AST } from "svelte/compiler";
3
3
  import { Message } from 'wuchale';
4
4
  import { Transformer } from 'wuchale/adapter-vanilla';
5
- import type { IndexTracker, HeuristicFunc, TransformOutput, CommentDirectives } from 'wuchale';
5
+ import type { IndexTracker, HeuristicFunc, TransformOutput, CommentDirectives, CatalogExpr, RuntimeConf } from 'wuchale';
6
6
  import { MixedVisitor } from "wuchale/adapter-utils";
7
7
  type MixedNodesTypes = AST.Text | AST.Tag | AST.ElementLike | AST.Block | AST.Comment;
8
8
  export declare class SvelteTransformer extends Transformer {
@@ -12,7 +12,7 @@ export declare class SvelteTransformer extends Transformer {
12
12
  lastVisitIsComment: boolean;
13
13
  currentSnippet: number;
14
14
  mixedVisitor: MixedVisitor<MixedNodesTypes>;
15
- constructor(content: string, filename: string, index: IndexTracker, heuristic: HeuristicFunc, pluralsFunc: string, initRuntime: string);
15
+ constructor(content: string, filename: string, index: IndexTracker, heuristic: HeuristicFunc, pluralsFunc: string, catalogExpr: CatalogExpr, rtConf: RuntimeConf);
16
16
  visitExpressionTag: (node: AST.ExpressionTag) => Message[];
17
17
  initMixedVisitor: () => MixedVisitor<MixedNodesTypes>;
18
18
  visitFragment: (node: AST.Fragment) => Message[];
@@ -34,6 +34,6 @@ export declare class SvelteTransformer extends Transformer {
34
34
  visitSvelteWindow: (node: AST.SvelteWindow) => Message[];
35
35
  visitRoot: (node: AST.Root) => Message[];
36
36
  visitSv: (node: AST.SvelteNode | AnyNode) => Message[];
37
- transformSv: (headerHead: string, headerExpr: string) => TransformOutput;
37
+ transformSv: (headerHead: string) => TransformOutput;
38
38
  }
39
39
  export {};
@@ -2,7 +2,7 @@ import MagicString from "magic-string";
2
2
  import { parse } from "svelte/compiler";
3
3
  import { Message } from 'wuchale';
4
4
  import { Transformer, parseScript } from 'wuchale/adapter-vanilla';
5
- import { MixedVisitor, nonWhitespaceText, runtimeVars } from "wuchale/adapter-utils";
5
+ import { MixedVisitor, nonWhitespaceText } from "wuchale/adapter-utils";
6
6
  const nodesWithChildren = ['RegularElement', 'Component'];
7
7
  const rtComponent = 'WuchaleTrans';
8
8
  const snipPrefix = 'wuchaleSnippet';
@@ -14,12 +14,13 @@ export class SvelteTransformer extends Transformer {
14
14
  lastVisitIsComment = false;
15
15
  currentSnippet = 0;
16
16
  mixedVisitor;
17
- constructor(content, filename, index, heuristic, pluralsFunc, initRuntime) {
18
- super(content, filename, index, heuristic, pluralsFunc, initRuntime);
17
+ constructor(content, filename, index, heuristic, pluralsFunc, catalogExpr, rtConf) {
18
+ super(content, filename, index, heuristic, pluralsFunc, catalogExpr, rtConf);
19
19
  }
20
20
  visitExpressionTag = (node) => this.visit(node.expression);
21
21
  initMixedVisitor = () => new MixedVisitor({
22
22
  mstr: this.mstr,
23
+ vars: this.vars,
23
24
  getRange: node => ({ start: node.start, end: node.end }),
24
25
  isText: node => node.type === 'Text',
25
26
  isComment: node => node.type === 'Comment',
@@ -44,17 +45,17 @@ export class SvelteTransformer extends Transformer {
44
45
  const snippetName = `${snipPrefix}${this.currentSnippet}`;
45
46
  snippets.push(snippetName);
46
47
  this.currentSnippet++;
47
- const snippetBegin = `\n{#snippet ${snippetName}(${haveCtx ? runtimeVars.nestCtx : ''})}\n`;
48
+ const snippetBegin = `\n{#snippet ${snippetName}(${haveCtx ? this.vars().nestCtx : ''})}\n`;
48
49
  this.mstr.appendRight(childStart, snippetBegin);
49
50
  this.mstr.prependLeft(childEnd, '\n{/snippet}');
50
51
  }
51
52
  let begin = `\n<${rtComponent} tags={[${snippets.join(', ')}]} ctx=`;
52
53
  if (this.inCompoundText) {
53
- begin += `{${runtimeVars.nestCtx}} nest`;
54
+ begin += `{${this.vars().nestCtx}} nest`;
54
55
  }
55
56
  else {
56
57
  const index = this.index.get(msgInfo.toKey());
57
- begin += `{${runtimeVars.rtCtx}(${index})}`;
58
+ begin += `{${this.vars().rtCtx}(${index})}`;
58
59
  }
59
60
  let end = ' />\n';
60
61
  if (hasExprs) {
@@ -93,7 +94,7 @@ export class SvelteTransformer extends Transformer {
93
94
  if (!pass) {
94
95
  return [];
95
96
  }
96
- this.mstr.update(node.start + startWh, node.end - endWh, `{${runtimeVars.rtTrans}(${this.index.get(msgInfo.toKey())})}`);
97
+ this.mstr.update(node.start + startWh, node.end - endWh, `{${this.vars().rtTrans}(${this.index.get(msgInfo.toKey())})}`);
97
98
  return [msgInfo];
98
99
  };
99
100
  visitSpreadAttribute = (node) => this.visit(node.expression);
@@ -120,7 +121,7 @@ export class SvelteTransformer extends Transformer {
120
121
  }
121
122
  const value = values[0];
122
123
  if (value.type !== 'Text') {
123
- return [];
124
+ return this.visitSv(value);
124
125
  }
125
126
  const [pass, msgInfo] = this.checkHeuristic(value.data, {
126
127
  scope: 'attribute',
@@ -130,7 +131,7 @@ export class SvelteTransformer extends Transformer {
130
131
  if (!pass) {
131
132
  return [];
132
133
  }
133
- this.mstr.update(value.start, value.end, `{${runtimeVars.rtTrans}(${this.index.get(msgInfo.toKey())})}`);
134
+ this.mstr.update(value.start, value.end, `{${this.vars().rtTrans}(${this.index.get(msgInfo.toKey())})}`);
134
135
  if (`'"`.includes(this.content[value.start - 1])) {
135
136
  this.mstr.remove(value.start - 1, value.start);
136
137
  this.mstr.remove(value.end, value.end + 1);
@@ -191,21 +192,17 @@ export class SvelteTransformer extends Transformer {
191
192
  const msgs = [];
192
193
  // @ts-ignore: module is a reserved keyword, not sure how to specify the type
193
194
  if (node.module) {
195
+ this.additionalState = { module: true };
194
196
  this.commentDirectives = {}; // reset
195
197
  // @ts-ignore
196
198
  msgs.push(...this.visitProgram(node.module.content));
199
+ this.additionalState = {}; // reset
197
200
  }
198
- // no need to init runtime inside components outside <script module>s
199
- // they run everytime they are rendered instead of once at startup
200
- const initRuntime = this.initRuntime;
201
- this.initRuntime = null;
202
201
  if (node.instance) {
203
202
  this.commentDirectives = {}; // reset
204
203
  msgs.push(...this.visitProgram(node.instance.content));
205
204
  }
206
205
  msgs.push(...this.visitFragment(node.fragment));
207
- // restore just in case
208
- this.initRuntime = initRuntime;
209
206
  return msgs;
210
207
  };
211
208
  visitSv = (node) => {
@@ -235,7 +232,7 @@ export class SvelteTransformer extends Transformer {
235
232
  this.commentDirectives = commentDirectivesPrev;
236
233
  return msgs;
237
234
  };
238
- transformSv = (headerHead, headerExpr) => {
235
+ transformSv = (headerHead) => {
239
236
  const isComponent = this.filename.endsWith('.svelte');
240
237
  let ast;
241
238
  if (isComponent) {
@@ -255,22 +252,23 @@ export class SvelteTransformer extends Transformer {
255
252
  const headerLines = [
256
253
  isComponent ? `\nimport ${rtComponent} from "@wuchale/svelte/runtime.svelte"` : '',
257
254
  headerHead,
258
- `const ${runtimeVars.rtConst} = $derived(${runtimeVars.rtWrap}(${headerExpr}))\n`,
255
+ this.initRuntime(this.filename, null, null, {}),
259
256
  ];
260
257
  const headerFin = headerLines.join('\n');
261
258
  if (ast.type === 'Program') {
262
- this.mstr.appendRight(0, headerFin + '\n');
263
- return this.finalize(msgs, 0);
259
+ const bodyStart = this.getRealBodyStart(ast.body);
260
+ this.mstr.appendRight(bodyStart, headerFin + '\n');
261
+ return this.finalize(msgs, bodyStart);
264
262
  }
265
263
  let hmrHeaderIndex = 0;
266
264
  if (ast.module) {
267
265
  // @ts-ignore
268
- hmrHeaderIndex = ast.module.content.start;
266
+ hmrHeaderIndex = this.getRealBodyStart(ast.module.content.body);
269
267
  this.mstr.appendRight(hmrHeaderIndex, headerFin);
270
268
  }
271
269
  else if (ast.instance) {
272
270
  // @ts-ignore
273
- hmrHeaderIndex = ast.instance.content.start;
271
+ hmrHeaderIndex = this.getRealBodyStart(ast.instance.content.body);
274
272
  this.mstr.appendRight(hmrHeaderIndex, headerFin);
275
273
  }
276
274
  else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wuchale/svelte",
3
- "version": "0.13.4",
3
+ "version": "0.14.0",
4
4
  "description": "Protobuf-like i18n from plain code: Svelte adapter",
5
5
  "scripts": {
6
6
  "dev": "tsc --watch",
@@ -52,7 +52,7 @@
52
52
  "license": "MIT",
53
53
  "dependencies": {
54
54
  "svelte": "^5.37.0",
55
- "wuchale": "^0.14.2"
55
+ "wuchale": "^0.15.0"
56
56
  },
57
57
  "devDependencies": {
58
58
  "acorn": "^8.15.0",
@@ -10,7 +10,11 @@ export function setLocale(newLocale) {
10
10
  locale = newLocale
11
11
  }
12
12
 
13
+ // for non-reactive
13
14
  /**
14
15
  * @param {{ [locale: string]: import("wuchale/runtime").CatalogModule }} catalogs
15
16
  */
16
- export default catalogs => catalogs[locale]
17
+ export const get = catalogs => catalogs[locale]
18
+
19
+ // same function, only will be inside $derived when used
20
+ export default get
@@ -8,4 +8,8 @@ import { registerLoaders, defaultCollection } from 'wuchale/load-utils'
8
8
 
9
9
  const catalogs = $state({})
10
10
 
11
- export default registerLoaders(key, loadCatalog, loadIDs, defaultCollection(catalogs))
11
+ // for non-reactive
12
+ export const get = registerLoaders(key, loadCatalog, loadIDs, defaultCollection(catalogs))
13
+
14
+ // same function, only will be inside $derived when used
15
+ export default get
@@ -0,0 +1,15 @@
1
+ // This is just the default loader.
2
+ // You can customize it however you want, it will not be overwritten once it exists and is not empty.
3
+
4
+ /// <reference types="wuchale/virtual" />
5
+
6
+ import { loadCatalog, loadIDs, key } from 'virtual:wuchale/proxy/sync' // because it's on the server
7
+ import { currentCatalog } from 'wuchale/load-utils/server'
8
+
9
+ export { loadCatalog, loadIDs, key } // for hooks.server.{js,ts}
10
+
11
+ // for non-reactive
12
+ export const get = (/** @type {string} */ loadID) => currentCatalog(key, loadID)
13
+
14
+ // same function, only will be inside $derived when used
15
+ export default get
@@ -1,21 +0,0 @@
1
- // This is just the default loader.
2
- // You can customize it however you want, it will not be overwritten once it exists and is not empty.
3
-
4
- /// <reference types="wuchale/virtual" />
5
-
6
- import { loadCatalog, loadIDs, key } from 'virtual:wuchale/proxy' // or proxy/sync
7
- import { registerLoaders, defaultCollection } from 'wuchale/load-utils'
8
-
9
- export { loadCatalog, loadIDs, key } // for +layout.{js,ts} and hooks.server.{js,ts}
10
-
11
- let loadC
12
-
13
- if (import.meta.env.SSR) { // stripped from production client builds
14
- const { currentCatalog } = await import('wuchale/load-utils/server')
15
- loadC = (/** @type {string} */ loadID) => currentCatalog(key, loadID)
16
- } else { // client
17
- const catalogs = $state({})
18
- loadC = registerLoaders(key, loadCatalog, loadIDs, defaultCollection(catalogs))
19
- }
20
-
21
- export default loadC