fix: placeholders now check for empty content compared to their "true" empty state (#5278)

* fix: placeholders now check for empty content compared to their "true" empty state

* chore: add changeset
This commit is contained in:
Nick Perez 2024-06-28 09:05:43 +02:00 committed by GitHub
parent c2e4ad9845
commit 89fefab9ac
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 8 additions and 23 deletions

View File

@ -0,0 +1,5 @@
---
"@tiptap/extension-placeholder": patch
---
Placeholders can now handle more complex default content

View File

@ -1,4 +1,4 @@
import { Editor, Extension } from '@tiptap/core'
import { Editor, Extension, isNodeEmpty } from '@tiptap/core'
import { Node as ProsemirrorNode } from '@tiptap/pm/model'
import { Plugin, PluginKey } from '@tiptap/pm/state'
import { Decoration, DecorationSet } from '@tiptap/pm/view'
@ -31,15 +31,6 @@ export interface PlaceholderOptions {
}) => string)
| string
/**
* **Used for empty check on the document.**
*
* If true, any node that is not a leaf or atom will be considered for empty check.
* If false, only default nodes (paragraphs) will be considered for empty check.
* @default false
*/
considerAnyAsEmpty: boolean
/**
* **Checks if the placeholder should be only shown when the editor is editable.**
*
@ -82,7 +73,6 @@ export const Placeholder = Extension.create<PlaceholderOptions>({
emptyNodeClass: 'is-empty',
placeholder: 'Write something …',
showOnlyWhenEditable: true,
considerAnyAsEmpty: false,
showOnlyCurrent: true,
includeChildren: false,
}
@ -102,21 +92,11 @@ export const Placeholder = Extension.create<PlaceholderOptions>({
return null
}
// only calculate isEmpty once due to its performance impacts (see issue #3360)
const { firstChild } = doc.content
const isLeaf = firstChild && firstChild.type.isLeaf
const isAtom = firstChild && firstChild.isAtom
const isValidNode = this.options.considerAnyAsEmpty
? true
: firstChild && firstChild.type.name === doc.type.contentMatch.defaultType?.name
const isEmptyDoc = doc.content.childCount <= 1
&& firstChild
&& isValidNode
&& (firstChild.nodeSize <= 2 && (!isLeaf || !isAtom))
const isEmptyDoc = this.editor.isEmpty
doc.descendants((node, pos) => {
const hasAnchor = anchor >= pos && anchor <= pos + node.nodeSize
const isEmpty = !node.isLeaf && !node.childCount
const isEmpty = !node.isLeaf && isNodeEmpty(node)
if ((hasAnchor || !this.options.showOnlyCurrent) && isEmpty) {
const classes = [this.options.emptyNodeClass]