Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
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
12 changes: 7 additions & 5 deletions 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 @@ -56,9 +59,8 @@ export const CodeContainer: React.FC<Readonly<CodeContainerProps>> = ({
const isCurrentLang = activeLang === language;
return (
<motion.button
className={`relative px-4 py-[8px] font-sans text-sm font-medium transition duration-200 ease-in-out hover:text-slate-12 ${
activeLang !== language ? 'text-slate-11' : 'text-slate-12'
}`}
className={`relative px-4 py-[8px] font-sans text-sm font-medium transition duration-200 ease-in-out hover:text-slate-12 ${activeLang !== language ? 'text-slate-11' : 'text-slate-12'
}`}
key={language}
onClick={() => {
setActiveLang(language);
Expand All @@ -83,7 +85,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 Expand Up @@ -141,7 +143,7 @@ const DownloadButton = ({ content, filename }: DownloadButtonProps) => {
return URL.createObjectURL(file);
}, [content, filename]);
const url = React.useSyncExternalStore(
() => () => {},
() => () => { },
() => generatedUrl,
() => undefined,
);
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