Compare commits

...

49 Commits

Author SHA1 Message Date
Zack Koppert
0eca75db93 Merge pull request #273 from github/dependabot-c67993ba-56b8-4f4e-a911-22640b185a14
Enable Dependabot
2024-04-02 10:52:47 -07:00
Zack Koppert
4e8e6b07eb Create dependabot.yaml 2024-01-09 21:17:56 -08:00
Mislav Marohnić
5476a66d27 gemoji 4.1.0 2023-03-29 14:56:48 +02:00
Mislav Marohnić
ee6e06c648 Merge pull request #262 from github/skin-tones-couple
Support skin tones for 🧑‍🤝‍🧑 emoji
2023-03-29 14:50:39 +02:00
Mislav Marohnić
da33f740a3 Support skin tones for 🧑‍🤝‍🧑 emoji 2023-03-29 14:47:00 +02:00
Mislav Marohnić
07b49d7de7 Merge pull request #261 from github/unicode-15
Import Emoji 15.0 characters
2023-03-29 12:17:44 +02:00
Mislav Marohnić
cb5c514d47 Import Emoji 15.0 characters 2023-03-29 12:14:38 +02:00
Mislav Marohnić
ed57eb86fd gemoji 4.0.1 2022-11-22 12:08:59 +01:00
Per Lundberg
33caddce20 Fix Ruby 2.6 breakage (#255)
Beginless ranges are a Ruby 2.7 feature and should be avoided in this gem which has `required_ruby_version = '> 1.9'`.
2022-11-22 12:02:59 +01:00
Mislav Marohnić
ac35c33c44 gemoji 4.0.0 2022-11-16 14:35:13 +01:00
Mislav Marohnić
70eb18cf81 Merge pull request #165 from github/skin-tones
Add skin tones support
2022-11-15 21:03:30 +01:00
Mislav Marohnić
d04fd7701e Merge pull request #253 from github/tests-refresh
Touch up emoji integrity tests
2022-11-15 21:01:09 +01:00
Mislav Marohnić
744495f776 Expand skin tones support
- Lookup emoji by unicode that contains a skin tone modifier
- Generate skin tone variants from an emoji
2022-11-15 20:41:33 +01:00
Mislav Marohnić
ea4d73899a People holding hands emoji doesn't seem to support skin tones rendering (macOS) 2022-11-15 20:40:52 +01:00
Mislav Marohnić
d7ca116556 Merge remote-tracking branch 'origin' into skin-tones 2022-11-15 19:21:39 +01:00
Mislav Marohnić
f7a6bb68c0 🔥 unused variable 2022-11-15 18:46:47 +01:00
Mislav Marohnić
a8d55fd539 Disallow dashes in new emoji aliases 2022-11-15 18:46:23 +01:00
Mislav Marohnić
5f3415f5fe Account for the addition of 🫃 2022-11-15 18:45:45 +01:00
Mislav Marohnić
9917299963 Merge pull request #244 from kardeslik/import-emoji-14
Import Emoji 14.0 characters
2022-11-15 18:30:26 +01:00
Mislav Marohnić
e13ac61ebd Merge pull request #252 from github/ci-update
Update Ruby CI testing setup
2022-11-15 18:29:27 +01:00
Mislav Marohnić
6af51fcecd Add tags to Unicode 14 2022-11-15 18:25:34 +01:00
Mislav Marohnić
a166a06499 Update Ruby CI testing setup 2022-11-15 18:03:48 +01:00
Mislav Marohnić
44c22eac93 🔥 Travis CI 2022-11-15 18:03:43 +01:00
Emmar Kardeslik
1c3519c6bb Import Emoji 14.0 characters 2022-07-26 12:43:16 +03:00
Kristján Oddsson
55bb37afa4 gemoji 4.0.0.rc3 2021-07-26 12:08:11 +01:00
Kristján Oddsson
64cd0e9ccf Merge pull request #209 from imageneratext/master
Import Emoji 13.1 characters
2021-07-26 12:00:14 +01:00
franciscorode
0f2f9ce047 Import Emoji 13.1 characters 2021-04-17 21:37:45 +02:00
Mislav Marohnić
b1c7878afe Change envelope and email alias (#185) 2020-10-07 17:08:43 +02:00
Job
ce6c4ab12a Changed canonical alias for email emoji 2020-08-26 09:49:07 +02:00
Job
4c47a26900 Added email tag to envelope for compatibility 2020-08-20 11:59:49 +02:00
Job
2a97e7e98c Fix indent 2020-08-20 11:57:23 +02:00
Job
f6fa963350 Move email alias from envelope to e-mail 2020-08-20 11:53:04 +02:00
Mislav Marohnić
2eb30abcd1 Merge pull request #181 from PurpleBooth/piñata-to-pinata
Safely transliterate international characters for aliases
2020-07-31 17:19:59 +02:00
Mislav Marohnić
59ef859169 Set up CI via GitHub Actions (#183) 2020-07-31 17:15:15 +02:00
Billie Thompson
be99618db3 Convert none ascii characters safely to their ASCII representation
Relates-to: github/gemoji#180
2020-07-30 22:06:23 +02:00
Kristján Oddsson
3675a8781f Merge pull request #182 from PurpleBooth/only-pinjata
Remove underscore from Pinata
2020-07-30 10:48:03 +01:00
Billie Thompson
7f6550fe73 Remove underscore from Pinata
Relates-to: github/gemoji#180
2020-07-30 08:46:57 +02:00
Mislav Marohnić
5361b5639f gemoji 4.0.0.rc2 2020-01-31 03:29:58 +01:00
Mislav Marohnić
955be747f2 Merge branch 'charvp/master' 2020-01-31 03:29:23 +01:00
Mislav Marohnić
d98617abf2 Bring back bride_with_veil for backwards compatibility 2020-01-31 03:26:58 +01:00
Charlotte Van Petegem
bf598c57fc Import Emoji 13.0 characters
https://emojipedia.org/emoji-13.0/
2020-01-30 14:16:34 +01:00
Mislav Marohnić
d371b81198 gemoji 4.0.0.rc1 2019-11-29 18:38:34 +01:00
Mislav Marohnić
cefc4b015e Merge branch 'unicode-12.1' 2019-11-29 18:37:18 +01:00
Mislav Marohnić
d1002aa48c Simplify emoji-test-parser 2019-11-29 17:44:55 +01:00
Mislav Marohnić
3cde479627 Import Unicode 12.1 characters
https://emojipedia.org/emoji-12.1/
2019-11-29 13:24:35 +01:00
Mislav Marohnić
cbf7fb30b9 Revert "Merge pull request #164 from github/mislav/text-glyphs"
This reverts commit d48b0d90ac, reversing
changes made to 03dea3bd7d.
2019-11-29 13:24:35 +01:00
Kristján Oddsson
59b3fde91e Merge pull request #169 from JuanitoFatas/fix-emoji-test-parser
Fix ArgumentError in emoji-test-parser
2019-09-16 09:29:00 +01:00
Juanito Fatas
f9e41a8739 Fix ArgumentError in emoji-test-parser 2019-09-16 14:32:34 +09:00
Mislav Marohnić
a5865153a2 Add Emoji::Character#skin_tones? 2019-07-03 18:28:34 +02:00
14 changed files with 7357 additions and 4475 deletions

11
.github/dependabot.yaml vendored Normal file
View File

@@ -0,0 +1,11 @@
---
version: 2
updates:
- package-ecosystem: 'bundler'
directory: '/'
schedule:
interval: 'weekly'
- package-ecosystem: 'github-actions'
directory: '/'
schedule:
interval: 'weekly'

24
.github/workflows/test.yml vendored Normal file
View File

@@ -0,0 +1,24 @@
name: Test
on: [push, pull_request]
jobs:
test:
strategy:
fail-fast: false
matrix:
ruby: ["2.7", "3.0", "3.1"]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{matrix.ruby}}
bundler-cache: true
- name: Run tests
run: bundle exec rake

View File

@@ -1,12 +0,0 @@
sudo: false
script: script/test
rvm:
- 1.9.3
- '2.1'
- '2.2'
- '2.3'
- '2.4'
- '2.5'
- '2.6'
notifications:
email: false

View File

@@ -2,5 +2,6 @@ source "https://rubygems.org"
gem "rake", "~> 10.3.2"
gem "minitest", "~> 5.3.5"
gem "i18n", "~> 1.8.5"
gemspec

25
Gemfile.lock Normal file
View File

@@ -0,0 +1,25 @@
PATH
remote: .
specs:
gemoji (4.1.0)
GEM
remote: https://rubygems.org/
specs:
concurrent-ruby (1.1.7)
i18n (1.8.5)
concurrent-ruby (~> 1.0)
minitest (5.3.5)
rake (10.3.2)
PLATFORMS
ruby
DEPENDENCIES
gemoji!
i18n (~> 1.8.5)
minitest (~> 5.3.5)
rake (~> 10.3.2)
BUNDLED WITH
2.4.10

View File

@@ -20,5 +20,5 @@ namespace :db do
end
file 'vendor/unicode-emoji-test.txt' do |t|
system 'curl', '-fsSL', 'http://unicode.org/Public/emoji/12.0/emoji-test.txt', '-o', t.name
system 'curl', '-fsSL', 'http://unicode.org/Public/emoji/15.0/emoji-test.txt', '-o', t.name
end

View File

@@ -1,9 +1,11 @@
# frozen_string_literal: true
require "i18n"
require 'emoji'
require 'json'
require_relative './emoji-test-parser'
I18n.config.available_locales = :en
items = []
_, categories = EmojiTestParser.parse(File.expand_path("../../vendor/unicode-emoji-test.txt", __FILE__))
@@ -12,34 +14,32 @@ seen_existing = {}
for category in categories
for sub_category in category[:emoji]
for emoji_item in sub_category[:emoji]
unicodes = emoji_item[:sequences].sort_by(&:bytesize)
existing_emoji = nil
unicodes.detect do |raw|
existing_emoji = Emoji.find_by_unicode(raw)
raw = emoji_item[:sequences][0]
existing_emoji = Emoji.find_by_unicode(raw) || Emoji.find_by_unicode("#{raw}\u{fe0f}")
if seen_existing.key?(existing_emoji)
existing_emoji = nil
else
seen_existing[existing_emoji] = true
end
existing_emoji = nil if seen_existing.key?(existing_emoji)
description = emoji_item[:description].sub(/^E\d+(\.\d+)? /, '')
output_item = {
emoji: unicodes[0],
description: emoji_item[:description],
emoji: raw,
description: description,
category: category[:name],
}
if existing_emoji
eu = existing_emoji.unicode_aliases
preferred_raw = eu.size == 2 && eu[0] == "#{eu[1]}\u{fe0f}" ? eu[1] : eu[0]
output_item.update(
emoji: preferred_raw,
aliases: existing_emoji.aliases,
tags: existing_emoji.tags,
unicode_version: existing_emoji.unicode_version,
ios_version: existing_emoji.ios_version,
)
seen_existing[existing_emoji] = true
else
output_item.update(
aliases: [emoji_item[:description].gsub(/\W+/, '_').downcase],
aliases: [I18n.transliterate(description).gsub(/\W+/, '_').downcase],
tags: [],
unicode_version: "12.0",
ios_version: "13.0",
unicode_version: "15.0",
ios_version: "16.4",
)
end
output_item[:skin_tones] = true if emoji_item[:skin_tones]

View File

@@ -9,12 +9,8 @@ module EmojiTestParser
"\u{1F3FE}", # medium-dark skin tone
"\u{1F3FF}", # dark skin tone
]
HAIR_MODIFIERS = [
"\u{1F9B0}", # red-haired
"\u{1F9B1}", # curly-haired
"\u{1F9B2}", # bald
"\u{1F9B3}", # white-haired
]
SKIN_TONES_RE = /(#{SKIN_TONES.join("|")})/o
SKIP_TYPES = ["unqualified", "component"]
module_function
@@ -52,12 +48,12 @@ module EmojiTestParser
else
row, desc = line.split("#", 2)
desc = desc.strip.split(" ", 2)[1]
codepoints, _ = row.split(";", 2)
codepoints, qualification = row.split(";", 2)
next if SKIP_TYPES.include?(qualification.strip)
emoji_raw = codepoints.strip.split.map { |c| c.hex }.pack("U*")
next if HAIR_MODIFIERS.include?(emoji_raw)
emoji_normalized = emoji_raw
.gsub(VARIATION_SELECTOR_16, "")
.gsub(/(#{SKIN_TONES.join("|")})/o, "")
.gsub(SKIN_TONES_RE, "")
emoji_item = emoji_map[emoji_normalized]
if SKIN_TONES.any? { |s| emoji_raw.include?(s) }
emoji_item[:skin_tones] = true if emoji_item
@@ -91,7 +87,7 @@ if $0 == __FILE__
html_output = true
end
_, categories = EmojiTestParser.parse
_, categories = EmojiTestParser.parse(File.expand_path("../../vendor/unicode-emoji-test.txt", __FILE__))
trap(:PIPE) { abort }

View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
Gem::Specification.new do |s|
s.name = "gemoji"
s.version = "4.0.0.pre0"
s.version = "4.1.0"
s.summary = "Unicode emoji library"
s.description = "Character information and metadata for Unicode emoji."

View File

@@ -51,11 +51,12 @@ module Emoji
# Public: Find an emoji by its unicode character. Return nil if missing.
def find_by_unicode(unicode)
unicodes_index[unicode]
unicodes_index[unicode] || unicodes_index[unicode.sub(SKIN_TONE_RE, "")]
end
private
VARIATION_SELECTOR_16 = "\u{fe0f}".freeze
SKIN_TONE_RE = /[\u{1F3FB}-\u{1F3FF}]/
# Characters which must have VARIATION_SELECTOR_16 to render as color emoji:
TEXT_GLYPHS = [
@@ -68,85 +69,9 @@ module Emoji
"\u{00ae}", # registered
"\u{2122}", # trade mark
"\u{3030}", # wavy dash
"\u{263a}", # smiling face
"\u{261D}", # index pointing up
"\u{270C}", # victory hand
"\u{270D}", # writing hand
"\u{2764}", # red heart
"\u{2763}", # heavy heart exclamation
"\u{2668}", # hot springs
"\u{2708}", # airplane
"\u{2600}", # sun
"\u{2601}", # cloud
"\u{2602}", # umbrella
"\u{2744}", # snowflake
"\u{2603}", # snowman
"\u{2660}", # spade suit
"\u{2665}", # heart suit
"\u{2666}", # diamond suit
"\u{2663}", # club suit
"\u{260e}", # telephone
"\u{2709}", # envelope
"\u{270F}", # pencil
"\u{2712}", # black nib
"\u{2702}", # scissors
"\u{26a0}", # warning
"\u{2B06}", # up arrow
"\u{2197}", # up-right arrow
"\u{27A1}", # right arrow
"\u{2198}", # down-right arrow
"\u{2B07}", # down arrow
"\u{2199}", # down-left arrow
"\u{2B05}", # left arrow
"\u{2196}", # up-left arrow
"\u{2195}", # up-down arrow
"\u{2194}", # left-right arrow
"\u{21A9}", # right arrow curving left
"\u{21AA}", # left arrow curving right
"\u{2934}", # right arrow curving up
"\u{2935}", # right arrow curving down
"\u{2721}", # star of David
"\u{262F}", # yin yang
"\u{271D}", # latin cross
"\u{25B6}", # play button
"\u{25C0}", # reverse button
"\u{23CF}", # eject button
"\u{2640}", # female sign
"\u{2642}", # male sign
"\u{267B}", # recycling symbol
"\u{2611}", # ballot box with check
"\u{2714}", # heavy check mark
"\u{2716}", # heavy multiplication x
"\u{303D}", # part alternation mark
"\u{2733}", # eight-spoked asterisk
"\u{2734}", # eight-pointed star
"\u{2747}", # sparkle
"\u{203C}", # double exclamation mark
"\u{2049}", # exclamation question mark
"\u{23}\u{20E3}", # keycap: #
"\u{2A}\u{20E3}", # keycap: *
"\u{30}\u{20E3}", # keycap: 0
"\u{31}\u{20E3}", # keycap: 1
"\u{32}\u{20E3}", # keycap: 2
"\u{33}\u{20E3}", # keycap: 3
"\u{34}\u{20E3}", # keycap: 4
"\u{35}\u{20E3}", # keycap: 5
"\u{36}\u{20E3}", # keycap: 6
"\u{37}\u{20E3}", # keycap: 7
"\u{38}\u{20E3}", # keycap: 8
"\u{39}\u{20E3}", # keycap: 9
"\u{2139}", # information
"\u{24C2}", # circled M
"\u{1F17F}", # P button
"\u{3297}", # Japanese “congratulations” button
"\u{3299}", # Japanese “secret” button
"\u{25AA}", # black small square
"\u{25AB}", # white small square
"\u{25FB}", # white medium square
"\u{25FC}", # black medium square
].freeze
private_constant :VARIATION_SELECTOR_16, :TEXT_GLYPHS
private_constant :VARIATION_SELECTOR_16, :TEXT_GLYPHS, :SKIN_TONE_RE
def parse_data_file
data = File.open(data_file, 'r:UTF-8') do |file|
@@ -194,6 +119,7 @@ module Emoji
emoji.description = dedup.call(raw_emoji[:description])
emoji.unicode_version = dedup.call(raw_emoji[:unicode_version])
emoji.ios_version = dedup.call(raw_emoji[:ios_version])
emoji.skin_tones = raw_emoji.fetch(:skin_tones, false)
end
end
end

View File

@@ -11,6 +11,11 @@ module Emoji
# True if the emoji is not a standard Emoji character.
def custom?() !raw end
# True if the emoji supports Fitzpatrick scale skin tone modifiers
def skin_tones?() @skin_tones end
attr_writer :skin_tones
# A list of names uniquely referring to this emoji.
attr_reader :aliases
@@ -38,6 +43,28 @@ module Emoji
# Raw Unicode string for an emoji. Nil if emoji is non-standard.
def raw() unicode_aliases.first end
# Raw Unicode strings for each skin tone variant of this emoji. The result is an empty array
# unless the emoji supports skin tones.
#
# Note: for emojis that depict multiple people (e.g. couples or families), this will not produce
# every possible permutation of skin tone per person.
def raw_skin_tone_variants
return [] if custom? || !skin_tones?
raw_normalized = raw.sub(VARIATION_SELECTOR_16, "")
idx = raw_normalized.index(ZERO_WIDTH_JOINER)
SKIN_TONES.map do |modifier|
if raw_normalized == PEOPLE_HOLDING_HANDS
# special case to apply the modifier to both persons
raw_normalized[0...idx] + modifier + raw_normalized[idx..nil] + modifier
elsif idx
# insert modifier before zero-width joiner
raw_normalized[0...idx] + modifier + raw_normalized[idx..nil]
else
raw_normalized + modifier
end
end
end
def add_unicode_alias(str)
unicode_aliases << str
end
@@ -54,6 +81,7 @@ module Emoji
@aliases = Array(name)
@unicode_aliases = []
@tags = []
@skin_tones = false
end
def inspect
@@ -77,6 +105,20 @@ module Emoji
private
VARIATION_SELECTOR_16 = "\u{fe0f}".freeze
ZERO_WIDTH_JOINER = "\u{200d}".freeze
PEOPLE_HOLDING_HANDS = "\u{1f9d1}\u{200d}\u{1f91d}\u{200d}\u{1f9d1}".freeze
SKIN_TONES = [
"\u{1F3FB}", # light skin tone
"\u{1F3FC}", # medium-light skin tone
"\u{1F3FD}", # medium skin tone
"\u{1F3FE}", # medium-dark skin tone
"\u{1F3FF}", # dark skin tone
]
private_constant :VARIATION_SELECTOR_16, :ZERO_WIDTH_JOINER, :PEOPLE_HOLDING_HANDS, :SKIN_TONES
def default_image_filename
if custom?
'%s.png' % name

View File

@@ -50,14 +50,19 @@ class EmojiTest < TestCase
GENDER_EXCEPTIONS = [
"man_with_gua_pi_mao",
"woman_with_headscarf",
"man_in_tuxedo",
"pregnant_woman",
"isle_of_man",
"blonde_woman",
"blonde_woman", # blond_haired_man
/^couple(kiss)?_/,
/^family_/,
]
DASH_EXCEPTIONS = [
"-1",
"t-rex",
"e-mail",
"non-potable_water",
]
test "emojis have valid names" do
aliases = Emoji.all.flat_map(&:aliases)
@@ -76,7 +81,7 @@ class EmojiTest < TestCase
alias_count = Hash.new(0)
aliases.each do |name|
alias_count[name] += 1
invalid << name if name !~ /\A[\w+-]+\Z/
invalid << name if name !~ /\A[\w+]+\Z/ && !DASH_EXCEPTIONS.include?(name)
another_gender = to_another_gender.call(name)
gender_mismatch << another_gender unless aliases.include?(another_gender)
end
@@ -97,12 +102,7 @@ class EmojiTest < TestCase
message = "Missing or incorrect unicodes:\n"
source_unicode_emoji.each do |emoji|
emoji[:sequences].each do |raw|
found = Emoji.find_by_unicode(raw)
if text_glyphs.include?(raw)
assert_nil found, Emoji::Character.hex_inspect(raw)
next
end
next if found
next if text_glyphs.include?(raw) || Emoji.find_by_unicode(raw)
message << "%s (%s)" % [Emoji::Character.hex_inspect(raw), emoji[:description]]
if found = Emoji.find_by_unicode(raw.gsub("\u{fe0f}", ""))
message << " - could be %s (:%s:)" % [found.hex_inspect, found.name]
@@ -115,13 +115,6 @@ class EmojiTest < TestCase
assert_equal 0, missing, message
end
test "raw representation does not include VARIATION SELECTOR 16 unless necessary" do
emoji = Emoji.all.select do |emoji|
!emoji.custom? && emoji.raw.end_with?("\u{fe0f}") && emoji.unicode_aliases.size == 2
end
assert_equal [], emoji
end
test "emoji have category" do
missing = Emoji.all.select { |e| e.category.to_s.empty? }
assert_equal [], missing.map(&:name), "some emoji don't have a category"
@@ -164,6 +157,36 @@ class EmojiTest < TestCase
assert_equal '8.3', emoji.ios_version
end
test "skin tones" do
smiley = Emoji.find_by_alias("smiley")
assert_equal false, smiley.skin_tones?
assert_equal [], smiley.raw_skin_tone_variants
wave = Emoji.find_by_alias("wave")
assert_equal true, wave.skin_tones?
wave = Emoji.find_by_unicode("\u{1f44b}\u{1f3ff}") # wave + dark skin tone
assert_equal "wave", wave.name
woman_with_beard = Emoji.find_by_unicode("\u{1f9d4}\u{200d}\u{2640}\u{fe0f}")
assert_equal [
"1f9d4-1f3fb-200d-2640",
"1f9d4-1f3fc-200d-2640",
"1f9d4-1f3fd-200d-2640",
"1f9d4-1f3fe-200d-2640",
"1f9d4-1f3ff-200d-2640",
], woman_with_beard.raw_skin_tone_variants.map { |u| Emoji::Character.hex_inspect(u) }
people_holding_hands = Emoji.find_by_alias("people_holding_hands")
assert_equal [
"1f9d1-1f3fb-200d-1f91d-200d-1f9d1-1f3fb",
"1f9d1-1f3fc-200d-1f91d-200d-1f9d1-1f3fc",
"1f9d1-1f3fd-200d-1f91d-200d-1f9d1-1f3fd",
"1f9d1-1f3fe-200d-1f91d-200d-1f9d1-1f3fe",
"1f9d1-1f3ff-200d-1f91d-200d-1f9d1-1f3ff",
], people_holding_hands.raw_skin_tone_variants.map { |u| Emoji::Character.hex_inspect(u) }
end
test "no custom emojis" do
custom = Emoji.all.select(&:custom?)
assert 0, custom.size

View File

File diff suppressed because it is too large Load Diff