asciidoctor-pdf 2.0.0.rc.1 → 2.0.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 +35 -0
- data/README.adoc +2 -2
- data/lib/asciidoctor/pdf/converter.rb +87 -77
- data/lib/asciidoctor/pdf/ext/prawn/extensions.rb +39 -11
- data/lib/asciidoctor/pdf/ext/prawn/formatted_text/protect_bottom_gutter.rb +8 -5
- data/lib/asciidoctor/pdf/ext/prawn-table.rb +11 -0
- data/lib/asciidoctor/pdf/formatted_text/inline_image_arranger.rb +5 -1
- data/lib/asciidoctor/pdf/formatted_text/source_wrap.rb +9 -3
- data/lib/asciidoctor/pdf/formatted_text/transform.rb +21 -17
- data/lib/asciidoctor/pdf/theme_loader.rb +7 -7
- data/lib/asciidoctor/pdf/version.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c06c3e7edce9f473ace6df96c041850636e6561860f21a12725410370527ac27
|
4
|
+
data.tar.gz: a6fd22809163ed0d4fa07b8f2a51e0e20227e69f03a9af884c5512ff79d39a06
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 397e550c0519ac08cab6af6f2ea2d598419a79c928a420d54ca296124a6ee6175a4005904c38c4a45e6cbdd5f01b61d410b673ad4133a018aafc69737b4c4c44
|
7
|
+
data.tar.gz: 19d24ba2f84be03ebff16a738224b1025a52e7a0d77c8dc1c3ffcc44d4c2a825989425da4ad00a886b3456c427287cd4b00b3943bbe13e4b9a4fb48b4842bb62
|
data/CHANGELOG.adoc
CHANGED
@@ -5,6 +5,40 @@
|
|
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.0.2 (2022-05-22) - @mojavelinux
|
9
|
+
|
10
|
+
Bug Fixes::
|
11
|
+
|
12
|
+
* use specified column widths to avoid bugs in column width calculation when using colspans (#1368)
|
13
|
+
* advance table to next page if rowspan in first row does not fit in space remaining on current page (#403)
|
14
|
+
|
15
|
+
=== Details
|
16
|
+
|
17
|
+
{url-repo}/releases/tag/v2.0.2[git tag] | {url-repo}/compare/v2.0.1\...v2.0.2[full diff]
|
18
|
+
|
19
|
+
== 2.0.1 (2022-05-21) - @mojavelinux
|
20
|
+
|
21
|
+
Bug Fixes::
|
22
|
+
|
23
|
+
* scale inline image to fit within available height of page, accounting for the top padding of the line height and the bottom gutter (#2193)
|
24
|
+
* short-circuit formatted text routine and log error if fragments in first line cannot fit on an empty page
|
25
|
+
* break and wrap long contiguous text in source block when linenums is enabled (#2198)
|
26
|
+
|
27
|
+
=== Details
|
28
|
+
|
29
|
+
{url-repo}/releases/tag/v2.0.1[git tag] | {url-repo}/compare/v2.0.0\...v2.0.1[full diff]
|
30
|
+
|
31
|
+
== 2.0.0 (2022-05-18) - @mojavelinux
|
32
|
+
|
33
|
+
Improvements::
|
34
|
+
|
35
|
+
* use more stable approach to recreating current bounds in scratch document
|
36
|
+
* add foundation to support multi-column layout for the body of an article (using an extended converter only)
|
37
|
+
|
38
|
+
=== Details
|
39
|
+
|
40
|
+
{url-repo}/releases/tag/v2.0.0[git tag] | {url-repo}/compare/v2.0.0.rc.1\...v2.0.0[full diff]
|
41
|
+
|
8
42
|
== 2.0.0.rc.1 (2022-05-17) - @mojavelinux
|
9
43
|
|
10
44
|
Enhancements::
|
@@ -95,6 +129,7 @@ Enhancements::
|
|
95
129
|
* use `base-border-color` as default border color; control appearance of border using `border-width` value alone (#2134)
|
96
130
|
* remove border colors in base theme so all border colors can be controlled using `base-border-color` when extending theme
|
97
131
|
* enable running footer when using base theme
|
132
|
+
* allow built-in optimizer to set PDF compliance flag (PDF/A and PDF/X) using value of `optimize` attribute (#125)
|
98
133
|
|
99
134
|
Bug Fixes::
|
100
135
|
|
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.0.
|
3
|
+
v2.0.2, 2022-05-22
|
4
4
|
// Settings:
|
5
5
|
:experimental:
|
6
6
|
:idprefix:
|
@@ -24,7 +24,7 @@ endif::[]
|
|
24
24
|
:project-handle: asciidoctor-pdf
|
25
25
|
// Variables:
|
26
26
|
:release-line: 2.0.x
|
27
|
-
:release-version: 2.0.
|
27
|
+
:release-version: 2.0.2
|
28
28
|
// URLs:
|
29
29
|
:url-gem: https://rubygems.org/gems/asciidoctor-pdf
|
30
30
|
:url-project: https://github.com/asciidoctor/asciidoctor-pdf
|
@@ -152,7 +152,7 @@ module Asciidoctor
|
|
152
152
|
# TODO: delegate to convert_method_missing
|
153
153
|
log :warn, %(missing convert handler for #{name} node in #{@backend} backend)
|
154
154
|
end
|
155
|
-
# NOTE: inline
|
155
|
+
# NOTE: inline node handlers generate HTML-like strings; all other handlers write directly to the PDF object
|
156
156
|
::Asciidoctor::Inline === node ? result : self
|
157
157
|
end
|
158
158
|
|
@@ -717,7 +717,7 @@ module Asciidoctor
|
|
717
717
|
when 'page'
|
718
718
|
pagenums = term.dests.uniq {|dest| dest[:page] }.map {|dest| %(<a anchor="#{dest[:anchor]}">#{dest[:page]}</a>) }
|
719
719
|
when 'range'
|
720
|
-
first_anchor_per_page = term.dests.
|
720
|
+
first_anchor_per_page = {}.tap {|accum| term.dests.each {|dest| accum[dest[:page]] ||= dest[:anchor] } }
|
721
721
|
pagenums = (consolidate_ranges first_anchor_per_page.keys).map do |range|
|
722
722
|
anchor = first_anchor_per_page[(range.include? '-') ? (range.partition '-')[0] : range]
|
723
723
|
%(<a anchor="#{anchor}">#{range}</a>)
|
@@ -814,7 +814,7 @@ module Asciidoctor
|
|
814
814
|
if (text_align = resolve_text_align_from_role (roles = node.roles), query_theme: true, remove_predefined: true)
|
815
815
|
prose_opts[:align] = text_align
|
816
816
|
end
|
817
|
-
role_keys = roles.map {|role| %(role_#{role})
|
817
|
+
role_keys = roles.map {|role| %(role_#{role}) } unless roles.empty?
|
818
818
|
if (text_indent = @theme.prose_text_indent) > 0 ||
|
819
819
|
((text_indent = @theme.prose_text_indent_inner) > 0 && node.previous_sibling&.context == :paragraph)
|
820
820
|
prose_opts[:indent_paragraphs] = text_indent
|
@@ -1081,7 +1081,7 @@ module Asciidoctor
|
|
1081
1081
|
highlight_lines = nil
|
1082
1082
|
else
|
1083
1083
|
pg_highlight_bg_color = pg_block_styles[:highlight_background_color]
|
1084
|
-
highlight_lines = highlight_lines.
|
1084
|
+
highlight_lines = {}.tap {|accum| highlight_lines.each {|linenum| accum[linenum] = pg_highlight_bg_color } }
|
1085
1085
|
end
|
1086
1086
|
end
|
1087
1087
|
if (node.option? 'linenums') || (node.attr? 'linenums')
|
@@ -1120,7 +1120,7 @@ module Asciidoctor
|
|
1120
1120
|
lexer ||= ::Rouge::Lexers::PlainText
|
1121
1121
|
source_string, conum_mapping = extract_conums source_string if callouts_enabled
|
1122
1122
|
if (node.attr? 'highlight') && !(hl_lines = (node.resolve_lines_to_highlight source_string, (node.attr 'highlight'))).empty?
|
1123
|
-
formatter_opts[:highlight_lines] = hl_lines.
|
1123
|
+
formatter_opts[:highlight_lines] = {}.tap {|accum| hl_lines.each {|linenum| accum[linenum] = true } }
|
1124
1124
|
end
|
1125
1125
|
fragments = formatter.format (lexer.lex source_string), formatter_opts rescue [text: source_string]
|
1126
1126
|
source_chunks = conum_mapping ? (restore_conums fragments, conum_mapping) : fragments
|
@@ -1396,7 +1396,7 @@ module Asciidoctor
|
|
1396
1396
|
end
|
1397
1397
|
theme_margin :prose, :bottom, (next_enclosed_block actual_node) #unless actual_node.nested?
|
1398
1398
|
when 'qanda'
|
1399
|
-
@list_numerals <<
|
1399
|
+
@list_numerals << 1
|
1400
1400
|
convert_list node
|
1401
1401
|
@list_numerals.pop
|
1402
1402
|
else
|
@@ -2167,6 +2167,7 @@ module Asciidoctor
|
|
2167
2167
|
|
2168
2168
|
left_padding = right_padding = nil
|
2169
2169
|
table table_data, table_settings do
|
2170
|
+
@column_widths = column_widths unless column_widths.empty?
|
2170
2171
|
# NOTE: call width to capture resolved table width
|
2171
2172
|
table_width = width
|
2172
2173
|
@pdf.ink_table_caption node, alignment, table_width, caption_max_width if node.title? && caption_end == :top
|
@@ -3261,64 +3262,70 @@ module Asciidoctor
|
|
3261
3262
|
end
|
3262
3263
|
end
|
3263
3264
|
|
3264
|
-
colspec_dict =
|
3265
|
-
|
3266
|
-
|
3267
|
-
|
3268
|
-
|
3269
|
-
|
3270
|
-
|
3271
|
-
|
3272
|
-
|
3273
|
-
|
3274
|
-
|
3275
|
-
tot_width = 0
|
3276
|
-
side_colspecs = colspecs.map do |col, spec|
|
3277
|
-
if (alignment_char = spec.chr).to_i.to_s == alignment_char
|
3278
|
-
alignment = :left
|
3279
|
-
rel_width = spec.to_f
|
3280
|
-
else
|
3281
|
-
alignment = AlignmentTable[alignment_char]
|
3282
|
-
rel_width = (spec.slice 1, spec.length).to_f
|
3265
|
+
colspec_dict = {}.tap do |acc|
|
3266
|
+
PageSides.each do |side|
|
3267
|
+
side_trim_content_width = trim_content_width[side]
|
3268
|
+
if (custom_colspecs = @theme[%(#{periphery}_#{side}_columns)] || @theme[%(#{periphery}_columns)])
|
3269
|
+
case (colspecs = (custom_colspecs.to_s.tr ',', ' ').split).size
|
3270
|
+
when 0, 1
|
3271
|
+
colspecs = { left: '0', center: colspecs[0] || '100', right: '0' }
|
3272
|
+
when 2
|
3273
|
+
colspecs = { left: colspecs[0], center: '0', right: colspecs[1] }
|
3274
|
+
else # 3
|
3275
|
+
colspecs = { left: colspecs[0], center: colspecs[1], right: colspecs[2] }
|
3283
3276
|
end
|
3284
|
-
tot_width
|
3285
|
-
|
3286
|
-
|
3287
|
-
|
3288
|
-
|
3289
|
-
|
3290
|
-
|
3291
|
-
|
3292
|
-
|
3293
|
-
|
3294
|
-
|
3295
|
-
|
3296
|
-
|
3277
|
+
tot_width = 0
|
3278
|
+
side_colspecs = {}.tap do |accum|
|
3279
|
+
colspecs.each do |col, spec|
|
3280
|
+
if (alignment_char = spec.chr).to_i.to_s == alignment_char
|
3281
|
+
alignment = :left
|
3282
|
+
rel_width = spec.to_f
|
3283
|
+
else
|
3284
|
+
alignment = AlignmentTable[alignment_char]
|
3285
|
+
rel_width = (spec.slice 1, spec.length).to_f
|
3286
|
+
end
|
3287
|
+
tot_width += rel_width
|
3288
|
+
accum[col] = { align: alignment, width: rel_width, x: 0 }
|
3289
|
+
end
|
3290
|
+
end
|
3291
|
+
# QUESTION: should we allow the columns to overlap (capping width at 100%)?
|
3292
|
+
side_colspecs.each {|_, colspec| colspec[:width] = (colspec[:width] / tot_width) * side_trim_content_width }
|
3293
|
+
side_colspecs[:right][:x] = (side_colspecs[:center][:x] = side_colspecs[:left][:width]) + side_colspecs[:center][:width]
|
3294
|
+
acc[side] = side_colspecs
|
3295
|
+
else
|
3296
|
+
acc[side] = {
|
3297
|
+
left: { align: :left, width: side_trim_content_width, x: 0 },
|
3298
|
+
center: { align: :center, width: side_trim_content_width, x: 0 },
|
3299
|
+
right: { align: :right, width: side_trim_content_width, x: 0 },
|
3300
|
+
}
|
3301
|
+
end
|
3297
3302
|
end
|
3298
3303
|
end
|
3299
3304
|
|
3300
|
-
content_dict =
|
3301
|
-
|
3302
|
-
|
3303
|
-
|
3304
|
-
|
3305
|
-
|
3306
|
-
|
3307
|
-
|
3308
|
-
|
3309
|
-
|
3310
|
-
|
3311
|
-
|
3305
|
+
content_dict = {}.tap do |acc|
|
3306
|
+
PageSides.each do |side|
|
3307
|
+
side_content = {}
|
3308
|
+
ColumnPositions.each do |position|
|
3309
|
+
next if (val = @theme[%(#{periphery}_#{side}_#{position}_content)]).nil_or_empty?
|
3310
|
+
val = val.to_s unless ::String === val
|
3311
|
+
if (val.include? ':') && val =~ ImageAttributeValueRx
|
3312
|
+
attrlist = $2
|
3313
|
+
image_attrs = (AttributeList.new attrlist).parse %w(alt width)
|
3314
|
+
image_path, image_format = ::Asciidoctor::Image.target_and_format $1, image_attrs
|
3315
|
+
if (image_path = resolve_image_path doc, image_path, image_format, @themesdir) && (::File.readable? image_path)
|
3316
|
+
image_opts = resolve_image_options image_path, image_format, image_attrs, container_size: [colspec_dict[side][position][:width], trim_content_height[side]]
|
3317
|
+
side_content[position] = [image_path, image_opts, image_attrs['link']]
|
3318
|
+
else
|
3319
|
+
# NOTE: allows inline image handler to report invalid reference and replace with alt text
|
3320
|
+
side_content[position] = %(image:#{image_path}[#{attrlist}])
|
3321
|
+
end
|
3312
3322
|
else
|
3313
|
-
|
3314
|
-
side_content[position] = %(image:#{image_path}[#{attrlist}])
|
3323
|
+
side_content[position] = val
|
3315
3324
|
end
|
3316
|
-
else
|
3317
|
-
side_content[position] = val
|
3318
3325
|
end
|
3319
|
-
end
|
3320
3326
|
|
3321
|
-
|
3327
|
+
acc[side] = side_content
|
3328
|
+
end
|
3322
3329
|
end
|
3323
3330
|
|
3324
3331
|
if (trim_bg_color = trim_styles[:bg_color]) || trim_bg_image || trim_border_width > 0
|
@@ -3866,18 +3873,17 @@ module Asciidoctor
|
|
3866
3873
|
|
3867
3874
|
def register_fonts font_catalog, fonts_dir
|
3868
3875
|
return unless font_catalog
|
3869
|
-
dirs = (fonts_dir.split ValueSeparatorRx, -1).map
|
3870
|
-
dir == 'GEM_FONTS_DIR' || dir.empty? ? ThemeLoader::FontsDir : dir
|
3871
|
-
end
|
3876
|
+
dirs = (fonts_dir.split ValueSeparatorRx, -1).map {|dir| dir == 'GEM_FONTS_DIR' || dir.empty? ? ThemeLoader::FontsDir : dir }
|
3872
3877
|
font_catalog.each do |key, styles|
|
3873
|
-
|
3874
|
-
|
3875
|
-
|
3876
|
-
|
3878
|
+
register_font key => ({}.tap do |accum|
|
3879
|
+
styles.each do |style, path|
|
3880
|
+
found = dirs.any? do |dir|
|
3881
|
+
resolved_font_path = font_path path, dir
|
3882
|
+
accum[style.to_sym] = resolved_font_path if ::File.readable? resolved_font_path
|
3883
|
+
end
|
3884
|
+
raise ::Errno::ENOENT, ((File.absolute_path? path) ? %(#{path} not found) : %(#{path} not found in #{fonts_dir.gsub ValueSeparatorRx, ' or '})) unless found
|
3877
3885
|
end
|
3878
|
-
|
3879
|
-
end
|
3880
|
-
register_font key => styles
|
3886
|
+
end)
|
3881
3887
|
end
|
3882
3888
|
end
|
3883
3889
|
|
@@ -4256,7 +4262,7 @@ module Asciidoctor
|
|
4256
4262
|
b_shift, b_gap_color = (b_width ||= 0.5) * 0.5, @page_bg_color
|
4257
4263
|
end
|
4258
4264
|
ink_caption node_with_caption, category: category if node_with_caption
|
4259
|
-
extent.from.page += 1 unless extent.from.page == page_number # sanity check
|
4265
|
+
extent.from.page += 1 unless extent.from.page == page_number || ColumnBox === bounds # sanity check
|
4260
4266
|
float do
|
4261
4267
|
extent.each_page do |first_page, last_page|
|
4262
4268
|
advance_page unless first_page
|
@@ -4578,14 +4584,16 @@ module Asciidoctor
|
|
4578
4584
|
def consolidate_ranges nums
|
4579
4585
|
if nums.size > 1
|
4580
4586
|
prev = nil
|
4581
|
-
|
4587
|
+
accum = []
|
4588
|
+
nums.each do |num|
|
4582
4589
|
if prev && (prev.to_i + 1) == num.to_i
|
4583
4590
|
accum[-1][1] = num
|
4584
4591
|
else
|
4585
4592
|
accum << [num]
|
4586
4593
|
end
|
4587
4594
|
prev = num
|
4588
|
-
end
|
4595
|
+
end
|
4596
|
+
accum.map {|range| range.join '-' }
|
4589
4597
|
else
|
4590
4598
|
nums
|
4591
4599
|
end
|
@@ -4930,14 +4938,16 @@ module Asciidoctor
|
|
4930
4938
|
result = yield
|
4931
4939
|
else
|
4932
4940
|
email = nil
|
4933
|
-
original_attrs =
|
4934
|
-
|
4935
|
-
|
4936
|
-
|
4937
|
-
|
4938
|
-
|
4939
|
-
|
4940
|
-
|
4941
|
+
original_attrs = {}.tap do |accum|
|
4942
|
+
AuthorAttributeNames.each do |prop_name, attr_name|
|
4943
|
+
accum[attr_name] = doc.attr attr_name
|
4944
|
+
if (val = author[prop_name])
|
4945
|
+
doc.set_attr attr_name, val
|
4946
|
+
# NOTE: email attribute could be a url
|
4947
|
+
email = val if prop_name == :email
|
4948
|
+
else
|
4949
|
+
doc.remove_attr attr_name
|
4950
|
+
end
|
4941
4951
|
end
|
4942
4952
|
end
|
4943
4953
|
doc.set_attr 'url', ((email.include? '@') ? %(mailto:#{email}) : email) if email
|
@@ -4,7 +4,7 @@ Prawn::Font::AFM.instance_variable_set :@hide_m17n_warning, true
|
|
4
4
|
|
5
5
|
require 'prawn/icon'
|
6
6
|
|
7
|
-
Prawn::Icon::Compatibility.
|
7
|
+
Prawn::Icon::Compatibility.prepend (::Module.new { def warning *_args; end })
|
8
8
|
|
9
9
|
module Asciidoctor
|
10
10
|
module Prawn
|
@@ -13,6 +13,8 @@ module Asciidoctor
|
|
13
13
|
include ::Asciidoctor::PDF::Sanitizer
|
14
14
|
include ::Asciidoctor::PDF::TextTransformer
|
15
15
|
|
16
|
+
ColumnBox = ::Prawn::Document::ColumnBox
|
17
|
+
|
16
18
|
FontAwesomeIconSets = %w(fab far fas)
|
17
19
|
IconSets = %w(fab far fas fi pf).to_set
|
18
20
|
IconSetPrefixes = IconSets.map {|it| it + '-' }
|
@@ -429,15 +431,19 @@ module Asciidoctor
|
|
429
431
|
|
430
432
|
# NOTE: override built-in fill_formatted_text_box to insert leading before second line when :first_line is true
|
431
433
|
def fill_formatted_text_box text, options
|
432
|
-
if (initial_gap = options[:initial_gap]) &&
|
434
|
+
if (initial_gap = options[:initial_gap]) && !text.empty? && text[0][:from_page] != page_number
|
433
435
|
self.y -= initial_gap
|
434
436
|
end
|
435
437
|
merge_text_box_positioning_options options
|
436
438
|
box = ::Prawn::Text::Formatted::Box.new text, options
|
437
|
-
|
439
|
+
remaining_fragments = box.render
|
438
440
|
@no_text_printed = box.nothing_printed?
|
439
441
|
@all_text_printed = box.everything_printed?
|
440
|
-
|
442
|
+
unless remaining_fragments.empty? || (remaining_fragments[0][:from_page] ||= page_number) == page_number
|
443
|
+
log :error, %(cannot fit formatted text on page: #{remaining_fragments.map {|it| it[:image_path] || it[:text] }.join})
|
444
|
+
page.tare_content_stream
|
445
|
+
remaining_fragments = {}
|
446
|
+
end
|
441
447
|
|
442
448
|
if @final_gap || (options[:first_line] && !(@no_text_printed || @all_text_printed))
|
443
449
|
self.y -= box.height + box.line_gap + box.leading
|
@@ -445,7 +451,7 @@ module Asciidoctor
|
|
445
451
|
self.y -= box.height
|
446
452
|
end
|
447
453
|
|
448
|
-
|
454
|
+
remaining_fragments
|
449
455
|
end
|
450
456
|
|
451
457
|
# NOTE: override built-in draw_indented_formatted_line to set first_line flag
|
@@ -481,7 +487,13 @@ module Asciidoctor
|
|
481
487
|
else
|
482
488
|
remaining_fragments = box.render dry_run: true
|
483
489
|
end
|
484
|
-
remaining_fragments.empty?
|
490
|
+
if remaining_fragments.empty?
|
491
|
+
remaining_fragments = nil
|
492
|
+
elsif (remaining_fragments[0][:from_page] ||= page_number) != page_number
|
493
|
+
log :error, %(cannot fit formatted text on page: #{remaining_fragments.map {|it| it[:image_path] || it[:text] }.join})
|
494
|
+
page.tare_content_stream
|
495
|
+
remaining_fragments = nil
|
496
|
+
end
|
485
497
|
if first_line_text_transform
|
486
498
|
# NOTE: applying text transform here could alter the wrapping, so isolate first line and shrink it to fit
|
487
499
|
first_line_text = (box.instance_variable_get :@printed_lines)[0]
|
@@ -543,6 +555,18 @@ module Asciidoctor
|
|
543
555
|
|
544
556
|
# Cursor
|
545
557
|
|
558
|
+
# Override the built-in float method to add support for restoring the current column of a ColumnBox
|
559
|
+
#
|
560
|
+
def float
|
561
|
+
original_page_number = page_number
|
562
|
+
original_y = y
|
563
|
+
original_column = bounds.instance_variable_get :@current_column if ColumnBox === bounds
|
564
|
+
yield
|
565
|
+
go_to_page original_page_number unless page_number == original_page_number
|
566
|
+
self.y = original_y
|
567
|
+
bounds.instance_variable_set :@current_column, original_column if original_column
|
568
|
+
end
|
569
|
+
|
546
570
|
# Short-circuits the call to the built-in move_up operation
|
547
571
|
# when n is 0.
|
548
572
|
#
|
@@ -1118,10 +1142,14 @@ module Asciidoctor
|
|
1118
1142
|
# Returns an Extent or ScratchExtent object that describes the bounds of the content block.
|
1119
1143
|
def dry_run keep_together: nil, pages_advanced: 0, single_page: nil, onto: nil, &block
|
1120
1144
|
(scratch_pdf = scratch).start_new_page
|
1121
|
-
|
1122
|
-
|
1123
|
-
|
1124
|
-
|
1145
|
+
saved_bounds = scratch_pdf.bounds
|
1146
|
+
scratch_pdf.bounds = bounds.dup.tap do |bounds_copy|
|
1147
|
+
bounds_copy.instance_variable_set :@document, scratch_pdf
|
1148
|
+
bounds_copy.instance_variable_set :@parent, saved_bounds
|
1149
|
+
if ColumnBox === bounds_copy
|
1150
|
+
bounds_copy.instance_variable_set :@width, bounds_copy.bare_column_width
|
1151
|
+
bounds_copy.instance_variable_set :@current_column, (bounds_copy.instance_variable_set :@columns, 1) - 1
|
1152
|
+
end
|
1125
1153
|
end
|
1126
1154
|
scratch_pdf.move_cursor_to cursor unless (scratch_start_at_top = keep_together || pages_advanced > 0 || at_page_top?)
|
1127
1155
|
scratch_start_cursor = scratch_pdf.cursor
|
@@ -1163,7 +1191,7 @@ module Asciidoctor
|
|
1163
1191
|
extent = ScratchExtent.new scratch_start_page, scratch_start_cursor, scratch_end_page, scratch_end_cursor
|
1164
1192
|
onto ? extent.position_onto(*onto) : extent
|
1165
1193
|
ensure
|
1166
|
-
|
1194
|
+
scratch_pdf.bounds = saved_bounds
|
1167
1195
|
end
|
1168
1196
|
end
|
1169
1197
|
end
|
@@ -2,12 +2,15 @@
|
|
2
2
|
|
3
3
|
module Prawn::Text::Formatted::ProtectBottomGutter
|
4
4
|
def enough_height_for_this_line?
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
if @arranger.finished? && @arranger.fragments.none? {|it| it.format_state[:full_height] }
|
6
|
+
begin
|
7
|
+
@height -= @bottom_gutter
|
8
|
+
super
|
9
|
+
ensure
|
10
|
+
@height += @bottom_gutter
|
11
|
+
end
|
12
|
+
else
|
8
13
|
super
|
9
|
-
ensure
|
10
|
-
@height += @bottom_gutter
|
11
14
|
end
|
12
15
|
end
|
13
16
|
end
|
@@ -1,6 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'prawn/table'
|
4
|
+
|
5
|
+
Prawn::Table.prepend (Module.new do
|
6
|
+
def initial_row_on_initial_page
|
7
|
+
return 0 if fits_on_page? @pdf.bounds.height
|
8
|
+
height_required = (row (0..number_of_header_rows)).height_with_span
|
9
|
+
return -1 if fits_on_page? height_required, true
|
10
|
+
@pdf.bounds.move_past_bottom
|
11
|
+
0
|
12
|
+
end
|
13
|
+
end)
|
14
|
+
|
4
15
|
require_relative 'prawn-table/cell'
|
5
16
|
require_relative 'prawn-table/cell/asciidoc'
|
6
17
|
require_relative 'prawn-table/cell/text'
|
@@ -38,7 +38,7 @@ module Asciidoctor::PDF::FormattedText
|
|
38
38
|
return if (raw_image_fragments = fragments.select {|f| (f.key? :image_path) && !(f.key? :image_obj) }).empty?
|
39
39
|
scratch = doc.scratch?
|
40
40
|
available_w = available_width
|
41
|
-
available_h = doc.
|
41
|
+
available_h = doc.bounds.height
|
42
42
|
last_fragment = {}
|
43
43
|
raw_image_fragments.each do |fragment|
|
44
44
|
if fragment[:object_id] == last_fragment[:object_id]
|
@@ -96,6 +96,10 @@ module Asciidoctor::PDF::FormattedText
|
|
96
96
|
if (f_height = image_h) > (line_font = doc.font).height * 1.5
|
97
97
|
# align with descender (equivalent to vertical-align: bottom in CSS)
|
98
98
|
fragment[:ascender] = f_height - (fragment[:descender] = line_font.descender)
|
99
|
+
if f_height == available_h
|
100
|
+
fragment[:ascender] -= (doc.calc_line_metrics (doc.instance_variable_get :@base_line_height), line_font, doc.font_size).padding_top
|
101
|
+
fragment[:full_height] = true
|
102
|
+
end
|
99
103
|
doc.font_size (fragment[:size] = f_height * (doc.font_size / line_font.height))
|
100
104
|
# align with baseline (roughly equivalent to vertical-align: baseline in CSS)
|
101
105
|
#fragment[:ascender] = f_height
|
@@ -11,15 +11,15 @@ module Asciidoctor
|
|
11
11
|
def wrap array
|
12
12
|
return super unless array[0][:linenum] # sanity check
|
13
13
|
initialize_wrap array
|
14
|
+
@line_wrap.extend SourceLineWrap
|
14
15
|
highlight_line = stop = nil
|
15
16
|
unconsumed = @arranger.unconsumed
|
16
17
|
until stop
|
17
18
|
if (first_fragment = unconsumed[0])[:linenum]
|
18
19
|
linenum_text = first_fragment[:text]
|
19
|
-
linenum_spacer ||= { text: (NoBreakSpace.encode linenum_text.encoding) + (' ' * (linenum_text.length - 1)) }
|
20
|
+
linenum_spacer ||= { text: (NoBreakSpace.encode linenum_text.encoding) + (' ' * (linenum_text.length - 1)), linenum: :spacer }
|
20
21
|
highlight_line = (second_fragment = unconsumed[1])[:highlight] ? second_fragment.dup : nil
|
21
|
-
else
|
22
|
-
# NOTE: a wrapped line
|
22
|
+
else # wrapped line
|
23
23
|
first_fragment[:text] = first_fragment[:text].lstrip
|
24
24
|
@arranger.unconsumed.unshift highlight_line if highlight_line
|
25
25
|
@arranger.unconsumed.unshift linenum_spacer.dup
|
@@ -43,6 +43,12 @@ module Asciidoctor
|
|
43
43
|
@arranger.unconsumed
|
44
44
|
end
|
45
45
|
end
|
46
|
+
|
47
|
+
module SourceLineWrap
|
48
|
+
def update_line_status_based_on_last_output
|
49
|
+
@arranger.current_format_state[:linenum] ? nil : super
|
50
|
+
end
|
51
|
+
end
|
46
52
|
end
|
47
53
|
end
|
48
54
|
end
|
@@ -95,22 +95,24 @@ module Asciidoctor
|
|
95
95
|
styles: (to_styles theme.menu_font_style),
|
96
96
|
}.compact,
|
97
97
|
}
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
(
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
98
|
+
@theme_settings.tap do |accum|
|
99
|
+
revise_roles = [].to_set
|
100
|
+
theme.each_pair do |key, val|
|
101
|
+
next unless (key = key.to_s).start_with? 'role_'
|
102
|
+
role, key = (key.slice 5, key.length).split '_', 2
|
103
|
+
if (prop = ThemeKeyToFragmentProperty[key])
|
104
|
+
(accum[role] ||= {})[prop] = val
|
105
|
+
#elsif key == 'font_kerning'
|
106
|
+
# unless (resolved_val = val == 'none' ? false : (val == 'normal' ? true : nil)).nil?
|
107
|
+
# (accum[role] ||= {})[:kerning] = resolved_val
|
108
|
+
# end
|
109
|
+
elsif key == 'font_style' || key == 'text_decoration'
|
110
|
+
revise_roles << role
|
111
|
+
end
|
112
|
+
end
|
113
|
+
revise_roles.each do |role|
|
114
|
+
(accum[role] ||= {})[:styles] = to_styles theme[%(role_#{role}_font_style)], theme[%(role_#{role}_text_decoration)]
|
110
115
|
end
|
111
|
-
end
|
112
|
-
revise_roles.each_with_object @theme_settings do |role, accum|
|
113
|
-
(accum[role] ||= {})[:styles] = to_styles theme[%(role_#{role}_font_style)], theme[%(role_#{role}_text_decoration)]
|
114
116
|
end
|
115
117
|
@theme_settings['line-through'] = { styles: [:strikethrough].to_set } unless @theme_settings.key? 'line-through'
|
116
118
|
@theme_settings['underline'] = { styles: [:underline].to_set } unless @theme_settings.key? 'underline'
|
@@ -276,8 +278,10 @@ module Asciidoctor
|
|
276
278
|
when '#' # hex string (e.g., #FF0000)
|
277
279
|
fragment[:color] = value.length == 7 ? (value.slice 1, 6) : (value.slice 1, 3).each_char.map {|c| c * 2 }.join if HexColorRx.match? value
|
278
280
|
when '[' # CMYK array (e.g., [50, 100, 0, 0])
|
279
|
-
fragment[:color] =
|
280
|
-
|
281
|
+
fragment[:color] = [0, 0, 0, 0].tap do |accum|
|
282
|
+
(((value.slice 1, value.length).chomp ']').split ', ', 4).each_with_index do |it, idx|
|
283
|
+
accum[idx] = (ival = it.to_i) == (fval = it.to_f) ? ival : fval
|
284
|
+
end
|
281
285
|
end
|
282
286
|
else # assume a 6-character hex color (internal only)
|
283
287
|
fragment[:color] = value
|
@@ -15,9 +15,7 @@ module Asciidoctor
|
|
15
15
|
BaseThemePath = ::File.join ThemesDir, 'base-theme.yml'
|
16
16
|
BundledThemeNames = (::Dir.children ThemesDir).map {|it| it.slice 0, it.length - 10 }
|
17
17
|
DeprecatedCategoryKeys = { 'blockquote' => 'quote', 'key' => 'kbd', 'literal' => 'codespan', 'outline_list' => 'list' }
|
18
|
-
DeprecatedKeys = %w(base heading heading_h1 heading_h2 heading_h3 heading_h4 heading_h5 heading_h6 title_page abstract abstract_title admonition_label sidebar_title toc_title).
|
19
|
-
accum[%(#{prefix}_align)] = %(#{prefix}_text_align)
|
20
|
-
end
|
18
|
+
DeprecatedKeys = { 'table_caption_side' => 'table_caption_end' }.tap {|accum| %w(base heading heading_h1 heading_h2 heading_h3 heading_h4 heading_h5 heading_h6 title_page abstract abstract_title admonition_label sidebar_title toc_title).each {|prefix| accum[%(#{prefix}_align)] = %(#{prefix}_text_align) } }
|
21
19
|
PaddingBottomHackKeys = %w(example_padding quote_padding sidebar_padding verse_padding)
|
22
20
|
|
23
21
|
VariableRx = /\$([a-z0-9_-]+)/
|
@@ -159,10 +157,12 @@ module Asciidoctor
|
|
159
157
|
elsif key == 'font_fallbacks'
|
160
158
|
data[key] = ::Array === val ? val.map {|name| expand_vars name.to_s, data } : []
|
161
159
|
elsif key.start_with? 'admonition_icon_'
|
162
|
-
data[key] =
|
163
|
-
|
164
|
-
|
165
|
-
|
160
|
+
data[key] = {}.tap do |accum|
|
161
|
+
val.each do |key2, val2|
|
162
|
+
key2 = key2.tr '-', '_' if key2.include? '-'
|
163
|
+
accum[key2.to_sym] = (key2.end_with? '_color') ? (to_color evaluate val2, data) : (evaluate val2, data)
|
164
|
+
end
|
165
|
+
end if val
|
166
166
|
elsif ::Hash === val
|
167
167
|
if (rekey = DeprecatedCategoryKeys[key])
|
168
168
|
logger.warn %(the #{key.tr '_', '-'} theme category is deprecated; use the #{rekey.tr '_', '-'} category instead)
|
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.0.
|
4
|
+
version: 2.0.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-05-
|
12
|
+
date: 2022-05-22 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: asciidoctor
|
@@ -325,9 +325,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
325
325
|
version: '0'
|
326
326
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
327
327
|
requirements:
|
328
|
-
- - "
|
328
|
+
- - ">="
|
329
329
|
- !ruby/object:Gem::Version
|
330
|
-
version:
|
330
|
+
version: '0'
|
331
331
|
requirements: []
|
332
332
|
rubygems_version: 3.3.7
|
333
333
|
signing_key:
|