twemoji 0.0.1 → 1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 30d5595bf4c341a2f7b960d79941a08571184fb3
4
- data.tar.gz: 1ba40ad4ea3c925acbca7a7cdd7e3ba1bf3fa9b0
3
+ metadata.gz: 23f6e3897cb5f1b31ad0c451f43db2b9aaa0cc66
4
+ data.tar.gz: ebd4be4bf5d973818ee506f13fc9c4ec79d8ad39
5
5
  SHA512:
6
- metadata.gz: e3d2628da8e26b765f96944e8a93328cfebb747fae0c13fb88db09cf72c1fab1f0d36cb9e4a05c8e3c4f31ff56ee88bb05b0690f77a10da2b7c00ee8963b5e40
7
- data.tar.gz: 9bd3620246f497178f7f6f13997ee83834ee90b005a130a1a787e25cf4726be049700976c1588789d3efe1378fb87412f227a68d5b72f48246d9b035c345dfa4
6
+ metadata.gz: 595e24e32a9371f00baca715dbf793b04327dfda9ef66aae9bba22a5b70b7737ed07fdf6b2e3c4bca8c9f33332bbef0d9a4768cac5ec8c183adcec00fee0f721
7
+ data.tar.gz: 2ba21f666a4831af30563d3d9dd8b494947cf6c7a6969e4c4f8b0e54d8535c066e658ad4ea73abb493f7de6a0196143991ff9f2e22b3d1cb732d8bcd9402a229
@@ -0,0 +1,20 @@
1
+ language: ruby
2
+ sudo: false
3
+ bundler_args: --retry=3 --jobs=3
4
+
5
+ rvm:
6
+ - 2.0
7
+ - 2.1
8
+ - 2.2
9
+ - jruby
10
+ - jruby-19mode
11
+ - jruby-head
12
+ - ruby-head
13
+
14
+ matrix:
15
+ allow_failures:
16
+ - rvm: jruby
17
+ - rvm: jruby-19mode
18
+ - rvm: juby-head
19
+ - rvm: ruby-head
20
+ fast_finish: true
data/Gemfile CHANGED
@@ -6,6 +6,7 @@ gemspec
6
6
  group :development do
7
7
  gem "rake"
8
8
  gem "bundler"
9
+ gem "pry"
9
10
  end
10
11
 
11
12
  group :test do
data/README.md CHANGED
@@ -1,6 +1,12 @@
1
1
  # Twemoji
2
2
 
3
- Get imoji img by text.
3
+ [![Gem Version](http://img.shields.io/gem/v/twemoji.svg)][gem]
4
+ [![Build Status](https://travis-ci.org/jollygoodcode/twemoji.svg)][travis]
5
+
6
+ [gem]: https://rubygems.org/gems/twemoji
7
+ [travis]: https://travis-ci.org/jollygoodcode/twemoji
8
+
9
+ Twitter Emoji has a official JavaScript implementation of [twemoji](https://github.com/twitter/twemoji). This RubyGem Twemoji is a minimum implementation in Ruby, does not implement all its features.
4
10
 
5
11
  ## Installation
6
12
 
@@ -33,24 +39,24 @@ Or install it yourself as:
33
39
 
34
40
  ```ruby
35
41
  > Twemoji.find_by_code("1f60d")
36
- => "1f60d"
42
+ => ":heart_eyes:"
37
43
  ```
38
44
 
39
45
  #### `.find_by` text or code
40
46
 
41
47
  ```ruby
42
- > Twemoji.find_by(text: ':heart_eyes:')
48
+ > Twemoji.find_by(text: ":heart_eyes:")
43
49
  => 1f60d
44
50
 
45
- > Twemoji.find_by(code: '1f60d')
51
+ > Twemoji.find_by(code: "1f60d")
46
52
  => :heart_eyes:
47
53
  ```
48
54
 
49
55
  #### `.parse`
50
56
 
51
57
  ```ruby
52
- > Twemoji.parse 'I like chocolate :heart_eyes:!'
53
- => 'I like chololate <img class="emoji" draggable="false" alt=":heart_eyes:" src="https://twemoji.maxcdn.com/36x36/1f60d.png">'
58
+ > Twemoji.parse "I like chocolate :heart_eyes:!"
59
+ => 'I like chololate <img class="emoji" draggable="false" alt=":heart_eyes:" src="https://twemoji.maxcdn.com/16x16/1f60d.png">'
54
60
  ```
55
61
 
56
62
  ##### asset_root
@@ -58,42 +64,40 @@ Or install it yourself as:
58
64
  Default assets root url, by default will be `https://twemoji.maxcdn.com/`:
59
65
 
60
66
  ```ruby
61
- > Twemoji.parse 'I like chocolate :heart_eyes:!', base: 'foocdn.com'
62
- => 'I like chololate <img class="emoji" draggable="false" alt=":heart_eyes:" src="https://foocdn.com/36x36/1f60d.png">'
67
+ > Twemoji.parse 'I like chocolate :heart_eyes:!', asset_root: "foocdn.com"
68
+ => 'I like chololate <img class="emoji" draggable="false" alt=":heart_eyes:" src="https://foocdn.com/16x16/1f60d.png">'
63
69
  ```
64
70
 
65
71
  ##### file_ext
66
72
 
67
- Default assets file extensions, by default '.svg'.
73
+ Default assets file extensions, by default `.png`.
68
74
 
69
75
  ```ruby
70
- > Twemoji.parse 'I like chocolate :heart_eyes:!', ext: '.png'
71
- => 'I like chololate <img class="emoji" draggable="false" alt=":heart_eyes:" src="https://twemoji.maxcdn.com/16x16/1f60d.png">'
76
+ > Twemoji.parse 'I like chocolate :heart_eyes:!', file_ext: ".svg"
77
+ => 'I like chololate <img class="emoji" draggable="false" alt=":heart_eyes:" src="https://twemoji.maxcdn.com/svg/1f60d.svg">'
72
78
  ```
73
79
 
74
80
  ##### image_size
75
81
 
76
- Default assets/folder size, by default "36x36". Available via Twitter CDN: 16, 36, 72
77
-
78
- Only applicable when file_ext is .png.
82
+ Default assets/folder size, by default `"16x16"`. Available via Twitter CDN: `16`, `36`, `72`.
79
83
 
80
84
  ```ruby
81
- > Twemoji.parse 'I like chocolate :heart_eyes:!', size: "72x72"
82
- => 'I like chololate <img class="emoji" draggable="false" alt=":heart_eyes:" src="https://foocdn.com/72x72/1f60d.png">'
85
+ > Twemoji.parse 'I like chocolate :heart_eyes:!', image_size: "72x72"
86
+ => 'I like chololate <img class="emoji" draggable="false" alt=":heart_eyes:" src="https://twemoji.maxcdn.com/72x72/1f60d.png">'
83
87
  ```
84
88
 
85
89
  ##### class_name
86
90
 
87
- Default img css class name, by default "emoji".
91
+ Default img css class name, by default `"emoji"`.
88
92
 
89
93
  ```ruby
90
- > Twemoji.parse 'I like chocolate :heart_eyes:!', class_name: 'superemoji'
91
- => 'I like chololate <img class="superemoji" draggable="false" alt=":heart_eyes:" src="https://foocdn.com/72x72/1f60d.png">'
94
+ > Twemoji.parse 'I like chocolate :heart_eyes:!', class_name: "superemoji"
95
+ => 'I like chololate <img class="superemoji" draggable="false" alt=":heart_eyes:" src="https://twemoji.maxcdn.com/16x16/1f60d.png">'
92
96
  ```
93
97
 
94
98
  ## Contributing
95
99
 
96
- 1. Fork it ( https://github.com/[my-github-username]/twemoji/fork )
100
+ 1. Fork it ( https://github.com/jollygoodcode/twemoji/fork )
97
101
  2. Create your feature branch (`git checkout -b my-new-feature`)
98
102
  3. Commit your changes (`git commit -am 'Add some feature'`)
99
103
  4. Push to the branch (`git push origin my-new-feature`)
@@ -3,20 +3,23 @@ require "nokogiri"
3
3
  require "twemoji/version"
4
4
  require "twemoji/map"
5
5
 
6
+ # Twemoji is a Ruby implementation, parses your text, replace emoji text
7
+ # with corresponding emoji image. Default emoji images are from Twiiter CDN.
6
8
  module Twemoji
7
9
  # Find code by text and find text by code.
8
10
  #
9
11
  # @example Usage
10
- #
11
12
  # Twemoji.find_by(text: :heart_eyes:) # => "1f60d"
12
- # Twemoji.find_by(code: :1f60d:) # => "heart_eyes"
13
+ # Twemoji.find_by(code: :1f60d:) # => ":heart_eyes:"
13
14
  #
14
15
  # @option options [String] (optional) :text
15
16
  # @option options [String] (optional) :code
16
17
  #
17
- # @return [String] Text or Code
18
+ # @return [String] Text or Code.
18
19
  def self.find_by(*args, text: nil, code: nil)
19
- raise "Can only specify text or code one at a time" if text && code
20
+ if text && code
21
+ raise ArgumentError, "Can only specify text or code one at a time"
22
+ end
20
23
 
21
24
  if text
22
25
  find_by_text text
@@ -25,30 +28,26 @@ module Twemoji
25
28
  end
26
29
  end
27
30
 
28
- # Find emoji code by text
31
+ # Find emoji code by emoji text
29
32
  #
30
33
  # @example Usage
31
- #
32
34
  # Twemoji.find_by_text ":heart_eyes:"
33
35
  # => "1f60d"
34
36
  #
35
- # @param text [String] Text to find emoji code
36
- #
37
- # @return [String] Emoji Code
37
+ # @param text [String] Text to find emoji code.
38
+ # @return [String] Emoji Code.
38
39
  def self.find_by_text(text)
39
40
  CODES[must_str(text)]
40
41
  end
41
42
 
42
- # Find text by emoji code
43
+ # Find emoji text by emoji code.
43
44
  #
44
45
  # @example Usage
45
- #
46
46
  # Twemoji.find_by_code "1f60d"
47
47
  # => ":heart_eyes:"
48
48
  #
49
- # @param code [String] Emoji code to find text
50
- #
51
- # @return [String] Text
49
+ # @param code [String] Emoji code to find text.
50
+ # @return [String] Emoji Text.
52
51
  def self.find_by_code(code)
53
52
  ICODES[must_str(code)]
54
53
  end
@@ -56,63 +55,78 @@ module Twemoji
56
55
  # Parse text, replace emoji text with image.
57
56
  #
58
57
  # @example Usage
59
- #
60
58
  # Twemoji.parse("I like chocolate :heart_eyes:!")
61
59
  # => => 'I like chololate <img class="emoji" draggable="false" alt=":heart_eyes:" src="https://twemoji.maxcdn.com/svg/1f60d.svg">'
62
60
  #
63
- # @param text [String] source text to parse.
61
+ # @param text [String] Source text to parse.
64
62
  #
65
63
  # @option options [String] (optional) asset_root Asset root url to serve emoji.
66
- # @option options [String] (optional) asset_path Folder where you store your emoji images.
67
64
  # @option options [String] (optional) file_ext File extension.
68
65
  # @option options [String] (optional) image_size Emoji image's size 16, 36, 72 applicable if specify .png.
69
66
  # @option options [String] (optional) class_name Emoji image's css class name.
70
67
  #
71
- # @return [String]
68
+ # @return [String] Original text with all occurrences of emoji text
69
+ # replaced by emoji image according to given options.
72
70
  def self.parse(text, asset_root: "https://twemoji.maxcdn.com/",
73
- asset_path: "",
74
- file_ext: ".svg",
71
+ file_ext: ".png",
75
72
  image_size: "16x16",
76
73
  class_name: "emoji")
77
74
 
78
75
  options[:asset_root] = asset_root
79
- options[:asset_path] = asset_path
80
76
  options[:file_ext] = file_ext
81
77
  options[:image_size] = image_size
82
78
  options[:class_name] = class_name
83
79
 
84
- if text.kind_of?(String)
85
- parse_html(text)
86
- else
80
+ if text.kind_of?(Nokogiri::HTML::DocumentFragment)
87
81
  parse_document(text)
82
+ else
83
+ parse_html(text)
88
84
  end
89
85
  end
90
86
 
91
- # Return all emoji patterns' regexp
87
+ # Return all emoji patterns' regular expressions.
88
+ #
89
+ # @return [RegExp] A Regular expression consists of all emojis text.
92
90
  def self.emoji_pattern
93
91
  @emoji_pattern ||= /(#{CODES.keys.each { |name| Regexp.escape(name) }.join("|") })/
94
92
  end
95
93
 
96
94
  private
97
- # Ensure text is string
98
- #
99
- # @param text [String]
95
+
96
+ # Ensure text is a string.
100
97
  #
101
- # @return [String]
98
+ # @param text [String] Text to ensure to be a string.
99
+ # @return [String] A String.
100
+ # @private
102
101
  def self.must_str(text)
103
102
  text = text.respond_to?(:to_str) ? text.to_str : text.to_s
104
103
  end
105
104
 
105
+ # Options hash for Twemoji.
106
+ #
107
+ # @return [Hash] Hash of options.
108
+ # @private
106
109
  def self.options
107
110
  @options ||= {}
108
111
  end
109
112
 
113
+ # Parse a HTML String, replace emoji text with corresponding emoji image.
114
+ #
115
+ # @param text [String] Text string to be parse.
116
+ # @return [String] Text with emoji text replaced by emoji image.
117
+ # @private
110
118
  def self.parse_html(text)
111
119
  return text if !text.include?(":")
112
120
 
113
121
  filter_emojis(text)
114
122
  end
115
123
 
124
+ # Parse a Nokogiri::HTML::DocumentFragment document, replace emoji text
125
+ # with corresponding emoji image.
126
+ #
127
+ # @param doc [Nokogiri::HTML::DocumentFragment] Document to parse.
128
+ # @return [Nokogiri::HTML::DocumentFragment] Parsed document.
129
+ # @private
116
130
  def self.parse_document(doc)
117
131
  doc.search('text()').each do |node|
118
132
  content = node.to_html
@@ -125,25 +139,53 @@ module Twemoji
125
139
  doc
126
140
  end
127
141
 
142
+ # Find out if a node with given exclude tags has ancestors.
143
+ #
144
+ # @param node [Nokogiri::XML::Text] Text node to find ancestor.
145
+ # @param tags [Array] Array of String represents tags.
146
+ # @return [Boolean] If has ancestor returns true, otherwise falsy (nil).
147
+ # @private
148
+ def self.has_ancestor?(node, tags)
149
+ while node = node.parent
150
+ if tags.include?(node.name.downcase)
151
+ break true
152
+ end
153
+ end
154
+ end
155
+
156
+ # Filter emoji text in content, replaced by corresponding emoji image.
157
+ #
158
+ # @param content [String] Contetn to filter emoji text to image.
159
+ # @return [String] Returns a String just like content with all emoji text
160
+ # replaced by the corresponding emoji image.
161
+ # @private
128
162
  def self.filter_emojis(content)
129
163
  content.gsub(emoji_pattern) { |match| img_tag(match) }
130
164
  end
131
165
 
166
+ # Returns emoji image by given name and options from `Twemoji.parse`.
167
+ #
168
+ # @param name [String] Emoji name to generate image tag.
169
+ # @return [String] Emoji image tag generated by name and options.
170
+ # @private
132
171
  def self.img_tag(name)
133
172
  "<img class='#{options[:class_name]}' draggable='false' title='#{name}' alt='#{name}' src='#{emoji_url(name)}'>"
134
173
  end
135
174
 
175
+ # Returns emoji url by given name and options from `Twemoji.parse`.
176
+ #
177
+ # @param name [String] Emoji name to generate image url.
178
+ # @return [String] Emoji image tag generated by name and options.
179
+ # @private
136
180
  def self.emoji_url(name)
137
181
  code = find_by_text(name)
138
182
 
139
- if options[:file_ext] == ".svg"
140
- File.join(options[:asset_root], "svg", "#{code}.svg")
141
- elsif !options[:asset_path].empty?
142
- File.join(options[:asset_root], options[:asset_path], "#{code}.#{options[:file_ext]}")
143
- elsif options[:file_ext] == ".png"
183
+ if options[:file_ext] == ".png"
144
184
  File.join(options[:asset_root], options[:image_size], "#{code}.png")
185
+ elsif options[:file_ext] == ".svg"
186
+ File.join(options[:asset_root], "svg", "#{code}.svg")
145
187
  else
146
- File.join(options[:asset_root], options[:image_size], "#{code}.#{options[:file_ext]}")
188
+ raise RuntimeError, "Unspported file extension: #{options[:file_ext]}"
147
189
  end
148
190
  end
149
191
  end
@@ -1,14 +1,11 @@
1
1
  module Twemoji
2
- # String to hex map
3
- #
4
- # This hash is frozen.
2
+ # Emoji Text to Codepoint mappings. This hash is frozen.
5
3
  #
6
4
  # @example Usage
7
- #
8
5
  # CODES[:smile:] # => "1f604"
9
6
  # CODES[:notebook_with_decorative_cover:] # => "1f4d4"
10
- #
11
7
  # @return [Hash<String => String>]
8
+ # @private
12
9
  CODES = {
13
10
  ":smile:" => "1f604",
14
11
  ":laughing:" => "1f606",
@@ -839,15 +836,13 @@ module Twemoji
839
836
  ":zero:" => "30-20e3"
840
837
  }.each { | k, v| k.freeze; v.freeze }.freeze
841
838
 
842
- # Hex to string map
843
- #
844
- # This hash is frozen.
839
+ # Emoji Codepoint to Text mappings. This hash is frozen.
845
840
  #
846
841
  # @example Usage
847
- #
848
842
  # ICODES["1f60d"] # => ":heart_eyes:"
849
843
  # ICODES["1f4d4"] # => ":notebook_with_decorative_cover:"
850
844
  #
851
845
  # @return [Hash<String => String>]
846
+ # @private
852
847
  ICODES = CODES.invert.freeze
853
848
  end
@@ -1,3 +1,3 @@
1
1
  module Twemoji
2
- VERSION = "0.0.1"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -21,19 +21,60 @@ class TwemojiTest < Minitest::Test
21
21
  assert_equal ":heart_eyes:", Twemoji.find_by(code: "1f60d")
22
22
  end
23
23
 
24
- def test_emoji_pattern
25
- assert_kind_of Regexp, Twemoji.emoji_pattern
24
+ def test_finder_methods_cannot_find_by_both
25
+ exception = assert_raises ArgumentError do
26
+ Twemoji.find_by(text: ":heart_eyes:", code: "1f60d")
27
+ end
28
+
29
+ assert_equal "Can only specify text or code one at a time", exception.message
30
+ end
31
+
32
+ def test_parse_html_string
33
+ expected = "I like chocolate <img class='emoji' draggable='false' title=':heart_eyes:' alt=':heart_eyes:' src='https://twemoji.maxcdn.com/16x16/1f60d.png'>!"
34
+
35
+ assert_equal expected, Twemoji.parse("I like chocolate :heart_eyes:!")
36
+ end
37
+
38
+ def test_parse_document
39
+ doc = Nokogiri::HTML::DocumentFragment.parse("<p>I like chocolate :heart_eyes:!</p>")
40
+ expected = '<p>I like chocolate <img class="emoji" draggable="false" title=":heart_eyes:" alt=":heart_eyes:" src="https://twemoji.maxcdn.com/16x16/1f60d.png">!</p>'
41
+
42
+ assert_equal expected, Twemoji.parse(doc).to_html
43
+ end
44
+
45
+ def test_parse_option_asset_root
46
+ expected = "I like chocolate <img class='emoji' draggable='false' title=':heart_eyes:' alt=':heart_eyes:' src='https://emoji.bestcdn.com/16x16/1f60d.png'>!"
47
+
48
+ assert_equal expected, Twemoji.parse("I like chocolate :heart_eyes:!", asset_root: 'https://emoji.bestcdn.com')
26
49
  end
27
50
 
28
- def test_parse
51
+ def test_parse_option_file_ext_svg
29
52
  expected = "I like chocolate <img class='emoji' draggable='false' title=':heart_eyes:' alt=':heart_eyes:' src='https://twemoji.maxcdn.com/svg/1f60d.svg'>!"
30
53
 
31
- assert_equal expected, Twemoji.parse('I like chocolate :heart_eyes:!')
54
+ assert_equal expected, Twemoji.parse("I like chocolate :heart_eyes:!", file_ext: '.svg')
55
+ end
56
+
57
+ def test_parse_option_unsupport_file_ext_gif
58
+ exception = assert_raises RuntimeError do
59
+ Twemoji.parse("I like chocolate :heart_eyes:!", file_ext: '.gif')
60
+ end
61
+
62
+ assert_equal "Unspported file extension: .gif", exception.message
32
63
  end
33
64
 
34
- def test_parse_with_different_cdn
35
- expected = "I like chocolate <img class='emoji' draggable='false' title=':heart_eyes:' alt=':heart_eyes:' src='https://emoji.bestcdn.com/svg/1f60d.svg'>!"
65
+ def test_parse_option_image_size
66
+ expected = "I like chocolate <img class='emoji' draggable='false' title=':heart_eyes:' alt=':heart_eyes:' src='https://twemoji.maxcdn.com/72x72/1f60d.png'>!"
67
+
68
+ assert_equal expected, Twemoji.parse("I like chocolate :heart_eyes:!", file_ext: ".png", image_size: "72x72")
69
+ end
36
70
 
37
- assert_equal expected, Twemoji.parse('I like chocolate :heart_eyes:!', asset_root: 'https://emoji.bestcdn.com')
71
+ def test_parse_option_class_name
72
+ expected = "I like chocolate <img class='twemoji' draggable='false' title=':heart_eyes:' alt=':heart_eyes:' src='https://twemoji.maxcdn.com/16x16/1f60d.png'>!"
73
+
74
+ assert_equal expected, Twemoji.parse("I like chocolate :heart_eyes:!", class_name: 'twemoji')
75
+ end
76
+
77
+ def test_emoji_pattern
78
+ assert_kind_of Regexp, Twemoji.emoji_pattern
38
79
  end
39
80
  end
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
10
10
  spec.email = %w(katehuang0320@gmail.com)
11
11
  spec.summary = %q{A RubyGem to convert :heart: to Twitter cdn url}
12
12
  spec.description = spec.summary
13
- spec.homepage = "https://github.com/JuanitoFatas/twemoji"
13
+ spec.homepage = "https://github.com/jollygoodcode/twemoji"
14
14
  spec.license = "MIT"
15
15
 
16
16
  spec.files = `git ls-files -z`.split("\x0")
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: twemoji
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Juanito
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-01-11 00:00:00.000000000 Z
12
+ date: 2015-01-12 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: nokogiri
@@ -33,6 +33,7 @@ extensions: []
33
33
  extra_rdoc_files: []
34
34
  files:
35
35
  - ".gitignore"
36
+ - ".travis.yml"
36
37
  - Gemfile
37
38
  - LICENSE
38
39
  - README.md
@@ -43,7 +44,7 @@ files:
43
44
  - test/test_helper.rb
44
45
  - test/twemoji_test.rb
45
46
  - twemoji.gemspec
46
- homepage: https://github.com/JuanitoFatas/twemoji
47
+ homepage: https://github.com/jollygoodcode/twemoji
47
48
  licenses:
48
49
  - MIT
49
50
  metadata: {}