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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/itchy-wasps-read.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@react-email/preview-server": patch
---

fix file names and extensions not being used in download
6 changes: 6 additions & 0 deletions packages/preview-server/src/actions/render-email-by-path.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ export interface RenderedEmailMetadata {
markupWithReferences?: string;
plainText: string;
reactMarkup: string;

basename: string;
extname: string;
}

export type EmailRenderingResult =
Expand Down Expand Up @@ -130,6 +133,9 @@ export const renderEmailByPath = async (
markupWithReferences: markupWithReferences.replaceAll('\0', ''),
plainText,
reactMarkup,

basename: path.basename(emailPath, path.extname(emailPath)),
extname: path.extname(emailPath).slice(1),
};

cache.set(emailPath, renderingResult);
Expand Down
9 changes: 6 additions & 3 deletions packages/preview-server/src/app/preview/[...slug]/preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const Preview = ({ emailTitle, className, ...props }: PreviewProps) => {

const isDarkModeEnabled = searchParams.get('dark') !== null;
const activeView = searchParams.get('view') ?? 'preview';
const activeLang = searchParams.get('lang') ?? 'jsx';
const activeLang = searchParams.get('lang') ?? 'tsx';
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Nov 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refactoring lang identifiers from jsx/markup to tsx/html without handling old values in URL parameters causes a crash. Visiting a previously valid URL with ?lang=jsx will now break the source view.

Prompt for AI agents
Address the following comment on packages/preview-server/src/app/preview/[...slug]/preview.tsx at line 39:

<comment>Refactoring `lang` identifiers from `jsx`/`markup` to `tsx`/`html` without handling old values in URL parameters causes a crash. Visiting a previously valid URL with `?lang=jsx` will now break the source view.</comment>

<file context>
@@ -36,7 +36,7 @@ const Preview = ({ emailTitle, className, ...props }: PreviewProps) =&gt; {
   const isDarkModeEnabled = searchParams.get(&#39;dark&#39;) !== null;
   const activeView = searchParams.get(&#39;view&#39;) ?? &#39;preview&#39;;
-  const activeLang = searchParams.get(&#39;lang&#39;) ?? &#39;jsx&#39;;
+  const activeLang = searchParams.get(&#39;lang&#39;) ?? &#39;tsx&#39;;
 
   const handleDarkModeChange = (enabled: boolean) =&gt; {
</file context>
Fix with Cubic


const handleDarkModeChange = (enabled: boolean) => {
const params = new URLSearchParams(searchParams);
Expand Down Expand Up @@ -207,17 +207,20 @@ const Preview = ({ emailTitle, className, ...props }: PreviewProps) => {
<Tooltip.Provider>
<CodeContainer
activeLang={activeLang}
basename={renderedEmailMetadata.basename}
markups={[
{
language: 'jsx',
language: 'tsx',
extension: renderedEmailMetadata.extname,
content: renderedEmailMetadata.reactMarkup,
},
{
language: 'markup',
language: 'html',
content: renderedEmailMetadata.prettyMarkup,
},
{
language: 'markdown',
extension: 'md',
content: renderedEmailMetadata.plainText,
},
]}
Expand Down
5 changes: 4 additions & 1 deletion packages/preview-server/src/components/code-container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,20 @@ import { Tooltip } from './tooltip';

interface CodeContainerProps {
markups: MarkupProps[];
basename: string;
activeLang: string;
setActiveLang: (lang: string) => void;
}

interface MarkupProps {
language: Language;
extension?: string;
content: string;
}

export const CodeContainer: React.FC<Readonly<CodeContainerProps>> = ({
markups,
basename: filename,
activeLang,
setActiveLang,
}) => {
Expand Down Expand Up @@ -83,7 +86,7 @@ export const CodeContainer: React.FC<Readonly<CodeContainerProps>> = ({
<CopyToClipboardButton content={activeMarkup.content} />
<DownloadButton
content={activeMarkup.content}
filename={`email.${activeMarkup.language}`}
filename={`${filename}.${activeMarkup.extension || activeMarkup.language}`}
/>
</div>
<div className="h-[calc(100%-2.25rem)]">
Expand Down
4 changes: 2 additions & 2 deletions packages/preview-server/src/utils/language-map.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const languageMap = {
jsx: 'React',
markup: 'HTML',
tsx: 'React',
html: 'HTML',
markdown: 'Plain Text',
};

Expand Down
Loading