@verbaly/vite 0.2.0 → 0.4.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/README.md +46 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/README.md
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://raw.githubusercontent.com/AronSoto/verbaly/develop/assets/logo-light.png" alt="Verbaly" width="300" />
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<p align="center"><em>Zero-config Vite plugin for Verbaly — live extraction, codegen and HMR.</em></p>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<a href="https://www.npmjs.com/package/@verbaly/vite"><img src="https://img.shields.io/npm/v/@verbaly/vite?logo=npm&color=cb3837" alt="npm version" /></a>
|
|
9
|
+
<a href="https://github.com/AronSoto/verbaly/blob/develop/LICENSE"><img src="https://img.shields.io/npm/l/@verbaly/vite?color=blue" alt="Apache-2.0" /></a>
|
|
10
|
+
</p>
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
The Vite plugin for [Verbaly](https://github.com/AronSoto/verbaly). Write natural text in your code; on save it extracts stable keys, syncs per-locale JSON catalogs, generates typed `virtual:verbaly` + `verbaly.d.ts`, and **fails `vite build` when a translation is missing**.
|
|
15
|
+
|
|
16
|
+
## Install
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
pnpm add verbaly @verbaly/vite
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
// vite.config.ts
|
|
24
|
+
import verbaly from '@verbaly/vite';
|
|
25
|
+
|
|
26
|
+
export default {
|
|
27
|
+
plugins: [verbaly({ sourceLocale: 'en', locales: ['en', 'es', 'pt'] })],
|
|
28
|
+
};
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
// anywhere in your app — extracted + typed on save
|
|
33
|
+
import { t, setLocale } from 'virtual:verbaly';
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
- **Live extraction** with debounced catalog writes + HMR.
|
|
37
|
+
- **Per-locale code-splitting** — `setLocale` lazy-loads only what's used.
|
|
38
|
+
- **Build gate** — missing translations stop the build (same as `verbaly check`).
|
|
39
|
+
|
|
40
|
+
📖 Docs & live playground: **https://verbaly-web.vercel.app**
|
|
41
|
+
|
|
42
|
+
> ⚠️ Early development (`0.x`) — API not stable yet.
|
|
43
|
+
|
|
44
|
+
## License
|
|
45
|
+
|
|
46
|
+
[Apache-2.0](https://github.com/AronSoto/verbaly/blob/develop/LICENSE) © Aron Soto
|
package/dist/index.js
CHANGED
|
@@ -79,6 +79,12 @@ function verbaly(options = {}) {
|
|
|
79
79
|
(file) => onCatalogFile(file, file.split(/[\\/]/).pop()?.slice(0, -5))
|
|
80
80
|
);
|
|
81
81
|
devServer.watcher.on("add", (file) => onCatalogFile(file));
|
|
82
|
+
devServer.watcher.on("unlink", (file) => {
|
|
83
|
+
if (SOURCE_RE.test(file) && !file.includes("node_modules")) {
|
|
84
|
+
registry.remove(file);
|
|
85
|
+
scheduleFlush();
|
|
86
|
+
}
|
|
87
|
+
});
|
|
82
88
|
},
|
|
83
89
|
resolveId(id) {
|
|
84
90
|
if (id === VIRTUAL_ID || id.startsWith(`${VIRTUAL_ID}/`)) return "\0" + id;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import {\
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import {\n MessageRegistry,\n VIRTUAL_ID,\n analyze,\n check,\n formatCheckResult,\n generateLocaleModule,\n generateRuntimeModule,\n loadCatalogs,\n loadConfig,\n syncCatalogs,\n transformCode,\n writeCatalog,\n writeDts,\n type Catalogs,\n type ResolvedConfig,\n type VerbalyConfig,\n} from '@verbaly/compiler';\nimport type { Plugin, ViteDevServer } from 'vite';\n\nconst RESOLVED = '\\0' + VIRTUAL_ID;\nconst LOCALE_PREFIX = `${RESOLVED}/locale/`;\nconst SOURCE_RE = /\\.[cm]?[jt]sx?$/;\n\nexport type { VerbalyConfig } from '@verbaly/compiler';\n\nexport default function verbaly(options: VerbalyConfig = {}): Plugin {\n let cfg: ResolvedConfig;\n let catalogs: Catalogs;\n let isBuild = false;\n let server: ViteDevServer | undefined;\n let writeTimer: ReturnType<typeof setTimeout> | undefined;\n const registry = new MessageRegistry();\n const selfWrites = new Map<string, string>();\n\n function invalidateVirtual(): void {\n if (!server) return;\n const ids = [RESOLVED, ...cfg.locales.map((locale) => LOCALE_PREFIX + locale)];\n for (const id of ids) {\n const mod = server.moduleGraph.getModuleById(id);\n if (mod) server.moduleGraph.invalidateModule(mod);\n }\n server.ws.send({ type: 'full-reload' });\n }\n\n function flushCatalogs(): void {\n syncCatalogs(cfg, catalogs, registry);\n for (const locale of cfg.locales) {\n const serialized = writeCatalog(cfg, locale, catalogs[locale] ?? {});\n selfWrites.set(locale, serialized);\n }\n writeDts(cfg, new Map(Object.entries(catalogs[cfg.sourceLocale] ?? {})));\n invalidateVirtual();\n }\n\n function scheduleFlush(): void {\n clearTimeout(writeTimer);\n writeTimer = setTimeout(flushCatalogs, 50);\n }\n\n async function reloadFromDisk(): Promise<void> {\n cfg = await loadConfig(cfg.root, options);\n catalogs = loadCatalogs(cfg);\n invalidateVirtual();\n }\n\n return {\n name: 'verbaly',\n enforce: 'pre',\n\n async configResolved(viteConfig) {\n isBuild = viteConfig.command === 'build';\n cfg = await loadConfig(options.root ?? viteConfig.root, options);\n catalogs = loadCatalogs(cfg);\n if (!isBuild) {\n writeDts(cfg, new Map(Object.entries(catalogs[cfg.sourceLocale] ?? {})));\n }\n },\n\n configureServer(devServer) {\n server = devServer;\n devServer.watcher.add(cfg.dir);\n const onCatalogFile = (file: string, locale?: string): void => {\n if (!file.startsWith(cfg.dir) || !file.endsWith('.json')) return;\n if (locale && selfWrites.get(locale) !== undefined) {\n selfWrites.delete(locale);\n return;\n }\n void reloadFromDisk();\n };\n devServer.watcher.on('change', (file) =>\n onCatalogFile(file, file.split(/[\\\\/]/).pop()?.slice(0, -5)),\n );\n devServer.watcher.on('add', (file) => onCatalogFile(file));\n devServer.watcher.on('unlink', (file) => {\n if (SOURCE_RE.test(file) && !file.includes('node_modules')) {\n registry.remove(file);\n scheduleFlush();\n }\n });\n },\n\n resolveId(id) {\n if (id === VIRTUAL_ID || id.startsWith(`${VIRTUAL_ID}/`)) return '\\0' + id;\n return undefined;\n },\n\n load(id) {\n if (id === RESOLVED) return generateRuntimeModule(cfg);\n if (id.startsWith(LOCALE_PREFIX)) {\n return generateLocaleModule(catalogs[id.slice(LOCALE_PREFIX.length)] ?? {});\n }\n return undefined;\n },\n\n transform(code, id) {\n if (!SOURCE_RE.test(id) || id.includes('node_modules') || id.startsWith('\\0')) {\n return undefined;\n }\n const analysis = analyze(code, id);\n registry.update(id, analysis);\n\n if (!isBuild && analysis.tagged.length > 0) {\n const source = (catalogs[cfg.sourceLocale] ??= {});\n let changed = false;\n for (const msg of analysis.tagged) {\n if (source[msg.key] !== msg.message) {\n source[msg.key] = msg.message;\n changed = true;\n }\n }\n if (changed) scheduleFlush();\n }\n\n return transformCode(code, id, analysis) ?? undefined;\n },\n\n buildEnd() {\n if (!isBuild) return;\n const result = check(cfg, loadCatalogs(cfg), registry);\n if (!result.ok) {\n throw new Error(\n `[verbaly] build blocked\\n${formatCheckResult(result)}\\n` +\n `Run \\`npx verbaly extract\\` and fill the missing translations.`,\n );\n }\n },\n };\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@verbaly/vite",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Zero-config Vite plugin for Verbaly — extraction, codegen and HMR.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"i18n",
|
|
@@ -38,15 +38,15 @@
|
|
|
38
38
|
"access": "public"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@verbaly/compiler": "0.
|
|
41
|
+
"@verbaly/compiler": "0.4.0"
|
|
42
42
|
},
|
|
43
43
|
"peerDependencies": {
|
|
44
44
|
"vite": "^7.0.0 || ^8.0.0",
|
|
45
|
-
"verbaly": "^0.
|
|
45
|
+
"verbaly": "^0.4.0"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
|
-
"vite": "^8.1.
|
|
49
|
-
"verbaly": "0.
|
|
48
|
+
"vite": "^8.1.3",
|
|
49
|
+
"verbaly": "0.4.0"
|
|
50
50
|
},
|
|
51
51
|
"scripts": {
|
|
52
52
|
"build": "tsup",
|