diff --git a/src/index.ts b/src/index.ts index b58d2ba..40080bb 100644 --- a/src/index.ts +++ b/src/index.ts @@ -51,6 +51,8 @@ export type { ContentProps } from './templates/content/content'; export { document, mergeShell, openTag, serializeAttributes } from './templates/document'; export type { DocumentProps, DocumentShellOptions, TagAttributes } from './templates/document'; +export { xhtmlDocument, XHTML_DOCTYPE } from './templates/document'; +export type { XhtmlDocumentProps } from './templates/document'; export { byteLength, measureSize, CLIP_BYTES, NEAR_BYTES } from './quality/size'; export type { ClipRisk, PartSize, SizeOptions, SizeReport } from './quality/size'; diff --git a/src/templates/document/index.ts b/src/templates/document/index.ts index a6d116e..1bbbfd3 100644 --- a/src/templates/document/index.ts +++ b/src/templates/document/index.ts @@ -16,3 +16,6 @@ export { openTag, serializeAttributes } from '../../utils/openTag'; export type { TagAttributes } from '../../utils/openTag'; export { mergeShell } from './mergeShell'; + +export { xhtmlDocument, XHTML_DOCTYPE } from './xhtmlDocument'; +export type { XhtmlDocumentProps } from './xhtmlDocument'; diff --git a/src/templates/document/xhtmlDocument.ts b/src/templates/document/xhtmlDocument.ts new file mode 100644 index 0000000..67a39cc --- /dev/null +++ b/src/templates/document/xhtmlDocument.ts @@ -0,0 +1,21 @@ +import { document } from './document'; +import type { DocumentProps } from './document'; + +/** XHTML 1.0 Transitional doctype used by classic table-based email templates. */ +export const XHTML_DOCTYPE = + ''; + +export type XhtmlDocumentProps = Omit; + +/** + * Full XHTML transitional document: XHTML doctype, ``, + * no `lang`. Same slots as `document()`; the shell is baked in. + */ +export function xhtmlDocument(props: XhtmlDocumentProps = {}): string { + return document({ + ...props, + doctype: XHTML_DOCTYPE, + lang: false, + htmlAttributes: { xmlns: 'http://www.w3.org/1999/xhtml' }, + }); +} diff --git a/test/index.test.ts b/test/index.test.ts index 5d6dbaa..e0f53e0 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -3,6 +3,8 @@ import { sampleHtml } from '../examples/compose'; import { body } from '../src/templates/body/body'; import { content } from '../src/templates/content/content'; import { document } from '../src/templates/document/document'; +import { xhtmlDocument, XHTML_DOCTYPE } from '../src/templates/document/xhtmlDocument'; +import * as root from '../src/index'; import { footer } from '../src/templates/footer/footer'; import { head } from '../src/templates/head/head'; import { main } from '../src/templates/main/main'; @@ -153,3 +155,20 @@ describe('content', () => { expect(content({ content: '

Hello

' })).toContain('

Hello

'); }); }); + +describe('xhtmlDocument', () => { + it('bakes in the XHTML doctype, xmlns and no lang', () => { + const html = xhtmlDocument({ headHtml: '', mainHtml: '
' }); + expect(html.startsWith(`${XHTML_DOCTYPE}\n`)).toBe( + true, + ); + expect(html).not.toContain('lang='); + expect(html).toContain('
'); + expect(html).not.toContain('undefined'); + }); + + it('works with no props and is exported from the root', () => { + expect(root.xhtmlDocument()).toBe(xhtmlDocument()); + expect(root.XHTML_DOCTYPE).toBe(XHTML_DOCTYPE); + }); +});