Skip to content

Commit

Permalink
Fix problems with footnote display on Kindles
Browse files Browse the repository at this point in the history
1. Backlinks must be at the start of the footnote or it causes Kindle
   software to mangle the display of footnotes (several footnotes are
   run together, and soft footnote links do not work as pop-overs).
2. Also, Amazon "strongly recommends" the use of the `aside` element.
   This is also recommended by Apple. So when using EPUB3 or HTML5, use
   `aside` elements instead of a list.

   Due to part 1, we have numbered backlinks at the start of footnotes,
   so I also changed EPUB2 to wrap with `div` (instead of `aside`) to
   remove the redundant numbering, and to be consistent with EPUB3
   output.
  • Loading branch information
Porges committed Apr 5, 2018
1 parent ff3ed5c commit dd07121
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 35 deletions.
30 changes: 14 additions & 16 deletions src/Text/Pandoc/Writers/HTML.hs
Original file line number Diff line number Diff line change
Expand Up @@ -490,8 +490,7 @@ footnoteSection opts notes = do
return $
if null notes
then mempty
else nl opts >> container (nl opts >> hrtag >> nl opts >>
H.ol (mconcat notes >> nl opts) >> nl opts)
else nl opts >> container (nl opts >> hrtag >> mconcat notes >> nl opts)

-- | Parse a mailto link; return Just (name, domain) or Nothing.
parseMailto :: String -> Maybe (String, String)
Expand Down Expand Up @@ -1166,22 +1165,21 @@ inlineToHtml opts inline = do

blockListToNote :: PandocMonad m => WriterOptions -> String -> [Block] -> StateT WriterState m Html
blockListToNote opts ref blocks =
-- If last block is Para or Plain, include the backlink at the end of
-- If first block is Para or Plain, include the backlink at the start of
-- that block. Otherwise, insert a new Plain block with the backlink.
let backlink = [Link ("",["footnote-back"],[]) [Str ""] ("#" ++ "fnref" ++ ref,[])]
blocks' = if null blocks
then []
else let lastBlock = last blocks
otherBlocks = init blocks
in case lastBlock of
(Para lst) -> otherBlocks ++
[Para (lst ++ backlink)]
(Plain lst) -> otherBlocks ++
[Plain (lst ++ backlink)]
_ -> otherBlocks ++ [lastBlock,
Plain backlink]
let backlink = [Link ("",["footnote-back"],[]) [Str (ref ++ ".")] ("#" ++ "fnref" ++ ref,[]), Space]
blocks' = case blocks of
[] -> []
(firstBlock:otherBlocks) ->
case firstBlock of
(Para lst) -> Para (backlink ++ lst) : otherBlocks
(Plain lst) -> Plain (backlink ++ lst) : otherBlocks
_ -> Plain backlink : blocks

in do contents <- blockListToHtml opts blocks'
let noteItem = H.li ! prefixedId opts ("fn" ++ ref) $ contents
html5 <- gets stHtml5
let noteElement = if html5 then H5.aside else H.div
let noteItem = noteElement ! prefixedId opts ("fn" ++ ref) $ contents
epubVersion <- gets stEPUBVersion
let noteItem' = case epubVersion of
Just EPUB3 -> noteItem ! customAttribute "epub:type" "footnote"
Expand Down
4 changes: 1 addition & 3 deletions test/command/4235.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ This.^[Has a footnote.]
<p>This.<a href="#foofn1" class="footnote-ref" id="foofnref1"><sup>1</sup></a></p>
<section class="footnotes">
<hr />
<ol>
<li id="foofn1"><p>Has a footnote.<a href="#foofnref1" class="footnote-back">↩</a></p></li>
</ol>
<aside id="foofn1"><p><a href="#foofnref1" class="footnote-back">1.</a> Has a footnote.</p></aside>
</section>
```
14 changes: 6 additions & 8 deletions test/writer.html4
Original file line number Diff line number Diff line change
Expand Up @@ -534,16 +534,14 @@ Blah
<p>This paragraph should not be part of the note, as it is not indented.</p>
<div class="footnotes">
<hr />
<ol>
<li id="fn1"><p>Here is the footnote. It can go anywhere after the footnote reference. It need not be placed at the end of the document.<a href="#fnref1" class="footnote-back">↩</a></p></li>
<li id="fn2"><p>Here’s the long note. This one contains multiple blocks.</p>
<div id="fn1"><p><a href="#fnref1" class="footnote-back">1.</a> Here is the footnote. It can go anywhere after the footnote reference. It need not be placed at the end of the document.</p></div>
<div id="fn2"><p><a href="#fnref2" class="footnote-back">2.</a> Here’s the long note. This one contains multiple blocks.</p>
<p>Subsequent blocks are indented to show that they belong to the footnote (as with list items).</p>
<pre><code> { &lt;code&gt; }</code></pre>
<p>If you want, you can indent every line, but you can also be lazy and just indent the first line of each block.<a href="#fnref2" class="footnote-back">↩</a></p></li>
<li id="fn3"><p>This is <em>easier</em> to type. Inline notes may contain <a href="http://google.com">links</a> and <code>]</code> verbatim characters, as well as [bracketed text].<a href="#fnref3" class="footnote-back">↩</a></p></li>
<li id="fn4"><p>In quote.<a href="#fnref4" class="footnote-back">↩</a></p></li>
<li id="fn5"><p>In list.<a href="#fnref5" class="footnote-back">↩</a></p></li>
</ol>
<p>If you want, you can indent every line, but you can also be lazy and just indent the first line of each block.</p></div>
<div id="fn3"><p><a href="#fnref3" class="footnote-back">3.</a> This is <em>easier</em> to type. Inline notes may contain <a href="http://google.com">links</a> and <code>]</code> verbatim characters, as well as [bracketed text].</p></div>
<div id="fn4"><p><a href="#fnref4" class="footnote-back">4.</a> In quote.</p></div>
<div id="fn5"><p><a href="#fnref5" class="footnote-back">5.</a> In list.</p></div>
</div>
</body>
</html>
14 changes: 6 additions & 8 deletions test/writer.html5
Original file line number Diff line number Diff line change
Expand Up @@ -536,16 +536,14 @@ Blah
<p>This paragraph should not be part of the note, as it is not indented.</p>
<section class="footnotes">
<hr />
<ol>
<li id="fn1"><p>Here is the footnote. It can go anywhere after the footnote reference. It need not be placed at the end of the document.<a href="#fnref1" class="footnote-back">↩</a></p></li>
<li id="fn2"><p>Here’s the long note. This one contains multiple blocks.</p>
<aside id="fn1"><p><a href="#fnref1" class="footnote-back">1.</a> Here is the footnote. It can go anywhere after the footnote reference. It need not be placed at the end of the document.</p></aside>
<aside id="fn2"><p><a href="#fnref2" class="footnote-back">2.</a> Here’s the long note. This one contains multiple blocks.</p>
<p>Subsequent blocks are indented to show that they belong to the footnote (as with list items).</p>
<pre><code> { &lt;code&gt; }</code></pre>
<p>If you want, you can indent every line, but you can also be lazy and just indent the first line of each block.<a href="#fnref2" class="footnote-back">↩</a></p></li>
<li id="fn3"><p>This is <em>easier</em> to type. Inline notes may contain <a href="http://google.com">links</a> and <code>]</code> verbatim characters, as well as [bracketed text].<a href="#fnref3" class="footnote-back">↩</a></p></li>
<li id="fn4"><p>In quote.<a href="#fnref4" class="footnote-back">↩</a></p></li>
<li id="fn5"><p>In list.<a href="#fnref5" class="footnote-back">↩</a></p></li>
</ol>
<p>If you want, you can indent every line, but you can also be lazy and just indent the first line of each block.</p></aside>
<aside id="fn3"><p><a href="#fnref3" class="footnote-back">3.</a> This is <em>easier</em> to type. Inline notes may contain <a href="http://google.com">links</a> and <code>]</code> verbatim characters, as well as [bracketed text].</p></aside>
<aside id="fn4"><p><a href="#fnref4" class="footnote-back">4.</a> In quote.</p></aside>
<aside id="fn5"><p><a href="#fnref5" class="footnote-back">5.</a> In list.</p></aside>
</section>
</body>
</html>

0 comments on commit dd07121

Please sign in to comment.