about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--package.json1
-rw-r--r--src/view/com/composer/text-input/TextInput.web.tsx96
-rw-r--r--src/view/com/composer/text-input/web/LinkDecorator.ts13
-rw-r--r--yarn.lock14
4 files changed, 44 insertions, 80 deletions
diff --git a/package.json b/package.json
index 61c20d2f5..32ca3de7a 100644
--- a/package.json
+++ b/package.json
@@ -63,6 +63,7 @@
     "@tiptap/extension-paragraph": "^2.0.0-beta.220",
     "@tiptap/extension-placeholder": "^2.0.0-beta.220",
     "@tiptap/extension-text": "^2.0.0-beta.220",
+    "@tiptap/html": "^2.1.11",
     "@tiptap/pm": "^2.0.0-beta.220",
     "@tiptap/react": "^2.0.0-beta.220",
     "@tiptap/suggestion": "^2.0.0-beta.220",
diff --git a/src/view/com/composer/text-input/TextInput.web.tsx b/src/view/com/composer/text-input/TextInput.web.tsx
index 7eea904ab..31e372567 100644
--- a/src/view/com/composer/text-input/TextInput.web.tsx
+++ b/src/view/com/composer/text-input/TextInput.web.tsx
@@ -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,
diff --git a/src/view/com/composer/text-input/web/LinkDecorator.ts b/src/view/com/composer/text-input/web/LinkDecorator.ts
index 531e8d5a0..19945de08 100644
--- a/src/view/com/composer/text-input/web/LinkDecorator.ts
+++ b/src/view/com/composer/text-input/web/LinkDecorator.ts
@@ -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)
 }
diff --git a/yarn.lock b/yarn.lock
index 2bd08edb9..7533bb439 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4972,6 +4972,13 @@
   resolved "https://registry.yarnpkg.com/@tiptap/extension-text/-/extension-text-2.1.6.tgz#23f36114ee164e3da2fd326145ac7b7f8bd34c56"
   integrity sha512-CqV0N6ngoXZFeJGlQ86FSZJ/0k7+BN3S6aSUcb5DRAKsSEv/Ga1LvSG24sHy+dwjTuj3EtRPJSVZTFcSB17ZSA==
 
+"@tiptap/html@^2.1.11":
+  version "2.1.11"
+  resolved "https://registry.yarnpkg.com/@tiptap/html/-/html-2.1.11.tgz#998421b526f200d01c549f37eb8fae2a0d1f0ed6"
+  integrity sha512-VKmBb1c3YN9hZfBzkV+QERf3ZWBUHHxjv2/BOr/Dw6mbb6+0iA1nxO9vQYPUb+xAmlm0n8vWwc7YQ8rxBwTKWQ==
+  dependencies:
+    zeed-dom "^0.9.19"
+
 "@tiptap/pm@^2.0.0-beta.220":
   version "2.1.6"
   resolved "https://registry.yarnpkg.com/@tiptap/pm/-/pm-2.1.6.tgz#4c196a7147fedd71316ef3413bb0e98d5c97726d"
@@ -19227,6 +19234,13 @@ yocto-queue@^1.0.0:
   resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-1.0.0.tgz#7f816433fb2cbc511ec8bf7d263c3b58a1a3c251"
   integrity sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==
 
+zeed-dom@^0.9.19:
+  version "0.9.26"
+  resolved "https://registry.yarnpkg.com/zeed-dom/-/zeed-dom-0.9.26.tgz#f0127d1024b34a1233a321bd6d0275b3ba998b30"
+  integrity sha512-HWjX8rA3Y/RI32zby3KIN1D+mgskce+She4K7kRyyx62OiVxJ5FnYm8vWq0YVAja3Tf2S1M0XAc6O2lRFcMgcQ==
+  dependencies:
+    css-what "^6.1.0"
+
 zeego@^1.6.2:
   version "1.7.0"
   resolved "https://registry.yarnpkg.com/zeego/-/zeego-1.7.0.tgz#8034adb842199c4ccf21bcb19877800bff18606b"