From 3a48c03dbf9166c37157556d0bef6b6ad0d76c84 Mon Sep 17 00:00:00 2001 From: Faisal Amir Date: Wed, 16 Oct 2024 09:46:07 +0700 Subject: [PATCH 1/8] feat: enable render markdown for user message --- .../SimpleTextMessage/index.tsx | 36 ++++++------------- 1 file changed, 11 insertions(+), 25 deletions(-) diff --git a/web/screens/Thread/ThreadCenterPanel/SimpleTextMessage/index.tsx b/web/screens/Thread/ThreadCenterPanel/SimpleTextMessage/index.tsx index da10300dc6..61ec0889a1 100644 --- a/web/screens/Thread/ThreadCenterPanel/SimpleTextMessage/index.tsx +++ b/web/screens/Thread/ThreadCenterPanel/SimpleTextMessage/index.tsx @@ -276,32 +276,18 @@ const SimpleTextMessage: React.FC = (props) => { )} - {isUser ? ( - <> - {editMessage === props.id ? ( -
- -
- ) : ( -
- {text} -
- )} - - ) : ( -
+ {editMessage === props.id && ( +
+ +
)} + +
From 162047a102d64908d8261f36113c98cea592dc6c Mon Sep 17 00:00:00 2001 From: Faisal Amir Date: Thu, 17 Oct 2024 13:31:37 +0700 Subject: [PATCH 2/8] wip: slate --- web/package.json | 4 +- .../ChatInput/CodeEditor.tsx | 138 ++++++++++++++++++ .../ThreadCenterPanel/ChatInput/index.tsx | 5 + 3 files changed, 146 insertions(+), 1 deletion(-) create mode 100644 web/screens/Thread/ThreadCenterPanel/ChatInput/CodeEditor.tsx diff --git a/web/package.json b/web/package.json index 1cf5aa752f..a5afc9cbc9 100644 --- a/web/package.json +++ b/web/package.json @@ -50,7 +50,9 @@ "ulidx": "^2.3.0", "use-debounce": "^10.0.0", "uuid": "^9.0.1", - "zod": "^3.22.4" + "zod": "^3.22.4", + "slate": "latest", + "slate-react": "latest" }, "devDependencies": { "@next/eslint-plugin-next": "^14.0.1", diff --git a/web/screens/Thread/ThreadCenterPanel/ChatInput/CodeEditor.tsx b/web/screens/Thread/ThreadCenterPanel/ChatInput/CodeEditor.tsx new file mode 100644 index 0000000000..9523eda79e --- /dev/null +++ b/web/screens/Thread/ThreadCenterPanel/ChatInput/CodeEditor.tsx @@ -0,0 +1,138 @@ +import { useCallback, useState } from 'react' + +import { + BaseEditor, + BaseRange, + createEditor, + Descendant, + Transforms, + Element, + Editor, +} from 'slate' +import { + Editable, + ReactEditor, + Slate, + withReact, + RenderLeafProps, +} from 'slate-react' + +type CustomElement = { type: 'paragraph' | 'codeblock'; children: CustomText[] } +type CustomText = { text: string; code?: boolean } + +declare module 'slate' { + interface CustomTypes { + Editor: BaseEditor & ReactEditor + Element: CustomElement + Text: CustomText + } +} + +const initialValue: CustomElement[] = [ + { + type: 'paragraph', + children: [{ text: 'A line of text in a paragraph.' }], + }, +] + +const App = () => { + const [editor] = useState(() => withReact(createEditor())) + + const renderLeaf = useCallback( + ({ attributes, children, leaf }: RenderLeafProps) => { + if (leaf.code) { + return ( + + {children} + + ) + } + + return {children} + }, + [] + ) + + const handleChange = (value: Descendant[]) => { + const paragraphs = value.filter( + (node) => (node as CustomElement).type === 'paragraph' + ) + let inCodeBlock = false // Flag to track if we are inside a code block + let codeBlockNodes: Descendant[] = [] // Array to hold nodes between backticks + + paragraphs.forEach((node, nodeIndex) => { + if ('children' in node) { + node.children.forEach((child, childIndex) => { + const text = child.text + + // Check for the start backtick + if (text === '```') { + if (!inCodeBlock) { + // We found the start of a code block + inCodeBlock = true + return // Skip to next node + } else { + // We found the end of a code block + inCodeBlock = false + // Log or process the collected nodes in codeBlockNodes + console.log('Code block nodes:', codeBlockNodes) + + codeBlockNodes = [] // Reset for the next block + return // Skip to next node + } + } + + // If we are inside a code block, add the node to codeBlockNodes + if (inCodeBlock) { + Transforms.setNodes( + editor, + { code: true }, + { at: [nodeIndex, childIndex], match: (n) => n === child } + ) + codeBlockNodes.push({ + text: text, + code: true, // Mark the text as code + }) + } + }) + } + }) + + // Handle case where the editor ends in a code block (if needed) + if (inCodeBlock) { + console.log('Incomplete code block:', codeBlockNodes) + } + } + + const useDecorate = (editor) => { + return useCallback( + ([node, path]) => { + console.log('node', node) + if (Element.isElement(node)) { + // Assuming you want to return an empty array as a default + if (node.children[0].text !== '```') { + Transforms.setNodes(editor, { code: false }) + } + return [] + } + + return [] + }, + [editor.nodeToDecorations] + ) + } + + const decorate = useDecorate(editor) + + return ( + + + + ) +} + +export default App diff --git a/web/screens/Thread/ThreadCenterPanel/ChatInput/index.tsx b/web/screens/Thread/ThreadCenterPanel/ChatInput/index.tsx index a7c5ad1216..606d1cc35e 100644 --- a/web/screens/Thread/ThreadCenterPanel/ChatInput/index.tsx +++ b/web/screens/Thread/ThreadCenterPanel/ChatInput/index.tsx @@ -29,6 +29,8 @@ import { isLocalEngine } from '@/utils/modelEngine' import FileUploadPreview from '../FileUploadPreview' import ImageUploadPreview from '../ImageUploadPreview' +import CodeEditor from './CodeEditor' + import { showRightPanelAtom } from '@/helpers/atoms/App.atom' import { experimentalFeatureEnabledAtom } from '@/helpers/atoms/AppConfig.atom' import { getCurrentChatMessagesAtom } from '@/helpers/atoms/ChatMessage.atom' @@ -163,6 +165,9 @@ const ChatInput = () => {
{renderPreview(fileUpload)} + + +