asciidoctor-pdf 1.5.0.alpha.12 → 1.5.0.alpha.13
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.adoc +325 -0
- data/Gemfile +1 -1
- data/README.adoc +97 -43
- data/asciidoctor-pdf.gemspec +7 -6
- data/data/fonts/mplus1mn-bold-ascii.ttf +0 -0
- data/data/fonts/mplus1mn-bold_italic-ascii.ttf +0 -0
- data/data/fonts/mplus1mn-italic-ascii.ttf +0 -0
- data/data/fonts/mplus1mn-regular-ascii-conums.ttf +0 -0
- data/data/fonts/notoserif-bold-subset.ttf +0 -0
- data/data/fonts/notoserif-bold_italic-subset.ttf +0 -0
- data/data/fonts/notoserif-italic-subset.ttf +0 -0
- data/data/fonts/notoserif-regular-subset.ttf +0 -0
- data/data/themes/default-theme.yml +22 -13
- data/docs/theming-guide.adoc +276 -110
- data/lib/asciidoctor-pdf/asciidoctor_ext/image.rb +7 -7
- data/lib/asciidoctor-pdf/asciidoctor_ext/list.rb +24 -1
- data/lib/asciidoctor-pdf/asciidoctor_ext/list_item.rb +3 -3
- data/lib/asciidoctor-pdf/asciidoctor_ext/section.rb +11 -3
- data/lib/asciidoctor-pdf/converter.rb +614 -401
- data/lib/asciidoctor-pdf/core_ext.rb +1 -0
- data/lib/asciidoctor-pdf/core_ext/array.rb +2 -2
- data/lib/asciidoctor-pdf/core_ext/numeric.rb +1 -1
- data/lib/asciidoctor-pdf/core_ext/ostruct.rb +10 -2
- data/lib/asciidoctor-pdf/core_ext/string.rb +11 -0
- data/lib/asciidoctor-pdf/formatted_text/inline_image_arranger.rb +2 -2
- data/lib/asciidoctor-pdf/formatted_text/inline_image_renderer.rb +5 -5
- data/lib/asciidoctor-pdf/formatted_text/transform.rb +6 -4
- data/lib/asciidoctor-pdf/implicit_header_processor.rb +1 -1
- data/lib/asciidoctor-pdf/pdf_core_ext/page.rb +1 -1
- data/lib/asciidoctor-pdf/prawn_ext/coderay_encoder.rb +3 -3
- data/lib/asciidoctor-pdf/prawn_ext/extensions.rb +77 -28
- data/lib/asciidoctor-pdf/prawn_ext/font/afm.rb +5 -4
- data/lib/asciidoctor-pdf/prawn_ext/images.rb +1 -1
- data/lib/asciidoctor-pdf/roman_numeral.rb +11 -4
- data/lib/asciidoctor-pdf/rouge_ext/formatters/prawn.rb +9 -9
- data/lib/asciidoctor-pdf/theme_loader.rb +16 -3
- data/lib/asciidoctor-pdf/version.rb +1 -1
- metadata +18 -9
@@ -2,10 +2,10 @@ class Array
|
|
2
2
|
if RUBY_VERSION < '2.1.0'
|
3
3
|
def to_h
|
4
4
|
Hash[to_a]
|
5
|
-
end unless
|
5
|
+
end unless method_defined? :to_h
|
6
6
|
end
|
7
7
|
|
8
8
|
def delete_all *entries
|
9
9
|
entries.map {|entry| delete entry }.compact
|
10
|
-
end unless
|
10
|
+
end unless method_defined? :delete_all
|
11
11
|
end
|
@@ -1,9 +1,17 @@
|
|
1
1
|
class OpenStruct
|
2
2
|
def [] key
|
3
3
|
send key
|
4
|
-
end unless
|
4
|
+
end unless method_defined? :[]
|
5
5
|
|
6
6
|
def []= key, val
|
7
7
|
send %(#{key}=), val
|
8
|
-
end unless
|
8
|
+
end unless method_defined? :[]=
|
9
9
|
end if RUBY_ENGINE == 'rbx' || RUBY_VERSION < '2.0.0'
|
10
|
+
|
11
|
+
class OpenStruct
|
12
|
+
def delete key
|
13
|
+
begin
|
14
|
+
delete_field key
|
15
|
+
rescue ::NameError; end
|
16
|
+
end
|
17
|
+
end
|
@@ -57,7 +57,7 @@ module InlineImageArranger
|
|
57
57
|
end
|
58
58
|
|
59
59
|
# TODO make helper method to calculate width and height of image
|
60
|
-
if fragment[:
|
60
|
+
if fragment[:image_format] == 'svg'
|
61
61
|
svg_obj = ::Prawn::Svg::Interface.new (::IO.read image_path), doc, at: doc.bounds.top_left, width: image_w, fallback_font_name: doc.default_svg_font
|
62
62
|
if image_w
|
63
63
|
fragment[:image_width] = svg_obj.document.sizing.output_width
|
@@ -69,7 +69,7 @@ module InlineImageArranger
|
|
69
69
|
fragment[:image_obj] = svg_obj
|
70
70
|
else
|
71
71
|
# TODO cache image info based on path (Prawn cached based on SHA1 of content)
|
72
|
-
image_obj, image_info = doc.build_image_object
|
72
|
+
image_obj, image_info = ::File.open(image_path, 'rb') {|fd| doc.build_image_object fd }
|
73
73
|
if image_w
|
74
74
|
fragment[:image_width], fragment[:image_height] = image_info.calc_image_dimensions width: image_w
|
75
75
|
else
|
@@ -24,12 +24,12 @@ module InlineImageRenderer
|
|
24
24
|
fragment.top - ((fragment.height - data[:image_height]) / 2.0)
|
25
25
|
end
|
26
26
|
image_left = fragment.left + ((fragment.width - data[:image_width]) / 2.0)
|
27
|
-
case data[:
|
27
|
+
case data[:image_format]
|
28
28
|
when 'svg'
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
29
|
+
(image_obj = data[:image_obj]).options[:at] = [image_left, image_top]
|
30
|
+
# NOTE prawn-svg messes with the cursor; use float to workaround
|
31
|
+
# NOTE prawn-svg 0.24.0, 0.25.0, & 0.25.1 didn't restore font after call to draw (see mogest/prawn-svg#80)
|
32
|
+
pdf.float { image_obj.draw }
|
33
33
|
else
|
34
34
|
pdf.embed_image data[:image_obj], data[:image_info], at: [image_left, image_top], width: data[:image_width]
|
35
35
|
end
|
@@ -2,7 +2,7 @@ module Asciidoctor
|
|
2
2
|
module Pdf
|
3
3
|
module FormattedText
|
4
4
|
class Transform
|
5
|
-
|
5
|
+
LF = %(\n)
|
6
6
|
CharEntityTable = {
|
7
7
|
lt: '<',
|
8
8
|
gt: '>',
|
@@ -72,16 +72,16 @@ class Transform
|
|
72
72
|
case node[:name]
|
73
73
|
when :br
|
74
74
|
if @merge_adjacent_text_nodes && previous_fragment_is_text
|
75
|
-
fragments << { text: %(#{fragments.pop[:text]}#{
|
75
|
+
fragments << { text: %(#{fragments.pop[:text]}#{LF}) }
|
76
76
|
else
|
77
|
-
fragments << { text:
|
77
|
+
fragments << { text: LF }
|
78
78
|
end
|
79
79
|
previous_fragment_is_text = true
|
80
80
|
when :img
|
81
81
|
attributes = node[:attributes]
|
82
82
|
fragment = {
|
83
83
|
image_path: attributes[:src],
|
84
|
-
|
84
|
+
image_format: attributes[:format],
|
85
85
|
image_tmp: (attributes[:tmp] == 'true'),
|
86
86
|
text: attributes[:alt],
|
87
87
|
callback: InlineImageRenderer
|
@@ -194,6 +194,8 @@ class Transform
|
|
194
194
|
} : value
|
195
195
|
end
|
196
196
|
if !fragment[:name] && (value = attrs[:name])
|
197
|
+
# NOTE ZeroWidthSpace is used as placeholder text so Prawn doesn't drop fragment
|
198
|
+
#fragment[:text] = ZeroWidthSpace
|
197
199
|
fragment[:name] = value
|
198
200
|
fragment[:callback] = InlineDestinationMarker
|
199
201
|
end
|
@@ -12,7 +12,7 @@ class ImplicitHeaderProcessor < ::Asciidoctor::Extensions::IncludeProcessor
|
|
12
12
|
if (first_line = fd.readline) && (first_line.start_with? '= ')
|
13
13
|
# HACK reset counters for each article for Editions
|
14
14
|
if doc.attr? 'env', 'editions'
|
15
|
-
doc.counters.each do |
|
15
|
+
doc.counters.each do |counter_key, counter_val|
|
16
16
|
doc.attributes.delete counter_key
|
17
17
|
end
|
18
18
|
doc.counters.clear
|
@@ -16,7 +16,7 @@ class Page
|
|
16
16
|
@content = document.ref({})
|
17
17
|
dictionary.data[:Contents] << document.state.store[@content]
|
18
18
|
document.renderer.open_graphics_state
|
19
|
-
end unless
|
19
|
+
end unless method_defined? :new_content_stream
|
20
20
|
end
|
21
21
|
end
|
22
22
|
end
|
@@ -68,7 +68,7 @@ class CodeRayEncoder < ::CodeRay::Encoders::Encoder
|
|
68
68
|
value: '336600'
|
69
69
|
}
|
70
70
|
|
71
|
-
|
71
|
+
LF = %(\n)
|
72
72
|
NoBreakSpace = %(\u00a0)
|
73
73
|
InnerIndent = %(\n )
|
74
74
|
GuardedIndent = %(\u00a0)
|
@@ -83,7 +83,7 @@ class CodeRayEncoder < ::CodeRay::Encoders::Encoder
|
|
83
83
|
end
|
84
84
|
|
85
85
|
def text_token text, kind
|
86
|
-
if text ==
|
86
|
+
if text == LF
|
87
87
|
@out << { text: text }
|
88
88
|
@start_of_line = true
|
89
89
|
# NOTE text is nil and kind is :error when CodeRay ends parsing on an error
|
@@ -99,7 +99,7 @@ class CodeRayEncoder < ::CodeRay::Encoders::Encoder
|
|
99
99
|
# QUESTION should we default to no color?
|
100
100
|
@out << { text: text, color: (COLORS[kind] || COLORS[@open.last] || COLORS[:default]) }
|
101
101
|
end
|
102
|
-
@start_of_line = text.end_with?
|
102
|
+
@start_of_line = text.end_with? LF
|
103
103
|
end
|
104
104
|
end
|
105
105
|
|
@@ -11,6 +11,7 @@ module Extensions
|
|
11
11
|
|
12
12
|
IconSets = ['fa', 'fi', 'octicon', 'pf'].to_set
|
13
13
|
MeasurementValueRx = /(\d+|\d*\.\d+)(in|mm|cm|px|pt)?$/
|
14
|
+
InitialPageContent = %(q\n)
|
14
15
|
|
15
16
|
# - :height is the height of a line
|
16
17
|
# - :leading is spacing between adjacent lines
|
@@ -53,6 +54,20 @@ module Extensions
|
|
53
54
|
reference_bounds.height
|
54
55
|
end
|
55
56
|
|
57
|
+
# Set the margins for the current page.
|
58
|
+
#
|
59
|
+
def set_page_margin margin
|
60
|
+
# FIXME is there a cleaner way to set margins? does it make sense to override create_new_page?
|
61
|
+
apply_margin_options margin: margin
|
62
|
+
generate_margin_box
|
63
|
+
end
|
64
|
+
|
65
|
+
# Returns the margins for the current page as a 4 element array (top, right, bottom, left)
|
66
|
+
#
|
67
|
+
def page_margin
|
68
|
+
[page.margins[:top], page.margins[:right], page.margins[:bottom], page.margins[:left]]
|
69
|
+
end
|
70
|
+
|
56
71
|
# Returns the width of the left margin for the current page
|
57
72
|
#
|
58
73
|
def page_margin_left
|
@@ -93,20 +108,38 @@ module Extensions
|
|
93
108
|
page.dimensions[2] - bounds.absolute_right
|
94
109
|
end
|
95
110
|
|
96
|
-
# Returns
|
111
|
+
# Returns the side the current page is facing, :recto or :verso.
|
112
|
+
#
|
113
|
+
def page_side pgnum = nil
|
114
|
+
(recto_page? pgnum) ? :recto : :verso
|
115
|
+
end
|
116
|
+
|
117
|
+
# Returns whether the page is a recto page.
|
118
|
+
#
|
119
|
+
def recto_page? pgnum = nil
|
120
|
+
(pgnum || page_number).odd?
|
121
|
+
end
|
122
|
+
|
123
|
+
# Returns whether the page is a verso page.
|
124
|
+
#
|
125
|
+
def verso_page? pgnum = nil
|
126
|
+
(pgnum || page_number).even?
|
127
|
+
end
|
128
|
+
|
129
|
+
# Returns whether the cursor is at the top of the page (i.e., margin box).
|
97
130
|
#
|
98
131
|
def at_page_top?
|
99
132
|
@y == @margin_box.absolute_top
|
100
133
|
end
|
101
134
|
|
102
|
-
# Returns whether the current page is empty (no content
|
103
|
-
#
|
135
|
+
# Returns whether the current page is empty (i.e., no content has been written).
|
136
|
+
# Returns false if a page has not yet been created.
|
104
137
|
#
|
105
138
|
def empty_page?
|
106
139
|
# if we are at the page top, assume we didn't write anything to the page
|
107
140
|
#at_page_top?
|
108
|
-
# ...or use low-level check (initial value is "q\n")
|
109
|
-
|
141
|
+
# ...or use more robust, low-level check (initial value of content is "q\n")
|
142
|
+
page_number > 0 && page.content.stream.filtered_stream == InitialPageContent
|
110
143
|
end
|
111
144
|
alias :page_is_empty? :empty_page?
|
112
145
|
|
@@ -119,17 +152,21 @@ module Extensions
|
|
119
152
|
# Converts the specified float value to a pt value from the
|
120
153
|
# specified unit of measurement (e.g., in, cm, mm, etc).
|
121
154
|
def to_pt num, units
|
122
|
-
|
123
|
-
when nil, 'pt'
|
155
|
+
if units.nil_or_empty?
|
124
156
|
num
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
157
|
+
else
|
158
|
+
case units
|
159
|
+
when 'pt'
|
160
|
+
num
|
161
|
+
when 'in'
|
162
|
+
num * 72
|
163
|
+
when 'mm'
|
164
|
+
num * (72 / 25.4)
|
165
|
+
when 'cm'
|
166
|
+
num * (720 / 25.4)
|
167
|
+
when 'px'
|
168
|
+
num * 0.75
|
169
|
+
end
|
133
170
|
end
|
134
171
|
end
|
135
172
|
|
@@ -158,15 +195,6 @@ module Extensions
|
|
158
195
|
dest_xyz 0, page_height, nil, (page_num ? state.pages[page_num - 1] : page)
|
159
196
|
end
|
160
197
|
|
161
|
-
# Text
|
162
|
-
|
163
|
-
=begin
|
164
|
-
# Draws a disc bullet as float text
|
165
|
-
def draw_bullet
|
166
|
-
float { text '•' }
|
167
|
-
end
|
168
|
-
=end
|
169
|
-
|
170
198
|
# Fonts
|
171
199
|
|
172
200
|
# Registers a new custom font described in the data parameter
|
@@ -474,7 +502,7 @@ module Extensions
|
|
474
502
|
#
|
475
503
|
def span_page_width_if verdict
|
476
504
|
if verdict
|
477
|
-
indent
|
505
|
+
indent(-bounds_margin_left, -bounds_margin_right) do
|
478
506
|
yield
|
479
507
|
end
|
480
508
|
else
|
@@ -482,6 +510,20 @@ module Extensions
|
|
482
510
|
end
|
483
511
|
end
|
484
512
|
|
513
|
+
# A flowing version of the bounding_box. If the content runs to another page, the cursor starts
|
514
|
+
# at the top of the page instead of the original cursor position. Similar to span, except
|
515
|
+
# you can specify an absolute left position and pass additional options through to bounding_box.
|
516
|
+
#
|
517
|
+
def flow_bounding_box left = 0, opts = {}
|
518
|
+
original_y = self.y
|
519
|
+
canvas do
|
520
|
+
bounding_box [margin_box.absolute_left + left, margin_box.absolute_top], opts do
|
521
|
+
self.y = original_y
|
522
|
+
yield
|
523
|
+
end
|
524
|
+
end
|
525
|
+
end
|
526
|
+
|
485
527
|
# Graphics
|
486
528
|
|
487
529
|
# Fills the current bounding box with the specified fill color. Before
|
@@ -616,7 +658,12 @@ module Extensions
|
|
616
658
|
pdf_store.pages.data[:Kids].pop
|
617
659
|
pdf_store.pages.data[:Count] -= 1
|
618
660
|
state.pages.pop
|
619
|
-
|
661
|
+
if pg > 1
|
662
|
+
go_to_page pg - 1
|
663
|
+
else
|
664
|
+
@page_number = 0
|
665
|
+
state.page = nil
|
666
|
+
end
|
620
667
|
end
|
621
668
|
|
622
669
|
# Import the specified page into the current document.
|
@@ -743,10 +790,12 @@ module Extensions
|
|
743
790
|
scratch.font font_family, style: font_style, size: font_size do
|
744
791
|
scratch.instance_exec(&block)
|
745
792
|
end
|
793
|
+
# NOTE don't count excess if cursor exceeds writable area (due to padding)
|
794
|
+
partial_page_height = [effective_page_height, start_y - scratch.y].min
|
746
795
|
scratch.bounds.subtract_left_padding left_padding if left_padding > 0
|
747
796
|
scratch.bounds.subtract_right_padding right_padding if right_padding > 0
|
748
797
|
whole_pages = scratch.page_number - start_page_number
|
749
|
-
[(whole_pages * bounds.height +
|
798
|
+
[(whole_pages * bounds.height + partial_page_height), whole_pages, partial_page_height]
|
750
799
|
end
|
751
800
|
|
752
801
|
# Attempt to keep the objects generated in the block on the same page
|
@@ -783,7 +832,7 @@ module Extensions
|
|
783
832
|
=begin
|
784
833
|
def run_with_trial &block
|
785
834
|
available_space = cursor
|
786
|
-
whole_pages, remainder = dry_run(&block)
|
835
|
+
total_height, whole_pages, remainder = dry_run(&block)
|
787
836
|
if whole_pages > 0 || remainder > available_space
|
788
837
|
started_new_page = true
|
789
838
|
else
|
@@ -1,4 +1,6 @@
|
|
1
1
|
class Prawn::Font::AFM
|
2
|
+
undef_method :normalize_encoding
|
3
|
+
|
2
4
|
# Patch normalize_encoding method to handle conversion more gracefully.
|
3
5
|
#
|
4
6
|
# Any valid utf-8 characters that cannot be encoded to windows-1252 are
|
@@ -9,11 +11,10 @@ class Prawn::Font::AFM
|
|
9
11
|
rescue ::Encoding::UndefinedConversionError
|
10
12
|
warn 'The following text could not be fully converted to the Windows-1252 character set:'
|
11
13
|
warn %(#{text.gsub(/^/, '| ').rstrip})
|
12
|
-
|
13
|
-
text.encode 'windows-1252', undef: :replace, replace: "\u00ac"
|
14
|
+
text.encode 'windows-1252', undef: :replace, replace: %(\u00ac)
|
14
15
|
rescue ::Encoding::InvalidByteSequenceError
|
15
16
|
raise Prawn::Errors::IncompatibleStringEncoding,
|
16
|
-
%(Your document includes text
|
17
|
-
If you need full UTF-8 support, use TTF fonts instead of
|
17
|
+
%(Your document includes text which is not compatible with the Windows-1252 character set.
|
18
|
+
If you need full UTF-8 support, use TTF fonts instead of the built-in PDF (AFM) fonts.)
|
18
19
|
end
|
19
20
|
end
|
@@ -30,7 +30,7 @@ module Images
|
|
30
30
|
{ width: img_size.output_width, height: img_size.output_height }
|
31
31
|
else
|
32
32
|
# NOTE build_image_object caches image data previously loaded
|
33
|
-
_, img_size = build_image_object
|
33
|
+
_, img_size = ::File.open(path, 'rb') {|fd| build_image_object fd }
|
34
34
|
{ width: img_size.width, height: img_size.height }
|
35
35
|
end
|
36
36
|
end
|
@@ -62,7 +62,10 @@ class RomanNumeral
|
|
62
62
|
end
|
63
63
|
|
64
64
|
def to_r
|
65
|
-
|
65
|
+
if (int = @integer_value) < 1
|
66
|
+
return int.to_s
|
67
|
+
end
|
68
|
+
roman = RomanNumeral.int_to_roman int
|
66
69
|
@letter_case == :lower ? roman.downcase : roman
|
67
70
|
end
|
68
71
|
|
@@ -79,15 +82,19 @@ class RomanNumeral
|
|
79
82
|
self
|
80
83
|
end
|
81
84
|
|
85
|
+
def pred
|
86
|
+
RomanNumeral.new @integer_value - 1, @letter_case
|
87
|
+
end
|
88
|
+
|
82
89
|
def self.int_to_roman value
|
83
|
-
result =
|
90
|
+
result = []
|
84
91
|
BaseDigits.keys.reverse.each do |ival|
|
85
92
|
while value >= ival
|
86
93
|
value -= ival
|
87
|
-
result
|
94
|
+
result << BaseDigits[ival]
|
88
95
|
end
|
89
96
|
end
|
90
|
-
result
|
97
|
+
result.join
|
91
98
|
end
|
92
99
|
|
93
100
|
def self.roman_to_int value
|
@@ -5,7 +5,7 @@ module Formatters
|
|
5
5
|
class Prawn < Formatter
|
6
6
|
tag 'prawn'
|
7
7
|
|
8
|
-
|
8
|
+
LF = %(\n)
|
9
9
|
NoBreakSpace = %(\u00a0)
|
10
10
|
InnerIndent = %(\n )
|
11
11
|
GuardedIndent = %(\u00a0)
|
@@ -39,15 +39,15 @@ class Prawn < Formatter
|
|
39
39
|
fragments = []
|
40
40
|
fragments << (create_linenum_fragment linenum += 1)
|
41
41
|
tokens.each do |tok, val|
|
42
|
-
if val ==
|
43
|
-
fragments << { text:
|
42
|
+
if val == LF
|
43
|
+
fragments << { text: LF }
|
44
44
|
fragments << (create_linenum_fragment linenum += 1)
|
45
|
-
elsif val.include?
|
45
|
+
elsif val.include? LF
|
46
46
|
base_fragment = create_fragment tok, val
|
47
47
|
val.each_line do |line|
|
48
48
|
fragments << (base_fragment.merge text: line)
|
49
49
|
# NOTE append linenum fragment if there's a next line; only works if source doesn't have trailing endline
|
50
|
-
if line.end_with?
|
50
|
+
if line.end_with? LF
|
51
51
|
fragments << (create_linenum_fragment linenum += 1)
|
52
52
|
end
|
53
53
|
end
|
@@ -58,7 +58,7 @@ class Prawn < Formatter
|
|
58
58
|
# NOTE drop orphaned linenum fragment (due to trailing endline in source)
|
59
59
|
fragments.pop if (last_fragment = fragments[-1]) && last_fragment[:linenum]
|
60
60
|
# NOTE pad numbers that have less digits than the largest line number
|
61
|
-
if (linenum_w =
|
61
|
+
if (linenum_w = linenum.to_s.size) > 1
|
62
62
|
# NOTE extra column is the trailing space after the line number
|
63
63
|
linenum_w += 1
|
64
64
|
fragments.each do |fragment|
|
@@ -70,13 +70,13 @@ class Prawn < Formatter
|
|
70
70
|
start_of_line = true
|
71
71
|
tokens.map do |tok, val|
|
72
72
|
# match one or more consecutive endlines
|
73
|
-
if val ==
|
73
|
+
if val == LF || (val == (LF * val.length))
|
74
74
|
start_of_line = true
|
75
75
|
{ text: val }
|
76
76
|
else
|
77
77
|
val[0] = GuardedIndent if start_of_line && (val.start_with? ' ')
|
78
78
|
val.gsub! InnerIndent, GuardedInnerIndent if val.include? InnerIndent
|
79
|
-
start_of_line = val.end_with?
|
79
|
+
start_of_line = val.end_with? LF
|
80
80
|
# NOTE this optimization assumes we don't support/use background colors
|
81
81
|
val.rstrip.empty? ? { text: val } : (create_fragment tok, val)
|
82
82
|
end
|
@@ -85,7 +85,7 @@ class Prawn < Formatter
|
|
85
85
|
end
|
86
86
|
end
|
87
87
|
|
88
|
-
# TODO method could still be optimized (for instance, check if val is
|
88
|
+
# TODO method could still be optimized (for instance, check if val is LF or empty)
|
89
89
|
def create_fragment tok, val = nil
|
90
90
|
fragment = val ? { text: val } : {}
|
91
91
|
if (style_rules = @theme.style_for tok)
|