asciidoctor-pdf 2.0.0.alpha.1 → 2.0.0.alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|