summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Allen <dan.j.allen@gmail.com>2019-04-13 00:48:46 -0600
committerGitHub <noreply@github.com>2019-04-13 00:48:46 -0600
commitf1410ff1b2bb8f1db18b12db6f14ca870f7eea2c (patch)
tree462bbe80bcc25b31f4b3689fe7155bfbecda3aa5
parent296994863dfede84852e7342a09dab967c0fab6a (diff)
resolves #85 place footnotes at end of chapter (book) or document (article) (PR #1016)
- place list of footnotes at end of chapter (when doctype is book) or document (when doctype is article) - add footnotes category to theme to style footnote list - add additional footnotes to example documents - honor footnotes-title attribute to control title of footnote list (unset by default)
-rw-r--r--CHANGELOG.adoc1
-rw-r--r--data/themes/default-theme.yml3
-rw-r--r--examples/basic-example.adoc6
-rw-r--r--examples/chronicles-example.adoc6
-rw-r--r--lib/asciidoctor-pdf/converter.rb36
5 files changed, 42 insertions, 10 deletions
diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc
index d6d79d3f..c4fd549d 100644
--- a/CHANGELOG.adoc
+++ b/CHANGELOG.adoc
@@ -13,6 +13,7 @@ For a detailed view of what has changed, refer to the {uri-repo}/commits/master[
* drop support for Rouge < 2
* allow running content (header and footer) to be enabled on title and toc pages; controlled by running_content_start_at property in theme (#606)
* upgrade to FontAwesome 5; introduce the fas, far, and fab icon sets, now preferred over fa; drop support for octicons (#891) (@jessedoyle)
+* place footnotes at end of chapters in books or end of document otherwise (#85) (@bcourtine)
* allow additional style properties to be set per heading level (#176) (@billybooth)
* add support for hexadecimal character references (#486)
* set line spacing for non-AsciiDoc table cells (#296)
diff --git a/data/themes/default-theme.yml b/data/themes/default-theme.yml
index 44ceb6ce..afa16b27 100644
--- a/data/themes/default-theme.yml
+++ b/data/themes/default-theme.yml
@@ -235,6 +235,9 @@ toc:
#content: ". "
font_color: a9a9a9
#levels: 2 3
+footnotes:
+ font_size: round($base_font_size * 0.75)
+ item_spacing: $outline_list_item_spacing / 2
# NOTE in addition to footer, header is also supported
footer:
font_size: $base_font_size_small
diff --git a/examples/basic-example.adoc b/examples/basic-example.adoc
index 9ce0ad51..29508620 100644
--- a/examples/basic-example.adoc
+++ b/examples/basic-example.adoc
@@ -12,7 +12,7 @@ A simple http://asciidoc.org[AsciiDoc] document.
== Introduction
-A paragraph followed by a simple list with square bullets.
+A paragraph followed by an unordered list{empty}footnote:[AsciiDoc supports unordered, ordered, and description lists.] with square bullets.footnote:[You may choose from square, disc, and circle for the bullet style.]
[square]
* item 1
@@ -29,3 +29,7 @@ Prawn::Document.generate 'example.pdf' do
text 'Hello, World!'
end
----
+
+== Conclusion
+
+That's all, folks!
diff --git a/examples/chronicles-example.adoc b/examples/chronicles-example.adoc
index 9f9aad57..6054112c 100644
--- a/examples/chronicles-example.adoc
+++ b/examples/chronicles-example.adoc
@@ -48,11 +48,11 @@ image::wolpertinger.jpg[Wolpertinger,pdfwidth=50%,link={uri-wolpertinger}]
You may not be familiar with these {uri-wolpertinger}[ravenous beasts].
Trust us, they'll eat your shorts and suck loops from your code.
In light of this danger, we've searched high and wide for the security crew's defensive operations manual.
-We can't find it and the DefOps{empty}footnote:[a portmanteau of “defensive” and “operations”] werewolves haven't returned from their rendezvous at Bier Central.
+We can't find it and the DefOps{empty}footnote:defops[DefOps is a portmanteau of "`defensive`" and "`operations`".] werewolves haven't returned from their rendezvous at Bier Central.
They've either eaten each other or fallen victim to the Wolpertingers roaming the streets of ((Antwerp)).
Quick, hit kbd:[Ctrl,Alt,Backspace] or select menu:File[Quit] and let's bail out of here!
-WARNING: Working with werewolves leads to howling and trying to train aggressive regular expressions with Pavlovian reinforcement.
+WARNING: Working with DefOps{empty}footnote:defops[] werewolves leads to howling and trying to train aggressive regular expressions with Pavlovian reinforcement.
_Weak light from the hallway trickled across the theater, chased by a distant scream._
@@ -79,7 +79,7 @@ Crystalline XML tags relentlessly bombarded the theater.
</author>
----
-Despite the assault, we were still attempting to draft an example of a defensive operation.
+Despite the assault, we continued our pursuit to draft a DefOps{empty}footnote:defops[] plan.
.DefOps Plan
====
diff --git a/lib/asciidoctor-pdf/converter.rb b/lib/asciidoctor-pdf/converter.rb
index 4d99a5b1..656f2fd7 100644
--- a/lib/asciidoctor-pdf/converter.rb
+++ b/lib/asciidoctor-pdf/converter.rb
@@ -235,6 +235,9 @@ class Converter < ::Prawn::Document
convert_content_for_block doc
+ # NOTE for a book, these are leftover footnotes; for an article this is everything
+ layout_footnotes doc
+
# NOTE delete orphaned page (a page was created but there was no additional content)
# QUESTION should we delete page if document is empty? (leaving no pages?)
delete_page if page_is_empty? && page_count > 1
@@ -299,6 +302,7 @@ class Converter < ::Prawn::Document
@font_color = theme.base_font_color
@base_align = (align = doc.attr 'text-alignment') && (TextAlignmentNames.include? align) ? align : theme.base_align
@text_transform = nil
+ @footnotes = []
@index = IndexCatalog.new
# NOTE we have to init Pdfmark class here while we have reference to the doc
@pdfmark = (doc.attr? 'pdfmark') ? (Pdfmark.new doc) : nil
@@ -426,10 +430,10 @@ class Converter < ::Prawn::Document
return convert_abstract sect
end
+ type = nil
theme_font :heading, level: (hlevel = sect.level + 1) do
title = sect.numbered_title formal: true
align = (@theme[%(heading_h#{hlevel}_align)] || @theme.heading_align || @base_align).to_sym
- type = nil
if sect.part_or_chapter?
if sect.chapter?
type = :chapter
@@ -458,9 +462,26 @@ class Converter < ::Prawn::Document
end
sect.sectname == 'index' ? (convert_index_section sect) : (convert_content_for_block sect)
+ layout_footnotes sect if type == :chapter
sect.set_attr 'pdf-page-end', page_number
end
+ # QUESTION if a footnote ref appears in a separate chapter, should the footnote def be duplicated?
+ def layout_footnotes node
+ return if (fns = (doc = node.document).footnotes - @footnotes).empty?
+ theme_margin :footnotes, :top
+ theme_font :footnotes do
+ # FIXME layout_caption resets the theme font for footnotes
+ (title = doc.attr 'footnotes-title') && (layout_caption title)
+ item_spacing = @theme.footnotes_item_spacing || 0
+ fns.each do |fn|
+ layout_prose %(<a name="_footnotedef_#{index = fn.index}">#{DummyText}</a>[<a anchor="_footnoteref_#{index}">#{index}</a>] #{fn.text}), margin_bottom: item_spacing
+ end
+ @footnotes += fns
+ end
+ nil
+ end
+
def convert_floating_title node
add_dest_for_block node if node.id
# QUESTION should we decouple styles from section titles?
@@ -2033,9 +2054,9 @@ class Converter < ::Prawn::Document
end
def convert_inline_footnote node
- if (index = node.attr 'index')
- #text = node.document.footnotes.find {|fn| fn.index == index }.text
- %( <color rgb="#999999">[#{index}: #{node.text}]</color>)
+ if (index = node.attr 'index') && (node.document.footnotes.find {|fn| fn.index == index })
+ anchor = node.type == :xref ? '' : %(<a name="_footnoteref_#{index}">#{DummyText}</a>)
+ %(#{anchor}<sup>[<a anchor="_footnotedef_#{index}">#{index}</a>]</sup>)
elsif node.type == :xref
# NOTE footnote reference not found
%( <color rgb="FF0000">[#{node.text}]</color>)
@@ -2376,7 +2397,6 @@ class Converter < ::Prawn::Document
end
# Render the caption and return the height of the rendered content
- # QUESTION should layout_caption check for title? and return 0 if false?
# TODO allow margin to be zeroed
def layout_caption subject, opts = {}
mark = { cursor: cursor, page_number: page_number }
@@ -2384,7 +2404,11 @@ class Converter < ::Prawn::Document
when ::String
string = subject
when ::Asciidoctor::AbstractBlock
- string = subject.title? ? subject.captioned_title : nil
+ if subject.title?
+ string = subject.captioned_title
+ else
+ return 0
+ end
else
return 0
end