Commit dc61de23 by Andrew Cantino

Merge remote-tracking branch 'mwunsch/master'

Conflicts:
	lib/rumoji/emoji/symbols.rb
parents 9647b786 344433e1
language: ruby
rvm:
- 1.9.3
- 2.0.0
- 2.1.0
- rbx
matrix:
allow_failures:
- rvm: rbx
......@@ -4,3 +4,8 @@ source 'https://rubygems.org'
gemspec
gem 'rake'
platforms :rbx do
gem 'rubysl', '~> 2.0'
gem 'minitest'
end
Copyright (c) 2012 Mark Wunsch
Copyright (c) 2013 Mark Wunsch
MIT License
......
......@@ -48,12 +48,10 @@ On the command line
Implement the emoji codes from emoji-cheat-sheet.com using a tool like [gemoji](https://github.com/github/gemoji) along with Rumoji, and you'll easily be able to transform user input with raw emoji unicode into images you can show to all users.
Currently, Rumoji only supports the _People_ and _Nature_ characters in emoji-cheat-sheet, but that will change!
_Having trouble discerning what's happening in this README?_ You might be on a device with NO emoji support! All the more reason to use Rumoji. Transcode the raw unicode into something users can understand across devices!
Thanks!
## Copyright
Copyright (c) 2009 - 2012 Mark Wunsch. Licensed under the [MIT License](http://opensource.org/licenses/mit-license.php).
Copyright (c) 2012 - 2015 Mark Wunsch. Licensed under the [MIT License](http://opensource.org/licenses/mit-license.php).
......@@ -8,24 +8,49 @@ module Rumoji
# Transform emoji into its cheat-sheet code
def encode(str)
remapped_codepoints = str.codepoints.flat_map do |codepoint|
emoji = Emoji.find_by_codepoint(codepoint)
emoji ? emoji.code.codepoints.entries : codepoint
end
remapped_codepoints.pack("U*")
io = StringIO.new(str)
encode_io(io).string
end
# Transform a cheat-sheet code into an Emoji
def decode(str)
str.gsub(/:(\S?\w+):/) {|sym| Emoji.find($1.intern).to_s }
str.gsub(/:([^s:]?[\w-]+):/) {|sym| (Emoji.find($1.intern) || sym).to_s }
end
def encode_io(readable, writeable=StringIO.new(""))
previous_codepoints = []
readable.each_codepoint do |codepoint|
emoji = Emoji.find_by_codepoint(codepoint)
emoji_or_character = emoji ? emoji.code : [codepoint].pack("U")
writeable.write emoji_or_character
possible_emoji = Emoji.select_by_codepoint(codepoint)
sequence = if possible_emoji.empty?
# If this codepoint is not part of an emoji
# just write it back out, along with any previously stored codepoints.
dump_codepoints_to_string(previous_codepoints << codepoint)
elsif !possible_emoji.any?(&:multiple?)
# If this codepoint is part of an emoji, but not one
# that contains multiple codepoints, write out the
# first possiblity's cheat code and the previously stored codepoints
dump_codepoints_to_string(previous_codepoints) << possible_emoji.first.code
else
# This codepoint is a part of an emoji with multiple
# codepoints, so push it onto the stack.
previous_codepoints.push(codepoint)
# Check and see if this completes the emoji, otherwise,
# write out an empty string.
if found = possible_emoji.find {|e| e.codepoints.eql?(previous_codepoints) }
previous_codepoints.clear and found.code
else
""
end
end
writeable.write sequence
end
# Write any remaining codepoints.
writeable.write dump_codepoints_to_string(previous_codepoints) if previous_codepoints.any?
writeable
end
......@@ -36,4 +61,12 @@ module Rumoji
writeable
end
private
def dump_codepoints_to_string(codepoints)
codepoints.pack("U*").tap do
codepoints.clear
end
end
end
......@@ -23,7 +23,7 @@ module Rumoji
end
def to_s
@codepoints.to_a.pack("U*")
codepoints.pack("U*")
end
def hash
......@@ -34,6 +34,14 @@ module Rumoji
@codepoints.map{|point| point.to_s(16).upcase }.join("-")
end
def codepoints
@codepoints.entries
end
def multiple?
codepoints.size > 1
end
autoload :PEOPLE, 'rumoji/emoji/people'
autoload :NATURE, 'rumoji/emoji/nature'
autoload :OBJECTS, 'rumoji/emoji/objects'
......@@ -50,8 +58,13 @@ module Rumoji
ALL.find {|emoji| emoji.to_s == string }
end
def self.select_by_codepoint(codepoint)
ALL.select {|emoji| emoji.codepoints.include? codepoint }
end
def self.find_by_codepoint(codepoint)
ALL.find {|emoji| emoji.hex == codepoint.to_s(16).upcase }
end
end
end
......@@ -97,7 +97,7 @@ module Rumoji
self.new("\u{1F333}", [:deciduous_tree]),
self.new("\u{1F330}", [:chestnut]),
self.new("\u{1F331}", [:seedling]),
self.new("\u{1F33C}", [:blossum]), # "daisy"
self.new("\u{1F33C}", [:blossom]), # "daisy"
self.new("\u{1F33E}", [:ear_of_rice]),
self.new("\u{1F41A}", [:shell], "SPIRAL SHELL"),
self.new("\u{1F310}", [:globe_with_meridians]), # "used to indicate international input source, world clocks with time zones, etc."
......
......@@ -20,7 +20,7 @@ module Rumoji
self.new("\u{1F60C}", [:satisfied], "RELIEVED FACE"),
self.new("\u{1F601}", [:grin], "GRINNING FACE WITH SMILING EYES"),
self.new("\u{1F609}", [:wink], "WINKING FACE"),
self.new("\u{1F61C}", [:wink2, :stuck_out_tongue_winking_eye], "FACE WITH STUCK OUT TONGUE AND WINKING EYE"), # "kidding, not serious"
self.new("\u{1F61C}", [:stuck_out_tongue_winking_eye, :wink2], "FACE WITH STUCK OUT TONGUE AND WINKING EYE"), # "kidding, not serious"
self.new("\u{1F61D}", [:stuck_out_tongue_closed_eyes], "FACE WITH STUCK-OUT TONGUE AND TIGHTLY-CLOSED EYES"), # "kidding, not serious"
self.new("\u{1F600}", [:grinning], "GRINNING FACE"),
self.new("\u{1F617}", [:kissing], "KISSING FACE"),
......@@ -40,7 +40,7 @@ module Rumoji
self.new("\u{1F613}", [:sweat], "FACE WITH COLD SWEAT"),
self.new("\u{1F629}", [:weary], "WEARY FACE"),
self.new("\u{1F614}", [:pensive], "PENSIVE FACE"),
self.new("\u{1F61E}", [:dissapointed], "DISAPPOINTED FACE"),
self.new("\u{1F61E}", [:disappointed], "DISAPPOINTED FACE"),
self.new("\u{1F616}", [:confounded], "CONFOUNDED FACE"),
self.new("\u{1F628}", [:fearful], "FEARFUL FACE"),
self.new("\u{1F630}", [:cold_sweat], "FACE WITH OPEN MOUTH AND COLD SWEAT"),
......@@ -94,7 +94,7 @@ module Rumoji
self.new("\u{1F3B5}", [:musical_note]), # "music, being in good mood"
self.new("\u{1F525}", [:fire], "FIRE"),
# Poop
self.new("\u{1F4A9}", [:hankey, :poop, :shit], "PILE OF POO"), # "dog dirt"
self.new("\u{1F4A9}", [:poop, :hankey, :shit], "PILE OF POO"), # "dog dirt"
self.new("\u{1F44D}", [:thumbsup, :"+1"], "THUMBS UP SIGN"),
self.new("\u{1F44E}", [:thumbsdown, :"-1"], "THUMBS DOWN SIGN"),
self.new("\u{1F44C}", [:ok_hand], "OK HAND SIGN"),
......
......@@ -98,16 +98,16 @@ module Rumoji
self.new("\u{26a0}" , [:warning]),
self.new("\u{1f492}", [:wedding]),
# Regional Indicator Symbols
self.new("\u{1f1ef}\u{1f1f5}", [:jp], "REGIONAL INDICATOR SYMBOL LETTERS JP"),
self.new("\u{1f1f0}\u{1f1f7}", [:kr], "REGIONAL INDICATOR SYMBOL LETTERS KR"),
self.new("\u{1f1e8}\u{1f1f3}", [:cn], "REGIONAL INDICATOR SYMBOL LETTERS CN"),
self.new("\u{1f1fa}\u{1f1f8}", [:us], "REGIONAL INDICATOR SYMBOL LETTERS US"),
self.new("\u{1f1eb}\u{1f1f7}", [:fr], "REGIONAL INDICATOR SYMBOL LETTERS FR"),
self.new("\u{1f1ea}\u{1f1f8}", [:es], "REGIONAL INDICATOR SYMBOL LETTERS ES"),
self.new("\u{1f1ee}\u{1f1f9}", [:it], "REGIONAL INDICATOR SYMBOL LETTERS IT"),
self.new("\u{1f1f7}\u{1f1fa}", [:ru], "REGIONAL INDICATOR SYMBOL LETTERS RU"),
self.new("\u{1f1ec}\u{1f1e7}", [:gb, :uk], "REGIONAL INDICATOR SYMBOL LETTERS GB"),
self.new("\u{1f1e9}\u{1f1ea}", [:de], "REGIONAL INDICATOR SYMBOL LETTERS DE"),
self.new("\u{1f1ef 1f1f5}", [:jp], "REGIONAL INDICATOR SYMBOL LETTERS JP"),
self.new("\u{1f1f0 1f1f7}", [:kr], "REGIONAL INDICATOR SYMBOL LETTERS KR"),
self.new("\u{1f1e8 1f1f3}", [:cn], "REGIONAL INDICATOR SYMBOL LETTERS CN"),
self.new("\u{1f1fa 1f1f8}", [:us], "REGIONAL INDICATOR SYMBOL LETTERS US"),
self.new("\u{1f1eb 1f1f7}", [:fr], "REGIONAL INDICATOR SYMBOL LETTERS FR"),
self.new("\u{1f1ea 1f1f8}", [:es], "REGIONAL INDICATOR SYMBOL LETTERS ES"),
self.new("\u{1f1ee 1f1f9}", [:it], "REGIONAL INDICATOR SYMBOL LETTERS IT"),
self.new("\u{1f1f7 1f1fa}", [:ru], "REGIONAL INDICATOR SYMBOL LETTERS RU"),
self.new("\u{1f1ec 1f1e7}", [:gb, :uk], "REGIONAL INDICATOR SYMBOL LETTERS GB"),
self.new("\u{1f1e9 1f1ea}", [:de], "REGIONAL INDICATOR SYMBOL LETTERS DE"),
]
end
end
......@@ -81,16 +81,16 @@ module Rumoji
self.new("\u{1f6c3}", [:customs]),
self.new("\u{1f4a0}", [:diamond_shape_with_a_dot_inside]),
self.new("\u{1f6af}", [:do_not_litter]),
# self.new("\u{0038}" , [:eight]),
self.new("\u{0038 fe0f 20e3}" , [:eight]),
self.new("\u{2734}" , [:eight_pointed_black_star]),
self.new("\u{2733}" , [:eight_spoked_asterisk]),
self.new("\u{1f51a}", [:end]),
self.new("\u{23e9}" , [:fast_forward]),
# self.new("\u{0035}" , [:five]),
# self.new("\u{0034}" , [:four]),
self.new("\u{0035 fe0f 20e3}" , [:five]),
self.new("\u{0034 fe0f 20e3}" , [:four]),
self.new("\u{1f193}", [:free]),
self.new("\u{264a}" , [:gemini]),
# self.new("\u{0023}" , [:hash]),
self.new("\u{0023 fe0f 20e3}" , [:hash]),
self.new("\u{1f49f}", [:heart_decoration]),
self.new("\u{2714}" , [:heavy_check_mark]),
self.new("\u{2797}" , [:heavy_division_sign]),
......@@ -120,7 +120,7 @@ module Rumoji
self.new("\u{274e}" , [:negative_squared_cross_mark]),
self.new("\u{1f195}", [:new]),
self.new("\u{1f196}", [:ng]),
# self.new("\u{0039}" , [:nine]),
self.new("\u{0039 fe0f 20e3}" , [:nine]),
self.new("\u{1f6b3}", [:no_bicycles]),
self.new("\u{26d4}" , [:no_entry]),
self.new("\u{1f6ab}", [:no_entry_sign]),
......@@ -132,7 +132,7 @@ module Rumoji
self.new("\u{1f17e}", [:o2]),
self.new("\u{1f197}", [:ok]),
self.new("\u{1f51b}", [:on]),
# self.new("\u{0031}" , [:one]),
self.new("\u{0031 fe0f 20e3}" , [:one]),
self.new("\u{26ce}" , [:ophiuchus]),
self.new("\u{1f17f}", [:parking]),
self.new("\u{303d}" , [:part_alternation_mark]),
......@@ -152,9 +152,9 @@ module Rumoji
self.new("\u{2650}" , [:sagittarius]),
self.new("\u{264f}" , [:scorpius]),
self.new("\u{3299}" , [:secret]),
# self.new("\u{0037}" , [:seven]),
self.new("\u{0037 fe0f 20e3}" , [:seven]),
self.new("\u{1f4f6}", [:signal_strength]),
# self.new("\u{0036}" , [:six]),
self.new("\u{0036 fe0f 20e3}" , [:six]),
self.new("\u{1f52f}", [:six_pointed_star]),
self.new("\u{1f539}", [:small_blue_diamond]),
self.new("\u{1f538}", [:small_orange_diamond]),
......@@ -164,12 +164,12 @@ module Rumoji
self.new("\u{1f198}", [:sos]),
self.new("\u{1f523}", [:symbols]),
self.new("\u{2649}" , [:taurus]),
# self.new("\u{0033}" , [:three]),
self.new("\u{0033 fe0f 20e3}" , [:three]),
self.new("\u{2122}" , [:tm]),
self.new("\u{1f51d}", [:top]),
self.new("\u{1f531}", [:trident]),
self.new("\u{1f500}", [:twisted_rightwards_arrows]),
# self.new("\u{0032}" , [:two]),
self.new("\u{0032 fe0f 20e3}" , [:two]),
self.new("\u{1f239}", [:u5272]),
self.new("\u{1f234}", [:u5408]),
self.new("\u{1f23a}", [:u55b6]),
......@@ -195,7 +195,7 @@ module Rumoji
self.new("\u{1f533}", [:white_square_button]),
self.new("\u{1f6ba}", [:womens]),
self.new("\u{274c}" , [:x]),
# self.new("\u{0030}" , [:zero])
self.new("\u{0030 fe0f 20e3}" , [:zero])
]
end
end
module Rumoji
VERSION = "0.2.0"
VERSION = "0.4.1"
end
......@@ -5,14 +5,14 @@ require 'minitest/autorun'
describe Rumoji::Emoji do
let(:symbols) { [:hankey, :poop, :shit] }
let(:name) { "PILE OF POO" }
let(:emoji_name) { "PILE OF POO" }
let(:poo_string) { "\u{1F4A9}" }
subject do
Rumoji::Emoji.new(poo_string, symbols, name)
Rumoji::Emoji.new(poo_string, symbols, emoji_name)
end
it("has a name") { subject.name.must_equal name }
it("has a name") { subject.name.must_equal emoji_name }
it("has a cheat sheet code") { symbols.must_include subject.code[1...-1].intern }
it("can test if it includes a cheat sheet code") { symbols.all?{|symbol| subject.include?(symbol) }.must_equal true }
it("converts to the emoji string") { subject.to_s.must_equal poo_string }
......@@ -44,11 +44,11 @@ describe Rumoji::Emoji do
#
# http://www.unicode.org/versions/Unicode6.2.0/
let(:symbol) { :us }
let(:name) { "REGIONAL INDICATOR SYMBOL LETTERS US" }
let(:emoji_name) { "REGIONAL INDICATOR SYMBOL LETTERS US" }
let(:us_string) { "\xF0\x9F\x87\xBA\xF0\x9F\x87\xB8" }
subject do
Rumoji::Emoji.new(us_string, symbol, name)
Rumoji::Emoji.new(us_string, symbol, emoji_name)
end
it("has one symbol, representing the code") { subject.symbol.must_equal symbol }
......
......@@ -7,12 +7,16 @@ describe Rumoji do
before do
@poop = "💩"
@smile = "😄"
@zero = "0️⃣"
@us = "🇺🇸"
@non_potable_water = "🚱"
end
describe "#encode" do
it "transforms emoji into cheat-sheet form" do
key = :smile
Rumoji.encode(@smile).must_equal ":smile:"
Rumoji.encode("#{@smile}").must_equal ":smile:"
end
end
......@@ -20,6 +24,18 @@ describe Rumoji do
it "transforms a cheat-sheet code into an emoji" do
Rumoji.decode(":poop:").must_equal @poop
end
it "transforms a cheat-sheet code into an emoji with colon" do
Rumoji.decode("::poop:").must_equal ':' + @poop
end
it "transforms a cheat-sheet code with a dash into an emoji" do
Rumoji.decode(":non-potable_water:").must_equal @non_potable_water
end
it "does not transform an arbitrary string wrapped in colons" do
Rumoji.decode(":this-is-just-a-string:").must_equal ":this-is-just-a-string:"
end
end
describe "#encode_io" do
......@@ -27,6 +43,48 @@ describe Rumoji do
io = StringIO.new("#{@smile}")
Rumoji.encode_io(io).string.must_equal ":smile:"
end
it "keeps codepoints that match the beginnings of multi-codepoint emoji" do
text = "i like #hashtags and 1direction they are the #1 band. end with 9"
io = StringIO.new(text)
Rumoji.encode_io(io).string.must_equal text
end
describe "with multiple codepoints" do
it "transforms a stream" do
io1 = StringIO.new("#{@zero}")
io2 = StringIO.new("#{@us}")
Rumoji.encode_io(io1).string.must_equal ":zero:"
Rumoji.encode_io(io2).string.must_equal ":us:"
end
it "transforms a stream of many emoji" do
num = ":one: :two: :three: :four: :five: :six: :seven: :eight: :nine: :zero: :hash:"
emoji = StringIO.new"1️⃣ 2️⃣ 3️⃣ 4️⃣ 5️⃣ 6️⃣ 7️⃣ 8️⃣ 9️⃣ 0️⃣ #️⃣"
Rumoji.encode_io(emoji).string.must_equal num
end
it "does not encode double digits" do
num = ":zero: :one: :two: :three: :four: :five: :six: :seven: :eight: :nine: :hash:"
double_digits = StringIO.new("00 11 22 33 44 55 66 77 88 99 ##")
Rumoji.encode_io(double_digits).string.wont_equal num
end
describe "with leading and trailing characters" do
it "is able to pull multipoint emoji out of a sequence" do
io = StringIO.new("An example of a multipoint emoji is the #{@us} flag.")
Rumoji.encode_io(io).string.must_equal "An example of a multipoint emoji is the :us: flag."
end
end
describe "with trailing emoji" do
it "writes characters that are in a multipoint emoji followed by an emoji" do
io = StringIO.new "I would like 0#{@poop}"
Rumoji.encode_io(io).string.must_equal "I would like 0:poop:"
end
end
end
end
describe "#decode_io" do
......@@ -34,5 +92,12 @@ describe Rumoji do
io = StringIO.new(":poop:")
Rumoji.decode_io(io).string.must_equal @poop
end
describe "with multiple codepoints" do
it "decodes a stream" do
io = StringIO.new(":zero:")
Rumoji.decode_io(io).string.must_equal @zero
end
end
end
end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment