Skip to content

Commit

Permalink
Merge pull request #4 from Zhaopudark/dev
Browse files Browse the repository at this point in the history
Modify `md2html_hash_anchor_and_internal_link_filter` to add an invisible link for each header.
  • Loading branch information
Zhaopudark authored May 23, 2024
2 parents 62bac98 + 7a33b12 commit e8463ae
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 31 deletions.
6 changes: 4 additions & 2 deletions RELEASE.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
# Pandoc-Filter 0.2.x

## Release 0.2.15
Working on...

- Modify `md2html_hash_anchor_and_internal_link_filter` to add an invisible link for each header.
- Now, for each header, an invisible link that links to the header itself will be added to it.
- The added invisible link will be assigned the class of `headerlink`.
- This will be useful for generating anchors by some renderers/frameworks/tools, such as [hexo-theme-butterfly](https://butterfly.js.org/posts/4aa8abbe/?highlight=%25+endnote#%E9%A0%81%E9%9D%A2%E9%8C%A8%E9%BB%9E).
## Release 0.2.14

- Modify `md2html_hash_anchor_and_internal_link_filter` to handle internal links within hexo tag plugins.
Expand Down
97 changes: 73 additions & 24 deletions resources/outputs/test_md2html_header_anchor_and_link.html
Original file line number Diff line number Diff line change
Expand Up @@ -237,14 +237,20 @@
<h1 class="title">test_md2html_anchor_and_link</h1>
</header>
<h2
id="fbf0b5c90527e8a9dd9607effa892937b6395152c108878118104590c3f9e362-1">引用链接</h2>
id="fbf0b5c90527e8a9dd9607effa892937b6395152c108878118104590c3f9e362-1"><a
href="#fbf0b5c90527e8a9dd9607effa892937b6395152c108878118104590c3f9e362-1"
class="headerlink" title=" 引用链接"></a>引用链接</h2>
<h3
id="4a63f752884096b557e2080b0ee0750ed524d5bcf766b68e583b69a670abe7a1-1">超链接</h3>
id="4a63f752884096b557e2080b0ee0750ed524d5bcf766b68e583b69a670abe7a1-1"><a
href="#4a63f752884096b557e2080b0ee0750ed524d5bcf766b68e583b69a670abe7a1-1"
class="headerlink" title=" 超链接"></a>超链接</h3>
<p>语法:<code>[Link Text](link-address)</code></p>
<p>效果:<a href="https://support.typoraio.cn/Links/">Links - Typora
Support (typoraio.cn)</a></p>
<h3
id="e33eb0a20e706fad034eff0b75744373919dcde27765bd863f9f215207d675be-1">参考链接</h3>
id="e33eb0a20e706fad034eff0b75744373919dcde27765bd863f9f215207d675be-1"><a
href="#e33eb0a20e706fad034eff0b75744373919dcde27765bd863f9f215207d675be-1"
class="headerlink" title=" 参考链接"></a>参考链接</h3>
<p>语法:</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="co">[</span><span class="ot">Link Text</span><span class="co">][Ref2]</span> </span>
Expand All @@ -254,15 +260,19 @@ <h1 class="title">test_md2html_anchor_and_link</h1>
<p><a href="https://support.typoraio.cn/Links/"
title="typora links">Link Text</a></p>
<h3
id="bd35eead251dc61c6dfb3ef11792211ea152f91378add9d60a809fa60f57691a-1">自动链接和网址</h3>
id="bd35eead251dc61c6dfb3ef11792211ea152f91378add9d60a809fa60f57691a-1"><a
href="#bd35eead251dc61c6dfb3ef11792211ea152f91378add9d60a809fa60f57691a-1"
class="headerlink" title=" 自动链接和网址"></a>自动链接和网址</h3>
<p>语法:<code>&lt;http://typora.io&gt;</code></p>
<p>效果:<a href="http://typora.io"
class="uri"><span>http://typora.io</span></a></p>
<p>语法:<code>This is a link: http://typora.io</code></p>
<p>效果:This is a link: <a
href="http://typora.io">http://typora.io</a></p>
<h3
id="264101a13c49c0740702b6312c1a5bd9f3e9e976089ad711d460ed10529627b0-1">本地资源链接</h3>
id="264101a13c49c0740702b6312c1a5bd9f3e9e976089ad711d460ed10529627b0-1"><a
href="#264101a13c49c0740702b6312c1a5bd9f3e9e976089ad711d460ed10529627b0-1"
class="headerlink" title=" 本地资源链接"></a>本地资源链接</h3>
<p>语法:参考<a
href="https://support.typoraio.cn/Links/#link-to-local-files">Links -
Typora Support (typoraio.cn)</a></p>
Expand All @@ -276,19 +286,28 @@ <h1 class="title">test_md2html_anchor_and_link</h1>
<p><a href="../404.html">404_page</a></p>
<p><a href="../posts/d36d5fbd.html">this_page</a></p>
<h3
id="1620841b21c25ccdfa3d8fdd74321f0a85170db8c04330f5b2b372fddb6cabb1-1">页内链接(链接到headings锚点和raw-HTML锚点)</h3>
id="1620841b21c25ccdfa3d8fdd74321f0a85170db8c04330f5b2b372fddb6cabb1-1"><a
href="#1620841b21c25ccdfa3d8fdd74321f0a85170db8c04330f5b2b372fddb6cabb1-1"
class="headerlink"
title=" 页内链接(链接到headings锚点和raw-HTML锚点)"></a>页内链接(链接到headings锚点和raw-HTML锚点)</h3>
<ul>
<li><p>当headings中含有大小写时,允许链接不区分大小写</p>
<h5
id="4a5f06ec672e3c2321239ec81dd50afa8a8059e0a55fb93607ac1e43a2bae990-1">A.1</h5>
id="4a5f06ec672e3c2321239ec81dd50afa8a8059e0a55fb93607ac1e43a2bae990-1"><a
href="#4a5f06ec672e3c2321239ec81dd50afa8a8059e0a55fb93607ac1e43a2bae990-1"
class="headerlink" title=" A.1"></a>A.1</h5>
<h3
id="c5ee560f6ab57c00d0e869ba0ec9ec9adde6fa5393e8291efe0f40b642d5ef3b-1">Second_level</h3>
id="c5ee560f6ab57c00d0e869ba0ec9ec9adde6fa5393e8291efe0f40b642d5ef3b-1"><a
href="#c5ee560f6ab57c00d0e869ba0ec9ec9adde6fa5393e8291efe0f40b642d5ef3b-1"
class="headerlink" title=" Second_level"></a>Second_level</h3>
<p><a
href="#c5ee560f6ab57c00d0e869ba0ec9ec9adde6fa5393e8291efe0f40b642d5ef3b-1">跳转到Second_level,#Second_level</a></p>
<p><a
href="#c5ee560f6ab57c00d0e869ba0ec9ec9adde6fa5393e8291efe0f40b642d5ef3b-1">跳转到Second_level,#second_level</a></p>
<h3
id="2c016825b481eae5b01451017adde9fd573469fede2b576b6c65ef5f376d38c3-1">ErJi目lu</h3>
id="2c016825b481eae5b01451017adde9fd573469fede2b576b6c65ef5f376d38c3-1"><a
href="#2c016825b481eae5b01451017adde9fd573469fede2b576b6c65ef5f376d38c3-1"
class="headerlink" title=" ErJi目lu"></a>ErJi目lu</h3>
<p><a
href="#2c016825b481eae5b01451017adde9fd573469fede2b576b6c65ef5f376d38c3-1">跳转到ErJi目lu,#ErJi目lu</a></p>
<p><a
Expand Down Expand Up @@ -317,12 +336,18 @@ <h1 class="title">test_md2html_anchor_and_link</h1>
<li>其余方式可能会出现意外结果</li>
</ul>
<h3
id="6865c5c8dc7862478d3c251a684a1a6a09594521713d3c81a91a988932f1cef8-1">带空格
id="6865c5c8dc7862478d3c251a684a1a6a09594521713d3c81a91a988932f1cef8-1"><a
href="#6865c5c8dc7862478d3c251a684a1a6a09594521713d3c81a91a988932f1cef8-1"
class="headerlink"
title=" 带空格 和`特殊字符` [链接](http://typora.io) 用于%%%%¥¥¥¥跳转测试 空格"></a>带空格
<code>特殊字符</code> <a href="http://typora.io">链接</a>
用于%%%%¥¥¥¥跳转测试 空格</h3>
<h4
id="4ed057d8cb9bb706509ec393bbef1c95cb64b853ad08c35b6c7a5c3ae43a4206-1">aAa-b
cC <code>Dd</code>, a#%&amp;<a href="yyy">xxx</a> Zzz [xx] (yy)</h4>
id="4ed057d8cb9bb706509ec393bbef1c95cb64b853ad08c35b6c7a5c3ae43a4206-1"><a
href="#4ed057d8cb9bb706509ec393bbef1c95cb64b853ad08c35b6c7a5c3ae43a4206-1"
class="headerlink"
title=" aAa-b cC `Dd`, a#%&amp;[xxx](yyy) Zzz \[xx\] (yy)"></a>aAa-b cC
<code>Dd</code>, a#%&amp;<a href="yyy">xxx</a> Zzz [xx] (yy)</h4>
<p>留白测试跳转</p>
<p>留白测试跳转</p>
<p>留白测试跳转</p>
Expand Down Expand Up @@ -350,17 +375,29 @@ <h1 class="title">test_md2html_anchor_and_link</h1>
</ul></li>
<li><p>链接允许多重#号</p>
<h2
id="a64ef18ab49bdc3ddeb76c73ef9a93c20a8edfc0737ebb4f11017c46672ff21b-1">一级目录</h2>
id="a64ef18ab49bdc3ddeb76c73ef9a93c20a8edfc0737ebb4f11017c46672ff21b-1"><a
href="#a64ef18ab49bdc3ddeb76c73ef9a93c20a8edfc0737ebb4f11017c46672ff21b-1"
class="headerlink" title=" 一级目录"></a>一级目录</h2>
<h3
id="d5335a84faaada3830bdd6b4cb3068c010d5c6f266d214a0ef9a7571bea8daad-1">二级目录</h3>
id="d5335a84faaada3830bdd6b4cb3068c010d5c6f266d214a0ef9a7571bea8daad-1"><a
href="#d5335a84faaada3830bdd6b4cb3068c010d5c6f266d214a0ef9a7571bea8daad-1"
class="headerlink" title=" 二级目录"></a>二级目录</h3>
<h4
id="646dd7daa0ffcf85d48e0b11bac57bb541226d8391a1ccff3136fcce78d48d6f-1">三级目录</h4>
id="646dd7daa0ffcf85d48e0b11bac57bb541226d8391a1ccff3136fcce78d48d6f-1"><a
href="#646dd7daa0ffcf85d48e0b11bac57bb541226d8391a1ccff3136fcce78d48d6f-1"
class="headerlink" title=" 三级目录"></a>三级目录</h4>
<h5
id="4f4ceee94c6d268a19c37bae4a43edc691b00675bf3dae1f60a56a4e43d2c00e-1">四级目录</h5>
id="4f4ceee94c6d268a19c37bae4a43edc691b00675bf3dae1f60a56a4e43d2c00e-1"><a
href="#4f4ceee94c6d268a19c37bae4a43edc691b00675bf3dae1f60a56a4e43d2c00e-1"
class="headerlink" title=" 四级目录"></a>四级目录</h5>
<h6
id="a831cf5aa06ec2c00e1d4823da9bea585a61792000a0e399f636e58791a469c3-1">五级目录</h6>
id="a831cf5aa06ec2c00e1d4823da9bea585a61792000a0e399f636e58791a469c3-1"><a
href="#a831cf5aa06ec2c00e1d4823da9bea585a61792000a0e399f636e58791a469c3-1"
class="headerlink" title=" 五级目录"></a>五级目录</h6>
<h6
id="e4a73c34f1669424113083143c44b4924fbe2c0ba8e4acddc3216592fbfda653-1">六级目录</h6>
id="e4a73c34f1669424113083143c44b4924fbe2c0ba8e4acddc3216592fbfda653-1"><a
href="#e4a73c34f1669424113083143c44b4924fbe2c0ba8e4acddc3216592fbfda653-1"
class="headerlink" title=" 六级目录"></a>六级目录</h6>
<p><a
href="#a64ef18ab49bdc3ddeb76c73ef9a93c20a8edfc0737ebb4f11017c46672ff21b-1">跳转到一级目录,且是单个#号,#一级目录</a></p>
<p><a
Expand Down Expand Up @@ -394,22 +431,34 @@ <h1 class="title">test_md2html_anchor_and_link</h1>
<li>需要确保上述匹配过程,至少有一个锚点是存在的。若这样的锚点不存在,渲染器手动抛出异常提醒。</li>
</ul>
<h3
id="2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824-1">hello</h3>
id="2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824-1"><a
href="#2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824-1"
class="headerlink" title=" hello"></a>hello</h3>
<p>二级目录 hello</p>
<h2
id="2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824-2">hello</h2>
id="2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824-2"><a
href="#2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824-2"
class="headerlink" title=" hello"></a>hello</h2>
<p>一级目录 hello</p>
<h2
id="f6ddc1bf7d9ef5b2a8d41329728d9c0c3a7a88a59413e8c282204ad4b111d1d1-1">hello-2</h2>
id="f6ddc1bf7d9ef5b2a8d41329728d9c0c3a7a88a59413e8c282204ad4b111d1d1-1"><a
href="#f6ddc1bf7d9ef5b2a8d41329728d9c0c3a7a88a59413e8c282204ad4b111d1d1-1"
class="headerlink" title=" hello-2"></a>hello-2</h2>
<p>一级目录 hello</p>
<h4
id="2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824-3">hello</h4>
id="2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824-3"><a
href="#2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824-3"
class="headerlink" title=" hello"></a>hello</h4>
<p>三级目录 hello</p>
<h6
id="2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824-4">hello</h6>
id="2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824-4"><a
href="#2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824-4"
class="headerlink" title=" hello"></a>hello</h6>
<p>五级目录 hello</p>
<h4
id="2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824-5">hello</h4>
id="2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824-5"><a
href="#2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824-5"
class="headerlink" title=" hello"></a>hello</h4>
<p>三级目录 hello</p>
<p><a id="2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824-6">hello</a></p>
<p>自定义锚点 hello</p>
Expand Down
16 changes: 11 additions & 5 deletions src/pandoc_filter/filters/md2html/hash_anchor_and_internal_link.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ def _hash_anchor_id(elem:pf.Element,doc:pf.Doc,tracing_logger:TracingLogger,**kw
header_text = pf.convert_text(elem,input_format='panflute',output_format='gfm',standalone=True).lstrip('#')
text_hash = __text_hash_count(doc,header_text)
elem.identifier = f"{text_hash}-{doc.runtime_dict['anchor_count'][text_hash]}"
# According to https://github.com/Zhaopudark/pandoc-filter/issues/3, add an invisible link in the header.
link_in_hearder = pf.Link(url=f"#{elem.identifier}",title=header_text,classes=['headerlink'])
elem.content.insert(0,link_in_hearder)

tracing_logger.check_and_log('headings anchor',elem)
elif isinstance(elem, pf.RawInline) and elem.format == 'html' and (raw_id_text:=get_html_id(elem.text)): # 获取id文本内容但不做任何剔除
tracing_logger.mark(elem)
Expand All @@ -103,10 +107,12 @@ def _internal_link_recorder(elem:pf.Element,doc:pf.Doc,**kwargs)->None:
[modify nothing]
"""
if isinstance(elem, pf.Link) and elem.url.startswith('#'):
# Olny md internal links need to be decoded since it will be encoded by pandoc before filter.
decoded_url = decode_internal_link_url(elem.url)
url,guessed_url_with_num = __url_hash_guess(decoded_url)
doc.runtime_dict['internal_link_record'].append(InternalLink(elem,url=url,guessed_url=guessed_url_with_num))
# Olny md internal links need to be decoded since it will be encoded by pandoc before filter.:
if 'headerlink' not in elem.classes: # pass the headerlink
decoded_url = decode_internal_link_url(elem.url)
url,guessed_url_with_num = __url_hash_guess(decoded_url)
doc.runtime_dict['internal_link_record'].append(InternalLink(elem,url=url,guessed_url=guessed_url_with_num))

elif isinstance(elem, pf.RawInline) and elem.format == 'html' and (old_href:=get_html_href(elem.text)) and old_href.startswith('#'):
# raw-HTML internal links will not be encoded by pandoc before filter. So there is no need to decode it.
url,guessed_url_with_num = __url_hash_guess(old_href)
Expand All @@ -124,7 +130,7 @@ def _finalize_hash_anchor_and_internal_link(doc:pf.Doc,tracing_logger:TracingLog
elif internal_link.guessed_url in id_set: # None is not in id_set
internal_link.sub(f"{internal_link.guessed_url}",tracing_logger)
else:
# According https://github.com/Zhaopudark/pandoc-filter/issues/1,
# According to https://github.com/Zhaopudark/pandoc-filter/issues/1,
# Even though the internal link's target is not found, we still modify it compulsorily, instead of do nothing.
# The warning message is just for reminding the user.
tracing_logger.warning("hash_anchor_and_internal_link",f"{internal_link.elem}")
Expand Down

0 comments on commit e8463ae

Please sign in to comment.