Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: 自动解析TOC #27

Closed
BillYang2016 opened this issue Jan 5, 2018 · 24 comments
Closed

chore: 自动解析TOC #27

BillYang2016 opened this issue Jan 5, 2018 · 24 comments
Assignees

Comments

@BillYang2016
Copy link

Next主题边框经过加密后未正常显示。
hexo-encrypt插件存在相同问题。
经过测试,左/右边框均无法正常显示。

Expected Behavior

正常情况时,文章边框
应该随着滚轮滚动并显示文章目录与站点概览。

Actual Behavior

实际情况,并没有正常显示

Steps to Reproduce the Problem

  1. 点击进入问题页面
  2. 密码是123
  3. 对比右边框与其他文章右边框

Specifications

(The version of the project, operating system, hardware etc.)
Next主题:v5.1.4
hexo-blog-encrypt:v2.0.3

另:hexo-fs弃用提示DeprecationWarning: fs.SyncWriteStream is deprecated.仍存在。

@lmy98129
Copy link

lmy98129 commented Feb 17, 2018

6.x版本的next主题里面这个issue的方法貌似已经失效了,scheme中的Mist、Gemini均无法起作用,同求最新的解决方法。

@ghost
Copy link

ghost commented Feb 19, 2018

@MikeCoder 我这边用的的next6.0.4,也和楼上一样出现问题,求解决办法
附:next6.0版本https://github.com/theme-next/hexo-theme-next

@BillYang2016
Copy link
Author

是的,5.1.4与6.0.x版本的NexT主题#16的方法失效。

@xiazeyu
Copy link
Collaborator

xiazeyu commented Feb 19, 2018

\themes\next\layout\_macro\sidebar.swig 不知道NexT6的Sidebar是不是这个
可能需要重新获取一下div名称。
关于隐藏和显示加密文章的TOC我觉得可以在
https://github.com/xiazeyu/hexo-blog-encrypt/blob/master/lib/blog-encrypt.js
里实现。具体流程还需要想想。不知道有没有什么不需要改模板的方法。
关键问题是toc是hexo的模板引擎生成的...
引擎需要接收到未加密的内容,而最终呈现需要时加密的

@ghost
Copy link

ghost commented Feb 19, 2018

所以呢,你们有解决办法了?

@xiazeyu
Copy link
Collaborator

xiazeyu commented Feb 19, 2018

@wuhang2003
只是思路...旧的思路应该还是可以继续沿用的...

@ghost
Copy link

ghost commented Feb 19, 2018

我对比了一下,6.0.4较5.0多了一些东西。(左为5.0,右为6.0)






我感觉代码变动有点多,你们认为呢?

@ghost
Copy link

ghost commented Feb 19, 2018

@xiazeyu

@xiazeyu
Copy link
Collaborator

xiazeyu commented Feb 19, 2018

@wuhang2003
我觉得在Chrome的DOM Tree里找会..人性化一点
毕竟major update啊..估计样式都重写了
我最近可能没时间...反正有空慢慢看

@ghost
Copy link

ghost commented Feb 19, 2018

OK,等你的好消息

@xiazeyu xiazeyu changed the title Next主题边框未正常显示 chore: 自动解析TOC Feb 22, 2018
@ghost
Copy link

ghost commented Feb 22, 2018

@xiazeyu 有结果了吗?

@xiazeyu
Copy link
Collaborator

xiazeyu commented Feb 22, 2018

关键是在什么时候加密
现在我有3种思路

  • 第一种还是原来的,在生成html前加密,但是需要手动修改模板。
    优点:简单易行
    缺点:需要手动修改模板,TOC会泄密
  • 第二种是在生成html前做标记,生成完毕再解析html完成加密。但是如果你使用searchdb会在搜索里泄漏原文
    优点:无需手动修改模板
    缺点:searchdb会泄密,TOC会泄密
  • 第三种是利用模板引擎,自定义getter,然后判断获取的是原文还是TOC。
    优点:无需修改模板
    缺点:TOC会泄密,过于依赖模板,部分模板可能无法实现
  • 第四种是直接加密,仅保留TOC,让模板引擎解析完成后再删除文章中的TOC。
    优点:无需修改模板
    缺点:需要实现对TOC的解析,TOC泄密

注1:如果要防止TOC泄密需要单独对TOC进行加密,那么就需要对主题进行单独适配
注2:上述searchdb泄密指可以在search.xml中搜索到原文,searchdb能搜索到所有TOC泄密内容

@xiazeyu
Copy link
Collaborator

xiazeyu commented Feb 22, 2018

那么需要确定2个方向:
是对所有主题TOC进行适配还是仅对Next主题TOC进行适配
TOC泄密是否需要处理

目前针对Searchdb泄密我有个想法,就是把加密内容都丢到的data中,这样searchdb就不会解析

@xiazeyu
Copy link
Collaborator

xiazeyu commented Feb 22, 2018

Sidebar中有关TOC的代码只有15-24行

@ghost
Copy link

ghost commented Feb 22, 2018

@xiazeyu 问一下如果是使用其他搜索服务的会泄露文章么?比如algolia

@xiazeyu
Copy link
Collaborator

xiazeyu commented Feb 22, 2018

你可以试试= =
如果是hexo插件的话目测搜索服务是直接遍历文章内容的..
就是说如果你文章内容是一坨密文,那么你搜索就会搜索到一坨乱七八糟的密文
如果是原文就会搜索到原文

@ghost
Copy link

ghost commented Feb 22, 2018

额,我等你完成代码再说

@D0n9X1n
Copy link
Owner

D0n9X1n commented Feb 23, 2018

@wuhang2003 next 6.0 的 toc 问题可以把 next/layout/_macro/sidebar.swig 文件修改如下:

{% macro render(is_post) %}
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    {% if theme.sidebar.onmobile %}
      <div id="sidebar-dimmer"></div>
    {% endif %}
    <div class="sidebar-inner">

      {% set display_toc = is_post and theme.toc.enable or is_page and theme.toc.enable %}

      {% if display_toc and (toc(page.content).length > 1 or toc(page.origin).length > 1) %}
        <ul class="sidebar-nav motion-element">
          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap">
            {{ __('sidebar.toc') }}
          </li>
          <li class="sidebar-nav-overview" data-target="site-overview-wrap">
            {{ __('sidebar.overview') }}
          </li>
        </ul>
      {% endif %}

      <section class="site-overview-wrap sidebar-panel{% if not display_toc or (toc(page.content).length <= 1 and toc(page.origin) <= 1) %} sidebar-panel-active{% endif %}">
        <div class="site-overview">
          <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
            {% if theme.avatar %}
              <img class="site-author-image" itemprop="image"
                src="{{ url_for( theme.avatar | default(theme.images + '/avatar.gif') ) }}"
                alt="{{ theme.author }}" />
            {% endif %}
              <p class="site-author-name" itemprop="name">{{ theme.author }}</p>
              <p class="site-description motion-element" itemprop="description">{#
              #}{{ theme.description }}{#
            #}</p>
          </div>

          {% if theme.site_state %}
            <nav class="site-state motion-element">
              {% if config.archive_dir != '/' and site.posts.length > 0 %}
                <div class="site-state-item site-state-posts">
                {% if theme.menu.archives %}
                  <a href="{{ url_for(theme.menu.archives).split('||')[0] | trim }}">
                {% else %}
                  <a href="{{ url_for(config.archive_dir) }}">
                {% endif %}
                    <span class="site-state-item-count">{{ site.posts.length }}</span>
                    <span class="site-state-item-name">{{ __('state.posts') }}</span>
                  </a>
                </div>
              {% endif %}

              {% if site.categories.length > 0 %}
                {% set categoriesPageQuery = site.pages.find({type: 'categories'}, {lean: true}) %}
                {% set hasCategoriesPage = categoriesPageQuery.length > 0 %}
                <div class="site-state-item site-state-categories">
                  {% if hasCategoriesPage %}<a href="{{ url_for(categoriesPageQuery[0].path) }}">{% endif %}
                    {% set visibleCategories = 0 %}
                    {% for cat in site.categories %}
                      {% if cat.length %}{% set visibleCategories += 1 %}{% endif %}
                    {% endfor %}
                    <span class="site-state-item-count">{{ visibleCategories }}</span>
                    <span class="site-state-item-name">{{ __('state.categories') }}</span>
                  {% if hasCategoriesPage %}</a>{% endif %}
                </div>
              {% endif %}

              {% if site.tags.length > 0 %}
                {% set tagsPageQuery = site.pages.find({type: 'tags'}, {lean: true}) %}
                {% set hasTagsPage = tagsPageQuery.length > 0 %}
                <div class="site-state-item site-state-tags">
                  {% if hasTagsPage %}<a href="{{ url_for(tagsPageQuery[0].path) }}">{% endif %}
                    {% set visibleTags = 0 %}
                    {% for tag in site.tags %}
                      {% if tag.length %}{% set visibleTags += 1 %}{% endif %}
                    {% endfor %}
                    <span class="site-state-item-count">{{ visibleTags }}</span>
                    <span class="site-state-item-name">{{ __('state.tags') }}</span>
                  {% if hasTagsPage %}</a>{% endif %}
                </div>
              {% endif %}
            </nav>
          {% endif %}

          {% if theme.rss %}
            <div class="feed-link motion-element">
              <a href="{{ url_for(theme.rss) }}" rel="alternate">
                <i class="fa fa-rss"></i>
                RSS
              </a>
            </div>
          {% endif %}

          {% if theme.social %}
            <div class="links-of-author motion-element">
              {% for name, link in theme.social %}
                <span class="links-of-author-item">
                  {% if theme.exturl && theme.social_icons.exturl %}
                    <span class="exturl" data-url="{{ link.split('||')[0] | trim }}" title="{{ name }}">{#
                #}{% else %}{#
                  #}<a href="{{ link.split('||')[0] | trim }}" target="_blank" title="{{ name }}"{% if theme.seo %} rel="external nofollow"{% endif %}>{#
                #}{% endif %}{#
                  #}{% if theme.social_icons.enable %}{#
                    #}<i class="fa fa-fw fa-{{ link.split('||')[1] | trim | default('globe') }}"></i>{#
                  #}{% endif %}{#
                  #}{% if not theme.social_icons.icons_only %}{#
                    #}{{ name }}{#
                  #}{% endif %}{#
                #}{% if theme.exturl && theme.social_icons.exturl %}{#
                  #}</span>
                  {% else %}{#
                  #}</a>
                  {% endif %}
                </span>
              {% endfor %}
            </div>
          {% endif %}

          {% set cc = {'by': 1, 'by-nc': 1, 'by-nc-nd': 1, 'by-nc-sa': 1, 'by-nd': 1, 'by-sa': 1, 'zero': 1} %}
          {% if theme.creative_commons in cc %}
            <div class="cc-license motion-element" itemprop="license">
              <a href="https://creativecommons.org/{% if theme.creative_commons === 'zero' %}publicdomain/zero/1.0{% else %}licenses/{{ theme.creative_commons }}/4.0{% endif %}/" class="cc-opacity" target="_blank"{% if theme.seo %} rel="external nofollow"{% endif %}>
                <img src="{{ url_for(theme.images) }}/cc-{{ theme.creative_commons }}.svg" alt="Creative Commons" />
              </a>
            </div>
          {% endif %}

          {# Blogroll #}
          {% if theme.links %}
            <div class="links-of-blogroll motion-element {{ "links-of-blogroll-" + theme.links_layout | default('inline') }}">
              <div class="links-of-blogroll-title">
                <i class="fa  fa-fw fa-{{ theme.links_icon | default('globe') | lower }}"></i>
                {{ theme.links_title }}
              </div>
              <ul class="links-of-blogroll-list">
                {% for name, link in theme.links %}
                  <li class="links-of-blogroll-item">
                    <a href="{{ link }}" title="{{ name }}" target="_blank">{{ name }}</a>
                  </li>
                {% endfor %}
              </ul>
            </div>
          {% endif %}

          {% if theme.custom_file_path.sidebar %}
            {% set custom_sidebar = '../../../../' + theme.custom_file_path.sidebar %}
          {% else %}
            {% set custom_sidebar = '../_custom/sidebar.swig' %}
          {% endif %}
          {% include custom_sidebar %}
        </div>
      </section>

      {% if display_toc and (toc(page.origin).length > 1 || toc(page.content).length > 1)%}
      <!--noindex-->
        <section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
          <div id="toc-div" class="post-toc" style="display:none">

            {% if page.password === undefined %}
                {% if page.toc_number === undefined %}
                {% set toc = toc(page.content, { "class": "nav", list_number: theme.toc.number }) %}
                {% else %}
                {% set toc = toc(page.content, { "class": "nav", list_number: page.toc_number }) %}
                {% endif %}
            {% else %}
                {% if page.toc_number === undefined %}
                {% set toc = toc(page.origin, { "class": "nav", list_number: theme.toc.number }) %}
                {% else %}
                {% set toc = toc(page.origin, { "class": "nav", list_number: page.toc_number }) %}
                {% endif %}
            {% endif %}

            {% if toc.length <= 1 %}
              <p class="post-toc-empty">{{ __('post.toc_empty') }}</p>
            {% else %}
              <div class="post-toc-content">{{ toc }}</div>
            {% endif %}

          </div>
        </section>
      <!--/noindex-->
      {% endif %}

      {% if theme.sidebar.b2t %}
        <div class="back-to-top">
          <i class="fa fa-arrow-up"></i>
          {% if theme.sidebar.scrollpercent %}
            <span id="scrollpercent"><span>0</span>%</span>
          {% endif %}
        </div>
      {% endif %}

    </div>
  </aside>
{% endmacro %}

效果见:https://mhexo.github.io/example-site/2016/10/26/HexoBlogEncrpyt/

@D0n9X1n
Copy link
Owner

D0n9X1n commented Feb 23, 2018

不过,目前只是把 toc 的内容隐藏了,如果 toc 泄密,那就很尴尬了。
主要修改部分为:

index 81eefcb..3f26158 100644
--- a/layout/_macro/sidebar.swig
+++ b/layout/_macro/sidebar.swig
@@ -15,7 +15,7 @@

       {% set display_toc = is_post and theme.toc.enable or is_page and theme.toc.enable %}

-      {% if display_toc and toc(page.content).length > 1 %}
+      {% if display_toc and (toc(page.content).length > 1 or toc(page.origin).length > 1) %}
         <ul class="sidebar-nav motion-element">
           <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap">
             {{ __('sidebar.toc') }}
@@ -26,7 +26,7 @@
         </ul>
       {% endif %}

-      <section class="site-overview-wrap sidebar-panel{% if not display_toc or toc(page.content).length <= 1 %} sidebar-panel-active{% endif %}">
+      <section class="site-overview-wrap sidebar-panel{% if not display_toc or (toc(page.content).length <= 1 and toc(page.origin) <= 1) %} sidebar-panel-active{% endif %}">
         <div class="site-overview">
           <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
             {% if theme.avatar %}
@@ -156,15 +156,23 @@
         </div>
       </section>

-      {% if display_toc and toc(page.content).length > 1 %}
+      {% if display_toc and (toc(page.origin).length > 1 || toc(page.content).length > 1)%}
       <!--noindex-->
         <section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
-          <div class="post-toc">
+          <div id="toc-div" class="post-toc" style="display:none">

-            {% if page.toc_number === undefined %}
-              {% set toc = toc(page.content, { "class": "nav", list_number: theme.toc.number }) %}
+            {% if page.password === undefined %}
+                {% if page.toc_number === undefined %}
+                {% set toc = toc(page.content, { "class": "nav", list_number: theme.toc.number }) %}
+                {% else %}
+                {% set toc = toc(page.content, { "class": "nav", list_number: page.toc_number }) %}
+                {% endif %}
             {% else %}
-              {% set toc = toc(page.content, { "class": "nav", list_number: page.toc_number }) %}
+                {% if page.toc_number === undefined %}
+                {% set toc = toc(page.origin, { "class": "nav", list_number: theme.toc.number }) %}
+                {% else %}
+                {% set toc = toc(page.origin, { "class": "nav", list_number: page.toc_number }) %}
+                {% endif %}
             {% endif %}

             {% if toc.length <= 1 %}

@xiazeyu
Copy link
Collaborator

xiazeyu commented Feb 23, 2018

@MikeCoder
所以说还是觉得改模板这个方向比较好?
其实可以写个util来自动改next主题模板的..然后其他主题反正加密后什么都没有..
然后TOC泄密嘛~
我们可以直接在after_render来黑科技解析渲染后的HTML,根据toc的div id="toc-div"特征来把toc一起加密了
然后解密脚本getElementByClass('encrypted')把页面所有加密元素全部解密

话说还是不知道<encrypted data="密文">这里面的密文有没有长度限制

@D0n9X1n
Copy link
Owner

D0n9X1n commented Feb 23, 2018

恩,toc-div 这个 id 还是要是改个模板(谁让 hexo 主题没有一个统一的规范- -)。
后面的加密是可以。只不过现在在新版本出来前,让先用上。
我明天写个新版计划吧。

@xiazeyu
Copy link
Collaborator

xiazeyu commented Feb 23, 2018

@MikeCoder
<encrypted data="密文">
就是用div或者直接整行匹配来在模板中定位,然后如果找到符合特征的就替换
也只是一个简化用户手动修改模板的方法
(计划我一直都是用的GitHub的Issue系统...感觉并不需要手动列计划..)
(准备今年搞一波3.0..)

@D0n9X1n D0n9X1n added this to the v3.0 milestone Feb 23, 2018
@D0n9X1n
Copy link
Owner

D0n9X1n commented Feb 23, 2018

@D0n9X1n D0n9X1n closed this as completed Jan 15, 2019
@D0n9X1n D0n9X1n removed this from the v3.0 milestone Sep 7, 2019
@ruozhiertong
Copy link

Hi,
toc泄密的有最后的解决方案吗?
现在最新的hexo-blog-encrypt只是将toc隐藏了,所以还是会造成toc泄密。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants