asciidoctor-pdf 2.1.3 → 2.1.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.adoc +16 -0
- data/README.adoc +1 -1
- data/lib/asciidoctor/pdf/converter.rb +19 -16
- data/lib/asciidoctor/pdf/ext/prawn/extensions.rb +0 -23
- 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 +33 -2
- 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,22 @@
|
|
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
|
+
|
8
24
|
== 2.1.3 (2022-06-23) - @mojavelinux
|
9
25
|
|
10
26
|
Bug Fixes::
|
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:
|
@@ -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])/
|
@@ -1886,7 +1887,7 @@ module Asciidoctor
|
|
1886
1887
|
add_dest_for_block node if node.id
|
1887
1888
|
audio_path = node.media_uri node.attr 'target'
|
1888
1889
|
play_symbol = (node.document.attr? 'icons', 'font') ? %(<font name="fas">#{(icon_font_data 'fas').unicode 'play'}</font>) : RightPointer
|
1889
|
-
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
|
1890
1891
|
ink_caption node, labeled: false, end: :bottom if node.title?
|
1891
1892
|
theme_margin :block, :bottom, (next_enclosed_block node)
|
1892
1893
|
end
|
@@ -1914,7 +1915,7 @@ module Asciidoctor
|
|
1914
1915
|
if poster.nil_or_empty?
|
1915
1916
|
add_dest_for_block node if node.id
|
1916
1917
|
play_symbol = (node.document.attr? 'icons', 'font') ? %(<font name="fas">#{(icon_font_data 'fas').unicode 'play'}</font>) : RightPointer
|
1917
|
-
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
|
1918
1919
|
ink_caption node, labeled: false, end: :bottom if node.title?
|
1919
1920
|
theme_margin :block, :bottom, (next_enclosed_block node)
|
1920
1921
|
else
|
@@ -2053,7 +2054,8 @@ module Asciidoctor
|
|
2053
2054
|
content: cell_text,
|
2054
2055
|
colspan: cell.colspan || 1,
|
2055
2056
|
align: (cell.attr 'halign').to_sym,
|
2056
|
-
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
|
2057
2059
|
end)
|
2058
2060
|
end
|
2059
2061
|
end unless head_rows.empty?
|
@@ -2072,7 +2074,8 @@ module Asciidoctor
|
|
2072
2074
|
colspan: cell.colspan || 1,
|
2073
2075
|
rowspan: cell.rowspan || 1,
|
2074
2076
|
align: (cell.attr 'halign').to_sym,
|
2075
|
-
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
|
2076
2079
|
cell_line_metrics = body_cell_line_metrics
|
2077
2080
|
case cell.style
|
2078
2081
|
when :emphasis
|
@@ -2133,7 +2136,7 @@ module Asciidoctor
|
|
2133
2136
|
# NOTE: line metrics get applied when AsciiDoc content is converted
|
2134
2137
|
cell_line_metrics = nil
|
2135
2138
|
asciidoc_cell = ::Prawn::Table::Cell::AsciiDoc.new self, (cell_data.merge content: cell.inner_document, padding: body_cell_padding)
|
2136
|
-
cell_data = { content: asciidoc_cell }
|
2139
|
+
cell_data = { content: asciidoc_cell, source_location: cell.source_location }
|
2137
2140
|
end
|
2138
2141
|
if cell_line_metrics
|
2139
2142
|
cell_padding = body_cell_padding.dup
|
@@ -2685,13 +2688,7 @@ module Asciidoctor
|
|
2685
2688
|
end
|
2686
2689
|
|
2687
2690
|
if (roles = node.role)
|
2688
|
-
|
2689
|
-
roles.split.each do |role|
|
2690
|
-
if (text_transform = theme[%(role_#{role}_text_transform)])
|
2691
|
-
inner_text = transform_text inner_text, text_transform
|
2692
|
-
end
|
2693
|
-
inner_text = inner_text.gsub DoubleSpaceRx, ' ' + ZeroWidthSpace if role == 'pre-wrap' && (inner_text.include? DoubleSpace)
|
2694
|
-
end
|
2691
|
+
inner_text = inner_text.gsub DoubleSpaceRx, ' ' + ZeroWidthSpace if (node.has_role? 'pre-wrap') && (inner_text.include? DoubleSpace)
|
2695
2692
|
quoted_text = is_tag ? %(#{open.chop} class="#{roles}">#{inner_text}#{close}) : %(<span class="#{roles}">#{open}#{inner_text}#{close}</span>)
|
2696
2693
|
else
|
2697
2694
|
quoted_text = %(#{open}#{inner_text}#{close})
|
@@ -3241,7 +3238,8 @@ module Asciidoctor
|
|
3241
3238
|
end
|
3242
3239
|
end
|
3243
3240
|
|
3244
|
-
# 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
|
3245
3243
|
def ink_prose string, opts = {}
|
3246
3244
|
top_margin = (margin = (opts.delete :margin)) || (opts.delete :margin_top) || 0
|
3247
3245
|
bot_margin = margin || (opts.delete :margin_bottom) || @theme.prose_margin_bottom
|
@@ -4255,10 +4253,10 @@ module Asciidoctor
|
|
4255
4253
|
# NOTE: this will catch a classloader resource path on JRuby (e.g., uri:classloader:/path/to/image)
|
4256
4254
|
elsif ::File.absolute_path? image_path
|
4257
4255
|
::File.absolute_path image_path
|
4258
|
-
elsif !(
|
4256
|
+
elsif !(is_url = url? image_path) && imagesdir && (::File.absolute_path? imagesdir)
|
4259
4257
|
::File.absolute_path image_path, imagesdir
|
4260
4258
|
# handle case when image is a URI
|
4261
|
-
elsif
|
4259
|
+
elsif is_url || (imagesdir && (url? imagesdir) && (image_path = node.normalize_web_path image_path, imagesdir, false))
|
4262
4260
|
if !allow_uri_read
|
4263
4261
|
log :warn, %(cannot embed remote image: #{image_path} (allow-uri-read attribute not enabled))
|
4264
4262
|
return
|
@@ -4496,6 +4494,7 @@ module Asciidoctor
|
|
4496
4494
|
end
|
4497
4495
|
|
4498
4496
|
# TODO: document me, esp the first line formatting functionality
|
4497
|
+
# NOTE: single_line option should only be used if height option is specified
|
4499
4498
|
def typeset_text string, line_metrics, opts = {}
|
4500
4499
|
opts = { leading: line_metrics.leading, final_gap: line_metrics.final_gap }.merge opts
|
4501
4500
|
string = string.gsub CjkLineBreakRx, ZeroWidthSpace if @cjk_line_breaks
|
@@ -4950,7 +4949,7 @@ module Asciidoctor
|
|
4950
4949
|
alt_text_vars[:'/link'] = ''
|
4951
4950
|
end
|
4952
4951
|
theme_font :image_alt do
|
4953
|
-
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
|
4954
4953
|
end
|
4955
4954
|
ink_caption node, category: :image, end: :bottom if node.title?
|
4956
4955
|
theme_margin :block, :bottom, (next_enclosed_block node) unless opts[:pinned]
|
@@ -5045,6 +5044,10 @@ module Asciidoctor
|
|
5045
5044
|
false
|
5046
5045
|
end
|
5047
5046
|
|
5047
|
+
def url? str
|
5048
|
+
(str.include? ':/') && (UrlSniffRx.match? str)
|
5049
|
+
end
|
5050
|
+
|
5048
5051
|
# Calculate the width that is needed to print all the
|
5049
5052
|
# fragments without wrapping any lines.
|
5050
5053
|
#
|
@@ -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
|
@@ -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]
|
@@ -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
|