@react-email/editor 0.0.0-experimental.41 → 0.0.0-experimental.42

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +0,0 @@
1
- {"version":3,"file":"extension-DyY8_bh4.mjs","names":["acc"],"sources":["../src/plugins/email-theming/css-transforms.ts","../src/plugins/email-theming/themes.ts","../src/plugins/email-theming/normalization.ts","../src/plugins/email-theming/extension.tsx"],"sourcesContent":["import { ensureBorderStyleFallback } from '../../utils/styles';\nimport type { CssJs, PanelGroup } from './types';\n\nexport function transformToCssJs(\n styleArray: PanelGroup[],\n baseFontSize: number,\n): CssJs {\n const cssJS = {} as CssJs;\n\n if (!Array.isArray(styleArray)) {\n return cssJS;\n }\n\n for (const style of styleArray) {\n for (const input of style.inputs) {\n let value = input.value;\n\n // If there's a unit property, append it to the value\n if (input.unit && typeof value === 'number') {\n // if font size prop convert px unit to em to adjust size in mobile\n if (input.prop === 'fontSize') {\n value = `${value / baseFontSize}em`;\n } else {\n value = `${value}${input.unit}`;\n }\n }\n\n if (!input.classReference) {\n continue;\n }\n\n if (!cssJS[input.classReference]) {\n cssJS[input.classReference] = {};\n }\n\n // @ts-expect-error -- backward compatibility: 'h-padding' is a legacy prop not in KnownCssProperties\n if (input.prop === 'h-padding') {\n cssJS[input.classReference].paddingLeft = value;\n cssJS[input.classReference].paddingRight = value;\n\n continue;\n }\n\n // @ts-expect-error -- input.prop is KnownCssProperties but CssJs values are React.CSSProperties; dynamic assignment is intentional\n cssJS[input.classReference][input.prop] = value;\n }\n }\n\n for (const key of Object.keys(cssJS)) {\n ensureBorderStyleFallback(\n cssJS[key as keyof CssJs] as Record<string, string | number>,\n );\n }\n\n return cssJS;\n}\n\nexport function mergeCssJs(original: CssJs, newCssJs: CssJs) {\n const merged = { ...original };\n\n for (const key in newCssJs) {\n const keyType = key as keyof CssJs;\n\n if (\n Object.hasOwn(merged, key) &&\n typeof merged[keyType] === 'object' &&\n !Array.isArray(merged[keyType])\n ) {\n merged[keyType] = {\n ...merged[keyType],\n ...newCssJs[keyType],\n };\n } else {\n merged[keyType] = newCssJs[keyType];\n }\n }\n\n return merged;\n}\n\nexport function injectThemeCss(\n styles: CssJs,\n options: { styleId?: string; scopeSelector?: string } = {},\n) {\n const container =\n options.scopeSelector ?? '.tiptap-extended .tiptap.ProseMirror';\n const prefix = '.node-';\n const styleId = options.styleId ?? 'tiptap-extended-theme-css';\n\n const css = Object.entries(styles).reduce((acc, [key, value]) => {\n const className =\n key === 'body' ? container : `${container} ${prefix}${key}`;\n\n const cssString = Object.entries(value).reduce((acc, [prop, val]) => {\n const normalizeProp = prop.replace(/([A-Z])/g, '-$1').toLowerCase();\n\n return `${acc}${normalizeProp}:${val};`;\n }, '');\n\n return `${acc}${className}{${cssString}}`;\n }, '');\n\n let styleTag = document.getElementById(styleId) as HTMLStyleElement;\n\n if (!styleTag) {\n styleTag = document.createElement('style');\n styleTag.textContent = css;\n styleTag.id = styleId;\n\n document.head.appendChild(styleTag);\n\n return;\n }\n\n styleTag.textContent = css;\n}\n\nexport function injectGlobalPlainCss(\n css?: string | null,\n options: { styleId?: string; scopeSelector?: string } = {},\n) {\n if (!css) {\n return;\n }\n\n const styleId = options.styleId ?? 'global-editor-style';\n const container = options.scopeSelector ?? '.tiptap-extended .ProseMirror';\n let styleElement = document.getElementById(styleId);\n\n if (!styleElement) {\n styleElement = document.createElement('style');\n styleElement.id = styleId;\n document.head.appendChild(styleElement);\n }\n\n // Remove CSS within @media (prefers-color-scheme: dark) blocks\n const cleanedCSS = css.replace(\n /@media\\s?\\(prefers-color-scheme:\\s?dark\\)\\s?{([\\s\\S]+?})\\s*}/g,\n '',\n );\n\n // TODO: Figure out a way to extract the body and apply the styles out of the nested .tiptap-extended\n styleElement.textContent = `${container} { ${cleanedCSS} }`;\n}\n","import type {\n EditorTheme,\n PanelGroup,\n PanelSectionId,\n ResetTheme,\n SupportedCssProperties,\n} from './types';\n\n/**\n * Single source of truth for panel section display titles.\n * Titles are resolved from here at render time via `getPanelTitle`,\n * so they never depend on what's persisted in the DB.\n */\nconst PANEL_SECTION_TITLES: Record<PanelSectionId, string> = {\n body: 'Background',\n container: 'Body',\n typography: 'Text',\n h1: 'Title',\n h2: 'Subtitle',\n h3: 'Heading',\n link: 'Link',\n image: 'Image',\n button: 'Button',\n 'code-block': 'Code Block',\n 'inline-code': 'Inline Code',\n};\n\n/**\n * Resolves the display title for a panel group.\n * Uses the `id` lookup when available, falls back to the\n * DB-persisted `title` for backwards compatibility.\n */\nexport function getPanelTitle(group: PanelGroup): string {\n if (group.id && group.id in PANEL_SECTION_TITLES) {\n return PANEL_SECTION_TITLES[group.id];\n }\n return group.title;\n}\n\nconst THEME_BASIC: PanelGroup[] = [\n {\n id: 'body',\n title: 'Background',\n classReference: 'body',\n inputs: [],\n },\n {\n id: 'container',\n title: 'Content',\n classReference: 'container',\n inputs: [\n {\n label: 'Align',\n type: 'select',\n value: 'left',\n options: {\n left: 'Left',\n center: 'Center',\n right: 'Right',\n },\n prop: 'align',\n classReference: 'container',\n },\n {\n label: 'Width',\n type: 'number',\n value: 600,\n unit: 'px',\n prop: 'width',\n classReference: 'container',\n },\n {\n label: 'Padding Left',\n type: 'number',\n value: 0,\n unit: 'px',\n prop: 'paddingLeft',\n classReference: 'container',\n },\n {\n label: 'Padding Right',\n type: 'number',\n value: 0,\n unit: 'px',\n prop: 'paddingRight',\n classReference: 'container',\n },\n ],\n },\n {\n id: 'typography',\n title: 'Text',\n classReference: 'body',\n inputs: [\n {\n label: 'Font size',\n type: 'number',\n value: 14,\n unit: 'px',\n prop: 'fontSize',\n classReference: 'body',\n },\n {\n label: 'Line Height',\n type: 'number',\n value: 155,\n unit: '%',\n prop: 'lineHeight',\n classReference: 'container',\n },\n ],\n },\n {\n id: 'h1',\n title: 'Title',\n category: 'Text',\n classReference: 'h1',\n inputs: [],\n },\n {\n id: 'h2',\n title: 'Subtitle',\n category: 'Text',\n classReference: 'h2',\n inputs: [],\n },\n {\n id: 'h3',\n title: 'Heading',\n category: 'Text',\n classReference: 'h3',\n inputs: [],\n },\n {\n id: 'link',\n title: 'Link',\n classReference: 'link',\n inputs: [\n {\n label: 'Color',\n type: 'color',\n value: '#0670DB',\n prop: 'color',\n classReference: 'link',\n },\n {\n label: 'Decoration',\n type: 'select',\n value: 'underline',\n prop: 'textDecoration',\n options: {\n underline: 'Underline',\n none: 'None',\n },\n classReference: 'link',\n },\n ],\n },\n {\n id: 'image',\n title: 'Image',\n classReference: 'image',\n inputs: [\n {\n label: 'Border radius',\n type: 'number',\n value: 8,\n unit: 'px',\n prop: 'borderRadius',\n classReference: 'image',\n },\n ],\n },\n {\n id: 'button',\n title: 'Button',\n classReference: 'button',\n inputs: [\n {\n label: 'Background',\n type: 'color',\n value: '#000000',\n prop: 'backgroundColor',\n classReference: 'button',\n },\n {\n label: 'Text color',\n type: 'color',\n value: '#ffffff',\n prop: 'color',\n classReference: 'button',\n },\n {\n label: 'Radius',\n type: 'number',\n value: 4,\n unit: 'px',\n prop: 'borderRadius',\n classReference: 'button',\n },\n {\n label: 'Padding Top',\n type: 'number',\n value: 7,\n unit: 'px',\n prop: 'paddingTop',\n classReference: 'button',\n },\n {\n label: 'Padding Right',\n type: 'number',\n value: 12,\n unit: 'px',\n prop: 'paddingRight',\n classReference: 'button',\n },\n {\n label: 'Padding Bottom',\n type: 'number',\n value: 7,\n unit: 'px',\n prop: 'paddingBottom',\n classReference: 'button',\n },\n {\n label: 'Padding Left',\n type: 'number',\n value: 12,\n unit: 'px',\n prop: 'paddingLeft',\n classReference: 'button',\n },\n ],\n },\n {\n id: 'code-block',\n title: 'Code Block',\n classReference: 'codeBlock',\n inputs: [\n {\n label: 'Border Radius',\n type: 'number',\n value: 4,\n unit: 'px',\n prop: 'borderRadius',\n classReference: 'codeBlock',\n },\n {\n label: 'Padding Top',\n type: 'number',\n value: 12,\n unit: 'px',\n prop: 'paddingTop',\n classReference: 'codeBlock',\n },\n {\n label: 'Padding Bottom',\n type: 'number',\n value: 12,\n unit: 'px',\n prop: 'paddingBottom',\n classReference: 'codeBlock',\n },\n {\n label: 'Padding Left',\n type: 'number',\n value: 16,\n unit: 'px',\n prop: 'paddingLeft',\n classReference: 'codeBlock',\n },\n {\n label: 'Padding Right',\n type: 'number',\n value: 16,\n unit: 'px',\n prop: 'paddingRight',\n classReference: 'codeBlock',\n },\n ],\n },\n {\n id: 'inline-code',\n title: 'Inline Code',\n classReference: 'inlineCode',\n inputs: [\n {\n label: 'Background',\n type: 'color',\n value: '#e5e7eb',\n prop: 'backgroundColor',\n classReference: 'inlineCode',\n },\n {\n label: 'Text color',\n type: 'color',\n value: '#1e293b',\n prop: 'color',\n classReference: 'inlineCode',\n },\n {\n label: 'Radius',\n type: 'number',\n value: 4,\n unit: 'px',\n prop: 'borderRadius',\n classReference: 'inlineCode',\n },\n ],\n },\n];\n\nconst THEME_MINIMAL = THEME_BASIC.map((item) => ({ ...item, inputs: [] }));\n\nconst RESET_BASIC: ResetTheme = {\n reset: {\n margin: '0',\n padding: '0',\n },\n body: {\n fontFamily:\n \"-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif\",\n fontSize: '14px',\n minHeight: '100%',\n lineHeight: '155%',\n },\n container: {},\n h1: {\n fontSize: '2.25em',\n lineHeight: '1.44em',\n paddingTop: '0.389em',\n fontWeight: 600,\n },\n h2: {\n fontSize: '1.8em',\n lineHeight: '1.44em',\n paddingTop: '0.389em',\n fontWeight: 600,\n },\n h3: {\n fontSize: '1.4em',\n lineHeight: '1.08em',\n paddingTop: '0.389em',\n fontWeight: 600,\n },\n paragraph: {\n fontSize: '1em',\n paddingTop: '0.5em',\n paddingBottom: '0.5em',\n },\n list: {\n paddingLeft: '1.1em',\n paddingBottom: '1em',\n },\n nestedList: {\n paddingLeft: '1.1em',\n paddingBottom: '0',\n },\n listItem: {\n marginLeft: '1em',\n marginBottom: '0.3em',\n marginTop: '0.3em',\n },\n listParagraph: { padding: '0', margin: '0' },\n blockquote: {\n borderLeft: '3px solid #acb3be',\n color: '#7e8a9a',\n marginLeft: 0,\n paddingLeft: '0.8em',\n fontSize: '1.1em',\n fontFamily:\n \"-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif\",\n },\n link: { textDecoration: 'underline' },\n footer: {\n fontSize: '0.8em',\n },\n hr: {\n paddingBottom: '1em',\n borderWidth: '2px',\n },\n image: {\n maxWidth: '100%',\n },\n button: {\n lineHeight: '100%',\n display: 'inline-block',\n },\n inlineCode: {\n paddingTop: '0.25em',\n paddingBottom: '0.25em',\n paddingLeft: '0.4em',\n paddingRight: '0.4em',\n background: '#e5e7eb',\n color: '#1e293b',\n borderRadius: '4px',\n },\n codeBlock: {\n fontFamily: 'monospace',\n fontWeight: '500',\n fontSize: '.92em',\n },\n codeTag: {\n lineHeight: '130%',\n fontFamily: 'monospace',\n fontSize: '.92em',\n },\n section: {\n padding: '10px 20px 10px 20px',\n boxSizing: 'border-box' as const,\n },\n};\n\nconst RESET_MINIMAL: ResetTheme = {\n ...Object.keys(RESET_BASIC).reduce<ResetTheme>((acc, key) => {\n acc[key as keyof ResetTheme] = {};\n return acc;\n }, {} as ResetTheme),\n reset: RESET_BASIC.reset,\n};\n\nexport const RESET_THEMES: Record<EditorTheme, ResetTheme> = {\n basic: RESET_BASIC,\n minimal: RESET_MINIMAL,\n};\n\nexport function resolveResetValue(\n value: string | number | undefined,\n targetUnit: 'px' | '%',\n bodyFontSizePx: number,\n): number | undefined {\n if (value === undefined) {\n return undefined;\n }\n const str = String(value);\n const num = Number.parseFloat(str);\n if (Number.isNaN(num)) {\n return undefined;\n }\n if (str.endsWith('em')) {\n return targetUnit === 'px' ? Math.floor(num * bodyFontSizePx) : num * 100;\n }\n return num;\n}\n\nexport const EDITOR_THEMES: Record<EditorTheme, PanelGroup[]> = {\n minimal: THEME_MINIMAL,\n basic: THEME_BASIC,\n};\n\nexport function getThemeBodyFontSizePx(theme: EditorTheme): number {\n for (const group of EDITOR_THEMES[theme]) {\n if (group.classReference !== 'body') {\n continue;\n }\n for (const input of group.inputs) {\n if (input.prop === 'fontSize' && typeof input.value === 'number') {\n return input.value;\n }\n }\n }\n return 14;\n}\n\n/**\n * Use to make the preview nicer once the theme might miss some\n * important properties to make layout accurate\n */\nexport const DEFAULT_INBOX_FONT_SIZE_PX = 14;\nexport const INBOX_EMAIL_DEFAULTS: Partial<ResetTheme> = {\n body: {\n color: '#000000',\n fontFamily:\n \"-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif\",\n fontSize: `${DEFAULT_INBOX_FONT_SIZE_PX}px`,\n lineHeight: '155%',\n },\n container: {\n width: 600,\n },\n};\n\nexport const SUPPORTED_CSS_PROPERTIES: SupportedCssProperties = {\n align: {\n label: 'Align',\n type: 'select',\n options: {\n left: 'Left',\n center: 'Center',\n right: 'Right',\n },\n defaultValue: 'left',\n category: 'layout',\n },\n backgroundColor: {\n label: 'Background',\n type: 'color',\n excludeNodes: ['image', 'youtube'],\n defaultValue: '#ffffff',\n category: 'appearance',\n },\n color: {\n label: 'Text color',\n type: 'color',\n excludeNodes: ['image', 'youtube'],\n defaultValue: '#000000',\n category: 'typography',\n },\n fontSize: {\n label: 'Font size',\n type: 'number',\n unit: 'px',\n excludeNodes: ['image', 'youtube'],\n defaultValue: 14,\n category: 'typography',\n },\n fontWeight: {\n label: 'Font weight',\n type: 'select',\n options: {\n 300: 'Light',\n 400: 'Normal',\n 600: 'Semi Bold',\n 700: 'Bold',\n 800: 'Extra Bold',\n },\n excludeNodes: ['image', 'youtube'],\n defaultValue: 400,\n category: 'typography',\n },\n letterSpacing: {\n label: 'Letter spacing',\n type: 'number',\n unit: 'px',\n excludeNodes: ['image', 'youtube'],\n defaultValue: 0,\n category: 'typography',\n },\n lineHeight: {\n label: 'Line height',\n type: 'number',\n unit: '%',\n defaultValue: 155,\n category: 'typography',\n },\n textDecoration: {\n label: 'Text decoration',\n type: 'select',\n options: {\n none: 'None',\n underline: 'Underline',\n 'line-through': 'Line-through',\n },\n defaultValue: 'none',\n category: 'typography',\n },\n borderRadius: {\n label: 'Border Radius',\n type: 'number',\n unit: 'px',\n defaultValue: 8,\n category: 'appearance',\n },\n borderTopLeftRadius: {\n label: 'Border Radius (Top-Left)',\n type: 'number',\n unit: 'px',\n defaultValue: 8,\n category: 'appearance',\n },\n borderTopRightRadius: {\n label: 'Border Radius (Top-Right)',\n type: 'number',\n unit: 'px',\n defaultValue: 8,\n category: 'appearance',\n },\n borderBottomLeftRadius: {\n label: 'Border Radius (Bottom-Left)',\n type: 'number',\n unit: 'px',\n defaultValue: 8,\n category: 'appearance',\n },\n borderBottomRightRadius: {\n label: 'Border Radius (Bottom-Right)',\n type: 'number',\n unit: 'px',\n defaultValue: 8,\n category: 'appearance',\n },\n borderWidth: {\n label: 'Border Width',\n type: 'number',\n unit: 'px',\n defaultValue: 1,\n category: 'appearance',\n },\n borderTopWidth: {\n label: 'Border Top Width',\n type: 'number',\n unit: 'px',\n defaultValue: 1,\n category: 'appearance',\n },\n borderRightWidth: {\n label: 'Border Right Width',\n type: 'number',\n unit: 'px',\n defaultValue: 1,\n category: 'appearance',\n },\n borderBottomWidth: {\n label: 'Border Bottom Width',\n type: 'number',\n unit: 'px',\n defaultValue: 1,\n category: 'appearance',\n },\n borderLeftWidth: {\n label: 'Border Left Width',\n type: 'number',\n unit: 'px',\n defaultValue: 1,\n category: 'appearance',\n },\n borderStyle: {\n label: 'Border Style',\n type: 'select',\n options: {\n solid: 'Solid',\n dashed: 'Dashed',\n dotted: 'Dotted',\n },\n defaultValue: 'solid',\n category: 'appearance',\n },\n borderTopStyle: {\n label: 'Border Top Style',\n type: 'select',\n options: {\n solid: 'Solid',\n dashed: 'Dashed',\n dotted: 'Dotted',\n },\n defaultValue: 'solid',\n category: 'appearance',\n },\n borderRightStyle: {\n label: 'Border Right Style',\n type: 'select',\n options: {\n solid: 'Solid',\n dashed: 'Dashed',\n dotted: 'Dotted',\n },\n defaultValue: 'solid',\n category: 'appearance',\n },\n borderBottomStyle: {\n label: 'Border Bottom Style',\n type: 'select',\n options: {\n solid: 'Solid',\n dashed: 'Dashed',\n dotted: 'Dotted',\n },\n defaultValue: 'solid',\n category: 'appearance',\n },\n borderLeftStyle: {\n label: 'Border Left Style',\n type: 'select',\n options: {\n solid: 'Solid',\n dashed: 'Dashed',\n dotted: 'Dotted',\n },\n defaultValue: 'solid',\n category: 'appearance',\n },\n borderColor: {\n label: 'Border Color',\n type: 'color',\n defaultValue: '#000000',\n category: 'appearance',\n },\n borderTopColor: {\n label: 'Border Top Color',\n type: 'color',\n defaultValue: '#000000',\n category: 'appearance',\n },\n borderRightColor: {\n label: 'Border Right Color',\n type: 'color',\n defaultValue: '#000000',\n category: 'appearance',\n },\n borderBottomColor: {\n label: 'Border Bottom Color',\n type: 'color',\n defaultValue: '#000000',\n category: 'appearance',\n },\n borderLeftColor: {\n label: 'Border Left Color',\n type: 'color',\n defaultValue: '#000000',\n category: 'appearance',\n },\n padding: {\n label: 'Padding',\n type: 'number',\n unit: 'px',\n defaultValue: 8,\n category: 'layout',\n },\n paddingTop: {\n label: 'Padding Top',\n type: 'number',\n unit: 'px',\n defaultValue: 8,\n category: 'layout',\n },\n paddingLeft: {\n label: 'Padding Left',\n type: 'number',\n unit: 'px',\n defaultValue: 8,\n category: 'layout',\n },\n paddingBottom: {\n label: 'Padding Bottom',\n type: 'number',\n unit: 'px',\n defaultValue: 8,\n category: 'layout',\n },\n paddingRight: {\n label: 'Padding Right',\n type: 'number',\n unit: 'px',\n defaultValue: 8,\n category: 'layout',\n },\n width: {\n label: 'Width',\n type: 'number',\n unit: 'px',\n defaultValue: 600,\n category: 'layout',\n },\n height: {\n label: 'Height',\n type: 'number',\n unit: 'px',\n defaultValue: 400,\n category: 'layout',\n },\n};\n","import { EDITOR_THEMES } from './themes';\nimport type {\n EditorTheme,\n KnownThemeComponents,\n PanelGroup,\n PanelSectionId,\n} from './types';\n\nconst PANEL_SECTION_IDS = new Set<PanelSectionId>([\n 'body',\n 'container',\n 'typography',\n 'link',\n 'image',\n 'button',\n 'code-block',\n 'inline-code',\n]);\n\nconst PANEL_SECTION_IDS_BY_TITLE: Record<string, PanelSectionId> = {\n background: 'body',\n body: 'body',\n content: 'container',\n container: 'container',\n typography: 'typography',\n link: 'link',\n image: 'image',\n button: 'button',\n 'code block': 'code-block',\n 'inline code': 'inline-code',\n};\n\nconst PANEL_SECTION_IDS_BY_CLASS_REFERENCE: Partial<\n Record<KnownThemeComponents, PanelSectionId>\n> = {\n container: 'container',\n link: 'link',\n image: 'image',\n button: 'button',\n codeBlock: 'code-block',\n inlineCode: 'inline-code',\n};\n\nfunction isPanelSectionId(value: unknown): value is PanelSectionId {\n return (\n typeof value === 'string' && PANEL_SECTION_IDS.has(value as PanelSectionId)\n );\n}\n\nfunction normalizeTitle(title: string | undefined): string {\n return title?.trim().toLowerCase().replace(/\\s+/g, ' ') ?? '';\n}\n\nfunction resolvePanelSectionId(group: PanelGroup): PanelSectionId | null {\n if (isPanelSectionId(group.id)) {\n return group.id;\n }\n\n const normalizedTitle = normalizeTitle(group.title);\n\n if (group.classReference === 'body') {\n if (normalizedTitle === 'typography') {\n return 'typography';\n }\n\n return 'body';\n }\n\n if (\n group.classReference &&\n PANEL_SECTION_IDS_BY_CLASS_REFERENCE[group.classReference]\n ) {\n return PANEL_SECTION_IDS_BY_CLASS_REFERENCE[group.classReference] ?? null;\n }\n\n return PANEL_SECTION_IDS_BY_TITLE[normalizedTitle] ?? null;\n}\n\nfunction normalizePanelInputs(\n inputs: PanelGroup['inputs'],\n defaultInputs: PanelGroup['inputs'],\n fallbackClassReference?: KnownThemeComponents,\n): PanelGroup['inputs'] {\n if (!Array.isArray(inputs)) {\n return [];\n }\n\n return inputs.map((input) => {\n const defaultInput = defaultInputs.find(\n (candidate) => candidate.prop === input.prop,\n );\n\n return {\n ...defaultInput,\n ...input,\n classReference:\n input.classReference ??\n defaultInput?.classReference ??\n fallbackClassReference,\n };\n });\n}\n\nexport function inferThemeFromPanelStyles(\n panelStyles: PanelGroup[] | null | undefined,\n): EditorTheme | null {\n if (!Array.isArray(panelStyles) || panelStyles.length === 0) {\n return null;\n }\n\n let finalTheme: EditorTheme | null = null;\n for (const group of panelStyles) {\n if (!Array.isArray(group?.inputs)) {\n finalTheme = null;\n break;\n }\n\n if (group.inputs.length !== 0) {\n finalTheme = 'basic';\n break;\n }\n\n finalTheme = 'minimal';\n }\n\n return finalTheme;\n}\n\nexport function normalizeThemePanelStyles(\n theme: EditorTheme,\n panelStyles: PanelGroup[] | null | undefined,\n): PanelGroup[] | null {\n if (!Array.isArray(panelStyles)) {\n return null;\n }\n\n return panelStyles.map((group) => {\n const panelId = resolvePanelSectionId(group);\n\n if (!panelId) {\n return group;\n }\n\n const defaultGroup = EDITOR_THEMES[theme].find(\n (candidate) => candidate.id === panelId,\n );\n\n if (!defaultGroup) {\n return group;\n }\n\n return {\n ...group,\n id: panelId,\n title: defaultGroup.title,\n classReference: defaultGroup.classReference,\n inputs: normalizePanelInputs(\n group.inputs,\n defaultGroup.inputs,\n defaultGroup.classReference,\n ),\n };\n });\n}\n","import { Body, Head, Html, Preview } from '@react-email/components';\nimport type { Editor, JSONContent } from '@tiptap/core';\nimport { Extension } from '@tiptap/core';\nimport { Plugin, PluginKey } from '@tiptap/pm/state';\nimport { useEditorState } from '@tiptap/react';\nimport type * as React from 'react';\nimport type { SerializerPlugin } from '../../core/serializer/serializer-plugin';\nimport { getGlobalContent } from '../../extensions/global-content';\nimport {\n injectGlobalPlainCss,\n injectThemeCss,\n mergeCssJs,\n transformToCssJs,\n} from './css-transforms';\nimport {\n inferThemeFromPanelStyles,\n normalizeThemePanelStyles,\n} from './normalization';\nimport {\n DEFAULT_INBOX_FONT_SIZE_PX,\n EDITOR_THEMES,\n RESET_THEMES,\n} from './themes';\nimport type {\n CssJs,\n EditorTheme,\n KnownThemeComponents,\n PanelGroup,\n} from './types';\n\n/**\n * Maps a document node (type + attrs) to the theme component key used for style lookup.\n * Centralizes all node-type → theme-component knowledge.\n */\nexport function getThemeComponentKey(\n nodeType: string,\n depth: number,\n attrs: Record<string, unknown> = {},\n): KnownThemeComponents | null {\n switch (nodeType) {\n case 'paragraph':\n if (depth > 0) {\n return 'listParagraph';\n }\n return 'paragraph';\n case 'heading': {\n const level = attrs.level as number | undefined;\n return `h${level ?? 1}` as KnownThemeComponents;\n }\n case 'blockquote':\n return 'blockquote';\n case 'button':\n return 'button';\n case 'container':\n return 'container';\n case 'section':\n return 'section';\n case 'footer':\n return 'footer';\n case 'image':\n return 'image';\n case 'youtube':\n case 'twitter':\n return 'image';\n case 'orderedList':\n case 'bulletList':\n if (depth > 0) {\n return 'nestedList';\n }\n return 'list';\n case 'listItem':\n return 'listItem';\n case 'codeBlock':\n return 'codeBlock';\n case 'code':\n return 'inlineCode';\n case 'link':\n return 'link';\n case 'horizontalRule':\n return 'hr';\n default:\n return null;\n }\n}\n\n/**\n * Returns merged theme styles (reset + panel styles) for the given editor.\n * Use when you have editor access and need the full CssJs map.\n */\nexport function getMergedCssJs(\n theme: EditorTheme,\n panelStyles: PanelGroup[] | undefined,\n): CssJs {\n const panels: PanelGroup[] =\n normalizeThemePanelStyles(theme, panelStyles) ?? EDITOR_THEMES[theme];\n const parsed = transformToCssJs(panels, DEFAULT_INBOX_FONT_SIZE_PX);\n const merged = mergeCssJs(RESET_THEMES[theme], parsed);\n\n return merged;\n}\n\n/**\n * Returns resolved React.CSSProperties for a node when you already have merged CssJs\n * (e.g. in the serializer where there is no editor). Centralizes which theme keys\n * apply to which node type.\n */\nconst RESET_NODE_TYPES = new Set([\n 'body',\n 'bulletList',\n 'container',\n 'button',\n 'columns',\n 'div',\n 'h1',\n 'h2',\n 'h3',\n 'list',\n 'listItem',\n 'listParagraph',\n 'nestedList',\n 'orderedList',\n 'table',\n 'paragraph',\n 'tableCell',\n 'tableHeader',\n 'tableRow',\n 'youtube',\n]);\n\nexport function getResolvedNodeStyles(\n node: JSONContent,\n depth: number,\n mergedCssJs: CssJs,\n): React.CSSProperties {\n const key = getThemeComponentKey(node.type ?? '', depth, node.attrs ?? {});\n if (!key) {\n if (RESET_NODE_TYPES.has(node.type ?? '')) {\n return mergedCssJs.reset ?? {};\n }\n return {};\n }\n const component = mergedCssJs[key] ?? {};\n const shouldReset =\n RESET_NODE_TYPES.has(key) || RESET_NODE_TYPES.has(node.type ?? '');\n if (shouldReset) {\n const reset = mergedCssJs.reset ?? {};\n return { ...reset, ...component };\n }\n return { ...component };\n}\n\nexport function stylesToCss(\n styles: PanelGroup[],\n theme: EditorTheme,\n): Record<KnownThemeComponents, React.CSSProperties> {\n const parsed = transformToCssJs(\n normalizeThemePanelStyles(theme, styles) ?? EDITOR_THEMES[theme],\n DEFAULT_INBOX_FONT_SIZE_PX,\n );\n return mergeCssJs(RESET_THEMES[theme], parsed);\n}\n\nfunction getEmailTheming(editor: Editor) {\n const theme = getEmailTheme(editor);\n const normalizedStyles =\n normalizeThemePanelStyles(theme, getEmailStyles(editor)) ??\n EDITOR_THEMES[theme];\n\n return {\n styles: normalizedStyles,\n theme,\n css: getEmailCss(editor),\n };\n}\n\nexport function useEmailTheming(editor: Editor | null) {\n return useEditorState({\n editor,\n selector({ editor: ed }) {\n if (!ed) {\n return null;\n }\n return getEmailTheming(ed);\n },\n });\n}\n\nfunction getEmailStyles(editor: Editor) {\n return getGlobalContent('styles', editor) as PanelGroup[] | null;\n}\n\n/**\n * Sets the global panel styles on the editor document.\n * Persists into the `GlobalContent` node under the `'styles'` key.\n */\nexport function setGlobalStyles(editor: Editor, styles: PanelGroup[]): boolean {\n return editor.commands.setGlobalContent('styles', styles);\n}\n\n/**\n * Sets the current email theme on the editor document.\n * Persists into the `GlobalContent` node under the `'theme'` key.\n */\nexport function setCurrentTheme(editor: Editor, theme: EditorTheme): boolean {\n return editor.commands.setGlobalContent('theme', theme);\n}\n\n/**\n * Sets the global CSS string injected into the email `<head>`.\n * Persists into the `GlobalContent` node under the `'css'` key.\n */\nexport function setGlobalCssInjected(editor: Editor, css: string): boolean {\n return editor.commands.setGlobalContent('css', css);\n}\n\nfunction getEmailTheme(editor: Editor) {\n const extensionTheme = (\n editor.extensionManager.extensions.find(\n (extension) => extension.name === 'theming',\n ) as { options?: { theme?: EditorTheme } }\n )?.options?.theme;\n if (extensionTheme === 'basic' || extensionTheme === 'minimal') {\n return extensionTheme;\n }\n\n const globalTheme = getGlobalContent('theme', editor) as EditorTheme | null;\n if (globalTheme === 'basic' || globalTheme === 'minimal') {\n return globalTheme;\n }\n\n const inferredTheme = inferThemeFromPanelStyles(getEmailStyles(editor));\n if (inferredTheme) {\n return inferredTheme;\n }\n\n return 'basic';\n}\n\nfunction getEmailCss(editor: Editor) {\n return getGlobalContent('css', editor) as string | null;\n}\n\nexport const EmailTheming = Extension.create<{\n theme?: EditorTheme;\n serializerPlugin: SerializerPlugin;\n}>({\n name: 'theming',\n\n addOptions() {\n return {\n theme: undefined as EditorTheme | undefined,\n serializerPlugin: {\n getNodeStyles(node, depth, editor): React.CSSProperties {\n const theming = getEmailTheming(editor);\n\n return getResolvedNodeStyles(\n node,\n depth,\n getMergedCssJs(theming.theme, theming.styles),\n );\n },\n BaseTemplate({ previewText, children, editor }) {\n const { css: globalCss, styles, theme } = getEmailTheming(editor);\n const mergedStyles = getMergedCssJs(theme, styles);\n\n return (\n <Html>\n <Head>\n <meta content=\"width=device-width\" name=\"viewport\" />\n <meta content=\"IE=edge\" httpEquiv=\"X-UA-Compatible\" />\n <meta name=\"x-apple-disable-message-reformatting\" />\n <meta\n content=\"telephone=no,address=no,email=no,date=no,url=no\"\n name=\"format-detection\"\n />\n\n {globalCss && <style>{globalCss}</style>}\n </Head>\n {previewText && previewText !== '' && (\n <Preview>{previewText}</Preview>\n )}\n\n <Body style={mergedStyles.body}>{children}</Body>\n </Html>\n );\n },\n } satisfies SerializerPlugin,\n };\n },\n\n addProseMirrorPlugins() {\n const { editor } = this;\n const scopeId = `tiptap-theme-${Math.random().toString(36).slice(2, 10)}`;\n const scopeAttribute = 'data-editor-theme-scope';\n const scopeSelector = `.tiptap.ProseMirror[${scopeAttribute}=\"${scopeId}\"]`;\n const themeStyleId = `${scopeId}-theme`;\n const globalStyleId = `${scopeId}-global`;\n\n return [\n new Plugin({\n key: new PluginKey('themingStyleInjector'),\n view(view) {\n let prevStyles: PanelGroup[] | null = null;\n let prevTheme: EditorTheme | null = null;\n let prevCss: string | null = null;\n\n view.dom.setAttribute(scopeAttribute, scopeId);\n\n const sync = () => {\n const theme = getEmailTheme(editor);\n const styles = getEmailStyles(editor);\n const resolvedStyles = styles ?? EDITOR_THEMES[theme];\n const css = getEmailCss(editor);\n\n if (styles !== prevStyles || theme !== prevTheme) {\n prevStyles = styles as PanelGroup[] | null;\n prevTheme = theme;\n const mergedCssJs = getMergedCssJs(theme, resolvedStyles);\n injectThemeCss(mergedCssJs, {\n scopeSelector,\n styleId: themeStyleId,\n });\n }\n\n if (css !== prevCss) {\n prevCss = css;\n injectGlobalPlainCss(css, {\n scopeSelector,\n styleId: globalStyleId,\n });\n }\n };\n\n sync();\n\n return {\n update: sync,\n destroy() {\n document.getElementById(themeStyleId)?.remove();\n document.getElementById(globalStyleId)?.remove();\n view.dom.removeAttribute(scopeAttribute);\n },\n };\n },\n }),\n ];\n },\n});\n"],"mappings":"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AAQ,CACN;GACE,OAAO;GACP,MAAM;GACN,OAAO;GACP,MAAM;GACN,MAAM;GACN,gBAAgB;GACjB,EACD;GACE,OAAO;GACP,MAAM;GACN,OAAO;GACP,MAAM;GACN,MAAM;GACN,gBAAgB;GACjB,CACF;EACF;CACD;EACE,IAAI;EACJ,OAAO;EACP,UAAU;EACV,gBAAgB;EAChB,QAAQ,EAAE;EACX;CACD;EACE,IAAI;EACJ,OAAO;EACP,UAAU;EACV,gBAAgB;EAChB,QAAQ,EAAE;EACX;CACD;EACE,IAAI;EACJ,OAAO;EACP,UAAU;EACV,gBAAgB;EAChB,QAAQ,EAAE;EACX;CACD;EACE,IAAI;EACJ,OAAO;EACP,gBAAgB;EAChB,QAAQ,CACN;GACE,OAAO;GACP,MAAM;GACN,OAAO;GACP,MAAM;GACN,gBAAgB;GACjB,EACD;GACE,OAAO;GACP,MAAM;GACN,OAAO;GACP,MAAM;GACN,SAAS;IACP,WAAW;IACX,MAAM;IACP;GACD,gBAAgB;GACjB,CACF;EACF;CACD;EACE,IAAI;EACJ,OAAO;EACP,gBAAgB;EAChB,QAAQ,CACN;GACE,OAAO;GACP,MAAM;GACN,OAAO;GACP,MAAM;GACN,MAAM;GACN,gBAAgB;GACjB,CACF;EACF;CACD;EACE,IAAI;EACJ,OAAO;EACP,gBAAgB;EAChB,QAAQ;GACN;IACE,OAAO;IACP,MAAM;IACN,OAAO;IACP,MAAM;IACN,gBAAgB;IACjB;GACD;IACE,OAAO;IACP,MAAM;IACN,OAAO;IACP,MAAM;IACN,gBAAgB;IACjB;GACD;IACE,OAAO;IACP,MAAM;IACN,OAAO;IACP,MAAM;IACN,MAAM;IACN,gBAAgB;IACjB;GACD;IACE,OAAO;IACP,MAAM;IACN,OAAO;IACP,MAAM;IACN,MAAM;IACN,gBAAgB;IACjB;GACD;IACE,OAAO;IACP,MAAM;IACN,OAAO;IACP,MAAM;IACN,MAAM;IACN,gBAAgB;IACjB;GACD;IACE,OAAO;IACP,MAAM;IACN,OAAO;IACP,MAAM;IACN,MAAM;IACN,gBAAgB;IACjB;GACD;IACE,OAAO;IACP,MAAM;IACN,OAAO;IACP,MAAM;IACN,MAAM;IACN,gBAAgB;IACjB;GACF;EACF;CACD;EACE,IAAI;EACJ,OAAO;EACP,gBAAgB;EAChB,QAAQ;GACN;IACE,OAAO;IACP,MAAM;IACN,OAAO;IACP,MAAM;IACN,MAAM;IACN,gBAAgB;IACjB;GACD;IACE,OAAO;IACP,MAAM;IACN,OAAO;IACP,MAAM;IACN,MAAM;IACN,gBAAgB;IACjB;GACD;IACE,OAAO;IACP,MAAM;IACN,OAAO;IACP,MAAM;IACN,MAAM;IACN,gBAAgB;IACjB;GACD;IACE,OAAO;IACP,MAAM;IACN,OAAO;IACP,MAAM;IACN,MAAM;IACN,gBAAgB;IACjB;GACD;IACE,OAAO;IACP,MAAM;IACN,OAAO;IACP,MAAM;IACN,MAAM;IACN,gBAAgB;IACjB;GACF;EACF;CACD;EACE,IAAI;EACJ,OAAO;EACP,gBAAgB;EAChB,QAAQ;GACN;IACE,OAAO;IACP,MAAM;IACN,OAAO;IACP,MAAM;IACN,gBAAgB;IACjB;GACD;IACE,OAAO;IACP,MAAM;IACN,OAAO;IACP,MAAM;IACN,gBAAgB;IACjB;GACD;IACE,OAAO;IACP,MAAM;IACN,OAAO;IACP,MAAM;IACN,MAAM;IACN,gBAAgB;IACjB;GACF;EACF;CACF;AAED,MAAM,gBAAgB,YAAY,KAAK,UAAU;CAAE,GAAG;CAAM,QAAQ,EAAE;CAAE,EAAE;AAE1E,MAAM,cAA0B;CAC9B,OAAO;EACL,QAAQ;EACR,SAAS;EACV;CACD,MAAM;EACJ,YACE;EACF,UAAU;EACV,WAAW;EACX,YAAY;EACb;CACD,WAAW,EAAE;CACb,IAAI;EACF,UAAU;EACV,YAAY;EACZ,YAAY;EACZ,YAAY;EACb;CACD,IAAI;EACF,UAAU;EACV,YAAY;EACZ,YAAY;EACZ,YAAY;EACb;CACD,IAAI;EACF,UAAU;EACV,YAAY;EACZ,YAAY;EACZ,YAAY;EACb;CACD,WAAW;EACT,UAAU;EACV,YAAY;EACZ,eAAe;EAChB;CACD,MAAM;EACJ,aAAa;EACb,eAAe;EAChB;CACD,YAAY;EACV,aAAa;EACb,eAAe;EAChB;CACD,UAAU;EACR,YAAY;EACZ,cAAc;EACd,WAAW;EACZ;CACD,eAAe;EAAE,SAAS;EAAK,QAAQ;EAAK;CAC5C,YAAY;EACV,YAAY;EACZ,OAAO;EACP,YAAY;EACZ,aAAa;EACb,UAAU;EACV,YACE;EACH;CACD,MAAM,EAAE,gBAAgB,aAAa;CACrC,QAAQ,EACN,UAAU,SACX;CACD,IAAI;EACF,eAAe;EACf,aAAa;EACd;CACD,OAAO,EACL,UAAU,QACX;CACD,QAAQ;EACN,YAAY;EACZ,SAAS;EACV;CACD,YAAY;EACV,YAAY;EACZ,eAAe;EACf,aAAa;EACb,cAAc;EACd,YAAY;EACZ,OAAO;EACP,cAAc;EACf;CACD,WAAW;EACT,YAAY;EACZ,YAAY;EACZ,UAAU;EACX;CACD,SAAS;EACP,YAAY;EACZ,YAAY;EACZ,UAAU;EACX;CACD,SAAS;EACP,SAAS;EACT,WAAW;EACZ;CACF;AAED,MAAM,gBAA4B;CAChC,GAAG,OAAO,KAAK,YAAY,CAAC,QAAoB,KAAK,QAAQ;AAC3D,MAAI,OAA2B,EAAE;AACjC,SAAO;IACN,EAAE,CAAe;CACpB,OAAO,YAAY;CACpB;AAED,MAAa,eAAgD;CAC3D,OAAO;CACP,SAAS;CACV;AAED,SAAgB,kBACd,OACA,YACA,gBACoB;AACpB,KAAI,UAAU,OACZ;CAEF,MAAM,MAAM,OAAO,MAAM;CACzB,MAAM,MAAM,OAAO,WAAW,IAAI;AAClC,KAAI,OAAO,MAAM,IAAI,CACnB;AAEF,KAAI,IAAI,SAAS,KAAK,CACpB,QAAO,eAAe,OAAO,KAAK,MAAM,MAAM,eAAe,GAAG,MAAM;AAExE,QAAO;;AAGT,MAAa,gBAAmD;CAC9D,SAAS;CACT,OAAO;CACR;AAED,SAAgB,uBAAuB,OAA4B;AACjE,MAAK,MAAM,SAAS,cAAc,QAAQ;AACxC,MAAI,MAAM,mBAAmB,OAC3B;AAEF,OAAK,MAAM,SAAS,MAAM,OACxB,KAAI,MAAM,SAAS,cAAc,OAAO,MAAM,UAAU,SACtD,QAAO,MAAM;;AAInB,QAAO;;;;;;AAOT,MAAa,6BAA6B;AAC1C,MAAa,uBAA4C;CACvD,MAAM;EACJ,OAAO;EACP,YACE;EACF,UAAU,GAAG,2BAA2B;EACxC,YAAY;EACb;CACD,WAAW,EACT,OAAO,KACR;CACF;AAED,MAAa,2BAAmD;CAC9D,OAAO;EACL,OAAO;EACP,MAAM;EACN,SAAS;GACP,MAAM;GACN,QAAQ;GACR,OAAO;GACR;EACD,cAAc;EACd,UAAU;EACX;CACD,iBAAiB;EACf,OAAO;EACP,MAAM;EACN,cAAc,CAAC,SAAS,UAAU;EAClC,cAAc;EACd,UAAU;EACX;CACD,OAAO;EACL,OAAO;EACP,MAAM;EACN,cAAc,CAAC,SAAS,UAAU;EAClC,cAAc;EACd,UAAU;EACX;CACD,UAAU;EACR,OAAO;EACP,MAAM;EACN,MAAM;EACN,cAAc,CAAC,SAAS,UAAU;EAClC,cAAc;EACd,UAAU;EACX;CACD,YAAY;EACV,OAAO;EACP,MAAM;EACN,SAAS;GACP,KAAK;GACL,KAAK;GACL,KAAK;GACL,KAAK;GACL,KAAK;GACN;EACD,cAAc,CAAC,SAAS,UAAU;EAClC,cAAc;EACd,UAAU;EACX;CACD,eAAe;EACb,OAAO;EACP,MAAM;EACN,MAAM;EACN,cAAc,CAAC,SAAS,UAAU;EAClC,cAAc;EACd,UAAU;EACX;CACD,YAAY;EACV,OAAO;EACP,MAAM;EACN,MAAM;EACN,cAAc;EACd,UAAU;EACX;CACD,gBAAgB;EACd,OAAO;EACP,MAAM;EACN,SAAS;GACP,MAAM;GACN,WAAW;GACX,gBAAgB;GACjB;EACD,cAAc;EACd,UAAU;EACX;CACD,cAAc;EACZ,OAAO;EACP,MAAM;EACN,MAAM;EACN,cAAc;EACd,UAAU;EACX;CACD,qBAAqB;EACnB,OAAO;EACP,MAAM;EACN,MAAM;EACN,cAAc;EACd,UAAU;EACX;CACD,sBAAsB;EACpB,OAAO;EACP,MAAM;EACN,MAAM;EACN,cAAc;EACd,UAAU;EACX;CACD,wBAAwB;EACtB,OAAO;EACP,MAAM;EACN,MAAM;EACN,cAAc;EACd,UAAU;EACX;CACD,yBAAyB;EACvB,OAAO;EACP,MAAM;EACN,MAAM;EACN,cAAc;EACd,UAAU;EACX;CACD,aAAa;EACX,OAAO;EACP,MAAM;EACN,MAAM;EACN,cAAc;EACd,UAAU;EACX;CACD,gBAAgB;EACd,OAAO;EACP,MAAM;EACN,MAAM;EACN,cAAc;EACd,UAAU;EACX;CACD,kBAAkB;EAChB,OAAO;EACP,MAAM;EACN,MAAM;EACN,cAAc;EACd,UAAU;EACX;CACD,mBAAmB;EACjB,OAAO;EACP,MAAM;EACN,MAAM;EACN,cAAc;EACd,UAAU;EACX;CACD,iBAAiB;EACf,OAAO;EACP,MAAM;EACN,MAAM;EACN,cAAc;EACd,UAAU;EACX;CACD,aAAa;EACX,OAAO;EACP,MAAM;EACN,SAAS;GACP,OAAO;GACP,QAAQ;GACR,QAAQ;GACT;EACD,cAAc;EACd,UAAU;EACX;CACD,gBAAgB;EACd,OAAO;EACP,MAAM;EACN,SAAS;GACP,OAAO;GACP,QAAQ;GACR,QAAQ;GACT;EACD,cAAc;EACd,UAAU;EACX;CACD,kBAAkB;EAChB,OAAO;EACP,MAAM;EACN,SAAS;GACP,OAAO;GACP,QAAQ;GACR,QAAQ;GACT;EACD,cAAc;EACd,UAAU;EACX;CACD,mBAAmB;EACjB,OAAO;EACP,MAAM;EACN,SAAS;GACP,OAAO;GACP,QAAQ;GACR,QAAQ;GACT;EACD,cAAc;EACd,UAAU;EACX;CACD,iBAAiB;EACf,OAAO;EACP,MAAM;EACN,SAAS;GACP,OAAO;GACP,QAAQ;GACR,QAAQ;GACT;EACD,cAAc;EACd,UAAU;EACX;CACD,aAAa;EACX,OAAO;EACP,MAAM;EACN,cAAc;EACd,UAAU;EACX;CACD,gBAAgB;EACd,OAAO;EACP,MAAM;EACN,cAAc;EACd,UAAU;EACX;CACD,kBAAkB;EAChB,OAAO;EACP,MAAM;EACN,cAAc;EACd,UAAU;EACX;CACD,mBAAmB;EACjB,OAAO;EACP,MAAM;EACN,cAAc;EACd,UAAU;EACX;CACD,iBAAiB;EACf,OAAO;EACP,MAAM;EACN,cAAc;EACd,UAAU;EACX;CACD,SAAS;EACP,OAAO;EACP,MAAM;EACN,MAAM;EACN,c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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"extensions-BvfmaKCn.mjs","names":["Body","Button","ReactEmailButton","CodeBlock","ReactEmailCodeBlock","Container","ReactEmailContainer","useEditor","useTipTapEditor","editor","Heading","TipTapHeading","EmailHeading","Link","ReactEmailLink","tr","Node","Section","ReactEmailSection","Node","Text","BaseText"],"sources":["../src/core/create-drop-handler.ts","../src/utils/paste-sanitizer.ts","../src/core/create-paste-handler.ts","../src/core/serializer/default-base-template.tsx","../src/core/serializer/email-mark.ts","../src/core/serializer/compose-react-email.tsx","../src/extensions/alignment-attribute.tsx","../src/utils/get-text-alignment.ts","../src/extensions/blockquote.tsx","../src/extensions/body.tsx","../src/extensions/bold.tsx","../src/extensions/bullet-list.tsx","../src/extensions/button.tsx","../src/extensions/class-attribute.tsx","../src/extensions/code.tsx","../src/utils/prism-utils.ts","../src/extensions/prism-plugin.ts","../src/extensions/code-block.tsx","../src/utils/is-collaboration.ts","../src/extensions/container.tsx","../src/extensions/div.tsx","../src/core/is-document-visually-empty.ts","../src/core/use-editor.ts","../src/extensions/divider.tsx","../src/extensions/hard-break.tsx","../src/extensions/heading.tsx","../src/extensions/italic.tsx","../src/extensions/preserved-style.tsx","../src/extensions/link.tsx","../src/extensions/list-item.tsx","../src/extensions/max-nesting.ts","../src/extensions/ordered-list.tsx","../src/extensions/paragraph.tsx","../src/extensions/placeholder.ts","../src/extensions/preview-text.ts","../src/extensions/section.tsx","../src/extensions/strike.tsx","../src/extensions/style-attribute.tsx","../src/extensions/sup.tsx","../src/extensions/table.tsx","../src/extensions/text.tsx","../src/extensions/trailing-node.tsx","../src/extensions/underline.tsx","../src/extensions/uppercase.tsx","../src/extensions/index.ts"],"sourcesContent":["import type { EditorView } from '@tiptap/pm/view';\nimport type { PasteHandler, UploadImageHandler } from './create-paste-handler';\n\nexport function createDropHandler({\n onPaste,\n onUploadImage,\n}: {\n onPaste?: PasteHandler;\n onUploadImage?: UploadImageHandler;\n}) {\n return (\n view: EditorView,\n event: DragEvent,\n _slice: unknown,\n moved: boolean,\n ): boolean => {\n if (\n !moved &&\n event.dataTransfer &&\n event.dataTransfer.files &&\n event.dataTransfer.files[0]\n ) {\n event.preventDefault();\n const file = event.dataTransfer.files[0];\n\n if (onPaste?.(file, view)) {\n return true;\n }\n\n if (file.type.includes('image/') && onUploadImage) {\n const coordinates = view.posAtCoords({\n left: event.clientX,\n top: event.clientY,\n });\n\n // here we deduct 1 from the pos or else the image will create an extra node\n void onUploadImage(file, view, (coordinates?.pos || 0) - 1);\n\n return true;\n }\n }\n return false;\n };\n}\n","/**\n * Sanitizes pasted HTML.\n * - From editor (has node-* classes): pass through as-is\n * - From external: strip all styles/classes, keep only semantic HTML\n */\n\n/**\n * Detects content from the Resend editor by checking for node-* class names.\n */\nconst EDITOR_CLASS_PATTERN = /class=\"[^\"]*node-/;\n\n/**\n * Attributes to preserve on specific elements for EXTERNAL content.\n * Only functional attributes - NO style or class.\n */\nconst PRESERVED_ATTRIBUTES: Record<string, string[]> = {\n a: ['href', 'target', 'rel'],\n img: ['src', 'alt', 'width', 'height'],\n td: ['colspan', 'rowspan'],\n th: ['colspan', 'rowspan', 'scope'],\n table: ['border', 'cellpadding', 'cellspacing'],\n '*': ['id'],\n};\n\nfunction isFromEditor(html: string): boolean {\n return EDITOR_CLASS_PATTERN.test(html);\n}\n\nexport function sanitizePastedHtml(html: string): string {\n if (isFromEditor(html)) {\n return html;\n }\n\n const parser = new DOMParser();\n const doc = parser.parseFromString(html, 'text/html');\n\n sanitizeNode(doc.body);\n\n return doc.body.innerHTML;\n}\n\nfunction sanitizeNode(node: Node): void {\n if (node.nodeType === Node.ELEMENT_NODE) {\n const el = node as HTMLElement;\n sanitizeElement(el);\n }\n\n for (const child of Array.from(node.childNodes)) {\n sanitizeNode(child);\n }\n}\n\nfunction sanitizeElement(el: HTMLElement): void {\n const tagName = el.tagName.toLowerCase();\n\n const allowedForTag = PRESERVED_ATTRIBUTES[tagName] || [];\n const allowedGlobal = PRESERVED_ATTRIBUTES['*'] || [];\n const allowed = new Set([...allowedForTag, ...allowedGlobal]);\n\n const attributesToRemove: string[] = [];\n\n for (const attr of Array.from(el.attributes)) {\n if (attr.name.startsWith('data-')) {\n attributesToRemove.push(attr.name);\n continue;\n }\n\n if (!allowed.has(attr.name)) {\n attributesToRemove.push(attr.name);\n }\n }\n\n for (const attr of attributesToRemove) {\n el.removeAttribute(attr);\n }\n}\n","import type { Extensions } from '@tiptap/core';\nimport { generateJSON } from '@tiptap/html';\nimport type { Slice } from '@tiptap/pm/model';\nimport type { EditorView } from '@tiptap/pm/view';\nimport { sanitizePastedHtml } from '../utils/paste-sanitizer';\n\nexport type PasteHandler = (\n payload: string | File,\n view: EditorView,\n) => boolean;\n\nexport type UploadImageHandler = (\n file: File,\n view: EditorView,\n pos: number,\n preserveAttributes?: {\n width?: string;\n height?: string;\n alignment?: string;\n href?: string;\n },\n) => void | Promise<void>;\n\nexport function createPasteHandler({\n onPaste,\n onUploadImage,\n extensions,\n}: {\n onPaste?: PasteHandler;\n onUploadImage?: UploadImageHandler;\n extensions: Extensions;\n}) {\n return (view: EditorView, event: ClipboardEvent, slice: Slice): boolean => {\n const text = event.clipboardData?.getData('text/plain');\n\n if (text && onPaste?.(text, view)) {\n event.preventDefault();\n\n return true;\n }\n\n if (event.clipboardData?.files?.[0]) {\n const file = event.clipboardData.files[0];\n if (onPaste?.(file, view)) {\n event.preventDefault();\n\n return true;\n }\n\n if (file.type.includes('image/') && onUploadImage) {\n const pos = view.state.selection.from;\n void onUploadImage(file, view, pos);\n\n return true;\n }\n }\n\n /**\n * If the coming content has a single child, we can assume\n * it's a plain text and doesn't need to be parsed and\n * be introduced in a new line\n */\n if (slice.content.childCount === 1) {\n return false;\n }\n\n if (event.clipboardData?.getData?.('text/html')) {\n event.preventDefault();\n const html = event.clipboardData.getData('text/html');\n\n // Strip visual styles, keep semantic formatting (bold, italic, links, etc.)\n const sanitizedHtml = sanitizePastedHtml(html);\n\n const jsonContent = generateJSON(sanitizedHtml, extensions);\n const node = view.state.schema.nodeFromJSON(jsonContent);\n\n // Insert the parsed content into the editor at the current selection\n const transaction = view.state.tr.replaceSelectionWith(node, false);\n view.dispatch(transaction);\n\n return true;\n }\n return false;\n };\n}\n","import { Body, Head, Html, Preview } from '@react-email/components';\nimport type * as React from 'react';\n\ntype BaseTemplateProps = {\n children: React.ReactNode;\n previewText?: string;\n};\n\nexport function DefaultBaseTemplate({\n children,\n previewText,\n}: BaseTemplateProps) {\n return (\n <Html>\n <Head>\n <meta content=\"width=device-width\" name=\"viewport\" />\n <meta content=\"IE=edge\" httpEquiv=\"X-UA-Compatible\" />\n <meta name=\"x-apple-disable-message-reformatting\" />\n <meta\n content=\"telephone=no,address=no,email=no,date=no,url=no\"\n name=\"format-detection\"\n />\n </Head>\n {previewText && previewText !== '' && <Preview>{previewText}</Preview>}\n\n <Body>{children}</Body>\n </Html>\n );\n}\n","import {\n type Editor,\n type JSONContent,\n Mark,\n type MarkConfig,\n type MarkType,\n} from '@tiptap/core';\n\nexport type SerializedMark = NonNullable<JSONContent['marks']>[number];\n\nexport type MarkRendererComponent = (props: {\n mark: SerializedMark;\n node: JSONContent;\n style: React.CSSProperties;\n children?: React.ReactNode;\n\n extension: EmailMark<any, any>;\n}) => React.ReactNode;\n\nexport interface EmailMarkConfig<Options, Storage>\n extends MarkConfig<Options, Storage> {\n renderToReactEmail: MarkRendererComponent;\n}\n\ntype ConfigParameter<Options, Storage> = Partial<\n Omit<EmailMarkConfig<Options, Storage>, 'renderToReactEmail'>\n> &\n Pick<EmailMarkConfig<Options, Storage>, 'renderToReactEmail'> &\n ThisType<{\n name: string;\n options: Options;\n storage: Storage;\n editor: Editor;\n type: MarkType;\n parent: (...args: any[]) => any;\n }>;\n\nexport class EmailMark<\n Options = Record<string, never>,\n Storage = Record<string, never>,\n> extends Mark<Options, Storage> {\n declare config: EmailMarkConfig<Options, Storage>;\n\n // biome-ignore lint/complexity/noUselessConstructor: This is only meant to change the types for config, hence why we keep it\n constructor(config: ConfigParameter<Options, Storage>) {\n super(config);\n }\n\n /**\n * Create a new Mark instance\n * @param config - Mark configuration object or a function that returns a configuration object\n */\n static create<O = Record<string, never>, S = Record<string, never>>(\n config: ConfigParameter<O, S> | (() => ConfigParameter<O, S>),\n ) {\n const resolvedConfig = typeof config === 'function' ? config() : config;\n return new EmailMark<O, S>(resolvedConfig);\n }\n\n static from<O, S>(\n mark: Mark<O, S>,\n renderToReactEmail: MarkRendererComponent,\n ): EmailMark<O, S> {\n const customMark = EmailMark.create({} as ConfigParameter<O, S>);\n // This only makes a shallow copy, so if there's nested objects here mutating things will be dangerous\n Object.assign(customMark, { ...mark });\n customMark.config = { ...mark.config, renderToReactEmail };\n return customMark;\n }\n\n // Subclass return types for configure/extend; safe at runtime. TipTap's Mark typings cause TS2416 when returning EmailMark.\n // @ts-expect-error - EmailMark is a valid Mark subclass; base typings don't support subclass return types\n configure(options?: Partial<Options>) {\n return super.configure(options) as EmailMark<Options, Storage>;\n }\n\n // @ts-expect-error - same as configure: extend returns EmailMark for chaining; base typings are incompatible\n extend<\n ExtendedOptions = Options,\n ExtendedStorage = Storage,\n ExtendedConfig extends MarkConfig<\n ExtendedOptions,\n ExtendedStorage\n > = EmailMarkConfig<ExtendedOptions, ExtendedStorage>,\n >(\n extendedConfig?:\n | (() => Partial<ExtendedConfig>)\n | (Partial<ExtendedConfig> &\n ThisType<{\n name: string;\n options: ExtendedOptions;\n storage: ExtendedStorage;\n editor: Editor;\n type: MarkType;\n }>),\n ): EmailMark<ExtendedOptions, ExtendedStorage> {\n const resolvedConfig =\n typeof extendedConfig === 'function' ? extendedConfig() : extendedConfig;\n return super.extend(resolvedConfig) as EmailMark<\n ExtendedOptions,\n ExtendedStorage\n >;\n }\n}\n","import { pretty, render, toPlainText } from '@react-email/components';\nimport type { Editor, JSONContent } from '@tiptap/core';\nimport { inlineCssToJs } from '../../utils/styles';\nimport { DefaultBaseTemplate } from './default-base-template';\nimport { EmailMark } from './email-mark';\nimport { EmailNode } from './email-node';\nimport type { SerializerPlugin } from './serializer-plugin';\n\nconst NODES_WITH_INCREMENTED_CHILD_DEPTH = new Set([\n 'bulletList',\n 'orderedList',\n]);\n\ninterface ComposeReactEmailResult {\n html: string;\n text: string;\n}\n\nexport const composeReactEmail = async ({\n editor,\n preview,\n}: {\n editor: Editor;\n preview?: string;\n}): Promise<ComposeReactEmailResult> => {\n const data = editor.getJSON();\n const extensions = editor.extensionManager.extensions;\n\n const serializerPlugin = extensions\n .map(\n (ext) =>\n (ext as { options?: { serializerPlugin?: SerializerPlugin } }).options\n ?.serializerPlugin,\n )\n .filter((p) => Boolean(p))\n .at(-1);\n\n const typeToExtensionMap = Object.fromEntries(\n extensions.map((extension) => [extension.name, extension]),\n );\n\n function parseContent(content: JSONContent[] | undefined, depth = 0) {\n if (!content) {\n return;\n }\n\n return content.map((node: JSONContent, index: number) => {\n const style = serializerPlugin?.getNodeStyles(node, depth, editor) ?? {};\n\n const inlineStyles = inlineCssToJs(node.attrs?.style);\n\n if (!node.type) {\n return null;\n }\n\n const emailNode = typeToExtensionMap[node.type];\n if (!emailNode || !(emailNode instanceof EmailNode)) {\n return null;\n }\n\n const NodeComponent = emailNode.config.renderToReactEmail;\n const childDepth = NODES_WITH_INCREMENTED_CHILD_DEPTH.has(node.type)\n ? depth + 1\n : depth;\n\n let renderedNode: React.ReactNode = node.text ? (\n node.text\n ) : (\n <NodeComponent\n key={index}\n node={\n node.type === 'table' && inlineStyles.width && !node.attrs?.width\n ? {\n ...node,\n attrs: { ...node.attrs, width: inlineStyles.width },\n }\n : node\n }\n style={style}\n extension={emailNode}\n >\n {parseContent(node.content, childDepth)}\n </NodeComponent>\n );\n if (node.marks) {\n for (const mark of node.marks) {\n const emailMark = typeToExtensionMap[mark.type];\n if (emailMark instanceof EmailMark) {\n const MarkComponent = emailMark.config.renderToReactEmail;\n const markStyle =\n serializerPlugin?.getNodeStyles(\n {\n type: mark.type,\n attrs: mark.attrs ?? {},\n },\n depth,\n editor,\n ) ?? {};\n renderedNode = (\n <MarkComponent\n mark={mark}\n node={node}\n style={markStyle}\n extension={emailMark}\n >\n {renderedNode}\n </MarkComponent>\n );\n }\n }\n }\n\n return renderedNode;\n });\n }\n\n const BaseTemplate = serializerPlugin?.BaseTemplate ?? DefaultBaseTemplate;\n\n const parsedContent = parseContent(data.content);\n const unformattedHtml = await render(\n <BaseTemplate previewText={preview} editor={editor}>\n {parsedContent}\n </BaseTemplate>,\n );\n\n const [prettyHtml, text] = await Promise.all([\n pretty(unformattedHtml),\n toPlainText(unformattedHtml),\n ]);\n\n return { html: prettyHtml, text };\n};\n","import { Extension } from '@tiptap/core';\n\nexport interface AlignmentOptions {\n types: string[];\n alignments: string[];\n}\n\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n alignment: {\n /**\n * Set the text align attribute\n */\n setAlignment: (alignment: string) => ReturnType;\n };\n }\n}\n\nexport const AlignmentAttribute = Extension.create<AlignmentOptions>({\n name: 'alignmentAttribute',\n\n addOptions() {\n return {\n types: [],\n alignments: ['left', 'center', 'right', 'justify'],\n };\n },\n\n addGlobalAttributes() {\n return [\n {\n types: this.options.types,\n attributes: {\n alignment: {\n parseHTML: (element) => {\n const explicitAlign =\n element.getAttribute('align') ||\n element.getAttribute('alignment') ||\n element.style.textAlign;\n if (\n explicitAlign &&\n this.options.alignments.includes(explicitAlign)\n ) {\n return explicitAlign;\n }\n\n // Return null to let natural inheritance work\n return null;\n },\n renderHTML: (attributes) => {\n if (attributes.alignment === 'left') {\n return {};\n }\n\n return { alignment: attributes.alignment };\n },\n },\n },\n },\n ];\n },\n\n addCommands() {\n return {\n setAlignment:\n (alignment) =>\n ({ commands }) => {\n if (!this.options.alignments.includes(alignment)) {\n return false;\n }\n\n return this.options.types.every((type) =>\n commands.updateAttributes(type, { alignment }),\n );\n },\n };\n },\n\n addKeyboardShortcuts() {\n return {\n Enter: () => {\n // Get the current node's alignment\n const { from } = this.editor.state.selection;\n const node = this.editor.state.doc.nodeAt(from);\n const currentAlignment = node?.attrs?.alignment;\n\n if (currentAlignment) {\n requestAnimationFrame(() => {\n // Preserve the current alignment when creating new nodes\n this.editor.commands.setAlignment(currentAlignment);\n });\n }\n\n return false;\n },\n 'Mod-Shift-l': () => this.editor.commands.setAlignment('left'),\n 'Mod-Shift-e': () => this.editor.commands.setAlignment('center'),\n 'Mod-Shift-r': () => this.editor.commands.setAlignment('right'),\n 'Mod-Shift-j': () => this.editor.commands.setAlignment('justify'),\n };\n },\n});\n","export function getTextAlignment(alignment: string | undefined) {\n switch (alignment) {\n case 'left':\n return { textAlign: 'left' } as const;\n case 'center':\n return { textAlign: 'center' } as const;\n case 'right':\n return { textAlign: 'right' } as const;\n default:\n return {};\n }\n}\n","import type { BlockquoteOptions } from '@tiptap/extension-blockquote';\nimport BlockquoteBase from '@tiptap/extension-blockquote';\nimport { EmailNode } from '../core/serializer/email-node';\nimport { getTextAlignment } from '../utils/get-text-alignment';\nimport { inlineCssToJs } from '../utils/styles';\n\nexport const Blockquote: EmailNode<BlockquoteOptions, any> = EmailNode.from(\n BlockquoteBase,\n ({ children, node, style }) => (\n <blockquote\n className={node.attrs?.class || undefined}\n style={{\n ...style,\n ...inlineCssToJs(node.attrs?.style),\n ...getTextAlignment(node.attrs?.align || node.attrs?.alignment),\n }}\n >\n {children}\n </blockquote>\n ),\n);\n","import { mergeAttributes } from '@tiptap/core';\nimport { EmailNode } from '../core/serializer/email-node';\nimport {\n COMMON_HTML_ATTRIBUTES,\n createStandardAttributes,\n LAYOUT_ATTRIBUTES,\n} from '../utils/attribute-helpers';\nimport { inlineCssToJs } from '../utils/styles';\n\nexport interface BodyOptions {\n HTMLAttributes: Record<string, unknown>;\n}\n\nexport const Body = EmailNode.create<BodyOptions>({\n name: 'body',\n\n group: 'block',\n\n content: 'block+',\n\n defining: true,\n isolating: true,\n\n addAttributes() {\n return {\n ...createStandardAttributes([\n ...COMMON_HTML_ATTRIBUTES,\n ...LAYOUT_ATTRIBUTES,\n ]),\n };\n },\n\n parseHTML() {\n return [\n {\n tag: 'body',\n getAttrs: (node) => {\n if (typeof node === 'string') {\n return false;\n }\n const element = node as HTMLElement;\n const attrs: Record<string, string> = {};\n\n // Preserve all attributes\n Array.from(element.attributes).forEach((attr) => {\n attrs[attr.name] = attr.value;\n });\n\n return attrs;\n },\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return [\n 'div',\n mergeAttributes(this.options.HTMLAttributes, HTMLAttributes),\n 0,\n ];\n },\n\n renderToReactEmail({ children, node, style }) {\n const inlineStyles = inlineCssToJs(node.attrs?.style);\n return (\n <div\n className={node.attrs?.class || undefined}\n style={{\n ...style,\n ...inlineStyles,\n }}\n >\n {children}\n </div>\n );\n },\n});\n","import type { BoldOptions as TipTapBoldOptions } from '@tiptap/extension-bold';\nimport BoldBase from '@tiptap/extension-bold';\nimport { EmailMark } from '../core/serializer/email-mark';\n\nexport type BoldOptions = TipTapBoldOptions;\n\nconst BoldWithoutFontWeightInference = BoldBase.extend({\n parseHTML() {\n return [\n {\n tag: 'strong',\n },\n {\n tag: 'b',\n getAttrs: (node) =>\n (node as HTMLElement).style.fontWeight !== 'normal' && null,\n },\n {\n style: 'font-weight=400',\n clearMark: (mark) => mark.type.name === this.name,\n },\n ];\n },\n});\n\nexport const Bold: EmailMark<TipTapBoldOptions, any> = EmailMark.from(\n BoldWithoutFontWeightInference,\n ({ children, style }) => <strong style={style}>{children}</strong>,\n);\n","import type { BulletListOptions } from '@tiptap/extension-bullet-list';\nimport BulletListBase from '@tiptap/extension-bullet-list';\nimport { EmailNode } from '../core/serializer/email-node';\nimport { inlineCssToJs } from '../utils/styles';\n\nexport const BulletList: EmailNode<BulletListOptions, any> = EmailNode.from(\n BulletListBase,\n ({ children, node, style }) => (\n <ul\n className={node.attrs?.class || undefined}\n style={{\n ...style,\n ...inlineCssToJs(node.attrs?.style),\n }}\n >\n {children}\n </ul>\n ),\n);\n","import {\n Column,\n Button as ReactEmailButton,\n Row,\n} from '@react-email/components';\nimport { mergeAttributes } from '@tiptap/core';\nimport { EmailNode } from '../core/serializer/email-node';\nimport { inlineCssToJs } from '../utils/styles';\n\nexport interface EditorButtonOptions {\n HTMLAttributes: Record<string, unknown>;\n [key: string]: unknown;\n}\n\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n button: {\n setButton: () => ReturnType;\n updateButton: (attributes: Record<string, unknown>) => ReturnType;\n };\n }\n}\n\nexport const Button = EmailNode.create<EditorButtonOptions>({\n name: 'button',\n group: 'block',\n content: 'inline*',\n defining: true,\n draggable: true,\n marks: 'bold',\n\n addAttributes() {\n return {\n class: {\n default: 'button',\n },\n href: {\n default: '#',\n },\n alignment: {\n default: 'left',\n },\n };\n },\n\n parseHTML() {\n return [\n {\n tag: 'a[data-id=\"react-email-button\"]',\n getAttrs: (node) => {\n if (typeof node === 'string') {\n return false;\n }\n const element = node as HTMLElement;\n const attrs: Record<string, string> = {};\n\n // Preserve all attributes\n Array.from(element.attributes).forEach((attr) => {\n attrs[attr.name] = attr.value;\n });\n\n return attrs;\n },\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return [\n 'div',\n mergeAttributes({\n class: `align-${HTMLAttributes?.alignment}`,\n }),\n [\n 'a',\n mergeAttributes({\n class: `node-button ${HTMLAttributes?.class}`,\n style: HTMLAttributes?.style,\n 'data-id': 'react-email-button',\n 'data-href': HTMLAttributes?.href,\n }),\n 0,\n ],\n ];\n },\n\n addCommands() {\n return {\n updateButton:\n (attributes) =>\n ({ commands }) => {\n return commands.updateAttributes('button', attributes);\n },\n\n setButton:\n () =>\n ({ commands }) => {\n return commands.insertContent({\n type: 'button',\n content: [\n {\n type: 'text',\n text: 'Button',\n },\n ],\n });\n },\n };\n },\n\n renderToReactEmail({ children, node, style }) {\n const inlineStyles = inlineCssToJs(node.attrs?.style);\n return (\n <Row>\n <Column align={node.attrs?.align || node.attrs?.alignment}>\n <ReactEmailButton\n className={node.attrs?.class || undefined}\n href={node.attrs?.href}\n style={{\n ...style,\n ...inlineStyles,\n }}\n >\n {children}\n </ReactEmailButton>\n </Column>\n </Row>\n );\n },\n});\n","import { Extension } from '@tiptap/core';\n\nexport interface ClassAttributeOptions {\n types: string[];\n class: string[];\n}\n\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n class: {\n /**\n * Set the class attribute\n */\n setClass: (classList: string) => ReturnType;\n /**\n * Unset the class attribute\n */\n unsetClass: () => ReturnType;\n };\n }\n}\n\nexport const ClassAttribute = Extension.create<ClassAttributeOptions>({\n name: 'classAttribute',\n\n addOptions() {\n return {\n types: [],\n class: [],\n };\n },\n\n addGlobalAttributes() {\n return [\n {\n types: this.options.types,\n attributes: {\n class: {\n default: '',\n parseHTML: (element) => element.className || '',\n renderHTML: (attributes) => {\n return attributes.class ? { class: attributes.class } : {};\n },\n },\n },\n },\n ];\n },\n\n addCommands() {\n return {\n unsetClass:\n () =>\n ({ commands }) => {\n return this.options.types.every((type) =>\n commands.resetAttributes(type, 'class'),\n );\n },\n setClass:\n (classList: string) =>\n ({ commands }) => {\n return this.options.types.every((type) =>\n commands.updateAttributes(type, { class: classList }),\n );\n },\n };\n },\n\n addKeyboardShortcuts() {\n return {\n Enter: ({ editor }) => {\n requestAnimationFrame(() => {\n editor.commands.resetAttributes('paragraph', 'class');\n });\n\n return false;\n },\n };\n },\n});\n","import CodeBase from '@tiptap/extension-code';\nimport { EmailMark } from '../core/serializer/email-mark';\nimport { inlineCssToJs } from '../utils/styles';\n\nexport const Code = EmailMark.from(CodeBase, ({ children, node, style }) => (\n <code style={{ ...style, ...inlineCssToJs(node.attrs?.style) }}>\n {children}\n </code>\n));\n","const publicURL = '/styles/prism';\n\nexport function loadPrismTheme(theme: string) {\n // Create new link element for the new theme\n const link = document.createElement('link');\n link.rel = 'stylesheet';\n link.href = `${publicURL}/prism-${theme}.css`;\n link.setAttribute('data-prism-theme', ''); // Mark this link as the Prism theme\n\n // Append the new link element to the head\n document.head.appendChild(link);\n}\n\nexport function removePrismTheme() {\n const existingTheme = document.querySelectorAll(\n 'link[rel=\"stylesheet\"][data-prism-theme]',\n );\n if (existingTheme.length > 0) {\n existingTheme.forEach((cssLinkTag) => {\n cssLinkTag.remove();\n });\n }\n}\n\nexport function hasPrismThemeLoaded(theme: string) {\n const existingTheme = document.querySelector(\n `link[rel=\"stylesheet\"][data-prism-theme][href=\"${publicURL}/prism-${theme}.css\"]`,\n );\n return !!existingTheme;\n}\n","import { findChildren } from '@tiptap/core';\nimport type { Node as ProsemirrorNode } from '@tiptap/pm/model';\nimport { Plugin, PluginKey } from '@tiptap/pm/state';\nimport type { EditorView } from '@tiptap/pm/view';\nimport { Decoration, DecorationSet } from '@tiptap/pm/view';\nimport { fromHtml } from 'hast-util-from-html';\nimport Prism from 'prismjs';\nimport {\n hasPrismThemeLoaded,\n loadPrismTheme,\n removePrismTheme,\n} from '../utils/prism-utils';\n\nconst PRISM_LANGUAGE_LOADED_META = 'prismLanguageLoaded';\n\ninterface RefractorNode {\n properties?: { className: string[] };\n children?: RefractorNode[];\n value?: string;\n}\n\nfunction parseNodes(\n nodes: RefractorNode[],\n className: string[] = [],\n): { text: string; classes: string[] }[] {\n return nodes.flatMap((node) => {\n const classes = [\n ...className,\n ...(node.properties ? node.properties.className : []),\n ];\n\n if (node.children) {\n return parseNodes(node.children, classes);\n }\n\n return {\n text: node.value ?? '',\n classes,\n };\n });\n}\n\nfunction getHighlightNodes(html: string) {\n return fromHtml(html, { fragment: true }).children;\n}\n\nfunction registeredLang(aliasOrLanguage: string) {\n const allSupportLang = Object.keys(Prism.languages).filter(\n (id) => typeof Prism.languages[id] === 'object',\n );\n return Boolean(allSupportLang.find((x) => x === aliasOrLanguage));\n}\n\nfunction getDecorations({\n doc,\n name,\n defaultLanguage,\n defaultTheme,\n loadingLanguages,\n onLanguageLoaded,\n}: {\n doc: ProsemirrorNode;\n name: string;\n defaultLanguage: string | null | undefined;\n defaultTheme: string | null | undefined;\n loadingLanguages: Set<string>;\n onLanguageLoaded: (language: string) => void;\n}) {\n const decorations: Decoration[] = [];\n\n findChildren(doc, (node) => node.type.name === name).forEach((block) => {\n let from = block.pos + 1;\n const language = block.node.attrs.language || defaultLanguage;\n const theme = block.node.attrs.theme || defaultTheme;\n let html = '';\n\n try {\n if (!registeredLang(language) && !loadingLanguages.has(language)) {\n loadingLanguages.add(language);\n import(`prismjs/components/prism-${language}`)\n .then(() => {\n loadingLanguages.delete(language);\n onLanguageLoaded(language);\n })\n .catch(() => {\n loadingLanguages.delete(language);\n });\n }\n\n if (!hasPrismThemeLoaded(theme)) {\n loadPrismTheme(theme);\n }\n\n html = Prism.highlight(\n block.node.textContent,\n Prism.languages[language],\n language,\n );\n } catch {\n html = Prism.highlight(\n block.node.textContent,\n Prism.languages.javascript,\n 'js',\n );\n }\n\n const nodes = getHighlightNodes(html);\n\n parseNodes(nodes as RefractorNode[]).forEach((node) => {\n const to = from + node.text.length;\n\n if (node.classes.length) {\n const decoration = Decoration.inline(from, to, {\n class: node.classes.join(' '),\n });\n\n decorations.push(decoration);\n }\n\n from = to;\n });\n });\n\n return DecorationSet.create(doc, decorations);\n}\n\nexport function PrismPlugin({\n name,\n defaultLanguage,\n defaultTheme,\n}: {\n name: string;\n defaultLanguage: string;\n defaultTheme: string;\n}) {\n if (!defaultLanguage) {\n throw Error('You must specify the defaultLanguage parameter');\n }\n\n const loadingLanguages = new Set<string>();\n let pluginView: EditorView | null = null;\n\n const onLanguageLoaded = (language: string) => {\n if (pluginView) {\n pluginView.dispatch(\n pluginView.state.tr.setMeta(PRISM_LANGUAGE_LOADED_META, language),\n );\n }\n };\n\n const prismjsPlugin: Plugin<DecorationSet> = new Plugin({\n key: new PluginKey('prism'),\n\n view(view) {\n pluginView = view;\n return {\n destroy() {\n pluginView = null;\n },\n };\n },\n\n state: {\n init: (_, { doc }) => {\n return getDecorations({\n doc,\n name,\n defaultLanguage,\n defaultTheme,\n loadingLanguages,\n onLanguageLoaded,\n });\n },\n apply: (transaction, decorationSet, oldState, newState) => {\n const oldNodeName = oldState.selection.$head.parent.type.name;\n const newNodeName = newState.selection.$head.parent.type.name;\n\n const oldNodes = findChildren(\n oldState.doc,\n (node) => node.type.name === name,\n );\n const newNodes = findChildren(\n newState.doc,\n (node) => node.type.name === name,\n );\n\n if (\n transaction.getMeta(PRISM_LANGUAGE_LOADED_META) ||\n (transaction.docChanged &&\n // Apply decorations if:\n // selection includes named node,\n ([oldNodeName, newNodeName].includes(name) ||\n // OR transaction adds/removes named node,\n newNodes.length !== oldNodes.length ||\n // OR transaction has changes that completely encapsulate a node\n // (for example, a transaction that affects the entire document).\n // Such transactions can happen during collab syncing via y-prosemirror, for example.\n transaction.steps.some((step) => {\n const rangeStep = step as unknown as {\n from?: number;\n to?: number;\n };\n return (\n rangeStep.from !== undefined &&\n rangeStep.to !== undefined &&\n oldNodes.some((node) => {\n return (\n node.pos >= rangeStep.from! &&\n node.pos + node.node.nodeSize <= rangeStep.to!\n );\n })\n );\n })))\n ) {\n return getDecorations({\n doc: transaction.doc,\n name,\n defaultLanguage,\n defaultTheme,\n loadingLanguages,\n onLanguageLoaded,\n });\n }\n\n return decorationSet.map(transaction.mapping, transaction.doc);\n },\n },\n\n props: {\n decorations(state) {\n return prismjsPlugin.getState(state);\n },\n },\n\n destroy() {\n pluginView = null;\n removePrismTheme();\n },\n });\n\n return prismjsPlugin;\n}\n","import * as ReactEmailComponents from '@react-email/components';\nimport {\n type PrismLanguage,\n CodeBlock as ReactEmailCodeBlock,\n} from '@react-email/components';\nimport { mergeAttributes } from '@tiptap/core';\nimport type { CodeBlockOptions } from '@tiptap/extension-code-block';\nimport CodeBlock from '@tiptap/extension-code-block';\nimport { TextSelection } from '@tiptap/pm/state';\nimport { EmailNode } from '../core/serializer/email-node';\nimport { PrismPlugin } from './prism-plugin';\n\nexport interface CodeBlockPrismOptions extends CodeBlockOptions {\n defaultLanguage: string;\n defaultTheme: string;\n}\n\nexport const CodeBlockPrism = EmailNode.from(\n CodeBlock.extend<CodeBlockPrismOptions>({\n addOptions(): CodeBlockPrismOptions {\n return {\n languageClassPrefix: 'language-',\n exitOnTripleEnter: false,\n exitOnArrowDown: false,\n enableTabIndentation: true,\n tabSize: 2,\n defaultLanguage: 'javascript',\n defaultTheme: 'default',\n HTMLAttributes: {},\n };\n },\n\n addAttributes() {\n return {\n ...this.parent?.(),\n language: {\n default: this.options.defaultLanguage,\n parseHTML: (element: HTMLElement | null) => {\n if (!element) {\n return null;\n }\n const { languageClassPrefix } = this.options;\n if (!languageClassPrefix) {\n return null;\n }\n const classNames = [\n ...(element.firstElementChild?.classList || []),\n ];\n const languages = classNames\n .filter((className) =>\n className.startsWith(languageClassPrefix || ''),\n )\n .map((className) => className.replace(languageClassPrefix, ''));\n const language = languages[0];\n\n if (!language) {\n return null;\n }\n\n return language;\n },\n rendered: false,\n },\n theme: {\n default: this.options.defaultTheme,\n rendered: false,\n },\n };\n },\n\n renderHTML({ node, HTMLAttributes }) {\n return [\n 'pre',\n mergeAttributes(\n this.options.HTMLAttributes,\n HTMLAttributes,\n {\n class: node.attrs.language\n ? `${this.options.languageClassPrefix}${node.attrs.language}`\n : null,\n },\n { 'data-theme': node.attrs.theme },\n ),\n [\n 'code',\n {\n class: node.attrs.language\n ? `${this.options.languageClassPrefix}${node.attrs.language} node-codeTag`\n : 'node-codeTag',\n },\n 0,\n ],\n ];\n },\n\n addKeyboardShortcuts() {\n return {\n ...this.parent?.(),\n 'Mod-a': ({ editor }) => {\n const { state } = editor;\n const { selection } = state;\n const { $from } = selection;\n\n for (let depth = $from.depth; depth >= 1; depth--) {\n if ($from.node(depth).type.name === this.name) {\n const blockStart = $from.start(depth);\n const blockEnd = $from.end(depth);\n\n const alreadyFullySelected =\n selection.from === blockStart && selection.to === blockEnd;\n if (alreadyFullySelected) {\n return false;\n }\n\n const tr = state.tr.setSelection(\n TextSelection.create(state.doc, blockStart, blockEnd),\n );\n editor.view.dispatch(tr);\n return true;\n }\n }\n\n return false;\n },\n };\n },\n\n addProseMirrorPlugins() {\n return [\n ...(this.parent?.() || []),\n PrismPlugin({\n name: this.name,\n defaultLanguage: this.options.defaultLanguage,\n defaultTheme: this.options.defaultTheme,\n }),\n ];\n },\n }),\n ({ node, style }) => {\n const language = node.attrs?.language\n ? `${node.attrs.language}`\n : 'javascript';\n\n // @ts-expect-error -- @react-email/components does not export theme objects by name; dynamic access needed for user-selected themes\n // biome-ignore lint/performance/noDynamicNamespaceImportAccess: dynamic access needed for user-selected themes\n const userTheme = ReactEmailComponents[node.attrs?.theme];\n\n // Without theme, render a gray code block\n const theme = userTheme\n ? {\n ...userTheme,\n base: {\n ...userTheme.base,\n borderRadius: '0.125rem',\n padding: '0.75rem 1rem',\n },\n }\n : {\n base: {\n color: '#1e293b',\n background: '#f1f5f9',\n lineHeight: '1.5',\n fontFamily:\n '\"Fira Code\", \"Fira Mono\", Menlo, Consolas, \"DejaVu Sans Mono\", monospace',\n padding: '0.75rem 1rem',\n borderRadius: '0.125rem',\n },\n };\n\n return (\n <ReactEmailCodeBlock\n code={node.content?.[0]?.text ?? ''}\n language={language as PrismLanguage}\n theme={theme}\n style={{\n width: 'auto',\n ...style,\n }}\n />\n );\n },\n);\n","import type { Extensions } from '@tiptap/core';\n\nconst COLLABORATION_EXTENSION_NAMES = new Set([\n 'liveblocksExtension',\n 'collaboration',\n]);\n\nexport function hasCollaborationExtension(exts: Extensions): boolean {\n return exts.some((ext) => COLLABORATION_EXTENSION_NAMES.has(ext.name));\n}\n","import { Container as ReactEmailContainer } from '@react-email/components';\nimport { mergeAttributes } from '@tiptap/core';\nimport type { Node as PmNode } from '@tiptap/pm/model';\nimport { type EditorState, Plugin, PluginKey } from '@tiptap/pm/state';\nimport { EmailNode } from '../core/serializer/email-node';\nimport { hasCollaborationExtension } from '../utils/is-collaboration';\nimport { inlineCssToJs } from '../utils/styles';\n\nfunction hasContainerNode(doc: PmNode): boolean {\n let found = false;\n doc.forEach((node) => {\n if (node.type.name === 'container') {\n found = true;\n }\n });\n return found;\n}\n\nfunction wrapInContainer(state: EditorState) {\n const { doc } = state;\n const containerType = state.schema.nodes.container;\n\n const contentNodes: PmNode[] = [];\n const globalContentNodes: PmNode[] = [];\n\n doc.forEach((node) => {\n if (node.type.name === 'globalContent') {\n globalContentNodes.push(node);\n } else {\n contentNodes.push(node);\n }\n });\n\n const containerContent =\n contentNodes.length > 0\n ? contentNodes\n : [state.schema.nodes.paragraph.create()];\n\n const containerNode = containerType.create(null, containerContent);\n\n const newDocContent = [...globalContentNodes, containerNode];\n\n const tr = state.tr;\n tr.replaceWith(0, doc.content.size, newDocContent);\n tr.setMeta('addToHistory', false);\n\n return tr;\n}\n\nexport interface ContainerOptions {\n HTMLAttributes: Record<string, unknown>;\n}\n\nexport const Container = EmailNode.create<ContainerOptions>({\n name: 'container',\n\n group: 'block',\n\n content: 'block+',\n\n defining: true,\n isolating: true,\n selectable: false,\n draggable: false,\n\n addOptions() {\n return {\n HTMLAttributes: {},\n };\n },\n\n parseHTML() {\n return [\n { tag: 'div[data-type=\"container\"]' },\n {\n tag: 'table[role=\"presentation\"]',\n priority: 60,\n getAttrs: (node) => {\n if (typeof node === 'string') {\n return false;\n }\n const table = node as HTMLElement;\n if (!table.style.maxWidth) {\n return false;\n }\n const td = table.querySelector(\n ':scope > tbody > tr:only-child > td:only-child',\n );\n if (!td) {\n return false;\n }\n return null;\n },\n contentElement: (node) =>\n node.querySelector(':scope > tbody > tr > td') as HTMLElement,\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return [\n 'div',\n mergeAttributes(\n { 'data-type': 'container', class: 'node-container' },\n this.options.HTMLAttributes,\n HTMLAttributes,\n ),\n 0,\n ];\n },\n\n addProseMirrorPlugins() {\n const isCollaborative = hasCollaborationExtension(\n this.editor.extensionManager.extensions,\n );\n return [\n new Plugin({\n key: new PluginKey('containerEnforcer'),\n view: isCollaborative\n ? undefined\n : (editorView) => {\n if (!hasContainerNode(editorView.state.doc)) {\n const tr = wrapInContainer(editorView.state);\n editorView.dispatch(tr);\n }\n return {};\n },\n appendTransaction(_transactions, oldState, newState) {\n if (hasContainerNode(newState.doc)) {\n return null;\n }\n\n // This is meant to deal with the weird behavior from Liveblocks's\n // extension. It repeatedly creates transactions that do basically no\n // changes before the actual content of the room arrives. And, if we\n // don't do this, this plugin wraps the initial document from TipTap\n // (an empty paragraph) with a container, and this is then kept in\n // the TipTap, effectively duplicating containers every time someone\n // opens the editor.\n //\n // This check is, at the end of the day, a heuristic and therefore it\n // might fail. It's just not the best solution, the best solution\n // would be for us to either not receive any content update until the\n // contents are actually being set, or to be able to distinguish\n // between \"fake\" transactions and \"real\" transactions in the\n // Liveblocks extension. But, for now, this is what we have.\n //\n // One such case where this fails is if the email's contents are\n // literally the default contents from TipTap, meaning an empty\n // paragraph, it won't wrap, and we have a test for this that's being\n // skipped in container.spec.tsx\n if (newState.doc.eq(oldState.doc)) {\n return null;\n }\n\n return wrapInContainer(newState);\n },\n }),\n ];\n },\n\n renderToReactEmail({ children, node, style }) {\n const inlineStyles = inlineCssToJs(node.attrs?.style);\n\n return (\n <ReactEmailContainer\n className={node.attrs?.class || undefined}\n style={{\n ...style,\n ...inlineStyles,\n width: '100%',\n maxWidth: style?.width ?? style?.maxWidth,\n }}\n >\n {children}\n </ReactEmailContainer>\n );\n },\n});\n","import { mergeAttributes } from '@tiptap/core';\nimport { EmailNode } from '../core/serializer/email-node';\nimport {\n COMMON_HTML_ATTRIBUTES,\n createStandardAttributes,\n LAYOUT_ATTRIBUTES,\n} from '../utils/attribute-helpers';\nimport { inlineCssToJs } from '../utils/styles';\n\nexport interface DivOptions {\n HTMLAttributes: Record<string, unknown>;\n}\n\nexport const Div = EmailNode.create<DivOptions>({\n name: 'div',\n\n group: 'block',\n\n content: 'block+',\n\n defining: true,\n isolating: true,\n\n parseHTML() {\n return [\n {\n tag: 'div:not([data-type])',\n getAttrs: (node) => {\n if (typeof node === 'string') {\n return false;\n }\n const element = node as HTMLElement;\n const attrs: Record<string, string> = {};\n\n // Preserve all attributes\n Array.from(element.attributes).forEach((attr) => {\n attrs[attr.name] = attr.value;\n });\n\n return attrs;\n },\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return [\n 'div',\n mergeAttributes(this.options.HTMLAttributes, HTMLAttributes),\n 0,\n ];\n },\n\n addAttributes() {\n return {\n ...createStandardAttributes([\n ...COMMON_HTML_ATTRIBUTES,\n ...LAYOUT_ATTRIBUTES,\n ]),\n };\n },\n\n renderToReactEmail({ children, node, style }) {\n const inlineStyles = inlineCssToJs(node.attrs?.style);\n return (\n <div\n className={node.attrs?.class || undefined}\n style={{\n ...style,\n ...inlineStyles,\n }}\n >\n {children}\n </div>\n );\n },\n});\n","import type { Node } from '@tiptap/pm/model';\n\nexport function isDocumentVisuallyEmpty(doc: Node): boolean {\n let nonGlobalNodeCount = 0;\n let firstNonGlobalNode: Node | null = null;\n\n for (let index = 0; index < doc.childCount; index += 1) {\n const node = doc.child(index);\n\n if (node.type.name === 'globalContent') {\n continue;\n }\n\n nonGlobalNodeCount += 1;\n\n if (firstNonGlobalNode === null) {\n firstNonGlobalNode = node;\n }\n }\n\n if (nonGlobalNodeCount === 0) {\n return true;\n }\n\n if (nonGlobalNodeCount !== 1) {\n return false;\n }\n\n if (firstNonGlobalNode!.type.name === 'container') {\n return hasOnlyEmptyParagraph(firstNonGlobalNode!);\n }\n\n return isEmptyParagraph(firstNonGlobalNode!);\n}\n\nfunction hasOnlyEmptyParagraph(node: Node): boolean {\n if (node.childCount === 0) {\n return true;\n }\n\n if (node.childCount !== 1) {\n return false;\n }\n\n return isEmptyParagraph(node.child(0));\n}\n\nfunction isEmptyParagraph(node: Node): boolean {\n return node.type.name === 'paragraph' && node.textContent.length === 0;\n}\n","import type { Content, Editor as EditorClass, Extensions } from '@tiptap/core';\nimport { UndoRedo } from '@tiptap/extensions';\nimport {\n type UseEditorOptions,\n useEditorState,\n useEditor as useTipTapEditor,\n} from '@tiptap/react';\nimport * as React from 'react';\nimport { StarterKit } from '../extensions';\nimport { hasCollaborationExtension } from '../utils/is-collaboration';\nimport { createDropHandler } from './create-drop-handler';\nimport {\n createPasteHandler,\n type PasteHandler,\n type UploadImageHandler,\n} from './create-paste-handler';\nimport { isDocumentVisuallyEmpty } from './is-document-visually-empty';\n\ntype Merge<A, B> = A & Omit<B, keyof A>;\n\nexport function useEditor({\n content,\n extensions = [],\n onUpdate,\n onPaste,\n onUploadImage,\n onReady,\n editable = true,\n ...rest\n}: Merge<\n {\n content: Content;\n extensions?: Extensions;\n onUpdate?: (\n editor: EditorClass,\n transaction: { getMeta: (key: string) => unknown },\n ) => void;\n onPaste?: PasteHandler;\n onUploadImage?: UploadImageHandler;\n onReady?: (editor: EditorClass | null) => void;\n editable?: boolean;\n },\n UseEditorOptions\n>) {\n const [contentError, setContentError] = React.useState<Error | null>(null);\n\n const isCollaborative = hasCollaborationExtension(extensions);\n\n const effectiveExtensions: Extensions = React.useMemo(\n () => [\n StarterKit,\n // Collaboration extensions handle their own undo/redo history,\n // so we only add TipTap's History extension for non-collaborative editors.\n ...(isCollaborative ? [] : [UndoRedo]),\n ...extensions,\n ],\n [extensions, isCollaborative],\n );\n\n const editor = useTipTapEditor({\n content: isCollaborative ? undefined : content,\n extensions: effectiveExtensions,\n editable,\n immediatelyRender: false,\n enableContentCheck: true,\n onContentError({ editor, error, disableCollaboration }) {\n disableCollaboration();\n setContentError(error);\n console.error(error);\n editor.setEditable(false);\n },\n onCreate({ editor }) {\n onReady?.(editor);\n },\n onUpdate({ editor, transaction }) {\n onUpdate?.(editor, transaction);\n },\n editorProps: {\n handleDOMEvents: {\n // Keep link behavior interception for view mode only.\n click: (view, event) => {\n if (!view.editable) {\n const target = event.target as HTMLElement;\n const link = target.closest('a');\n if (link) {\n event.preventDefault();\n return true;\n }\n }\n return false;\n },\n },\n handlePaste: createPasteHandler({\n onPaste,\n onUploadImage,\n extensions: effectiveExtensions,\n }),\n handleDrop: createDropHandler({\n onPaste,\n onUploadImage,\n }),\n },\n ...rest,\n });\n\n const isEditorEmpty = useEditorState({\n editor,\n selector: (context) => {\n if (!context.editor) {\n return true;\n }\n\n return isDocumentVisuallyEmpty(context.editor.state.doc);\n },\n });\n\n return {\n editor,\n isEditorEmpty: isEditorEmpty ?? true,\n extensions: effectiveExtensions,\n contentError,\n isCollaborative,\n };\n}\n","import { Hr } from '@react-email/components';\nimport { InputRule } from '@tiptap/core';\nimport type { HorizontalRuleOptions } from '@tiptap/extension-horizontal-rule';\nimport HorizontalRule from '@tiptap/extension-horizontal-rule';\n\nexport type DividerOptions = HorizontalRuleOptions;\n\nimport { NodeViewWrapper, ReactNodeViewRenderer } from '@tiptap/react';\nimport { EmailNode } from '../core';\nimport { inlineCssToJs } from '../utils/styles';\n\nexport const Divider: EmailNode<HorizontalRuleOptions, any> = EmailNode.from(\n HorizontalRule.extend({\n addAttributes() {\n return {\n class: {\n default: 'divider',\n },\n };\n },\n // patch to fix horizontal rule bug: https://github.com/ueberdosis/tiptap/pull/3859#issuecomment-1536799740\n addInputRules() {\n return [\n new InputRule({\n find: /^(?:---|—-|___\\s|\\*\\*\\*\\s)$/,\n handler: ({ state, range }) => {\n const attributes = {};\n\n const { tr } = state;\n const start = range.from;\n const end = range.to;\n\n tr.insert(start - 1, this.type.create(attributes)).delete(\n tr.mapping.map(start),\n tr.mapping.map(end),\n );\n },\n }),\n ];\n },\n addNodeView() {\n return ReactNodeViewRenderer((props) => {\n const node = props.node;\n const { class: className, ...rest } = node.attrs;\n\n const attrs = {\n ...rest,\n className: 'node-hr',\n style: inlineCssToJs(node.attrs.style),\n };\n\n return (\n <NodeViewWrapper>\n <Hr {...attrs} />\n </NodeViewWrapper>\n );\n });\n },\n }),\n ({ node, style }) => {\n return (\n <Hr\n className={node.attrs?.class || undefined}\n style={{ ...style, ...inlineCssToJs(node.attrs?.style) }}\n />\n );\n },\n);\n","import type { HardBreakOptions } from '@tiptap/extension-hard-break';\nimport HardBreakBase from '@tiptap/extension-hard-break';\nimport { EmailNode } from '../core/serializer/email-node';\n\nexport const HardBreak: EmailNode<HardBreakOptions, any> = EmailNode.from(\n HardBreakBase,\n () => <br />,\n);\n","import { Heading as EmailHeading } from '@react-email/components';\nimport type { HeadingOptions as TipTapHeadingOptions } from '@tiptap/extension-heading';\nimport { Heading as TipTapHeading } from '@tiptap/extension-heading';\n\nexport type HeadingOptions = TipTapHeadingOptions;\n\nimport {\n NodeViewContent,\n NodeViewWrapper,\n ReactNodeViewRenderer,\n} from '@tiptap/react';\nimport { EmailNode } from '../core';\nimport { getTextAlignment } from '../utils/get-text-alignment';\nimport { inlineCssToJs } from '../utils/styles';\n\nexport const Heading: EmailNode<TipTapHeadingOptions, any> = EmailNode.from(\n TipTapHeading.extend({\n addNodeView() {\n return ReactNodeViewRenderer(({ node }) => {\n const level = (node.attrs.level as number) ?? 1;\n const { class: className, ...rest } = node.attrs;\n\n const attrs = {\n ...rest,\n className: `node-h${level} ${className}`,\n style: inlineCssToJs(node.attrs.style),\n };\n\n return (\n <NodeViewWrapper>\n <EmailHeading as={`h${level}` as 'h1' | 'h2' | 'h3'} {...attrs}>\n <NodeViewContent />\n </EmailHeading>\n </NodeViewWrapper>\n );\n });\n },\n }),\n ({ children, node, style }) => {\n const level = node.attrs?.level ?? 1;\n return (\n <EmailHeading\n as={`h${level}` as 'h1' | 'h2' | 'h3'}\n className={node.attrs?.class || undefined}\n style={{\n ...style,\n ...inlineCssToJs(node.attrs?.style),\n ...getTextAlignment(node.attrs?.align ?? node.attrs?.alignment),\n }}\n >\n {children}\n </EmailHeading>\n );\n },\n);\n","import type { ItalicOptions } from '@tiptap/extension-italic';\nimport ItalicBase from '@tiptap/extension-italic';\nimport { EmailMark } from '../core/serializer/email-mark';\n\nexport const Italic: EmailMark<ItalicOptions, any> = EmailMark.from(\n ItalicBase,\n ({ children, style }) => <em style={style}>{children}</em>,\n);\n","import { mergeAttributes } from '@tiptap/core';\nimport { EmailMark } from '../core/serializer/email-mark';\nimport { inlineCssToJs } from '../utils/styles';\n\nexport const PreservedStyle = EmailMark.create({\n name: 'preservedStyle',\n\n addAttributes() {\n return {\n style: {\n default: null,\n parseHTML: (element) => element.getAttribute('style'),\n renderHTML: (attributes) => {\n if (!attributes.style) {\n return {};\n }\n return { style: attributes.style };\n },\n },\n };\n },\n\n parseHTML() {\n return [\n {\n tag: 'span[style]',\n getAttrs: (element) => {\n if (typeof element === 'string') {\n return false;\n }\n const style = element.getAttribute('style');\n if (style && hasPreservableStyles(style)) {\n return { style };\n }\n return false;\n },\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return ['span', mergeAttributes(HTMLAttributes), 0];\n },\n\n renderToReactEmail({ children, mark }) {\n const preservedStyles = mark.attrs?.style\n ? inlineCssToJs(mark.attrs.style)\n : undefined;\n\n return <span style={preservedStyles}>{children}</span>;\n },\n});\n\nconst LINK_INDICATOR_STYLES = [\n 'color',\n 'text-decoration',\n 'text-decoration-line',\n 'text-decoration-color',\n 'text-decoration-style',\n];\n\nfunction parseStyleString(styleString: string): CSSStyleDeclaration {\n const temp = document.createElement('div');\n temp.style.cssText = styleString;\n return temp.style;\n}\n\nfunction hasBackground(style: CSSStyleDeclaration): boolean {\n const bgColor = style.backgroundColor;\n const bg = style.background;\n\n if (bgColor && bgColor !== 'transparent' && bgColor !== 'rgba(0, 0, 0, 0)') {\n return true;\n }\n\n if (\n bg &&\n bg !== 'transparent' &&\n bg !== 'none' &&\n bg !== 'rgba(0, 0, 0, 0)'\n ) {\n return true;\n }\n\n return false;\n}\n\nfunction hasPreservableStyles(styleString: string): boolean {\n return processStylesForUnlink(styleString) !== null;\n}\n\n/**\n * Processes styles when unlinking:\n * - Has background (button-like): preserve all styles\n * - No background: strip link-indicator styles (color, text-decoration), keep the rest\n */\nexport function processStylesForUnlink(\n styleString: string | null | undefined,\n): string | null {\n if (!styleString) {\n return null;\n }\n\n const style = parseStyleString(styleString);\n\n if (hasBackground(style)) {\n return styleString;\n }\n\n const filtered: string[] = [];\n\n for (let i = 0; i < style.length; i++) {\n const prop = style[i];\n\n if (LINK_INDICATOR_STYLES.includes(prop)) {\n continue;\n }\n\n const value = style.getPropertyValue(prop);\n if (value) {\n filtered.push(`${prop}: ${value}`);\n }\n }\n\n return filtered.length > 0 ? filtered.join('; ') : null;\n}\n","import { Link as ReactEmailLink } from '@react-email/components';\nimport type { LinkOptions as TipTapLinkOptions } from '@tiptap/extension-link';\nimport TiptapLink from '@tiptap/extension-link';\n\nexport type LinkOptions = TipTapLinkOptions;\n\nimport { editorEventBus } from '../core';\nimport { EmailMark } from '../core/serializer/email-mark';\nimport { inlineCssToJs } from '../utils/styles';\nimport { processStylesForUnlink } from './preserved-style';\n\nexport const Link: EmailMark<TipTapLinkOptions, any> = EmailMark.from(\n TiptapLink,\n ({ children, mark, style }) => {\n const linkMarkStyle = mark.attrs?.style\n ? inlineCssToJs(mark.attrs.style)\n : {};\n\n return (\n <ReactEmailLink\n href={mark.attrs?.href ?? undefined}\n rel={mark.attrs?.rel ?? undefined}\n style={{\n ...style,\n ...linkMarkStyle,\n }}\n target={mark.attrs?.target ?? undefined}\n {...(mark.attrs?.['ses:no-track']\n ? { 'ses:no-track': mark.attrs['ses:no-track'] }\n : {})}\n >\n {children}\n </ReactEmailLink>\n );\n },\n).extend({\n parseHTML() {\n return [\n {\n tag: 'a[target]:not([data-id=\"react-email-button\"])',\n getAttrs: (node) => {\n if (typeof node === 'string') {\n return false;\n }\n const element = node as HTMLElement;\n const attrs: Record<string, string> = {};\n\n // Preserve all attributes\n Array.from(element.attributes).forEach((attr) => {\n attrs[attr.name] = attr.value;\n });\n\n return attrs;\n },\n },\n {\n tag: 'a[href]:not([data-id=\"react-email-button\"])',\n getAttrs: (node) => {\n if (typeof node === 'string') {\n return false;\n }\n const element = node as HTMLElement;\n const attrs: Record<string, string> = {};\n\n // Preserve all attributes\n Array.from(element.attributes).forEach((attr) => {\n attrs[attr.name] = attr.value;\n });\n\n return attrs;\n },\n },\n ];\n },\n\n addAttributes() {\n return {\n ...this.parent?.(),\n\n 'ses:no-track': {\n default: null,\n parseHTML: (element) => element.getAttribute('ses:no-track'),\n },\n };\n },\n\n addCommands() {\n return {\n ...this.parent?.(),\n\n unsetLink:\n () =>\n ({ state, chain }) => {\n const { from } = state.selection;\n const linkMark = state.doc\n .resolve(from)\n .marks()\n .find((m) => m.type.name === 'link');\n const linkStyle = linkMark?.attrs?.style ?? null;\n\n const preservedStyle = processStylesForUnlink(linkStyle);\n\n const shouldRemoveUnderline = preservedStyle !== linkStyle;\n\n if (preservedStyle) {\n const cmd = chain()\n .extendMarkRange('link')\n .unsetMark('link')\n .setMark('preservedStyle', { style: preservedStyle });\n\n return shouldRemoveUnderline\n ? cmd.unsetMark('underline').run()\n : cmd.run();\n }\n\n return chain()\n .extendMarkRange('link')\n .unsetMark('link')\n .unsetMark('underline')\n .run();\n },\n };\n },\n\n addKeyboardShortcuts() {\n return {\n 'Mod-k': () => {\n editorEventBus.dispatch('bubble-menu:add-link', undefined);\n // unselect\n return this.editor.chain().focus().toggleLink({ href: '' }).run();\n },\n };\n },\n});\n","import type { ListItemOptions } from '@tiptap/extension-list-item';\nimport ListItemBase from '@tiptap/extension-list-item';\nimport { EmailNode } from '../core/serializer/email-node';\nimport { getTextAlignment } from '../utils/get-text-alignment';\nimport { inlineCssToJs } from '../utils/styles';\n\nexport const ListItem: EmailNode<ListItemOptions, any> = EmailNode.from(\n ListItemBase,\n ({ children, node, style }) => (\n <li\n className={node.attrs?.class || undefined}\n style={{\n ...style,\n ...inlineCssToJs(node.attrs?.style),\n ...getTextAlignment(node.attrs?.align || node.attrs?.alignment),\n }}\n >\n {children}\n </li>\n ),\n);\n","import { Extension } from '@tiptap/core';\nimport type { NodeRange } from '@tiptap/pm/model';\nimport { Plugin, PluginKey } from '@tiptap/pm/state';\n\nexport interface MaxNestingOptions {\n maxDepth: number;\n nodeTypes?: string[];\n}\n\nexport const MaxNesting = Extension.create<MaxNestingOptions>({\n name: 'maxNesting',\n\n addOptions() {\n return {\n maxDepth: 3,\n nodeTypes: undefined,\n };\n },\n\n addProseMirrorPlugins() {\n const { maxDepth, nodeTypes } = this.options;\n\n if (typeof maxDepth !== 'number' || maxDepth < 1) {\n throw new Error('maxDepth must be a positive number');\n }\n\n return [\n new Plugin({\n key: new PluginKey('maxNesting'),\n\n appendTransaction(transactions, _oldState, newState) {\n const docChanged = transactions.some((tr) => tr.docChanged);\n if (!docChanged) {\n return null;\n }\n\n // Collect all ranges that need to be lifted\n const rangesToLift: { range: NodeRange; target: number }[] = [];\n\n newState.doc.descendants((node, pos) => {\n let depth = 0;\n let currentPos = pos;\n let currentNode = node;\n\n while (currentNode && depth <= maxDepth) {\n if (!nodeTypes || nodeTypes.includes(currentNode.type.name)) {\n depth++;\n }\n\n const $pos = newState.doc.resolve(currentPos);\n if ($pos.depth === 0) {\n break;\n }\n\n currentPos = $pos.before($pos.depth);\n currentNode = newState.doc.nodeAt(currentPos)!;\n }\n\n if (depth > maxDepth) {\n const $pos = newState.doc.resolve(pos);\n if ($pos.depth > 0) {\n const range = $pos.blockRange();\n if (\n range &&\n 'canReplace' in newState.schema.nodes.doc &&\n typeof newState.schema.nodes.doc.canReplace === 'function' &&\n newState.schema.nodes.doc.canReplace(\n range.start - 1,\n range.end + 1,\n newState.doc.slice(range.start, range.end).content,\n )\n ) {\n rangesToLift.push({ range, target: range.start - 1 });\n }\n }\n }\n });\n\n if (rangesToLift.length === 0) {\n return null;\n }\n\n // Process ranges in reverse order (end to start) to maintain position validity\n const tr = newState.tr;\n for (let i = rangesToLift.length - 1; i >= 0; i--) {\n const { range, target } = rangesToLift[i];\n tr.lift(range, target);\n }\n\n return tr;\n },\n\n filterTransaction(tr) {\n if (!tr.docChanged) {\n return true;\n }\n\n let wouldCreateDeepNesting = false;\n const newDoc = tr.doc;\n\n newDoc.descendants((node, pos) => {\n if (wouldCreateDeepNesting) {\n return false;\n }\n\n let depth = 0;\n let currentPos = pos;\n let currentNode = node;\n\n while (currentNode && depth <= maxDepth) {\n if (!nodeTypes || nodeTypes.includes(currentNode.type.name)) {\n depth++;\n }\n\n const $pos = newDoc.resolve(currentPos);\n if ($pos.depth === 0) {\n break;\n }\n\n currentPos = $pos.before($pos.depth);\n currentNode = newDoc.nodeAt(currentPos)!;\n }\n\n if (depth > maxDepth) {\n wouldCreateDeepNesting = true;\n return false;\n }\n });\n\n return !wouldCreateDeepNesting;\n },\n }),\n ];\n },\n});\n","import type { OrderedListOptions } from '@tiptap/extension-ordered-list';\nimport OrderedListBase from '@tiptap/extension-ordered-list';\nimport { EmailNode } from '../core/serializer/email-node';\nimport { inlineCssToJs } from '../utils/styles';\n\nexport const OrderedList: EmailNode<OrderedListOptions, any> = EmailNode.from(\n OrderedListBase,\n ({ children, node, style }) => (\n <ol\n className={node.attrs?.class || undefined}\n start={node.attrs?.start}\n style={{\n ...style,\n ...inlineCssToJs(node.attrs?.style),\n }}\n >\n {children}\n </ol>\n ),\n);\n","import type { ParagraphOptions } from '@tiptap/extension-paragraph';\nimport ParagraphBase from '@tiptap/extension-paragraph';\nimport { EmailNode } from '../core/serializer/email-node';\nimport { getTextAlignment } from '../utils/get-text-alignment';\nimport { inlineCssToJs } from '../utils/styles';\n\nexport const Paragraph: EmailNode<ParagraphOptions, any> = EmailNode.from(\n ParagraphBase,\n ({ children, node, style }) => {\n const isEmpty = !node.content || node.content.length === 0;\n\n return (\n <p\n className={node.attrs?.class || undefined}\n style={{\n ...style,\n ...inlineCssToJs(node.attrs?.style),\n ...getTextAlignment(node.attrs?.align || node.attrs?.alignment),\n }}\n >\n {isEmpty ? (\n /* Add <br/> inside empty paragraph to make sure what users sees in the preview is the space that will be render in the email */\n <br />\n ) : (\n children\n )}\n </p>\n );\n },\n);\n","import type { Extension } from '@tiptap/core';\nimport type { PlaceholderOptions as TipTapPlaceholderOptions } from '@tiptap/extension-placeholder';\nimport TipTapPlaceholder from '@tiptap/extension-placeholder';\nimport type { Node } from '@tiptap/pm/model';\n\nexport interface PlaceholderOptions {\n placeholder?: string | ((props: { node: Node }) => string);\n includeChildren?: boolean;\n}\n\nexport const Placeholder: Extension<TipTapPlaceholderOptions, any> =\n TipTapPlaceholder.configure({\n placeholder: ({ node }) => {\n if (node.type.name === 'heading') {\n return `Heading ${node.attrs.level}`;\n }\n return \"Press '/' for commands\";\n },\n includeChildren: true,\n });\n","import { Node } from '@tiptap/core';\n\nexport interface PreviewTextOptions {\n HTMLAttributes: Record<string, unknown>;\n}\n\nexport const PreviewText = Node.create<PreviewTextOptions>({\n name: 'previewText',\n\n group: 'block',\n\n selectable: false,\n draggable: false,\n atom: true,\n\n addOptions() {\n return {\n HTMLAttributes: {},\n };\n },\n\n addStorage() {\n return {\n previewText: null,\n };\n },\n\n renderHTML() {\n return ['div', { style: 'display: none' }];\n },\n\n parseHTML() {\n return [\n // react-email parsing\n {\n tag: 'div[data-skip-in-text=\"true\"]',\n getAttrs: (node) => {\n if (typeof node === 'string') {\n return false;\n }\n const element = node as HTMLElement;\n\n // Extract and store preview text directly\n let directText = '';\n for (const child of element.childNodes) {\n if (child.nodeType === 3) {\n // TEXT_NODE = 3\n // Anything other than text will be pruned\n // This is particularly useful for react email,\n // because we have a nested div full of white spaces that will just be ignored\n directText += child.textContent || '';\n }\n }\n const cleanText = directText.trim();\n\n if (cleanText) {\n this.storage.previewText = cleanText;\n }\n\n return false; // Don't create a node\n },\n },\n // preheader class parsing\n {\n tag: 'span.preheader',\n getAttrs: (node) => {\n if (typeof node === 'string') {\n return false;\n }\n const element = node as HTMLElement;\n const preheaderText = element.textContent?.trim();\n\n if (preheaderText) {\n this.storage.previewText = preheaderText;\n }\n\n return false; // Don't create a node, just extract to storage\n },\n },\n ];\n },\n});\n","import { Section as ReactEmailSection } from '@react-email/components';\nimport { mergeAttributes } from '@tiptap/core';\nimport type * as React from 'react';\nimport { EmailNode } from '../core/serializer/email-node';\nimport { getTextAlignment } from '../utils/get-text-alignment';\nimport { inlineCssToJs } from '../utils/styles';\n\nexport interface SectionOptions {\n HTMLAttributes: Record<string, unknown>;\n [key: string]: unknown;\n}\n\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n section: {\n insertSection: () => ReturnType;\n };\n }\n}\n\nexport const Section = EmailNode.create<SectionOptions>({\n name: 'section',\n group: 'block',\n content: 'block+',\n isolating: true,\n defining: true,\n\n parseHTML() {\n return [{ tag: 'section[data-type=\"section\"]' }];\n },\n\n renderHTML({ HTMLAttributes }) {\n return [\n 'section',\n mergeAttributes(\n { 'data-type': 'section', class: 'node-section' },\n HTMLAttributes,\n ),\n 0,\n ];\n },\n\n addCommands() {\n return {\n insertSection:\n () =>\n ({ commands }) => {\n return commands.insertContent({\n type: this.name,\n content: [\n {\n type: 'paragraph',\n content: [],\n },\n ],\n });\n },\n };\n },\n\n renderToReactEmail({ children, node, style }) {\n const inlineStyles = inlineCssToJs(node.attrs?.style);\n const textAlign = node.attrs?.align || node.attrs?.alignment;\n\n return (\n <ReactEmailSection\n className={node.attrs?.class || undefined}\n align={textAlign}\n style={\n {\n ...style,\n ...inlineStyles,\n ...getTextAlignment(textAlign),\n } as React.CSSProperties\n }\n >\n {children}\n </ReactEmailSection>\n );\n },\n});\n","import type { StrikeOptions } from '@tiptap/extension-strike';\nimport StrikeBase from '@tiptap/extension-strike';\nimport { EmailMark } from '../core/serializer/email-mark';\n\nexport const Strike: EmailMark<StrikeOptions, any> = EmailMark.from(\n StrikeBase,\n ({ children, style }) => <s style={style}>{children}</s>,\n);\n","import { Extension } from '@tiptap/core';\n\nexport interface StyleAttributeOptions {\n types: string[];\n style: string[];\n}\n\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n textAlign: {\n /**\n * Set the style attribute\n */\n setStyle: (style: string) => ReturnType;\n /**\n * Unset the style attribute\n */\n unsetStyle: () => ReturnType;\n };\n }\n}\n\nexport const StyleAttribute = Extension.create<StyleAttributeOptions>({\n name: 'styleAttribute',\n priority: 101,\n\n addOptions() {\n return {\n types: [],\n style: [],\n };\n },\n\n addGlobalAttributes() {\n return [\n {\n types: this.options.types,\n attributes: {\n style: {\n default: '',\n parseHTML: (element) => element.getAttribute('style') || '',\n renderHTML: (attributes) => {\n return { style: attributes.style ?? '' };\n },\n },\n },\n },\n ];\n },\n\n addCommands() {\n return {\n unsetStyle:\n () =>\n ({ commands }) => {\n return this.options.types.every((type) =>\n commands.resetAttributes(type, 'style'),\n );\n },\n setStyle:\n (style: string) =>\n ({ commands }) => {\n return this.options.types.every((type) =>\n commands.updateAttributes(type, { style }),\n );\n },\n };\n },\n\n addKeyboardShortcuts() {\n return {\n Enter: ({ editor }) => {\n // Check if any suggestion plugin is active by looking for decorations\n // that indicate an active suggestion/autocomplete\n const { state } = editor.view;\n const { selection } = state;\n const { $from } = selection;\n\n // Check if we're in a position where suggestion might be active\n // by looking at the text before cursor for trigger characters\n const textBefore = $from.nodeBefore?.text || '';\n const hasTrigger =\n textBefore.includes('{{') || textBefore.includes('{{{');\n\n // If we have trigger characters, assume suggestion might be handling this\n // Don't reset styles\n if (hasTrigger) {\n return false;\n }\n\n // Otherwise, reset paragraph styles on Enter\n requestAnimationFrame(() => {\n editor.commands.resetAttributes('paragraph', 'style');\n });\n return false;\n },\n };\n },\n});\n","import type { SuperscriptExtensionOptions as TipTapSuperscriptOptions } from '@tiptap/extension-superscript';\nimport SuperscriptBase from '@tiptap/extension-superscript';\nimport { EmailMark } from '../core/serializer/email-mark';\n\nexport type SupOptions = TipTapSuperscriptOptions;\n\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n sup: {\n /**\n * Set a superscript mark\n */\n setSup: () => ReturnType;\n /**\n * Toggle a superscript mark\n */\n toggleSup: () => ReturnType;\n /**\n * Unset a superscript mark\n */\n unsetSup: () => ReturnType;\n };\n }\n}\n\nconst SupBase = SuperscriptBase.extend({\n name: 'sup',\n\n addCommands() {\n return {\n ...this.parent?.(),\n setSup:\n () =>\n ({ commands }) => {\n return commands.setMark(this.name);\n },\n toggleSup:\n () =>\n ({ commands }) => {\n return commands.toggleMark(this.name);\n },\n unsetSup:\n () =>\n ({ commands }) => {\n return commands.unsetMark(this.name);\n },\n };\n },\n});\n\nexport const Sup: EmailMark<TipTapSuperscriptOptions, any> = EmailMark.from(\n SupBase,\n ({ children, style }) => <sup style={style}>{children}</sup>,\n);\n","import { Column, Section } from '@react-email/components';\nimport type { ParentConfig } from '@tiptap/core';\nimport { mergeAttributes, Node } from '@tiptap/core';\nimport { EmailNode } from '../core/serializer/email-node';\nimport {\n COMMON_HTML_ATTRIBUTES,\n createStandardAttributes,\n LAYOUT_ATTRIBUTES,\n TABLE_ATTRIBUTES,\n TABLE_CELL_ATTRIBUTES,\n TABLE_HEADER_ATTRIBUTES,\n} from '../utils/attribute-helpers';\nimport { inlineCssToJs, resolveConflictingStyles } from '../utils/styles';\n\ndeclare module '@tiptap/core' {\n interface NodeConfig<Options, Storage> {\n /**\n * A string or function to determine the role of the table.\n * @default 'table'\n * @example () => 'table'\n */\n tableRole?:\n | string\n | ((this: {\n name: string;\n options: Options;\n storage: Storage;\n parent: ParentConfig<NodeConfig<Options>>['tableRole'];\n }) => string);\n }\n}\n\nexport interface TableOptions {\n HTMLAttributes: Record<string, unknown>;\n}\n\nexport const Table = EmailNode.create<TableOptions>({\n name: 'table',\n\n group: 'block',\n\n content: 'tableRow+',\n\n isolating: true,\n\n tableRole: 'table',\n\n addAttributes() {\n return {\n ...createStandardAttributes([\n ...TABLE_ATTRIBUTES,\n ...LAYOUT_ATTRIBUTES,\n ...COMMON_HTML_ATTRIBUTES,\n ]),\n };\n },\n\n parseHTML() {\n return [\n {\n tag: 'table',\n getAttrs: (node) => {\n if (typeof node === 'string') {\n return false;\n }\n const element = node as HTMLElement;\n const attrs: Record<string, string> = {};\n\n Array.from(element.attributes).forEach((attr) => {\n attrs[attr.name] = attr.value;\n });\n\n return attrs;\n },\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n const attrs = mergeAttributes(this.options.HTMLAttributes, HTMLAttributes);\n\n return ['table', attrs, ['tbody', {}, 0]];\n },\n\n renderToReactEmail({ children, node, style }) {\n const inlineStyles = inlineCssToJs(node.attrs?.style);\n const alignment = node.attrs?.align || node.attrs?.alignment;\n const width = node.attrs?.width;\n\n const centeringStyles: Record<string, string> =\n alignment === 'center' ? { marginLeft: 'auto', marginRight: 'auto' } : {};\n\n return (\n <Section\n className={node.attrs?.class || undefined}\n align={alignment}\n style={resolveConflictingStyles(style, {\n ...inlineStyles,\n ...centeringStyles,\n })}\n {...(width !== undefined ? { width } : {})}\n >\n {children}\n </Section>\n );\n },\n});\n\nexport interface TableRowOptions extends Record<string, unknown> {\n HTMLAttributes?: Record<string, unknown>;\n}\n\nexport const TableRow = EmailNode.create<TableRowOptions>({\n name: 'tableRow',\n\n group: 'tableRow',\n\n content: '(tableCell | tableHeader)+',\n\n addAttributes() {\n return {\n ...createStandardAttributes([\n ...TABLE_CELL_ATTRIBUTES,\n ...LAYOUT_ATTRIBUTES,\n ...COMMON_HTML_ATTRIBUTES,\n ]),\n };\n },\n\n parseHTML() {\n return [\n {\n tag: 'tr',\n getAttrs: (node) => {\n if (typeof node === 'string') {\n return false;\n }\n const element = node as HTMLElement;\n const attrs: Record<string, string> = {};\n\n Array.from(element.attributes).forEach((attr) => {\n attrs[attr.name] = attr.value;\n });\n\n return attrs;\n },\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return ['tr', HTMLAttributes, 0];\n },\n\n renderToReactEmail({ children, node, style }) {\n const inlineStyles = inlineCssToJs(node.attrs?.style);\n return (\n <tr\n className={node.attrs?.class || undefined}\n style={{\n ...style,\n ...inlineStyles,\n }}\n >\n {children}\n </tr>\n );\n },\n});\n\nexport interface TableCellOptions extends Record<string, unknown> {\n HTMLAttributes?: Record<string, unknown>;\n}\n\nexport const TableCell = EmailNode.create<TableCellOptions>({\n name: 'tableCell',\n\n group: 'tableCell',\n\n content: 'block+',\n\n isolating: true,\n\n addAttributes() {\n return {\n ...createStandardAttributes([\n ...TABLE_CELL_ATTRIBUTES,\n ...LAYOUT_ATTRIBUTES,\n ...COMMON_HTML_ATTRIBUTES,\n ]),\n };\n },\n\n parseHTML() {\n return [\n {\n tag: 'td',\n getAttrs: (node) => {\n if (typeof node === 'string') {\n return false;\n }\n const element = node as HTMLElement;\n const attrs: Record<string, string> = {};\n\n Array.from(element.attributes).forEach((attr) => {\n attrs[attr.name] = attr.value;\n });\n\n return attrs;\n },\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return ['td', HTMLAttributes, 0];\n },\n\n renderToReactEmail({ children, node, style }) {\n const inlineStyles = inlineCssToJs(node.attrs?.style);\n return (\n <Column\n className={node.attrs?.class || undefined}\n align={node.attrs?.align || node.attrs?.alignment}\n style={{\n ...style,\n ...inlineStyles,\n }}\n >\n {children}\n </Column>\n );\n },\n});\n\nexport const TableHeader = Node.create({\n name: 'tableHeader',\n\n group: 'tableCell',\n\n content: 'block+',\n\n isolating: true,\n\n addAttributes() {\n return {\n ...createStandardAttributes([\n ...TABLE_HEADER_ATTRIBUTES,\n ...TABLE_CELL_ATTRIBUTES,\n ...LAYOUT_ATTRIBUTES,\n ...COMMON_HTML_ATTRIBUTES,\n ]),\n };\n },\n\n parseHTML() {\n return [\n {\n tag: 'th',\n getAttrs: (node) => {\n if (typeof node === 'string') {\n return false;\n }\n const element = node as HTMLElement;\n const attrs: Record<string, string> = {};\n\n Array.from(element.attributes).forEach((attr) => {\n attrs[attr.name] = attr.value;\n });\n\n return attrs;\n },\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return ['th', HTMLAttributes, 0];\n },\n});\n","import { Text as BaseText } from '@tiptap/extension-text';\nimport { EmailNode } from '../core';\n\nexport const Text = EmailNode.from(BaseText, ({ children }) => {\n return <>{children}</>;\n});\n","// Most of this code was copied over from https://github.com/ueberdosis/tiptap which is MIT licensed and allows for this.\n\nimport { Extension } from '@tiptap/core';\nimport type { Node, NodeType } from '@tiptap/pm/model';\nimport { Plugin, PluginKey } from '@tiptap/pm/state';\n\nexport const skipTrailingNodeMeta = 'skipTrailingNode';\n\nfunction nodeEqualsType({\n types,\n node,\n}: {\n types: NodeType | NodeType[];\n node: Node | null | undefined;\n}) {\n return (\n (node && Array.isArray(types) && types.includes(node.type)) ||\n node?.type === types\n );\n}\n\n/**\n * Extension based on:\n * - https://github.com/ueberdosis/tiptap/blob/v1/packages/tiptap-extensions/src/extensions/TrailingNode.js\n * - https://github.com/remirror/remirror/blob/e0f1bec4a1e8073ce8f5500d62193e52321155b9/packages/prosemirror-trailing-node/src/trailing-node-plugin.ts\n */\n\nexport interface TrailingNodeOptions {\n /**\n * The node type that should be inserted at the end of the document.\n * @note the node will always be added to the `notAfter` lists to\n * prevent an infinite loop.\n * @default undefined\n */\n node?: string;\n /**\n * The node that the trailing node should be appended to. The default is the 'doc', giving the same behavior as TipTap's extension.\n */\n appendTo?: string;\n /**\n * The node types after which the trailing node should not be inserted.\n * @default ['paragraph']\n */\n notAfter?: string | string[];\n}\n\n/**\n * This extension allows you to add an extra node at the end of a node.\n *\n * Differently from TipTap's native one, it allows you to pick which node to append the trailing node to.\n * @see https://www.tiptap.dev/api/extensions/trailing-node\n *\n * We could contribute this to TipTap's core extensions and I think we should at some once we get some time.\n */\nexport const TrailingNode = Extension.create<TrailingNodeOptions>({\n name: 'trailingNode',\n\n addOptions() {\n return {\n node: undefined,\n appendTo: 'doc',\n notAfter: [],\n };\n },\n\n addProseMirrorPlugins() {\n const plugin = new PluginKey(this.name);\n const defaultNode =\n this.options.node ||\n this.editor.schema.topNodeType.contentMatch.defaultType?.name ||\n 'paragraph';\n\n const notAfter = Array.isArray(this.options.notAfter)\n ? this.options.notAfter\n : [this.options.notAfter].filter(Boolean);\n\n const disabledNodes = Object.entries(this.editor.schema.nodes)\n .map(([, value]) => value)\n .filter((node) => notAfter.concat(defaultNode).includes(node.name));\n\n const appendToType =\n this.editor.schema.nodes[this.options.appendTo || 'doc'];\n\n const getInsertPositions = (doc: Node): number[] => {\n const positions: number[] = [];\n\n if (doc.type === appendToType) {\n if (!nodeEqualsType({ node: doc.lastChild, types: disabledNodes })) {\n positions.push(doc.content.size);\n }\n }\n\n doc.descendants((node, pos) => {\n if (node.type !== appendToType) return;\n if (!nodeEqualsType({ node: node.lastChild, types: disabledNodes })) {\n positions.push(pos + node.nodeSize - 1);\n }\n });\n\n return positions;\n };\n\n return [\n new Plugin({\n key: plugin,\n appendTransaction: (transactions, __, state) => {\n const { doc, tr, schema } = state;\n const shouldInsert = plugin.getState(state);\n const type = schema.nodes[defaultNode];\n\n if (\n transactions.some((transaction) =>\n transaction.getMeta(skipTrailingNodeMeta),\n )\n ) {\n return;\n }\n\n if (!shouldInsert) {\n return;\n }\n\n const positions = getInsertPositions(doc);\n\n for (const pos of positions.sort((a, b) => b - a)) {\n tr.insert(pos, type.create());\n }\n\n return positions.length > 0 ? tr : undefined;\n },\n state: {\n init: (_, state) => {\n return getInsertPositions(state.doc).length > 0;\n },\n apply: (tr, value) => {\n if (!tr.docChanged) {\n return value;\n }\n\n // Ignore transactions from UniqueID extension to prevent infinite loops\n // when UniqueID adds IDs to newly inserted trailing nodes\n if (tr.getMeta('__uniqueIDTransaction')) {\n return value;\n }\n\n return getInsertPositions(tr.doc).length > 0;\n },\n },\n }),\n ];\n },\n});\n","import type { UnderlineOptions as TipTapUnderlineOptions } from '@tiptap/extension-underline';\nimport UnderlineBase from '@tiptap/extension-underline';\nimport { EmailMark } from '../core/serializer/email-mark';\n\nexport type UnderlineOptions = TipTapUnderlineOptions;\n\nexport const Underline: EmailMark<TipTapUnderlineOptions, any> = EmailMark.from(\n UnderlineBase,\n ({ children, style }) => <u style={style}>{children}</u>,\n);\n","import { mergeAttributes } from '@tiptap/core';\nimport { EmailMark } from '../core/serializer/email-mark';\n\nexport interface UppercaseOptions {\n HTMLAttributes: Record<string, unknown>;\n}\n\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n uppercase: {\n setUppercase: () => ReturnType;\n toggleUppercase: () => ReturnType;\n unsetUppercase: () => ReturnType;\n };\n }\n}\n\nexport const Uppercase = EmailMark.create<UppercaseOptions>({\n name: 'uppercase',\n\n addOptions() {\n return {\n HTMLAttributes: {},\n };\n },\n\n parseHTML() {\n return [\n {\n tag: 'span',\n getAttrs: (node) => {\n const el = node as HTMLElement;\n if (el.style.textTransform === 'uppercase') {\n return {};\n }\n return false;\n },\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return [\n 'span',\n mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, {\n style: 'text-transform: uppercase',\n }),\n 0,\n ];\n },\n\n renderToReactEmail({ children, style }) {\n return (\n <span\n style={{\n ...style,\n textTransform: 'uppercase',\n }}\n >\n {children}\n </span>\n );\n },\n\n addCommands() {\n return {\n setUppercase:\n () =>\n ({ commands }) => {\n return commands.setMark(this.name);\n },\n toggleUppercase:\n () =>\n ({ commands }) => {\n return commands.toggleMark(this.name);\n },\n unsetUppercase:\n () =>\n ({ commands }) => {\n return commands.unsetMark(this.name);\n },\n };\n },\n});\n","import { type AnyExtension, Extension } from '@tiptap/core';\nimport type { BlockquoteOptions } from '@tiptap/extension-blockquote';\nimport type { BulletListOptions } from '@tiptap/extension-bullet-list';\nimport type { CodeOptions } from '@tiptap/extension-code';\nimport type { HardBreakOptions } from '@tiptap/extension-hard-break';\nimport type { ItalicOptions } from '@tiptap/extension-italic';\nimport type { ListItemOptions } from '@tiptap/extension-list-item';\nimport type { OrderedListOptions } from '@tiptap/extension-ordered-list';\nimport type { ParagraphOptions } from '@tiptap/extension-paragraph';\nimport type { StrikeOptions } from '@tiptap/extension-strike';\nimport TipTapStarterKit, {\n type StarterKitOptions as TipTapStarterKitOptions,\n} from '@tiptap/starter-kit';\nimport type { AlignmentOptions } from './alignment-attribute';\nimport { AlignmentAttribute } from './alignment-attribute';\nimport { Blockquote } from './blockquote';\nimport type { BodyOptions } from './body';\nimport { Body } from './body';\nimport type { BoldOptions } from './bold';\nimport { Bold } from './bold';\nimport { BulletList } from './bullet-list';\nimport type { EditorButtonOptions } from './button';\nimport { Button } from './button';\nimport type { ClassAttributeOptions } from './class-attribute';\nimport { ClassAttribute } from './class-attribute';\nimport { Code } from './code';\nimport type { CodeBlockPrismOptions } from './code-block';\nimport { CodeBlockPrism } from './code-block';\nimport {\n ColumnsColumn,\n FourColumns,\n ThreeColumns,\n TwoColumns,\n} from './columns';\nimport type { ContainerOptions } from './container';\nimport { Container } from './container';\nimport type { DivOptions } from './div';\nimport { Div } from './div';\nimport type { DividerOptions } from './divider';\nimport { Divider } from './divider';\nimport type { GlobalContentOptions } from './global-content';\nimport { GlobalContent } from './global-content';\nimport { HardBreak } from './hard-break';\nimport type { HeadingOptions } from './heading';\nimport { Heading } from './heading';\nimport { Italic } from './italic';\nimport type { LinkOptions } from './link';\nimport { Link } from './link';\nimport { ListItem } from './list-item';\nimport type { MaxNestingOptions } from './max-nesting';\nimport { MaxNesting } from './max-nesting';\nimport { OrderedList } from './ordered-list';\nimport { Paragraph } from './paragraph';\nimport type { PlaceholderOptions } from './placeholder';\nimport { Placeholder } from './placeholder';\nimport { PreservedStyle } from './preserved-style';\nimport type { PreviewTextOptions } from './preview-text';\nimport { PreviewText } from './preview-text';\nimport type { SectionOptions } from './section';\nimport { Section } from './section';\nimport { Strike } from './strike';\nimport type { StyleAttributeOptions } from './style-attribute';\nimport { StyleAttribute } from './style-attribute';\nimport type { SupOptions } from './sup';\nimport { Sup } from './sup';\nimport type { TableCellOptions, TableOptions, TableRowOptions } from './table';\nimport { Table, TableCell, TableHeader, TableRow } from './table';\nimport { Text } from './text';\nimport { TrailingNode, type TrailingNodeOptions } from './trailing-node';\nimport type { UnderlineOptions } from './underline';\nimport { Underline } from './underline';\nimport type { UppercaseOptions } from './uppercase';\nimport { Uppercase } from './uppercase';\n\nexport * from './alignment-attribute';\nexport * from './blockquote';\nexport * from './body';\nexport * from './bold';\nexport * from './bullet-list';\nexport * from './button';\nexport * from './class-attribute';\nexport * from './code';\nexport * from './code-block';\nexport * from './columns';\nexport * from './container';\nexport * from './div';\nexport * from './divider';\nexport * from './global-content';\nexport * from './hard-break';\nexport * from './heading';\nexport * from './italic';\nexport * from './link';\nexport * from './list-item';\nexport * from './max-nesting';\nexport * from './ordered-list';\nexport * from './paragraph';\nexport * from './placeholder';\nexport * from './preserved-style';\nexport * from './preview-text';\nexport * from './section';\nexport * from './strike';\nexport * from './style-attribute';\nexport * from './sup';\nexport * from './table';\nexport * from './text';\nexport * from './trailing-node';\nexport * from './underline';\nexport * from './uppercase';\n\nconst starterKitExtensions: Record<string, AnyExtension> = {\n CodeBlockPrism,\n Code,\n TwoColumns,\n ThreeColumns,\n FourColumns,\n Container,\n ColumnsColumn,\n Paragraph,\n BulletList,\n OrderedList,\n Blockquote,\n ListItem,\n HardBreak,\n Italic,\n Placeholder,\n PreviewText,\n TrailingNode,\n Bold,\n Strike,\n Heading,\n Divider,\n Link,\n Sup,\n Underline,\n Uppercase,\n PreservedStyle,\n Table,\n TableRow,\n TableCell,\n TableHeader,\n Body,\n Div,\n Button,\n Section,\n GlobalContent,\n Text,\n AlignmentAttribute,\n StyleAttribute,\n ClassAttribute,\n MaxNesting,\n};\n\nexport type StarterKitOptions = {\n CodeBlockPrism: Partial<CodeBlockPrismOptions> | false;\n Code: Partial<CodeOptions> | false;\n TwoColumns: Partial<Record<string, never>> | false;\n ThreeColumns: Partial<Record<string, never>> | false;\n FourColumns: Partial<Record<string, never>> | false;\n ColumnsColumn: Partial<Record<string, never>> | false;\n Paragraph: Partial<ParagraphOptions> | false;\n BulletList: Partial<BulletListOptions> | false;\n OrderedList: Partial<OrderedListOptions> | false;\n TrailingNode: Partial<TrailingNodeOptions> | false;\n Blockquote: Partial<BlockquoteOptions> | false;\n ListItem: Partial<ListItemOptions> | false;\n HardBreak: Partial<HardBreakOptions> | false;\n Italic: Partial<ItalicOptions> | false;\n Placeholder: Partial<PlaceholderOptions> | false;\n PreviewText: Partial<PreviewTextOptions> | false;\n Bold: Partial<BoldOptions> | false;\n Strike: Partial<StrikeOptions> | false;\n Heading: Partial<HeadingOptions> | false;\n Divider: Partial<DividerOptions> | false;\n Link: Partial<LinkOptions> | false;\n Sup: Partial<SupOptions> | false;\n Underline: Partial<UnderlineOptions> | false;\n Uppercase: Partial<UppercaseOptions> | false;\n PreservedStyle: Partial<Record<string, never>> | false;\n Table: Partial<TableOptions> | false;\n TableRow: Partial<TableRowOptions> | false;\n TableCell: Partial<TableCellOptions> | false;\n TableHeader: Partial<Record<string, any>> | false;\n Body: Partial<BodyOptions> | false;\n Container: Partial<ContainerOptions> | false;\n Div: Partial<DivOptions> | false;\n Text: Record<string, never> | false;\n Button: Partial<EditorButtonOptions> | false;\n Section: Partial<SectionOptions> | false;\n GlobalContent: Partial<GlobalContentOptions> | false;\n AlignmentAttribute: Partial<AlignmentOptions> | false;\n StyleAttribute: Partial<StyleAttributeOptions> | false;\n ClassAttribute: Partial<ClassAttributeOptions> | false;\n MaxNesting: Partial<MaxNestingOptions> | false;\n TiptapStarterKit: Partial<TipTapStarterKitOptions> | false;\n};\n\nexport const StarterKit = Extension.create<StarterKitOptions>({\n name: 'reactEmailStarterKit',\n\n addOptions() {\n return {\n TiptapStarterKit: {},\n CodeBlockPrism: {\n defaultLanguage: 'javascript',\n HTMLAttributes: {\n class: 'prism node-codeBlock',\n },\n },\n TrailingNode: {\n node: 'paragraph',\n appendTo: 'container',\n },\n Code: {\n HTMLAttributes: {\n class: 'node-inlineCode',\n spellcheck: 'false',\n },\n },\n TwoColumns: {},\n ThreeColumns: {},\n FourColumns: {},\n ColumnsColumn: {},\n Paragraph: {\n HTMLAttributes: {\n class: 'node-paragraph',\n },\n },\n BulletList: {\n HTMLAttributes: {\n class: 'node-bulletList',\n },\n },\n OrderedList: {\n HTMLAttributes: {\n class: 'node-orderedList',\n },\n },\n Blockquote: {\n HTMLAttributes: {\n class: 'node-blockquote',\n },\n },\n ListItem: {},\n HardBreak: {},\n Italic: {},\n Placeholder: {},\n PreviewText: {},\n Bold: {},\n Strike: {},\n Heading: {},\n Divider: {},\n Link: { openOnClick: false, HTMLAttributes: { class: 'node-link' } },\n Sup: {},\n Underline: {},\n Uppercase: {},\n PreservedStyle: {},\n Table: {},\n TableRow: {},\n TableCell: {},\n TableHeader: {},\n Body: {},\n Container: {},\n Div: {},\n Button: {},\n Section: {},\n GlobalContent: {},\n AlignmentAttribute: {\n types: [\n 'heading',\n 'paragraph',\n 'image',\n 'blockquote',\n 'codeBlock',\n 'bulletList',\n 'orderedList',\n 'listItem',\n 'button',\n 'youtube',\n 'twitter',\n 'table',\n 'tableRow',\n 'tableCell',\n 'tableHeader',\n 'columnsColumn',\n ],\n },\n StyleAttribute: {\n types: [\n 'heading',\n 'paragraph',\n 'image',\n 'blockquote',\n 'codeBlock',\n 'bulletList',\n 'orderedList',\n 'listItem',\n 'button',\n 'youtube',\n 'twitter',\n 'horizontalRule',\n 'footer',\n 'section',\n 'div',\n 'body',\n 'table',\n 'tableRow',\n 'tableCell',\n 'tableHeader',\n 'columnsColumn',\n 'link',\n ],\n },\n Text: {},\n ClassAttribute: {\n types: [\n 'heading',\n 'paragraph',\n 'image',\n 'blockquote',\n 'bulletList',\n 'orderedList',\n 'listItem',\n 'button',\n 'youtube',\n 'twitter',\n 'horizontalRule',\n 'footer',\n 'section',\n 'div',\n 'body',\n 'table',\n 'tableRow',\n 'tableCell',\n 'tableHeader',\n 'columnsColumn',\n 'link',\n ],\n },\n MaxNesting: {\n maxDepth: 50,\n nodeTypes: ['section', 'bulletList', 'orderedList'],\n },\n };\n },\n\n addExtensions() {\n const extensions: AnyExtension[] = [];\n\n if (this.options.TiptapStarterKit !== false) {\n extensions.push(\n TipTapStarterKit.configure({\n // Collaboration extensions handle history separately.\n undoRedo: false,\n heading: false,\n link: false,\n underline: false,\n trailingNode: false,\n bold: false,\n italic: false,\n strike: false,\n code: false,\n paragraph: false,\n bulletList: false,\n orderedList: false,\n listItem: false,\n blockquote: false,\n hardBreak: false,\n gapcursor: false,\n codeBlock: false,\n text: false,\n horizontalRule: false,\n dropcursor: {\n color: '#61a8f8',\n class: 'rounded-full animate-[fade-in_300ms_ease-in-out] !z-40',\n width: 4,\n },\n ...this.options.TiptapStarterKit,\n }),\n );\n }\n\n for (const [name, extension] of Object.entries(starterKitExtensions)) {\n const key = name as keyof StarterKitOptions;\n const extensionOptions = this.options[key];\n if (extensionOptions !== false) {\n extensions.push(\n (extension as AnyExtension).configure(extensionOptions),\n );\n }\n }\n\n return extensions;\n },\n});\n"],"mappings":"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CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD;AA8CD,MAAa,aAAa,UAAU,OAA0B;CAC5D,MAAM;CAEN,aAAa;AACX,SAAO;GACL,kBAAkB,EAAE;GACpB,gBAAgB;IACd,iBAAiB;IACjB,gBAAgB,EACd,OAAO,wBACR;IACF;GACD,cAAc;IACZ,MAAM;IACN,UAAU;IACX;GACD,MAAM,EACJ,gBAAgB;IACd,OAAO;IACP,YAAY;IACb,EACF;GACD,YAAY,EAAE;GACd,cAAc,EAAE;GAChB,aAAa,EAAE;GACf,eAAe,EAAE;GACjB,WAAW,EACT,gBAAgB,EACd,OAAO,kBACR,EACF;GACD,YAAY,EACV,gBAAgB,EACd,OAAO,mBACR,EACF;GACD,aAAa,EACX,gBAAgB,EACd,OAAO,oBACR,EACF;GACD,YAAY,EACV,gBAAgB,EACd,OAAO,mBACR,EACF;GACD,UAAU,EAAE;GACZ,WAAW,EAAE;GACb,QAAQ,EAAE;GACV,aAAa,EAAE;GACf,aAAa,EAAE;GACf,MAAM,EAAE;GACR,QAAQ,EAAE;GACV,SAAS,EAAE;GACX,SAAS,EAAE;GACX,MAAM;IAAE,aAAa;IAAO,gBAAgB,EAAE,OAAO,aAAa;IAAE;GACpE,KAAK,EAAE;GACP,WAAW,EAAE;GACb,WAAW,EAAE;GACb,gBAAgB,EAAE;GAClB,OAAO,EAAE;GACT,UAAU,EAAE;GACZ,WAAW,EAAE;GACb,aAAa,EAAE;GACf,MAAM,EAAE;GACR,WAAW,EAAE;GACb,KAAK,EAAE;GACP,QAAQ,EAAE;GACV,SAAS,EAAE;GACX,eAAe,EAAE;GACjB,oBAAoB,EAClB,OAAO;IACL;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACD,EACF;GACD,gBAAgB,EACd,OAAO;IACL;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACD,EACF;GACD,MAAM,EAAE;GACR,gBAAgB,EACd,OAAO;IACL;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACD,EACF;GACD,YAAY;IACV,UAAU;IACV,WAAW;KAAC;KAAW;KAAc;KAAc;IACpD;GACF;;CAGH,gBAAgB;EACd,MAAM,aAA6B,EAAE;AAErC,MAAI,KAAK,QAAQ,qBAAqB,MACpC,YAAW,KACT,iBAAiB,UAAU;GAEzB,UAAU;GACV,SAAS;GACT,MAAM;GACN,WAAW;GACX,cAAc;GACd,MAAM;GACN,QAAQ;GACR,QAAQ;GACR,MAAM;GACN,WAAW;GACX,YAAY;GACZ,aAAa;GACb,UAAU;GACV,YAAY;GACZ,WAAW;GACX,WAAW;GACX,WAAW;GACX,MAAM;GACN,gBAAgB;GAChB,YAAY;IACV,OAAO;IACP,OAAO;IACP,OAAO;IACR;GACD,GAAG,KAAK,QAAQ;GACjB,CAAC,CACH;AAGH,OAAK,MAAM,CAAC,MAAM,cAAc,OAAO,QAAQ,qBAAqB,EAAE;GACpE,MAAM,MAAM;GACZ,MAAM,mBAAmB,KAAK,QAAQ;AACtC,OAAI,qBAAqB,MACvB,YAAW,KACR,UAA2B,UAAU,iBAAiB,CACxD;;AAIL,SAAO;;CAEV,CAAC"}