@tiptap/core
Advanced tools
Comparing version 2.8.0 to 2.9.0
@@ -75,6 +75,6 @@ import { MarkType, NodeType, Schema } from '@tiptap/pm/model'; | ||
* | ||
* @param nameOrPluginKey The plugins name | ||
* @param nameOrPluginKeyToRemove The plugins name | ||
* @returns The new editor state or undefined if the editor is destroyed | ||
*/ | ||
unregisterPlugin(nameOrPluginKey: string | PluginKey): EditorState | undefined; | ||
unregisterPlugin(nameOrPluginKeyToRemove: string | PluginKey | (string | PluginKey)[]): EditorState | undefined; | ||
/** | ||
@@ -81,0 +81,0 @@ * Creates an extension manager. |
@@ -1,4 +0,5 @@ | ||
import { Mark as ProseMirrorMark, Node as ProseMirrorNode, NodeType, ParseOptions, Slice } from '@tiptap/pm/model'; | ||
import { Mark as ProseMirrorMark, Node as ProseMirrorNode, ParseOptions, Slice } from '@tiptap/pm/model'; | ||
import { EditorState, Transaction } from '@tiptap/pm/state'; | ||
import { Decoration, EditorProps, EditorView, NodeView, NodeViewConstructor } from '@tiptap/pm/view'; | ||
import { Mappable } from '@tiptap/pm/transform'; | ||
import { Decoration, DecorationAttrs, EditorProps, EditorView, NodeView, NodeViewConstructor } from '@tiptap/pm/view'; | ||
import { Editor } from './Editor.js'; | ||
@@ -203,4 +204,21 @@ import { Extension } from './Extension.js'; | ||
}[keyof T]; | ||
export type DOMNode = InstanceType<typeof window.Node>; | ||
/** | ||
* prosemirror-view does not export the `type` property of `Decoration`. | ||
* So, this defines the `DecorationType` interface to include the `type` property. | ||
*/ | ||
export interface DecorationType { | ||
spec: any; | ||
map(mapping: Mappable, span: Decoration, offset: number, oldOffset: number): Decoration | null; | ||
valid(node: Node, span: Decoration): boolean; | ||
eq(other: DecorationType): boolean; | ||
destroy(dom: DOMNode): void; | ||
readonly attrs: DecorationAttrs; | ||
} | ||
/** | ||
* prosemirror-view does not export the `type` property of `Decoration`. | ||
* This adds the `type` property to the `Decoration` type. | ||
*/ | ||
export type DecorationWithType = Decoration & { | ||
type: NodeType; | ||
type: DecorationType; | ||
}; | ||
@@ -226,9 +244,35 @@ export interface NodeViewProps extends NodeViewRendererProps { | ||
export interface NodeViewRendererProps { | ||
/** | ||
* The node that is being rendered. | ||
*/ | ||
node: Parameters<NodeViewConstructor>[0]; | ||
/** | ||
* The editor's view. | ||
*/ | ||
view: Parameters<NodeViewConstructor>[1]; | ||
/** | ||
* A function that can be called to get the node's current position in the document. | ||
*/ | ||
getPos: () => number; | ||
/** | ||
* is an array of node or inline decorations that are active around the node. | ||
* They are automatically drawn in the normal way, and you will usually just want to ignore this, but they can also be used as a way to provide context information to the node view without adding it to the document itself. | ||
*/ | ||
decorations: Parameters<NodeViewConstructor>[3]; | ||
/** | ||
* holds the decorations for the node's content. You can safely ignore this if your view has no content or a contentDOM property, since the editor will draw the decorations on the content. | ||
* But if you, for example, want to create a nested editor with the content, it may make sense to provide it with the inner decorations. | ||
*/ | ||
innerDecorations: Parameters<NodeViewConstructor>[4]; | ||
/** | ||
* The editor instance. | ||
*/ | ||
editor: Editor; | ||
/** | ||
* The extension that is responsible for the node. | ||
*/ | ||
extension: Node; | ||
/** | ||
* The HTML attributes that should be added to the node's DOM element. | ||
*/ | ||
HTMLAttributes: Record<string, any>; | ||
@@ -235,0 +279,0 @@ } |
{ | ||
"name": "@tiptap/core", | ||
"description": "headless rich text editor", | ||
"version": "2.8.0", | ||
"version": "2.9.0", | ||
"homepage": "https://tiptap.dev", | ||
@@ -35,3 +35,3 @@ "keywords": [ | ||
"devDependencies": { | ||
"@tiptap/pm": "^2.8.0" | ||
"@tiptap/pm": "^2.9.0" | ||
}, | ||
@@ -38,0 +38,0 @@ "peerDependencies": { |
@@ -66,3 +66,3 @@ import { Fragment, Node as ProseMirrorNode, ParseOptions } from '@tiptap/pm/model' | ||
options = { | ||
parseOptions: {}, | ||
parseOptions: editor.options.parseOptions, | ||
updateSelection: true, | ||
@@ -89,3 +89,5 @@ applyInputRules: false, | ||
disableCollaboration: () => { | ||
console.error('[tiptap error]: Unable to disable collaboration at this point in time') | ||
if (editor.storage.collaboration) { | ||
editor.storage.collaboration.isDisabled = true | ||
} | ||
}, | ||
@@ -92,0 +94,0 @@ }) |
@@ -240,6 +240,6 @@ import { | ||
* | ||
* @param nameOrPluginKey The plugins name | ||
* @param nameOrPluginKeyToRemove The plugins name | ||
* @returns The new editor state or undefined if the editor is destroyed | ||
*/ | ||
public unregisterPlugin(nameOrPluginKey: string | PluginKey): EditorState | undefined { | ||
public unregisterPlugin(nameOrPluginKeyToRemove: string | PluginKey | (string | PluginKey)[]): EditorState | undefined { | ||
if (this.isDestroyed) { | ||
@@ -249,10 +249,22 @@ return undefined | ||
// @ts-ignore | ||
const name = typeof nameOrPluginKey === 'string' ? `${nameOrPluginKey}$` : nameOrPluginKey.key | ||
const prevPlugins = this.state.plugins | ||
let plugins = prevPlugins; | ||
const state = this.state.reconfigure({ | ||
([] as (string | PluginKey)[]).concat(nameOrPluginKeyToRemove).forEach(nameOrPluginKey => { | ||
// @ts-ignore | ||
plugins: this.state.plugins.filter(plugin => !plugin.key.startsWith(name)), | ||
const name = typeof nameOrPluginKey === 'string' ? `${nameOrPluginKey}$` : nameOrPluginKey.key | ||
// @ts-ignore | ||
plugins = prevPlugins.filter(plugin => !plugin.key.startsWith(name)) | ||
}) | ||
if (prevPlugins.length === plugins.length) { | ||
// No plugin was removed, so we don’t need to update the state | ||
return undefined | ||
} | ||
const state = this.state.reconfigure({ | ||
plugins, | ||
}) | ||
this.view.updateState(state) | ||
@@ -330,2 +342,5 @@ | ||
disableCollaboration: () => { | ||
if (this.storage.collaboration) { | ||
this.storage.collaboration.isDisabled = true | ||
} | ||
// To avoid syncing back invalid content, reinitialize the extensions without the collaboration extension | ||
@@ -358,2 +373,10 @@ this.options.extensions = this.options.extensions.filter(extension => extension.name !== 'collaboration') | ||
// add `role="textbox"` to the editor element | ||
this.view.dom.setAttribute('role', 'textbox') | ||
// add aria-label to the editor element | ||
if (!this.view.dom.getAttribute('aria-label')) { | ||
this.view.dom.setAttribute('aria-label', 'Rich-Text Editor') | ||
} | ||
// `editor.view` is not yet available at this time. | ||
@@ -360,0 +383,0 @@ // Therefore we will add all plugins and node views directly afterwards. |
@@ -32,13 +32,16 @@ import { Mark as ProseMirrorMark, MarkType, ResolvedPos } from '@tiptap/pm/model' | ||
} | ||
let start = $pos.parent.childAfter($pos.parentOffset) | ||
if ($pos.parentOffset === start.offset && start.offset !== 0) { | ||
// If the cursor is at the start of a text node that does not have the mark, look backward | ||
if (!start.node || !start.node.marks.some(mark => mark.type === type)) { | ||
start = $pos.parent.childBefore($pos.parentOffset) | ||
} | ||
if (!start.node) { | ||
// If there is no text node with the mark even backward, return undefined | ||
if (!start.node || !start.node.marks.some(mark => mark.type === type)) { | ||
return | ||
} | ||
// We now know that the cursor is either at the start, middle or end of a text node with the specified mark | ||
// so we can look it up on the targeted mark | ||
const mark = findMarkInSet([...start.node.marks], type, attributes) | ||
@@ -45,0 +48,0 @@ |
@@ -138,4 +138,5 @@ import { | ||
const isBlock = node.isBlock && !node.isTextblock | ||
const isNonTextAtom = node.isAtom && !node.isText | ||
const targetPos = this.pos + offset + 1 | ||
const targetPos = this.pos + offset + (isNonTextAtom ? 0 : 1) | ||
const $pos = this.resolvedPos.doc.resolve(targetPos) | ||
@@ -239,7 +240,11 @@ | ||
setAttribute(attributes: { [key: string]: any }) { | ||
const oldSelection = this.editor.state.selection | ||
const { tr } = this.editor.state | ||
this.editor.chain().setTextSelection(this.from).updateAttributes(this.node.type.name, attributes).setTextSelection(oldSelection.from) | ||
.run() | ||
tr.setNodeMarkup(this.from, undefined, { | ||
...this.node.attrs, | ||
...attributes, | ||
}) | ||
this.editor.view.dispatch(tr) | ||
} | ||
} |
import { | ||
Mark as ProseMirrorMark, | ||
Node as ProseMirrorNode, | ||
NodeType, | ||
ParseOptions, | ||
@@ -9,4 +8,6 @@ Slice, | ||
import { EditorState, Transaction } from '@tiptap/pm/state' | ||
import { Mappable } from '@tiptap/pm/transform' | ||
import { | ||
Decoration, | ||
DecorationAttrs, | ||
EditorProps, | ||
@@ -228,4 +229,23 @@ EditorView, | ||
export type DOMNode = InstanceType<typeof window.Node> | ||
/** | ||
* prosemirror-view does not export the `type` property of `Decoration`. | ||
* So, this defines the `DecorationType` interface to include the `type` property. | ||
*/ | ||
export interface DecorationType { | ||
spec: any | ||
map(mapping: Mappable, span: Decoration, offset: number, oldOffset: number): Decoration | null | ||
valid(node: Node, span: Decoration): boolean | ||
eq(other: DecorationType): boolean | ||
destroy(dom: DOMNode): void | ||
readonly attrs: DecorationAttrs | ||
} | ||
/** | ||
* prosemirror-view does not export the `type` property of `Decoration`. | ||
* This adds the `type` property to the `Decoration` type. | ||
*/ | ||
export type DecorationWithType = Decoration & { | ||
type: NodeType; | ||
type: DecorationType; | ||
}; | ||
@@ -251,10 +271,36 @@ | ||
// pass-through from prosemirror | ||
/** | ||
* The node that is being rendered. | ||
*/ | ||
node: Parameters<NodeViewConstructor>[0]; | ||
/** | ||
* The editor's view. | ||
*/ | ||
view: Parameters<NodeViewConstructor>[1]; | ||
/** | ||
* A function that can be called to get the node's current position in the document. | ||
*/ | ||
getPos: () => number; // TODO getPos was incorrectly typed before, change to `Parameters<NodeViewConstructor>[2];` in the next major version | ||
/** | ||
* is an array of node or inline decorations that are active around the node. | ||
* They are automatically drawn in the normal way, and you will usually just want to ignore this, but they can also be used as a way to provide context information to the node view without adding it to the document itself. | ||
*/ | ||
decorations: Parameters<NodeViewConstructor>[3]; | ||
/** | ||
* holds the decorations for the node's content. You can safely ignore this if your view has no content or a contentDOM property, since the editor will draw the decorations on the content. | ||
* But if you, for example, want to create a nested editor with the content, it may make sense to provide it with the inner decorations. | ||
*/ | ||
innerDecorations: Parameters<NodeViewConstructor>[4]; | ||
// tiptap-specific | ||
/** | ||
* The editor instance. | ||
*/ | ||
editor: Editor; | ||
/** | ||
* The extension that is responsible for the node. | ||
*/ | ||
extension: Node; | ||
/** | ||
* The HTML attributes that should be added to the node's DOM element. | ||
*/ | ||
HTMLAttributes: Record<string, any>; | ||
@@ -261,0 +307,0 @@ } |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
2489542
28105