fix: handle edge cases syntax highlight (#3892)

* fix: handle edge cases syntax highlight

* chore: remove unused import

* chore: remove unused code

* chore: reset type code when selection delete
This commit is contained in:
Faisal Amir 2024-10-31 10:19:22 +07:00 committed by GitHub
parent 267f3ab051
commit a6ca2e2bf0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -5,7 +5,7 @@ import { MessageStatus } from '@janhq/core'
import hljs from 'highlight.js'
import { useAtom, useAtomValue } from 'jotai'
import { BaseEditor, createEditor, Editor, Element, Transforms } from 'slate'
import { BaseEditor, createEditor, Editor, Transforms } from 'slate'
import { withHistory } from 'slate-history' // Import withHistory
import {
Editable,
@ -129,14 +129,27 @@ const RichTextEditor = ({
})
}
if (Editor.isBlock(editor, node) && node.type === 'code') {
if (Editor.isBlock(editor, node) && node.type === 'paragraph') {
node.children.forEach((child: { text: any }, childIndex: number) => {
const text = child.text
const { selection } = editor
if (selection) {
const selectedNode = Editor.node(editor, selection)
if (Editor.isBlock(editor, selectedNode[0] as CustomElement)) {
const isNodeEmpty = Editor.string(editor, selectedNode[1]) === ''
if (isNodeEmpty) {
// Reset language when a node is cleared
currentLanguage.current = 'plaintext'
}
}
}
// Match code block start and end
const startMatch = text.match(/^```(\w*)$/)
const endMatch = text.match(/^```$/)
const inlineMatch = text.match(/^`([^`]+)`$/) // Match inline code
if (startMatch) {
// If it's the start of a code block, store the language
@ -144,38 +157,6 @@ const RichTextEditor = ({
} else if (endMatch) {
// Reset language when code block ends
currentLanguage.current = 'plaintext'
} else if (inlineMatch) {
// Apply syntax highlighting to inline code
const codeContent = inlineMatch[1] // Get the content within the backticks
try {
hljs.highlight(codeContent, {
language:
currentLanguage.current.length > 1
? currentLanguage.current
: 'plaintext',
}).value
} catch (err) {
hljs.highlight(codeContent, {
language: 'javascript',
}).value
}
// Calculate the range for the inline code
const length = codeContent.length
ranges.push({
anchor: {
path: [...path, childIndex],
offset: inlineMatch.index + 1,
},
focus: {
path: [...path, childIndex],
offset: inlineMatch.index + 1 + length,
},
type: 'code',
code: true,
language: currentLanguage.current,
className: '', // Specify class name if needed
})
} else if (currentLanguage.current !== 'plaintext') {
// Highlight entire code line if in a code block
const leadingSpaces = text.match(/^\s*/)?.[0] ?? '' // Capture leading spaces
@ -206,7 +187,7 @@ const RichTextEditor = ({
anchor: { path: [...path, childIndex], offset: 0 },
focus: {
path: [...path, childIndex],
offset: leadingSpaces.length,
offset: slateTextIndex,
},
type: 'code',
code: true,
@ -240,6 +221,7 @@ const RichTextEditor = ({
slateTextIndex += length
})
} else {
currentLanguage.current = 'plaintext'
ranges.push({
anchor: { path: [...path, childIndex], offset: 0 },
focus: { path: [...path, childIndex], offset: text.length },
@ -341,35 +323,6 @@ const RichTextEditor = ({
resetEditor()
} else onStopInferenceClick()
}
if (event.key === '`') {
// Determine whether any of the currently selected blocks are code blocks.
const [match] = Editor.nodes(editor, {
match: (n) =>
Element.isElement(n) && (n as CustomElement).type === 'code',
})
// Toggle the block type dependsing on whether there's already a match.
Transforms.setNodes(
editor,
{ type: match ? 'paragraph' : 'code' },
{ match: (n) => Element.isElement(n) && Editor.isBlock(editor, n) }
)
}
if (event.key === 'Tab') {
const [match] = Editor.nodes(editor, {
match: (n) => {
return (n as CustomElement).type === 'code'
},
mode: 'lowest',
})
if (match) {
event.preventDefault()
// Insert a tab character
Editor.insertText(editor, ' ') // Insert 2 spaces
}
}
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[currentPrompt, editor, messages]