negarmoji 0.1.1 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.codeclimate.yml +64 -0
- data/.gitignore +144 -5
- data/.gitlab-ci.yml +124 -0
- data/.gitlab/issue_templates/Default.md +20 -0
- data/.gitlab/merge_request_templates/Default.md +25 -0
- data/.rubocop.yml +47 -0
- data/.rubocop_todo.yml +7 -0
- data/CHANGELOG.md +6 -0
- data/CODE_OF_CONDUCT.md +78 -0
- data/CONTRIBUTING.md +190 -21
- data/CREDITS +11 -0
- data/Gemfile +5 -3
- data/README.md +81 -0
- data/ROADMAP.md +28 -0
- data/Rakefile +7 -5
- data/SUPPORT.md +6 -0
- data/db/dump.rb +35 -37
- data/db/emoji-test-parser.rb +28 -33
- data/db/negarmoji.json +20788 -18818
- data/lib/negarmoji/character.rb +12 -6
- data/lib/negarmoji/emoji.rb +71 -146
- data/lib/negarmoji/version.rb +1 -1
- data/logo.svg +200 -0
- data/negarmoji.gemspec +11 -4
- data/script/ci_rubygems.sh +13 -0
- data/script/dev_release.py +91 -0
- data/script/dev_revert_tag.py +39 -0
- data/script/test.sh +12 -0
- data/script/test_module.sh +10 -0
- data/script/test_style.sh +18 -0
- data/test/documentation_test.rb +17 -10
- data/test/emoji_test.rb +44 -54
- data/test/test_helper.rb +12 -2
- data/vendor/{unicode-negarmoji-test.txt → unicode-emoji-test.txt} +4028 -3842
- metadata +109 -11
- data/.travis.yml +0 -12
- data/script/console +0 -16
- data/script/release +0 -31
- data/script/test +0 -14
data/negarmoji.gemspec
CHANGED
@@ -11,14 +11,21 @@ Gem::Specification.new do |spec|
|
|
11
11
|
spec.authors = ["Mohammad Mahdi Baghbani Pourvahid"]
|
12
12
|
spec.email = "MahdiBaghbani@protonmail.com"
|
13
13
|
spec.homepage = "https://gitlab.com/Azadeh-Afzar/Web-Development/Negareh-Emoji-Library"
|
14
|
-
spec.description = "
|
15
|
-
spec.summary = "Unicode emoji library"
|
14
|
+
spec.description = "Character information and metadata for Unicode emoji."
|
15
|
+
spec.summary = "Unicode emoji library."
|
16
16
|
spec.licenses = "GPL-3.0"
|
17
17
|
|
18
18
|
spec.files = `git ls-files -z`.split("\x0")
|
19
|
-
spec.executables = spec.files.grep(%r
|
20
|
-
spec.test_files = spec.files.grep(%r
|
19
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
20
|
+
spec.test_files = spec.files.grep(%r{^test/})
|
21
21
|
spec.require_paths = ["lib"]
|
22
22
|
|
23
23
|
spec.required_ruby_version = ">= 2.3.0"
|
24
|
+
|
25
|
+
spec.add_development_dependency "bundler", "~> 2.0"
|
26
|
+
spec.add_development_dependency "minitest", "~> 5.13"
|
27
|
+
spec.add_development_dependency "rake", "~> 13.0"
|
28
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
29
|
+
spec.add_development_dependency "rubocop", "~> 0.77"
|
30
|
+
spec.add_development_dependency "simplecov", "~> 0.17.0"
|
24
31
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
# Usage: script/ci_rubygems.sh
|
3
|
+
#
|
4
|
+
# Create credential file for rubygems.org.
|
5
|
+
|
6
|
+
# set flag for shell execution.
|
7
|
+
# -e Exit immediately if a command exits with a non-zero status.
|
8
|
+
set -e
|
9
|
+
|
10
|
+
mkdir -p ~/.gem
|
11
|
+
touch ~/.gem/credentials
|
12
|
+
chmod 0600 ~/.gem/credentials
|
13
|
+
printf -- "---\r\n:rubygems_api_key: %s\n" "${RUBYGEMS_API_KEY}" > ~/.gem/credentials
|
@@ -0,0 +1,91 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
|
3
|
+
# Python Standard Library
|
4
|
+
import os
|
5
|
+
import subprocess
|
6
|
+
|
7
|
+
# get path to this file's directory, then go one directory up.
|
8
|
+
file_path = os.path.abspath(os.path.dirname(__file__))
|
9
|
+
base_path = os.path.abspath(os.path.dirname(file_path))
|
10
|
+
version_file_path = os.path.join(base_path, "lib", "negarmoji", "version.rb")
|
11
|
+
|
12
|
+
# open version file.
|
13
|
+
with open(version_file_path) as file:
|
14
|
+
version_file = file.readlines()
|
15
|
+
|
16
|
+
# set version and version_info to None, so if we didn't find
|
17
|
+
# a version in version.rb, we can throw an error.
|
18
|
+
version = None
|
19
|
+
version_info = None
|
20
|
+
|
21
|
+
# find version.
|
22
|
+
for line in version_file:
|
23
|
+
if "VERSION = " in line:
|
24
|
+
# find version string and covert it to
|
25
|
+
# standard x.y.z version format.
|
26
|
+
double_quote_left = line.index("\"") + 1
|
27
|
+
double_quote_right = line[double_quote_left:].index("\"") + double_quote_left
|
28
|
+
version = line[double_quote_left:double_quote_right]
|
29
|
+
# creat a list from x.y.z string which has [x, y, z]
|
30
|
+
# notice that x, y , z must be converted to integer
|
31
|
+
version_info = [int(number) for number in version.split(".")]
|
32
|
+
|
33
|
+
# throw error if version not found.
|
34
|
+
if not version or not version_info:
|
35
|
+
raise ValueError("ERROR: version not found at version.rb.")
|
36
|
+
|
37
|
+
print("This program will tag a new release of Negareh Emoji Library\n"
|
38
|
+
+ "and it will push to gitlab and github for building,\n"
|
39
|
+
+ "gitlab will push a built gem to rubygems.org.\n\n"
|
40
|
+
+ f"current version is {version}\n\n")
|
41
|
+
|
42
|
+
# read and convert to integer.
|
43
|
+
print("Version is in X.Y.Z form.\n"
|
44
|
+
"X is version major, Y is version minor, Z is version minor.\n\n")
|
45
|
+
new_major = int(input("Enter version major number:\n"))
|
46
|
+
new_minor = int(input("Enter version minor number:\n"))
|
47
|
+
new_patch = int(input("Enter version patch number:\n"))
|
48
|
+
|
49
|
+
new_version = ".".join(map(str, [new_major, new_minor, new_patch]))
|
50
|
+
|
51
|
+
# check version to be bigger than last version.
|
52
|
+
if new_version == version:
|
53
|
+
raise ValueError("Version can't be same as current version!")
|
54
|
+
|
55
|
+
if new_major < version_info[0]:
|
56
|
+
raise ValueError("Major version can't be less than current version!")
|
57
|
+
elif new_minor < version_info[1]:
|
58
|
+
raise ValueError("Minor version can't be less than current version!")
|
59
|
+
elif new_patch < version_info[2]:
|
60
|
+
raise ValueError("Patch version can't be less than current version!")
|
61
|
+
|
62
|
+
|
63
|
+
# creat an empty list for new version.rb file
|
64
|
+
print("Writing new version. \n\n")
|
65
|
+
|
66
|
+
new_version_rb = list()
|
67
|
+
|
68
|
+
# write new VERSION in version.rb.
|
69
|
+
new_version_info = f" VERSION = \"{new_major}.{new_minor}.{new_patch}\"\n"
|
70
|
+
|
71
|
+
# replace old version with new one.
|
72
|
+
with open(version_file_path, "r") as file:
|
73
|
+
lines = file.readlines()
|
74
|
+
for line in lines:
|
75
|
+
if "VERSION = " in line:
|
76
|
+
new_version_rb.append(new_version_info)
|
77
|
+
else:
|
78
|
+
new_version_rb.append(line)
|
79
|
+
|
80
|
+
# write updated content from new_version_rb
|
81
|
+
# back into version.rb. file
|
82
|
+
with open(version_file_path, "w+") as file:
|
83
|
+
file.writelines(new_version_rb)
|
84
|
+
|
85
|
+
# do git commit and tag and push to upstreams
|
86
|
+
print("Commit and Tag and Push to upstream. \n\n")
|
87
|
+
|
88
|
+
subprocess.call(f"git commit \"{version_file_path}\" -m \"version: Negareh Emoji Library v{new_version}\"", shell=True)
|
89
|
+
subprocess.call(f"git tag \"v{new_version}\"", shell=True)
|
90
|
+
subprocess.call(f"git push origin HEAD \"v{new_version}\"", shell=True)
|
91
|
+
subprocess.call(f"git push github HEAD \"v{new_version}\"", shell=True)
|
@@ -0,0 +1,39 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
|
3
|
+
# Python Standard Library
|
4
|
+
import os
|
5
|
+
import subprocess
|
6
|
+
|
7
|
+
# get path to this file's directory, then go one directory up.
|
8
|
+
file_path = os.path.abspath(os.path.dirname(__file__))
|
9
|
+
base_path = os.path.abspath(os.path.dirname(file_path))
|
10
|
+
version_file_path = os.path.join(base_path, "lib", "negarmoji", "version.rb")
|
11
|
+
|
12
|
+
# open version file.
|
13
|
+
with open(version_file_path) as file:
|
14
|
+
version_file = file.readlines()
|
15
|
+
|
16
|
+
# set version and version_info to None, so if we didn't find
|
17
|
+
# a version in version.rb, we can throw an error.
|
18
|
+
version = None
|
19
|
+
|
20
|
+
# find version
|
21
|
+
for line in version_file:
|
22
|
+
if "VERSION = " in line:
|
23
|
+
# find version string and covert it to
|
24
|
+
# standard x.y.z version format.
|
25
|
+
double_quote_left = line.index("\"") + 1
|
26
|
+
double_quote_right = line[double_quote_left:].index("\"") + double_quote_left
|
27
|
+
version = line[double_quote_left:double_quote_right]
|
28
|
+
|
29
|
+
# throe error if version not found
|
30
|
+
if not version:
|
31
|
+
raise ValueError("ERROR: version not found at version.rb.")
|
32
|
+
|
33
|
+
# remove tag in local and remote repository
|
34
|
+
subprocess.call(f"git tag -d \"v{version}\"", shell=True)
|
35
|
+
subprocess.call(f"git push --delete origin \"v{version}\"", shell=True)
|
36
|
+
subprocess.call(f"git push --delete github \"v{version}\"", shell=True)
|
37
|
+
|
38
|
+
# revert last commit
|
39
|
+
subprocess.call(f"git revert HEAD", shell=True)
|
data/script/test.sh
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
# Usage: script/ci_test.sh
|
3
|
+
#
|
4
|
+
# run all the tests.
|
5
|
+
|
6
|
+
# set flag for shell execution.
|
7
|
+
# -e Exit immediately if a command exits with a non-zero status.
|
8
|
+
# -x Print commands and their arguments as they are executed.
|
9
|
+
set -ex
|
10
|
+
|
11
|
+
script/test_style.sh
|
12
|
+
script/test_module.sh
|
@@ -0,0 +1,18 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
# Usage: script/test_style.sh
|
3
|
+
#
|
4
|
+
# Check code style wit rubocop.
|
5
|
+
|
6
|
+
# set flag for shell execution.
|
7
|
+
# -e Exit immediately if a command exits with a non-zero status.
|
8
|
+
set -e
|
9
|
+
|
10
|
+
echo "Rubocop $(bundle exec rubocop --version)"
|
11
|
+
bundle exec rubocop -S -D -E "$@"
|
12
|
+
|
13
|
+
success=$?
|
14
|
+
if ((success != 0)); then
|
15
|
+
echo -e "\nTry running \`script/fmt -a\` to automatically fix errors"
|
16
|
+
fi
|
17
|
+
|
18
|
+
exit $success
|
data/test/documentation_test.rb
CHANGED
@@ -1,13 +1,20 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "test_helper"
|
2
4
|
|
3
5
|
# Pull the EmojiHelper example from the docs
|
4
|
-
readme = File.expand_path(
|
5
|
-
docs = File.open(readme,
|
6
|
-
eval docs.match(
|
6
|
+
readme = File.expand_path("../README.md", __dir__)
|
7
|
+
docs = File.open(readme, "r:UTF-8", &:read)
|
8
|
+
eval docs.match(%r{^module.+?^end}m)[0]
|
7
9
|
|
8
10
|
String.class_eval do
|
9
|
-
def html_safe
|
10
|
-
|
11
|
+
def html_safe
|
12
|
+
self
|
13
|
+
end
|
14
|
+
|
15
|
+
def present?
|
16
|
+
!empty?
|
17
|
+
end
|
11
18
|
end
|
12
19
|
|
13
20
|
class DocumentationTest < TestCase
|
@@ -15,7 +22,7 @@ class DocumentationTest < TestCase
|
|
15
22
|
extend EmojiHelper
|
16
23
|
|
17
24
|
def self.h(str)
|
18
|
-
str.gsub(
|
25
|
+
str.gsub("<", "<").gsub(">", ">")
|
19
26
|
end
|
20
27
|
|
21
28
|
def self.image_path(img)
|
@@ -27,7 +34,7 @@ class DocumentationTest < TestCase
|
|
27
34
|
assert_equal "It's raining " \
|
28
35
|
'<img alt="cat" src="/images/emoji/1f431.svg?123" style="vertical-align:middle" width="20" height="20" />s and ' \
|
29
36
|
'<img alt="dog" src="/images/emoji/1f436.svg?123" style="vertical-align:middle" width="20" height="20" />s!',
|
30
|
-
|
37
|
+
Helper.emojify("It's raining :cat:s and :dog:s!")
|
31
38
|
end
|
32
39
|
|
33
40
|
test "doesn't replace unknown emoji" do
|
@@ -37,10 +44,10 @@ class DocumentationTest < TestCase
|
|
37
44
|
|
38
45
|
test "escapes other HTML" do
|
39
46
|
assert_equal "You have been <script>alert('pwned!')</script>",
|
40
|
-
|
47
|
+
Helper.emojify("You have been <script>alert('pwned!')</script>")
|
41
48
|
end
|
42
49
|
|
43
50
|
test "returns nil for blank content" do
|
44
|
-
assert_nil Helper.emojify(
|
51
|
+
assert_nil Helper.emojify("")
|
45
52
|
end
|
46
53
|
end
|
data/test/emoji_test.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
require
|
2
|
-
require_relative
|
1
|
+
require "test_helper"
|
2
|
+
require_relative "../db/emoji-test-parser"
|
3
3
|
|
4
4
|
class EmojiTest < TestCase
|
5
5
|
test "fetching all negarmoji" do
|
@@ -14,11 +14,11 @@ class EmojiTest < TestCase
|
|
14
14
|
end
|
15
15
|
|
16
16
|
test "finding negarmoji by alias" do
|
17
|
-
assert_equal
|
17
|
+
assert_equal "smile", Emoji.find_by_alias("smile").name
|
18
18
|
end
|
19
19
|
|
20
20
|
test "finding nonexistent negarmoji by alias returns nil" do
|
21
|
-
assert_nil Emoji.find_by_alias(
|
21
|
+
assert_nil Emoji.find_by_alias("$$$")
|
22
22
|
end
|
23
23
|
|
24
24
|
test "finding negarmoji by unicode" do
|
@@ -32,7 +32,7 @@ class EmojiTest < TestCase
|
|
32
32
|
|
33
33
|
test "unicode_aliases" do
|
34
34
|
emoji = Emoji.find_by_unicode("\u{2728}") # sparkles
|
35
|
-
assert_equal [
|
35
|
+
assert_equal %w[2728 2728-fe0f], emoji.unicode_aliases.map { |u| Emoji::Character.hex_inspect(u) }
|
36
36
|
end
|
37
37
|
|
38
38
|
test "unicode_aliases doesn't necessarily include form without VARIATION_SELECTOR_16" do
|
@@ -41,22 +41,22 @@ class EmojiTest < TestCase
|
|
41
41
|
end
|
42
42
|
|
43
43
|
test "emojis have tags" do
|
44
|
-
emoji = Emoji.find_by_alias(
|
45
|
-
assert emoji.tags.include?(
|
46
|
-
assert emoji.tags.include?(
|
47
|
-
assert emoji.tags.include?(
|
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
48
|
end
|
49
49
|
|
50
50
|
GENDER_EXCEPTIONS = [
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
]
|
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
|
+
%r{^couple(kiss)?_},
|
58
|
+
%r{^family_}
|
59
|
+
].freeze
|
60
60
|
|
61
61
|
test "emojis have valid names" do
|
62
62
|
aliases = Emoji.all.flat_map(&:aliases)
|
@@ -66,7 +66,7 @@ class EmojiTest < TestCase
|
|
66
66
|
case name
|
67
67
|
when *GENDER_EXCEPTIONS then name
|
68
68
|
else
|
69
|
-
name.sub(
|
69
|
+
name.sub(%r{(?<=^|_)(?:wo)?man(?=_|$)}) do |match|
|
70
70
|
match == "woman" ? "man" : "woman"
|
71
71
|
end
|
72
72
|
end
|
@@ -76,7 +76,7 @@ class EmojiTest < TestCase
|
|
76
76
|
alias_count = Hash.new(0)
|
77
77
|
aliases.each do |name|
|
78
78
|
alias_count[name] += 1
|
79
|
-
invalid << name if name !~
|
79
|
+
invalid << name if name !~ %r{\A[\w+-]+\Z}
|
80
80
|
another_gender = to_another_gender.call(name)
|
81
81
|
gender_mismatch << another_gender unless aliases.include?(another_gender)
|
82
82
|
end
|
@@ -89,23 +89,20 @@ class EmojiTest < TestCase
|
|
89
89
|
end
|
90
90
|
|
91
91
|
test "missing or incorrect unicodes" do
|
92
|
-
emoji_map,
|
92
|
+
emoji_map, = EmojiTestParser.parse(File.expand_path("../vendor/unicode-emoji-test.txt", __dir__))
|
93
93
|
source_unicode_emoji = emoji_map.values
|
94
|
+
supported_sequences = Emoji.all.flat_map(&:unicode_aliases)
|
94
95
|
text_glyphs = Emoji.const_get(:TEXT_GLYPHS)
|
95
96
|
|
96
97
|
missing = 0
|
97
98
|
message = "Missing or incorrect unicodes:\n"
|
98
99
|
source_unicode_emoji.each do |emoji|
|
99
100
|
emoji[:sequences].each do |raw|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
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]
|
101
|
+
next if text_glyphs.include?(raw) || Emoji.find_by_unicode(raw)
|
102
|
+
|
103
|
+
message << format("%s (%s)", Emoji::Character.hex_inspect(raw), emoji[:description])
|
104
|
+
if (found = Emoji.find_by_unicode(raw.gsub("\u{fe0f}", "")))
|
105
|
+
message << format(" - could be %s (:%s:)", found.hex_inspect, found.name)
|
109
106
|
end
|
110
107
|
message << "\n"
|
111
108
|
missing += 1
|
@@ -115,31 +112,24 @@ class EmojiTest < TestCase
|
|
115
112
|
assert_equal 0, missing, message
|
116
113
|
end
|
117
114
|
|
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
115
|
test "negarmoji have category" do
|
126
116
|
missing = Emoji.all.select { |e| e.category.to_s.empty? }
|
127
117
|
assert_equal [], missing.map(&:name), "some negarmoji don't have a category"
|
128
118
|
|
129
|
-
emoji = Emoji.find_by_alias(
|
130
|
-
assert_equal
|
119
|
+
emoji = Emoji.find_by_alias("family_man_woman_girl")
|
120
|
+
assert_equal "People & Body", emoji.category
|
131
121
|
|
132
122
|
categories = Emoji.all.map(&:category).uniq.compact
|
133
123
|
assert_equal [
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
124
|
+
"Smileys & Emotion",
|
125
|
+
"People & Body",
|
126
|
+
"Animals & Nature",
|
127
|
+
"Food & Drink",
|
128
|
+
"Travel & Places",
|
129
|
+
"Activities",
|
130
|
+
"Objects",
|
131
|
+
"Symbols",
|
132
|
+
"Flags"
|
143
133
|
], categories
|
144
134
|
end
|
145
135
|
|
@@ -147,21 +137,21 @@ class EmojiTest < TestCase
|
|
147
137
|
missing = Emoji.all.select { |e| e.description.to_s.empty? }
|
148
138
|
assert_equal [], missing.map(&:name), "some negarmoji don't have a description"
|
149
139
|
|
150
|
-
emoji = Emoji.find_by_alias(
|
151
|
-
assert_equal
|
140
|
+
emoji = Emoji.find_by_alias("family_man_woman_girl")
|
141
|
+
assert_equal "family: man, woman, girl", emoji.description
|
152
142
|
end
|
153
143
|
|
154
144
|
test "negarmoji have Unicode version" do
|
155
|
-
emoji = Emoji.find_by_alias(
|
156
|
-
assert_equal
|
145
|
+
emoji = Emoji.find_by_alias("family_man_woman_girl")
|
146
|
+
assert_equal "6.0", emoji.unicode_version
|
157
147
|
end
|
158
148
|
|
159
149
|
test "negarmoji have iOS version" do
|
160
150
|
missing = Emoji.all.select { |e| e.ios_version.to_s.empty? }
|
161
151
|
assert_equal [], missing.map(&:name), "some negarmoji don't have an iOS version"
|
162
152
|
|
163
|
-
emoji = Emoji.find_by_alias(
|
164
|
-
assert_equal
|
153
|
+
emoji = Emoji.find_by_alias("family_man_woman_girl")
|
154
|
+
assert_equal "8.3", emoji.ios_version
|
165
155
|
end
|
166
156
|
|
167
157
|
test "no custom emojis" do
|