mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-01-10 15:49:29 +08:00
feat(Markdown): support disabling single dollar math (#9131)
* feat(Markdown): support disabling single dollar math * fix: lint error
This commit is contained in:
parent
ceef19e55b
commit
4cda5f1787
@ -2715,6 +2715,17 @@
|
||||
"title": "Launch",
|
||||
"totray": "Minimize to Tray on Launch"
|
||||
},
|
||||
"math": {
|
||||
"engine": {
|
||||
"label": "Math engine",
|
||||
"none": "None"
|
||||
},
|
||||
"single_dollar": {
|
||||
"label": "Enable $...$",
|
||||
"tip": "Render math equations quoted by single dollar signs $...$. Default is enabled."
|
||||
},
|
||||
"title": "Math Settings"
|
||||
},
|
||||
"mcp": {
|
||||
"actions": "Actions",
|
||||
"active": "Active",
|
||||
@ -2945,10 +2956,6 @@
|
||||
"title": "Input Settings"
|
||||
},
|
||||
"markdown_rendering_input_message": "Markdown render input message",
|
||||
"math_engine": {
|
||||
"label": "Math engine",
|
||||
"none": "None"
|
||||
},
|
||||
"metrics": "{{time_first_token_millsec}}ms to first token | {{token_speed}} tok/sec",
|
||||
"model": {
|
||||
"title": "Model Settings"
|
||||
|
||||
@ -2715,6 +2715,17 @@
|
||||
"title": "起動",
|
||||
"totray": "起動時にトレイに最小化"
|
||||
},
|
||||
"math": {
|
||||
"engine": {
|
||||
"label": "数式エンジン",
|
||||
"none": "なし"
|
||||
},
|
||||
"single_dollar": {
|
||||
"label": "$...$ を有効にする",
|
||||
"tip": "単一のドル記号 $...$ で囲まれた数式をレンダリングします。デフォルトで有効です。"
|
||||
},
|
||||
"title": "数式設定"
|
||||
},
|
||||
"mcp": {
|
||||
"actions": "操作",
|
||||
"active": "有効",
|
||||
@ -2945,10 +2956,6 @@
|
||||
"title": "入力設定"
|
||||
},
|
||||
"markdown_rendering_input_message": "Markdownで入力メッセージをレンダリング",
|
||||
"math_engine": {
|
||||
"label": "数式エンジン",
|
||||
"none": "なし"
|
||||
},
|
||||
"metrics": "最初のトークンまでの時間 {{time_first_token_millsec}}ms | トークン速度 {{token_speed}} tok/sec",
|
||||
"model": {
|
||||
"title": "モデル設定"
|
||||
|
||||
@ -2715,6 +2715,17 @@
|
||||
"title": "Запуск",
|
||||
"totray": "Свернуть в трей при запуске"
|
||||
},
|
||||
"math": {
|
||||
"engine": {
|
||||
"label": "Математический движок",
|
||||
"none": "Нет"
|
||||
},
|
||||
"single_dollar": {
|
||||
"label": "Включить $...$",
|
||||
"tip": "Отображать математические формулы, заключенные в одиночные символы доллара $...$. По умолчанию включено."
|
||||
},
|
||||
"title": "Настройки математических формул"
|
||||
},
|
||||
"mcp": {
|
||||
"actions": "Действия",
|
||||
"active": "Активен",
|
||||
@ -2945,10 +2956,6 @@
|
||||
"title": "Настройки ввода"
|
||||
},
|
||||
"markdown_rendering_input_message": "Отображение ввода в формате Markdown",
|
||||
"math_engine": {
|
||||
"label": "Математический движок",
|
||||
"none": "Нет"
|
||||
},
|
||||
"metrics": "{{time_first_token_millsec}}ms до первого токена | {{token_speed}} tok/sec",
|
||||
"model": {
|
||||
"title": "Настройки модели"
|
||||
|
||||
@ -2715,6 +2715,17 @@
|
||||
"title": "启动",
|
||||
"totray": "启动时最小化到托盘"
|
||||
},
|
||||
"math": {
|
||||
"engine": {
|
||||
"label": "数学公式引擎",
|
||||
"none": "无"
|
||||
},
|
||||
"single_dollar": {
|
||||
"label": "启用 $...$",
|
||||
"tip": "渲染单个美元符号 $...$ 包裹的数学公式,默认启用。"
|
||||
},
|
||||
"title": "数学公式设置"
|
||||
},
|
||||
"mcp": {
|
||||
"actions": "操作",
|
||||
"active": "启用",
|
||||
@ -2945,10 +2956,6 @@
|
||||
"title": "输入设置"
|
||||
},
|
||||
"markdown_rendering_input_message": "Markdown 渲染输入消息",
|
||||
"math_engine": {
|
||||
"label": "数学公式引擎",
|
||||
"none": "无"
|
||||
},
|
||||
"metrics": "首字时延 {{time_first_token_millsec}} ms | 每秒 {{token_speed}} tokens",
|
||||
"model": {
|
||||
"title": "模型设置"
|
||||
|
||||
@ -2715,6 +2715,17 @@
|
||||
"title": "啟動",
|
||||
"totray": "啟動時最小化到系统匣"
|
||||
},
|
||||
"math": {
|
||||
"engine": {
|
||||
"label": "數學公式引擎",
|
||||
"none": "無"
|
||||
},
|
||||
"single_dollar": {
|
||||
"label": "啟用 $...$",
|
||||
"tip": "渲染單個美元符號 $...$ 包裹的數學公式,默認啟用。"
|
||||
},
|
||||
"title": "數學公式設定"
|
||||
},
|
||||
"mcp": {
|
||||
"actions": "操作",
|
||||
"active": "啟用",
|
||||
@ -2945,10 +2956,6 @@
|
||||
"title": "輸入設定"
|
||||
},
|
||||
"markdown_rendering_input_message": "Markdown 渲染輸入訊息",
|
||||
"math_engine": {
|
||||
"label": "數學公式引擎",
|
||||
"none": "無"
|
||||
},
|
||||
"metrics": "首字延遲 {{time_first_token_millsec}} ms | 每秒 {{token_speed}} tokens",
|
||||
"model": {
|
||||
"title": "模型設定"
|
||||
|
||||
@ -46,7 +46,7 @@ interface Props {
|
||||
|
||||
const Markdown: FC<Props> = ({ block, postProcess }) => {
|
||||
const { t } = useTranslation()
|
||||
const { mathEngine } = useSettings()
|
||||
const { mathEngine, mathEnableSingleDollar } = useSettings()
|
||||
|
||||
const isTrulyDone = 'status' in block && block.status === 'success'
|
||||
const [displayedContent, setDisplayedContent] = useState(postProcess ? postProcess(block.content) : block.content)
|
||||
@ -98,10 +98,10 @@ const Markdown: FC<Props> = ({ block, postProcess }) => {
|
||||
remarkDisableConstructs(['codeIndented'])
|
||||
]
|
||||
if (mathEngine !== 'none') {
|
||||
plugins.push(remarkMath)
|
||||
plugins.push([remarkMath, { singleDollarTextMath: mathEnableSingleDollar }])
|
||||
}
|
||||
return plugins
|
||||
}, [mathEngine])
|
||||
}, [mathEngine, mathEnableSingleDollar])
|
||||
|
||||
const messageContent = useMemo(() => {
|
||||
if ('status' in block && block.status === 'paused' && isEmpty(block.content)) {
|
||||
|
||||
@ -144,7 +144,7 @@ describe('Markdown', () => {
|
||||
vi.clearAllMocks()
|
||||
|
||||
// Default settings
|
||||
mockUseSettings.mockReturnValue({ mathEngine: 'KaTeX' })
|
||||
mockUseSettings.mockReturnValue({ mathEngine: 'KaTeX', mathEnableSingleDollar: true })
|
||||
mockUseTranslation.mockReturnValue({
|
||||
t: (key: string) => (key === 'message.chat.completion.paused' ? 'Paused' : key)
|
||||
})
|
||||
@ -270,7 +270,7 @@ describe('Markdown', () => {
|
||||
|
||||
describe('math engine configuration', () => {
|
||||
it('should configure KaTeX when mathEngine is KaTeX', () => {
|
||||
mockUseSettings.mockReturnValue({ mathEngine: 'KaTeX' })
|
||||
mockUseSettings.mockReturnValue({ mathEngine: 'KaTeX', mathEnableSingleDollar: true })
|
||||
|
||||
render(<Markdown block={createMainTextBlock()} />)
|
||||
|
||||
@ -279,7 +279,7 @@ describe('Markdown', () => {
|
||||
})
|
||||
|
||||
it('should configure MathJax when mathEngine is MathJax', () => {
|
||||
mockUseSettings.mockReturnValue({ mathEngine: 'MathJax' })
|
||||
mockUseSettings.mockReturnValue({ mathEngine: 'MathJax', mathEnableSingleDollar: true })
|
||||
|
||||
render(<Markdown block={createMainTextBlock()} />)
|
||||
|
||||
@ -288,7 +288,7 @@ describe('Markdown', () => {
|
||||
})
|
||||
|
||||
it('should not load math plugins when mathEngine is none', () => {
|
||||
mockUseSettings.mockReturnValue({ mathEngine: 'none' })
|
||||
mockUseSettings.mockReturnValue({ mathEngine: 'none', mathEnableSingleDollar: true })
|
||||
|
||||
render(<Markdown block={createMainTextBlock()} />)
|
||||
|
||||
@ -384,12 +384,12 @@ describe('Markdown', () => {
|
||||
})
|
||||
|
||||
it('should re-render when math engine changes', () => {
|
||||
mockUseSettings.mockReturnValue({ mathEngine: 'KaTeX' })
|
||||
mockUseSettings.mockReturnValue({ mathEngine: 'KaTeX', mathEnableSingleDollar: true })
|
||||
const { rerender } = render(<Markdown block={createMainTextBlock()} />)
|
||||
|
||||
expect(screen.getByTestId('markdown-content')).toBeInTheDocument()
|
||||
|
||||
mockUseSettings.mockReturnValue({ mathEngine: 'MathJax' })
|
||||
mockUseSettings.mockReturnValue({ mathEngine: 'MathJax', mathEnableSingleDollar: true })
|
||||
rerender(<Markdown block={createMainTextBlock()} />)
|
||||
|
||||
// Should still render correctly with new math engine
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { Root, Node, Element, Text } from 'hast'
|
||||
import type { Element, Node, Root, Text } from 'hast'
|
||||
import { visit } from 'unist-util-visit'
|
||||
|
||||
/**
|
||||
|
||||
@ -29,6 +29,7 @@ import {
|
||||
setEnableBackspaceDeleteModel,
|
||||
setEnableQuickPanelTriggers,
|
||||
setFontSize,
|
||||
setMathEnableSingleDollar,
|
||||
setMathEngine,
|
||||
setMessageFont,
|
||||
setMessageNavigation,
|
||||
@ -97,6 +98,7 @@ const SettingsTab: FC<Props> = (props) => {
|
||||
codeImageTools,
|
||||
codeExecution,
|
||||
mathEngine,
|
||||
mathEnableSingleDollar,
|
||||
autoTranslateWithSpace,
|
||||
pasteLongTextThreshold,
|
||||
multiModelMessageStyle,
|
||||
@ -382,19 +384,6 @@ const SettingsTab: FC<Props> = (props) => {
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
<SettingRowTitleSmall>{t('settings.messages.math_engine.label')}</SettingRowTitleSmall>
|
||||
<Selector
|
||||
value={mathEngine}
|
||||
onChange={(value) => dispatch(setMathEngine(value as MathEngine))}
|
||||
options={[
|
||||
{ value: 'KaTeX', label: 'KaTeX' },
|
||||
{ value: 'MathJax', label: 'MathJax' },
|
||||
{ value: 'none', label: t('settings.messages.math_engine.none') }
|
||||
]}
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
<SettingRowTitleSmall>{t('settings.font_size.title')}</SettingRowTitleSmall>
|
||||
</SettingRow>
|
||||
@ -418,6 +407,37 @@ const SettingsTab: FC<Props> = (props) => {
|
||||
<SettingDivider />
|
||||
</SettingGroup>
|
||||
</CollapsibleSettingGroup>
|
||||
<CollapsibleSettingGroup title={t('settings.math.title')} defaultExpanded={true}>
|
||||
<SettingGroup>
|
||||
<SettingRow>
|
||||
<SettingRowTitleSmall>{t('settings.math.engine.label')}</SettingRowTitleSmall>
|
||||
<Selector
|
||||
value={mathEngine}
|
||||
onChange={(value) => dispatch(setMathEngine(value as MathEngine))}
|
||||
options={[
|
||||
{ value: 'KaTeX', label: 'KaTeX' },
|
||||
{ value: 'MathJax', label: 'MathJax' },
|
||||
{ value: 'none', label: t('settings.math.engine.none') }
|
||||
]}
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
<SettingRowTitleSmall>
|
||||
{t('settings.math.single_dollar.label')}{' '}
|
||||
<Tooltip title={t('settings.math.single_dollar.tip')}>
|
||||
<CircleHelp size={14} style={{ marginLeft: 4 }} color="var(--color-text-2)" />
|
||||
</Tooltip>
|
||||
</SettingRowTitleSmall>
|
||||
<Switch
|
||||
size="small"
|
||||
checked={mathEnableSingleDollar}
|
||||
onChange={(checked) => dispatch(setMathEnableSingleDollar(checked))}
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
</SettingGroup>
|
||||
</CollapsibleSettingGroup>
|
||||
<CollapsibleSettingGroup title={t('chat.settings.code.title')} defaultExpanded={true}>
|
||||
<SettingGroup>
|
||||
<SettingRow>
|
||||
|
||||
@ -62,7 +62,7 @@ const persistedReducer = persistReducer(
|
||||
{
|
||||
key: 'cherry-studio',
|
||||
storage,
|
||||
version: 130,
|
||||
version: 131,
|
||||
blacklist: ['runtime', 'messages', 'messageBlocks', 'tabs'],
|
||||
migrate
|
||||
},
|
||||
|
||||
@ -2094,6 +2094,15 @@ const migrateConfig = {
|
||||
logger.error('migrate 130 error', error as Error)
|
||||
return state
|
||||
}
|
||||
},
|
||||
'131': (state: RootState) => {
|
||||
try {
|
||||
state.settings.mathEnableSingleDollar = true
|
||||
return state
|
||||
} catch (error) {
|
||||
logger.error('migrate 131 error', error as Error)
|
||||
return state
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -105,6 +105,7 @@ export interface SettingsState {
|
||||
codeWrappable: boolean
|
||||
codeImageTools: boolean
|
||||
mathEngine: MathEngine
|
||||
mathEnableSingleDollar: boolean
|
||||
messageStyle: 'plain' | 'bubble'
|
||||
foldDisplayMode: 'expanded' | 'compact'
|
||||
gridColumns: number
|
||||
@ -287,6 +288,7 @@ export const initialState: SettingsState = {
|
||||
codeWrappable: false,
|
||||
codeImageTools: false,
|
||||
mathEngine: 'KaTeX',
|
||||
mathEnableSingleDollar: true,
|
||||
messageStyle: 'plain',
|
||||
foldDisplayMode: 'expanded',
|
||||
gridColumns: 2,
|
||||
@ -616,6 +618,9 @@ const settingsSlice = createSlice({
|
||||
setMathEngine: (state, action: PayloadAction<MathEngine>) => {
|
||||
state.mathEngine = action.payload
|
||||
},
|
||||
setMathEnableSingleDollar: (state, action: PayloadAction<boolean>) => {
|
||||
state.mathEnableSingleDollar = action.payload
|
||||
},
|
||||
setFoldDisplayMode: (state, action: PayloadAction<'expanded' | 'compact'>) => {
|
||||
state.foldDisplayMode = action.payload
|
||||
},
|
||||
@ -898,6 +903,7 @@ export const {
|
||||
setCodeWrappable,
|
||||
setCodeImageTools,
|
||||
setMathEngine,
|
||||
setMathEnableSingleDollar,
|
||||
setFoldDisplayMode,
|
||||
setGridColumns,
|
||||
setGridPopoverTrigger,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user