@leancodepl/mail-translation 9.2.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.
Files changed (49) hide show
  1. package/CHANGELOG.md +64 -0
  2. package/README.md +248 -0
  3. package/package.json +27 -0
  4. package/schema.json +53 -0
  5. package/src/bin.d.ts +2 -0
  6. package/src/bin.js +19 -0
  7. package/src/bin.js.map +1 -0
  8. package/src/compileMjml.d.ts +13 -0
  9. package/src/compileMjml.js +29 -0
  10. package/src/compileMjml.js.map +1 -0
  11. package/src/config.d.ts +21 -0
  12. package/src/config.js +35 -0
  13. package/src/config.js.map +1 -0
  14. package/src/generate.d.ts +2 -0
  15. package/src/generate.js +23 -0
  16. package/src/generate.js.map +1 -0
  17. package/src/generateConfigSchema.d.ts +1 -0
  18. package/src/generateConfigSchema.js +17 -0
  19. package/src/generateConfigSchema.js.map +1 -0
  20. package/src/generateKratosOutputTemplates.d.ts +9 -0
  21. package/src/generateKratosOutputTemplates.js +48 -0
  22. package/src/generateKratosOutputTemplates.js.map +1 -0
  23. package/src/generateOutputTemplates.d.ts +12 -0
  24. package/src/generateOutputTemplates.js +18 -0
  25. package/src/generateOutputTemplates.js.map +1 -0
  26. package/src/generateRazorOutputTemplates.d.ts +8 -0
  27. package/src/generateRazorOutputTemplates.js +50 -0
  28. package/src/generateRazorOutputTemplates.js.map +1 -0
  29. package/src/index.d.ts +2 -0
  30. package/src/index.js +6 -0
  31. package/src/index.js.map +1 -0
  32. package/src/loadConfig.d.ts +2 -0
  33. package/src/loadConfig.js +41 -0
  34. package/src/loadConfig.js.map +1 -0
  35. package/src/loadTemplates.d.ts +7 -0
  36. package/src/loadTemplates.js +47 -0
  37. package/src/loadTemplates.js.map +1 -0
  38. package/src/loadTranslations.d.ts +7 -0
  39. package/src/loadTranslations.js +37 -0
  40. package/src/loadTranslations.js.map +1 -0
  41. package/src/processTemplate.d.ts +28 -0
  42. package/src/processTemplate.js +36 -0
  43. package/src/processTemplate.js.map +1 -0
  44. package/src/processTranslations.d.ts +6 -0
  45. package/src/processTranslations.js +31 -0
  46. package/src/processTranslations.js.map +1 -0
  47. package/src/saveOutputs.d.ts +5 -0
  48. package/src/saveOutputs.js +16 -0
  49. package/src/saveOutputs.js.map +1 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,64 @@
1
+ # Change Log
2
+
3
+ All notable changes to this project will be documented in this file. See
4
+ [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
+
6
+ # [9.2.0](https://github.com/leancodepl/js_corelibrary/compare/v9.1.0...v9.2.0) (2025-07-24)
7
+
8
+ ### Bug Fixes
9
+
10
+ - add empty lines at the end to test examples
11
+ ([a5872b8](https://github.com/leancodepl/js_corelibrary/commit/a5872b8d0059968f9b7a7c09ea77429c3042cac6))
12
+ - add newline at the end of schema.json
13
+ ([ef4eb59](https://github.com/leancodepl/js_corelibrary/commit/ef4eb598320c119ff775cd4a99e31c334218aa05))
14
+ - building and publishing mail-translation package
15
+ ([88acaa6](https://github.com/leancodepl/js_corelibrary/commit/88acaa6bbe1e08f5a510479411250a9bf5ad9d29))
16
+ - export only processTemplate functionality
17
+ ([cf2ab8b](https://github.com/leancodepl/js_corelibrary/commit/cf2ab8bb769d2712b0162772fd8c6e86beecec72))
18
+ - handling no translations and no default language
19
+ ([8e64bfd](https://github.com/leancodepl/js_corelibrary/commit/8e64bfdf9ef3226006ffeced47ab4eb0dd30ff66))
20
+ - include all css at rules for razor escaping
21
+ ([274ac88](https://github.com/leancodepl/js_corelibrary/commit/274ac88a38245bcd31020adedecf34634a7acca3))
22
+ - include schema.json usage examples in readme
23
+ ([2bb9009](https://github.com/leancodepl/js_corelibrary/commit/2bb90093a7f56f424af94dc4e246c430652b30da))
24
+ - including common mjml templates
25
+ ([ac4dad0](https://github.com/leancodepl/js_corelibrary/commit/ac4dad018b717654e9756cfd316e2178ab58b4e7))
26
+ - leave only simple interpolations in translations
27
+ ([3e57b3f](https://github.com/leancodepl/js_corelibrary/commit/3e57b3f178b00a1e23b4c2645af20f7737b0a191))
28
+ - mail-translation package version
29
+ ([2c70fbd](https://github.com/leancodepl/js_corelibrary/commit/2c70fbdadc89ed355840b2c9777efb742b1a989a))
30
+ - remove package.json config reference from readme
31
+ ([5f56832](https://github.com/leancodepl/js_corelibrary/commit/5f56832fecf7d333873c56df412c9ca8a00e1ea0))
32
+ - resolving cheerio dependencies
33
+ ([c08303f](https://github.com/leancodepl/js_corelibrary/commit/c08303f3eb0dffea1a5ea66be1d3f81305d6849a))
34
+ - simplify generating kratos output
35
+ ([bbab869](https://github.com/leancodepl/js_corelibrary/commit/bbab86941dfbc71ab275a716d1fa24a8a1f9e79b))
36
+ - simplify ProcessedTemplate interface
37
+ ([d494888](https://github.com/leancodepl/js_corelibrary/commit/d494888b081cd381caef393f832febb95b7cd972))
38
+ - translations template and parsing parameters
39
+ ([2dbd6f5](https://github.com/leancodepl/js_corelibrary/commit/2dbd6f531479aa3f28adef953c4d0d0409841b1e))
40
+
41
+ ### Features
42
+
43
+ - add better support for yaml configuration files
44
+ ([6cf386f](https://github.com/leancodepl/js_corelibrary/commit/6cf386f5a68ae595001024926d8cae8fbe9fb261))
45
+ - add handling plaintext templates
46
+ ([93bab30](https://github.com/leancodepl/js_corelibrary/commit/93bab30feef7124b09be57f8f2ce15be1cf0758c))
47
+ - add overriding kratos language variable
48
+ ([8d810db](https://github.com/leancodepl/js_corelibrary/commit/8d810dbf2f5cbd21765bd5f7bab8125ee7364bea))
49
+ - escape [@media](https://github.com/media) and [@import](https://github.com/import) statement in razor outputs
50
+ ([f960be6](https://github.com/leancodepl/js_corelibrary/commit/f960be6dd395486e97a9aa760919f66395a87c29))
51
+ - export config schema
52
+ ([5cdd27c](https://github.com/leancodepl/js_corelibrary/commit/5cdd27cdd44672ca3ecb2f9a857b1bb729eb21a0))
53
+ - generate mails without any translations
54
+ ([beb4ad0](https://github.com/leancodepl/js_corelibrary/commit/beb4ad00a4d2cbbbf1104be9dc7ca585ca82a0cf))
55
+ - initial mail translation tool implementation
56
+ ([da7f050](https://github.com/leancodepl/js_corelibrary/commit/da7f0501e6696d969d505316b72db215798203a9))
57
+ - move generation logic from bin to generate function
58
+ ([c7f1218](https://github.com/leancodepl/js_corelibrary/commit/c7f12186311a88e1b873d1b505c94a81bc39f898))
59
+ - refactor template processing
60
+ ([10b226b](https://github.com/leancodepl/js_corelibrary/commit/10b226bebe8bd98bcbaaaf794662d32c1d7c80b4))
61
+ - test processTemplate and fix folders structure
62
+ ([50a7c81](https://github.com/leancodepl/js_corelibrary/commit/50a7c81d796a3520c064a09588dd542a86b9b8cf))
63
+ - use ICU format and add passing parameters in mjml templates
64
+ ([fe0bd1c](https://github.com/leancodepl/js_corelibrary/commit/fe0bd1cf6d4c74471e9adddbab0141415a257e60))
package/README.md ADDED
@@ -0,0 +1,248 @@
1
+ # @leancodepl/mail-translation
2
+
3
+ A command-line tool for processing MJML and plaintext email templates with optional internationalization support.
4
+ Compiles MJML templates to HTML and can convert templates with translation placeholders into localized email files for
5
+ Kratos or Razor templating systems.
6
+
7
+ ## Installation
8
+
9
+ ```sh
10
+ npm install -D @leancodepl/mail-translation
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ ```sh
16
+ npx @leancodepl/mail-translation
17
+
18
+ # Or with custom config file
19
+ npx @leancodepl/mail-translation --config custom-config.js
20
+ ```
21
+
22
+ ## Configuration
23
+
24
+ Mail translation is configured using [lilconfig](https://github.com/antonk52/lilconfig). Valid configuration sources
25
+ include:
26
+
27
+ - `.mail-translationrc.json`, `.mail-translationrc` for JSON format
28
+ - `.mail-translationrc.yaml`, `.mail-translationrc.yml` for YAML format
29
+ - `mail-translation.config.js`, `mail-translation.config.cjs`, `.mail-translationrc.js`, `.mail-translationrc.cjs` for
30
+ JavaScript configuration files
31
+ - Path to JavaScript/JSON/YAML config file passed via optional `--config/-c` parameter
32
+
33
+ ### Configuration Options
34
+
35
+ - `mailsPath` (`string`, **required**) - Path to directory containing MJML email templates
36
+ - `outputPath` (`string`, **required**) - Directory where processed templates will be saved
37
+ - `outputMode` (`"kratos" | "razor"`, **required**) - Target templating system format
38
+ - `translationsPath` (`string`, optional) - Path to translation files directory. When omitted, templates are compiled
39
+ without translations
40
+ - `plaintextMailsPath` (`string`, optional) - Path to plaintext templates (defaults to `mailsPath`)
41
+ - `defaultLanguage` (`string`, **required when `translationsPath` is provided**) - Default language code for templates
42
+ with translations
43
+ - `languages` (`string[]`, optional) - Array of language codes to process. When omitted, all languages found in
44
+ translation files are processed
45
+ - `kratosLanguageVariable` (`string`, optional, **Kratos mode only**) - Variable path used for language detection in
46
+ Kratos templates (defaults to `".Identity.traits.lang"`).
47
+
48
+ ### JSON Schema
49
+
50
+ The package exports a JSON Schema file (`schema.json`) that can be used for configuration validation and IDE
51
+ autocompletion. For JSON configuration files, add the `$schema` property to get autocompletion and validation. Example:
52
+
53
+ ```json
54
+ {
55
+ "$schema": "./node_modules/@leancodepl/mail-translation/schema.json"
56
+ }
57
+ ```
58
+
59
+ ### Example Configuration
60
+
61
+ **With translations:**
62
+
63
+ ```json
64
+ {
65
+ "$schema": "./node_modules/@leancodepl/mail-translation/schema.json",
66
+ "translationsPath": "./translations",
67
+ "mailsPath": "./templates/mjml",
68
+ "plaintextMailsPath": "./templates/plaintext",
69
+ "outputPath": "./dist/emails",
70
+ "outputMode": "kratos",
71
+ "defaultLanguage": "en",
72
+ "kratosLanguageVariable": ".Identity.traits.locale", // optional - defaults to .Identity.traits.lang
73
+ "languages": ["en", "pl", "de"] // optional - will auto-detect from translation files
74
+ }
75
+ ```
76
+
77
+ **MJML compilation only (no translations):**
78
+
79
+ ```json
80
+ {
81
+ "$schema": "./node_modules/@leancodepl/mail-translation/schema.json",
82
+ "mailsPath": "./templates/mjml",
83
+ "outputPath": "./dist/emails",
84
+ "outputMode": "kratos"
85
+ }
86
+ ```
87
+
88
+ ## Template Structure
89
+
90
+ ### MJML Templates
91
+
92
+ Place MJML files in your `mailsPath` directory:
93
+
94
+ ```
95
+ templates/
96
+ ├── welcome.mjml
97
+ ├── password-reset.mjml
98
+ └── components/
99
+ ├── header.mjml
100
+ └── footer.mjml
101
+ ```
102
+
103
+ ### Translation Files
104
+
105
+ Create JSON translation files in your `translationsPath`:
106
+
107
+ ```
108
+ translations/
109
+ ├── en.json
110
+ ├── pl.json
111
+ └── de.json
112
+ ```
113
+
114
+ Example translation file (`en.json`):
115
+
116
+ ```json
117
+ {
118
+ "welcome_title": "Welcome to our platform!",
119
+ "welcome_greeting": "Hello {name}!",
120
+ "verify_button": "Verify Account",
121
+ "footer_text": "© 2024 Company. All rights reserved."
122
+ }
123
+ ```
124
+
125
+ ### Template Syntax
126
+
127
+ Use `((t "key"))` for simple translations:
128
+
129
+ ```mjml
130
+ <mj-text>((t "welcome_title"))</mj-text>
131
+ ```
132
+
133
+ Use `((t "key", {...}))` for parameterized translations with JSON objects:
134
+
135
+ ```mjml
136
+ <mj-text>((t "welcome_greeting", {"name": "{{ .Identity.traits.first_name }}"}))</mj-text>
137
+ ```
138
+
139
+ Use multiple parameters for complex translations:
140
+
141
+ ```mjml
142
+ <mj-text>
143
+ ((t "account_info", {"email": "{{ .Identity.traits.email }}", "plan": "{{ .Identity.traits.plan }}"}))
144
+ </mj-text>
145
+ ```
146
+
147
+ ## Output Modes
148
+
149
+ ### Kratos Mode
150
+
151
+ Generates Go template files compatible with Ory Kratos identity management system:
152
+
153
+ **File Structure:**
154
+
155
+ - **Body templates**: `template_name.gotmpl` (e.g., `welcome.gotmpl`)
156
+ - **Plaintext templates**: `template_name.plaintext.gotmpl` (e.g., `welcome.plaintext.gotmpl`)
157
+ - Single file with multiple language template definitions
158
+
159
+ **Template Syntax:**
160
+
161
+ - Uses Go template `{{define "language"}}` blocks for each language
162
+ - Template selection logic at the bottom using Kratos variables
163
+ - Kratos variables available (e.g., `{{ .Identity.traits.email }}`)
164
+ - Language detection via `{{ .Identity.traits.lang }}` by default (configurable via `kratosLanguageVariable`)
165
+
166
+ **Example Output:**
167
+
168
+ ```gotmpl
169
+ {{define "en"}}
170
+ <html>
171
+ <body>
172
+ <h1>Welcome to our platform!</h1>
173
+ <p>Hello {{ .Identity.traits.first_name }}!</p>
174
+ <p>Thank you for registering with us.</p>
175
+ <p><strong>Verification Code: {{ .VerificationCode }}</strong></p>
176
+ <p>Account: {{ .Identity.traits.email }}</p>
177
+ </body>
178
+ </html>
179
+ {{end}}
180
+
181
+ {{define "pl"}}
182
+ <html>
183
+ <body>
184
+ <h1>Witamy na naszej platformie!</h1>
185
+ <p>Witaj {{ .Identity.traits.first_name }}!</p>
186
+ <p>Dziękujemy za rejestrację.</p>
187
+ <p><strong>Kod weryfikacyjny: {{ .VerificationCode }}</strong></p>
188
+ <p>Konto: {{ .Identity.traits.email }}</p>
189
+ </body>
190
+ </html>
191
+ {{end}}
192
+
193
+ {{- if eq .Identity.traits.lang "pl" -}}
194
+ {{ template "pl" . }}
195
+ {{- else -}}
196
+ {{ template "en" . }}
197
+ {{- end -}}
198
+ ```
199
+
200
+ ### Razor Mode
201
+
202
+ Generates C# Razor template files:
203
+
204
+ **File Structure:**
205
+
206
+ - **HTML templates**: `TemplateName.cshtml` (default language), `TemplateName.language.cshtml` (other languages)
207
+ - **Plain text templates**: `TemplateName.txt.cshtml` (default language), `TemplateName.language.txt.cshtml` (other
208
+ languages)
209
+ - Separate files for each language
210
+
211
+ **Template Syntax:**
212
+
213
+ - Uses Razor syntax: `@Model.Property`
214
+ - CSS `@` symbols escaped as `@@` for media queries
215
+
216
+ **Example Output:**
217
+
218
+ Assuming english is the default language, the output will be:
219
+
220
+ English template (`notification.cshtml`):
221
+
222
+ ```html
223
+ <html>
224
+ <body>
225
+ <h1>System Notification</h1>
226
+ <p>Dear @Model.User.FullName,</p>
227
+ <p>Your account status has been updated to: @Model.Status as of @Model.UpdateDate.</p>
228
+ <p>Action required: @Model.RequiredAction</p>
229
+ <a href="@Model.ActionUrl">Take Action Now</a>
230
+ <p>Reference: @Model.ReferenceNumber</p>
231
+ </body>
232
+ </html>
233
+ ```
234
+
235
+ Polish template (`notification.pl.cshtml`):
236
+
237
+ ```html
238
+ <html>
239
+ <body>
240
+ <h1>Powiadomienie systemowe</h1>
241
+ <p>Szanowny/a @Model.User.FullName,</p>
242
+ <p>Status Twojego konta został zaktualizowany na: @Model.Status z dniem @Model.UpdateDate.</p>
243
+ <p>Wymagane działanie: @Model.RequiredAction</p>
244
+ <a href="@Model.ActionUrl">Wykonaj działanie teraz</a>
245
+ <p>Numer referencyjny: @Model.ReferenceNumber</p>
246
+ </body>
247
+ </html>
248
+ ```
package/package.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "@leancodepl/mail-translation",
3
+ "version": "9.2.0",
4
+ "license": "Apache-2.0",
5
+ "bin": {
6
+ "mail-translation": "src/bin.js"
7
+ },
8
+ "dependencies": {
9
+ "intl-messageformat": "^10.7.16",
10
+ "js-beautify": "^1.15.4",
11
+ "lilconfig": "^3.1.3",
12
+ "mjml": "^4.15.3",
13
+ "tslib": "^2.8.1",
14
+ "yaml": "^2.8.0",
15
+ "yargs": "^18.0.0",
16
+ "zod": "^4.0.5"
17
+ },
18
+ "devDependencies": {
19
+ "@types/js-beautify": "^1.14.3",
20
+ "@types/mjml": "^4.7.4",
21
+ "@types/yaml": "^1.9.7",
22
+ "@types/yargs": "^17.0.33"
23
+ },
24
+ "types": "./src/index.d.ts",
25
+ "main": "./src/index.js",
26
+ "type": "commonjs"
27
+ }
package/schema.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "title": "@leancodepl/mail-translation Configuration",
4
+ "description": "Schema for @leancodepl/mail-translation configuration",
5
+ "type": "object",
6
+ "properties": {
7
+ "translationsPath": {
8
+ "description": "Path to directory containing translation JSON files. When omitted, templates are compiled without translations. Each JSON file should be named with the language code (e.g., en.json, pl.json).",
9
+ "type": "string"
10
+ },
11
+ "mailsPath": {
12
+ "description": "Path to directory containing MJML email templates. All .mjml files in this directory will be processed.",
13
+ "type": "string"
14
+ },
15
+ "plaintextMailsPath": {
16
+ "description": "Path to directory containing plaintext templates. If not specified, defaults to the same value as mailsPath. Used for generating text-only versions of emails alongside HTML versions.",
17
+ "type": "string"
18
+ },
19
+ "outputPath": {
20
+ "description": "Directory where processed templates will be saved. The tool will create this directory if it doesn't exist.",
21
+ "type": "string"
22
+ },
23
+ "outputMode": {
24
+ "description": "Target templating system format: 'kratos' for Go template files compatible with Ory Kratos, 'razor' for C# Razor template files.",
25
+ "type": "string",
26
+ "enum": [
27
+ "kratos",
28
+ "razor"
29
+ ]
30
+ },
31
+ "defaultLanguage": {
32
+ "description": "Default language code for templates with translations. Required when translationsPath is provided.",
33
+ "type": "string"
34
+ },
35
+ "languages": {
36
+ "description": "Array of language codes to process. When omitted, all languages found in translation files are automatically processed. Use this to limit output to specific languages.",
37
+ "type": "array",
38
+ "items": {
39
+ "type": "string"
40
+ }
41
+ },
42
+ "kratosLanguageVariable": {
43
+ "description": "Variable path used for language detection in Kratos templates. Defaults to '.Identity.traits.lang'. This determines how the generated template will access the user's language preference. Only used in Kratos mode.",
44
+ "type": "string"
45
+ }
46
+ },
47
+ "required": [
48
+ "mailsPath",
49
+ "outputPath",
50
+ "outputMode"
51
+ ],
52
+ "additionalProperties": false
53
+ }
package/src/bin.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/src/bin.js ADDED
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const tslib_1 = require("tslib");
5
+ const helpers_1 = require("yargs/helpers");
6
+ const yargs_1 = tslib_1.__importDefault(require("yargs/yargs"));
7
+ const generate_1 = require("./generate");
8
+ const loadConfig_1 = require("./loadConfig");
9
+ const saveOutputs_1 = require("./saveOutputs");
10
+ const argv = (0, yargs_1.default)((0, helpers_1.hideBin)(process.argv))
11
+ .option("config", {
12
+ alias: "c",
13
+ type: "string",
14
+ description: "Config file location",
15
+ })
16
+ .parseSync();
17
+ const config = (0, loadConfig_1.loadConfig)(argv.config);
18
+ (0, generate_1.generate)(config).then(processedTemplates => (0, saveOutputs_1.saveOutputs)({ processedTemplates, outputPath: config.outputPath }));
19
+ //# sourceMappingURL=bin.js.map
package/src/bin.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bin.js","sourceRoot":"","sources":["../../../../packages/mail-translation/src/bin.ts"],"names":[],"mappings":";;;;AAEA,2CAAuC;AACvC,gEAA+B;AAC/B,yCAAqC;AACrC,6CAAyC;AACzC,+CAA2C;AAE3C,MAAM,IAAI,GAAG,IAAA,eAAK,EAAC,IAAA,iBAAO,EAAC,OAAO,CAAC,IAAI,CAAC,CAAC;KACtC,MAAM,CAAC,QAAQ,EAAE;IAChB,KAAK,EAAE,GAAG;IACV,IAAI,EAAE,QAAQ;IACd,WAAW,EAAE,sBAAsB;CACpC,CAAC;KACD,SAAS,EAAE,CAAA;AAEd,MAAM,MAAM,GAAG,IAAA,uBAAU,EAAC,IAAI,CAAC,MAAM,CAAC,CAAA;AAEtC,IAAA,mBAAQ,EAAC,MAAM,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,EAAE,CAAC,IAAA,yBAAW,EAAC,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,CAAA"}
@@ -0,0 +1,13 @@
1
+ export interface MjmlParseError {
2
+ line: number;
3
+ message: string;
4
+ tagName: string;
5
+ }
6
+ export interface MjmlCompileResult {
7
+ html: string;
8
+ mjmlParseErrors: MjmlParseError[];
9
+ }
10
+ export declare function compileMjml({ mjmlContent, filePath }: {
11
+ mjmlContent: string;
12
+ filePath: string;
13
+ }): MjmlCompileResult;
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.compileMjml = compileMjml;
4
+ const tslib_1 = require("tslib");
5
+ const js_beautify_1 = require("js-beautify");
6
+ const mjml_1 = tslib_1.__importDefault(require("mjml"));
7
+ function compileMjml({ mjmlContent, filePath }) {
8
+ try {
9
+ const result = (0, mjml_1.default)(mjmlContent, {
10
+ keepComments: false,
11
+ validationLevel: "soft",
12
+ filePath,
13
+ });
14
+ // js-beautify is used to format the HTML as beautify option is deprecated in mjml-core
15
+ const html = (0, js_beautify_1.html)(result.html, {
16
+ indent_size: 2,
17
+ preserve_newlines: true,
18
+ max_preserve_newlines: 1,
19
+ });
20
+ return {
21
+ html,
22
+ mjmlParseErrors: result.errors || [],
23
+ };
24
+ }
25
+ catch (error) {
26
+ throw new Error(`MJML compilation failed: ${error}`);
27
+ }
28
+ }
29
+ //# sourceMappingURL=compileMjml.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compileMjml.js","sourceRoot":"","sources":["../../../../packages/mail-translation/src/compileMjml.ts"],"names":[],"mappings":";;AAcA,kCAsBC;;AApCD,6CAAkD;AAClD,wDAA4B;AAa5B,SAAgB,WAAW,CAAC,EAAE,WAAW,EAAE,QAAQ,EAA6C;IAC9F,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAA,cAAS,EAAC,WAAW,EAAE;YACpC,YAAY,EAAE,KAAK;YACnB,eAAe,EAAE,MAAM;YACvB,QAAQ;SACT,CAAC,CAAA;QAEF,uFAAuF;QACvF,MAAM,IAAI,GAAG,IAAA,kBAAY,EAAC,MAAM,CAAC,IAAI,EAAE;YACrC,WAAW,EAAE,CAAC;YACd,iBAAiB,EAAE,IAAI;YACvB,qBAAqB,EAAE,CAAC;SACzB,CAAC,CAAA;QAEF,OAAO;YACL,IAAI;YACJ,eAAe,EAAE,MAAM,CAAC,MAAM,IAAI,EAAE;SACrC,CAAA;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,4BAA4B,KAAK,EAAE,CAAC,CAAA;IACtD,CAAC;AACH,CAAC"}
@@ -0,0 +1,21 @@
1
+ import { z } from "zod/v4";
2
+ declare const outputModeSchema: z.ZodEnum<{
3
+ kratos: "kratos";
4
+ razor: "razor";
5
+ }>;
6
+ export type OutputMode = z.infer<typeof outputModeSchema>;
7
+ export declare const mailTranslationConfigSchema: z.ZodObject<{
8
+ translationsPath: z.ZodOptional<z.ZodString>;
9
+ mailsPath: z.ZodString;
10
+ plaintextMailsPath: z.ZodOptional<z.ZodString>;
11
+ outputPath: z.ZodString;
12
+ outputMode: z.ZodEnum<{
13
+ kratos: "kratos";
14
+ razor: "razor";
15
+ }>;
16
+ defaultLanguage: z.ZodOptional<z.ZodString>;
17
+ languages: z.ZodOptional<z.ZodArray<z.ZodString>>;
18
+ kratosLanguageVariable: z.ZodOptional<z.ZodString>;
19
+ }, z.core.$strip>;
20
+ export type MailTranslationConfig = z.infer<typeof mailTranslationConfigSchema>;
21
+ export {};
package/src/config.js ADDED
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.mailTranslationConfigSchema = void 0;
4
+ const v4_1 = require("zod/v4");
5
+ const outputModeSchema = v4_1.z.enum(["kratos", "razor"]);
6
+ exports.mailTranslationConfigSchema = v4_1.z.object({
7
+ translationsPath: v4_1.z
8
+ .string()
9
+ .optional()
10
+ .describe("Path to directory containing translation JSON files. When omitted, templates are compiled without translations. Each JSON file should be named with the language code (e.g., en.json, pl.json)."),
11
+ mailsPath: v4_1.z
12
+ .string()
13
+ .describe("Path to directory containing MJML email templates. All .mjml files in this directory will be processed."),
14
+ plaintextMailsPath: v4_1.z
15
+ .string()
16
+ .optional()
17
+ .describe("Path to directory containing plaintext templates. If not specified, defaults to the same value as mailsPath. Used for generating text-only versions of emails alongside HTML versions."),
18
+ outputPath: v4_1.z
19
+ .string()
20
+ .describe("Directory where processed templates will be saved. The tool will create this directory if it doesn't exist."),
21
+ outputMode: outputModeSchema.describe("Target templating system format: 'kratos' for Go template files compatible with Ory Kratos, 'razor' for C# Razor template files."),
22
+ defaultLanguage: v4_1.z
23
+ .string()
24
+ .optional()
25
+ .describe("Default language code for templates with translations. Required when translationsPath is provided."),
26
+ languages: v4_1.z
27
+ .array(v4_1.z.string())
28
+ .optional()
29
+ .describe("Array of language codes to process. When omitted, all languages found in translation files are automatically processed. Use this to limit output to specific languages."),
30
+ kratosLanguageVariable: v4_1.z
31
+ .string()
32
+ .optional()
33
+ .describe("Variable path used for language detection in Kratos templates. Defaults to '.Identity.traits.lang'. This determines how the generated template will access the user's language preference. Only used in Kratos mode."),
34
+ });
35
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../../../packages/mail-translation/src/config.ts"],"names":[],"mappings":";;;AAAA,+BAA0B;AAE1B,MAAM,gBAAgB,GAAG,MAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAA;AAIvC,QAAA,2BAA2B,GAAG,MAAC,CAAC,MAAM,CAAC;IAClD,gBAAgB,EAAE,MAAC;SAChB,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CACP,iMAAiM,CAClM;IACH,SAAS,EAAE,MAAC;SACT,MAAM,EAAE;SACR,QAAQ,CACP,yGAAyG,CAC1G;IACH,kBAAkB,EAAE,MAAC;SAClB,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CACP,wLAAwL,CACzL;IACH,UAAU,EAAE,MAAC;SACV,MAAM,EAAE;SACR,QAAQ,CACP,6GAA6G,CAC9G;IACH,UAAU,EAAE,gBAAgB,CAAC,QAAQ,CACnC,kIAAkI,CACnI;IACD,eAAe,EAAE,MAAC;SACf,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,oGAAoG,CAAC;IACjH,SAAS,EAAE,MAAC;SACT,KAAK,CAAC,MAAC,CAAC,MAAM,EAAE,CAAC;SACjB,QAAQ,EAAE;SACV,QAAQ,CACP,yKAAyK,CAC1K;IACH,sBAAsB,EAAE,MAAC;SACtB,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CACP,sNAAsN,CACvN;CACJ,CAAC,CAAA"}
@@ -0,0 +1,2 @@
1
+ import { MailTranslationConfig } from "./config";
2
+ export declare function generate(config: Omit<MailTranslationConfig, "outputPath">): Promise<import("./processTemplate").ProcessedTemplate[]>;
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generate = generate;
4
+ const loadTemplates_1 = require("./loadTemplates");
5
+ const loadTranslations_1 = require("./loadTranslations");
6
+ const processTemplate_1 = require("./processTemplate");
7
+ async function generate(config) {
8
+ const translationData = await (0, loadTranslations_1.loadTranslations)(config.translationsPath);
9
+ const mjmlTemplates = await (0, loadTemplates_1.loadMjmlTemplates)(config.mailsPath);
10
+ const plaintextTemplates = await (0, loadTemplates_1.loadPlaintextTemplates)({
11
+ plaintextMailsPath: config.plaintextMailsPath ?? config.mailsPath,
12
+ outputMode: config.outputMode,
13
+ });
14
+ return [...mjmlTemplates, ...plaintextTemplates].map(template => (0, processTemplate_1.processTemplate)({
15
+ template,
16
+ translationData,
17
+ outputMode: config.outputMode,
18
+ defaultLanguage: config.defaultLanguage,
19
+ kratosLanguageVariable: config.kratosLanguageVariable,
20
+ mailsPath: config.mailsPath,
21
+ }));
22
+ }
23
+ //# sourceMappingURL=generate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate.js","sourceRoot":"","sources":["../../../../packages/mail-translation/src/generate.ts"],"names":[],"mappings":";;AAKA,4BAoBC;AAxBD,mDAA2E;AAC3E,yDAAqD;AACrD,uDAAmD;AAE5C,KAAK,UAAU,QAAQ,CAAC,MAAiD;IAC9E,MAAM,eAAe,GAAG,MAAM,IAAA,mCAAgB,EAAC,MAAM,CAAC,gBAAgB,CAAC,CAAA;IAEvE,MAAM,aAAa,GAAG,MAAM,IAAA,iCAAiB,EAAC,MAAM,CAAC,SAAS,CAAC,CAAA;IAC/D,MAAM,kBAAkB,GACtB,MAAM,IAAA,sCAAsB,EAAC;QAC7B,kBAAkB,EAAE,MAAM,CAAC,kBAAkB,IAAI,MAAM,CAAC,SAAS;QACjE,UAAU,EAAE,MAAM,CAAC,UAAU;KAC9B,CAAC,CAAA;IAEF,OAAO,CAAC,GAAG,aAAa,EAAE,GAAG,kBAAkB,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAC9D,IAAA,iCAAe,EAAC;QACd,QAAQ;QACR,eAAe;QACf,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,eAAe,EAAE,MAAM,CAAC,eAAe;QACvC,sBAAsB,EAAE,MAAM,CAAC,sBAAsB;QACrD,SAAS,EAAE,MAAM,CAAC,SAAS;KAC5B,CAAC,CACH,CAAA;AACH,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const fs_1 = require("fs");
4
+ const path_1 = require("path");
5
+ const v4_1 = require("zod/v4");
6
+ const config_1 = require("./config");
7
+ const jsonSchema = v4_1.z.toJSONSchema(config_1.mailTranslationConfigSchema);
8
+ const output = {
9
+ $schema: "http://json-schema.org/draft-07/schema#",
10
+ title: "@leancodepl/mail-translation Configuration",
11
+ description: "Schema for @leancodepl/mail-translation configuration",
12
+ ...jsonSchema,
13
+ };
14
+ const packageRoot = (0, path_1.join)(__dirname, "..");
15
+ const outputPath = (0, path_1.join)(packageRoot, "schema.json");
16
+ (0, fs_1.writeFileSync)(outputPath, JSON.stringify(output, null, 2) + '\n');
17
+ //# sourceMappingURL=generateConfigSchema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generateConfigSchema.js","sourceRoot":"","sources":["../../../../packages/mail-translation/src/generateConfigSchema.ts"],"names":[],"mappings":";;AAAA,2BAAkC;AAClC,+BAA2B;AAC3B,+BAA0B;AAC1B,qCAAsD;AAEtD,MAAM,UAAU,GAAG,MAAC,CAAC,YAAY,CAAC,oCAA2B,CAAC,CAAA;AAE9D,MAAM,MAAM,GAAG;IACb,OAAO,EAAE,yCAAyC;IAClD,KAAK,EAAE,4CAA4C;IACnD,WAAW,EAAE,uDAAuD;IACpE,GAAG,UAAU;CACd,CAAA;AAED,MAAM,WAAW,GAAG,IAAA,WAAI,EAAC,SAAS,EAAE,IAAI,CAAC,CAAA;AACzC,MAAM,UAAU,GAAG,IAAA,WAAI,EAAC,WAAW,EAAE,aAAa,CAAC,CAAA;AAEnD,IAAA,kBAAa,EAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAA"}
@@ -0,0 +1,9 @@
1
+ import { TranslatedTemplate } from "./processTemplate";
2
+ export declare function generateKratosOutputTemplates({ translatedTemplates, defaultLanguage, kratosLanguageVariable, }: {
3
+ translatedTemplates: TranslatedTemplate[];
4
+ defaultLanguage?: string;
5
+ kratosLanguageVariable?: string;
6
+ }): {
7
+ filename: string;
8
+ content: string;
9
+ }[];
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateKratosOutputTemplates = generateKratosOutputTemplates;
4
+ function generateKratosOutputTemplates({ translatedTemplates, defaultLanguage, kratosLanguageVariable, }) {
5
+ const plainTextTemplates = translatedTemplates.filter(template => template.isPlaintext);
6
+ const htmlTemplates = translatedTemplates.filter(template => !template.isPlaintext);
7
+ const htmlOutputTemplates = htmlTemplates.map(template => ({
8
+ filename: `${template.name}.gotmpl`,
9
+ content: generateKratosOutputTemplate({
10
+ templates: htmlTemplates,
11
+ defaultLanguage,
12
+ kratosLanguageVariable,
13
+ }),
14
+ }));
15
+ const plainTextOutputTemplates = plainTextTemplates.map(template => ({
16
+ filename: `${template.name}.plaintext.gotmpl`,
17
+ content: generateKratosOutputTemplate({
18
+ templates: plainTextTemplates,
19
+ defaultLanguage,
20
+ kratosLanguageVariable,
21
+ }),
22
+ }));
23
+ return [...htmlOutputTemplates, ...plainTextOutputTemplates];
24
+ }
25
+ function generateKratosOutputTemplate({ templates, defaultLanguage, kratosLanguageVariable = ".Identity.traits.lang", }) {
26
+ if (templates.length === 1 || !defaultLanguage) {
27
+ return templates[0].content;
28
+ }
29
+ let outputTemplate = "";
30
+ templates.forEach(template => {
31
+ outputTemplate += `{{define "${template.language}"}}\n`;
32
+ outputTemplate += template.content;
33
+ outputTemplate += "\n{{end}}\n\n";
34
+ });
35
+ const nonDefaultLanguages = templates
36
+ .filter(template => template.language !== defaultLanguage)
37
+ .map(template => template.language);
38
+ nonDefaultLanguages.forEach((language, index) => {
39
+ const condition = index === 0 ? "if" : "else if";
40
+ outputTemplate += `{{- ${condition} eq ${kratosLanguageVariable} "${language}" -}}\n`;
41
+ outputTemplate += `{{ template "${language}" . }}\n`;
42
+ });
43
+ outputTemplate += "{{- else -}}\n";
44
+ outputTemplate += `{{ template "${defaultLanguage}" . }}\n`;
45
+ outputTemplate += "{{- end -}}\n";
46
+ return outputTemplate;
47
+ }
48
+ //# sourceMappingURL=generateKratosOutputTemplates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generateKratosOutputTemplates.js","sourceRoot":"","sources":["../../../../packages/mail-translation/src/generateKratosOutputTemplates.ts"],"names":[],"mappings":";;AAEA,sEA+BC;AA/BD,SAAgB,6BAA6B,CAAC,EAC5C,mBAAmB,EACnB,eAAe,EACf,sBAAsB,GAKvB;IACC,MAAM,kBAAkB,GAAG,mBAAmB,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAA;IACvF,MAAM,aAAa,GAAG,mBAAmB,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAA;IAEnF,MAAM,mBAAmB,GAAG,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QACzD,QAAQ,EAAE,GAAG,QAAQ,CAAC,IAAI,SAAS;QACnC,OAAO,EAAE,4BAA4B,CAAC;YACpC,SAAS,EAAE,aAAa;YACxB,eAAe;YACf,sBAAsB;SACvB,CAAC;KACH,CAAC,CAAC,CAAA;IAEH,MAAM,wBAAwB,GAAG,kBAAkB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QACnE,QAAQ,EAAE,GAAG,QAAQ,CAAC,IAAI,mBAAmB;QAC7C,OAAO,EAAE,4BAA4B,CAAC;YACpC,SAAS,EAAE,kBAAkB;YAC7B,eAAe;YACf,sBAAsB;SACvB,CAAC;KACH,CAAC,CAAC,CAAA;IAEH,OAAO,CAAC,GAAG,mBAAmB,EAAE,GAAG,wBAAwB,CAAC,CAAA;AAC9D,CAAC;AAED,SAAS,4BAA4B,CAAC,EACpC,SAAS,EACT,eAAe,EACf,sBAAsB,GAAG,uBAAuB,GAKjD;IACC,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC;QAC/C,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,CAAA;IAC7B,CAAC;IAED,IAAI,cAAc,GAAG,EAAE,CAAA;IAEvB,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE;QAC3B,cAAc,IAAI,aAAa,QAAQ,CAAC,QAAQ,OAAO,CAAA;QACvD,cAAc,IAAI,QAAQ,CAAC,OAAO,CAAA;QAClC,cAAc,IAAI,eAAe,CAAA;IACnC,CAAC,CAAC,CAAA;IAEF,MAAM,mBAAmB,GAAG,SAAS;SAClC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,QAAQ,KAAK,eAAe,CAAC;SACzD,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;IAErC,mBAAmB,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,KAAK,EAAE,EAAE;QAC9C,MAAM,SAAS,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAA;QAEhD,cAAc,IAAI,OAAO,SAAS,OAAO,sBAAsB,KAAK,QAAQ,SAAS,CAAA;QACrF,cAAc,IAAI,gBAAgB,QAAQ,UAAU,CAAA;IACtD,CAAC,CAAC,CAAA;IAEF,cAAc,IAAI,gBAAgB,CAAA;IAClC,cAAc,IAAI,gBAAgB,eAAe,UAAU,CAAA;IAC3D,cAAc,IAAI,eAAe,CAAA;IAEjC,OAAO,cAAc,CAAA;AACvB,CAAC"}
@@ -0,0 +1,12 @@
1
+ import { OutputMode } from "./config";
2
+ import { TranslatedTemplate } from "./processTemplate";
3
+ export interface OutputTemplate {
4
+ filename: string;
5
+ content: string;
6
+ }
7
+ export declare function generateOutputTemplates({ translatedTemplates, outputMode, defaultLanguage, kratosLanguageVariable, }: {
8
+ translatedTemplates: TranslatedTemplate[];
9
+ outputMode: OutputMode;
10
+ defaultLanguage?: string;
11
+ kratosLanguageVariable?: string;
12
+ }): OutputTemplate[];
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateOutputTemplates = generateOutputTemplates;
4
+ const generateKratosOutputTemplates_1 = require("./generateKratosOutputTemplates");
5
+ const generateRazorOutputTemplates_1 = require("./generateRazorOutputTemplates");
6
+ function generateOutputTemplates({ translatedTemplates, outputMode, defaultLanguage, kratosLanguageVariable, }) {
7
+ switch (outputMode) {
8
+ case "kratos":
9
+ return (0, generateKratosOutputTemplates_1.generateKratosOutputTemplates)({
10
+ translatedTemplates,
11
+ defaultLanguage,
12
+ kratosLanguageVariable,
13
+ });
14
+ case "razor":
15
+ return (0, generateRazorOutputTemplates_1.generateRazorOutputTemplates)({ translatedTemplates, defaultLanguage });
16
+ }
17
+ }
18
+ //# sourceMappingURL=generateOutputTemplates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generateOutputTemplates.js","sourceRoot":"","sources":["../../../../packages/mail-translation/src/generateOutputTemplates.ts"],"names":[],"mappings":";;AAUA,0DAqBC;AA9BD,mFAA+E;AAC/E,iFAA6E;AAQ7E,SAAgB,uBAAuB,CAAC,EACtC,mBAAmB,EACnB,UAAU,EACV,eAAe,EACf,sBAAsB,GAMvB;IACC,QAAQ,UAAU,EAAE,CAAC;QACnB,KAAK,QAAQ;YACX,OAAO,IAAA,6DAA6B,EAAC;gBACnC,mBAAmB;gBACnB,eAAe;gBACf,sBAAsB;aACvB,CAAC,CAAA;QACJ,KAAK,OAAO;YACV,OAAO,IAAA,2DAA4B,EAAC,EAAE,mBAAmB,EAAE,eAAe,EAAE,CAAC,CAAA;IACjF,CAAC;AACH,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { TranslatedTemplate } from "./processTemplate";
2
+ export declare function generateRazorOutputTemplates({ translatedTemplates, defaultLanguage, }: {
3
+ translatedTemplates: TranslatedTemplate[];
4
+ defaultLanguage?: string;
5
+ }): {
6
+ filename: string;
7
+ content: string;
8
+ }[];
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateRazorOutputTemplates = generateRazorOutputTemplates;
4
+ function generateRazorOutputTemplates({ translatedTemplates, defaultLanguage, }) {
5
+ return translatedTemplates.map(template => ({
6
+ filename: getFilename({ template, defaultLanguage }),
7
+ content: escapeRazorConflicts(template.content),
8
+ }));
9
+ }
10
+ function escapeRazorConflicts(templateContent) {
11
+ const cssAtRules = [
12
+ "annotation",
13
+ "character-variant",
14
+ "charset",
15
+ "color-profile",
16
+ "container",
17
+ "counter-style",
18
+ "font-face",
19
+ "font-feature-values",
20
+ "font-palette-values",
21
+ "import",
22
+ "keyframes",
23
+ "-webkit-keyframes",
24
+ "layer",
25
+ "media",
26
+ "namespace",
27
+ "ornaments",
28
+ "page",
29
+ "position-try",
30
+ "property",
31
+ "scope",
32
+ "starting-style",
33
+ "styleset",
34
+ "stylistic",
35
+ "supports",
36
+ "swash",
37
+ "view-transition",
38
+ ].join("|");
39
+ return templateContent.replace(new RegExp(`(?<!@)@(${cssAtRules})`, "g"), "@@$1");
40
+ }
41
+ function getFilename({ template, defaultLanguage, }) {
42
+ const includeLanguage = !!defaultLanguage && !!template.language && template.language !== defaultLanguage;
43
+ return [
44
+ template.name,
45
+ ...(includeLanguage ? [template.language] : []),
46
+ ...(template.isPlaintext ? ["txt"] : []),
47
+ "cshtml",
48
+ ].join(".");
49
+ }
50
+ //# sourceMappingURL=generateRazorOutputTemplates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generateRazorOutputTemplates.js","sourceRoot":"","sources":["../../../../packages/mail-translation/src/generateRazorOutputTemplates.ts"],"names":[],"mappings":";;AAEA,oEAWC;AAXD,SAAgB,4BAA4B,CAAC,EAC3C,mBAAmB,EACnB,eAAe,GAIhB;IACC,OAAO,mBAAmB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAC1C,QAAQ,EAAE,WAAW,CAAC,EAAE,QAAQ,EAAE,eAAe,EAAE,CAAC;QACpD,OAAO,EAAE,oBAAoB,CAAC,QAAQ,CAAC,OAAO,CAAC;KAChD,CAAC,CAAC,CAAA;AACL,CAAC;AAED,SAAS,oBAAoB,CAAC,eAAuB;IACnD,MAAM,UAAU,GAAG;QACjB,YAAY;QACZ,mBAAmB;QACnB,SAAS;QACT,eAAe;QACf,WAAW;QACX,eAAe;QACf,WAAW;QACX,qBAAqB;QACrB,qBAAqB;QACrB,QAAQ;QACR,WAAW;QACX,mBAAmB;QACnB,OAAO;QACP,OAAO;QACP,WAAW;QACX,WAAW;QACX,MAAM;QACN,cAAc;QACd,UAAU;QACV,OAAO;QACP,gBAAgB;QAChB,UAAU;QACV,WAAW;QACX,UAAU;QACV,OAAO;QACP,iBAAiB;KAClB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IAEX,OAAO,eAAe,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,WAAW,UAAU,GAAG,EAAE,GAAG,CAAC,EAAE,MAAM,CAAC,CAAA;AACnF,CAAC;AAED,SAAS,WAAW,CAAC,EACnB,QAAQ,EACR,eAAe,GAIhB;IACC,MAAM,eAAe,GAAG,CAAC,CAAC,eAAe,IAAI,CAAC,CAAC,QAAQ,CAAC,QAAQ,IAAI,QAAQ,CAAC,QAAQ,KAAK,eAAe,CAAA;IAEzG,OAAO;QACL,QAAQ,CAAC,IAAI;QACb,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/C,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACxC,QAAQ;KACT,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AACb,CAAC"}
package/src/index.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export * from "./generate";
2
+ export * from "./saveOutputs";
package/src/index.js ADDED
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ tslib_1.__exportStar(require("./generate"), exports);
5
+ tslib_1.__exportStar(require("./saveOutputs"), exports);
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../packages/mail-translation/src/index.ts"],"names":[],"mappings":";;;AAAA,qDAA0B;AAC1B,wDAA6B"}
@@ -0,0 +1,2 @@
1
+ import { MailTranslationConfig } from "./config";
2
+ export declare function loadConfig(configPath?: string): MailTranslationConfig;
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.loadConfig = loadConfig;
4
+ const tslib_1 = require("tslib");
5
+ const lilconfig_1 = require("lilconfig");
6
+ const yaml = tslib_1.__importStar(require("yaml"));
7
+ const config_1 = require("./config");
8
+ function loadYaml(filepath, content) {
9
+ return yaml.parse(content);
10
+ }
11
+ const packageName = "mail-translation";
12
+ const options = {
13
+ searchPlaces: [
14
+ `.${packageName}rc`,
15
+ `.${packageName}rc.json`,
16
+ `.${packageName}rc.yaml`,
17
+ `.${packageName}rc.yml`,
18
+ `.${packageName}rc.js`,
19
+ `.${packageName}rc.cjs`,
20
+ `${packageName}.config.js`,
21
+ `${packageName}.config.cjs`,
22
+ ],
23
+ loaders: {
24
+ ".yaml": loadYaml,
25
+ ".yml": loadYaml,
26
+ },
27
+ };
28
+ function loadConfig(configPath) {
29
+ const searcher = (0, lilconfig_1.lilconfigSync)("mail-translation", options);
30
+ const result = configPath ? searcher.load(configPath) : searcher.search();
31
+ if (!result) {
32
+ throw new Error("No configuration file found");
33
+ }
34
+ try {
35
+ return config_1.mailTranslationConfigSchema.parse(result.config);
36
+ }
37
+ catch (error) {
38
+ throw new Error(`Failed to load configuration: ${error}`);
39
+ }
40
+ }
41
+ //# sourceMappingURL=loadConfig.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loadConfig.js","sourceRoot":"","sources":["../../../../packages/mail-translation/src/loadConfig.ts"],"names":[],"mappings":";;AA2BA,gCAaC;;AAxCD,yCAA8E;AAC9E,mDAA4B;AAC5B,qCAA6E;AAE7E,SAAS,QAAQ,CAAC,QAAgB,EAAE,OAAe;IACjD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;AAC5B,CAAC;AAED,MAAM,WAAW,GAAG,kBAAkB,CAAA;AAEtC,MAAM,OAAO,GAAyB;IACpC,YAAY,EAAE;QACZ,IAAI,WAAW,IAAI;QACnB,IAAI,WAAW,SAAS;QACxB,IAAI,WAAW,SAAS;QACxB,IAAI,WAAW,QAAQ;QACvB,IAAI,WAAW,OAAO;QACtB,IAAI,WAAW,QAAQ;QACvB,GAAG,WAAW,YAAY;QAC1B,GAAG,WAAW,aAAa;KAC5B;IACD,OAAO,EAAE;QACP,OAAO,EAAE,QAAQ;QACjB,MAAM,EAAE,QAAQ;KACjB;CACF,CAAA;AAED,SAAgB,UAAU,CAAC,UAAmB;IAC5C,MAAM,QAAQ,GAAG,IAAA,yBAAa,EAAC,kBAAkB,EAAE,OAAO,CAAC,CAAA;IAE3D,MAAM,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAA;IACzE,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAA;IAChD,CAAC;IAED,IAAI,CAAC;QACH,OAAO,oCAA2B,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;IACzD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,iCAAiC,KAAK,EAAE,CAAC,CAAA;IAC3D,CAAC;AACH,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { OutputMode } from "./config";
2
+ import { Template } from "./processTemplate";
3
+ export declare function loadMjmlTemplates(mailsPath: string): Promise<Template[]>;
4
+ export declare function loadPlaintextTemplates({ plaintextMailsPath, outputMode, }: {
5
+ plaintextMailsPath: string;
6
+ outputMode: OutputMode;
7
+ }): Promise<Template[]>;
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.loadMjmlTemplates = loadMjmlTemplates;
4
+ exports.loadPlaintextTemplates = loadPlaintextTemplates;
5
+ const promises_1 = require("fs/promises");
6
+ const path_1 = require("path");
7
+ async function loadMjmlTemplates(mailsPath) {
8
+ try {
9
+ const files = await (0, promises_1.readdir)(mailsPath);
10
+ const mjmlFiles = files.filter(file => (0, path_1.extname)(file) === ".mjml");
11
+ return Promise.all(mjmlFiles.map(async (file) => {
12
+ const templateName = (0, path_1.basename)(file, ".mjml");
13
+ const filePath = (0, path_1.join)(mailsPath, file);
14
+ const content = await (0, promises_1.readFile)(filePath, "utf8");
15
+ return {
16
+ name: templateName,
17
+ content,
18
+ isPlaintext: false,
19
+ };
20
+ }));
21
+ }
22
+ catch (error) {
23
+ throw new Error(`Failed to load templates: ${error}`);
24
+ }
25
+ }
26
+ async function loadPlaintextTemplates({ plaintextMailsPath, outputMode, }) {
27
+ try {
28
+ const files = await (0, promises_1.readdir)(plaintextMailsPath);
29
+ const plaintextFiles = outputMode === "kratos"
30
+ ? files.filter(file => file.endsWith(".plaintext.gotmpl"))
31
+ : files.filter(file => file.endsWith(".txt.cshtml"));
32
+ return Promise.all(plaintextFiles.map(async (file) => {
33
+ const templateName = outputMode === "kratos" ? file.replace(/\.plaintext\.gotmpl$/, "") : file.replace(/\.txt\.cshtml$/, "");
34
+ const filePath = (0, path_1.join)(plaintextMailsPath, file);
35
+ const content = await (0, promises_1.readFile)(filePath, "utf8");
36
+ return {
37
+ name: templateName,
38
+ content,
39
+ isPlaintext: true,
40
+ };
41
+ }));
42
+ }
43
+ catch (error) {
44
+ throw new Error(`Failed to load plaintext templates: ${error}`);
45
+ }
46
+ }
47
+ //# sourceMappingURL=loadTemplates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loadTemplates.js","sourceRoot":"","sources":["../../../../packages/mail-translation/src/loadTemplates.ts"],"names":[],"mappings":";;AAKA,8CAqBC;AAED,wDAgCC;AA5DD,0CAA+C;AAC/C,+BAA8C;AAIvC,KAAK,UAAU,iBAAiB,CAAC,SAAiB;IACvD,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,IAAA,kBAAO,EAAC,SAAS,CAAC,CAAA;QACtC,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAA,cAAO,EAAC,IAAI,CAAC,KAAK,OAAO,CAAC,CAAA;QAEjE,OAAO,OAAO,CAAC,GAAG,CAChB,SAAS,CAAC,GAAG,CAAC,KAAK,EAAC,IAAI,EAAC,EAAE;YACzB,MAAM,YAAY,GAAG,IAAA,eAAQ,EAAC,IAAI,EAAE,OAAO,CAAC,CAAA;YAC5C,MAAM,QAAQ,GAAG,IAAA,WAAI,EAAC,SAAS,EAAE,IAAI,CAAC,CAAA;YACtC,MAAM,OAAO,GAAG,MAAM,IAAA,mBAAQ,EAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;YAEhD,OAAO;gBACL,IAAI,EAAE,YAAY;gBAClB,OAAO;gBACP,WAAW,EAAE,KAAK;aACnB,CAAA;QACH,CAAC,CAAC,CACH,CAAA;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,6BAA6B,KAAK,EAAE,CAAC,CAAA;IACvD,CAAC;AACH,CAAC;AAEM,KAAK,UAAU,sBAAsB,CAAC,EAC3C,kBAAkB,EAClB,UAAU,GAIX;IACC,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,IAAA,kBAAO,EAAC,kBAAkB,CAAC,CAAA;QAE/C,MAAM,cAAc,GAClB,UAAU,KAAK,QAAQ;YACrB,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC;YAC1D,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAA;QAExD,OAAO,OAAO,CAAC,GAAG,CAChB,cAAc,CAAC,GAAG,CAAC,KAAK,EAAC,IAAI,EAAC,EAAE;YAC9B,MAAM,YAAY,GAChB,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,sBAAsB,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAA;YACzG,MAAM,QAAQ,GAAG,IAAA,WAAI,EAAC,kBAAkB,EAAE,IAAI,CAAC,CAAA;YAC/C,MAAM,OAAO,GAAG,MAAM,IAAA,mBAAQ,EAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;YAEhD,OAAO;gBACL,IAAI,EAAE,YAAY;gBAClB,OAAO;gBACP,WAAW,EAAE,IAAI;aAClB,CAAA;QACH,CAAC,CAAC,CACH,CAAA;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,uCAAuC,KAAK,EAAE,CAAC,CAAA;IACjE,CAAC;AACH,CAAC"}
@@ -0,0 +1,7 @@
1
+ export interface Translations {
2
+ [key: string]: string;
3
+ }
4
+ export interface TranslationData {
5
+ [language: string]: Translations;
6
+ }
7
+ export declare function loadTranslations(translationsPath?: string): Promise<TranslationData>;
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.loadTranslations = loadTranslations;
4
+ const promises_1 = require("fs/promises");
5
+ const path_1 = require("path");
6
+ async function loadTranslations(translationsPath) {
7
+ const translationData = {};
8
+ if (!translationsPath) {
9
+ return translationData;
10
+ }
11
+ try {
12
+ const files = await (0, promises_1.readdir)(translationsPath);
13
+ const jsonFiles = files.filter(file => (0, path_1.extname)(file) === ".json");
14
+ if (jsonFiles.length === 0) {
15
+ console.warn(`No translation files found in: ${translationsPath}. Continuing without translations.`);
16
+ return translationData;
17
+ }
18
+ for (const file of jsonFiles) {
19
+ const language = (0, path_1.basename)(file, ".json");
20
+ const filePath = (0, path_1.join)(translationsPath, file);
21
+ try {
22
+ const content = await (0, promises_1.readFile)(filePath, "utf8");
23
+ const translations = JSON.parse(content);
24
+ translationData[language] = translations;
25
+ }
26
+ catch (error) {
27
+ console.warn(`Failed to load translation file ${file}:`, error);
28
+ }
29
+ }
30
+ return translationData;
31
+ }
32
+ catch (error) {
33
+ console.warn(`Failed to load translations: ${error}. Continuing without translations.`);
34
+ return translationData;
35
+ }
36
+ }
37
+ //# sourceMappingURL=loadTranslations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loadTranslations.js","sourceRoot":"","sources":["../../../../packages/mail-translation/src/loadTranslations.ts"],"names":[],"mappings":";;AAWA,4CAkCC;AA7CD,0CAA+C;AAC/C,+BAA8C;AAUvC,KAAK,UAAU,gBAAgB,CAAC,gBAAyB;IAC9D,MAAM,eAAe,GAAoB,EAAE,CAAA;IAE3C,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACtB,OAAO,eAAe,CAAA;IACxB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,IAAA,kBAAO,EAAC,gBAAgB,CAAC,CAAA;QAC7C,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAA,cAAO,EAAC,IAAI,CAAC,KAAK,OAAO,CAAC,CAAA;QAEjE,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3B,OAAO,CAAC,IAAI,CAAC,kCAAkC,gBAAgB,oCAAoC,CAAC,CAAA;YACpG,OAAO,eAAe,CAAA;QACxB,CAAC;QAED,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;YAC7B,MAAM,QAAQ,GAAG,IAAA,eAAQ,EAAC,IAAI,EAAE,OAAO,CAAC,CAAA;YACxC,MAAM,QAAQ,GAAG,IAAA,WAAI,EAAC,gBAAgB,EAAE,IAAI,CAAC,CAAA;YAE7C,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,MAAM,IAAA,mBAAQ,EAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;gBAChD,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;gBACxC,eAAe,CAAC,QAAQ,CAAC,GAAG,YAAY,CAAA;YAC1C,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,IAAI,CAAC,mCAAmC,IAAI,GAAG,EAAE,KAAK,CAAC,CAAA;YACjE,CAAC;QACH,CAAC;QAED,OAAO,eAAe,CAAA;IACxB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,IAAI,CAAC,gCAAgC,KAAK,oCAAoC,CAAC,CAAA;QACvF,OAAO,eAAe,CAAA;IACxB,CAAC;AACH,CAAC"}
@@ -0,0 +1,28 @@
1
+ import { MjmlParseError } from "./compileMjml";
2
+ import { OutputMode } from "./config";
3
+ import { OutputTemplate } from "./generateOutputTemplates";
4
+ import { TranslationData } from "./loadTranslations";
5
+ export interface Template {
6
+ name: string;
7
+ content: string;
8
+ isPlaintext: boolean;
9
+ }
10
+ export interface TranslatedTemplate {
11
+ name: string;
12
+ content: string;
13
+ isPlaintext: boolean;
14
+ language?: string;
15
+ }
16
+ export interface ProcessedTemplate {
17
+ name: string;
18
+ mjmlParseErrors: MjmlParseError[];
19
+ outputTemplates: OutputTemplate[];
20
+ }
21
+ export declare function processTemplate({ template, translationData, outputMode, defaultLanguage, kratosLanguageVariable, mailsPath, }: {
22
+ template: Template;
23
+ translationData: TranslationData;
24
+ outputMode: OutputMode;
25
+ defaultLanguage?: string;
26
+ kratosLanguageVariable?: string;
27
+ mailsPath: string;
28
+ }): ProcessedTemplate;
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.processTemplate = processTemplate;
4
+ const compileMjml_1 = require("./compileMjml");
5
+ const generateOutputTemplates_1 = require("./generateOutputTemplates");
6
+ const processTranslations_1 = require("./processTranslations");
7
+ function processTemplate({ template, translationData, outputMode, defaultLanguage, kratosLanguageVariable, mailsPath, }) {
8
+ const availableLanguages = Object.keys(translationData);
9
+ const languagesToProcess = availableLanguages.length > 0 ? availableLanguages : [defaultLanguage];
10
+ const mjmlCompileResult = template.isPlaintext
11
+ ? undefined
12
+ : (0, compileMjml_1.compileMjml)({ mjmlContent: template.content, filePath: mailsPath });
13
+ const content = template.isPlaintext ? template.content : (mjmlCompileResult?.html ?? "");
14
+ const translatedTemplates = languagesToProcess.map(language => {
15
+ const translations = language ? (translationData[language] ?? {}) : {};
16
+ const translatedContent = (0, processTranslations_1.processTranslations)({ template: content, translations, language });
17
+ return {
18
+ name: template.name,
19
+ content: translatedContent,
20
+ isPlaintext: template.isPlaintext,
21
+ language,
22
+ };
23
+ });
24
+ const outputTemplates = (0, generateOutputTemplates_1.generateOutputTemplates)({
25
+ translatedTemplates,
26
+ outputMode,
27
+ defaultLanguage,
28
+ kratosLanguageVariable,
29
+ });
30
+ return {
31
+ name: template.name,
32
+ mjmlParseErrors: mjmlCompileResult?.mjmlParseErrors ?? [],
33
+ outputTemplates,
34
+ };
35
+ }
36
+ //# sourceMappingURL=processTemplate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"processTemplate.js","sourceRoot":"","sources":["../../../../packages/mail-translation/src/processTemplate.ts"],"names":[],"mappings":";;AAyBA,0CAiDC;AA1ED,+CAA2D;AAE3D,uEAAmF;AAEnF,+DAA2D;AAqB3D,SAAgB,eAAe,CAAC,EAC9B,QAAQ,EACR,eAAe,EACf,UAAU,EACV,eAAe,EACf,sBAAsB,EACtB,SAAS,GAQV;IACC,MAAM,kBAAkB,GAAG,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAA;IACvD,MAAM,kBAAkB,GAAG,kBAAkB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAA;IAEjG,MAAM,iBAAiB,GAAG,QAAQ,CAAC,WAAW;QAC5C,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,IAAA,yBAAW,EAAC,EAAE,WAAW,EAAE,QAAQ,CAAC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAA;IAEvE,MAAM,OAAO,GAAG,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,iBAAiB,EAAE,IAAI,IAAI,EAAE,CAAC,CAAA;IAEzF,MAAM,mBAAmB,GAAG,kBAAkB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE;QAC5D,MAAM,YAAY,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;QAEtE,MAAM,iBAAiB,GAAG,IAAA,yCAAmB,EAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAC,CAAA;QAE5F,OAAO;YACL,IAAI,EAAE,QAAQ,CAAC,IAAI;YACnB,OAAO,EAAE,iBAAiB;YAC1B,WAAW,EAAE,QAAQ,CAAC,WAAW;YACjC,QAAQ;SACT,CAAA;IACH,CAAC,CAAC,CAAA;IAEF,MAAM,eAAe,GAAG,IAAA,iDAAuB,EAAC;QAC9C,mBAAmB;QACnB,UAAU;QACV,eAAe;QACf,sBAAsB;KACvB,CAAC,CAAA;IAEF,OAAO;QACL,IAAI,EAAE,QAAQ,CAAC,IAAI;QACnB,eAAe,EAAE,iBAAiB,EAAE,eAAe,IAAI,EAAE;QACzD,eAAe;KAChB,CAAA;AACH,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { Translations } from "./loadTranslations";
2
+ export declare function processTranslations({ template, translations, language, }: {
3
+ template: string;
4
+ translations: Translations;
5
+ language?: string;
6
+ }): string;
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.processTranslations = processTranslations;
4
+ const tslib_1 = require("tslib");
5
+ const intl_messageformat_1 = tslib_1.__importDefault(require("intl-messageformat"));
6
+ function processTranslations({ template, translations, language, }) {
7
+ const translationRegex = /\(\(t\s+['"]([^'"]+)['"]\s*(?:,\s*(\{.*?\}))?\s*\)\)/g;
8
+ const processedTemplate = template.replace(translationRegex, (match, key, jsonParams) => {
9
+ const translation = translations[key];
10
+ if (!translation || !language) {
11
+ console.warn(`Translation is missing for key "${key}"` + (language ? ` for "${language}" language` : ""));
12
+ return key;
13
+ }
14
+ if (jsonParams && language) {
15
+ try {
16
+ const params = JSON.parse(jsonParams);
17
+ const formatter = new intl_messageformat_1.default(translation, language);
18
+ return formatter.format(params);
19
+ }
20
+ catch (error) {
21
+ console.warn(`Error parsing JSON parameters or formatting message for key "${key}":`, error);
22
+ return key;
23
+ }
24
+ }
25
+ else {
26
+ return translation;
27
+ }
28
+ });
29
+ return processedTemplate;
30
+ }
31
+ //# sourceMappingURL=processTranslations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"processTranslations.js","sourceRoot":"","sources":["../../../../packages/mail-translation/src/processTranslations.ts"],"names":[],"mappings":";;AAGA,kDAkCC;;AArCD,oFAAkD;AAGlD,SAAgB,mBAAmB,CAAC,EAClC,QAAQ,EACR,YAAY,EACZ,QAAQ,GAKT;IACC,MAAM,gBAAgB,GAAG,uDAAuD,CAAA;IAEhF,MAAM,iBAAiB,GAAG,QAAQ,CAAC,OAAO,CAAC,gBAAgB,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,UAAU,EAAE,EAAE;QACtF,MAAM,WAAW,GAAG,YAAY,CAAC,GAAG,CAAC,CAAA;QAErC,IAAI,CAAC,WAAW,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC9B,OAAO,CAAC,IAAI,CAAC,mCAAmC,GAAG,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,QAAQ,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;YACzG,OAAO,GAAG,CAAA;QACZ,CAAC;QAED,IAAI,UAAU,IAAI,QAAQ,EAAE,CAAC;YAC3B,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAA;gBACrC,MAAM,SAAS,GAAG,IAAI,4BAAiB,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAA;gBAC9D,OAAO,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;YACjC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,IAAI,CAAC,gEAAgE,GAAG,IAAI,EAAE,KAAK,CAAC,CAAA;gBAC5F,OAAO,GAAG,CAAA;YACZ,CAAC;QACH,CAAC;aAAM,CAAC;YACN,OAAO,WAAW,CAAA;QACpB,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,OAAO,iBAAiB,CAAA;AAC1B,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { ProcessedTemplate } from "./processTemplate";
2
+ export declare function saveOutputs({ processedTemplates, outputPath, }: {
3
+ processedTemplates: ProcessedTemplate[];
4
+ outputPath: string;
5
+ }): Promise<void>;
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.saveOutputs = saveOutputs;
4
+ const promises_1 = require("fs/promises");
5
+ const path_1 = require("path");
6
+ async function saveOutputs({ processedTemplates, outputPath, }) {
7
+ await (0, promises_1.mkdir)(outputPath, { recursive: true });
8
+ const outputTemplates = processedTemplates.flatMap(processedTemplate => processedTemplate.outputTemplates);
9
+ await Promise.all(outputTemplates.map(template => (0, promises_1.writeFile)((0, path_1.join)(outputPath, template.filename), template.content, "utf8")));
10
+ for (const processedTemplate of processedTemplates) {
11
+ if (processedTemplate.mjmlParseErrors.length > 0) {
12
+ console.warn(`Errors in ${processedTemplate.name}:`, processedTemplate.mjmlParseErrors);
13
+ }
14
+ }
15
+ }
16
+ //# sourceMappingURL=saveOutputs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"saveOutputs.js","sourceRoot":"","sources":["../../../../packages/mail-translation/src/saveOutputs.ts"],"names":[],"mappings":";;AAIA,kCAoBC;AAxBD,0CAA8C;AAC9C,+BAA2B;AAGpB,KAAK,UAAU,WAAW,CAAC,EAChC,kBAAkB,EAClB,UAAU,GAIX;IACC,MAAM,IAAA,gBAAK,EAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAE5C,MAAM,eAAe,GAAG,kBAAkB,CAAC,OAAO,CAAC,iBAAiB,CAAC,EAAE,CAAC,iBAAiB,CAAC,eAAe,CAAC,CAAA;IAE1G,MAAM,OAAO,CAAC,GAAG,CACf,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAA,oBAAS,EAAC,IAAA,WAAI,EAAC,UAAU,EAAE,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAC1G,CAAA;IAED,KAAK,MAAM,iBAAiB,IAAI,kBAAkB,EAAE,CAAC;QACnD,IAAI,iBAAiB,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACjD,OAAO,CAAC,IAAI,CAAC,aAAa,iBAAiB,CAAC,IAAI,GAAG,EAAE,iBAAiB,CAAC,eAAe,CAAC,CAAA;QACzF,CAAC;IACH,CAAC;AACH,CAAC"}