@tiptap/extension-code-block
Version:
code block extension for tiptap
1 lines • 20.6 kB
Source Map (JSON)
{"version":3,"sources":["../src/index.ts","../src/code-block.ts"],"sourcesContent":["import { CodeBlock } from './code-block.js'\n\nexport * from './code-block.js'\n\nexport default CodeBlock\n","import { mergeAttributes, Node, textblockTypeInputRule } from '@tiptap/core'\nimport { Plugin, PluginKey, Selection, TextSelection } from '@tiptap/pm/state'\n\nconst DEFAULT_TAB_SIZE = 4\n\nexport interface CodeBlockOptions {\n /**\n * Adds a prefix to language classes that are applied to code tags.\n * @default 'language-'\n */\n languageClassPrefix: string | null | undefined\n /**\n * Define whether the node should be exited on triple enter.\n * @default true\n */\n exitOnTripleEnter: boolean | null | undefined\n /**\n * Define whether the node should be exited on arrow down if there is no node after it.\n * @default true\n */\n exitOnArrowDown: boolean | null | undefined\n /**\n * The default language.\n * @default null\n * @example 'js'\n */\n defaultLanguage: string | null | undefined\n /**\n * Enable tab key for indentation in code blocks.\n * @default false\n */\n enableTabIndentation: boolean | null | undefined\n /**\n * The number of spaces to use for tab indentation.\n * @default 4\n */\n tabSize: number | null | undefined\n /**\n * Custom HTML attributes that should be added to the rendered HTML tag.\n * @default {}\n * @example { class: 'foo' }\n */\n HTMLAttributes: Record<string, any>\n}\n\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n codeBlock: {\n /**\n * Set a code block\n * @param attributes Code block attributes\n * @example editor.commands.setCodeBlock({ language: 'javascript' })\n */\n setCodeBlock: (attributes?: { language: string }) => ReturnType\n /**\n * Toggle a code block\n * @param attributes Code block attributes\n * @example editor.commands.toggleCodeBlock({ language: 'javascript' })\n */\n toggleCodeBlock: (attributes?: { language: string }) => ReturnType\n }\n }\n}\n\n/**\n * Matches a code block with backticks.\n */\nexport const backtickInputRegex = /^```([a-z]+)?[\\s\\n]$/\n\n/**\n * Matches a code block with tildes.\n */\nexport const tildeInputRegex = /^~~~([a-z]+)?[\\s\\n]$/\n\n/**\n * This extension allows you to create code blocks.\n * @see https://tiptap.dev/api/nodes/code-block\n */\nexport const CodeBlock = Node.create<CodeBlockOptions>({\n name: 'codeBlock',\n\n addOptions() {\n return {\n languageClassPrefix: 'language-',\n exitOnTripleEnter: true,\n exitOnArrowDown: true,\n defaultLanguage: null,\n enableTabIndentation: false,\n tabSize: DEFAULT_TAB_SIZE,\n HTMLAttributes: {},\n }\n },\n\n content: 'text*',\n\n marks: '',\n\n group: 'block',\n\n code: true,\n\n defining: true,\n\n addAttributes() {\n return {\n language: {\n default: this.options.defaultLanguage,\n parseHTML: element => {\n const { languageClassPrefix } = this.options\n\n if (!languageClassPrefix) {\n return null\n }\n\n const classNames = [...(element.firstElementChild?.classList || [])]\n const languages = classNames\n .filter(className => className.startsWith(languageClassPrefix))\n .map(className => className.replace(languageClassPrefix, ''))\n const language = languages[0]\n\n if (!language) {\n return null\n }\n\n return language\n },\n rendered: false,\n },\n }\n },\n\n parseHTML() {\n return [\n {\n tag: 'pre',\n preserveWhitespace: 'full',\n },\n ]\n },\n\n renderHTML({ node, HTMLAttributes }) {\n return [\n 'pre',\n mergeAttributes(this.options.HTMLAttributes, HTMLAttributes),\n [\n 'code',\n {\n class: node.attrs.language ? this.options.languageClassPrefix + node.attrs.language : null,\n },\n 0,\n ],\n ]\n },\n\n markdownTokenName: 'code',\n\n parseMarkdown: (token, helpers) => {\n if (token.raw?.startsWith('```') === false && token.codeBlockStyle !== 'indented') {\n return []\n }\n\n return helpers.createNode(\n 'codeBlock',\n { language: token.lang || null },\n token.text ? [helpers.createTextNode(token.text)] : [],\n )\n },\n\n renderMarkdown: (node, h) => {\n let output = ''\n const language = node.attrs?.language || ''\n\n if (!node.content) {\n output = `\\`\\`\\`${language}\\n\\n\\`\\`\\``\n } else {\n const lines = [`\\`\\`\\`${language}`, h.renderChildren(node.content), '```']\n output = lines.join('\\n')\n }\n\n return output\n },\n\n addCommands() {\n return {\n setCodeBlock:\n attributes =>\n ({ commands }) => {\n return commands.setNode(this.name, attributes)\n },\n toggleCodeBlock:\n attributes =>\n ({ commands }) => {\n return commands.toggleNode(this.name, 'paragraph', attributes)\n },\n }\n },\n\n addKeyboardShortcuts() {\n return {\n 'Mod-Alt-c': () => this.editor.commands.toggleCodeBlock(),\n\n // remove code block when at start of document or code block is empty\n Backspace: () => {\n const { empty, $anchor } = this.editor.state.selection\n const isAtStart = $anchor.pos === 1\n\n if (!empty || $anchor.parent.type.name !== this.name) {\n return false\n }\n\n if (isAtStart || !$anchor.parent.textContent.length) {\n return this.editor.commands.clearNodes()\n }\n\n return false\n },\n\n // handle tab indentation\n Tab: ({ editor }) => {\n if (!this.options.enableTabIndentation) {\n return false\n }\n\n const tabSize = this.options.tabSize ?? DEFAULT_TAB_SIZE\n const { state } = editor\n const { selection } = state\n const { $from, empty } = selection\n\n if ($from.parent.type !== this.type) {\n return false\n }\n\n const indent = ' '.repeat(tabSize)\n\n if (empty) {\n return editor.commands.insertContent(indent)\n }\n\n return editor.commands.command(({ tr }) => {\n const { from, to } = selection\n const text = state.doc.textBetween(from, to, '\\n', '\\n')\n const lines = text.split('\\n')\n const indentedText = lines.map(line => indent + line).join('\\n')\n\n tr.replaceWith(from, to, state.schema.text(indentedText))\n return true\n })\n },\n\n // handle shift+tab reverse indentation\n 'Shift-Tab': ({ editor }) => {\n if (!this.options.enableTabIndentation) {\n return false\n }\n\n const tabSize = this.options.tabSize ?? DEFAULT_TAB_SIZE\n const { state } = editor\n const { selection } = state\n const { $from, empty } = selection\n\n if ($from.parent.type !== this.type) {\n return false\n }\n\n if (empty) {\n return editor.commands.command(({ tr }) => {\n const { pos } = $from\n const codeBlockStart = $from.start()\n const codeBlockEnd = $from.end()\n\n const allText = state.doc.textBetween(codeBlockStart, codeBlockEnd, '\\n', '\\n')\n const lines = allText.split('\\n')\n\n let currentLineIndex = 0\n let charCount = 0\n const relativeCursorPos = pos - codeBlockStart\n\n for (let i = 0; i < lines.length; i += 1) {\n if (charCount + lines[i].length >= relativeCursorPos) {\n currentLineIndex = i\n break\n }\n charCount += lines[i].length + 1\n }\n\n const currentLine = lines[currentLineIndex]\n const leadingSpaces = currentLine.match(/^ */)?.[0] || ''\n const spacesToRemove = Math.min(leadingSpaces.length, tabSize)\n\n if (spacesToRemove === 0) {\n return true\n }\n\n let lineStartPos = codeBlockStart\n for (let i = 0; i < currentLineIndex; i += 1) {\n lineStartPos += lines[i].length + 1\n }\n\n tr.delete(lineStartPos, lineStartPos + spacesToRemove)\n\n const cursorPosInLine = pos - lineStartPos\n if (cursorPosInLine <= spacesToRemove) {\n tr.setSelection(TextSelection.create(tr.doc, lineStartPos))\n }\n\n return true\n })\n }\n\n return editor.commands.command(({ tr }) => {\n const { from, to } = selection\n const text = state.doc.textBetween(from, to, '\\n', '\\n')\n const lines = text.split('\\n')\n const reverseIndentText = lines\n .map(line => {\n const leadingSpaces = line.match(/^ */)?.[0] || ''\n const spacesToRemove = Math.min(leadingSpaces.length, tabSize)\n return line.slice(spacesToRemove)\n })\n .join('\\n')\n\n tr.replaceWith(from, to, state.schema.text(reverseIndentText))\n return true\n })\n },\n\n // exit node on triple enter\n Enter: ({ editor }) => {\n if (!this.options.exitOnTripleEnter) {\n return false\n }\n\n const { state } = editor\n const { selection } = state\n const { $from, empty } = selection\n\n if (!empty || $from.parent.type !== this.type) {\n return false\n }\n\n const isAtEnd = $from.parentOffset === $from.parent.nodeSize - 2\n const endsWithDoubleNewline = $from.parent.textContent.endsWith('\\n\\n')\n\n if (!isAtEnd || !endsWithDoubleNewline) {\n return false\n }\n\n return editor\n .chain()\n .command(({ tr }) => {\n tr.delete($from.pos - 2, $from.pos)\n\n return true\n })\n .exitCode()\n .run()\n },\n\n // exit node on arrow down\n ArrowDown: ({ editor }) => {\n if (!this.options.exitOnArrowDown) {\n return false\n }\n\n const { state } = editor\n const { selection, doc } = state\n const { $from, empty } = selection\n\n if (!empty || $from.parent.type !== this.type) {\n return false\n }\n\n const isAtEnd = $from.parentOffset === $from.parent.nodeSize - 2\n\n if (!isAtEnd) {\n return false\n }\n\n const after = $from.after()\n\n if (after === undefined) {\n return false\n }\n\n const nodeAfter = doc.nodeAt(after)\n\n if (nodeAfter) {\n return editor.commands.command(({ tr }) => {\n tr.setSelection(Selection.near(doc.resolve(after)))\n return true\n })\n }\n\n return editor.commands.exitCode()\n },\n }\n },\n\n addInputRules() {\n return [\n textblockTypeInputRule({\n find: backtickInputRegex,\n type: this.type,\n getAttributes: match => ({\n language: match[1],\n }),\n }),\n textblockTypeInputRule({\n find: tildeInputRegex,\n type: this.type,\n getAttributes: match => ({\n language: match[1],\n }),\n }),\n ]\n },\n\n addProseMirrorPlugins() {\n return [\n // this plugin creates a code block for pasted content from VS Code\n // we can also detect the copied code language\n new Plugin({\n key: new PluginKey('codeBlockVSCodeHandler'),\n props: {\n handlePaste: (view, event) => {\n if (!event.clipboardData) {\n return false\n }\n\n // don’t create a new code block within code blocks\n if (this.editor.isActive(this.type.name)) {\n return false\n }\n\n const text = event.clipboardData.getData('text/plain')\n const vscode = event.clipboardData.getData('vscode-editor-data')\n const vscodeData = vscode ? JSON.parse(vscode) : undefined\n const language = vscodeData?.mode\n\n if (!text || !language) {\n return false\n }\n\n const { tr, schema } = view.state\n\n // prepare a text node\n // strip carriage return chars from text pasted as code\n // see: https://github.com/ProseMirror/prosemirror-view/commit/a50a6bcceb4ce52ac8fcc6162488d8875613aacd\n const textNode = schema.text(text.replace(/\\r\\n?/g, '\\n'))\n\n // create a code block with the text node\n // replace selection with the code block\n tr.replaceSelectionWith(this.type.create({ language }, textNode))\n\n if (tr.selection.$from.parent.type !== this.type) {\n // put cursor inside the newly created code block\n tr.setSelection(TextSelection.near(tr.doc.resolve(Math.max(0, tr.selection.from - 2))))\n }\n\n // store meta information\n // this is useful for other plugins that depends on the paste event\n // like the paste rule plugin\n tr.setMeta('paste', true)\n\n view.dispatch(tr)\n\n return true\n },\n },\n }),\n ]\n },\n})\n"],"mappings":"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","names":["_a"]}