You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 15:34:58