Labs: Add opt-in single-dollar inline LaTeX rendering

Add a 'Dollar Inline LaTeX' toggle in Settings > Labs that enables
single-dollar ($...$) inline math rendering via remark-math. Off by
default since it can cause false positives with currency ($10) and
stock symbols ($AAPL). Closes #795.

Co-authored-by: Enrico Ros <enricoros@users.noreply.github.com>
This commit is contained in:
claude[bot]
2026-04-24 04:25:44 +00:00
parent 9bb178413b
commit 7bc02acff4
3 changed files with 34 additions and 10 deletions
@@ -3,6 +3,7 @@ import * as React from 'react';
import { FormControl, Typography } from '@mui/joy';
import EditNoteIcon from '@mui/icons-material/EditNote';
import AttachFileRoundedIcon from '@mui/icons-material/AttachFileRounded';
import FunctionsIcon from '@mui/icons-material/Functions';
import ShortcutIcon from '@mui/icons-material/Shortcut';
import SpeedIcon from '@mui/icons-material/Speed';
@@ -24,6 +25,7 @@ export function UxLabsSettings() {
labsAutoHideComposer, setLabsAutoHideComposer,
labsShowShortcutBar, setLabsShowShortcutBar,
labsComposerAttachmentsInline, setLabsComposerAttachmentsInline,
labsSingleDollarLatex, setLabsSingleDollarLatex,
} = useUXLabsStore();
return <>
@@ -39,6 +41,17 @@ export function UxLabsSettings() {
checked={labsLosslessImages} onChange={setLabsPreserveLosslessImages}
/>
<FormSwitchControl
title={<><FunctionsIcon sx={{ fontSize: 'lg', mr: 0.5, mb: 0.25 }} />Dollar Inline LaTeX</>} description={labsSingleDollarLatex ? 'Enabled' : 'Disabled'}
tooltipWarning={labsSingleDollarLatex}
tooltip={<>
Renders single-dollar <code>$...$</code> as inline LaTeX math formulas, in addition to the default <code>{'\\\\(...)\\\\)'}</code> and <code>$$...$$</code> formats.
<hr />
WARNING: This may cause false positives - currency values like $10 or stock symbols like $AAPL could be incorrectly rendered as math.
</>}
checked={labsSingleDollarLatex} onChange={setLabsSingleDollarLatex}
/>
<FormSwitchControl
title={<><SpeedIcon sx={{ fontSize: 'lg', mr: 0.5, mb: 0.25 }} />Unlock Refresh</>} description={labsHighPerformance ? 'Unlocked' : 'Default'}
tooltipWarning={labsHighPerformance}
+6
View File
@@ -25,6 +25,9 @@ interface UXLabsStore {
labsLosslessImages: boolean;
setLabsPreserveLosslessImages: (labsLosslessImages: boolean) => void;
labsSingleDollarLatex: boolean;
setLabsSingleDollarLatex: (labsSingleDollarLatex: boolean) => void;
}
export const useUXLabsStore = create<UXLabsStore>()(
@@ -46,6 +49,9 @@ export const useUXLabsStore = create<UXLabsStore>()(
labsLosslessImages: false,
setLabsPreserveLosslessImages: (labsLosslessImages: boolean) => set({ labsLosslessImages }),
labsSingleDollarLatex: false,
setLabsSingleDollarLatex: (labsSingleDollarLatex: boolean) => set({ labsSingleDollarLatex }),
}),
{
name: 'app-ux-labs',
@@ -12,6 +12,7 @@ import { Box, Chip } from '@mui/joy';
import { copyToClipboard } from '~/common/util/clipboardUtils';
import { downloadBlob } from '~/common/util/downloadUtils';
import { useUXLabsStore } from '~/common/stores/store-ux-labs';
import { CustomARenderer } from './CustomARenderer';
import { remarkTableCellBreaks } from './tableBreaks.remark';
@@ -208,18 +209,18 @@ const reactMarkdownComponents = {
// math/inlineMath components are not needed, rehype-katex handles this automatically
} as ReactMarkdownComponents;
const remarkPluginsStable: UnifiedPluggable[] = [
const remarkPluginsBase: UnifiedPluggable[] = [
remarkGfm, // GitHub Flavored Markdown
remarkMark, // Mark-Highlight, for ==yellow==
remarkTableCellBreaks, // Convert <br> HTML tags inside tables to break nodes (for line breaks in table cells)
[remarkMath, {
/**
* NOTE: this could be configurable, some users reported liking single dollar signs math, despite even the official
* LaTeX documentation recommending against it: https://docs.mathjax.org/en/latest/input/tex/delimiters.html
* So in the future this could be a user setting.
*/
singleDollarTextMath: false,
}],
[remarkMath, { singleDollarTextMath: false }],
];
const remarkPluginsSingleDollar: UnifiedPluggable[] = [
remarkGfm,
remarkMark,
remarkTableCellBreaks,
[remarkMath, { singleDollarTextMath: true }],
];
const rehypePluginsStable: UnifiedPluggable[] = [
@@ -275,10 +276,14 @@ function preprocessMarkdown(markdownText: string) {
}
export default function CustomMarkdownRenderer(props: { content: string, disablePreprocessor?: boolean }) {
// external state
const singleDollarLatex = useUXLabsStore((s) => s.labsSingleDollarLatex);
return (
<ReactMarkdown
components={reactMarkdownComponents}
remarkPlugins={remarkPluginsStable}
remarkPlugins={singleDollarLatex ? remarkPluginsSingleDollar : remarkPluginsBase}
rehypePlugins={rehypePluginsStable}
>
{props.disablePreprocessor ? props.content : preprocessMarkdown(props.content)}