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

Wagtail富文本编辑器代码块钩子问题:多行生成多个div

Wagtail富文本编辑器代码块钩子异常问题解决方向

问题现象

选中多行内容应用自定义代码块时,每行内容被单独包裹在<div class="code">标签内,而非整个选中区块用单个div包裹:

预期输出

<div class="code">
content line one 
content line two
</div>

实际输出

<div class="code">content line one </div>
<div class="code">content line two </div>

原钩子代码

@hooks.register('register_rich_text_features')
def register_py_code_block_feature(features):
    """
    Registering for adding python code block
    """
    feature_name = 'py-code-block'
    type_ = 'py-code-block'

    control = {
        'type': type_,
        'label': 'PY',
        'description': 'Python Code Block',        
        # Optionally, we can tell Draftail what element to use when displaying those blocks in the editor.
        'element': 'div',
        'style': {
            "display": "block",
        },
    }

    db_conversion = {
        'from_database_format': {'div': BlockElementHandler(type_)},
        'to_database_format': {'block_map': {type_: {
                                                        'element': 'div',
                                                        'props': {
                                                            'class': 'code blog_code language-python'
                                                            }
                                                    }
                                            }
                                },
        }

    features.register_editor_plugin('draftail', feature_name, draftail_features.BlockFeature(control)) 
    features.register_converter_rule('contentstate', feature_name, db_conversion)
    features.default_features.append('py-code-block')

解决方向

核心原因

Draftail的BlockFeature默认将每行文本视为独立块处理,同时原生的BlockElementHandler不会合并连续的同类型块元素。

具体修改方案

  1. 调整编辑器控件配置,允许块合并
    在control字典中添加merge属性并启用,同时设置样式保留换行格式:

    control = {
        'type': type_,
        'label': 'PY',
        'description': 'Python Code Block',        
        'element': 'div',
        'block': True,
        'merge': True,  # 允许连续的同类型块自动合并
        'style': {
            "display": "block",
            "white-space": "pre-wrap",  # 保留原始换行符格式
        },
    }
    
  2. 自定义块元素处理器,合并连续区块
    继承BlockElementHandler并重写处理逻辑,避免将连续的同类型div拆分成多个块:

    from wagtail.core.rich_text import BlockElementHandler
    
    class MergedBlockElementHandler(BlockElementHandler):
        def handle_starttag(self, attrs, state):
            # 检查当前是否已处于目标类型的块中,避免重复创建块
            if state.get('current_block_type') == self.block_type:
                return state
            return super().handle_starttag(attrs, state)
    
        def handle_endtag(self, state):
            # 记录当前块类型的结束状态
            state.pop('current_block_type', None)
            return super().handle_endtag(state)
    
    # 更新数据库转换配置中的处理器
    db_conversion = {
        'from_database_format': {'div': MergedBlockElementHandler(type_)},
        'to_database_format': {'block_map': {type_: {
                                                        'element': 'div',
                                                        'props': {
                                                            'class': 'code blog_code language-python'
                                                            }
                                                    }
                                            }
                                },
    }
    
  3. 处理编辑器文本拆分逻辑
    Draftail默认会将换行文本拆分为多个段落,应用代码块前可通过编辑器API将选中的多行文本合并为一个单一文本节点,确保代码块能包裹整个选中内容。

内容的提问来源于stack exchange,提问作者sherin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 15:52:40