Skip to content

Commit

Permalink
Merge pull request #34 from jessedoyle/fa-4-compat
Browse files Browse the repository at this point in the history
2.1.0 - FontAwesome 4 Shim
  • Loading branch information
Jesse Doyle authored Apr 2, 2018
2 parents 3dcefcc + 97c100e commit 51a84ae
Show file tree
Hide file tree
Showing 8 changed files with 249 additions and 9 deletions.
2 changes: 2 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,5 @@ Metrics/AbcSize:
Max: 20
Layout/EmptyLineAfterMagicComment:
Enabled: false
Layout/IndentHeredoc:
Enabled: false
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
# 2.1.0 - April 1, 2018

* Introduce backwards compatibility with FontAwesome 4 icon keys by dynamically
rewriting all instances of `fa-*` to their appropriate FontAwesome 5 equivalent
key. This is achieved by implementing a shim generated from the FontAwesome metadata.
* Introduce a deprecation warning written to `STDERR` when any `fa-*` key is
encountered. The compatibility shim will be removed in the next major version
of `Prawn::Icon` (`3.0.0`).
* See the [discussion here](https://github.com/jessedoyle/prawn-icon/pull/33) for more details.

# 2.0.0 - March 7, 2018

* [**breaking change**] Update to FontAwesome 5.0.8. FontAwesome 5 now provides 3 different font families: `brands`, `regular` and `solid`. The specifiers for these font icons are now: `fab`, `far` and `fas`.
Expand Down
1 change: 1 addition & 0 deletions lib/prawn/icon.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@
require_relative 'icon/font_data'
require_relative 'icon/parser'
require_relative 'icon/interface'
require_relative 'icon/compatibility'

Prawn::Document.extensions << Prawn::Icon::Interface
178 changes: 178 additions & 0 deletions lib/prawn/icon/compatibility.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
# encoding: utf-8
#
# compatibility.rb - Prawn::Icon FontAwesome 4/5 compatibility shim.
#
# Copyright March 2018, Jesse Doyle. All rights reserved.
#
# This is free software. Please see the LICENSE and COPYING files for details.

# rubocop:disable Metrics/ClassLength
module Prawn
class Icon
class Compatibility
SHIMS = {
'fa-area-chart' => 'fas-chart-area',
'fa-arrow-circle-o-down' => 'far-arrow-alt-circle-down',
'fa-arrow-circle-o-left' => 'far-arrow-alt-circle-left',
'fa-arrow-circle-o-right' => 'far-arrow-alt-circle-right',
'fa-arrow-circle-o-up' => 'far-arrow-alt-circle-up',
'fa-arrows' => 'fas-arrows-alt',
'fa-arrows-alt' => 'fas-expand-arrows-alt',
'fa-arrows-h' => 'fas-arrows-alt-h',
'fa-arrows-v' => 'fas-arrows-alt-v',
'fa-bar-chart' => 'far-chart-bar',
'fa-bitbucket-square' => 'fab-bitbucket',
'fa-calendar' => 'fas-calendar-alt',
'fa-calendar-o' => 'far-calendar',
'fa-caret-square-o-down' => 'far-caret-square-down',
'fa-caret-square-o-left' => 'far-caret-square-left',
'fa-caret-square-o-right' => 'far-caret-square-right',
'fa-caret-square-o-up' => 'far-caret-square-up',
'fa-cc' => 'far-closed-captioning',
'fa-chain-broken' => 'fas-unlink',
'fa-circle-o-notch' => 'fas-circle-notch',
'fa-circle-thin' => 'far-circle',
'fa-clipboard' => 'far-clipboard',
'fa-clone' => 'far-clone',
'fa-cloud-download' => 'fas-cloud-download-alt',
'fa-cloud-upload' => 'fas-cloud-upload-alt',
'fa-code-fork' => 'fas-code-branch',
'fa-commenting' => 'fas-comment-alt',
'fa-compass' => 'far-compass',
'fa-copyright' => 'far-copyright',
'fa-creative-commons' => 'fab-creative-commons',
'fa-credit-card' => 'far-credit-card',
'fa-credit-card-alt' => 'fas-credit-card',
'fa-cutlery' => 'fas-utensils',
'fa-diamond' => 'far-gem',
'fa-eercast' => 'fab-sellcast',
'fa-eur' => 'fas-euro-sign',
'fa-exchange' => 'fas-exchange-alt',
'fa-external-link' => 'fas-external-link-alt',
'fa-external-link-square' => 'fas-external-link-square-alt',
'fa-eye-dropper' => 'far-eye-dropper',
'fa-eye-slash' => 'far-eye-slash',
'fa-eyedropper' => 'fas-eye-dropper',
'fa-facebook' => 'fab-facebook-f',
'fa-facebook-official' => 'fab-facebook',
'fa-file-text' => 'fas-file-alt',
'fa-files-o' => 'far-copy',
'fa-floppy-o' => 'far-save',
'fa-gbp' => 'fas-pound-sign',
'fa-glass' => 'fas-glass-martini',
'fa-google-plus' => 'fab-google-plus-g',
'fa-google-plus-circle' => 'fab-google-plus',
'fa-google-plus-official' => 'fab-google-plus',
'fa-hand-o-down' => 'far-hand-point-down',
'fa-hand-o-left' => 'far-hand-point-left',
'fa-hand-o-right' => 'far-hand-point-right',
'fa-hand-o-up' => 'far-hand-point-up',
'fa-header' => 'fas-heading',
'fa-id-badge' => 'far-id-badge',
'fa-ils' => 'fas-shekel-sign',
'fa-inr' => 'fas-rupee-sign',
'fa-intersex' => 'fas-transgender',
'fa-jpy' => 'fas-yen-sign',
'fa-krw' => 'fas-won-sign',
'fa-level-down' => 'fas-level-down-alt',
'fa-level-up' => 'fas-level-up-alt',
'fa-life-ring' => 'far-life-ring',
'fa-line-chart' => 'fas-chart-line',
'fa-linkedin' => 'fab-linkedin-in',
'fa-linkedin-square' => 'fab-linkedin',
'fa-list-alt' => 'far-list-alt',
'fa-long-arrow-down' => 'fas-long-arrow-alt-down',
'fa-long-arrow-left' => 'fas-long-arrow-alt-left',
'fa-long-arrow-right' => 'fas-long-arrow-alt-right',
'fa-long-arrow-up' => 'fas-long-arrow-alt-up',
'fa-map-marker' => 'fas-map-marker-alt',
'fa-meanpath' => 'fab-font-awesome',
'fa-mobile' => 'fas-mobile-alt',
'fa-money' => 'far-money-bill-alt',
'fa-object-group' => 'far-object-group',
'fa-object-ungroup' => 'far-object-ungroup',
'fa-paste' => 'far-paste',
'fa-pencil' => 'fas-pencil-alt',
'fa-pencil-square' => 'fas-pen-square',
'fa-pencil-square-o' => 'far-edit',
'fa-picture' => 'fas-image',
'fa-pie-chart' => 'fas-chart-pie',
'fa-refresh' => 'fas-sync',
'fa-registered' => 'far-registered',
'fa-repeat' => 'fas-redo',
'fa-rub' => 'fas-ruble-sign',
'fa-scissors' => 'fas-cut',
'fa-shield' => 'fas-shield-alt',
'fa-sign-in' => 'fas-sign-in-alt',
'fa-sign-out' => 'fas-sign-out-alt',
'fa-sliders' => 'fas-sliders-h',
'fa-sort-alpha-asc' => 'fas-sort-alpha-down',
'fa-sort-alpha-desc' => 'fas-sort-alpha-up',
'fa-sort-amount-asc' => 'fas-sort-amount-down',
'fa-sort-amount-desc' => 'fas-sort-amount-up',
'fa-sort-asc' => 'fas-sort-up',
'fa-sort-desc' => 'fas-sort-down',
'fa-sort-numeric-asc' => 'fas-sort-numeric-down',
'fa-sort-numeric-desc' => 'fas-sort-numeric-up',
'fa-spoon' => 'fas-utensil-spoon',
'fa-star-half-empty' => 'fas-star-half',
'fa-star-half-full' => 'fas-star-half',
'fa-support' => 'far-life-ring',
'fa-tablet' => 'fas-tablet-alt',
'fa-tachometer' => 'fas-tachometer-alt',
'fa-television' => 'fas-tv',
'fa-thumb-tack' => 'fas-thumbtack',
'fa-thumbs-o-down' => 'far-thumbs-down',
'fa-thumbs-o-up' => 'far-thumbs-up',
'fa-ticket' => 'fas-ticket-alt',
'fa-trash' => 'fas-trash-alt',
'fa-trash-o' => 'far-trash-alt',
'fa-try' => 'fas-lira-sign',
'fa-usd' => 'fas-dollar-sign',
'fa-video-camera' => 'fas-video',
'fa-vimeo' => 'fab-vimeo-v',
'fa-volume-control-phone' => 'fas-phone-volume',
'fa-wheelchair-alt' => 'fab-accessible-icon',
'fa-window-maximize' => 'far-window-maximize',
'fa-window-restore' => 'far-window-restore',
'fa-youtube-play' => 'fab-youtube'
}.freeze

attr_accessor :key

def initialize(opts = {})
self.key = opts.fetch(:key)
end

def translate(io = STDERR)
@translate ||= begin
if key.start_with?('fa-')
map.tap { |replaced| warning(replaced, key, io) }
else
key
end
end
end

private

def map
SHIMS.fetch(key) do
# FontAwesome shim metadata assumes "fas" as the default
# font family if not explicity referenced.
"fas-#{key.sub(/fa-/, '')}"
end
end

def warning(new_key, old_key, io)
io.puts <<-DEPRECATION
[Prawn::Icon - DEPRECATION WARNING]
FontAwesome 4 icon was referenced as '#{old_key}'.
Use the FontAwesome 5 icon '#{new_key}' instead.
This compatibility layer will be removed in Prawn::Icon 3.0.0.
DEPRECATION
end
end
end
end
# rubocop:enable Metrics/ClassLength
12 changes: 9 additions & 3 deletions lib/prawn/icon/interface.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ module Interface
# inline_format: true
#
def icon(key, opts = {})
key = translate_key(key)
make_icon(key, opts).tap(&:render)
end

Expand All @@ -81,7 +82,8 @@ def icon(key, opts = {})
# the underlying text method call.
#
def make_icon(key, opts = {})
if opts[:inline_format]
key = translate_key(key)
if opts.fetch(:inline_format, false)
inline_icon(key, opts)
else
Icon.new(key, self, opts)
Expand Down Expand Up @@ -151,6 +153,7 @@ def inline_icon(text, opts = {})
# pdf.table(data) => (2 x 2 table)
#
def table_icon(key, opts = {})
key = translate_key(key)
if opts[:inline_format]
content = Icon::Parser.format(self, key)
opts.merge(content: content)
Expand All @@ -161,6 +164,10 @@ def table_icon(key, opts = {})

private

def translate_key(key)
Compatibility.new(key: key).translate
end

def icon_box(content, opts = {}) # :nodoc:
Text::Formatted::Box.new(content, opts).tap do |box|
box.render(dry_run: true)
Expand All @@ -176,8 +183,7 @@ def icon_box(content, opts = {}) # :nodoc:

def initialize(key, document, opts = {})
@pdf = document
@set = opts[:set] ||
FontData.specifier_from_key(key)
@set = opts.fetch(:set) { FontData.specifier_from_key(key) }
@data = FontData.load(document, @set)
@key = strip_specifier_from_key(key)
@unicode = @data.unicode(@key)
Expand Down
9 changes: 4 additions & 5 deletions lib/prawn/icon/parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -57,16 +57,14 @@ def config_from_tokens(tokens)
tokens.each do |token|
# Skip the closing tag
next if token =~ /<\/icon>/i
icon = {}

# Convert [[1,2], [3,4]] to { :1 => 2, :3 => 4 }
attrs = token.scan(ATTR_REGEX).inject({}) do |k, v|
val = attr_hash(v)
k.merge!(val)
end

icon.merge!(attrs)
array << icon
array << attrs
end
end
end
Expand Down Expand Up @@ -101,13 +99,14 @@ def icon_tags(icons)
def keys_to_unicode(document, content, config)
[].tap do |icons|
content.each_with_index do |icon, index|
key = Compatibility.new(key: icon).translate
options ||= {}
options = config[index] if config.any?
info = {
set: FontData.specifier_from_key(icon),
set: FontData.specifier_from_key(key),
size: options[:size],
color: options[:color],
content: FontData.unicode_from_key(document, icon)
content: FontData.unicode_from_key(document, key)
}
icons << info
end
Expand Down
2 changes: 1 addition & 1 deletion lib/prawn/icon/version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@

module Prawn
class Icon
VERSION = '2.0.0'.freeze
VERSION = '2.1.0'.freeze
end
end
44 changes: 44 additions & 0 deletions spec/unit/compatibility_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# encoding: utf-8
#
# Copyright March 2018, Jesse Doyle. All rights reserved.
#
# This is free software. Please see the LICENSE and COPYING files for details.

describe Prawn::Icon::Compatibility do
describe '#translate' do
let(:stderr) { StringIO.new }
subject { described_class.new(key: key) }

context 'with a non-deprecated key' do
let(:key) { 'fas-adjust' }

it 'does not write to STDERR' do
value = subject.translate(stderr)
stderr.rewind
expect(stderr.read).to be_empty
end

it 'returns the original key' do
expect(subject.translate(stderr)).to eq(key)
end
end

context 'with a depreacted FontAwesome key' do
let(:key) { 'fa-birthday-cake' }
let(:mapped_key) { 'fas-birthday-cake' }

it 'writes a deprecation warning to STDERR' do
subject.translate(stderr)
stderr.rewind
errors = stderr.read
expect(errors).to include('DEPRECATION')
expect(errors).to include(key)
expect(errors).to include(mapped_key)
end

it 'returns the mapped key' do
expect(subject.translate(stderr)).to eq(mapped_key)
end
end
end
end

0 comments on commit 51a84ae

Please sign in to comment.