From 74b3e3f13e4a4e88e4fb727599da46422ebeff9d Mon Sep 17 00:00:00 2001 From: Axel Rindle Date: Wed, 21 Aug 2024 15:33:27 +0200 Subject: [PATCH 1/4] wip --- bun.lockb | Bin 267796 -> 268495 bytes cli/actions/email/compile.ts | 63 ++++++++++++++++++++++++++++-- cli/config.ts | 6 ++- cli/types.ts | 4 ++ package.json | 1 + supabase/emails/confirmation.mjml | 4 +- supabase/i18n/de.js | 5 +++ supabase/i18n/en.js | 5 +++ 8 files changed, 83 insertions(+), 5 deletions(-) create mode 100644 supabase/i18n/de.js create mode 100644 supabase/i18n/en.js diff --git a/bun.lockb b/bun.lockb index 8d62ecf60092c4df5251edf6aec2e40da353cb88..434254b2fc64085e0a438eac1f073b7e9bb4be75 100755 GIT binary patch delta 27818 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 MHm}qENY1tY2f>i$Hvj+t diff --git a/cli/actions/email/compile.ts b/cli/actions/email/compile.ts index f37fd30..18f96ce 100644 --- a/cli/actions/email/compile.ts +++ b/cli/actions/email/compile.ts @@ -1,7 +1,10 @@ +import config from '@/config.js' import type { GlobalOptions, Installer } from '@/types.js' import { action, supabaseProjectRef } from '@/utils.js' import { Option } from 'commander' import { log } from 'console' +import { getProperty } from 'dot-prop' +import { compile } from 'ejs' import { readFile, writeFile } from 'fs/promises' import { glob } from 'glob' import type { Root } from 'hast' @@ -14,6 +17,7 @@ import rehypeMinify from 'rehype-preset-minify' import rehypeStringify from 'rehype-stringify' const directory = resolve('supabase/emails') +const i18n = resolve('supabase/i18n') const supabaseConfigMap: Record = { 'confirmation': 'mailer_templates_confirmation_content', @@ -25,12 +29,50 @@ const supabaseConfigMap: Record = { } type Options = GlobalOptions & { + minify: boolean deploy: boolean } +type Translations = Record> + +function ejsTranslate(translations: Translations) { + return (key: string) => { + const languages = Object.keys(translations) + const branches = languages.map((lang, index) => { + if (index === 0) { + return `{{ if eq .Data.${config.i18n.attribute} "${lang}" }}` + } else { + return `{{ else if eq .Data.${config.i18n.attribute} "${lang}" }}` + } + }).concat('{{ end }}') + + let cursor = 0 + const result = [] + const max = branches.length * 2 - 1 + for (let i = 0; i < max; i++) { + if (i % 2 === 0) { + result.push(branches[cursor++]) + } else { + result.push(getProperty( + translations[languages[cursor - 1]], + key, + getProperty( + translations[config.i18n.default], + key, + '!!MISSING TRANSLATION KEY!!', + ), + )) + } + } + + return result.join('\n') + } +} + const installer: Installer = program => { program.command('email:compile') .description('Compile and optionally deploy email templates') + .option('--no-minify', 'Disable minifying of the result files.') .addOption( new Option('--deploy', 'Enable deployment to linked Supabase project. (Implies --linked)') .implies({ linked: true }), @@ -38,6 +80,13 @@ const installer: Installer = program => { .action(action(async ({ opts }) => { const projectRef = opts.deploy ? await supabaseProjectRef() : null + const languages = await glob('*.js', { cwd: i18n }) + const languageMap: Translations = {} + for await (const language of languages) { + const { default: data } = await import(`${i18n}/${language}`) + languageMap[basename(language, '.js')] = data + } + const files = await glob('*.mjml', { cwd: directory }) files.sort() @@ -50,8 +99,16 @@ const installer: Installer = program => { log(`Processing file ${file} (${++i}/${files.length}) …`) const abs = join(directory, file) - const template = await readFile(abs) - const converted = convert(template.toString('utf8'), { + const contents = await readFile(abs) + const template = compile(contents.toString('utf8'), { + async: true, + beautify: false, + cache: true, + }) + const compiled = await template({ + __: ejsTranslate(languageMap), + }) + const converted = convert(compiled, { filePath: abs, }) @@ -69,7 +126,7 @@ const installer: Installer = program => { const result = await rehype() .use(inlineImages) - .use(rehypeMinify) + .use(opts.minify ? rehypeMinify : null) .use(rehypeStringify) .process(html) diff --git a/cli/config.ts b/cli/config.ts index 38cfab6..dbc5fe6 100644 --- a/cli/config.ts +++ b/cli/config.ts @@ -37,10 +37,14 @@ async function load(file?: string): Promise { } } -const defaults: Config = { +export const defaults: Config = { typeFiles: [ 'db.ts', ], + i18n: { + attribute: 'language', + default: 'en', + }, } const configFile = await selectFile() diff --git a/cli/types.ts b/cli/types.ts index 2cc3674..10c94a4 100644 --- a/cli/types.ts +++ b/cli/types.ts @@ -3,6 +3,10 @@ import { z } from 'zod' export type Config = { typeFiles: string[] + i18n: { + attribute: string + default: string + } } export const globalOptionsSchema = z.object({ diff --git a/package.json b/package.json index b53655b..6b9169b 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,7 @@ "@types/slug": "^5.0.8", "acorn": "^8.12.1", "comment-parser": "^1.4.1", + "dot-prop": "^9.0.0", "ejs": "^3.1.10", "eslint": "^9.8.0", "espree": "^10.1.0", diff --git a/supabase/emails/confirmation.mjml b/supabase/emails/confirmation.mjml index 1e3a50d..08f41db 100644 --- a/supabase/emails/confirmation.mjml +++ b/supabase/emails/confirmation.mjml @@ -12,7 +12,9 @@ - Hello World + + <%- __("my.key") %> + Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. diff --git a/supabase/i18n/de.js b/supabase/i18n/de.js new file mode 100644 index 0000000..b335bfa --- /dev/null +++ b/supabase/i18n/de.js @@ -0,0 +1,5 @@ +export default { + my: { + key: 'Hallo Welt' + } +} diff --git a/supabase/i18n/en.js b/supabase/i18n/en.js new file mode 100644 index 0000000..25acf35 --- /dev/null +++ b/supabase/i18n/en.js @@ -0,0 +1,5 @@ +export default { + my: { + key: 'Hello World' + } +} From 39113b2225f1099e8c5d6caf19d21bad35c6dae2 Mon Sep 17 00:00:00 2001 From: Axel Rindle Date: Thu, 22 Aug 2024 10:56:36 +0200 Subject: [PATCH 2/4] fix: add else branch for when attribute is not set --- bun.lockb | Bin 268495 -> 268495 bytes cli/actions/email/compile.ts | 42 +++++++++++++------------- cli/utils/interpose.ts | 48 ++++++++++++++++++++++++++++++ eslint.config.js | 2 +- supabase/emails/confirmation.mjml | 10 +++---- supabase/i18n/de.js | 10 +++++-- supabase/i18n/en.js | 10 +++++-- 7 files changed, 89 insertions(+), 33 deletions(-) create mode 100644 cli/utils/interpose.ts diff --git a/bun.lockb b/bun.lockb index 434254b2fc64085e0a438eac1f073b7e9bb4be75..3bd6adbc70307f3ba1a7fc820a426ef1bf4cea4a 100755 GIT binary patch delta 31 ncmX@VQQ-VWfrb{wElk~;*%{+3^$he3+9z#h+CFJBvu!E>$wLd| delta 31 kcmX@VQQ-VWfrb{wElk~;*_jx?pncM2rtOn9Gux&D0JiZ8k^lez diff --git a/cli/actions/email/compile.ts b/cli/actions/email/compile.ts index 18f96ce..904ebb3 100644 --- a/cli/actions/email/compile.ts +++ b/cli/actions/email/compile.ts @@ -1,6 +1,7 @@ import config from '@/config.js' import type { GlobalOptions, Installer } from '@/types.js' import { action, supabaseProjectRef } from '@/utils.js' +import interpose from '@/utils/interpose.js' import { Option } from 'commander' import { log } from 'console' import { getProperty } from 'dot-prop' @@ -44,26 +45,25 @@ function ejsTranslate(translations: Translations) { } else { return `{{ else if eq .Data.${config.i18n.attribute} "${lang}" }}` } - }).concat('{{ end }}') - - let cursor = 0 - const result = [] - const max = branches.length * 2 - 1 - for (let i = 0; i < max; i++) { - if (i % 2 === 0) { - result.push(branches[cursor++]) - } else { - result.push(getProperty( - translations[languages[cursor - 1]], - key, - getProperty( - translations[config.i18n.default], - key, - '!!MISSING TRANSLATION KEY!!', - ), - )) + }).concat('{{ else }}', '{{ end }}') + + const result = interpose(branches, ({ cursor, last }) => { + const _default = getProperty( + translations[config.i18n.default], + key, + '!!MISSING TRANSLATION KEY!!', + ) + + if (last) { + return _default } - } + + return getProperty( + translations[languages[cursor - 1]], + key, + _default, + ) + }) return result.join('\n') } @@ -108,7 +108,7 @@ const installer: Installer = program => { const compiled = await template({ __: ejsTranslate(languageMap), }) - const converted = convert(compiled, { + const converted = convertMjml(compiled, { filePath: abs, }) @@ -170,7 +170,7 @@ type ConvertResults = { error: null } & MJMLParseResults -function convert(input: string, options?: MJMLParsingOptions): ConvertResults { +function convertMjml(input: string, options?: MJMLParsingOptions): ConvertResults { try { const results = mjml2html(input, options) return { diff --git a/cli/utils/interpose.ts b/cli/utils/interpose.ts new file mode 100644 index 0000000..012f131 --- /dev/null +++ b/cli/utils/interpose.ts @@ -0,0 +1,48 @@ +type Args = { + /** + * The current index of the overall iteration. + */ + index: number + + /** + * The current index of the interpose iteration. + */ + cursor: number + + /** + * Whether this is the first interpose. + */ + first: boolean + + /** + * Whether this is the last interpose. + */ + last: boolean +} + +/** + * Interpose items to an array. + * + * @param arr The source array to modify. + * @param producer A function that returns the items to interpose. + * @returns The interposed array. + */ +export default function interpose(arr: T[], producer: (args: Args) => T) { + let cursor = 0 + + const result = [] + const max = arr.length * 2 - 1 + + for (let index = 0; index < max; index++) { + const first = index == 1 + const last = index === max - 2 + + if (index % 2 === 0) { + result.push(arr[cursor++]) + } else { + result.push(producer({index, cursor, first, last})) + } + } + + return result +} diff --git a/eslint.config.js b/eslint.config.js index 09ee24c..844b592 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -6,7 +6,7 @@ const config = [ { ignores: [ '*.d.ts', - 'supabase/', + 'supabase/functions', '.venv', ], }, diff --git a/supabase/emails/confirmation.mjml b/supabase/emails/confirmation.mjml index 08f41db..b2e5c02 100644 --- a/supabase/emails/confirmation.mjml +++ b/supabase/emails/confirmation.mjml @@ -13,14 +13,14 @@ - <%- __("my.key") %> + <%- __("confirmation.title") %> + - Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + <%- __("confirmation.text1") %> - - Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + <%- __("confirmation.text2") %> @@ -40,7 +40,7 @@ - Copyright (c) [NAME] [YEAR] + Copyright (c) act coding GbR {{ now.UTC.Year }} diff --git a/supabase/i18n/de.js b/supabase/i18n/de.js index b335bfa..3df2f78 100644 --- a/supabase/i18n/de.js +++ b/supabase/i18n/de.js @@ -1,5 +1,9 @@ export default { - my: { - key: 'Hallo Welt' - } + confirmation: { + title: 'Konto aktivieren', + text1: `Es wurde ein neues Konto mit dieser E-Mail-Adresse erstellt. + Verwende den unten stehenden Link, um die Erstellung des Kontos zu bestätigen.`, + text2: `Wenn du kein Konto bei uns registriert haben, kannst du diese E-Mail einfach ignorieren. + Prüfe aber zur Sicherheit die Integrität deiner E-Mail-Adresse.`, + }, } diff --git a/supabase/i18n/en.js b/supabase/i18n/en.js index 25acf35..b7db2ba 100644 --- a/supabase/i18n/en.js +++ b/supabase/i18n/en.js @@ -1,5 +1,9 @@ export default { - my: { - key: 'Hello World' - } + confirmation: { + title: 'Active account', + text1: `A new account has been created using this email address. + Use the link below to confirm the account creation.`, + text2: `If you did not register an account with us, you can simply ignore + this email. Be sure to verify your email's account integrity.`, + }, } From 97320ba546cd8ca5d5672a3da01fe90d14753e1c Mon Sep 17 00:00:00 2001 From: Axel Rindle Date: Thu, 22 Aug 2024 10:57:37 +0200 Subject: [PATCH 3/4] restore lockfile --- bun.lockb | Bin 268495 -> 268495 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/bun.lockb b/bun.lockb index 3bd6adbc70307f3ba1a7fc820a426ef1bf4cea4a..434254b2fc64085e0a438eac1f073b7e9bb4be75 100755 GIT binary patch delta 31 kcmX@VQQ-VWfrb{wElk~;*_jx?pncM2rtOn9Gux&D0JiZ8k^lez delta 31 ncmX@VQQ-VWfrb{wElk~;*%{+3^$he3+9z#h+CFJBvu!E>$wLd| From 643c73ca50ba2f8b484dd28f9bfdd29030b5ced2 Mon Sep 17 00:00:00 2001 From: Axel Rindle Date: Thu, 22 Aug 2024 11:43:06 +0200 Subject: [PATCH 4/4] fix: make dot-prop a non-dev dependency --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6b9169b..9419be6 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,6 @@ "@types/slug": "^5.0.8", "acorn": "^8.12.1", "comment-parser": "^1.4.1", - "dot-prop": "^9.0.0", "ejs": "^3.1.10", "eslint": "^9.8.0", "espree": "^10.1.0", @@ -69,6 +68,7 @@ "@inquirer/select": "^2.4.7", "commander": "^12.1.0", "dayjs": "^1.11.12", + "dot-prop": "^9.0.0", "dotenv": "^16.4.5", "glob": "^11.0.0", "hast-util-select": "^6.0.2",