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

使用nbconvert导出Jupyter Notebook为HTML时同时实现目录与输入单元格隐藏

解决Jupyter Notebook导出HTML时同时保留目录和隐藏输入单元格的问题

我之前也碰到过一模一样的问题——单独用html_toc导出目录正常,单独用隐藏代码模板也能隐藏输入,但两者结合就只剩单元格内容,目录直接消失了。核心原因是--template参数会直接覆盖html_toc的内置模板结构,导致目录所需的HTML结构、CSS和JS都没被渲染出来。下面是我亲测有效的解决思路和步骤:

核心思路:合并两个模板的功能

我们需要创建一个继承自html_toc的自定义模板,同时把隐藏输入单元格的逻辑加进去,这样就能同时保留目录和隐藏代码的功能。

步骤1:定位nbconvert模板的存放路径

首先找到你的Jupyter模板目录,执行以下命令:

jupyter --data-dir

输出的路径一般类似~/.local/share/jupyter(Linux/macOS)或者C:\Users\<你的用户名>\AppData\Roaming\jupyter(Windows)。进入这个路径下的nbconvert/templates文件夹,这是自定义模板的存放位置。

步骤2:创建自定义模板文件夹

在templates里新建一个文件夹,比如命名为html_toc_hidecode,然后在里面创建两个文件:

文件1:template.conf(用于继承html_toc模板)

内容如下:

[main]
extends = html_toc

这个文件告诉nbconvert,我们的新模板是基于内置的html_toc模板扩展的,这样目录功能会被保留。

文件2:index.html.j2(添加隐藏输入单元格的逻辑)

这个文件是模板的核心,我们需要修改输入单元格的渲染方式,同时可以添加切换显示/隐藏的按钮。内容如下:

{% extends 'html_toc/index.html.j2' %}

{% block header %}
{{ super() }}
<!-- 自定义CSS:默认隐藏输入单元格 -->
<style>
.input {
    display: none;
}
.show-input-btn {
    margin: 8px 0;
    padding: 4px 10px;
    border: 1px solid #ccc;
    border-radius: 4px;
    background-color: #f8f8f8;
    cursor: pointer;
}
.show-input-btn:hover {
    background-color: #e8e8e8;
}
</style>
<!-- 自定义JS:添加显示/隐藏输入的按钮 -->
<script>
document.addEventListener('DOMContentLoaded', function() {
    const inputBlocks = document.querySelectorAll('.input');
    inputBlocks.forEach(block => {
        const btn = document.createElement('button');
        btn.className = 'show-input-btn';
        btn.textContent = '显示输入代码';
        btn.onclick = () => {
            block.style.display = block.style.display === 'none' ? 'block' : 'none';
            btn.textContent = block.style.display === 'none' ? '显示输入代码' : '隐藏输入代码';
        };
        // 把按钮放到输入块的前面
        block.parentNode.insertBefore(btn, block);
    });
});
</script>
{% endblock header %}

{% block input %}
<!-- 修改输入单元格的渲染逻辑:默认隐藏 -->
<div class="input">
    <div class="prompt input_prompt"></div>
    <div class="input_area">
        {% for attachment in cell.attachments.values() %}
            <img src="{{ attachment['image/png'] }}" class="attachment" alt="attachment" />
        {% endfor %}
        {{ cell.source | highlight_code(cell.language) }}
    </div>
</div>
{% endblock input %}

如果你不想全局隐藏所有输入单元格,而是想通过单元格元数据控制,可以把{% block input %}部分改成:

{% block input %}
{% if cell.metadata.get('hide_input', True) %}
<div class="input" style="display:none;">
{% else %}
<div class="input">
{% endif %}
    <div class="prompt input_prompt">{% if not cell.metadata.get('hide_input', True) %}In [{% trans cell_index=cell.index %} {{ cell_index }} {% endtrans %}]:{% endif %}</div>
    <div class="input_area">
        {% for attachment in cell.attachments.values() %}
            <img src="{{ attachment['image/png'] }}" class="attachment" alt="attachment" />
        {% endfor %}
        {{ cell.source | highlight_code(cell.language) }}
    </div>
</div>
{% endblock input %}

这样的话,只有添加了"hide_input": true元数据的单元格才会被隐藏(你可以在Jupyter里右键单元格→“编辑元数据”来添加)。

步骤3:使用自定义模板导出

现在执行以下命令导出Notebook,就能同时得到目录和隐藏的输入单元格了:

jupyter nbconvert --to html --template html_toc_hidecode YOUR_NOTEBOOK.ipynb

注意这里用--to html而不是html_toc,因为我们的自定义模板已经继承了html_toc的目录功能。

额外提示

  • 如果你的隐藏代码模板有其他自定义样式(比如修改输出单元格样式),可以把对应的代码也复制到index.html.j2的对应块里,比如{% block output %}。
  • 导出后的HTML文件里,所有输入单元格默认隐藏,点击“显示输入代码”按钮就能展开查看代码,非常方便。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:11:24