@tiptap/core 2.5.6 → 2.5.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,2 +1,8 @@
1
1
  import { Node as ProseMirrorNode } from '@tiptap/pm/model';
2
- export declare function isNodeEmpty(node: ProseMirrorNode): boolean;
2
+ /**
3
+ * Returns true if the given node is empty.
4
+ * When `checkChildren` is true (default), it will also check if all children are empty.
5
+ */
6
+ export declare function isNodeEmpty(node: ProseMirrorNode, { checkChildren }?: {
7
+ checkChildren: boolean;
8
+ }): boolean;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tiptap/core",
3
3
  "description": "headless rich text editor",
4
- "version": "2.5.6",
4
+ "version": "2.5.7",
5
5
  "homepage": "https://tiptap.dev",
6
6
  "keywords": [
7
7
  "tiptap",
@@ -32,10 +32,10 @@
32
32
  "dist"
33
33
  ],
34
34
  "devDependencies": {
35
- "@tiptap/pm": "^2.5.6"
35
+ "@tiptap/pm": "^2.5.7"
36
36
  },
37
37
  "peerDependencies": {
38
- "@tiptap/pm": "^2.5.6"
38
+ "@tiptap/pm": "^2.5.7"
39
39
  },
40
40
  "repository": {
41
41
  "type": "git",
package/src/Editor.ts CHANGED
@@ -39,6 +39,7 @@ import { isFunction } from './utilities/isFunction.js'
39
39
 
40
40
  export * as extensions from './extensions/index.js'
41
41
 
42
+ // @ts-ignore
42
43
  export interface TiptapEditorHTMLElement extends HTMLElement {
43
44
  editor?: Editor
44
45
  }
@@ -340,6 +341,7 @@ export class Editor extends EventEmitter<EditorEvents> {
340
341
 
341
342
  // Let’s store the editor instance in the DOM element.
342
343
  // So we’ll have access to it for tests.
344
+ // @ts-ignore
343
345
  const dom = this.view.dom as TiptapEditorHTMLElement
344
346
 
345
347
  dom.editor = this
@@ -81,6 +81,13 @@ export const insertContentAt: RawCommands['insertContentAt'] = (position, value,
81
81
  errorOnInvalidContent: options.errorOnInvalidContent ?? editor.options.enableContentCheck,
82
82
  })
83
83
  } catch (e) {
84
+ editor.emit('contentError', {
85
+ editor,
86
+ error: e as Error,
87
+ disableCollaboration: () => {
88
+ console.error('[tiptap error]: Unable to disable collaboration at this point in time')
89
+ },
90
+ })
84
91
  return false
85
92
  }
86
93
 
@@ -58,13 +58,14 @@ export function createNodeFromContent(
58
58
  }
59
59
 
60
60
  if (isTextContent) {
61
- let schemaToUse = schema
62
- let hasInvalidContent = false
63
- let invalidContent = ''
64
61
 
65
- // Only ever check for invalid content if we're supposed to throw an error
62
+ // Check for invalid content
66
63
  if (options.errorOnInvalidContent) {
67
- schemaToUse = new Schema({
64
+ let hasInvalidContent = false
65
+ let invalidContent = ''
66
+
67
+ // A copy of the current schema with a catch-all node at the end
68
+ const contentCheckSchema = new Schema({
68
69
  topNode: schema.spec.topNode,
69
70
  marks: schema.spec.marks,
70
71
  // Prosemirror's schemas are executed such that: the last to execute, matches last
@@ -88,19 +89,26 @@ export function createNodeFromContent(
88
89
  },
89
90
  }),
90
91
  })
91
- }
92
92
 
93
- const parser = DOMParser.fromSchema(schemaToUse)
93
+ if (options.slice) {
94
+ DOMParser.fromSchema(contentCheckSchema).parseSlice(elementFromString(content), options.parseOptions)
95
+ } else {
96
+ DOMParser.fromSchema(contentCheckSchema).parse(elementFromString(content), options.parseOptions)
97
+ }
94
98
 
95
- const response = options.slice
96
- ? parser.parseSlice(elementFromString(content), options.parseOptions).content
97
- : parser.parse(elementFromString(content), options.parseOptions)
99
+ if (options.errorOnInvalidContent && hasInvalidContent) {
100
+ throw new Error('[tiptap error]: Invalid HTML content', { cause: new Error(`Invalid element found: ${invalidContent}`) })
101
+ }
102
+ }
103
+
104
+ const parser = DOMParser.fromSchema(schema)
98
105
 
99
- if (options.errorOnInvalidContent && hasInvalidContent) {
100
- throw new Error('[tiptap error]: Invalid HTML content', { cause: new Error(`Invalid element found: ${invalidContent}`) })
106
+ if (options.slice) {
107
+ return parser.parseSlice(elementFromString(content), options.parseOptions).content
101
108
  }
102
109
 
103
- return response
110
+ return parser.parse(elementFromString(content), options.parseOptions)
111
+
104
112
  }
105
113
 
106
114
  return createNodeFromContent('', schema, options)
@@ -1,11 +1,41 @@
1
1
  import { Node as ProseMirrorNode } from '@tiptap/pm/model'
2
2
 
3
- export function isNodeEmpty(node: ProseMirrorNode): boolean {
4
- const defaultContent = node.type.createAndFill(node.attrs)
3
+ /**
4
+ * Returns true if the given node is empty.
5
+ * When `checkChildren` is true (default), it will also check if all children are empty.
6
+ */
7
+ export function isNodeEmpty(
8
+ node: ProseMirrorNode,
9
+ { checkChildren }: { checkChildren: boolean } = { checkChildren: true },
10
+ ): boolean {
11
+ if (node.isText) {
12
+ return !node.text
13
+ }
14
+
15
+ if (node.content.childCount === 0) {
16
+ return true
17
+ }
5
18
 
6
- if (!defaultContent) {
19
+ if (node.isLeaf) {
7
20
  return false
8
21
  }
9
22
 
10
- return node.eq(defaultContent)
23
+ if (checkChildren) {
24
+ let hasSameContent = true
25
+
26
+ node.content.forEach(childNode => {
27
+ if (hasSameContent === false) {
28
+ // Exit early for perf
29
+ return
30
+ }
31
+
32
+ if (!isNodeEmpty(childNode)) {
33
+ hasSameContent = false
34
+ }
35
+ })
36
+
37
+ return hasSameContent
38
+ }
39
+
40
+ return false
11
41
  }