asciidoctor-pdf 2.1.1 → 2.1.4
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 +41 -0
- data/README.adoc +1 -3
- data/lib/asciidoctor/pdf/converter.rb +43 -43
- data/lib/asciidoctor/pdf/ext/prawn/document/column_box.rb +10 -7
- data/lib/asciidoctor/pdf/ext/prawn/extensions.rb +11 -27
- data/lib/asciidoctor/pdf/ext/prawn-table/cell/asciidoc.rb +3 -1
- data/lib/asciidoctor/pdf/ext/prawn-table/cell/text.rb +3 -1
- data/lib/asciidoctor/pdf/ext/prawn-table/cell.rb +2 -0
- data/lib/asciidoctor/pdf/formatted_text/transform.rb +36 -5
- data/lib/asciidoctor/pdf/index_catalog.rb +1 -1
- data/lib/asciidoctor/pdf/text_transformer.rb +23 -0
- data/lib/asciidoctor/pdf/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eb8baebe850d75fcfc95460fbbdf89978867adb076acf572abaff0f51e18fb04
|
4
|
+
data.tar.gz: d4dbbaab4981db0666488ae108aee0f5851feb706e3846b13cd5cf46c341b5bc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 26b1c9830deeb0a39494e9cdb85fa5c2e2295efe8b3d527525b27c6dcf420a8ab94e06eeaca3431425e9cf547150d372bab49813af946cdd5ea0e155d6aad1f0
|
7
|
+
data.tar.gz: d584830d1eb1f76a005b48cf6a20030311d40184254d4ddfbd752f99a66c27feab85292c79012af0c9c4b7272a1727f402828f1c6d992228660ccbf78be44d2a
|
data/CHANGELOG.adoc
CHANGED
@@ -5,6 +5,47 @@
|
|
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.4 (2022-06-26) - @mojavelinux
|
9
|
+
|
10
|
+
Improvements::
|
11
|
+
|
12
|
+
* include source location in warning message for truncated table cell if sourcemap is enabled (#2261)
|
13
|
+
|
14
|
+
Bug Fixes::
|
15
|
+
|
16
|
+
* allow alt text for block image, video, and audio to wrap to next line on same page (#2258)
|
17
|
+
* apply text-tranform from custom role on phrase after attributes have been resolved (#2263)
|
18
|
+
* make URL check more strict so image target containing a colon is not mistaken as a URL
|
19
|
+
|
20
|
+
=== Details
|
21
|
+
|
22
|
+
{url-repo}/releases/tag/v2.1.4[git tag] | {url-repo}/compare/v2.1.3\...v2.1.4[full diff]
|
23
|
+
|
24
|
+
== 2.1.3 (2022-06-23) - @mojavelinux
|
25
|
+
|
26
|
+
Bug Fixes::
|
27
|
+
|
28
|
+
* interpret `start-at` theme keys with value `1` correctly (as `1` instead of `2`) (#2255)
|
29
|
+
* restore column layout after importing page(s) from PDF (#2253)
|
30
|
+
* fix crash when border color is transparent (`thematic-break-border-color`, `admonition-column-rule`, `quote-border-color`, `verse-border-color`)
|
31
|
+
* ensure page margin is restored after imported page
|
32
|
+
|
33
|
+
=== Details
|
34
|
+
|
35
|
+
{url-repo}/releases/tag/v2.1.3[git tag] | {url-repo}/compare/v2.1.2\...v2.1.3[full diff]
|
36
|
+
|
37
|
+
== 2.1.2 (2022-06-17) - @mojavelinux
|
38
|
+
|
39
|
+
Bug Fixes::
|
40
|
+
|
41
|
+
* apply page layout from main document to new page in scratch document (#2248)
|
42
|
+
* use correct logic to insert page before TOC with automatic placement when doctype=book and media=prepress
|
43
|
+
* use `get_entries_for_toc` to determine if the TOC is non-empty rather than `Document#sections?`
|
44
|
+
|
45
|
+
=== Details
|
46
|
+
|
47
|
+
{url-repo}/releases/tag/v2.1.2[git tag] | {url-repo}/compare/v2.1.1\...v2.1.2[full diff]
|
48
|
+
|
8
49
|
== 2.1.1 (2022-06-15) - @mojavelinux
|
9
50
|
|
10
51
|
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.1.
|
3
|
+
v2.1.4, 2022-06-26
|
4
4
|
// Settings:
|
5
5
|
:experimental:
|
6
6
|
:idprefix:
|
@@ -22,8 +22,6 @@ endif::[]
|
|
22
22
|
// Aliases:
|
23
23
|
:project-name: Asciidoctor PDF
|
24
24
|
:project-handle: asciidoctor-pdf
|
25
|
-
// Variables:
|
26
|
-
:release-line: 2.1.x
|
27
25
|
// URLs:
|
28
26
|
:url-gem: https://rubygems.org/gems/asciidoctor-pdf
|
29
27
|
:url-project: https://github.com/asciidoctor/asciidoctor-pdf
|
@@ -114,6 +114,7 @@ module Asciidoctor
|
|
114
114
|
UriBreakCharsRx = %r((?:/|\?|&|#)(?!$))
|
115
115
|
UriBreakCharRepl = %(\\&#{ZeroWidthSpace})
|
116
116
|
UriSchemeBoundaryRx = %r((?<=://))
|
117
|
+
UrlSniffRx = %r(^\p{Alpha}[\p{Alnum}+.-]*://)
|
117
118
|
LineScanRx = /\n|.+/
|
118
119
|
BlankLineRx = /\n{2,}/
|
119
120
|
CjkLineBreakRx = /(?=[\u3000\u30a0-\u30ff\u3040-\u309f\p{Han}\uff00-\uffef])/
|
@@ -198,8 +199,8 @@ module Asciidoctor
|
|
198
199
|
|
199
200
|
indent_section do
|
200
201
|
toc_num_levels = (doc.attr 'toclevels', 2).to_i
|
201
|
-
if (insert_toc = (doc.attr? 'toc') && !((toc_placement = doc.attr 'toc-placement') == 'macro' || toc_placement == 'preamble') && doc.
|
202
|
-
|
202
|
+
if (insert_toc = (doc.attr? 'toc') && !((toc_placement = doc.attr 'toc-placement') == 'macro' || toc_placement == 'preamble') && !(get_entries_for_toc doc).empty?)
|
203
|
+
start_new_page if @ppbook && verso_page?
|
203
204
|
add_dest_for_block doc, id: 'toc', y: (at_page_top? ? page_height : nil)
|
204
205
|
@toc_extent = allocate_toc doc, toc_num_levels, cursor, title_page_on
|
205
206
|
else
|
@@ -213,7 +214,7 @@ module Asciidoctor
|
|
213
214
|
first_page_offset = has_title_page ? zero_page_offset.next : zero_page_offset
|
214
215
|
body_offset = (body_start_page_number = page_number) - 1
|
215
216
|
if ::Integer === (running_content_start_at = @theme.running_content_start_at)
|
216
|
-
running_content_body_offset = body_offset + [running_content_start_at.pred,
|
217
|
+
running_content_body_offset = body_offset + [running_content_start_at.pred, 0].max
|
217
218
|
running_content_start_at = 'body'
|
218
219
|
else
|
219
220
|
running_content_body_offset = body_offset
|
@@ -227,7 +228,7 @@ module Asciidoctor
|
|
227
228
|
end
|
228
229
|
end
|
229
230
|
if ::Integer === (page_numbering_start_at = @theme.page_numbering_start_at)
|
230
|
-
page_numbering_body_offset = body_offset + [page_numbering_start_at.pred,
|
231
|
+
page_numbering_body_offset = body_offset + [page_numbering_start_at.pred, 0].max
|
231
232
|
page_numbering_start_at = 'body'
|
232
233
|
else
|
233
234
|
page_numbering_body_offset = body_offset
|
@@ -263,12 +264,12 @@ module Asciidoctor
|
|
263
264
|
else
|
264
265
|
body_offset = body_start_page_number - 1
|
265
266
|
if ::Integer === (running_content_start_at = @theme.running_content_start_at)
|
266
|
-
running_content_body_offset = body_offset + [running_content_start_at.pred,
|
267
|
+
running_content_body_offset = body_offset + [running_content_start_at.pred, 0].max
|
267
268
|
else
|
268
269
|
running_content_body_offset = body_offset
|
269
270
|
end
|
270
271
|
if ::Integer === (page_numbering_start_at = @theme.page_numbering_start_at)
|
271
|
-
page_numbering_body_offset = body_offset + [page_numbering_start_at.pred,
|
272
|
+
page_numbering_body_offset = body_offset + [page_numbering_start_at.pred, 0].max
|
272
273
|
elsif page_numbering_start_at == 'cover' && has_front_cover
|
273
274
|
page_numbering_body_offset = 0
|
274
275
|
else
|
@@ -371,8 +372,6 @@ module Asciidoctor
|
|
371
372
|
if (page_margin_inner = theme.page_margin_inner)
|
372
373
|
page_margin_recto[3] = page_margin_verso[1] = page_margin_inner
|
373
374
|
end
|
374
|
-
# NOTE: prepare scratch document to use page margin from recto side (which has same width as verso side)
|
375
|
-
set_page_margin page_margin_recto unless page_margin_recto == page_margin
|
376
375
|
else
|
377
376
|
@ppbook = nil
|
378
377
|
end
|
@@ -581,6 +580,7 @@ module Asciidoctor
|
|
581
580
|
end
|
582
581
|
|
583
582
|
def prepare_theme theme
|
583
|
+
theme.base_border_color = nil if theme.base_border_color == 'transparent'
|
584
584
|
theme.base_font_color ||= '000000'
|
585
585
|
theme.base_font_size ||= 12
|
586
586
|
theme.base_font_style = theme.base_font_style&.to_sym || :normal
|
@@ -943,7 +943,7 @@ module Asciidoctor
|
|
943
943
|
if extent
|
944
944
|
label_height = extent.single_page_height || cursor
|
945
945
|
if (rule_width = @theme.admonition_column_rule_width || 0) > 0 &&
|
946
|
-
(rule_color =
|
946
|
+
(rule_color = resolve_theme_color :admonition_column_rule_color, @theme.base_border_color, nil)
|
947
947
|
rule_style = @theme.admonition_column_rule_style&.to_sym || :solid
|
948
948
|
float do
|
949
949
|
extent.each_page do |first_page, last_page|
|
@@ -1273,7 +1273,7 @@ module Asciidoctor
|
|
1273
1273
|
category = node.context == :quote ? :quote : :verse
|
1274
1274
|
# NOTE: b_width and b_left_width are mutually exclusive
|
1275
1275
|
if (b_left_width = @theme[%(#{category}_border_left_width)]) && b_left_width > 0
|
1276
|
-
b_color =
|
1276
|
+
b_left_width = nil unless (b_color = resolve_theme_color %(#{category}_border_color), @theme.base_border_color, nil)
|
1277
1277
|
else
|
1278
1278
|
b_left_width = nil
|
1279
1279
|
b_width = nil if (b_width = @theme[%(#{category}_border_width)]) == 0
|
@@ -1887,7 +1887,7 @@ module Asciidoctor
|
|
1887
1887
|
add_dest_for_block node if node.id
|
1888
1888
|
audio_path = node.media_uri node.attr 'target'
|
1889
1889
|
play_symbol = (node.document.attr? 'icons', 'font') ? %(<font name="fas">#{(icon_font_data 'fas').unicode 'play'}</font>) : RightPointer
|
1890
|
-
ink_prose %(#{play_symbol}#{NoBreakSpace}<a href="#{audio_path}">#{audio_path}</a> <em>(audio)</em>), normalize: false, margin: 0
|
1890
|
+
ink_prose %(#{play_symbol}#{NoBreakSpace}<a href="#{audio_path}">#{audio_path}</a> <em>(audio)</em>), normalize: false, margin: 0
|
1891
1891
|
ink_caption node, labeled: false, end: :bottom if node.title?
|
1892
1892
|
theme_margin :block, :bottom, (next_enclosed_block node)
|
1893
1893
|
end
|
@@ -1915,7 +1915,7 @@ module Asciidoctor
|
|
1915
1915
|
if poster.nil_or_empty?
|
1916
1916
|
add_dest_for_block node if node.id
|
1917
1917
|
play_symbol = (node.document.attr? 'icons', 'font') ? %(<font name="fas">#{(icon_font_data 'fas').unicode 'play'}</font>) : RightPointer
|
1918
|
-
ink_prose %(#{play_symbol}#{NoBreakSpace}<a href="#{video_path}">#{video_path}</a> <em>(#{type})</em>), normalize: false, margin: 0
|
1918
|
+
ink_prose %(#{play_symbol}#{NoBreakSpace}<a href="#{video_path}">#{video_path}</a> <em>(#{type})</em>), normalize: false, margin: 0
|
1919
1919
|
ink_caption node, labeled: false, end: :bottom if node.title?
|
1920
1920
|
theme_margin :block, :bottom, (next_enclosed_block node)
|
1921
1921
|
else
|
@@ -2054,7 +2054,8 @@ module Asciidoctor
|
|
2054
2054
|
content: cell_text,
|
2055
2055
|
colspan: cell.colspan || 1,
|
2056
2056
|
align: (cell.attr 'halign').to_sym,
|
2057
|
-
valign: (val = cell.attr 'valign') == 'middle' ? :center : val.to_sym
|
2057
|
+
valign: (val = cell.attr 'valign') == 'middle' ? :center : val.to_sym,
|
2058
|
+
source_location: cell.source_location
|
2058
2059
|
end)
|
2059
2060
|
end
|
2060
2061
|
end unless head_rows.empty?
|
@@ -2073,7 +2074,8 @@ module Asciidoctor
|
|
2073
2074
|
colspan: cell.colspan || 1,
|
2074
2075
|
rowspan: cell.rowspan || 1,
|
2075
2076
|
align: (cell.attr 'halign').to_sym,
|
2076
|
-
valign: (val = cell.attr 'valign') == 'middle' ? :center : val.to_sym
|
2077
|
+
valign: (val = cell.attr 'valign') == 'middle' ? :center : val.to_sym,
|
2078
|
+
source_location: cell.source_location
|
2077
2079
|
cell_line_metrics = body_cell_line_metrics
|
2078
2080
|
case cell.style
|
2079
2081
|
when :emphasis
|
@@ -2134,7 +2136,7 @@ module Asciidoctor
|
|
2134
2136
|
# NOTE: line metrics get applied when AsciiDoc content is converted
|
2135
2137
|
cell_line_metrics = nil
|
2136
2138
|
asciidoc_cell = ::Prawn::Table::Cell::AsciiDoc.new self, (cell_data.merge content: cell.inner_document, padding: body_cell_padding)
|
2137
|
-
cell_data = { content: asciidoc_cell }
|
2139
|
+
cell_data = { content: asciidoc_cell, source_location: cell.source_location }
|
2138
2140
|
end
|
2139
2141
|
if cell_line_metrics
|
2140
2142
|
cell_padding = body_cell_padding.dup
|
@@ -2341,9 +2343,11 @@ module Asciidoctor
|
|
2341
2343
|
|
2342
2344
|
def convert_thematic_break node
|
2343
2345
|
pad_box @theme.thematic_break_padding || [@theme.thematic_break_margin_top, 0] do
|
2344
|
-
|
2345
|
-
|
2346
|
-
|
2346
|
+
if (b_color = resolve_theme_color :thematic_break_border_color)
|
2347
|
+
stroke_horizontal_rule b_color,
|
2348
|
+
line_width: @theme.thematic_break_border_width,
|
2349
|
+
line_style: (@theme.thematic_break_border_style&.to_sym || :solid)
|
2350
|
+
end
|
2347
2351
|
end
|
2348
2352
|
conceal_page_top { theme_margin :block, :bottom, (next_enclosed_block node) }
|
2349
2353
|
end
|
@@ -2352,7 +2356,7 @@ module Asciidoctor
|
|
2352
2356
|
# NOTE: only allow document to have a single managed toc
|
2353
2357
|
return if @toc_extent
|
2354
2358
|
is_macro = (placement = opts[:placement] || 'macro') == 'macro'
|
2355
|
-
if ((doc = node.document).attr? 'toc-placement', placement) && (doc.attr? 'toc') && doc.
|
2359
|
+
if ((doc = node.document).attr? 'toc-placement', placement) && (doc.attr? 'toc') && !(get_entries_for_toc doc).empty?
|
2356
2360
|
start_toc_page node, placement if (is_book = doc.doctype == 'book')
|
2357
2361
|
add_dest_for_block node, id: (node.id || 'toc') if is_macro
|
2358
2362
|
toc_extent = @toc_extent = allocate_toc doc, (doc.attr 'toclevels', 2).to_i, cursor, (title_page_on = is_book || (doc.attr? 'title-page'))
|
@@ -2684,13 +2688,7 @@ module Asciidoctor
|
|
2684
2688
|
end
|
2685
2689
|
|
2686
2690
|
if (roles = node.role)
|
2687
|
-
|
2688
|
-
roles.split.each do |role|
|
2689
|
-
if (text_transform = theme[%(role_#{role}_text_transform)])
|
2690
|
-
inner_text = transform_text inner_text, text_transform
|
2691
|
-
end
|
2692
|
-
inner_text = inner_text.gsub DoubleSpaceRx, ' ' + ZeroWidthSpace if role == 'pre-wrap' && (inner_text.include? DoubleSpace)
|
2693
|
-
end
|
2691
|
+
inner_text = inner_text.gsub DoubleSpaceRx, ' ' + ZeroWidthSpace if (node.has_role? 'pre-wrap') && (inner_text.include? DoubleSpace)
|
2694
2692
|
quoted_text = is_tag ? %(#{open.chop} class="#{roles}">#{inner_text}#{close}) : %(<span class="#{roles}">#{open}#{inner_text}#{close}</span>)
|
2695
2693
|
else
|
2696
2694
|
quoted_text = %(#{open}#{inner_text}#{close})
|
@@ -2802,13 +2800,7 @@ module Asciidoctor
|
|
2802
2800
|
value = (value.split LF).delete_if {|line| SimpleAttributeRefRx.match? line }.join LF if opts[:drop_lines_with_unresolved_attributes] && (value.include? '{')
|
2803
2801
|
value = value.gsub '\{', '{' if escaped_attr_ref
|
2804
2802
|
doc.set_attr 'attribute-missing', attribute_missing unless attribute_missing == 'skip'
|
2805
|
-
if imagesdir
|
2806
|
-
if imagesdir_to_restore
|
2807
|
-
doc.set_attr 'imagesdir', imagesdir_to_restore
|
2808
|
-
else
|
2809
|
-
doc.remove_attr 'imagesdir'
|
2810
|
-
end
|
2811
|
-
end
|
2803
|
+
imagesdir_to_restore ? (doc.set_attr 'imagesdir', imagesdir_to_restore) : (doc.remove_attr 'imagesdir') if imagesdir
|
2812
2804
|
value
|
2813
2805
|
end
|
2814
2806
|
|
@@ -3246,7 +3238,8 @@ module Asciidoctor
|
|
3246
3238
|
end
|
3247
3239
|
end
|
3248
3240
|
|
3249
|
-
# NOTE: inline_format is true by default
|
3241
|
+
# NOTE: inline_format option is true by default
|
3242
|
+
# NOTE: single_line option is not compatible with this method
|
3250
3243
|
def ink_prose string, opts = {}
|
3251
3244
|
top_margin = (margin = (opts.delete :margin)) || (opts.delete :margin_top) || 0
|
3252
3245
|
bot_margin = margin || (opts.delete :margin_bottom) || @theme.prose_margin_bottom
|
@@ -4260,10 +4253,10 @@ module Asciidoctor
|
|
4260
4253
|
# NOTE: this will catch a classloader resource path on JRuby (e.g., uri:classloader:/path/to/image)
|
4261
4254
|
elsif ::File.absolute_path? image_path
|
4262
4255
|
::File.absolute_path image_path
|
4263
|
-
elsif !(
|
4256
|
+
elsif !(is_url = url? image_path) && imagesdir && (::File.absolute_path? imagesdir)
|
4264
4257
|
::File.absolute_path image_path, imagesdir
|
4265
4258
|
# handle case when image is a URI
|
4266
|
-
elsif
|
4259
|
+
elsif is_url || (imagesdir && (url? imagesdir) && (image_path = node.normalize_web_path image_path, imagesdir, false))
|
4267
4260
|
if !allow_uri_read
|
4268
4261
|
log :warn, %(cannot embed remote image: #{image_path} (allow-uri-read attribute not enabled))
|
4269
4262
|
return
|
@@ -4501,6 +4494,7 @@ module Asciidoctor
|
|
4501
4494
|
end
|
4502
4495
|
|
4503
4496
|
# TODO: document me, esp the first line formatting functionality
|
4497
|
+
# NOTE: single_line option should only be used if height option is specified
|
4504
4498
|
def typeset_text string, line_metrics, opts = {}
|
4505
4499
|
opts = { leading: line_metrics.leading, final_gap: line_metrics.final_gap }.merge opts
|
4506
4500
|
string = string.gsub CjkLineBreakRx, ZeroWidthSpace if @cjk_line_breaks
|
@@ -4823,18 +4817,17 @@ module Asciidoctor
|
|
4823
4817
|
end
|
4824
4818
|
|
4825
4819
|
# NOTE: init_page is called within a float context; this will suppress prawn-svg messing with the cursor
|
4826
|
-
# NOTE: init_page is not called for imported pages,
|
4820
|
+
# NOTE: init_page is not called for imported pages, cover pages, image pages, and pages in the scratch document
|
4827
4821
|
def init_page *_args
|
4828
4822
|
next_page_side = page_side nil, @folio_placement[:inverted]
|
4829
4823
|
if @media == 'prepress' && (next_page_margin = @page_margin_by_side[page_number == 1 ? :cover : next_page_side]) != page_margin
|
4830
4824
|
set_page_margin next_page_margin
|
4831
4825
|
end
|
4832
4826
|
unless @page_bg_color == 'FFFFFF'
|
4833
|
-
tare = true
|
4834
4827
|
fill_absolute_bounds @page_bg_color
|
4828
|
+
tare = true
|
4835
4829
|
end
|
4836
4830
|
if (bg_image_path, bg_image_opts = @page_bg_image[next_page_side])
|
4837
|
-
tare = true
|
4838
4831
|
begin
|
4839
4832
|
if bg_image_opts[:format] == 'pdf'
|
4840
4833
|
# NOTE: pages that use PDF for the background do not support a background color or running content
|
@@ -4843,6 +4836,7 @@ module Asciidoctor
|
|
4843
4836
|
else
|
4844
4837
|
canvas { image bg_image_path, ({ position: :center, vposition: :center }.merge bg_image_opts) }
|
4845
4838
|
end
|
4839
|
+
tare = true
|
4846
4840
|
rescue
|
4847
4841
|
facing_page_side = (PageSides - [next_page_side])[0]
|
4848
4842
|
@page_bg_image[facing_page_side] = nil if @page_bg_image[facing_page_side] == @page_bg_image[next_page_side]
|
@@ -4955,7 +4949,7 @@ module Asciidoctor
|
|
4955
4949
|
alt_text_vars[:'/link'] = ''
|
4956
4950
|
end
|
4957
4951
|
theme_font :image_alt do
|
4958
|
-
ink_prose alt_text_template % alt_text_vars, align: opts[:align], margin: 0, normalize: false
|
4952
|
+
ink_prose alt_text_template % alt_text_vars, align: opts[:align], margin: 0, normalize: false
|
4959
4953
|
end
|
4960
4954
|
ink_caption node, category: :image, end: :bottom if node.title?
|
4961
4955
|
theme_margin :block, :bottom, (next_enclosed_block node) unless opts[:pinned]
|
@@ -5037,10 +5031,8 @@ module Asciidoctor
|
|
5037
5031
|
# QUESTION: should we pass a category as an argument?
|
5038
5032
|
# QUESTION: should we make this a method on the theme ostruct? (e.g., @theme.resolve_color key, fallback)
|
5039
5033
|
def resolve_theme_color key, fallback_color = nil, transparent_color = fallback_color
|
5040
|
-
if (color = @theme[key])
|
5034
|
+
if (color = @theme[key] || fallback_color)
|
5041
5035
|
color == 'transparent' ? transparent_color : color
|
5042
|
-
else
|
5043
|
-
fallback_color
|
5044
5036
|
end
|
5045
5037
|
end
|
5046
5038
|
|
@@ -5052,6 +5044,10 @@ module Asciidoctor
|
|
5052
5044
|
false
|
5053
5045
|
end
|
5054
5046
|
|
5047
|
+
def url? str
|
5048
|
+
(str.include? ':/') && (UrlSniffRx.match? str)
|
5049
|
+
end
|
5050
|
+
|
5055
5051
|
# Calculate the width that is needed to print all the
|
5056
5052
|
# fragments without wrapping any lines.
|
5057
5053
|
#
|
@@ -5120,6 +5116,10 @@ module Asciidoctor
|
|
5120
5116
|
end
|
5121
5117
|
|
5122
5118
|
def init_scratch originator
|
5119
|
+
if @media == 'prepress' && page_margin != (page_margin_recto = @page_margin_by_side[:recto])
|
5120
|
+
# NOTE: prepare scratch document to use page margin from recto side (which has same width as verso side)
|
5121
|
+
set_page_margin page_margin_recto
|
5122
|
+
end
|
5123
5123
|
@scratch_prototype = originator.instance_variable_get :@scratch_prototype
|
5124
5124
|
@tmp_files = originator.instance_variable_get :@tmp_files
|
5125
5125
|
text_formatter.scratch = true
|
@@ -6,20 +6,23 @@ Prawn::Document::ColumnBox.prepend (Module.new do
|
|
6
6
|
def move_past_bottom
|
7
7
|
(doc = @document).y = @y
|
8
8
|
return if (@current_column = (@current_column + 1) % @columns) > 0
|
9
|
-
|
10
|
-
if (
|
11
|
-
@y = par.absolute_top
|
12
|
-
@height = par.height unless stretchy?
|
13
|
-
end
|
9
|
+
parent_ = @parent
|
10
|
+
reset_top parent_ if (reflow_at = @reflow_margins) && (reflow_at == true || reflow_at > doc.page_number)
|
14
11
|
initial_margins = doc.page.margins
|
15
|
-
|
12
|
+
parent_.move_past_bottom
|
16
13
|
if doc.page.margins != initial_margins
|
17
|
-
doc.bounds = self.class.new doc,
|
14
|
+
doc.bounds = self.class.new doc, parent_, [(margin_box = doc.margin_box).absolute_left, @y],
|
18
15
|
columns: @columns, reflow_margins: @reflow_margins, spacer: @spacer, width: margin_box.width, height: @height
|
19
16
|
end
|
20
17
|
nil
|
21
18
|
end
|
22
19
|
|
20
|
+
def reset_top parent_ = @parent
|
21
|
+
@current_column = 0
|
22
|
+
@height = parent_.height unless stretchy?
|
23
|
+
@y = parent_.absolute_top
|
24
|
+
end
|
25
|
+
|
23
26
|
# Rearranges the column box into a single column, where the original columns are in a single file. Used
|
24
27
|
# for the purpose of computing the extent of content in a scratch document.
|
25
28
|
def single_file
|
@@ -528,29 +528,6 @@ module Asciidoctor
|
|
528
528
|
end
|
529
529
|
end
|
530
530
|
|
531
|
-
# Apply the text transform to the specified text.
|
532
|
-
#
|
533
|
-
# Supported transform values are "uppercase", "lowercase", or "none" (passed
|
534
|
-
# as either a String or a Symbol). When the uppercase transform is applied to
|
535
|
-
# the text, it correctly uppercases visible text while leaving markup and
|
536
|
-
# named character entities unchanged. The none transform returns the text
|
537
|
-
# unmodified.
|
538
|
-
#
|
539
|
-
def transform_text text, transform
|
540
|
-
case transform
|
541
|
-
when :uppercase, 'uppercase'
|
542
|
-
uppercase_pcdata text
|
543
|
-
when :lowercase, 'lowercase'
|
544
|
-
lowercase_pcdata text
|
545
|
-
when :capitalize, 'capitalize'
|
546
|
-
capitalize_words_pcdata text
|
547
|
-
when :smallcaps, 'smallcaps'
|
548
|
-
smallcaps_pcdata text
|
549
|
-
else
|
550
|
-
text
|
551
|
-
end
|
552
|
-
end
|
553
|
-
|
554
531
|
def hyphenate_text text, hyphenator
|
555
532
|
hyphenate_words_pcdata text, hyphenator
|
556
533
|
end
|
@@ -924,6 +901,8 @@ module Asciidoctor
|
|
924
901
|
def import_page file, options = {}
|
925
902
|
prev_page_layout = page.layout
|
926
903
|
prev_page_size = page.size
|
904
|
+
prev_page_margin = page_margin
|
905
|
+
prev_bounds = bounds
|
927
906
|
state.compress = false if state.compress # can't use compression if using template
|
928
907
|
prev_text_rendering_mode = (defined? @text_rendering_mode) ? @text_rendering_mode : nil
|
929
908
|
delete_current_page if options[:replace]
|
@@ -936,11 +915,15 @@ module Asciidoctor
|
|
936
915
|
# NOTE: set page size & layout explicitly in case imported page differs
|
937
916
|
# I'm not sure it's right to start a new page here, but unfortunately there's no other
|
938
917
|
# way atm to prevent the size & layout of the imported page from affecting subsequent pages
|
939
|
-
|
918
|
+
if options.fetch :advance, true
|
919
|
+
advance_page layout: prev_page_layout, margin: prev_page_margin, size: prev_page_size
|
920
|
+
(@bounding_box = prev_bounds).reset_top if ColumnBox === prev_bounds
|
921
|
+
end
|
940
922
|
elsif options.fetch :advance_if_missing, true
|
941
923
|
delete_current_page
|
942
924
|
# NOTE: see previous comment
|
943
|
-
advance_page
|
925
|
+
advance_page layout: prev_page_layout, margin: prev_page_margin, size: prev_page_size
|
926
|
+
@y = (@bounding_box = prev_bounds).reset_top if ColumnBox === prev_bounds
|
944
927
|
else
|
945
928
|
delete_current_page
|
946
929
|
end
|
@@ -1112,7 +1095,8 @@ module Asciidoctor
|
|
1112
1095
|
# This method performs all work in a scratch document (or documents). It begins by starting a
|
1113
1096
|
# new page in the scratch document, first creating the scratch document if necessary. It then
|
1114
1097
|
# applies all the settings from the main document to the scratch document that impact
|
1115
|
-
# rendering. This includes the bounds, the cursor position, and the font settings.
|
1098
|
+
# rendering. This includes the bounds, the cursor position, and the font settings. This method
|
1099
|
+
# assumes that the content area remains constant when content flows from one page to the next.
|
1116
1100
|
#
|
1117
1101
|
# From this point, the number of attempts the method makes is determined by the value of the
|
1118
1102
|
# keep_together keyword parameter. If the value is true (or the parent document is inhibiting
|
@@ -1149,7 +1133,7 @@ module Asciidoctor
|
|
1149
1133
|
#
|
1150
1134
|
# Returns an Extent or ScratchExtent object that describes the bounds of the content block.
|
1151
1135
|
def dry_run keep_together: nil, pages_advanced: 0, single_page: nil, onto: nil, &block
|
1152
|
-
(scratch_pdf = scratch).start_new_page
|
1136
|
+
(scratch_pdf = scratch).start_new_page layout: page.layout
|
1153
1137
|
saved_bounds = scratch_pdf.bounds
|
1154
1138
|
scratch_pdf.bounds = bounds.dup.tap do |bounds_copy|
|
1155
1139
|
bounds_copy.instance_variable_set :@document, scratch_pdf
|
@@ -91,7 +91,9 @@ module Prawn
|
|
91
91
|
# TODO: apply horizontal alignment; currently it is necessary to specify alignment on content blocks
|
92
92
|
apply_font_properties { pdf.traverse content }
|
93
93
|
if (extra_pages = pdf.page_number - start_page) > 0
|
94
|
-
|
94
|
+
unless extra_pages == 1 && pdf.page.empty?
|
95
|
+
logger.error message_with_context %(the table cell on page #{start_page} has been truncated; Asciidoctor PDF does not support table cell content that exceeds the height of a single page), source_location: @source_location
|
96
|
+
end
|
95
97
|
extra_pages.times { pdf.delete_current_page }
|
96
98
|
end
|
97
99
|
nil
|
@@ -16,7 +16,9 @@ class Prawn::Table::Cell::Text
|
|
16
16
|
height: spanned_content_height + FPTolerance,
|
17
17
|
at: [0, @pdf.cursor]).render
|
18
18
|
end
|
19
|
-
|
19
|
+
unless remaining_text.empty? || @pdf.scratch?
|
20
|
+
logger.error message_with_context %(the table cell on page #{@pdf.page_number} has been truncated; Asciidoctor PDF does not support table cell content that exceeds the height of a single page), source_location: @source_location
|
21
|
+
end
|
20
22
|
end
|
21
23
|
end
|
22
24
|
|
@@ -4,6 +4,8 @@ module Asciidoctor
|
|
4
4
|
module PDF
|
5
5
|
module FormattedText
|
6
6
|
class Transform
|
7
|
+
include TextTransformer
|
8
|
+
|
7
9
|
LF = ?\n
|
8
10
|
ZeroWidthSpace = ?\u200b
|
9
11
|
CharEntityTable = { amp: '&', apos: ?', gt: '>', lt: '<', nbsp: ?\u00a0, quot: '"' }
|
@@ -21,8 +23,8 @@ module Asciidoctor
|
|
21
23
|
'font_size' => :size,
|
22
24
|
'text_decoration_color' => :text_decoration_color,
|
23
25
|
'text_decoration_width' => :text_decoration_width,
|
26
|
+
'text_transform' => :text_transform,
|
24
27
|
}
|
25
|
-
#DummyText = ?\u0000
|
26
28
|
|
27
29
|
def initialize options = {}
|
28
30
|
@merge_adjacent_text_nodes = options[:merge_adjacent_text_nodes]
|
@@ -96,7 +98,7 @@ module Asciidoctor
|
|
96
98
|
}.compact,
|
97
99
|
}
|
98
100
|
@theme_settings.tap do |accum|
|
99
|
-
|
101
|
+
roles_with_styles = [].to_set
|
100
102
|
theme.each_pair do |key, val|
|
101
103
|
next unless (key = key.to_s).start_with? 'role_'
|
102
104
|
role, key = (key.slice 5, key.length).split '_', 2
|
@@ -110,10 +112,10 @@ module Asciidoctor
|
|
110
112
|
# (accum[role] ||= {})[:kerning] = resolved_val
|
111
113
|
# end
|
112
114
|
elsif key == 'font_style' || key == 'text_decoration'
|
113
|
-
|
115
|
+
roles_with_styles << role
|
114
116
|
end
|
115
117
|
end
|
116
|
-
|
118
|
+
roles_with_styles.each do |role|
|
117
119
|
(accum[role] ||= {})[:styles] = to_styles theme[%(role_#{role}_font_style)], theme[%(role_#{role}_text_decoration)]
|
118
120
|
end
|
119
121
|
end
|
@@ -172,6 +174,11 @@ module Asciidoctor
|
|
172
174
|
previous_fragment_is_text && ((previous_fragment_text = fragments[-1][:text]).end_with? ' ')
|
173
175
|
fragments[-1][:text] = previous_fragment_text.chop
|
174
176
|
end
|
177
|
+
if (text_transform = fragment.delete :text_transform)
|
178
|
+
text = (text_chunks = extract_text pcdata).join
|
179
|
+
text_io = StringIO.new transform_text text, text_transform
|
180
|
+
restore_text pcdata, text_chunks.each_with_object([]) {|chunk, accum| accum << (text_io.read chunk.length) }
|
181
|
+
end
|
175
182
|
# NOTE: decorate child fragments with inherited properties from this element
|
176
183
|
apply pcdata, fragments, fragment
|
177
184
|
previous_fragment_is_text = false
|
@@ -251,6 +258,8 @@ module Asciidoctor
|
|
251
258
|
fragments
|
252
259
|
end
|
253
260
|
|
261
|
+
private
|
262
|
+
|
254
263
|
def build_fragment fragment, tag_name, attrs
|
255
264
|
styles = (fragment[:styles] ||= ::Set.new)
|
256
265
|
case tag_name
|
@@ -324,7 +333,6 @@ module Asciidoctor
|
|
324
333
|
# NOTE: spaces in style value are superfluous for our purpose; split drops record after trailing ;
|
325
334
|
attrs[:style].tr(' ', '').split(';').each do |style|
|
326
335
|
pname, pvalue = style.split ':', 2
|
327
|
-
# TODO: text-transform
|
328
336
|
case pname
|
329
337
|
when 'color' # color needed to support syntax highlighters
|
330
338
|
fragment[:color] = pvalue.length == 7 ? (pvalue.slice 1, 6) : (pvalue.slice 1, 3).each_char.map {|c| c * 2 }.join if (pvalue.start_with? '#') && (HexColorRx.match? pvalue)
|
@@ -409,6 +417,29 @@ module Asciidoctor
|
|
409
417
|
end
|
410
418
|
end
|
411
419
|
end
|
420
|
+
|
421
|
+
def extract_text pcdata
|
422
|
+
pcdata.reduce [] do |accum, it|
|
423
|
+
case it[:type]
|
424
|
+
when :text
|
425
|
+
accum << it[:value]
|
426
|
+
when :element
|
427
|
+
accum += (extract_text it[:pcdata]) if it.key? :pcdata
|
428
|
+
end
|
429
|
+
accum
|
430
|
+
end
|
431
|
+
end
|
432
|
+
|
433
|
+
def restore_text pcdata, text_chunks
|
434
|
+
pcdata.each do |it|
|
435
|
+
case it[:type]
|
436
|
+
when :text
|
437
|
+
it[:value] = text_chunks.shift
|
438
|
+
when :element
|
439
|
+
restore_text it[:pcdata], text_chunks if it.key? :pcdata
|
440
|
+
end
|
441
|
+
end
|
442
|
+
end
|
412
443
|
end
|
413
444
|
end
|
414
445
|
end
|
@@ -64,6 +64,29 @@ module Asciidoctor
|
|
64
64
|
string.tr LowerAlphaChars, SmallCapsChars
|
65
65
|
end
|
66
66
|
end
|
67
|
+
|
68
|
+
# Apply the text transform to the specified text.
|
69
|
+
#
|
70
|
+
# Supported transform values are "uppercase", "lowercase", or "none" (passed
|
71
|
+
# as either a String or a Symbol). When the uppercase transform is applied to
|
72
|
+
# the text, it correctly uppercases visible text while leaving markup and
|
73
|
+
# named character entities unchanged. The none transform returns the text
|
74
|
+
# unmodified.
|
75
|
+
#
|
76
|
+
def transform_text text, transform
|
77
|
+
case transform
|
78
|
+
when :uppercase, 'uppercase'
|
79
|
+
uppercase_pcdata text
|
80
|
+
when :lowercase, 'lowercase'
|
81
|
+
lowercase_pcdata text
|
82
|
+
when :capitalize, 'capitalize'
|
83
|
+
capitalize_words_pcdata text
|
84
|
+
when :smallcaps, 'smallcaps'
|
85
|
+
smallcaps_pcdata text
|
86
|
+
else
|
87
|
+
text
|
88
|
+
end
|
89
|
+
end
|
67
90
|
end
|
68
91
|
end
|
69
92
|
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.1.
|
4
|
+
version: 2.1.4
|
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-26 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: asciidoctor
|