This commit is contained in:
Tony Hallett 2023-09-13 10:11:17 +01:00
parent 7832b96afb
commit baf6947d52
7 changed files with 116 additions and 2 deletions

View File

@ -0,0 +1,26 @@
import { mergeAttributes, Node } from '@tiptap/core'
export default Node.create({
name: 'foo',
group: 'inline',
inline: true,
parseHTML() {
return [
{
tag: 'span',
getAttrs: node => (node as HTMLElement).hasAttribute('data-foo') && null,
},
]
},
renderHTML({ HTMLAttributes }) {
return ['span', mergeAttributes({ 'data-foo': '', HTMLAttributes }), 'foo']
},
renderText() {
return 'foo'
},
})

View File

@ -0,0 +1,27 @@
import './styles.scss'
import { EditorContent, FloatingMenu, useEditor } from '@tiptap/react'
import StarterKit from '@tiptap/starter-kit'
import React from 'react'
import Foo from './foo.js'
export default () => {
const editor = useEditor({
extensions: [
StarterKit, Foo,
],
content: `
<p><span data-foo=''>foo</span></p>
`,
})
return (
<>
{editor && <FloatingMenu editor={editor} tippyOptions={{ duration: 100 }}>
<div>Hello</div>
</FloatingMenu>}
<EditorContent editor={editor} />
</>
)
}

View File

@ -0,0 +1,10 @@
.tiptap {
> * + * {
margin-top: 0.75em;
}
ul,
ol {
padding: 0 1rem;
}
}

View File

@ -0,0 +1,26 @@
import { mergeAttributes, Node } from '@tiptap/core'
export default Node.create({
name: 'foo',
group: 'inline',
inline: true,
parseHTML() {
return [
{
tag: 'span',
getAttrs: node => (node as HTMLElement).hasAttribute('data-foo') && null,
},
]
},
renderHTML({ HTMLAttributes }) {
return ['span', mergeAttributes({ 'data-foo': '', HTMLAttributes }), 'foo']
},
renderText() {
return 'foo'
},
})

View File

@ -1,4 +1,7 @@
import { Editor, posToDOMRect } from '@tiptap/core'
import {
Editor, getText, getTextSerializersFromSchema, posToDOMRect,
} from '@tiptap/core'
import { Node as ProseMirrorNode } from '@tiptap/pm/model'
import { EditorState, Plugin, PluginKey } from '@tiptap/pm/state'
import { EditorView } from '@tiptap/pm/view'
import tippy, { Instance, Props } from 'tippy.js'
@ -35,11 +38,15 @@ export class FloatingMenuView {
public tippyOptions?: Partial<Props>
private getTextContent(node:ProseMirrorNode) {
return getText(node, { textSerializers: getTextSerializersFromSchema(this.editor.schema) })
}
public shouldShow: Exclude<FloatingMenuPluginProps['shouldShow'], null> = ({ view, state }) => {
const { selection } = state
const { $anchor, empty } = selection
const isRootDepth = $anchor.depth === 1
const isEmptyTextBlock = $anchor.parent.isTextblock && !$anchor.parent.type.spec.code && !$anchor.parent.textContent
const isEmptyTextBlock = $anchor.parent.isTextblock && !$anchor.parent.type.spec.code && !this.getTextContent($anchor.parent)
if (
!view.hasFocus()

View File

@ -0,0 +1,18 @@
/// <reference types="cypress" />
import { Editor } from '@tiptap/core'
interface EditorElement extends HTMLElement {
editor: Editor
}
context('/cypress/integration/Issue4327/React/', () => {
before(() => {
cy.visit('/src/Examples/Issue4327/React/')
})
it('should not show menu when node has renderText returning text with length > 0', () => {
cy.get('.tiptap').then(([editorElement]) => {
(editorElement as EditorElement).editor.commands.focus()
}).get('.ProseMirror-focused').get('#app')
.should('not.have.descendants', '[data-tippy-root]')
})
})