prawn-html 0.4.2 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/prawn-html.rb +1 -1
- data/lib/prawn_html/attributes.rb +33 -19
- data/lib/prawn_html/callbacks/{highlight.rb → background.rb} +3 -3
- data/lib/prawn_html/context.rb +21 -8
- data/lib/prawn_html/document_renderer.rb +40 -21
- data/lib/prawn_html/pdf_wrapper.rb +51 -4
- data/lib/prawn_html/tag.rb +14 -9
- data/lib/prawn_html/tags/a.rb +7 -1
- data/lib/prawn_html/tags/blockquote.rb +3 -3
- data/lib/prawn_html/tags/body.rb +4 -0
- data/lib/prawn_html/tags/br.rb +2 -2
- data/lib/prawn_html/tags/del.rb +1 -1
- data/lib/prawn_html/tags/h.rb +15 -15
- data/lib/prawn_html/tags/img.rb +5 -4
- data/lib/prawn_html/tags/li.rb +17 -2
- data/lib/prawn_html/tags/mark.rb +1 -1
- data/lib/prawn_html/tags/ol.rb +20 -3
- data/lib/prawn_html/tags/p.rb +2 -2
- data/lib/prawn_html/tags/ul.rb +23 -2
- data/lib/prawn_html/utils.rb +29 -11
- data/lib/prawn_html/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e82e0a464e39fd4c47c399cb043ceefe090524b29ead1c06795a484d4c648388
|
4
|
+
data.tar.gz: e124a7fb9800a434f42d403b478c6a6cb30b4e7d1e7e540d015028dec6daaa59
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c08e1252e2c9c8f1591840179549d3e14483d91361b1a9f56d96f23cfa30829b98d8d2ace33808a73a9467e1ff37054d7f462d1c7170db273a4ff83b203d807f
|
7
|
+
data.tar.gz: '0979bd9a66e463ee8e4ea3c141a2d4e2fcc0e3b1bc82397aeda2e357c10c4518b00b1e1e4fc3f2ec786070c6d229241423cd5933a89fbc9137bdccc211d22a44'
|
data/lib/prawn-html.rb
CHANGED
@@ -7,16 +7,15 @@ module PrawnHtml
|
|
7
7
|
attr_reader :styles
|
8
8
|
|
9
9
|
STYLES_APPLY = {
|
10
|
-
block: %i[align leading left margin_left padding_left position top],
|
10
|
+
block: %i[align bottom leading left margin_left padding_left position right top],
|
11
11
|
tag_close: %i[margin_bottom padding_bottom break_after],
|
12
12
|
tag_open: %i[margin_top padding_top break_before],
|
13
|
-
text_node: %i[
|
13
|
+
text_node: %i[callback character_spacing color font link list_style_type size styles white_space]
|
14
14
|
}.freeze
|
15
15
|
|
16
16
|
STYLES_LIST = {
|
17
17
|
# text node styles
|
18
|
-
'background' => { key: :
|
19
|
-
'callback' => { key: :callback, set: :copy_value },
|
18
|
+
'background' => { key: :callback, set: :callback_background },
|
20
19
|
'color' => { key: :color, set: :convert_color },
|
21
20
|
'font-family' => { key: :font, set: :unquote },
|
22
21
|
'font-size' => { key: :size, set: :convert_size },
|
@@ -25,7 +24,7 @@ module PrawnHtml
|
|
25
24
|
'href' => { key: :link, set: :copy_value },
|
26
25
|
'letter-spacing' => { key: :character_spacing, set: :convert_float },
|
27
26
|
'list-style-type' => { key: :list_style_type, set: :unquote },
|
28
|
-
'text-decoration' => { key: :styles, set: :
|
27
|
+
'text-decoration' => { key: :styles, set: :append_text_decoration },
|
29
28
|
'vertical-align' => { key: :styles, set: :append_styles },
|
30
29
|
'white-space' => { key: :white_space, set: :convert_symbol },
|
31
30
|
# tag opening styles
|
@@ -37,13 +36,15 @@ module PrawnHtml
|
|
37
36
|
'margin-bottom' => { key: :margin_bottom, set: :convert_size },
|
38
37
|
'padding-bottom' => { key: :padding_bottom, set: :convert_size },
|
39
38
|
# block styles
|
40
|
-
'
|
39
|
+
'bottom' => { key: :bottom, set: :convert_size, options: :height },
|
40
|
+
'left' => { key: :left, set: :convert_size, options: :width },
|
41
41
|
'line-height' => { key: :leading, set: :convert_size },
|
42
42
|
'margin-left' => { key: :margin_left, set: :convert_size },
|
43
43
|
'padding-left' => { key: :padding_left, set: :convert_size },
|
44
44
|
'position' => { key: :position, set: :convert_symbol },
|
45
|
+
'right' => { key: :right, set: :convert_size, options: :width },
|
45
46
|
'text-align' => { key: :align, set: :convert_symbol },
|
46
|
-
'top' => { key: :top, set: :convert_size }
|
47
|
+
'top' => { key: :top, set: :convert_size, options: :height }
|
47
48
|
}.freeze
|
48
49
|
|
49
50
|
STYLES_MERGE = %i[margin_left padding_left].freeze
|
@@ -67,9 +68,10 @@ module PrawnHtml
|
|
67
68
|
# Merge text styles
|
68
69
|
#
|
69
70
|
# @param text_styles [String] styles to parse and process
|
70
|
-
|
71
|
+
# @param options [Hash] options (container width/height/etc.)
|
72
|
+
def merge_text_styles!(text_styles, options: {})
|
71
73
|
hash_styles = Attributes.parse_styles(text_styles)
|
72
|
-
process_styles(hash_styles) unless hash_styles.empty?
|
74
|
+
process_styles(hash_styles, options: options) unless hash_styles.empty?
|
73
75
|
end
|
74
76
|
|
75
77
|
class << self
|
@@ -100,21 +102,33 @@ module PrawnHtml
|
|
100
102
|
|
101
103
|
private
|
102
104
|
|
103
|
-
def
|
104
|
-
|
105
|
+
def process_styles(hash_styles, options:)
|
106
|
+
hash_styles.each do |key, value|
|
107
|
+
rule = evaluate_rule(key, value)
|
108
|
+
apply_rule!(merged_styles: @styles, rule: rule, value: value, options: options)
|
109
|
+
end
|
110
|
+
@styles
|
111
|
+
end
|
105
112
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
113
|
+
def evaluate_rule(rule_key, attr_value)
|
114
|
+
rule = STYLES_LIST[rule_key]
|
115
|
+
if rule && rule[:set] == :append_text_decoration
|
116
|
+
return { key: :callback, set: :callback_strike_through } if attr_value == 'line-through'
|
117
|
+
|
118
|
+
return { key: :styles, set: :append_styles }
|
110
119
|
end
|
120
|
+
rule
|
111
121
|
end
|
112
122
|
|
113
|
-
def
|
114
|
-
|
115
|
-
|
123
|
+
def apply_rule!(merged_styles:, rule:, value:, options:)
|
124
|
+
return unless rule
|
125
|
+
|
126
|
+
if rule[:set] == :append_styles
|
127
|
+
(merged_styles[rule[:key]] ||= []) << Utils.normalize_style(value)
|
128
|
+
else
|
129
|
+
opts = rule[:options] ? options[rule[:options]] : nil
|
130
|
+
merged_styles[rule[:key]] = Utils.send(rule[:set], value, options: opts)
|
116
131
|
end
|
117
|
-
@styles
|
118
132
|
end
|
119
133
|
end
|
120
134
|
end
|
@@ -2,12 +2,12 @@
|
|
2
2
|
|
3
3
|
module PrawnHtml
|
4
4
|
module Callbacks
|
5
|
-
class
|
5
|
+
class Background
|
6
6
|
DEF_HIGHLIGHT = 'ffff00'
|
7
7
|
|
8
|
-
def initialize(pdf,
|
8
|
+
def initialize(pdf, color = nil)
|
9
9
|
@pdf = pdf
|
10
|
-
@color =
|
10
|
+
@color = color || DEF_HIGHLIGHT
|
11
11
|
end
|
12
12
|
|
13
13
|
def render_behind(fragment)
|
data/lib/prawn_html/context.rb
CHANGED
@@ -2,15 +2,17 @@
|
|
2
2
|
|
3
3
|
module PrawnHtml
|
4
4
|
class Context < Array
|
5
|
-
DEF_FONT_SIZE =
|
5
|
+
DEF_FONT_SIZE = 16 * PX
|
6
6
|
|
7
|
-
|
7
|
+
attr_reader :previous_tag
|
8
|
+
attr_accessor :last_text_node
|
8
9
|
|
9
10
|
# Init the Context
|
10
11
|
def initialize(*_args)
|
11
12
|
super
|
12
|
-
@last_margin = 0
|
13
13
|
@last_text_node = false
|
14
|
+
@merged_styles = nil
|
15
|
+
@previous_tag = nil
|
14
16
|
end
|
15
17
|
|
16
18
|
# Add an element to the context
|
@@ -25,6 +27,7 @@ module PrawnHtml
|
|
25
27
|
element.parent = last
|
26
28
|
push(element)
|
27
29
|
element.on_context_add(self) if element.respond_to?(:on_context_add)
|
30
|
+
@merged_styles = nil
|
28
31
|
self
|
29
32
|
end
|
30
33
|
|
@@ -49,11 +52,21 @@ module PrawnHtml
|
|
49
52
|
# Merge the context styles for text nodes
|
50
53
|
#
|
51
54
|
# @return [Hash] the hash of merged styles
|
52
|
-
def
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
55
|
+
def merged_styles
|
56
|
+
@merged_styles ||=
|
57
|
+
each_with_object(base_styles) do |element, res|
|
58
|
+
evaluate_element_styles(element, res)
|
59
|
+
element.update_styles(res) if element.respond_to?(:update_styles)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Remove the last element from the context
|
64
|
+
def remove_last
|
65
|
+
last.on_context_remove(self) if last.respond_to?(:on_context_remove)
|
66
|
+
@merged_styles = nil
|
67
|
+
@last_text_node = false
|
68
|
+
@previous_tag = last.tag
|
69
|
+
pop
|
57
70
|
end
|
58
71
|
|
59
72
|
private
|
@@ -11,6 +11,7 @@ module PrawnHtml
|
|
11
11
|
def initialize(pdf)
|
12
12
|
@buffer = []
|
13
13
|
@context = Context.new
|
14
|
+
@last_margin = 0
|
14
15
|
@pdf = pdf
|
15
16
|
end
|
16
17
|
|
@@ -20,8 +21,7 @@ module PrawnHtml
|
|
20
21
|
def on_tag_close(element)
|
21
22
|
render_if_needed(element)
|
22
23
|
apply_tag_close_styles(element)
|
23
|
-
context.
|
24
|
-
context.pop
|
24
|
+
context.remove_last
|
25
25
|
end
|
26
26
|
|
27
27
|
# On tag open callback
|
@@ -35,8 +35,9 @@ module PrawnHtml
|
|
35
35
|
tag_class = Tag.class_for(tag_name)
|
36
36
|
return unless tag_class
|
37
37
|
|
38
|
-
|
39
|
-
|
38
|
+
options = { width: pdf.page_width, height: pdf.page_height }
|
39
|
+
tag_class.new(tag_name, attributes: attributes, options: options).tap do |element|
|
40
|
+
setup_element(element, element_styles: element_styles)
|
40
41
|
end
|
41
42
|
end
|
42
43
|
|
@@ -48,7 +49,7 @@ module PrawnHtml
|
|
48
49
|
def on_text_node(content)
|
49
50
|
return if content.match?(/\A\s*\Z/)
|
50
51
|
|
51
|
-
buffer << context.
|
52
|
+
buffer << context.merged_styles.merge(text: prepare_text(content))
|
52
53
|
context.last_text_node = true
|
53
54
|
nil
|
54
55
|
end
|
@@ -59,19 +60,20 @@ module PrawnHtml
|
|
59
60
|
|
60
61
|
output_content(buffer.dup, context.block_styles)
|
61
62
|
buffer.clear
|
62
|
-
|
63
|
+
@last_margin = 0
|
63
64
|
end
|
64
65
|
|
65
66
|
alias_method :flush, :render
|
66
67
|
|
67
68
|
private
|
68
69
|
|
69
|
-
attr_reader :buffer, :context, :pdf
|
70
|
+
attr_reader :buffer, :context, :last_margin, :pdf
|
70
71
|
|
71
|
-
def setup_element(element)
|
72
|
+
def setup_element(element, element_styles:)
|
72
73
|
add_space_if_needed unless render_if_needed(element)
|
73
|
-
apply_tag_open_styles(element)
|
74
74
|
context.add(element)
|
75
|
+
element.process_styles(element_styles: element_styles)
|
76
|
+
apply_tag_open_styles(element)
|
75
77
|
element.custom_render(pdf, context) if element.respond_to?(:custom_render)
|
76
78
|
end
|
77
79
|
|
@@ -89,14 +91,14 @@ module PrawnHtml
|
|
89
91
|
|
90
92
|
def apply_tag_close_styles(element)
|
91
93
|
tag_styles = element.tag_close_styles
|
92
|
-
|
93
|
-
pdf.advance_cursor(
|
94
|
+
@last_margin = tag_styles[:margin_bottom].to_f
|
95
|
+
pdf.advance_cursor(last_margin + tag_styles[:padding_bottom].to_f)
|
94
96
|
pdf.start_new_page if tag_styles[:break_after]
|
95
97
|
end
|
96
98
|
|
97
99
|
def apply_tag_open_styles(element)
|
98
100
|
tag_styles = element.tag_open_styles
|
99
|
-
move_down = (tag_styles[:margin_top].to_f -
|
101
|
+
move_down = (tag_styles[:margin_top].to_f - last_margin) + tag_styles[:padding_top].to_f
|
100
102
|
pdf.advance_cursor(move_down) if move_down > 0
|
101
103
|
pdf.start_new_page if tag_styles[:break_before]
|
102
104
|
end
|
@@ -111,24 +113,41 @@ module PrawnHtml
|
|
111
113
|
def output_content(buffer, block_styles)
|
112
114
|
apply_callbacks(buffer)
|
113
115
|
left_indent = block_styles[:margin_left].to_f + block_styles[:padding_left].to_f
|
114
|
-
options = block_styles.slice(:align, :leading, :mode, :padding_left)
|
115
|
-
options[:
|
116
|
-
pdf.puts(buffer, options, bounding_box: bounds(block_styles))
|
116
|
+
options = block_styles.slice(:align, :indent_paragraphs, :leading, :mode, :padding_left)
|
117
|
+
options[:leading] = adjust_leading(buffer, options[:leading])
|
118
|
+
pdf.puts(buffer, options, bounding_box: bounds(buffer, options, block_styles), left_indent: left_indent)
|
117
119
|
end
|
118
120
|
|
119
121
|
def apply_callbacks(buffer)
|
120
122
|
buffer.select { |item| item[:callback] }.each do |item|
|
121
|
-
callback =
|
122
|
-
|
123
|
+
callback, arg = item[:callback]
|
124
|
+
callback_class = Tag::CALLBACKS[callback]
|
125
|
+
item[:callback] = callback_class.new(pdf, arg)
|
123
126
|
end
|
124
127
|
end
|
125
128
|
|
126
|
-
def
|
129
|
+
def adjust_leading(buffer, leading)
|
130
|
+
return leading if leading
|
131
|
+
|
132
|
+
(buffer.map { |item| item[:size] || Context::DEF_FONT_SIZE }.max * 0.055).round(4)
|
133
|
+
end
|
134
|
+
|
135
|
+
def bounds(buffer, options, block_styles)
|
127
136
|
return unless block_styles[:position] == :absolute
|
128
137
|
|
129
|
-
|
130
|
-
|
131
|
-
|
138
|
+
x = if block_styles.include?(:right)
|
139
|
+
x1 = pdf.calc_buffer_width(buffer) + block_styles[:right]
|
140
|
+
x1 < pdf.page_width ? (pdf.page_width - x1) : 0
|
141
|
+
else
|
142
|
+
block_styles[:left] || 0
|
143
|
+
end
|
144
|
+
y = if block_styles.include?(:bottom)
|
145
|
+
pdf.calc_buffer_height(buffer, options) + block_styles[:bottom]
|
146
|
+
else
|
147
|
+
pdf.page_height - (block_styles[:top] || 0)
|
148
|
+
end
|
149
|
+
|
150
|
+
[[x, y], { width: pdf.page_width - x }]
|
132
151
|
end
|
133
152
|
end
|
134
153
|
end
|
@@ -6,7 +6,7 @@ module PrawnHtml
|
|
6
6
|
class PdfWrapper
|
7
7
|
extend Forwardable
|
8
8
|
|
9
|
-
def_delegators :@pdf, :
|
9
|
+
def_delegators :@pdf, :start_new_page
|
10
10
|
|
11
11
|
# Wrapper for Prawn PDF Document
|
12
12
|
#
|
@@ -24,6 +24,46 @@ module PrawnHtml
|
|
24
24
|
pdf.move_down(move_down)
|
25
25
|
end
|
26
26
|
|
27
|
+
# Calculate the height of a buffer of items
|
28
|
+
#
|
29
|
+
# @param buffer [Array] Buffer of items
|
30
|
+
# @param options [Hash] Output options
|
31
|
+
#
|
32
|
+
# @return [Float] calculated height
|
33
|
+
def calc_buffer_height(buffer, options)
|
34
|
+
pdf.height_of_formatted(buffer, options)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Calculate the width of a buffer of items
|
38
|
+
#
|
39
|
+
# @param buffer [Array] Buffer of items
|
40
|
+
#
|
41
|
+
# @return [Float] calculated width
|
42
|
+
def calc_buffer_width(buffer)
|
43
|
+
width = 0
|
44
|
+
buffer.each do |item|
|
45
|
+
font_family = item[:font] || pdf.font.name
|
46
|
+
pdf.font(font_family, size: item[:size] || pdf.font_size) do
|
47
|
+
width += pdf.width_of(item[:text], inline_format: true)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
width
|
51
|
+
end
|
52
|
+
|
53
|
+
# Height of the page
|
54
|
+
#
|
55
|
+
# @return [Float] height
|
56
|
+
def page_height
|
57
|
+
pdf.bounds.height
|
58
|
+
end
|
59
|
+
|
60
|
+
# Width of the page
|
61
|
+
#
|
62
|
+
# @return [Float] width
|
63
|
+
def page_width
|
64
|
+
pdf.bounds.width
|
65
|
+
end
|
66
|
+
|
27
67
|
# Draw a rectangle
|
28
68
|
#
|
29
69
|
# @param x [Float] left position of the rectangle
|
@@ -66,12 +106,12 @@ module PrawnHtml
|
|
66
106
|
# @param buffer [Array] array of text items
|
67
107
|
# @param options [Hash] hash of options
|
68
108
|
# @param bounding_box [Array] bounding box arguments, if bounded
|
69
|
-
def puts(buffer, options, bounding_box: nil)
|
70
|
-
return
|
109
|
+
def puts(buffer, options, bounding_box: nil, left_indent: 0)
|
110
|
+
return output_buffer(buffer, options, left_indent: left_indent) unless bounding_box
|
71
111
|
|
72
112
|
current_y = pdf.cursor
|
73
113
|
pdf.bounding_box(*bounding_box) do
|
74
|
-
|
114
|
+
output_buffer(buffer, options, left_indent: left_indent)
|
75
115
|
end
|
76
116
|
pdf.move_cursor_to(current_y)
|
77
117
|
end
|
@@ -90,5 +130,12 @@ module PrawnHtml
|
|
90
130
|
private
|
91
131
|
|
92
132
|
attr_reader :pdf
|
133
|
+
|
134
|
+
def output_buffer(buffer, options, left_indent:)
|
135
|
+
formatted_text = proc { pdf.formatted_text(buffer, options) }
|
136
|
+
return formatted_text.call if left_indent == 0
|
137
|
+
|
138
|
+
pdf.indent(left_indent, 0, &formatted_text)
|
139
|
+
end
|
93
140
|
end
|
94
141
|
end
|
data/lib/prawn_html/tag.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
module PrawnHtml
|
4
4
|
class Tag
|
5
5
|
CALLBACKS = {
|
6
|
-
'
|
6
|
+
'Background' => Callbacks::Background,
|
7
7
|
'StrikeThrough' => Callbacks::StrikeThrough
|
8
8
|
}.freeze
|
9
9
|
TAG_CLASSES = %w[A B Blockquote Body Br Code Del Div H Hr I Img Li Mark Ol P Pre Small Span Sub Sup U Ul].freeze
|
@@ -15,11 +15,11 @@ module PrawnHtml
|
|
15
15
|
#
|
16
16
|
# @param tag [Symbol] tag name
|
17
17
|
# @param attributes [Hash] hash of element attributes
|
18
|
-
# @param
|
19
|
-
def initialize(tag, attributes: {},
|
18
|
+
# @param options [Hash] options (container width/height/etc.)
|
19
|
+
def initialize(tag, attributes: {}, options: {})
|
20
20
|
@tag = tag
|
21
|
+
@options = options
|
21
22
|
@attrs = Attributes.new(attributes)
|
22
|
-
process_styles(element_styles, attributes['style'])
|
23
23
|
end
|
24
24
|
|
25
25
|
# Is a block tag?
|
@@ -38,6 +38,15 @@ module PrawnHtml
|
|
38
38
|
block_styles
|
39
39
|
end
|
40
40
|
|
41
|
+
# Process tag styles
|
42
|
+
#
|
43
|
+
# @param element_styles [String] extra styles to apply to the element
|
44
|
+
def process_styles(element_styles: nil)
|
45
|
+
attrs.merge_text_styles!(tag_styles, options: options) if respond_to?(:tag_styles)
|
46
|
+
attrs.merge_text_styles!(element_styles, options: options) if element_styles
|
47
|
+
attrs.merge_text_styles!(attrs.style, options: options)
|
48
|
+
end
|
49
|
+
|
41
50
|
# Styles to apply on tag closing
|
42
51
|
#
|
43
52
|
# @return [Hash] hash of styles to apply
|
@@ -77,10 +86,6 @@ module PrawnHtml
|
|
77
86
|
|
78
87
|
private
|
79
88
|
|
80
|
-
|
81
|
-
attrs.merge_text_styles!(tag_styles) if respond_to?(:tag_styles)
|
82
|
-
attrs.merge_text_styles!(element_styles)
|
83
|
-
attrs.merge_text_styles!(inline_styles)
|
84
|
-
end
|
89
|
+
attr_reader :options
|
85
90
|
end
|
86
91
|
end
|
data/lib/prawn_html/tags/a.rb
CHANGED
data/lib/prawn_html/tags/body.rb
CHANGED
data/lib/prawn_html/tags/br.rb
CHANGED
@@ -5,14 +5,14 @@ module PrawnHtml
|
|
5
5
|
class Br < Tag
|
6
6
|
ELEMENTS = [:br].freeze
|
7
7
|
|
8
|
-
BR_SPACING = Utils.convert_size('
|
8
|
+
BR_SPACING = Utils.convert_size('17')
|
9
9
|
|
10
10
|
def block?
|
11
11
|
true
|
12
12
|
end
|
13
13
|
|
14
14
|
def custom_render(pdf, context)
|
15
|
-
return if context.last_text_node
|
15
|
+
return if context.last_text_node || context.previous_tag != :br
|
16
16
|
|
17
17
|
pdf.advance_cursor(BR_SPACING)
|
18
18
|
end
|
data/lib/prawn_html/tags/del.rb
CHANGED
data/lib/prawn_html/tags/h.rb
CHANGED
@@ -6,30 +6,30 @@ module PrawnHtml
|
|
6
6
|
ELEMENTS = [:h1, :h2, :h3, :h4, :h5, :h6].freeze
|
7
7
|
|
8
8
|
MARGINS_TOP = {
|
9
|
-
h1: 25
|
9
|
+
h1: 25,
|
10
10
|
h2: 20.5,
|
11
|
-
h3:
|
12
|
-
h4:
|
11
|
+
h3: 18,
|
12
|
+
h4: 21.2,
|
13
13
|
h5: 21.2,
|
14
|
-
h6:
|
14
|
+
h6: 22.8
|
15
15
|
}.freeze
|
16
16
|
|
17
17
|
MARGINS_BOTTOM = {
|
18
|
-
h1:
|
19
|
-
h2:
|
20
|
-
h3:
|
21
|
-
h4:
|
22
|
-
h5:
|
23
|
-
h6:
|
18
|
+
h1: 15.8,
|
19
|
+
h2: 15.8,
|
20
|
+
h3: 15.8,
|
21
|
+
h4: 20,
|
22
|
+
h5: 21.4,
|
23
|
+
h6: 24.8
|
24
24
|
}.freeze
|
25
25
|
|
26
26
|
SIZES = {
|
27
|
-
h1: 31,
|
28
|
-
h2:
|
29
|
-
h3: 18.
|
30
|
-
h4:
|
27
|
+
h1: 31.5,
|
28
|
+
h2: 24,
|
29
|
+
h3: 18.7,
|
30
|
+
h4: 15.7,
|
31
31
|
h5: 13,
|
32
|
-
h6: 10.
|
32
|
+
h6: 10.8
|
33
33
|
}.freeze
|
34
34
|
|
35
35
|
def block?
|
data/lib/prawn_html/tags/img.rb
CHANGED
@@ -12,16 +12,17 @@ module PrawnHtml
|
|
12
12
|
def custom_render(pdf, context)
|
13
13
|
parsed_styles = Attributes.parse_styles(attrs.style)
|
14
14
|
block_styles = context.block_styles
|
15
|
-
evaluated_styles =
|
15
|
+
evaluated_styles = adjust_styles(pdf, block_styles.merge(parsed_styles))
|
16
16
|
pdf.image(@attrs.src, evaluated_styles)
|
17
17
|
end
|
18
18
|
|
19
19
|
private
|
20
20
|
|
21
|
-
def
|
21
|
+
def adjust_styles(pdf, img_styles)
|
22
22
|
{}.tap do |result|
|
23
|
-
|
24
|
-
result[:
|
23
|
+
w, h = img_styles['width'], img_styles['height']
|
24
|
+
result[:width] = Utils.convert_size(w, options: pdf.page_width) if w
|
25
|
+
result[:height] = Utils.convert_size(h, options: pdf.page_height) if h
|
25
26
|
result[:position] = img_styles[:align] if %i[left center right].include?(img_styles[:align])
|
26
27
|
end
|
27
28
|
end
|
data/lib/prawn_html/tags/li.rb
CHANGED
@@ -5,6 +5,9 @@ module PrawnHtml
|
|
5
5
|
class Li < Tag
|
6
6
|
ELEMENTS = [:li].freeze
|
7
7
|
|
8
|
+
INDENT_OL = -12
|
9
|
+
INDENT_UL = -6
|
10
|
+
|
8
11
|
def block?
|
9
12
|
true
|
10
13
|
end
|
@@ -13,9 +16,21 @@ module PrawnHtml
|
|
13
16
|
@counter ? "#{@counter}. " : "#{@symbol} "
|
14
17
|
end
|
15
18
|
|
19
|
+
def block_styles
|
20
|
+
super.tap do |bs|
|
21
|
+
bs[:indent_paragraphs] = @indent
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
16
25
|
def on_context_add(_context)
|
17
|
-
|
18
|
-
|
26
|
+
case parent.class.to_s
|
27
|
+
when 'PrawnHtml::Tags::Ol'
|
28
|
+
@indent = INDENT_OL
|
29
|
+
@counter = (parent.counter += 1)
|
30
|
+
when 'PrawnHtml::Tags::Ul'
|
31
|
+
@indent = INDENT_UL
|
32
|
+
@symbol = parent.styles[:list_style_type] || '•'
|
33
|
+
end
|
19
34
|
end
|
20
35
|
end
|
21
36
|
end
|
data/lib/prawn_html/tags/mark.rb
CHANGED
data/lib/prawn_html/tags/ol.rb
CHANGED
@@ -5,21 +5,38 @@ module PrawnHtml
|
|
5
5
|
class Ol < Tag
|
6
6
|
ELEMENTS = [:ol].freeze
|
7
7
|
|
8
|
-
|
8
|
+
MARGIN_TOP = 15
|
9
|
+
MARGIN_LEFT = 40
|
10
|
+
MARGIN_BOTTOM = 15
|
9
11
|
|
10
12
|
attr_accessor :counter
|
11
13
|
|
12
|
-
def initialize(tag, attributes: {},
|
14
|
+
def initialize(tag, attributes: {}, options: {})
|
13
15
|
super
|
14
16
|
@counter = 0
|
17
|
+
@first_level = false
|
15
18
|
end
|
16
19
|
|
17
20
|
def block?
|
18
21
|
true
|
19
22
|
end
|
20
23
|
|
24
|
+
def on_context_add(context)
|
25
|
+
return if context.map(&:tag).count { |el| el == :ol } > 1
|
26
|
+
|
27
|
+
@first_level = true
|
28
|
+
end
|
29
|
+
|
21
30
|
def tag_styles
|
22
|
-
|
31
|
+
if @first_level
|
32
|
+
<<~STYLES
|
33
|
+
margin-top: #{MARGIN_TOP}px;
|
34
|
+
margin-left: #{MARGIN_LEFT}px;
|
35
|
+
margin-bottom: #{MARGIN_BOTTOM}px;
|
36
|
+
STYLES
|
37
|
+
else
|
38
|
+
"margin-left: #{MARGIN_LEFT}px"
|
39
|
+
end
|
23
40
|
end
|
24
41
|
end
|
25
42
|
end
|
data/lib/prawn_html/tags/p.rb
CHANGED
data/lib/prawn_html/tags/ul.rb
CHANGED
@@ -5,14 +5,35 @@ module PrawnHtml
|
|
5
5
|
class Ul < Tag
|
6
6
|
ELEMENTS = [:ul].freeze
|
7
7
|
|
8
|
-
|
8
|
+
MARGIN_TOP = 15
|
9
|
+
MARGIN_LEFT = 40
|
10
|
+
MARGIN_BOTTOM = 15
|
11
|
+
|
12
|
+
def initialize(tag, attributes: {}, options: {})
|
13
|
+
super
|
14
|
+
@first_level = false
|
15
|
+
end
|
9
16
|
|
10
17
|
def block?
|
11
18
|
true
|
12
19
|
end
|
13
20
|
|
21
|
+
def on_context_add(context)
|
22
|
+
return if context.map(&:tag).count { |el| el == :ul } > 1
|
23
|
+
|
24
|
+
@first_level = true
|
25
|
+
end
|
26
|
+
|
14
27
|
def tag_styles
|
15
|
-
|
28
|
+
if @first_level
|
29
|
+
<<~STYLES
|
30
|
+
margin-top: #{MARGIN_TOP}px;
|
31
|
+
margin-left: #{MARGIN_LEFT}px;
|
32
|
+
margin-bottom: #{MARGIN_BOTTOM}px;
|
33
|
+
STYLES
|
34
|
+
else
|
35
|
+
"margin-left: #{MARGIN_LEFT}px"
|
36
|
+
end
|
16
37
|
end
|
17
38
|
end
|
18
39
|
end
|
data/lib/prawn_html/utils.rb
CHANGED
@@ -10,6 +10,24 @@ module PrawnHtml
|
|
10
10
|
'underline' => :underline
|
11
11
|
}.freeze
|
12
12
|
|
13
|
+
# Setup a background callback
|
14
|
+
#
|
15
|
+
# @param value [String] HTML string color
|
16
|
+
#
|
17
|
+
# @return [Array] callback name and argument value
|
18
|
+
def callback_background(value, options: nil)
|
19
|
+
['Background', convert_color(value, options: options)]
|
20
|
+
end
|
21
|
+
|
22
|
+
# Setup a strike through callback
|
23
|
+
#
|
24
|
+
# @param value [String] unused
|
25
|
+
#
|
26
|
+
# @return [Array] callback name and argument value
|
27
|
+
def callback_strike_through(value, options: nil)
|
28
|
+
['StrikeThrough', nil]
|
29
|
+
end
|
30
|
+
|
13
31
|
# Converts a color string
|
14
32
|
#
|
15
33
|
# Supported formats:
|
@@ -21,7 +39,7 @@ module PrawnHtml
|
|
21
39
|
# @param value [String] HTML string color
|
22
40
|
#
|
23
41
|
# @return [String] adjusted string color or nil if value is invalid
|
24
|
-
def convert_color(value)
|
42
|
+
def convert_color(value, options: nil)
|
25
43
|
val = value.to_s.strip.downcase
|
26
44
|
return Regexp.last_match[1] if val.match /\A#([a-f0-9]{6})\Z/ # rubocop:disable Performance/RedundantMatch
|
27
45
|
|
@@ -42,7 +60,7 @@ module PrawnHtml
|
|
42
60
|
# @param value [String] string decimal
|
43
61
|
#
|
44
62
|
# @return [Float] converted and rounded float number
|
45
|
-
def convert_float(value)
|
63
|
+
def convert_float(value, options: nil)
|
46
64
|
val = value&.gsub(/[^0-9.]/, '') || ''
|
47
65
|
val.to_f.round(4)
|
48
66
|
end
|
@@ -50,14 +68,14 @@ module PrawnHtml
|
|
50
68
|
# Converts a size string
|
51
69
|
#
|
52
70
|
# @param value [String] size string
|
53
|
-
# @param
|
71
|
+
# @param options [Numeric] container size
|
54
72
|
#
|
55
73
|
# @return [Float] converted and rounded size
|
56
|
-
def convert_size(value,
|
74
|
+
def convert_size(value, options: nil)
|
57
75
|
val = value&.gsub(/[^0-9.]/, '') || ''
|
58
76
|
val =
|
59
|
-
if
|
60
|
-
val.to_f *
|
77
|
+
if options && value&.include?('%')
|
78
|
+
val.to_f * options * 0.01
|
61
79
|
else
|
62
80
|
val.to_f * PrawnHtml::PX
|
63
81
|
end
|
@@ -69,7 +87,7 @@ module PrawnHtml
|
|
69
87
|
# @param value [String] string
|
70
88
|
#
|
71
89
|
# @return [Symbol] symbol
|
72
|
-
def convert_symbol(value)
|
90
|
+
def convert_symbol(value, options: nil)
|
73
91
|
value.to_sym if value && !value.match?(/\A\s*\Z/)
|
74
92
|
end
|
75
93
|
|
@@ -78,7 +96,7 @@ module PrawnHtml
|
|
78
96
|
# @param value
|
79
97
|
#
|
80
98
|
# @return value
|
81
|
-
def copy_value(value)
|
99
|
+
def copy_value(value, options: nil)
|
82
100
|
value
|
83
101
|
end
|
84
102
|
|
@@ -97,13 +115,13 @@ module PrawnHtml
|
|
97
115
|
# @param value [String] string
|
98
116
|
#
|
99
117
|
# @return [String] string without quotes at the beginning/ending
|
100
|
-
def unquote(value)
|
118
|
+
def unquote(value, options: nil)
|
101
119
|
(value&.strip || +'').tap do |val|
|
102
120
|
val.gsub!(/\A['"]|["']\Z/, '')
|
103
121
|
end
|
104
122
|
end
|
105
123
|
|
106
|
-
module_function :
|
107
|
-
:unquote
|
124
|
+
module_function :callback_background, :callback_strike_through, :convert_color, :convert_float, :convert_size,
|
125
|
+
:convert_symbol, :copy_value, :normalize_style, :unquote
|
108
126
|
end
|
109
127
|
end
|
data/lib/prawn_html/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: prawn-html
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mattia Roccoberton
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-09-
|
11
|
+
date: 2021-09-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: oga
|
@@ -48,7 +48,7 @@ files:
|
|
48
48
|
- README.md
|
49
49
|
- lib/prawn-html.rb
|
50
50
|
- lib/prawn_html/attributes.rb
|
51
|
-
- lib/prawn_html/callbacks/
|
51
|
+
- lib/prawn_html/callbacks/background.rb
|
52
52
|
- lib/prawn_html/callbacks/strike_through.rb
|
53
53
|
- lib/prawn_html/context.rb
|
54
54
|
- lib/prawn_html/document_renderer.rb
|