prawn-html 0.1.4 → 0.4.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/README.md +51 -8
- data/lib/prawn-html.rb +170 -14
- data/lib/prawn_html/attributes.rb +71 -110
- data/lib/prawn_html/callbacks/highlight.rb +2 -4
- data/lib/prawn_html/callbacks/strike_through.rb +4 -4
- data/lib/prawn_html/context.rb +29 -12
- data/lib/prawn_html/document_renderer.rb +45 -50
- data/lib/prawn_html/html_parser.rb +95 -0
- data/lib/prawn_html/pdf_wrapper.rb +94 -0
- data/lib/prawn_html/tag.rb +86 -0
- data/lib/prawn_html/tags/a.rb +3 -5
- data/lib/prawn_html/tags/b.rb +3 -7
- data/lib/prawn_html/tags/blockquote.rb +25 -0
- data/lib/prawn_html/tags/body.rb +1 -3
- data/lib/prawn_html/tags/br.rb +3 -6
- data/lib/prawn_html/tags/del.rb +3 -7
- data/lib/prawn_html/tags/div.rb +1 -3
- data/lib/prawn_html/tags/h.rb +8 -10
- data/lib/prawn_html/tags/hr.rb +19 -9
- data/lib/prawn_html/tags/i.rb +3 -7
- data/lib/prawn_html/tags/img.rb +11 -13
- data/lib/prawn_html/tags/li.rb +8 -7
- data/lib/prawn_html/tags/mark.rb +3 -7
- data/lib/prawn_html/tags/ol.rb +26 -0
- data/lib/prawn_html/tags/p.rb +6 -8
- data/lib/prawn_html/tags/small.rb +1 -3
- data/lib/prawn_html/tags/span.rb +1 -3
- data/lib/prawn_html/tags/u.rb +3 -5
- data/lib/prawn_html/tags/ul.rb +3 -7
- data/lib/prawn_html/utils.rb +107 -0
- data/lib/prawn_html/version.rb +1 -1
- metadata +8 -4
- data/lib/prawn_html/html_handler.rb +0 -68
- data/lib/prawn_html/tags/base.rb +0 -54
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4dec0bd9a3746705bdaca34d49c8a8eff5700fd8a5feebc3b3452001cd239b0b
|
4
|
+
data.tar.gz: 74b5e31d3056560435ea939f50f713f11c44ad4c1f584873203b910754e1f782
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 814c481a5fce1da43dcb04254ed97f76f234fbdcaa6826070b00594f80cd3b4396c190a2972c0f6f72e00d35e5fd1b534cf22c9ef932b8ee308562de7c6bc854
|
7
|
+
data.tar.gz: f99ce1543d1b28689b19ceddd8e86a73fae8e204bc98270e6a422dd93e44d89ff50366969b67e0fb2a9a4e91d03367981ab5c0f9481b91378df57e2304358f40
|
data/README.md
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# Prawn HTML
|
2
|
-
[](https://
|
2
|
+
[](https://rubygems.org/gems/prawn-html)
|
3
3
|
[](https://github.com/blocknotes/prawn-html/actions/workflows/linters.yml)
|
4
4
|
[](https://github.com/blocknotes/prawn-html/actions/workflows/specs.yml)
|
5
5
|
|
@@ -8,9 +8,10 @@ HTML to PDF renderer using [Prawn PDF](https://github.com/prawnpdf/prawn).
|
|
8
8
|
Features:
|
9
9
|
- support a [good set](#supported-tags--attributes) of HTML tags and CSS properties;
|
10
10
|
- handle [document styles](#document-styles);
|
11
|
-
-
|
11
|
+
- custom [data attributes](#data-attributes) for Prawn PDF features;
|
12
|
+
- no extra settings: it just parses an input HTML and outputs to a Prawn PDF document.
|
12
13
|
|
13
|
-
**Notice**: render HTML documents properly is not an easy task, this gem support only some HTML tags and a small set of CSS attributes. If you need more rendering accuracy take a look at other projects like WickedPDF
|
14
|
+
**Notice**: render HTML documents properly is not an easy task, this gem support only some HTML tags and a small set of CSS attributes. If you need more rendering accuracy take a look at other projects like *WickedPDF* or *PDFKit*.
|
14
15
|
|
15
16
|
> [prawn-styled-text](https://github.com/blocknotes/prawn-styled-text) rewritten from scratch, finally!
|
16
17
|
|
@@ -38,6 +39,7 @@ HTML tags:
|
|
38
39
|
|
39
40
|
- **a**: link
|
40
41
|
- **b**: bold
|
42
|
+
- **blockquote**: block quotation element
|
41
43
|
- **br**: new line
|
42
44
|
- **del**: strike-through
|
43
45
|
- **div**: block element
|
@@ -49,38 +51,57 @@ HTML tags:
|
|
49
51
|
- **img**: image
|
50
52
|
- **li**: list item
|
51
53
|
- **mark**: highlight
|
54
|
+
- **ol**: ordered list
|
52
55
|
- **p**: block element
|
53
56
|
- **s**: strike-through
|
54
57
|
- **small**: smaller text
|
55
58
|
- **span**: inline element
|
56
59
|
- **strong**: bold
|
57
60
|
- **u**: underline
|
58
|
-
- **ul**: list
|
61
|
+
- **ul**: unordered list
|
59
62
|
|
60
63
|
CSS attributes (dimensional units are ignored and considered in pixel):
|
61
64
|
|
62
|
-
- **background**: for *mark* tag
|
63
|
-
- **
|
65
|
+
- **background**: for *mark* tag (3/6 hex digits or RGB or color name), ex. `style="background: #FECD08"`
|
66
|
+
- **break-after**: go to a new page after some elements, ex. `style="break-after: auto"`
|
67
|
+
- **break-before**: go to a new page before some elements, ex. `style="break-before: auto"`
|
68
|
+
- **color**: (3/6 hex digits or RGB or color name) ex. `style="color: #FB1"`
|
64
69
|
- **font-family**: font must be registered, quotes are optional, ex. `style="font-family: Courier"`
|
65
70
|
- **font-size**: ex. `style="font-size: 20px"`
|
66
71
|
- **font-style**: values: *:italic*, ex. `style="font-style: italic"`
|
67
72
|
- **font-weight**: values: *:bold*, ex. `style="font-weight: bold"`
|
68
73
|
- **height**: for *img* tag, ex. `<img src="image.jpg" style="height: 200px"/>`
|
69
74
|
- **href**: for *a* tag, ex. `<a href="http://www.google.com/">Google</a>`
|
75
|
+
- **left**: see *position (absolute)*
|
70
76
|
- **letter-spacing**: ex. `style="letter-spacing: 1.5"`
|
71
77
|
- **line-height**: ex. `style="line-height: 10px"`
|
78
|
+
- **list-style-type**: for *ul*, a string, ex. `style="list-style-type: '- '"`
|
72
79
|
- **margin-bottom**: ex. `style="margin-bottom: 10px"`
|
73
80
|
- **margin-left**: ex. `style="margin-left: 15px"`
|
74
81
|
- **margin-top**: ex. `style="margin-top: 20px"`
|
82
|
+
- **position**: `absolute`, ex. `style="position: absolute; left: 20px; top: 100px"`
|
75
83
|
- **src**: for *img* tag, ex. `<img src="image.jpg"/>`
|
76
84
|
- **text-align**: `left` | `center` | `right` | `justify`, ex. `style="text-align: center"`
|
77
85
|
- **text-decoration**: `underline`, ex. `style="text-decoration: underline"`
|
86
|
+
- **top**: see *position (absolute)*
|
78
87
|
- **width**: for *img* tag, support also percentage, ex. `<img src="image.jpg" style="width: 50%; height: 200px"/>`
|
79
88
|
|
89
|
+
For colors, the supported formats are:
|
90
|
+
- 3 hex digits, ex. `color: #FB1`;
|
91
|
+
- 6 hex digits, ex. `color: #abcdef`;
|
92
|
+
- RGB, ex. `color: RGB(64, 0, 128)`;
|
93
|
+
- color name, ex. `color: yellow`.
|
94
|
+
|
95
|
+
## Data attributes
|
96
|
+
|
97
|
+
Some custom data attributes are used to pass options:
|
98
|
+
|
99
|
+
- **dash**: for *hr* tag, accepts an integer or a list of integers), ex. `data-data="2, 4, 3"`
|
100
|
+
- **mode**: allow to specify the text mode (stroke|fill||fill_stroke), ex. `data-mode="stroke"`
|
101
|
+
|
80
102
|
## Document styles
|
81
103
|
|
82
|
-
|
83
|
-
Only single CSS selectors and basic ones are supported. Example:
|
104
|
+
You can define document CSS rules inside an _head_ tag. Example:
|
84
105
|
|
85
106
|
```html
|
86
107
|
<!DOCTYPE html>
|
@@ -105,6 +126,28 @@ Only single CSS selectors and basic ones are supported. Example:
|
|
105
126
|
</html>
|
106
127
|
```
|
107
128
|
|
129
|
+
## Additional notes
|
130
|
+
|
131
|
+
### Rails: generate PDF on the fly
|
132
|
+
|
133
|
+
Sample controller's action to create a PDF from Rails:
|
134
|
+
|
135
|
+
```rb
|
136
|
+
class SomeController < ApplicationController
|
137
|
+
def sample_action
|
138
|
+
respond_to do |format|
|
139
|
+
format.pdf do
|
140
|
+
pdf = Prawn::Document.new
|
141
|
+
PrawnHtml.append_html(pdf, '<h1 style="text-align: center">Just a test</h1>')
|
142
|
+
send_data(pdf.render, filename: 'sample.pdf', type: 'application/pdf')
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
```
|
148
|
+
|
149
|
+
More details in this blogpost: [generate PDF from HTML](https://www.blocknot.es/2021-08-20-rails-generate-pdf-from-html/)
|
150
|
+
|
108
151
|
## Do you like it? Star it!
|
109
152
|
|
110
153
|
If you use this component just star it. A developer is more motivated to improve a project when there is some interest.
|
data/lib/prawn-html.rb
CHANGED
@@ -1,24 +1,180 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'prawn'
|
4
|
-
|
5
|
-
require 'prawn_html/tags/base'
|
6
|
-
Dir["#{__dir__}/prawn_html/tags/*.rb"].sort.each { |f| require f }
|
7
|
-
|
8
|
-
Dir["#{__dir__}/prawn_html/callbacks/*.rb"].sort.each { |f| require f }
|
9
|
-
|
10
|
-
require 'prawn_html/attributes'
|
11
|
-
require 'prawn_html/context'
|
12
|
-
require 'prawn_html/document_renderer'
|
13
|
-
require 'prawn_html/html_handler'
|
14
|
-
|
15
3
|
module PrawnHtml
|
16
4
|
PX = 0.66 # conversion constant for pixel sixes
|
17
5
|
|
6
|
+
COLORS = {
|
7
|
+
'aliceblue' => 'f0f8ff',
|
8
|
+
'antiquewhite' => 'faebd7',
|
9
|
+
'aqua' => '00ffff',
|
10
|
+
'aquamarine' => '7fffd4',
|
11
|
+
'azure' => 'f0ffff',
|
12
|
+
'beige' => 'f5f5dc',
|
13
|
+
'bisque' => 'ffe4c4',
|
14
|
+
'black' => '000000',
|
15
|
+
'blanchedalmond' => 'ffebcd',
|
16
|
+
'blue' => '0000ff',
|
17
|
+
'blueviolet' => '8a2be2',
|
18
|
+
'brown' => 'a52a2a',
|
19
|
+
'burlywood' => 'deb887',
|
20
|
+
'cadetblue' => '5f9ea0',
|
21
|
+
'chartreuse' => '7fff00',
|
22
|
+
'chocolate' => 'd2691e',
|
23
|
+
'coral' => 'ff7f50',
|
24
|
+
'cornflowerblue' => '6495ed',
|
25
|
+
'cornsilk' => 'fff8dc',
|
26
|
+
'crimson' => 'dc143c',
|
27
|
+
'cyan' => '00ffff',
|
28
|
+
'darkblue' => '00008b',
|
29
|
+
'darkcyan' => '008b8b',
|
30
|
+
'darkgoldenrod' => 'b8860b',
|
31
|
+
'darkgray' => 'a9a9a9',
|
32
|
+
'darkgreen' => '006400',
|
33
|
+
'darkgrey' => 'a9a9a9',
|
34
|
+
'darkkhaki' => 'bdb76b',
|
35
|
+
'darkmagenta' => '8b008b',
|
36
|
+
'darkolivegreen' => '556b2f',
|
37
|
+
'darkorange' => 'ff8c00',
|
38
|
+
'darkorchid' => '9932cc',
|
39
|
+
'darkred' => '8b0000',
|
40
|
+
'darksalmon' => 'e9967a',
|
41
|
+
'darkseagreen' => '8fbc8f',
|
42
|
+
'darkslateblue' => '483d8b',
|
43
|
+
'darkslategray' => '2f4f4f',
|
44
|
+
'darkslategrey' => '2f4f4f',
|
45
|
+
'darkturquoise' => '00ced1',
|
46
|
+
'darkviolet' => '9400d3',
|
47
|
+
'deeppink' => 'ff1493',
|
48
|
+
'deepskyblue' => '00bfff',
|
49
|
+
'dimgray' => '696969',
|
50
|
+
'dimgrey' => '696969',
|
51
|
+
'dodgerblue' => '1e90ff',
|
52
|
+
'firebrick' => 'b22222',
|
53
|
+
'floralwhite' => 'fffaf0',
|
54
|
+
'forestgreen' => '228b22',
|
55
|
+
'fuchsia' => 'ff00ff',
|
56
|
+
'gainsboro' => 'dcdcdc',
|
57
|
+
'ghostwhite' => 'f8f8ff',
|
58
|
+
'gold' => 'ffd700',
|
59
|
+
'goldenrod' => 'daa520',
|
60
|
+
'gray' => '808080',
|
61
|
+
'green' => '008000',
|
62
|
+
'greenyellow' => 'adff2f',
|
63
|
+
'grey' => '808080',
|
64
|
+
'honeydew' => 'f0fff0',
|
65
|
+
'hotpink' => 'ff69b4',
|
66
|
+
'indianred' => 'cd5c5c',
|
67
|
+
'indigo' => '4b0082',
|
68
|
+
'ivory' => 'fffff0',
|
69
|
+
'khaki' => 'f0e68c',
|
70
|
+
'lavender' => 'e6e6fa',
|
71
|
+
'lavenderblush' => 'fff0f5',
|
72
|
+
'lawngreen' => '7cfc00',
|
73
|
+
'lemonchiffon' => 'fffacd',
|
74
|
+
'lightblue' => 'add8e6',
|
75
|
+
'lightcoral' => 'f08080',
|
76
|
+
'lightcyan' => 'e0ffff',
|
77
|
+
'lightgoldenrodyellow' => 'fafad2',
|
78
|
+
'lightgray' => 'd3d3d3',
|
79
|
+
'lightgreen' => '90ee90',
|
80
|
+
'lightgrey' => 'd3d3d3',
|
81
|
+
'lightpink' => 'ffb6c1',
|
82
|
+
'lightsalmon' => 'ffa07a',
|
83
|
+
'lightseagreen' => '20b2aa',
|
84
|
+
'lightskyblue' => '87cefa',
|
85
|
+
'lightslategray' => '778899',
|
86
|
+
'lightslategrey' => '778899',
|
87
|
+
'lightsteelblue' => 'b0c4de',
|
88
|
+
'lightyellow' => 'ffffe0',
|
89
|
+
'lime' => '00ff00',
|
90
|
+
'limegreen' => '32cd32',
|
91
|
+
'linen' => 'faf0e6',
|
92
|
+
'magenta' => 'ff00ff',
|
93
|
+
'maroon' => '800000',
|
94
|
+
'mediumaquamarine' => '66cdaa',
|
95
|
+
'mediumblue' => '0000cd',
|
96
|
+
'mediumorchid' => 'ba55d3',
|
97
|
+
'mediumpurple' => '9370db',
|
98
|
+
'mediumseagreen' => '3cb371',
|
99
|
+
'mediumslateblue' => '7b68ee',
|
100
|
+
'mediumspringgreen' => '00fa9a',
|
101
|
+
'mediumturquoise' => '48d1cc',
|
102
|
+
'mediumvioletred' => 'c71585',
|
103
|
+
'midnightblue' => '191970',
|
104
|
+
'mintcream' => 'f5fffa',
|
105
|
+
'mistyrose' => 'ffe4e1',
|
106
|
+
'moccasin' => 'ffe4b5',
|
107
|
+
'navajowhite' => 'ffdead',
|
108
|
+
'navy' => '000080',
|
109
|
+
'oldlace' => 'fdf5e6',
|
110
|
+
'olive' => '808000',
|
111
|
+
'olivedrab' => '6b8e23',
|
112
|
+
'orange' => 'ffa500',
|
113
|
+
'orangered' => 'ff4500',
|
114
|
+
'orchid' => 'da70d6',
|
115
|
+
'palegoldenrod' => 'eee8aa',
|
116
|
+
'palegreen' => '98fb98',
|
117
|
+
'paleturquoise' => 'afeeee',
|
118
|
+
'palevioletred' => 'db7093',
|
119
|
+
'papayawhip' => 'ffefd5',
|
120
|
+
'peachpuff' => 'ffdab9',
|
121
|
+
'peru' => 'cd853f',
|
122
|
+
'pink' => 'ffc0cb',
|
123
|
+
'plum' => 'dda0dd',
|
124
|
+
'powderblue' => 'b0e0e6',
|
125
|
+
'purple' => '800080',
|
126
|
+
'rebeccapurple' => '663399',
|
127
|
+
'red' => 'ff0000',
|
128
|
+
'rosybrown' => 'bc8f8f',
|
129
|
+
'royalblue' => '4169e1',
|
130
|
+
'saddlebrown' => '8b4513',
|
131
|
+
'salmon' => 'fa8072',
|
132
|
+
'sandybrown' => 'f4a460',
|
133
|
+
'seagreen' => '2e8b57',
|
134
|
+
'seashell' => 'fff5ee',
|
135
|
+
'sienna' => 'a0522d',
|
136
|
+
'silver' => 'c0c0c0',
|
137
|
+
'skyblue' => '87ceeb',
|
138
|
+
'slateblue' => '6a5acd',
|
139
|
+
'slategray' => '708090',
|
140
|
+
'slategrey' => '708090',
|
141
|
+
'snow' => 'fffafa',
|
142
|
+
'springgreen' => '00ff7f',
|
143
|
+
'steelblue' => '4682b4',
|
144
|
+
'tan' => 'd2b48c',
|
145
|
+
'teal' => '008080',
|
146
|
+
'thistle' => 'd8bfd8',
|
147
|
+
'tomato' => 'ff6347',
|
148
|
+
'turquoise' => '40e0d0',
|
149
|
+
'violet' => 'ee82ee',
|
150
|
+
'wheat' => 'f5deb3',
|
151
|
+
'white' => 'ffffff',
|
152
|
+
'whitesmoke' => 'f5f5f5',
|
153
|
+
'yellow' => 'ffff00',
|
154
|
+
'yellowgreen' => '9acd32'
|
155
|
+
}.freeze
|
156
|
+
|
18
157
|
def append_html(pdf, html)
|
19
|
-
|
20
|
-
|
158
|
+
pdf_wrapper = PdfWrapper.new(pdf)
|
159
|
+
renderer = DocumentRenderer.new(pdf_wrapper)
|
160
|
+
html_parser = PrawnHtml::HtmlParser.new(renderer)
|
161
|
+
html_parser.process(html)
|
21
162
|
end
|
22
163
|
|
23
164
|
module_function :append_html
|
24
165
|
end
|
166
|
+
|
167
|
+
require 'prawn'
|
168
|
+
|
169
|
+
require 'prawn_html/utils'
|
170
|
+
|
171
|
+
Dir["#{__dir__}/prawn_html/callbacks/*.rb"].sort.each { |f| require f }
|
172
|
+
|
173
|
+
require 'prawn_html/tag'
|
174
|
+
Dir["#{__dir__}/prawn_html/tags/*.rb"].sort.each { |f| require f }
|
175
|
+
|
176
|
+
require 'prawn_html/attributes'
|
177
|
+
require 'prawn_html/context'
|
178
|
+
require 'prawn_html/pdf_wrapper'
|
179
|
+
require 'prawn_html/document_renderer'
|
180
|
+
require 'prawn_html/html_parser'
|
@@ -3,124 +3,87 @@
|
|
3
3
|
require 'ostruct'
|
4
4
|
|
5
5
|
module PrawnHtml
|
6
|
-
class Attributes
|
7
|
-
attr_reader :
|
6
|
+
class Attributes < OpenStruct
|
7
|
+
attr_reader :styles
|
8
|
+
|
9
|
+
STYLES_APPLY = {
|
10
|
+
block: %i[align leading left margin_left padding_left position top],
|
11
|
+
tag_close: %i[margin_bottom padding_bottom break_after],
|
12
|
+
tag_open: %i[margin_top padding_top break_before],
|
13
|
+
text_node: %i[background callback character_spacing color font link list_style_type size styles]
|
14
|
+
}.freeze
|
8
15
|
|
9
16
|
STYLES_LIST = {
|
10
|
-
# styles
|
11
|
-
'background' => { key: :background, set: :convert_color
|
12
|
-
'
|
13
|
-
'
|
14
|
-
'font-
|
15
|
-
'font-
|
16
|
-
'font-
|
17
|
-
'
|
18
|
-
|
19
|
-
'
|
20
|
-
|
21
|
-
'
|
22
|
-
|
23
|
-
|
24
|
-
'
|
25
|
-
'
|
26
|
-
|
27
|
-
'
|
28
|
-
'
|
29
|
-
'
|
17
|
+
# text node styles
|
18
|
+
'background' => { key: :background, set: :convert_color },
|
19
|
+
'callback' => { key: :callback, set: :copy_value },
|
20
|
+
'color' => { key: :color, set: :convert_color },
|
21
|
+
'font-family' => { key: :font, set: :unquote },
|
22
|
+
'font-size' => { key: :size, set: :convert_size },
|
23
|
+
'font-style' => { key: :styles, set: :append_styles },
|
24
|
+
'font-weight' => { key: :styles, set: :append_styles },
|
25
|
+
'href' => { key: :link, set: :copy_value },
|
26
|
+
'letter-spacing' => { key: :character_spacing, set: :convert_float },
|
27
|
+
'list-style-type' => { key: :list_style_type, set: :unquote },
|
28
|
+
'text-decoration' => { key: :styles, set: :append_styles },
|
29
|
+
# tag opening styles
|
30
|
+
'break-before' => { key: :break_before, set: :convert_symbol },
|
31
|
+
'margin-top' => { key: :margin_top, set: :convert_size },
|
32
|
+
'padding-top' => { key: :padding_top, set: :convert_size },
|
33
|
+
# tag closing styles
|
34
|
+
'break-after' => { key: :break_after, set: :convert_symbol },
|
35
|
+
'margin-bottom' => { key: :margin_bottom, set: :convert_size },
|
36
|
+
'padding-bottom' => { key: :padding_bottom, set: :convert_size },
|
37
|
+
# block styles
|
38
|
+
'left' => { key: :left, set: :convert_size },
|
39
|
+
'line-height' => { key: :leading, set: :convert_size },
|
40
|
+
'margin-left' => { key: :margin_left, set: :convert_size },
|
41
|
+
'padding-left' => { key: :padding_left, set: :convert_size },
|
42
|
+
'position' => { key: :position, set: :convert_symbol },
|
43
|
+
'text-align' => { key: :align, set: :convert_symbol },
|
44
|
+
'top' => { key: :top, set: :convert_size }
|
30
45
|
}.freeze
|
31
46
|
|
32
47
|
STYLES_MERGE = %i[margin_left padding_left].freeze
|
33
48
|
|
34
49
|
# Init the Attributes
|
35
|
-
|
36
|
-
|
37
|
-
def initialize(attributes)
|
38
|
-
@hash = ::OpenStruct.new(attributes)
|
39
|
-
@options = {}
|
40
|
-
@post_styles = {}
|
41
|
-
@pre_styles = {}
|
50
|
+
def initialize(attributes = {})
|
51
|
+
super
|
42
52
|
@styles = {} # result styles
|
43
|
-
parsed_styles = Attributes.parse_styles(hash.style)
|
44
|
-
process_styles(parsed_styles)
|
45
53
|
end
|
46
54
|
|
47
|
-
# Processes the
|
55
|
+
# Processes the data attributes
|
48
56
|
#
|
49
|
-
# @
|
50
|
-
def
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
apply_rule(rule, value)
|
57
|
+
# @return [Hash] hash of data attributes with 'data-' prefix removed and stripped values
|
58
|
+
def data
|
59
|
+
to_h.each_with_object({}) do |(key, value), res|
|
60
|
+
data_key = key.match /\Adata-(.+)/
|
61
|
+
res[data_key[1]] = value.strip if data_key
|
56
62
|
end
|
57
63
|
end
|
58
64
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
val = value&.downcase || +''
|
67
|
-
val.gsub!(/[^a-f0-9]/, '')
|
68
|
-
return val unless val.size == 3
|
69
|
-
|
70
|
-
a, b, c = val.chars
|
71
|
-
a * 2 + b * 2 + c * 2
|
72
|
-
end
|
73
|
-
|
74
|
-
# Converts a decimal number string
|
75
|
-
#
|
76
|
-
# @param value [String] string decimal
|
77
|
-
#
|
78
|
-
# @return [Float] converted and rounded float number
|
79
|
-
def convert_float(value)
|
80
|
-
val = value&.gsub(/[^0-9.]/, '') || ''
|
81
|
-
val.to_f.round(4)
|
82
|
-
end
|
83
|
-
|
84
|
-
# Converts a size string
|
85
|
-
#
|
86
|
-
# @param value [String] size string
|
87
|
-
# @param container_size [Numeric] container size
|
88
|
-
#
|
89
|
-
# @return [Float] converted and rounded size
|
90
|
-
def convert_size(value, container_size = nil)
|
91
|
-
val = value&.gsub(/[^0-9.]/, '') || ''
|
92
|
-
val =
|
93
|
-
if container_size && value.include?('%')
|
94
|
-
val.to_f * container_size * 0.01
|
95
|
-
else
|
96
|
-
val.to_f * PX
|
97
|
-
end
|
98
|
-
# pdf.bounds.height
|
99
|
-
val.round(4)
|
100
|
-
end
|
101
|
-
|
102
|
-
# Converts a string to symbol
|
103
|
-
#
|
104
|
-
# @param value [String] string
|
105
|
-
#
|
106
|
-
# @return [Symbol] symbol
|
107
|
-
def convert_symbol(value)
|
108
|
-
value.to_sym if value && !value.match?(/\A\s*\Z/)
|
109
|
-
end
|
65
|
+
# Merge text styles
|
66
|
+
#
|
67
|
+
# @param text_styles [String] styles to parse and process
|
68
|
+
def merge_text_styles!(text_styles)
|
69
|
+
hash_styles = Attributes.parse_styles(text_styles)
|
70
|
+
process_styles(hash_styles) unless hash_styles.empty?
|
71
|
+
end
|
110
72
|
|
73
|
+
class << self
|
111
74
|
# Merges attributes
|
112
75
|
#
|
113
|
-
# @param
|
76
|
+
# @param attributes [Hash] target attributes hash
|
114
77
|
# @param key [Symbol] key
|
115
78
|
# @param value
|
116
79
|
#
|
117
80
|
# @return [Hash] the updated hash of attributes
|
118
|
-
def merge_attr!(
|
81
|
+
def merge_attr!(attributes, key, value)
|
119
82
|
return unless key
|
120
|
-
return (
|
83
|
+
return (attributes[key] = value) unless Attributes::STYLES_MERGE.include?(key)
|
121
84
|
|
122
|
-
|
123
|
-
|
85
|
+
attributes[key] ||= 0
|
86
|
+
attributes[key] += value
|
124
87
|
end
|
125
88
|
|
126
89
|
# Parses a string of styles
|
@@ -131,27 +94,25 @@ module PrawnHtml
|
|
131
94
|
def parse_styles(styles)
|
132
95
|
(styles || '').scan(/\s*([^:;]+)\s*:\s*([^;]+)\s*/).to_h
|
133
96
|
end
|
134
|
-
|
135
|
-
# Unquotes a string
|
136
|
-
#
|
137
|
-
# @param value [String] string
|
138
|
-
#
|
139
|
-
# @return [String] string without quotes at the beginning/ending
|
140
|
-
def unquote(value)
|
141
|
-
(value&.strip || +'').tap do |val|
|
142
|
-
val.gsub!(/\A['"]|["']\Z/, '')
|
143
|
-
end
|
144
|
-
end
|
145
97
|
end
|
146
98
|
|
147
99
|
private
|
148
100
|
|
149
|
-
def apply_rule(rule, value)
|
150
|
-
|
151
|
-
|
101
|
+
def apply_rule!(result, rule, value)
|
102
|
+
return unless rule
|
103
|
+
|
104
|
+
if rule[:set] == :append_styles
|
105
|
+
(result[rule[:key]] ||= []) << Utils.normalize_style(value)
|
152
106
|
else
|
153
|
-
|
107
|
+
result[rule[:key]] = Utils.send(rule[:set], value)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def process_styles(hash_styles)
|
112
|
+
hash_styles.each do |key, value|
|
113
|
+
apply_rule!(@styles, STYLES_LIST[key], value)
|
154
114
|
end
|
115
|
+
@styles
|
155
116
|
end
|
156
117
|
end
|
157
118
|
end
|