emoji_data 0.0.3 β†’ 0.1.0.rc1

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