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

174 lines 7.99 kB
import { compilePattern } from "./compile-pattern.js"; import { inputsType } from "./jsdoc-types.js"; import { compileLocalVariable } from "./compile-local-variable.js"; import { renderInputMatchCondition } from "./match-literals.js"; import { compileInputAccess } from "./variable-access.js"; /** * Returns the compiled message as a string * */ export const compileMessage = (declarations, message, variants, matchTypes, inputTypeAliasName) => { // return empty string instead? if (variants.length == 0) { throw new Error("Message must have at least one variant"); } const hasMultipleVariants = variants.length > 1; return hasMultipleVariants ? compileMessageWithMultipleVariants(declarations, message, variants, matchTypes, inputTypeAliasName) : compileMessageWithOneVariant(declarations, message, variants, matchTypes, inputTypeAliasName); }; function compileMessageWithOneVariant(declarations, message, variants, matchTypes, inputTypeAliasName) { const variant = variants[0]; if (!variant || variants.length !== 1) { throw new Error("Message must have exactly one variant"); } const hasMarkup = patternHasMarkup(variant.pattern); const inputs = declarations.filter((decl) => decl.type === "input-variable"); const hasInputs = inputs.length > 0; const messageInputType = inputTypeAliasName ?? inputsType(inputs, matchTypes); const compiledPattern = compilePattern({ pattern: variant.pattern, declarations, locale: message.locale, }); const compiledLocalVariables = []; for (const declaration of declarations) { if (declaration.type === "local-variable") { compiledLocalVariables.push(compileLocalVariable({ declaration, locale: message.locale })); } } if (!hasMarkup) { const code = `/** @type {(inputs: ${messageInputType}) => LocalizedString} */ (${hasInputs ? "i" : ""}) => { ${compiledLocalVariables.join("\n\t")}return /** @type {LocalizedString} */ (${compiledPattern.code}) };`; return { code, node: message }; } const compiledPartsPattern = compilePattern({ pattern: variant.pattern, declarations, mode: "parts", locale: message.locale, }); const localVariablesCode = compiledLocalVariables.length ? compiledLocalVariables.join("\n\t") + "\n\t" : ""; const inputType = messageInputType; const messageInput = hasInputs ? "i" : ""; const partsCode = `/** @type {((inputs: ${inputType}) => LocalizedString) & { parts: (inputs: ${inputType}) => import('../runtime.js').MessagePart[] }} */ ( /* @__PURE__ */ Object.assign( /** @type {(inputs: ${inputType}) => LocalizedString} */ ((${messageInput}) => { ${localVariablesCode}return /** @type {LocalizedString} */ (${compiledPattern.code}) }), { parts: /** @type {(inputs: ${inputType}) => import('../runtime.js').MessagePart[]} */ ((${messageInput}) => { ${localVariablesCode}return /** @type {import('../runtime.js').MessagePart[]} */ (${compiledPartsPattern.code}) }) } ) );`; return { code: partsCode, node: message }; } function compileMessageWithMultipleVariants(declarations, message, variants, matchTypes, inputTypeAliasName) { if (variants.length <= 1) { throw new Error("Message must have more than one variant"); } const hasMarkup = variants.some((variant) => patternHasMarkup(variant.pattern)); const inputs = declarations.filter((decl) => decl.type === "input-variable"); const hasInputs = inputs.length > 0; const messageInputType = inputTypeAliasName ?? inputsType(inputs, matchTypes); // TODO make sure that matchers use keys instead of indexes const compiledVariants = []; const compiledPartsVariants = []; let hasCatchAll = false; for (const variant of variants) { const compiledPattern = compilePattern({ pattern: variant.pattern, declarations, locale: message.locale, }); const compiledPartsPattern = hasMarkup ? compilePattern({ pattern: variant.pattern, declarations, mode: "parts", locale: message.locale, }) : undefined; const isCatchAll = variant.matches.every((match) => match.type === "catchall-match"); if (isCatchAll) { compiledVariants.push(`return /** @type {LocalizedString} */ (${compiledPattern.code})`); if (compiledPartsPattern) { compiledPartsVariants.push(`return /** @type {import('../runtime.js').MessagePart[]} */ (${compiledPartsPattern.code})`); } hasCatchAll = true; } const conditions = []; for (const match of variant.matches) { // catch all matches are not used in the conditions if (match.type !== "literal-match") { continue; } const variableType = declarations.find((decl) => decl.name === match.key)?.type; if (variableType === "input-variable") { conditions.push(renderInputMatchCondition(compileInputAccess(match.key), match.value)); } else if (variableType === "local-variable") { conditions.push(`${match.key} === ${JSON.stringify(match.value)}`); } } if (conditions.length === 0) continue; compiledVariants.push(`if (${conditions.join(" && ")}) return /** @type {LocalizedString} */ (${compiledPattern.code});`); if (compiledPartsPattern) { compiledPartsVariants.push(`if (${conditions.join(" && ")}) return /** @type {import('../runtime.js').MessagePart[]} */ (${compiledPartsPattern.code});`); } } const compiledLocalVariables = []; for (const declaration of declarations) { if (declaration.type === "local-variable") { compiledLocalVariables.push(compileLocalVariable({ declaration, locale: message.locale })); } } if (!hasMarkup) { const code = `/** @type {(inputs: ${messageInputType}) => LocalizedString} */ (${hasInputs ? "i" : ""}) => {${compiledLocalVariables.join("\n\t")} ${compiledVariants.join("\n\t")} ${hasCatchAll ? "" : `return /** @type {LocalizedString} */ ("${message.bundleId}");`} };`; return { code, node: message }; } const localVariablesCode = compiledLocalVariables.length ? compiledLocalVariables.join("\n\t") + "\n\t" : ""; const stringVariantsCode = compiledVariants.length ? compiledVariants.join("\n\t") + "\n\t" : ""; const partsVariantsCode = compiledPartsVariants.length ? compiledPartsVariants.join("\n\t") + "\n\t" : ""; const inputType = messageInputType; const fallbackParts = `[{ type: "text", value: ${JSON.stringify(message.bundleId)} }]`; const messageInput = hasInputs ? "i" : ""; const code = `/** @type {((inputs: ${inputType}) => LocalizedString) & { parts: (inputs: ${inputType}) => import('../runtime.js').MessagePart[] }} */ ( /* @__PURE__ */ Object.assign( /** @type {(inputs: ${inputType}) => LocalizedString} */ ((${messageInput}) => { ${localVariablesCode}${stringVariantsCode}${hasCatchAll ? "" : `return /** @type {LocalizedString} */ (${JSON.stringify(message.bundleId)});`} }), { parts: /** @type {(inputs: ${inputType}) => import('../runtime.js').MessagePart[]} */ ((${messageInput}) => { ${localVariablesCode}${partsVariantsCode}${hasCatchAll ? "" : `return /** @type {import('../runtime.js').MessagePart[]} */ (${fallbackParts});`} }) } ) );`; return { code, node: message }; } function patternHasMarkup(pattern) { return pattern.some((part) => part.type === "markup-start" || part.type === "markup-end" || part.type === "markup-standalone"); } //# sourceMappingURL=compile-message.js.map