Merge branch 'main' of github.com:ueberdosis/tiptap into add-empty-editor-class-to-root-div

This commit is contained in:
Dominik Biedebach
2022-09-10 15:31:04 +02:00
647 changed files with 40003 additions and 11691 deletions

View File

@@ -3,6 +3,102 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [2.0.0-beta.183](https://github.com/ueberdosis/tiptap/compare/@tiptap/core@2.0.0-beta.182...@tiptap/core@2.0.0-beta.183) (2022-09-03)
### Bug Fixes
* **core:** createCan command props shouldn't try dispatch ([#3025](https://github.com/ueberdosis/tiptap/issues/3025)) ([#3026](https://github.com/ueberdosis/tiptap/issues/3026)) ([40f4ea3](https://github.com/ueberdosis/tiptap/commit/40f4ea31efc59c1578b783a5b64572ac2846c5a6))
* **core:** isNodeSelection, isTextSelection not always false ([#3089](https://github.com/ueberdosis/tiptap/issues/3089)) ([574cd69](https://github.com/ueberdosis/tiptap/commit/574cd69e06bfdc3771006ed4eda341a6c9722a42)), closes [#2979](https://github.com/ueberdosis/tiptap/issues/2979)
* **core:** make setEditable trigger all 'update' listeners ([#3140](https://github.com/ueberdosis/tiptap/issues/3140)) ([4851fc5](https://github.com/ueberdosis/tiptap/commit/4851fc5e9b6daccc15a1839e471db489401eca0c))
* **core:** make setEditable trigger onUpdate function ([#2935](https://github.com/ueberdosis/tiptap/issues/2935)) ([de1253a](https://github.com/ueberdosis/tiptap/commit/de1253a8b06eeb7339f0bba8c04917890c9b21ae))
* **core:** setNodeSelection should not clamp pos by Selection.atStart/atEnd ([#3091](https://github.com/ueberdosis/tiptap/issues/3091)) ([313b8b8](https://github.com/ueberdosis/tiptap/commit/313b8b8d0af7059c420ffc96c9362f0f4acc2138)), closes [#3090](https://github.com/ueberdosis/tiptap/issues/3090)
# [2.0.0-beta.182](https://github.com/ueberdosis/tiptap/compare/@tiptap/core@2.0.0-beta.181...@tiptap/core@2.0.0-beta.182) (2022-07-06)
### Bug Fixes
* **core:** dont use selection for setContent replacement ([#2934](https://github.com/ueberdosis/tiptap/issues/2934)) ([134a4bd](https://github.com/ueberdosis/tiptap/commit/134a4bd1fbbd7f56faa1fc70c97d3b58554fc3f1))
* **core:** only respect text of node before current position ([#2937](https://github.com/ueberdosis/tiptap/issues/2937)) ([#2941](https://github.com/ueberdosis/tiptap/issues/2941)) ([e280a02](https://github.com/ueberdosis/tiptap/commit/e280a02597d15460fce97a7555f91ff04926f0e7))
# [2.0.0-beta.181](https://github.com/ueberdosis/tiptap/compare/@tiptap/core@2.0.0-beta.180...@tiptap/core@2.0.0-beta.181) (2022-06-27)
### Bug Fixes
* **core:** fix focus command passing through editor state instead of existing transaction ([5b0b7d9](https://github.com/ueberdosis/tiptap/commit/5b0b7d91023c87e9ddb85ff3a776273d12a22d16))
### Features
* **core:** add nodePasteRule to core ([15123ee](https://github.com/ueberdosis/tiptap/commit/15123ee092261fe86352d491121804607e08e031))
# [2.0.0-beta.180](https://github.com/ueberdosis/tiptap/compare/@tiptap/core@2.0.0-beta.179...@tiptap/core@2.0.0-beta.180) (2022-06-20)
**Note:** Version bump only for package @tiptap/core
# [2.0.0-beta.179](https://github.com/ueberdosis/tiptap/compare/@tiptap/core@2.0.0-beta.177...@tiptap/core@2.0.0-beta.179) (2022-06-17)
### Reverts
* Revert "Publish" ([9c38d27](https://github.com/ueberdosis/tiptap/commit/9c38d2713e6feac5645ad9c1bfc57abdbf054576))
# [2.0.0-beta.177](https://github.com/ueberdosis/tiptap/compare/@tiptap/core@2.0.0-beta.177...@tiptap/core@2.0.0-beta.177) (2022-06-17)
### Reverts
* Revert "Publish" ([9c38d27](https://github.com/ueberdosis/tiptap/commit/9c38d2713e6feac5645ad9c1bfc57abdbf054576))
# [2.0.0-beta.176](https://github.com/ueberdosis/tiptap/compare/@tiptap/core@2.0.0-beta.175...@tiptap/core@2.0.0-beta.176) (2022-05-18)
### Bug Fixes
* lint error ([e17c414](https://github.com/ueberdosis/tiptap/commit/e17c41498aa0df71a827bf41f5c52745f3853c43))
* properly calculate setDragImage position ([7401d45](https://github.com/ueberdosis/tiptap/commit/7401d45b7e3ff40e2ac894810bf85461761eb25b))
# [2.0.0-beta.175](https://github.com/ueberdosis/tiptap/compare/@tiptap/core@2.0.0-beta.174...@tiptap/core@2.0.0-beta.175) (2022-04-27)
### Bug Fixes
* don't override behaviour of Home / End in pc keymap ([d270419](https://github.com/ueberdosis/tiptap/commit/d270419ad8dc6182a949c5d263c47e90ee4466ff))
# [2.0.0-beta.174](https://github.com/ueberdosis/tiptap/compare/@tiptap/core@2.0.0-beta.173...@tiptap/core@2.0.0-beta.174) (2022-02-07)

View File

@@ -1,7 +1,7 @@
{
"name": "@tiptap/core",
"description": "headless rich text editor",
"version": "2.0.0-beta.174",
"version": "2.0.0-beta.183",
"homepage": "https://tiptap.dev",
"keywords": [
"tiptap",
@@ -24,20 +24,13 @@
"dist"
],
"dependencies": {
"@types/prosemirror-commands": "^1.0.4",
"@types/prosemirror-keymap": "^1.0.4",
"@types/prosemirror-model": "^1.16.0",
"@types/prosemirror-schema-list": "^1.0.3",
"@types/prosemirror-state": "^1.2.8",
"@types/prosemirror-transform": "^1.1.5",
"@types/prosemirror-view": "^1.23.1",
"prosemirror-commands": "^1.2.1",
"prosemirror-keymap": "^1.1.5",
"prosemirror-model": "^1.16.1",
"prosemirror-schema-list": "^1.1.6",
"prosemirror-state": "^1.3.4",
"prosemirror-transform": "^1.3.3",
"prosemirror-view": "^1.23.6"
"prosemirror-commands": "1.3.0",
"prosemirror-keymap": "1.2.0",
"prosemirror-model": "1.18.1",
"prosemirror-schema-list": "1.2.0",
"prosemirror-state": "1.4.1",
"prosemirror-transform": "1.6.0",
"prosemirror-view": "1.26.2"
},
"repository": {
"type": "git",

View File

@@ -1,12 +1,13 @@
import { EditorState, Transaction } from 'prosemirror-state'
import { Editor } from './Editor'
import { createChainableState } from './helpers/createChainableState'
import {
SingleCommands,
ChainedCommands,
CanCommands,
AnyCommands,
CanCommands,
ChainedCommands,
CommandProps,
SingleCommands,
} from './types'
export class CommandManager {
@@ -106,13 +107,13 @@ export class CommandManager {
public createCan(startTr?: Transaction): CanCommands {
const { rawCommands, state } = this
const dispatch = undefined
const dispatch = false
const tr = startTr || state.tr
const props = this.buildProps(tr, dispatch)
const formattedCommands = Object.fromEntries(Object
.entries(rawCommands)
.map(([name, command]) => {
return [name, (...args: never[]) => command(...args)({ ...props, dispatch })]
return [name, (...args: never[]) => command(...args)({ ...props, dispatch: undefined })]
})) as unknown as SingleCommands
return {

View File

@@ -1,3 +1,4 @@
import { MarkType, NodeType, Schema } from 'prosemirror-model'
import {
EditorState,
Plugin,
@@ -5,31 +6,31 @@ import {
Transaction,
} from 'prosemirror-state'
import { EditorView } from 'prosemirror-view'
import { Schema, MarkType, NodeType } from 'prosemirror-model'
import { getAttributes } from './helpers/getAttributes'
import { isActive } from './helpers/isActive'
import { CommandManager } from './CommandManager'
import { EventEmitter } from './EventEmitter'
import { ExtensionManager } from './ExtensionManager'
import * as extensions from './extensions'
import { createDocument } from './helpers/createDocument'
import { getAttributes } from './helpers/getAttributes'
import { getHTMLFromFragment } from './helpers/getHTMLFromFragment'
import { getText } from './helpers/getText'
import { getTextSerializersFromSchema } from './helpers/getTextSerializersFromSchema'
import { isActive } from './helpers/isActive'
import { isNodeEmpty } from './helpers/isNodeEmpty'
import { resolveFocusPosition } from './helpers/resolveFocusPosition'
import { getTextSeralizersFromSchema } from './helpers/getTextSeralizersFromSchema'
import { createStyleTag } from './utilities/createStyleTag'
import { isFunction } from './utilities/isFunction'
import { CommandManager } from './CommandManager'
import { ExtensionManager } from './ExtensionManager'
import { EventEmitter } from './EventEmitter'
import { style } from './style'
import {
EditorOptions,
CanCommands,
ChainedCommands,
EditorEvents,
EditorOptions,
JSONContent,
SingleCommands,
TextSerializer,
EditorEvents,
} from './types'
import * as extensions from './extensions'
import { style } from './style'
import { createStyleTag } from './utilities/createStyleTag'
import { isFunction } from './utilities/isFunction'
export { extensions }
@@ -57,6 +58,7 @@ export class Editor extends EventEmitter<EditorEvents> {
element: document.createElement('div'),
content: '',
injectCSS: true,
injectNonce: undefined,
extensions: [],
autofocus: false,
editable: true,
@@ -136,7 +138,7 @@ export class Editor extends EventEmitter<EditorEvents> {
*/
private injectCSS(): void {
if (this.options.injectCSS && document) {
this.css = createStyleTag(style)
this.css = createStyleTag(style, this.options.injectNonce)
}
}
@@ -167,6 +169,7 @@ export class Editor extends EventEmitter<EditorEvents> {
*/
public setEditable(editable: boolean): void {
this.setOptions({ editable })
this.emit('update', { editor: this, transaction: this.state.tr })
}
/**
@@ -196,7 +199,7 @@ export class Editor extends EventEmitter<EditorEvents> {
*/
public registerPlugin(plugin: Plugin, handlePlugins?: (newPlugin: Plugin, plugins: Plugin[]) => Plugin[]): void {
const plugins = isFunction(handlePlugins)
? handlePlugins(plugin, this.state.plugins)
? handlePlugins(plugin, [...this.state.plugins])
: [...this.state.plugins, plugin]
const state = this.state.reconfigure({ plugins })
@@ -269,7 +272,7 @@ export class Editor extends EventEmitter<EditorEvents> {
dispatchTransaction: this.dispatchTransaction.bind(this),
state: EditorState.create({
doc,
selection,
selection: selection || undefined,
}),
})
@@ -435,7 +438,7 @@ export class Editor extends EventEmitter<EditorEvents> {
blockSeparator,
textSerializers: {
...textSerializers,
...getTextSeralizersFromSchema(this.schema),
...getTextSerializersFromSchema(this.schema),
},
})
}

View File

@@ -1,21 +1,22 @@
import { Plugin, Transaction } from 'prosemirror-state'
import { InputRule } from './InputRule'
import { PasteRule } from './PasteRule'
import { ExtensionConfig } from '.'
import { Editor } from './Editor'
import { Node } from './Node'
import { Mark } from './Mark'
import { mergeDeep } from './utilities/mergeDeep'
import { callOrReturn } from './utilities/callOrReturn'
import { getExtensionField } from './helpers/getExtensionField'
import { InputRule } from './InputRule'
import { Mark } from './Mark'
import { Node } from './Node'
import { PasteRule } from './PasteRule'
import {
AnyConfig,
Extensions,
GlobalAttributes,
RawCommands,
ParentConfig,
KeyboardShortcutCommand,
ParentConfig,
RawCommands,
} from './types'
import { ExtensionConfig } from '.'
import { callOrReturn } from './utilities/callOrReturn'
import { mergeDeep } from './utilities/mergeDeep'
declare module '@tiptap/core' {
interface ExtensionConfig<Options = any, Storage = any> {

View File

@@ -1,22 +1,23 @@
import { keymap } from 'prosemirror-keymap'
import { Schema, Node as ProsemirrorNode } from 'prosemirror-model'
import { inputRulesPlugin } from './InputRule'
import { pasteRulesPlugin } from './PasteRule'
import { EditorView, Decoration } from 'prosemirror-view'
import { Node as ProsemirrorNode, Schema } from 'prosemirror-model'
import { Plugin } from 'prosemirror-state'
import { Decoration, EditorView } from 'prosemirror-view'
import { Mark, NodeConfig } from '.'
import { Editor } from './Editor'
import { Extensions, RawCommands, AnyConfig } from './types'
import { getAttributesFromExtensions } from './helpers/getAttributesFromExtensions'
import { getExtensionField } from './helpers/getExtensionField'
import { getNodeType } from './helpers/getNodeType'
import { getRenderedAttributes } from './helpers/getRenderedAttributes'
import { getSchemaByResolvedExtensions } from './helpers/getSchemaByResolvedExtensions'
import { getSchemaTypeByName } from './helpers/getSchemaTypeByName'
import { getNodeType } from './helpers/getNodeType'
import { splitExtensions } from './helpers/splitExtensions'
import { getAttributesFromExtensions } from './helpers/getAttributesFromExtensions'
import { getRenderedAttributes } from './helpers/getRenderedAttributes'
import { isExtensionRulesEnabled } from './helpers/isExtensionRulesEnabled'
import { splitExtensions } from './helpers/splitExtensions'
import { inputRulesPlugin } from './InputRule'
import { pasteRulesPlugin } from './PasteRule'
import { AnyConfig, Extensions, RawCommands } from './types'
import { callOrReturn } from './utilities/callOrReturn'
import { findDuplicates } from './utilities/findDuplicates'
import { NodeConfig } from '.'
export class ExtensionManager {
@@ -251,6 +252,13 @@ export class ExtensionManager {
context,
)
let defaultBindings: Record<string, () => boolean> = {}
// bind exit handling
if (extension.type === 'mark' && extension.config.exitable) {
defaultBindings.ArrowRight = () => Mark.handleExit({ editor, mark: (extension as Mark) })
}
if (addKeyboardShortcuts) {
const bindings = Object.fromEntries(
Object
@@ -260,11 +268,13 @@ export class ExtensionManager {
}),
)
const keyMapPlugin = keymap(bindings)
plugins.push(keyMapPlugin)
defaultBindings = { ...defaultBindings, ...bindings }
}
const keyMapPlugin = keymap(defaultBindings)
plugins.push(keyMapPlugin)
const addInputRules = getExtensionField<AnyConfig['addInputRules']>(
extension,
'addInputRules',

View File

@@ -1,15 +1,17 @@
import { EditorState, Plugin, TextSelection } from 'prosemirror-state'
import { Editor } from './Editor'
import { CommandManager } from './CommandManager'
import { Editor } from './Editor'
import { createChainableState } from './helpers/createChainableState'
import { isRegExp } from './utilities/isRegExp'
import { getTextContentFromNodes } from './helpers/getTextContentFromNodes'
import {
Range,
ExtendedRegExpMatchArray,
SingleCommands,
ChainedCommands,
CanCommands,
ChainedCommands,
ExtendedRegExpMatchArray,
Range,
SingleCommands,
} from './types'
import { isRegExp } from './utilities/isRegExp'
export type InputRuleMatch = {
index: number,
@@ -114,13 +116,8 @@ function run(config: {
}
let matched = false
const maxMatch = 500
const textBefore = $from.parent.textBetween(
Math.max(0, $from.parentOffset - maxMatch),
$from.parentOffset,
undefined,
' ',
) + text
const textBefore = getTextContentFromNodes($from) + text
rules.forEach(rule => {
if (matched) {
@@ -191,7 +188,7 @@ export function inputRulesPlugin(props: { editor: Editor, rules: InputRule[] }):
return null
},
apply(tr, prev) {
const stored = tr.getMeta(this)
const stored = tr.getMeta(plugin)
if (stored) {
return stored

View File

@@ -1,27 +1,28 @@
import {
DOMOutputSpec,
MarkSpec,
Mark as ProseMirrorMark,
MarkSpec,
MarkType,
} from 'prosemirror-model'
import { Plugin, Transaction } from 'prosemirror-state'
import { InputRule } from './InputRule'
import { PasteRule } from './PasteRule'
import { mergeDeep } from './utilities/mergeDeep'
import { callOrReturn } from './utilities/callOrReturn'
import { getExtensionField } from './helpers/getExtensionField'
import {
AnyConfig,
Extensions,
Attributes,
RawCommands,
GlobalAttributes,
ParentConfig,
KeyboardShortcutCommand,
} from './types'
import { Node } from './Node'
import { MarkConfig } from '.'
import { Editor } from './Editor'
import { getExtensionField } from './helpers/getExtensionField'
import { InputRule } from './InputRule'
import { Node } from './Node'
import { PasteRule } from './PasteRule'
import {
AnyConfig,
Attributes,
Extensions,
GlobalAttributes,
KeyboardShortcutCommand,
ParentConfig,
RawCommands,
} from './types'
import { callOrReturn } from './utilities/callOrReturn'
import { mergeDeep } from './utilities/mergeDeep'
declare module '@tiptap/core' {
export interface MarkConfig<Options = any, Storage = any> {
@@ -303,6 +304,11 @@ declare module '@tiptap/core' {
parent: ParentConfig<MarkConfig<Options, Storage>>['excludes'],
}) => MarkSpec['excludes']),
/**
* Marks this Mark as exitable
*/
exitable?: boolean | (() => boolean),
/**
* Group
*/
@@ -485,4 +491,38 @@ export class Mark<Options = any, Storage = any> {
return extension
}
static handleExit({
editor,
mark,
}: {
editor: Editor
mark: Mark
}) {
const { tr } = editor.state
const currentPos = editor.state.selection.$from
const isAtEnd = currentPos.pos === currentPos.end()
if (isAtEnd) {
const currentMarks = currentPos.marks()
const isInMark = !!currentMarks.find(m => m?.type.name === mark.name)
if (!isInMark) {
return false
}
const removeMark = currentMarks.find(m => m?.type.name === mark.name)
if (removeMark) {
tr.removeStoredMark(removeMark)
}
tr.insertText(' ', currentPos.pos)
editor.view.dispatch(tr)
return true
}
return false
}
}

View File

@@ -1,27 +1,28 @@
import {
DOMOutputSpec,
NodeSpec,
Node as ProseMirrorNode,
NodeSpec,
NodeType,
} from 'prosemirror-model'
import { Plugin, Transaction } from 'prosemirror-state'
import { InputRule } from './InputRule'
import { PasteRule } from './PasteRule'
import { mergeDeep } from './utilities/mergeDeep'
import { callOrReturn } from './utilities/callOrReturn'
import { getExtensionField } from './helpers/getExtensionField'
import {
AnyConfig,
Extensions,
Attributes,
NodeViewRenderer,
GlobalAttributes,
RawCommands,
ParentConfig,
KeyboardShortcutCommand,
} from './types'
import { NodeConfig } from '.'
import { Editor } from './Editor'
import { getExtensionField } from './helpers/getExtensionField'
import { InputRule } from './InputRule'
import { PasteRule } from './PasteRule'
import {
AnyConfig,
Attributes,
Extensions,
GlobalAttributes,
KeyboardShortcutCommand,
NodeViewRenderer,
ParentConfig,
RawCommands,
} from './types'
import { callOrReturn } from './utilities/callOrReturn'
import { mergeDeep } from './utilities/mergeDeep'
declare module '@tiptap/core' {
interface NodeConfig<Options = any, Storage = any> {

View File

@@ -1,10 +1,11 @@
import { Decoration, NodeView as ProseMirrorNodeView } from 'prosemirror-view'
import { NodeSelection } from 'prosemirror-state'
import { Node as ProseMirrorNode } from 'prosemirror-model'
import { NodeSelection } from 'prosemirror-state'
import { Decoration, NodeView as ProseMirrorNodeView } from 'prosemirror-view'
import { Editor as CoreEditor } from './Editor'
import { Node } from './Node'
import { NodeViewRendererOptions, NodeViewRendererProps } from './types'
import { isiOS } from './utilities/isiOS'
import { NodeViewRendererProps, NodeViewRendererOptions } from './types'
export class NodeView<
Component,
@@ -48,11 +49,11 @@ export class NodeView<
return
}
get dom(): Element | null {
return null
get dom(): HTMLElement {
return this.editor.view.dom as HTMLElement
}
get contentDOM(): Element | null {
get contentDOM(): HTMLElement | null {
return null
}
@@ -82,8 +83,12 @@ export class NodeView<
const domBox = this.dom.getBoundingClientRect()
const handleBox = dragHandle.getBoundingClientRect()
x = handleBox.x - domBox.x + event.offsetX
y = handleBox.y - domBox.y + event.offsetY
// In React, we have to go through nativeEvent to reach offsetX/offsetY.
const offsetX = event.offsetX ?? (event as any).nativeEvent?.offsetX
const offsetY = event.offsetY ?? (event as any).nativeEvent?.offsetY
x = handleBox.x - domBox.x + offsetX
y = handleBox.y - domBox.y + offsetY
}
event.dataTransfer?.setDragImage(this.dom, x, y)

View File

@@ -1,16 +1,17 @@
import { EditorState, Plugin } from 'prosemirror-state'
import { Editor } from './Editor'
import { CommandManager } from './CommandManager'
import { Editor } from './Editor'
import { createChainableState } from './helpers/createChainableState'
import { isRegExp } from './utilities/isRegExp'
import { isNumber } from './utilities/isNumber'
import {
Range,
ExtendedRegExpMatchArray,
SingleCommands,
ChainedCommands,
CanCommands,
ChainedCommands,
ExtendedRegExpMatchArray,
Range,
SingleCommands,
} from './types'
import { isNumber } from './utilities/isNumber'
import { isRegExp } from './utilities/isRegExp'
export type PasteRuleMatch = {
index: number,
@@ -189,8 +190,8 @@ export function pasteRulesPlugin(props: { editor: Editor, rules: PasteRule[] }):
return false
},
paste: (view, event) => {
const html = event.clipboardData?.getData('text/html')
paste: (view, event: Event) => {
const html = (event as ClipboardEvent).clipboardData?.getData('text/html')
isPastedFromProseMirror = !!html?.includes('data-pm-slice')
@@ -228,7 +229,7 @@ export function pasteRulesPlugin(props: { editor: Editor, rules: PasteRule[] }):
editor,
state: chainableState,
from: Math.max(from - 1, 0),
to: to.b,
to: to.b - 1,
rule,
})

View File

@@ -1,4 +1,5 @@
import { liftTarget } from 'prosemirror-transform'
import { RawCommands } from '../types'
declare module '@tiptap/core' {

View File

@@ -1,4 +1,5 @@
import { createParagraphNear as originalCreateParagraphNear } from 'prosemirror-commands'
import { RawCommands } from '../types'
declare module '@tiptap/core' {

View File

@@ -1,4 +1,5 @@
import { NodeType } from 'prosemirror-model'
import { getNodeType } from '../helpers/getNodeType'
import { RawCommands } from '../types'

View File

@@ -1,4 +1,4 @@
import { RawCommands, Range } from '../types'
import { Range, RawCommands } from '../types'
declare module '@tiptap/core' {
interface Commands<ReturnType> {

View File

@@ -1,4 +1,5 @@
import { deleteSelection as originalDeleteSelection } from 'prosemirror-commands'
import { RawCommands } from '../types'
declare module '@tiptap/core' {

View File

@@ -1,4 +1,5 @@
import { exitCode as originalExitCode } from 'prosemirror-commands'
import { RawCommands } from '../types'
declare module '@tiptap/core' {

View File

@@ -1,8 +1,9 @@
import { TextSelection } from 'prosemirror-state'
import { MarkType } from 'prosemirror-model'
import { RawCommands } from '../types'
import { getMarkType } from '../helpers/getMarkType'
import { TextSelection } from 'prosemirror-state'
import { getMarkRange } from '../helpers/getMarkRange'
import { getMarkType } from '../helpers/getMarkType'
import { RawCommands } from '../types'
declare module '@tiptap/core' {
interface Commands<ReturnType> {

View File

@@ -1,7 +1,7 @@
import { RawCommands, FocusPosition } from '../types'
import { isTextSelection } from '../helpers/isTextSelection'
import { isiOS } from '../utilities/isiOS'
import { resolveFocusPosition } from '../helpers/resolveFocusPosition'
import { FocusPosition, RawCommands } from '../types'
import { isiOS } from '../utilities/isiOS'
declare module '@tiptap/core' {
interface Commands<ReturnType> {
@@ -19,7 +19,7 @@ declare module '@tiptap/core' {
}
}
export const focus: RawCommands['focus'] = (position = null, options) => ({
export const focus: RawCommands['focus'] = (position = null, options = {}) => ({
editor,
view,
tr,
@@ -60,7 +60,9 @@ export const focus: RawCommands['focus'] = (position = null, options) => ({
return true
}
const selection = resolveFocusPosition(editor.state.doc, position) || editor.state.selection
// pass through tr.doc instead of editor.state.doc
// since transactions could change the editors state before this command has been run
const selection = resolveFocusPosition(tr.doc, position) || editor.state.selection
const isSameSelection = editor.state.selection.eq(selection)
if (dispatch) {

View File

@@ -0,0 +1,50 @@
export * from './blur'
export * from './clearContent'
export * from './clearNodes'
export * from './command'
export * from './createParagraphNear'
export * from './deleteNode'
export * from './deleteRange'
export * from './deleteSelection'
export * from './enter'
export * from './exitCode'
export * from './extendMarkRange'
export * from './first'
export * from './focus'
export * from './forEach'
export * from './insertContent'
export * from './insertContentAt'
export * from './joinBackward'
export * from './joinForward'
export * from './keyboardShortcut'
export * from './lift'
export * from './liftEmptyBlock'
export * from './liftListItem'
export * from './newlineInCode'
export * from './resetAttributes'
export * from './scrollIntoView'
export * from './selectAll'
export * from './selectNodeBackward'
export * from './selectNodeForward'
export * from './selectParentNode'
export * from './selectTextblockEnd'
export * from './selectTextblockStart'
export * from './setContent'
export * from './setMark'
export * from './setMeta'
export * from './setNode'
export * from './setNodeSelection'
export * from './setTextSelection'
export * from './sinkListItem'
export * from './splitBlock'
export * from './splitListItem'
export * from './toggleList'
export * from './toggleMark'
export * from './toggleNode'
export * from './toggleWrap'
export * from './undoInputRule'
export * from './unsetAllMarks'
export * from './unsetMark'
export * from './updateAttributes'
export * from './wrapIn'
export * from './wrapInList'

View File

@@ -1,5 +1,6 @@
import { ParseOptions } from 'prosemirror-model'
import { RawCommands, Content } from '../types'
import { Content, RawCommands } from '../types'
declare module '@tiptap/core' {
interface Commands<ReturnType> {

View File

@@ -1,10 +1,11 @@
import { Fragment, Node as ProseMirrorNode, ParseOptions } from 'prosemirror-model'
import { createNodeFromContent } from '../helpers/createNodeFromContent'
import { selectionToInsertionEnd } from '../helpers/selectionToInsertionEnd'
import {
RawCommands,
Content,
Range,
RawCommands,
} from '../types'
declare module '@tiptap/core' {

View File

@@ -1,4 +1,5 @@
import { joinBackward as originalJoinBackward } from 'prosemirror-commands'
import { RawCommands } from '../types'
declare module '@tiptap/core' {

View File

@@ -1,4 +1,5 @@
import { joinForward as originalJoinForward } from 'prosemirror-commands'
import { RawCommands } from '../types'
declare module '@tiptap/core' {

View File

@@ -1,8 +1,9 @@
import { lift as originalLift } from 'prosemirror-commands'
import { NodeType } from 'prosemirror-model'
import { RawCommands } from '../types'
import { isNodeActive } from '../helpers/isNodeActive'
import { getNodeType } from '../helpers/getNodeType'
import { isNodeActive } from '../helpers/isNodeActive'
import { RawCommands } from '../types'
declare module '@tiptap/core' {
interface Commands<ReturnType> {

View File

@@ -1,4 +1,5 @@
import { liftEmptyBlock as originalLiftEmptyBlock } from 'prosemirror-commands'
import { RawCommands } from '../types'
declare module '@tiptap/core' {

View File

@@ -1,7 +1,8 @@
import { liftListItem as originalLiftListItem } from 'prosemirror-schema-list'
import { NodeType } from 'prosemirror-model'
import { RawCommands } from '../types'
import { liftListItem as originalLiftListItem } from 'prosemirror-schema-list'
import { getNodeType } from '../helpers/getNodeType'
import { RawCommands } from '../types'
declare module '@tiptap/core' {
interface Commands<ReturnType> {

View File

@@ -1,4 +1,5 @@
import { newlineInCode as originalNewlineInCode } from 'prosemirror-commands'
import { RawCommands } from '../types'
declare module '@tiptap/core' {

View File

@@ -1,9 +1,10 @@
import { NodeType, MarkType } from 'prosemirror-model'
import { getNodeType } from '../helpers/getNodeType'
import { MarkType, NodeType } from 'prosemirror-model'
import { getMarkType } from '../helpers/getMarkType'
import { getNodeType } from '../helpers/getNodeType'
import { getSchemaTypeNameByName } from '../helpers/getSchemaTypeNameByName'
import { deleteProps } from '../utilities/deleteProps'
import { RawCommands } from '../types'
import { deleteProps } from '../utilities/deleteProps'
declare module '@tiptap/core' {
interface Commands<ReturnType> {

View File

@@ -1,4 +1,5 @@
import { selectNodeBackward as originalSelectNodeBackward } from 'prosemirror-commands'
import { RawCommands } from '../types'
declare module '@tiptap/core' {

View File

@@ -1,4 +1,5 @@
import { selectNodeForward as originalSelectNodeForward } from 'prosemirror-commands'
import { RawCommands } from '../types'
declare module '@tiptap/core' {

View File

@@ -1,4 +1,5 @@
import { selectParentNode as originalSelectParentNode } from 'prosemirror-commands'
import { RawCommands } from '../types'
declare module '@tiptap/core' {

View File

@@ -1,6 +1,7 @@
// @ts-ignore
// TODO: add types to @types/prosemirror-commands
import { selectTextblockEnd as originalSelectTextblockEnd } from 'prosemirror-commands'
import { RawCommands } from '../types'
declare module '@tiptap/core' {

View File

@@ -1,6 +1,7 @@
// @ts-ignore
// TODO: add types to @types/prosemirror-commands
import { selectTextblockStart as originalSelectTextblockStart } from 'prosemirror-commands'
import { RawCommands } from '../types'
declare module '@tiptap/core' {

View File

@@ -1,7 +1,7 @@
import { TextSelection } from 'prosemirror-state'
import { ParseOptions } from 'prosemirror-model'
import { createDocument } from '../helpers/createDocument'
import { RawCommands, Content } from '../types'
import { Content, RawCommands } from '../types'
declare module '@tiptap/core' {
interface Commands<ReturnType> {
@@ -21,11 +21,9 @@ declare module '@tiptap/core' {
export const setContent: RawCommands['setContent'] = (content, emitUpdate = false, parseOptions = {}) => ({ tr, editor, dispatch }) => {
const { doc } = tr
const document = createDocument(content, editor.schema, parseOptions)
const selection = TextSelection.create(doc, 0, doc.content.size)
if (dispatch) {
tr.setSelection(selection)
.replaceSelectionWith(document, false)
tr.replaceWith(0, doc.content.size, document)
.setMeta('preventUpdate', !emitUpdate)
}

View File

@@ -1,7 +1,8 @@
import { MarkType } from 'prosemirror-model'
import { RawCommands } from '../types'
import { getMarkType } from '../helpers/getMarkType'
import { getMarkAttributes } from '../helpers/getMarkAttributes'
import { getMarkType } from '../helpers/getMarkType'
import { RawCommands } from '../types'
declare module '@tiptap/core' {
interface Commands<ReturnType> {

View File

@@ -1,7 +1,8 @@
import { NodeType } from 'prosemirror-model'
import { setBlockType } from 'prosemirror-commands'
import { RawCommands } from '../types'
import { NodeType } from 'prosemirror-model'
import { getNodeType } from '../helpers/getNodeType'
import { RawCommands } from '../types'
declare module '@tiptap/core' {
interface Commands<ReturnType> {

View File

@@ -1,6 +1,7 @@
import { Selection, NodeSelection } from 'prosemirror-state'
import { minMax } from '../utilities/minMax'
import { NodeSelection } from 'prosemirror-state'
import { RawCommands } from '../types'
import { minMax } from '../utilities/minMax'
declare module '@tiptap/core' {
interface Commands<ReturnType> {
@@ -16,10 +17,8 @@ declare module '@tiptap/core' {
export const setNodeSelection: RawCommands['setNodeSelection'] = position => ({ tr, dispatch }) => {
if (dispatch) {
const { doc } = tr
const minPos = Selection.atStart(doc).from
const maxPos = Selection.atEnd(doc).to
const resolvedPos = minMax(position, minPos, maxPos)
const selection = NodeSelection.create(doc, resolvedPos)
const from = minMax(position, 0, doc.content.size)
const selection = NodeSelection.create(doc, from)
tr.setSelection(selection)
}

View File

@@ -1,6 +1,7 @@
import { TextSelection } from 'prosemirror-state'
import { Range, RawCommands } from '../types'
import { minMax } from '../utilities/minMax'
import { RawCommands, Range } from '../types'
declare module '@tiptap/core' {
interface Commands<ReturnType> {

View File

@@ -1,7 +1,8 @@
import { sinkListItem as originalSinkListItem } from 'prosemirror-schema-list'
import { NodeType } from 'prosemirror-model'
import { RawCommands } from '../types'
import { sinkListItem as originalSinkListItem } from 'prosemirror-schema-list'
import { getNodeType } from '../helpers/getNodeType'
import { RawCommands } from '../types'
declare module '@tiptap/core' {
interface Commands<ReturnType> {

View File

@@ -1,19 +1,9 @@
import { canSplit } from 'prosemirror-transform'
import { ContentMatch } from 'prosemirror-model'
import { EditorState, NodeSelection, TextSelection } from 'prosemirror-state'
import { RawCommands } from '../types'
import { canSplit } from 'prosemirror-transform'
import { defaultBlockAt } from '../helpers/defaultBlockAt'
import { getSplittedAttributes } from '../helpers/getSplittedAttributes'
function defaultBlockAt(match: ContentMatch) {
for (let i = 0; i < match.edgeCount; i += 1) {
const { type } = match.edge(i)
if (type.isTextblock && !type.hasRequiredAttrs()) {
return type
}
}
return null
}
import { RawCommands } from '../types'
function ensureMarks(state: EditorState, splittableMarks?: string[]) {
const marks = state.storedMarks

View File

@@ -1,14 +1,15 @@
import {
NodeType,
Node as ProseMirrorNode,
Fragment,
Node as ProseMirrorNode,
NodeType,
Slice,
} from 'prosemirror-model'
import { canSplit } from 'prosemirror-transform'
import { TextSelection } from 'prosemirror-state'
import { RawCommands } from '../types'
import { canSplit } from 'prosemirror-transform'
import { getNodeType } from '../helpers/getNodeType'
import { getSplittedAttributes } from '../helpers/getSplittedAttributes'
import { RawCommands } from '../types'
declare module '@tiptap/core' {
interface Commands<ReturnType> {

View File

@@ -1,10 +1,11 @@
import { NodeType } from 'prosemirror-model'
import { Transaction } from 'prosemirror-state'
import { canJoin } from 'prosemirror-transform'
import { RawCommands } from '../types'
import { getNodeType } from '../helpers/getNodeType'
import { findParentNode } from '../helpers/findParentNode'
import { getNodeType } from '../helpers/getNodeType'
import { isList } from '../helpers/isList'
import { RawCommands } from '../types'
const joinListBackwards = (tr: Transaction, listType: NodeType): boolean => {
const list = findParentNode(node => node.type === listType)(tr.selection)

View File

@@ -1,7 +1,8 @@
import { MarkType } from 'prosemirror-model'
import { RawCommands } from '../types'
import { getMarkType } from '../helpers/getMarkType'
import { isMarkActive } from '../helpers/isMarkActive'
import { RawCommands } from '../types'
declare module '@tiptap/core' {
interface Commands<ReturnType> {

View File

@@ -1,7 +1,8 @@
import { NodeType } from 'prosemirror-model'
import { RawCommands } from '../types'
import { isNodeActive } from '../helpers/isNodeActive'
import { getNodeType } from '../helpers/getNodeType'
import { isNodeActive } from '../helpers/isNodeActive'
import { RawCommands } from '../types'
declare module '@tiptap/core' {
interface Commands<ReturnType> {

View File

@@ -1,7 +1,8 @@
import { NodeType } from 'prosemirror-model'
import { RawCommands } from '../types'
import { isNodeActive } from '../helpers/isNodeActive'
import { getNodeType } from '../helpers/getNodeType'
import { isNodeActive } from '../helpers/isNodeActive'
import { RawCommands } from '../types'
declare module '@tiptap/core' {
interface Commands<ReturnType> {

View File

@@ -1,7 +1,8 @@
import { MarkType } from 'prosemirror-model'
import { RawCommands } from '../types'
import { getMarkType } from '../helpers/getMarkType'
import { getMarkRange } from '../helpers/getMarkRange'
import { getMarkType } from '../helpers/getMarkType'
import { RawCommands } from '../types'
declare module '@tiptap/core' {
interface Commands<ReturnType> {

View File

@@ -1,6 +1,7 @@
import { NodeType, MarkType } from 'prosemirror-model'
import { getNodeType } from '../helpers/getNodeType'
import { MarkType, NodeType } from 'prosemirror-model'
import { getMarkType } from '../helpers/getMarkType'
import { getNodeType } from '../helpers/getNodeType'
import { getSchemaTypeNameByName } from '../helpers/getSchemaTypeNameByName'
import { RawCommands } from '../types'

View File

@@ -1,7 +1,8 @@
import { wrapIn as originalWrapIn } from 'prosemirror-commands'
import { NodeType } from 'prosemirror-model'
import { RawCommands } from '../types'
import { getNodeType } from '../helpers/getNodeType'
import { RawCommands } from '../types'
declare module '@tiptap/core' {
interface Commands<ReturnType> {

View File

@@ -1,7 +1,8 @@
import { wrapInList as originalWrapInList } from 'prosemirror-schema-list'
import { NodeType } from 'prosemirror-model'
import { RawCommands } from '../types'
import { wrapInList as originalWrapInList } from 'prosemirror-schema-list'
import { getNodeType } from '../helpers/getNodeType'
import { RawCommands } from '../types'
declare module '@tiptap/core' {
interface Commands<ReturnType> {

View File

@@ -1,7 +1,8 @@
import { Plugin, PluginKey } from 'prosemirror-state'
import { Extension } from '../Extension'
import { getTextBetween } from '../helpers/getTextBetween'
import { getTextSeralizersFromSchema } from '../helpers/getTextSeralizersFromSchema'
import { getTextSerializersFromSchema } from '../helpers/getTextSerializersFromSchema'
export const ClipboardTextSerializer = Extension.create({
name: 'clipboardTextSerializer',
@@ -18,7 +19,7 @@ export const ClipboardTextSerializer = Extension.create({
const { ranges } = selection
const from = Math.min(...ranges.map(range => range.$from.pos))
const to = Math.max(...ranges.map(range => range.$to.pos))
const textSerializers = getTextSeralizersFromSchema(schema)
const textSerializers = getTextSerializersFromSchema(schema)
const range = { from, to }
return getTextBetween(doc, range, {

View File

@@ -1,161 +1,14 @@
import * as commands from '../commands'
import { Extension } from '../Extension'
import * as blur from '../commands/blur'
import * as clearContent from '../commands/clearContent'
import * as clearNodes from '../commands/clearNodes'
import * as command from '../commands/command'
import * as createParagraphNear from '../commands/createParagraphNear'
import * as deleteNode from '../commands/deleteNode'
import * as deleteRange from '../commands/deleteRange'
import * as deleteSelection from '../commands/deleteSelection'
import * as enter from '../commands/enter'
import * as exitCode from '../commands/exitCode'
import * as extendMarkRange from '../commands/extendMarkRange'
import * as first from '../commands/first'
import * as focus from '../commands/focus'
import * as forEach from '../commands/forEach'
import * as insertContent from '../commands/insertContent'
import * as insertContentAt from '../commands/insertContentAt'
import * as joinBackward from '../commands/joinBackward'
import * as joinForward from '../commands/joinForward'
import * as keyboardShortcut from '../commands/keyboardShortcut'
import * as lift from '../commands/lift'
import * as liftEmptyBlock from '../commands/liftEmptyBlock'
import * as liftListItem from '../commands/liftListItem'
import * as newlineInCode from '../commands/newlineInCode'
import * as resetAttributes from '../commands/resetAttributes'
import * as scrollIntoView from '../commands/scrollIntoView'
import * as selectAll from '../commands/selectAll'
import * as selectNodeBackward from '../commands/selectNodeBackward'
import * as selectNodeForward from '../commands/selectNodeForward'
import * as selectParentNode from '../commands/selectParentNode'
import * as selectTextblockEnd from '../commands/selectTextblockEnd'
import * as selectTextblockStart from '../commands/selectTextblockStart'
import * as setContent from '../commands/setContent'
import * as setMark from '../commands/setMark'
import * as setMeta from '../commands/setMeta'
import * as setNode from '../commands/setNode'
import * as setNodeSelection from '../commands/setNodeSelection'
import * as setTextSelection from '../commands/setTextSelection'
import * as sinkListItem from '../commands/sinkListItem'
import * as splitBlock from '../commands/splitBlock'
import * as splitListItem from '../commands/splitListItem'
import * as toggleList from '../commands/toggleList'
import * as toggleMark from '../commands/toggleMark'
import * as toggleNode from '../commands/toggleNode'
import * as toggleWrap from '../commands/toggleWrap'
import * as undoInputRule from '../commands/undoInputRule'
import * as unsetAllMarks from '../commands/unsetAllMarks'
import * as unsetMark from '../commands/unsetMark'
import * as updateAttributes from '../commands/updateAttributes'
import * as wrapIn from '../commands/wrapIn'
import * as wrapInList from '../commands/wrapInList'
export { blur }
export { clearContent }
export { clearNodes }
export { command }
export { createParagraphNear }
export { deleteNode }
export { deleteRange }
export { deleteSelection }
export { enter }
export { exitCode }
export { extendMarkRange }
export { first }
export { focus }
export { forEach }
export { insertContent }
export { insertContentAt }
export { joinBackward }
export { joinForward }
export { keyboardShortcut }
export { lift }
export { liftEmptyBlock }
export { liftListItem }
export { newlineInCode }
export { resetAttributes }
export { scrollIntoView }
export { selectAll }
export { selectNodeBackward }
export { selectNodeForward }
export { selectParentNode }
export { selectTextblockEnd }
export { selectTextblockStart }
export { setContent }
export { setMark }
export { setMeta }
export { setNode }
export { setNodeSelection }
export { setTextSelection }
export { sinkListItem }
export { splitBlock }
export { splitListItem }
export { toggleList }
export { toggleMark }
export { toggleNode }
export { toggleWrap }
export { undoInputRule }
export { unsetAllMarks }
export { unsetMark }
export { updateAttributes }
export { wrapIn }
export { wrapInList }
export * from '../commands'
export const Commands = Extension.create({
name: 'commands',
addCommands() {
return {
...blur,
...clearContent,
...clearNodes,
...command,
...createParagraphNear,
...deleteNode,
...deleteRange,
...deleteSelection,
...enter,
...exitCode,
...extendMarkRange,
...first,
...focus,
...forEach,
...insertContent,
...insertContentAt,
...joinBackward,
...joinForward,
...keyboardShortcut,
...lift,
...liftEmptyBlock,
...liftListItem,
...newlineInCode,
...resetAttributes,
...scrollIntoView,
...selectAll,
...selectNodeBackward,
...selectNodeForward,
...selectParentNode,
...selectTextblockEnd,
...selectTextblockStart,
...setContent,
...setMark,
...setMeta,
...setNode,
...setNodeSelection,
...setTextSelection,
...sinkListItem,
...splitBlock,
...splitListItem,
...toggleList,
...toggleMark,
...toggleNode,
...toggleWrap,
...undoInputRule,
...unsetAllMarks,
...unsetMark,
...updateAttributes,
...wrapIn,
...wrapInList,
...commands,
}
},
})

View File

@@ -1,4 +1,5 @@
import { Plugin, PluginKey } from 'prosemirror-state'
import { Extension } from '../Extension'
export const Editable = Extension.create({

View File

@@ -1,4 +1,5 @@
import { Plugin, PluginKey } from 'prosemirror-state'
import { Extension } from '../Extension'
export const FocusEvents = Extension.create({
@@ -12,7 +13,7 @@ export const FocusEvents = Extension.create({
key: new PluginKey('focusEvents'),
props: {
handleDOMEvents: {
focus: (view, event) => {
focus: (view, event: Event) => {
editor.isFocused = true
const transaction = editor.state.tr
@@ -23,7 +24,7 @@ export const FocusEvents = Extension.create({
return false
},
blur: (view, event) => {
blur: (view, event: Event) => {
editor.isFocused = false
const transaction = editor.state.tr

View File

@@ -1,9 +1,10 @@
import { Plugin, PluginKey, Selection } from 'prosemirror-state'
import { CommandManager } from '../CommandManager'
import { Extension } from '../Extension'
import { createChainableState } from '../helpers/createChainableState'
import { isiOS } from '../utilities/isiOS'
import { isMacOS } from '../utilities/isMacOS'
import { CommandManager } from '../CommandManager'
import { Extension } from '../Extension'
export const Keymap = Extension.create({
name: 'keymap',
@@ -60,8 +61,6 @@ export const Keymap = Extension.create({
const pcKeymap = {
...baseKeymap,
Home: () => this.editor.commands.selectTextblockStart(),
End: () => this.editor.commands.selectTextblockEnd(),
}
const macKeymap = {

View File

@@ -1,4 +1,5 @@
import { Plugin, PluginKey } from 'prosemirror-state'
import { Extension } from '../Extension'
export const Tabindex = Extension.create({
@@ -9,13 +10,7 @@ export const Tabindex = Extension.create({
new Plugin({
key: new PluginKey('tabindex'),
props: {
attributes: () => {
if (this.editor.isEditable) {
return {
tabindex: '0',
}
}
},
attributes: this.editor.isEditable ? { tabindex: '0' } : {},
},
}),
]

View File

@@ -11,10 +11,11 @@ export function createChainableState(config: {
return {
...state,
schema: state.schema,
plugins: state.plugins,
apply: state.apply.bind(state),
applyTransaction: state.applyTransaction.bind(state),
filterTransaction: state.filterTransaction,
plugins: state.plugins,
schema: state.schema,
reconfigure: state.reconfigure.bind(state),
toJSON: state.toJSON.bind(state),
get storedMarks() {

View File

@@ -1,4 +1,5 @@
import { Schema, Node as ProseMirrorNode, ParseOptions } from 'prosemirror-model'
import { Node as ProseMirrorNode, ParseOptions, Schema } from 'prosemirror-model'
import { Content } from '../types'
import { createNodeFromContent } from './createNodeFromContent'

View File

@@ -1,12 +1,13 @@
import {
Schema,
DOMParser,
Node as ProseMirrorNode,
Fragment,
Node as ProseMirrorNode,
ParseOptions,
Schema,
} from 'prosemirror-model'
import { elementFromString } from '../utilities/elementFromString'
import { Content } from '../types'
import { elementFromString } from '../utilities/elementFromString'
export type CreateNodeFromContentOptions = {
slice?: boolean,

View File

@@ -1,5 +1,6 @@
import { Node as ProseMirrorNode } from 'prosemirror-model'
import { Predicate, NodeWithPos } from '../types'
import { NodeWithPos, Predicate } from '../types'
export function findChildren(node: ProseMirrorNode, predicate: Predicate): NodeWithPos[] {
const nodesWithPos: NodeWithPos[] = []

View File

@@ -1,5 +1,6 @@
import { Node as ProseMirrorNode } from 'prosemirror-model'
import { Predicate, Range, NodeWithPos } from '../types'
import { NodeWithPos, Predicate, Range } from '../types'
/**
* Same as `findChildren` but searches only within a `range`.

View File

@@ -1,6 +1,7 @@
import { Selection } from 'prosemirror-state'
import { findParentNodeClosestToPos } from './findParentNodeClosestToPos'
import { Predicate } from '../types'
import { findParentNodeClosestToPos } from './findParentNodeClosestToPos'
export function findParentNode(predicate: Predicate) {
return (selection: Selection) => findParentNodeClosestToPos(selection.$from, predicate)

View File

@@ -1,4 +1,5 @@
import { ResolvedPos, Node as ProseMirrorNode } from 'prosemirror-model'
import { Node as ProseMirrorNode, ResolvedPos } from 'prosemirror-model'
import { Predicate } from '../types'
export function findParentNodeClosestToPos($pos: ResolvedPos, predicate: Predicate): ({

View File

@@ -1,7 +1,8 @@
import { Node } from 'prosemirror-model'
import { getSchema } from './getSchema'
import { getHTMLFromFragment } from './getHTMLFromFragment'
import { Extensions, JSONContent } from '../types'
import { getHTMLFromFragment } from './getHTMLFromFragment'
import { getSchema } from './getSchema'
export function generateHTML(doc: JSONContent, extensions: Extensions): string {
const schema = getSchema(extensions)

View File

@@ -1,7 +1,8 @@
import { DOMParser } from 'prosemirror-model'
import { getSchema } from './getSchema'
import { elementFromString } from '../utilities/elementFromString'
import { Extensions } from '../types'
import { elementFromString } from '../utilities/elementFromString'
import { getSchema } from './getSchema'
export function generateJSON(html: string, extensions: Extensions): Record<string, any> {
const schema = getSchema(extensions)

View File

@@ -1,8 +1,9 @@
import { Node } from 'prosemirror-model'
import { getSchema } from './getSchema'
import { Extensions, JSONContent, TextSerializer } from '../types'
import { getTextSeralizersFromSchema } from './getTextSeralizersFromSchema'
import { getSchema } from './getSchema'
import { getText } from './getText'
import { getTextSerializersFromSchema } from './getTextSerializersFromSchema'
export function generateText(
doc: JSONContent,
@@ -23,7 +24,7 @@ export function generateText(
blockSeparator,
textSerializers: {
...textSerializers,
...getTextSeralizersFromSchema(schema),
...getTextSerializersFromSchema(schema),
},
})
}

View File

@@ -1,8 +1,9 @@
import { MarkType, NodeType } from 'prosemirror-model'
import { EditorState } from 'prosemirror-state'
import { getSchemaTypeNameByName } from './getSchemaTypeNameByName'
import { getNodeAttributes } from './getNodeAttributes'
import { getMarkAttributes } from './getMarkAttributes'
import { getNodeAttributes } from './getNodeAttributes'
import { getSchemaTypeNameByName } from './getSchemaTypeNameByName'
export function getAttributes(
state: EditorState,

View File

@@ -1,14 +1,14 @@
import { splitExtensions } from './splitExtensions'
import { getExtensionField } from './getExtensionField'
import { MarkConfig, NodeConfig } from '..'
import {
AnyConfig,
Attribute,
Attributes,
ExtensionAttribute,
Extensions,
GlobalAttributes,
Attributes,
Attribute,
ExtensionAttribute,
AnyConfig,
} from '../types'
import { NodeConfig, MarkConfig } from '..'
import { getExtensionField } from './getExtensionField'
import { splitExtensions } from './splitExtensions'
/**
* Get a list of all extension attributes defined in `addAttribute` and `addGlobalAttribute`.
@@ -24,6 +24,7 @@ export function getAttributesFromExtensions(extensions: Extensions): ExtensionAt
renderHTML: null,
parseHTML: null,
keepOnSplit: true,
isRequired: false,
}
extensions.forEach(extension => {
@@ -87,13 +88,19 @@ export function getAttributesFromExtensions(extensions: Extensions): ExtensionAt
Object
.entries(attributes)
.forEach(([name, attribute]) => {
const mergedAttr = {
...defaultAttribute,
...attribute,
}
if (attribute.isRequired && attribute.default === undefined) {
delete mergedAttr.default
}
extensionAttributes.push({
type: extension.name,
name,
attribute: {
...defaultAttribute,
...attribute,
},
attribute: mergedAttr,
})
})
})

View File

@@ -1,4 +1,5 @@
import { Transform, Step } from 'prosemirror-transform'
import { Step, Transform } from 'prosemirror-transform'
import { Range } from '../types'
import { removeDuplicates } from '../utilities/removeDuplicates'

View File

@@ -1,4 +1,5 @@
import { Node as ProseMirrorNode } from 'prosemirror-model'
import { JSONContent } from '../types'
interface DebugJSONContent extends JSONContent {

View File

@@ -1,4 +1,4 @@
import { AnyExtension, RemoveThis, MaybeThisParameterType } from '../types'
import { AnyExtension, MaybeThisParameterType, RemoveThis } from '../types'
export function getExtensionField<T = any>(
extension: AnyExtension,

View File

@@ -1,4 +1,4 @@
import { DOMSerializer, Schema, Fragment } from 'prosemirror-model'
import { DOMSerializer, Fragment, Schema } from 'prosemirror-model'
export function getHTMLFromFragment(fragment: Fragment, schema: Schema): string {
const documentFragment = DOMSerializer

View File

@@ -1,5 +1,6 @@
import { EditorState } from 'prosemirror-state'
import { Mark, MarkType } from 'prosemirror-model'
import { EditorState } from 'prosemirror-state'
import { getMarkType } from './getMarkType'
export function getMarkAttributes(state: EditorState, typeOrName: string | MarkType): Record<string, any> {

View File

@@ -1,6 +1,7 @@
import { Mark as ProseMirrorMark, MarkType, ResolvedPos } from 'prosemirror-model'
import { objectIncludes } from '../utilities/objectIncludes'
import { Range } from '../types'
import { objectIncludes } from '../utilities/objectIncludes'
function findMarkInSet(
marks: ProseMirrorMark[],
@@ -29,24 +30,28 @@ export function getMarkRange(
return
}
const start = $pos.parent.childAfter($pos.parentOffset)
let start = $pos.parent.childAfter($pos.parentOffset)
if ($pos.parentOffset === start.offset && start.offset !== 0) {
start = $pos.parent.childBefore($pos.parentOffset)
}
if (!start.node) {
return
}
const mark = findMarkInSet(start.node.marks, type, attributes)
const mark = findMarkInSet([...start.node.marks], type, attributes)
if (!mark) {
return
}
let startIndex = $pos.index()
let startIndex = start.index
let startPos = $pos.start() + start.offset
let endIndex = startIndex + 1
let endPos = startPos + start.node.nodeSize
findMarkInSet(start.node.marks, type, attributes)
findMarkInSet([...start.node.marks], type, attributes)
while (startIndex > 0 && mark.isInSet($pos.parent.child(startIndex - 1).marks)) {
startIndex -= 1
@@ -55,7 +60,7 @@ export function getMarkRange(
while (
endIndex < $pos.parent.childCount
&& isMarkInSet($pos.parent.child(endIndex).marks, type, attributes)
&& isMarkInSet([...$pos.parent.child(endIndex).marks], type, attributes)
) {
endPos += $pos.parent.child(endIndex).nodeSize
endIndex += 1

View File

@@ -1,4 +1,5 @@
import { Node as ProseMirrorNode } from 'prosemirror-model'
import { MarkRange } from '../types'
import { getMarkRange } from './getMarkRange'

View File

@@ -1,5 +1,6 @@
import { EditorState } from 'prosemirror-state'
import { Node, NodeType } from 'prosemirror-model'
import { EditorState } from 'prosemirror-state'
import { getNodeType } from './getNodeType'
export function getNodeAttributes(state: EditorState, typeOrName: string | NodeType): Record<string, any> {

View File

@@ -1,4 +1,5 @@
import { Node, Mark } from 'prosemirror-model'
import { Mark, Node } from 'prosemirror-model'
import { ExtensionAttribute } from '../types'
import { mergeAttributes } from '../utilities/mergeAttributes'

View File

@@ -1,7 +1,8 @@
import { Schema } from 'prosemirror-model'
import { getSchemaByResolvedExtensions } from './getSchemaByResolvedExtensions'
import { ExtensionManager } from '../ExtensionManager'
import { Extensions } from '../types'
import { getSchemaByResolvedExtensions } from './getSchemaByResolvedExtensions'
export function getSchema(extensions: Extensions): Schema {
const resolvedExtensions = ExtensionManager.resolve(extensions)

View File

@@ -1,13 +1,14 @@
import { NodeSpec, MarkSpec, Schema } from 'prosemirror-model'
import { MarkSpec, NodeSpec, Schema } from 'prosemirror-model'
import { MarkConfig, NodeConfig } from '..'
import { AnyConfig, Extensions } from '../types'
import { NodeConfig, MarkConfig } from '..'
import { splitExtensions } from './splitExtensions'
import { getAttributesFromExtensions } from './getAttributesFromExtensions'
import { getRenderedAttributes } from './getRenderedAttributes'
import { isEmptyObject } from '../utilities/isEmptyObject'
import { injectExtensionAttributesToParseRule } from './injectExtensionAttributesToParseRule'
import { callOrReturn } from '../utilities/callOrReturn'
import { isEmptyObject } from '../utilities/isEmptyObject'
import { getAttributesFromExtensions } from './getAttributesFromExtensions'
import { getExtensionField } from './getExtensionField'
import { getRenderedAttributes } from './getRenderedAttributes'
import { injectExtensionAttributesToParseRule } from './injectExtensionAttributesToParseRule'
import { splitExtensions } from './splitExtensions'
function cleanUpSchemaItem<T>(data: T) {
return Object.fromEntries(Object.entries(data).filter(([key, value]) => {

View File

@@ -1,5 +1,6 @@
import { TextSerializer } from '../types'
import { Node as ProseMirrorNode } from 'prosemirror-model'
import { TextSerializer } from '../types'
import { getTextBetween } from './getTextBetween'
export function getText(

View File

@@ -1,6 +1,7 @@
import { Range, TextSerializer } from '../types'
import { Node as ProseMirrorNode } from 'prosemirror-model'
import { Range, TextSerializer } from '../types'
export function getTextBetween(
startNode: ProseMirrorNode,
range: Range,
@@ -26,14 +27,17 @@ export function getTextBetween(
separated = true
}
text += textSerializer({
node,
pos,
parent,
index,
})
if (parent) {
text += textSerializer({
node,
pos,
parent,
index,
range,
})
}
} else if (node.isText) {
text += node?.text?.slice(Math.max(from, pos) - pos, to - pos)
text += node?.text?.slice(Math.max(from, pos) - pos, to - pos) // eslint-disable-line
separated = false
} else if (node.isBlock && !separated) {
text += blockSeparator

View File

@@ -0,0 +1,17 @@
import { ResolvedPos } from 'prosemirror-model'
export const getTextContentFromNodes = ($from: ResolvedPos, maxMatch = 500) => {
let textBefore = ''
$from.parent.nodesBetween(
Math.max(0, $from.parentOffset - maxMatch),
$from.parentOffset,
(node, pos, parent, index) => {
textBefore += node.type.spec.toText?.({
node, pos, parent, index,
}) || $from.nodeBefore?.text || '%leaf%'
},
)
return textBefore
}

View File

@@ -1,7 +1,8 @@
import { Schema } from 'prosemirror-model'
import { TextSerializer } from '../types'
export function getTextSeralizersFromSchema(schema: Schema): Record<string, TextSerializer> {
export function getTextSerializersFromSchema(schema: Schema): Record<string, TextSerializer> {
return Object.fromEntries(Object
.entries(schema.nodes)
.filter(([, node]) => node.spec.toText)

View File

@@ -0,0 +1,33 @@
export * from './combineTransactionSteps'
export * from './defaultBlockAt'
export * from './findChildren'
export * from './findChildrenInRange'
export * from './findParentNode'
export * from './findParentNodeClosestToPos'
export * from './generateHTML'
export * from './generateJSON'
export * from './generateText'
export * from './getAttributes'
export * from './getChangedRanges'
export * from './getDebugJSON'
export * from './getExtensionField'
export * from './getHTMLFromFragment'
export * from './getMarkAttributes'
export * from './getMarkRange'
export * from './getMarksBetween'
export * from './getMarkType'
export * from './getNodeAttributes'
export * from './getNodeType'
export * from './getSchema'
export * from './getText'
export * from './getTextBetween'
export * from './getTextContentFromNodes'
export * from './getTextSerializersFromSchema'
export * from './isActive'
export * from './isList'
export * from './isMarkActive'
export * from './isNodeActive'
export * from './isNodeEmpty'
export * from './isNodeSelection'
export * from './isTextSelection'
export * from './posToDOMRect'

View File

@@ -1,4 +1,5 @@
import { ParseRule } from 'prosemirror-model'
import { ExtensionAttribute } from '../types'
import { fromString } from '../utilities/fromString'

View File

@@ -1,7 +1,8 @@
import { EditorState } from 'prosemirror-state'
import { isNodeActive } from './isNodeActive'
import { isMarkActive } from './isMarkActive'
import { getSchemaTypeNameByName } from './getSchemaTypeNameByName'
import { isMarkActive } from './isMarkActive'
import { isNodeActive } from './isNodeActive'
export function isActive(state: EditorState, name: string | null, attributes: Record<string, any> = {}): boolean {
if (!name) {

View File

@@ -1,8 +1,8 @@
import { Extensions } from '../types'
import { NodeConfig } from '..'
import { splitExtensions } from './splitExtensions'
import { callOrReturn } from '../utilities/callOrReturn'
import { getExtensionField } from '../helpers/getExtensionField'
import { Extensions } from '../types'
import { callOrReturn } from '../utilities/callOrReturn'
import { splitExtensions } from './splitExtensions'
export function isList(name: string, extensions: Extensions): boolean {
const { nodeExtensions } = splitExtensions(extensions)

View File

@@ -1,8 +1,9 @@
import { EditorState } from 'prosemirror-state'
import { MarkType } from 'prosemirror-model'
import { EditorState } from 'prosemirror-state'
import { MarkRange } from '../types'
import { objectIncludes } from '../utilities/objectIncludes'
import { getMarkType } from './getMarkType'
import { MarkRange } from '../types'
export function isMarkActive(
state: EditorState,

View File

@@ -1,8 +1,9 @@
import { EditorState } from 'prosemirror-state'
import { NodeType } from 'prosemirror-model'
import { EditorState } from 'prosemirror-state'
import { NodeRange } from '../types'
import { objectIncludes } from '../utilities/objectIncludes'
import { getNodeType } from './getNodeType'
import { NodeRange } from '../types'
export function isNodeActive(
state: EditorState,

View File

@@ -1,6 +1,5 @@
import { NodeSelection } from 'prosemirror-state'
import { isObject } from '../utilities/isObject'
export function isNodeSelection(value: unknown): value is NodeSelection {
return isObject(value) && value instanceof NodeSelection
return value instanceof NodeSelection
}

View File

@@ -1,6 +1,5 @@
import { TextSelection } from 'prosemirror-state'
import { isObject } from '../utilities/isObject'
export function isTextSelection(value: unknown): value is TextSelection {
return isObject(value) && value instanceof TextSelection
return value instanceof TextSelection
}

View File

@@ -1,4 +1,5 @@
import { EditorView } from 'prosemirror-view'
import { minMax } from '../utilities/minMax'
export function posToDOMRect(view: EditorView, from: number, to: number): DOMRect {

View File

@@ -1,5 +1,6 @@
import { Node as ProseMirrorNode } from 'prosemirror-model'
import { Selection, TextSelection } from 'prosemirror-state'
import { FocusPosition } from '../types'
import { minMax } from '../utilities/minMax'

View File

@@ -1,5 +1,5 @@
import { Selection, Transaction } from 'prosemirror-state'
import { ReplaceStep, ReplaceAroundStep } from 'prosemirror-transform'
import { ReplaceAroundStep, ReplaceStep } from 'prosemirror-transform'
// source: https://github.com/ProseMirror/prosemirror-state/blob/master/src/selection.js#L466
export function selectionToInsertionEnd(tr: Transaction, startLen: number, bias: number) {

View File

@@ -1,7 +1,7 @@
import { Extensions } from '../types'
import { Extension } from '../Extension'
import { Node } from '../Node'
import { Mark } from '../Mark'
import { Node } from '../Node'
import { Extensions } from '../types'
export function splitExtensions(extensions: Extensions) {
const baseExtensions = extensions.filter(extension => extension.type === 'extension') as Extension[]

View File

@@ -1,60 +1,18 @@
import * as extensions from './extensions'
export { extensions }
export * from './CommandManager'
export * from './Editor'
export * from './Extension'
export * from './Node'
export * from './Mark'
export * from './NodeView'
export * from './Tracker'
export * as extensions from './extensions'
export * from './helpers'
export * from './InputRule'
export * from './inputRules'
export * from './Mark'
export * from './Node'
export * from './NodeView'
export * from './PasteRule'
export * from './CommandManager'
export * from './pasteRules'
export * from './Tracker'
export * from './types'
export * from './inputRules/nodeInputRule'
export * from './inputRules/markInputRule'
export * from './inputRules/textblockTypeInputRule'
export * from './inputRules/textInputRule'
export * from './inputRules/wrappingInputRule'
export * from './pasteRules/markPasteRule'
export * from './pasteRules/textPasteRule'
export * from './utilities/callOrReturn'
export * from './utilities/escapeForRegEx'
export * from './utilities/mergeAttributes'
export * from './helpers/combineTransactionSteps'
export * from './helpers/defaultBlockAt'
export * from './helpers/getExtensionField'
export * from './helpers/findChildren'
export * from './helpers/findChildrenInRange'
export * from './helpers/findParentNode'
export * from './helpers/findParentNodeClosestToPos'
export * from './helpers/generateHTML'
export * from './helpers/generateJSON'
export * from './helpers/generateText'
export * from './helpers/getChangedRanges'
export * from './helpers/getSchema'
export * from './helpers/getHTMLFromFragment'
export * from './helpers/getDebugJSON'
export * from './helpers/getAttributes'
export * from './helpers/getMarkAttributes'
export * from './helpers/getMarkRange'
export * from './helpers/getMarkType'
export * from './helpers/getMarksBetween'
export * from './helpers/getNodeAttributes'
export * from './helpers/getNodeType'
export * from './helpers/getText'
export * from './helpers/getTextBetween'
export * from './helpers/isActive'
export * from './helpers/isList'
export * from './helpers/isMarkActive'
export * from './helpers/isNodeActive'
export * from './helpers/isNodeEmpty'
export * from './helpers/isNodeSelection'
export * from './helpers/isTextSelection'
export * from './helpers/posToDOMRect'
export * from './utilities'
// eslint-disable-next-line
export interface Commands<ReturnType = any> {}

View File

@@ -0,0 +1,5 @@
export * from './markInputRule'
export * from './nodeInputRule'
export * from './textblockTypeInputRule'
export * from './textInputRule'
export * from './wrappingInputRule'

View File

@@ -1,8 +1,9 @@
import { InputRule, InputRuleFinder } from '../InputRule'
import { MarkType } from 'prosemirror-model'
import { getMarksBetween } from '../helpers/getMarksBetween'
import { callOrReturn } from '../utilities/callOrReturn'
import { InputRule, InputRuleFinder } from '../InputRule'
import { ExtendedRegExpMatchArray } from '../types'
import { callOrReturn } from '../utilities/callOrReturn'
/**
* Build an input rule that adds a mark when the

View File

@@ -1,4 +1,5 @@
import { NodeType } from 'prosemirror-model'
import { InputRule, InputRuleFinder } from '../InputRule'
import { ExtendedRegExpMatchArray } from '../types'
import { callOrReturn } from '../utilities/callOrReturn'

View File

@@ -1,5 +1,6 @@
import { InputRule, InputRuleFinder } from '../InputRule'
import { NodeType } from 'prosemirror-model'
import { InputRule, InputRuleFinder } from '../InputRule'
import { ExtendedRegExpMatchArray } from '../types'
import { callOrReturn } from '../utilities/callOrReturn'

Some files were not shown because too many files have changed in this diff Show More