1
0
mirror of https://github.com/lencx/ChatGPT.git synced 2024-10-01 01:06:13 -04:00

chore: markdown

This commit is contained in:
lencx 2023-01-19 00:13:10 +08:00
parent 8a3ccb6231
commit 1af173cb24
7 changed files with 108 additions and 43 deletions

View File

@ -46,6 +46,7 @@
"react-resizable-panels": "^0.0.33", "react-resizable-panels": "^0.0.33",
"react-router-dom": "^6.4.5", "react-router-dom": "^6.4.5",
"react-syntax-highlighter": "^15.5.0", "react-syntax-highlighter": "^15.5.0",
"remark-gfm": "^3.0.1",
"uuid": "^9.0.0" "uuid": "^9.0.0"
}, },
"devDependencies": { "devDependencies": {

View File

@ -1,21 +1,41 @@
import { FC, useEffect, useState } from 'react';
import Editor from "@monaco-editor/react"; import Editor from "@monaco-editor/react";
import { Panel, PanelGroup, PanelResizeHandle } from 'react-resizable-panels'; import { Panel, PanelGroup, PanelResizeHandle } from 'react-resizable-panels';
import Markdown from '@/components/Markdown';
import './index.scss'; import './index.scss';
const MarkdownEditor = () => { interface MarkdownEditorProps {
value?: string;
onChange?: (v: string) => void;
}
const MarkdownEditor: FC<MarkdownEditorProps> = ({ value = '', onChange }) => {
const [content, setContent] = useState(value);
useEffect(() => {
setContent(value);
onChange && onChange(value);
}, [value])
const handleEdit = (e: any) => {
setContent(e);
onChange && onChange(e);
}
return ( return (
<div> <div className="md-main">
<PanelGroup direction="horizontal"> <PanelGroup direction="horizontal">
<Panel> <Panel>
<Editor <Editor
height="calc(100vh - 120px)"
language="markdown" language="markdown"
value={content}
onChange={handleEdit}
/> />
</Panel> </Panel>
<PanelResizeHandle className="resize-handle" /> <PanelResizeHandle className="resize-handle" />
<Panel collapsible={true}> <Panel collapsible={true}>
<div>1284</div> <Markdown className="edit-preview">{content}</Markdown>
</Panel> </Panel>
</PanelGroup> </PanelGroup>
</div> </div>

View File

@ -1,11 +1,24 @@
.markdown-body { .markdown-body {
height: 100%;
overflow: auto;
font-family: -apple-system,BlinkMacSystemFont,"Segoe UI","Noto Sans",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji"; font-family: -apple-system,BlinkMacSystemFont,"Segoe UI","Noto Sans",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";
&.edit-preview {
padding: 10px;
font-size: 14px;
}
pre, code { pre, code {
font-family: monospace, monospace; font-family: monospace, monospace;
} }
} }
.md-main {
height: calc(100vh - 130px);
overflow: hidden;
}
.resize-handle { .resize-handle {
width: 0.25rem; width: 0.25rem;
transition: 250ms linear background-color; transition: 250ms linear background-color;

View File

@ -1,5 +1,7 @@
import { FC } from 'react'; import { FC } from 'react';
import clsx from 'clsx';
import ReactMarkdown from 'react-markdown'; import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import SyntaxHighlighter from 'react-syntax-highlighter'; import SyntaxHighlighter from 'react-syntax-highlighter';
import agate from 'react-syntax-highlighter/dist/esm/styles/hljs/agate'; import agate from 'react-syntax-highlighter/dist/esm/styles/hljs/agate';
@ -7,36 +9,40 @@ import './index.scss';
interface MarkdownProps { interface MarkdownProps {
children: string; children: string;
className?: string;
} }
const Markdown: FC<MarkdownProps> = ({ children }) => { const Markdown: FC<MarkdownProps> = ({ children, className }) => {
return ( return (
<div className='markdown-body'> <div className={clsx(className, 'markdown-body')}>
<ReactMarkdown <div>
children={children} <ReactMarkdown
linkTarget="_blank" children={children}
components={{ linkTarget="_blank"
code({node, inline, className, children, ...props}) { remarkPlugins={[remarkGfm]}
const match = /language-(\w+)/.exec(className || '') components={{
return !inline && match ? ( code({node, inline, className, children, ...props}) {
<SyntaxHighlighter const match = /language-(\w+)/.exec(className || '')
children={String(children).replace(/\n$/, '')} return !inline && match ? (
style={agate as any} <SyntaxHighlighter
language={match[1]} children={String(children).replace(/\n$/, '')}
showLineNumbers style={agate as any}
lineNumberStyle={{ color: '#999' }} language={match[1]}
PreTag="div" showLineNumbers
{...props} lineNumberStyle={{ color: '#999' }}
/> PreTag="div"
) : ( {...props}
<code className={className} {...props}> />
{children} ) : (
</code> <code className={className} {...props}>
) {children}
} </code>
}} )
/> }
}}
/>
</div>
</div> </div>
) )
} }

5
src/main.scss vendored
View File

@ -69,12 +69,11 @@ html, body {
} }
} }
.chat-file-path, .chat-file-path {
.chat-sync-path {
font-size: 12px; font-size: 12px;
font-weight: 500; font-weight: 500;
color: #888; color: #888;
margin-bottom: 5px; margin-bottom: 3px;
line-height: 16px; line-height: 16px;
> div { > div {

15
src/view/markdown/index.scss vendored Normal file
View File

@ -0,0 +1,15 @@
.md-task {
margin-bottom: 5px;
.ant-breadcrumb-link {
padding: 3px 5px;
transition: all 300ms ease;
border-radius: 4px;
&:hover {
color: rgba(0, 0, 0, 0.88);
background-color: rgba(0, 0, 0, 0.06);
cursor: pointer;
}
}
}

View File

@ -3,30 +3,41 @@ import { useLocation } from 'react-router-dom';
import { Breadcrumb } from 'antd'; import { Breadcrumb } from 'antd';
import { ArrowLeftOutlined } from '@ant-design/icons'; import { ArrowLeftOutlined } from '@ant-design/icons';
import MarkdownEditor from '@/components/Markdown/Editor'; import MarkdownEditor from '@/components/Markdown/Editor';
import { fs, shell } from '@tauri-apps/api';
import useInit from '@/hooks/useInit'; import useInit from '@/hooks/useInit';
import { getPath } from '@/view/notes/config'; import { getPath } from '@/view/notes/config';
import './index.scss';
export default function Markdown() { export default function Markdown() {
const [filePath, setFilePath] = useState(''); const [filePath, setFilePath] = useState('');
const [source, setSource] = useState('');
const location = useLocation(); const location = useLocation();
const state = location?.state; const state = location?.state;
useInit(async () => { useInit(async () => {
setFilePath(await getPath(state)); const file = await getPath(state);
setFilePath(file);
setSource(await fs.readTextFile(file))
}) })
const handleChange = async (v: string) => {
await fs.writeTextFile(filePath, v);
};
return ( return (
<> <>
<Breadcrumb separator=" "> <div className="md-task">
<Breadcrumb.Item href=""> <Breadcrumb separator="">
<ArrowLeftOutlined /> <Breadcrumb.Item onClick={() => history.go(-1)}>
</Breadcrumb.Item> <ArrowLeftOutlined />
<Breadcrumb.Item href=""> </Breadcrumb.Item>
{filePath} <Breadcrumb.Item onClick={() => shell.open(filePath)}>
</Breadcrumb.Item> {filePath}
</Breadcrumb> </Breadcrumb.Item>
<MarkdownEditor /> </Breadcrumb>
</div>
<MarkdownEditor value={source} onChange={handleChange} />
</> </>
); );
} }