fix link highlighting with mention present (#1544)
This commit is contained in:
parent
6d4ad59416
commit
b030d94a64
4 changed files with 44 additions and 80 deletions
|
@ -17,6 +17,7 @@ import {useColorSchemeStyle} from 'lib/hooks/useColorSchemeStyle'
|
|||
import {isUriImage, blobToDataUri} from 'lib/media/util'
|
||||
import {Emoji} from './web/EmojiPicker.web'
|
||||
import {LinkDecorator} from './web/LinkDecorator'
|
||||
import {generateJSON} from '@tiptap/html'
|
||||
|
||||
export interface TextInputRef {
|
||||
focus: () => void
|
||||
|
@ -52,6 +53,26 @@ export const TextInput = React.forwardRef(function TextInputImpl(
|
|||
ref,
|
||||
) {
|
||||
const modeClass = useColorSchemeStyle('ProseMirror-light', 'ProseMirror-dark')
|
||||
const extensions = React.useMemo(
|
||||
() => [
|
||||
Document,
|
||||
LinkDecorator,
|
||||
Mention.configure({
|
||||
HTMLAttributes: {
|
||||
class: 'mention',
|
||||
},
|
||||
suggestion: createSuggestion({autocompleteView}),
|
||||
}),
|
||||
Paragraph,
|
||||
Placeholder.configure({
|
||||
placeholder,
|
||||
}),
|
||||
Text,
|
||||
History,
|
||||
Hardbreak,
|
||||
],
|
||||
[autocompleteView, placeholder],
|
||||
)
|
||||
|
||||
React.useEffect(() => {
|
||||
textInputWebEmitter.addListener('publish', onPressPublish)
|
||||
|
@ -68,23 +89,7 @@ export const TextInput = React.forwardRef(function TextInputImpl(
|
|||
|
||||
const editor = useEditor(
|
||||
{
|
||||
extensions: [
|
||||
Document,
|
||||
LinkDecorator,
|
||||
Mention.configure({
|
||||
HTMLAttributes: {
|
||||
class: 'mention',
|
||||
},
|
||||
suggestion: createSuggestion({autocompleteView}),
|
||||
}),
|
||||
Paragraph,
|
||||
Placeholder.configure({
|
||||
placeholder,
|
||||
}),
|
||||
Text,
|
||||
History,
|
||||
Hardbreak,
|
||||
],
|
||||
extensions,
|
||||
editorProps: {
|
||||
attributes: {
|
||||
class: modeClass,
|
||||
|
@ -107,7 +112,7 @@ export const TextInput = React.forwardRef(function TextInputImpl(
|
|||
}
|
||||
},
|
||||
},
|
||||
content: textToEditorJson(richtext.text.toString()),
|
||||
content: generateJSON(richtext.text.toString(), extensions),
|
||||
autofocus: 'end',
|
||||
editable: true,
|
||||
injectCSS: true,
|
||||
|
@ -182,61 +187,6 @@ function editorJsonToText(json: JSONContent): string {
|
|||
return text
|
||||
}
|
||||
|
||||
function textToEditorJson(text: string): JSONContent {
|
||||
if (text === '' || text.length === 0) {
|
||||
return {
|
||||
text: '',
|
||||
}
|
||||
}
|
||||
|
||||
const lines = text.split('\n')
|
||||
const docContent: JSONContent[] = []
|
||||
|
||||
for (const line of lines) {
|
||||
if (line.trim() === '') {
|
||||
continue // skip empty lines
|
||||
}
|
||||
|
||||
const paragraphContent: JSONContent[] = []
|
||||
let position = 0
|
||||
|
||||
while (position < line.length) {
|
||||
if (line[position] === '@') {
|
||||
// Handle mentions
|
||||
let endPosition = position + 1
|
||||
while (endPosition < line.length && /\S/.test(line[endPosition])) {
|
||||
endPosition++
|
||||
}
|
||||
const mentionId = line.substring(position + 1, endPosition)
|
||||
paragraphContent.push({
|
||||
type: 'mention',
|
||||
attrs: {id: mentionId},
|
||||
})
|
||||
position = endPosition
|
||||
} else {
|
||||
// Handle regular text
|
||||
let endPosition = line.indexOf('@', position)
|
||||
if (endPosition === -1) endPosition = line.length
|
||||
paragraphContent.push({
|
||||
type: 'text',
|
||||
text: line.substring(position, endPosition),
|
||||
})
|
||||
position = endPosition
|
||||
}
|
||||
}
|
||||
|
||||
docContent.push({
|
||||
type: 'paragraph',
|
||||
content: paragraphContent,
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'doc',
|
||||
content: docContent,
|
||||
}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
import {Mark} from '@tiptap/core'
|
||||
import {Plugin, PluginKey} from '@tiptap/pm/state'
|
||||
import {findChildren} from '@tiptap/core'
|
||||
import {Node as ProsemirrorNode} from '@tiptap/pm/model'
|
||||
import {Decoration, DecorationSet} from '@tiptap/pm/view'
|
||||
import {isValidDomain} from 'lib/strings/url-helpers'
|
||||
|
@ -36,20 +35,20 @@ export const LinkDecorator = Mark.create({
|
|||
function getDecorations(doc: ProsemirrorNode) {
|
||||
const decorations: Decoration[] = []
|
||||
|
||||
findChildren(doc, node => node.type.name === 'paragraph').forEach(
|
||||
paragraphNode => {
|
||||
const textContent = paragraphNode.node.textContent
|
||||
doc.descendants((node, pos) => {
|
||||
if (node.isText && node.text) {
|
||||
const textContent = node.textContent
|
||||
|
||||
// links
|
||||
iterateUris(textContent, (from, to) => {
|
||||
decorations.push(
|
||||
Decoration.inline(paragraphNode.pos + from, paragraphNode.pos + to, {
|
||||
Decoration.inline(pos + from, pos + to, {
|
||||
class: 'autolink',
|
||||
}),
|
||||
)
|
||||
})
|
||||
},
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
return DecorationSet.create(doc, decorations)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue