Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions src/serve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { renderUnicodeCompact } from 'uqr'
import vue from '@vitejs/plugin-vue'
import tailwindcss from '@tailwindcss/vite'
import { glob } from 'tinyglobby'
import defu from 'defu'
import { createHighlighter, type Highlighter } from 'shiki'
import { createPlaintext } from './plaintext.ts'
import { stripForHtml, stripForPlaintext } from './utils/output-markers.ts'
Expand Down Expand Up @@ -707,8 +708,9 @@ async function servePlaintext(url: string, config: MaizzleConfig, renderer: Rend
const absolutePath = resolve(match)

try {
const { rawHtml } = await getRendered(absolutePath, config, renderer, events)
const plaintext = createPlaintext(stripForPlaintext(rawHtml))
const { rawHtml, templateConfig, rendered } = await getRendered(absolutePath, config, renderer, events)
const globalPlaintext = typeof templateConfig.plaintext === 'object' ? templateConfig.plaintext : {}
const plaintext = createPlaintext(stripForPlaintext(rawHtml), defu(rendered.plaintext?.options, globalPlaintext.options))

res.setHeader('Content-Type', 'text/plain')
res.end(plaintext)
Expand Down Expand Up @@ -816,10 +818,11 @@ async function serveEmailEndpoint(url: string, req: any, res: any, config: Maizz
const absolutePath = resolve(match)

try {
const { rawHtml, doctype, templateConfig } = await getRendered(absolutePath, config, renderer, events)
const { rawHtml, doctype, templateConfig, rendered } = await getRendered(absolutePath, config, renderer, events)
let html = doctype ? `${doctype}\n${rawHtml}` : rawHtml

const text = createPlaintext(stripForPlaintext(html))
const globalPlaintext = typeof templateConfig.plaintext === 'object' ? templateConfig.plaintext : {}
const text = createPlaintext(stripForPlaintext(html), defu(rendered.plaintext?.options, globalPlaintext.options))
html = stripForHtml(html)

const result = await sendEmail(
Expand Down
69 changes: 69 additions & 0 deletions src/tests/serve.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { serve } from '../serve.ts'
import { render } from '../render/index.ts'
import { getActiveRenderer } from '../render/active.ts'
import * as rendererMod from '../render/createRenderer.ts'
import * as emailMod from '../server/email.ts'
import type { Renderer } from '../render/createRenderer.ts'

const realCreateRenderer = rendererMod.createRenderer
Expand Down Expand Up @@ -259,6 +260,74 @@ describe('serve dev server', () => {
expect(html).toContain('<!-- transformed -->')
}, 30000)

it('applies plaintext.options in the plaintext preview', async () => {
writeFileSync(join(tempDir, 'maizzle.config.js'), `
export default {
plaintext: { options: { ignoreTags: ['b'] } },
}
`)
mkdirSync(join(tempDir, 'emails'), { recursive: true })
writeFileSync(join(tempDir, 'emails/welcome.vue'), '<template><p>Hello <b>World</b></p></template>\n')

server = await serve({ port: 3157, silent: true })

const res = await fetch('http://localhost:3157/__maizzle/plaintext/emails/welcome')
const text = await res.text()

expect(text).toContain('<b>World</b>')
}, 30000)

it('prefers usePlaintext() options over global ones in the plaintext preview', async () => {
writeFileSync(join(tempDir, 'maizzle.config.js'), `
export default {
plaintext: { options: { dumpLinkHrefsNearby: { enabled: true } } },
}
`)
mkdirSync(join(tempDir, 'emails'), { recursive: true })
writeFileSync(join(tempDir, 'emails/welcome.vue'), `
<script setup>
usePlaintext({ options: { dumpLinkHrefsNearby: { enabled: false } } })
</script>
<template><p><a href="https://example.com">Visit</a></p></template>
`)

server = await serve({ port: 3157, silent: true })

const res = await fetch('http://localhost:3157/__maizzle/plaintext/emails/welcome')
const text = await res.text()

expect(text).toContain('Visit')
expect(text).not.toContain('https://example.com')
}, 30000)

it('applies plaintext.options to the test email text', async () => {
writeFileSync(join(tempDir, 'maizzle.config.js'), `
export default {
plaintext: { options: { ignoreTags: ['b'] } },
}
`)
mkdirSync(join(tempDir, 'emails'), { recursive: true })
writeFileSync(join(tempDir, 'emails/welcome.vue'), '<template><p>Hello <b>World</b></p></template>\n')

const spy = vi.spyOn(emailMod, 'sendEmail').mockResolvedValue({ success: true } as any)

try {
server = await serve({ port: 3157, silent: true })

const res = await fetch('http://localhost:3157/__maizzle/email/emails/welcome', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ to: ['test@example.com'], subject: 'Test' }),
})

expect(res.status).toBe(200)
expect(spy).toHaveBeenCalledOnce()
expect(spy.mock.calls[0][0].text).toContain('<b>World</b>')
} finally {
spy.mockRestore()
}
}, 30000)

it('renders definePreviewProps() sample data in the dev server but not in render()', async () => {
mkdirSync(join(tempDir, 'emails'), { recursive: true })
writeFileSync(join(tempDir, 'emails/welcome.vue'), `
Expand Down
Loading