unplugin-saykit 0.2.0 → 0.3.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 CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  > Universal build-tool plugin for [SayKit](https://saykit.js.org).
4
4
 
5
+ [![Coverage](https://codecov.io/gh/k0d13/saykit/graph/badge.svg?flag=plugin-unplugin)](https://codecov.io/gh/k0d13/saykit?flags%5B0%5D=plugin-unplugin)
6
+
5
7
  Works with Vite, Rollup, Rolldown, Webpack, Rspack, esbuild, Farm, and Bun via [unplugin](https://github.com/unjs/unplugin).
6
8
 
7
9
  ## Install
package/dist/bun.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { t as src_default } from "./src-C-_DjRpL.mjs";
1
+ import { t as src_default } from "./src-B4Rsypvw.mjs";
2
2
  //#region src/bun.ts
3
3
  var bun_default = src_default.bun;
4
4
  //#endregion
package/dist/esbuild.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { t as src_default } from "./src-C-_DjRpL.mjs";
1
+ import { t as src_default } from "./src-B4Rsypvw.mjs";
2
2
  //#region src/esbuild.ts
3
3
  var esbuild_default = src_default.esbuild;
4
4
  //#endregion
package/dist/farm.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { t as src_default } from "./src-C-_DjRpL.mjs";
1
+ import { t as src_default } from "./src-B4Rsypvw.mjs";
2
2
  //#region src/farm.ts
3
3
  var farm_default = src_default.farm;
4
4
  //#endregion
package/dist/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { t as src_default } from "./src-C-_DjRpL.mjs";
1
+ import { t as src_default } from "./src-B4Rsypvw.mjs";
2
2
  export { src_default as default };
@@ -1,7 +1,7 @@
1
- import { join } from "node:path";
2
- import { generateHash } from "@saykit/config/features/messages";
3
- import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
1
+ import { dirname, join } from "node:path";
2
+ import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
4
3
  import { tmpdir } from "node:os";
4
+ import { generateHash } from "@saykit/config/features/messages";
5
5
  //#region ../../node_modules/.pnpm/tinyrainbow@3.1.0/node_modules/tinyrainbow/dist/index.js
6
6
  var b = {
7
7
  reset: [0, 0],
@@ -13650,20 +13650,39 @@ Object.defineProperty(globalThis, GLOBAL_EXPECT, {
13650
13650
  });
13651
13651
  //#endregion
13652
13652
  //#region src/index.test.ts
13653
- const config = { buckets: [{
13654
- match: (id) => id.endsWith(".ts"),
13655
- output: { match: (id) => id.endsWith("messages.json") },
13656
- transformer: { transform: (code) => code.replace("say", "SAY") },
13657
- formatter: { parse: (content) => JSON.parse(content) }
13658
- }] };
13653
+ const dir = mkdtempSync(join(tmpdir(), "saykit-unplugin-"));
13654
+ const config = {
13655
+ locales: [
13656
+ "en",
13657
+ "en-GB",
13658
+ "en-NZ",
13659
+ "fr"
13660
+ ],
13661
+ fallbackLocales: { "en-NZ": ["en-GB"] },
13662
+ buckets: [{
13663
+ match: (id) => id.endsWith(".ts"),
13664
+ output: Object.assign(join(dir, "{locale}", "messages.{extension}"), { match: (id) => id.endsWith("messages.json") }),
13665
+ transformer: { transform: (code) => code.replace("say", "SAY") },
13666
+ formatter: {
13667
+ extension: ".json",
13668
+ parse: (content) => JSON.parse(content)
13669
+ }
13670
+ }]
13671
+ };
13659
13672
  vi.mock("@saykit/config/features/loader", () => ({ resolveConfig: () => config }));
13660
13673
  const { default: unplugin } = await import("./index.mjs");
13661
13674
  const plugin = unplugin.raw(void 0, { framework: "rollup" });
13662
- const dir = mkdtempSync(join(tmpdir(), "saykit-unplugin-"));
13663
13675
  afterAll(() => rmSync(dir, {
13664
13676
  recursive: true,
13665
13677
  force: true
13666
13678
  }));
13679
+ const write = (locale, content) => {
13680
+ const file = join(dir, locale, "messages.json");
13681
+ mkdirSync(dirname(file), { recursive: true });
13682
+ writeFileSync(file, typeof content === "string" ? content : JSON.stringify(content));
13683
+ return file;
13684
+ };
13685
+ const record = (output) => JSON.parse(output.replace("export default ", ""));
13667
13686
  describe("unplugin transform", () => {
13668
13687
  it("transforms code for a matching bucket", () => {
13669
13688
  globalExpect(plugin.transform.handler("say`Hi`", join(process.cwd(), "src/app.ts"))).toBe("SAY`Hi`");
@@ -13673,21 +13692,79 @@ describe("unplugin transform", () => {
13673
13692
  });
13674
13693
  });
13675
13694
  describe("unplugin load", () => {
13676
- it("loads a catalogue file into a default-exported record", async () => {
13677
- const file = join(dir, "messages.json");
13678
- writeFileSync(file, JSON.stringify([{
13695
+ it("loads the source locale into a default-exported record", async () => {
13696
+ const file = write("en", [{
13679
13697
  message: "Hello",
13680
- translation: "Bonjour",
13698
+ translation: "",
13681
13699
  id: "greeting"
13682
13700
  }, {
13683
13701
  message: "Bye",
13684
13702
  translation: ""
13685
- }]));
13703
+ }]);
13686
13704
  const output = await plugin.load.handler(file);
13687
13705
  globalExpect(output).toContain("export default");
13688
- const record = JSON.parse(output.replace("export default ", ""));
13689
- globalExpect(record.greeting).toBe("Bonjour");
13690
- globalExpect(record[generateHash("Bye", void 0)]).toBe("Bye");
13706
+ const messages = record(output);
13707
+ globalExpect(messages.greeting).toBe("Hello");
13708
+ globalExpect(messages[generateHash("Bye", void 0)]).toBe("Bye");
13709
+ });
13710
+ it("falls back to the source string for keys untranslated in a non-source locale", async () => {
13711
+ write("en", [{
13712
+ message: "Hello",
13713
+ id: "greeting"
13714
+ }, {
13715
+ message: "Bye",
13716
+ id: "farewell"
13717
+ }]);
13718
+ const file = write("fr", [{
13719
+ message: "Hello",
13720
+ translation: "Bonjour",
13721
+ id: "greeting"
13722
+ }]);
13723
+ const messages = record(await plugin.load.handler(file));
13724
+ globalExpect(messages.greeting).toBe("Bonjour");
13725
+ globalExpect(messages.farewell).toBe("Bye");
13726
+ });
13727
+ it("resolves an empty non-source locale entirely to source strings", async () => {
13728
+ write("en", [{
13729
+ message: "Hello",
13730
+ id: "greeting"
13731
+ }]);
13732
+ const file = write("fr", "");
13733
+ globalExpect(record(await plugin.load.handler(file)).greeting).toBe("Hello");
13734
+ });
13735
+ it("resolves a configured fallback chain before the source locale", async () => {
13736
+ write("en", [
13737
+ {
13738
+ message: "A",
13739
+ id: "a"
13740
+ },
13741
+ {
13742
+ message: "B",
13743
+ id: "b"
13744
+ },
13745
+ {
13746
+ message: "C",
13747
+ id: "c"
13748
+ }
13749
+ ]);
13750
+ write("en-GB", [{
13751
+ message: "B",
13752
+ translation: "B-GB",
13753
+ id: "b"
13754
+ }, {
13755
+ message: "C",
13756
+ translation: "C-GB",
13757
+ id: "c"
13758
+ }]);
13759
+ const file = write("en-NZ", [{
13760
+ message: "C",
13761
+ translation: "C-NZ",
13762
+ id: "c"
13763
+ }]);
13764
+ const messages = record(await plugin.load.handler(file));
13765
+ globalExpect(messages.a).toBe("A");
13766
+ globalExpect(messages.b).toBe("B-GB");
13767
+ globalExpect(messages.c).toBe("C-NZ");
13691
13768
  });
13692
13769
  it("returns undefined when the id does not match a bucket output", async () => {
13693
13770
  globalExpect(await plugin.load.handler(join(dir, "other.txt"))).toBeUndefined();
package/dist/rolldown.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { t as src_default } from "./src-C-_DjRpL.mjs";
1
+ import { t as src_default } from "./src-B4Rsypvw.mjs";
2
2
  //#region src/rolldown.ts
3
3
  var rolldown_default = src_default.rolldown;
4
4
  //#endregion
package/dist/rollup.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { t as src_default } from "./src-C-_DjRpL.mjs";
1
+ import { t as src_default } from "./src-B4Rsypvw.mjs";
2
2
  //#region src/rollup.ts
3
3
  var rollup_default = src_default.rollup;
4
4
  //#endregion
package/dist/rspack.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { t as src_default } from "./src-C-_DjRpL.mjs";
1
+ import { t as src_default } from "./src-B4Rsypvw.mjs";
2
2
  //#region src/rspack.ts
3
3
  var rspack_default = src_default.rspack;
4
4
  //#endregion
@@ -1,7 +1,7 @@
1
1
  import { readFile } from "node:fs/promises";
2
2
  import { relative } from "node:path";
3
+ import { assembleCatalogueRecord, resolveCatalogueSources } from "@saykit/config/features/catalogue";
3
4
  import { resolveConfig } from "@saykit/config/features/loader";
4
- import { generateHash } from "@saykit/config/features/messages";
5
5
  import { createUnplugin } from "unplugin";
6
6
  //#region src/index.ts
7
7
  var src_default = createUnplugin((_options) => {
@@ -18,13 +18,15 @@ var src_default = createUnplugin((_options) => {
18
18
  },
19
19
  load: {
20
20
  filter: { id: { exclude: /node_modules/ } },
21
- handler: async (id_) => {
21
+ handler: async function(id_) {
22
22
  const id = relative(process.cwd(), id_).replaceAll("\\", "/").split("?")[0];
23
23
  const bucket = config.buckets.find((b) => b.output.match(id));
24
24
  if (!bucket) return;
25
- const content = await readFile(id, "utf8");
26
- const entries = bucket.formatter.parse(content).map((m) => [m.id || generateHash(m.message, m.context), m.translation || m.message]);
27
- return `export default ${JSON.stringify(Object.fromEntries(entries))}`;
25
+ const { sources } = resolveCatalogueSources(config, bucket, id);
26
+ const contents = await Promise.all(sources.map((source) => readFile(source, "utf8").catch(() => "")));
27
+ for (const source of sources) this.addWatchFile?.(source);
28
+ const record = assembleCatalogueRecord(bucket, contents);
29
+ return `export default ${JSON.stringify(record)}`;
28
30
  }
29
31
  }
30
32
  };
package/dist/unloader.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { t as src_default } from "./src-C-_DjRpL.mjs";
1
+ import { t as src_default } from "./src-B4Rsypvw.mjs";
2
2
  //#region src/unloader.ts
3
3
  var unloader_default = src_default.unloader;
4
4
  //#endregion
package/dist/vite.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { t as src_default } from "./src-C-_DjRpL.mjs";
1
+ import { t as src_default } from "./src-B4Rsypvw.mjs";
2
2
  //#region src/vite.ts
3
3
  var vite_default = src_default.vite;
4
4
  //#endregion
package/dist/webpack.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { t as src_default } from "./src-C-_DjRpL.mjs";
1
+ import { t as src_default } from "./src-B4Rsypvw.mjs";
2
2
  //#region src/webpack.ts
3
3
  var webpack_default = src_default.webpack;
4
4
  //#endregion
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "unplugin-saykit",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Universal build tool plugin for saykit (Vite, Rollup, Webpack, esbuild)",
5
5
  "keywords": [
6
6
  "i18n",
@@ -41,7 +41,7 @@
41
41
  },
42
42
  "dependencies": {
43
43
  "unplugin": "^3.3.0",
44
- "@saykit/config": "^0.2.0"
44
+ "@saykit/config": "^0.3.0"
45
45
  },
46
46
  "scripts": {
47
47
  "check": "tsc --noEmit",