@nxgt/mail-i18n 0.2.0 → 0.3.1
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 +11 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +3 -3
- package/dist/manifest.d.ts +13 -0
- package/dist/manifest.d.ts.map +1 -1
- package/docs/README.md +1 -1
- package/docs/guide/manifest.md +89 -2
- package/docs/guide/templates.md +4 -2
- package/docs/roadmap.md +10 -17
- package/docs/troubleshooting.md +6 -3
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -88,6 +88,7 @@ file is how the editor learns them. See
|
|
|
88
88
|
| `createTranslator(catalogues, getLanguage)` | `t(key, args?, language?)` outside templates, shaped like `@nxgt/i18n`, but it throws on a missing key |
|
|
89
89
|
| `emailKey(email)` | Where an e-mail's messages live: `auth/reset-password` → `auth.resetPassword` |
|
|
90
90
|
| `MANIFEST_FILE` | `'mail-manifest.json'`, the manifest's name in the output folder |
|
|
91
|
+
| `MANIFEST_FORMAT` | `1`, the manifest format this version writes as `formatVersion`: it changes only with the manifest's shape, and `@nxgt/mail`'s renderer reads every format up to its own within 0.x |
|
|
91
92
|
| `WRAPPERS_DIR` | `'.maizzle/emails'`, where the generated files go |
|
|
92
93
|
| `I18nOptions`, `Layout`, `TemplateSource` | The plugin's options, `'nested' \| 'flat'`, and a package's folder of templates for `templates` |
|
|
93
94
|
| `Catalogue`, `Catalogues`, `ArgumentKind` | A catalogue as written, catalogues by locale, and `'string' \| 'number' \| 'date'` |
|
|
@@ -260,11 +261,13 @@ catalogues`. See [Catalogues](docs/guide/catalogues.md#the-subject).
|
|
|
260
261
|
### The manifest
|
|
261
262
|
|
|
262
263
|
`dist/mail-manifest.json` is written by `maizzle build`, for the code that
|
|
263
|
-
sends.
|
|
264
|
-
image URL starts with, its subject in each
|
|
264
|
+
sends. It starts with its format; then, for each e-mail, it records its
|
|
265
|
+
placeholders, the ones a link or an image URL starts with, its subject in each
|
|
266
|
+
locale, and its files:
|
|
265
267
|
|
|
266
268
|
```json
|
|
267
269
|
{
|
|
270
|
+
"formatVersion": 1,
|
|
268
271
|
"locales": ["en", "fr"],
|
|
269
272
|
"fallbackLocale": "en",
|
|
270
273
|
"emails": {
|
|
@@ -286,7 +289,9 @@ image URL starts with, its subject in each locale, and its files:
|
|
|
286
289
|
|
|
287
290
|
`createMailRenderer` from `@nxgt/mail/renderer` reads it at send time:
|
|
288
291
|
`createMailRenderer({ dir: 'dist' }).render('verify-email', { name, link })`
|
|
289
|
-
answers the subject, HTML and text, every value escaped.
|
|
292
|
+
answers the subject, HTML and text, every value escaped. Within 0.x, a newer
|
|
293
|
+
`@nxgt/mail` reads a build from any earlier `@nxgt/mail-i18n`: see
|
|
294
|
+
[The manifest — `formatVersion`](docs/guide/manifest.md#formatversion).
|
|
290
295
|
|
|
291
296
|
After the manifest, each build writes `generated/mail.ts`, in the project — the manifest's e-mails
|
|
292
297
|
and variables as a type, rewritten only when they change. **Git-ignore it**
|
|
@@ -402,7 +407,9 @@ the build.
|
|
|
402
407
|
**List the plugin that brings a template's components.** A tag that
|
|
403
408
|
resolves to no component renders nothing, and the build fails with
|
|
404
409
|
`i18n: fr/welcome.html is empty — a tag of its template resolved to no
|
|
405
|
-
component; list the plugin that brings it, as ui()`.
|
|
410
|
+
component; list the plugin that brings it, as ui()`. With `ui()` listed, a
|
|
411
|
+
tag that resolves to no component fails the build first, nested or not:
|
|
412
|
+
`ui: <NxButon> in emails/welcome.vue is no component — …`.
|
|
406
413
|
|
|
407
414
|
**Leave the output paths to the plugin.** An `output.path` set in a
|
|
408
415
|
template, or a `plaintext.destination`, moves a file out of the plugin's
|
package/dist/index.d.ts
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
*/
|
|
18
18
|
import './vue';
|
|
19
19
|
export type { ArgumentKind, Catalogue, Catalogues, } from './catalogues';
|
|
20
|
-
export { emailKey, type Manifest, type ManifestEmail, } from './manifest';
|
|
20
|
+
export { emailKey, MANIFEST_FORMAT, type Manifest, type ManifestEmail, } from './manifest';
|
|
21
21
|
export { type I18nOptions, i18n, MANIFEST_FILE, WRAPPERS_DIR, } from './plugin';
|
|
22
22
|
export type { TemplateSource } from './sources';
|
|
23
23
|
export { createTranslator, type LanguageProvider, type MessageArgs, type Translate, } from './translator';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,OAAO,CAAC;AAEf,YAAY,EACX,YAAY,EACZ,SAAS,EACT,UAAU,GACV,MAAM,cAAc,CAAC;AACtB,OAAO,EACN,QAAQ,EACR,KAAK,QAAQ,EACb,KAAK,aAAa,GAClB,MAAM,YAAY,CAAC;AACpB,OAAO,EACN,KAAK,WAAW,EAChB,IAAI,EACJ,aAAa,EACb,YAAY,GACZ,MAAM,UAAU,CAAC;AAClB,YAAY,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,EACN,gBAAgB,EAChB,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAChB,KAAK,SAAS,GACd,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,OAAO,CAAC;AACzE,YAAY,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,OAAO,CAAC;AAEf,YAAY,EACX,YAAY,EACZ,SAAS,EACT,UAAU,GACV,MAAM,cAAc,CAAC;AACtB,OAAO,EACN,QAAQ,EACR,eAAe,EACf,KAAK,QAAQ,EACb,KAAK,aAAa,GAClB,MAAM,YAAY,CAAC;AACpB,OAAO,EACN,KAAK,WAAW,EAChB,IAAI,EACJ,aAAa,EACb,YAAY,GACZ,MAAM,UAAU,CAAC;AAClB,YAAY,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,EACN,gBAAgB,EAChB,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAChB,KAAK,SAAS,GACd,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,OAAO,CAAC;AACzE,YAAY,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -186,6 +186,7 @@ function watchTemplates(emailsDir, regenerate) {
|
|
|
186
186
|
}
|
|
187
187
|
|
|
188
188
|
// src/manifest.ts
|
|
189
|
+
var MANIFEST_FORMAT = 1;
|
|
189
190
|
var PLACEHOLDER = /\{\{\s*([a-z][a-zA-Z0-9]*)\s*\}\}/g;
|
|
190
191
|
var URL_ATTRIBUTE = /\s(?:href|src|background|poster|action)\s*=\s*(?:"\s*(\{\{[^"]*)"|'\s*(\{\{[^']*)')/gi;
|
|
191
192
|
var placeholderMark = (name) => `{{ ${name} }}`;
|
|
@@ -267,6 +268,7 @@ function buildManifest(options) {
|
|
|
267
268
|
};
|
|
268
269
|
}
|
|
269
270
|
return {
|
|
271
|
+
formatVersion: MANIFEST_FORMAT,
|
|
270
272
|
locales: [...locales],
|
|
271
273
|
fallbackLocale: options.fallbackLocale,
|
|
272
274
|
emails
|
|
@@ -665,11 +667,12 @@ function i18n(options) {
|
|
|
665
667
|
}
|
|
666
668
|
export {
|
|
667
669
|
MANIFEST_FILE,
|
|
670
|
+
MANIFEST_FORMAT,
|
|
668
671
|
WRAPPERS_DIR,
|
|
669
672
|
createTranslator,
|
|
670
673
|
emailKey,
|
|
671
674
|
i18n
|
|
672
675
|
};
|
|
673
676
|
|
|
674
|
-
//# debugId=
|
|
677
|
+
//# debugId=3C814EA0EFDDBF5664756E2164756E21
|
|
675
678
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/manifest.ts", "../src/translator.ts", "../src/wrappers.ts", "../src/plugin.ts", "../src/catalogues.ts", "../src/sources.ts", "../src/template.ts", "../src/types.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import { readFileSync } from 'node:fs';\nimport { isAbsolute, join, relative, sep } from 'node:path';\nimport type { Messages } from './catalogues';\nimport { createFormatter } from './translator';\nimport { type Entry, entryPath, type Layout, parseEntry } from './wrappers';\n\n/** One e-mail, as the renderer reads it. */\nexport interface ManifestEmail {\n\t/** Every placeholder of the e-mail, in any locale, sorted. */\n\treadonly variables: readonly string[];\n\t/**\n\t * The placeholders a URL attribute starts with — `href`, `src`,\n\t * `background`, `poster`, `action`: they decide the scheme, so a URL fills\n\t * them. One later in the value, as `?token={{ token }}`, is not one.\n\t */\n\treadonly urlVariables: readonly string[];\n\t/** The subject per locale, its placeholders kept as `{{ name }}`. */\n\treadonly subject: Readonly<Record<string, string>>;\n\t/** The built files per locale, relative to the output folder. */\n\treadonly files: Readonly<\n\t\tRecord<string, { readonly html: string; readonly text: string | null }>\n\t>;\n}\n\n/** `dist/mail-manifest.json`: what the build wrote, for the renderer. */\nexport interface Manifest {\n\treadonly locales: readonly string[];\n\treadonly fallbackLocale: string;\n\treadonly emails: Readonly<Record<string, ManifestEmail>>;\n}\n\n// Copied in packages/mail/src/renderer.ts, which reads this manifest: change both.\nconst PLACEHOLDER = /\\{\\{\\s*([a-z][a-zA-Z0-9]*)\\s*\\}\\}/g;\n/** An attribute that holds a URL, its value starting with a placeholder: that placeholder is the whole scheme. */\nconst URL_ATTRIBUTE =\n\t/\\s(?:href|src|background|poster|action)\\s*=\\s*(?:\"\\s*(\\{\\{[^\"]*)\"|'\\s*(\\{\\{[^']*)')/gi;\n\n/** `{{ name }}` — what `placeholder('name')` writes. */\nexport const placeholderMark = (name: string) => `{{ ${name} }}`;\n\nconst placeholdersIn = (text: string) =>\n\t[...text.matchAll(PLACEHOLDER)].map((match) => match[1] as string);\n\n/** `auth/reset-password` → `auth.resetPassword`: where its messages live. */\nexport const emailKey = (email: string) =>\n\temail\n\t\t.split('/')\n\t\t.map((segment) =>\n\t\t\tsegment.replace(/-([a-z0-9])/g, (_, char: string) => char.toUpperCase()),\n\t\t)\n\t\t.join('.');\n\n/**\n * The subject of `email` in `locale`: the message `<emailKey>.subject`, each\n * argument a placeholder. A missing subject, or one with an argument that is\n * not a string, **throws**.\n */\nfunction subjectOf(\n\temail: string,\n\tlocale: string,\n\tmessages: Messages,\n\tformat: ReturnType<typeof createFormatter>,\n): string {\n\tconst key = `${emailKey(email)}.subject`;\n\tconst message = messages.get(key);\n\tif (message === undefined) {\n\t\tthrow new Error(\n\t\t\t`i18n: ${email} has no subject — add ${key} to the catalogues`,\n\t\t);\n\t}\n\tconst args: Record<string, string> = {};\n\tfor (const [name, kind] of message.args) {\n\t\tif (message.selects.has(name)) {\n\t\t\tthrow new Error(\n\t\t\t\t`i18n: ${locale}: ${key} chooses on {${name}} with a select — a subject's arguments are placeholders, which always choose other`,\n\t\t\t);\n\t\t}\n\t\tif (kind !== 'string') {\n\t\t\tthrow new Error(\n\t\t\t\t`i18n: ${locale}: ${key} uses {${name}} as a ${kind} — a subject's arguments are placeholders, filled at send time as strings`,\n\t\t\t);\n\t\t}\n\t\targs[name] = placeholderMark(name);\n\t}\n\treturn format(locale, key, message.text, args);\n}\n\n/** One e-mail in one locale, as found in the build's files. */\ninterface Built {\n\treadonly entry: Entry;\n\thtml: string | null;\n\ttext: string | null;\n}\n\nconst sorted = (values: Iterable<string>) => [...new Set(values)].sort();\n\n/**\n * Reads what the build wrote — `files`, absolute, under `outputDir` — and\n * answers the manifest: for each e-mail its placeholders, those in a URL, its\n * subject per locale and its files.\n */\nexport function buildManifest(options: {\n\treadonly files: readonly string[];\n\treadonly outputDir: string;\n\treadonly htmlExtension: string;\n\treadonly layout: Layout;\n\treadonly locales: readonly string[];\n\treadonly fallbackLocale: string;\n\treadonly messages: ReadonlyMap<string, Messages>;\n}): Manifest {\n\tconst { layout, locales } = options;\n\tconst format = createFormatter('i18n');\n\tconst found = new Map<string, Built>();\n\tfor (const file of options.files) {\n\t\tconst path = relative(options.outputDir, file).split(sep).join('/');\n\t\tif (path.startsWith('../') || isAbsolute(path)) {\n\t\t\tthrow new Error(\n\t\t\t\t`i18n: ${path} was written outside the output folder — the i18n plugin lays out every e-mail; set no plaintext.destination and no output path in a template`,\n\t\t\t);\n\t\t}\n\t\tconst dot = path.lastIndexOf('.');\n\t\tconst base = path.slice(0, Math.max(dot, 0));\n\t\tconst entry = dot > 0 ? parseEntry(base, layout, locales) : null;\n\t\tif (entry === null) {\n\t\t\tthrow new Error(\n\t\t\t\t`i18n: ${path} is not where the i18n plugin puts an e-mail — set no output path in a template`,\n\t\t\t);\n\t\t}\n\t\tconst seen = found.get(base) ?? { entry, html: null, text: null };\n\t\tif (path.slice(dot + 1) === options.htmlExtension) seen.html = path;\n\t\telse seen.text = path;\n\t\tfound.set(base, seen);\n\t}\n\n\tconst emails: Record<string, ManifestEmail> = {};\n\tfor (const email of sorted(\n\t\t[...found.values()].map((seen) => seen.entry.email),\n\t)) {\n\t\tconst variables: string[] = [];\n\t\tconst urlVariables: string[] = [];\n\t\tconst subject: Record<string, string> = {};\n\t\tconst files: Record<string, { html: string; text: string | null }> = {};\n\t\tfor (const locale of locales) {\n\t\t\tconst seen = found.get(entryPath({ email, locale }, layout));\n\t\t\tif (seen?.html == null) {\n\t\t\t\tthrow new Error(`i18n: ${email} was not built in ${locale}`);\n\t\t\t}\n\t\t\tconst html = readFileSync(join(options.outputDir, seen.html), 'utf8');\n\t\t\t// Vue renders an unresolved component as nothing, and Maizzle still\n\t\t\t// writes the doctype: the build would pass with an empty e-mail.\n\t\t\tif (html.replace(/<!doctype[^>]*>/i, '').trim() === '') {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`i18n: ${seen.html} is empty — a tag of its template resolved to no component; list the plugin that brings it, as ui()`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tvariables.push(...placeholdersIn(html));\n\t\t\tfor (const match of html.matchAll(URL_ATTRIBUTE)) {\n\t\t\t\turlVariables.push(\n\t\t\t\t\t...placeholdersIn(match[1] ?? match[2] ?? '').slice(0, 1),\n\t\t\t\t);\n\t\t\t}\n\t\t\t// A <Plaintext> block is in the text part only.\n\t\t\tif (seen.text !== null) {\n\t\t\t\tconst text = readFileSync(join(options.outputDir, seen.text), 'utf8');\n\t\t\t\tvariables.push(...placeholdersIn(text));\n\t\t\t}\n\t\t\tsubject[locale] = subjectOf(\n\t\t\t\temail,\n\t\t\t\tlocale,\n\t\t\t\toptions.messages.get(locale) as Messages,\n\t\t\t\tformat,\n\t\t\t);\n\t\t\tvariables.push(...placeholdersIn(subject[locale]));\n\t\t\tfiles[locale] = { html: seen.html, text: seen.text };\n\t\t}\n\t\temails[email] = {\n\t\t\tvariables: sorted(variables),\n\t\t\turlVariables: sorted(urlVariables),\n\t\t\tsubject,\n\t\t\tfiles,\n\t\t};\n\t}\n\treturn {\n\t\tlocales: [...locales],\n\t\tfallbackLocale: options.fallbackLocale,\n\t\temails,\n\t};\n}\n",
|
|
5
|
+
"import { readFileSync } from 'node:fs';\nimport { isAbsolute, join, relative, sep } from 'node:path';\nimport type { Messages } from './catalogues';\nimport { createFormatter } from './translator';\nimport { type Entry, entryPath, type Layout, parseEntry } from './wrappers';\n\n/** One e-mail, as the renderer reads it. */\nexport interface ManifestEmail {\n\t/** Every placeholder of the e-mail, in any locale, sorted. */\n\treadonly variables: readonly string[];\n\t/**\n\t * The placeholders a URL attribute starts with — `href`, `src`,\n\t * `background`, `poster`, `action`: they decide the scheme, so a URL fills\n\t * them. One later in the value, as `?token={{ token }}`, is not one.\n\t */\n\treadonly urlVariables: readonly string[];\n\t/** The subject per locale, its placeholders kept as `{{ name }}`. */\n\treadonly subject: Readonly<Record<string, string>>;\n\t/** The built files per locale, relative to the output folder. */\n\treadonly files: Readonly<\n\t\tRecord<string, { readonly html: string; readonly text: string | null }>\n\t>;\n}\n\n/**\n * The manifest's format. It changes only with the manifest's shape, and\n * `@nxgt/mail`'s renderer reads every format up to its own within 0.x: a\n * build from an older `@nxgt/mail-i18n` keeps working with a newer renderer.\n * Copied in packages/mail/src/renderer.ts: change both.\n */\nexport const MANIFEST_FORMAT = 1;\n\n/** `dist/mail-manifest.json`: what the build wrote, for the renderer. */\nexport interface Manifest {\n\t/**\n\t * {@link MANIFEST_FORMAT} when built, and the first key written. This type\n\t * is what this version writes: a manifest from `@nxgt/mail-i18n` 0.1 or\n\t * 0.2 has no such field, and the renderer reads it as format 1.\n\t */\n\treadonly formatVersion: number;\n\treadonly locales: readonly string[];\n\treadonly fallbackLocale: string;\n\treadonly emails: Readonly<Record<string, ManifestEmail>>;\n}\n\n// Copied in packages/mail/src/renderer.ts, which reads this manifest: change both.\nconst PLACEHOLDER = /\\{\\{\\s*([a-z][a-zA-Z0-9]*)\\s*\\}\\}/g;\n/** An attribute that holds a URL, its value starting with a placeholder: that placeholder is the whole scheme. */\nconst URL_ATTRIBUTE =\n\t/\\s(?:href|src|background|poster|action)\\s*=\\s*(?:\"\\s*(\\{\\{[^\"]*)\"|'\\s*(\\{\\{[^']*)')/gi;\n\n/** `{{ name }}` — what `placeholder('name')` writes. */\nexport const placeholderMark = (name: string) => `{{ ${name} }}`;\n\nconst placeholdersIn = (text: string) =>\n\t[...text.matchAll(PLACEHOLDER)].map((match) => match[1] as string);\n\n/** `auth/reset-password` → `auth.resetPassword`: where its messages live. */\nexport const emailKey = (email: string) =>\n\temail\n\t\t.split('/')\n\t\t.map((segment) =>\n\t\t\tsegment.replace(/-([a-z0-9])/g, (_, char: string) => char.toUpperCase()),\n\t\t)\n\t\t.join('.');\n\n/**\n * The subject of `email` in `locale`: the message `<emailKey>.subject`, each\n * argument a placeholder. A missing subject, or one with an argument that is\n * not a string, **throws**.\n */\nfunction subjectOf(\n\temail: string,\n\tlocale: string,\n\tmessages: Messages,\n\tformat: ReturnType<typeof createFormatter>,\n): string {\n\tconst key = `${emailKey(email)}.subject`;\n\tconst message = messages.get(key);\n\tif (message === undefined) {\n\t\tthrow new Error(\n\t\t\t`i18n: ${email} has no subject — add ${key} to the catalogues`,\n\t\t);\n\t}\n\tconst args: Record<string, string> = {};\n\tfor (const [name, kind] of message.args) {\n\t\tif (message.selects.has(name)) {\n\t\t\tthrow new Error(\n\t\t\t\t`i18n: ${locale}: ${key} chooses on {${name}} with a select — a subject's arguments are placeholders, which always choose other`,\n\t\t\t);\n\t\t}\n\t\tif (kind !== 'string') {\n\t\t\tthrow new Error(\n\t\t\t\t`i18n: ${locale}: ${key} uses {${name}} as a ${kind} — a subject's arguments are placeholders, filled at send time as strings`,\n\t\t\t);\n\t\t}\n\t\targs[name] = placeholderMark(name);\n\t}\n\treturn format(locale, key, message.text, args);\n}\n\n/** One e-mail in one locale, as found in the build's files. */\ninterface Built {\n\treadonly entry: Entry;\n\thtml: string | null;\n\ttext: string | null;\n}\n\nconst sorted = (values: Iterable<string>) => [...new Set(values)].sort();\n\n/**\n * Reads what the build wrote — `files`, absolute, under `outputDir` — and\n * answers the manifest: for each e-mail its placeholders, those in a URL, its\n * subject per locale and its files.\n */\nexport function buildManifest(options: {\n\treadonly files: readonly string[];\n\treadonly outputDir: string;\n\treadonly htmlExtension: string;\n\treadonly layout: Layout;\n\treadonly locales: readonly string[];\n\treadonly fallbackLocale: string;\n\treadonly messages: ReadonlyMap<string, Messages>;\n}): Manifest {\n\tconst { layout, locales } = options;\n\tconst format = createFormatter('i18n');\n\tconst found = new Map<string, Built>();\n\tfor (const file of options.files) {\n\t\tconst path = relative(options.outputDir, file).split(sep).join('/');\n\t\tif (path.startsWith('../') || isAbsolute(path)) {\n\t\t\tthrow new Error(\n\t\t\t\t`i18n: ${path} was written outside the output folder — the i18n plugin lays out every e-mail; set no plaintext.destination and no output path in a template`,\n\t\t\t);\n\t\t}\n\t\tconst dot = path.lastIndexOf('.');\n\t\tconst base = path.slice(0, Math.max(dot, 0));\n\t\tconst entry = dot > 0 ? parseEntry(base, layout, locales) : null;\n\t\tif (entry === null) {\n\t\t\tthrow new Error(\n\t\t\t\t`i18n: ${path} is not where the i18n plugin puts an e-mail — set no output path in a template`,\n\t\t\t);\n\t\t}\n\t\tconst seen = found.get(base) ?? { entry, html: null, text: null };\n\t\tif (path.slice(dot + 1) === options.htmlExtension) seen.html = path;\n\t\telse seen.text = path;\n\t\tfound.set(base, seen);\n\t}\n\n\tconst emails: Record<string, ManifestEmail> = {};\n\tfor (const email of sorted(\n\t\t[...found.values()].map((seen) => seen.entry.email),\n\t)) {\n\t\tconst variables: string[] = [];\n\t\tconst urlVariables: string[] = [];\n\t\tconst subject: Record<string, string> = {};\n\t\tconst files: Record<string, { html: string; text: string | null }> = {};\n\t\tfor (const locale of locales) {\n\t\t\tconst seen = found.get(entryPath({ email, locale }, layout));\n\t\t\tif (seen?.html == null) {\n\t\t\t\tthrow new Error(`i18n: ${email} was not built in ${locale}`);\n\t\t\t}\n\t\t\tconst html = readFileSync(join(options.outputDir, seen.html), 'utf8');\n\t\t\t// Vue renders an unresolved component as nothing, and Maizzle still\n\t\t\t// writes the doctype: the build would pass with an empty e-mail.\n\t\t\tif (html.replace(/<!doctype[^>]*>/i, '').trim() === '') {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`i18n: ${seen.html} is empty — a tag of its template resolved to no component; list the plugin that brings it, as ui()`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tvariables.push(...placeholdersIn(html));\n\t\t\tfor (const match of html.matchAll(URL_ATTRIBUTE)) {\n\t\t\t\turlVariables.push(\n\t\t\t\t\t...placeholdersIn(match[1] ?? match[2] ?? '').slice(0, 1),\n\t\t\t\t);\n\t\t\t}\n\t\t\t// A <Plaintext> block is in the text part only.\n\t\t\tif (seen.text !== null) {\n\t\t\t\tconst text = readFileSync(join(options.outputDir, seen.text), 'utf8');\n\t\t\t\tvariables.push(...placeholdersIn(text));\n\t\t\t}\n\t\t\tsubject[locale] = subjectOf(\n\t\t\t\temail,\n\t\t\t\tlocale,\n\t\t\t\toptions.messages.get(locale) as Messages,\n\t\t\t\tformat,\n\t\t\t);\n\t\t\tvariables.push(...placeholdersIn(subject[locale]));\n\t\t\tfiles[locale] = { html: seen.html, text: seen.text };\n\t\t}\n\t\temails[email] = {\n\t\t\tvariables: sorted(variables),\n\t\t\turlVariables: sorted(urlVariables),\n\t\t\tsubject,\n\t\t\tfiles,\n\t\t};\n\t}\n\treturn {\n\t\tformatVersion: MANIFEST_FORMAT,\n\t\tlocales: [...locales],\n\t\tfallbackLocale: options.fallbackLocale,\n\t\temails,\n\t};\n}\n",
|
|
6
6
|
"import { IntlMessageFormat } from 'intl-messageformat';\nimport type { Catalogue, Catalogues } from './catalogues';\n\n/** The values a message's arguments take: `{ name: 'Ada', count: 3 }`. */\nexport type MessageArgs = Readonly<Record<string, string | number | Date>>;\n\n/** A locale, or a function that answers it at each call — as in `@nxgt/i18n`. */\nexport type LanguageProvider = string | (() => string);\n\n/** `t(key, args?, language?)`: the message `key`, formatted in the language. */\nexport type Translate = (\n\tkey: string,\n\targs?: MessageArgs,\n\tlanguage?: LanguageProvider,\n) => string;\n\nfunction lookup(catalogue: Catalogue, key: string): string | null {\n\tlet node: string | Catalogue | undefined = catalogue;\n\tfor (const segment of key.split('.')) {\n\t\tif (typeof node !== 'object' || !Object.hasOwn(node, segment)) return null;\n\t\tnode = node[segment];\n\t}\n\treturn typeof node === 'string' ? node : null;\n}\n\nconst resolveLanguage = (language: LanguageProvider): unknown =>\n\ttypeof language === 'function' ? language() : language;\n\n/**\n * Formats with a cache of compiled messages, one per locale and key. A\n * message that does not format **throws**, the formatter's error as the\n * cause.\n */\nexport function createFormatter(prefix: string) {\n\tconst compiled = new Map<string, IntlMessageFormat>();\n\treturn (locale: string, key: string, text: string, args?: MessageArgs) => {\n\t\tconst id = `${locale}\\u0000${key}`;\n\t\ttry {\n\t\t\tlet format = compiled.get(id);\n\t\t\tif (format === undefined) {\n\t\t\t\tformat = new IntlMessageFormat(text, locale, undefined, {\n\t\t\t\t\tignoreTag: true,\n\t\t\t\t});\n\t\t\t\tcompiled.set(id, format);\n\t\t\t}\n\t\t\treturn String(format.format(args));\n\t\t} catch (cause) {\n\t\t\tthrow new Error(`${prefix}: ${locale}: ${key} could not be formatted`, {\n\t\t\t\tcause,\n\t\t\t});\n\t\t}\n\t};\n}\n\n/**\n * The translator of `@nxgt/i18n`, for mail: `createTranslator(catalogues,\n * getLanguage)` answers `t(key, args?, language?)`.\n *\n * Where `@nxgt/i18n` answers the key, this **throws**: a key the language's\n * catalogue does not have, a language with no catalogue, and a message that\n * does not format. An e-mail is not sent with a key in it.\n *\n * ```ts\n * import en from './locales/en.json';\n * import fr from './locales/fr.json';\n *\n * const t = createTranslator({ en, fr }, () => pickLocale(user.locale, ['en', 'fr'], 'en'));\n * t('verifyEmail.subject');\n * ```\n */\nexport function createTranslator(\n\tcatalogues: Catalogues,\n\tgetLanguage: LanguageProvider,\n): Translate {\n\tif (typeof catalogues !== 'object' || catalogues === null) {\n\t\tthrow new TypeError(\n\t\t\t'createTranslator: catalogues must be an object of catalogues by locale, as { en, fr }',\n\t\t);\n\t}\n\tif (typeof getLanguage !== 'string' && typeof getLanguage !== 'function') {\n\t\tthrow new TypeError(\n\t\t\t'createTranslator: getLanguage must be a locale or a function that answers one',\n\t\t);\n\t}\n\tconst format = createFormatter('t');\n\treturn (key, args, language = getLanguage) => {\n\t\tconst locale = resolveLanguage(language);\n\t\tif (typeof locale !== 'string' || !Object.hasOwn(catalogues, locale)) {\n\t\t\tthrow new Error(\n\t\t\t\t't: the language is not a locale of the catalogues — pick one with pickLocale',\n\t\t\t);\n\t\t}\n\t\tconst text = lookup(catalogues[locale] as Catalogue, key);\n\t\tif (text === null) throw new Error(`t: ${locale}: ${key} is not a key`);\n\t\treturn format(locale, key, text, args);\n\t};\n}\n",
|
|
7
7
|
"import {\n\texistsSync,\n\tmkdirSync,\n\treaddirSync,\n\treadFileSync,\n\trmSync,\n\twriteFileSync,\n} from 'node:fs';\nimport { dirname, join, relative, sep } from 'node:path';\n\n/**\n * Where each locale's output goes: `nested` writes `en/verify-email.html`,\n * `flat` writes `verify-email.en.html`.\n */\nexport type Layout = 'nested' | 'flat';\n\n/** One e-mail in one locale: `{ email: 'auth/reset-password', locale: 'fr' }`. */\nexport interface Entry {\n\treadonly email: string;\n\treadonly locale: string;\n}\n\nconst NAME = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;\n\nconst posix = (path: string) => path.split(sep).join('/');\n\n/** Every `.vue` file under `dir`, as a slash-separated path without `.vue`. */\nfunction listEmails(dir: string, label: string): string[] {\n\tif (!existsSync(dir)) return [];\n\treturn readdirSync(dir, { recursive: true, encoding: 'utf8' })\n\t\t.filter((file) => file.endsWith('.vue'))\n\t\t.map((file) => {\n\t\t\tconst email = posix(file).slice(0, -'.vue'.length);\n\t\t\tfor (const segment of email.split('/')) {\n\t\t\t\tif (!NAME.test(segment)) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`i18n: ${label}/${email}.vue is not a kebab-case name — name a template as verify-email.vue`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn email;\n\t\t})\n\t\t.sort();\n}\n\n/** The path of `entry`'s file under a folder laid out as `layout`, without an extension. */\nexport function entryPath(entry: Entry, layout: Layout): string {\n\treturn layout === 'nested'\n\t\t? `${entry.locale}/${entry.email}`\n\t\t: `${entry.email}.${entry.locale}`;\n}\n\n/**\n * Reads back what {@link entryPath} wrote — `path` relative to its folder,\n * slash-separated, without an extension — or `null` for a path that is not\n * one e-mail in one of `locales`.\n */\nexport function parseEntry(\n\tpath: string,\n\tlayout: Layout,\n\tlocales: readonly string[],\n): Entry | null {\n\tif (layout === 'nested') {\n\t\tconst [locale, ...rest] = path.split('/');\n\t\tif (locale === undefined || rest.length === 0) return null;\n\t\treturn locales.includes(locale) ? { email: rest.join('/'), locale } : null;\n\t}\n\tconst dot = path.lastIndexOf('.');\n\tconst locale = path.slice(dot + 1);\n\treturn dot > 0 && locales.includes(locale)\n\t\t? { email: path.slice(0, dot), locale }\n\t\t: null;\n}\n\nfunction wrapperSource(wrapper: string, template: string): string {\n\tconst from = posix(relative(dirname(wrapper), template));\n\treturn [\n\t\t'<!-- Generated by @nxgt/mail-i18n: one per template and locale. Never edited, never committed. -->',\n\t\t'<script setup>',\n\t\t`import Email from '${from.startsWith('.') ? from : `./${from}`}';`,\n\t\t'</script>',\n\t\t'<template><Email /></template>',\n\t\t'',\n\t].join('\\n');\n}\n\n/** Every file under `dir`, absolute. */\nfunction listFiles(dir: string): string[] {\n\tif (!existsSync(dir)) return [];\n\treturn readdirSync(dir, { recursive: true, encoding: 'utf8' })\n\t\t.map((file) => join(dir, file))\n\t\t.filter((file) => file.endsWith('.vue'));\n}\n\n/**\n * A folder of templates. `label` names it in an error: `emails`, or\n * `templates[0]` for a package's. `only`, when given, keeps those e-mails of\n * the folder and no other. A `packaged` folder — a package's — must hold\n * templates, and shares no name with another package's.\n */\nexport interface TemplateFolder {\n\treadonly dir: string;\n\treadonly label: string;\n\treadonly only?: readonly string[];\n\treadonly packaged?: boolean;\n}\n\n/** The e-mails of `folder`, the ones it keeps, checked. */\nfunction folderEmails({\n\tdir,\n\tlabel,\n\tonly,\n\tpackaged,\n}: TemplateFolder): string[] {\n\tconst emails = listEmails(dir, label);\n\tif (packaged && emails.length === 0) {\n\t\tthrow new Error(\n\t\t\t`i18n: ${label} holds no template — is ${dir} the folder of a package's e-mails?`,\n\t\t);\n\t}\n\tfor (const email of only ?? []) {\n\t\tif (!emails.includes(email)) {\n\t\t\tthrow new Error(\n\t\t\t\t`i18n: ${label} has no template ${email}.vue — name one of its e-mails`,\n\t\t\t);\n\t\t}\n\t}\n\treturn [...(only ?? emails)];\n}\n\n/**\n * Each e-mail of `folders` and its file. The project's folder, first, wins\n * over a package's; two packages with the same e-mail **throw**, since\n * neither would be the obvious one.\n */\nfunction collectTemplates(\n\tfolders: readonly TemplateFolder[],\n): Map<string, string> {\n\tconst templates = new Map<string, string>();\n\tconst owners = new Map<string, TemplateFolder>();\n\tfor (const folder of folders) {\n\t\tfor (const email of folderEmails(folder)) {\n\t\t\tconst owner = owners.get(email);\n\t\t\tif (owner === undefined) {\n\t\t\t\towners.set(email, folder);\n\t\t\t\ttemplates.set(email, join(folder.dir, `${email}.vue`));\n\t\t\t} else if (owner.packaged) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`i18n: ${owner.label} and ${folder.label} both have ${email}.vue — keep one with emails: [...], or write the project's own in its folder`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\treturn templates;\n}\n\n/**\n * Writes one wrapper per template of `folders` and locale under\n * `wrappersDir` — the project's folder first, so its template replaces a\n * package's of the same name — each only when its text changed, and removes\n * the wrappers of templates that are gone, so a running dev server sees a\n * change only where there is one. Answers the e-mails, sorted.\n */\nexport function writeWrappers(options: {\n\treadonly folders: readonly TemplateFolder[];\n\treadonly wrappersDir: string;\n\treadonly locales: readonly string[];\n\treadonly layout: Layout;\n}): string[] {\n\tconst { wrappersDir, locales, layout } = options;\n\tconst templates = collectTemplates(options.folders);\n\tconst wanted = new Set<string>();\n\tfor (const [email, template] of templates) {\n\t\tfor (const locale of locales) {\n\t\t\tconst wrapper = join(\n\t\t\t\twrappersDir,\n\t\t\t\t`${entryPath({ email, locale }, layout)}.vue`,\n\t\t\t);\n\t\t\twanted.add(wrapper);\n\t\t\tconst source = wrapperSource(wrapper, template);\n\t\t\tif (existsSync(wrapper) && readFileSync(wrapper, 'utf8') === source) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tmkdirSync(dirname(wrapper), { recursive: true });\n\t\t\twriteFileSync(wrapper, source);\n\t\t}\n\t}\n\tfor (const file of listFiles(wrappersDir)) {\n\t\tif (!wanted.has(file)) rmSync(file);\n\t}\n\treturn [...templates.keys()].sort();\n}\n\n/** The part of Vite's dev server the watcher uses. */\ninterface WatchedServer {\n\treadonly watcher: {\n\t\tadd(path: string): void;\n\t\ton(event: 'add' | 'unlink', listener: (file: string) => void): void;\n\t};\n}\n\n/**\n * A Vite plugin for Maizzle's renderer: under `maizzle serve`, a template\n * added to or removed from `emailsDir` gets its wrappers at once, so the\n * preview lists it without a restart. A template the build would refuse is\n * reported, never thrown: an error in a watcher would stop the server.\n */\nexport function watchTemplates(emailsDir: string, regenerate: () => void) {\n\treturn {\n\t\tname: 'nxgt-mail-i18n:wrappers',\n\t\tconfigureServer(server: WatchedServer) {\n\t\t\tserver.watcher.add(emailsDir);\n\t\t\tconst onTemplate = (file: string) => {\n\t\t\t\tif (!file.startsWith(emailsDir + sep) || !file.endsWith('.vue')) return;\n\t\t\t\ttry {\n\t\t\t\t\tregenerate();\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconsole.error(error instanceof Error ? error.message : error);\n\t\t\t\t}\n\t\t\t};\n\t\t\tserver.watcher.on('add', onTemplate);\n\t\t\tserver.watcher.on('unlink', onTemplate);\n\t\t},\n\t};\n}\n",
|
|
8
8
|
"import { existsSync, readFileSync, writeFileSync } from 'node:fs';\nimport { join, relative, resolve, sep } from 'node:path';\nimport { isMainThread } from 'node:worker_threads';\nimport { defineMailPlugin, type MailPlugin } from '@nxgt/mail-config';\nimport {\n\ttype Catalogue,\n\ttype Catalogues,\n\tcheckCatalogues,\n\tlayerCatalogues,\n\ttype Messages,\n} from './catalogues';\nimport { buildManifest } from './manifest';\nimport {\n\tcheckTemplates,\n\ttype TemplateSource,\n\ttemplateFolders,\n} from './sources';\nimport { templateProperties } from './template';\nimport { createFormatter } from './translator';\nimport {\n\tRENDERER_TYPES_FILE,\n\trendererTypes,\n\tTYPES_FILE,\n\ttemplateTypes,\n\twriteIfChanged,\n\twriteRendererTypes,\n} from './types';\nimport {\n\ttype Layout,\n\tparseEntry,\n\twatchTemplates,\n\twriteWrappers,\n} from './wrappers';\n\nexport interface I18nOptions {\n\t/** Every locale the project writes, as BCP 47 tags: `['en', 'fr']`. */\n\treadonly locales: readonly string[];\n\t/** The reference every other locale is checked against. Default the first locale. */\n\treadonly fallbackLocale?: string;\n\t/** The folder of `<locale>.json` catalogues. Default `locales`. */\n\treadonly dir?: string;\n\t/** The folder of templates. Default `emails`. */\n\treadonly emails?: string;\n\t/** `nested` writes `dist/en/verify-email.html`; `flat` writes `dist/verify-email.en.html`. Default `nested`. */\n\treadonly layout?: Layout;\n\t/**\n\t * Catalogues under the project's own, as a package ships them —\n\t * `[uiCatalogues]` from `@nxgt/mail-ui`. Each is merged key by key under\n\t * the next, and the project's `<locale>.json` over all of them.\n\t */\n\treadonly catalogues?: readonly Catalogues[];\n\t/**\n\t * Folders of templates under the project's own, as a package ships them —\n\t * `presets().templates` from `@nxgt/mail-presets`. A template in the\n\t * project's `emails/` replaces a package's of the same name.\n\t */\n\treadonly templates?: readonly TemplateSource[];\n\t/**\n\t * The module typing the renderer, written after each build: `MailEmails`,\n\t * for `createMailRenderer<MailEmails>(…)` in the code that sends. A path\n\t * from where `maizzle` runs — outside the project too, as\n\t * `../api/src/generated/mail.ts` — or `false` to write none. Default\n\t * `generated/mail.ts`.\n\t */\n\treadonly rendererTypes?: string | false;\n}\n\n/** Where the wrappers go, under the project. */\nexport const WRAPPERS_DIR = '.maizzle/emails';\n\n/** The manifest's name, in the output folder. */\nexport const MANIFEST_FILE = 'mail-manifest.json';\n\nconst LOCALE = /^[a-z]{2,3}(-[A-Za-z0-9]{2,8})*$/;\n\nconst isObject = (value: unknown): value is Record<string, unknown> =>\n\ttypeof value === 'object' && value !== null && !Array.isArray(value);\n\nfunction checkOptions(options: I18nOptions): void {\n\tif (typeof options !== 'object' || options === null) {\n\t\tthrow new TypeError(\n\t\t\t\"i18n: options must be an object, as { locales: ['en', 'fr'] }\",\n\t\t);\n\t}\n\tconst { locales } = options;\n\tif (!Array.isArray(locales) || locales.length === 0) {\n\t\tthrow new TypeError(\n\t\t\t\"i18n: locales must hold at least one locale, as ['en', 'fr']\",\n\t\t);\n\t}\n\tfor (const locale of locales) {\n\t\tif (typeof locale !== 'string' || !LOCALE.test(locale)) {\n\t\t\tthrow new TypeError(\n\t\t\t\t'i18n: locales holds something that is not a locale — write each as a BCP 47 tag, as en or pt-BR',\n\t\t\t);\n\t\t}\n\t}\n\tif (new Set(locales).size !== locales.length) {\n\t\tthrow new TypeError('i18n: locales holds the same locale twice');\n\t}\n\tif (\n\t\toptions.fallbackLocale !== undefined &&\n\t\t!locales.includes(options.fallbackLocale)\n\t) {\n\t\tthrow new TypeError('i18n: fallbackLocale must be one of locales');\n\t}\n\tfor (const key of ['dir', 'emails'] as const) {\n\t\tconst value = options[key];\n\t\tif (value !== undefined && (typeof value !== 'string' || value === '')) {\n\t\t\tthrow new TypeError(`i18n: ${key} must be a folder of the project`);\n\t\t}\n\t}\n\tif (\n\t\toptions.layout !== undefined &&\n\t\toptions.layout !== 'nested' &&\n\t\toptions.layout !== 'flat'\n\t) {\n\t\tthrow new TypeError(\"i18n: layout must be 'nested' or 'flat'\");\n\t}\n\tconst { catalogues } = options;\n\tif (\n\t\tcatalogues !== undefined &&\n\t\t(!Array.isArray(catalogues) ||\n\t\t\t!catalogues.every(\n\t\t\t\t(source) => isObject(source) && Object.values(source).every(isObject),\n\t\t\t))\n\t) {\n\t\tthrow new TypeError(\n\t\t\t'i18n: catalogues must be a list of catalogues by locale, as [{ en: {...}, fr: {...} }]',\n\t\t);\n\t}\n\tconst typesPath = options.rendererTypes;\n\tif (\n\t\ttypesPath !== undefined &&\n\t\ttypesPath !== false &&\n\t\t(typeof typesPath !== 'string' || !typesPath.endsWith('.ts'))\n\t) {\n\t\tthrow new TypeError(\n\t\t\t'i18n: rendererTypes must be the path of a .ts file, as generated/mail.ts, or false',\n\t\t);\n\t}\n\tcheckTemplates(options.templates);\n}\n\n/** Reads `<dir>/<locale>.json` for each locale. A missing or broken file **throws**. */\nfunction readCatalogues(\n\tdir: string,\n\tdirName: string,\n\tlocales: readonly string[],\n): Record<string, Catalogue> {\n\tconst out: Record<string, Catalogue> = {};\n\tfor (const locale of locales) {\n\t\tconst file = join(dir, `${locale}.json`);\n\t\tconst name = `${dirName}/${locale}.json`;\n\t\tif (!existsSync(file)) {\n\t\t\tthrow new Error(\n\t\t\t\t`i18n: ${name} is missing — every locale has a catalogue`,\n\t\t\t);\n\t\t}\n\t\ttry {\n\t\t\tout[locale] = JSON.parse(readFileSync(file, 'utf8'));\n\t\t} catch {\n\t\t\tthrow new Error(`i18n: ${name} is not valid JSON`);\n\t\t}\n\t}\n\treturn out;\n}\n\n/**\n * The i18n plugin, for `defineMailConfig`:\n *\n * ```ts\n * defineMailConfig({ plugins: [i18n({ locales: ['en', 'fr'] })] });\n * ```\n *\n * It checks `locales/<locale>.json`, writes one wrapper per template and\n * locale under `.maizzle/emails/` so one build writes every locale, gives each\n * template `t`, `locale` and `placeholder`, and writes\n * `dist/mail-manifest.json`. A catalogue or a template that cannot be right\n * **fails the build**, naming the locale and the key.\n */\nexport function i18n(options: I18nOptions): MailPlugin {\n\tcheckOptions(options);\n\tconst { locales } = options;\n\tconst fallbackLocale = options.fallbackLocale ?? (locales[0] as string);\n\tconst layout = options.layout ?? 'nested';\n\tconst dirName = options.dir ?? 'locales';\n\tconst emailsName = options.emails ?? 'emails';\n\tconst cwd = process.cwd();\n\tconst emailsDir = resolve(cwd, emailsName);\n\tconst wrappersDir = resolve(cwd, WRAPPERS_DIR);\n\n\tconst messages = checkCatalogues(\n\t\tlayerCatalogues(\n\t\t\toptions.catalogues ?? [],\n\t\t\treadCatalogues(resolve(cwd, dirName), dirName, locales),\n\t\t),\n\t\tlocales,\n\t\tfallbackLocale,\n\t);\n\tconst reference = messages.get(fallbackLocale) as Messages;\n\tconst format = createFormatter('i18n');\n\tconst regenerate = () =>\n\t\twriteWrappers({\n\t\t\tfolders: templateFolders(\n\t\t\t\t{ dir: emailsDir, name: emailsName },\n\t\t\t\toptions.templates ?? [],\n\t\t\t),\n\t\t\twrappersDir,\n\t\t\tlocales,\n\t\t\tlayout,\n\t\t});\n\t// A parallel build loads the config again in each worker: only the main\n\t// thread writes, so two workers never write the same file.\n\tif (isMainThread) {\n\t\tregenerate();\n\t\twriteIfChanged(\n\t\t\tresolve(cwd, TYPES_FILE),\n\t\t\ttemplateTypes(reference, fallbackLocale),\n\t\t);\n\t}\n\n\treturn defineMailPlugin({\n\t\tname: 'i18n',\n\t\tcontent: [`${wrappersDir}/**/*.vue`],\n\t\t// `maizzle serve` watches locales/ already; another folder is added.\n\t\t...(dirName === 'locales' ? {} : { server: { watch: [`${dirName}/**`] } }),\n\t\tvite: { plugins: [watchTemplates(emailsDir, regenerate)] },\n\t\tbeforeRender({ config, template }) {\n\t\t\tconst path = relative(\n\t\t\t\twrappersDir,\n\t\t\t\tjoin(template.path.dir, template.path.name),\n\t\t\t)\n\t\t\t\t.split(sep)\n\t\t\t\t.join('/');\n\t\t\tconst entry = parseEntry(path, layout, locales);\n\t\t\tif (entry === null) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`i18n: ${relative(cwd, join(template.path.dir, template.path.base))} is not built through the i18n plugin — leave content to it, and put templates in ${emailsName}/`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconfig.vue ??= {};\n\t\t\tconfig.vue.globalProperties = {\n\t\t\t\t...config.vue.globalProperties,\n\t\t\t\t...templateProperties({\n\t\t\t\t\t...entry,\n\t\t\t\t\tmessages: messages.get(entry.locale) as Messages,\n\t\t\t\t\treference,\n\t\t\t\t\tformat,\n\t\t\t\t}),\n\t\t\t};\n\t\t},\n\t\tafterBuild({ files, config }) {\n\t\t\tconst outputDir = resolve(cwd, config.output?.path ?? 'dist');\n\t\t\tconst manifest = buildManifest({\n\t\t\t\tfiles,\n\t\t\t\toutputDir,\n\t\t\t\thtmlExtension: config.output?.extension ?? 'html',\n\t\t\t\tlayout,\n\t\t\t\tlocales,\n\t\t\t\tfallbackLocale,\n\t\t\t\tmessages,\n\t\t\t});\n\t\t\twriteFileSync(\n\t\t\t\tjoin(outputDir, MANIFEST_FILE),\n\t\t\t\t`${JSON.stringify(manifest, null, '\\t')}\\n`,\n\t\t\t);\n\t\t\tconst typesFile = options.rendererTypes ?? RENDERER_TYPES_FILE;\n\t\t\tif (typesFile !== false) {\n\t\t\t\twriteRendererTypes(\n\t\t\t\t\tresolve(cwd, typesFile),\n\t\t\t\t\ttypesFile,\n\t\t\t\t\trendererTypes(manifest),\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\t});\n}\n",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"import type { ArgumentKind, Messages } from './catalogues';\nimport { placeholderMark } from './manifest';\nimport type { createFormatter, MessageArgs } from './translator';\n\nconst NAME = /^[a-z][a-zA-Z0-9]*$/;\n\nconst KINDS: Record<ArgumentKind, (value: unknown) => boolean> = {\n\tstring: (value) => typeof value === 'string' || typeof value === 'number',\n\tnumber: (value) => typeof value === 'number',\n\tdate: (value) => value instanceof Date || typeof value === 'number',\n};\n\nconst isPlaceholder = (value: unknown) =>\n\ttypeof value === 'string' && /^\\{\\{ [a-z][a-zA-Z0-9]* \\}\\}$/.test(value);\n\nconst kindOf = (value: unknown) =>\n\tvalue === null ? 'null' : value instanceof Date ? 'date' : typeof value;\n\n/**\n * What one template gets in one locale: `t`, `locale` and `placeholder`.\n *\n * `t` is checked against the fallback locale's message, which declares every\n * argument: an unknown key, an argument left out, one the message does not\n * use, or one of the wrong kind **fails the build**, naming the locale, the\n * template and the key.\n */\nexport function templateProperties(options: {\n\treadonly email: string;\n\treadonly locale: string;\n\treadonly messages: Messages;\n\treadonly reference: Messages;\n\treadonly format: ReturnType<typeof createFormatter>;\n}) {\n\tconst { email, locale, messages, reference, format } = options;\n\tconst where = `i18n: ${locale}: ${email}`;\n\treturn {\n\t\tlocale,\n\t\tt(key: string, args: MessageArgs = {}): string {\n\t\t\tconst message = typeof key === 'string' ? messages.get(key) : undefined;\n\t\t\tconst declared = typeof key === 'string' ? reference.get(key) : undefined;\n\t\t\tif (message === undefined || declared === undefined) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`${where} calls t('${String(key)}'), which is not a key of the catalogues`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (typeof args !== 'object' || args === null) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`${where} calls t('${key}') with arguments that are not an object, as { name: placeholder('name') }`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tfor (const [name, kind] of declared.args) {\n\t\t\t\tif (!Object.hasOwn(args, name)) {\n\t\t\t\t\tthrow new Error(`${where} calls t('${key}') without {${name}}`);\n\t\t\t\t}\n\t\t\t\tif (declared.selects.has(name) && isPlaceholder(args[name])) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`${where} passes a placeholder to {${name}}, which ${key} chooses on with a select — a placeholder always chooses other`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (!KINDS[kind](args[name])) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`${where} passes {${name}} to ${key} as a ${kindOf(args[name])} — the message uses it as a ${kind}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (const name of Object.keys(args)) {\n\t\t\t\tif (!declared.args.has(name)) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`${where} passes {${name}} to ${key}, which does not use it`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn format(locale, key, message.text, args);\n\t\t},\n\t\tplaceholder(name: string): string {\n\t\t\tif (typeof name !== 'string' || !NAME.test(name)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`${where} calls placeholder() with a name that is not camelCase — as placeholder('firstName')`,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn placeholderMark(name);\n\t\t},\n\t};\n}\n",
|
|
12
12
|
"import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport type { ArgumentKind, Messages } from './catalogues';\nimport type { Manifest } from './manifest';\n\n/** Where the template types go, under the project: `.maizzle/*.d.ts` is in the starter's `tsconfig.json`. */\nexport const TYPES_FILE = '.maizzle/nxgt-mail-i18n.d.ts';\n\n/** What `t` accepts for each kind — as the build checks it. */\nconst TYPE_OF: Readonly<Record<ArgumentKind, string>> = {\n\tstring: 'string | number',\n\tnumber: 'number',\n\tdate: 'Date | number',\n};\n\n/**\n * The declaration file that types `t` in the templates: each key of the\n * `reference` catalogue, with its arguments, so an editor completes a key and\n * flags an unknown one or a missing argument. Keys and names are checked\n * before this runs, so they are safe to write quoted.\n */\nexport function templateTypes(\n\treference: Messages,\n\tfallbackLocale: string,\n): string {\n\tconst entries = [...reference.entries()]\n\t\t.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))\n\t\t.map(([key, message]) => {\n\t\t\tconst args = [...message.args.entries()]\n\t\t\t\t.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))\n\t\t\t\t.map(([name, kind]) => `${name}: ${TYPE_OF[kind]}`);\n\t\t\treturn `\\t\\t'${key}': { ${args.join('; ')}${args.length > 0 ? ' ' : ''}};`;\n\t\t});\n\treturn [\n\t\t`// Generated by @nxgt/mail-i18n from the ${fallbackLocale} catalogue, each time the config loads.`,\n\t\t'// Never edited, never committed: it types t() in the templates.',\n\t\t\"import type {} from '@nxgt/mail-i18n';\",\n\t\t'',\n\t\t\"declare module '@nxgt/mail-i18n' {\",\n\t\t'\\tinterface TemplateMessages {',\n\t\t...entries,\n\t\t'\\t}',\n\t\t'}',\n\t\t'',\n\t].join('\\n');\n}\n\n/** The first line of the renderer's types: a file without it is not the plugin's to replace. */\nconst RENDERER_TYPES_HEADER = '// Generated by @nxgt/mail-i18n from the build';\n\n/** Where the renderer's types go, under the project, by default. */\nexport const RENDERER_TYPES_FILE = 'generated/mail.ts';\n\n/**\n * The module that types the renderer: `MailEmails`, each e-mail of the build\n * with the variables it takes at send time, for\n * `createMailRenderer<MailEmails>(…)`. A URL variable takes a string; any\n * other a string or a number, as `render` writes it. `@nxgt/mail`'s\n * `RenderArguments` reads `Readonly<Record<string, never>>` as an e-mail\n * without variables, and its type specs copy this output: change them\n * together.\n */\nexport function rendererTypes(manifest: Manifest): string {\n\tconst entries = Object.entries(manifest.emails)\n\t\t.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))\n\t\t.map(([email, { variables, urlVariables }]) => {\n\t\t\tconst fields = variables.map(\n\t\t\t\t(name) =>\n\t\t\t\t\t`readonly ${name}: ${urlVariables.includes(name) ? 'string' : 'string | number'}`,\n\t\t\t);\n\t\t\tconst type =\n\t\t\t\tfields.length > 0\n\t\t\t\t\t? `{ ${fields.join('; ')} }`\n\t\t\t\t\t: 'Readonly<Record<string, never>>';\n\t\t\t// A name is a file's path, quoted as JSON: valid TypeScript whatever it holds.\n\t\t\treturn `\\t${JSON.stringify(email)}: ${type};`;\n\t\t});\n\treturn [\n\t\t`${RENDERER_TYPES_HEADER}, after each maizzle build.`,\n\t\t'// Never edited, never committed: git-ignore it, and build before type-checking.',\n\t\t'',\n\t\t'/** The e-mails of the build, each with the variables it takes when it is sent. */',\n\t\t'export interface MailEmails {',\n\t\t...entries,\n\t\t'}',\n\t\t'',\n\t].join('\\n');\n}\n\n/**\n * Writes the renderer's types to `file`, shown as `path` — unless `file` holds\n * something the plugin did not write: that **throws**, and the file is kept.\n */\nexport function writeRendererTypes(\n\tfile: string,\n\tpath: string,\n\tsource: string,\n): void {\n\tif (\n\t\texistsSync(file) &&\n\t\t!readFileSync(file, 'utf8').startsWith(RENDERER_TYPES_HEADER)\n\t) {\n\t\tthrow new Error(\n\t\t\t`i18n: ${path} was not written by i18n() — point rendererTypes at a file of its own`,\n\t\t);\n\t}\n\twriteIfChanged(file, source);\n}\n\n/** Writes `source` to `file` only when it changed, so an editor or a watcher sees a change only where there is one. */\nexport function writeIfChanged(file: string, source: string): void {\n\tif (existsSync(file) && readFileSync(file, 'utf8') === source) return;\n\tmkdirSync(dirname(file), { recursive: true });\n\twriteFileSync(file, source);\n}\n"
|
|
13
13
|
],
|
|
14
|
-
"mappings": "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",
|
|
15
|
-
"debugId": "
|
|
14
|
+
"mappings": "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",
|
|
15
|
+
"debugId": "3C814EA0EFDDBF5664756E2164756E21",
|
|
16
16
|
"names": []
|
|
17
17
|
}
|
package/dist/manifest.d.ts
CHANGED
|
@@ -18,8 +18,21 @@ export interface ManifestEmail {
|
|
|
18
18
|
readonly text: string | null;
|
|
19
19
|
}>>;
|
|
20
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* The manifest's format. It changes only with the manifest's shape, and
|
|
23
|
+
* `@nxgt/mail`'s renderer reads every format up to its own within 0.x: a
|
|
24
|
+
* build from an older `@nxgt/mail-i18n` keeps working with a newer renderer.
|
|
25
|
+
* Copied in packages/mail/src/renderer.ts: change both.
|
|
26
|
+
*/
|
|
27
|
+
export declare const MANIFEST_FORMAT = 1;
|
|
21
28
|
/** `dist/mail-manifest.json`: what the build wrote, for the renderer. */
|
|
22
29
|
export interface Manifest {
|
|
30
|
+
/**
|
|
31
|
+
* {@link MANIFEST_FORMAT} when built, and the first key written. This type
|
|
32
|
+
* is what this version writes: a manifest from `@nxgt/mail-i18n` 0.1 or
|
|
33
|
+
* 0.2 has no such field, and the renderer reads it as format 1.
|
|
34
|
+
*/
|
|
35
|
+
readonly formatVersion: number;
|
|
23
36
|
readonly locales: readonly string[];
|
|
24
37
|
readonly fallbackLocale: string;
|
|
25
38
|
readonly emails: Readonly<Record<string, ManifestEmail>>;
|
package/dist/manifest.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAE7C,OAAO,EAAyB,KAAK,MAAM,EAAc,MAAM,YAAY,CAAC;AAE5E,4CAA4C;AAC5C,MAAM,WAAW,aAAa;IAC7B,8DAA8D;IAC9D,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC;;;;OAIG;IACH,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,qEAAqE;IACrE,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACnD,iEAAiE;IACjE,QAAQ,CAAC,KAAK,EAAE,QAAQ,CACvB,MAAM,CAAC,MAAM,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC,CACvE,CAAC;CACF;AAED,yEAAyE;AACzE,MAAM,WAAW,QAAQ;IACxB,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC;CACzD;AAQD,wDAAwD;AACxD,eAAO,MAAM,eAAe,GAAI,MAAM,MAAM,WAAoB,CAAC;AAKjE,6EAA6E;AAC7E,eAAO,MAAM,QAAQ,GAAI,OAAO,MAAM,WAM1B,CAAC;AA8Cb;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE;IACtC,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;CACjD,GAAG,QAAQ,
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAE7C,OAAO,EAAyB,KAAK,MAAM,EAAc,MAAM,YAAY,CAAC;AAE5E,4CAA4C;AAC5C,MAAM,WAAW,aAAa;IAC7B,8DAA8D;IAC9D,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC;;;;OAIG;IACH,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,qEAAqE;IACrE,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACnD,iEAAiE;IACjE,QAAQ,CAAC,KAAK,EAAE,QAAQ,CACvB,MAAM,CAAC,MAAM,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC,CACvE,CAAC;CACF;AAED;;;;;GAKG;AACH,eAAO,MAAM,eAAe,IAAI,CAAC;AAEjC,yEAAyE;AACzE,MAAM,WAAW,QAAQ;IACxB;;;;OAIG;IACH,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC;CACzD;AAQD,wDAAwD;AACxD,eAAO,MAAM,eAAe,GAAI,MAAM,MAAM,WAAoB,CAAC;AAKjE,6EAA6E;AAC7E,eAAO,MAAM,QAAQ,GAAI,OAAO,MAAM,WAM1B,CAAC;AA8Cb;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE;IACtC,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;CACjD,GAAG,QAAQ,CA+EX"}
|
package/docs/README.md
CHANGED
|
@@ -10,7 +10,7 @@ in the
|
|
|
10
10
|
| --- | --- |
|
|
11
11
|
| [Catalogues](guide/catalogues.md) | You are writing `locales/<locale>.json`: nesting and `camelCase`, the kinds of argument, what each locale is checked for against the fallback locale, the subject key of each e-mail, catalogues a package ships (the `catalogues` option), and every build failure a catalogue causes |
|
|
12
12
|
| [Templates](guide/templates.md) | You are writing `emails/*.vue`: `t`, `locale` and `placeholder`, where a placeholder can go, templates a package ships (the `templates` option), what fails the build, the files the build writes, and `maizzle serve` and its watcher |
|
|
13
|
-
| [The manifest](guide/manifest.md) | You are reading `dist/mail-manifest.json`, the file the sending code uses: each field, how it is computed, and the flat layout; and `generated/mail.ts`, the `MailEmails` type that types `createMailRenderer`, with the `rendererTypes` option |
|
|
13
|
+
| [The manifest](guide/manifest.md) | You are reading `dist/mail-manifest.json`, the file the sending code uses: each field, how it is computed, and the flat layout; `formatVersion` and which `@nxgt/mail` reads it; shipping a build in a package; and `generated/mail.ts`, the `MailEmails` type that types `createMailRenderer`, with the `rendererTypes` option |
|
|
14
14
|
| [Editor and type checking](guide/editor.md) | You want the editor to complete `t('…')` and flag an unknown key or a wrong argument, and `vue-tsc` to check your templates in CI: the tsconfig, `maizzle prepare`, the generated `.maizzle/nxgt-mail-i18n.d.ts`, what each kind of argument accepts, and `TemplateMessages`, `TemplateKey`, `TemplateArgs` |
|
|
15
15
|
| [Translating outside templates](guide/translator.md) | You need a message in your application's code (a notification, a text message, a test) with `createTranslator`, and want to know how it differs from `@nxgt/i18n` |
|
|
16
16
|
| [Troubleshooting](troubleshooting.md) | You have an error message and want its cause and its fix |
|
package/docs/guide/manifest.md
CHANGED
|
@@ -39,6 +39,7 @@ against:
|
|
|
39
39
|
|
|
40
40
|
```json
|
|
41
41
|
{
|
|
42
|
+
"formatVersion": 1,
|
|
42
43
|
"locales": ["en", "fr"],
|
|
43
44
|
"fallbackLocale": "en",
|
|
44
45
|
"emails": {
|
|
@@ -85,7 +86,10 @@ against:
|
|
|
85
86
|
## The shape
|
|
86
87
|
|
|
87
88
|
```ts
|
|
89
|
+
const MANIFEST_FORMAT = 1;
|
|
90
|
+
|
|
88
91
|
interface Manifest {
|
|
92
|
+
readonly formatVersion: number;
|
|
89
93
|
readonly locales: readonly string[];
|
|
90
94
|
readonly fallbackLocale: string;
|
|
91
95
|
readonly emails: Readonly<Record<string, ManifestEmail>>;
|
|
@@ -101,6 +105,7 @@ interface ManifestEmail {
|
|
|
101
105
|
|
|
102
106
|
| Field | Holds |
|
|
103
107
|
| --- | --- |
|
|
108
|
+
| `formatVersion` | The manifest's format, `MANIFEST_FORMAT` of the `@nxgt/mail-i18n` that built it: `1`. Written first |
|
|
104
109
|
| `locales` | The plugin's `locales`, in the order given |
|
|
105
110
|
| `fallbackLocale` | The plugin's `fallbackLocale`, or the first locale |
|
|
106
111
|
| `emails` | One entry per e-mail, keyed by its template's path under `emails/` without `.vue` (`auth/reset-password`), sorted |
|
|
@@ -114,6 +119,30 @@ Each e-mail:
|
|
|
114
119
|
| `subject` | The subject per locale, formatted from `<emailKey>.subject`, each argument kept as `{{ name }}` |
|
|
115
120
|
| `files` | The built files per locale, relative to the output folder: `html`, and `text` or `null` when there is no plain-text part |
|
|
116
121
|
|
|
122
|
+
### `formatVersion`
|
|
123
|
+
|
|
124
|
+
The format of the manifest's shape, so the renderer knows what it reads:
|
|
125
|
+
|
|
126
|
+
```ts
|
|
127
|
+
import { MANIFEST_FORMAT } from '@nxgt/mail-i18n';
|
|
128
|
+
|
|
129
|
+
MANIFEST_FORMAT; // 1 — what this version writes as formatVersion
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
- **It changes only when the manifest's shape does.** A new
|
|
133
|
+
`@nxgt/mail-i18n` that writes the same fields writes the same format.
|
|
134
|
+
- **`@nxgt/mail`'s renderer reads every format up to its own**, its
|
|
135
|
+
`MANIFEST_FORMAT` from `@nxgt/mail/renderer`, within 0.x. A build from any
|
|
136
|
+
earlier `@nxgt/mail-i18n` 0.x keeps working with a newer `@nxgt/mail`; a
|
|
137
|
+
newer format fails at start-up with `… is manifest format 2, newer than this
|
|
138
|
+
@nxgt/mail reads (1) — upgrade @nxgt/mail`.
|
|
139
|
+
- **A manifest without it is format 1**, as `@nxgt/mail-i18n` 0.1 and 0.2
|
|
140
|
+
wrote it.
|
|
141
|
+
|
|
142
|
+
See
|
|
143
|
+
[Rendering — which builds it reads](https://github.com/softistx/nxgt-mail/blob/develop/packages/mail/docs/guide/rendering.md#which-builds-it-reads--manifest_format)
|
|
144
|
+
in `@nxgt/mail`.
|
|
145
|
+
|
|
117
146
|
### `variables`
|
|
118
147
|
|
|
119
148
|
Collected from the built files, not from the template's source: every
|
|
@@ -200,7 +229,7 @@ catalogues, not a condition to catch:
|
|
|
200
229
|
| `i18n: en: welcome.subject uses {count} as a number — a subject's arguments are placeholders, filled at send time as strings` | A subject with a `number`, `plural` or `date` argument |
|
|
201
230
|
| `i18n: en: welcome.subject chooses on {kind} with a select — a subject's arguments are placeholders, which always choose other` | A subject with a `select` argument |
|
|
202
231
|
| `i18n: welcome was not built in fr` | No HTML file (with `output.extension`) was written for that e-mail in that locale |
|
|
203
|
-
| `i18n: fr/welcome.html is empty — a tag of its template resolved to no component; list the plugin that brings it, as ui()` | The file holds nothing but its doctype: a tag of the template matched no component, which Vue renders as nothing. See [Templates from a package](templates.md#templates-from-a-package) |
|
|
232
|
+
| `i18n: fr/welcome.html is empty — a tag of its template resolved to no component; list the plugin that brings it, as ui()` | The file holds nothing but its doctype: a tag of the template matched no component, which Vue renders as nothing. With `ui()` listed, the build fails earlier on `ui: <Tag> in <file> is no component`. See [Templates from a package](templates.md#templates-from-a-package) |
|
|
204
233
|
| `i18n: ../text/welcome.en.txt was written outside the output folder — the i18n plugin lays out every e-mail; set no plaintext.destination and no output path in a template` | A `plaintext.destination`, or an output path set in a template, put a file outside `output.path` |
|
|
205
234
|
| `i18n: custom/welcome.html is not where the i18n plugin puts an e-mail — set no output path in a template` | A file in the output folder that is not `<locale>/<email>` (or `<email>.<locale>` with the flat layout), usually from an output path set in a template |
|
|
206
235
|
|
|
@@ -351,8 +380,66 @@ describe('the built e-mails', () => {
|
|
|
351
380
|
`acme-mails` stands for wherever your built project lives: a package of its
|
|
352
381
|
own, a folder of the repository, a build artefact.
|
|
353
382
|
|
|
383
|
+
## Shipping a build in a package
|
|
384
|
+
|
|
385
|
+
A package can publish its e-mails already built — `mails/`, with its manifest
|
|
386
|
+
— so the application that installs it only creates a renderer. The build
|
|
387
|
+
decides which `@nxgt/mail` can read it, so the package peers the range whose
|
|
388
|
+
renderers read its format, and checks it when it builds:
|
|
389
|
+
|
|
390
|
+
```json
|
|
391
|
+
{
|
|
392
|
+
"name": "acme-mails",
|
|
393
|
+
"files": ["mails"],
|
|
394
|
+
"scripts": {
|
|
395
|
+
"build": "maizzle build && bun run scripts/check-manifest-format.ts"
|
|
396
|
+
},
|
|
397
|
+
"peerDependencies": {
|
|
398
|
+
"@nxgt/mail": ">=0.1.0 <1"
|
|
399
|
+
},
|
|
400
|
+
"devDependencies": {
|
|
401
|
+
"@nxgt/mail": "0.5.1",
|
|
402
|
+
"@nxgt/mail-i18n": "^0.3.0"
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
`maizzle.config.ts` writes the build there, with Maizzle's `output.path`:
|
|
408
|
+
`defineMailConfig({ output: { path: 'mails' }, plugins: [i18n({ locales:
|
|
409
|
+
['en', 'fr'] })] })`. The check reads the format the build wrote, and compares
|
|
410
|
+
it with what the oldest `@nxgt/mail` you support reads:
|
|
411
|
+
|
|
412
|
+
```ts
|
|
413
|
+
// scripts/check-manifest-format.ts — after maizzle build, before publishing
|
|
414
|
+
import { readFileSync } from 'node:fs';
|
|
415
|
+
import { MANIFEST_FILE, MANIFEST_FORMAT, type Manifest } from '@nxgt/mail-i18n';
|
|
416
|
+
import { MANIFEST_FORMAT as READABLE } from '@nxgt/mail/renderer'; // the devDependency: the oldest @nxgt/mail supported
|
|
417
|
+
|
|
418
|
+
const manifest: Manifest = JSON.parse(readFileSync(`mails/${MANIFEST_FILE}`, 'utf8'));
|
|
419
|
+
|
|
420
|
+
if (manifest.formatVersion !== MANIFEST_FORMAT) {
|
|
421
|
+
throw new Error(`mails/ is manifest format ${manifest.formatVersion}, not ${MANIFEST_FORMAT} — run maizzle build again`);
|
|
422
|
+
}
|
|
423
|
+
if (manifest.formatVersion > READABLE) {
|
|
424
|
+
throw new Error(
|
|
425
|
+
`mails/ is manifest format ${manifest.formatVersion}; the oldest @nxgt/mail supported reads up to ${READABLE} — raise the @nxgt/mail peer and devDependency`,
|
|
426
|
+
);
|
|
427
|
+
}
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
- **The devDependency is the peer's lower bound**, so `MANIFEST_FORMAT` from
|
|
431
|
+
`@nxgt/mail/renderer` is what the oldest renderer an application may install
|
|
432
|
+
reads. `@nxgt/mail` 0.5.0 and earlier do not export it; they read format 1,
|
|
433
|
+
as 0.5.1 does, so a format-1 build pins 0.5.1 and still peers
|
|
434
|
+
`>=0.1.0 <1`.
|
|
435
|
+
- **When `@nxgt/mail-i18n` writes a new format**, the second check fails the
|
|
436
|
+
build: raise the peer's lower bound, and the devDependency with it, to the
|
|
437
|
+
first `@nxgt/mail` that reads it.
|
|
438
|
+
- **The first check** catches a `mails/` folder left from another build, made
|
|
439
|
+
before `@nxgt/mail-i18n` was upgraded.
|
|
440
|
+
|
|
354
441
|
## See also
|
|
355
442
|
|
|
356
|
-
- [Rendering](https://github.com/softistx/nxgt-mail/blob/develop/packages/mail/docs/guide/rendering.md) in `@nxgt/mail` — the renderer that reads the manifest at send time.
|
|
443
|
+
- [Rendering](https://github.com/softistx/nxgt-mail/blob/develop/packages/mail/docs/guide/rendering.md) in `@nxgt/mail` — the renderer that reads the manifest at send time, and the formats it reads.
|
|
357
444
|
- [Templates](templates.md) — where placeholders come from.
|
|
358
445
|
- [Catalogues](catalogues.md#the-subject) — the subject of each e-mail.
|
package/docs/guide/templates.md
CHANGED
|
@@ -266,7 +266,9 @@ which skips that folder. The plugin that ships the components resolves them —
|
|
|
266
266
|
`@nxgt/mail-ui`'s `ui()` does, for its `Nx*` components and Maizzle's
|
|
267
267
|
built-ins, so list it in `plugins`. A tag left unresolved renders nothing,
|
|
268
268
|
and the build fails on the empty e-mail (see
|
|
269
|
-
[What fails the build](#what-fails-the-build))
|
|
269
|
+
[What fails the build](#what-fails-the-build)); with `ui()` listed, one
|
|
270
|
+
nested anywhere fails it too, naming the tag and the file:
|
|
271
|
+
`ui: <NxButon> in emails/welcome.vue is no component — …`.
|
|
270
272
|
|
|
271
273
|
### Its errors
|
|
272
274
|
|
|
@@ -302,7 +304,7 @@ the template or the catalogues, to fix, not a condition to catch.
|
|
|
302
304
|
| `i18n: templates[0] has no template sign-in.vue — name one of its e-mails` | A [package's source](#templates-from-a-package) lists, in `emails`, a template its folder does not have; checked when the config loads |
|
|
303
305
|
| `i18n: templates[0] holds no template — is /…/emails the folder of a package's e-mails?` | A package's source whose `dir` is missing or has no template; checked when the config loads |
|
|
304
306
|
| `i18n: templates[0] and templates[1] both have welcome.vue — keep one with emails: [...], or write the project's own in its folder` | Two package sources ship the same e-mail; checked when the config loads |
|
|
305
|
-
| `i18n: fr/welcome.html is empty — a tag of its template resolved to no component; list the plugin that brings it, as ui()` | The e-mail rendered nothing but the doctype: a tag of its template, usually the layout, matched no component, and Vue renders an unknown component as nothing. Typically `ui()` is missing from `plugins`, or a package's template uses a component no plugin brings. Reported when the manifest is written |
|
|
307
|
+
| `i18n: fr/welcome.html is empty — a tag of its template resolved to no component; list the plugin that brings it, as ui()` | The e-mail rendered nothing but the doctype: a tag of its template, usually the layout, matched no component, and Vue renders an unknown component as nothing. Typically `ui()` is missing from `plugins`, or a package's template uses a component no plugin brings. Reported when the manifest is written; with `ui()` listed, the build fails earlier on `ui: <Tag> in <file> is no component` |
|
|
306
308
|
| `i18n: emails/Welcome.vue is not a kebab-case name — name a template as verify-email.vue` | A template whose path is not kebab-case, checked when the config loads. Under `maizzle serve`, one added while the server runs is printed with `console.error`, and the server keeps running |
|
|
307
309
|
| `i18n: welcome has no subject — add welcome.subject to the catalogues` | The e-mail has no subject message; reported when the manifest is written, at the end of the build. The other manifest failures, including an output path set in a template, are in [The manifest](manifest.md#where-it-is-written) |
|
|
308
310
|
| `i18n: emails/verify-email.vue is not built through the i18n plugin — leave content to it, and put templates in emails/` | Maizzle rendered a template directly: the project set its own `content` |
|
package/docs/roadmap.md
CHANGED
|
@@ -5,11 +5,7 @@ no dates here, and the version something shipped in is the only number.
|
|
|
5
5
|
|
|
6
6
|
## Now
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
template and locale move from `.maizzle/i18n/` to `.maizzle/emails/`, so
|
|
10
|
-
`maizzle serve` lists the e-mails under `.maizzle/emails/en` rather than a
|
|
11
|
-
folder named after the plugin. The build output does not move. Built, not
|
|
12
|
-
yet published.
|
|
8
|
+
Nothing between releases.
|
|
13
9
|
|
|
14
10
|
## Next
|
|
15
11
|
|
|
@@ -42,6 +38,15 @@ Nothing yet. A request is welcome as an
|
|
|
42
38
|
The last ten, newest first, each with the version it came in. Everything
|
|
43
39
|
before is in the [CHANGELOG](../CHANGELOG.md).
|
|
44
40
|
|
|
41
|
+
- **The manifest's format, versioned, v0.3.0** — `mail-manifest.json` starts
|
|
42
|
+
with `formatVersion`, `MANIFEST_FORMAT` is exported, and the format changes
|
|
43
|
+
only with the manifest's shape: any later `@nxgt/mail` 0.x reads the build.
|
|
44
|
+
The `@nxgt/mail-config` peer moves to `^0.2.0`.
|
|
45
|
+
- **The wrappers under `.maizzle/emails/`, v0.2.0** — the files generated per
|
|
46
|
+
template and locale move from `.maizzle/i18n/` to `.maizzle/emails/`, so
|
|
47
|
+
`maizzle serve` lists the e-mails under `.maizzle/emails/en` rather than a
|
|
48
|
+
folder named after the plugin; `WRAPPERS_DIR` follows. The build output
|
|
49
|
+
does not move. Delete the old `.maizzle/i18n/` after upgrading.
|
|
45
50
|
- **i18n as a plugin, v0.1.0** — `i18n({ locales, fallbackLocale })`, listed in
|
|
46
51
|
`defineMailConfig`'s `plugins`: one template per e-mail, its text keys into
|
|
47
52
|
`locales/<locale>.json` ICU catalogues, and one output per locale from a
|
|
@@ -81,15 +86,3 @@ before is in the [CHANGELOG](../CHANGELOG.md).
|
|
|
81
86
|
catalogues each time the config loads, so an editor completes `t('…')` and
|
|
82
87
|
flags an unknown key or a wrong argument, and `vue-tsc` checks templates in
|
|
83
88
|
CI.
|
|
84
|
-
- **The renderer typed by the build, v0.1.0** — after each `maizzle build`, the
|
|
85
|
-
plugin writes `generated/mail.ts`: `MailEmails`, each e-mail with the
|
|
86
|
-
variables it takes, a URL variable as a `string`. With it,
|
|
87
|
-
`createMailRenderer<MailEmails>` from `@nxgt/mail/renderer` refuses an
|
|
88
|
-
unknown e-mail, a missing or unknown variable, or a number for a URL at
|
|
89
|
-
compile time. Rewritten only when it changes;
|
|
90
|
-
`rendererTypes` moves it, or `false` turns it off.
|
|
91
|
-
- **A starter project, with v0.1.0** — the official Maizzle starter with
|
|
92
|
-
`defineMailConfig`, the i18n and the UI plugins wired in as the READMEs
|
|
93
|
-
say, built, rendered in `en` and `fr` and served in CI, so the snippets are
|
|
94
|
-
known to work: [`examples/starter`](https://github.com/softistx/nxgt-mail/tree/develop/examples/starter).
|
|
95
|
-
In the repository; its README says how to start your own from npm.
|
package/docs/troubleshooting.md
CHANGED
|
@@ -828,9 +828,12 @@ such warning for each tag that did not resolve.
|
|
|
828
828
|
|
|
829
829
|
**When:** `maizzle build`, after the templates, when a template's outermost
|
|
830
830
|
tag is a component that nothing resolves. Most often `ui()` is missing from
|
|
831
|
-
the plugins while a template uses `<NxLayout
|
|
832
|
-
|
|
833
|
-
the
|
|
831
|
+
the plugins while a template uses `<NxLayout>`, or a package's template,
|
|
832
|
+
under `node_modules`, uses a component that no plugin in the list resolves
|
|
833
|
+
for it. With `@nxgt/mail-ui`'s `ui()` listed, the build stops earlier, on
|
|
834
|
+
`ui: <NxLayout> in emails/welcome.vue is no component — check its name, or add
|
|
835
|
+
the plugin or the components folder that brings it`, for any tag nested or
|
|
836
|
+
not.
|
|
834
837
|
**Why:** Vue renders a component it cannot resolve as nothing, and Maizzle
|
|
835
838
|
still writes the file, with its doctype alone. The e-mail would go out
|
|
836
839
|
blank, so the build stops.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nxgt/mail-i18n",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "An i18n plugin for a Maizzle project: ICU catalogues checked at build time, t() in templates, one output per locale, and the manifest the renderer reads. createTranslator for use outside templates.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -52,14 +52,14 @@
|
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"@maizzle/framework": "6.1.7",
|
|
54
54
|
"@maizzle/tailwindcss": "1.5.6",
|
|
55
|
-
"@nxgt/mail-config": "0.1
|
|
55
|
+
"@nxgt/mail-config": "0.2.1",
|
|
56
56
|
"@types/bun": "^1.4.2",
|
|
57
57
|
"vue": "3.5.43",
|
|
58
58
|
"vue-tsc": "^3.3.11"
|
|
59
59
|
},
|
|
60
60
|
"peerDependencies": {
|
|
61
61
|
"@maizzle/framework": "^6.1.7",
|
|
62
|
-
"@nxgt/mail-config": "^0.1
|
|
62
|
+
"@nxgt/mail-config": "^0.2.1",
|
|
63
63
|
"typescript": "^6.0.3",
|
|
64
64
|
"vue": "^3.5.0"
|
|
65
65
|
},
|