asciidoctor-pdf 2.1.5 → 2.3.0
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 +71 -8
- data/README.adoc +1 -1
- data/bin/asciidoctor-pdf +26 -7
- data/bin/asciidoctor-pdf-optimize +1 -2
- data/data/themes/base-theme.yml +2 -2
- data/data/themes/default-theme.yml +7 -30
- data/lib/asciidoctor/pdf/converter.rb +232 -154
- data/lib/asciidoctor/pdf/ext/asciidoctor/document.rb +5 -0
- data/lib/asciidoctor/pdf/ext/prawn/document/column_box.rb +4 -0
- data/lib/asciidoctor/pdf/ext/prawn/extensions.rb +10 -4
- data/lib/asciidoctor/pdf/ext/prawn/formatted_text/arranger.rb +11 -0
- data/lib/asciidoctor/pdf/ext/prawn/formatted_text/line_wrap.rb +42 -0
- data/lib/asciidoctor/pdf/ext/prawn.rb +1 -0
- data/lib/asciidoctor/pdf/formatted_text/transform.rb +5 -2
- data/lib/asciidoctor/pdf/sanitizer.rb +7 -3
- data/lib/asciidoctor/pdf/theme_loader.rb +10 -14
- data/lib/asciidoctor/pdf/version.rb +1 -1
- metadata +3 -2
@@ -371,14 +371,16 @@ module Asciidoctor
|
|
371
371
|
else
|
372
372
|
super points.to_f
|
373
373
|
end
|
374
|
-
# NOTE: assume em value (since a font size of 1 is extremely unlikely)
|
375
|
-
elsif points <= 1
|
376
|
-
super @font_size * points
|
377
374
|
else
|
378
375
|
super points
|
379
376
|
end
|
380
377
|
end
|
381
378
|
|
379
|
+
def set_font font, size = nil
|
380
|
+
@font = font
|
381
|
+
font_size size if size
|
382
|
+
end
|
383
|
+
|
382
384
|
def resolve_font_style styles
|
383
385
|
if styles.include? :bold
|
384
386
|
(styles.include? :italic) ? :bold_italic : :bold
|
@@ -1121,6 +1123,10 @@ module Asciidoctor
|
|
1121
1123
|
# Note that if the block has content that itself requires a dry run, that nested dry run will
|
1122
1124
|
# be performed in a separate scratch document.
|
1123
1125
|
#
|
1126
|
+
# The block passed to dry run should take steps to avoid leaving the document state modified.
|
1127
|
+
# This can be done by calling `push_scratch doc` at the start of the block and `pop_scratch`
|
1128
|
+
# in the ensure clause of the block.
|
1129
|
+
#
|
1124
1130
|
# options - A Hash of options that configure the dry run computation:
|
1125
1131
|
# :keep_together - A Boolean indicating whether an attempt should be made to keep
|
1126
1132
|
# the content on the same page (optional, default: false).
|
@@ -1133,7 +1139,7 @@ module Asciidoctor
|
|
1133
1139
|
#
|
1134
1140
|
# Returns an Extent or ScratchExtent object that describes the bounds of the content block.
|
1135
1141
|
def dry_run keep_together: nil, pages_advanced: 0, single_page: nil, onto: nil, &block
|
1136
|
-
(scratch_pdf = scratch).start_new_page layout: page.layout
|
1142
|
+
(scratch_pdf = scratch).start_new_page layout: page.layout, margin: page_margin
|
1137
1143
|
saved_bounds = scratch_pdf.bounds
|
1138
1144
|
scratch_pdf.bounds = bounds.dup.tap do |bounds_copy|
|
1139
1145
|
bounds_copy.instance_variable_set :@document, scratch_pdf
|
@@ -26,6 +26,17 @@ Prawn::Text::Formatted::Arranger.prepend (Module.new do
|
|
26
26
|
(string = super) == @dummy_text ? (string.extend Prawn::Text::NoopLstripBang) : string
|
27
27
|
end
|
28
28
|
|
29
|
+
def preview_joined_string
|
30
|
+
if (next_unconsumed = @unconsumed[0] || {})[:wj] && !(@consumed[-1] || [])[:wj]
|
31
|
+
idx = 0
|
32
|
+
str = '' if (str = next_unconsumed[:text]) == @dummy_text
|
33
|
+
while (next_unconsumed = @unconsumed[idx += 1] || {})[:wj] && (next_string = next_unconsumed[:text])
|
34
|
+
str += next_string unless next_string == @dummy_text
|
35
|
+
end
|
36
|
+
str unless str == ''
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
29
40
|
def apply_font_size size, styles
|
30
41
|
if (subscript? styles) || (superscript? styles)
|
31
42
|
size ||= @document.font_size
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
Prawn::Text::Formatted::LineWrap.prepend (Module.new do
|
4
|
+
def add_fragment_to_line fragment
|
5
|
+
case fragment
|
6
|
+
when ''
|
7
|
+
true
|
8
|
+
when ?\n
|
9
|
+
@newline_encountered = true
|
10
|
+
false
|
11
|
+
else
|
12
|
+
if (joined_string = @arranger.preview_joined_string)
|
13
|
+
joined_string_width = @document.width_of (tokenize joined_string)[0], kerning: @kerning
|
14
|
+
else
|
15
|
+
joined_string_width = 0
|
16
|
+
end
|
17
|
+
last_idx = (segments = tokenize fragment).length - 1
|
18
|
+
segments.each_with_index do |segment, idx|
|
19
|
+
if segment == (zero_width_space segment.encoding)
|
20
|
+
segment_width = effective_segment_width = 0
|
21
|
+
else
|
22
|
+
segment_width = effective_segment_width = @document.width_of segment, kerning: @kerning
|
23
|
+
effective_segment_width += joined_string_width if idx === last_idx
|
24
|
+
end
|
25
|
+
if @accumulated_width + effective_segment_width <= @width
|
26
|
+
@accumulated_width += segment_width
|
27
|
+
if segment[-1] == (shy = soft_hyphen segment.encoding)
|
28
|
+
@accumulated_width -= (@document.width_of shy, kerning: @kerning)
|
29
|
+
end
|
30
|
+
@fragment_output += segment
|
31
|
+
else
|
32
|
+
@line_contains_more_than_one_word = false if @accumulated_width == 0 && @line_contains_more_than_one_word
|
33
|
+
end_of_the_line_reached segment
|
34
|
+
fragment_finished fragment
|
35
|
+
return false
|
36
|
+
end
|
37
|
+
end
|
38
|
+
fragment_finished fragment
|
39
|
+
true
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end)
|
@@ -13,5 +13,6 @@ require_relative 'prawn/formatted_text/arranger'
|
|
13
13
|
require_relative 'prawn/formatted_text/box'
|
14
14
|
require_relative 'prawn/formatted_text/fragment'
|
15
15
|
require_relative 'prawn/formatted_text/indented_paragraph_wrap'
|
16
|
+
require_relative 'prawn/formatted_text/line_wrap'
|
16
17
|
require_relative 'prawn/formatted_text/protect_bottom_gutter'
|
17
18
|
require_relative 'prawn/extensions'
|
@@ -315,10 +315,12 @@ module Asciidoctor
|
|
315
315
|
end) : value
|
316
316
|
elsif (value = attrs[:id])
|
317
317
|
# NOTE: text is null character, which is used as placeholder text so Prawn doesn't drop fragment
|
318
|
-
|
318
|
+
new_fragment = { name: value, callback: [InlineDestinationMarker] }
|
319
|
+
new_fragment[:wj] = true if fragment[:wj]
|
319
320
|
if (type = attrs[:type])
|
320
|
-
|
321
|
+
new_fragment[:type] = type.to_sym
|
321
322
|
end
|
323
|
+
fragment = new_fragment
|
322
324
|
visible = nil
|
323
325
|
end
|
324
326
|
end
|
@@ -357,6 +359,7 @@ module Asciidoctor
|
|
357
359
|
end
|
358
360
|
# TODO: we could limit to select tags, but doesn't seem to really affect performance
|
359
361
|
attrs[:class].split.each do |class_name|
|
362
|
+
fragment[:wj] = true if class_name == 'wj'
|
360
363
|
next unless @theme_settings.key? class_name
|
361
364
|
update_fragment fragment, @theme_settings[class_name]
|
362
365
|
# NOTE: defer assignment of callback since we must look at combined styles of element and role
|
@@ -8,7 +8,7 @@ module Asciidoctor
|
|
8
8
|
'>' => '>',
|
9
9
|
'&' => '&',
|
10
10
|
}
|
11
|
-
XMLSpecialCharsRx =
|
11
|
+
XMLSpecialCharsRx = /&(?:[lg]t|amp);/
|
12
12
|
InverseXMLSpecialChars = XMLSpecialChars.invert
|
13
13
|
InverseXMLSpecialCharsRx = /[#{InverseXMLSpecialChars.keys.join}]/
|
14
14
|
(BuiltInNamedEntities = {
|
@@ -28,16 +28,20 @@ module Asciidoctor
|
|
28
28
|
#
|
29
29
|
# FIXME: move to a module so we can mix it in elsewhere
|
30
30
|
# FIXME: add option to control escaping entities, or a filter mechanism in general
|
31
|
-
def sanitize string
|
31
|
+
def sanitize string, compact: true
|
32
32
|
string = string.gsub SanitizeXMLRx, '' if string.include? '<'
|
33
33
|
string = string.gsub(CharRefRx) { $1 ? BuiltInNamedEntities[$1] : ([$2 ? $2.to_i : ($3.to_i 16)].pack 'U1') } if string.include? '&'
|
34
|
-
string.strip.tr_s ' ', ' '
|
34
|
+
compact ? (string.strip.tr_s ' ', ' ') : string
|
35
35
|
end
|
36
36
|
|
37
37
|
def escape_xml string
|
38
38
|
string.gsub InverseXMLSpecialCharsRx, InverseXMLSpecialChars
|
39
39
|
end
|
40
40
|
|
41
|
+
def unescape_xml string
|
42
|
+
string.gsub XMLSpecialCharsRx, XMLSpecialChars
|
43
|
+
end
|
44
|
+
|
41
45
|
def escape_amp string
|
42
46
|
string.gsub UnescapedAmpersandRx, '&'
|
43
47
|
end
|
@@ -160,7 +160,7 @@ module Asciidoctor
|
|
160
160
|
data[key] = {}.tap do |accum|
|
161
161
|
val.each do |key2, val2|
|
162
162
|
key2 = key2.tr '-', '_' if key2.include? '-'
|
163
|
-
accum[key2.to_sym] = (key2.end_with? '_color') ? (to_color evaluate val2, data) : (evaluate val2, data)
|
163
|
+
accum[key2.to_sym] = (key2.end_with? '_color') ? (to_color evaluate val2, data, math: false) : (evaluate val2, data)
|
164
164
|
end
|
165
165
|
end if val
|
166
166
|
elsif ::Hash === val
|
@@ -173,20 +173,18 @@ module Asciidoctor
|
|
173
173
|
end
|
174
174
|
elsif (rekey = DeprecatedKeys[key]) ||
|
175
175
|
((key.start_with? 'role_') && (key.end_with? '_align') && (rekey = key.sub RoleAlignKeyRx, '_text_align'))
|
176
|
-
data[rekey] = evaluate val, data
|
176
|
+
data[rekey] = evaluate val, data, math: false
|
177
177
|
elsif PaddingBottomHackKeys.include? key
|
178
178
|
val = evaluate val, data
|
179
179
|
# normalize padding hacks for themes designed before the converter had smart margins
|
180
180
|
val[2] = val[0] if ::Array === val && val[0].to_f >= 0 && val[2].to_f <= 0
|
181
181
|
data[key] = val
|
182
|
-
# QUESTION: do we really need to evaluate_math in this case?
|
183
182
|
elsif key.end_with? '_color'
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
data[key] = val.map {|it| to_color evaluate it, data }
|
183
|
+
# assume table_grid_color is a single color unless the value is a 2-element array for backwards compatibility
|
184
|
+
if key == 'table_border_color' ? ::Array === val : (key == 'table_grid_color' && ::Array === val && val.size == 2)
|
185
|
+
data[key] = val.map {|it| to_color evaluate it, data, math: false }
|
188
186
|
else
|
189
|
-
data[key] = to_color evaluate val, data
|
187
|
+
data[key] = to_color evaluate val, data, math: false
|
190
188
|
end
|
191
189
|
elsif key.end_with? '_content'
|
192
190
|
data[key] = (expand_vars val.to_s, data).to_s
|
@@ -196,12 +194,12 @@ module Asciidoctor
|
|
196
194
|
data
|
197
195
|
end
|
198
196
|
|
199
|
-
def evaluate expr, vars
|
197
|
+
def evaluate expr, vars, math: true
|
200
198
|
case expr
|
201
199
|
when ::String
|
202
|
-
evaluate_math expand_vars expr, vars
|
200
|
+
math ? (evaluate_math expand_vars expr, vars) : (expand_vars expr, vars)
|
203
201
|
when ::Array
|
204
|
-
expr.map {|e| evaluate e, vars }
|
202
|
+
expr.map {|e| evaluate e, vars, math: math }
|
205
203
|
else
|
206
204
|
expr
|
207
205
|
end
|
@@ -233,7 +231,6 @@ module Asciidoctor
|
|
233
231
|
def evaluate_math expr
|
234
232
|
return expr if !(::String === expr) || ColorValue === expr
|
235
233
|
# resolve measurement values (e.g., 0.5in => 36)
|
236
|
-
# QUESTION: should we round the value? perhaps leave that to the precision functions
|
237
234
|
# NOTE: leave % as a string; handled by converter for now
|
238
235
|
original, expr = expr, (resolve_measurement_values expr)
|
239
236
|
while true
|
@@ -257,8 +254,7 @@ module Asciidoctor
|
|
257
254
|
end
|
258
255
|
end
|
259
256
|
if (expr.end_with? ')') && expr =~ PrecisionFuncRx
|
260
|
-
op = $1
|
261
|
-
offset = op.length + 1
|
257
|
+
offset = (op = $1).length + 1
|
262
258
|
expr = expr[offset...-1].to_f.send op.to_sym
|
263
259
|
end
|
264
260
|
if expr == original
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: asciidoctor-pdf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.3.0
|
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-
|
12
|
+
date: 2022-08-16 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: asciidoctor
|
@@ -280,6 +280,7 @@ files:
|
|
280
280
|
- lib/asciidoctor/pdf/ext/prawn/formatted_text/box.rb
|
281
281
|
- lib/asciidoctor/pdf/ext/prawn/formatted_text/fragment.rb
|
282
282
|
- lib/asciidoctor/pdf/ext/prawn/formatted_text/indented_paragraph_wrap.rb
|
283
|
+
- lib/asciidoctor/pdf/ext/prawn/formatted_text/line_wrap.rb
|
283
284
|
- lib/asciidoctor/pdf/ext/prawn/formatted_text/protect_bottom_gutter.rb
|
284
285
|
- lib/asciidoctor/pdf/ext/prawn/images.rb
|
285
286
|
- lib/asciidoctor/pdf/ext/pygments.rb
|