add core extensions
This commit is contained in:
22
packages/core/src/extensions/blur.ts
Normal file
22
packages/core/src/extensions/blur.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { Command } from '../Editor'
|
||||
import { createExtension } from '../Extension'
|
||||
|
||||
export const Blur = createExtension({
|
||||
addCommands() {
|
||||
return {
|
||||
blur: (): Command => ({ view }) => {
|
||||
const element = view.dom as HTMLElement
|
||||
|
||||
element.blur()
|
||||
|
||||
return true
|
||||
},
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
declare module '../Editor' {
|
||||
interface AllExtensions {
|
||||
Blur: typeof Blur,
|
||||
}
|
||||
}
|
||||
18
packages/core/src/extensions/clearContent.ts
Normal file
18
packages/core/src/extensions/clearContent.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { Command } from '../Editor'
|
||||
import { createExtension } from '../Extension'
|
||||
|
||||
export const ClearContent = createExtension({
|
||||
addCommands() {
|
||||
return {
|
||||
clearContent: (emitUpdate: Boolean = false): Command => ({ commands }) => {
|
||||
return commands.setContent('', emitUpdate)
|
||||
},
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
declare module '../Editor' {
|
||||
interface AllExtensions {
|
||||
ClearContent: typeof ClearContent,
|
||||
}
|
||||
}
|
||||
19
packages/core/src/extensions/deleteSelection.ts
Normal file
19
packages/core/src/extensions/deleteSelection.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { deleteSelection as originalDeleteSelection } from 'prosemirror-commands'
|
||||
import { Command } from '../Editor'
|
||||
import { createExtension } from '../Extension'
|
||||
|
||||
export const DeleteSelection = createExtension({
|
||||
addCommands() {
|
||||
return {
|
||||
deleteSelection: (): Command => ({ state, dispatch }) => {
|
||||
return originalDeleteSelection(state, dispatch)
|
||||
},
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
declare module '../Editor' {
|
||||
interface AllExtensions {
|
||||
DeleteSelection: typeof DeleteSelection,
|
||||
}
|
||||
}
|
||||
67
packages/core/src/extensions/focus.ts
Normal file
67
packages/core/src/extensions/focus.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
import { TextSelection } from 'prosemirror-state'
|
||||
import { Editor, Command } from '../Editor'
|
||||
import { createExtension } from '../Extension'
|
||||
import minMax from '../utils/minMax'
|
||||
|
||||
type Position = 'start' | 'end' | number | boolean | null
|
||||
|
||||
interface ResolvedSelection {
|
||||
from: number,
|
||||
to: number,
|
||||
}
|
||||
|
||||
function resolveSelection(editor: Editor, position: Position = null): ResolvedSelection {
|
||||
if (position === null) {
|
||||
return editor.selection
|
||||
}
|
||||
|
||||
if (position === 'start' || position === true) {
|
||||
return {
|
||||
from: 0,
|
||||
to: 0,
|
||||
}
|
||||
}
|
||||
|
||||
if (position === 'end') {
|
||||
const { size } = editor.state.doc.content
|
||||
|
||||
return {
|
||||
from: size,
|
||||
to: size - 1, // TODO: -1 only for nodes with content
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
from: position as number,
|
||||
to: position as number,
|
||||
}
|
||||
}
|
||||
|
||||
export const Focus = createExtension({
|
||||
addCommands() {
|
||||
return {
|
||||
focus: (position: Position = null): Command => ({ editor, view, tr }) => {
|
||||
if ((view.hasFocus() && position === null) || position === false) {
|
||||
return true
|
||||
}
|
||||
|
||||
const { from, to } = resolveSelection(editor, position)
|
||||
const { doc } = tr
|
||||
const resolvedFrom = minMax(from, 0, doc.content.size)
|
||||
const resolvedEnd = minMax(to, 0, doc.content.size)
|
||||
const selection = TextSelection.create(doc, resolvedFrom, resolvedEnd)
|
||||
|
||||
tr.setSelection(selection)
|
||||
view.focus()
|
||||
|
||||
return true
|
||||
},
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
declare module '../Editor' {
|
||||
interface AllExtensions {
|
||||
Focus: typeof Focus,
|
||||
}
|
||||
}
|
||||
21
packages/core/src/extensions/index.ts
Normal file
21
packages/core/src/extensions/index.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
export { Blur } from './blur'
|
||||
export { ClearContent } from './clearContent'
|
||||
export { DeleteSelection } from './deleteSelection'
|
||||
export { Focus } from './focus'
|
||||
export { InsertHTML } from './insertHTML'
|
||||
export { InsertText } from './insertText'
|
||||
export { LiftListItem } from './liftListItem'
|
||||
export { RemoveMark } from './removeMark'
|
||||
export { RemoveMarks } from './removeMarks'
|
||||
export { ScrollIntoView } from './scrollIntoView'
|
||||
export { SelectAll } from './selectAll'
|
||||
export { SelectParentNode } from './selectParentNode'
|
||||
export { SetBlockType } from './setBlockType'
|
||||
export { SetContent } from './setContent'
|
||||
export { SinkListItem } from './sinkListItem'
|
||||
export { SplitListItem } from './splitListItem'
|
||||
export { ToggleBlockType } from './toggleBlockType'
|
||||
export { ToggleList } from './toggleList'
|
||||
export { ToggleMark } from './toggleMark'
|
||||
export { UpdateMark } from './updateMark'
|
||||
export { ToggleWrap } from './toggleWrap'
|
||||
42
packages/core/src/extensions/insertHTML.ts
Normal file
42
packages/core/src/extensions/insertHTML.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { DOMParser } from 'prosemirror-model'
|
||||
import { Selection, Transaction } from 'prosemirror-state'
|
||||
import { ReplaceStep, ReplaceAroundStep } from 'prosemirror-transform'
|
||||
import elementFromString from '../utils/elementFromString'
|
||||
import { Command } from '../Editor'
|
||||
import { createExtension } from '../Extension'
|
||||
|
||||
// TODO: move to utils
|
||||
// https://github.com/ProseMirror/prosemirror-state/blob/master/src/selection.js#L466
|
||||
function selectionToInsertionEnd(tr: Transaction, startLen: number, bias: number) {
|
||||
const last = tr.steps.length - 1
|
||||
if (last < startLen) return
|
||||
const step = tr.steps[last]
|
||||
if (!(step instanceof ReplaceStep || step instanceof ReplaceAroundStep)) return
|
||||
const map = tr.mapping.maps[last]
|
||||
let end = 0
|
||||
map.forEach((_from, _to, _newFrom, newTo) => { if (end === 0) end = newTo })
|
||||
tr.setSelection(Selection.near(tr.doc.resolve(end as unknown as number), bias))
|
||||
}
|
||||
|
||||
export const InsertHTML = createExtension({
|
||||
addCommands() {
|
||||
return {
|
||||
insertHTML: (value: string): Command => ({ tr, state }) => {
|
||||
const { selection } = tr
|
||||
const element = elementFromString(value)
|
||||
const slice = DOMParser.fromSchema(state.schema).parseSlice(element)
|
||||
|
||||
tr.insert(selection.anchor, slice.content)
|
||||
selectionToInsertionEnd(tr, tr.steps.length - 1, -1)
|
||||
|
||||
return true
|
||||
},
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
declare module '../Editor' {
|
||||
interface AllExtensions {
|
||||
InsertHTML: typeof InsertHTML,
|
||||
}
|
||||
}
|
||||
20
packages/core/src/extensions/insertText.ts
Normal file
20
packages/core/src/extensions/insertText.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { Command } from '../Editor'
|
||||
import { createExtension } from '../Extension'
|
||||
|
||||
export const InsertText = createExtension({
|
||||
addCommands() {
|
||||
return {
|
||||
insertText: (value: string): Command => ({ tr }) => {
|
||||
tr.insertText(value)
|
||||
|
||||
return true
|
||||
},
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
declare module '../Editor' {
|
||||
interface AllExtensions {
|
||||
InsertText: typeof InsertText,
|
||||
}
|
||||
}
|
||||
23
packages/core/src/extensions/liftListItem.ts
Normal file
23
packages/core/src/extensions/liftListItem.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { liftListItem as originalLiftListItem } from 'prosemirror-schema-list'
|
||||
import { NodeType } from 'prosemirror-model'
|
||||
import { Command } from '../Editor'
|
||||
import { createExtension } from '../Extension'
|
||||
import getNodeType from '../utils/getNodeType'
|
||||
|
||||
export const LiftListItem = createExtension({
|
||||
addCommands() {
|
||||
return {
|
||||
liftListItem: (typeOrName: string | NodeType): Command => ({ state, dispatch }) => {
|
||||
const type = getNodeType(typeOrName, state.schema)
|
||||
|
||||
return originalLiftListItem(type)(state, dispatch)
|
||||
},
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
declare module '../Editor' {
|
||||
interface AllExtensions {
|
||||
LiftListItem: typeof LiftListItem,
|
||||
}
|
||||
}
|
||||
37
packages/core/src/extensions/removeMark.ts
Normal file
37
packages/core/src/extensions/removeMark.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import { MarkType } from 'prosemirror-model'
|
||||
import { Command } from '../Editor'
|
||||
import { createExtension } from '../Extension'
|
||||
import getMarkType from '../utils/getMarkType'
|
||||
import getMarkRange from '../utils/getMarkRange'
|
||||
|
||||
export const RemoveMark = createExtension({
|
||||
addCommands() {
|
||||
return {
|
||||
removeMark: (typeOrName: string | MarkType): Command => ({ tr, state }) => {
|
||||
const { selection } = tr
|
||||
const type = getMarkType(typeOrName, state.schema)
|
||||
let { from, to } = selection
|
||||
const { $from, empty } = selection
|
||||
|
||||
if (empty) {
|
||||
const range = getMarkRange($from, type)
|
||||
|
||||
if (range) {
|
||||
from = range.from
|
||||
to = range.to
|
||||
}
|
||||
}
|
||||
|
||||
tr.removeMark(from, to, type)
|
||||
|
||||
return true
|
||||
},
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
declare module '../Editor' {
|
||||
interface AllExtensions {
|
||||
RemoveMark: typeof RemoveMark,
|
||||
}
|
||||
}
|
||||
31
packages/core/src/extensions/removeMarks.ts
Normal file
31
packages/core/src/extensions/removeMarks.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import { Command } from '../Editor'
|
||||
import { createExtension } from '../Extension'
|
||||
|
||||
export const RemoveMarks = createExtension({
|
||||
addCommands() {
|
||||
return {
|
||||
removeMarks: (): Command => ({ tr, state }) => {
|
||||
const { selection } = tr
|
||||
const { from, to, empty } = selection
|
||||
|
||||
if (empty) {
|
||||
return true
|
||||
}
|
||||
|
||||
Object
|
||||
.entries(state.schema.marks)
|
||||
.forEach(([, mark]) => {
|
||||
tr.removeMark(from, to, mark as any)
|
||||
})
|
||||
|
||||
return true
|
||||
},
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
declare module '../Editor' {
|
||||
interface AllExtensions {
|
||||
RemoveMarks: typeof RemoveMarks,
|
||||
}
|
||||
}
|
||||
20
packages/core/src/extensions/scrollIntoView.ts
Normal file
20
packages/core/src/extensions/scrollIntoView.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { Command } from '../Editor'
|
||||
import { createExtension } from '../Extension'
|
||||
|
||||
export const ScrollIntoView = createExtension({
|
||||
addCommands() {
|
||||
return {
|
||||
scrollIntoView: (): Command => ({ tr }) => {
|
||||
tr.scrollIntoView()
|
||||
|
||||
return true
|
||||
},
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
declare module '../Editor' {
|
||||
interface AllExtensions {
|
||||
ScrollIntoView: typeof ScrollIntoView,
|
||||
}
|
||||
}
|
||||
19
packages/core/src/extensions/selectAll.ts
Normal file
19
packages/core/src/extensions/selectAll.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { selectAll as originalSelectAll } from 'prosemirror-commands'
|
||||
import { Command } from '../Editor'
|
||||
import { createExtension } from '../Extension'
|
||||
|
||||
export const SelectAll = createExtension({
|
||||
addCommands() {
|
||||
return {
|
||||
selectAll: (): Command => ({ state, dispatch }) => {
|
||||
return originalSelectAll(state, dispatch)
|
||||
},
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
declare module '../Editor' {
|
||||
interface AllExtensions {
|
||||
SelectAll: typeof SelectAll,
|
||||
}
|
||||
}
|
||||
19
packages/core/src/extensions/selectParentNode.ts
Normal file
19
packages/core/src/extensions/selectParentNode.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { selectParentNode as originalSelectParentNode } from 'prosemirror-commands'
|
||||
import { Command } from '../Editor'
|
||||
import { createExtension } from '../Extension'
|
||||
|
||||
export const SelectParentNode = createExtension({
|
||||
addCommands() {
|
||||
return {
|
||||
selectParentNode: (): Command => ({ state, dispatch }) => {
|
||||
return originalSelectParentNode(state, dispatch)
|
||||
},
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
declare module '../Editor' {
|
||||
interface AllExtensions {
|
||||
SelectParentNode: typeof SelectParentNode,
|
||||
}
|
||||
}
|
||||
23
packages/core/src/extensions/setBlockType.ts
Normal file
23
packages/core/src/extensions/setBlockType.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { NodeType } from 'prosemirror-model'
|
||||
import { setBlockType as originalSetBlockType } from 'prosemirror-commands'
|
||||
import { Command } from '../Editor'
|
||||
import { createExtension } from '../Extension'
|
||||
import getNodeType from '../utils/getNodeType'
|
||||
|
||||
export const SetBlockType = createExtension({
|
||||
addCommands() {
|
||||
return {
|
||||
setBlockType: (typeOrName: string | NodeType, attrs = {}): Command => ({ state, dispatch }) => {
|
||||
const type = getNodeType(typeOrName, state.schema)
|
||||
|
||||
return originalSetBlockType(type, attrs)(state, dispatch)
|
||||
},
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
declare module '../Editor' {
|
||||
interface AllExtensions {
|
||||
SetBlockType: typeof SetBlockType,
|
||||
}
|
||||
}
|
||||
28
packages/core/src/extensions/setContent.ts
Normal file
28
packages/core/src/extensions/setContent.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { TextSelection } from 'prosemirror-state'
|
||||
import { Command } from '../Editor'
|
||||
import { createExtension } from '../Extension'
|
||||
|
||||
export const SetContent = createExtension({
|
||||
addCommands() {
|
||||
return {
|
||||
setContent: (content: string, emitUpdate: Boolean = false, parseOptions = {}): Command => ({ tr, editor }) => {
|
||||
const { createDocument } = editor
|
||||
const { doc } = tr
|
||||
const document = createDocument(content, parseOptions)
|
||||
const selection = TextSelection.create(doc, 0, doc.content.size)
|
||||
|
||||
tr.setSelection(selection)
|
||||
.replaceSelectionWith(document, false)
|
||||
.setMeta('preventUpdate', !emitUpdate)
|
||||
|
||||
return true
|
||||
},
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
declare module '../Editor' {
|
||||
interface AllExtensions {
|
||||
SetContent: typeof SetContent,
|
||||
}
|
||||
}
|
||||
23
packages/core/src/extensions/sinkListItem.ts
Normal file
23
packages/core/src/extensions/sinkListItem.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { sinkListItem as originalSinkListItem } from 'prosemirror-schema-list'
|
||||
import { NodeType } from 'prosemirror-model'
|
||||
import { Command } from '../Editor'
|
||||
import { createExtension } from '../Extension'
|
||||
import getNodeType from '../utils/getNodeType'
|
||||
|
||||
export const SinkListItem = createExtension({
|
||||
addCommands() {
|
||||
return {
|
||||
sinkListItem: (typeOrName: string | NodeType): Command => ({ state, dispatch }) => {
|
||||
const type = getNodeType(typeOrName, state.schema)
|
||||
|
||||
return originalSinkListItem(type)(state, dispatch)
|
||||
},
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
declare module '../Editor' {
|
||||
interface AllExtensions {
|
||||
SinkListItem: typeof SinkListItem,
|
||||
}
|
||||
}
|
||||
23
packages/core/src/extensions/splitListItem.ts
Normal file
23
packages/core/src/extensions/splitListItem.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { splitListItem as originalSplitListItem } from 'prosemirror-schema-list'
|
||||
import { NodeType } from 'prosemirror-model'
|
||||
import { Command } from '../Editor'
|
||||
import { createExtension } from '../Extension'
|
||||
import getNodeType from '../utils/getNodeType'
|
||||
|
||||
export const SplitListItem = createExtension({
|
||||
addCommands() {
|
||||
return {
|
||||
splitListItem: (typeOrName: string | NodeType): Command => ({ state, dispatch }) => {
|
||||
const type = getNodeType(typeOrName, state.schema)
|
||||
|
||||
return originalSplitListItem(type)(state, dispatch)
|
||||
},
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
declare module '../Editor' {
|
||||
interface AllExtensions {
|
||||
SplitListItem: typeof SplitListItem,
|
||||
}
|
||||
}
|
||||
29
packages/core/src/extensions/toggleBlockType.ts
Normal file
29
packages/core/src/extensions/toggleBlockType.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { NodeType } from 'prosemirror-model'
|
||||
import { Command } from '../Editor'
|
||||
import { createExtension } from '../Extension'
|
||||
import nodeIsActive from '../utils/nodeIsActive'
|
||||
import getNodeType from '../utils/getNodeType'
|
||||
|
||||
export const ToggleBlockType = createExtension({
|
||||
addCommands() {
|
||||
return {
|
||||
toggleBlockType: (typeOrName: string | NodeType, toggleTypeOrName: string | NodeType, attrs = {}): Command => ({ state, commands }) => {
|
||||
const type = getNodeType(typeOrName, state.schema)
|
||||
const toggleType = getNodeType(toggleTypeOrName, state.schema)
|
||||
const isActive = nodeIsActive(state, type, attrs)
|
||||
|
||||
if (isActive) {
|
||||
return commands.setBlockType(toggleType)
|
||||
}
|
||||
|
||||
return commands.setBlockType(type, attrs)
|
||||
},
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
declare module '../Editor' {
|
||||
interface AllExtensions {
|
||||
ToggleBlockType: typeof ToggleBlockType,
|
||||
}
|
||||
}
|
||||
52
packages/core/src/extensions/toggleList.ts
Normal file
52
packages/core/src/extensions/toggleList.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import { wrapInList, liftListItem } from 'prosemirror-schema-list'
|
||||
import { findParentNode } from 'prosemirror-utils'
|
||||
import { Node, NodeType, Schema } from 'prosemirror-model'
|
||||
import { Command } from '../Editor'
|
||||
import { createExtension } from '../Extension'
|
||||
import getNodeType from '../utils/getNodeType'
|
||||
|
||||
function isList(node: Node, schema: Schema) {
|
||||
return (node.type === schema.nodes.bullet_list
|
||||
|| node.type === schema.nodes.ordered_list
|
||||
|| node.type === schema.nodes.todo_list)
|
||||
}
|
||||
|
||||
export const ToggleList = createExtension({
|
||||
addCommands() {
|
||||
return {
|
||||
toggleList: (listTypeOrName: string | NodeType, itemTypeOrName: string | NodeType): Command => ({ tr, state, dispatch }) => {
|
||||
const listType = getNodeType(listTypeOrName, state.schema)
|
||||
const itemType = getNodeType(itemTypeOrName, state.schema)
|
||||
const { schema, selection } = state
|
||||
const { $from, $to } = selection
|
||||
const range = $from.blockRange($to)
|
||||
|
||||
if (!range) {
|
||||
return false
|
||||
}
|
||||
|
||||
const parentList = findParentNode(node => isList(node, schema))(selection)
|
||||
|
||||
if (range.depth >= 1 && parentList && range.depth - parentList.depth <= 1) {
|
||||
if (parentList.node.type === listType) {
|
||||
return liftListItem(itemType)(state, dispatch)
|
||||
}
|
||||
|
||||
if (isList(parentList.node, schema) && listType.validContent(parentList.node.content)) {
|
||||
tr.setNodeMarkup(parentList.pos, listType)
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return wrapInList(listType)(state, dispatch)
|
||||
},
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
declare module '../Editor' {
|
||||
interface AllExtensions {
|
||||
ToggleList: typeof ToggleList,
|
||||
}
|
||||
}
|
||||
23
packages/core/src/extensions/toggleMark.ts
Normal file
23
packages/core/src/extensions/toggleMark.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { toggleMark as originalToggleMark } from 'prosemirror-commands'
|
||||
import { MarkType } from 'prosemirror-model'
|
||||
import { Command } from '../Editor'
|
||||
import { createExtension } from '../Extension'
|
||||
import getMarkType from '../utils/getMarkType'
|
||||
|
||||
export const ToggleMark = createExtension({
|
||||
addCommands() {
|
||||
return {
|
||||
toggleMark: (typeOrName: string | MarkType): Command => ({ state, dispatch }) => {
|
||||
const type = getMarkType(typeOrName, state.schema)
|
||||
|
||||
return originalToggleMark(type)(state, dispatch)
|
||||
},
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
declare module '../Editor' {
|
||||
interface AllExtensions {
|
||||
ToggleMark: typeof ToggleMark,
|
||||
}
|
||||
}
|
||||
29
packages/core/src/extensions/toggleWrap.ts
Normal file
29
packages/core/src/extensions/toggleWrap.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { wrapIn, lift } from 'prosemirror-commands'
|
||||
import { NodeType } from 'prosemirror-model'
|
||||
import { Command } from '../Editor'
|
||||
import { createExtension } from '../Extension'
|
||||
import nodeIsActive from '../utils/nodeIsActive'
|
||||
import getNodeType from '../utils/getNodeType'
|
||||
|
||||
export const ToggleWrap = createExtension({
|
||||
addCommands() {
|
||||
return {
|
||||
toggleWrap: (typeOrName: string | NodeType, attrs = {}): Command => ({ state, dispatch }) => {
|
||||
const type = getNodeType(typeOrName, state.schema)
|
||||
const isActive = nodeIsActive(state, type, attrs)
|
||||
|
||||
if (isActive) {
|
||||
return lift(state, dispatch)
|
||||
}
|
||||
|
||||
return wrapIn(type, attrs)(state, dispatch)
|
||||
},
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
declare module '../Editor' {
|
||||
interface AllExtensions {
|
||||
ToggleWrap: typeof ToggleWrap,
|
||||
}
|
||||
}
|
||||
43
packages/core/src/extensions/updateMark.ts
Normal file
43
packages/core/src/extensions/updateMark.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import { MarkType } from 'prosemirror-model'
|
||||
import { Command } from '../Editor'
|
||||
import { createExtension } from '../Extension'
|
||||
import getMarkType from '../utils/getMarkType'
|
||||
import getMarkRange from '../utils/getMarkRange'
|
||||
|
||||
export const UpdateMark = createExtension({
|
||||
addCommands() {
|
||||
return {
|
||||
updateMark: (typeOrName: string | MarkType, attrs: {}): Command => ({ tr, state }) => {
|
||||
const { selection, doc } = tr
|
||||
let { from, to } = selection
|
||||
const { $from, empty } = selection
|
||||
const type = getMarkType(typeOrName, state.schema)
|
||||
|
||||
if (empty) {
|
||||
const range = getMarkRange($from, type)
|
||||
|
||||
if (range) {
|
||||
from = range.from
|
||||
to = range.to
|
||||
}
|
||||
}
|
||||
|
||||
const hasMark = doc.rangeHasMark(from, to, type)
|
||||
|
||||
if (hasMark) {
|
||||
tr.removeMark(from, to, type)
|
||||
}
|
||||
|
||||
tr.addMark(from, to, type.create(attrs))
|
||||
|
||||
return true
|
||||
},
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
declare module '../Editor' {
|
||||
interface AllExtensions {
|
||||
UpdateMark: typeof UpdateMark,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user