prawn-icon 1.0.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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