d0n9x1n/hexo-blog-encrypt/hexo-encrypt-toc
- community
Checking that the SKILL.md file is still in the repository.
Patches any Hexo theme so its table of contents works with hexo-blog-encrypt without leaking encrypted headings. Use when a theme shows an empty, hidden, or plaintext TOC on password-protected posts, when installing hexo-blog-encrypt on a theme with a TOC, or when asked to "fix TOC for encrypted posts". Do NOT use for themes with no TOC, or for changing the encryption plugin itself.
Install
npx vskill@latest install d0n9x1n/hexo-blog-encrypt/hexo-encrypt-tocSKILL.md
Encrypted-post TOC for any Hexo theme
hexo-blog-encrypt replaces page.content with ciphertext in an after_post_render filter, sets page.encrypt = true, and keeps the plaintext in page.origin. After the reader decrypts, it swaps in the post as #hexo-blog-encrypt.hbe-decrypted-content and dispatches hexo-blog-decrypt on window.
That breaks theme TOCs in one of three ways:
| Symptom | Cause | Risk | |
|---|---|---|---|
| TOC empty or missing | toc(page.content) sees ciphertext | Cosmetic | |
| TOC visible on the locked page | toc(page.origin) rendered | Plaintext headings published | |
| TOC hidden, appears after decrypt | toc(page.origin) with display:none | Plaintext headings published (view source) |
The goal is always the same: no encrypted heading in the generated HTML, and a working TOC after decryption. This procedure works for any theme; the per-theme notes in Per-theme examples are examples, not a whitelist. Everything the procedure needs is in this one file: the builder script is Appendix A and the leak checker is Appendix B.
1. Locate the TOC
Run from the Hexo site root. Include theme packages installed from npm.
Also search component packages the theme depends on (for example Icarus renders its TOC from hexo-component-inferno).
Classify every hit:
- Server TOC: a template calls
toc(...)(ejs, njk, pug, jsx, swig). - Client TOC: JavaScript scans headings in the DOM (tocbot, a custom
querySelectorAll('h1,h2,…'), or a theme initTOC function).
- Theme-native encryption: the theme has its own
passwordhandling or
bundles a copy of hexo-blog-encrypt. Resolve this first (see step 5).
Record the TOC container selector, the class passed to toc() (default toc), and the function that starts scrollspy or highlighting.
2. Remove every plaintext source
In each server template:
- Delete any
toc(page.origin),toc(post.origin), or equivalent. - Guard the remaining call with the encrypt flag and **still output the empty
container**, because many themes drop the sidebar panel when the TOC is empty:
Nunjucks: {% if not page.encrypt %}…{% endif %}. Pug: if !page.encrypt with the container outside the branch. JSX: pass '' instead of origin.
Also check head templates for open_graph() and meta descriptions, and search, feed, and sitemap generator configs for fields that read origin, raw, or _content.
3. Rebuild the TOC after decryption
Prefer the theme's own initializer. Otherwise use the generic builder.
Client TOC (tocbot style). Make sure the decrypted node is inside the scanner's content selector, then refresh:
Server TOC. Write the builder from Appendix A to themes/$THEME/source/js/hbe-toc.js (or the theme's equivalent asset folder) and load it on post pages after the theme's own scripts:
The builder emits the same markup as Hexo's toc() helper, so theme CSS applies. It reads heading text with textContent and never innerHTML. It runs on the decrypt event and once on load, which covers autoSave pages that decrypt from a cached key before the theme's script runs.
Event rules for any custom handler:
- Do not depend on
event.detail; some forks dispatch a plainEvent. - Also check for
#hexo-blog-encrypt.hbe-decrypted-contentat load time. - On PJAX themes, re-run the handler after each page swap.
4. Verify
The checker reads every post with a front-matter password, extracts its Markdown headings (code fences skipped, headings shorter than 4 characters ignored), and searches all generated .html, .xml, .json, .txt, and .js files. Pass tag-encrypted posts explicitly with --post <file>. Add --body to also check every prose line of 40+ characters (search indexes, feeds, metadata). Exit code 1 means a leak; fix it before deploying. A heading that also appears in an unencrypted post is a false positive; confirm by viewing source.
Then in a browser:
- Open an encrypted post: the TOC is empty or hidden, and view-source shows no
headings.
- Enter the password: the TOC appears, links scroll to headings, scrollspy
highlights the current section.
- With
autoSave: true, reload: the TOC appears without a password. - Open an unencrypted post: the TOC is unchanged.
5. Pitfalls
- Theme-native encryption (for example Keep's
passwordfilter, or
Redefine's bundled copy of hexo-blog-encrypt): use one system. With both, posts can be encrypted twice or the plugin's form never renders. Remove or disable the theme's copy, or don't install the plugin.
- Hidden is not secret.
display:none,hidden, and CSS-only tricks still
publish headings.
- Stale hooks. Themes written for plugin v3 may wait for elements that v4
no longer outputs (for example hbe-prefix). Replace them with the hexo-blog-decrypt listener.
- Theme updates overwrite edits in
themes/<name>. Prefer the theme's
override mechanism (source/_data, injectors, custom layouts) or record the patch so it can be re-applied.
Report back
State the theme and version, the files changed, the checker's output, and the browser checks you ran. Say which checks you could not run.
Per-theme examples
Examples gathered from each theme's default branch on 2026-10-12. Line numbers drift; re-run the step 1 search before editing. Themes not listed here use the same procedure.
| Theme | TOC source | Type | Leaks today? | Re-init after decrypt | |
|---|---|---|---|---|---|
| NexT | layout/_macro/sidebar.njk toc(page.content, {class: 'nav'}) | Server | No (empty) | NexT.utils.registerSidebarTOC(), NexT.utils.activateSidebarPanel(0) | |
| Butterfly | layout/includes/widget/card_post_toc.pug | Server | Yes, hidden toc(page.origin) | Build into #card-toc .toc-content before the theme's own hexo-blog-decrypt listener runs forPostFn() | |
| AnZhiYu | layout/includes/widget/card_post_toc.pug | Server | Yes, hidden toc(page.origin) | Build into #card-toc .toc-content, then call the theme's scrollFnToDo() | |
| Fluid | layout/_partials/post/toc.ejs | Client (tocbot, .markdown-body) | No | Add markdown-body to #hexo-blog-encrypt, then Fluid.boot.refresh(). The theme's hbe-prefix hook is from plugin v3 and never fires | |
| Icarus | hexo-component-inferno src/view/widget/toc.jsx | Server | Yes, visible encrypt ? origin : content | Override the widget to pass '' when encrypted; build ul.menu-list and reload /js/toc.js | |
| Stellar | layout/_partial/widgets/toc.ejs | Server + client rebuild | No | Output an empty nav.toc, then dispatch stellar:mdrender on document | |
| Redefine | layout/pages/post/toc.ejs | Server | No | Remove the theme's bundled copy of the plugin first; fill .post-toc and dispatch redefine:page:refresh | |
| Volantis | layout/_widget/toc.ejs | Server | Yes, hidden page.encrypt ? page.origin : page.content | Render an empty #toc-div .content, build, then listenSidebarTOC() | |
| Matery | layout/_partial/post-detail-toc.ejs | Client (tocbot, #articleContent) | No | tocbot.refresh() | |
| Keep | layout/_partial/toc.ejs | Server | No, but has its own password encryption | Choose one encryption system; then fill .post-toc and call KEEP.initTOC() | |
| Shoka | layout/_macro/sidebar.njk | Server | No | Output an empty .contents panel; build ol.toc; call sidebarTOC() | |
| Cactus | layout/_partial/post/actions_desktop.ejs, actions_mobile.ejs | Server | No | Always output an empty #toc; fill it. No scrollspy | |
| Landscape | none | — | No | Nothing to do |
Notes
- `class` option. NexT, Keep, and Redefine call
toc()with
class: 'nav'. Set window.HBE_TOC.className = 'nav' so their CSS and scrollspy selectors match.
- Closure-scoped initializers. Butterfly and AnZhiYu keep their scrollspy
inside main.js. Either build the TOC before their own decrypt listener runs, or expose the function with a one-line edit.
- Hidden-origin pattern. Any template that renders
origininside a
hidden container publishes the headings. Replace it with an empty container and the builder; do not keep the hidden copy.
Appendix A: hbe-toc.js
Theme-agnostic TOC builder. Write this block verbatim to the theme's JavaScript folder.
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 100 of 100Pattern checks on the skill's files.
- Model reviewNot runA model review is scheduled for the next rescan.
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingskills/hexo-encrypt-toc/SKILL.md
Popularity
- Repository stars
- 1,052
- Repository forks
- 108
- 7-day trend score
- 0
Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/d0n9x1n/hexo-blog-encrypt/hexo-encrypt-toc)