jekyll-emoji 0.1.4 → 0.1.5
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 +4 -4
- data/README.md +10 -4
- data/lib/jekyll/emoji.rb +3 -242
- data/lib/jekyll/emoji/converter.rb +386 -0
- data/lib/jekyll/emoji/filter.rb +30 -0
- data/lib/jekyll/emoji/version.rb +1 -1
- data/tests/conversion_test.rb +5 -5
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fa05cb9d3d721a154defea59300d2091a943aace
|
4
|
+
data.tar.gz: 5cdfae6341a486064fa2ab6abcdb05d3a6501d1d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5279d5dd2b413b01fda17517d0b5a2402d29b99a2b444487d888bddb4fb1c9fa01b2689dfa00c8363283442d1096cd9ba41e22c7b7703b54835106444dcc58b2
|
7
|
+
data.tar.gz: 680a167683ebec39347fc7fe10d50f936ecff530b9caf00bb55a39538b0d7577f1d26fd24898e8c83243135766ebb0bf0bfbe225dc6caa0592c7e3043e21aa56
|
data/README.md
CHANGED
@@ -48,10 +48,6 @@ There's also a Liquid filter called `emojify`. It accepts three parameters: `for
|
|
48
48
|
{{ ":kissing_heart: :heart: :stuck_out_tongue:" | emojify }}
|
49
49
|
```
|
50
50
|
|
51
|
-
## Development
|
52
|
-
|
53
|
-
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
54
|
-
|
55
51
|
## Known Issues
|
56
52
|
|
57
53
|
### `emojify` filter performance
|
@@ -74,10 +70,20 @@ When the `emojify` filter is used inside a markdown file (say, a blog post), and
|
|
74
70
|
|
75
71
|
This is due to the fact that HTML encoding is done in a post-processing step to simplify and speed up the implementation.
|
76
72
|
|
73
|
+
## Development
|
74
|
+
|
75
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
76
|
+
|
77
77
|
## Contributing
|
78
78
|
|
79
79
|
Bug reports and pull requests are welcome on GitHub at https://github.com/omninonsense/jekyll-emoji. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](contributor-covenant.org) code of conduct.
|
80
80
|
|
81
|
+
## Thanks
|
82
|
+
|
83
|
+
The following parties deserve my gratitude:
|
84
|
+
- [Emoji One](http://emojione.com/) for creating emojis that I actually *like*, as opposed to not mind.
|
85
|
+
- [@YorickPeterse](https://github.com/YorickPeterse) for introducing me to [Oga](https://github.com/YorickPeterse).
|
86
|
+
It was <3></3> at first sight!
|
81
87
|
|
82
88
|
## License
|
83
89
|
|
data/lib/jekyll/emoji.rb
CHANGED
@@ -1,245 +1,6 @@
|
|
1
|
-
require "jekyll/emoji/version"
|
2
1
|
require 'oga'
|
3
2
|
require 'yajl'
|
4
3
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
safe true
|
9
|
-
priority :lowest
|
10
|
-
|
11
|
-
Defaults = {
|
12
|
-
'format' => 'html',
|
13
|
-
'ascii' => false,
|
14
|
-
'shortname' => true
|
15
|
-
}.freeze
|
16
|
-
|
17
|
-
Attribute_blacklist = %w{
|
18
|
-
data-no-emoji
|
19
|
-
data-no-emojis
|
20
|
-
}
|
21
|
-
|
22
|
-
Class_blacklist = %w{
|
23
|
-
no-emoji
|
24
|
-
no-emojis
|
25
|
-
|
26
|
-
no_emoji
|
27
|
-
no_emojis
|
28
|
-
}
|
29
|
-
|
30
|
-
Element_blacklist = %w{
|
31
|
-
code
|
32
|
-
pre
|
33
|
-
}
|
34
|
-
|
35
|
-
def initialize(conf = nil)
|
36
|
-
parser = Yajl::Parser.new
|
37
|
-
|
38
|
-
@@site_conf = conf
|
39
|
-
configure(@@site_conf)
|
40
|
-
|
41
|
-
formats = %w{
|
42
|
-
html
|
43
|
-
unicode
|
44
|
-
emojione-png
|
45
|
-
emojione-svg
|
46
|
-
}
|
47
|
-
|
48
|
-
if !formats.include? @conf['format']
|
49
|
-
raise(ArgumentError, "Unknown emoji format: '#{@conf['format']}'; Supported formats are: #{formats}")
|
50
|
-
end
|
51
|
-
|
52
|
-
@emoji_map = {}
|
53
|
-
@encoding_map = {}
|
54
|
-
|
55
|
-
@shortname_aliases = []
|
56
|
-
@ascii_aliases = []
|
57
|
-
|
58
|
-
# This JSON file is nicked from the Emoji One project
|
59
|
-
# Go shower them in love (not that kinda love :smirk:).
|
60
|
-
emojione_json = nil
|
61
|
-
File.open(File.expand_path('../../../emoji.json', __FILE__), 'r') do |f|
|
62
|
-
emojione_json ||= parser.parse(f)
|
63
|
-
end
|
64
|
-
|
65
|
-
emojione_json.each_value do |v|
|
66
|
-
codepoints = v['unicode'].split('-')
|
67
|
-
unicode = codepoints.map(&:hex).pack("U*")
|
68
|
-
|
69
|
-
@shortname_aliases << v['shortname']
|
70
|
-
@emoji_map[v['shortname']] = v['unicode']
|
71
|
-
|
72
|
-
v['aliases'].each do |emoji_alias|
|
73
|
-
@shortname_aliases << emoji_alias
|
74
|
-
@emoji_map[emoji_alias] = v['unicode']
|
75
|
-
end
|
76
|
-
|
77
|
-
v['aliases_ascii'].each do |emoji_alias|
|
78
|
-
@ascii_aliases << emoji_alias
|
79
|
-
@emoji_map[emoji_alias] = v['unicode']
|
80
|
-
end
|
81
|
-
|
82
|
-
@encoding_map[unicode] = codepoints.map{|cp| "&#x#{cp};" }.join
|
83
|
-
@emoji_map[unicode] = v['unicode']
|
84
|
-
end
|
85
|
-
|
86
|
-
build_emoji_regexp
|
87
|
-
|
88
|
-
# @emoji_regexp = Regexp.new (@emoji_map.keys.map{|k| Regexp.quote(k) }).join('|')
|
89
|
-
@encoding_regexp = Regexp.new (@encoding_map.keys.map{|k| Regexp.quote(k) }).join('|')
|
90
|
-
end
|
91
|
-
|
92
|
-
def build_emoji_regexp(previous_conf = nil)
|
93
|
-
return if previous_conf == @conf
|
94
|
-
|
95
|
-
valid = @encoding_map.keys
|
96
|
-
valid += @shortname_aliases if @conf['shortname']
|
97
|
-
valid += @ascii_aliases if @conf['ascii']
|
98
|
-
|
99
|
-
@emoji_regexp = Regexp.union(valid)
|
100
|
-
end
|
101
|
-
|
102
|
-
def configure(h)
|
103
|
-
if h['emoji']
|
104
|
-
@conf = Defaults.merge(h['emoji'])
|
105
|
-
else
|
106
|
-
@conf = Defaults
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
def reconfigure(h)
|
111
|
-
previous_conf = @conf
|
112
|
-
@conf = configure(@@site_conf).merge(h){|k, o, n| n.nil? ? o : n }
|
113
|
-
build_emoji_regexp(previous_conf)
|
114
|
-
end
|
115
|
-
|
116
|
-
def matches(ext)
|
117
|
-
ext =~ /^\.(md|markdown)$/i
|
118
|
-
end
|
119
|
-
|
120
|
-
def output_ext(ext)
|
121
|
-
".html"
|
122
|
-
end
|
123
|
-
|
124
|
-
##
|
125
|
-
# Return whether whether `node` should contain emojis or not
|
126
|
-
#
|
127
|
-
# @param [Oga::XML::Node] node
|
128
|
-
#
|
129
|
-
# @return [Boolean]
|
130
|
-
#
|
131
|
-
def emoji_enabled?(node)
|
132
|
-
|
133
|
-
return true if node.is_a? Oga::XML::Document
|
134
|
-
|
135
|
-
if node.is_a? Oga::XML::Element
|
136
|
-
classes = node.get('class')
|
137
|
-
|
138
|
-
return false if Element_blacklist.any? {|e| e == node.name }
|
139
|
-
return false if Attribute_blacklist.any? {|a| node.attr(a) }
|
140
|
-
return false unless (Class_blacklist & classes.split).empty? unless classes.nil?
|
141
|
-
|
142
|
-
end
|
143
|
-
|
144
|
-
return true
|
145
|
-
end
|
146
|
-
|
147
|
-
##
|
148
|
-
# Recursively add emojis to all child nodes
|
149
|
-
#
|
150
|
-
# @param [Oga::XML::Document|Oga::XML::Node|Oga::XML::Element] node
|
151
|
-
#
|
152
|
-
# @return [NilClass]
|
153
|
-
#
|
154
|
-
def add_emojis(node)
|
155
|
-
return unless emoji_enabled?(node)
|
156
|
-
|
157
|
-
node.children.each do |child|
|
158
|
-
if child.is_a?(Oga::XML::Text)
|
159
|
-
process_node(child)
|
160
|
-
else
|
161
|
-
add_emojis(child)
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
return nil
|
166
|
-
end
|
167
|
-
|
168
|
-
##
|
169
|
-
# Add emojis to {Oga::XML::Text} node
|
170
|
-
#
|
171
|
-
# @param [Oga::XML::Text] node
|
172
|
-
#
|
173
|
-
# @return [NilClass]
|
174
|
-
#
|
175
|
-
def process_node(node)
|
176
|
-
str = node.text
|
177
|
-
str.gsub!(@emoji_regexp) do |m|
|
178
|
-
codepoints = @emoji_map[m]
|
179
|
-
|
180
|
-
unicode_emoji = codepoints.split('-').map(&:hex).pack("U*")
|
181
|
-
|
182
|
-
case @conf['format']
|
183
|
-
when 'unicode', 'html'
|
184
|
-
unicode_emoji
|
185
|
-
when 'emojione-png', 'emojione-svg'
|
186
|
-
vendor, ext = @conf['format'].split('-')
|
187
|
-
loc = str.index(m)
|
188
|
-
|
189
|
-
before = Oga::XML::Text.new
|
190
|
-
after = Oga::XML::Text.new
|
191
|
-
|
192
|
-
before.text = str[0...loc]
|
193
|
-
after.text = str[loc + m.length..-1]
|
194
|
-
img = Oga::XML::Element.new name: 'img'
|
195
|
-
img.set('class', vendor)
|
196
|
-
img.set('alt', unicode_emoji)
|
197
|
-
img.set('src', "https://cdn.jsdelivr.net/#{vendor}/assets/#{ext}/#{codepoints}.#{ext}")
|
198
|
-
|
199
|
-
if node.node_set
|
200
|
-
node.before(before)
|
201
|
-
node.after(after)
|
202
|
-
node.replace img
|
203
|
-
end
|
204
|
-
|
205
|
-
end
|
206
|
-
end
|
207
|
-
|
208
|
-
return nil
|
209
|
-
end
|
210
|
-
|
211
|
-
def convert(content)
|
212
|
-
document = Oga.parse_html(content)
|
213
|
-
add_emojis(document)
|
214
|
-
docstr = document.to_xml
|
215
|
-
|
216
|
-
# Now we only need to encode the Emojis into HTML Entities
|
217
|
-
if @conf['format'] == 'html'
|
218
|
-
docstr.gsub!(@encoding_regexp, @encoding_map)
|
219
|
-
end
|
220
|
-
|
221
|
-
return docstr
|
222
|
-
end # convert
|
223
|
-
|
224
|
-
def self.site_conf
|
225
|
-
@@site_conf
|
226
|
-
end
|
227
|
-
end #Converter
|
228
|
-
|
229
|
-
module Filter
|
230
|
-
def emojify(input, output_format = nil, ascii = nil, shortname = nil)
|
231
|
-
@@emoji_converter ||= Converter.new(Converter.site_conf)
|
232
|
-
@@emoji_converter.reconfigure('format' => output_format, 'ascii' => ascii, 'shortname' => shortname)
|
233
|
-
|
234
|
-
output = @@emoji_converter.convert(input)
|
235
|
-
|
236
|
-
# NOTE: This impacts performance in certain cases
|
237
|
-
@@emoji_converter.reconfigure(Converter.site_conf)
|
238
|
-
|
239
|
-
return output
|
240
|
-
end
|
241
|
-
end #Filter
|
242
|
-
end #Emoji
|
243
|
-
end
|
244
|
-
|
245
|
-
Liquid::Template.register_filter(Jekyll::Emoji::Filter)
|
4
|
+
require "jekyll/emoji/version"
|
5
|
+
require "jekyll/emoji/converter"
|
6
|
+
require "jekyll/emoji/filter"
|
@@ -0,0 +1,386 @@
|
|
1
|
+
require "jekyll/emoji/version"
|
2
|
+
require 'oga'
|
3
|
+
require 'yajl'
|
4
|
+
|
5
|
+
module Jekyll
|
6
|
+
module Emoji
|
7
|
+
class Converter < Converter
|
8
|
+
safe true
|
9
|
+
priority :lowest
|
10
|
+
|
11
|
+
DEFAULTS = {
|
12
|
+
'format' => 'html',
|
13
|
+
'ascii' => false,
|
14
|
+
'shortname' => true
|
15
|
+
}.freeze
|
16
|
+
|
17
|
+
BLACKLIST_ATTRIBUTES = %w{
|
18
|
+
data-no-emoji
|
19
|
+
data-no-emojis
|
20
|
+
}
|
21
|
+
|
22
|
+
BLACKLIST_CLASSES = %w{
|
23
|
+
no-emoji
|
24
|
+
no-emojis
|
25
|
+
|
26
|
+
no_emoji
|
27
|
+
no_emojis
|
28
|
+
}
|
29
|
+
|
30
|
+
BLACKLIST_ELEMENTS = %w{
|
31
|
+
code
|
32
|
+
pre
|
33
|
+
}
|
34
|
+
|
35
|
+
SUPPORTED_FORMATS = %w{
|
36
|
+
html
|
37
|
+
unicode
|
38
|
+
emojione-png
|
39
|
+
emojione-svg
|
40
|
+
}
|
41
|
+
|
42
|
+
EMOJI_JSON_FILE = '../../../../emoji.json'
|
43
|
+
|
44
|
+
##
|
45
|
+
# Initialize the object.
|
46
|
+
# conf Hash should be the following format:
|
47
|
+
#
|
48
|
+
# {
|
49
|
+
# ...
|
50
|
+
# 'emoji' => {
|
51
|
+
# 'format' => [String],
|
52
|
+
# 'ascii' => [TrueClass|FalseClass],
|
53
|
+
# 'shortcode' => [TrueClass|FalseClass]
|
54
|
+
# }
|
55
|
+
# ...
|
56
|
+
# }
|
57
|
+
#
|
58
|
+
# @param [Hash] conf
|
59
|
+
#
|
60
|
+
def initialize(conf = {'emoji' => DEFAULTS})
|
61
|
+
@@site_conf = conf
|
62
|
+
configure(@@site_conf)
|
63
|
+
|
64
|
+
validate_format
|
65
|
+
|
66
|
+
@emoji_map = {}
|
67
|
+
@encoding_map = {}
|
68
|
+
|
69
|
+
@shortname_aliases = []
|
70
|
+
@ascii_aliases = []
|
71
|
+
|
72
|
+
load_emoji_data
|
73
|
+
build_emoji_regexp
|
74
|
+
|
75
|
+
@encoding_regexp = Regexp.new (@encoding_map.keys.map{|k| Regexp.quote(k) }).join('|')
|
76
|
+
end
|
77
|
+
|
78
|
+
##
|
79
|
+
# Load up a JSON file containing emoji data, but discards the keys
|
80
|
+
# because the json file we're reading from contains names in keys
|
81
|
+
# which are surplus in our case.
|
82
|
+
#
|
83
|
+
# @param [String] path
|
84
|
+
# @return [Array]
|
85
|
+
#
|
86
|
+
def load_emoji_json(path)
|
87
|
+
parser = Yajl::Parser.new
|
88
|
+
emoji_hash = nil
|
89
|
+
File.open(File.expand_path(path, __FILE__), 'r') do |f|
|
90
|
+
emoji_hash = parser.parse(f)
|
91
|
+
end
|
92
|
+
|
93
|
+
# keys are emoji names, we don't need those.
|
94
|
+
return emoji_hash.values
|
95
|
+
end
|
96
|
+
|
97
|
+
##
|
98
|
+
# Populates aliases, and reference maps for faster lookup during
|
99
|
+
# the encoding and decoding process. It acceps a path to a file
|
100
|
+
# from which the data should be loaded.
|
101
|
+
#
|
102
|
+
# @param [String] path
|
103
|
+
# @return [NilClass]
|
104
|
+
#
|
105
|
+
def load_emoji_data(path = EMOJI_JSON_FILE)
|
106
|
+
data = load_emoji_json(path)
|
107
|
+
|
108
|
+
data.each do |v|
|
109
|
+
codepoints = v['unicode'].split('-')
|
110
|
+
unicode = codepoints_to_unicode(codepoints)
|
111
|
+
|
112
|
+
@shortname_aliases << v['shortname']
|
113
|
+
@emoji_map[v['shortname']] = v['unicode']
|
114
|
+
|
115
|
+
v['aliases'].each do |emoji_alias|
|
116
|
+
@shortname_aliases << emoji_alias
|
117
|
+
@emoji_map[emoji_alias] = v['unicode']
|
118
|
+
end
|
119
|
+
|
120
|
+
v['aliases_ascii'].each do |emoji_alias|
|
121
|
+
@ascii_aliases << emoji_alias
|
122
|
+
@emoji_map[emoji_alias] = v['unicode']
|
123
|
+
end
|
124
|
+
|
125
|
+
@encoding_map[unicode] = codepoints.map{|cp| "&#x#{cp};" }.join
|
126
|
+
@emoji_map[unicode] = v['unicode']
|
127
|
+
end
|
128
|
+
|
129
|
+
return nil
|
130
|
+
end
|
131
|
+
|
132
|
+
##
|
133
|
+
# Validates if desired format is supported. If it isn't supported
|
134
|
+
# an exception is raised.
|
135
|
+
#
|
136
|
+
# @param [String] f
|
137
|
+
# @return [TrueClass]
|
138
|
+
#
|
139
|
+
def validate_format(f = @conf['format'])
|
140
|
+
if !SUPPORTED_FORMATS.include? f
|
141
|
+
raise(ArgumentError, "Unknown emoji format: '#{f}'; Supported formats are: #{SUPPORTED_FORMATS}")
|
142
|
+
end
|
143
|
+
|
144
|
+
true
|
145
|
+
end
|
146
|
+
|
147
|
+
##
|
148
|
+
# Rebuilds the cached Regexp object in case the converter was
|
149
|
+
# reconfigured.
|
150
|
+
#
|
151
|
+
# @param [Hash|NilClass]
|
152
|
+
# @return [Regexp]
|
153
|
+
#
|
154
|
+
def build_emoji_regexp(previous_conf = nil)
|
155
|
+
return if previous_conf == @conf
|
156
|
+
|
157
|
+
valid = @encoding_map.keys
|
158
|
+
valid += @shortname_aliases if @conf['shortname']
|
159
|
+
valid += @ascii_aliases if @conf['ascii']
|
160
|
+
|
161
|
+
@emoji_regexp = Regexp.union(valid)
|
162
|
+
end
|
163
|
+
|
164
|
+
##
|
165
|
+
# Configure the internal state.
|
166
|
+
#
|
167
|
+
# @param [Hash] h
|
168
|
+
# @return [Hash]
|
169
|
+
#
|
170
|
+
def configure(h)
|
171
|
+
if h['emoji']
|
172
|
+
@conf = DEFAULTS.merge(h['emoji'])
|
173
|
+
else
|
174
|
+
@conf = DEFAULTS
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
##
|
179
|
+
# Reconfigure the internal state.
|
180
|
+
#
|
181
|
+
# @param [Hash] h
|
182
|
+
# @return [Hash]
|
183
|
+
#
|
184
|
+
def reconfigure(h)
|
185
|
+
previous_conf = @conf
|
186
|
+
@conf = configure(@@site_conf).merge(h){|k, o, n| n.nil? ? o : n }
|
187
|
+
validate_format
|
188
|
+
build_emoji_regexp(previous_conf)
|
189
|
+
|
190
|
+
return @conf
|
191
|
+
end
|
192
|
+
|
193
|
+
##
|
194
|
+
# Return whether we should convert a file based on its extension.
|
195
|
+
#
|
196
|
+
# @param [String] ext
|
197
|
+
# @return [TrueClass|FalseClass]
|
198
|
+
#
|
199
|
+
def matches(ext)
|
200
|
+
ext =~ /^\.(md|markdown)$/i
|
201
|
+
end
|
202
|
+
##
|
203
|
+
# Returns the extension with the Converter should output.
|
204
|
+
#
|
205
|
+
# @param [String] ext
|
206
|
+
# @return [String]
|
207
|
+
#
|
208
|
+
def output_ext(ext)
|
209
|
+
".html"
|
210
|
+
end
|
211
|
+
|
212
|
+
##
|
213
|
+
# Return whether whether `node` should contain emojis or not.
|
214
|
+
#
|
215
|
+
# @param [Oga::XML::Node] node
|
216
|
+
# @return [TrueClass|FalseClass]
|
217
|
+
#
|
218
|
+
def emoji_enabled?(node)
|
219
|
+
|
220
|
+
return true if node.is_a? Oga::XML::Document
|
221
|
+
|
222
|
+
if node.is_a? Oga::XML::Element
|
223
|
+
classes = node.get('class')
|
224
|
+
|
225
|
+
return false if BLACKLIST_ELEMENTS.any? {|e| e == node.name }
|
226
|
+
return false if BLACKLIST_ATTRIBUTES.any? {|a| node.attr(a) }
|
227
|
+
return false unless (BLACKLIST_CLASSES & classes.split).empty? unless classes.nil?
|
228
|
+
|
229
|
+
end
|
230
|
+
|
231
|
+
return true
|
232
|
+
end
|
233
|
+
|
234
|
+
##
|
235
|
+
# Recursively add emojis to all child nodes.
|
236
|
+
#
|
237
|
+
# @param [Oga::XML::Document|Oga::XML::Node|Oga::XML::Element] node
|
238
|
+
# @return [NilClass]
|
239
|
+
#
|
240
|
+
def add_emojis(node)
|
241
|
+
return unless emoji_enabled?(node)
|
242
|
+
|
243
|
+
node.children.each do |child|
|
244
|
+
if child.is_a?(Oga::XML::Text)
|
245
|
+
process_node(child)
|
246
|
+
else
|
247
|
+
add_emojis(child)
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
# return nil
|
252
|
+
end
|
253
|
+
|
254
|
+
##
|
255
|
+
# Add emojis to {Oga::XML::Text} node.
|
256
|
+
#
|
257
|
+
# @param [Oga::XML::Text] node
|
258
|
+
# @return [NilClass]
|
259
|
+
#
|
260
|
+
def process_node(node)
|
261
|
+
str = node.text
|
262
|
+
|
263
|
+
str.gsub!(@emoji_regexp) do |m|
|
264
|
+
codepoints = @emoji_map[m]
|
265
|
+
|
266
|
+
case @conf['format']
|
267
|
+
when 'unicode', 'html'
|
268
|
+
codepoints_to_unicode(codepoints)
|
269
|
+
when 'emojione-png', 'emojione-svg'
|
270
|
+
before, after = split_to_nodes(str, m)
|
271
|
+
img = emojione_img_node(codepoints)
|
272
|
+
|
273
|
+
if node.node_set
|
274
|
+
node.before(before)
|
275
|
+
node.after(after)
|
276
|
+
node.replace img
|
277
|
+
end
|
278
|
+
|
279
|
+
return nil
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
return nil
|
284
|
+
end
|
285
|
+
|
286
|
+
##
|
287
|
+
# Generates a populated {Oga::XML::Element} node.
|
288
|
+
#
|
289
|
+
# @param [String|Array] codepoints
|
290
|
+
# @return [Oga::XML::Element(name:img)]
|
291
|
+
#
|
292
|
+
def emojione_img_node(codepoints)
|
293
|
+
ext = @conf['format'].split('-').last
|
294
|
+
img = Oga::XML::Element.new name: 'img'
|
295
|
+
img.set('class', 'emojione')
|
296
|
+
img.set('alt', codepoints_to_unicode(codepoints))
|
297
|
+
img.set('src', "https://cdn.jsdelivr.net/emojione/assets/#{ext}/#{codepoints}.#{ext}")
|
298
|
+
|
299
|
+
return img
|
300
|
+
end
|
301
|
+
|
302
|
+
##
|
303
|
+
# Splits `str` into an {Array} with two {Oga::XML::Text} nodes at
|
304
|
+
# `seperator`.
|
305
|
+
#
|
306
|
+
# @param [String] str
|
307
|
+
# @param [String] seperator
|
308
|
+
# @return [Array]
|
309
|
+
#
|
310
|
+
def split_to_nodes(str, seperator)
|
311
|
+
|
312
|
+
before, after = str.split(seperator)
|
313
|
+
|
314
|
+
node_before = Oga::XML::Text.new
|
315
|
+
node_after = Oga::XML::Text.new
|
316
|
+
|
317
|
+
node_before.text = before
|
318
|
+
node_after.text = after || ""
|
319
|
+
|
320
|
+
return [node_before, node_after ]
|
321
|
+
end
|
322
|
+
|
323
|
+
##
|
324
|
+
# Convert `unicode` string into a `"HHHH-HHHH"` string, which represents
|
325
|
+
# the codepoints of the unicode string, but only if `unicode`
|
326
|
+
# is a valid emoji.
|
327
|
+
#
|
328
|
+
#
|
329
|
+
# @param [String] unicode
|
330
|
+
# @return [String]
|
331
|
+
#
|
332
|
+
def unicode_to_codepoints(unicode)
|
333
|
+
return unicode unless @encoding_map.key? unicode
|
334
|
+
unicode.codepoints.map {|cp| cp.to_s 16}.join('-')
|
335
|
+
end
|
336
|
+
|
337
|
+
##
|
338
|
+
# Convert `codepoints` into an unicode string.
|
339
|
+
#
|
340
|
+
# @param [String|Array] codepoints
|
341
|
+
# @return [String]
|
342
|
+
#
|
343
|
+
def codepoints_to_unicode(codepoints)
|
344
|
+
if codepoints.is_a? String
|
345
|
+
codepoints.split('-').map(&:hex).pack("U*")
|
346
|
+
elsif codepoints.is_a? Array
|
347
|
+
codepoints.map {|cp| cp.is_a?(String) ? cp.hex : cp }.pack("U*")
|
348
|
+
else
|
349
|
+
raise(ArgumentError, "must be String or Array")
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
353
|
+
##
|
354
|
+
# Emojify the string. If the string is an HTML strings, certain elements
|
355
|
+
# won't be emojified. Check the `BLACKLIST_*`` constants, or the docs for
|
356
|
+
# more information.
|
357
|
+
#
|
358
|
+
# @param [String] convert
|
359
|
+
# @return [String]
|
360
|
+
#
|
361
|
+
def convert(content)
|
362
|
+
document = Oga.parse_html(content)
|
363
|
+
add_emojis(document)
|
364
|
+
docstr = document.to_xml
|
365
|
+
|
366
|
+
# Now we only need to encode the Emojis into HTML Entities
|
367
|
+
if @conf['format'] == 'html'
|
368
|
+
docstr.gsub!(@encoding_regexp, @encoding_map)
|
369
|
+
end
|
370
|
+
|
371
|
+
return docstr
|
372
|
+
end # convert
|
373
|
+
|
374
|
+
def self.site_conf
|
375
|
+
@@site_conf
|
376
|
+
end
|
377
|
+
|
378
|
+
private :load_emoji_json, :load_emoji_data
|
379
|
+
private :validate_format
|
380
|
+
private :build_emoji_regexp
|
381
|
+
private :process_node
|
382
|
+
private :emojione_img_node, :split_to_nodes
|
383
|
+
private :unicode_to_codepoints, :codepoints_to_unicode
|
384
|
+
end #Converter
|
385
|
+
end #Emoji
|
386
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Jekyll
|
2
|
+
module Emoji
|
3
|
+
module Filter
|
4
|
+
##
|
5
|
+
# Emojify the string. If the string is an HTML strings, certain elements
|
6
|
+
# won't be emojified. Check the `BLACKLIST_*`` constants, and/or the docs
|
7
|
+
# inside the README for more information.
|
8
|
+
#
|
9
|
+
# @param [String] input
|
10
|
+
# @param [String] output_format
|
11
|
+
# @param [FalseClass|TrueClass|NilClass] ascii
|
12
|
+
# @param [FalseClass|TrueClass|NilClass] shortname
|
13
|
+
# @return [String]
|
14
|
+
#
|
15
|
+
def emojify(input, output_format = nil, ascii = nil, shortname = nil)
|
16
|
+
@@emoji_converter ||= Converter.new(Converter.site_conf)
|
17
|
+
@@emoji_converter.reconfigure('format' => output_format, 'ascii' => ascii, 'shortname' => shortname)
|
18
|
+
|
19
|
+
output = @@emoji_converter.convert(input)
|
20
|
+
|
21
|
+
# NOTE: This impacts performance in certain cases
|
22
|
+
@@emoji_converter.reconfigure(Converter.site_conf)
|
23
|
+
|
24
|
+
return output
|
25
|
+
end
|
26
|
+
end #Filter
|
27
|
+
end #Emoji
|
28
|
+
end
|
29
|
+
|
30
|
+
Liquid::Template.register_filter(Jekyll::Emoji::Filter)
|
data/lib/jekyll/emoji/version.rb
CHANGED
data/tests/conversion_test.rb
CHANGED
@@ -26,10 +26,10 @@ class TestConversion < MiniTest::Test
|
|
26
26
|
|
27
27
|
def test_svg
|
28
28
|
@converter.reconfigure 'format' => 'emojione-svg'
|
29
|
-
img = %q{<img class="emojione" alt="3⃣" src="https://cdn.jsdelivr.net/emojione/assets/svg/0033-20E3.svg" />}
|
30
|
-
assert_equal img, @converter.convert("\u{0033}\u{20E3}")
|
31
|
-
assert_equal img, @converter.convert(":three:")
|
32
|
-
assert_equal "3", @converter.convert("3")
|
29
|
+
img = %q{the number <img class="emojione" alt="3⃣" src="https://cdn.jsdelivr.net/emojione/assets/svg/0033-20E3.svg" /> is smaller than 4}
|
30
|
+
assert_equal img, @converter.convert("the number \u{0033}\u{20E3} is smaller than 4")
|
31
|
+
assert_equal img, @converter.convert("the number :three: is smaller than 4")
|
32
|
+
assert_equal "the number 3 is smaller than 4", @converter.convert("the number 3 is smaller than 4")
|
33
33
|
end
|
34
34
|
|
35
35
|
def test_reconfiguring_aliases
|
@@ -62,7 +62,7 @@ class TestConversion < MiniTest::Test
|
|
62
62
|
assert_equal result2, @converter.convert(test2)
|
63
63
|
end
|
64
64
|
|
65
|
-
def
|
65
|
+
def test_node_blacklists
|
66
66
|
test1 = %q{<code>:)</code>}
|
67
67
|
result1 = %q{<code>:)</code>}
|
68
68
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jekyll-emoji
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nino Miletich
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-08-
|
11
|
+
date: 2015-08-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -125,6 +125,8 @@ files:
|
|
125
125
|
- jekyll-emoji.gemspec
|
126
126
|
- lib/jekyll-emoji.rb
|
127
127
|
- lib/jekyll/emoji.rb
|
128
|
+
- lib/jekyll/emoji/converter.rb
|
129
|
+
- lib/jekyll/emoji/filter.rb
|
128
130
|
- lib/jekyll/emoji/version.rb
|
129
131
|
- tests/conversion_test.rb
|
130
132
|
homepage: https://github.com/omninonsense/jekyll-emoji
|