diff --git a/package.json b/package.json index edcbec5..6710d91 100644 --- a/package.json +++ b/package.json @@ -50,8 +50,8 @@ "dependencies": { "@nuxt/kit": "^3.10.0", "defu": "^6.1.4", - "vue-email": "^0.8.7", - "@vue-email/compiler": "^0.8.9", + "vue-email": "npm:vue-email-edge@0.8.7-28446842.1f6e4a0", + "@vue-email/compiler": "npm:@vue-email/compiler-edge@0.8.9-28446863.0aab8eb", "sirv": "^2.0.4" }, "devDependencies": { diff --git a/playground/nuxt-layer/emails/TestEmail.vue b/playground/nuxt-layer/emails/TestEmail.vue index a87bce8..a239e99 100644 --- a/playground/nuxt-layer/emails/TestEmail.vue +++ b/playground/nuxt-layer/emails/TestEmail.vue @@ -1,156 +1,144 @@ diff --git a/playground/nuxt.config.ts b/playground/nuxt.config.ts index c149ca6..0c20a78 100644 --- a/playground/nuxt.config.ts +++ b/playground/nuxt.config.ts @@ -1,27 +1,36 @@ export default defineNuxtConfig({ - modules: ['../src/module'], - extends: [ - './nuxt-layer' - ], + modules: ["../src/module", "@nuxtjs/tailwindcss"], + extends: ["./nuxt-layer"], vueEmail: { - baseUrl: 'https://vue-email-demo.vercel.app/', + baseUrl: "https://vue-email-demo.vercel.app/", i18n: { - defaultLocale: 'fr', + defaultLocale: "fr", translations: { en: { - title: 'Welcome to Vue Email', - subtitle: 'A Vue.js component for generating beautiful emails using MJML', - button: 'Get Started', + title: "Welcome to Vue Email", + subtitle: + "A Vue.js component for generating beautiful emails using MJML", + button: "Get Started", }, fr: { - title: 'Bienvenue sur Vue Email', - subtitle: 'Un composant Vue.js pour générer de beaux emails en utilisant MJML', - button: 'Commencer', + title: "Bienvenue sur Vue Email", + subtitle: + "Un composant Vue.js pour générer de beaux emails en utilisant MJML", + button: "Commencer", }, }, }, - autoImport: false + autoImport: false, + // tailwind: { + // theme: { + // extend: { + // colors: { + // primary: "#ea580c", + // secondary: "#ca8a04", + // }, + // }, + // }, + // }, }, devtools: { enabled: true }, - -}) +}); diff --git a/playground/package.json b/playground/package.json index 5e00220..50b3643 100644 --- a/playground/package.json +++ b/playground/package.json @@ -10,6 +10,7 @@ "analyze": "nuxt analyze" }, "devDependencies": { + "@nuxtjs/tailwindcss": "^6.11.2", "nuxt": "latest" } } diff --git a/playground/server/api/test.get.ts b/playground/server/api/test.get.ts index 41eb8d5..2fc5773 100644 --- a/playground/server/api/test.get.ts +++ b/playground/server/api/test.get.ts @@ -1,20 +1,19 @@ -import { useCompiler } from '#vue-email' +import { useCompiler } from "#vue-email"; export default defineEventHandler(async () => { try { - const template = await useCompiler('TestEmail.vue', { + const template = await useCompiler("TestEmail.vue", { props: { - username: 'Flowko', + username: "Flowko", }, }).catch((error) => { console.error(error); - }) + }); - if(!template) return null + if (!template) return null; - return template.html + return template.html; } catch (error) { console.error(error); - } -}) +}); diff --git a/playground/tailwind.config.js b/playground/tailwind.config.js new file mode 100644 index 0000000..b89c848 --- /dev/null +++ b/playground/tailwind.config.js @@ -0,0 +1,13 @@ +/** @type {import('tailwindcss').Config} */ +export default { + content: [], + theme: { + extend: { + colors: { + primary: "cyan", + secondary: "#ca8a04", + }, + }, + }, + plugins: [], +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 12a6f40..f77afec 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,8 +12,8 @@ importers: specifier: ^3.10.0 version: 3.10.0(rollup@3.29.4) '@vue-email/compiler': - specifier: ^0.8.9 - version: 0.8.9(typescript@5.3.3)(vue@3.4.15) + specifier: npm:@vue-email/compiler-edge@0.8.9-28446863.0aab8eb + version: /@vue-email/compiler-edge@0.8.9-28446863.0aab8eb(typescript@5.3.3)(vue@3.4.15) defu: specifier: ^6.1.4 version: 6.1.4 @@ -21,8 +21,8 @@ importers: specifier: ^2.0.4 version: 2.0.4 vue-email: - specifier: ^0.8.7 - version: 0.8.7(typescript@5.3.3)(vue@3.4.15) + specifier: npm:vue-email-edge@0.8.7-28446842.1f6e4a0 + version: /vue-email-edge@0.8.7-28446842.1f6e4a0(typescript@5.3.3)(vue@3.4.15) devDependencies: '@nuxt/devtools': specifier: latest @@ -123,6 +123,9 @@ importers: playground: devDependencies: + '@nuxtjs/tailwindcss': + specifier: ^6.11.2 + version: 6.11.2(rollup@3.29.4) nuxt: specifier: latest version: 3.9.3(@types/node@20.11.10)(eslint@8.56.0)(rollup@3.29.4)(typescript@5.3.3)(vite@5.0.12) @@ -1960,6 +1963,31 @@ packages: - ts-node dev: true + /@nuxtjs/tailwindcss@6.11.2(rollup@3.29.4): + resolution: {integrity: sha512-06e8t9ia6Ru/RPMATuhGwi16rMYeZPseXiI4QmRDk/IkvluU60GxhLZOjdUIa+U7DVCECgDsRNEo/rD8/1sMKQ==} + dependencies: + '@nuxt/kit': 3.10.0(rollup@3.29.4) + autoprefixer: 10.4.17(postcss@8.4.33) + chokidar: 3.5.3 + clear-module: 4.1.2 + colorette: 2.0.20 + consola: 3.2.3 + defu: 6.1.4 + h3: 1.10.1 + micromatch: 4.0.5 + pathe: 1.1.2 + postcss: 8.4.33 + postcss-custom-properties: 13.3.4(postcss@8.4.33) + postcss-nesting: 12.0.2(postcss@8.4.33) + tailwind-config-viewer: 1.7.3(tailwindcss@3.4.1) + tailwindcss: 3.4.1 + ufo: 1.3.2 + transitivePeerDependencies: + - rollup + - supports-color + - ts-node + dev: true + /@one-ini/wasm@0.1.1: resolution: {integrity: sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==} dev: true @@ -2465,6 +2493,10 @@ packages: selderee: 0.11.0 dev: true + /@shikijs/core@1.0.0-beta.1: + resolution: {integrity: sha512-z3gdznaRj/DJSLQdR2Gdx6AB3e5+Il/kSGdLTGHI7HnalgPL15RbGgBSdLHW8rKAz4+dezAcTdnxm8z6YTu7nA==} + dev: false + /@sigstore/bundle@2.1.1: resolution: {integrity: sha512-v3/iS+1nufZdKQ5iAlQKcCsoh0jffQyABvYIxKsZQFWc4ubuGjwZklFHpDgV6O6T7vvV78SW5NHI91HFKEcxKg==} engines: {node: ^16.14.0 || >=18.0.0} @@ -2937,8 +2969,8 @@ packages: pretty-format: 29.7.0 dev: true - /@vue-email/cli@0.0.10(typescript@5.3.3)(vue@3.4.15): - resolution: {integrity: sha512-F99FOPQ8++SGJ8toAqboiW78o2d9ZDMmh7B9x8OZBvHyq/cH4KZca3VCQ9JaaOX4Rrovu6R3mwdPgJhtfK+l8A==} + /@vue-email/cli@0.0.11(typescript@5.3.3)(vue@3.4.15): + resolution: {integrity: sha512-nPOiCwRYc0Z3BIsTJ1rnFNcQaJQ2iE1QB/GaHVMR0fxM72VB0qcQ/LsrMDgvewAgY1ZJkpGGVrwwIR7T6PEU/w==} hasBin: true dependencies: '@vue-email/compiler': 0.8.9(typescript@5.3.3)(vue@3.4.15) @@ -2952,6 +2984,25 @@ packages: - vue dev: false + /@vue-email/compiler-edge@0.8.9-28446863.0aab8eb(typescript@5.3.3)(vue@3.4.15): + resolution: {integrity: sha512-PxPJifTQGqHCK0gK4yBt05dzyArfMAj467wSJ8JL7YMZvELXlG/cMDkRC6nQ1PexiFCdTQnsjW5akAwWTVDGhQ==} + peerDependencies: + vue: ^3.3.8 + dependencies: + import-string: 0.1.2(typescript@5.3.3) + kolorist: 1.8.0 + scule: 1.2.0 + vue: 3.4.15(typescript@5.3.3) + vue-email: /vue-email-edge@0.8.7-28446842.1f6e4a0(typescript@5.3.3)(vue@3.4.15) + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - ts-node + - typescript + - utf-8-validate + dev: false + /@vue-email/compiler@0.8.9(typescript@5.3.3)(vue@3.4.15): resolution: {integrity: sha512-5sHZiK/jQ/cDgCOAlenO7LZjN5DpAnnUsA7RX5n+xgMW/HrrBO2x1l9Za20TuH09CPmpePPIVGoT8DACA08IjQ==} peerDependencies: @@ -8077,6 +8128,12 @@ packages: resolution: {integrity: sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==} dev: true + /shiki@1.0.0-beta.1: + resolution: {integrity: sha512-iq32WxjemJVlAHg5HjYoL1qCxGmvyh3Z8kr2E/gMTQdcxyXxTpMhahIC7myxFBapAk9o8QN8mxCpr4JT5rqpRQ==} + dependencies: + '@shikijs/core': 1.0.0-beta.1 + dev: false + /shikiji-core@0.10.2: resolution: {integrity: sha512-9Of8HMlF96usXJHmCL3Gd0Fcf0EcyJUF9m8EoAKKd98mHXi0La2AZl1h6PegSFGtiYcBDK/fLuKbDa1l16r1fA==} dev: false @@ -9410,13 +9467,35 @@ packages: resolution: {integrity: sha512-RutnB7X8c5hjq39NceArgXg28WZtZpGc3+J16ljMiYnFhKvd8hITxSWQSQ5bvldxMDU6gG5mkxl1MTQLXckVSQ==} dev: true + /vue-email-edge@0.8.7-28446842.1f6e4a0(typescript@5.3.3)(vue@3.4.15): + resolution: {integrity: sha512-tYhsDpxH+Ds93vk32TKdFrg3fx8p24wxvu+EA1zFuaJCH2YJzHyklcDI5M2+yu1yOFofi+mGbW5jV+NmeAuUXA==} + hasBin: true + peerDependencies: + vue: ^3.4.15 + dependencies: + '@vue-email/cli': 0.0.11(typescript@5.3.3)(vue@3.4.15) + '@vue-email/tailwind': 0.0.6 + isomorphic-dompurify: 2.3.0 + shiki: 1.0.0-beta.1 + ufo: 1.3.2 + vue: 3.4.15(typescript@5.3.3) + vue-i18n: 9.9.0(vue@3.4.15) + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - ts-node + - typescript + - utf-8-validate + dev: false + /vue-email@0.8.7(typescript@5.3.3)(vue@3.4.15): resolution: {integrity: sha512-VxJHqXpVnFIezZ4Oj+vhtjBNBQZtqbKud+WicLQLSIqdtcV9hnM6f3+BQIXW2AijglVCTtUel/Z2Tn1m7/teRA==} hasBin: true peerDependencies: vue: ^3.4.15 dependencies: - '@vue-email/cli': 0.0.10(typescript@5.3.3)(vue@3.4.15) + '@vue-email/cli': 0.0.11(typescript@5.3.3)(vue@3.4.15) '@vue-email/tailwind': 0.0.6 isomorphic-dompurify: 2.3.0 shikiji: 0.10.2 diff --git a/src/module.ts b/src/module.ts index 6248f72..2516b28 100644 --- a/src/module.ts +++ b/src/module.ts @@ -8,10 +8,11 @@ import { addTemplate, createResolver, defineNuxtModule, + hasNuxtModule, } from "@nuxt/kit"; import { defu } from "defu"; import sirv from "sirv"; -import type { I18n } from "vue-email"; +import type { I18n, VueEmailPluginOptions } from "vue-email"; const components = [ "EBody", @@ -44,6 +45,8 @@ export interface ModuleOptions { i18n?: I18n; playground?: boolean; autoImport?: boolean; + useNuxtTailwind?: boolean; + tailwind?: VueEmailPluginOptions["tailwind"]; } export default defineNuxtModule({ @@ -63,6 +66,8 @@ export default defineNuxtModule({ baseUrl: null, playground: isDev, autoImport: false, + useNuxtTailwind: true, + tailwind: undefined, }; }, async setup(options, nuxt) { @@ -85,6 +90,17 @@ export default defineNuxtModule({ break; } + if (hasNuxtModule("@nuxtjs/tailwindcss") && options.useNuxtTailwind) { + // @ts-ignore + nuxt.hook("tailwindcss:resolvedConfig", function (resolvedConfig) { + options.tailwind = resolvedConfig; + nuxt.options.runtimeConfig.public.vueEmail = defu( + nuxt.options.runtimeConfig.public.vueEmail, + options + ); + }); + } + nuxt.options.nitro.alias = nuxt.options.nitro.alias || {}; nuxt.options.nitro.externals = defu( typeof nuxt.options.nitro.externals === "object" diff --git a/src/runtime/server/nitro/useCompiler.ts b/src/runtime/server/nitro/useCompiler.ts index 7c8c035..2300637 100644 --- a/src/runtime/server/nitro/useCompiler.ts +++ b/src/runtime/server/nitro/useCompiler.ts @@ -1,9 +1,9 @@ -import type { RenderOptions } from '@vue-email/compiler' -import { templateRender } from '@vue-email/compiler' -import type { ModuleOptions } from '../../../module' -import { useRuntimeConfig, useStorage } from '#imports' +import type { RenderOptions } from "@vue-email/compiler"; +import { templateRender } from "@vue-email/compiler"; +import type { ModuleOptions } from "../../../module"; +import { useRuntimeConfig, useStorage } from "#imports"; -const storageKey = 'assets:emails' +const storageKey = "assets:emails"; /** * Compile a email template @@ -22,34 +22,44 @@ const storageKey = 'assets:emails' * }) * ``` */ -export async function useCompiler(filename: string, data?: RenderOptions, verbose = false) { - const vueEmailOptions = useRuntimeConfig().public.vueEmail as ModuleOptions - const source = await useStorage(storageKey).getItem(filename) - const keys = await useStorage(storageKey).getKeys() +export async function useCompiler( + filename: string, + data?: RenderOptions, + verbose = false +) { + const vueEmailOptions = useRuntimeConfig().public.vueEmail as ModuleOptions; + const source = await useStorage(storageKey).getItem(filename); + const keys = await useStorage(storageKey).getKeys(); const components: { - name: string - source: string - }[] = [] + name: string; + source: string; + }[] = []; for (const key of keys) { - const value = await useStorage(storageKey).getItem(key) + const value = await useStorage(storageKey).getItem(key); - if (value && key.endsWith('.vue')) { + if (value && key.endsWith(".vue")) { components.push({ name: key, source: value as string, - }) + }); } } - if(!source) throw new Error(`Template ${filename} not found`) + if (!source) throw new Error(`Template ${filename} not found`); - const template = await templateRender(filename, { source: source as string, components }, data, { - verbose, - options: { - baseUrl: vueEmailOptions?.baseUrl, - i18n: vueEmailOptions?.i18n, - }, - }) + const template = await templateRender( + filename, + { source: source as string, components }, + data, + { + verbose, + options: { + baseUrl: vueEmailOptions?.baseUrl, + i18n: vueEmailOptions?.i18n, + tailwind: vueEmailOptions?.tailwind, + }, + } + ); - return template + return template; }