asciidoctor-pdf 2.0.8 → 2.1.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 +47 -0
- data/README.adoc +6 -12
- data/lib/asciidoctor/pdf/converter.rb +150 -74
- data/lib/asciidoctor/pdf/ext/asciidoctor/section.rb +4 -0
- data/lib/asciidoctor/pdf/ext/prawn/extensions.rb +28 -27
- data/lib/asciidoctor/pdf/formatted_string.rb +13 -0
- data/lib/asciidoctor/pdf/formatted_text/inline_image_arranger.rb +5 -0
- data/lib/asciidoctor/pdf/formatted_text/text_background_and_border_renderer.rb +3 -3
- data/lib/asciidoctor/pdf/formatted_text/transform.rb +6 -3
- data/lib/asciidoctor/pdf/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2109e7ec140c759820252d4c7f0f155c2d7bf4adfcad9d34fddb8cf4bc81a260
|
4
|
+
data.tar.gz: c18e3fb15231f968d907fc05693f6c4d7f9fbedfd29e368b0dc355f44d2e4254
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4e51a465c863440441cae24e429bbf84d9fb782e2c711958d5b72dfa585ba4b1b7c9c94b92d8155b2cea0d72eec276fac6e4669ea8a50c175ff8ed82ab91eb8d
|
7
|
+
data.tar.gz: a62b653261f3194d51a738cc4b1cf46f4a78a6ba0c1687fbeb06bf5049ecc9d65a20edd7acc463a2f4b473d1248795ce39902b214b87b019cbc8485d394a32f3
|
data/CHANGELOG.adoc
CHANGED
@@ -5,6 +5,53 @@
|
|
5
5
|
This document provides a high-level view of the changes to the {project-name} by release.
|
6
6
|
For a detailed view of what has changed, refer to the {url-repo}/commits/main[commit history] on GitHub.
|
7
7
|
|
8
|
+
== 2.1.2 (2022-06-17) - @mojavelinux
|
9
|
+
|
10
|
+
Bug Fixes::
|
11
|
+
|
12
|
+
* apply page layout from main document to new page in scratch document (#2248)
|
13
|
+
* use correct logic to insert page before TOC with automatic placement when doctype=book and media=prepress
|
14
|
+
* use `get_entries_for_toc` to determine if the TOC is non-empty rather than `Document#sections?`
|
15
|
+
|
16
|
+
=== Details
|
17
|
+
|
18
|
+
{url-repo}/releases/tag/v2.1.2[git tag] | {url-repo}/compare/v2.1.1\...v2.1.2[full diff]
|
19
|
+
|
20
|
+
== 2.1.1 (2022-06-15) - @mojavelinux
|
21
|
+
|
22
|
+
Improvements::
|
23
|
+
|
24
|
+
* store zero-based column on Extent for extensions to use to position cursor at start of extent
|
25
|
+
|
26
|
+
Bug Fixes::
|
27
|
+
|
28
|
+
* place block image in SVG format in correct column when align is left and page columns are enabled (#2241)
|
29
|
+
* accurately trap LoadError from CodeRay if source language is not recognized on code block
|
30
|
+
* only draw rounded rectangle around phrase if `border-radius` is > 0
|
31
|
+
* use `base-border-color` value if border width is set on role for inline phrase but not border color
|
32
|
+
|
33
|
+
=== Details
|
34
|
+
|
35
|
+
{url-repo}/releases/tag/v2.1.1[git tag] | {url-repo}/compare/v2.1.0\...v2.1.1[full diff]
|
36
|
+
|
37
|
+
== 2.1.0 (2022-06-11) - @mojavelinux
|
38
|
+
|
39
|
+
Enhancements::
|
40
|
+
|
41
|
+
* arrange body of article or manpage doctype into multiple columns if `page-columns` key is set in theme (#327)
|
42
|
+
* allow column gap to be specified using `page-column-gap` key (#327)
|
43
|
+
* introduce `convert_index_categories` method to handle rendering of categories for index inside column box (#327)
|
44
|
+
* rename `convert_index_list` method to `convert_index_term` to make its purpose more clear (#327)
|
45
|
+
* add `save_theme` helper to work with a copy of the theme within a scope (#2196)
|
46
|
+
* add support for `scale` attribute or `iw` unit on `pdfwidth` attribute on image macros (#1933)
|
47
|
+
* add backlink from bibref on bibliography entry to first reference to that entry in the document (#1737)
|
48
|
+
* preserve text formatting on index term in index section (#897)
|
49
|
+
* don't insert page break between part and first chapter if `heading-part-break-after` key in theme is `avoid` (#1795)
|
50
|
+
|
51
|
+
=== Details
|
52
|
+
|
53
|
+
{url-repo}/releases/tag/v2.1.0[git tag] | {url-repo}/compare/v2.0.8\...v2.1.0[full diff]
|
54
|
+
|
8
55
|
== 2.0.8 (2022-06-08) - @mojavelinux
|
9
56
|
|
10
57
|
Improvements::
|
data/README.adoc
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
= Asciidoctor PDF: A native PDF converter for AsciiDoc
|
2
2
|
Dan Allen <https://github.com/mojavelinux[@mojavelinux]>; Sarah White <https://github.com/graphitefriction[@graphitefriction]>
|
3
|
-
v2.
|
3
|
+
v2.1.2, 2022-06-17
|
4
4
|
// Settings:
|
5
5
|
:experimental:
|
6
6
|
:idprefix:
|
@@ -23,8 +23,7 @@ endif::[]
|
|
23
23
|
:project-name: Asciidoctor PDF
|
24
24
|
:project-handle: asciidoctor-pdf
|
25
25
|
// Variables:
|
26
|
-
:release-line: 2.
|
27
|
-
:release-version: 2.0.8
|
26
|
+
:release-line: 2.1.x
|
28
27
|
// URLs:
|
29
28
|
:url-gem: https://rubygems.org/gems/asciidoctor-pdf
|
30
29
|
:url-project: https://github.com/asciidoctor/asciidoctor-pdf
|
@@ -47,7 +46,7 @@ The aim of this library is to take the pain out of creating PDF documents from A
|
|
47
46
|
|
48
47
|
[NOTE]
|
49
48
|
====
|
50
|
-
The documentation for Asciidoctor PDF
|
49
|
+
The documentation for the latest, stable release of Asciidoctor PDF is available at {url-project-docs}/.
|
51
50
|
|
52
51
|
If you're looking for the documentation for Asciidoctor PDF 1.6, refer to the {url-project-repo}/tree/v1.6.x#readme[README] in the v1.6.x branch.
|
53
52
|
Asciidoctor PDF 1.6 is no longer being developed and will reach EOL later this year.
|
@@ -114,11 +113,11 @@ There are several optional features of this converter that require additional ge
|
|
114
113
|
Those features are as follows.
|
115
114
|
|
116
115
|
Source highlighting::
|
117
|
-
You'll need to {url-project-
|
116
|
+
You'll need to {url-project-docs}/syntax-highlighting/[install a syntax highlighter] to use source highlighting (build-time only).
|
118
117
|
|
119
118
|
PDF optimization::
|
120
119
|
If you want to optimize your PDF, you'll need rghost or hexapdf.
|
121
|
-
See {url-project-
|
120
|
+
See {url-project-docs}/optimize-pdf/[Optimize the PDF] for installation and usage instructions.
|
122
121
|
|
123
122
|
Automatic hyphenation::
|
124
123
|
To turn on automatic hyphenation using the `hyphens` attribute, you'll need to install the `text-hyphen` gem:
|
@@ -128,7 +127,7 @@ To turn on automatic hyphenation using the `hyphens` attribute, you'll need to i
|
|
128
127
|
Accelerated image decoding::
|
129
128
|
Ruby is not particularly fast at decoding images, and the image formats it supports are limited.
|
130
129
|
To help, you can install prawn-gmagick, which delegates the work of decoding images to GraphicsMagick.
|
131
|
-
Refer to {url-project-
|
130
|
+
Refer to {url-project-docs}/image-paths-and-formats/#other-image-formats[Supporting additional image file formats] for instructions about how to enable this integration.
|
132
131
|
|
133
132
|
Check the {url-project-docs}/install/#table-minimum-version[minimum supported version table] to make sure you're using a supported version of the dependency.
|
134
133
|
|
@@ -197,11 +196,6 @@ ifndef::env-site[]
|
|
197
196
|
See the <<CONTRIBUTING.adoc#,contributing guide>>.
|
198
197
|
To help develop {project-name}, or to simply use the development version, refer to the <<CONTRIBUTING-CODE.adoc#,developing and contributing code guide>>.
|
199
198
|
|
200
|
-
[[resources,Links]]
|
201
|
-
== Resources
|
202
|
-
|
203
|
-
* https://groups.google.com/forum/#!msg/prawn-ruby/MbMsCx862iY/6ImCsvLGfVcJ[Discussion about image quality in PDFs]
|
204
|
-
|
205
199
|
== Authors
|
206
200
|
|
207
201
|
{project-name} was written by https://github.com/mojavelinux[Dan Allen] and https://github.com/graphitefriction[Sarah White] of OpenDevise Inc. on behalf of the Asciidoctor Project.
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative 'formatted_string'
|
3
4
|
require_relative 'formatted_text'
|
4
5
|
require_relative 'index_catalog'
|
5
6
|
require_relative 'pdfmark'
|
@@ -124,6 +125,7 @@ module Asciidoctor
|
|
124
125
|
DropAnchorRx = %r(<(?:a\b[^>]*|/a)>)
|
125
126
|
SourceHighlighters = %w(coderay pygments rouge).to_set
|
126
127
|
ViewportWidth = ::Module.new
|
128
|
+
ImageWidth = ::Module.new
|
127
129
|
(TitleStyles = {
|
128
130
|
'toc' => [:numbered_title],
|
129
131
|
'basic' => [:title],
|
@@ -169,7 +171,8 @@ module Asciidoctor
|
|
169
171
|
# NOTE: a new page will already be started (page_number = 2) if the front cover image is a PDF
|
170
172
|
ink_cover_page doc, :front
|
171
173
|
has_front_cover = page_number > marked_page_number
|
172
|
-
|
174
|
+
doctype = doc.doctype
|
175
|
+
if (has_title_page = (title_page_on = doctype == 'book' || (doc.attr? 'title-page')) && (start_title_page doc))
|
173
176
|
# NOTE: the base font must be set before any content is written to the main or scratch document
|
174
177
|
font @theme.base_font_family, size: @root_font_size, style: @theme.base_font_style
|
175
178
|
if perform_on_single_page { ink_title_page doc }
|
@@ -195,8 +198,8 @@ module Asciidoctor
|
|
195
198
|
|
196
199
|
indent_section do
|
197
200
|
toc_num_levels = (doc.attr 'toclevels', 2).to_i
|
198
|
-
if (insert_toc = (doc.attr? 'toc') && !((toc_placement = doc.attr 'toc-placement') == 'macro' || toc_placement == 'preamble') && doc.
|
199
|
-
|
201
|
+
if (insert_toc = (doc.attr? 'toc') && !((toc_placement = doc.attr 'toc-placement') == 'macro' || toc_placement == 'preamble') && !(get_entries_for_toc doc).empty?)
|
202
|
+
start_new_page if @ppbook && verso_page?
|
200
203
|
add_dest_for_block doc, id: 'toc', y: (at_page_top? ? page_height : nil)
|
201
204
|
@toc_extent = allocate_toc doc, toc_num_levels, cursor, title_page_on
|
202
205
|
else
|
@@ -278,12 +281,19 @@ module Asciidoctor
|
|
278
281
|
doc.set_attr 'pdf-anchor', (derive_anchor_from_id doc.id, 'top')
|
279
282
|
doc.set_attr 'pdf-page-start', page_number
|
280
283
|
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
284
|
+
if doctype == 'book' || (columns = @theme.page_columns || 1) < 2
|
285
|
+
convert_section generate_manname_section doc if doctype == 'manpage' && (doc.attr? 'manpurpose')
|
286
|
+
traverse doc
|
287
|
+
# NOTE: for a book, these are leftover footnotes; for an article this is everything
|
288
|
+
outdent_section { ink_footnotes doc }
|
289
|
+
else
|
290
|
+
column_box [bounds.left, cursor], columns: columns, width: bounds.width, reflow_margins: true, spacer: @theme.page_column_gap do
|
291
|
+
convert_section generate_manname_section doc if doctype == 'manpage' && (doc.attr? 'manpurpose')
|
292
|
+
traverse doc
|
293
|
+
# NOTE: for a book, these are leftover footnotes; for an article this is everything
|
294
|
+
outdent_section { ink_footnotes doc }
|
295
|
+
end
|
296
|
+
end
|
287
297
|
|
288
298
|
if (toc_extent = @toc_extent)
|
289
299
|
if title_page_on && !insert_toc
|
@@ -402,6 +412,7 @@ module Asciidoctor
|
|
402
412
|
@list_bullets = []
|
403
413
|
@bottom_gutters = [{}]
|
404
414
|
@rendered_footnotes = []
|
415
|
+
@bibref_refs = ::Set.new
|
405
416
|
@conum_glyphs = ConumSets[@theme.conum_glyphs || 'circled'] || (@theme.conum_glyphs.split ',').map do |r|
|
406
417
|
from, to = r.lstrip.split '-', 2
|
407
418
|
to ? ((get_char from)..(get_char to)).to_a : [(get_char from)]
|
@@ -575,6 +586,8 @@ module Asciidoctor
|
|
575
586
|
theme.base_font_style = theme.base_font_style&.to_sym || :normal
|
576
587
|
theme.page_numbering_start_at ||= 'body'
|
577
588
|
theme.running_content_start_at ||= 'body'
|
589
|
+
theme.heading_chapter_break_before ||= 'always'
|
590
|
+
theme.heading_part_break_before ||= 'always'
|
578
591
|
theme.heading_margin_page_top ||= 0
|
579
592
|
theme.heading_margin_top ||= 0
|
580
593
|
theme.heading_margin_bottom ||= 0
|
@@ -609,6 +622,13 @@ module Asciidoctor
|
|
609
622
|
theme
|
610
623
|
end
|
611
624
|
|
625
|
+
def save_theme
|
626
|
+
@theme = (original_theme = theme).dup
|
627
|
+
yield
|
628
|
+
ensure
|
629
|
+
@theme = original_theme
|
630
|
+
end
|
631
|
+
|
612
632
|
def indent_section
|
613
633
|
if (values = @section_indent)
|
614
634
|
indent(values[0], values[1]) { yield }
|
@@ -647,13 +667,14 @@ module Asciidoctor
|
|
647
667
|
hidden = sect.option? 'notitle'
|
648
668
|
hopts = { align: text_align, level: hlevel, part: part, chapterlike: chapterlike, outdent: !(part || chapterlike) }
|
649
669
|
if part
|
650
|
-
|
670
|
+
if @theme.heading_part_break_before == 'always'
|
651
671
|
started_new = true
|
652
672
|
start_new_part sect
|
653
673
|
end
|
654
674
|
elsif chapterlike
|
655
|
-
if @theme.heading_chapter_break_before
|
656
|
-
(@theme.heading_part_break_after == '
|
675
|
+
if (@theme.heading_chapter_break_before == 'always' &&
|
676
|
+
!(@theme.heading_part_break_after == 'avoid' && sect.first_section_of_part?)) ||
|
677
|
+
(@theme.heading_part_break_after == 'always' && sect.first_section_of_part?)
|
657
678
|
started_new = true
|
658
679
|
start_new_chapter sect
|
659
680
|
end
|
@@ -700,53 +721,74 @@ module Asciidoctor
|
|
700
721
|
end
|
701
722
|
|
702
723
|
def convert_index_section node
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
category.terms.each {|term| convert_index_list_item term, pagenum_sequence_style }
|
715
|
-
@theme.prose_margin_bottom > cursor ? bounds.move_past_bottom : (move_down @theme.prose_margin_bottom)
|
716
|
-
end
|
717
|
-
end_cursor = cursor if bounds.current_column == 0
|
718
|
-
end
|
719
|
-
# Q: could we move this logic into column_box?
|
720
|
-
move_cursor_to end_cursor if end_cursor
|
724
|
+
if ColumnBox === bounds || (columns = @theme.index_columns || 1) < 2
|
725
|
+
convert_index_categories @index.categories, (node.document.attr 'index-pagenum-sequence-style')
|
726
|
+
else
|
727
|
+
end_cursor = nil
|
728
|
+
column_box [bounds.left, cursor], columns: columns, width: bounds.width, reflow_margins: true, spacer: @theme.index_column_gap do
|
729
|
+
convert_index_categories @index.categories, (node.document.attr 'index-pagenum-sequence-style')
|
730
|
+
end_cursor = cursor if bounds.current_column == 0
|
731
|
+
end
|
732
|
+
# Q: could we move this logic into column_box?
|
733
|
+
move_cursor_to end_cursor if end_cursor
|
734
|
+
end
|
721
735
|
nil
|
722
736
|
end
|
723
737
|
|
724
|
-
def
|
725
|
-
|
738
|
+
def convert_index_categories categories, pagenum_sequence_style = nil
|
739
|
+
space_needed_for_category = @theme.description_list_term_spacing + (2 * (height_of_typeset_text 'A'))
|
740
|
+
categories.each do |category|
|
741
|
+
bounds.move_past_bottom if space_needed_for_category > cursor
|
742
|
+
ink_prose category.name,
|
743
|
+
align: :left,
|
744
|
+
inline_format: false,
|
745
|
+
margin_bottom: @theme.description_list_term_spacing,
|
746
|
+
style: @theme.description_list_term_font_style&.to_sym
|
747
|
+
category.terms.each {|term| convert_index_term term, pagenum_sequence_style }
|
748
|
+
@theme.prose_margin_bottom > cursor ? bounds.move_past_bottom : (move_down @theme.prose_margin_bottom)
|
749
|
+
end
|
750
|
+
end
|
751
|
+
|
752
|
+
def convert_index_term term, pagenum_sequence_style = nil
|
753
|
+
term_fragments = term.name.fragments
|
726
754
|
unless term.container?
|
755
|
+
pagenum_fragment = (parse_text %(<a>#{DummyText}</a>), inline_format: true)[0]
|
727
756
|
if @media == 'screen'
|
728
757
|
case pagenum_sequence_style
|
729
758
|
when 'page'
|
730
|
-
pagenums = term.dests.uniq {|dest| dest[:page] }.map {|dest|
|
759
|
+
pagenums = term.dests.uniq {|dest| dest[:page] }.map {|dest| pagenum_fragment.merge anchor: dest[:anchor], text: dest[:page] }
|
731
760
|
when 'range'
|
732
761
|
first_anchor_per_page = {}.tap {|accum| term.dests.each {|dest| accum[dest[:page]] ||= dest[:anchor] } }
|
733
762
|
pagenums = (consolidate_ranges first_anchor_per_page.keys).map do |range|
|
734
763
|
anchor = first_anchor_per_page[(range.include? '-') ? (range.partition '-')[0] : range]
|
735
|
-
|
764
|
+
pagenum_fragment.merge text: range, anchor: anchor
|
736
765
|
end
|
737
766
|
else # term
|
738
|
-
pagenums = term.dests.map {|dest|
|
767
|
+
pagenums = term.dests.map {|dest| pagenum_fragment.merge text: dest[:page], anchor: dest[:anchor] }
|
739
768
|
end
|
740
769
|
else
|
741
770
|
pagenums = consolidate_ranges term.dests.map {|dest| dest[:page] }.uniq
|
742
771
|
end
|
743
|
-
|
772
|
+
pagenums.each do |pagenum|
|
773
|
+
# NOTE: addresses a very minor kerning issue for text adjacent to the comma
|
774
|
+
if (prev_fragment = term_fragments[-1]).size == 1
|
775
|
+
if ::String === pagenum
|
776
|
+
term_fragments[-1] = prev_fragment.merge text: %(#{prev_fragment[:text]}, #{pagenum})
|
777
|
+
next
|
778
|
+
else
|
779
|
+
term_fragments[-1] = prev_fragment.merge text: %(#{prev_fragment[:text]}, )
|
780
|
+
end
|
781
|
+
else
|
782
|
+
term_fragments << ({ text: ', ' })
|
783
|
+
end
|
784
|
+
term_fragments << (::String === pagenum ? { text: pagenum } : pagenum)
|
785
|
+
end
|
744
786
|
end
|
745
787
|
subterm_indent = @theme.description_list_description_indent
|
746
|
-
|
788
|
+
typeset_formatted_text term_fragments, (calc_line_metrics @base_line_height), align: :left, color: @font_color, hanging_indent: subterm_indent * 2
|
747
789
|
indent subterm_indent do
|
748
790
|
term.subterms.each do |subterm|
|
749
|
-
|
791
|
+
convert_index_term subterm, pagenum_sequence_style
|
750
792
|
end
|
751
793
|
end unless term.leaf?
|
752
794
|
end
|
@@ -1066,7 +1108,10 @@ module Asciidoctor
|
|
1066
1108
|
srclang = node.attr 'language', 'text'
|
1067
1109
|
begin
|
1068
1110
|
::CodeRay::Scanners[(srclang = (srclang.start_with? 'html+') ? (srclang.slice 5, srclang.length).to_sym : srclang.to_sym)]
|
1069
|
-
rescue
|
1111
|
+
rescue
|
1112
|
+
until ::LoadError === (cause ||= $!) || ::ArgumentError === cause
|
1113
|
+
raise $! unless (cause = cause.cause)
|
1114
|
+
end
|
1070
1115
|
srclang = :text
|
1071
1116
|
end
|
1072
1117
|
fragments = (::CodeRay.scan source_string, srclang).to_prawn
|
@@ -1715,9 +1760,14 @@ module Asciidoctor
|
|
1715
1760
|
return on_image_error :missing, node, target, (opts.merge align: alignment) unless image_path
|
1716
1761
|
|
1717
1762
|
# TODO: support cover (aka canvas) image layout using "canvas" (or "cover") role
|
1718
|
-
width = resolve_explicit_width node.attributes, bounds_width: (available_w = bounds.width), support_vw: true, use_fallback: true, constrain_to_bounds: true
|
1719
|
-
|
1720
|
-
|
1763
|
+
case (width = resolve_explicit_width node.attributes, bounds_width: (available_w = bounds.width), support_vw: true, use_fallback: true, constrain_to_bounds: true)
|
1764
|
+
when ViewportWidth
|
1765
|
+
# TODO: add `to_pt page_width` method to ViewportWidth type
|
1766
|
+
width = page_width * (width.to_f / 100)
|
1767
|
+
when ImageWidth
|
1768
|
+
scale = width.to_f / 100
|
1769
|
+
width = nil
|
1770
|
+
end
|
1721
1771
|
|
1722
1772
|
caption_end = @theme.image_caption_end&.to_sym || :bottom
|
1723
1773
|
caption_max_width = @theme.image_caption_max_width
|
@@ -1740,14 +1790,15 @@ module Asciidoctor
|
|
1740
1790
|
file_request_root = { base: (::File.dirname image_path), root: @jail_dir }
|
1741
1791
|
end
|
1742
1792
|
svg_obj = ::Prawn::SVG::Interface.new svg_data, self,
|
1743
|
-
position: alignment,
|
1744
1793
|
width: width,
|
1745
1794
|
fallback_font_name: fallback_svg_font_name,
|
1746
1795
|
enable_web_requests: allow_uri_read ? (method :load_open_uri).to_proc : false,
|
1747
1796
|
enable_file_requests_with_root: file_request_root,
|
1748
1797
|
cache_images: cache_uri
|
1749
1798
|
rendered_w = (svg_size = svg_obj.document.sizing).output_width
|
1750
|
-
if
|
1799
|
+
if scale
|
1800
|
+
svg_size = svg_obj.resize width: (rendered_w = [available_w, rendered_w * scale].min)
|
1801
|
+
elsif !width && (svg_obj.document.root.attributes.key? 'width') && rendered_w > available_w
|
1751
1802
|
# NOTE: restrict width to available width (prawn-svg already coerces to pixels)
|
1752
1803
|
svg_size = svg_obj.resize width: (rendered_w = available_w)
|
1753
1804
|
end
|
@@ -1755,7 +1806,6 @@ module Asciidoctor
|
|
1755
1806
|
if (rendered_h = svg_size.output_height) > (available_h = cursor - caption_h)
|
1756
1807
|
unless pinned || at_page_top?
|
1757
1808
|
advance_page
|
1758
|
-
(svg_obj.options[:at] = svg_obj.position)[0] += bounds.left if ColumnBox === bounds
|
1759
1809
|
available_h = cursor - caption_h
|
1760
1810
|
end
|
1761
1811
|
rendered_w = (svg_obj.resize height: (rendered_h = available_h)).output_width if rendered_h > available_h
|
@@ -1766,7 +1816,16 @@ module Asciidoctor
|
|
1766
1816
|
update_colors if graphic_state.color_space.empty?
|
1767
1817
|
ink_caption node, category: :image, end: :top, block_align: alignment, block_width: rendered_w, max_width: caption_max_width if caption_end == :top && node.title?
|
1768
1818
|
image_y = y
|
1769
|
-
|
1819
|
+
# NOTE: prawn-svg does not compute :at for alignment correctly in column box, so resort to our own logic
|
1820
|
+
case alignment
|
1821
|
+
when :center
|
1822
|
+
left = bounds.left + (available_w - rendered_w) * 0.5
|
1823
|
+
when :right
|
1824
|
+
left = bounds.left + available_w - rendered_w
|
1825
|
+
else
|
1826
|
+
left = bounds.left
|
1827
|
+
end
|
1828
|
+
svg_obj.options[:at] = [left, (image_cursor = cursor)]
|
1770
1829
|
svg_obj.draw # NOTE: cursor advances automatically
|
1771
1830
|
svg_obj.document.warnings.each do |img_warning|
|
1772
1831
|
log :warn, %(problem encountered in image: #{image_path}; #{img_warning})
|
@@ -1781,8 +1840,10 @@ module Asciidoctor
|
|
1781
1840
|
image_obj, image_info = ::Base64 === image_path ?
|
1782
1841
|
::StringIO.open((::Base64.decode64 image_path), 'rb') {|fd| build_image_object fd } :
|
1783
1842
|
::File.open(image_path, 'rb') {|fd| build_image_object fd }
|
1843
|
+
actual_w = to_pt image_info.width, :px
|
1844
|
+
width = actual_w * scale if scale
|
1784
1845
|
# NOTE: if width is not specified, scale native width & height from px to pt and restrict width to available width
|
1785
|
-
rendered_w, rendered_h = image_info.calc_image_dimensions width: (width || [available_w,
|
1846
|
+
rendered_w, rendered_h = image_info.calc_image_dimensions width: (width || [available_w, actual_w].min)
|
1786
1847
|
# NOTE: shrink image so it fits within available space; group image & caption
|
1787
1848
|
if rendered_h > (available_h = cursor - caption_h)
|
1788
1849
|
unless pinned || at_page_top?
|
@@ -2291,7 +2352,7 @@ module Asciidoctor
|
|
2291
2352
|
# NOTE: only allow document to have a single managed toc
|
2292
2353
|
return if @toc_extent
|
2293
2354
|
is_macro = (placement = opts[:placement] || 'macro') == 'macro'
|
2294
|
-
if ((doc = node.document).attr? 'toc-placement', placement) && (doc.attr? 'toc') && doc.
|
2355
|
+
if ((doc = node.document).attr? 'toc-placement', placement) && (doc.attr? 'toc') && !(get_entries_for_toc doc).empty?
|
2295
2356
|
start_toc_page node, placement if (is_book = doc.doctype == 'book')
|
2296
2357
|
add_dest_for_block node, id: (node.id || 'toc') if is_macro
|
2297
2358
|
toc_extent = @toc_extent = allocate_toc doc, (doc.attr 'toclevels', 2).to_i, cursor, (title_page_on = is_book || (doc.attr? 'title-page'))
|
@@ -2380,9 +2441,12 @@ module Asciidoctor
|
|
2380
2441
|
if (text = ref.xreftext node.attr 'xrefstyle', nil, true)&.include? '<a'
|
2381
2442
|
text = text.gsub DropAnchorRx, ''
|
2382
2443
|
end
|
2444
|
+
if ref.inline? && ref.type == :bibref && !scratch? && (@bibref_refs.add? refid)
|
2445
|
+
anchor = %(<a id="_bibref_ref_#{refid}">#{DummyText}</a>)
|
2446
|
+
end
|
2383
2447
|
@resolving_xref = nil
|
2384
2448
|
end
|
2385
|
-
%(<a anchor="#{derive_anchor_from_id refid}">#{text || "[#{refid}]"}</a>).gsub ']', ']'
|
2449
|
+
%(#{anchor || ''}<a anchor="#{derive_anchor_from_id refid}">#{text || "[#{refid}]"}</a>).gsub ']', ']'
|
2386
2450
|
else
|
2387
2451
|
%(<a anchor="#{doc.attr 'pdf-anchor'}">#{node.text || '[^top]'}</a>)
|
2388
2452
|
end
|
@@ -2390,10 +2454,12 @@ module Asciidoctor
|
|
2390
2454
|
# NOTE: destination is created inside callback registered by FormattedTextTransform#build_fragment
|
2391
2455
|
%(<a id="#{node.id}">#{DummyText}</a>)
|
2392
2456
|
when :bibref
|
2393
|
-
|
2457
|
+
id = node.id
|
2394
2458
|
# NOTE: technically node.text should be node.reftext, but subs have already been applied to text
|
2395
|
-
reftext = (reftext = node.reftext) ? %([#{reftext}]) : %([#{
|
2396
|
-
%(<a
|
2459
|
+
reftext = (reftext = node.reftext) ? %([#{reftext}]) : %([#{id}])
|
2460
|
+
reftext = %(<a anchor="_bibref_ref_#{id}">#{reftext}</a>) if @bibref_refs.include? id
|
2461
|
+
# NOTE: destination is created inside callback registered by FormattedTextTransform#build_fragment
|
2462
|
+
%(<a id="#{id}">#{DummyText}</a>#{reftext})
|
2397
2463
|
else
|
2398
2464
|
log :warn, %(unknown anchor type: #{node.type.inspect})
|
2399
2465
|
nil
|
@@ -2515,12 +2581,18 @@ module Asciidoctor
|
|
2515
2581
|
class_attr = (role = node.role) ? %( class="#{role}") : ''
|
2516
2582
|
fit_attr = (fit = node.attr 'fit') ? %( fit="#{fit}") : ''
|
2517
2583
|
if (width = resolve_explicit_width node.attributes)
|
2518
|
-
if
|
2519
|
-
|
2584
|
+
if ImageWidth === width
|
2585
|
+
if state # check that converter is initialized
|
2586
|
+
width = (intrinsic_image_width image_path, image_format) * (width.to_f / 100)
|
2587
|
+
else
|
2588
|
+
width = %(auto*#{width})
|
2589
|
+
end
|
2590
|
+
elsif node.parent.context == :table_cell && ::String === width && (width.end_with? '%')
|
2591
|
+
width += (intrinsic_image_width image_path, image_format).to_s
|
2520
2592
|
end
|
2521
2593
|
width_attr = %( width="#{width}")
|
2522
2594
|
elsif state # check that converter is initialized
|
2523
|
-
width_attr = %( width="#{
|
2595
|
+
width_attr = %( width="#{intrinsic_image_width image_path, image_format}")
|
2524
2596
|
else
|
2525
2597
|
width_attr = ' width="auto"' # defer operation until arranger runs
|
2526
2598
|
end
|
@@ -2541,17 +2613,20 @@ module Asciidoctor
|
|
2541
2613
|
if scratch?
|
2542
2614
|
visible ? node.text : ''
|
2543
2615
|
else
|
2544
|
-
|
2545
|
-
|
2616
|
+
unless defined? @index
|
2617
|
+
# NOTE: initialize index and text formatter in case converter is called before PDF is initialized
|
2618
|
+
@index = IndexCatalog.new
|
2619
|
+
@text_formatter = FormattedText::Formatter.new theme: (load_theme node.document)
|
2620
|
+
end
|
2546
2621
|
# NOTE: page number (:page key) is added by InlineDestinationMarker
|
2547
2622
|
dest = { anchor: (anchor_name = @index.next_anchor_name) }
|
2548
2623
|
anchor = %(<a id="#{anchor_name}" type="indexterm"#{visible ? ' visible="true"' : ''}>#{DummyText}</a>)
|
2549
2624
|
if visible
|
2550
2625
|
visible_term = node.text
|
2551
|
-
@index.store_primary_term (
|
2626
|
+
@index.store_primary_term (FormattedString.new parse_text visible_term, inline_format: [normalize: true]), dest
|
2552
2627
|
%(#{anchor}#{visible_term})
|
2553
2628
|
else
|
2554
|
-
@index.store_term (node.attr 'terms').map {|term|
|
2629
|
+
@index.store_term (node.attr 'terms').map {|term| FormattedString.new parse_text term, inline_format: [normalize: true] }, dest
|
2555
2630
|
anchor
|
2556
2631
|
end
|
2557
2632
|
end
|
@@ -2578,8 +2653,6 @@ module Asciidoctor
|
|
2578
2653
|
end
|
2579
2654
|
|
2580
2655
|
def convert_inline_quoted node
|
2581
|
-
theme = load_theme node.document
|
2582
|
-
|
2583
2656
|
case node.type
|
2584
2657
|
when :emphasis
|
2585
2658
|
open, close, is_tag = ['<em>', '</em>', true]
|
@@ -2592,25 +2665,26 @@ module Asciidoctor
|
|
2592
2665
|
when :subscript
|
2593
2666
|
open, close, is_tag = ['<sub>', '</sub>', true]
|
2594
2667
|
when :double
|
2595
|
-
open, close
|
2668
|
+
open, close = (load_theme node.document).quotes.slice 0, 2
|
2596
2669
|
quotes = true
|
2597
2670
|
when :single
|
2598
|
-
open, close
|
2671
|
+
open, close = (load_theme node.document).quotes.slice 2, 2
|
2599
2672
|
quotes = true
|
2600
2673
|
when :mark
|
2601
2674
|
open, close, is_tag = ['<mark>', '</mark>', true]
|
2602
2675
|
else
|
2603
|
-
open
|
2676
|
+
open = close = ''
|
2604
2677
|
end
|
2605
2678
|
|
2606
2679
|
inner_text = node.text
|
2607
2680
|
|
2608
|
-
if quotes && (len = inner_text.length) > 3 &&
|
2609
|
-
|
2681
|
+
if quotes && (len = inner_text.length) > 3 && (inner_text.end_with? '...') &&
|
2682
|
+
!((inner_text_trunc = inner_text.slice 0, len - 3).end_with? ?\\)
|
2610
2683
|
inner_text = inner_text_trunc + '…'
|
2611
2684
|
end
|
2612
2685
|
|
2613
2686
|
if (roles = node.role)
|
2687
|
+
theme = load_theme node.document
|
2614
2688
|
roles.split.each do |role|
|
2615
2689
|
if (text_transform = theme[%(role_#{role}_text_transform)])
|
2616
2690
|
inner_text = transform_text inner_text, text_transform
|
@@ -2728,13 +2802,7 @@ module Asciidoctor
|
|
2728
2802
|
value = (value.split LF).delete_if {|line| SimpleAttributeRefRx.match? line }.join LF if opts[:drop_lines_with_unresolved_attributes] && (value.include? '{')
|
2729
2803
|
value = value.gsub '\{', '{' if escaped_attr_ref
|
2730
2804
|
doc.set_attr 'attribute-missing', attribute_missing unless attribute_missing == 'skip'
|
2731
|
-
if imagesdir
|
2732
|
-
if imagesdir_to_restore
|
2733
|
-
doc.set_attr 'imagesdir', imagesdir_to_restore
|
2734
|
-
else
|
2735
|
-
doc.remove_attr 'imagesdir'
|
2736
|
-
end
|
2737
|
-
end
|
2805
|
+
imagesdir_to_restore ? (doc.set_attr 'imagesdir', imagesdir_to_restore) : (doc.remove_attr 'imagesdir') if imagesdir
|
2738
2806
|
value
|
2739
2807
|
end
|
2740
2808
|
|
@@ -3871,6 +3939,10 @@ module Asciidoctor
|
|
3871
3939
|
{ width: 0, height: 0 }
|
3872
3940
|
end
|
3873
3941
|
|
3942
|
+
def intrinsic_image_width path, format
|
3943
|
+
(intrinsic_image_dimensions path, format)[:width]
|
3944
|
+
end
|
3945
|
+
|
3874
3946
|
# Sends the specified message to the log unless this method is called from the scratch document
|
3875
3947
|
def log severity, message = nil, &block
|
3876
3948
|
logger.send severity, message, &block unless scratch?
|
@@ -4042,11 +4114,15 @@ module Asciidoctor
|
|
4042
4114
|
if attrs.key? 'pdfwidth'
|
4043
4115
|
if (width = attrs['pdfwidth']).end_with? '%'
|
4044
4116
|
bounds_width ? (width.to_f / 100) * bounds_width : width
|
4117
|
+
elsif width.end_with? 'iw'
|
4118
|
+
(width.chomp 'iw').extend ImageWidth
|
4045
4119
|
elsif opts[:support_vw] && (width.end_with? 'vw')
|
4046
4120
|
(width.chomp 'vw').extend ViewportWidth
|
4047
4121
|
else
|
4048
4122
|
str_to_pt width
|
4049
4123
|
end
|
4124
|
+
elsif attrs.key? 'scale'
|
4125
|
+
attrs['scale'].dup.extend ImageWidth
|
4050
4126
|
elsif attrs.key? 'scaledwidth'
|
4051
4127
|
# NOTE: the parser automatically appends % if value is unitless
|
4052
4128
|
if (width = attrs['scaledwidth']).end_with? '%'
|
@@ -4317,7 +4393,7 @@ module Asciidoctor
|
|
4317
4393
|
b_shift, b_gap_color = (b_width ||= 0.5) * 0.5, @page_bg_color
|
4318
4394
|
end
|
4319
4395
|
ink_caption node_with_caption, category: category if node_with_caption
|
4320
|
-
extent.from.page
|
4396
|
+
extent.from.page = page_number unless extent.from.page == page_number # sanity check
|
4321
4397
|
float do
|
4322
4398
|
extent.each_page do |first_page, last_page|
|
4323
4399
|
advance_page unless first_page
|
@@ -30,4 +30,8 @@ class Asciidoctor::Section
|
|
30
30
|
end
|
31
31
|
opts[:formal] ? @cached_formal_numbered_title : @cached_numbered_title
|
32
32
|
end unless method_defined? :numbered_title
|
33
|
+
|
34
|
+
def first_section_of_part?
|
35
|
+
(par = @parent).context == :section && par.sectname == 'part' && self == par.blocks.find {|it| it.context == :section }
|
36
|
+
end unless method_defined? :first_section_of_part?
|
33
37
|
end
|
@@ -34,13 +34,14 @@ module Asciidoctor
|
|
34
34
|
# - :final_gap determines whether a gap is added below the last line
|
35
35
|
LineMetrics = ::Struct.new :height, :leading, :padding_top, :padding_bottom, :final_gap
|
36
36
|
|
37
|
-
Position = ::Struct.new :page, :cursor
|
37
|
+
Position = ::Struct.new :page, :column, :cursor
|
38
38
|
|
39
39
|
Extent = ::Struct.new :current, :from, :to do
|
40
|
-
def initialize current_page, current_cursor,
|
41
|
-
self.
|
42
|
-
self.from = Position.new
|
43
|
-
self.
|
40
|
+
def initialize current_page, current_column, current_cursor, from_page, from_column, from_cursor, to_page, to_cursor
|
41
|
+
self.current = Position.new current_page, current_column, current_cursor
|
42
|
+
self.from = Position.new from_page, from_column, from_cursor
|
43
|
+
self.from = current if from == current
|
44
|
+
self.to = Position.new to_page, nil, to_cursor
|
44
45
|
end
|
45
46
|
|
46
47
|
def each_page
|
@@ -64,23 +65,23 @@ module Asciidoctor
|
|
64
65
|
|
65
66
|
ScratchExtent = ::Struct.new :from, :to do
|
66
67
|
def initialize start_page, start_cursor, end_page, end_cursor
|
67
|
-
self.from = Position.new start_page, start_cursor
|
68
|
-
self.to = Position.new end_page, end_cursor
|
68
|
+
self.from = Position.new start_page, 0, start_cursor
|
69
|
+
self.to = Position.new end_page, 0, end_cursor
|
69
70
|
end
|
70
71
|
|
71
72
|
def position_onto pdf, keep_together = nil
|
72
73
|
current_page = pdf.page_number
|
74
|
+
current_column = ColumnBox === pdf.bounds ? (column_box = pdf.bounds).current_column : 0
|
73
75
|
current_cursor = pdf.cursor
|
74
|
-
|
75
|
-
to_page = current_page + (to.page - 1)
|
76
|
-
if advance_by > 0
|
76
|
+
if (advance_by = from.page - 1) > 0
|
77
77
|
advance_by.times { pdf.advance_page }
|
78
78
|
elsif keep_together && single_page? && !(try_to_fit_on_previous current_cursor)
|
79
79
|
pdf.advance_page
|
80
|
-
from_page += 1
|
81
|
-
to_page += 1
|
82
80
|
end
|
83
|
-
|
81
|
+
from_page = pdf.page_number
|
82
|
+
from_column = column_box&.current_column || 0
|
83
|
+
to_page = from_page + (to.page - from.page)
|
84
|
+
Extent.new current_page, current_column, current_cursor, from_page, from_column, from.cursor, to_page, to.cursor
|
84
85
|
end
|
85
86
|
|
86
87
|
def single_page?
|
@@ -972,11 +973,11 @@ module Asciidoctor
|
|
972
973
|
state.on_page_create_callback = saved_callback
|
973
974
|
end
|
974
975
|
|
975
|
-
# This method is a smarter version of start_new_page. It calls start_new_page
|
976
|
-
#
|
977
|
-
#
|
976
|
+
# This method is a smarter version of start_new_page. It only calls start_new_page options are
|
977
|
+
# specified and the current page is the last page in the document. Otherwise, it advances the
|
978
|
+
# cursor to the next page (or column) using Bounds#move_past_bottom.
|
978
979
|
def advance_page options = {}
|
979
|
-
|
980
|
+
options.empty? || !last_page? ? bounds.move_past_bottom : (start_new_page options)
|
980
981
|
end
|
981
982
|
|
982
983
|
# Start a new page without triggering the on_page_create callback
|
@@ -1136,19 +1137,19 @@ module Asciidoctor
|
|
1136
1137
|
# Note that if the block has content that itself requires a dry run, that nested dry run will
|
1137
1138
|
# be performed in a separate scratch document.
|
1138
1139
|
#
|
1139
|
-
#
|
1140
|
-
#
|
1141
|
-
#
|
1142
|
-
#
|
1143
|
-
#
|
1144
|
-
#
|
1145
|
-
#
|
1146
|
-
#
|
1147
|
-
#
|
1140
|
+
# options - A Hash of options that configure the dry run computation:
|
1141
|
+
# :keep_together - A Boolean indicating whether an attempt should be made to keep
|
1142
|
+
# the content on the same page (optional, default: false).
|
1143
|
+
# :single_page - A Boolean indicating whether the operation should stop if the
|
1144
|
+
# content exceeds the height of a single page.
|
1145
|
+
# :onto - The document onto which to position the scratch extent. If this option is
|
1146
|
+
# set, the method returns an Extent instance (optional, default: false)
|
1147
|
+
# :pages_advanced - The number of pages the content has been advanced during this
|
1148
|
+
# operation (internal only) (optional, default: 0)
|
1148
1149
|
#
|
1149
1150
|
# Returns an Extent or ScratchExtent object that describes the bounds of the content block.
|
1150
1151
|
def dry_run keep_together: nil, pages_advanced: 0, single_page: nil, onto: nil, &block
|
1151
|
-
(scratch_pdf = scratch).start_new_page
|
1152
|
+
(scratch_pdf = scratch).start_new_page layout: page.layout
|
1152
1153
|
saved_bounds = scratch_pdf.bounds
|
1153
1154
|
scratch_pdf.bounds = bounds.dup.tap do |bounds_copy|
|
1154
1155
|
bounds_copy.instance_variable_set :@document, scratch_pdf
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class FormattedString < String
|
4
|
+
attr_reader :fragments
|
5
|
+
|
6
|
+
def initialize fragments
|
7
|
+
super [].tap {|accum| (@fragments = fragments).each {|it| accum << it[:text] } }.join
|
8
|
+
end
|
9
|
+
|
10
|
+
def eql? other
|
11
|
+
super && (FormattedString === other ? (@fragments ||= nil) == other.fragments : true)
|
12
|
+
end
|
13
|
+
end
|
@@ -51,6 +51,9 @@ module Asciidoctor::PDF::FormattedText
|
|
51
51
|
image_format = fragment[:image_format]
|
52
52
|
if (image_w = fragment[:image_width] || '100%') == 'auto'
|
53
53
|
image_w = nil # use intrinsic width
|
54
|
+
elsif image_w.start_with? 'auto*'
|
55
|
+
image_scale = (image_w.slice 5, image_w.length).to_f
|
56
|
+
image_w = nil # use intrinsic width
|
54
57
|
elsif (pctidx = image_w.index '%') && pctidx + 1 < image_w.length
|
55
58
|
# NOTE: intrinsic width is stored behind % symbol
|
56
59
|
pct = (image_w.slice 0, pctidx).to_f / 100
|
@@ -79,6 +82,7 @@ module Asciidoctor::PDF::FormattedText
|
|
79
82
|
image_w = svg_size.output_width
|
80
83
|
else
|
81
84
|
fragment[:image_width] = (image_w = svg_size.output_width).to_s
|
85
|
+
image_w *= image_scale if image_scale
|
82
86
|
image_w = available_w if image_w > available_w
|
83
87
|
end
|
84
88
|
fragment[:image_obj] = svg_obj
|
@@ -88,6 +92,7 @@ module Asciidoctor::PDF::FormattedText
|
|
88
92
|
image_obj, image_info = ::File.open(image_path, 'rb') {|fd| doc.build_image_object fd }
|
89
93
|
unless image_w
|
90
94
|
fragment[:image_width] = (image_w = to_pt image_info.width, :px).to_s
|
95
|
+
image_w *= image_scale if image_scale
|
91
96
|
image_w = available_w if image_w > available_w
|
92
97
|
end
|
93
98
|
if (image_h = image_w * (image_info.height.fdiv image_info.width)) > max_image_h
|
@@ -25,11 +25,11 @@ module Asciidoctor::PDF::FormattedText
|
|
25
25
|
width = fragment.width
|
26
26
|
height = fragment.height
|
27
27
|
end
|
28
|
-
border_radius = data[:border_radius]
|
28
|
+
border_radius = data[:border_radius] || 0
|
29
29
|
if (background_color = data[:background_color])
|
30
30
|
prev_fill_color = pdf.fill_color
|
31
31
|
pdf.fill_color background_color
|
32
|
-
if border_radius
|
32
|
+
if border_radius > 0
|
33
33
|
pdf.fill_rounded_rectangle at, width, height, border_radius
|
34
34
|
else
|
35
35
|
pdf.fill_rectangle at, width, height
|
@@ -41,7 +41,7 @@ module Asciidoctor::PDF::FormattedText
|
|
41
41
|
prev_line_width = pdf.line_width
|
42
42
|
pdf.stroke_color border_color
|
43
43
|
pdf.line_width border_width
|
44
|
-
border_radius ? (pdf.stroke_rounded_rectangle at, width, height, border_radius) : (pdf.stroke_rectangle at, width, height)
|
44
|
+
border_radius > 0 ? (pdf.stroke_rounded_rectangle at, width, height, border_radius) : (pdf.stroke_rectangle at, width, height)
|
45
45
|
pdf.stroke_color prev_stroke_color
|
46
46
|
pdf.line_width prev_line_width
|
47
47
|
end
|
@@ -96,21 +96,24 @@ module Asciidoctor
|
|
96
96
|
}.compact,
|
97
97
|
}
|
98
98
|
@theme_settings.tap do |accum|
|
99
|
-
|
99
|
+
roles_with_styles = [].to_set
|
100
100
|
theme.each_pair do |key, val|
|
101
101
|
next unless (key = key.to_s).start_with? 'role_'
|
102
102
|
role, key = (key.slice 5, key.length).split '_', 2
|
103
103
|
if (prop = ThemeKeyToFragmentProperty[key])
|
104
104
|
(accum[role] ||= {})[prop] = val
|
105
|
+
if key == 'border_width' && val && !(theme[%(role_#{role}_border_color)])
|
106
|
+
accum[role][:border_color] = theme.base_border_color
|
107
|
+
end
|
105
108
|
#elsif key == 'font_kerning'
|
106
109
|
# unless (resolved_val = val == 'none' ? false : (val == 'normal' ? true : nil)).nil?
|
107
110
|
# (accum[role] ||= {})[:kerning] = resolved_val
|
108
111
|
# end
|
109
112
|
elsif key == 'font_style' || key == 'text_decoration'
|
110
|
-
|
113
|
+
roles_with_styles << role
|
111
114
|
end
|
112
115
|
end
|
113
|
-
|
116
|
+
roles_with_styles.each do |role|
|
114
117
|
(accum[role] ||= {})[:styles] = to_styles theme[%(role_#{role}_font_style)], theme[%(role_#{role}_text_decoration)]
|
115
118
|
end
|
116
119
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: asciidoctor-pdf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dan Allen
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2022-06-
|
12
|
+
date: 2022-06-17 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: asciidoctor
|
@@ -286,6 +286,7 @@ files:
|
|
286
286
|
- lib/asciidoctor/pdf/ext/rouge.rb
|
287
287
|
- lib/asciidoctor/pdf/ext/rouge/formatters/prawn.rb
|
288
288
|
- lib/asciidoctor/pdf/ext/rouge/themes/asciidoctor_pdf_default.rb
|
289
|
+
- lib/asciidoctor/pdf/formatted_string.rb
|
289
290
|
- lib/asciidoctor/pdf/formatted_text.rb
|
290
291
|
- lib/asciidoctor/pdf/formatted_text/formatter.rb
|
291
292
|
- lib/asciidoctor/pdf/formatted_text/fragment_position_renderer.rb
|