Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: markdown inline inputbox #4269

Merged
merged 1 commit into from
Dec 12, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import { useCallback, useEffect, useMemo, useRef, ClipboardEvent } from 'react'

import { MessageStatus } from '@janhq/core'
import hljs from 'highlight.js'
import { useAtom, useAtomValue } from 'jotai'

import { BaseEditor, createEditor, Editor, Transforms } from 'slate'
Expand Down Expand Up @@ -85,20 +84,20 @@
// The decorate function identifies code blocks and marks the ranges
const decorate = useCallback(
(entry: [any, any]) => {
const ranges: any[] = []
const [node, path] = entry

Check warning on line 88 in web/screens/Thread/ThreadCenterPanel/ChatInput/RichTextEditor.tsx

View workflow job for this annotation

GitHub Actions / coverage-check

87-88 lines are not covered with tests

if (Editor.isBlock(editor, node) && node.type === 'paragraph') {
node.children.forEach((child: { text: any }, childIndex: number) => {
const text = child.text

Check warning on line 92 in web/screens/Thread/ThreadCenterPanel/ChatInput/RichTextEditor.tsx

View workflow job for this annotation

GitHub Actions / coverage-check

90-92 lines are not covered with tests

// Match bold text pattern *text*
const boldMatches = [...text.matchAll(/(\*.*?\*)/g)] // Find bold patterns
boldMatches.forEach((match) => {
const startOffset = match.index + 1 || 0
const length = match[0].length - 2

Check warning on line 98 in web/screens/Thread/ThreadCenterPanel/ChatInput/RichTextEditor.tsx

View workflow job for this annotation

GitHub Actions / coverage-check

95-98 lines are not covered with tests

ranges.push({

Check warning on line 100 in web/screens/Thread/ThreadCenterPanel/ChatInput/RichTextEditor.tsx

View workflow job for this annotation

GitHub Actions / coverage-check

100 line is not covered with tests
anchor: { path: [...path, childIndex], offset: startOffset },
focus: {
path: [...path, childIndex],
Expand All @@ -111,17 +110,17 @@
})
}

if (Editor.isBlock(editor, node) && node.type === 'paragraph') {
node.children.forEach((child: { text: any }, childIndex: number) => {
const text = child.text

Check warning on line 115 in web/screens/Thread/ThreadCenterPanel/ChatInput/RichTextEditor.tsx

View workflow job for this annotation

GitHub Actions / coverage-check

113-115 lines are not covered with tests

// Match bold text pattern **text**
const boldMatches = [...text.matchAll(/(\*\*.*?\*\*)/g)] // Find bold patterns
boldMatches.forEach((match) => {
const startOffset = match.index + 2 || 0
const length = match[0].length - 4

Check warning on line 121 in web/screens/Thread/ThreadCenterPanel/ChatInput/RichTextEditor.tsx

View workflow job for this annotation

GitHub Actions / coverage-check

118-121 lines are not covered with tests

ranges.push({

Check warning on line 123 in web/screens/Thread/ThreadCenterPanel/ChatInput/RichTextEditor.tsx

View workflow job for this annotation

GitHub Actions / coverage-check

123 line is not covered with tests
anchor: { path: [...path, childIndex], offset: startOffset },
focus: {
path: [...path, childIndex],
Expand All @@ -134,97 +133,9 @@
})
}

if (Editor.isBlock(editor, node) && node.type === 'paragraph') {
node.children.forEach((child: { text: any }, childIndex: number) => {
const text = child.text

const codeBlockStartRegex = /```(\w*)/g
const matches = [...currentPrompt.matchAll(codeBlockStartRegex)]

if (matches.length % 2 !== 0) {
hasEndBackticks.current = false
}

// Match code block start and end
const lang = text.match(/^```(\w*)$/)
const endMatch = text.match(/^```$/)

if (lang) {
// If it's the start of a code block, store the language
currentLanguage.current = lang[1] || 'plaintext'
} else if (endMatch) {
// Reset language when code block ends
currentLanguage.current = 'plaintext'
} else if (
hasStartBackticks.current &&
hasEndBackticks.current &&
currentLanguage.current !== 'plaintext'
) {
// Highlight entire code line if in a code block

const codeContent = text.trim() // Remove leading spaces for highlighting

let highlighted = ''
highlighted = hljs.highlightAuto(codeContent).value
try {
highlighted = hljs.highlight(codeContent, {
language:
currentLanguage.current.length > 1
? currentLanguage.current
: 'plaintext',
}).value
} catch (err) {
highlighted = hljs.highlight(codeContent, {
language: 'javascript',
}).value
}

const parser = new DOMParser()
const doc = parser.parseFromString(highlighted, 'text/html')

let slateTextIndex = 0

doc.body.childNodes.forEach((childNode) => {
const childText = childNode.textContent || ''

const length = childText.length
const className =
childNode.nodeType === Node.ELEMENT_NODE
? (childNode as HTMLElement).className
: ''

ranges.push({
anchor: {
path: [...path, childIndex],
offset: slateTextIndex,
},
focus: {
path: [...path, childIndex],
offset: slateTextIndex + length,
},
type: 'code',
code: true,
language: currentLanguage.current,
className,
})

slateTextIndex += length
})
} else {
currentLanguage.current = 'plaintext'
ranges.push({
anchor: { path: [...path, childIndex], offset: 0 },
focus: { path: [...path, childIndex], offset: text.length },
type: 'paragraph', // Treat as a paragraph
code: false,
})
}
})
}

return ranges

Check warning on line 136 in web/screens/Thread/ThreadCenterPanel/ChatInput/RichTextEditor.tsx

View workflow job for this annotation

GitHub Actions / coverage-check

136 line is not covered with tests
},
[currentPrompt, editor]
[editor]
)

// RenderLeaf applies the decoration styles
Expand Down Expand Up @@ -269,10 +180,10 @@

useEffect(() => {
if (textareaRef.current?.clientHeight) {
textareaRef.current.style.height = activeSettingInputBox

Check warning on line 183 in web/screens/Thread/ThreadCenterPanel/ChatInput/RichTextEditor.tsx

View workflow job for this annotation

GitHub Actions / coverage-check

183 line is not covered with tests
? '100px'
: '40px'
textareaRef.current.style.height =

Check warning on line 186 in web/screens/Thread/ThreadCenterPanel/ChatInput/RichTextEditor.tsx

View workflow job for this annotation

GitHub Actions / coverage-check

186 line is not covered with tests
textareaRef.current.scrollHeight + 2 + 'px'
textareaRef.current?.scrollTo({
top: textareaRef.current.scrollHeight,
Expand Down
Loading