feat: enhance markdown style
This commit is contained in:
parent
5d90489a04
commit
2969a05f10
@ -33,10 +33,14 @@
|
|||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
font-size: 2em;
|
font-size: 2em;
|
||||||
|
border-bottom: 0.5px solid var(--color-border);
|
||||||
|
padding-bottom: 0.3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
h2 {
|
h2 {
|
||||||
font-size: 1.5em;
|
font-size: 1.5em;
|
||||||
|
border-bottom: 0.5px solid var(--color-border);
|
||||||
|
padding-bottom: 0.3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
h3 {
|
h3 {
|
||||||
@ -69,11 +73,16 @@
|
|||||||
margin-bottom: 0.5em;
|
margin-bottom: 0.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
li > ul,
|
||||||
|
li > ol {
|
||||||
|
margin: 0.5em 0;
|
||||||
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
border: none;
|
border: none;
|
||||||
border-top: 1px solid #555;
|
border-top: 0.5px solid var(--color-border);
|
||||||
margin: 20px 0;
|
margin: 20px 0;
|
||||||
background-color: #555;
|
background-color: var(--color-border);
|
||||||
}
|
}
|
||||||
|
|
||||||
span {
|
span {
|
||||||
@ -82,6 +91,7 @@
|
|||||||
|
|
||||||
code {
|
code {
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
|
font-family: 'Courier New', Courier, monospace;
|
||||||
}
|
}
|
||||||
|
|
||||||
p code {
|
p code {
|
||||||
@ -90,7 +100,84 @@
|
|||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre pre {
|
pre {
|
||||||
|
white-space: pre-wrap;
|
||||||
|
padding: 1em;
|
||||||
|
border-radius: 5px;
|
||||||
|
overflow-x: auto;
|
||||||
|
pre {
|
||||||
margin: 0 !important;
|
margin: 0 !important;
|
||||||
}
|
}
|
||||||
|
code {
|
||||||
|
background: none;
|
||||||
|
padding: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote {
|
||||||
|
margin: 1em 0;
|
||||||
|
padding-left: 1em;
|
||||||
|
color: var(--color-text-light);
|
||||||
|
border-left: 4px solid var(--color-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
margin: 1em 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
th,
|
||||||
|
td {
|
||||||
|
border: 0.5px solid var(--color-border);
|
||||||
|
padding: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
th {
|
||||||
|
background-color: var(--color-background-mute);
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
max-width: 100%;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: var(--color-primary);
|
||||||
|
text-decoration: none;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
strong {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
em {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
del {
|
||||||
|
text-decoration: line-through;
|
||||||
|
}
|
||||||
|
|
||||||
|
sup,
|
||||||
|
sub {
|
||||||
|
font-size: 75%;
|
||||||
|
line-height: 0;
|
||||||
|
position: relative;
|
||||||
|
vertical-align: baseline;
|
||||||
|
}
|
||||||
|
|
||||||
|
sup {
|
||||||
|
top: -0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub {
|
||||||
|
bottom: -0.25em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
/* 全局初始化滚动条样式 */
|
/* 全局初始化滚动条样式 */
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
width: 3px;
|
width: 3px;
|
||||||
|
height: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar-track {
|
::-webkit-scrollbar-track {
|
||||||
|
|||||||
@ -146,7 +146,7 @@ const AssistantItem = styled.div`
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
padding: 7px 10px;
|
padding: 7px 10px;
|
||||||
position: relative;
|
position: relative;
|
||||||
border-radius: 3px;
|
border-radius: 8px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-family: Poppins;
|
font-family: Poppins;
|
||||||
.anticon {
|
.anticon {
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import {
|
|||||||
DeleteOutlined,
|
DeleteOutlined,
|
||||||
EditOutlined,
|
EditOutlined,
|
||||||
MenuOutlined,
|
MenuOutlined,
|
||||||
|
QuestionCircleOutlined,
|
||||||
SaveOutlined,
|
SaveOutlined,
|
||||||
SyncOutlined
|
SyncOutlined
|
||||||
} from '@ant-design/icons'
|
} from '@ant-design/icons'
|
||||||
@ -15,7 +16,7 @@ import { useRuntime } from '@renderer/hooks/useStore'
|
|||||||
import { EVENT_NAMES, EventEmitter } from '@renderer/services/event'
|
import { EVENT_NAMES, EventEmitter } from '@renderer/services/event'
|
||||||
import { Message } from '@renderer/types'
|
import { Message } from '@renderer/types'
|
||||||
import { firstLetter, removeLeadingEmoji } from '@renderer/utils'
|
import { firstLetter, removeLeadingEmoji } from '@renderer/utils'
|
||||||
import { Avatar, Dropdown, Tooltip } from 'antd'
|
import { Avatar, Dropdown, Popconfirm, Tooltip } from 'antd'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import { upperFirst } from 'lodash'
|
import { upperFirst } from 'lodash'
|
||||||
import { FC, memo, useCallback, useMemo, useState } from 'react'
|
import { FC, memo, useCallback, useMemo, useState } from 'react'
|
||||||
@ -52,17 +53,6 @@ const MessageItem: FC<Props> = ({ message, index, showMenu, onDeleteMessage }) =
|
|||||||
setTimeout(() => setCopied(false), 2000)
|
setTimeout(() => setCopied(false), 2000)
|
||||||
}, [message.content, t])
|
}, [message.content, t])
|
||||||
|
|
||||||
const onDelete = useCallback(async () => {
|
|
||||||
const confirmed = await window.modal.confirm({
|
|
||||||
icon: null,
|
|
||||||
title: t('message.message.delete.title'),
|
|
||||||
content: t('message.message.delete.content'),
|
|
||||||
okText: t('common.delete'),
|
|
||||||
okType: 'danger'
|
|
||||||
})
|
|
||||||
confirmed && onDeleteMessage?.(message)
|
|
||||||
}, [message, onDeleteMessage, t])
|
|
||||||
|
|
||||||
const onEdit = useCallback(() => EventEmitter.emit(EVENT_NAMES.EDIT_MESSAGE, message), [message])
|
const onEdit = useCallback(() => EventEmitter.emit(EVENT_NAMES.EDIT_MESSAGE, message), [message])
|
||||||
|
|
||||||
const onRegenerate = useCallback(() => {
|
const onRegenerate = useCallback(() => {
|
||||||
@ -142,11 +132,17 @@ const MessageItem: FC<Props> = ({ message, index, showMenu, onDeleteMessage }) =
|
|||||||
{copied && <CheckOutlined style={{ color: 'var(--color-primary)' }} />}
|
{copied && <CheckOutlined style={{ color: 'var(--color-primary)' }} />}
|
||||||
</ActionButton>
|
</ActionButton>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Tooltip title={t('common.delete')} mouseEnterDelay={0.8}>
|
<Popconfirm
|
||||||
<ActionButton onClick={onDelete}>
|
title={t('message.message.delete.content')}
|
||||||
|
okButtonProps={{ danger: true }}
|
||||||
|
icon={<QuestionCircleOutlined style={{ color: 'red' }} />}
|
||||||
|
onConfirm={() => onDeleteMessage?.(message)}>
|
||||||
|
<Tooltip title={t('common.delete')} mouseEnterDelay={1}>
|
||||||
|
<ActionButton>
|
||||||
<DeleteOutlined />
|
<DeleteOutlined />
|
||||||
</ActionButton>
|
</ActionButton>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
</Popconfirm>
|
||||||
{canRegenerate && (
|
{canRegenerate && (
|
||||||
<Tooltip title={t('common.regenerate')} mouseEnterDelay={0.8}>
|
<Tooltip title={t('common.regenerate')} mouseEnterDelay={0.8}>
|
||||||
<ActionButton onClick={onRegenerate}>
|
<ActionButton onClick={onRegenerate}>
|
||||||
|
|||||||
@ -5,7 +5,8 @@ import {
|
|||||||
FullscreenOutlined,
|
FullscreenOutlined,
|
||||||
HistoryOutlined,
|
HistoryOutlined,
|
||||||
PauseCircleOutlined,
|
PauseCircleOutlined,
|
||||||
PlusCircleOutlined
|
PlusCircleOutlined,
|
||||||
|
QuestionCircleOutlined
|
||||||
} from '@ant-design/icons'
|
} from '@ant-design/icons'
|
||||||
import { DEFAULT_CONEXTCOUNT } from '@renderer/config/constant'
|
import { DEFAULT_CONEXTCOUNT } from '@renderer/config/constant'
|
||||||
import { useAssistant } from '@renderer/hooks/useAssistant'
|
import { useAssistant } from '@renderer/hooks/useAssistant'
|
||||||
@ -149,11 +150,11 @@ const Inputbar: FC<Props> = ({ assistant, setActiveTopic }) => {
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Tooltip placement="top" title={t('assistant.input.clear')} arrow>
|
<Tooltip placement="top" title={t('assistant.input.clear')} arrow>
|
||||||
<Popconfirm
|
<Popconfirm
|
||||||
icon={false}
|
title={t('assistant.input.clear.content')}
|
||||||
title={t('assistant.input.clear.title')}
|
|
||||||
description={t('assistant.input.clear.content')}
|
|
||||||
placement="top"
|
placement="top"
|
||||||
onConfirm={clearTopic}
|
onConfirm={clearTopic}
|
||||||
|
okButtonProps={{ danger: true }}
|
||||||
|
icon={<QuestionCircleOutlined style={{ color: 'red' }} />}
|
||||||
okText={t('assistant.input.clear')}>
|
okText={t('assistant.input.clear')}>
|
||||||
<ToolbarButton type="text">
|
<ToolbarButton type="text">
|
||||||
<ClearOutlined />
|
<ClearOutlined />
|
||||||
|
|||||||
@ -33,13 +33,13 @@ const Markdown: FC<Props> = ({ message }) => {
|
|||||||
<ReactMarkdown
|
<ReactMarkdown
|
||||||
className="markdown"
|
className="markdown"
|
||||||
remarkPlugins={[remarkGfm, remarkMath]}
|
remarkPlugins={[remarkGfm, remarkMath]}
|
||||||
remarkRehypeOptions={{ footnoteLabel: t('common.footnote'), footnoteLabelTagName: 'h4' }}
|
remarkRehypeOptions={{ footnoteLabel: ' ', footnoteLabelTagName: 'h4' }}
|
||||||
rehypePlugins={[rehypeKatex]}
|
rehypePlugins={[rehypeKatex]}
|
||||||
components={{ code: CodeBlock as any, a: Link as any }}>
|
components={{ code: CodeBlock as any, a: Link as any }}>
|
||||||
{getMessageContent(message)}
|
{getMessageContent(message)}
|
||||||
</ReactMarkdown>
|
</ReactMarkdown>
|
||||||
)
|
)
|
||||||
}, [getMessageContent, message, t])
|
}, [getMessageContent, message])
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Markdown
|
export default Markdown
|
||||||
|
|||||||
@ -108,6 +108,7 @@ const Tab = styled.div`
|
|||||||
const TabContent = styled.div`
|
const TabContent = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
flex-direction: column;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
`
|
`
|
||||||
|
|
||||||
|
|||||||
@ -142,7 +142,7 @@ const Container = styled.div`
|
|||||||
const TopicListItem = styled.div`
|
const TopicListItem = styled.div`
|
||||||
padding: 8px 10px;
|
padding: 8px 10px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
border-radius: 3px;
|
border-radius: 8px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|||||||
@ -16,7 +16,7 @@ const AntdProvider: FC<PropsWithChildren> = ({ children }) => {
|
|||||||
algorithm: [_theme === 'dark' ? theme.darkAlgorithm : theme.defaultAlgorithm],
|
algorithm: [_theme === 'dark' ? theme.darkAlgorithm : theme.defaultAlgorithm],
|
||||||
token: {
|
token: {
|
||||||
colorPrimary: '#00b96b',
|
colorPrimary: '#00b96b',
|
||||||
borderRadius: 3
|
borderRadius: 8
|
||||||
}
|
}
|
||||||
}}>
|
}}>
|
||||||
{children}
|
{children}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user