prawn-html 0.4.2 → 0.5.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/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
|