Compare commits

...

39 Commits

Author SHA1 Message Date
Vicent Marti
1e85635643 Replace emoji from a LUT 2015-05-18 17:41:13 +02:00
Joshua Peek
df1b6fac6e Merge pull request #66 from asianmack/basecamp
Add emoji for :basecamp: and :basecampy:
2014-11-06 12:36:50 -08:00
Jamie Dihiansan
eda537e1a9 Add :basecamp: and :basecampy: to emoji.json 2014-11-06 12:49:49 -06:00
Jamie Dihiansan
9967b2ef28 Add emoji for :basecamp: and :basecampy: 2014-11-06 12:25:44 -06:00
Javan Makhmali
d41a53d459 Merge pull request #65 from tricknotes/ruby-2.2
Test against Ruby 2.2 on Travis CI
2014-10-23 09:44:44 -05:00
Ryunosuke SATO
06a2df3427 Test against Ruby 2.2 on Travis CI 2014-10-21 00:21:16 +09:00
Mislav Marohnić
757584d2b9 Merge pull request #63 from github/extractor
Extract PNG images from Apple's "Apple Color Emoji.ttf" font
2014-10-16 15:50:52 +02:00
Mislav Marohnić
f5092b7aa4 Tweak extractor.rb code style 2014-10-16 13:06:20 +02:00
Mislav Marohnić
8a9a8572aa Run the rest of the PNGs through ImageOptim
Command used:

    $ imageOptim -a -d images/emoji/
2014-09-25 10:19:41 -07:00
Mislav Marohnić
3d35b9f862 Simplify special case for "black_medium_square" in checksum test 2014-09-25 10:19:41 -07:00
Javan Makhmali
5dea160045 Update test for expected identical emoji checksums 2014-09-25 10:19:41 -07:00
Javan Makhmali
6984758915 Extract and optimize PNGs from "Apple Color Emoji.ttf"
Commands used:

    $ rake images:extract
    $ imageOptim -a -d images/emoji/unicode/

This required both ImageOptim and ImageAlpha to be installed as OS X apps.
2014-09-25 10:17:30 -07:00
Javan Makhmali
29c25127d0 Automate extracting PNG images from "Apple Color Emoji.ttf" 2014-09-25 10:17:29 -07:00
Mislav Marohnić
701f434b60 gemoji 2.1.0 2014-08-06 17:56:17 -07:00
Mislav Marohnić
112cc8fb8b Replace MAINTAINING with CONTRIBUTING 2014-08-06 17:54:19 -07:00
Mislav Marohnić
5162959546 Refactor test to remove Ruby syntax warning 2014-08-06 17:38:26 -07:00
Mislav Marohnić
75ada7cc89 Merge pull request #60 from github/resolve-unicode-aliases
Resolve the emoji.json "unicodes" mess
2014-08-06 17:24:48 -07:00
Mislav Marohnić
0bb789e3e6 Convert applescript to plain text format
So that it's readable and diffable from the web interface

[ci skip]
2014-08-06 07:51:55 -07:00
Mislav Marohnić
9beb9c0172 Remove need for explicit "unicodes" aliases in emoji.json
We now operate on a new set of assumptions:

- Characters with VARIATION_SELECTOR_15 shouldn't render as emoji, even
  if OS X doesn't respect that currently. This removes explicit aliases
  that include VARIATION_SELECTOR_15.

- VARIATION_SELECTOR_16 is optional for most characters to render as
  emoji on OS X. For those that *don't* have it optional, we include
  VARIATION_SELECTOR_16 in their raw representation in `emoji.json`.
  Other characters list their form including VARIATION_SELECTOR_16
  implicitly in `unicode_aliases`.

- For emoji that consist of 2 characters + variation selector, we assume
  that the selector can come between the 2 characters or *after* them,
  so `find_by_unicode` now supports both forms.

- The `db/aliases.html` script ensures that `emoji.json` only contains
  characters that Safari on OS X actually renders as emojis.
2014-08-06 00:08:47 -07:00
Mislav Marohnić
ea70c98946 Only create canvas elements of just the size required to create an emoji
Otherwise canvas element defaults to a larger size.
2014-08-06 00:08:47 -07:00
Mislav Marohnić
7d416739ba Merge pull request #59 from github/script-tools
Add useful tools to `script/*`
2014-08-06 00:08:11 -07:00
Mislav Marohnić
96295d7871 Add script/release 2014-08-05 23:51:22 -07:00
Mislav Marohnić
584939127e Add script/regenerate to rebuild db/emoji.json database
Uses AppleScript to open Safari and filter the emojis by whether they
render as actual emoji on OS X or not.
2014-08-05 23:25:35 -07:00
Mislav Marohnić
680d1bc59b Add script/console for experimentation from Ruby 2014-08-05 23:08:01 -07:00
Mislav Marohnić
2c58377420 Configure Travis CI to use script/test 2014-08-05 23:07:39 -07:00
Mislav Marohnić
3bb3cea8d3 Add script/bootstrap & script/test 2014-08-05 23:06:52 -07:00
Mislav Marohnić
5e6dcae949 Merge pull request #58 from github/plain-copyright
Don't treat plain "(c)" symbol or similar as emoji
2014-08-05 22:29:50 -07:00
Mislav Marohnić
2aaf9693a9 Ruby 1.9 compat in tests 2014-08-05 22:27:01 -07:00
Mislav Marohnić
0d1a82dc6a Don't treat plain "(c)" symbol or similar as emoji
Unless these characters are followed by VARIATION SELECTOR-16, which
indicates that the should be rendered as emoji, OS X renders these
characters using plain font glyphs.

Previously we assumed that the emoji list we get from
`Category-Emoji.json` (OS X emoji character picker) are all valid emoji,
but for some reason some plain Unicode characters are included in there
without being suffixed with VARIATION SELECTOR-16.
2014-08-05 22:16:54 -07:00
Mislav Marohnić
6b9cdd6eb5 Rename PNGs on disk to not contain VARIATION_SELECTOR_16
Even if the emoji contains it, the filename on disk doesn't have to.
This will reduce having to keep renaming PNGs on disk while we tweak the
emoji database in the future in regard to which are required to have
VARIATION_SELECTOR_16 and which are not.
2014-08-05 22:16:27 -07:00
Mislav Marohnić
75f837e6b5 Improve failure message for images on disk test 2014-08-05 22:16:27 -07:00
Mislav Marohnić
c2286e7c5b Fix failure message in tests
This got broken by Emoji::Character API change in
3935375ca8
2014-08-05 20:29:17 -07:00
Adam Roben
3e21d95409 Merge pull request #56 from github/match-osx-behavior
Use the same unicode aliases as Safari 7.0.5 on OS X 10.9.4
2014-08-01 23:06:51 -04:00
Adam Roben
a86999a7f1 Fix tests 2014-08-01 14:11:13 -04:00
Adam Roben
b7c2b8e4d8 Remove incorrect unicode aliases
db/aliases.html now clears out any incorrect aliases it finds.
2014-08-01 13:56:38 -04:00
Adam Roben
1212951bc6 Use the same unicode aliases as Safari 7.0.5 on OS X 10.9.4
Category-Emoji.json contains many code point sequences ending in U+FE0F
VARIATION SELECTOR-16. OS X renders some of these code point sequences
as color emoji even if you strip off VARIATION SELECTOR-16. (And in fact
it even renders some of them as color emoji if you replace VARIATION
SELECTOR-16 with VARIATION SELECTOR-15, even though that is explicitly
requesting a "text" variant of the character).

We used to assume that VARIATION SELECTOR-16 was optional for all emoji.
But this doesn't match OS X's behavior. This could cause problems, e.g.,
if you were to use the unicode_aliases property to detect Unicode emoji
and replace them with images for browsers that don't support emoji
natively.

The Ruby code no longer does anything special with VARIATION SELECTOR-16
other than to remove it from the description of each emoji. The new
db/aliases.html file can be used to determine which the correct Unicode
aliases for each emoji are. That page takes each emoji, generates a set
of variants using VARIATION SELECTOR-16 and VARIATION SELECTOR-15,
and renders each variant into a <canvas> element twice: once with a red
font color, and once with a green font color. If the variant renders the
same way, the OS is rendering the variant as a color emoji, and we add
it to the "unicodes" array for that emoji.

So the new process for generating db/emoji.json is:

1. rake db:dump > tmp
2. mv tmp db/emoji.json
3. open -a Safari db/aliases.html
4. Copy the resulting JSON from Safari
5. pbpaste > db/emoji.json

This ensures that unicode_aliases only contains those code point
sequences which actually render as color emoji on OS X.
2014-08-01 13:37:40 -04:00
Joshua Peek
b1736a387c Merge pull request #54 from jeremy/nil_style_find_api
Change find_by_* to return nil rather than raise an exception
2014-07-19 13:14:51 -07:00
Jeremy Kemper
f9aba615af Change find_by_* to return nil rather than raise an exception.
This is a breaking API change.

You probably have code that looks like
  if emoji = Emoji.find_by_alias($1) { nil }
that you can change to
  if emoji = Emoji.find_by_alias($1)
2014-07-18 09:16:21 -07:00
Jeremy Kemper
2741be5eb6 Reflect current 2.0.0 release in Gemfile.lock 2014-07-17 17:50:05 -07:00
1000 changed files with 711 additions and 193 deletions

View File

@@ -1,5 +1,7 @@
script: script/test
rvm:
- 1.9.3
- 2.1.2
- 2.2
notifications:
email: false

49
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,49 @@
Our emoji set is based off Apple's emoji character palette, plus some custom
emoji such as :octocat: :shipit: :metal:.
Some useful tools in development are:
```
script/bootstrap
```
Sets up the development environment. The prerequisites are:
* Ruby 1.9+
* Bundler
```
rake db:generate
```
On OS X, this will rebuild the `db/Category-Emoji.json` file from the system
one, pulling in any new emoji that Apple may have added in the meantime.
```
script/test
```
Runs the test suite, including the integrity test where we assert that we have
covered each of Apple's emoji.
```
script/regenerate
```
Rebuilds the `db/emoji.json` file which is our main list of emoji: their
canonical representations, descriptions, aliases, and tags. This requires OS X
because Safari is used in the process to verify which character render as emoji
and which render as ordinary Unicode glyphs from the current font.
```
script/console
```
Opens `irb` console with gemoji library preloded for experimentation.
```
script/release
```
For maintainers only: after the gemspec has been edited, this commits the
change, tags a release, and pushes it to both GitHub and RubyGems.org.

View File

@@ -1,5 +1,6 @@
source "https://rubygems.org"
gem "ttfunk", "~> 1.4.0"
gem "rake"
gem "minitest"

View File

@@ -1,13 +1,14 @@
PATH
remote: .
specs:
gemoji (1.5.0)
gemoji (2.1.0)
GEM
remote: https://rubygems.org/
specs:
minitest (5.3.5)
rake (10.3.2)
ttfunk (1.4.0)
PLATFORMS
ruby
@@ -16,3 +17,4 @@ DEPENDENCIES
gemoji!
minitest
rake
ttfunk (~> 1.4.0)

View File

@@ -1,27 +0,0 @@
# Maintainers
## Releasing a new gem
If you are just adding new emoji or making a small fix, only increment the patch level "1.0.x". If you need to rename a ton of emojis or making any other radical (but still mostly backwards compatible changes), bump the minor version "1.x.x".
### Make a release commit
To prepare the release commit, edit the [gemoji.gemspec](https://github.com/github/gemoji/blob/master/gemoji.gemspec) `version` value. Then make a single commit with the description as "Gemoji 1.x.x". Finally, tag the commit with `v1.x.x`.
Example commit https://github.com/github/gemoji/commit/v1.0.0
```
$ git ci -m "Gemoji 1.0.0"
$ git tag v1.0.0
$ git push
$ git push --tags
```
### Publish the gem
Build and push the new gem with
```
$ gem build gemoji.gemspec
$ gem push gemoji-1.0.0.gem
```

View File

@@ -56,7 +56,7 @@ See the [Emoji cheat sheet](http://www.emoji-cheat-sheet.com) for more examples.
module EmojiHelper
def emojify(content)
h(content).to_str.gsub(/:([\w+-]+):/) do |match|
if emoji = Emoji.find_by_alias($1) { nil }
if emoji = Emoji.find_by_alias($1)
%(<img alt="#$1" src="#{asset_path("emoji/#{emoji.image_filename}")}" style="vertical-align:middle" width="20" height="20" />)
else
match

View File

@@ -1,4 +1,5 @@
require 'rake/testtask'
require 'rake/extensiontask'
task :default => :test
@@ -27,3 +28,25 @@ end
file 'db/NamesList.txt' do |t|
system "curl -fsSL '#{nameslist_url}' -o '#{t.name}'"
end
namespace :images do
desc %(Extract PNG images from Apple's "Apple Color Emoji.ttf" font)
task :extract do
require 'emoji/extractor'
gem_dir = File.dirname(File.realpath(__FILE__))
Emoji::Extractor.new(64, "#{gem_dir}/images/emoji/unicode").extract!
end
end
namespace :c do
task :headers do
require 'emoji/tables'
gem_dir = File.dirname(File.realpath(__FILE__))
File.open(File.join(gem_dir, "ext/gemoji/emoji.h"), "w") do |file|
file.puts(Emoji::Tables.generate_length_tables)
end
end
end
Rake::ExtensionTask.new('gemoji')

13
db/aliases.applescript Normal file
View File

@@ -0,0 +1,13 @@
set jsCode to "document.getElementById('output').value"
set json to missing value
tell application "Safari"
repeat
set json to (do JavaScript jsCode in current tab of window 1)
if (json is not missing value) then exit repeat
delay 0.5
end repeat
close current tab of window 1
end tell
return json

81
db/aliases.html Normal file
View File

@@ -0,0 +1,81 @@
<!DOCTYPE html>
<title>Emoji alias detection</title>
<style>
textarea {
font-family: monospace;
}
</style>
<p>Save the following as <tt>emoji.json</tt>:</p>
<textarea id="output" rows="50" cols="80"></textarea>
<script>
const VARIATION_SELECTOR_15 = String.fromCharCode(0xfe0e);
const VARIATION_SELECTOR_16 = String.fromCharCode(0xfe0f);
const EMOJI_SIZE = 32
function detectAliases(db) {
for (var i = 0; i < db.length; ++i) {
var emoji = db[i];
var raw = emoji.emoji;
if (!raw) {
continue;
}
if (raw.indexOf(VARIATION_SELECTOR_16) > -1) {
var candidates = [raw.replace(VARIATION_SELECTOR_16, ""), raw];
} else {
var candidates = [raw, raw + VARIATION_SELECTOR_16];
}
var aliases = candidates.filter(isColorEmoji);
emoji.emoji = aliases[0];
}
dump(db);
}
function isColorEmoji(candidate) {
// Draw the emoji twice using a different color each time. If the emoji
// draws as the same color regardless of what color we set, it's a color
// emoji.
return color(candidate, "#f00") === color(candidate, "#0f0");
}
var canvas = document.createElement("canvas");
canvas.width = canvas.height = EMOJI_SIZE;
function color(emoji, rgb) {
var context = canvas.getContext("2d");
context.clearRect(0, 0, canvas.width, canvas.height);
context.fillStyle = rgb;
context.textBaseline = "top";
context.font = EMOJI_SIZE+"px Arial";
context.fillText(emoji, 0, 0);
var data = context.getImageData(0, 0, EMOJI_SIZE, EMOJI_SIZE).data;
for (var i = 0; i < data.length; i += 4) {
if (data[i] === 0 && data[i + 1] === 0 && data[i + 2] === 0) {
continue;
}
return data[i].toString(16)
+ data[i + 1].toString(16)
+ data[i + 2].toString(16);
}
return "no colored pixel found";
}
function dump(db) {
var json = JSON.stringify(db, null, " ")
.replace(/^( +)(.+)\[\](,?)$/mg, "$1$2[\n$1]$3")
.replace(/,\n( *) /g, "\n$1, ");
document.getElementById("output").value = json + "\n";
}
var xhr = new XMLHttpRequest;
xhr.onload = function() {
detectAliases(JSON.parse(this.responseText));
};
xhr.open("GET", "emoji.json", false);
xhr.send(null);
</script>

View File

@@ -52,19 +52,14 @@ end
trap(:PIPE) { abort }
items = []
variation = Emoji::VARIATION_SELECTOR_16
variation_codepoint = Emoji::VARIATION_SELECTOR_16.codepoints[0]
for emoji in Emoji.all
unicodes = emoji.unicode_aliases.dup
item = {}
unless emoji.custom?
variation_codepoint = variation.codepoints[0]
chars = emoji.raw.codepoints.map { |code| UnicodeCharacter.fetch(code) unless code == variation_codepoint }.compact
unicodes.select { |u| u.index(variation) }.each { |u| unicodes.delete(u.sub(variation, '')) }
item[:emoji] = unicodes.shift
item[:unicodes] = unicodes if unicodes.any?
item[:emoji] = emoji.raw
item[:description] = chars.map(&:description).join(' + ')
end

View File

@@ -2904,7 +2904,7 @@
]
}
, {
"emoji": "⭐"
"emoji": "⭐"
, "description": "white medium star"
, "aliases": [
"star"
@@ -2923,7 +2923,7 @@
]
}
, {
"emoji": "⛅"
"emoji": "⛅"
, "description": "sun behind cloud"
, "aliases": [
"partly_sunny"
@@ -2943,7 +2943,7 @@
]
}
, {
"emoji": "⚡"
"emoji": "⚡"
, "description": "high voltage sign"
, "aliases": [
"zap"
@@ -2954,7 +2954,7 @@
]
}
, {
"emoji": "☔"
"emoji": "☔"
, "description": "umbrella with rain drops"
, "aliases": [
"umbrella"
@@ -2977,7 +2977,7 @@
]
}
, {
"emoji": "⛄"
"emoji": "⛄"
, "description": "snowman without snow"
, "aliases": [
"snowman"
@@ -3491,7 +3491,7 @@
]
}
, {
"emoji": "⌛"
"emoji": "⌛"
, "description": "hourglass"
, "aliases": [
"hourglass"
@@ -3511,7 +3511,7 @@
]
}
, {
"emoji": "⌚"
"emoji": "⌚"
, "description": "watch"
, "aliases": [
"watch"
@@ -4487,7 +4487,7 @@
]
}
, {
"emoji": "🀄"
"emoji": "🀄"
, "description": "mahjong tile red dragon"
, "aliases": [
"mahjong"
@@ -4537,7 +4537,7 @@
]
}
, {
"emoji": "⚽"
"emoji": "⚽"
, "description": "soccer ball"
, "aliases": [
"soccer"
@@ -4596,7 +4596,7 @@
]
}
, {
"emoji": "⛳"
"emoji": "⛳"
, "description": "flag in hole"
, "aliases": [
"golf"
@@ -4700,7 +4700,7 @@
]
}
, {
"emoji": "☕"
"emoji": "☕"
, "description": "hot beverage"
, "aliases": [
"coffee"
@@ -5358,7 +5358,7 @@
]
}
, {
"emoji": "⛪"
"emoji": "⛪"
, "description": "church"
, "aliases": [
"church"
@@ -5421,7 +5421,7 @@
]
}
, {
"emoji": "⛺"
"emoji": "⛺"
, "description": "tent"
, "aliases": [
"tent"
@@ -5530,7 +5530,7 @@
]
}
, {
"emoji": "⛲"
"emoji": "⛲"
, "description": "fountain"
, "aliases": [
"fountain"
@@ -5557,7 +5557,7 @@
]
}
, {
"emoji": "⛵"
"emoji": "⛵"
, "description": "sailboat"
, "aliases": [
"boat"
@@ -5586,7 +5586,7 @@
]
}
, {
"emoji": "⚓"
"emoji": "⚓"
, "description": "anchor"
, "aliases": [
"anchor"
@@ -6014,7 +6014,7 @@
]
}
, {
"emoji": "⛽"
"emoji": "⛽"
, "description": "fuel pump"
, "aliases": [
"fuelpump"
@@ -6696,10 +6696,7 @@
]
}
, {
"emoji": "🈯"
, "unicodes": [
"指"
]
"emoji": "🈯"
, "description": "squared cjk unified ideograph-6307"
, "aliases": [
"u6307"
@@ -6709,9 +6706,6 @@
}
, {
"emoji": "🈳"
, "unicodes": [
"空"
]
, "description": "squared cjk unified ideograph-7a7a"
, "aliases": [
"u7a7a"
@@ -6721,9 +6715,6 @@
}
, {
"emoji": "🈵"
, "unicodes": [
"満"
]
, "description": "squared cjk unified ideograph-6e80"
, "aliases": [
"u6e80"
@@ -6733,9 +6724,6 @@
}
, {
"emoji": "🈴"
, "unicodes": [
"合"
]
, "description": "squared cjk unified ideograph-5408"
, "aliases": [
"u5408"
@@ -6745,9 +6733,6 @@
}
, {
"emoji": "🈲"
, "unicodes": [
"禁"
]
, "description": "squared cjk unified ideograph-7981"
, "aliases": [
"u7981"
@@ -6766,9 +6751,6 @@
}
, {
"emoji": "🈹"
, "unicodes": [
"割"
]
, "description": "squared cjk unified ideograph-5272"
, "aliases": [
"u5272"
@@ -6778,9 +6760,6 @@
}
, {
"emoji": "🈺"
, "unicodes": [
"営"
]
, "description": "squared cjk unified ideograph-55b6"
, "aliases": [
"u55b6"
@@ -6790,9 +6769,6 @@
}
, {
"emoji": "🈶"
, "unicodes": [
"有"
]
, "description": "squared cjk unified ideograph-6709"
, "aliases": [
"u6709"
@@ -6801,10 +6777,7 @@
]
}
, {
"emoji": "🈚"
, "unicodes": [
"無"
]
"emoji": "🈚"
, "description": "squared cjk unified ideograph-7121"
, "aliases": [
"u7121"
@@ -6888,7 +6861,7 @@
]
}
, {
"emoji": "♿"
"emoji": "♿"
, "description": "wheelchair symbol"
, "aliases": [
"wheelchair"
@@ -6907,10 +6880,7 @@
]
}
, {
"emoji": "🈷"
, "unicodes": [
"月"
]
"emoji": "🈷"
, "description": "squared cjk unified ideograph-6708"
, "aliases": [
"u6708"
@@ -6920,9 +6890,6 @@
}
, {
"emoji": "🈸"
, "unicodes": [
"申"
]
, "description": "squared cjk unified ideograph-7533"
, "aliases": [
"u7533"
@@ -6931,7 +6898,7 @@
]
}
, {
"emoji": "🈂"
"emoji": "🈂"
, "description": "squared katakana sa"
, "aliases": [
"sa"
@@ -7116,7 +7083,7 @@
]
}
, {
"emoji": "⛔"
"emoji": "⛔"
, "description": "no entry"
, "aliases": [
"no_entry"
@@ -7209,7 +7176,7 @@
]
}
, {
"emoji": "🅰"
"emoji": "🅰"
, "description": "negative squared latin capital letter a"
, "aliases": [
"a"
@@ -7218,7 +7185,7 @@
]
}
, {
"emoji": "🅱"
"emoji": "🅱"
, "description": "negative squared latin capital letter b"
, "aliases": [
"b"
@@ -7236,7 +7203,7 @@
]
}
, {
"emoji": "🅾"
"emoji": "🅾"
, "description": "negative squared latin capital letter o"
, "aliases": [
"o2"
@@ -7274,7 +7241,7 @@
]
}
, {
"emoji": "♈"
"emoji": "♈"
, "description": "aries"
, "aliases": [
"aries"
@@ -7283,7 +7250,7 @@
]
}
, {
"emoji": "♉"
"emoji": "♉"
, "description": "taurus"
, "aliases": [
"taurus"
@@ -7292,7 +7259,7 @@
]
}
, {
"emoji": "♊"
"emoji": "♊"
, "description": "gemini"
, "aliases": [
"gemini"
@@ -7301,7 +7268,7 @@
]
}
, {
"emoji": "♋"
"emoji": "♋"
, "description": "cancer"
, "aliases": [
"cancer"
@@ -7310,7 +7277,7 @@
]
}
, {
"emoji": "♌"
"emoji": "♌"
, "description": "leo"
, "aliases": [
"leo"
@@ -7319,7 +7286,7 @@
]
}
, {
"emoji": "♍"
"emoji": "♍"
, "description": "virgo"
, "aliases": [
"virgo"
@@ -7328,7 +7295,7 @@
]
}
, {
"emoji": "♎"
"emoji": "♎"
, "description": "libra"
, "aliases": [
"libra"
@@ -7337,7 +7304,7 @@
]
}
, {
"emoji": "♏"
"emoji": "♏"
, "description": "scorpius"
, "aliases": [
"scorpius"
@@ -7346,7 +7313,7 @@
]
}
, {
"emoji": "♐"
"emoji": "♐"
, "description": "sagittarius"
, "aliases": [
"sagittarius"
@@ -7355,7 +7322,7 @@
]
}
, {
"emoji": "♑"
"emoji": "♑"
, "description": "capricorn"
, "aliases": [
"capricorn"
@@ -7364,7 +7331,7 @@
]
}
, {
"emoji": "♒"
"emoji": "♒"
, "description": "aquarius"
, "aliases": [
"aquarius"
@@ -7373,7 +7340,7 @@
]
}
, {
"emoji": "♓"
"emoji": "♓"
, "description": "pisces"
, "aliases": [
"pisces"
@@ -7436,7 +7403,7 @@
]
}
, {
"emoji": "©"
"emoji": "
, "description": "copyright sign"
, "aliases": [
"copyright"
@@ -7445,7 +7412,7 @@
]
}
, {
"emoji": "®"
"emoji": "
, "description": "registered sign"
, "aliases": [
"registered"
@@ -7454,7 +7421,7 @@
]
}
, {
"emoji": "™"
"emoji": "™"
, "description": "trade mark sign"
, "aliases": [
"tm"
@@ -7491,7 +7458,7 @@
]
}
, {
"emoji": "❗"
"emoji": "❗"
, "description": "heavy exclamation mark symbol"
, "aliases": [
"exclamation"
@@ -7530,7 +7497,7 @@
]
}
, {
"emoji": "⭕"
"emoji": "⭕"
, "description": "heavy large circle"
, "aliases": [
"o"
@@ -7946,7 +7913,7 @@
]
}
, {
"emoji": "〰"
"emoji": "〰"
, "description": "wavy dash"
, "aliases": [
"wavy_dash"
@@ -7991,7 +7958,7 @@
]
}
, {
"emoji": "◾"
"emoji": "◾"
, "description": "black medium small square"
, "aliases": [
"black_medium_small_square"
@@ -8000,7 +7967,7 @@
]
}
, {
"emoji": "◽"
"emoji": "◽"
, "description": "white medium small square"
, "aliases": [
"white_medium_small_square"
@@ -8054,7 +8021,7 @@
]
}
, {
"emoji": "⚫"
"emoji": "⚫"
, "description": "medium black circle"
, "aliases": [
"black_circle"
@@ -8063,7 +8030,7 @@
]
}
, {
"emoji": "⚪"
"emoji": "⚪"
, "description": "medium white circle"
, "aliases": [
"white_circle"
@@ -8099,7 +8066,7 @@
]
}
, {
"emoji": "⬜"
"emoji": "⬜"
, "description": "white large square"
, "aliases": [
"white_large_square"
@@ -8108,7 +8075,7 @@
]
}
, {
"emoji": "⬛"
"emoji": "⬛"
, "description": "black large square"
, "aliases": [
"black_large_square"
@@ -8152,6 +8119,20 @@
, "tags": [
]
}
, {
"aliases": [
"basecamp"
]
, "tags": [
]
}
, {
"aliases": [
"basecampy"
]
, "tags": [
]
}
, {
"aliases": [
"bowtie"

11
ext/gemoji/emoji.h Normal file
View File

@@ -0,0 +1,11 @@
static const long emoji_byte_lengths[][5] = {
{0},
{11, 8, 7, 4, 0},
{6, 3, 0},
{7, 0},
{6, 0},
{5, 0},
};
static const int8_t emoji_magic_bytes[] =
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};

6
ext/gemoji/extconf.rb Normal file
View File

@@ -0,0 +1,6 @@
require 'mkmf'
$CFLAGS << ' -ggdb3 -O0 '
dir_config('gemoji')
create_makefile('gemoji')

125
ext/gemoji/gemoji.c Normal file
View File

@@ -0,0 +1,125 @@
#include <ruby.h>
#include <ruby/encoding.h>
#include "emoji.h"
#define unlikely(x) __builtin_expect((x),0)
static long
lookup_emoji(VALUE *rb_emoji, VALUE rb_bytes, VALUE rb_unicode_map, const long *possible_len)
{
const uint8_t *src = (uint8_t *)RSTRING_PTR(rb_bytes);
for (; *possible_len; ++possible_len) {
const long emoji_size = *possible_len;
if (emoji_size > RSTRING_LEN(rb_bytes))
continue;
if ((src[emoji_size - 1] & 0xC0) != 0x80)
continue;
rb_str_set_len(rb_bytes, emoji_size);
*rb_emoji = rb_hash_lookup(rb_unicode_map, rb_bytes);
if (!NIL_P(*rb_emoji))
return emoji_size;
}
return 0;
}
static VALUE
replace_emoji(const uint8_t *src, long size, VALUE rb_unicode_map)
{
VALUE rb_emoji, rb_bytes, rb_out = Qnil;
long i = 0, org, emoji_len;
int8_t emoji_byte;
while (i < size) {
org = i;
retry_search:
while (i < size && (emoji_byte = emoji_magic_bytes[(int)src[i]]) == 0)
i++;
if (i + 1 < size && (src[i + 1] & 0x80) != 0x80) {
i++;
goto retry_search;
}
if (unlikely(org == 0)) {
if (i == size)
return Qnil;
rb_out = rb_str_buf_new(size * 4 / 3);
rb_enc_associate(rb_out, rb_utf8_encoding());
rb_bytes = rb_str_buf_new(16);
rb_enc_associate(rb_bytes, rb_utf8_encoding());
}
if (i > org)
rb_str_buf_cat(rb_out, (const char *)src + org, i - org);
if (unlikely(i == size))
break;
emoji_len = size - i;
if (emoji_len > 12)
emoji_len = 12;
memcpy(RSTRING_PTR(rb_bytes), src + i, emoji_len);
rb_str_set_len(rb_bytes, emoji_len);
emoji_len = lookup_emoji(&rb_emoji, rb_bytes, rb_unicode_map, emoji_byte_lengths[(int)emoji_byte]);
if (emoji_len) {
VALUE rb_repl = rb_yield(rb_emoji);
if (NIL_P(rb_repl)) {
rb_str_buf_cat(rb_out, (const char *)src + i, emoji_len);
} else {
Check_Type(rb_repl, T_STRING);
rb_str_buf_append(rb_out, rb_repl);
}
i += emoji_len;
continue;
}
rb_str_buf_cat(rb_out, (const char *)src + i, 1);
i++;
}
return rb_out;
}
static VALUE
rb_gemoji_replace_unicode(VALUE klass, VALUE rb_source)
{
VALUE rb_output;
VALUE rb_unicode_map = rb_funcall(klass, rb_intern("unicodes_index"), 0);
Check_Type(rb_source, T_STRING);
Check_Type(rb_unicode_map, T_HASH);
rb_must_asciicompat(rb_source);
if (ENC_CODERANGE_ASCIIONLY(rb_source))
return rb_source;
if (rb_enc_get(rb_source) != rb_utf8_encoding())
rb_raise(rb_eEncCompatError, "expected UTF-8 encoding");
rb_output = replace_emoji((uint8_t *)RSTRING_PTR(rb_source), RSTRING_LEN(rb_source), rb_unicode_map);
if (NIL_P(rb_output))
return rb_source;
return rb_output;
}
void Init_gemoji(void)
{
VALUE rb_mEmoji = rb_define_module("Emoji");
rb_define_method(rb_mEmoji, "gsub_unicode", rb_gemoji_replace_unicode, 1);
}

View File

@@ -1,6 +1,6 @@
Gem::Specification.new do |s|
s.name = "gemoji"
s.version = "2.0.0"
s.version = "2.1.0"
s.summary = "Emoji conversion and image assets"
s.description = "Image assets and character information for emoji."

BIN
images/emoji/basecamp.png Normal file
View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 898 B

BIN
images/emoji/basecampy.png Normal file
View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1016 B

After

Width:  |  Height:  |  Size: 1004 B

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Some files were not shown because too many files have changed in this diff Show More