如何为Tiptap的extension-code-block-lowlight实现缩进功能?
解决方案
1. 自定义CodeBlockLowlight扩展,支持indent属性
扩展原插件,添加indent属性的解析与渲染逻辑,让pre标签能接收缩进相关的属性或样式:
import CodeBlockLowlight from '@tiptap/extension-code-block-lowlight' export const CustomCodeBlock = CodeBlockLowlight.extend({ addAttributes() { return { ...this.parent(), indent: { default: 0, parseHTML: (element) => parseInt(element.getAttribute('data-indent')) || 0, renderHTML: (attributes) => { if (!attributes.indent) return {} // 可选:用data属性配合CSS,或直接写内联样式 return { 'data-indent': attributes.indent, style: `padding-left: ${attributes.indent * 2}em;` } } } } }, renderHTML({ node, HTMLAttributes }) { const { indent, ...restAttrs } = HTMLAttributes const preAttrs = { ...restAttrs, ...(indent ? { 'data-indent': indent, style: `padding-left: ${indent * 2}em;` } : {}) } return [ 'pre', preAttrs, [ 'code', { class: `language-${node.attrs.language || 'plaintext'}` }, 0 ] ] } })
2. 重写Indent命令,支持CodeBlock节点
默认Indent命令仅处理段落,需要扩展命令逻辑,让它能识别并更新CodeBlock的indent属性:
import { indent as DefaultIndent } from '@tiptap/core' export const CustomIndent = DefaultIndent.extend({ addCommands() { return { indent: () => ({ chain }) => { return chain() .updateAttributes( (node) => ['paragraph', 'codeBlock'].includes(node.type.name), { indent: (node.attrs.indent || 0) + 1 } ) .run() }, outdent: () => ({ chain }) => { return chain() .updateAttributes( (node) => ['paragraph', 'codeBlock'].includes(node.type.name), { indent: Math.max((node.attrs.indent || 0) - 1, 0) } ) .run() } } } })
3. 配置Tiptap实例
替换原插件和命令,在编辑器配置中引入自定义的CodeBlock和Indent:
import { Editor } from '@tiptap/core' import { CustomCodeBlock } from './CustomCodeBlock' import { CustomIndent } from './CustomIndent' import { lowlight } from 'lowlight' const editor = new Editor({ extensions: [ CustomCodeBlock.configure({ lowlight }), CustomIndent.configure({ types: ['paragraph', 'codeBlock'] }), // 其他扩展... ], // 编辑器配置... })
4. 补充CSS样式(可选)
如果使用data-indent属性而非内联样式,添加CSS控制缩进:
pre[data-indent] { --indent-step: 2em; /* 可自定义缩进步长 */ padding-left: calc(var(--indent-step) * attr(data-indent number)); }
关键说明
之前直接在Indent配置的types中添加codeBlock无效,是因为:
- 默认Indent命令仅针对单一节点(如
<p>)设计,未处理CodeBlock这种嵌套节点(<pre><code></code></pre>)的属性更新逻辑 - 需要通过扩展CodeBlock的属性定义,同时重写Indent命令的节点匹配与属性更新逻辑,才能让缩进功能作用于代码块
内容的提问来源于stack exchange,提问作者seungyong
相关产品推荐
相关产品推荐

