negarmoji 0.1.0 → 0.1.1
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/.gitignore +6 -0
- data/.travis.yml +12 -0
- data/CONTRIBUTING.md +31 -0
- data/Gemfile +6 -0
- data/Rakefile +24 -0
- data/db/dump.rb +69 -0
- data/db/emoji-test-parser.rb +121 -0
- data/db/index.html +113 -0
- data/db/{emoji.json → negarmoji.json} +0 -0
- data/lib/negarmoji.rb +1 -1
- data/lib/{emoji → negarmoji}/character.rb +7 -7
- data/lib/{emoji.rb → negarmoji/emoji.rb} +11 -11
- data/lib/negarmoji/version.rb +5 -0
- data/negarmoji.gemspec +24 -0
- data/script/bootstrap +10 -0
- data/script/console +16 -0
- data/script/release +31 -0
- data/script/test +14 -0
- data/test/documentation_test.rb +46 -0
- data/test/emoji_test.rb +243 -0
- data/test/test_helper.rb +8 -0
- data/vendor/unicode-negarmoji-test.txt +4119 -0
- metadata +31 -10
@@ -1,14 +1,14 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
require
|
5
|
-
require
|
4
|
+
require "negarmoji/character"
|
5
|
+
require "json"
|
6
6
|
|
7
7
|
module Emoji
|
8
8
|
extend self
|
9
9
|
|
10
10
|
def data_file
|
11
|
-
File.expand_path(
|
11
|
+
File.expand_path("../../../db/negarmoji.json", __FILE__)
|
12
12
|
end
|
13
13
|
|
14
14
|
def all
|
@@ -26,7 +26,7 @@ module Emoji
|
|
26
26
|
emoji
|
27
27
|
end
|
28
28
|
|
29
|
-
# Public: Yield an
|
29
|
+
# Public: Yield an negarmoji to the block and update the indices in case its
|
30
30
|
# aliases or unicode_aliases lists changed.
|
31
31
|
def edit_emoji(emoji)
|
32
32
|
@names_index ||= Hash.new
|
@@ -44,12 +44,12 @@ module Emoji
|
|
44
44
|
emoji
|
45
45
|
end
|
46
46
|
|
47
|
-
# Public: Find an
|
47
|
+
# Public: Find an negarmoji by its aliased name. Return nil if missing.
|
48
48
|
def find_by_alias(name)
|
49
49
|
names_index[name]
|
50
50
|
end
|
51
51
|
|
52
|
-
# Public: Find an
|
52
|
+
# Public: Find an negarmoji by its unicode character. Return nil if missing.
|
53
53
|
def find_by_unicode(unicode)
|
54
54
|
unicodes_index[unicode]
|
55
55
|
end
|
@@ -57,7 +57,7 @@ module Emoji
|
|
57
57
|
private
|
58
58
|
VARIATION_SELECTOR_16 = "\u{fe0f}".freeze
|
59
59
|
|
60
|
-
|
60
|
+
# Characters which must have VARIATION_SELECTOR_16 to render as color negarmoji:
|
61
61
|
TEXT_GLYPHS = [
|
62
62
|
"\u{1f237}", # Japanese “monthly amount” button
|
63
63
|
"\u{1f202}", # Japanese “service charge” button
|
@@ -149,7 +149,7 @@ module Emoji
|
|
149
149
|
private_constant :VARIATION_SELECTOR_16, :TEXT_GLYPHS
|
150
150
|
|
151
151
|
def parse_data_file
|
152
|
-
data = File.open(data_file,
|
152
|
+
data = File.open(data_file, "r:UTF-8") do |file|
|
153
153
|
JSON.parse(file.read, symbolize_names: true)
|
154
154
|
end
|
155
155
|
|
@@ -170,10 +170,10 @@ module Emoji
|
|
170
170
|
data.each do |raw_emoji|
|
171
171
|
self.create(nil) do |emoji|
|
172
172
|
raw_emoji.fetch(:aliases).each { |name| emoji.add_alias(dedup.call(name)) }
|
173
|
-
if raw = raw_emoji[:emoji]
|
173
|
+
if (raw = raw_emoji[:emoji])
|
174
174
|
append_unicode.call(emoji, raw)
|
175
175
|
start_pos = 0
|
176
|
-
while found_index = raw.index(VARIATION_SELECTOR_16, start_pos)
|
176
|
+
while (found_index = raw.index(VARIATION_SELECTOR_16, start_pos))
|
177
177
|
# register every variant where one VARIATION_SELECTOR_16 is removed
|
178
178
|
raw_alternate = raw.dup
|
179
179
|
raw_alternate[found_index] = ""
|
@@ -209,5 +209,5 @@ module Emoji
|
|
209
209
|
end
|
210
210
|
end
|
211
211
|
|
212
|
-
# Preload
|
212
|
+
# Preload negarmoji into memory
|
213
213
|
Emoji.all
|
data/negarmoji.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path("lib", __dir__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
require "negarmoji/version"
|
6
|
+
|
7
|
+
Gem::Specification.new do |spec|
|
8
|
+
spec.name = "negarmoji"
|
9
|
+
spec.version = Emoji::VERSION
|
10
|
+
spec.platform = Gem::Platform::RUBY
|
11
|
+
spec.authors = ["Mohammad Mahdi Baghbani Pourvahid"]
|
12
|
+
spec.email = "MahdiBaghbani@protonmail.com"
|
13
|
+
spec.homepage = "https://gitlab.com/Azadeh-Afzar/Web-Development/Negareh-Emoji-Library"
|
14
|
+
spec.description = "%(Character information and metadata for Unicode emoji)"
|
15
|
+
spec.summary = "Unicode emoji library"
|
16
|
+
spec.licenses = "GPL-3.0"
|
17
|
+
|
18
|
+
spec.files = `git ls-files -z`.split("\x0")
|
19
|
+
spec.executables = spec.files.grep(%r!^bin/!) { |f| File.basename(f) }
|
20
|
+
spec.test_files = spec.files.grep(%r!^test/!)
|
21
|
+
spec.require_paths = ["lib"]
|
22
|
+
|
23
|
+
spec.required_ruby_version = ">= 2.3.0"
|
24
|
+
end
|
data/script/bootstrap
ADDED
data/script/console
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
set -e
|
3
|
+
|
4
|
+
public_methods() {
|
5
|
+
sed '/^ *private/,$d' "$1" | grep -w def | sed -E 's/^ *def / /; s/).+/)/'
|
6
|
+
}
|
7
|
+
|
8
|
+
echo "Emoji methods:"
|
9
|
+
public_methods lib/negarmoji.rb
|
10
|
+
echo
|
11
|
+
echo "Emoji::Character methods:"
|
12
|
+
public_methods lib/negarmoji/character.rb
|
13
|
+
echo
|
14
|
+
|
15
|
+
exec irb -I lib -r negarmoji
|
16
|
+
zz
|
data/script/release
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
# Usage: script/release
|
3
|
+
#
|
4
|
+
# 1. Checks if tests pass,
|
5
|
+
# 2. commits gemspec,
|
6
|
+
# 3. tags the release with the version in the gemspec,
|
7
|
+
# 4. pushes "negarmoji" gem to RubyGems.org.
|
8
|
+
|
9
|
+
set -e
|
10
|
+
|
11
|
+
case "$1" in
|
12
|
+
-h | --help )
|
13
|
+
sed -ne '/^#/!q;s/.\{1,2\}//;1d;p' < "$0"
|
14
|
+
exit 0
|
15
|
+
;;
|
16
|
+
esac
|
17
|
+
|
18
|
+
if git diff --quiet negarmoji.gemspec; then
|
19
|
+
echo "You must bump the version in the gemspec first." >&2
|
20
|
+
exit 1
|
21
|
+
fi
|
22
|
+
|
23
|
+
script/test
|
24
|
+
|
25
|
+
trap 'rm *.gem' EXIT
|
26
|
+
|
27
|
+
version="$(gem build negarmoji.gemspec | awk '/Version:/ { print $2 }')"
|
28
|
+
git commit negarmoji.gemspec -m "negarmoji $version"
|
29
|
+
git tag "v${version}"
|
30
|
+
git push origin HEAD "v${version}"
|
31
|
+
|
data/script/test
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
# Pull the EmojiHelper example from the docs
|
4
|
+
readme = File.expand_path('../../README.md', __FILE__)
|
5
|
+
docs = File.open(readme, 'r:UTF-8') { |f| f.read }
|
6
|
+
eval docs.match(/^module.+?^end/m)[0]
|
7
|
+
|
8
|
+
String.class_eval do
|
9
|
+
def html_safe() self end
|
10
|
+
def present?() !empty? end
|
11
|
+
end
|
12
|
+
|
13
|
+
class DocumentationTest < TestCase
|
14
|
+
module Helper
|
15
|
+
extend EmojiHelper
|
16
|
+
|
17
|
+
def self.h(str)
|
18
|
+
str.gsub('<', '<').gsub('>', '>')
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.image_path(img)
|
22
|
+
"/images/#{img}?123"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
test "replaces emoji syntax with images" do
|
27
|
+
assert_equal "It's raining " \
|
28
|
+
'<img alt="cat" src="/images/emoji/1f431.svg?123" style="vertical-align:middle" width="20" height="20" />s and ' \
|
29
|
+
'<img alt="dog" src="/images/emoji/1f436.svg?123" style="vertical-align:middle" width="20" height="20" />s!',
|
30
|
+
Helper.emojify("It's raining :cat:s and :dog:s!")
|
31
|
+
end
|
32
|
+
|
33
|
+
test "doesn't replace unknown emoji" do
|
34
|
+
content = ":jupiter: is in :space:"
|
35
|
+
assert_equal content, Helper.emojify(content)
|
36
|
+
end
|
37
|
+
|
38
|
+
test "escapes other HTML" do
|
39
|
+
assert_equal "You have been <script>alert('pwned!')</script>",
|
40
|
+
Helper.emojify("You have been <script>alert('pwned!')</script>")
|
41
|
+
end
|
42
|
+
|
43
|
+
test "returns nil for blank content" do
|
44
|
+
assert_nil Helper.emojify('')
|
45
|
+
end
|
46
|
+
end
|
data/test/emoji_test.rb
ADDED
@@ -0,0 +1,243 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require_relative '../db/emoji-test-parser'
|
3
|
+
|
4
|
+
class EmojiTest < TestCase
|
5
|
+
test "fetching all negarmoji" do
|
6
|
+
count = Emoji.all.size
|
7
|
+
assert count > 845, "there were too few emojis: #{count}"
|
8
|
+
end
|
9
|
+
|
10
|
+
test "unicodes set contains the unicodes" do
|
11
|
+
min_size = Emoji.all.size
|
12
|
+
count = Emoji.all.map(&:unicode_aliases).flatten.size
|
13
|
+
assert count > min_size, "there were too few unicode mappings: #{count}"
|
14
|
+
end
|
15
|
+
|
16
|
+
test "finding negarmoji by alias" do
|
17
|
+
assert_equal 'smile', Emoji.find_by_alias('smile').name
|
18
|
+
end
|
19
|
+
|
20
|
+
test "finding nonexistent negarmoji by alias returns nil" do
|
21
|
+
assert_nil Emoji.find_by_alias('$$$')
|
22
|
+
end
|
23
|
+
|
24
|
+
test "finding negarmoji by unicode" do
|
25
|
+
emoji = Emoji.find_by_unicode("\u{1f604}") # grinning face with smiling eyes
|
26
|
+
assert_equal "\u{1f604}", emoji.raw
|
27
|
+
end
|
28
|
+
|
29
|
+
test "finding nonexistent negarmoji by unicode returns nil" do
|
30
|
+
assert_nil Emoji.find_by_unicode("\u{1234}")
|
31
|
+
end
|
32
|
+
|
33
|
+
test "unicode_aliases" do
|
34
|
+
emoji = Emoji.find_by_unicode("\u{2728}") # sparkles
|
35
|
+
assert_equal ["2728", "2728-fe0f"], emoji.unicode_aliases.map { |u| Emoji::Character.hex_inspect(u) }
|
36
|
+
end
|
37
|
+
|
38
|
+
test "unicode_aliases doesn't necessarily include form without VARIATION_SELECTOR_16" do
|
39
|
+
emoji = Emoji.find_by_unicode("\u{00a9}\u{fe0f}") # copyright symbol
|
40
|
+
assert_equal ["00a9-fe0f"], emoji.unicode_aliases.map { |u| Emoji::Character.hex_inspect(u) }
|
41
|
+
end
|
42
|
+
|
43
|
+
test "emojis have tags" do
|
44
|
+
emoji = Emoji.find_by_alias('smile')
|
45
|
+
assert emoji.tags.include?('happy')
|
46
|
+
assert emoji.tags.include?('joy')
|
47
|
+
assert emoji.tags.include?('pleased')
|
48
|
+
end
|
49
|
+
|
50
|
+
GENDER_EXCEPTIONS = [
|
51
|
+
"man_with_gua_pi_mao",
|
52
|
+
"woman_with_headscarf",
|
53
|
+
"man_in_tuxedo",
|
54
|
+
"pregnant_woman",
|
55
|
+
"isle_of_man",
|
56
|
+
"blonde_woman",
|
57
|
+
/^couple(kiss)?_/,
|
58
|
+
/^family_/,
|
59
|
+
]
|
60
|
+
|
61
|
+
test "emojis have valid names" do
|
62
|
+
aliases = Emoji.all.flat_map(&:aliases)
|
63
|
+
|
64
|
+
gender_mismatch = []
|
65
|
+
to_another_gender = lambda do |name|
|
66
|
+
case name
|
67
|
+
when *GENDER_EXCEPTIONS then name
|
68
|
+
else
|
69
|
+
name.sub(/(?<=^|_)(?:wo)?man(?=_|$)/) do |match|
|
70
|
+
match == "woman" ? "man" : "woman"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
invalid = []
|
76
|
+
alias_count = Hash.new(0)
|
77
|
+
aliases.each do |name|
|
78
|
+
alias_count[name] += 1
|
79
|
+
invalid << name if name !~ /\A[\w+-]+\Z/
|
80
|
+
another_gender = to_another_gender.call(name)
|
81
|
+
gender_mismatch << another_gender unless aliases.include?(another_gender)
|
82
|
+
end
|
83
|
+
|
84
|
+
duplicates = alias_count.select { |_, count| count > 1 }.keys
|
85
|
+
|
86
|
+
assert_equal [], invalid, "some negarmoji have invalid names"
|
87
|
+
assert_equal [], duplicates, "some negarmoji aliases have duplicates"
|
88
|
+
assert_equal [], gender_mismatch, "missing gender variants"
|
89
|
+
end
|
90
|
+
|
91
|
+
test "missing or incorrect unicodes" do
|
92
|
+
emoji_map, _ = EmojiTestParser.parse(File.expand_path("../../vendor/unicode-negarmoji-test.txt", __FILE__))
|
93
|
+
source_unicode_emoji = emoji_map.values
|
94
|
+
text_glyphs = Emoji.const_get(:TEXT_GLYPHS)
|
95
|
+
|
96
|
+
missing = 0
|
97
|
+
message = "Missing or incorrect unicodes:\n"
|
98
|
+
source_unicode_emoji.each do |emoji|
|
99
|
+
emoji[:sequences].each do |raw|
|
100
|
+
found = Emoji.find_by_unicode(raw)
|
101
|
+
if text_glyphs.include?(raw)
|
102
|
+
assert_nil found, Emoji::Character.hex_inspect(raw)
|
103
|
+
next
|
104
|
+
end
|
105
|
+
next if found
|
106
|
+
message << "%s (%s)" % [Emoji::Character.hex_inspect(raw), emoji[:description]]
|
107
|
+
if found = Emoji.find_by_unicode(raw.gsub("\u{fe0f}", ""))
|
108
|
+
message << " - could be %s (:%s:)" % [found.hex_inspect, found.name]
|
109
|
+
end
|
110
|
+
message << "\n"
|
111
|
+
missing += 1
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
assert_equal 0, missing, message
|
116
|
+
end
|
117
|
+
|
118
|
+
test "raw representation does not include VARIATION SELECTOR 16 unless necessary" do
|
119
|
+
emoji = Emoji.all.select do |emoji|
|
120
|
+
!emoji.custom? && emoji.raw.end_with?("\u{fe0f}") && emoji.unicode_aliases.size == 2
|
121
|
+
end
|
122
|
+
assert_equal [], emoji
|
123
|
+
end
|
124
|
+
|
125
|
+
test "negarmoji have category" do
|
126
|
+
missing = Emoji.all.select { |e| e.category.to_s.empty? }
|
127
|
+
assert_equal [], missing.map(&:name), "some negarmoji don't have a category"
|
128
|
+
|
129
|
+
emoji = Emoji.find_by_alias('family_man_woman_girl')
|
130
|
+
assert_equal 'People & Body', emoji.category
|
131
|
+
|
132
|
+
categories = Emoji.all.map(&:category).uniq.compact
|
133
|
+
assert_equal [
|
134
|
+
"Smileys & Emotion",
|
135
|
+
"People & Body",
|
136
|
+
"Animals & Nature",
|
137
|
+
"Food & Drink",
|
138
|
+
"Travel & Places",
|
139
|
+
"Activities",
|
140
|
+
"Objects",
|
141
|
+
"Symbols",
|
142
|
+
"Flags",
|
143
|
+
], categories
|
144
|
+
end
|
145
|
+
|
146
|
+
test "negarmoji have description" do
|
147
|
+
missing = Emoji.all.select { |e| e.description.to_s.empty? }
|
148
|
+
assert_equal [], missing.map(&:name), "some negarmoji don't have a description"
|
149
|
+
|
150
|
+
emoji = Emoji.find_by_alias('family_man_woman_girl')
|
151
|
+
assert_equal 'family: man, woman, girl', emoji.description
|
152
|
+
end
|
153
|
+
|
154
|
+
test "negarmoji have Unicode version" do
|
155
|
+
emoji = Emoji.find_by_alias('family_man_woman_girl')
|
156
|
+
assert_equal '6.0', emoji.unicode_version
|
157
|
+
end
|
158
|
+
|
159
|
+
test "negarmoji have iOS version" do
|
160
|
+
missing = Emoji.all.select { |e| e.ios_version.to_s.empty? }
|
161
|
+
assert_equal [], missing.map(&:name), "some negarmoji don't have an iOS version"
|
162
|
+
|
163
|
+
emoji = Emoji.find_by_alias('family_man_woman_girl')
|
164
|
+
assert_equal '8.3', emoji.ios_version
|
165
|
+
end
|
166
|
+
|
167
|
+
test "no custom emojis" do
|
168
|
+
custom = Emoji.all.select(&:custom?)
|
169
|
+
assert 0, custom.size
|
170
|
+
end
|
171
|
+
|
172
|
+
test "create" do
|
173
|
+
emoji = Emoji.create("music") do |char|
|
174
|
+
char.add_unicode_alias "\u{266b}"
|
175
|
+
char.add_unicode_alias "\u{266a}"
|
176
|
+
char.add_tag "notes"
|
177
|
+
char.add_tag "eighth"
|
178
|
+
end
|
179
|
+
|
180
|
+
begin
|
181
|
+
assert_equal emoji, Emoji.all.last
|
182
|
+
assert_equal emoji, Emoji.find_by_alias("music")
|
183
|
+
assert_equal emoji, Emoji.find_by_unicode("\u{266a}")
|
184
|
+
assert_equal emoji, Emoji.find_by_unicode("\u{266b}")
|
185
|
+
|
186
|
+
assert_equal "\u{266b}", emoji.raw
|
187
|
+
assert_equal "266b.svg", emoji.image_filename
|
188
|
+
assert_equal %w[music], emoji.aliases
|
189
|
+
assert_equal %w[notes eighth], emoji.tags
|
190
|
+
ensure
|
191
|
+
Emoji.all.pop
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
test "create with custom filename" do
|
196
|
+
emoji = Emoji.create("music") do |char|
|
197
|
+
char.image_filename = "some_path/my_emoji.gif"
|
198
|
+
end
|
199
|
+
|
200
|
+
begin
|
201
|
+
assert_equal "some_path/my_emoji.gif", emoji.image_filename
|
202
|
+
ensure
|
203
|
+
Emoji.all.pop
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
test "create without block" do
|
208
|
+
emoji = Emoji.create("music")
|
209
|
+
|
210
|
+
begin
|
211
|
+
assert_equal emoji, Emoji.find_by_alias("music")
|
212
|
+
assert_equal [], emoji.unicode_aliases
|
213
|
+
assert_equal [], emoji.tags
|
214
|
+
assert_equal "music.svg", emoji.image_filename
|
215
|
+
ensure
|
216
|
+
Emoji.all.pop
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
test "edit" do
|
221
|
+
emoji = Emoji.find_by_alias("weary")
|
222
|
+
|
223
|
+
emoji = Emoji.edit_emoji(emoji) do |char|
|
224
|
+
char.add_alias "whining"
|
225
|
+
char.add_unicode_alias "\u{1f629}\u{266a}"
|
226
|
+
char.add_tag "complaining"
|
227
|
+
end
|
228
|
+
|
229
|
+
begin
|
230
|
+
assert_equal emoji, Emoji.find_by_alias("weary")
|
231
|
+
assert_equal emoji, Emoji.find_by_alias("whining")
|
232
|
+
assert_equal emoji, Emoji.find_by_unicode("\u{1f629}")
|
233
|
+
assert_equal emoji, Emoji.find_by_unicode("\u{1f629}\u{266a}")
|
234
|
+
|
235
|
+
assert_equal %w[weary whining], emoji.aliases
|
236
|
+
assert_includes emoji.tags, "complaining"
|
237
|
+
ensure
|
238
|
+
emoji.aliases.pop
|
239
|
+
emoji.unicode_aliases.pop
|
240
|
+
emoji.tags.pop
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|