mirror of
https://github.com/ueberdosis/tiptap.git
synced 2025-06-12 21:00:02 +08:00
use custom splitblock command for text align
This commit is contained in:
parent
2c150f5192
commit
8d0c67cc66
@ -14,6 +14,7 @@ export { SetNodeAttributes } from './setNodeAttributes'
|
|||||||
export { SetBlockType } from './setBlockType'
|
export { SetBlockType } from './setBlockType'
|
||||||
export { SetContent } from './setContent'
|
export { SetContent } from './setContent'
|
||||||
export { SinkListItem } from './sinkListItem'
|
export { SinkListItem } from './sinkListItem'
|
||||||
|
export { SplitBlock } from './splitBlock'
|
||||||
export { SplitListItem } from './splitListItem'
|
export { SplitListItem } from './splitListItem'
|
||||||
export { ToggleBlockType } from './toggleBlockType'
|
export { ToggleBlockType } from './toggleBlockType'
|
||||||
export { ToggleList } from './toggleList'
|
export { ToggleList } from './toggleList'
|
||||||
|
71
packages/core/src/extensions/splitBlock.ts
Normal file
71
packages/core/src/extensions/splitBlock.ts
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
// import {
|
||||||
|
// baseKeymap, chainCommands, newlineInCode, createParagraphNear, liftEmptyBlock, splitBlock,
|
||||||
|
// } from 'prosemirror-commands'
|
||||||
|
import { canSplit } from 'prosemirror-transform'
|
||||||
|
import { ContentMatch, Fragment } from 'prosemirror-model'
|
||||||
|
import { NodeSelection, TextSelection } from 'prosemirror-state'
|
||||||
|
import { Command } from '../Editor'
|
||||||
|
import { createExtension } from '../Extension'
|
||||||
|
// import getNodeType from '../utils/getNodeType'
|
||||||
|
|
||||||
|
function defaultBlockAt(match: ContentMatch) {
|
||||||
|
for (let i = 0; i < match.edgeCount; i + 1) {
|
||||||
|
const { type } = match.edge(i)
|
||||||
|
// @ts-ignore
|
||||||
|
if (type.isTextblock && !type.hasRequiredAttrs()) return type
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
export const SplitBlock = createExtension({
|
||||||
|
addCommands() {
|
||||||
|
return {
|
||||||
|
splitBlock: (copyAttributes = false): Command => ({ state, dispatch }) => {
|
||||||
|
// const type = getNodeType(typeOrName, state.schema)
|
||||||
|
|
||||||
|
const { $from, $to } = state.selection
|
||||||
|
if (state.selection instanceof NodeSelection && state.selection.node.isBlock) {
|
||||||
|
if (!$from.parentOffset || !canSplit(state.doc, $from.pos)) return false
|
||||||
|
if (dispatch) dispatch(state.tr.split($from.pos).scrollIntoView())
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$from.parent.isBlock) return false
|
||||||
|
|
||||||
|
if (dispatch) {
|
||||||
|
const atEnd = $to.parentOffset === $to.parent.content.size
|
||||||
|
const { tr } = state
|
||||||
|
if (state.selection instanceof TextSelection) tr.deleteSelection()
|
||||||
|
const deflt = $from.depth === 0 ? null : defaultBlockAt($from.node(-1).contentMatchAt($from.indexAfter(-1)))
|
||||||
|
let types = atEnd && deflt ? [{ type: deflt, attrs: copyAttributes ? $from.node().attrs : {} }] : null
|
||||||
|
// let types = atEnd && deflt ? [{ type: deflt }] : null
|
||||||
|
// @ts-ignore
|
||||||
|
let can = canSplit(tr.doc, tr.mapping.map($from.pos), 1, types)
|
||||||
|
// @ts-ignore
|
||||||
|
if (!types && !can && canSplit(tr.doc, tr.mapping.map($from.pos), 1, deflt && [{ type: deflt }])) {
|
||||||
|
// @ts-ignore
|
||||||
|
types = [{ type: deflt, attrs: copyAttributes ? $from.node().attrs : {} }]
|
||||||
|
// types = [{ type: deflt }]
|
||||||
|
can = true
|
||||||
|
}
|
||||||
|
if (can) {
|
||||||
|
// @ts-ignore
|
||||||
|
tr.split(tr.mapping.map($from.pos), 1, types)
|
||||||
|
if (!atEnd && !$from.parentOffset && $from.parent.type !== deflt
|
||||||
|
// @ts-ignore
|
||||||
|
&& $from.node(-1).canReplace($from.index(-1), $from.indexAfter(-1), Fragment.from(deflt.create(), $from.parent))) { tr.setNodeMarkup(tr.mapping.map($from.before()), deflt) }
|
||||||
|
}
|
||||||
|
dispatch(tr.scrollIntoView())
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
declare module '../Editor' {
|
||||||
|
interface AllExtensions {
|
||||||
|
SplitBlock: typeof SplitBlock,
|
||||||
|
}
|
||||||
|
}
|
@ -1,82 +1,16 @@
|
|||||||
import { keymap } from 'prosemirror-keymap'
|
import { keymap } from 'prosemirror-keymap'
|
||||||
import {
|
import { baseKeymap } from 'prosemirror-commands'
|
||||||
baseKeymap, chainCommands, newlineInCode, createParagraphNear, liftEmptyBlock, splitBlock,
|
|
||||||
} from 'prosemirror-commands'
|
|
||||||
import { canSplit } from 'prosemirror-transform'
|
|
||||||
import { dropCursor } from 'prosemirror-dropcursor'
|
import { dropCursor } from 'prosemirror-dropcursor'
|
||||||
import { gapCursor } from 'prosemirror-gapcursor'
|
import { gapCursor } from 'prosemirror-gapcursor'
|
||||||
import { undoInputRule } from 'prosemirror-inputrules'
|
import { undoInputRule } from 'prosemirror-inputrules'
|
||||||
import {
|
|
||||||
EditorState, NodeSelection, TextSelection, Transaction,
|
|
||||||
} from 'prosemirror-state'
|
|
||||||
import { ContentMatch, Fragment } from 'prosemirror-model'
|
|
||||||
import editable from './editable'
|
import editable from './editable'
|
||||||
import focus from './focus'
|
import focus from './focus'
|
||||||
|
|
||||||
function defaultBlockAt(match: ContentMatch) {
|
|
||||||
for (let i = 0; i < match.edgeCount; i + 1) {
|
|
||||||
const { type } = match.edge(i)
|
|
||||||
// @ts-ignore
|
|
||||||
if (type.isTextblock && !type.hasRequiredAttrs()) return type
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
// eslint-disable-next-line
|
|
||||||
function customSplitBlock(state: EditorState, dispatch?: (tr: Transaction) => void) {
|
|
||||||
const { $from, $to } = state.selection
|
|
||||||
if (state.selection instanceof NodeSelection && state.selection.node.isBlock) {
|
|
||||||
if (!$from.parentOffset || !canSplit(state.doc, $from.pos)) return false
|
|
||||||
if (dispatch) dispatch(state.tr.split($from.pos).scrollIntoView())
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$from.parent.isBlock) return false
|
|
||||||
|
|
||||||
if (dispatch) {
|
|
||||||
const atEnd = $to.parentOffset === $to.parent.content.size
|
|
||||||
const { tr } = state
|
|
||||||
if (state.selection instanceof TextSelection) tr.deleteSelection()
|
|
||||||
const deflt = $from.depth === 0 ? null : defaultBlockAt($from.node(-1).contentMatchAt($from.indexAfter(-1)))
|
|
||||||
let types = atEnd && deflt ? [{ type: deflt, attrs: $from.node().attrs }] : null
|
|
||||||
console.log(1, { types })
|
|
||||||
// let types = atEnd && deflt ? [{ type: deflt }] : null
|
|
||||||
// @ts-ignore
|
|
||||||
let can = canSplit(tr.doc, tr.mapping.map($from.pos), 1, types)
|
|
||||||
// @ts-ignore
|
|
||||||
if (!types && !can && canSplit(tr.doc, tr.mapping.map($from.pos), 1, deflt && [{ type: deflt }])) {
|
|
||||||
// @ts-ignore
|
|
||||||
types = [{ type: deflt, attrs: $from.node().attrs }]
|
|
||||||
console.log(2, { types })
|
|
||||||
// types = [{ type: deflt }]
|
|
||||||
can = true
|
|
||||||
}
|
|
||||||
if (can) {
|
|
||||||
// @ts-ignore
|
|
||||||
tr.split(tr.mapping.map($from.pos), 1, types)
|
|
||||||
if (!atEnd && !$from.parentOffset && $from.parent.type !== deflt
|
|
||||||
// @ts-ignore
|
|
||||||
&& $from.node(-1).canReplace($from.index(-1), $from.indexAfter(-1), Fragment.from(deflt.create(), $from.parent))) { tr.setNodeMarkup(tr.mapping.map($from.before()), deflt) }
|
|
||||||
}
|
|
||||||
dispatch(tr.scrollIntoView())
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
export default [
|
export default [
|
||||||
() => dropCursor(),
|
() => dropCursor(),
|
||||||
() => gapCursor(),
|
() => gapCursor(),
|
||||||
() => keymap({ Backspace: undoInputRule }),
|
() => keymap({ Backspace: undoInputRule }),
|
||||||
() => keymap({
|
() => keymap(baseKeymap),
|
||||||
...baseKeymap,
|
|
||||||
Enter: chainCommands(
|
|
||||||
newlineInCode,
|
|
||||||
createParagraphNear,
|
|
||||||
liftEmptyBlock,
|
|
||||||
splitBlock,
|
|
||||||
// customSplitBlock,
|
|
||||||
),
|
|
||||||
}),
|
|
||||||
editable,
|
editable,
|
||||||
focus,
|
focus,
|
||||||
]
|
]
|
||||||
|
@ -43,6 +43,14 @@ const TextAlign = createExtension({
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
addKeyboardShortcuts() {
|
||||||
|
return {
|
||||||
|
// TODO: use custom splitBlock only for `this.options.types`
|
||||||
|
// TODO: use complete default enter handler (chainCommand) with custom splitBlock
|
||||||
|
Enter: () => this.editor.splitBlock(true),
|
||||||
|
}
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
export default TextAlign
|
export default TextAlign
|
||||||
|
Loading…
Reference in New Issue
Block a user