tiptap/packages/core/src/Editor.ts

524 lines
13 KiB
TypeScript
Raw Normal View History

import {
MarkType, NodeType, Schema,
} from '@tiptap/pm/model'
2021-03-30 20:07:18 +08:00
import {
feat(pm): new prosemirror package for dependency resolving * chore:(core): migrate to tsup * chore: migrate blockquote and bold to tsup * chore: migrated bubble-menu and bullet-list to tsup * chore: migrated more packages to tsup * chore: migrate code and character extensions to tsup * chore: update package.json to simplify build for all packages * chore: move all packages to tsup as a build process * chore: change ci build task * feat(pm): add prosemirror meta package * rfix: resolve issues with build paths & export mappings * docs: update documentation to include notes for @tiptap/pm * chore(pm): update tsconfig * chore(packages): update packages * fix(pm): add package export infos & fix dependencies * chore(general): start moving to pm package as deps * chore: move to tiptap pm package internally * fix(demos): fix demos working with new pm package * fix(tables): fix tables package * fix(tables): fix tables package * chore(demos): pinned typescript version * chore: remove unnecessary tsconfig * chore: fix netlify build * fix(demos): fix package resolving for pm packages * fix(tests): fix package resolving for pm packages * fix(tests): fix package resolving for pm packages * chore(tests): fix tests not running correctly after pm package * chore(pm): add files to files array * chore: update build workflow * chore(tests): increase timeout time back to 12s * chore(docs): update docs * chore(docs): update installation guides & pm information to docs * chore(docs): add link to prosemirror docs * fix(vue-3): add missing build step * chore(docs): comment out cdn link * chore(docs): remove semicolons from docs * chore(docs): remove unnecessary installation note * chore(docs): remove unnecessary installation note
2023-02-03 00:37:33 +08:00
EditorState, Plugin, PluginKey, Transaction,
} from '@tiptap/pm/state'
import { EditorView } from '@tiptap/pm/view'
import { CommandManager } from './CommandManager.js'
import { EventEmitter } from './EventEmitter.js'
import { ExtensionManager } from './ExtensionManager.js'
import {
ClipboardTextSerializer, Commands, Editable, FocusEvents, Keymap, Tabindex,
} from './extensions/index.js'
import { createDocument } from './helpers/createDocument.js'
import { getAttributes } from './helpers/getAttributes.js'
import { getHTMLFromFragment } from './helpers/getHTMLFromFragment.js'
import { getText } from './helpers/getText.js'
import { getTextSerializersFromSchema } from './helpers/getTextSerializersFromSchema.js'
import { isActive } from './helpers/isActive.js'
import { isNodeEmpty } from './helpers/isNodeEmpty.js'
import { resolveFocusPosition } from './helpers/resolveFocusPosition.js'
import { NodePos } from './NodePos.js'
import { style } from './style.js'
2021-01-28 16:04:55 +08:00
import {
CanCommands,
ChainedCommands,
EditorEvents,
EditorOptions,
JSONContent,
2021-01-28 16:04:55 +08:00
SingleCommands,
2021-09-30 15:34:45 +08:00
TextSerializer,
} from './types.js'
import { createStyleTag } from './utilities/createStyleTag.js'
import { isFunction } from './utilities/isFunction.js'
2020-08-21 05:25:55 +08:00
export * as extensions from './extensions/index.js'
2020-11-17 04:54:40 +08:00
export interface HTMLElement {
2020-09-12 00:06:13 +08:00
editor?: Editor
}
export class Editor extends EventEmitter<EditorEvents> {
2020-09-23 03:25:32 +08:00
private commandManager!: CommandManager
2020-09-24 06:29:05 +08:00
2021-01-20 03:27:51 +08:00
public extensionManager!: ExtensionManager
2020-09-24 06:29:05 +08:00
2020-08-18 15:36:37 +08:00
private css!: HTMLStyleElement
2020-09-24 06:29:05 +08:00
2020-08-18 15:36:37 +08:00
public schema!: Schema
2020-09-24 06:29:05 +08:00
2020-08-18 15:36:37 +08:00
public view!: EditorView
2020-09-24 06:29:05 +08:00
2020-08-22 04:08:54 +08:00
public isFocused = false
2020-09-24 06:29:05 +08:00
2021-10-22 14:52:54 +08:00
public extensionStorage: Record<string, any> = {}
2020-08-18 15:41:31 +08:00
public options: EditorOptions = {
2020-04-11 20:33:58 +08:00
element: document.createElement('div'),
2020-03-05 05:40:08 +08:00
content: '',
injectCSS: true,
injectNonce: undefined,
2020-03-06 03:30:58 +08:00
extensions: [],
2020-11-17 22:47:39 +08:00
autofocus: false,
2020-08-22 03:53:45 +08:00
editable: true,
2020-11-18 04:21:19 +08:00
editorProps: {},
2020-11-18 04:15:10 +08:00
parseOptions: {},
coreExtensionOptions: {},
enableInputRules: true,
enablePasteRules: true,
enableCoreExtensions: true,
2021-04-02 06:07:40 +08:00
onBeforeCreate: () => null,
2020-11-30 20:56:42 +08:00
onCreate: () => null,
2020-11-17 22:27:00 +08:00
onUpdate: () => null,
onSelectionUpdate: () => null,
2020-11-17 22:27:00 +08:00
onTransaction: () => null,
onFocus: () => null,
onBlur: () => null,
2020-11-30 20:56:42 +08:00
onDestroy: () => null,
2020-03-05 05:40:08 +08:00
}
2020-08-11 22:57:11 +08:00
2020-04-14 16:13:27 +08:00
constructor(options: Partial<EditorOptions> = {}) {
2020-03-06 06:59:48 +08:00
super()
this.setOptions(options)
2020-03-06 04:49:53 +08:00
this.createExtensionManager()
2021-02-10 21:52:08 +08:00
this.createCommandManager()
2020-03-06 04:49:53 +08:00
this.createSchema()
this.on('beforeCreate', this.options.onBeforeCreate)
2021-04-02 06:07:40 +08:00
this.emit('beforeCreate', { editor: this })
2020-03-06 04:49:53 +08:00
this.createView()
2020-09-30 23:12:17 +08:00
this.injectCSS()
2020-11-30 20:56:42 +08:00
this.on('create', this.options.onCreate)
2020-11-17 22:27:00 +08:00
this.on('update', this.options.onUpdate)
this.on('selectionUpdate', this.options.onSelectionUpdate)
2020-11-17 22:27:00 +08:00
this.on('transaction', this.options.onTransaction)
this.on('focus', this.options.onFocus)
this.on('blur', this.options.onBlur)
2020-11-30 20:56:42 +08:00
this.on('destroy', this.options.onDestroy)
2020-11-17 22:27:00 +08:00
window.setTimeout(() => {
if (this.isDestroyed) {
return
}
2020-11-17 22:47:39 +08:00
this.commands.focus(this.options.autofocus)
this.emit('create', { editor: this })
2020-11-17 22:27:00 +08:00
}, 0)
2019-12-08 07:16:44 +08:00
}
2021-10-22 14:52:54 +08:00
/**
* Returns the editor storage.
*/
public get storage(): Record<string, any> {
return this.extensionStorage
}
/**
* An object of all registered commands.
*/
2021-01-28 16:04:55 +08:00
public get commands(): SingleCommands {
return this.commandManager.commands
2020-11-13 16:58:30 +08:00
}
2020-09-23 03:25:32 +08:00
/**
* Create a command chain to call multiple commands at once.
*/
2021-01-28 16:04:55 +08:00
public chain(): ChainedCommands {
return this.commandManager.chain()
2020-09-22 00:40:32 +08:00
}
2020-11-03 00:18:12 +08:00
/**
* Check if a command or a command chain can be executed. Without executing it.
*/
2021-01-28 16:04:55 +08:00
public can(): CanCommands {
return this.commandManager.can()
2020-11-03 00:18:12 +08:00
}
2020-09-30 23:12:17 +08:00
/**
* Inject CSS styles.
*/
2021-01-28 16:04:55 +08:00
private injectCSS(): void {
2020-09-30 23:12:17 +08:00
if (this.options.injectCSS && document) {
this.css = createStyleTag(style, this.options.injectNonce)
2020-09-30 23:12:17 +08:00
}
}
2020-08-22 05:35:15 +08:00
/**
* Update editor options.
2020-09-03 21:11:55 +08:00
*
2020-08-22 05:35:15 +08:00
* @param options A list of options
*/
2021-01-28 16:04:55 +08:00
public setOptions(options: Partial<EditorOptions> = {}): void {
2021-08-09 23:24:18 +08:00
this.options = {
...this.options,
...options,
}
if (!this.view || !this.state || this.isDestroyed) {
return
}
2021-08-09 23:24:18 +08:00
if (this.options.editorProps) {
this.view.setProps(this.options.editorProps)
}
2021-08-09 23:24:18 +08:00
this.view.updateState(this.state)
}
2021-03-05 19:15:50 +08:00
/**
* Update editable state of the editor.
*/
public setEditable(editable: boolean, emitUpdate = true): void {
this.setOptions({ editable })
if (emitUpdate) {
this.emit('update', { editor: this, transaction: this.state.tr })
}
2020-08-22 03:53:45 +08:00
}
2020-09-03 21:11:55 +08:00
2020-08-22 05:35:15 +08:00
/**
* Returns whether the editor is editable.
*/
2021-01-28 16:04:55 +08:00
public get isEditable(): boolean {
// since plugins are applied after creating the view
// `editable` is always `true` for one tick.
// thats why we also have to check for `options.editable`
feat(pm): new prosemirror package for dependency resolving * chore:(core): migrate to tsup * chore: migrate blockquote and bold to tsup * chore: migrated bubble-menu and bullet-list to tsup * chore: migrated more packages to tsup * chore: migrate code and character extensions to tsup * chore: update package.json to simplify build for all packages * chore: move all packages to tsup as a build process * chore: change ci build task * feat(pm): add prosemirror meta package * rfix: resolve issues with build paths & export mappings * docs: update documentation to include notes for @tiptap/pm * chore(pm): update tsconfig * chore(packages): update packages * fix(pm): add package export infos & fix dependencies * chore(general): start moving to pm package as deps * chore: move to tiptap pm package internally * fix(demos): fix demos working with new pm package * fix(tables): fix tables package * fix(tables): fix tables package * chore(demos): pinned typescript version * chore: remove unnecessary tsconfig * chore: fix netlify build * fix(demos): fix package resolving for pm packages * fix(tests): fix package resolving for pm packages * fix(tests): fix package resolving for pm packages * chore(tests): fix tests not running correctly after pm package * chore(pm): add files to files array * chore: update build workflow * chore(tests): increase timeout time back to 12s * chore(docs): update docs * chore(docs): update installation guides & pm information to docs * chore(docs): add link to prosemirror docs * fix(vue-3): add missing build step * chore(docs): comment out cdn link * chore(docs): remove semicolons from docs * chore(docs): remove unnecessary installation note * chore(docs): remove unnecessary installation note
2023-02-03 00:37:33 +08:00
return this.options.editable && this.view && this.view.editable
2020-08-22 04:08:54 +08:00
}
2020-08-22 05:35:15 +08:00
/**
* Returns the editor state.
*/
2021-01-28 16:04:55 +08:00
public get state(): EditorState {
2020-03-29 07:21:28 +08:00
return this.view.state
}
2020-08-22 05:35:15 +08:00
/**
* Register a ProseMirror plugin.
2020-09-03 21:11:55 +08:00
*
2020-08-22 05:35:15 +08:00
* @param plugin A ProseMirror plugin
* @param handlePlugins Control how to merge the plugin into the existing plugins.
*/
feat(pm): new prosemirror package for dependency resolving * chore:(core): migrate to tsup * chore: migrate blockquote and bold to tsup * chore: migrated bubble-menu and bullet-list to tsup * chore: migrated more packages to tsup * chore: migrate code and character extensions to tsup * chore: update package.json to simplify build for all packages * chore: move all packages to tsup as a build process * chore: change ci build task * feat(pm): add prosemirror meta package * rfix: resolve issues with build paths & export mappings * docs: update documentation to include notes for @tiptap/pm * chore(pm): update tsconfig * chore(packages): update packages * fix(pm): add package export infos & fix dependencies * chore(general): start moving to pm package as deps * chore: move to tiptap pm package internally * fix(demos): fix demos working with new pm package * fix(tables): fix tables package * fix(tables): fix tables package * chore(demos): pinned typescript version * chore: remove unnecessary tsconfig * chore: fix netlify build * fix(demos): fix package resolving for pm packages * fix(tests): fix package resolving for pm packages * fix(tests): fix package resolving for pm packages * chore(tests): fix tests not running correctly after pm package * chore(pm): add files to files array * chore: update build workflow * chore(tests): increase timeout time back to 12s * chore(docs): update docs * chore(docs): update installation guides & pm information to docs * chore(docs): add link to prosemirror docs * fix(vue-3): add missing build step * chore(docs): comment out cdn link * chore(docs): remove semicolons from docs * chore(docs): remove unnecessary installation note * chore(docs): remove unnecessary installation note
2023-02-03 00:37:33 +08:00
public registerPlugin(
plugin: Plugin,
handlePlugins?: (newPlugin: Plugin, plugins: Plugin[]) => Plugin[],
): void {
const plugins = isFunction(handlePlugins)
? handlePlugins(plugin, [...this.state.plugins])
2021-01-29 00:39:57 +08:00
: [...this.state.plugins, plugin]
2020-04-11 03:43:23 +08:00
const state = this.state.reconfigure({ plugins })
2020-04-11 03:43:23 +08:00
this.view.updateState(state)
}
2020-08-22 05:35:15 +08:00
/**
* Unregister a ProseMirror plugin.
2020-09-03 21:11:55 +08:00
*
* @param nameOrPluginKey The plugins name
2020-08-22 05:35:15 +08:00
*/
2021-03-30 20:07:18 +08:00
public unregisterPlugin(nameOrPluginKey: string | PluginKey): void {
if (this.isDestroyed) {
return
}
feat(pm): new prosemirror package for dependency resolving * chore:(core): migrate to tsup * chore: migrate blockquote and bold to tsup * chore: migrated bubble-menu and bullet-list to tsup * chore: migrated more packages to tsup * chore: migrate code and character extensions to tsup * chore: update package.json to simplify build for all packages * chore: move all packages to tsup as a build process * chore: change ci build task * feat(pm): add prosemirror meta package * rfix: resolve issues with build paths & export mappings * docs: update documentation to include notes for @tiptap/pm * chore(pm): update tsconfig * chore(packages): update packages * fix(pm): add package export infos & fix dependencies * chore(general): start moving to pm package as deps * chore: move to tiptap pm package internally * fix(demos): fix demos working with new pm package * fix(tables): fix tables package * fix(tables): fix tables package * chore(demos): pinned typescript version * chore: remove unnecessary tsconfig * chore: fix netlify build * fix(demos): fix package resolving for pm packages * fix(tests): fix package resolving for pm packages * fix(tests): fix package resolving for pm packages * chore(tests): fix tests not running correctly after pm package * chore(pm): add files to files array * chore: update build workflow * chore(tests): increase timeout time back to 12s * chore(docs): update docs * chore(docs): update installation guides & pm information to docs * chore(docs): add link to prosemirror docs * fix(vue-3): add missing build step * chore(docs): comment out cdn link * chore(docs): remove semicolons from docs * chore(docs): remove unnecessary installation note * chore(docs): remove unnecessary installation note
2023-02-03 00:37:33 +08:00
// @ts-ignore
const name = typeof nameOrPluginKey === 'string' ? `${nameOrPluginKey}$` : nameOrPluginKey.key
2021-03-30 20:07:18 +08:00
2020-04-11 04:55:14 +08:00
const state = this.state.reconfigure({
// @ts-ignore
2021-03-30 20:07:18 +08:00
plugins: this.state.plugins.filter(plugin => !plugin.key.startsWith(name)),
2020-04-11 04:55:14 +08:00
})
this.view.updateState(state)
}
2020-08-22 05:35:15 +08:00
/**
* Creates an extension manager.
*/
2021-01-28 16:04:55 +08:00
private createExtensionManager(): void {
const coreExtensions = this.options.enableCoreExtensions ? [
Editable,
ClipboardTextSerializer.configure({
blockSeparator: this.options.coreExtensionOptions?.clipboardTextSerializer?.blockSeparator,
}),
Commands,
FocusEvents,
Keymap,
Tabindex,
] : []
2021-01-29 00:39:57 +08:00
const allExtensions = [...coreExtensions, ...this.options.extensions].filter(extension => {
2020-12-22 00:43:29 +08:00
return ['extension', 'node', 'mark'].includes(extension?.type)
})
2020-10-23 16:44:30 +08:00
2021-02-17 01:54:44 +08:00
this.extensionManager = new ExtensionManager(allExtensions, this)
2019-12-08 07:16:44 +08:00
}
2020-09-23 03:25:32 +08:00
/**
* Creates an command manager.
*/
2021-01-28 16:04:55 +08:00
private createCommandManager(): void {
this.commandManager = new CommandManager({
editor: this,
})
2020-09-23 03:25:32 +08:00
}
2020-08-22 05:35:15 +08:00
/**
* Creates a ProseMirror schema.
*/
2021-01-28 16:04:55 +08:00
private createSchema(): void {
2020-09-10 06:09:05 +08:00
this.schema = this.extensionManager.schema
2020-03-06 04:05:01 +08:00
}
2020-08-22 05:35:15 +08:00
/**
* Creates a ProseMirror view.
*/
2021-01-28 16:04:55 +08:00
private createView(): void {
const doc = createDocument(this.options.content, this.schema, this.options.parseOptions)
const selection = resolveFocusPosition(doc, this.options.autofocus)
2021-12-03 17:36:51 +08:00
2020-04-11 20:33:58 +08:00
this.view = new EditorView(this.options.element, {
2020-11-18 04:21:19 +08:00
...this.options.editorProps,
2020-11-04 22:31:42 +08:00
dispatchTransaction: this.dispatchTransaction.bind(this),
2020-03-06 04:49:53 +08:00
state: EditorState.create({
doc,
selection: selection || undefined,
2020-03-06 04:49:53 +08:00
}),
})
// `editor.view` is not yet available at this time.
2020-11-04 22:31:42 +08:00
// Therefore we will add all plugins and node views directly afterwards.
const newState = this.state.reconfigure({
plugins: this.extensionManager.plugins,
2020-11-04 22:31:42 +08:00
})
this.view.updateState(newState)
this.createNodeViews()
this.prependClass()
2020-09-12 00:06:13 +08:00
// Lets store the editor instance in the DOM element.
// So well have access to it for tests.
2020-09-12 00:06:13 +08:00
const dom = this.view.dom as HTMLElement
2021-02-17 01:54:44 +08:00
dom.editor = this
2019-12-08 07:16:44 +08:00
}
/**
* Creates all node views.
*/
2021-01-28 16:04:55 +08:00
public createNodeViews(): void {
this.view.setProps({
nodeViews: this.extensionManager.nodeViews,
})
}
/**
* Prepend class name to element.
*/
public prependClass(): void {
this.view.dom.className = `tiptap ${this.view.dom.className}`
}
2021-02-09 17:06:13 +08:00
public isCapturingTransaction = false
private capturedTransaction: Transaction | null = null
public captureTransaction(fn: Function) {
this.isCapturingTransaction = true
fn()
this.isCapturingTransaction = false
const tr = this.capturedTransaction
this.capturedTransaction = null
return tr
}
2020-08-22 05:35:15 +08:00
/**
* The callback over which to send transactions (state updates) produced by the view.
2020-09-03 21:11:55 +08:00
*
2020-08-22 05:35:15 +08:00
* @param transaction An editor state transaction
*/
2021-01-28 16:04:55 +08:00
private dispatchTransaction(transaction: Transaction): void {
// if the editor / the view of the editor was destroyed
// the transaction should not be dispatched as there is no view anymore.
if (this.view.isDestroyed) {
return
}
2021-02-09 17:06:13 +08:00
if (this.isCapturingTransaction) {
if (!this.capturedTransaction) {
this.capturedTransaction = transaction
return
}
transaction.steps.forEach(step => this.capturedTransaction?.step(step))
return
}
2020-03-05 05:40:08 +08:00
const state = this.state.apply(transaction)
2020-11-27 21:52:19 +08:00
const selectionHasChanged = !this.state.selection.eq(state.selection)
2020-11-17 22:27:00 +08:00
2020-03-05 05:40:08 +08:00
this.view.updateState(state)
this.emit('transaction', {
editor: this,
transaction,
})
2020-08-11 22:57:11 +08:00
2020-11-27 21:52:19 +08:00
if (selectionHasChanged) {
this.emit('selectionUpdate', {
editor: this,
transaction,
})
2020-11-27 21:52:19 +08:00
}
2020-11-17 22:27:00 +08:00
const focus = transaction.getMeta('focus')
const blur = transaction.getMeta('blur')
if (focus) {
this.emit('focus', {
editor: this,
event: focus.event,
transaction,
})
2020-11-17 22:27:00 +08:00
}
if (blur) {
this.emit('blur', {
editor: this,
event: blur.event,
transaction,
})
2020-11-17 22:27:00 +08:00
}
2019-12-08 07:16:44 +08:00
if (!transaction.docChanged || transaction.getMeta('preventUpdate')) {
return
}
this.emit('update', {
editor: this,
transaction,
})
2019-12-08 07:16:44 +08:00
}
2019-12-17 06:51:18 +08:00
/**
* Get attributes of the currently selected node or mark.
*/
public getAttributes(nameOrType: string | NodeType | MarkType): Record<string, any> {
return getAttributes(this.state, nameOrType)
}
2020-08-22 05:35:15 +08:00
/**
* Returns if the currently selected node or mark is active.
2020-09-03 21:11:55 +08:00
*
2020-08-22 05:35:15 +08:00
* @param name Name of the node or mark
* @param attributes Attributes of the node or mark
2020-08-22 05:35:15 +08:00
*/
feat(pm): new prosemirror package for dependency resolving * chore:(core): migrate to tsup * chore: migrate blockquote and bold to tsup * chore: migrated bubble-menu and bullet-list to tsup * chore: migrated more packages to tsup * chore: migrate code and character extensions to tsup * chore: update package.json to simplify build for all packages * chore: move all packages to tsup as a build process * chore: change ci build task * feat(pm): add prosemirror meta package * rfix: resolve issues with build paths & export mappings * docs: update documentation to include notes for @tiptap/pm * chore(pm): update tsconfig * chore(packages): update packages * fix(pm): add package export infos & fix dependencies * chore(general): start moving to pm package as deps * chore: move to tiptap pm package internally * fix(demos): fix demos working with new pm package * fix(tables): fix tables package * fix(tables): fix tables package * chore(demos): pinned typescript version * chore: remove unnecessary tsconfig * chore: fix netlify build * fix(demos): fix package resolving for pm packages * fix(tests): fix package resolving for pm packages * fix(tests): fix package resolving for pm packages * chore(tests): fix tests not running correctly after pm package * chore(pm): add files to files array * chore: update build workflow * chore(tests): increase timeout time back to 12s * chore(docs): update docs * chore(docs): update installation guides & pm information to docs * chore(docs): add link to prosemirror docs * fix(vue-3): add missing build step * chore(docs): comment out cdn link * chore(docs): remove semicolons from docs * chore(docs): remove unnecessary installation note * chore(docs): remove unnecessary installation note
2023-02-03 00:37:33 +08:00
public isActive(name: string, attributes?: {}): boolean
public isActive(attributes: {}): boolean
public isActive(nameOrAttributes: string, attributesOrUndefined?: {}): boolean {
feat(pm): new prosemirror package for dependency resolving * chore:(core): migrate to tsup * chore: migrate blockquote and bold to tsup * chore: migrated bubble-menu and bullet-list to tsup * chore: migrated more packages to tsup * chore: migrate code and character extensions to tsup * chore: update package.json to simplify build for all packages * chore: move all packages to tsup as a build process * chore: change ci build task * feat(pm): add prosemirror meta package * rfix: resolve issues with build paths & export mappings * docs: update documentation to include notes for @tiptap/pm * chore(pm): update tsconfig * chore(packages): update packages * fix(pm): add package export infos & fix dependencies * chore(general): start moving to pm package as deps * chore: move to tiptap pm package internally * fix(demos): fix demos working with new pm package * fix(tables): fix tables package * fix(tables): fix tables package * chore(demos): pinned typescript version * chore: remove unnecessary tsconfig * chore: fix netlify build * fix(demos): fix package resolving for pm packages * fix(tests): fix package resolving for pm packages * fix(tests): fix package resolving for pm packages * chore(tests): fix tests not running correctly after pm package * chore(pm): add files to files array * chore: update build workflow * chore(tests): increase timeout time back to 12s * chore(docs): update docs * chore(docs): update installation guides & pm information to docs * chore(docs): add link to prosemirror docs * fix(vue-3): add missing build step * chore(docs): comment out cdn link * chore(docs): remove semicolons from docs * chore(docs): remove unnecessary installation note * chore(docs): remove unnecessary installation note
2023-02-03 00:37:33 +08:00
const name = typeof nameOrAttributes === 'string' ? nameOrAttributes : null
feat(pm): new prosemirror package for dependency resolving * chore:(core): migrate to tsup * chore: migrate blockquote and bold to tsup * chore: migrated bubble-menu and bullet-list to tsup * chore: migrated more packages to tsup * chore: migrate code and character extensions to tsup * chore: update package.json to simplify build for all packages * chore: move all packages to tsup as a build process * chore: change ci build task * feat(pm): add prosemirror meta package * rfix: resolve issues with build paths & export mappings * docs: update documentation to include notes for @tiptap/pm * chore(pm): update tsconfig * chore(packages): update packages * fix(pm): add package export infos & fix dependencies * chore(general): start moving to pm package as deps * chore: move to tiptap pm package internally * fix(demos): fix demos working with new pm package * fix(tables): fix tables package * fix(tables): fix tables package * chore(demos): pinned typescript version * chore: remove unnecessary tsconfig * chore: fix netlify build * fix(demos): fix package resolving for pm packages * fix(tests): fix package resolving for pm packages * fix(tests): fix package resolving for pm packages * chore(tests): fix tests not running correctly after pm package * chore(pm): add files to files array * chore: update build workflow * chore(tests): increase timeout time back to 12s * chore(docs): update docs * chore(docs): update installation guides & pm information to docs * chore(docs): add link to prosemirror docs * fix(vue-3): add missing build step * chore(docs): comment out cdn link * chore(docs): remove semicolons from docs * chore(docs): remove unnecessary installation note * chore(docs): remove unnecessary installation note
2023-02-03 00:37:33 +08:00
const attributes = typeof nameOrAttributes === 'string' ? attributesOrUndefined : nameOrAttributes
return isActive(this.state, name, attributes)
2020-03-06 04:49:53 +08:00
}
2020-08-22 05:35:15 +08:00
/**
* Get the document as JSON.
*/
public getJSON(): JSONContent {
2020-03-04 17:21:48 +08:00
return this.state.doc.toJSON()
}
2020-08-22 05:35:15 +08:00
/**
* Get the document as HTML.
*/
2021-01-28 16:04:55 +08:00
public getHTML(): string {
return getHTMLFromFragment(this.state.doc.content, this.schema)
2020-03-04 17:21:48 +08:00
}
2020-03-05 04:45:49 +08:00
/**
* Get the document as text.
*/
public getText(options?: {
feat(pm): new prosemirror package for dependency resolving * chore:(core): migrate to tsup * chore: migrate blockquote and bold to tsup * chore: migrated bubble-menu and bullet-list to tsup * chore: migrated more packages to tsup * chore: migrate code and character extensions to tsup * chore: update package.json to simplify build for all packages * chore: move all packages to tsup as a build process * chore: change ci build task * feat(pm): add prosemirror meta package * rfix: resolve issues with build paths & export mappings * docs: update documentation to include notes for @tiptap/pm * chore(pm): update tsconfig * chore(packages): update packages * fix(pm): add package export infos & fix dependencies * chore(general): start moving to pm package as deps * chore: move to tiptap pm package internally * fix(demos): fix demos working with new pm package * fix(tables): fix tables package * fix(tables): fix tables package * chore(demos): pinned typescript version * chore: remove unnecessary tsconfig * chore: fix netlify build * fix(demos): fix package resolving for pm packages * fix(tests): fix package resolving for pm packages * fix(tests): fix package resolving for pm packages * chore(tests): fix tests not running correctly after pm package * chore(pm): add files to files array * chore: update build workflow * chore(tests): increase timeout time back to 12s * chore(docs): update docs * chore(docs): update installation guides & pm information to docs * chore(docs): add link to prosemirror docs * fix(vue-3): add missing build step * chore(docs): comment out cdn link * chore(docs): remove semicolons from docs * chore(docs): remove unnecessary installation note * chore(docs): remove unnecessary installation note
2023-02-03 00:37:33 +08:00
blockSeparator?: string
textSerializers?: Record<string, TextSerializer>
}): string {
feat(pm): new prosemirror package for dependency resolving * chore:(core): migrate to tsup * chore: migrate blockquote and bold to tsup * chore: migrated bubble-menu and bullet-list to tsup * chore: migrated more packages to tsup * chore: migrate code and character extensions to tsup * chore: update package.json to simplify build for all packages * chore: move all packages to tsup as a build process * chore: change ci build task * feat(pm): add prosemirror meta package * rfix: resolve issues with build paths & export mappings * docs: update documentation to include notes for @tiptap/pm * chore(pm): update tsconfig * chore(packages): update packages * fix(pm): add package export infos & fix dependencies * chore(general): start moving to pm package as deps * chore: move to tiptap pm package internally * fix(demos): fix demos working with new pm package * fix(tables): fix tables package * fix(tables): fix tables package * chore(demos): pinned typescript version * chore: remove unnecessary tsconfig * chore: fix netlify build * fix(demos): fix package resolving for pm packages * fix(tests): fix package resolving for pm packages * fix(tests): fix package resolving for pm packages * chore(tests): fix tests not running correctly after pm package * chore(pm): add files to files array * chore: update build workflow * chore(tests): increase timeout time back to 12s * chore(docs): update docs * chore(docs): update installation guides & pm information to docs * chore(docs): add link to prosemirror docs * fix(vue-3): add missing build step * chore(docs): comment out cdn link * chore(docs): remove semicolons from docs * chore(docs): remove unnecessary installation note * chore(docs): remove unnecessary installation note
2023-02-03 00:37:33 +08:00
const { blockSeparator = '\n\n', textSerializers = {} } = options || {}
return getText(this.state.doc, {
blockSeparator,
textSerializers: {
...getTextSerializersFromSchema(this.schema),
...textSerializers,
},
})
}
2020-10-23 20:28:25 +08:00
/**
* Check if there is no content.
*/
2021-03-25 05:23:08 +08:00
public get isEmpty(): boolean {
return isNodeEmpty(this.state.doc)
2020-10-23 20:28:25 +08:00
}
/**
* Get the number of characters for the current document.
*
* @deprecated
*/
2021-01-28 16:04:55 +08:00
public getCharacterCount(): number {
feat(pm): new prosemirror package for dependency resolving * chore:(core): migrate to tsup * chore: migrate blockquote and bold to tsup * chore: migrated bubble-menu and bullet-list to tsup * chore: migrated more packages to tsup * chore: migrate code and character extensions to tsup * chore: update package.json to simplify build for all packages * chore: move all packages to tsup as a build process * chore: change ci build task * feat(pm): add prosemirror meta package * rfix: resolve issues with build paths & export mappings * docs: update documentation to include notes for @tiptap/pm * chore(pm): update tsconfig * chore(packages): update packages * fix(pm): add package export infos & fix dependencies * chore(general): start moving to pm package as deps * chore: move to tiptap pm package internally * fix(demos): fix demos working with new pm package * fix(tables): fix tables package * fix(tables): fix tables package * chore(demos): pinned typescript version * chore: remove unnecessary tsconfig * chore: fix netlify build * fix(demos): fix package resolving for pm packages * fix(tests): fix package resolving for pm packages * fix(tests): fix package resolving for pm packages * chore(tests): fix tests not running correctly after pm package * chore(pm): add files to files array * chore: update build workflow * chore(tests): increase timeout time back to 12s * chore(docs): update docs * chore(docs): update installation guides & pm information to docs * chore(docs): add link to prosemirror docs * fix(vue-3): add missing build step * chore(docs): comment out cdn link * chore(docs): remove semicolons from docs * chore(docs): remove unnecessary installation note * chore(docs): remove unnecessary installation note
2023-02-03 00:37:33 +08:00
console.warn(
'[tiptap warn]: "editor.getCharacterCount()" is deprecated. Please use "editor.storage.characterCount.characters()" instead.',
)
return this.state.doc.content.size - 2
}
2020-08-22 05:35:15 +08:00
/**
* Destroy the editor.
*/
2021-01-28 16:04:55 +08:00
public destroy(): void {
2020-11-30 20:50:06 +08:00
this.emit('destroy')
2020-03-31 19:07:57 +08:00
if (this.view) {
this.view.destroy()
2020-03-05 04:45:49 +08:00
}
2020-03-06 06:59:48 +08:00
this.removeAllListeners()
2020-03-05 04:45:49 +08:00
}
2020-09-24 06:29:05 +08:00
2020-10-01 04:43:58 +08:00
/**
* Check if the editor is already destroyed.
*/
public get isDestroyed(): boolean {
2020-10-01 04:43:58 +08:00
// @ts-ignore
return !this.view?.docView
}
public $node(selector: string, attributes?: { [key: string]: any }): NodePos | null {
return this.$doc?.querySelector(selector, attributes) || null
}
public $nodes(selector: string, attributes?: { [key: string]: any }): NodePos[] | null {
return this.$doc?.querySelectorAll(selector, attributes) || null
}
public $pos(pos: number) {
const $pos = this.state.doc.resolve(pos)
return new NodePos($pos, this)
}
get $doc() {
return this.$pos(0)
}
2019-12-08 07:16:44 +08:00
}