hexo-blog-encrypt 插件无法加密很多主题的文章目录,我使用的 hexo-theme-yun 也是如此。这篇文章记录了如何解决这个问题。
Demo:
在 hexo-theme-yun 主题上最新的一个 issue 里面提到的就是这个问题。
对于这个问题的解决,在 hexo-blog-encrypt 插件的 readme 里面已经提到了一些关于加密目录的解决方案,它需要修改主题的源代码,而且对于不同的主题,修改的地方也不一样。
对于 hexo-theme-yun 主题,在我研究了一个下午后,我的基本结论是:
hexo-theme-yun 主题无法使用 hexo-blog-encrypt 插件加密文章目录。
因为我发现 hexo-theme-yun 主题的文章目录是在 sidebar 里面的,而 hexo-blog-encrypt 插件加密的是文章内容,所以这个问题是无法解决的。
好吧,这确实是一个标题党的文章,下面记录一下我是如何
优雅解决这个问题的。
问题一:目录无法渲染
在研究代码的过程中,我发现对于设置的密码的文章,hexo-theme-yun 甚至无法正确渲染出文章的目录。
这是因为它使用 page.content
来渲染文章内容,而 hexo-blog-encrypt 插件会加密 page.content
,所以导致目录无法正确渲染。
- var toc_content = toc(page.content, {list_number: theme.toc.list_number, max_depth: theme.toc.max_depth, min_depth: theme.toc.min_depth})
要解决这个问题,我们需要使用 page.origin
来生成文章的目录。
这里我把它改成了首先判断是否加密,如果加密了就使用 page.origin
,否则使用 page.content
。
- var toc_content = page.encrypt ? toc(page.origin, {list_number: theme.toc.list_number, max_depth: theme.toc.max_depth, min_depth: theme.toc.min_depth}) : toc(page.content, {list_number: theme.toc.list_number, max_depth: theme.toc.max_depth, min_depth: theme.toc.min_depth})
改了这行代码,目录就可以正确渲染了。
问题二:目录无法隐藏
但是,这样做还是有一个问题,就是对于加密了的文章,目录无法正确隐藏。
可以从代码里面看出如果目录里面有内容,就会直接显示目录。
if display_toc
#post-toc-wrap.sidebar-panel(class=toc_content.length > 1 ? 'sidebar-panel-active' : '')
.post-toc
.post-toc-content
!= toc_content.length > 1 ? toc_content : theme.toc.placeholder || __('post.toc_empty')
因为目录本身不会被加密,为了实现加密的效果,在生成目录时判断文章是否加密,如果是加密了的文章就用 CSS 的方式把目录隐藏起来。
然后再通过 JS 脚本来监听解密事件,解密后再把目录的 CSS 样式改成显示。
if display_toc
#post-toc-wrap.sidebar-panel(class=toc_content.length > 1 ? 'sidebar-panel-active' : '')
.post-toc
.post-toc-content
if page.encrypt
#toc-div(style="display:none")
!= toc(page.origin, {list_number: theme.toc.list_number, max_depth: theme.toc.max_depth, min_depth: theme.toc.min_depth})
script.
window.addEventListener('hexo-blog-decrypt', function() {
var tocDiv = document.getElementById('toc-div');
if (tocDiv) {
tocDiv.style.display = 'block';
}
});
else
!= toc_content.length > 1 ? toc_content : theme.toc.placeholder || __('post.toc_empty')
这样就可以实现目录的隐藏和显示了。
sidebar-panel-active 的优化
在 hexo-theme-yun 主题的 sidebar 里面,如果目录有内容,那么目录就是 active 的,如果目录没有内容,那么信息页就是 active 的。
在我的这个加密方法里面,目录内容实际上是存在的,只是被 CSS 隐藏了,所以对于加密了的文章,进入文章页后,目录页是 active 的,但却是空空如也。
所以这里我们需要优化一下 sidebar 的 active 逻辑,改为 如果目录有内容且文章没有加密,那么目录页是 active 的。
否则,信息页是 active 的。
if display_toc
ul.sidebar-nav
li.sidebar-nav-item.sidebar-nav-toc.hty-icon-button(data-target='post-toc-wrap', title=__('sidebar.toc'), class=(toc_content && !page.encrypt) ? 'sidebar-nav-active' : '')
+icon('ri:list-ordered')
li.sidebar-nav-item.sidebar-nav-overview.hty-icon-button(data-target='site-overview-wrap', title=__('sidebar.overview'), class=(toc_content && !page.encrypt) ? '' : 'sidebar-nav-active')
+icon('ri:passport-line')
...
#post-toc-wrap.sidebar-panel(class=(toc_content.length <= 1 || page.encrypt) ? '' : 'sidebar-panel-active')
完整的 patch
完整的修改如下:
diff --git a/themes/hexo-theme-yun/layout/_partial/sidebar.pug b/themes/hexo-theme-yun/layout/_partial/sidebar.pug
index b4214d8..435ebd6 100755
--- a/themes/hexo-theme-yun/layout/_partial/sidebar.pug
+++ b/themes/hexo-theme-yun/layout/_partial/sidebar.pug
@@ -11,15 +11,16 @@ aside.sidebar
//- can not be async
//- https://stackoverflow.com/questions/9237044/async-loaded-scripts-with-domcontentloaded-or-load-event-handlers-not-being-call
script(src=url_for(theme.cdn.pre + '/js/sidebar.js'), type='module')
- - var toc_content = toc(page.content, {list_number: theme.toc.list_number, max_depth: theme.toc.max_depth, min_depth: theme.toc.min_depth})
+ - var toc_content = page.encrypt ? toc(page.origin, {list_number: theme.toc.list_number, max_depth: theme.toc.max_depth, min_depth: theme.toc.min_depth}) : toc(page.content, {list_number: theme.toc.list_number, max_depth: theme.toc.max_depth, min_depth: theme.toc.min_depth})
if display_toc
ul.sidebar-nav
- li.sidebar-nav-item.sidebar-nav-toc.hty-icon-button(data-target='post-toc-wrap', title=__('sidebar.toc'), class=toc_content ? 'sidebar-nav-active' : '')
+ li.sidebar-nav-item.sidebar-nav-toc.hty-icon-button(data-target='post-toc-wrap', title=__('sidebar.toc'), class=(toc_content && !page.encrypt) ? 'sidebar-nav-active' : '')
+icon('ri:list-ordered')
- li.sidebar-nav-item.sidebar-nav-overview.hty-icon-button(data-target='site-overview-wrap', title=__('sidebar.overview'), class=toc_content ? '' : 'sidebar-nav-active')
+ li.sidebar-nav-item.sidebar-nav-overview.hty-icon-button(data-target='site-overview-wrap', title=__('sidebar.overview'), class=(toc_content && !page.encrypt) ? '' : 'sidebar-nav-active')
+icon('ri:passport-line')
- #site-overview-wrap.sidebar-panel(class=display_toc && toc_content.length > 1 ? '' : 'sidebar-panel-active')
+ #site-overview-wrap.sidebar-panel(class=(display_toc && toc_content.length > 1 && !page.encrypt) ? '' : 'sidebar-panel-active')
include ./sidebar/info.pug
nav.site-state
@@ -92,12 +93,28 @@ aside.sidebar
a#toggle-mode-btn.links-item.hty-icon-button(href='javascript:;' title="Mode" style='color: #f1cb64')
+icon('ri:contrast-2-line')
if display_toc
- #post-toc-wrap.sidebar-panel(class=toc_content.length > 1 ? 'sidebar-panel-active' : '')
+ #post-toc-wrap.sidebar-panel(class=(toc_content.length <= 1 || page.encrypt) ? '' : 'sidebar-panel-active')
.post-toc
.post-toc-content
- != toc_content.length > 1 ? toc_content : theme.toc.placeholder || __('post.toc_empty')
-
+ if page.encrypt
+ #toc-div(style="display:none")
+ != toc(page.origin, {list_number: theme.toc.list_number, max_depth: theme.toc.max_depth, min_depth: theme.toc.min_depth})
+ script.
+ window.addEventListener('hexo-blog-decrypt', function() {
+ var tocDiv = document.getElementById('toc-div');
+ if (tocDiv) {
+ tocDiv.style.display = 'block';
+ }
+ });
+ else
+ != toc_content.length > 1 ? toc_content : theme.toc.placeholder || __('post.toc_empty')
+
if theme.sidebar.tagcloud.enable
.tag-cloud
- var start_color = theme.colors.tag_start_color || '#333'
其他已知问题
这样修改之后,目录的隐藏和显示已经可以正常工作了,但是还有一个问题,就是在正确输入密码之后,虽然目录可以显示出来,但是无法实现点击目录跳转到对应的位置。
需要手动刷新页面,然后这个目录就能正常工作了。
关于 hexo-blog-encrypt 插件目前我还发现了一个问题,就是解密后的文章图片没有办法点击放大查看,这个问题我还没有解决。
By The Way
这个博客主题我已经使用了 4 年。主题的作者开发了一个基于 Vue 的新博客框架,名为 Valaxy。我原计划在 2025 年逐步迁移到这个新框架,希望 Valaxy 的加密功能能解决 Hexo 中遇到的问题,但尚未进行实际测试。
经过这个周末的研究,我修复了 Hexo 加密插件与 Dplayer 以及博客目录之间的冲突,因此迁移的紧迫性也不再那么强烈了。
让它再开发一会儿吧。