tiptap/packages/extension-heading/src/index.ts

101 lines
2.1 KiB
TypeScript
Raw Normal View History

import { Command, Node } from '@tiptap/core'
2020-04-22 04:48:27 +08:00
import { textblockTypeInputRule } from 'prosemirror-inputrules'
2020-04-22 04:16:26 +08:00
type Level = 1 | 2 | 3 | 4 | 5 | 6
2020-09-10 00:55:19 +08:00
export interface HeadingOptions {
2020-08-22 03:01:41 +08:00
levels: Level[],
2020-11-13 23:07:20 +08:00
HTMLAttributes: {
[key: string]: any
},
2020-04-22 04:16:26 +08:00
}
const Heading = Node.create({
2020-10-22 18:34:49 +08:00
name: 'heading',
2020-04-22 04:16:26 +08:00
2020-10-22 18:34:49 +08:00
defaultOptions: <HeadingOptions>{
2020-09-09 05:44:45 +08:00
levels: [1, 2, 3, 4, 5, 6],
2020-11-13 23:07:20 +08:00
HTMLAttributes: {},
2020-10-22 18:34:49 +08:00
},
content: 'inline*',
group: 'block',
defining: true,
addAttributes() {
return {
2020-09-09 05:44:45 +08:00
level: {
default: 1,
2020-10-22 18:34:49 +08:00
rendered: false,
2020-04-22 04:36:31 +08:00
},
2020-10-22 18:34:49 +08:00
}
},
parseHTML() {
return this.options.levels
2020-09-09 05:44:45 +08:00
.map((level: Level) => ({
tag: `h${level}`,
attrs: { level },
2020-10-22 18:34:49 +08:00
}))
},
2020-11-13 23:07:20 +08:00
renderHTML({ node, HTMLAttributes }) {
2020-11-11 17:20:50 +08:00
const hasLevel = this.options.levels.includes(node.attrs.level)
const level = hasLevel
? node.attrs.level
: this.options.levels[0]
2020-11-13 23:07:20 +08:00
return [`h${level}`, HTMLAttributes, 0]
2020-10-22 18:34:49 +08:00
},
addCommands() {
return {
2020-11-18 19:24:41 +08:00
/**
* Set a heading node
*/
setHeading: (attributes: { level: Level }): Command => ({ commands }) => {
if (!this.options.levels.includes(attributes.level)) {
return false
}
return commands.setBlockType('heading', attributes)
},
2020-10-23 04:40:40 +08:00
/**
2020-11-13 22:08:30 +08:00
* Toggle a heading node
2020-10-23 04:40:40 +08:00
*/
2020-11-18 19:24:41 +08:00
toggleHeading: (attributes: { level: Level }): Command => ({ commands }) => {
if (!this.options.levels.includes(attributes.level)) {
2020-11-11 17:20:50 +08:00
return false
}
2020-11-18 19:24:41 +08:00
return commands.toggleBlockType('heading', 'paragraph', attributes)
2020-10-22 18:34:49 +08:00
},
}
},
addKeyboardShortcuts() {
return this.options.levels.reduce((items, level) => ({
2020-09-25 23:17:54 +08:00
...items,
...{
2020-11-18 19:24:41 +08:00
[`Mod-Alt-${level}`]: () => this.editor.commands.toggleHeading({ level }),
2020-09-25 23:17:54 +08:00
},
}), {})
2020-10-22 18:34:49 +08:00
},
addInputRules() {
return this.options.levels.map(level => {
return textblockTypeInputRule(new RegExp(`^(#{1,${level}})\\s$`), this.type, { level })
2020-09-10 00:07:17 +08:00
})
2020-10-22 18:34:49 +08:00
},
})
2020-10-23 04:40:40 +08:00
export default Heading
declare module '@tiptap/core' {
interface AllExtensions {
Heading: typeof Heading,
2020-10-23 04:40:40 +08:00
}
}