epub: escape ids and hrefs in the EPUB templates - #2269
Merged
Merged
Conversation
26a96dd routed interpolated attribute values through ExDoc.Utils.h/1, fixing DocAST.ast_attributes_to_string and HTML.Templates.enc, but the EPUB templates still interpolate bare URI.encode/1 output into XML attributes. URI.encode keeps every reserved character literal, so an ampersand survives it, and in XML a bare ampersand is a fatal parse error rather than a quirk. A configured extra filename reaches those attributes unfiltered: validate_extra_string! only checks is_binary. Generating with extras: [{"readme.md", filename: "a&b"}] emits <item id="a&b" href="a&b.xhtml" .../> and neither content.opf nor nav.xhtml is well-formed, so the book will not open. Adds the same enc/1 the HTML templates use, which is h(URI.encode(...)), and applies it at the five live sites. toc_item_template.eex has the same shape but is unreachable, with no call sites since the EPUB2 NCX era, so it is left alone.
|
📦 Docs artifacts are ready: https://github.com/elixir-lang/ex_doc/actions/runs/34967795218/artifacts/10395819975 |
Member
|
💚 💙 💜 💛 ❤️ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
26a96dd3"Escape attributes" routed interpolated attribute values throughExDoc.Utils.h/1. It fixedDocAST.ast_attributes_to_stringandHTML.Templates.enc, and left the EPUB templates interpolating bareURI.encode/1output into XML attributes.URI.encode/1keeps every reserved character literal, so&survives it. In XML a bare&is a fatal parse error, not a quirk.A configured extra filename reaches those attributes unfiltered, because
validate_extra_string!only checksis_binary. Generating withextras: [{"readme.md", filename: "a&b"}]emitsand neither
content.opfnornav.xhtmlis well-formed, so the book does not open.nav_grouped_item_template.eex:7shows the asymmetry in one line: the link text goes throughh, thehrefbeside it does not.Adds the same
enc/1the HTML templates already use,h(URI.encode(...)), and applies it at the five live sites.Verification
Measured by generating an EPUB and handing the result to an XML parser.
<item id=...>emittedcontent.opfnav.xhtmlid="a&b%3Cc%22d"id="a&b%3Cc%22d"id="plainname"Note
<and"are already handled, becauseURI.encodepercent-encodes them;&is the one that gets through, which is why the symptom is a hard parse failure rather than mangled text.Added one test to
epub_test.exsasserting the escaped output and then feeding both files to:xmerl_scan.string/1, which raises on malformed XML. Reverting only the three template files makes it fail. Full suite: 452 tests, 0 failures, against 451 on main.toc_item_template.eexhas the same shape at three sites but is left alone: it is defined atepub/templates.ex:106and has zero call sites, sincenav_template.eexonly invokesnav_grouped_item_template. It looks like a leftover from the EPUB2 NCX era. Happy to include it or delete it if you would rather it did not linger.The module and task ids that flow through the same lines cannot contain these characters when they come from Elixir, so the reachable producer here is the
:filenameoption. The sites are fixed uniformly rather than only the reachable ones, since they all answer the same question.Related: #1851 reports the same class of fatal EPUB parse error. The specific href in that issue is already fixed by
26a96dd3; these template sites are the part it did not reach. This is a different surface from #2111, which is about named character references in content needing an entity declaration.Disclosure: written with AI assistance (Claude). Every number above is measured.