UNPKG

@inlang/paraglide-js

Version:

[![NPM Downloads](https://img.shields.io/npm/dw/%40inlang%2Fparaglide-js?logo=npm&logoColor=red&label=npm%20downloads)](https://www.npmjs.com/package/@inlang/paraglide-js) [![GitHub Issues](https://img.shields.io/github/issues-closed/opral/paraglide-js?lo

297 lines 11.4 kB
import { test, expect } from "vitest"; import { compileBundle, toBundleInputTypeAliasName } from "./compile-bundle.js"; import { toSafeModuleId } from "./safe-module-id.js"; test("compiles to jsdoc", async () => { const mockBundle = { id: "blue_moon_bottle", declarations: [{ type: "input-variable", name: "age" }], messages: [ { id: "message-id", bundleId: "blue_moon_bottle", locale: "en", selectors: [], variants: [ { id: "1", messageId: "message-id", matches: [], pattern: [ { type: "text", value: "Hello" }, { type: "expression", arg: { type: "variable-reference", name: "age" }, }, ], }, ], }, ], }; const result = compileBundle({ fallbackMap: { en: "en", "en-US": "en", }, bundle: mockBundle, messageReferenceExpression: (locale) => `${toSafeModuleId(locale)}.blue_moon_bottle`, settings: { locales: ["en", "en-US"], }, }); expect(result.bundle.code).toMatchInlineSnapshot(` "/** * | output | * | --- | * | "Hello{age}" | * * @param {Blue_Moon_BottleInputs} inputs * @param {{ locale?: "en" | "en-US" }} options * @returns {LocalizedString} */ export const blue_moon_bottle = /** @type {((inputs: Blue_Moon_BottleInputs, options?: { locale?: "en" | "en-US" }) => LocalizedString) & import('../runtime.js').MessageMetadata<Blue_Moon_BottleInputs, { locale?: "en" | "en-US" }, {}>} */ ((inputs, options = {}) => { const locale = experimentalStaticLocale ?? options.locale ?? getLocale() if (locale === "en") return en.blue_moon_bottle(inputs) return en_us2.blue_moon_bottle(inputs) });" `); }); test("emits middleware locale splitting hooks when enabled", () => { const mockBundle = { id: "blue_moon_bottle", declarations: [{ type: "input-variable", name: "age" }], messages: [ { id: "message-id", bundleId: "blue_moon_bottle", locale: "en", selectors: [], variants: [{ id: "1", messageId: "message-id", matches: [], pattern: [] }], }, ], }; const result = compileBundle({ fallbackMap: { en: "en" }, bundle: mockBundle, messageReferenceExpression: (locale) => `${toSafeModuleId(locale)}.blue_moon_bottle`, settings: { locales: ["en"], }, experimentalMiddlewareLocaleSplitting: true, }); expect(result.bundle.code).toContain("if (experimentalMiddlewareLocaleSplitting && isServer === false)"); expect(result.bundle.code).toContain("trackMessageCall(\"blue_moon_bottle\", locale)"); expect(result.bundle.code).toContain("globalThis).__paraglide.ssr.blue_moon_bottle(inputs)"); }); test("compiles to jsdoc with missing translation", async () => { const mockBundle = { id: "blue_moon_bottle", declarations: [{ type: "input-variable", name: "age" }], messages: [ { id: "message-id", bundleId: "blue_moon_bottle", locale: "en", selectors: [], variants: [ { id: "1", messageId: "message-id", matches: [], pattern: [ { type: "text", value: "Hello" }, { type: "expression", arg: { type: "variable-reference", name: "age" }, }, ], }, ], }, ], }; const result = compileBundle({ fallbackMap: { en: "en", "en-US": "en", }, bundle: mockBundle, messageReferenceExpression: (locale) => `${toSafeModuleId(locale)}.blue_moon_bottle`, settings: { locales: ["en", "en-US", "fr"], }, }); expect(result.bundle.code).toMatchInlineSnapshot(` "/** * | output | * | --- | * | "Hello{age}" | * * @param {Blue_Moon_BottleInputs} inputs * @param {{ locale?: "en" | "en-US" }} options * @returns {LocalizedString} */ export const blue_moon_bottle = /** @type {((inputs: Blue_Moon_BottleInputs, options?: { locale?: "en" | "en-US" }) => LocalizedString) & import('../runtime.js').MessageMetadata<Blue_Moon_BottleInputs, { locale?: "en" | "en-US" }, {}>} */ ((inputs, options = {}) => { const locale = experimentalStaticLocale ?? options.locale ?? getLocale() if (locale === "en") return en.blue_moon_bottle(inputs) if (locale === "en-US") return en_us2.blue_moon_bottle(inputs) return /** @type {LocalizedString} */ ("blue_moon_bottle") });" `); }); // https://github.com/opral/inlang-paraglide-js/issues/285 test("compiles bundles with arbitrary module identifiers", async () => { const mockBundle = { id: "$p@44🍌", declarations: [{ type: "input-variable", name: "age" }], messages: [ { id: "message-id", bundleId: "$p@44🍌", locale: "en", selectors: [], variants: [ { id: "1", messageId: "message-id", matches: [], pattern: [ { type: "text", value: "Hello" }, { type: "expression", arg: { type: "variable-reference", name: "age" }, }, ], }, ], }, ], }; const result = compileBundle({ fallbackMap: {}, bundle: mockBundle, messageReferenceExpression: (locale) => `${toSafeModuleId(locale)}.blue_moon_bottle`, }); expect(result.bundle.code).includes(`export { ${toSafeModuleId("$p@44🍌")} as "$p@44🍌" }`); }); test("keeps generated input typedef names collision-free for repeated underscores", () => { expect(toBundleInputTypeAliasName("foo_bar")).toBe("Foo_BarInputs"); expect(toBundleInputTypeAliasName("foo__bar")).toBe("Foo__BarInputs"); expect(toBundleInputTypeAliasName("foo_bar")).not.toBe(toBundleInputTypeAliasName("foo__bar")); }); test("handles message pattern with duplicate variable references", async () => { const mockBundle = { id: "date_last_days", declarations: [ { type: "input-variable", name: "days" }, { type: "input-variable", name: "days" }, ], messages: [ { id: "date_last_days", bundleId: "date_last_days", locale: "en", selectors: [], variants: [ { id: "1", messageId: "date_last_days", matches: [], pattern: [ { type: "text", value: "Last " }, { type: "expression", arg: { type: "variable-reference", name: "days" }, }, { type: "text", value: " days, showing " }, { type: "expression", arg: { type: "variable-reference", name: "days" }, }, { type: "text", value: " items" }, ], }, ], }, ], }; const result = compileBundle({ fallbackMap: { en: "en", }, bundle: mockBundle, messageReferenceExpression: (locale) => `${toSafeModuleId(locale)}.date_last_days`, }); // The JSDoc should not have duplicate parameters expect(result.bundle.code).toContain("@param {Date_Last_DaysInputs} inputs"); expect(result.bundle.code).not.toContain("days: NonNullable<unknown>, days: NonNullable<unknown>"); // Check that the pattern is compiled correctly const enMessage = result.messages?.en; expect(enMessage).toBeDefined(); expect(enMessage?.code).toContain("Last ${i?.days} days, showing ${i?.days} items"); }); test("adds .parts() to bundle functions when markup exists", async () => { const mockBundle = { id: "notice", declarations: [{ type: "input-variable", name: "count" }], messages: [ { id: "notice-id", bundleId: "notice", locale: "en", selectors: [], variants: [ { id: "1", messageId: "notice-id", matches: [], pattern: [ { type: "markup-start", name: "strong", options: [], attributes: [] }, { type: "expression", arg: { type: "variable-reference", name: "count" }, }, { type: "text", value: " items" }, { type: "markup-end", name: "strong", options: [], attributes: [] }, ], }, ], }, ], }; const result = compileBundle({ fallbackMap: { en: undefined, }, bundle: mockBundle, messageReferenceExpression: (locale) => `${toSafeModuleId(locale)}.notice`, settings: { locales: ["en"], }, }); const compiledEnMessage = result.messages.en; if (!compiledEnMessage) { throw new Error("Expected compiled english message"); } const moduleSource = ` const getLocale = () => "en"; const trackMessageCall = () => {}; const experimentalMiddlewareLocaleSplitting = false; const isServer = true; const experimentalStaticLocale = undefined; const en = { notice: ${compiledEnMessage.code.replace(/;\s*$/, "")} }; ${result.bundle.code} `; const { notice } = await import("data:text/javascript;base64," + btoa(moduleSource)); expect(notice({ count: 3 })).toBe("3 items"); expect(notice.parts({ count: 3 })).toEqual([ { type: "markup-start", name: "strong", options: {}, attributes: {} }, { type: "text", value: "3" }, { type: "text", value: " items" }, { type: "markup-end", name: "strong", options: {}, attributes: {} }, ]); expect(result.bundle.code).toContain('MessageMetadata<NoticeInputs, { locale?: "en" }, { strong: { options: {}; attributes: {}; children: true } }>'); }); //# sourceMappingURL=compile-bundle.test.js.map