prawn-markup 0.1.0 → 0.2.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 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