prawn-styled-text 0.1.4 → 0.1.5
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 +5 -5
- data/Gemfile +2 -0
- data/README.md +40 -40
- data/examples/basic.rb +6 -2
- data/examples/columns.rb +9 -5
- data/examples/erb.rb +7 -3
- data/examples/grid.rb +12 -8
- data/examples/slim.rb +7 -3
- data/examples/test.html +12 -0
- data/lib/prawn-styled-text.rb +2 -0
- data/lib/prawn-styled-text/callbacks.rb +10 -8
- data/lib/prawn-styled-text/prawn-document.rb +27 -24
- data/lib/prawn-styled-text/prawn-styled-text.rb +33 -26
- data/lib/prawn-styled-text/version.rb +3 -1
- data/prawn-styled-text.gemspec +6 -2
- metadata +23 -10
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: c4d9cebb86cc3f9c771ea5b309c8905cc28851eb0b3d5def9290c06050424208
|
|
4
|
+
data.tar.gz: a9a601e1bf00a37dcd3f5bb93d79ec09191cd91fcf1eafd664de456b3903ae92
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e7ee55a9586cc519144be5576caab20f30348461dc0ff32deb15eff03a004a5d35ec13f94ab02544a54da4496e22131b81440842ca84e0c289ace2e594690e12
|
|
7
|
+
data.tar.gz: 12ad62b6582c0611c3be916fe56853c83d227d37a7769ea5ffa63e0014fc35a834c5d22037bbfc8718ed038ff7b1ba9c9069b78e8bfc708b3c012d6f5e3fdd04
|
data/Gemfile
CHANGED
data/README.md
CHANGED
|
@@ -20,50 +20,50 @@ For more examples see this [folder](https://github.com/blocknotes/prawn-styled-t
|
|
|
20
20
|
## Supported tags & attributes
|
|
21
21
|
|
|
22
22
|
HTML tags:
|
|
23
|
-
- a
|
|
24
|
-
- b
|
|
25
|
-
- br
|
|
26
|
-
- del
|
|
27
|
-
- div
|
|
28
|
-
- em
|
|
29
|
-
- h1 - h6
|
|
30
|
-
- hr
|
|
31
|
-
- i
|
|
32
|
-
- ins
|
|
33
|
-
- img
|
|
34
|
-
- li
|
|
35
|
-
- mark
|
|
36
|
-
- p
|
|
37
|
-
- s
|
|
38
|
-
- small
|
|
39
|
-
- span
|
|
40
|
-
- strong
|
|
41
|
-
- u
|
|
42
|
-
- ul
|
|
23
|
+
- **a**: link
|
|
24
|
+
- **b**: bold
|
|
25
|
+
- **br**: new line
|
|
26
|
+
- **del**: strike-through
|
|
27
|
+
- **div**: block element
|
|
28
|
+
- **em**: italic
|
|
29
|
+
- **h1** - **h6**: headings
|
|
30
|
+
- **hr**: horizontal line
|
|
31
|
+
- **i**: italic
|
|
32
|
+
- **ins**: underline
|
|
33
|
+
- **img**: image
|
|
34
|
+
- **li**: list item
|
|
35
|
+
- **mark**: highlight
|
|
36
|
+
- **p**: block element
|
|
37
|
+
- **s**: strike-through
|
|
38
|
+
- **small**: smaller text
|
|
39
|
+
- **span**: inline element
|
|
40
|
+
- **strong**: bold
|
|
41
|
+
- **u**: underline
|
|
42
|
+
- **ul**: list
|
|
43
43
|
|
|
44
44
|
CSS attributes:
|
|
45
|
-
- background
|
|
46
|
-
- color
|
|
47
|
-
- font-family
|
|
48
|
-
- font-size
|
|
49
|
-
- font-style
|
|
50
|
-
- height
|
|
51
|
-
- href
|
|
52
|
-
- letter-spacing
|
|
53
|
-
- line-height
|
|
54
|
-
- margin-left
|
|
55
|
-
- margin-top
|
|
56
|
-
- src
|
|
57
|
-
- text-align
|
|
58
|
-
- width
|
|
45
|
+
- **background**: for *mark* tag, only 6 hex digits format, # is ignored - ex. `style="background: #FFCC00"`
|
|
46
|
+
- **color**: only 6 hex digits format, # is ignored - ex. `style="color: #FFBB11"`
|
|
47
|
+
- **font-family**: font must be registered, quotes are optional, ex. `style="font: Courier"`
|
|
48
|
+
- **font-size**: units are ignored - ex. `style="font-size: 20px"`
|
|
49
|
+
- **font-style**: values: *:bold*, *:bold_italic*, *:italic*, *:normal*; string or comma separated strings - ex. `style="font-style: bold, italic"`
|
|
50
|
+
- **height**: for *img* tag, ex. `<img src="test.jpg" style="width: 50%; height: 200"/>`
|
|
51
|
+
- **href**: for *a* tag, ex. `<a href="http://www.google.com/">Google</a>`
|
|
52
|
+
- **letter-spacing**: ex. `style="letter-spacing: 1.5"`
|
|
53
|
+
- **line-height**: heading, units are ignored - ex. `style="line-height: 10"`
|
|
54
|
+
- **margin-left**: units are ignored - ex. `style="margin-left: 15"`
|
|
55
|
+
- **margin-top**: units are ignored - ex. `style="margin-top: 20"`
|
|
56
|
+
- **src**: for *img* tag, ex. `<img src="test.jpg"/>`
|
|
57
|
+
- **text-align**: ex. `style="text-align: center"`
|
|
58
|
+
- **width**: for *img* tag, ex. `<img src="test.jpg" style="width: 50%; height: 200"/>`
|
|
59
59
|
|
|
60
60
|
Olther attributes:
|
|
61
|
-
- dash
|
|
62
|
-
- image-at
|
|
63
|
-
- image-position
|
|
64
|
-
- image-scale
|
|
65
|
-
- list-symbol
|
|
66
|
-
- mode
|
|
61
|
+
- **dash**: for *hr* tag, dash types, integer or comma separated integers, ex. `<hr style="dash: 4"/>`
|
|
62
|
+
- **image-at**: for *img* tag, origin (0, 0) is left bottom, ex. `<img src="image.jpg" style="image-at: 100, 600" />`
|
|
63
|
+
- **image-position**: for *img* tag, ex. `<img src="image.jpg" style="image-position: center" />`
|
|
64
|
+
- **image-scale**: for *img* tag, ex. `<img src="image.jpg" style="image-scale: 0.3" />`
|
|
65
|
+
- **list-symbol**: for *ul* tag, ex. `<ul style="list-symbol: -">`
|
|
66
|
+
- **mode**: text mode, values: *:clip*, *:fill*, *:fill_clip*, *:fill_stroke*, *:fill_stroke_clip*, *:invisible*, *:stroke*, *:stroke_clip*, ex. `<h3 style="mode: stroke">Stroke text</h3>`
|
|
67
67
|
|
|
68
68
|
See [Prawn documentation](https://github.com/prawnpdf/prawn-table#documentation) for PDF options details.
|
|
69
69
|
|
data/examples/basic.rb
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
$LOAD_PATH << '../lib'
|
|
4
|
+
|
|
1
5
|
require 'prawn'
|
|
2
6
|
require 'prawn-styled-text'
|
|
3
7
|
require 'oga'
|
|
@@ -5,5 +9,5 @@ require 'oga'
|
|
|
5
9
|
Prawn::Font::AFM.hide_m17n_warning = true
|
|
6
10
|
|
|
7
11
|
pdf = Prawn::Document.new
|
|
8
|
-
pdf.styled_text
|
|
9
|
-
pdf.render_file
|
|
12
|
+
pdf.styled_text(File.read('test.html'))
|
|
13
|
+
pdf.render_file('basic.pdf')
|
data/examples/columns.rb
CHANGED
|
@@ -1,16 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
$LOAD_PATH << '../lib'
|
|
4
|
+
|
|
1
5
|
require 'prawn'
|
|
2
6
|
require 'prawn-styled-text'
|
|
3
7
|
require 'oga'
|
|
4
8
|
|
|
5
|
-
html = <<~
|
|
9
|
+
html = <<~CONTENT
|
|
6
10
|
<div style="font-size: 16px; text-align: justify">Lorem ipsum dolor sit <b>amet</b>, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud <i>exercitation</i> ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in <u>reprehenderit</u> in voluptate velit esse cillum dolore eu fugiat nulla pariatur.<br/>Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
|
7
11
|
<br/>
|
|
8
12
|
</div>
|
|
9
|
-
|
|
13
|
+
CONTENT
|
|
10
14
|
|
|
11
15
|
pdf = Prawn::Document.new
|
|
12
16
|
pdf.styled_text '<h1 style="text-align: center">2 columns</h1>'
|
|
13
|
-
pdf.column_box(
|
|
14
|
-
pdf.styled_text
|
|
17
|
+
pdf.column_box([0, pdf.cursor], columns: 2, width: pdf.bounds.width) do
|
|
18
|
+
pdf.styled_text(html * 4)
|
|
15
19
|
end
|
|
16
|
-
pdf.render_file
|
|
20
|
+
pdf.render_file('columns.pdf')
|
data/examples/erb.rb
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
$LOAD_PATH << '../lib'
|
|
4
|
+
|
|
1
5
|
require 'erb'
|
|
2
6
|
require 'prawn'
|
|
3
7
|
require 'prawn-styled-text'
|
|
@@ -8,6 +12,6 @@ ERB_FILE = 'test.html.erb'
|
|
|
8
12
|
Prawn::Font::AFM.hide_m17n_warning = true
|
|
9
13
|
|
|
10
14
|
pdf = Prawn::Document.new
|
|
11
|
-
pdf.text
|
|
12
|
-
pdf.styled_text ERB.new(
|
|
13
|
-
pdf.render_file
|
|
15
|
+
pdf.text("\nA test document\n", align: :center, size: 18)
|
|
16
|
+
pdf.styled_text ERB.new(File.read(ERB_FILE)).result(binding)
|
|
17
|
+
pdf.render_file('erb.pdf')
|
data/examples/grid.rb
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
$LOAD_PATH << '../lib'
|
|
4
|
+
|
|
1
5
|
require 'prawn'
|
|
2
6
|
require 'prawn-styled-text'
|
|
3
7
|
require 'oga'
|
|
4
8
|
|
|
5
|
-
html = <<~
|
|
9
|
+
html = <<~CONTENT
|
|
6
10
|
<h4 style="text-align: center">Some text</h4>
|
|
7
11
|
<div style="font-size: 10px; text-align: justify">Lorem ipsum dolor sit <b>amet</b>, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud <i>exercitation</i> ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in <u>reprehenderit</u> in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</div>
|
|
8
|
-
|
|
12
|
+
CONTENT
|
|
9
13
|
|
|
10
|
-
# html = <<~
|
|
14
|
+
# html = <<~CONTENT
|
|
11
15
|
# <span>span 1</span>
|
|
12
16
|
# <div>div 1</div>
|
|
13
17
|
# <span>span 2</span>
|
|
@@ -16,11 +20,11 @@ EOL
|
|
|
16
20
|
# <span>span 4</span>
|
|
17
21
|
# <div>div 3</div>
|
|
18
22
|
# <div>div 4</div>
|
|
19
|
-
#
|
|
23
|
+
# CONTENT
|
|
20
24
|
|
|
21
25
|
pdf = Prawn::Document.new
|
|
22
|
-
pdf.define_grid(:
|
|
23
|
-
pdf.grid(
|
|
24
|
-
pdf.styled_text
|
|
26
|
+
pdf.define_grid(columns: 3, rows: 3, gutter: 10)
|
|
27
|
+
pdf.grid(1, 1).bounding_box do
|
|
28
|
+
pdf.styled_text(html)
|
|
25
29
|
end
|
|
26
|
-
pdf.render_file
|
|
30
|
+
pdf.render_file('grid.pdf')
|
data/examples/slim.rb
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
$LOAD_PATH << '../lib'
|
|
4
|
+
|
|
1
5
|
require 'prawn'
|
|
2
6
|
require 'prawn-styled-text'
|
|
3
7
|
require 'oga'
|
|
@@ -8,7 +12,7 @@ SLIM_FILE = 'test.html.slim'
|
|
|
8
12
|
Prawn::Font::AFM.hide_m17n_warning = true
|
|
9
13
|
|
|
10
14
|
pdf = Prawn::Document.new
|
|
11
|
-
pdf.text
|
|
15
|
+
pdf.text("\nA test document\n", align: :center, size: 18)
|
|
12
16
|
# Slim::Template.new{ 'h1 A test document' }.render
|
|
13
|
-
pdf.styled_text
|
|
14
|
-
pdf.render_file
|
|
17
|
+
pdf.styled_text(Slim::Template.new(SLIM_FILE).render)
|
|
18
|
+
pdf.render_file('slim.pdf')
|
data/examples/test.html
CHANGED
|
@@ -36,6 +36,18 @@ Some HTML entities: € × ÷ ½ « » ©
|
|
|
36
36
|
<br/>
|
|
37
37
|
|
|
38
38
|
A span with a color: <span style="color: #4488CC">this is <span style="color: #ff0000; font-family: 'Courier'; font-size: 20px">courier red 20</span>, this is <span style="color: #008800; font-style: bold, italic">green bold italic</span>, this is <span style="letter-spacing: 2">character spacing 2</span>, this is <a href="http://www.google.com">a Google link</a></span>
|
|
39
|
+
|
|
40
|
+
<br/>
|
|
41
|
+
Line1<br/>Line2<br/>Line3
|
|
42
|
+
<br />
|
|
43
|
+
Word1
|
|
44
|
+
Word2
|
|
45
|
+
|
|
46
|
+
Word3
|
|
47
|
+
<br/>
|
|
48
|
+
<br/>
|
|
49
|
+
Line4
|
|
50
|
+
|
|
39
51
|
<h3 style="mode: stroke">Stroke mode</h3>
|
|
40
52
|
<div style="font-size: 14px; line-height: 12px; text-align: justify">line-height test... Lorem ipsum dolor sit amet, consectetur <small>adipisicing</small> elit, sed do eiusmod <em>tempor</em> incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure <strong>dolor</strong> in reprehenderit in voluptate velit.</div>
|
|
41
53
|
<hr/>
|
data/lib/prawn-styled-text.rb
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module PrawnStyledText
|
|
2
4
|
class HighlightCallback
|
|
3
|
-
def initialize(
|
|
5
|
+
def initialize(pdf)
|
|
4
6
|
@document = pdf
|
|
5
7
|
end
|
|
6
8
|
|
|
7
|
-
def set_color(
|
|
8
|
-
@color = color
|
|
9
|
+
def set_color(color) # rubocop:disable Naming/AccessorMethodName
|
|
10
|
+
@color = color || DEF_BG_MARK
|
|
9
11
|
end
|
|
10
12
|
|
|
11
|
-
def render_behind(
|
|
13
|
+
def render_behind(fragment)
|
|
12
14
|
original_color = @document.fill_color
|
|
13
15
|
@document.fill_color = @color
|
|
14
16
|
@document.fill_rectangle(fragment.top_left, fragment.width, fragment.height)
|
|
@@ -17,14 +19,14 @@ module PrawnStyledText
|
|
|
17
19
|
end
|
|
18
20
|
|
|
19
21
|
class StrikeThroughCallback
|
|
20
|
-
def initialize(
|
|
22
|
+
def initialize(pdf)
|
|
21
23
|
@document = pdf
|
|
22
24
|
end
|
|
23
25
|
|
|
24
|
-
def render_in_front(
|
|
25
|
-
y = (
|
|
26
|
+
def render_in_front(fragment)
|
|
27
|
+
y = (fragment.top_left[1] + fragment.bottom_left[1]) / 2
|
|
26
28
|
@document.stroke do
|
|
27
|
-
@document.line [
|
|
29
|
+
@document.line [fragment.top_left[0], y], [fragment.top_right[0], y]
|
|
28
30
|
end
|
|
29
31
|
end
|
|
30
32
|
end
|
|
@@ -1,18 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'prawn'
|
|
2
4
|
|
|
3
5
|
Prawn::Document.class_eval do
|
|
4
|
-
def styled_text(
|
|
6
|
+
def styled_text(data)
|
|
5
7
|
parts = []
|
|
6
8
|
text_options = {}
|
|
7
9
|
extra_options = { margin_left: 0 }
|
|
8
10
|
oga = Oga.parse_html data
|
|
9
11
|
PrawnStyledText::traverse oga.children do |type, text, data|
|
|
10
|
-
context =
|
|
11
|
-
|
|
12
|
+
context =
|
|
13
|
+
if type == :text_node
|
|
14
|
+
PrawnStyledText::text_node(self, data)
|
|
12
15
|
elsif type == :opening_tag
|
|
13
|
-
PrawnStyledText::opening_tag(
|
|
16
|
+
PrawnStyledText::opening_tag(self, data)
|
|
14
17
|
else
|
|
15
|
-
PrawnStyledText::closing_tag(
|
|
18
|
+
PrawnStyledText::closing_tag(self, data)
|
|
16
19
|
end
|
|
17
20
|
if context[:flush] && parts.any? # flush current parts
|
|
18
21
|
parts[0][:text] = parts[0][:text].lstrip
|
|
@@ -23,8 +26,8 @@ Prawn::Document.class_eval do
|
|
|
23
26
|
end
|
|
24
27
|
if parts.any?
|
|
25
28
|
parts[0][:text] = extra_options[:pre] + parts[0][:text] if extra_options[:pre]
|
|
26
|
-
|
|
27
|
-
|
|
29
|
+
indent(extra_options[:margin_left]) do
|
|
30
|
+
formatted_text(parts, text_options)
|
|
28
31
|
end
|
|
29
32
|
end
|
|
30
33
|
parts = []
|
|
@@ -34,44 +37,44 @@ Prawn::Document.class_eval do
|
|
|
34
37
|
options = context[:options]
|
|
35
38
|
if type == :text_node
|
|
36
39
|
text_options[:align] = options[:'text-align'].to_sym if options[:'text-align']
|
|
37
|
-
margin_top = options.delete(
|
|
38
|
-
|
|
39
|
-
margin_left = options.delete(
|
|
40
|
-
extra_options[:margin_left] = margin_left if margin_left
|
|
41
|
-
if !text_options[:leading] && (
|
|
40
|
+
margin_top = options.delete(:'margin-top').to_i
|
|
41
|
+
move_down(margin_top) if margin_top.positive?
|
|
42
|
+
margin_left = options.delete(:'margin-left').to_i
|
|
43
|
+
extra_options[:margin_left] = margin_left if margin_left.positive?
|
|
44
|
+
if !text_options[:leading] && (leading = options.delete(:'line-height').to_i).positive?
|
|
42
45
|
text_options[:leading] = leading
|
|
43
46
|
end
|
|
44
47
|
text_options[:mode] = options[:mode].to_sym if options[:mode]
|
|
45
48
|
extra_options[:pre] = context[:pre] if context[:pre]
|
|
46
|
-
parts << { text: text }.merge(
|
|
49
|
+
parts << { text: text }.merge(options) # push the data
|
|
47
50
|
elsif type == :closing_tag
|
|
48
|
-
|
|
51
|
+
formatted_text(context[:text]) if context[:text]
|
|
49
52
|
if context[:tag] == :hr
|
|
50
|
-
|
|
53
|
+
dash(options[:dash].include?(',') ? options[:dash].split(',').map(&:to_i) : options[:dash].to_i) if options[:dash]
|
|
51
54
|
if options[:color]
|
|
52
|
-
last_stroke_color =
|
|
53
|
-
|
|
55
|
+
last_stroke_color = stroke_color
|
|
56
|
+
stroke_color(options[:color])
|
|
54
57
|
end
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
+
stroke_horizontal_rule
|
|
59
|
+
stroke_color(last_stroke_color) if options[:color]
|
|
60
|
+
undash if options[:dash]
|
|
58
61
|
elsif context[:tag] == :img && context[:src]
|
|
59
62
|
image_options = {}
|
|
60
63
|
image_options[:scale] = options[:'image-scale'].to_f if options[:'image-scale']
|
|
61
64
|
if options[:'image-at']
|
|
62
|
-
xy = options[:'image-at'].split(
|
|
65
|
+
xy = options[:'image-at'].split(',').map &:to_i
|
|
63
66
|
image_options[:at] = xy if xy.count == 2
|
|
64
67
|
end
|
|
65
68
|
if options[:'image-position']
|
|
66
69
|
pos = options[:'image-position'].to_i
|
|
67
|
-
image_options[:position] = pos
|
|
70
|
+
image_options[:position] = pos.positive? ? pos : options[:'image-position']
|
|
68
71
|
end
|
|
69
72
|
image_options[:width] = options[:width] if options[:width]
|
|
70
73
|
image_options[:height] = options[:height] if options[:height]
|
|
71
|
-
|
|
74
|
+
image context[:src], image_options
|
|
72
75
|
end
|
|
73
76
|
end
|
|
74
77
|
end
|
|
75
|
-
|
|
78
|
+
formatted_text(parts, text_options)
|
|
76
79
|
end
|
|
77
80
|
end
|
|
@@ -1,26 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'oga'
|
|
2
4
|
require_relative 'callbacks'
|
|
3
5
|
require_relative 'prawn-document'
|
|
4
6
|
|
|
5
7
|
module PrawnStyledText
|
|
6
|
-
BLOCK_TAGS = [
|
|
8
|
+
BLOCK_TAGS = [:br, :div, :h1, :h2, :h3, :h4, :h5, :h6, :hr, :li, :p, :ul].freeze
|
|
7
9
|
DEF_BG_MARK = 'ffff00'
|
|
8
10
|
DEF_HEADING_T = 16
|
|
9
11
|
DEF_HEADING_H = 8
|
|
10
12
|
DEF_MARGIN_UL = 15
|
|
11
13
|
DEF_SYMBOL_UL = "\x95 "
|
|
12
|
-
HEADINGS = { h1: 32, h2: 24, h3: 20, h4: 16, h5: 14, h6: 13 }
|
|
13
|
-
RENAME = { 'font-family': :font, 'font-size': :size, 'font-style': :styles, 'letter-spacing': :character_spacing }
|
|
14
|
+
HEADINGS = { h1: 32, h2: 24, h3: 20, h4: 16, h5: 14, h6: 13 }.freeze
|
|
15
|
+
RENAME = { 'font-family': :font, 'font-size': :size, 'font-style': :styles, 'letter-spacing': :character_spacing }.freeze
|
|
14
16
|
|
|
15
17
|
@@margin_ul = 0
|
|
16
18
|
@@symbol_ul = ''
|
|
19
|
+
@@last_el = nil
|
|
17
20
|
|
|
18
|
-
def self.adjust_values(
|
|
21
|
+
def self.adjust_values(pdf, values)
|
|
19
22
|
ret = {}
|
|
20
23
|
values.each do |k, v|
|
|
21
24
|
key = k.to_sym
|
|
22
|
-
key = RENAME[key] if RENAME.include?(
|
|
23
|
-
ret[key] =
|
|
25
|
+
key = RENAME[key] if RENAME.include?(key)
|
|
26
|
+
ret[key] =
|
|
27
|
+
case key
|
|
24
28
|
when :character_spacing
|
|
25
29
|
v.to_f
|
|
26
30
|
when :color
|
|
@@ -30,14 +34,14 @@ module PrawnStyledText
|
|
|
30
34
|
matches[3] || matches[2] || matches[1] || ''
|
|
31
35
|
when :height
|
|
32
36
|
i = v.to_i
|
|
33
|
-
v.include?(
|
|
37
|
+
v.include?('%') ? (i * pdf.bounds.height * 0.01) : i
|
|
34
38
|
when :size
|
|
35
39
|
v.to_i
|
|
36
40
|
when :styles
|
|
37
|
-
v.split(
|
|
41
|
+
v.split(',').map { |s| s.strip.to_sym }
|
|
38
42
|
when :width
|
|
39
43
|
i = v.to_i
|
|
40
|
-
v.include?(
|
|
44
|
+
v.include?('%') ? (i * pdf.bounds.width * 0.01) : i
|
|
41
45
|
else
|
|
42
46
|
v
|
|
43
47
|
end
|
|
@@ -45,13 +49,13 @@ module PrawnStyledText
|
|
|
45
49
|
ret
|
|
46
50
|
end
|
|
47
51
|
|
|
48
|
-
def self.closing_tag(
|
|
52
|
+
def self.closing_tag(pdf, data)
|
|
49
53
|
context = { tag: data[:name], options: {} }
|
|
50
54
|
context[:flush] ||= true if BLOCK_TAGS.include? data[:name]
|
|
51
55
|
# Evalutate tag
|
|
52
56
|
case data[:name]
|
|
53
57
|
when :br # new line
|
|
54
|
-
context[:text] ||= [ { text: "\n" } ]
|
|
58
|
+
context[:text] ||= [ { text: "\n" } ] if @@last_el == :br
|
|
55
59
|
when :img # image
|
|
56
60
|
context[:flush] ||= true
|
|
57
61
|
context[:src] = data[:node].get 'src'
|
|
@@ -60,29 +64,29 @@ module PrawnStyledText
|
|
|
60
64
|
end
|
|
61
65
|
# Evalutate attributes
|
|
62
66
|
attributes = data[:node].get 'style'
|
|
63
|
-
context[:options] = adjust_values(
|
|
67
|
+
context[:options] = adjust_values(pdf, attributes.scan(/\s*([^:]+):\s*([^;]+)[;]*/)) if attributes
|
|
64
68
|
context
|
|
65
69
|
end
|
|
66
70
|
|
|
67
|
-
def self.opening_tag(
|
|
71
|
+
def self.opening_tag(pdf, data)
|
|
68
72
|
context = { tag: data[:name], options: {} }
|
|
69
73
|
context[:flush] ||= true if BLOCK_TAGS.include? data[:name]
|
|
70
74
|
# Evalutate attributes
|
|
71
75
|
attributes = data[:node].get 'style'
|
|
72
|
-
context[:options].merge!(
|
|
76
|
+
context[:options].merge!(adjust_values(pdf, attributes.scan(/\s*([^:]+):\s*([^;]+)[;]*/))) if attributes
|
|
73
77
|
if data[:name] == :ul
|
|
74
|
-
@@margin_ul += (
|
|
78
|
+
@@margin_ul += (context[:options][:'margin-left'] ? context[:options][:'margin-left'].to_i : DEF_MARGIN_UL)
|
|
75
79
|
@@symbol_ul = if context[:options][:'list-symbol']
|
|
76
80
|
matches = context[:options][:'list-symbol'].match /'([^']*)'|"([^"]*)"|(.*)/
|
|
77
81
|
matches[3] || matches[2] || matches[1] || ''
|
|
78
82
|
else
|
|
79
|
-
DEF_SYMBOL_UL
|
|
83
|
+
DEF_SYMBOL_UL.dup
|
|
80
84
|
end
|
|
81
85
|
end
|
|
82
86
|
context
|
|
83
87
|
end
|
|
84
88
|
|
|
85
|
-
def self.text_node(
|
|
89
|
+
def self.text_node(pdf, data)
|
|
86
90
|
context = { pre: '', options: {} }
|
|
87
91
|
styles = []
|
|
88
92
|
font_size = pdf.font_size
|
|
@@ -96,7 +100,7 @@ module PrawnStyledText
|
|
|
96
100
|
when :b, :strong # bold
|
|
97
101
|
styles.push :bold
|
|
98
102
|
when :del, :s
|
|
99
|
-
@@strike_through ||= StrikeThroughCallback.new(
|
|
103
|
+
@@strike_through ||= StrikeThroughCallback.new(pdf)
|
|
100
104
|
context[:options][:callback] = @@strike_through
|
|
101
105
|
when :h1, :h2, :h3, :h4, :h5, :h6
|
|
102
106
|
context[:options][:size] = HEADINGS[tag]
|
|
@@ -106,9 +110,9 @@ module PrawnStyledText
|
|
|
106
110
|
styles.push :italic
|
|
107
111
|
when :li # list item
|
|
108
112
|
context[:options][:'margin-left'] = @@margin_ul
|
|
109
|
-
context[:pre] = @@symbol_ul.force_encoding(
|
|
113
|
+
context[:pre] = @@symbol_ul.force_encoding('windows-1252').encode('UTF-8')
|
|
110
114
|
when :mark
|
|
111
|
-
@@highlight ||= HighlightCallback.new(
|
|
115
|
+
@@highlight ||= HighlightCallback.new(pdf)
|
|
112
116
|
@@highlight.set_color nil
|
|
113
117
|
context[:options][:callback] = @@highlight
|
|
114
118
|
when :small
|
|
@@ -120,8 +124,8 @@ module PrawnStyledText
|
|
|
120
124
|
# Evalutate attributes
|
|
121
125
|
attributes = part[:node].get 'style'
|
|
122
126
|
if attributes
|
|
123
|
-
values = adjust_values(
|
|
124
|
-
@@highlight.set_color(
|
|
127
|
+
values = adjust_values(pdf, attributes.scan(/\s*([^:]+):\s*([^;]+)[;]*/))
|
|
128
|
+
@@highlight.set_color(values[:background].delete('#')) if tag == :mark && values[:background]
|
|
125
129
|
context[:options].merge! values
|
|
126
130
|
end
|
|
127
131
|
font_size = context[:options][:size] if font_size
|
|
@@ -129,16 +133,19 @@ module PrawnStyledText
|
|
|
129
133
|
context
|
|
130
134
|
end
|
|
131
135
|
|
|
132
|
-
def self.traverse(
|
|
136
|
+
def self.traverse(nodes, context = [], &block)
|
|
133
137
|
nodes.each do |node|
|
|
134
138
|
if node.is_a? Oga::XML::Text
|
|
135
|
-
|
|
139
|
+
text = node.text.delete("\n\r")
|
|
140
|
+
yield :text_node, text, context
|
|
141
|
+
@@last_el = nil unless text.empty?
|
|
136
142
|
elsif node.is_a? Oga::XML::Element
|
|
137
143
|
element = { name: node.name.to_sym, node: node }
|
|
138
144
|
yield :opening_tag, element[:name], element
|
|
139
|
-
context.push(
|
|
140
|
-
traverse(
|
|
145
|
+
context.push(element)
|
|
146
|
+
traverse(node.children, context, &block) if node.children.count > 0
|
|
141
147
|
yield :closing_tag, element[:name], context.pop
|
|
148
|
+
@@last_el = element[:name]
|
|
142
149
|
end
|
|
143
150
|
end
|
|
144
151
|
end
|
data/prawn-styled-text.gemspec
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
lib = File.expand_path('../lib', __FILE__)
|
|
2
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
3
5
|
require 'prawn-styled-text/version'
|
|
@@ -15,6 +17,8 @@ Gem::Specification.new do |spec|
|
|
|
15
17
|
spec.files = `git ls-files -z`.split("\x0")
|
|
16
18
|
spec.require_paths = ['lib']
|
|
17
19
|
|
|
18
|
-
spec.add_runtime_dependency '
|
|
19
|
-
spec.add_runtime_dependency '
|
|
20
|
+
spec.add_runtime_dependency 'oga', '~> 2.16'
|
|
21
|
+
spec.add_runtime_dependency 'prawn', '~> 2.2.2'
|
|
22
|
+
|
|
23
|
+
spec.add_development_dependency 'rubocop', '~> 0.76'
|
|
20
24
|
end
|
metadata
CHANGED
|
@@ -1,43 +1,57 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: prawn-styled-text
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Mattia Roccoberton
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2019-12-27 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
|
-
name:
|
|
14
|
+
name: oga
|
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
|
16
16
|
requirements:
|
|
17
17
|
- - "~>"
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '2'
|
|
19
|
+
version: '2.16'
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: '2'
|
|
26
|
+
version: '2.16'
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
|
-
name:
|
|
28
|
+
name: prawn
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
30
30
|
requirements:
|
|
31
31
|
- - "~>"
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
|
-
version:
|
|
33
|
+
version: 2.2.2
|
|
34
34
|
type: :runtime
|
|
35
35
|
prerelease: false
|
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
37
|
requirements:
|
|
38
38
|
- - "~>"
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
|
-
version:
|
|
40
|
+
version: 2.2.2
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: rubocop
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '0.76'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '0.76'
|
|
41
55
|
description: A Prawn PDF component which adds basic HTML support
|
|
42
56
|
email: mat@blocknot.es
|
|
43
57
|
executables: []
|
|
@@ -82,8 +96,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
82
96
|
- !ruby/object:Gem::Version
|
|
83
97
|
version: '0'
|
|
84
98
|
requirements: []
|
|
85
|
-
|
|
86
|
-
rubygems_version: 2.5.2
|
|
99
|
+
rubygems_version: 3.0.2
|
|
87
100
|
signing_key:
|
|
88
101
|
specification_version: 4
|
|
89
102
|
summary: Prawn PDF styled text
|