diff --git a/src/render/buildTemplate.ts b/src/render/buildTemplate.ts index 0e11791a..7b2dcd24 100644 --- a/src/render/buildTemplate.ts +++ b/src/render/buildTemplate.ts @@ -5,6 +5,7 @@ import { runTransformers } from '../transformers/index.ts' import { createPlaintext } from '../plaintext.ts' import { stripForHtml, stripForPlaintext } from '../utils/output-markers.ts' import { _setCurrentTemplate } from '../composables/useCurrentTemplate.ts' +import { cloneConfig } from '../utils/cloneConfig.ts' import type { EventManager } from '../events/index.ts' import type { Renderer } from './createRenderer.ts' import type { MaizzleConfig } from '../types/index.ts' @@ -57,7 +58,7 @@ export async function buildTemplate( * preheader, injecting fetched data, etc.) stay scoped to this template * instead of leaking into later ones through the shared config object. */ - const renderConfig = defu({}, config) as MaizzleConfig + const renderConfig = cloneConfig(config) const originalSource = template.source await events.fireBeforeRender({ config: renderConfig, template }) @@ -133,6 +134,7 @@ export async function buildTemplate( mkdirSync(dirname(ptOutputPath), { recursive: true }) writeFileSync(ptOutputPath, plaintext) + files.push(ptOutputPath) } } finally { _setCurrentTemplate(undefined) diff --git a/src/tests/build.test.ts b/src/tests/build.test.ts index 9ef6ab69..2f81640f 100644 --- a/src/tests/build.test.ts +++ b/src/tests/build.test.ts @@ -210,6 +210,45 @@ describe('build', () => { expect(bHtml).toContain('none') }) + it('scopes nested beforeRender config mutations per template', async () => { + writeSfc(tempDir, 'emails/a.vue', ` + + + `) + + writeSfc(tempDir, 'emails/b.vue', ` + + + `) + + writeFileSync(join(tempDir, 'maizzle.config.js'), ` + export default { + custom: { val: 'base' }, + beforeRender({ template, config }) { + if (template.path.name === 'a') config.custom.val = 'AAA' + } + } + `) + + const result = await build() + const aHtml = readFileSync(result.files.find(f => f.includes('a.html'))!, 'utf-8') + const bHtml = readFileSync(result.files.find(f => f.includes('b.html'))!, 'utf-8') + + // 'a' sees its own nested mutation + expect(aHtml).toContain('AAA') + // 'b' must NOT inherit 'a's nested mutation (deep per-template clone) + expect(bHtml).not.toContain('AAA') + expect(bHtml).toContain('base') + }) + it('fires afterRender event and uses modified HTML', async () => { writeSfc(tempDir, 'emails/test.vue', `