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

如何用纯Jinja2实现Markdown文档的二级编号(1、2a格式)

纯Jinja2实现Markdown二级自动编号解决方案

问题根源分析

你之前的两个方案存在三个核心问题:

  1. 变量作用域限制:Jinja2宏内部的{% set %}默认创建局部变量,无法修改外部定义的number和sub_number,导致主编号始终不递增,子编号逻辑完全混乱。
  2. 依赖Python内置函数:方案2中使用的chr()/ord()并非Jinja2默认提供的工具,直接调用会报错。
  3. 子编号转换逻辑错误:方案1中把字符'a'转为整数会得到0,后续递增后变成数字字符串,完全偏离字母子编号的需求。

标准解决方案(区分一级/二级标题)

使用Jinja2的namespace对象维护全局状态,配合字母列表实现纯Jinja2的子编号递增,无需依赖外部函数。

完整实现代码

{% set ns = namespace(main_num=1, sub_idx=0, letters=['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']) %}

{# 生成一级编号(如1、3) #}
{% macro main_heading() -%}
  {{ ns.main_num }}
  {%- set ns.main_num = ns.main_num + 1 %}
  {%- set ns.sub_idx = 0 %} {# 重置子编号索引 #}
{%- endmacro %}

{# 生成二级编号(如2a、2b、4a) #}
{% macro sub_heading() -%}
  {{ ns.main_num - 1 }}{{ ns.letters[ns.sub_idx] }}
  {%- set ns.sub_idx = ns.sub_idx + 1 %}
  {# 子编号到z后,自动递增主编号并重置子索引 #}
  {%- if ns.sub_idx >= ns.letters|length %}
    {%- set ns.main_num = ns.main_num + 1 %}
    {%- set ns.sub_idx = 0 %}
  {%- endif %}
{%- endmacro %}

调用示例

# {{ main_heading() }} 一级标题1
## {{ sub_heading() }} 二级标题2a
## {{ sub_heading() }} 二级标题2b
## {{ sub_heading() }} 二级标题2c
# {{ main_heading() }} 一级标题3
## {{ sub_heading() }} 二级标题4a

渲染结果

# 1 一级标题1
## 2a 二级标题2a
## 2b 二级标题2b
## 2c 二级标题2c
# 3 一级标题3
## 4a 二级标题4a

混合编号实现(自动切换1、2a、2b、3、4a格式)

如果需要无需手动区分一级/二级,自动生成混合编号,可使用以下逻辑:

完整实现代码

{% set ns = namespace(current_main=1, sub_idx=-1, letters=['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']) %}

{% macro auto_number() -%}
  {%- if ns.sub_idx == -1 %}
    {# 生成主编号 #}
    {{ ns.current_main }}
    {%- set ns.sub_idx = 0 %}
  {%- else %}
    {# 生成二级编号 #}
    {{ ns.current_main }}{{ ns.letters[ns.sub_idx] }}
    {%- set ns.sub_idx = ns.sub_idx + 1 %}
    {# 子编号到z后切换主编号 #}
    {%- if ns.sub_idx >= ns.letters|length %}
      {%- set ns.current_main = ns.current_main + 1 %}
      {%- set ns.sub_idx = -1 %}
    {%- endif %}
  {%- endif %}
{%- endmacro %}

{# 手动切换到下一个主编号(用于提前结束子编号组) #}
{% macro next_main() -%}
  {%- set ns.current_main = ns.current_main + 1 %}
  {%- set ns.sub_idx = -1 %}
{%- endmacro %}

调用示例

## {{ auto_number() }} 标题1
## {{ auto_number() }} 标题2a
## {{ auto_number() }} 标题2b
## {{ auto_number() }} 标题2c
{{ next_main() }}
## {{ auto_number() }} 标题3
{{ next_main() }}
## {{ auto_number() }} 标题4a

渲染结果

## 1 标题1
## 2a 标题2a
## 2b 标题2b
## 2c 标题2c
## 3 标题3
## 4a 标题4a

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 03:20:28