asciidoctor-pdf 2.3.19 → 2.3.21
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 +39 -0
- data/README.adoc +1 -1
- data/asciidoctor-pdf.gemspec +1 -1
- data/data/fonts/mplus1p-regular-fallback.ttf +0 -0
- data/lib/asciidoctor/pdf/converter.rb +152 -75
- data/lib/asciidoctor/pdf/ext/prawn/extensions.rb +5 -1
- data/lib/asciidoctor/pdf/ext/prawn/font/ttf.rb +8 -0
- data/lib/asciidoctor/pdf/ext/prawn/formatted_text/arranger.rb +9 -4
- data/lib/asciidoctor/pdf/ext/prawn.rb +1 -0
- data/lib/asciidoctor/pdf/formatted_text/formatter.rb +2 -1
- data/lib/asciidoctor/pdf/formatted_text/transform.rb +6 -2
- data/lib/asciidoctor/pdf/index_catalog.rb +69 -13
- data/lib/asciidoctor/pdf/version.rb +1 -1
- data/lib/asciidoctor/pdf.rb +9 -2
- metadata +6 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4250f6c0a0f203fe5e164656467da521bf4741771dd2627030c02a5401c24970
|
4
|
+
data.tar.gz: ef2cdb91e970f26ec2cbbb680d94db21d613aaf3c339492f63bbdb5c30a19337
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a53a41fffe731219da61c25eea7f443dd7cb3b64594e116637f28f2f43173a8d4f43c1b7040cacee56566a3e0bb6be474a6d488275d02094646ea1d48b1fb9a2
|
7
|
+
data.tar.gz: 717af76d4f0f4d958301f099e68ccd3395bc54b5740b2fa47d741fee2bd13aec2d2f48e5443c5d43f64535f23f6b12dc1a00d1c0dd74216a0f95f7ac15845e89
|
data/CHANGELOG.adoc
CHANGED
@@ -5,6 +5,45 @@
|
|
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.3.21 (2025-10-08) - @mojavelinux
|
9
|
+
|
10
|
+
Improvements::
|
11
|
+
|
12
|
+
* remove shy hyphens from text in log message when formatted text cannot be parsed (#2599)
|
13
|
+
* clear float box if next block falls outside of flaot group (#2596)
|
14
|
+
* resolve fonts relative to theme dir before GEM_FONTS_DIR if `pdf-fontsdir` not specified (#2349)
|
15
|
+
* add see and see-also associations on index terms to index (#2527)
|
16
|
+
|
17
|
+
=== Details
|
18
|
+
|
19
|
+
{url-repo}/releases/tag/v2.3.21[git tag] | {url-repo}/compare/v2.3.20\...v2.3.21[full diff]
|
20
|
+
|
21
|
+
== 2.3.20 (2025-09-17) - @mojavelinux
|
22
|
+
|
23
|
+
Improvements::
|
24
|
+
|
25
|
+
* add symbols for shift, command, option, and return keys to the fallback font
|
26
|
+
* render horizontal dlist without using prawn-table, allowing the description to exceed the height of one page (#2591)
|
27
|
+
* allow relative font size for sub and sup to be set independently (support combined setting for backwards compatibility)
|
28
|
+
* allow value of `base-font-size-min` and `<category>-font-size-min` theme keys to be relative (e.g., 0.75em) (#2547)
|
29
|
+
* respect `hide-uri-scheme` attribute when appending URL to link text when media is print or prepress (#2583)
|
30
|
+
|
31
|
+
Bug Fixes::
|
32
|
+
|
33
|
+
* always force NULL character to have 0 width, even if missing from font (#2585)
|
34
|
+
* don't drop line in running content if attribute reference resolves to text that contains attribute reference (not originally present)
|
35
|
+
* correctly calculate extent for block in columns that starts below doctitle (#2579)
|
36
|
+
* support internal link on image (value of link attribute starts with #) (#2572)
|
37
|
+
|
38
|
+
Compliance::
|
39
|
+
|
40
|
+
* suppress warning about the use of Ruby's logger gem when loading Asciidoctor
|
41
|
+
* ignore error if bigdecimal gem cannot be eagerly required
|
42
|
+
|
43
|
+
=== Details
|
44
|
+
|
45
|
+
{url-repo}/releases/tag/v2.3.20[git tag] | {url-repo}/compare/v2.3.19\...v2.3.20[full diff]
|
46
|
+
|
8
47
|
== 2.3.19 (2024-10-11) - @mojavelinux
|
9
48
|
|
10
49
|
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.
|
3
|
+
v2.3.21, 2025-10-08
|
4
4
|
// Settings:
|
5
5
|
:experimental:
|
6
6
|
:idprefix:
|
data/asciidoctor-pdf.gemspec
CHANGED
@@ -41,7 +41,7 @@ Gem::Specification.new do |s|
|
|
41
41
|
s.add_runtime_dependency 'prawn-templates', '~> 0.1.0'
|
42
42
|
s.add_runtime_dependency 'prawn-svg', '~> 0.34.0'
|
43
43
|
s.add_runtime_dependency 'prawn-icon', '~> 3.0.0'
|
44
|
-
s.add_runtime_dependency 'concurrent-ruby', '~> 1.
|
44
|
+
s.add_runtime_dependency 'concurrent-ruby', '~> 1.3'
|
45
45
|
s.add_runtime_dependency 'treetop', '~> 1.6.0'
|
46
46
|
|
47
47
|
s.add_development_dependency 'rake', '~> 13.0.0'
|
Binary file
|
@@ -1,6 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative 'formatted_string'
|
4
3
|
require_relative 'formatted_text'
|
5
4
|
require_relative 'index_catalog'
|
6
5
|
require_relative 'pdfmark'
|
@@ -104,7 +103,7 @@ module Asciidoctor
|
|
104
103
|
}
|
105
104
|
TypographicQuotes = %w(“ ” ‘ ’)
|
106
105
|
InlineFormatSniffRx = /[<&]/
|
107
|
-
SimpleAttributeRefRx = /(?<!\\)\{\w+(?:-\w+)
|
106
|
+
SimpleAttributeRefRx = /(?<!\\)\{(\w+(?:-\w+)*)\}/
|
108
107
|
MeasurementRxt = '\\d+(?:\\.\\d+)?(?:in|cm|mm|p[txc])?'
|
109
108
|
MeasurementPartsRx = /^(\d+(?:\.\d+)?)(in|mm|cm|p[txc])?$/
|
110
109
|
PageSizeRx = /^(?:\[(#{MeasurementRxt}), ?(#{MeasurementRxt})\]|(#{MeasurementRxt})(?: x |x)(#{MeasurementRxt})|\S+)$/
|
@@ -403,7 +402,7 @@ module Asciidoctor
|
|
403
402
|
@page_bg_image = {}
|
404
403
|
@page_bg_color = resolve_theme_color :page_background_color, 'FFFFFF'
|
405
404
|
# QUESTION: should ThemeLoader handle registering fonts instead?
|
406
|
-
register_fonts theme.font_catalog, ((doc.attr 'pdf-fontsdir')&.sub '{docdir}', (doc.attr 'docdir')) || 'GEM_FONTS_DIR'
|
405
|
+
register_fonts theme.font_catalog, ((doc.attr 'pdf-fontsdir')&.sub '{docdir}', (doc.attr 'docdir')) || (theme.__dir__ == ThemeLoader::ThemesDir ? 'GEM_FONTS_DIR' : %(#{theme.__dir__};GEM_FONTS_DIR))
|
407
406
|
default_kerning theme.base_font_kerning != 'none'
|
408
407
|
@fallback_fonts = Array theme.font_fallbacks
|
409
408
|
@root_font_size = theme.base_font_size
|
@@ -710,6 +709,7 @@ module Asciidoctor
|
|
710
709
|
end
|
711
710
|
|
712
711
|
def convert_index_section node
|
712
|
+
@index.link_associations
|
713
713
|
if ColumnBox === bounds || (columns = @theme.index_columns || 1) < 2
|
714
714
|
convert_index_categories @index.categories, (node.document.attr 'index-pagenum-sequence-style')
|
715
715
|
else
|
@@ -739,41 +739,73 @@ module Asciidoctor
|
|
739
739
|
end
|
740
740
|
|
741
741
|
def convert_index_term term, pagenum_sequence_style = nil
|
742
|
-
|
742
|
+
# NOTE: dup fragment list and all fragments to avoid any modification
|
743
|
+
term_fragments = term.name.fragments.map(&:dup)
|
743
744
|
unless term.container?
|
744
|
-
pagenum_fragment = (parse_text %(<a>#{DummyText}</a>), inline_format: true)[0]
|
745
745
|
if @media == 'screen'
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
pagenums = term.dests.map {|dest| pagenum_fragment.merge text: dest[:page], anchor: dest[:anchor] }
|
746
|
+
link_fragment = (parse_text %(<a>#{DummyText}</a>), inline_format: true)[0]
|
747
|
+
term_fragments.unshift name: term.anchor, callback: [FormattedText::InlineDestinationMarker], text: DummyText
|
748
|
+
end
|
749
|
+
if (see = term.see)
|
750
|
+
term_fragments << { text: ' (see ' }
|
751
|
+
if link_fragment && IndexTerm === see
|
752
|
+
link_fragment_ = link_fragment.merge anchor: see.anchor
|
753
|
+
see.name.fragments.each {|it| term_fragments << (link_fragment_.merge it) }
|
754
|
+
else
|
755
|
+
term_fragments.concat see.name.fragments
|
757
756
|
end
|
757
|
+
term_fragments << { text: ')' }
|
758
758
|
else
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
759
|
+
if @media == 'screen'
|
760
|
+
case pagenum_sequence_style
|
761
|
+
when 'page'
|
762
|
+
pagenums = term.dests.uniq {|dest| dest[:page] }.map {|dest| link_fragment.merge anchor: dest[:anchor], text: dest[:page] }
|
763
|
+
when 'range'
|
764
|
+
first_anchor_per_page = {}.tap {|accum| term.dests.each {|dest| accum[dest[:page]] ||= dest[:anchor] } }
|
765
|
+
pagenums = (consolidate_ranges first_anchor_per_page.keys).map do |range|
|
766
|
+
anchor = first_anchor_per_page[(range.include? '-') ? (range.partition '-')[0] : range]
|
767
|
+
link_fragment.merge text: range, anchor: anchor
|
768
|
+
end
|
769
|
+
else # term
|
770
|
+
pagenums = term.dests.map {|dest| link_fragment.merge text: dest[:page], anchor: dest[:anchor] }
|
771
|
+
end
|
764
772
|
else
|
765
|
-
|
766
|
-
|
773
|
+
pagenums = consolidate_ranges term.dests.map {|dest| dest[:page] }.uniq
|
774
|
+
end
|
775
|
+
pagenums.each do |pagenum|
|
776
|
+
if ::String === pagenum
|
777
|
+
term_fragments << ({ text: %(, #{pagenum}) })
|
778
|
+
else
|
779
|
+
term_fragments << { text: ', ' }
|
780
|
+
term_fragments << pagenum
|
781
|
+
end
|
782
|
+
end
|
783
|
+
if (see_also = term.see_also)
|
784
|
+
see_also_items = []
|
785
|
+
see_also.each do |also_term|
|
786
|
+
see_also_fragments = [{ text: '(see also ' }]
|
787
|
+
if link_fragment && IndexTerm === also_term
|
788
|
+
link_fragment_ = link_fragment.merge anchor: also_term.anchor
|
789
|
+
also_term.name.fragments.map {|it| see_also_fragments << (link_fragment_.merge it) }
|
790
|
+
else
|
791
|
+
see_also_fragments.concat also_term.name.fragments
|
792
|
+
end
|
793
|
+
see_also_fragments << { text: ')' }
|
794
|
+
see_also_items << see_also_fragments
|
795
|
+
end
|
767
796
|
end
|
768
797
|
end
|
769
798
|
end
|
770
799
|
subterm_indent = @theme.description_list_description_indent
|
771
800
|
typeset_formatted_text term_fragments, (calc_line_metrics @base_line_height), align: :left, color: @font_color, hanging_indent: subterm_indent * 2, consolidate: true
|
772
801
|
indent subterm_indent do
|
802
|
+
see_also_items&.each do |see_also_fragments|
|
803
|
+
typeset_formatted_text see_also_fragments, (calc_line_metrics @base_line_height), align: :left, color: @font_color, hanging_indent: subterm_indent * 2, consolidate: true
|
804
|
+
end
|
773
805
|
term.subterms.each do |subterm|
|
774
806
|
convert_index_term subterm, pagenum_sequence_style
|
775
|
-
end
|
776
|
-
end
|
807
|
+
end unless term.leaf?
|
808
|
+
end if see_also_items || !term.leaf?
|
777
809
|
end
|
778
810
|
|
779
811
|
def convert_preamble node
|
@@ -871,14 +903,19 @@ module Asciidoctor
|
|
871
903
|
end
|
872
904
|
|
873
905
|
if (float_box = (@float_box ||= nil))
|
874
|
-
|
875
|
-
|
876
|
-
|
877
|
-
|
878
|
-
|
879
|
-
|
880
|
-
|
906
|
+
if (prev_sibling = node.previous_sibling)&.context == :open && (prev_sibling.role? 'float-group')
|
907
|
+
move_cursor_to float_box[:bottom]
|
908
|
+
@float_box = nil
|
909
|
+
else
|
910
|
+
ink_paragraph_in_float_box node, float_box, prose_opts, role_keys, block_next, insert_margin_bottom
|
911
|
+
return
|
912
|
+
end
|
881
913
|
end
|
914
|
+
# TODO: check if we're within one line of the bottom of the page
|
915
|
+
# and advance to the next page if so (similar to logic for section titles)
|
916
|
+
ink_caption node, labeled: false if node.title?
|
917
|
+
role_keys ? theme_font_cascade(role_keys) { ink_prose node.content, prose_opts } : (ink_prose node.content, prose_opts)
|
918
|
+
insert_margin_bottom.call
|
882
919
|
end
|
883
920
|
|
884
921
|
def convert_admonition node
|
@@ -1421,55 +1458,62 @@ module Asciidoctor
|
|
1421
1458
|
convert_list list
|
1422
1459
|
markers.pop
|
1423
1460
|
when 'horizontal'
|
1424
|
-
|
1425
|
-
term_padding = term_padding_no_blocks = term_font_color = term_transform = desc_padding = term_line_metrics = term_inline_format = term_kerning = nil
|
1461
|
+
ink_caption node, category: :description_list, labeled: false if node.title?
|
1426
1462
|
max_term_width = 0
|
1463
|
+
term_height = term_padding = term_font_styles = term_transform = desc_padding = term_line_metrics = term_inline_format = term_kerning = nil
|
1427
1464
|
theme_font :description_list_term do
|
1428
|
-
|
1465
|
+
term_height = height_of_typeset_text 'A'
|
1429
1466
|
term_transform = @text_transform
|
1430
1467
|
term_inline_format = (term_font_styles = font_styles).empty? ? true : [inherited: { styles: term_font_styles }]
|
1431
1468
|
term_line_metrics = calc_line_metrics @base_line_height
|
1432
|
-
|
1433
|
-
(term_padding = (term_padding_no_blocks.drop 0))[2] += @theme.prose_margin_bottom * 0.5
|
1469
|
+
term_padding = [term_line_metrics.padding_top, 10, term_line_metrics.padding_bottom, 10]
|
1434
1470
|
desc_padding = [0, 10, 0, 10]
|
1435
1471
|
term_kerning = default_kerning?
|
1436
1472
|
end
|
1437
|
-
|
1438
|
-
|
1473
|
+
prose_height = height_of_typeset_text 'A'
|
1474
|
+
items = node.items.map do |item|
|
1439
1475
|
terms, desc = item
|
1440
|
-
|
1441
|
-
|
1442
|
-
|
1443
|
-
|
1444
|
-
|
1445
|
-
|
1446
|
-
text_color: term_font_color,
|
1447
|
-
kerning: term_kerning,
|
1448
|
-
content: term_text,
|
1449
|
-
inline_format: term_inline_format,
|
1450
|
-
padding: desc&.blocks? ? term_padding : term_padding_no_blocks,
|
1451
|
-
leading: term_line_metrics.leading,
|
1452
|
-
# FIXME: prawn-table doesn't have support for final_gap option
|
1453
|
-
#final_gap: term_line_metrics.final_gap,
|
1454
|
-
valign: :top,
|
1455
|
-
}]
|
1456
|
-
if desc
|
1457
|
-
desc_container = Block.new node, :open
|
1458
|
-
desc_container << (Block.new desc_container, :paragraph, source: (desc.instance_variable_get :@text), subs: :default) if desc.text?
|
1459
|
-
desc.blocks.each {|b| desc_container << b.dup } if desc.blocks?
|
1460
|
-
row_data << { content: (::Prawn::Table::Cell::AsciiDoc.new self, content: (item[1] = desc_container), text_color: @font_color, padding: desc_padding, valign: :top, source_location: desc.source_location) }
|
1461
|
-
else
|
1462
|
-
row_data << {}
|
1476
|
+
terms_as_text = terms.map do |term|
|
1477
|
+
term_text = term_transform ? (transform_text term.text, term_transform) : term.text
|
1478
|
+
if (term_width = width_of term_text, inline_format: term_inline_format, kerning: term_kerning) > max_term_width
|
1479
|
+
max_term_width = term_width
|
1480
|
+
end
|
1481
|
+
term_text
|
1463
1482
|
end
|
1464
|
-
|
1483
|
+
[terms_as_text, desc]
|
1465
1484
|
end
|
1466
|
-
|
1467
|
-
|
1468
|
-
|
1469
|
-
|
1470
|
-
|
1485
|
+
term_side_padding = term_padding[1] + (term_left = term_padding[3])
|
1486
|
+
max_term_width += term_side_padding
|
1487
|
+
term_column_width = [max_term_width, bounds.width * 0.5 - term_side_padding].min
|
1488
|
+
term_spacing = @theme.description_list_term_spacing
|
1489
|
+
items.each do |terms_as_text, desc|
|
1490
|
+
advance_page if !at_page_top? && cursor < [((term_spacing + term_height) * terms_as_text.size) - term_spacing, desc ? prose_height : 0].max
|
1491
|
+
initial_y = y
|
1492
|
+
initial_page_number = page_number
|
1493
|
+
indent term_left, (bounds.width - term_column_width) do
|
1494
|
+
theme_font :description_list_term do
|
1495
|
+
terms_as_text.each_with_index do |term_text, idx|
|
1496
|
+
ink_prose term_text, margin_top: (idx > 0 ? term_spacing : 0), margin_bottom: 0, align: :left, normalize_line_height: true, styles: term_font_styles
|
1497
|
+
end
|
1498
|
+
end
|
1499
|
+
end
|
1500
|
+
if desc # rubocop:disable Style/Next
|
1501
|
+
after_term_y = y
|
1502
|
+
after_term_page_number = page_number
|
1503
|
+
go_to_page initial_page_number if page_number > initial_page_number
|
1504
|
+
@y = initial_y
|
1505
|
+
indent term_column_width + desc_padding[3], desc_padding[1] do
|
1506
|
+
traverse_list_item desc, :dlist_desc, normalize_line_height: true, margin_bottom: ((next_enclosed_block desc, descend: true) ? nil : 0)
|
1507
|
+
end
|
1508
|
+
if page_number < after_term_page_number
|
1509
|
+
go_to_page after_term_page_number
|
1510
|
+
@y = after_term_y
|
1511
|
+
elsif y > after_term_y
|
1512
|
+
@y = after_term_y
|
1513
|
+
end
|
1514
|
+
end
|
1471
1515
|
end
|
1472
|
-
theme_margin :prose, :bottom, (next_enclosed_block
|
1516
|
+
theme_margin :prose, :bottom, (next_enclosed_block node) unless node.nested?
|
1473
1517
|
when 'qanda'
|
1474
1518
|
@list_numerals << 1
|
1475
1519
|
convert_list node
|
@@ -2459,6 +2503,7 @@ module Asciidoctor
|
|
2459
2503
|
%(#{anchor}<a href="#{target}"#{attrs.join}>#{breakable_uri text}</a>)
|
2460
2504
|
# NOTE: @media may not be initialized if method is called before convert phase
|
2461
2505
|
elsif (doc.attr? 'show-link-uri') || (@media != 'screen' && (doc.attr_unspecified? 'show-link-uri'))
|
2506
|
+
bare_target = (bare_target.split UriSchemeBoundaryRx, 2)[1] || bare_target if doc.attr? 'hide-uri-scheme'
|
2462
2507
|
# QUESTION: should we insert breakable chars into URI when building fragment instead?
|
2463
2508
|
# TODO: allow style of printed link to be controlled by theme
|
2464
2509
|
%(#{anchor}<a href="#{target}"#{attrs.join}>#{text}</a> [<font size="0.85em">#{breakable_uri bare_target}</font>])
|
@@ -2639,7 +2684,11 @@ module Asciidoctor
|
|
2639
2684
|
img = %([#{node.attr 'alt'}])
|
2640
2685
|
end
|
2641
2686
|
end
|
2642
|
-
(node.attr? 'link')
|
2687
|
+
if (node.attr? 'link') && (link = node.attr 'link')
|
2688
|
+
link.chr == '#' ? %(<a anchor="#{link.slice 1}">#{img}</a>) : %(<a href="#{link}">#{img}</a>)
|
2689
|
+
else
|
2690
|
+
img
|
2691
|
+
end
|
2643
2692
|
end
|
2644
2693
|
|
2645
2694
|
def convert_inline_indexterm node
|
@@ -2655,12 +2704,19 @@ module Asciidoctor
|
|
2655
2704
|
# NOTE: page number (:page key) is added by InlineDestinationMarker
|
2656
2705
|
dest = { anchor: (anchor_name = @index.next_anchor_name) }
|
2657
2706
|
anchor = %(<a id="#{anchor_name}" type="indexterm"#{visible ? ' visible="true"' : ''}>#{DummyText}</a>)
|
2707
|
+
assoc = {}
|
2708
|
+
if (see = node.attr 'see')
|
2709
|
+
assoc[:see] = parse_text see, inline_format: [normalize: true]
|
2710
|
+
end
|
2711
|
+
if (see_also = node.attr 'see-also')
|
2712
|
+
assoc[:see_also] = see_also.map {|term| parse_text term, inline_format: [normalize: true] }
|
2713
|
+
end
|
2658
2714
|
if visible
|
2659
2715
|
visible_term = node.text
|
2660
|
-
@index.
|
2716
|
+
@index.store_term [(parse_text visible_term, inline_format: [normalize: true])], dest, assoc
|
2661
2717
|
%(#{anchor}#{visible_term})
|
2662
2718
|
else
|
2663
|
-
@index.store_term (node.attr 'terms').map {|term|
|
2719
|
+
@index.store_term (node.attr 'terms').map {|term| parse_text term, inline_format: [normalize: true] }, dest, assoc
|
2664
2720
|
anchor
|
2665
2721
|
end
|
2666
2722
|
end
|
@@ -2831,8 +2887,11 @@ module Asciidoctor
|
|
2831
2887
|
# FIXME: get sub_attributes to handle drop-line w/o a warning
|
2832
2888
|
doc.set_attr 'attribute-missing', 'skip' unless (attribute_missing = doc.attr 'attribute-missing') == 'skip'
|
2833
2889
|
value = value.gsub '\{', '\\\\\\{' if (escaped_attr_ref = value.include? '\{')
|
2890
|
+
value_before_subs = value
|
2834
2891
|
value = (subs = opts[:subs]) ? (doc.apply_subs value, subs) : (doc.apply_subs value)
|
2835
|
-
|
2892
|
+
if opts[:drop_lines_with_unresolved_attributes] && (value.include? '{')
|
2893
|
+
value = (value.split LF).delete_if {|line| SimpleAttributeRefRx =~ line && (value_before_subs.include? '{' + $1 + '}') }.join LF
|
2894
|
+
end
|
2836
2895
|
value = value.gsub '\{', '{' if escaped_attr_ref
|
2837
2896
|
doc.set_attr 'attribute-missing', attribute_missing unless attribute_missing == 'skip'
|
2838
2897
|
page_layout_to_restore ? (doc.set_attr 'page-layout', page_layout_to_restore) : (doc.remove_attr 'page-layout') if page_layout
|
@@ -4724,7 +4783,12 @@ module Asciidoctor
|
|
4724
4783
|
image_y = y - image_opts[:vposition]
|
4725
4784
|
end unless (image_y = image_opts[:y])
|
4726
4785
|
|
4727
|
-
|
4786
|
+
loc = [image_x, (image_y - image_height), (image_x + image_width), image_y]
|
4787
|
+
if uri.chr == '#'
|
4788
|
+
link_annotation loc, Border: [0, 0, 0], Dest: (uri.slice 1)
|
4789
|
+
else
|
4790
|
+
link_annotation loc, Border: [0, 0, 0], A: { Type: :Action, S: :URI, URI: uri.as_pdf }
|
4791
|
+
end
|
4728
4792
|
end
|
4729
4793
|
|
4730
4794
|
def admonition_icon_data key
|
@@ -4805,7 +4869,7 @@ module Asciidoctor
|
|
4805
4869
|
padding = expand_padding_value @theme[%(#{category}_padding)]
|
4806
4870
|
if actual_width > (available_width = bounds.width - padding[3].to_f - padding[1].to_f)
|
4807
4871
|
adjusted_font_size = ((available_width * font_size).to_f / actual_width).truncate 4
|
4808
|
-
if (min = @theme[%(#{category}_font_size_min)] || @theme.base_font_size_min) && adjusted_font_size < min
|
4872
|
+
if (min = @theme[%(#{category}_font_size_min)] || @theme.base_font_size_min) && adjusted_font_size < (min = resolve_font_size min)
|
4809
4873
|
min
|
4810
4874
|
else
|
4811
4875
|
adjusted_font_size
|
@@ -4813,6 +4877,19 @@ module Asciidoctor
|
|
4813
4877
|
end
|
4814
4878
|
end
|
4815
4879
|
|
4880
|
+
def resolve_font_size value
|
4881
|
+
return value unless ::String === value
|
4882
|
+
if value.end_with? 'rem'
|
4883
|
+
@root_font_size * value.to_f
|
4884
|
+
elsif value.end_with? 'em'
|
4885
|
+
font_size * value.to_f
|
4886
|
+
elsif value.end_with? '%'
|
4887
|
+
font_size * (value.to_f / 100)
|
4888
|
+
else
|
4889
|
+
value.to_f
|
4890
|
+
end
|
4891
|
+
end
|
4892
|
+
|
4816
4893
|
def consolidate_ranges nums
|
4817
4894
|
if nums.size > 1
|
4818
4895
|
prev = nil
|
@@ -1146,7 +1146,11 @@ module Asciidoctor
|
|
1146
1146
|
bounds_copy.instance_variable_set :@parent, saved_bounds
|
1147
1147
|
bounds_copy.single_file if ColumnBox === bounds_copy
|
1148
1148
|
end
|
1149
|
-
|
1149
|
+
if !(scratch_start_at_top = keep_together || pages_advanced > 0 || at_page_top?)
|
1150
|
+
scratch_pdf.move_cursor_to cursor
|
1151
|
+
elsif ColumnBox === bounds
|
1152
|
+
scratch_pdf.move_cursor_to scratch_pdf.bounds.top
|
1153
|
+
end
|
1150
1154
|
scratch_start_cursor = scratch_pdf.cursor
|
1151
1155
|
scratch_start_page = scratch_pdf.page_number
|
1152
1156
|
inhibit_new_page = state.on_page_create_callback == InhibitNewPageProc
|
@@ -9,7 +9,7 @@ Prawn::Text::Formatted::Arranger.prepend (Module.new do
|
|
9
9
|
super
|
10
10
|
@dummy_text = ?\u0000
|
11
11
|
@normalize_line_height = false
|
12
|
-
@
|
12
|
+
@sub_relative_size = @sup_relative_size = 0.583
|
13
13
|
end
|
14
14
|
|
15
15
|
def format_array= array
|
@@ -38,13 +38,18 @@ Prawn::Text::Formatted::Arranger.prepend (Module.new do
|
|
38
38
|
end
|
39
39
|
|
40
40
|
def apply_font_size size, styles
|
41
|
-
if (subscript? styles) || (superscript? styles)
|
41
|
+
if (sub = subscript? styles) || (superscript? styles)
|
42
42
|
size ||= @document.font_size
|
43
|
+
if instance_variable_defined? :@sub_and_sup_relative_size
|
44
|
+
relative_size = @sub_and_sup_relative_size
|
45
|
+
else
|
46
|
+
relative_size = sub ? @sub_relative_size : @sup_relative_size
|
47
|
+
end
|
43
48
|
if String === size
|
44
49
|
units = (size.end_with? 'em', '%') ? ((size.end_with? '%') ? '%' : 'em') : ''
|
45
|
-
size = %(#{size.to_f *
|
50
|
+
size = %(#{size.to_f * relative_size}#{units})
|
46
51
|
else
|
47
|
-
size *=
|
52
|
+
size *= relative_size
|
48
53
|
end
|
49
54
|
@document.font_size(size) { yield }
|
50
55
|
elsif size
|
@@ -8,6 +8,7 @@ Prawn::FLOAT_PRECISION = 1e-3
|
|
8
8
|
require_relative 'prawn/document/column_box'
|
9
9
|
require_relative 'prawn/font_metric_cache'
|
10
10
|
require_relative 'prawn/font/afm'
|
11
|
+
require_relative 'prawn/font/ttf'
|
11
12
|
require_relative 'prawn/images'
|
12
13
|
require_relative 'prawn/formatted_text/arranger'
|
13
14
|
require_relative 'prawn/formatted_text/box'
|
@@ -10,6 +10,7 @@ module Asciidoctor
|
|
10
10
|
|
11
11
|
FormattingSnifferPattern = /[<&]/
|
12
12
|
WHITESPACE = %( \t\n)
|
13
|
+
SHY = ::Prawn::Text::SHY
|
13
14
|
|
14
15
|
def initialize options = {}
|
15
16
|
@parser = MarkupParser.new
|
@@ -26,7 +27,7 @@ module Asciidoctor
|
|
26
27
|
return @transform.apply parsed.content, [], inherited
|
27
28
|
end
|
28
29
|
reason = @parser.failure_reason.sub %r/ at line \d+, column \d+ \(byte (\d+)\)(.*)/, '\2 at byte \1'
|
29
|
-
logger.error %(failed to parse formatted text: #{string} (reason: #{reason})) unless @scratch
|
30
|
+
logger.error %(failed to parse formatted text: #{string.tr SHY, ''} (reason: #{reason.tr SHY, ''})) unless @scratch
|
30
31
|
end
|
31
32
|
[inherited ? (inherited.merge text: string) : { text: string }]
|
32
33
|
end
|
@@ -212,8 +212,12 @@ module Asciidoctor
|
|
212
212
|
fragment[:callback] = [TextBackgroundAndBorderRenderer] | fragment[:callback]
|
213
213
|
end
|
214
214
|
end if attributes.key? :class
|
215
|
-
if inherited
|
216
|
-
|
215
|
+
if inherited
|
216
|
+
if (link = inherited[:link])
|
217
|
+
fragment[:link] = link
|
218
|
+
elsif (anchor = inherited[:anchor])
|
219
|
+
fragment[:anchor] = anchor
|
220
|
+
end
|
217
221
|
end
|
218
222
|
if (img_w = attributes[:width])
|
219
223
|
fragment[:image_width] = img_w
|
@@ -1,5 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'digest'
|
4
|
+
require_relative 'formatted_string'
|
5
|
+
|
3
6
|
module Asciidoctor
|
4
7
|
module PDF
|
5
8
|
class IndexCatalog
|
@@ -20,29 +23,29 @@ module Asciidoctor
|
|
20
23
|
%(__indexterm-#{@sequence += 1})
|
21
24
|
end
|
22
25
|
|
23
|
-
def store_term names, dest
|
24
|
-
if (num_terms = names.size)
|
25
|
-
|
26
|
+
def store_term names, dest, assoc = {}
|
27
|
+
if (num_terms = (names = names.map {|name| FormattedString.new name }).size) == 1
|
28
|
+
store_primary_term names[0], dest, assoc
|
26
29
|
elsif num_terms == 2
|
27
|
-
store_secondary_term names[0], names[1], dest
|
28
|
-
elsif num_terms
|
29
|
-
|
30
|
+
store_secondary_term names[0], names[1], dest, assoc
|
31
|
+
elsif num_terms > 2
|
32
|
+
store_tertiary_term names[0], names[1], names[2], dest, assoc
|
30
33
|
end
|
31
34
|
end
|
32
35
|
|
33
|
-
def store_primary_term name, dest = nil
|
36
|
+
def store_primary_term name, dest = nil, assoc = {}
|
34
37
|
store_dest dest if dest
|
35
|
-
(init_category name.chr.upcase).store_term name, dest
|
38
|
+
(init_category name.chr.upcase).store_term name, dest, assoc
|
36
39
|
end
|
37
40
|
|
38
|
-
def store_secondary_term primary_name, secondary_name, dest = nil
|
41
|
+
def store_secondary_term primary_name, secondary_name, dest = nil, assoc = {}
|
39
42
|
store_dest dest if dest
|
40
|
-
(store_primary_term primary_name).store_term secondary_name, dest
|
43
|
+
(store_primary_term primary_name).store_term secondary_name, dest, assoc
|
41
44
|
end
|
42
45
|
|
43
|
-
def store_tertiary_term primary_name, secondary_name, tertiary_name, dest
|
46
|
+
def store_tertiary_term primary_name, secondary_name, tertiary_name, dest, assoc = {}
|
44
47
|
store_dest dest
|
45
|
-
(store_secondary_term primary_name, secondary_name).store_term tertiary_name, dest
|
48
|
+
(store_secondary_term primary_name, secondary_name).store_term tertiary_name, dest, assoc
|
46
49
|
end
|
47
50
|
|
48
51
|
def init_category name
|
@@ -54,6 +57,34 @@ module Asciidoctor
|
|
54
57
|
@categories[name]
|
55
58
|
end
|
56
59
|
|
60
|
+
def find_primary_term name
|
61
|
+
@categories.each_value do |category|
|
62
|
+
term = category.terms.find {|candidate| candidate.name == name }
|
63
|
+
return term if term
|
64
|
+
end
|
65
|
+
nil
|
66
|
+
end
|
67
|
+
|
68
|
+
def link_associations group = nil
|
69
|
+
if group
|
70
|
+
group.terms.each do |term|
|
71
|
+
associations = term.associations
|
72
|
+
if (see_name = associations[:see])
|
73
|
+
see_name = FormattedString.new see_name
|
74
|
+
term.see = (find_primary_term see_name) || (UnresolvedIndexTerm.new see_name)
|
75
|
+
elsif (see_also_names = associations[:see_also])
|
76
|
+
term.see_also = see_also_names.map do |see_also_name|
|
77
|
+
see_also_name = FormattedString.new see_also_name
|
78
|
+
(find_primary_term see_also_name) || (UnresolvedIndexTerm.new see_also_name)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
link_associations term unless term.leaf?
|
82
|
+
end
|
83
|
+
else
|
84
|
+
@categories.each_value {|category| link_associations category }
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
57
88
|
def store_dest dest
|
58
89
|
@dests[dest[:anchor]] = dest
|
59
90
|
end
|
@@ -83,9 +114,18 @@ module Asciidoctor
|
|
83
114
|
@terms = {}
|
84
115
|
end
|
85
116
|
|
86
|
-
def store_term name, dest
|
117
|
+
def store_term name, dest, assoc = {}
|
87
118
|
term = (@terms[name] ||= (IndexTerm.new name))
|
88
119
|
term.add_dest dest if dest
|
120
|
+
term.associations ||= {}
|
121
|
+
unless assoc.empty?
|
122
|
+
if !term.associations[:see] && (see = assoc[:see])
|
123
|
+
term.associations[:see] = see
|
124
|
+
end
|
125
|
+
if (see_also = assoc[:see_also])
|
126
|
+
(term.associations[:see_also] ||= []).concat see_also
|
127
|
+
end
|
128
|
+
end
|
89
129
|
term
|
90
130
|
end
|
91
131
|
|
@@ -100,10 +140,22 @@ module Asciidoctor
|
|
100
140
|
|
101
141
|
class IndexTermCategory < IndexTermGroup; end
|
102
142
|
|
143
|
+
class UnresolvedIndexTerm < IndexTermGroup; end
|
144
|
+
|
103
145
|
class IndexTerm < IndexTermGroup
|
146
|
+
attr_reader :anchor
|
147
|
+
|
148
|
+
attr_accessor :associations
|
149
|
+
|
150
|
+
attr_accessor :see
|
151
|
+
|
152
|
+
attr_writer :see_also
|
153
|
+
|
104
154
|
def initialize name
|
105
155
|
super
|
106
156
|
@dests = ::Set.new
|
157
|
+
@anchor = %(__indextermdef-#{(::Digest::MD5.new << name.to_s).hexdigest})
|
158
|
+
@associations = @see = @see_also = nil
|
107
159
|
end
|
108
160
|
|
109
161
|
alias subterms terms
|
@@ -124,6 +176,10 @@ module Asciidoctor
|
|
124
176
|
def leaf?
|
125
177
|
@terms.empty?
|
126
178
|
end
|
179
|
+
|
180
|
+
def see_also
|
181
|
+
@see_also&.sort
|
182
|
+
end
|
127
183
|
end
|
128
184
|
end
|
129
185
|
end
|
data/lib/asciidoctor/pdf.rb
CHANGED
@@ -2,7 +2,10 @@
|
|
2
2
|
|
3
3
|
proc do
|
4
4
|
old_verbose, $VERBOSE = $VERBOSE, nil
|
5
|
-
|
5
|
+
begin
|
6
|
+
require 'bigdecimal' # try to eagerly require bigdecimal with warnings off to avoid warning caused by ttfunk 1.7.0
|
7
|
+
rescue Exception # rubocop:disable Lint/SuppressedException,Lint/RescueException
|
8
|
+
end
|
6
9
|
$VERBOSE = old_verbose
|
7
10
|
end.call
|
8
11
|
|
@@ -11,7 +14,11 @@ autoload :StringIO, 'stringio'
|
|
11
14
|
autoload :Tempfile, 'tempfile'
|
12
15
|
require 'time' unless defined? Time.parse
|
13
16
|
require_relative 'pdf/version'
|
14
|
-
|
17
|
+
proc do
|
18
|
+
old_verbose, $VERBOSE = $VERBOSE, nil
|
19
|
+
require 'asciidoctor' # avoid warning in Ruby 3.4 caused by use of logger
|
20
|
+
$VERBOSE = old_verbose
|
21
|
+
end.call
|
15
22
|
require 'prawn'
|
16
23
|
require 'prawn/templates'
|
17
24
|
require_relative 'pdf/measurements'
|
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.3.
|
4
|
+
version: 2.3.21
|
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:
|
12
|
+
date: 2025-10-08 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: asciidoctor
|
@@ -129,14 +129,14 @@ dependencies:
|
|
129
129
|
requirements:
|
130
130
|
- - "~>"
|
131
131
|
- !ruby/object:Gem::Version
|
132
|
-
version: '1.
|
132
|
+
version: '1.3'
|
133
133
|
type: :runtime
|
134
134
|
prerelease: false
|
135
135
|
version_requirements: !ruby/object:Gem::Requirement
|
136
136
|
requirements:
|
137
137
|
- - "~>"
|
138
138
|
- !ruby/object:Gem::Version
|
139
|
-
version: '1.
|
139
|
+
version: '1.3'
|
140
140
|
- !ruby/object:Gem::Dependency
|
141
141
|
name: treetop
|
142
142
|
requirement: !ruby/object:Gem::Requirement
|
@@ -290,6 +290,7 @@ files:
|
|
290
290
|
- lib/asciidoctor/pdf/ext/prawn/document/column_box.rb
|
291
291
|
- lib/asciidoctor/pdf/ext/prawn/extensions.rb
|
292
292
|
- lib/asciidoctor/pdf/ext/prawn/font/afm.rb
|
293
|
+
- lib/asciidoctor/pdf/ext/prawn/font/ttf.rb
|
293
294
|
- lib/asciidoctor/pdf/ext/prawn/font_metric_cache.rb
|
294
295
|
- lib/asciidoctor/pdf/ext/prawn/formatted_text/arranger.rb
|
295
296
|
- lib/asciidoctor/pdf/ext/prawn/formatted_text/box.rb
|
@@ -351,7 +352,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
351
352
|
- !ruby/object:Gem::Version
|
352
353
|
version: '0'
|
353
354
|
requirements: []
|
354
|
-
rubygems_version: 3.5.
|
355
|
+
rubygems_version: 3.5.22
|
355
356
|
signing_key:
|
356
357
|
specification_version: 4
|
357
358
|
summary: Converts AsciiDoc documents to PDF using Asciidoctor and Prawn
|