asciidoctor-pdf 2.0.0.alpha.1 → 2.0.0.alpha.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.adoc +38 -1
- data/README.adoc +3 -3
- data/data/themes/base-theme.yml +3 -2
- data/data/themes/default-theme.yml +6 -5
- data/docs/theming-guide.adoc +3 -3
- data/lib/asciidoctor/pdf/converter.rb +282 -208
- data/lib/asciidoctor/pdf/ext/asciidoctor/document.rb +4 -0
- data/lib/asciidoctor/pdf/ext/prawn/extensions.rb +57 -3
- data/lib/asciidoctor/pdf/ext/prawn/formatted_text/box.rb +5 -0
- data/lib/asciidoctor/pdf/ext/prawn/formatted_text/protect_bottom_gutter.rb +13 -0
- data/lib/asciidoctor/pdf/ext/prawn/images.rb +6 -2
- data/lib/asciidoctor/pdf/ext/prawn.rb +1 -0
- data/lib/asciidoctor/pdf/formatted_text/transform.rb +7 -2
- data/lib/asciidoctor/pdf/nogmagick.rb +6 -0
- data/lib/asciidoctor/pdf/theme_loader.rb +13 -3
- data/lib/asciidoctor/pdf/version.rb +1 -1
- metadata +4 -2
@@ -164,8 +164,11 @@ module Asciidoctor
|
|
164
164
|
if node.blocks?
|
165
165
|
node.content
|
166
166
|
elsif node.content_model != :compound && (string = node.content)
|
167
|
-
|
168
|
-
|
167
|
+
prose_opts = opts.merge hyphenate: true, margin_bottom: 0
|
168
|
+
if (bottom_gutter = @bottom_gutters[-1][node])
|
169
|
+
prose_opts[:bottom_gutter] = bottom_gutter
|
170
|
+
end
|
171
|
+
inscribe_prose string, prose_opts
|
169
172
|
end
|
170
173
|
ensure
|
171
174
|
node.document.instance_variable_set :@converter, prev_converter if prev_converter
|
@@ -187,25 +190,22 @@ module Asciidoctor
|
|
187
190
|
|
188
191
|
marked_page_number = page_number
|
189
192
|
# NOTE: a new page will already be started (page_number = 2) if the front cover image is a PDF
|
190
|
-
|
193
|
+
inscribe_cover_page doc, :front
|
191
194
|
has_front_cover = page_number > marked_page_number
|
192
|
-
|
193
|
-
if (use_title_page = doc.doctype == 'book' || (doc.attr? 'title-page'))
|
194
|
-
layout_title_page doc
|
195
|
-
has_title_page = page_number == (has_front_cover ? 2 : 1)
|
196
|
-
end
|
195
|
+
has_title_page = inscribe_title_page doc if (title_page_on = doc.doctype == 'book' || (doc.attr? 'title-page'))
|
197
196
|
|
198
197
|
@page_margin_by_side[:cover] = @page_margin_by_side[:recto] if @media == 'prepress' && page_number == 0
|
199
198
|
|
200
199
|
start_new_page unless page&.empty? # rubocop:disable Lint/SafeNavigationWithEmpty
|
201
200
|
|
202
|
-
# NOTE: font must be set before content is written to the main or scratch document
|
201
|
+
# NOTE: the base font must be set before any content is written to the main or scratch document
|
202
|
+
# this method is called inside inscribe_title_page if the title page is active
|
203
203
|
font @theme.base_font_family, size: @root_font_size, style: @theme.base_font_style unless has_title_page
|
204
204
|
|
205
|
-
unless
|
205
|
+
unless title_page_on
|
206
206
|
body_start_page_number = page_number
|
207
207
|
theme_font :heading, level: 1 do
|
208
|
-
|
208
|
+
inscribe_general_heading doc, doc.doctitle, align: (@theme.heading_h1_text_align&.to_sym || :center), level: 1, role: :doctitle
|
209
209
|
end if doc.header? && !doc.notitle
|
210
210
|
end
|
211
211
|
|
@@ -216,14 +216,14 @@ module Asciidoctor
|
|
216
216
|
if (insert_toc = (doc.attr? 'toc') && !((toc_placement = doc.attr 'toc-placement') == 'macro' || toc_placement == 'preamble') && doc.sections?)
|
217
217
|
start_new_page if @ppbook && verso_page?
|
218
218
|
add_dest_for_block doc, id: 'toc', y: (at_page_top? ? page_height : nil)
|
219
|
-
allocate_toc doc, toc_num_levels, cursor,
|
219
|
+
allocate_toc doc, toc_num_levels, cursor, title_page_on
|
220
220
|
else
|
221
221
|
@toc_extent = nil
|
222
222
|
end
|
223
223
|
|
224
224
|
start_new_page if @ppbook && verso_page? && !(((next_block = doc.blocks[0])&.context == :preamble ? next_block.blocks[0] : next_block)&.option? 'nonfacing')
|
225
225
|
|
226
|
-
if
|
226
|
+
if title_page_on
|
227
227
|
zero_page_offset = has_front_cover ? 1 : 0
|
228
228
|
first_page_offset = has_title_page ? zero_page_offset.next : zero_page_offset
|
229
229
|
body_offset = (body_start_page_number = page_number) - 1
|
@@ -301,14 +301,14 @@ module Asciidoctor
|
|
301
301
|
traverse doc
|
302
302
|
|
303
303
|
# NOTE: for a book, these are leftover footnotes; for an article this is everything
|
304
|
-
outdent_section {
|
304
|
+
outdent_section { inscribe_footnotes doc }
|
305
305
|
|
306
306
|
if @toc_extent
|
307
|
-
if
|
307
|
+
if title_page_on && !insert_toc
|
308
308
|
num_front_matter_pages[0] = @toc_extent.to.page if @theme.running_content_start_at == 'after-toc'
|
309
309
|
num_front_matter_pages[1] = @toc_extent.to.page if @theme.page_numbering_start_at == 'after-toc'
|
310
310
|
end
|
311
|
-
toc_page_nums =
|
311
|
+
toc_page_nums = inscribe_toc doc, toc_num_levels, @toc_extent.from.page, @toc_extent.from.cursor, num_front_matter_pages[1]
|
312
312
|
else
|
313
313
|
toc_page_nums = []
|
314
314
|
end
|
@@ -319,8 +319,8 @@ module Asciidoctor
|
|
319
319
|
end
|
320
320
|
|
321
321
|
unless page_count < body_start_page_number
|
322
|
-
|
323
|
-
|
322
|
+
inscribe_running_content :header, doc, num_front_matter_pages, body_start_page_number unless doc.noheader || @theme.header_height.to_f == 0 # rubocop:disable Lint/FloatComparison
|
323
|
+
inscribe_running_content :footer, doc, num_front_matter_pages, body_start_page_number unless doc.nofooter || @theme.footer_height.to_f == 0 # rubocop:disable Lint/FloatComparison
|
324
324
|
end
|
325
325
|
|
326
326
|
add_outline doc, (doc.attr 'outlinelevels', toc_num_levels), toc_page_nums, num_front_matter_pages[1], has_front_cover
|
@@ -337,7 +337,7 @@ module Asciidoctor
|
|
337
337
|
catalog.data[:ViewerPreferences] = { DisplayDocTitle: true }
|
338
338
|
|
339
339
|
stamp_foreground_image doc, has_front_cover
|
340
|
-
|
340
|
+
inscribe_cover_page doc, :back
|
341
341
|
add_dest_for_top doc
|
342
342
|
nil
|
343
343
|
end
|
@@ -402,7 +402,7 @@ module Asciidoctor
|
|
402
402
|
@font_scale = 1
|
403
403
|
@font_color = theme.base_font_color
|
404
404
|
@text_decoration_width = theme.base_text_decoration_width
|
405
|
-
@
|
405
|
+
@base_text_align = (align = doc.attr 'text-align') && (TextAlignmentNames.include? align) ? align : theme.base_text_align
|
406
406
|
@base_line_height = theme.base_line_height
|
407
407
|
@cjk_line_breaks = doc.attr? 'scripts', 'cjk'
|
408
408
|
if (hyphen_lang = doc.attr 'hyphens') &&
|
@@ -415,6 +415,7 @@ module Asciidoctor
|
|
415
415
|
@text_transform = nil
|
416
416
|
@list_numerals = []
|
417
417
|
@list_bullets = []
|
418
|
+
@bottom_gutters = [{}]
|
418
419
|
@rendered_footnotes = []
|
419
420
|
@conum_glyphs = ConumSets[@theme.conum_glyphs || 'circled'] || (@theme.conum_glyphs.split ',').map do |r|
|
420
421
|
from, to = r.lstrip.split '-', 2
|
@@ -661,22 +662,23 @@ module Asciidoctor
|
|
661
662
|
title = %(#{title}\n<em class="subtitle">#{subtitle}</em>)
|
662
663
|
end
|
663
664
|
hlevel = sect.level + 1
|
664
|
-
align = (@theme[%(heading_h#{hlevel}
|
665
|
+
align = (@theme[%(heading_h#{hlevel}_text_align)] || @theme.heading_text_align || @base_text_align).to_sym
|
665
666
|
chapterlike = !(part = sectname == 'part') && (sectname == 'chapter' || (sect.document.doctype == 'book' && sect.level == 1))
|
666
|
-
|
667
|
+
hidden = sect.option? 'notitle'
|
668
|
+
hopts = { align: align, level: hlevel, part: part, chapterlike: chapterlike, outdent: !(part || chapterlike) }
|
667
669
|
if part
|
668
670
|
unless @theme.heading_part_break_before == 'auto'
|
669
671
|
start_new = true
|
670
|
-
|
672
|
+
start_new_part sect
|
671
673
|
end
|
672
674
|
elsif chapterlike
|
673
675
|
if @theme.heading_chapter_break_before != 'auto' ||
|
674
676
|
(@theme.heading_part_break_after == 'always' && sect == sect.parent.sections[0])
|
675
677
|
start_new = true
|
676
|
-
|
678
|
+
start_new_chapter sect
|
677
679
|
end
|
678
680
|
end
|
679
|
-
arrange_section sect, title, hopts unless start_new || at_page_top?
|
681
|
+
arrange_section sect, title, hopts unless hidden || start_new || at_page_top?
|
680
682
|
# QUESTION: should we store pdf-page-start, pdf-anchor & pdf-destination in internal map?
|
681
683
|
sect.set_attr 'pdf-page-start', (start_pgnum = page_number)
|
682
684
|
# QUESTION: should we just assign the section this generated id?
|
@@ -685,20 +687,20 @@ module Asciidoctor
|
|
685
687
|
add_dest_for_block sect, id: sect_anchor, y: (at_page_top? ? page_height : nil)
|
686
688
|
theme_font :heading, level: hlevel do
|
687
689
|
if part
|
688
|
-
|
690
|
+
inscribe_part_title sect, title, hopts
|
689
691
|
elsif chapterlike
|
690
|
-
|
692
|
+
inscribe_chapter_title sect, title, hopts
|
691
693
|
else
|
692
|
-
|
694
|
+
inscribe_general_heading sect, title, hopts
|
693
695
|
end
|
694
|
-
end
|
696
|
+
end unless hidden
|
695
697
|
|
696
698
|
if index_section
|
697
699
|
outdent_section { convert_index_section sect }
|
698
700
|
else
|
699
701
|
traverse sect
|
700
702
|
end
|
701
|
-
outdent_section {
|
703
|
+
outdent_section { inscribe_footnotes sect } if chapterlike
|
702
704
|
sect.set_attr 'pdf-page-end', page_number
|
703
705
|
end
|
704
706
|
|
@@ -719,7 +721,7 @@ module Asciidoctor
|
|
719
721
|
end
|
720
722
|
|
721
723
|
# QUESTION: if a footnote ref appears in a separate chapter, should the footnote def be duplicated?
|
722
|
-
def
|
724
|
+
def inscribe_footnotes node
|
723
725
|
return if (fns = (doc = node.document).footnotes - @rendered_footnotes).empty?
|
724
726
|
theme_margin :block, :bottom if node.context == :document || node == node.document.blocks[-1]
|
725
727
|
theme_margin :footnotes, :top
|
@@ -728,7 +730,7 @@ module Asciidoctor
|
|
728
730
|
move_down delta
|
729
731
|
end
|
730
732
|
theme_font :footnotes do
|
731
|
-
(title = doc.attr 'footnotes-title') && (
|
733
|
+
(title = doc.attr 'footnotes-title') && (inscribe_caption title, category: :footnotes)
|
732
734
|
item_spacing = @theme.footnotes_item_spacing
|
733
735
|
index_offset = @rendered_footnotes.length
|
734
736
|
sect_xreftext = node.context == :section && (node.xreftext node.document.attr 'xrefstyle')
|
@@ -738,7 +740,7 @@ module Asciidoctor
|
|
738
740
|
fn.singleton_class.send :attr_accessor, :label unless fn.respond_to? :label=
|
739
741
|
fn.label = %(#{label} - #{sect_xreftext})
|
740
742
|
end
|
741
|
-
|
743
|
+
inscribe_prose %(<a id="_footnotedef_#{index}">#{DummyText}</a>[<a anchor="_footnoteref_#{index}">#{label}</a>] #{fn.text}), margin_bottom: item_spacing, hyphenate: true
|
742
744
|
end
|
743
745
|
@rendered_footnotes += fns if extent
|
744
746
|
end
|
@@ -750,11 +752,11 @@ module Asciidoctor
|
|
750
752
|
add_dest_for_block node if node.id
|
751
753
|
hlevel = node.level.next
|
752
754
|
unless (align = resolve_alignment_from_role node.roles)
|
753
|
-
align = (@theme[%(heading_h#{hlevel}
|
755
|
+
align = (@theme[%(heading_h#{hlevel}_text_align)] || @theme.heading_text_align || @base_text_align).to_sym
|
754
756
|
end
|
755
757
|
# QUESTION: should we decouple styles from section titles?
|
756
758
|
theme_font :heading, level: hlevel do
|
757
|
-
|
759
|
+
inscribe_general_heading node, node.title, align: align, level: hlevel, outdent: (node.parent.context == :section)
|
758
760
|
end
|
759
761
|
end
|
760
762
|
|
@@ -763,10 +765,10 @@ module Asciidoctor
|
|
763
765
|
outdent_section do
|
764
766
|
pad_box @theme.abstract_padding do
|
765
767
|
theme_font :abstract_title do
|
766
|
-
|
768
|
+
inscribe_prose node.title, align: (@theme.abstract_title_text_align || @base_text_align).to_sym, margin_top: @theme.heading_margin_top, margin_bottom: @theme.heading_margin_bottom, line_height: (@theme.heading_line_height || @theme.base_line_height)
|
767
769
|
end if node.title?
|
768
770
|
theme_font :abstract do
|
769
|
-
prose_opts = { align: (@theme.
|
771
|
+
prose_opts = { align: (@theme.abstract_text_align || @base_text_align).to_sym, hyphenate: true }
|
770
772
|
if (text_indent = @theme.prose_text_indent) > 0
|
771
773
|
prose_opts[:indent_paragraphs] = text_indent
|
772
774
|
end
|
@@ -785,7 +787,7 @@ module Asciidoctor
|
|
785
787
|
if child.context == :paragraph
|
786
788
|
child.document.playback_attributes child.attributes
|
787
789
|
prose_opts[:margin_bottom] = 0 if child == last_block
|
788
|
-
|
790
|
+
inscribe_prose child.content, ((align = resolve_alignment_from_role child.roles) ? (prose_opts.merge align: align) : prose_opts.dup)
|
789
791
|
prose_opts.delete :first_line_options
|
790
792
|
prose_opts.delete :margin_bottom
|
791
793
|
else
|
@@ -797,7 +799,7 @@ module Asciidoctor
|
|
797
799
|
if (align = resolve_alignment_from_role node.roles)
|
798
800
|
prose_opts[:align] = align
|
799
801
|
end
|
800
|
-
|
802
|
+
inscribe_prose string, (prose_opts.merge margin_bottom: 0)
|
801
803
|
end
|
802
804
|
end
|
803
805
|
end
|
@@ -809,7 +811,7 @@ module Asciidoctor
|
|
809
811
|
def convert_preamble node
|
810
812
|
# FIXME: core should not be promoting paragraph to preamble if there are no sections
|
811
813
|
if node.blocks? && (first_block = node.blocks[0]).context == :paragraph && node.document.sections? && !first_block.role?
|
812
|
-
first_block.
|
814
|
+
first_block.role = 'lead'
|
813
815
|
end
|
814
816
|
traverse node
|
815
817
|
theme_margin :block, :bottom, (next_enclosed_block node)
|
@@ -832,13 +834,17 @@ module Asciidoctor
|
|
832
834
|
|
833
835
|
# TODO: check if we're within one line of the bottom of the page
|
834
836
|
# and advance to the next page if so (similar to logic for section titles)
|
835
|
-
|
837
|
+
inscribe_caption node, labeled: false if node.title?
|
838
|
+
|
839
|
+
if (bottom_gutter = @bottom_gutters[-1][node])
|
840
|
+
prose_opts[:bottom_gutter] = bottom_gutter
|
841
|
+
end
|
836
842
|
|
837
843
|
if roles.empty?
|
838
|
-
|
844
|
+
inscribe_prose node.content, prose_opts
|
839
845
|
else
|
840
846
|
theme_font_cascade (roles.map {|role| %(role_#{role}).to_sym }) do
|
841
|
-
|
847
|
+
inscribe_prose node.content, prose_opts
|
842
848
|
end
|
843
849
|
end
|
844
850
|
|
@@ -852,7 +858,7 @@ module Asciidoctor
|
|
852
858
|
|
853
859
|
def convert_admonition node
|
854
860
|
type = node.attr 'name'
|
855
|
-
label_align = @theme.
|
861
|
+
label_align = @theme.admonition_label_text_align&.to_sym || :center
|
856
862
|
# TODO: allow vertical_align to be a number
|
857
863
|
if (label_valign = @theme.admonition_label_vertical_align&.to_sym || :middle) == :middle
|
858
864
|
label_valign = :center
|
@@ -861,18 +867,21 @@ module Asciidoctor
|
|
861
867
|
label_min_width = label_min_width.to_f
|
862
868
|
end
|
863
869
|
if (doc = node.document).attr? 'icons'
|
864
|
-
if (
|
870
|
+
if !(has_icon = node.attr? 'icon') && (doc.attr 'icons') == 'font'
|
865
871
|
icons = 'font'
|
866
872
|
label_text = type.to_sym
|
867
873
|
icon_data = admonition_icon_data label_text
|
868
874
|
icon_size = icon_data[:size] || 24
|
869
875
|
label_width = label_min_width || (icon_size * 1.5)
|
870
|
-
elsif (icon_path =
|
876
|
+
elsif (icon_path = has_icon || !(icon_path = (@theme[%(admonition_icon_#{type})] || {})[:image]) ?
|
877
|
+
(resolve_icon_image_path node, type) :
|
878
|
+
(ThemeLoader.resolve_theme_asset (apply_subs_discretely doc, icon_path, subs: [:attributes]), @themesdir)) &&
|
879
|
+
(::File.readable? icon_path)
|
871
880
|
icons = true
|
872
881
|
# TODO: introduce @theme.admonition_image_width? or use size key from admonition_icon_<name>?
|
873
882
|
label_width = label_min_width || 36.0
|
874
883
|
else
|
875
|
-
log :warn, %(admonition icon not found or not readable: #{icon_path || (resolve_icon_image_path node, type, false)})
|
884
|
+
log :warn, %(admonition icon image#{has_icon ? '' : ' for ' + type.upcase} not found or not readable: #{icon_path || (resolve_icon_image_path node, type, false)})
|
876
885
|
end
|
877
886
|
end
|
878
887
|
unless icons
|
@@ -945,7 +954,7 @@ module Asciidoctor
|
|
945
954
|
log :warn, %(problem encountered in image: #{icon_path}; #{icon_warning})
|
946
955
|
end unless scratch?
|
947
956
|
rescue
|
948
|
-
log :warn, %(could not embed admonition icon: #{icon_path}; #{$!.message})
|
957
|
+
log :warn, %(could not embed admonition icon image: #{icon_path}; #{$!.message})
|
949
958
|
icons = nil
|
950
959
|
end
|
951
960
|
else
|
@@ -959,7 +968,7 @@ module Asciidoctor
|
|
959
968
|
end
|
960
969
|
embed_image image_obj, image_info, width: icon_width, position: label_align, vposition: label_valign
|
961
970
|
rescue
|
962
|
-
log :warn, %(could not embed admonition icon: #{icon_path}; #{$!.message})
|
971
|
+
log :warn, %(could not embed admonition icon image: #{icon_path}; #{$!.message})
|
963
972
|
icons = nil
|
964
973
|
end
|
965
974
|
end
|
@@ -987,7 +996,7 @@ module Asciidoctor
|
|
987
996
|
end
|
988
997
|
end
|
989
998
|
@text_transform = nil # already applied to label
|
990
|
-
|
999
|
+
inscribe_prose label_text,
|
991
1000
|
align: label_align,
|
992
1001
|
valign: label_valign,
|
993
1002
|
line_height: 1,
|
@@ -1000,8 +1009,8 @@ module Asciidoctor
|
|
1000
1009
|
end
|
1001
1010
|
end
|
1002
1011
|
end
|
1003
|
-
pad_box [cpad[0], 0, cpad[2], label_width + lpad[1] + cpad[3]] do
|
1004
|
-
|
1012
|
+
pad_box [cpad[0], 0, cpad[2], label_width + lpad[1] + cpad[3]], node do
|
1013
|
+
inscribe_caption node, category: :admonition, labeled: false if node.title?
|
1005
1014
|
theme_font :admonition do
|
1006
1015
|
traverse node
|
1007
1016
|
end
|
@@ -1018,7 +1027,7 @@ module Asciidoctor
|
|
1018
1027
|
tare_first_page_content_stream do
|
1019
1028
|
theme_fill_and_stroke_block :example, extent, caption_node: node
|
1020
1029
|
end
|
1021
|
-
pad_box @theme.example_padding do
|
1030
|
+
pad_box @theme.example_padding, node do
|
1022
1031
|
theme_font :example do
|
1023
1032
|
traverse node
|
1024
1033
|
end
|
@@ -1035,13 +1044,13 @@ module Asciidoctor
|
|
1035
1044
|
arrange_block node do
|
1036
1045
|
add_dest_for_block node if id
|
1037
1046
|
tare_first_page_content_stream do
|
1038
|
-
node.context == :example ? (
|
1047
|
+
node.context == :example ? (inscribe_caption %(\u25bc #{node.title})) : (inscribe_caption node, labeled: false)
|
1039
1048
|
end if has_title
|
1040
1049
|
traverse node
|
1041
1050
|
end
|
1042
1051
|
else
|
1043
1052
|
add_dest_for_block node if id
|
1044
|
-
node.context == :example ? (
|
1053
|
+
node.context == :example ? (inscribe_caption %(\u25bc #{node.title})) : (inscribe_caption node, labeled: false) if has_title
|
1045
1054
|
traverse node
|
1046
1055
|
end
|
1047
1056
|
end
|
@@ -1055,6 +1064,13 @@ module Asciidoctor
|
|
1055
1064
|
b_left_width = nil
|
1056
1065
|
b_width = nil if (b_width = @theme[%(#{category}_border_width)]) == 0
|
1057
1066
|
end
|
1067
|
+
if (attribution = (node.attr? 'attribution') && (node.attr 'attribution'))
|
1068
|
+
# NOTE: temporary workaround to allow bare & to be used without having to wrap value in single quotes
|
1069
|
+
attribution = escape_amp attribution if attribution.include? '&'
|
1070
|
+
if (citetitle = node.attr 'citetitle') && (citetitle.include? '&')
|
1071
|
+
citetitle = escape_amp citetitle
|
1072
|
+
end
|
1073
|
+
end
|
1058
1074
|
arrange_block node do |extent|
|
1059
1075
|
add_dest_for_block node if node.id
|
1060
1076
|
tare_first_page_content_stream do
|
@@ -1072,27 +1088,25 @@ module Asciidoctor
|
|
1072
1088
|
end
|
1073
1089
|
end
|
1074
1090
|
end
|
1075
|
-
pad_box @theme[%(#{category}_padding)] do
|
1091
|
+
pad_box @theme[%(#{category}_padding)], (attribution ? nil : node) do
|
1076
1092
|
theme_font category do
|
1077
1093
|
if category == :quote
|
1078
1094
|
traverse node
|
1079
1095
|
else # :verse
|
1080
1096
|
content = guard_indentation node.content
|
1081
|
-
|
1097
|
+
inscribe_prose content,
|
1098
|
+
normalize: false,
|
1099
|
+
align: :left,
|
1100
|
+
hyphenate: true,
|
1101
|
+
margin_bottom: 0,
|
1102
|
+
bottom_gutter: (attribution ? nil : @bottom_gutters[-1][node])
|
1082
1103
|
end
|
1083
1104
|
end
|
1084
|
-
if
|
1105
|
+
if attribution
|
1085
1106
|
margin_bottom @theme.block_margin_bottom
|
1086
1107
|
theme_font %(#{category}_cite) do
|
1087
|
-
|
1088
|
-
|
1089
|
-
attribution = escape_amp attribution if attribution.include? '&'
|
1090
|
-
attribution_parts = [attribution]
|
1091
|
-
if (citetitle = node.attr 'citetitle')
|
1092
|
-
citetitle = escape_amp citetitle if citetitle.include? '&'
|
1093
|
-
attribution_parts << citetitle
|
1094
|
-
end
|
1095
|
-
layout_prose %(#{EmDash} #{attribution_parts.join ', '}), align: :left, normalize: false, margin_bottom: 0
|
1108
|
+
attribution_parts = citetitle ? [attribution, citetitle] : [attribution]
|
1109
|
+
inscribe_prose %(#{EmDash} #{attribution_parts.join ', '}), align: :left, normalize: false, margin_bottom: 0
|
1096
1110
|
end
|
1097
1111
|
end
|
1098
1112
|
end
|
@@ -1107,10 +1121,10 @@ module Asciidoctor
|
|
1107
1121
|
arrange_block node do |extent|
|
1108
1122
|
add_dest_for_block node if node.id
|
1109
1123
|
theme_fill_and_stroke_block :sidebar, extent if extent
|
1110
|
-
pad_box @theme.sidebar_padding do
|
1124
|
+
pad_box @theme.sidebar_padding, node do
|
1111
1125
|
theme_font :sidebar_title do
|
1112
1126
|
# QUESTION: should we allow margins of sidebar title to be customized?
|
1113
|
-
|
1127
|
+
inscribe_prose node.title, align: (@theme.sidebar_title_text_align || @theme.heading_text_align || @base_text_align).to_sym, margin_bottom: @theme.heading_margin_bottom, line_height: (@theme.heading_line_height || @theme.base_line_height)
|
1114
1128
|
end if node.title?
|
1115
1129
|
theme_font :sidebar do
|
1116
1130
|
traverse node
|
@@ -1149,7 +1163,7 @@ module Asciidoctor
|
|
1149
1163
|
marker_width = rendered_width_of_string %(#{marker = conum_glyph index}x)
|
1150
1164
|
float do
|
1151
1165
|
bounding_box [0, cursor], width: marker_width do
|
1152
|
-
|
1166
|
+
inscribe_prose marker, align: :center, inline_format: false, margin: 0
|
1153
1167
|
end
|
1154
1168
|
end
|
1155
1169
|
end
|
@@ -1233,7 +1247,7 @@ module Asciidoctor
|
|
1233
1247
|
max_term_width += (term_padding[1] + term_padding[3])
|
1234
1248
|
term_column_width = [max_term_width, bounds.width * 0.5].min
|
1235
1249
|
table table_data, position: :left, cell_style: { border_width: 0 }, column_widths: [term_column_width] do
|
1236
|
-
@pdf.
|
1250
|
+
@pdf.inscribe_table_caption node if node.title?
|
1237
1251
|
end
|
1238
1252
|
theme_margin :prose, :bottom, (next_enclosed_block actual_node) #unless actual_node.nested?
|
1239
1253
|
when 'qanda'
|
@@ -1243,7 +1257,7 @@ module Asciidoctor
|
|
1243
1257
|
else
|
1244
1258
|
# TODO: check if we're within one line of the bottom of the page
|
1245
1259
|
# and advance to the next page if so (similar to logic for section titles)
|
1246
|
-
|
1260
|
+
inscribe_caption node, category: :description_list, labeled: false if node.title?
|
1247
1261
|
|
1248
1262
|
term_spacing = @theme.description_list_term_spacing
|
1249
1263
|
term_height = theme_font(:description_list_term) { height_of_typeset_text 'A' }
|
@@ -1255,8 +1269,8 @@ module Asciidoctor
|
|
1255
1269
|
term_font_styles = nil
|
1256
1270
|
end
|
1257
1271
|
terms.each_with_index do |term, idx|
|
1258
|
-
# QUESTION: should we pass down styles in other calls to
|
1259
|
-
|
1272
|
+
# QUESTION: should we pass down styles in other calls to inscribe_prose
|
1273
|
+
inscribe_prose term.text, margin_top: (idx > 0 ? term_spacing : 0), margin_bottom: 0, align: :left, normalize_line_height: true, styles: term_font_styles
|
1260
1274
|
end
|
1261
1275
|
end
|
1262
1276
|
indent @theme.description_list_description_indent do
|
@@ -1343,7 +1357,7 @@ module Asciidoctor
|
|
1343
1357
|
def convert_list node
|
1344
1358
|
# TODO: check if we're within one line of the bottom of the page
|
1345
1359
|
# and advance to the next page if so (similar to logic for section titles)
|
1346
|
-
|
1360
|
+
inscribe_caption node, category: :list, labeled: false if node.title?
|
1347
1361
|
|
1348
1362
|
opts = {}
|
1349
1363
|
if (align = resolve_alignment_from_role node.roles)
|
@@ -1440,7 +1454,7 @@ module Asciidoctor
|
|
1440
1454
|
float do
|
1441
1455
|
advance_page if @media == 'prepress' && cursor < marker_height
|
1442
1456
|
flow_bounding_box position: start_position, width: marker_width do
|
1443
|
-
|
1457
|
+
inscribe_prose marker,
|
1444
1458
|
align: :right,
|
1445
1459
|
character_spacing: -0.5,
|
1446
1460
|
color: marker_style[:font_color],
|
@@ -1468,16 +1482,16 @@ module Asciidoctor
|
|
1468
1482
|
def traverse_list_item node, list_type, opts = {}
|
1469
1483
|
if list_type == :dlist # qanda
|
1470
1484
|
terms, desc = node
|
1471
|
-
terms.each {|term|
|
1485
|
+
terms.each {|term| inscribe_prose %(<em>#{term.text}</em>), (opts.merge margin_bottom: @theme.description_list_term_spacing) }
|
1472
1486
|
if desc
|
1473
|
-
|
1487
|
+
inscribe_prose desc.text, (opts.merge hyphenate: true) if desc.text?
|
1474
1488
|
traverse desc
|
1475
1489
|
end
|
1476
1490
|
else
|
1477
1491
|
if (primary_text = node.text).nil_or_empty?
|
1478
|
-
|
1492
|
+
inscribe_prose DummyText, opts unless node.blocks?
|
1479
1493
|
else
|
1480
|
-
|
1494
|
+
inscribe_prose primary_text, (opts.merge hyphenate: true)
|
1481
1495
|
end
|
1482
1496
|
traverse node
|
1483
1497
|
end
|
@@ -1498,24 +1512,33 @@ module Asciidoctor
|
|
1498
1512
|
elsif (image_path = resolve_image_path node, target, image_format, (opts.fetch :relative_to_imagesdir, true))
|
1499
1513
|
if image_format == 'pdf'
|
1500
1514
|
if ::File.readable? image_path
|
1501
|
-
if (
|
1515
|
+
if (replace = page.empty?) && ((parent = node.parent).attr? 'pdf-page-start', page_number) && (parent.attr? 'pdf-anchor')
|
1516
|
+
replace_parent = parent
|
1517
|
+
end
|
1518
|
+
if (id = node.id) || replace_parent
|
1502
1519
|
add_dest_block = proc do
|
1503
|
-
|
1504
|
-
|
1520
|
+
node_dest = dest_top
|
1521
|
+
if id
|
1522
|
+
node.set_attr 'pdf-destination', node_dest
|
1523
|
+
add_dest id, node_dest
|
1524
|
+
end
|
1525
|
+
if replace_parent
|
1526
|
+
replace_parent.set_attr 'pdf-destination', node_dest
|
1527
|
+
add_dest (replace_parent.attr 'pdf-anchor'), node_dest
|
1528
|
+
end
|
1505
1529
|
end
|
1506
1530
|
end
|
1507
1531
|
# NOTE: import_page automatically advances to next page afterwards
|
1508
|
-
# QUESTION: should we add destination to top of imported page?
|
1509
1532
|
if (pgnums = node.attr 'pages')
|
1510
1533
|
(resolve_pagenums pgnums).each_with_index do |pgnum, idx|
|
1511
1534
|
if idx == 0
|
1512
|
-
import_page image_path, page: pgnum, replace:
|
1535
|
+
import_page image_path, page: pgnum, replace: replace, &add_dest_block
|
1513
1536
|
else
|
1514
1537
|
import_page image_path, page: pgnum, replace: true
|
1515
1538
|
end
|
1516
1539
|
end
|
1517
1540
|
else
|
1518
|
-
import_page image_path, page: [(node.attr 'page', nil, 1).to_i, 1].max, replace:
|
1541
|
+
import_page image_path, page: [(node.attr 'page', nil, 1).to_i, 1].max, replace: replace, &add_dest_block
|
1519
1542
|
end
|
1520
1543
|
return
|
1521
1544
|
else
|
@@ -1532,14 +1555,14 @@ module Asciidoctor
|
|
1532
1555
|
|
1533
1556
|
alignment = (alignment = node.attr 'align') ?
|
1534
1557
|
((BlockAlignmentNames.include? alignment) ? alignment.to_sym : :left) :
|
1535
|
-
(resolve_alignment_from_role node.roles) ||
|
1558
|
+
(resolve_alignment_from_role node.roles) || @theme.image_align&.to_sym || :left
|
1536
1559
|
# TODO: support cover (aka canvas) image layout using "canvas" (or "cover") role
|
1537
1560
|
width = resolve_explicit_width node.attributes, bounds_width: (available_w = bounds.width), support_vw: true, use_fallback: true, constrain_to_bounds: true
|
1538
1561
|
# TODO: add `to_pt page_width` method to ViewportWidth type
|
1539
1562
|
width = (width.to_f / 100) * page_width if ViewportWidth === width
|
1540
1563
|
|
1541
1564
|
# NOTE: if width is not set explicitly and max-width is fit-content, caption height may not be accurate
|
1542
|
-
caption_h = node.title? ? (
|
1565
|
+
caption_h = node.title? ? (inscribe_caption node, category: :image, side: :bottom, block_align: alignment, block_width: width, max_width: @theme.image_caption_max_width, dry_run: true, force_top_margin: true) : 0
|
1543
1566
|
|
1544
1567
|
align_to_page = node.option? 'align-to-page'
|
1545
1568
|
pinned = opts[:pinned]
|
@@ -1622,7 +1645,7 @@ module Asciidoctor
|
|
1622
1645
|
move_down rendered_h if y == image_y
|
1623
1646
|
end
|
1624
1647
|
end
|
1625
|
-
|
1648
|
+
inscribe_caption node, category: :image, side: :bottom, block_align: alignment, block_width: rendered_w, max_width: @theme.image_caption_max_width if node.title?
|
1626
1649
|
theme_margin :block, :bottom, (next_enclosed_block node) unless pinned
|
1627
1650
|
rescue => e
|
1628
1651
|
raise if ::StopIteration === e
|
@@ -1662,9 +1685,9 @@ module Asciidoctor
|
|
1662
1685
|
alignment = (alignment = node.attr 'align') ?
|
1663
1686
|
((BlockAlignmentNames.include? alignment) ? alignment.to_sym : :left) :
|
1664
1687
|
(resolve_alignment_from_role node.roles) || (@theme.image_align&.to_sym || :left)
|
1665
|
-
|
1688
|
+
inscribe_prose alt_text_template % alt_text_vars, align: alignment, margin: 0, normalize: false, single_line: true
|
1666
1689
|
end
|
1667
|
-
|
1690
|
+
inscribe_caption node, category: :image, side: :bottom if node.title?
|
1668
1691
|
theme_margin :block, :bottom, (next_enclosed_block node) unless opts[:pinned]
|
1669
1692
|
nil
|
1670
1693
|
end
|
@@ -1673,8 +1696,8 @@ module Asciidoctor
|
|
1673
1696
|
add_dest_for_block node if node.id
|
1674
1697
|
audio_path = node.media_uri node.attr 'target'
|
1675
1698
|
play_symbol = (node.document.attr? 'icons', 'font') ? %(<font name="fas">#{(icon_font_data 'fas').unicode 'play'}</font>) : RightPointer
|
1676
|
-
|
1677
|
-
|
1699
|
+
inscribe_prose %(#{play_symbol}#{NoBreakSpace}<a href="#{audio_path}">#{audio_path}</a> <em>(audio)</em>), normalize: false, margin: 0, single_line: true
|
1700
|
+
inscribe_caption node, labeled: false, side: :bottom if node.title?
|
1678
1701
|
theme_margin :block, :bottom, (next_enclosed_block node)
|
1679
1702
|
end
|
1680
1703
|
|
@@ -1701,8 +1724,8 @@ module Asciidoctor
|
|
1701
1724
|
if poster.nil_or_empty?
|
1702
1725
|
add_dest_for_block node if node.id
|
1703
1726
|
play_symbol = (node.document.attr? 'icons', 'font') ? %(<font name="fas">#{(icon_font_data 'fas').unicode 'play'}</font>) : RightPointer
|
1704
|
-
|
1705
|
-
|
1727
|
+
inscribe_prose %(#{play_symbol}#{NoBreakSpace}<a href="#{video_path}">#{video_path}</a> <em>(#{type})</em>), normalize: false, margin: 0, single_line: true
|
1728
|
+
inscribe_caption node, labeled: false, side: :bottom if node.title?
|
1706
1729
|
theme_margin :block, :bottom, (next_enclosed_block node)
|
1707
1730
|
else
|
1708
1731
|
original_attributes = node.attributes.dup
|
@@ -1717,7 +1740,8 @@ module Asciidoctor
|
|
1717
1740
|
|
1718
1741
|
# QUESTION: can we avoid arranging fragments multiple times (conums & autofit) by eagerly preparing arranger?
|
1719
1742
|
def convert_listing_or_literal node
|
1720
|
-
|
1743
|
+
extensions = []
|
1744
|
+
source_chunks = bg_color_override = font_color_override = adjusted_font_size = nil
|
1721
1745
|
theme_font :code do
|
1722
1746
|
# HACK: disable built-in syntax highlighter; must be done before calling node.content!
|
1723
1747
|
if node.style == 'source' && (highlighter = (syntax_hl = node.document.syntax_highlighter)&.highlight? && syntax_hl.name)
|
@@ -1797,7 +1821,7 @@ module Asciidoctor
|
|
1797
1821
|
if (node.option? 'linenums') || (node.attr? 'linenums')
|
1798
1822
|
linenums = (node.attr 'start', 1).to_i
|
1799
1823
|
postprocess = true
|
1800
|
-
|
1824
|
+
extensions << FormattedText::SourceWrap
|
1801
1825
|
elsif conum_mapping || highlight_lines
|
1802
1826
|
postprocess = true
|
1803
1827
|
end
|
@@ -1814,7 +1838,7 @@ module Asciidoctor
|
|
1814
1838
|
else
|
1815
1839
|
if (node.option? 'linenums') || (node.attr? 'linenums')
|
1816
1840
|
formatter_opts = { line_numbers: true, start_line: (node.attr 'start', 1).to_i }
|
1817
|
-
|
1841
|
+
extensions << FormattedText::SourceWrap
|
1818
1842
|
else
|
1819
1843
|
formatter_opts = {}
|
1820
1844
|
end
|
@@ -1848,14 +1872,13 @@ module Asciidoctor
|
|
1848
1872
|
tare_first_page_content_stream do
|
1849
1873
|
theme_fill_and_stroke_block :code, extent, background_color: bg_color_override, caption_node: node
|
1850
1874
|
end
|
1851
|
-
pad_box @theme.code_padding do
|
1875
|
+
pad_box @theme.code_padding, node do
|
1852
1876
|
theme_font :code do
|
1853
|
-
::Prawn::Text::Formatted::Box.extensions << wrap_ext if wrap_ext
|
1854
1877
|
typeset_formatted_text source_chunks, (calc_line_metrics @base_line_height),
|
1855
1878
|
color: (font_color_override || @theme.code_font_color || @font_color),
|
1856
|
-
size: adjusted_font_size
|
1857
|
-
|
1858
|
-
|
1879
|
+
size: adjusted_font_size,
|
1880
|
+
bottom_gutter: @bottom_gutters[-1][node],
|
1881
|
+
extensions: extensions.empty? ? nil : extensions
|
1859
1882
|
end
|
1860
1883
|
end
|
1861
1884
|
end
|
@@ -2159,45 +2182,36 @@ module Asciidoctor
|
|
2159
2182
|
end
|
2160
2183
|
end
|
2161
2184
|
|
2162
|
-
# NOTE: Prawn
|
2185
|
+
# NOTE: Prawn crashes if table data is empty, so ensure there's at least one row
|
2163
2186
|
if table_data.empty?
|
2164
2187
|
log(:warn) { message_with_context 'no rows found in table', source_location: node.source_location }
|
2165
2188
|
table_data << ::Array.new([node.columns.size, 1].max) { { content: '' } }
|
2166
2189
|
end
|
2167
2190
|
|
2168
|
-
|
2169
|
-
|
2170
|
-
|
2171
|
-
|
2172
|
-
|
2173
|
-
|
2174
|
-
|
2175
|
-
|
2176
|
-
end
|
2177
|
-
[:top, :bottom, :left, :right].each {|edge| border_width[edge] = table_border_width }
|
2191
|
+
rect_side_names = [:top, :right, :bottom, :left]
|
2192
|
+
grid_axis_names = [:rows, :cols]
|
2193
|
+
border_color = (rect_side_names.zip expand_rect_values theme.table_border_color, (theme.base_border_color || 'transparent')).to_h
|
2194
|
+
border_style = (rect_side_names.zip (expand_rect_values theme.table_border_style, :solid).map(&:to_sym)).to_h
|
2195
|
+
border_width = (rect_side_names.zip expand_rect_values theme.table_border_width, 0).to_h
|
2196
|
+
grid_color = (grid_axis_names.zip expand_grid_values (theme.table_grid_color || [border_color[:top], border_color[:left]]), 'transparent').to_h
|
2197
|
+
grid_style = (grid_axis_names.zip (expand_grid_values (theme.table_grid_style || [border_style[:top], border_style[:left]]), :solid).map(&:to_sym)).to_h
|
2198
|
+
grid_width = (grid_axis_names.zip expand_grid_values theme.table_grid_width, 0).to_h
|
2178
2199
|
|
2179
|
-
|
2180
|
-
|
2181
|
-
|
2182
|
-
|
2183
|
-
table_grid_style = [table_grid_style.to_sym]
|
2184
|
-
end
|
2185
|
-
if ::Array === (table_grid_width = theme.table_grid_width || theme.table_border_width)
|
2186
|
-
border_width[:rows] = table_grid_width[0]
|
2187
|
-
border_width[:cols] = table_grid_width[1]
|
2188
|
-
else
|
2189
|
-
[:cols, :rows].each {|edge| border_width[edge] = table_grid_width }
|
2200
|
+
if table_header_size
|
2201
|
+
head_border_bottom_color = theme.table_head_border_bottom_color || grid_color[:rows]
|
2202
|
+
head_border_bottom_style = theme.table_head_border_bottom_style&.to_sym || grid_style[:rows]
|
2203
|
+
head_border_bottom_width = theme.table_head_border_bottom_width || grid_width[:rows]
|
2190
2204
|
end
|
2191
2205
|
|
2192
2206
|
case (grid = node.attr 'grid', 'all', 'table-grid')
|
2193
2207
|
when 'all'
|
2194
2208
|
# keep inner borders
|
2195
2209
|
when 'cols'
|
2196
|
-
|
2210
|
+
grid_width[:rows] = 0
|
2197
2211
|
when 'rows'
|
2198
|
-
|
2212
|
+
grid_width[:cols] = 0
|
2199
2213
|
else # none
|
2200
|
-
|
2214
|
+
grid_width[:rows] = grid_width[:cols] = 0
|
2201
2215
|
end
|
2202
2216
|
|
2203
2217
|
case (frame = node.attr 'frame', 'all', 'table-frame')
|
@@ -2234,13 +2248,8 @@ module Asciidoctor
|
|
2234
2248
|
header: table_header_size,
|
2235
2249
|
# NOTE: position is handled by this method
|
2236
2250
|
position: :left,
|
2237
|
-
|
2238
|
-
|
2239
|
-
border_color: table_grid_color,
|
2240
|
-
border_lines: table_grid_style,
|
2241
|
-
# NOTE: the border width is set later
|
2242
|
-
border_width: 0,
|
2243
|
-
},
|
2251
|
+
# NOTE: the border color, style, and width of the outer frame is set in the table callback block
|
2252
|
+
cell_style: { border_color: grid_color.values, border_lines: grid_style.values, border_width: grid_width.values },
|
2244
2253
|
width: table_width,
|
2245
2254
|
column_widths: column_widths,
|
2246
2255
|
}
|
@@ -2261,7 +2270,7 @@ module Asciidoctor
|
|
2261
2270
|
table table_data, table_settings do
|
2262
2271
|
# NOTE: call width to capture resolved table width
|
2263
2272
|
table_width = width
|
2264
|
-
@pdf.
|
2273
|
+
@pdf.inscribe_table_caption node, alignment, table_width, caption_max_width if node.title? && caption_side == :top
|
2265
2274
|
# NOTE: align using padding instead of bounding_box as prawn-table does
|
2266
2275
|
# using a bounding_box across pages mangles the margin box of subsequent pages
|
2267
2276
|
if alignment != :left && table_width != (this_bounds = @pdf.bounds).width
|
@@ -2282,7 +2291,7 @@ module Asciidoctor
|
|
2282
2291
|
end if table_header_size
|
2283
2292
|
else
|
2284
2293
|
# apply the grid setting first across all cells
|
2285
|
-
cells.border_width = [
|
2294
|
+
cells.border_width = [grid_width[:rows], grid_width[:cols], grid_width[:rows], grid_width[:cols]]
|
2286
2295
|
|
2287
2296
|
if table_header_size
|
2288
2297
|
(rows table_header_size - 1).tap do |r|
|
@@ -2299,19 +2308,19 @@ module Asciidoctor
|
|
2299
2308
|
|
2300
2309
|
# top edge of table
|
2301
2310
|
(rows 0).tap do |r|
|
2302
|
-
r.border_top_color, r.border_top_line, r.border_top_width =
|
2311
|
+
r.border_top_color, r.border_top_line, r.border_top_width = border_color[:top], border_style[:top], border_width[:top]
|
2303
2312
|
end
|
2304
2313
|
# right edge of table
|
2305
2314
|
(columns num_cols - 1).tap do |r|
|
2306
|
-
r.border_right_color, r.border_right_line, r.border_right_width =
|
2315
|
+
r.border_right_color, r.border_right_line, r.border_right_width = border_color[:right], border_style[:right], border_width[:right]
|
2307
2316
|
end
|
2308
2317
|
# bottom edge of table
|
2309
2318
|
(rows num_rows - 1).tap do |r|
|
2310
|
-
r.border_bottom_color, r.border_bottom_line, r.border_bottom_width =
|
2319
|
+
r.border_bottom_color, r.border_bottom_line, r.border_bottom_width = border_color[:bottom], border_style[:bottom], border_width[:bottom]
|
2311
2320
|
end
|
2312
2321
|
# left edge of table
|
2313
2322
|
(columns 0).tap do |r|
|
2314
|
-
r.border_left_color, r.border_left_line, r.border_left_width =
|
2323
|
+
r.border_left_color, r.border_left_line, r.border_left_width = border_color[:left], border_style[:left], border_width[:left]
|
2315
2324
|
end
|
2316
2325
|
end
|
2317
2326
|
|
@@ -2334,7 +2343,7 @@ module Asciidoctor
|
|
2334
2343
|
bounds.subtract_left_padding left_padding
|
2335
2344
|
bounds.subtract_right_padding right_padding if right_padding
|
2336
2345
|
end
|
2337
|
-
|
2346
|
+
inscribe_table_caption node, alignment, table_width, caption_max_width, caption_side if node.title? && caption_side == :bottom
|
2338
2347
|
theme_margin :block, :bottom, (next_enclosed_block node)
|
2339
2348
|
rescue ::Prawn::Errors::CannotFit
|
2340
2349
|
log :error, (message_with_context 'cannot fit contents of table cell into specified column width', source_location: node.source_location)
|
@@ -2356,8 +2365,8 @@ module Asciidoctor
|
|
2356
2365
|
start_new_page if @ppbook && verso_page? && !(is_macro && (node.option? 'nonfacing'))
|
2357
2366
|
end
|
2358
2367
|
add_dest_for_block node, id: (node.id || 'toc') if is_macro
|
2359
|
-
allocate_toc doc, (doc.attr 'toclevels', 2).to_i, cursor, (
|
2360
|
-
@index.start_page_number = @toc_extent.to.page + 1 if
|
2368
|
+
allocate_toc doc, (doc.attr 'toclevels', 2).to_i, cursor, (title_page_on = is_book || (doc.attr? 'title-page'))
|
2369
|
+
@index.start_page_number = @toc_extent.to.page + 1 if title_page_on && @theme.page_numbering_start_at == 'after-toc'
|
2361
2370
|
if is_macro
|
2362
2371
|
@disable_running_content[:header] += @toc_extent.page_range if node.option? 'noheader'
|
2363
2372
|
@disable_running_content[:footer] += @toc_extent.page_range if node.option? 'nofooter'
|
@@ -2398,7 +2407,7 @@ module Asciidoctor
|
|
2398
2407
|
@index.categories.each do |category|
|
2399
2408
|
# NOTE: cursor method always returns 0 inside column_box; breaks reference_bounds.move_past_bottom
|
2400
2409
|
bounds.move_past_bottom if space_needed_for_category > y - reference_bounds.absolute_bottom
|
2401
|
-
|
2410
|
+
inscribe_prose category.name,
|
2402
2411
|
align: :left,
|
2403
2412
|
inline_format: false,
|
2404
2413
|
margin_bottom: @theme.description_list_term_spacing,
|
@@ -2426,7 +2435,7 @@ module Asciidoctor
|
|
2426
2435
|
text = %(#{text}, #{pagenums.join ', '})
|
2427
2436
|
end
|
2428
2437
|
subterm_indent = @theme.description_list_description_indent
|
2429
|
-
|
2438
|
+
inscribe_prose text, align: :left, margin: 0, hanging_indent: subterm_indent * 2
|
2430
2439
|
indent subterm_indent do
|
2431
2440
|
term.subterms.each do |subterm|
|
2432
2441
|
convert_index_list_item subterm
|
@@ -2527,14 +2536,14 @@ module Asciidoctor
|
|
2527
2536
|
end
|
2528
2537
|
|
2529
2538
|
def convert_inline_icon node
|
2530
|
-
if node.document.attr
|
2539
|
+
if (icons = (doc = node.document).attr 'icons') == 'font'
|
2531
2540
|
if (icon_name = node.target).include? '@'
|
2532
2541
|
icon_name, icon_set = icon_name.split '@', 2
|
2533
2542
|
explicit_icon_set = true
|
2534
2543
|
elsif (icon_set = node.attr 'set')
|
2535
2544
|
explicit_icon_set = true
|
2536
2545
|
else
|
2537
|
-
icon_set =
|
2546
|
+
icon_set = doc.attr 'icon-set', 'fa'
|
2538
2547
|
end
|
2539
2548
|
if icon_set == 'fa' || !(IconSets.include? icon_set)
|
2540
2549
|
icon_set = 'fa'
|
@@ -2580,6 +2589,14 @@ module Asciidoctor
|
|
2580
2589
|
log :warn, %(#{icon_name} is not a valid icon name in the #{icon_set} icon set)
|
2581
2590
|
%([#{node.attr 'alt'}])
|
2582
2591
|
end
|
2592
|
+
elsif icons
|
2593
|
+
image_path = ::File.absolute_path %(#{icon_name = node.target}.#{image_format = doc.attr 'icontype', 'png'}), (doc.attr 'iconsdir')
|
2594
|
+
if ::File.readable? image_path
|
2595
|
+
%(<img src="#{image_path}" format="#{image_format}" alt="#{node.attr 'alt'}" fit="line">)
|
2596
|
+
else
|
2597
|
+
log :warn, %(image icon for '#{icon_name}' not found or not readable: #{image_path})
|
2598
|
+
%([#{icon_name}])
|
2599
|
+
end
|
2583
2600
|
else
|
2584
2601
|
%([#{node.attr 'alt'}])
|
2585
2602
|
end
|
@@ -2616,15 +2633,16 @@ module Asciidoctor
|
|
2616
2633
|
end
|
2617
2634
|
|
2618
2635
|
def convert_inline_indexterm node
|
2636
|
+
visible = node.type == :visible
|
2619
2637
|
if scratch?
|
2620
|
-
|
2638
|
+
visible ? node.text : ''
|
2621
2639
|
else
|
2622
2640
|
# NOTE: initialize index in case converter is called before PDF is initialized
|
2623
2641
|
@index ||= IndexCatalog.new
|
2624
2642
|
# NOTE: page number (:page key) is added by InlineDestinationMarker
|
2625
2643
|
dest = { anchor: (anchor_name = @index.next_anchor_name) }
|
2626
|
-
anchor = %(<a id="#{anchor_name}" type="indexterm">#{DummyText}</a>)
|
2627
|
-
if
|
2644
|
+
anchor = %(<a id="#{anchor_name}" type="indexterm"#{visible ? ' visible="true"' : ''}>#{DummyText}</a>)
|
2645
|
+
if visible
|
2628
2646
|
visible_term = node.text
|
2629
2647
|
@index.store_primary_term (sanitize visible_term), dest
|
2630
2648
|
%(#{anchor}#{visible_term})
|
@@ -2671,8 +2689,10 @@ module Asciidoctor
|
|
2671
2689
|
open, close, is_tag = ['<sub>', '</sub>', true]
|
2672
2690
|
when :double
|
2673
2691
|
open, close, is_tag = [theme.quotes[0], theme.quotes[1], false]
|
2692
|
+
quotes = true
|
2674
2693
|
when :single
|
2675
2694
|
open, close, is_tag = [theme.quotes[2], theme.quotes[3], false]
|
2695
|
+
quotes = true
|
2676
2696
|
when :mark
|
2677
2697
|
open, close, is_tag = ['<mark>', '</mark>', true]
|
2678
2698
|
else
|
@@ -2681,6 +2701,11 @@ module Asciidoctor
|
|
2681
2701
|
|
2682
2702
|
inner_text = node.text
|
2683
2703
|
|
2704
|
+
if quotes && (len = inner_text.length) > 3 &&
|
2705
|
+
(inner_text.end_with? '...') && !((inner_text_trunc = inner_text.slice 0, len - 3).end_with? ?\\)
|
2706
|
+
inner_text = inner_text_trunc + '…'
|
2707
|
+
end
|
2708
|
+
|
2684
2709
|
if (roles = node.role)
|
2685
2710
|
roles.split.each do |role|
|
2686
2711
|
if (text_transform = theme[%(role_#{role}_text_transform)])
|
@@ -2697,7 +2722,8 @@ module Asciidoctor
|
|
2697
2722
|
node.id ? %(<a id="#{node.id}">#{DummyText}</a>#{quoted_text}) : quoted_text
|
2698
2723
|
end
|
2699
2724
|
|
2700
|
-
|
2725
|
+
# Returns a Boolean indicating whether the title page was created
|
2726
|
+
def inscribe_title_page doc
|
2701
2727
|
return unless doc.header? && !doc.notitle && @theme.title_page != false
|
2702
2728
|
|
2703
2729
|
# NOTE: a new page may have already been started at this point, so decide what to do with it
|
@@ -2724,7 +2750,7 @@ module Asciidoctor
|
|
2724
2750
|
font @theme.base_font_family, size: @root_font_size, style: @theme.base_font_style
|
2725
2751
|
|
2726
2752
|
# QUESTION: allow alignment per element on title page?
|
2727
|
-
title_align = (@theme.
|
2753
|
+
title_align = (@theme.title_page_text_align || @base_text_align).to_sym
|
2728
2754
|
|
2729
2755
|
if @theme.title_page_logo_display != 'none' && (logo_image_path = (doc.attr 'title-logo-image') || (logo_image_from_theme = @theme.title_page_logo_image))
|
2730
2756
|
if (logo_image_path.include? ':') && logo_image_path =~ ImageAttributeValueRx
|
@@ -2773,7 +2799,7 @@ module Asciidoctor
|
|
2773
2799
|
move_down @theme.title_page_title_margin_top || 0
|
2774
2800
|
indent (@theme.title_page_title_margin_left || 0), (@theme.title_page_title_margin_right || 0) do
|
2775
2801
|
theme_font :title_page_title do
|
2776
|
-
|
2802
|
+
inscribe_prose doctitle.main, align: title_align, margin: 0
|
2777
2803
|
end
|
2778
2804
|
end
|
2779
2805
|
move_down @theme.title_page_title_margin_bottom || 0
|
@@ -2782,7 +2808,7 @@ module Asciidoctor
|
|
2782
2808
|
move_down @theme.title_page_subtitle_margin_top || 0
|
2783
2809
|
indent (@theme.title_page_subtitle_margin_left || 0), (@theme.title_page_subtitle_margin_right || 0) do
|
2784
2810
|
theme_font :title_page_subtitle do
|
2785
|
-
|
2811
|
+
inscribe_prose subtitle, align: title_align, margin: 0
|
2786
2812
|
end
|
2787
2813
|
end
|
2788
2814
|
move_down @theme.title_page_subtitle_margin_bottom || 0
|
@@ -2807,7 +2833,7 @@ module Asciidoctor
|
|
2807
2833
|
end
|
2808
2834
|
end.join @theme.title_page_authors_delimiter
|
2809
2835
|
theme_font :title_page_authors do
|
2810
|
-
|
2836
|
+
inscribe_prose authors, align: title_align, margin: 0, normalize: true
|
2811
2837
|
end
|
2812
2838
|
end
|
2813
2839
|
move_down @theme.title_page_authors_margin_bottom || 0
|
@@ -2820,17 +2846,18 @@ module Asciidoctor
|
|
2820
2846
|
end
|
2821
2847
|
indent (@theme.title_page_revision_margin_left || 0), (@theme.title_page_revision_margin_right || 0) do
|
2822
2848
|
theme_font :title_page_revision do
|
2823
|
-
|
2849
|
+
inscribe_prose revision_text, align: title_align, margin: 0, normalize: false
|
2824
2850
|
end
|
2825
2851
|
end
|
2826
2852
|
move_down @theme.title_page_revision_margin_bottom || 0
|
2827
2853
|
end
|
2828
2854
|
end
|
2829
2855
|
|
2830
|
-
|
2856
|
+
inscribe_prose DummyText, margin: 0, line_height: 1, normalize: false if page.empty?
|
2857
|
+
true
|
2831
2858
|
end
|
2832
2859
|
|
2833
|
-
def
|
2860
|
+
def inscribe_cover_page doc, face
|
2834
2861
|
image_path, image_opts = resolve_background_image doc, @theme, %(#{face}-cover-image), theme_key: %(cover_#{face}_image).to_sym, symbolic_paths: ['', '~']
|
2835
2862
|
if image_path
|
2836
2863
|
if image_path.empty?
|
@@ -2876,37 +2903,58 @@ module Asciidoctor
|
|
2876
2903
|
|
2877
2904
|
def start_new_chapter chapter
|
2878
2905
|
start_new_page unless at_page_top?
|
2879
|
-
# TODO: must call update_colors before advancing to next page if start_new_page is called in
|
2906
|
+
# TODO: must call update_colors before advancing to next page if start_new_page is called in inscribe_chapter_title
|
2880
2907
|
start_new_page if @ppbook && verso_page? && !(chapter.option? 'nonfacing')
|
2881
2908
|
end
|
2882
2909
|
|
2883
2910
|
alias start_new_part start_new_chapter
|
2884
2911
|
|
2885
2912
|
def arrange_section sect, title, opts
|
2886
|
-
|
2887
|
-
|
2888
|
-
|
2889
|
-
|
2890
|
-
|
2891
|
-
|
2892
|
-
|
2893
|
-
|
2894
|
-
|
2913
|
+
if sect.option? 'breakable'
|
2914
|
+
orphaned = nil
|
2915
|
+
dry_run single_page: true do
|
2916
|
+
start_page = page
|
2917
|
+
theme_font :heading, level: opts[:level] do
|
2918
|
+
if opts[:part]
|
2919
|
+
inscribe_part_title sect, title, opts
|
2920
|
+
elsif opts[:chapterlike]
|
2921
|
+
inscribe_chapter_title sect, title, opts
|
2922
|
+
else
|
2923
|
+
inscribe_general_heading sect, title, opts
|
2924
|
+
end
|
2925
|
+
end
|
2926
|
+
if page == start_page
|
2927
|
+
page.tare_content_stream
|
2928
|
+
orphaned = stop_if_first_page_empty { traverse sect }
|
2929
|
+
end
|
2930
|
+
end
|
2931
|
+
start_new_page if orphaned
|
2932
|
+
else
|
2933
|
+
theme_font :heading, level: (hlevel = opts[:level]) do
|
2934
|
+
# FIXME: this height doesn't account for impact of text transform or inline formatting
|
2935
|
+
heading_height =
|
2936
|
+
(height_of_typeset_text title) +
|
2937
|
+
(@theme[%(heading_h#{hlevel}_margin_top)] || @theme.heading_margin_top) +
|
2938
|
+
(@theme[%(heading_h#{hlevel}_margin_bottom)] || @theme.heading_margin_bottom)
|
2939
|
+
heading_height += @theme.heading_min_height_after if sect.blocks? && @theme.heading_min_height_after
|
2940
|
+
start_new_page unless cursor > heading_height
|
2941
|
+
end
|
2895
2942
|
end
|
2943
|
+
nil
|
2896
2944
|
end
|
2897
2945
|
|
2898
|
-
def
|
2899
|
-
|
2946
|
+
def inscribe_chapter_title node, title, opts = {}
|
2947
|
+
inscribe_general_heading node, title, (opts.merge outdent: true)
|
2900
2948
|
end
|
2901
2949
|
|
2902
|
-
alias
|
2950
|
+
alias inscribe_part_title inscribe_chapter_title
|
2903
2951
|
|
2904
|
-
def
|
2905
|
-
|
2952
|
+
def inscribe_general_heading _node, title, opts = {}
|
2953
|
+
inscribe_heading title, opts
|
2906
2954
|
end
|
2907
2955
|
|
2908
|
-
# NOTE:
|
2909
|
-
def
|
2956
|
+
# NOTE: inscribe_heading doesn't set the theme font because it's used for various types of headings
|
2957
|
+
def inscribe_heading string, opts = {}
|
2910
2958
|
hlevel = opts[:level]
|
2911
2959
|
unless (top_margin = (margin = (opts.delete :margin)) || (opts.delete :margin_top))
|
2912
2960
|
if at_page_top?
|
@@ -2933,14 +2981,14 @@ module Asciidoctor
|
|
2933
2981
|
typeset_text string, (calc_line_metrics (opts.delete :line_height) || @base_line_height), {
|
2934
2982
|
color: @font_color,
|
2935
2983
|
inline_format: inline_format_opts,
|
2936
|
-
align: @
|
2984
|
+
align: @base_text_align.to_sym,
|
2937
2985
|
}.merge(opts)
|
2938
2986
|
margin_bottom bot_margin
|
2939
2987
|
end
|
2940
2988
|
end
|
2941
2989
|
|
2942
2990
|
# NOTE: inline_format is true by default
|
2943
|
-
def
|
2991
|
+
def inscribe_prose string, opts = {}
|
2944
2992
|
top_margin = (margin = (opts.delete :margin)) || (opts.delete :margin_top) || 0
|
2945
2993
|
bot_margin = margin || (opts.delete :margin_bottom) || @theme.prose_margin_bottom
|
2946
2994
|
if (transform = resolve_text_transform opts)
|
@@ -2964,7 +3012,7 @@ module Asciidoctor
|
|
2964
3012
|
typeset_text string, (calc_line_metrics (opts.delete :line_height) || @base_line_height), {
|
2965
3013
|
color: @font_color,
|
2966
3014
|
inline_format: [inline_format_opts],
|
2967
|
-
align: @
|
3015
|
+
align: @base_text_align.to_sym,
|
2968
3016
|
}.merge(opts)
|
2969
3017
|
margin_bottom bot_margin
|
2970
3018
|
end
|
@@ -2987,13 +3035,13 @@ module Asciidoctor
|
|
2987
3035
|
# The subject argument can either be a String or an AbstractNode. If
|
2988
3036
|
# subject is an AbstractNode, only call this method if the node has a
|
2989
3037
|
# title (i.e., subject.title? returns true).
|
2990
|
-
def
|
3038
|
+
def inscribe_caption subject, opts = {}
|
2991
3039
|
if opts.delete :dry_run
|
2992
3040
|
force_top_margin = !at_page_top? if (force_top_margin = opts.delete :force_top_margin).nil?
|
2993
3041
|
return (dry_run keep_together: true, single_page: :enforce do
|
2994
3042
|
# TODO: encapsulate this logic to force top margin to be applied
|
2995
3043
|
margin_box.instance_variable_set :@y, margin_box.absolute_top + 0.0001 if force_top_margin
|
2996
|
-
|
3044
|
+
inscribe_caption subject, opts
|
2997
3045
|
end).single_page_height
|
2998
3046
|
end
|
2999
3047
|
if ::Asciidoctor::AbstractBlock === subject
|
@@ -3001,21 +3049,23 @@ module Asciidoctor
|
|
3001
3049
|
else
|
3002
3050
|
string = subject.to_s
|
3003
3051
|
end
|
3052
|
+
block_align = opts.delete :block_align
|
3053
|
+
block_width = opts.delete :block_width
|
3004
3054
|
category_caption = (category = opts[:category]) ? %(#{category}_caption) : 'caption'
|
3055
|
+
caption_margin_outside = @theme[%(#{category_caption}_margin_outside)] || @theme.caption_margin_outside
|
3056
|
+
caption_margin_inside = @theme[%(#{category_caption}_margin_inside)] || @theme.caption_margin_inside
|
3005
3057
|
container_width = bounds.width
|
3006
|
-
|
3058
|
+
indent_by = [0, 0]
|
3007
3059
|
if (align = @theme[%(#{category_caption}_align)] || @theme.caption_align)
|
3008
|
-
align = align == 'inherit' ? (block_align || @
|
3060
|
+
align = align == 'inherit' ? (block_align || @base_text_align.to_sym) : align.to_sym
|
3009
3061
|
else
|
3010
|
-
align = @
|
3062
|
+
align = @base_text_align.to_sym
|
3011
3063
|
end
|
3012
3064
|
if (text_align = @theme[%(#{category_caption}_text_align)] || @theme.caption_text_align)
|
3013
3065
|
text_align = text_align == 'inherit' ? align : text_align.to_sym
|
3014
3066
|
else
|
3015
3067
|
text_align = align
|
3016
3068
|
end
|
3017
|
-
indent_by = [0, 0]
|
3018
|
-
block_width = opts.delete :block_width
|
3019
3069
|
if (max_width = opts.delete :max_width) && max_width != 'none'
|
3020
3070
|
if ::String === max_width
|
3021
3071
|
if max_width.start_with? 'fit-content'
|
@@ -3047,8 +3097,6 @@ module Asciidoctor
|
|
3047
3097
|
end
|
3048
3098
|
end
|
3049
3099
|
theme_font_cascade [:caption, category_caption] do
|
3050
|
-
caption_margin_outside = @theme[%(#{category_caption}_margin_outside)] || @theme.caption_margin_outside
|
3051
|
-
caption_margin_inside = @theme[%(#{category_caption}_margin_inside)] || @theme.caption_margin_inside
|
3052
3100
|
if ((opts.delete :side) || :top) == :top
|
3053
3101
|
margin = { top: caption_margin_outside, bottom: caption_margin_inside }
|
3054
3102
|
else
|
@@ -3057,8 +3105,13 @@ module Asciidoctor
|
|
3057
3105
|
unless (inherited = apply_text_decoration [], :caption).empty?
|
3058
3106
|
opts = opts.merge inherited
|
3059
3107
|
end
|
3108
|
+
unless scratch? || !(bg_color = @theme[%(#{category_caption}_background_color)] || @theme.caption_background_color)
|
3109
|
+
caption_height = height_of_typeset_text string
|
3110
|
+
fill_at = [0, cursor + (margin[:top] || 0)]
|
3111
|
+
float { bounding_box(fill_at, width: container_width, height: caption_height) { fill_bounds bg_color } }
|
3112
|
+
end
|
3060
3113
|
indent(*indent_by) do
|
3061
|
-
|
3114
|
+
inscribe_prose string, ({
|
3062
3115
|
margin_top: margin[:top],
|
3063
3116
|
margin_bottom: margin[:bottom],
|
3064
3117
|
align: text_align,
|
@@ -3072,18 +3125,18 @@ module Asciidoctor
|
|
3072
3125
|
end
|
3073
3126
|
|
3074
3127
|
# Render the caption for a table and return the height of the rendered content
|
3075
|
-
def
|
3076
|
-
|
3128
|
+
def inscribe_table_caption node, table_alignment = :left, table_width = nil, max_width = nil, side = :top
|
3129
|
+
inscribe_caption node, category: :table, side: side, block_align: table_alignment, block_width: table_width, max_width: max_width
|
3077
3130
|
end
|
3078
3131
|
|
3079
|
-
def allocate_toc doc, toc_num_levels, toc_start_cursor,
|
3132
|
+
def allocate_toc doc, toc_num_levels, toc_start_cursor, title_page_on
|
3080
3133
|
toc_start_page = page_number
|
3081
3134
|
extent = dry_run onto: self do
|
3082
|
-
|
3083
|
-
margin_bottom @theme.block_margin_bottom unless
|
3135
|
+
inscribe_toc doc, toc_num_levels, toc_start_page, toc_start_cursor
|
3136
|
+
margin_bottom @theme.block_margin_bottom unless title_page_on
|
3084
3137
|
end
|
3085
3138
|
# NOTE: reserve pages for the toc; leaves cursor on page after last page in toc
|
3086
|
-
if
|
3139
|
+
if title_page_on
|
3087
3140
|
extent.each_page { start_new_page }
|
3088
3141
|
else
|
3089
3142
|
extent.each_page {|first_page| start_new_page unless first_page }
|
@@ -3093,14 +3146,14 @@ module Asciidoctor
|
|
3093
3146
|
end
|
3094
3147
|
|
3095
3148
|
# NOTE: num_front_matter_pages not used during a dry run
|
3096
|
-
def
|
3149
|
+
def inscribe_toc doc, num_levels, toc_page_number, start_cursor, num_front_matter_pages = 0
|
3097
3150
|
go_to_page toc_page_number unless (page_number == toc_page_number) || scratch?
|
3098
3151
|
start_page_number = page_number
|
3099
3152
|
move_cursor_to start_cursor
|
3100
3153
|
unless (toc_title = doc.attr 'toc-title').nil_or_empty?
|
3101
3154
|
theme_font_cascade [[:heading, level: 2], :toc_title] do
|
3102
|
-
toc_title_align = (@theme.
|
3103
|
-
|
3155
|
+
toc_title_align = (@theme.toc_title_text_align || @theme.heading_h2_text_align || @theme.heading_text_align || @base_text_align).to_sym
|
3156
|
+
inscribe_general_heading doc, toc_title, align: toc_title_align, level: 2, outdent: true, role: :toctitle
|
3104
3157
|
end
|
3105
3158
|
end
|
3106
3159
|
# QUESTION: should we skip this whole method if num_levels < 0?
|
@@ -3125,7 +3178,7 @@ module Asciidoctor
|
|
3125
3178
|
}
|
3126
3179
|
end
|
3127
3180
|
theme_margin :toc, :top
|
3128
|
-
|
3181
|
+
inscribe_toc_level doc.sections, num_levels, dot_leader, num_front_matter_pages
|
3129
3182
|
end
|
3130
3183
|
# NOTE: range must be calculated relative to toc_page_number; absolute page number in scratch document is arbitrary
|
3131
3184
|
toc_page_numbers = (toc_page_number..(toc_page_number + (page_number - start_page_number)))
|
@@ -3133,7 +3186,7 @@ module Asciidoctor
|
|
3133
3186
|
toc_page_numbers
|
3134
3187
|
end
|
3135
3188
|
|
3136
|
-
def
|
3189
|
+
def inscribe_toc_level sections, num_levels, dot_leader, num_front_matter_pages
|
3137
3190
|
# NOTE: font options aren't always reliable, so store size separately
|
3138
3191
|
toc_font_info = theme_font :toc do
|
3139
3192
|
{ font: font, size: @font_size }
|
@@ -3149,7 +3202,7 @@ module Asciidoctor
|
|
3149
3202
|
if scratch?
|
3150
3203
|
indent 0, pgnum_label_placeholder_width do
|
3151
3204
|
# NOTE: must wrap title in empty anchor element in case links are styled with different font family / size
|
3152
|
-
|
3205
|
+
inscribe_prose sect_title, anchor: true, normalize: false, hanging_indent: hanging_indent, normalize_line_height: true, margin: 0
|
3153
3206
|
end
|
3154
3207
|
else
|
3155
3208
|
physical_pgnum = sect.attr 'pdf-page-start'
|
@@ -3194,7 +3247,7 @@ module Asciidoctor
|
|
3194
3247
|
end
|
3195
3248
|
end
|
3196
3249
|
indent @theme.toc_indent do
|
3197
|
-
|
3250
|
+
inscribe_toc_level sect.sections, num_levels_for_sect, dot_leader, num_front_matter_pages
|
3198
3251
|
end if num_levels_for_sect > sect.level
|
3199
3252
|
end
|
3200
3253
|
end
|
@@ -3222,8 +3275,8 @@ module Asciidoctor
|
|
3222
3275
|
icon_data
|
3223
3276
|
end
|
3224
3277
|
|
3225
|
-
# TODO: delegate to
|
3226
|
-
def
|
3278
|
+
# TODO: delegate to inscribe_page_header and inscribe_page_footer per page
|
3279
|
+
def inscribe_running_content periphery, doc, skip = [1, 1], body_start_page_number = 1
|
3227
3280
|
skip_pages, skip_pagenums = skip
|
3228
3281
|
# NOTE: find and advance to first non-imported content page to use as model page
|
3229
3282
|
return unless (content_start_page = state.pages[skip_pages..-1].index {|it| !it.imported_page? })
|
@@ -3790,7 +3843,7 @@ module Asciidoctor
|
|
3790
3843
|
def theme_fill_and_stroke_block category, extent, opts = {}
|
3791
3844
|
node_with_caption = nil unless (node_with_caption = opts[:caption_node])&.title?
|
3792
3845
|
unless extent
|
3793
|
-
|
3846
|
+
inscribe_caption node_with_caption, category: category if node_with_caption
|
3794
3847
|
return
|
3795
3848
|
end
|
3796
3849
|
if (b_width = (opts.key? :border_width) ? opts[:border_width] : @theme[%(#{category}_border_width)])
|
@@ -3804,7 +3857,7 @@ module Asciidoctor
|
|
3804
3857
|
bg_color = nil
|
3805
3858
|
end
|
3806
3859
|
unless b_width || bg_color
|
3807
|
-
|
3860
|
+
inscribe_caption node_with_caption, category: category if node_with_caption
|
3808
3861
|
return
|
3809
3862
|
end
|
3810
3863
|
if (b_color = @theme[%(#{category}_border_color)]) == 'transparent'
|
@@ -3822,7 +3875,7 @@ module Asciidoctor
|
|
3822
3875
|
else # let page background cut into block background; guarantees b_width is set
|
3823
3876
|
b_shift, b_gap_color = (b_width ||= 0.5) * 0.5, @page_bg_color
|
3824
3877
|
end
|
3825
|
-
|
3878
|
+
inscribe_caption node_with_caption, category: category if node_with_caption
|
3826
3879
|
extent.from.page += 1 unless extent.from.page == page_number # sanity check
|
3827
3880
|
float do
|
3828
3881
|
extent.each_page do |first_page, last_page|
|
@@ -4206,7 +4259,7 @@ module Asciidoctor
|
|
4206
4259
|
(align_role.slice 5, align_role.length).to_sym
|
4207
4260
|
elsif use_theme
|
4208
4261
|
roles.reverse.each do |role|
|
4209
|
-
if (align = @theme[%(role_#{role}
|
4262
|
+
if (align = @theme[%(role_#{role}_text_align)])
|
4210
4263
|
return align.to_sym
|
4211
4264
|
end
|
4212
4265
|
end
|
@@ -4542,6 +4595,27 @@ module Asciidoctor
|
|
4542
4595
|
end
|
4543
4596
|
end
|
4544
4597
|
|
4598
|
+
# Deprecated method names
|
4599
|
+
alias layout_footnotes inscribe_footnotes
|
4600
|
+
alias layout_title_page inscribe_title_page
|
4601
|
+
alias layout_cover_page inscribe_cover_page
|
4602
|
+
alias layout_chapter_title inscribe_chapter_title
|
4603
|
+
alias layout_part_title inscribe_part_title
|
4604
|
+
alias layout_general_heading inscribe_general_heading
|
4605
|
+
alias layout_heading inscribe_heading
|
4606
|
+
alias layout_prose inscribe_prose
|
4607
|
+
alias layout_caption inscribe_caption
|
4608
|
+
alias layout_table_caption inscribe_table_caption
|
4609
|
+
alias layout_toc inscribe_toc
|
4610
|
+
alias layout_toc_level inscribe_toc_level
|
4611
|
+
alias layout_running_content inscribe_running_content
|
4612
|
+
|
4613
|
+
def self.method_added method
|
4614
|
+
if (method_name = method.to_s).start_with? 'layout_'
|
4615
|
+
alias_method %(inscribe_#{method_name.slice 7, method_name.length}).to_sym, method
|
4616
|
+
end
|
4617
|
+
end
|
4618
|
+
|
4545
4619
|
private
|
4546
4620
|
|
4547
4621
|
def add_link_to_image uri, image_info, image_opts
|