prawn-icon 1.0.0 → 2.0.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.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +54 -1
  3. data/GPLv2 +21 -22
  4. data/README.md +10 -10
  5. data/data/fonts/fab/LICENSE +34 -0
  6. data/data/fonts/fab/fa-brands.ttf +0 -0
  7. data/data/fonts/fab/fab.yml +333 -0
  8. data/data/fonts/far/LICENSE +34 -0
  9. data/data/fonts/far/fa-regular.ttf +0 -0
  10. data/data/fonts/far/far.yml +119 -0
  11. data/data/fonts/fas/LICENSE +34 -0
  12. data/data/fonts/fas/fa-solid.ttf +0 -0
  13. data/data/fonts/fas/fas.yml +503 -0
  14. data/data/fonts/pf/paymentfont-webfont.ttf +0 -0
  15. data/data/fonts/pf/pf.yml +118 -97
  16. data/examples/fas-beer-inline.png +0 -0
  17. data/examples/fas-beer.png +0 -0
  18. data/examples/fontawesome.rb +28 -20
  19. data/examples/foundation_icons.rb +1 -1
  20. data/examples/paymentfont.rb +1 -1
  21. data/lib/prawn/icon.rb +3 -200
  22. data/lib/prawn/icon/base.rb +19 -0
  23. data/lib/prawn/icon/errors.rb +21 -0
  24. data/lib/prawn/icon/font_data.rb +11 -13
  25. data/lib/prawn/icon/interface.rb +208 -0
  26. data/lib/prawn/icon/parser.rb +45 -53
  27. data/lib/prawn/icon/version.rb +1 -1
  28. data/prawn-icon.gemspec +8 -9
  29. data/spec/integration/icon_spec.rb +80 -60
  30. data/spec/spec_helper.rb +4 -0
  31. data/spec/support/parser_helper.rb +1 -1
  32. data/spec/support/pdf_helper.rb +1 -1
  33. data/spec/unit/base_spec.rb +15 -0
  34. data/spec/unit/errors/icon_key_empty_spec.rb +19 -0
  35. data/spec/unit/errors/icon_not_found_spec.rb +19 -0
  36. data/spec/unit/font_data_spec.rb +54 -73
  37. data/spec/unit/icon_spec.rb +20 -27
  38. data/spec/unit/parser_spec.rb +66 -63
  39. metadata +35 -41
  40. data/data/fonts/fa/LICENSE +0 -4
  41. data/data/fonts/fa/fa.yml +0 -676
  42. data/data/fonts/fa/fontawesome.ttf +0 -0
  43. data/data/fonts/octicon/LICENSE +0 -9
  44. data/data/fonts/octicon/octicon.yml +0 -192
  45. data/data/fonts/octicon/octicons.ttf +0 -0
  46. data/examples/fa-beer-inline.png +0 -0
  47. data/examples/fa-beer.png +0 -0
  48. data/examples/octicons.rb +0 -35
@@ -0,0 +1,19 @@
1
+ # encoding: utf-8
2
+ #
3
+ # base.rb - Base configuration for Prawn::Icon.
4
+ #
5
+ # Copyright September 2016, Jesse Doyle. All rights reserved.
6
+ #
7
+ # This is free software. Please see the LICENSE and COPYING files for details.
8
+
9
+ require 'prawn'
10
+ require_relative 'errors'
11
+
12
+ module Prawn
13
+ class Icon
14
+ module Base
15
+ FONTDIR = File.join \
16
+ File.expand_path('../../../..', __FILE__), 'data/fonts'
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,21 @@
1
+ # encoding: utf-8
2
+ #
3
+ # errors.rb - Prawn::Icon standard errors.
4
+ #
5
+ # Copyright September 2016, Jesse Doyle. All rights reserved.
6
+ #
7
+ # This is free software. Please see the LICENSE and COPYING files for details.
8
+
9
+ module Prawn
10
+ class Icon
11
+ module Errors
12
+ # Error raised when an icon glyph is not found
13
+ #
14
+ IconNotFound = Class.new(StandardError)
15
+
16
+ # Error raised when an icon key is not provided
17
+ #
18
+ IconKeyEmpty = Class.new(StandardError)
19
+ end
20
+ end
21
+ end
@@ -34,7 +34,7 @@ module Prawn
34
34
 
35
35
  def specifier_from_key(key)
36
36
  if key.nil? || key == ''
37
- raise Prawn::Errors::IconKeyEmpty,
37
+ raise Errors::IconKeyEmpty,
38
38
  'Icon key provided was nil.'
39
39
  end
40
40
 
@@ -45,7 +45,7 @@ module Prawn
45
45
  attr_reader :set
46
46
 
47
47
  def initialize(document, opts = {})
48
- @set = opts[:set] || :fa
48
+ @set = opts.fetch(:set)
49
49
  load_fonts(document)
50
50
  end
51
51
 
@@ -63,15 +63,15 @@ module Prawn
63
63
  end
64
64
 
65
65
  def path
66
- ttf = File.join(Icon::FONTDIR, @set.to_s, '*.ttf')
67
- fonts = Dir[ttf]
66
+ ttf = File.join(Icon::Base::FONTDIR, @set.to_s, '*.ttf')
67
+ font = Dir[ttf].first
68
68
 
69
- if fonts.empty?
69
+ if font.nil?
70
70
  raise Prawn::Errors::UnknownFont,
71
71
  "Icon font not found for set: #{@set}"
72
72
  end
73
73
 
74
- @path ||= fonts.first
74
+ @path ||= font
75
75
  end
76
76
 
77
77
  def specifier
@@ -79,14 +79,12 @@ module Prawn
79
79
  end
80
80
 
81
81
  def unicode(key)
82
- char = yaml[specifier][key]
83
-
84
- unless char
85
- raise Prawn::Errors::IconNotFound,
86
- "Key: #{specifier}-#{key} not found"
82
+ yaml[specifier][key].tap do |char|
83
+ unless char
84
+ raise Errors::IconNotFound,
85
+ "Key: #{specifier}-#{key} not found"
86
+ end
87
87
  end
88
-
89
- char
90
88
  end
91
89
 
92
90
  def keys
@@ -0,0 +1,208 @@
1
+ # encoding: utf-8
2
+ #
3
+ # interface.rb: Prawn extension module and logic.
4
+ #
5
+ # Copyright October 2016, Jesse Doyle. All rights reserved.
6
+ #
7
+ # This is free software. Please see the LICENSE and COPYING files for details.
8
+
9
+ module Prawn
10
+ # Easy icon font usage within Prawn. Currently
11
+ # supported icon fonts include: FontAwesome,
12
+ # Zurb Foundicons and PaymentFont.
13
+ #
14
+ # = Icon Keys
15
+ #
16
+ # Icon keys must be supplied to most +Prawn::Icon+
17
+ # methods. Keys map directly to a unicode character
18
+ # within the font that produces a given icon. As a
19
+ # rule, included icon keys should match the keys from
20
+ # the font provider. The icon key mapping is specified
21
+ # in the font's +legend_file+, which is a +YAML+ file
22
+ # located in Prawn::Icon::Base::FONTDIR/font/font.yml.
23
+ #
24
+ # Prawn::Icon::
25
+ # Houses the methods and interfaces necessary for
26
+ # rendering icons to the Prawn::Document.
27
+ #
28
+ # Prawn::Icon::FontData::
29
+ # Used to store various information about an icon font,
30
+ # including the key-to-unicode mapping information.
31
+ # Also houses methods to cache and lazily load the
32
+ # requested font data on a document basis.
33
+ #
34
+ # Prawn::Icon::Parser::
35
+ # Used to initially parse icons that are used with the
36
+ # inline_format: true option. The input string is parsed
37
+ # once for <icon></icon> tags, then the output is provided
38
+ # to Prawn's internal formatted text parser.
39
+ #
40
+ class Icon
41
+ FONTDIR = Icon::Base::FONTDIR
42
+
43
+ module Interface
44
+ # Set up and draw an icon on this document. This
45
+ # method operates much like +Prawn::Text::Box+.
46
+ #
47
+ # == Parameters:
48
+ # key::
49
+ # Contains the key to a particular icon within
50
+ # a font family. If :inline_format is true,
51
+ # then key may contain formatted text marked
52
+ # with <icon></icon> tags and any tag supported
53
+ # by Prawn's parser.
54
+ #
55
+ # opts::
56
+ # A hash of options that may be supplied to
57
+ # the underlying +text+ method call.
58
+ #
59
+ # == Examples:
60
+ # pdf.icon 'fas-beer'
61
+ # pdf.icon '<icon color="0099FF">fas-user-circle</icon>',
62
+ # inline_format: true
63
+ #
64
+ def icon(key, opts = {})
65
+ make_icon(key, opts).tap(&:render)
66
+ end
67
+
68
+ # Initialize a new icon object, but do
69
+ # not render it to the document.
70
+ #
71
+ # == Parameters:
72
+ # key::
73
+ # Contains the key to a particular icon within
74
+ # a font family. If :inline_format is true,
75
+ # then key may contain formatted text marked
76
+ # with <icon></icon> tags and any tag supported
77
+ # by Prawn's parser.
78
+ #
79
+ # opts::
80
+ # A hash of options that may be supplied to
81
+ # the underlying text method call.
82
+ #
83
+ def make_icon(key, opts = {})
84
+ if opts[:inline_format]
85
+ inline_icon(key, opts)
86
+ else
87
+ Icon.new(key, self, opts)
88
+ end
89
+ end
90
+
91
+ # Initialize a new formatted text box containing
92
+ # icon information, but don't render it to the
93
+ # document.
94
+ #
95
+ # == Parameters:
96
+ # text::
97
+ # Input text to be parsed initially for <icon>
98
+ # tags, then passed to Prawn's formatted text
99
+ # parser.
100
+ #
101
+ # opts::
102
+ # A hash of options that may be supplied to the
103
+ # underlying text call.
104
+ #
105
+ def inline_icon(text, opts = {})
106
+ parsed = Icon::Parser.format(self, text)
107
+ content = Text::Formatted::Parser.format(parsed)
108
+ box_options = opts.merge(
109
+ inline_format: true,
110
+ document: self,
111
+ at: [bounds.left, cursor]
112
+ )
113
+ icon_box(content, box_options)
114
+ end
115
+
116
+ # Initialize a new Prawn::Icon, but don't render
117
+ # the icon to a document. Intended to be used as
118
+ # an entry of a data array when combined with
119
+ # Prawn::Table.
120
+ #
121
+ # == Parameters:
122
+ # key::
123
+ # Contains the key to a particular icon within
124
+ # a font family. The key may contain a string
125
+ # with format tags if +inline_format: true+ in
126
+ # the +opts+ hash.
127
+ #
128
+ # opts::
129
+ # A hash of options that may be supplied to the
130
+ # underlying text call.
131
+ #
132
+ # == Returns:
133
+ # A Hash containing +font+ and +content+ keys
134
+ # that match the data necessary for the
135
+ # specified icon.
136
+ #
137
+ # eg. { font: 'fas', content: "\uf2b9" }
138
+ #
139
+ # Note that the +font+ key will not be set
140
+ # if +inline_format: true+.
141
+ #
142
+ # == Examples:
143
+ # require 'prawn/table'
144
+ #
145
+ # data = [
146
+ # # Explicit brackets must be used here
147
+ # [pdf.table_icon('fas-coffee'), 'Cell 1'],
148
+ # ['Cell 2', 'Cell 3']
149
+ # ]
150
+ #
151
+ # pdf.table(data) => (2 x 2 table)
152
+ #
153
+ def table_icon(key, opts = {})
154
+ if opts[:inline_format]
155
+ content = Icon::Parser.format(self, key)
156
+ opts.merge(content: content)
157
+ else
158
+ make_icon(key, opts).format_hash
159
+ end
160
+ end
161
+
162
+ private
163
+
164
+ def icon_box(content, opts = {}) # :nodoc:
165
+ Text::Formatted::Box.new(content, opts).tap do |box|
166
+ box.render(dry_run: true)
167
+ self.y -= box.height
168
+ unless opts.fetch(:final_gap, true)
169
+ self.y -= box.line_gap + box.leading
170
+ end
171
+ end
172
+ end
173
+ end
174
+
175
+ attr_reader :set, :unicode
176
+
177
+ def initialize(key, document, opts = {})
178
+ @pdf = document
179
+ @set = opts[:set] ||
180
+ FontData.specifier_from_key(key)
181
+ @data = FontData.load(document, @set)
182
+ @key = strip_specifier_from_key(key)
183
+ @unicode = @data.unicode(@key)
184
+ @options = opts
185
+ end
186
+
187
+ def format_hash
188
+ base = { font: @set.to_s, content: @unicode }
189
+ opts = @options.dup
190
+ # Prawn::Table renames :color to :text_color
191
+ opts[:text_color] = opts.delete(:color)
192
+ base.merge(opts)
193
+ end
194
+
195
+ def render
196
+ @pdf.font(@data.path) do
197
+ @pdf.text @unicode, @options
198
+ end
199
+ end
200
+
201
+ private
202
+
203
+ def strip_specifier_from_key(key) # :nodoc:
204
+ reg = Regexp.new "#{@data.specifier}-"
205
+ key.sub(reg, '') # Only one specifier
206
+ end
207
+ end
208
+ end
@@ -49,77 +49,69 @@ module Prawn
49
49
  icons = keys_to_unicode(document, content, config)
50
50
  tags = icon_tags(icons)
51
51
 
52
- string.gsub(TAG_REGEX).with_index do |_, i|
53
- tags[i]
54
- end
52
+ string.gsub(TAG_REGEX).with_index { |_, i| tags[i] }
55
53
  end
56
54
 
57
55
  def config_from_tokens(tokens)
58
- array = []
59
-
60
- tokens.each do |token|
61
- # Skip the closing tag
62
- next if token =~ /<\/icon>/i
63
- icon = {}
64
-
65
- # Convert [[1,2], [3,4]] to { :1 => 2, :3 => 4 }
66
- attrs = token.scan(ATTR_REGEX).inject({}) do |k, v|
67
- val = attr_hash(v)
68
- k.merge!(val)
56
+ [].tap do |array|
57
+ tokens.each do |token|
58
+ # Skip the closing tag
59
+ next if token =~ /<\/icon>/i
60
+ icon = {}
61
+
62
+ # Convert [[1,2], [3,4]] to { :1 => 2, :3 => 4 }
63
+ attrs = token.scan(ATTR_REGEX).inject({}) do |k, v|
64
+ val = attr_hash(v)
65
+ k.merge!(val)
66
+ end
67
+
68
+ icon.merge!(attrs)
69
+ array << icon
69
70
  end
70
-
71
- icon.merge!(attrs)
72
- array << icon
73
71
  end
74
-
75
- array
76
72
  end
77
73
 
78
74
  def icon_tags(icons)
79
- tags = []
75
+ [].tap do |tags|
76
+ icons.each do |icon|
77
+ # Mandatory
78
+ content = icon[:content]
79
+ set = icon[:set]
80
80
 
81
- icons.each do |icon|
82
- # Mandatory
83
- content = icon[:content]
84
- set = icon[:set]
81
+ # Optional
82
+ color = icon[:color]
83
+ size = icon[:size]
85
84
 
86
- # Optional
87
- color = icon[:color]
88
- size = icon[:size]
85
+ opening = "<font name=\"#{set}\""
89
86
 
90
- opening = "<font name=\"#{set}\""
87
+ unless color || size
88
+ tags << "#{opening}>#{content}</font>"
89
+ next
90
+ end
91
91
 
92
- unless color || size
93
- tags << "#{opening}>#{content}</font>"
94
- next
95
- end
92
+ opening += " size=\"#{size}\"" if size
93
+ content = "<color rgb=\"#{color}\">#{content}</color>" if color
96
94
 
97
- opening += " size=\"#{size}\"" if size
98
- content = "<color rgb=\"#{color}\">#{content}</color>" if color
99
-
100
- opening += '>'
101
- tags << "#{opening}#{content}</font>"
95
+ opening += '>'
96
+ tags << "#{opening}#{content}</font>"
97
+ end
102
98
  end
103
-
104
- tags
105
99
  end
106
100
 
107
101
  def keys_to_unicode(document, content, config)
108
- icons = []
109
-
110
- content.each_with_index do |icon, index|
111
- options ||= {}
112
- options = config[index] if config.any?
113
- info = {
114
- set: FontData.specifier_from_key(icon),
115
- size: options[:size],
116
- color: options[:color],
117
- content: FontData.unicode_from_key(document, icon)
118
- }
119
- icons << info
102
+ [].tap do |icons|
103
+ content.each_with_index do |icon, index|
104
+ options ||= {}
105
+ options = config[index] if config.any?
106
+ info = {
107
+ set: FontData.specifier_from_key(icon),
108
+ size: options[:size],
109
+ color: options[:color],
110
+ content: FontData.unicode_from_key(document, icon)
111
+ }
112
+ icons << info
113
+ end
120
114
  end
121
-
122
- icons
123
115
  end
124
116
 
125
117
  private
@@ -8,6 +8,6 @@
8
8
 
9
9
  module Prawn
10
10
  class Icon
11
- VERSION = '1.0.0'.freeze
11
+ VERSION = '2.0.0'.freeze
12
12
  end
13
13
  end
@@ -7,9 +7,9 @@ Gem::Specification.new do |spec|
7
7
  spec.platform = Gem::Platform::RUBY
8
8
  spec.summary = 'Provides icon fonts for PrawnPDF'
9
9
  spec.files = Dir.glob('{lib,spec,data,examples}/**/**/*') +
10
- %w(prawn-icon.gemspec Gemfile Rakefile) +
11
- %w(README.md CHANGELOG.md) +
12
- %w(COPYING LICENSE GPLv2 GPLv3)
10
+ %w[prawn-icon.gemspec Gemfile Rakefile] +
11
+ %w[README.md CHANGELOG.md] +
12
+ %w[COPYING LICENSE GPLv2 GPLv3]
13
13
 
14
14
  spec.require_path = 'lib'
15
15
  spec.required_ruby_version = '>= 1.9.3'
@@ -24,17 +24,16 @@ Gem::Specification.new do |spec|
24
24
 
25
25
  spec.add_dependency('prawn', '>= 1.1.0', '< 3.0.0')
26
26
 
27
- spec.add_development_dependency('pdf-inspector', '~> 1.1.0')
28
- spec.add_development_dependency('rspec', '~>2.14.1')
29
- spec.add_development_dependency('rubocop', '~>0.27.0')
30
- spec.add_development_dependency('mocha')
27
+ spec.add_development_dependency('pdf-inspector', '>= 1.2.1')
28
+ spec.add_development_dependency('rspec', '>= 3.5.0')
29
+ spec.add_development_dependency('rubocop', '~> 0.49.1')
31
30
  spec.add_development_dependency('rake')
31
+ spec.add_development_dependency('pdf-reader', '>= 1.4')
32
32
  spec.add_development_dependency('simplecov')
33
- spec.add_development_dependency('pdf-reader', '~>1.2')
34
33
 
35
34
  spec.description = <<-END_DESC
36
35
  Prawn::Icon provides various icon fonts including
37
- FontAwesome, Foundation Icons and GitHub Octicons
36
+ FontAwesome, PaymentFont and Foundation Icons
38
37
  for use with the Prawn PDF toolkit.
39
38
  END_DESC
40
39
  end