emoji_data 0.0.3 β†’ 0.1.0.rc1

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
2
  SHA1:
3
- metadata.gz: c7a2b01097e18162bdb426c05bfb76f871ca7f39
4
- data.tar.gz: 5e75e18ab2252aab634cd17863a6b7cbb471119b
3
+ metadata.gz: 7c2cca7a834cd49e348c09b50c042596f93f5076
4
+ data.tar.gz: 8402df0f4d2d828ec9ed322d093da13602a4d64c
5
5
  SHA512:
6
- metadata.gz: 23f834f7c47f8015bf14a80623cdaf95ebfd45a2d33f9eeeda0434232146311c439b895476ac7b65382e12c0a8b7038cd7508b6352871d643474acf20f32d838
7
- data.tar.gz: 7a93b457a18d7bfec72cf3914527a9426abe03aab8b186812b6e7d8fd3cf3ee576cf57c1f88ba415862ce10dba388215e014e10f204ad625d52d6e1e2aeb6526
6
+ metadata.gz: 95dba4e1fbb80d741b5c535b091ecf60fd6666c0a810f6e69eaf15a64a13aab72eae8b1b5b1969b3b8d5894bf5f4dd646261a1560a28b02ef331678dbf8481c7
7
+ data.tar.gz: fdebfa5d68128ec34273fd4e21192e0203fd2f377a2c083b9282688bc205500b65f69fc410ffa6cc4f80133623bff0bac0e090352177f10cd5702b557ad86814
@@ -0,0 +1,2 @@
1
+ service_name: travis-ci
2
+
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.0 (Pending)
4
+
5
+ * Add support for Unicode variant encodings, used by MacOSX 10.9 / iOS 7.
6
+ - For more info: http://www.unicode.org/L2/L2011/11438-emoji-var.pdf
7
+ - By default, `EmojiChar.to_s()` and `.char()` will now use the variant encoding.
8
+ * Import latest version of iamcal/emoji-data.
9
+ * 100% test coverage. :sunglasses:
10
+
3
11
  ## 0.0.3 (1 April 2013)
4
12
 
5
13
  * On initialization, create hashmaps to cache lookups for `.find_by_unified()`.
data/README.md CHANGED
@@ -1,13 +1,17 @@
1
1
  # emoji_data.rb
2
2
 
3
- [![Gem Version](https://badge.fury.io/rb/emoji_data.png)](http://badge.fury.io/rb/emoji_data)
4
- [![Build Status](https://travis-ci.org/mroth/emoji_data.rb.png?branch=master)](https://travis-ci.org/mroth/emoji_data.rb)
3
+ [![Gem Version](http://img.shields.io/gem/v/emoji_data.svg?style=flat)](https://rubygems.org/gems/emoji_data)
4
+ [![Build Status](http://img.shields.io/travis/mroth/emoji_data.rb.svg?style=flat)](https://travis-ci.org/mroth/emoji_data.rb)
5
+ [![Dependency Status](http://img.shields.io/gemnasium/mroth/emoji_data.rb.svg?style=flat)](https://gemnasium.com/mroth/emoji_data.rb)
6
+ [![CodeClimate Status](http://img.shields.io/codeclimate/github/mroth/emoji_data.rb.svg?style=flat)](https://codeclimate.com/github/mroth/emoji_data.rb)
7
+ [![Coverage Status](http://img.shields.io/coveralls/mroth/emoji_data.rb.svg?style=flat)](https://coveralls.io/r/mroth/emoji_data.rb)
8
+
5
9
 
6
10
  Provides classes and helpers for dealing with emoji character data as unicode. Wraps a library of all known emoji characters and provides convenience methods.
7
11
 
8
- Note, this is mostly useful for low-level operations. If you can avoid having to deal with unicode character data extensively and just want to encode/decode stuff, [rumoji](https://github.com/mwunsch/rumoji) might be a better bet for you.
12
+ Note, this is mostly useful for low-level operations. If you can avoid having to deal with unicode character data extensively and just want to encode/decode stuff, [rumoji](https://github.com/mwunsch/rumoji) might be a better bet for you. If however, you are doing anything complicated involving emoji encoding/decoding, or you are just obsessed with understanding the details, this library is your new best friend.
9
13
 
10
- This library currently uses `iamcal/emoji-data` as it's library dataset, and thus considers it to be the "source of truth" regarding certain things, such as how to represent doublebyte unified codepoint IDs as strings (seperated by a dash).
14
+ This library currently uses `iamcal/emoji-data` as it's dataset, and thus considers it to be the "source of truth" regarding certain things, such as how to represent doublebyte unified codepoint IDs as strings (seperated by a dash).
11
15
 
12
16
  This is basically a helper library for my [emojitrack](https://github.com/mroth/emojitrack) and [emojistatic](https://github.com/mroth/emojistatic) projects, but may be useful for other people.
13
17
 
@@ -25,7 +29,7 @@ Or install it yourself as:
25
29
 
26
30
  $ gem install emoji_data
27
31
 
28
- Currently requires Ruby 1.9 or more recent.
32
+ Currently requires `RUBY_VERSION >= 1.9.2`.
29
33
 
30
34
  ## Library Usage
31
35
 
@@ -64,5 +68,3 @@ Some notable methods to call out:
64
68
  `EmojiData::EmojiChar` is a class representing a single emoji character. All the variables from the `iamcal/emoji-data` dataset have dynamically generated getter methods.
65
69
 
66
70
  There are some additional convenience methods, such as `#doublebyte?` etc. Most important addition is the `#char` method which will output a properly unicode encoded string containing the character.
67
-
68
-
@@ -21,6 +21,8 @@ Gem::Specification.new do |spec|
21
21
  spec.add_development_dependency "bundler", "~> 1.3"
22
22
  spec.add_development_dependency "rake"
23
23
  spec.add_development_dependency "rspec"
24
+ spec.add_development_dependency 'simplecov', '~> 0.7.1'
25
+ spec.add_development_dependency 'coveralls', '~> 0.7.0'
24
26
 
25
27
  spec.required_ruby_version = '>= 1.9.2'
26
28
  end
@@ -8,19 +8,48 @@ module EmojiData
8
8
  EMOJI_MAP = JSON.parse( RAW_JSON )
9
9
  EMOJI_CHARS = EMOJI_MAP.map { |em| EmojiChar.new(em) }
10
10
 
11
- # hashmap for fast unified lookups
11
+ #
12
+ # construct hashmap for fast precached lookups for `.find_by_unified`
13
+ #
12
14
  EMOJICHAR_UNIFIED_MAP = Hash[EMOJI_CHARS.map { |u| [u.unified, u] }]
15
+ # merge variant encodings into map so we can look them up as well
16
+ EMOJI_CHARS.select(&:variant?).each do |char|
17
+ char.variations.each do |variant|
18
+ EMOJICHAR_UNIFIED_MAP.merge! Hash[variant,char]
19
+ end
20
+ end
13
21
 
14
22
  def self.all
15
23
  EMOJI_CHARS
16
24
  end
17
25
 
18
- def self.chars
19
- @chars ||= EMOJI_CHARS.map(&:char)
26
+ def self.all_doublebyte
27
+ EMOJI_CHARS.select(&:doublebyte?)
28
+ end
29
+
30
+ def self.all_with_variants
31
+ EMOJI_CHARS.select(&:variant?)
32
+ end
33
+
34
+ def self.chars(options={})
35
+ options = {include_variants: false}.merge(options)
36
+
37
+ normals = EMOJI_CHARS.map { |c| c.char({variant_encoding: false}) }
38
+ extras = self.all_with_variants.map { |c| c.char({variant_encoding: true}) }
39
+
40
+ if options[:include_variants]
41
+ return normals + extras
42
+ end
43
+ normals
20
44
  end
21
45
 
22
- def self.codepoints
23
- @codepoints ||= EMOJI_CHARS.map(&:unified)
46
+ def self.codepoints(options={})
47
+ options = {include_variants: false}.merge(options)
48
+
49
+ if options[:include_variants]
50
+ return EMOJI_CHARS.map(&:unified) + self.all_with_variants.map {|c| c.variant}
51
+ end
52
+ EMOJI_CHARS.map(&:unified)
24
53
  end
25
54
 
26
55
  def self.char_to_unified(char)
@@ -28,26 +57,25 @@ module EmojiData
28
57
  end
29
58
 
30
59
  def self.unified_to_char(cp)
31
- find_by_unified(cp).char
60
+ EmojiChar::unified_to_char(cp)
32
61
  end
33
62
 
34
63
  def self.find_by_unified(cp)
35
- # EMOJI_CHARS.detect { |ec| ec.unified == cp.upcase }
36
64
  EMOJICHAR_UNIFIED_MAP[cp.upcase]
37
65
  end
38
66
 
39
67
  def self.find_by_str(str)
40
- matches = EMOJI_CHARS.select { |ec| str.include? ec.char }
41
- matches.sort_by { |matched_char| str.index(matched_char.char) }
68
+ str.extend EmojiData::StringUtils
69
+
70
+ matches = EMOJI_CHARS.select { |ec| str.include_any? ec.chars }
71
+ matches.sort_by { |mc| str.index_first(mc.chars) }
42
72
  end
43
73
 
44
74
  def self.find_by_name(name)
45
- # self.all.select { |char| char.name.include? name.upcase }
46
75
  self.find_by_value(:name, name.upcase)
47
76
  end
48
77
 
49
78
  def self.find_by_short_name(short_name)
50
- # self.all.select { |char| char.short_name.include? name.downcase }
51
79
  self.find_by_value(:short_name, short_name.downcase)
52
80
  end
53
81
 
@@ -56,4 +84,17 @@ module EmojiData
56
84
  self.all.select { |char| char.send(field).include? value }
57
85
  end
58
86
 
87
+ module StringUtils
88
+ def include_any?(charstr)
89
+ charstr.any? { |char| self.include? char }
90
+ end
91
+
92
+ def index_first(charstr)
93
+ charstr.each do |char|
94
+ return self.index(char) if !self.index(char).nil?
95
+ end
96
+ nil
97
+ end
98
+ end
99
+
59
100
  end
@@ -2,6 +2,11 @@ module EmojiData
2
2
 
3
3
  class EmojiChar
4
4
  def initialize(emoji_hash)
5
+ # work around inconsistency in emoji.json for now by just setting a blank
6
+ # array for instance value, and let it get overriden in main
7
+ # deserialization loop if variable is present.
8
+ @variations = []
9
+
5
10
  # http://stackoverflow.com/questions/1615190/declaring-instance-variables-iterating-over-a-hash
6
11
  emoji_hash.each do |k,v|
7
12
  instance_variable_set("@#{k}",v)
@@ -10,9 +15,25 @@ module EmojiData
10
15
  end
11
16
  end
12
17
 
13
- # Public: Returns a version of the character for rendering to screen.
14
- def char
15
- @char ||= @unified.split('-').map { |i| i.hex }.pack("U*")
18
+ # Returns a version of the character for rendering to screen.
19
+ #
20
+ # By default this will now use the variant encoding if it exists.
21
+ def char(options = {})
22
+ options = {variant_encoding: true}.merge(options)
23
+ #decide whether to use the normal unified ID or the variant for encoding to str
24
+ target = (self.variant? && options[:variant_encoding]) ? self.variant : @unified
25
+ EmojiChar::unified_to_char(target)
26
+ end
27
+
28
+ # Return ALL known possible string encodings of the emoji char.
29
+ #
30
+ # Mostly useful for doing find operations when you need them all.
31
+ def chars
32
+ results = [self.char({variant_encoding: false})]
33
+ @variations.each do |variation|
34
+ results << EmojiChar::unified_to_char(variation)
35
+ end
36
+ @chars ||= results
16
37
  end
17
38
 
18
39
  # Public: Is the character represented by a doublebyte unicode codepoint in unicode?
@@ -20,7 +41,25 @@ module EmojiData
20
41
  @unified.match(/-/)
21
42
  end
22
43
 
44
+ # does the emojichar have an alternate variant encoding?
45
+ def variant?
46
+ @variations.length > 0
47
+ end
48
+
49
+ # return whatever is the most likely variant ID for the emojichar
50
+ # for now, there can only be one, so just return first.
51
+ # (in the future, there may be multiple variants, who knows!)
52
+ def variant
53
+ @variations.first
54
+ end
55
+
23
56
  alias_method :to_s, :char
57
+
58
+ protected
59
+ def self.unified_to_char(cps)
60
+ cps.split('-').map { |i| i.hex }.pack("U*")
61
+ end
62
+
24
63
  end
25
64
 
26
65
  end
@@ -1,3 +1,3 @@
1
1
  module EmojiData
2
- VERSION = "0.0.3"
2
+ VERSION = "0.1.0.rc1"
3
3
  end
@@ -4,18 +4,19 @@ require 'spec_helper'
4
4
  describe EmojiChar do
5
5
  describe ".new" do
6
6
  before(:all) do
7
- poop_json = %q/{"name":"PILE OF POO","unified":"1F4A9","docomo":"","au":"E4F5","softbank":"E05A","google":"FE4F4","image":"1f4a9.png","sheet_x":13,"sheet_y":19,"short_name":"hankey","short_names":["hankey","poop","shit"],"text":null}/
7
+ poop_json = %q/{"name":"PILE OF POO","unified":"1F4A9","variations":[],"docomo":"","au":"E4F5","softbank":"E05A","google":"FE4F4","image":"1f4a9.png","sheet_x":11,"sheet_y":19,"short_name":"hankey","short_names":["hankey","poop","shit"],"text":null}/
8
8
  @poop = EmojiChar.new(JSON.parse poop_json)
9
9
  end
10
10
  it "should create instance getters for all key-values in emoji.json, with blanks as nil" do
11
11
  @poop.name.should eq('PILE OF POO')
12
12
  @poop.unified.should eq('1F4A9')
13
+ @poop.variations.should eq([])
13
14
  @poop.docomo.should eq('')
14
15
  @poop.au.should eq('E4F5')
15
16
  @poop.softbank.should eq('E05A')
16
17
  @poop.google.should eq('FE4F4')
17
18
  @poop.image.should eq('1f4a9.png')
18
- @poop.sheet_x.should eq(13)
19
+ @poop.sheet_x.should eq(11)
19
20
  @poop.sheet_y.should eq(19)
20
21
  @poop.short_name.should eq('hankey')
21
22
  @poop.short_names.should eq(["hankey","poop","shit"])
@@ -25,8 +26,10 @@ describe EmojiChar do
25
26
 
26
27
  context "instance methods" do
27
28
  before(:all) do
28
- @invader = EmojiChar.new({'unified' => '1F47E'})
29
- @usflag = EmojiChar.new({'unified' => '1F1FA-1F1F8'})
29
+ @invader = EmojiChar.new({'unified' => '1F47E'})
30
+ @usflag = EmojiChar.new({'unified' => '1F1FA-1F1F8'})
31
+ @hourglass = EmojiChar.new({'unified' => '231B', 'variations' => ['231B-FE0F']})
32
+ @cloud = EmojiChar.new({'unified' => '2601', 'variations' => ['2601-FE0F']})
30
33
  end
31
34
 
32
35
  describe "#to_s" do
@@ -42,6 +45,23 @@ describe EmojiChar do
42
45
  it "should render as happy shiny unicode for doublebyte chars too" do
43
46
  @usflag.char.should eq("πŸ‡ΊπŸ‡Έ")
44
47
  end
48
+ it "should have a flag to output forced emoji variant char encoding if requested" do
49
+ @cloud.char( {variant_encoding: false}).should eq("\u{2601}")
50
+ @cloud.char( {variant_encoding: true}).should eq("\u{2601}\u{FE0F}")
51
+ @invader.char( {variant_encoding: false}).should eq("\u{1F47E}")
52
+ @invader.char( {variant_encoding: true}).should eq("\u{1F47E}")
53
+ end
54
+ it "should default to variant encoding for chars with a variant present" do
55
+ @cloud.char.should eq("\u{2601}\u{FE0F}")
56
+ @hourglass.char.should eq("\u{231B}\u{FE0F}")
57
+ end
58
+ end
59
+
60
+ describe "#chars" do
61
+ it "should return an array of all possible string render variations" do
62
+ @invader.chars.should eq(["\u{1F47E}"])
63
+ @cloud.chars.should eq(["\u{2601}","\u{2601}\u{FE0F}"])
64
+ end
45
65
  end
46
66
 
47
67
  describe "#doublebyte?" do
@@ -50,5 +70,21 @@ describe EmojiChar do
50
70
  @invader.doublebyte?.should be_false
51
71
  end
52
72
  end
73
+
74
+ describe "#variant?" do
75
+ it "should indicate when a character has an alternate variant encoding" do
76
+ @hourglass.variant?.should be_true
77
+ @usflag.variant?.should be_false
78
+ end
79
+ end
80
+
81
+ describe "#variant" do
82
+ it "should return the most likely variant encoding ID representation for the char" do
83
+ @hourglass.variant.should eq('231B-FE0F')
84
+ end
85
+ it "should return nil if no variant encoding for the char exists" do
86
+ @usflag.variant.should be_nil
87
+ end
88
+ end
53
89
  end
54
- end
90
+ end
@@ -3,18 +3,65 @@ require 'spec_helper'
3
3
 
4
4
  describe EmojiData do
5
5
  describe ".all" do
6
- it "should return an array of all known emoji chars" do
7
- EmojiData.all.count.should eq(842)
6
+ it "should return an array of all 845 known emoji chars" do
7
+ EmojiData.all.count.should eq(845)
8
8
  end
9
9
  it "should return all EmojiChar objects" do
10
10
  EmojiData.all.all? {|char| char.class == EmojiData::EmojiChar}.should be_true
11
11
  end
12
12
  end
13
13
 
14
+ describe ".all_doublebyte" do
15
+ it "should return an array of all 21 known emoji chars with doublebyte encoding" do
16
+ EmojiData.all_doublebyte.count.should eq(21)
17
+ end
18
+ end
19
+
20
+ describe ".all_with_variants" do
21
+ it "should return an array of all 107 known emoji chars with variant encodings" do
22
+ EmojiData.all_with_variants.count.should eq(107)
23
+ end
24
+ end
25
+
26
+ describe ".chars" do
27
+ it "should return an array of all chars in unicode string format" do
28
+ EmojiData.chars.all? {|char| char.class == String}.should be_true
29
+ end
30
+ it "should by default return one entry per known EmojiChar" do
31
+ EmojiData.chars.count.should eq(EmojiData.all.count)
32
+ end
33
+ it "should include variants in list when options {include_variants: true}" do
34
+ results = EmojiData.chars({include_variants: true})
35
+ numChars = EmojiData.all.count
36
+ numVariants = EmojiData.all_with_variants.count
37
+ results.count.should eq(numChars + numVariants)
38
+ end
39
+ it "should not have any duplicates in list when variants are included" do
40
+ results = EmojiData.chars({include_variants: true})
41
+ results.count.should eq(results.uniq.count)
42
+ end
43
+ end
44
+
45
+ describe ".codepoints" do
46
+ it "should return an array of all known codepoints in dashed string representation" do
47
+ EmojiData.codepoints.all? {|cp| cp.class == String}.should be_true
48
+ EmojiData.codepoints.all? {|cp| cp.match(/^[0-9A-F\-]{4,11}$/)}.should be_true
49
+ end
50
+ it "should include variants in list when options {include_variants: true}" do
51
+ results = EmojiData.codepoints({include_variants: true})
52
+ numChars = EmojiData.all.count
53
+ numVariants = EmojiData.all_with_variants.count
54
+ results.count.should eq(numChars + numVariants)
55
+ results.all? {|cp| cp.match(/^[0-9A-F\-]{4,16}$/)}.should be_true
56
+ end
57
+ end
58
+
14
59
  describe ".find_by_str" do
15
60
  before(:all) do
16
- @exact_results = EmojiData.find_by_str("πŸš€")
17
- @multi_results = EmojiData.find_by_str("flying on my πŸš€ to visit the πŸ‘Ύ people.")
61
+ @exact_results = EmojiData.find_by_str("πŸš€")
62
+ @multi_results = EmojiData.find_by_str("flying on my πŸš€ to visit the πŸ‘Ύ people.")
63
+ @variant_results = EmojiData.find_by_str("\u{0023}\u{FE0F}\u{20E3}")
64
+ @variant_multi = EmojiData.find_by_str("first a \u{0023}\u{FE0F}\u{20E3} then a πŸš€")
18
65
  end
19
66
  it "should find the proper EmojiChar object from a single string char" do
20
67
  @exact_results.should be_kind_of(Array)
@@ -22,6 +69,10 @@ describe EmojiData do
22
69
  @exact_results.first.should be_kind_of(EmojiChar)
23
70
  @exact_results.first.name.should eq('ROCKET')
24
71
  end
72
+ it "should find the proper EmojiChar object from a variant encoded char" do
73
+ @variant_results.length.should eq(1)
74
+ @variant_results.first.name.should eq('HASH KEY')
75
+ end
25
76
  it "should match multiple chars from within a string" do
26
77
  @multi_results.should be_kind_of(Array)
27
78
  @multi_results.length.should eq(2)
@@ -32,6 +83,10 @@ describe EmojiData do
32
83
  @multi_results[0].name.should eq('ROCKET')
33
84
  @multi_results[1].name.should eq('ALIEN MONSTER')
34
85
  end
86
+ it "should return multiple matches in the proper order for variant encodings" do
87
+ @variant_multi[0].name.should eq('HASH KEY')
88
+ @variant_multi[1].name.should eq('ROCKET')
89
+ end
35
90
  end
36
91
 
37
92
  describe ".find_by_unified" do
@@ -40,9 +95,14 @@ describe EmojiData do
40
95
  results.should be_kind_of(EmojiChar)
41
96
  results.name.should eq('ROCKET')
42
97
  end
43
- it "should normallise capitalization for hex values" do
98
+ it "should normalise capitalization for hex values" do
44
99
  EmojiData.find_by_unified('1f680').should_not be_nil
45
100
  end
101
+ it "should find via variant encoding ID format as well" do
102
+ results = EmojiData.find_by_unified('2764-fe0f')
103
+ results.should_not be_nil
104
+ results.name.should eq('HEAVY BLACK HEART')
105
+ end
46
106
  end
47
107
 
48
108
  describe ".find_by_name" do
@@ -78,6 +138,9 @@ describe EmojiData do
78
138
  EmojiData.char_to_unified("πŸ‡ΊπŸ‡Έ").should eq('1F1FA-1F1F8')
79
139
  EmojiData.char_to_unified("#⃣").should eq('0023-20E3')
80
140
  end
141
+ it "converts variant encoded emoji to variant unified codepoint" do
142
+ EmojiData.char_to_unified("\u{2601}\u{FE0F}").should eq('2601-FE0F')
143
+ end
81
144
  end
82
145
 
83
146
  # TODO: below is kinda redundant but it is helpful as a helper method so maybe still test
@@ -90,5 +153,11 @@ describe EmojiData do
90
153
  EmojiData.unified_to_char('1F1FA-1F1F8').should eq("πŸ‡ΊπŸ‡Έ")
91
154
  EmojiData.unified_to_char('0023-20E3').should eq("#⃣")
92
155
  end
156
+ it "converts variant unified codepoints to unicode strings" do
157
+ EmojiData.unified_to_char('2764-fe0f').should eq("\u{2764}\u{FE0F}")
158
+ end
159
+ it "converts variant+doublebyte chars (triplets!) to unicode strings" do
160
+ EmojiData.unified_to_char('0030-FE0F-20E3').should eq("\u{0030}\u{FE0F}\u{20E3}")
161
+ end
93
162
  end
94
- end
163
+ end