prawn-markup 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 17db8afa6a062ac1cac8322276b7f013e2d9ba7c
4
- data.tar.gz: 03a009820c6851a0d06ca2812487757e1a142056
2
+ SHA256:
3
+ metadata.gz: b195d6ff3dfeacfc8e8112f17323bfdc8981b955a994862d9609b07184dd229f
4
+ data.tar.gz: 33113b2d2db4aedae4eb7c412f65d7d2400d89f4dc94f30d9f4a700ea6598164
5
5
  SHA512:
6
- metadata.gz: b9d20fb86722b5ade3804c648116b84e3d423b39a3ffcdeadd2340b6b5d886e1ba80a98fa0a570bf1b448d2e0f1a88058781ccf5330cb6f9c218e7c8467da770
7
- data.tar.gz: 8fdce13e68ce84ccbace42d051ffc5d66f3888ad9094af6aa79abc62a0251e386088ccc81e627dc0a3be67ef746c5d6e82575af4455f14121cf50ec3d89a54f6
6
+ metadata.gz: 912de36400986c54d00f4ca94fa5e37207236e79152490370278f2c11895da5e75041b1bd528e6c179c11b145723a7ee1a4fdee8da05f384f4054d711a589117
7
+ data.tar.gz: 3f03640c1d82f6a46f2d5c74e9fcb8ff16287a0b83ad6a6e273f55ba03f2d4a716e0a549e7e6c9b64551062522e04ae2108678b048163fb21b5554a327c6b6fa
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- prawn-markup (0.1.0)
4
+ prawn-markup (0.2.0)
5
5
  nokogiri
6
6
  prawn
7
7
  prawn-table
@@ -14,63 +14,61 @@ GEM
14
14
  ast (2.4.0)
15
15
  byebug (10.0.2)
16
16
  diff-lcs (1.3)
17
- docile (1.3.1)
17
+ docile (1.3.2)
18
18
  hashery (2.1.2)
19
- jaro_winkler (1.5.1)
20
- json (2.1.0)
21
- mini_portile2 (2.3.0)
22
- nokogiri (1.8.4)
23
- mini_portile2 (~> 2.3.0)
24
- parallel (1.12.1)
25
- parser (2.5.1.2)
19
+ jaro_winkler (1.5.3)
20
+ json (2.2.0)
21
+ mini_portile2 (2.4.0)
22
+ nokogiri (1.9.1)
23
+ mini_portile2 (~> 2.4.0)
24
+ parallel (1.17.0)
25
+ parser (2.6.3.0)
26
26
  ast (~> 2.4.0)
27
27
  pdf-core (0.7.0)
28
28
  pdf-inspector (1.3.0)
29
29
  pdf-reader (>= 1.0, < 3.0.a)
30
- pdf-reader (2.1.0)
30
+ pdf-reader (2.2.0)
31
31
  Ascii85 (~> 1.0.0)
32
32
  afm (~> 0.2.1)
33
33
  hashery (~> 2.0)
34
34
  ruby-rc4
35
35
  ttfunk
36
- powerpack (0.1.2)
37
36
  prawn (2.2.2)
38
37
  pdf-core (~> 0.7.0)
39
38
  ttfunk (~> 1.5)
40
39
  prawn-table (0.2.2)
41
40
  prawn (>= 1.3.0, < 3.0.0)
42
41
  rainbow (3.0.0)
43
- rake (12.3.1)
42
+ rake (12.3.2)
44
43
  rspec (3.8.0)
45
44
  rspec-core (~> 3.8.0)
46
45
  rspec-expectations (~> 3.8.0)
47
46
  rspec-mocks (~> 3.8.0)
48
- rspec-core (3.8.0)
47
+ rspec-core (3.8.2)
49
48
  rspec-support (~> 3.8.0)
50
- rspec-expectations (3.8.1)
49
+ rspec-expectations (3.8.4)
51
50
  diff-lcs (>= 1.2.0, < 2.0)
52
51
  rspec-support (~> 3.8.0)
53
- rspec-mocks (3.8.0)
52
+ rspec-mocks (3.8.1)
54
53
  diff-lcs (>= 1.2.0, < 2.0)
55
54
  rspec-support (~> 3.8.0)
56
- rspec-support (3.8.0)
57
- rubocop (0.58.2)
55
+ rspec-support (3.8.2)
56
+ rubocop (0.68.1)
58
57
  jaro_winkler (~> 1.5.1)
59
58
  parallel (~> 1.10)
60
59
  parser (>= 2.5, != 2.5.1.1)
61
- powerpack (~> 0.1)
62
60
  rainbow (>= 2.2.2, < 4.0)
63
61
  ruby-progressbar (~> 1.7)
64
- unicode-display_width (~> 1.0, >= 1.0.1)
65
- ruby-progressbar (1.10.0)
62
+ unicode-display_width (>= 1.4.0, < 1.6)
63
+ ruby-progressbar (1.10.1)
66
64
  ruby-rc4 (0.1.5)
67
- simplecov (0.16.1)
65
+ simplecov (0.17.0)
68
66
  docile (~> 1.1)
69
67
  json (>= 1.8, < 3)
70
68
  simplecov-html (~> 0.10.0)
71
69
  simplecov-html (0.10.2)
72
70
  ttfunk (1.5.1)
73
- unicode-display_width (1.4.0)
71
+ unicode-display_width (1.5.0)
74
72
 
75
73
  PLATFORMS
76
74
  ruby
@@ -86,4 +84,4 @@ DEPENDENCIES
86
84
  simplecov
87
85
 
88
86
  BUNDLED WITH
89
- 1.16.2
87
+ 1.17.3
data/README.md CHANGED
@@ -74,15 +74,15 @@ A callable gets the URL of the IFrame as an argument. Defaults to ignore iframes
74
74
 
75
75
  This gem parses the given HTML and layouts the following elements in a vertical order:
76
76
 
77
- * Text content: `p`, `div`, `ol`, `ul`, `li`, `hr`
78
- * Text semantics: `b`, `strong`, `i`, `em`, `u`, `a`, `br`
77
+ * Text blocks: `p`, `div`, `ol`, `ul`, `li`, `hr`, `br`
78
+ * Text semantics: `a`, `b`, `strong`, `i`, `em`, `u`, `s`, `del`, `sub`, `sup`
79
79
  * Headings: `h1`, `h2`, `h3`, `h4`, `h5`, `h6`
80
80
  * Tables: `table`, `tr`, `td`, `th`
81
81
  * Media: `img`, `iframe`
82
82
 
83
83
  All other elements are ignored, their content is added to the parent element. With a few exceptions, no CSS is processed. One exception is the `width` property of `img`, `td` and `th`, which may contain values in `cm`, `mm`, `px`, `pt`, `%` or `auto`.
84
84
 
85
- If no explicit loader is given (see above), images are loaded from `http(s)` addresses are may be contained in the `src` attribute as base64 encoded data URIs. Prawn only supports `PNG` and `JPG`.
85
+ If no explicit loader is given (see above), images are loaded from `http(s)` addresses or may be contained in the `src` attribute as base64 encoded data URIs. Prawn only supports `PNG` and `JPG`.
86
86
 
87
87
 
88
88
  ## Development
@@ -170,6 +170,7 @@ module Prawn
170
170
  def distribute_remaing_width(count)
171
171
  equal_width = (total_width - column_width_sum) / count.to_f
172
172
  return if equal_width < 0
173
+
173
174
  column_widths.map! { |width| width || equal_width }
174
175
  end
175
176
 
@@ -21,12 +21,14 @@ module Prawn
21
21
  self.logger = defined?(Rails) ? Rails.logger : nil
22
22
 
23
23
  require 'prawn/markup/processor/text'
24
+ require 'prawn/markup/processor/blocks'
24
25
  require 'prawn/markup/processor/headings'
25
26
  require 'prawn/markup/processor/images'
26
27
  require 'prawn/markup/processor/tables'
27
28
  require 'prawn/markup/processor/lists'
28
29
 
29
30
  prepend Prawn::Markup::Processor::Text
31
+ prepend Prawn::Markup::Processor::Blocks
30
32
  prepend Prawn::Markup::Processor::Headings
31
33
  prepend Prawn::Markup::Processor::Images
32
34
  prepend Prawn::Markup::Processor::Tables
@@ -39,6 +41,7 @@ module Prawn
39
41
 
40
42
  def parse(html)
41
43
  return if html.to_s.strip.empty?
44
+
42
45
  reset
43
46
  html = Prawn::Markup::Normalizer.new(html).normalize
44
47
  Nokogiri::HTML::SAX::Parser.new(self).parse(html) { |ctx| ctx.recovery = true }
@@ -62,11 +65,11 @@ module Prawn
62
65
  end
63
66
 
64
67
  def error(string)
65
- logger.debug('SAX parsing error: ' + string) if logger
68
+ logger.info('SAX parsing error: ' + string.strip) if logger
66
69
  end
67
70
 
68
71
  def warning(string)
69
- logger.warn(string) if logger
72
+ logger.info('SAX parsing warning: ' + string.strip) if logger
70
73
  end
71
74
 
72
75
  private
@@ -0,0 +1,148 @@
1
+ module Prawn
2
+ module Markup
3
+ module Processor::Blocks
4
+ def self.prepended(base)
5
+ base.known_elements.push('p', 'br', 'div', 'hr')
6
+ end
7
+
8
+ def start_br
9
+ append_text("\n")
10
+ end
11
+
12
+ def start_p
13
+ handle_text_element
14
+ end
15
+
16
+ def end_p
17
+ if inside_container?
18
+ append_new_line
19
+ append_text("\n")
20
+ else
21
+ add_paragraph
22
+ end
23
+ end
24
+
25
+ def start_div
26
+ handle_text_element
27
+ end
28
+
29
+ def end_div
30
+ handle_text_element
31
+ end
32
+
33
+ def start_hr
34
+ return if inside_container?
35
+
36
+ put_bottom_margin(nil)
37
+ add_current_text
38
+ pdf.move_down(hr_vertical_margin_top)
39
+ pdf.stroke_horizontal_rule
40
+ pdf.move_down(hr_vertical_margin_bottom)
41
+ end
42
+
43
+ def end_document
44
+ add_current_text
45
+ end
46
+
47
+ private
48
+
49
+ def handle_text_element
50
+ if inside_container?
51
+ append_new_line
52
+ else
53
+ add_current_text
54
+ end
55
+ end
56
+
57
+ def append_new_line
58
+ append_text("\n") if buffered_text? && text_buffer[-1] != "\n"
59
+ end
60
+
61
+ def add_paragraph
62
+ text = dump_text
63
+ text.gsub!(/[^\n]/, '') if text.strip.empty?
64
+ unless text.empty?
65
+ add_bottom_margin
66
+ add_formatted_text(text, text_options)
67
+ put_bottom_margin(text_margin_bottom)
68
+ end
69
+ end
70
+
71
+ def add_current_text(options = text_options)
72
+ add_bottom_margin
73
+ return unless buffered_text?
74
+
75
+ string = dump_text
76
+ string.strip!
77
+ add_formatted_text(string, options)
78
+ end
79
+
80
+ def add_bottom_margin
81
+ if @bottom_margin
82
+ pdf.move_down(@bottom_margin)
83
+ @bottom_margin = nil
84
+ end
85
+ end
86
+
87
+ def add_formatted_text(string, options = text_options)
88
+ with_font(options) do
89
+ pdf.text(string, options)
90
+ end
91
+ end
92
+
93
+ def with_font(options)
94
+ pdf.font(options[:font] || pdf.font.family,
95
+ size: options[:size],
96
+ style: options[:style]) do
97
+ return yield
98
+ end
99
+ end
100
+
101
+ def hr_vertical_margin_top
102
+ @hr_vertical_margin_top ||=
103
+ (text_options[:size] || pdf.font_size) / 2.0
104
+ end
105
+
106
+ def hr_vertical_margin_bottom
107
+ @hr_vertical_margin_bottom ||= with_font(text_options) do
108
+ hr_vertical_margin_top +
109
+ pdf.font.descender +
110
+ text_leading -
111
+ pdf.line_width
112
+ end
113
+ end
114
+
115
+ def reset
116
+ super
117
+ text_margin_bottom # pre-calculate
118
+ end
119
+
120
+ def text_margin_bottom
121
+ options[:text] ||= {}
122
+ options[:text][:margin_bottom] ||= default_text_margin_bottom
123
+ end
124
+
125
+ def default_text_margin_bottom
126
+ with_font(text_options) do
127
+ pdf.font.line_gap +
128
+ pdf.font.descender +
129
+ text_leading
130
+ end
131
+ end
132
+
133
+ def text_leading
134
+ text_options[:leading] || pdf.default_leading
135
+ end
136
+
137
+ def text_options
138
+ @text_options ||= HashMerger.deep(default_text_options, options[:text] || {})
139
+ end
140
+
141
+ def default_text_options
142
+ {
143
+ inline_format: true
144
+ }
145
+ end
146
+ end
147
+ end
148
+ end
@@ -32,10 +32,14 @@ module Prawn
32
32
  alias end_ul end_list
33
33
 
34
34
  def start_li
35
+ return unless inside_container?
36
+
35
37
  current_list.items << Elements::Item.new
36
38
  end
37
39
 
38
40
  def end_li
41
+ return unless inside_container?
42
+
39
43
  add_cell_text_node(current_list_item)
40
44
  end
41
45
 
@@ -73,6 +73,7 @@ module Prawn
73
73
 
74
74
  def add_cell_text_node(cell, options = {})
75
75
  return unless buffered_text?
76
+
76
77
  cell.nodes << options.merge(content: dump_text.strip)
77
78
  end
78
79
 
@@ -2,41 +2,21 @@ module Prawn
2
2
  module Markup
3
3
  module Processor::Text
4
4
  def self.prepended(base)
5
- base.known_elements.push('p', 'br', 'div', 'b', 'strong', 'i', 'em', 'u', 'a', 'hr')
6
- end
7
-
8
- def start_br
9
- append_text("\n")
10
- end
11
-
12
- def start_p
13
- handle_text_element
14
- end
15
-
16
- def end_p
17
- if inside_container?
18
- append_new_line
19
- append_text("\n")
20
- else
21
- add_paragraph
22
- end
23
- end
24
-
25
- def start_div
26
- handle_text_element
27
- end
28
-
29
- def end_div
30
- handle_text_element
5
+ base.known_elements.push(
6
+ 'a', 'b', 'strong', 'i', 'em', 'u', 'strikethrough', 'strike', 's', 'del',
7
+ 'sub', 'sup'
8
+ )
31
9
  end
32
10
 
33
11
  def start_a
34
12
  append_text("<link href=\"#{current_attrs['href']}\">")
35
13
  end
14
+ alias start_link start_a
36
15
 
37
16
  def end_a
38
17
  append_text('</link>')
39
18
  end
19
+ alias end_link end_a
40
20
 
41
21
  def start_b
42
22
  append_text('<b>')
@@ -58,119 +38,44 @@ module Prawn
58
38
  end
59
39
  alias end_em end_i
60
40
 
61
- def start_hr
62
- return if inside_container?
63
-
64
- put_bottom_margin(nil)
65
- add_current_text
66
- pdf.move_down(hr_vertical_margin_top)
67
- pdf.stroke_horizontal_rule
68
- pdf.move_down(hr_vertical_margin_bottom)
69
- end
70
-
71
- def end_document
72
- add_current_text
73
- end
74
-
75
- private
76
-
77
- def handle_text_element
78
- if inside_container?
79
- append_new_line
80
- else
81
- add_current_text
82
- end
83
- end
84
-
85
- def append_new_line
86
- append_text("\n") if buffered_text? && text_buffer[-1] != "\n"
87
- end
88
-
89
- def add_paragraph
90
- text = dump_text
91
- text.gsub!(/[^\n]/, '') if text.strip.empty?
92
- unless text.empty?
93
- add_bottom_margin
94
- add_formatted_text(text, text_options)
95
- put_bottom_margin(text_margin_bottom)
96
- end
97
- end
98
-
99
- def add_current_text(options = text_options)
100
- add_bottom_margin
101
- return unless buffered_text?
102
-
103
- string = dump_text
104
- string.strip!
105
- add_formatted_text(string, options)
41
+ def start_u
42
+ append_text('<u>')
106
43
  end
107
44
 
108
- def add_bottom_margin
109
- if @bottom_margin
110
- pdf.move_down(@bottom_margin)
111
- @bottom_margin = nil
112
- end
45
+ def end_u
46
+ append_text('</u>')
113
47
  end
114
48
 
115
- def add_formatted_text(string, options = text_options)
116
- with_font(options) do
117
- pdf.text(string, options)
118
- end
49
+ def start_strikethrough
50
+ append_text('<strikethrough>')
119
51
  end
52
+ alias start_s start_strikethrough
53
+ alias start_strike start_strikethrough
54
+ alias start_del start_strikethrough
120
55
 
121
- def with_font(options)
122
- pdf.font(options[:font] || pdf.font.family,
123
- size: options[:size],
124
- style: options[:style]) do
125
- return yield
126
- end
56
+ def end_strikethrough
57
+ append_text('</strikethrough>')
127
58
  end
59
+ alias end_s end_strikethrough
60
+ alias end_strike end_strikethrough
61
+ alias end_del end_strikethrough
128
62
 
129
- def hr_vertical_margin_top
130
- @hr_vertical_margin_top ||=
131
- (text_options[:size] || pdf.font_size) / 2.0
63
+ def start_sub
64
+ append_text('<sub>')
132
65
  end
133
66
 
134
- def hr_vertical_margin_bottom
135
- @hr_vertical_margin_bottom ||= with_font(text_options) do
136
- hr_vertical_margin_top +
137
- pdf.font.descender +
138
- text_leading -
139
- pdf.line_width
140
- end
67
+ def end_sub
68
+ append_text('</sub>')
141
69
  end
142
70
 
143
- def reset
144
- super
145
- text_margin_bottom # pre-calculate
71
+ def start_sup
72
+ append_text('<sup>')
146
73
  end
147
74
 
148
- def text_margin_bottom
149
- options[:text] ||= {}
150
- options[:text][:margin_bottom] ||= default_text_margin_bottom
75
+ def end_sup
76
+ append_text('</sup>')
151
77
  end
152
78
 
153
- def default_text_margin_bottom
154
- with_font(text_options) do
155
- pdf.font.line_gap +
156
- pdf.font.descender +
157
- text_leading
158
- end
159
- end
160
-
161
- def text_leading
162
- text_options[:leading] || pdf.default_leading
163
- end
164
-
165
- def text_options
166
- @text_options ||= HashMerger.deep(default_text_options, options[:text] || {})
167
- end
168
-
169
- def default_text_options
170
- {
171
- inline_format: true
172
- }
173
- end
174
79
  end
175
80
  end
176
81
  end
@@ -22,7 +22,7 @@ module Prawn
22
22
  close_self_closing_elements
23
23
  normalize_spaces
24
24
  replace_html_entities
25
- "<root>#{html}</root>"
25
+ "<body>#{html}</body>"
26
26
  end
27
27
 
28
28
  private
@@ -43,6 +43,7 @@ module Prawn
43
43
  html.gsub!(/&#{entity};/, string)
44
44
  end
45
45
  end
46
+
46
47
  end
47
48
  end
48
49
  end
@@ -1,5 +1,5 @@
1
1
  module Prawn
2
2
  module Markup
3
- VERSION = '0.1.0'.freeze
3
+ VERSION = '0.2.0'.freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: prawn-markup
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pascal Zumkehr
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-09-10 00:00:00.000000000 Z
11
+ date: 2019-07-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -180,6 +180,7 @@ files:
180
180
  - lib/prawn/markup/elements/list.rb
181
181
  - lib/prawn/markup/interface.rb
182
182
  - lib/prawn/markup/processor.rb
183
+ - lib/prawn/markup/processor/blocks.rb
183
184
  - lib/prawn/markup/processor/headings.rb
184
185
  - lib/prawn/markup/processor/images.rb
185
186
  - lib/prawn/markup/processor/lists.rb
@@ -210,7 +211,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
210
211
  version: '0'
211
212
  requirements: []
212
213
  rubyforge_project:
213
- rubygems_version: 2.4.8
214
+ rubygems_version: 2.7.8
214
215
  signing_key:
215
216
  specification_version: 4
216
217
  summary: Parse simple HTML markup to include in Prawn PDFs