tiptap/packages/extension-code-block/index.ts

100 lines
2.1 KiB
TypeScript
Raw Normal View History

2020-10-22 18:34:49 +08:00
import { Command, createNode } from '@tiptap/core'
2020-09-10 21:10:22 +08:00
import { textblockTypeInputRule } from 'prosemirror-inputrules'
export interface CodeBlockOptions {
languageClassPrefix: string,
}
export const backtickInputRegex = /^```(?<language>[a-z]*)? $/
export const tildeInputRegex = /^~~~(?<language>[a-z]*)? $/
2020-09-27 02:20:52 +08:00
2020-10-23 04:40:40 +08:00
const CodeBlock = createNode({
2020-10-22 18:34:49 +08:00
name: 'code_block',
defaultOptions: <CodeBlockOptions>{
languageClassPrefix: 'language-',
2020-10-22 18:34:49 +08:00
},
content: 'text*',
marks: '',
group: 'block',
code: true,
defining: true,
addAttributes() {
return {
2020-09-27 02:20:52 +08:00
language: {
default: null,
2020-10-27 21:53:23 +08:00
parseHTML: element => {
const classAttribute = element.firstElementChild?.getAttribute('class')
if (!classAttribute) {
return null
}
const regexLanguageClassPrefix = new RegExp(`^(${this.options.languageClassPrefix})`)
return {
language: classAttribute.replace(regexLanguageClassPrefix, ''),
}
},
renderHTML: attributes => {
if (!attributes.language) {
return null
}
return {
class: this.options.languageClassPrefix + attributes.language,
}
},
2020-09-27 02:20:52 +08:00
},
2020-10-22 18:34:49 +08:00
}
},
parseHTML() {
return [
2020-09-30 22:25:32 +08:00
{
tag: 'pre',
preserveWhitespace: 'full',
},
2020-10-22 18:34:49 +08:00
]
},
2020-10-27 21:53:23 +08:00
renderHTML({ attributes }) {
return ['pre', ['code', attributes, 0]]
2020-10-22 18:34:49 +08:00
},
addCommands() {
return {
2020-10-23 04:40:40 +08:00
codeBlock: (attrs?: CodeBlockOptions): Command => ({ commands }) => {
2020-10-22 18:34:49 +08:00
return commands.toggleBlockType('code_block', 'paragraph', attrs)
},
}
},
addKeyboardShortcuts() {
return {
'Mod-Shift-c': () => this.editor.codeBlock(),
}
},
addInputRules() {
return [
textblockTypeInputRule(backtickInputRegex, this.type, ({ groups }: any) => groups),
textblockTypeInputRule(tildeInputRegex, this.type, ({ groups }: any) => groups),
]
},
})
2020-10-23 04:40:40 +08:00
export default CodeBlock
declare module '@tiptap/core/src/Editor' {
interface AllExtensions {
CodeBlock: typeof CodeBlock,
}
}