@ultimat3/mail 5.0.1 → 7.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +6 -6
- package/src/catalog.ts +16 -22
- package/src/index.ts +1 -6
- package/src/layout.ts +14 -15
- package/src/render.ts +7 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ultimat3/mail",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "7.0.0",
|
|
4
4
|
"description": "Transactional email as data: one template renders HTML and text, sent through a job.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -31,10 +31,10 @@
|
|
|
31
31
|
"test": "bun test"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@ultimat3/core": "
|
|
35
|
-
"@ultimat3/i18n": "
|
|
36
|
-
"@ultimat3/jobs": "
|
|
37
|
-
"@ultimat3/schema": "
|
|
38
|
-
"@ultimat3/time": "
|
|
34
|
+
"@ultimat3/core": "7.0.0",
|
|
35
|
+
"@ultimat3/i18n": "7.0.0",
|
|
36
|
+
"@ultimat3/jobs": "7.0.0",
|
|
37
|
+
"@ultimat3/schema": "7.0.0",
|
|
38
|
+
"@ultimat3/time": "7.0.0"
|
|
39
39
|
}
|
|
40
40
|
}
|
package/src/catalog.ts
CHANGED
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
type Locale,
|
|
10
10
|
loadCatalog,
|
|
11
11
|
type NestedCatalog,
|
|
12
|
-
|
|
12
|
+
registerBaseCatalog,
|
|
13
13
|
} from '@ultimat3/i18n';
|
|
14
14
|
|
|
15
15
|
export const MAIL_CATALOG_SOURCE: NestedCatalog = {
|
|
@@ -85,24 +85,18 @@ export const MAIL_CATALOG: Catalog = loadCatalog(MAIL_CATALOG_SOURCE);
|
|
|
85
85
|
/** The one locale these strings are written in. */
|
|
86
86
|
export const MAIL_CATALOG_LOCALE: Locale = DEFAULT_LOCALE;
|
|
87
87
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
* `resetCatalogs()` runs (`packages/testing/src/registry-snapshot.ts`), which would silently stop
|
|
104
|
-
* registering altogether. Stating the limit beats inventing a guard that fails quietly.
|
|
105
|
-
*/
|
|
106
|
-
export function registerMailCatalog(): void {
|
|
107
|
-
registerCatalog(MAIL_CATALOG_LOCALE, MAIL_CATALOG);
|
|
108
|
-
}
|
|
88
|
+
// At module scope, and that is the whole point: importing `@ultimat3/mail` is what installs these
|
|
89
|
+
// strings, so no app and no boot can forget them. `registerMailCatalog()` was the alternative and
|
|
90
|
+
// it had **zero** production callers — only this package's own tests — so every `mail.*` string in
|
|
91
|
+
// every running Ultimate app rendered as a loud miss, which is issue #249 one package over.
|
|
92
|
+
//
|
|
93
|
+
// Under an app's catalog, never over it: `registerBaseCatalog` merges the base FIRST and whatever
|
|
94
|
+
// `registerCatalog` seated second, so an app that translated `mail.footer.unsubscribe` keeps it
|
|
95
|
+
// through every later install. That is the "guard by CONTENT" this file said needed an i18n
|
|
96
|
+
// primitive that did not exist — it exists now, and it is idempotent by construction rather than
|
|
97
|
+
// by a module flag `resetCatalogs()` would go stale against.
|
|
98
|
+
//
|
|
99
|
+
// Under the ONE locale these strings are written in. Seating English under `es` made `isMiss` read
|
|
100
|
+
// FALSE for a subject nobody had translated — a fallback locale chain wearing registration as a
|
|
101
|
+
// disguise. A non-`en` app translates the `mail.*` keys it renders into its own catalog.
|
|
102
|
+
registerBaseCatalog(MAIL_CATALOG_LOCALE, MAIL_CATALOG);
|
package/src/index.ts
CHANGED
|
@@ -7,12 +7,7 @@ export { t } from '@ultimat3/schema';
|
|
|
7
7
|
export type { CalloutTone, MailBlock, MailTemplate, TemplateArgs } from './blocks';
|
|
8
8
|
export { blocks } from './blocks';
|
|
9
9
|
|
|
10
|
-
export {
|
|
11
|
-
MAIL_CATALOG,
|
|
12
|
-
MAIL_CATALOG_LOCALE,
|
|
13
|
-
MAIL_CATALOG_SOURCE,
|
|
14
|
-
registerMailCatalog,
|
|
15
|
-
} from './catalog';
|
|
10
|
+
export { MAIL_CATALOG, MAIL_CATALOG_LOCALE, MAIL_CATALOG_SOURCE } from './catalog';
|
|
16
11
|
export type {
|
|
17
12
|
MailDriver,
|
|
18
13
|
MailMessage,
|
package/src/layout.ts
CHANGED
|
@@ -21,21 +21,20 @@ export type MailToken =
|
|
|
21
21
|
| 'calloutDangerBg'
|
|
22
22
|
| 'calloutDangerText';
|
|
23
23
|
|
|
24
|
-
export const MAIL_TOKENS
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
});
|
|
24
|
+
export const MAIL_TOKENS = Object.freeze<Record<MailToken, Readonly<Record<ColorScheme, string>>>>({
|
|
25
|
+
pageBg: { light: '#f4f5f7', dark: '#0b0d10' },
|
|
26
|
+
surfaceBg: { light: '#ffffff', dark: '#14181d' },
|
|
27
|
+
textPrimary: { light: '#16191d', dark: '#e7eaee' },
|
|
28
|
+
textMuted: { light: '#5c6470', dark: '#9aa4b1' },
|
|
29
|
+
borderSubtle: { light: '#e2e6ea', dark: '#262c33' },
|
|
30
|
+
accentBg: { light: '#2f6df6', dark: '#4f86ff' },
|
|
31
|
+
accentText: { light: '#ffffff', dark: '#0b0d10' },
|
|
32
|
+
linkText: { light: '#2f6df6', dark: '#7aa7ff' },
|
|
33
|
+
calloutInfoBg: { light: '#eef3ff', dark: '#141c2c' },
|
|
34
|
+
calloutInfoText: { light: '#1f3f8f', dark: '#b9cdfb' },
|
|
35
|
+
calloutDangerBg: { light: '#fdeceb', dark: '#2a1416' },
|
|
36
|
+
calloutDangerText: { light: '#8c2118', dark: '#f5b3ad' },
|
|
37
|
+
});
|
|
39
38
|
|
|
40
39
|
/** Resolve a token to a hex value. The only function in the package that returns a colour. */
|
|
41
40
|
export function token(name: MailToken, scheme: ColorScheme = 'light'): string {
|
package/src/render.ts
CHANGED
|
@@ -5,6 +5,13 @@
|
|
|
5
5
|
|
|
6
6
|
import { directionOf, type TranslateVars, type Translator, translatorFor } from '@ultimat3/i18n';
|
|
7
7
|
import type { CalloutTone, MailBlock, MailTemplate } from './blocks';
|
|
8
|
+
// The renderer depends on the strings it renders. This is the only module that resolves a `mail.*`
|
|
9
|
+
// key, and `catalog.ts` installs them at ITS module scope — so importing it here is what makes
|
|
10
|
+
// "a rendered mail has words in it" structural rather than something a caller has to arrange.
|
|
11
|
+
// Without this edge, only the package ENTRY reached the catalog: every deep import of `render.ts`
|
|
12
|
+
// produced `⟦mail.welcome.subject⟧`, and the tests that would have noticed were the ones calling
|
|
13
|
+
// `registerMailCatalog()` themselves — the exact shape of issue #249.
|
|
14
|
+
import './catalog';
|
|
8
15
|
import { layoutUnknown, textMissing } from './errors';
|
|
9
16
|
import { escapeHtml, safeUrl, styleAttr } from './html';
|
|
10
17
|
import { layoutFor, registeredLayouts, token } from './layout';
|