Skip to content

fix: footnotes rendered as raw markdown#16

Merged
nycterent merged 1 commit into
mainfrom
fix/footnotes
Jun 19, 2026
Merged

fix: footnotes rendered as raw markdown#16
nycterent merged 1 commit into
mainfrom
fix/footnotes

Conversation

@nycterent

Copy link
Copy Markdown
Contributor

/archive/duok-povilui-jis-dabar-laisvesnis/ shipped footnote definitions as raw markdown ([^1]: ...).

Cause: mistune's footnotes plugin wasn't enabled, so [^1] refs and defs passed through untouched. The md-leak guard only checked images/headings, so it slipped by.

Fix: create_markdown(escape=False, plugins=['footnotes']) — inline [^1]<sup> link, defs → anchored <section> with backlinks. Allow <section> in the sanitizer; style .post-body section as footnotes (rule separator, muted). Extended the build guard to also catch raw [^..] so this can't recur. Regression test added. 21 tests green. Squash-merge.

Footnote defs shipped as raw markdown ([^1]: ...) because mistune's
footnotes plugin wasn't enabled. Enable plugins=['footnotes'] (inline
[^1] -> <sup> link, defs -> anchored <section>). Allow <section> in
sanitizer; style .post-body section as footnotes (rule + muted). Extend
md-leak build guard to catch raw [^..] footnotes. Regression test.
Copilot AI review requested due to automatic review settings June 19, 2026 22:23
@nycterent nycterent merged commit 3a4fcf8 into main Jun 19, 2026
2 checks passed
@nycterent nycterent deleted the fix/footnotes branch June 19, 2026 22:25

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a rendering regression where Mistune footnote references/definitions ([^1], [^1]: ...) were leaking into published HTML as raw markdown by enabling Mistune’s footnotes plugin, adjusting sanitization/styling for the generated footnote markup, and adding a regression test.

Changes:

  • Enable Mistune footnotes plugin and extend the build-time “markdown leak” guard to detect raw footnote markers.
  • Allow <section> through the HTML sanitizer and add CSS styling for the generated footnote block.
  • Regenerate affected /archive/*/index.html pages and add a footnotes regression test.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
render.py Enables Mistune footnotes, allowlists <section>, and expands the markdown-leak guard to include footnote markers.
style.css Adds styling for footnotes output (rendered as a <section> containing an ordered list).
tests/test_render.py Adds a regression test ensuring footnotes render to HTML rather than leaking raw markdown.
archive/story-points/index.html Regenerated HTML now renders footnote refs/defs as <sup> + footnote <section>.
archive/pokycio-kainos-euristika/index.html Regenerated HTML now renders footnote refs/defs as <sup> + footnote <section>.
archive/pokalbis-kuris-dar-neivyko/index.html Regenerated HTML now renders footnote refs/defs as <sup> + footnote <section>.
archive/pasiruosimas-kuris-nepadeda/index.html Regenerated HTML now renders footnote refs/defs as <sup> + footnote <section>.
archive/langas-kurio-galva-nepramusi/index.html Regenerated HTML now renders footnote refs/defs as <sup> + footnote <section>.
archive/kodel-visi-daro-teisingai-ir-vis-tiek-pralaimi/index.html Regenerated HTML now renders footnote refs/defs as <sup> + footnote <section>.
archive/eksperimentas-kurio-nebuvo/index.html Regenerated HTML removed [^n]: ... citation paragraphs (now interpreted as unreferenced footnotes).
archive/duok-povilui-jis-dabar-laisvesnis/index.html Regenerated HTML now renders footnote refs/defs as <sup> + footnote <section>.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread render.py
Comment on lines 111 to +113
def md_leaked(html):
"""True if rendered output still contains unrendered markdown (image or heading)."""
return bool(_MD_IMAGE.search(html) or _MD_HEADING.search(html))
"""True if rendered output still contains unrendered markdown (image, heading, footnote)."""
return bool(_MD_IMAGE.search(html) or _MD_HEADING.search(html) or _MD_FOOTNOTE.search(html))
Comment thread style.css
Comment on lines +403 to +415
/* footnotes (mistune wraps them in <section>) */
.post-body.mm-read section {
margin-top: 3rem;
padding-top: 1.2rem;
border-top: 3px solid var(--rule);
font-size: 0.92rem;
line-height: 1.6;
color: var(--muted);
text-align: left;
}
.post-body.mm-read section ol { padding-left: 1.4rem; }
.post-body.mm-read section li { margin: 0 0 0.6rem; }
.post-body.mm-read section a { border-bottom: none; }
Comment on lines 56 to 58
<p>Tikrasis Stephensono radinys kalba apie tai, kaip perduodamas <em>leidimas klysti arba neklysti</em> — stebint aplinką, be instrukcijų, be taisyklių.</p>
<p>P.S. Eksperimentas, kurio nebuvo, paaiškina elgesį tiksliau nei daugelis, kurie buvo. Gal todėl niekas ir neklausė.</p>
<p>P.P.S. Pasakojimą apie bezdžiones mėgstu porinti ir aš, o kai sužinojau, kad ji išgalvota — dar ir dėl to, kad ji yra rekursyvi (skaityti nuo pradžių). Tereikėjo porą šimtų pasakojimų, kai, prieš rašydamas (kitą) blog postą nusprendžiau pasidomėti jos istorija.</p>
Comment thread tests/test_render.py
Comment on lines +72 to +80
def test_footnotes_rendered_not_raw():
body = ("Tekstas su išnaša.[^1]\n\n"
"## Skyrius\n\nDar tekstas.[^2]\n\n"
"[^1]: Pirmas šaltinis.\n[^2]: Antras šaltinis.")
out = render.article(body)
assert "[^1]" not in out and "[^1]:" not in out # not raw
assert "<sup" in out # inline ref rendered
assert "Pirmas šaltinis." in out # definition present
assert 'href="#fn' in out or 'id="fn' in out # anchor wiring
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants