Files
tiptap/packages/extension-horizontal-rule/src/horizontal-rule.ts
Philipp Kühn 9afadeb7fe feat!: Replace defaultOptions with addOptions (#2088)
* add new addOptions option

* replace defaultOptions with addOptions for all extensions

* replace defaultOptions with addOptions for all demos

* replace defaultOptions with addOptions in docs

* refactoring

* refactoring

* drop object support for addOptions

* fix optional options

* fix tests
2021-10-26 18:31:13 +02:00

104 lines
2.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import {
Node,
nodeInputRule,
mergeAttributes,
} from '@tiptap/core'
import { TextSelection } from 'prosemirror-state'
export interface HorizontalRuleOptions {
HTMLAttributes: Record<string, any>,
}
declare module '@tiptap/core' {
interface Commands<ReturnType> {
horizontalRule: {
/**
* Add a horizontal rule
*/
setHorizontalRule: () => ReturnType,
}
}
}
export const HorizontalRule = Node.create<HorizontalRuleOptions>({
name: 'horizontalRule',
addOptions() {
return {
HTMLAttributes: {},
}
},
group: 'block',
parseHTML() {
return [
{ tag: 'hr' },
]
},
renderHTML({ HTMLAttributes }) {
return ['hr', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes)]
},
addCommands() {
return {
setHorizontalRule: () => ({ chain }) => {
return chain()
// remove node before hr if its an empty text block
.command(({ tr, dispatch }) => {
const { selection } = tr
const { empty, $anchor } = selection
const isEmptyTextBlock = $anchor.parent.isTextblock
&& !$anchor.parent.type.spec.code
&& !$anchor.parent.textContent
if (!empty || !isEmptyTextBlock || !dispatch) {
return true
}
const from = $anchor.before()
const to = $anchor.start()
tr.deleteRange(from, to)
tr.setSelection(TextSelection.create(tr.doc, from))
return true
})
.insertContent({ type: this.name })
// add node after hr if its the end of the document
.command(({ tr, dispatch }) => {
if (dispatch) {
const { parent, pos } = tr.selection.$from
const posAfter = pos + 1
const nodeAfter = tr.doc.nodeAt(posAfter)
if (!nodeAfter) {
const node = parent.type.contentMatch.defaultType?.create()
if (node) {
tr.insert(posAfter, node)
tr.setSelection(TextSelection.create(tr.doc, posAfter))
}
}
tr.scrollIntoView()
}
return true
})
.run()
},
}
},
addInputRules() {
return [
nodeInputRule({
find: /^(?:---|—-|___\s|\*\*\*\s)$/,
type: this.type,
}),
]
},
})