Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
- [pull #734] Fix empty list items being parsed as nested lists (#167)
- [pull #735] Fix `smarty-pants` extra converting quotes inside inline HTML tags and comments (#150)
- [pull #737] Fix XSS from code spans that the span gamut doesn't treat as code spans in safe mode (#726)
- [pull #743] Add a `strip-syntax` option to the `header-ids` extra that leaves link URLs, image paths, inline HTML tags and emphasis markers out of header ids (#192)


## python-markdown2 2.5.5
Expand Down
20 changes: 17 additions & 3 deletions lib/markdown2.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@
* footnotes: Support footnotes as in use on daringfireball.net and
implemented in other Markdown processors (tho not in Markdown.pl v1.0.1).
* header-ids: Adds "id" attributes to headers. The id value is a slug of
the header text.
the header text. With `{"strip-syntax": True}`, the slug is made from the
rendered header, so link URLs, image paths, inline HTML tags and emphasis
markers are left out of it.
* highlightjs-lang: Allows specifying the language which used for syntax
highlighting when using fenced-code-blocks and highlightjs.
* html-classes: Takes a dict mapping html tag names (lowercase) to a
Expand Down Expand Up @@ -1661,6 +1663,8 @@ def _do_links(self, text: str) -> str:
text = link_processor.run(text)
return text

_html_tag_re = re.compile(r'<[^>]*>')

def header_id_from_text(self,
text: str,
prefix: str,
Expand Down Expand Up @@ -1745,16 +1749,26 @@ def _h_sub(self, match: re.Match[str]) -> str:
if demote_headers:
n = min(n + demote_headers, 6)
header_id_attr = ""
html = self._run_span_gamut(header_group)
if "header-ids" in self.extras:
# in safe mode, inline HTML is hashed by now. Unhash it so the
# sanitized HTML doesn't get swapped back into the id attribute
header_text = self._unhash_html_spans(header_group)
if self.extras["header-ids"].get('strip-syntax'):
# build the id from the rendered header so that markdown syntax
# (link URLs, image paths, emphasis markers) doesn't end up in it.
header_text = self._html_tag_re.sub('', self._unhash_html_spans(html))
if "footnotes" in self.extras:
# footnote refs are numbered later on. Drop the placeholder
# so it doesn't end up in the id
marker = self._footnote_marker + '-'
header_text = header_text.replace(marker, '')
else:
header_text = self._unhash_html_spans(header_group)
header_id = self.header_id_from_text(
self._unescape_special_chars(header_text),
self.extras["header-ids"].get('prefix'), n)
if header_id:
header_id_attr = ' id="%s"' % header_id
html = self._run_span_gamut(header_group)
if "toc" in self.extras and header_id:
self._toc_add_entry(n, header_id, html)
return "<h%d%s>%s</h%d>\n\n" % (n, header_id_attr, html, n)
Expand Down
16 changes: 16 additions & 0 deletions test/tm-cases/header_ids_footnote_ref.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<h1 id="header-with-a-footnote1">Header with a footnote<sup class="footnote-ref" id="fnref-1"><a href="#fn-1">1</a></sup></h1>

<h1 id="linked-headernote"><a href="http://example.com">Linked</a> header<sup class="footnote-ref" id="fnref-note"><a href="#fn-note">2</a></sup></h1>

<div class="footnotes">
<hr />
<ol>
<li id="fn-1">
<p>The first note.&#160;<a href="#fnref-1" class="footnoteBackLink" title="Jump back to footnote 1 in the text.">&#8617;</a></p>
</li>

<li id="fn-note">
<p>The second note.&#160;<a href="#fnref-note" class="footnoteBackLink" title="Jump back to footnote 2 in the text.">&#8617;</a></p>
</li>
</ol>
</div>
1 change: 1 addition & 0 deletions test/tm-cases/header_ids_footnote_ref.opts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"extras": {"header-ids": {"strip-syntax": True}, "footnotes": None}}
1 change: 1 addition & 0 deletions test/tm-cases/header_ids_footnote_ref.tags
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
extra header-ids footnotes issue192
6 changes: 6 additions & 0 deletions test/tm-cases/header_ids_footnote_ref.text
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Header with a footnote[^1]

# [Linked](http://example.com) header[^note]

[^1]: The first note.
[^note]: The second note.
16 changes: 16 additions & 0 deletions test/tm-cases/header_ids_footnote_ref_default.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<h1 id="header-with-a-footnote1">Header with a footnote<sup class="footnote-ref" id="fnref-1"><a href="#fn-1">1</a></sup></h1>

<h1 id="linkedhttpexamplecom-headernote"><a href="http://example.com">Linked</a> header<sup class="footnote-ref" id="fnref-note"><a href="#fn-note">2</a></sup></h1>

<div class="footnotes">
<hr />
<ol>
<li id="fn-1">
<p>The first note.&#160;<a href="#fnref-1" class="footnoteBackLink" title="Jump back to footnote 1 in the text.">&#8617;</a></p>
</li>

<li id="fn-note">
<p>The second note.&#160;<a href="#fnref-note" class="footnoteBackLink" title="Jump back to footnote 2 in the text.">&#8617;</a></p>
</li>
</ol>
</div>
1 change: 1 addition & 0 deletions test/tm-cases/header_ids_footnote_ref_default.opts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"extras": ["header-ids", "footnotes"]}
1 change: 1 addition & 0 deletions test/tm-cases/header_ids_footnote_ref_default.tags
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
extra header-ids footnotes issue192
6 changes: 6 additions & 0 deletions test/tm-cases/header_ids_footnote_ref_default.text
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Header with a footnote[^1]

# [Linked](http://example.com) header[^note]

[^1]: The first note.
[^note]: The second note.
13 changes: 13 additions & 0 deletions test/tm-cases/header_ids_issue192.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<h1 id="inline-link"><a href="https://github.com">Inline link</a></h1>

<h1 id="reference-link"><a href="http://example.com">Reference link</a></h1>

<h1 id="image"><img src="logo.png" alt="logo" /> Image</h1>

<h1 id="bold-link"><strong><a href="http://example.com" title="Title">Bold link</a></strong></h1>

<h1 id="inline-html"><span>Inline</span> HTML</h1>

<h1 id="strong-and-em"><strong>Strong</strong> and <em>em</em></h1>

<h1 id="code_span-stays"><code>code_span</code> stays</h1>
1 change: 1 addition & 0 deletions test/tm-cases/header_ids_issue192.opts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"extras": {"header-ids": {"strip-syntax": True}}}
1 change: 1 addition & 0 deletions test/tm-cases/header_ids_issue192.tags
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
extra header-ids issue192
15 changes: 15 additions & 0 deletions test/tm-cases/header_ids_issue192.text
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# [Inline link](https://github.com)

# [Reference link][ref]

# ![logo](logo.png) Image

# **[Bold link](http://example.com "Title")**

# <span>Inline</span> HTML

# __Strong__ and _em_

# `code_span` stays

[ref]: http://example.com
13 changes: 13 additions & 0 deletions test/tm-cases/header_ids_issue192_default.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<h1 id="inline-linkhttpsgithubcom"><a href="https://github.com">Inline link</a></h1>

<h1 id="reference-linkref"><a href="http://example.com">Reference link</a></h1>

<h1 id="logologopng-image"><img src="logo.png" alt="logo" /> Image</h1>

<h1 id="bold-linkhttpexamplecom-title"><strong><a href="http://example.com" title="Title">Bold link</a></strong></h1>

<h1 id="spaninlinespan-html"><span>Inline</span> HTML</h1>

<h1 id="__strong__-and-_em_"><strong>Strong</strong> and <em>em</em></h1>

<h1 id="code_span-stays"><code>code_span</code> stays</h1>
1 change: 1 addition & 0 deletions test/tm-cases/header_ids_issue192_default.opts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"extras": ["header-ids"]}
1 change: 1 addition & 0 deletions test/tm-cases/header_ids_issue192_default.tags
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
extra header-ids issue192
15 changes: 15 additions & 0 deletions test/tm-cases/header_ids_issue192_default.text
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# [Inline link](https://github.com)

# [Reference link][ref]

# ![logo](logo.png) Image

# **[Bold link](http://example.com "Title")**

# <span>Inline</span> HTML

# __Strong__ and _em_

# `code_span` stays

[ref]: http://example.com