gemoji 3.0.1 → 4.0.0.rc3

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.
data/lib/emoji.rb CHANGED
@@ -1,4 +1,6 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
3
+
2
4
  require 'emoji/character'
3
5
  require 'json'
4
6
 
@@ -9,14 +11,6 @@ module Emoji
9
11
  File.expand_path('../../db/emoji.json', __FILE__)
10
12
  end
11
13
 
12
- def apple_palette_file
13
- File.expand_path('../../db/Category-Emoji.json', __FILE__)
14
- end
15
-
16
- def images_path
17
- File.expand_path("../../images", __FILE__)
18
- end
19
-
20
14
  def all
21
15
  return @all if defined? @all
22
16
  @all = []
@@ -24,17 +18,6 @@ module Emoji
24
18
  @all
25
19
  end
26
20
 
27
- def apple_palette
28
- return @apple_palette if defined? @apple_palette
29
- data = File.open(apple_palette_file, 'r:UTF-8') { |f| JSON.parse(f.read) }
30
- @apple_palette = data.fetch('EmojiDataArray').each_with_object({}) do |group, all|
31
- title = group.fetch('CVDataTitle').split('-', 2)[1]
32
- all[title] = group.fetch('CVCategoryData').fetch('Data').split(',').map do |raw|
33
- TEXT_GLYPHS.include?(raw) ? raw + VARIATION_SELECTOR_16 : raw
34
- end
35
- end
36
- end
37
-
38
21
  # Public: Initialize an Emoji::Character instance and yield it to the block.
39
22
  # The character is added to the `Emoji.all` set.
40
23
  def create(name)
@@ -73,45 +56,68 @@ module Emoji
73
56
 
74
57
  private
75
58
  VARIATION_SELECTOR_16 = "\u{fe0f}".freeze
76
- ZERO_WIDTH_JOINER = "\u{200d}".freeze
77
- FEMALE_SYMBOL = "\u{2640}".freeze
78
- MALE_SYMBOL = "\u{2642}".freeze
79
59
 
80
- # Chars from Apple's palette which must have VARIATION_SELECTOR_16 to render:
81
- TEXT_GLYPHS = ["🈷", "🈂", "🅰", "🅱", "🅾", "©", "®", "™", "〰"].freeze
60
+ # Characters which must have VARIATION_SELECTOR_16 to render as color emoji:
61
+ TEXT_GLYPHS = [
62
+ "\u{1f237}", # Japanese “monthly amount” button
63
+ "\u{1f202}", # Japanese “service charge” button
64
+ "\u{1f170}", # A button (blood type)
65
+ "\u{1f171}", # B button (blood type)
66
+ "\u{1f17e}", # O button (blood type)
67
+ "\u{00a9}", # copyright
68
+ "\u{00ae}", # registered
69
+ "\u{2122}", # trade mark
70
+ "\u{3030}", # wavy dash
71
+ ].freeze
72
+
73
+ private_constant :VARIATION_SELECTOR_16, :TEXT_GLYPHS
82
74
 
83
75
  def parse_data_file
84
- data = File.open(data_file, 'r:UTF-8') { |file| JSON.parse(file.read) }
85
- data.each do |raw_emoji|
86
- self.create(nil) do |emoji|
87
- raw_emoji.fetch('aliases').each { |name| emoji.add_alias(name) }
88
- if raw = raw_emoji['emoji']
89
- unicodes = [raw, raw.sub(VARIATION_SELECTOR_16, '') + VARIATION_SELECTOR_16].uniq
90
- unicodes.each { |uni| emoji.add_unicode_alias(uni) }
91
- end
92
- raw_emoji.fetch('tags').each { |tag| emoji.add_tag(tag) }
76
+ data = File.open(data_file, 'r:UTF-8') do |file|
77
+ JSON.parse(file.read, symbolize_names: true)
78
+ end
93
79
 
94
- emoji.category = raw_emoji['category']
95
- emoji.description = raw_emoji['description']
96
- emoji.unicode_version = raw_emoji['unicode_version']
97
- emoji.ios_version = raw_emoji['ios_version']
80
+ if "".respond_to?(:-@)
81
+ # Ruby >= 2.3 this is equivalent to .freeze
82
+ # Ruby >= 2.5 this will freeze and dedup
83
+ dedup = lambda { |str| -str }
84
+ else
85
+ dedup = lambda { |str| str.freeze }
86
+ end
87
+
88
+ append_unicode = lambda do |emoji, raw|
89
+ unless TEXT_GLYPHS.include?(raw) || emoji.unicode_aliases.include?(raw)
90
+ emoji.add_unicode_alias(dedup.call(raw))
98
91
  end
99
92
  end
100
93
 
101
- # Add an explicit gendered variant to emoji that historically imply a gender
102
94
  data.each do |raw_emoji|
103
- raw = raw_emoji['emoji']
104
- next unless raw
105
- no_gender = raw.sub(/(#{VARIATION_SELECTOR_16})?#{ZERO_WIDTH_JOINER}(#{FEMALE_SYMBOL}|#{MALE_SYMBOL})/, '')
106
- next unless $2
107
- emoji = find_by_unicode(no_gender)
108
- next unless emoji
109
- edit_emoji(emoji) do
110
- emoji.add_unicode_alias(
111
- $2 == FEMALE_SYMBOL ?
112
- raw.sub(FEMALE_SYMBOL, MALE_SYMBOL) :
113
- raw.sub(MALE_SYMBOL, FEMALE_SYMBOL)
114
- )
95
+ self.create(nil) do |emoji|
96
+ raw_emoji.fetch(:aliases).each { |name| emoji.add_alias(dedup.call(name)) }
97
+ if raw = raw_emoji[:emoji]
98
+ append_unicode.call(emoji, raw)
99
+ start_pos = 0
100
+ while found_index = raw.index(VARIATION_SELECTOR_16, start_pos)
101
+ # register every variant where one VARIATION_SELECTOR_16 is removed
102
+ raw_alternate = raw.dup
103
+ raw_alternate[found_index] = ""
104
+ append_unicode.call(emoji, raw_alternate)
105
+ start_pos = found_index + 1
106
+ end
107
+ if start_pos > 0
108
+ # register a variant with all VARIATION_SELECTOR_16 removed
109
+ append_unicode.call(emoji, raw.gsub(VARIATION_SELECTOR_16, ""))
110
+ else
111
+ # register a variant where VARIATION_SELECTOR_16 is added
112
+ append_unicode.call(emoji, "#{raw}#{VARIATION_SELECTOR_16}")
113
+ end
114
+ end
115
+ raw_emoji.fetch(:tags).each { |tag| emoji.add_tag(dedup.call(tag)) }
116
+
117
+ emoji.category = dedup.call(raw_emoji[:category])
118
+ emoji.description = dedup.call(raw_emoji[:description])
119
+ emoji.unicode_version = dedup.call(raw_emoji[:unicode_version])
120
+ emoji.ios_version = dedup.call(raw_emoji[:ios_version])
115
121
  end
116
122
  end
117
123
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Emoji
2
4
  class Character
3
5
  # Inspect individual Unicode characters in a string by dumping its
data/lib/gemoji.rb CHANGED
@@ -1 +1,3 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'emoji'
metadata CHANGED
@@ -1,53 +1,32 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gemoji
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.1
4
+ version: 4.0.0.rc3
5
5
  platform: ruby
6
6
  authors:
7
7
  - GitHub
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-04-25 00:00:00.000000000 Z
11
+ date: 2021-07-26 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: Character information and metadata for standard and custom emoji.
13
+ description: Character information and metadata for Unicode emoji.
14
14
  email: support@github.com
15
- executables:
16
- - gemoji
15
+ executables: []
17
16
  extensions: []
18
17
  extra_rdoc_files: []
19
18
  files:
19
+ - LICENSE
20
20
  - README.md
21
- - bin/gemoji
22
- - db/Category-Emoji.json
23
21
  - db/emoji.json
24
- - images/basecamp.png
25
- - images/basecampy.png
26
- - images/bowtie.png
27
- - images/feelsgood.png
28
- - images/finnadie.png
29
- - images/goberserk.png
30
- - images/godmode.png
31
- - images/hurtrealbad.png
32
- - images/neckbeard.png
33
- - images/octocat.png
34
- - images/rage1.png
35
- - images/rage2.png
36
- - images/rage3.png
37
- - images/rage4.png
38
- - images/shipit.png
39
- - images/suspect.png
40
- - images/trollface.png
41
22
  - lib/emoji.rb
42
23
  - lib/emoji/character.rb
43
- - lib/emoji/cli.rb
44
- - lib/emoji/extractor.rb
45
24
  - lib/gemoji.rb
46
25
  homepage: https://github.com/github/gemoji
47
26
  licenses:
48
27
  - MIT
49
28
  metadata: {}
50
- post_install_message:
29
+ post_install_message:
51
30
  rdoc_options: []
52
31
  require_paths:
53
32
  - lib
@@ -58,13 +37,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
58
37
  version: '1.9'
59
38
  required_rubygems_version: !ruby/object:Gem::Requirement
60
39
  requirements:
61
- - - ">="
40
+ - - ">"
62
41
  - !ruby/object:Gem::Version
63
- version: '0'
42
+ version: 1.3.1
64
43
  requirements: []
65
- rubyforge_project:
66
- rubygems_version: 2.5.2.3
67
- signing_key:
44
+ rubygems_version: 3.0.3
45
+ signing_key:
68
46
  specification_version: 4
69
- summary: Emoji library
47
+ summary: Unicode emoji library
70
48
  test_files: []
data/bin/gemoji DELETED
@@ -1,5 +0,0 @@
1
- #!/usr/bin/env ruby
2
- require 'emoji/cli'
3
-
4
- exit_code = Emoji::CLI.dispatch(ARGV)
5
- exit exit_code
@@ -1,71 +0,0 @@
1
- {
2
- "EmojiDataArray" : [
3
- {
4
- "CVDataTitle" : "EmojiCategory-People",
5
- "CVCategoryImage" : "Emoji-HumanImage",
6
- "CVCategoryData" : {
7
- "CVSkipNullGlyphs" : false,
8
- "Data" : "😀,😃,😄,😁,😆,😅,😂,🤣,☺️,😊,😇,🙂,🙃,😉,😌,😍,😘,😗,😙,😚,😋,😜,😝,😛,🤑,🤗,🤓,😎,🤡,🤠,😏,😒,😞,😔,😟,😕,🙁,☹️,😣,😖,😫,😩,😤,😠,😡,😶,😐,😑,😯,😦,😧,😮,😲,😵,😳,😱,😨,😰,😢,😥,🤤,😭,😓,😪,😴,🙄,🤔,🤥,😬,🤐,🤢,🤧,😷,🤒,🤕,😈,👿,👹,👺,💩,👻,💀,☠️,👽,👾,🤖,🎃,😺,😸,😹,😻,😼,😽,🙀,😿,😾,👐,🙌,👏,🙏,🤝,👍,👎,👊,✊,🤛,🤜,🤞,✌️,🤘,👌,👈,👉,👆,👇,☝️,✋,🤚,🖐,🖖,👋,🤙,💪,🖕,✍️,🤳,💅,💍,💄,💋,👄,👅,👂,👃,👣,👁,👀,🗣,👤,👥,👶,👦,👧,👨,👩,👱‍♀️,👱,👴,👵,👲,👳‍♀️,👳,👮‍♀️,👮,👷‍♀️,👷,💂‍♀️,💂,🕵️‍♀️,🕵️,👩‍⚕️,👨‍⚕️,👩‍🌾,👨‍🌾,👩‍🍳,👨‍🍳,👩‍🎓,👨‍🎓,👩‍🎤,👨‍🎤,👩‍🏫,👨‍🏫,👩‍🏭,👨‍🏭,👩‍💻,👨‍💻,👩‍💼,👨‍💼,👩‍🔧,👨‍🔧,👩‍🔬,👨‍🔬,👩‍🎨,👨‍🎨,👩‍🚒,👨‍🚒,👩‍✈️,👨‍✈️,👩‍🚀,👨‍🚀,👩‍⚖️,👨‍⚖️,🤶,🎅,👸,🤴,👰,🤵,👼,🤰,🙇‍♀️,🙇,💁,💁‍♂️,🙅,🙅‍♂️,🙆,🙆‍♂️,🙋,🙋‍♂️,🤦‍♀️,🤦‍♂️,🤷‍♀️,🤷‍♂️,🙎,🙎‍♂️,🙍,🙍‍♂️,💇,💇‍♂️,💆,💆‍♂️,🕴,💃,🕺,👯,👯‍♂️,🚶‍♀️,🚶,🏃‍♀️,🏃,👫,👭,👬,💑,👩‍❤️‍👩,👨‍❤️‍👨,💏,👩‍❤️‍💋‍👩,👨‍❤️‍💋‍👨,👪,👨‍👩‍👧,👨‍👩‍👧‍👦,👨‍👩‍👦‍👦,👨‍👩‍👧‍👧,👩‍👩‍👦,👩‍👩‍👧,👩‍👩‍👧‍👦,👩‍👩‍👦‍👦,👩‍👩‍👧‍👧,👨‍👨‍👦,👨‍👨‍👧,👨‍👨‍👧‍👦,👨‍👨‍👦‍👦,👨‍👨‍👧‍👧,👩‍👦,👩‍👧,👩‍👧‍👦,👩‍👦‍👦,👩‍👧‍👧,👨‍👦,👨‍👧,👨‍👧‍👦,👨‍👦‍👦,👨‍👧‍👧,👚,👕,👖,👔,👗,👙,👘,👠,👡,👢,👞,👟,👒,🎩,🎓,👑,⛑,🎒,👝,👛,👜,💼,👓,🕶,🌂,☂️"
9
- }
10
- },
11
- {
12
- "CVDataTitle" : "EmojiCategory-Nature",
13
- "CVCategoryImage" : "Emoji-NatureImage",
14
- "CVCategoryData" : {
15
- "CVSkipNullGlyphs" : false,
16
- "Data" : "🐶,🐱,🐭,🐹,🐰,🦊,🐻,🐼,🐨,🐯,🦁,🐮,🐷,🐽,🐸,🐵,🙈,🙉,🙊,🐒,🐔,🐧,🐦,🐤,🐣,🐥,🦆,🦅,🦉,🦇,🐺,🐗,🐴,🦄,🐝,🐛,🦋,🐌,🐚,🐞,🐜,🕷,🕸,🐢,🐍,🦎,🦂,🦀,🦑,🐙,🦐,🐠,🐟,🐡,🐬,🦈,🐳,🐋,🐊,🐆,🐅,🐃,🐂,🐄,🦌,🐪,🐫,🐘,🦏,🦍,🐎,🐖,🐐,🐏,🐑,🐕,🐩,🐈,🐓,🦃,🕊,🐇,🐁,🐀,🐿,🐾,🐉,🐲,🌵,🎄,🌲,🌳,🌴,🌱,🌿,☘️,🍀,🎍,🎋,🍃,🍂,🍁,🍄,🌾,💐,🌷,🌹,🥀,🌻,🌼,🌸,🌺,🌎,🌍,🌏,🌕,🌖,🌗,🌘,🌑,🌒,🌓,🌔,🌚,🌝,🌞,🌛,🌜,🌙,💫,⭐️,🌟,✨,⚡️,🔥,💥,☄️,☀️,🌤,⛅️,🌥,🌦,🌈,☁️,🌧,⛈,🌩,🌨,☃️,⛄️,❄️,🌬,💨,🌪,🌫,🌊,💧,💦,☔️"
17
- }
18
- },
19
- {
20
- "CVDataTitle" : "EmojiCategory-Foods",
21
- "CVCategoryImage" : "Emoji-FoodsImage",
22
- "CVCategoryData" : {
23
- "CVSkipNullGlyphs" : false,
24
- "Data" : "🍏,🍎,🍐,🍊,🍋,🍌,🍉,🍇,🍓,🍈,🍒,🍑,🍍,🥝,🥑,🍅,🍆,🥒,🥕,🌽,🌶,🥔,🍠,🌰,🥜,🍯,🥐,🍞,🥖,🧀,🥚,🍳,🥓,🥞,🍤,🍗,🍖,🍕,🌭,🍔,🍟,🥙,🌮,🌯,🥗,🥘,🍝,🍜,🍲,🍥,🍣,🍱,🍛,🍚,🍙,🍘,🍢,🍡,🍧,🍨,🍦,🍰,🎂,🍮,🍭,🍬,🍫,🍿,🍩,🍪,🥛,🍼,☕️,🍵,🍶,🍺,🍻,🥂,🍷,🥃,🍸,🍹,🍾,🥄,🍴,🍽"
25
- }
26
- },
27
- {
28
- "CVDataTitle" : "EmojiCategory-Activity",
29
- "CVCategoryImage" : "Emoji-ActivityImage",
30
- "CVCategoryData" : {
31
- "CVSkipNullGlyphs" : false,
32
- "Data" : "⚽️,🏀,🏈,⚾️,🎾,🏐,🏉,🎱,🏓,🏸,🥅,🏒,🏑,🏏,⛳️,🏹,🎣,🥊,🥋,⛸,🎿,⛷,🏂,🏋️‍♀️,🏋️,🤺,🤼‍♀️,🤼‍♂️,🤸‍♀️,🤸‍♂️,⛹️‍♀️,⛹️,🤾‍♀️,🤾‍♂️,🏌️‍♀️,🏌️,🏄‍♀️,🏄,🏊‍♀️,🏊,🤽‍♀️,🤽‍♂️,🚣‍♀️,🚣,🏇,🚴‍♀️,🚴,🚵‍♀️,🚵,🎽,🏅,🎖,🥇,🥈,🥉,🏆,🏵,🎗,🎫,🎟,🎪,🤹‍♀️,🤹‍♂️,🎭,🎨,🎬,🎤,🎧,🎼,🎹,🥁,🎷,🎺,🎸,🎻,🎲,🎯,🎳,🎮,🎰"
33
- }
34
- },
35
- {
36
- "CVDataTitle" : "EmojiCategory-Places",
37
- "CVCategoryImage" : "Emoji-PlacesImage",
38
- "CVCategoryData" : {
39
- "CVSkipNullGlyphs" : false,
40
- "Data" : "🚗,🚕,🚙,🚌,🚎,🏎,🚓,🚑,🚒,🚐,🚚,🚛,🚜,🛴,🚲,🛵,🏍,🚨,🚔,🚍,🚘,🚖,🚡,🚠,🚟,🚃,🚋,🚞,🚝,🚄,🚅,🚈,🚂,🚆,🚇,🚊,🚉,🚁,🛩,✈️,🛫,🛬,🚀,🛰,💺,🛶,⛵️,🛥,🚤,🛳,⛴,🚢,⚓️,🚧,⛽️,🚏,🚦,🚥,🗺,🗿,🗽,⛲️,🗼,🏰,🏯,🏟,🎡,🎢,🎠,⛱,🏖,🏝,⛰,🏔,🗻,🌋,🏜,🏕,⛺️,🛤,🛣,🏗,🏭,🏠,🏡,🏘,🏚,🏢,🏬,🏣,🏤,🏥,🏦,🏨,🏪,🏫,🏩,💒,🏛,⛪️,🕌,🕍,🕋,⛩,🗾,🎑,🏞,🌅,🌄,🌠,🎇,🎆,🌇,🌆,🏙,🌃,🌌,🌉,🌁"
41
- }
42
- },
43
- {
44
- "CVDataTitle" : "EmojiCategory-Objects",
45
- "CVCategoryImage" : "Emoji-ObjectsImage",
46
- "CVCategoryData" : {
47
- "CVSkipNullGlyphs" : false,
48
- "Data" : "⌚️,📱,📲,💻,⌨️,🖥,🖨,🖱,🖲,🕹,🗜,💽,💾,💿,📀,📼,📷,📸,📹,🎥,📽,🎞,📞,☎️,📟,📠,📺,📻,🎙,🎚,🎛,⏱,⏲,⏰,🕰,⌛️,⏳,📡,🔋,🔌,💡,🔦,🕯,🗑,🛢,💸,💵,💴,💶,💷,💰,💳,💎,⚖️,🔧,🔨,⚒,🛠,⛏,🔩,⚙️,⛓,🔫,💣,🔪,🗡,⚔️,🛡,🚬,⚰️,⚱️,🏺,🔮,📿,💈,⚗️,🔭,🔬,🕳,💊,💉,🌡,🚽,🚰,🚿,🛁,🛀,🛎,🔑,🗝,🚪,🛋,🛏,🛌,🖼,🛍,🛒,🎁,🎈,🎏,🎀,🎊,🎉,🎎,🏮,🎐,✉️,📩,📨,📧,💌,📥,📤,📦,🏷,📪,📫,📬,📭,📮,📯,📜,📃,📄,📑,📊,📈,📉,🗒,🗓,📆,📅,📇,🗃,🗳,🗄,📋,📁,📂,🗂,🗞,📰,📓,📔,📒,📕,📗,📘,📙,📚,📖,🔖,🔗,📎,🖇,📐,📏,📌,📍,✂️,🖊,🖋,✒️,🖌,🖍,📝,✏️,🔍,🔎,🔏,🔐,🔒,🔓"
49
- }
50
- },
51
- {
52
- "CVDataTitle" : "EmojiCategory-Symbols",
53
- "CVCategoryImage" : "Emoji-SymbolImage",
54
- "CVCategoryData" : {
55
- "CVSkipNullGlyphs" : false,
56
- "Data" : "❤️,💛,💚,💙,💜,🖤,💔,❣️,💕,💞,💓,💗,💖,💘,💝,💟,☮️,✝️,☪️,🕉,☸️,✡️,🔯,🕎,☯️,☦️,🛐,⛎,♈️,♉️,♊️,♋️,♌️,♍️,♎️,♏️,♐️,♑️,♒️,♓️,🆔,⚛️,🉑,☢️,☣️,📴,📳,🈶,🈚️,🈸,🈺,🈷️,✴️,🆚,💮,🉐,㊙️,㊗️,🈴,🈵,🈹,🈲,🅰️,🅱️,🆎,🆑,🅾️,🆘,❌,⭕️,🛑,⛔️,📛,🚫,💯,💢,♨️,🚷,🚯,🚳,🚱,🔞,📵,🚭,❗️,❕,❓,❔,‼️,⁉️,🔅,🔆,〽️,⚠️,🚸,🔱,⚜️,🔰,♻️,✅,🈯️,💹,❇️,✳️,❎,🌐,💠,Ⓜ️,🌀,💤,🏧,🚾,♿️,🅿️,🈳,🈂️,🛂,🛃,🛄,🛅,🚹,🚺,🚼,🚻,🚮,🎦,📶,🈁,🔣,ℹ️,🔤,🔡,🔠,🆖,🆗,🆙,🆒,🆕,🆓,0️⃣,1️⃣,2️⃣,3️⃣,4️⃣,5️⃣,6️⃣,7️⃣,8️⃣,9️⃣,🔟,🔢,#️⃣,*️⃣,▶️,⏸,⏯,⏹,⏺,⏭,⏮,⏩,⏪,⏫,⏬,◀️,🔼,🔽,➡️,⬅️,⬆️,⬇️,↗️,↘️,↙️,↖️,↕️,↔️,↪️,↩️,⤴️,⤵️,🔀,🔁,🔂,🔄,🔃,🎵,🎶,➕,➖,➗,✖️,💲,💱,™️,©️,®️,〰️,➰,➿,🔚,🔙,🔛,🔝,🔜,✔️,☑️,🔘,⚪️,⚫️,🔴,🔵,🔺,🔻,🔸,🔹,🔶,🔷,🔳,🔲,▪️,▫️,◾️,◽️,◼️,◻️,⬛️,⬜️,🔈,🔇,🔉,🔊,🔔,🔕,📣,📢,👁‍🗨,💬,💭,🗯,♠️,♣️,♥️,♦️,🃏,🎴,🀄️,🕐,🕑,🕒,🕓,🕔,🕕,🕖,🕗,🕘,🕙,🕚,🕛,🕜,🕝,🕞,🕟,🕠,🕡,🕢,🕣,🕤,🕥,🕦,🕧"
57
- }
58
- },
59
- {
60
- "CVDataTitle" : "EmojiCategory-Flags",
61
- "CVCategoryImage" : "Emoji-FlagsImage",
62
- "CVCategoryData" : {
63
- "CVSkipNullGlyphs" : false,
64
- "Data" : "🏳️,🏴,🏁,🚩,🏳️‍🌈,🇦🇫,🇦🇽,🇦🇱,🇩🇿,🇦🇸,🇦🇩,🇦🇴,🇦🇮,🇦🇶,🇦🇬,🇦🇷,🇦🇲,🇦🇼,🇦🇺,🇦🇹,🇦🇿,🇧🇸,🇧🇭,🇧🇩,🇧🇧,🇧🇾,🇧🇪,🇧🇿,🇧🇯,🇧🇲,🇧🇹,🇧🇴,🇧🇶,🇧🇦,🇧🇼,🇧🇷,🇮🇴,🇻🇬,🇧🇳,🇧🇬,🇧🇫,🇧🇮,🇨🇻,🇰🇭,🇨🇲,🇨🇦,🇮🇨,🇰🇾,🇨🇫,🇹🇩,🇨🇱,🇨🇳,🇨🇽,🇨🇨,🇨🇴,🇰🇲,🇨🇬,🇨🇩,🇨🇰,🇨🇷,🇨🇮,🇭🇷,🇨🇺,🇨🇼,🇨🇾,🇨🇿,🇩🇰,🇩🇯,🇩🇲,🇩🇴,🇪🇨,🇪🇬,🇸🇻,🇬🇶,🇪🇷,🇪🇪,🇪🇹,🇪🇺,🇫🇰,🇫🇴,🇫🇯,🇫🇮,🇫🇷,🇬🇫,🇵🇫,🇹🇫,🇬🇦,🇬🇲,🇬🇪,🇩🇪,🇬🇭,🇬🇮,🇬🇷,🇬🇱,🇬🇩,🇬🇵,🇬🇺,🇬🇹,🇬🇬,🇬🇳,🇬🇼,🇬🇾,🇭🇹,🇭🇳,🇭🇰,🇭🇺,🇮🇸,🇮🇳,🇮🇩,🇮🇷,🇮🇶,🇮🇪,🇮🇲,🇮🇱,🇮🇹,🇯🇲,🇯🇵,🎌,🇯🇪,🇯🇴,🇰🇿,🇰🇪,🇰🇮,🇽🇰,🇰🇼,🇰🇬,🇱🇦,🇱🇻,🇱🇧,🇱🇸,🇱🇷,🇱🇾,🇱🇮,🇱🇹,🇱🇺,🇲🇴,🇲🇰,🇲🇬,🇲🇼,🇲🇾,🇲🇻,🇲🇱,🇲🇹,🇲🇭,🇲🇶,🇲🇷,🇲🇺,🇾🇹,🇲🇽,🇫🇲,🇲🇩,🇲🇨,🇲🇳,🇲🇪,🇲🇸,🇲🇦,🇲🇿,🇲🇲,🇳🇦,🇳🇷,🇳🇵,🇳🇱,🇳🇨,🇳🇿,🇳🇮,🇳🇪,🇳🇬,🇳🇺,🇳🇫,🇲🇵,🇰🇵,🇳🇴,🇴🇲,🇵🇰,🇵🇼,🇵🇸,🇵🇦,🇵🇬,🇵🇾,🇵🇪,🇵🇭,🇵🇳,🇵🇱,🇵🇹,🇵🇷,🇶🇦,🇷🇪,🇷🇴,🇷🇺,🇷🇼,🇧🇱,🇸🇭,🇰🇳,🇱🇨,🇵🇲,🇻🇨,🇼🇸,🇸🇲,🇸🇹,🇸🇦,🇸🇳,🇷🇸,🇸🇨,🇸🇱,🇸🇬,🇸🇽,🇸🇰,🇸🇮,🇸🇧,🇸🇴,🇿🇦,🇬🇸,🇰🇷,🇸🇸,🇪🇸,🇱🇰,🇸🇩,🇸🇷,🇸🇿,🇸🇪,🇨🇭,🇸🇾,🇹🇼,🇹🇯,🇹🇿,🇹🇭,🇹🇱,🇹🇬,🇹🇰,🇹🇴,🇹🇹,🇹🇳,🇹🇷,🇹🇲,🇹🇨,🇹🇻,🇺🇬,🇺🇦,🇦🇪,🇬🇧,🇺🇸,🇻🇮,🇺🇾,🇺🇿,🇻🇺,🇻🇦,🇻🇪,🇻🇳,🇼🇫,🇪🇭,🇾🇪,🇿🇲,🇿🇼"
65
- }
66
- }
67
- ],
68
- "CVViewFontList" : [
69
- "AppleColorEmoji"
70
- ]
71
- }
data/images/basecamp.png DELETED
Binary file
data/images/basecampy.png DELETED
Binary file
data/images/bowtie.png DELETED
Binary file
data/images/feelsgood.png DELETED
Binary file
data/images/finnadie.png DELETED
Binary file
data/images/goberserk.png DELETED
Binary file
data/images/godmode.png DELETED
Binary file
Binary file
data/images/neckbeard.png DELETED
Binary file
data/images/octocat.png DELETED
Binary file
data/images/rage1.png DELETED
Binary file
data/images/rage2.png DELETED
Binary file
data/images/rage3.png DELETED
Binary file
data/images/rage4.png DELETED
Binary file
data/images/shipit.png DELETED
Binary file
data/images/suspect.png DELETED
Binary file
data/images/trollface.png DELETED
Binary file
data/lib/emoji/cli.rb DELETED
@@ -1,68 +0,0 @@
1
- require 'emoji/extractor'
2
- require 'fileutils'
3
- require 'optparse'
4
-
5
- module Emoji
6
- module CLI
7
- extend self
8
-
9
- InvalidUsage = Class.new(RuntimeError)
10
-
11
- def dispatch(argv)
12
- cmd = argv[0]
13
- argv = argv[1..-1]
14
-
15
- case cmd
16
- when "extract"
17
- public_send(cmd, argv)
18
- when "help", "--help", "-h"
19
- help
20
- else
21
- raise InvalidUsage
22
- end
23
-
24
- return 0
25
- rescue InvalidUsage, OptionParser::InvalidArgument, OptionParser::InvalidOption => err
26
- unless err.message == err.class.to_s
27
- $stderr.puts err.message
28
- $stderr.puts
29
- end
30
- $stderr.puts usage_text
31
- return 1
32
- end
33
-
34
- def help
35
- puts usage_text
36
- end
37
-
38
- VALID_SIZES = [ 20, 32, 40, 48, 64, 96, 160 ]
39
-
40
- def extract(argv)
41
- size = 64
42
-
43
- OptionParser.new do |opts|
44
- opts.on("--size=#{size}", Integer) do |val|
45
- if VALID_SIZES.include?(val)
46
- size = val
47
- else
48
- raise InvalidUsage, "size should be one of: #{VALID_SIZES.join(', ')}"
49
- end
50
- end
51
- end.parse!(argv)
52
-
53
- raise InvalidUsage unless argv.size == 1
54
- path = argv[0]
55
-
56
- Emoji::Extractor.new(size, path).extract!
57
- Dir["#{Emoji.images_path}/*.png"].each do |png|
58
- FileUtils.cp(png, File.join(path, File.basename(png)))
59
- end
60
- end
61
-
62
- def usage_text
63
- <<EOF
64
- Usage: gemoji extract <path> [--size=64]
65
- EOF
66
- end
67
- end
68
- end
@@ -1,190 +0,0 @@
1
- require 'emoji'
2
- require 'fileutils'
3
-
4
- module Emoji
5
- class Extractor
6
- EMOJI_TTF = "/System/Library/Fonts/Apple Color Emoji.ttc"
7
-
8
- attr_reader :size, :images_path
9
-
10
- def initialize(size, images_path)
11
- @size = size
12
- @images_path = images_path
13
- end
14
-
15
- def each(&block)
16
- return to_enum(__method__) unless block_given?
17
-
18
- File.open(EMOJI_TTF, 'rb') do |file|
19
- font_offsets = parse_ttc(file)
20
- file.pos = font_offsets[0]
21
-
22
- tables = parse_tables(file)
23
- glyph_index = extract_glyph_index(file, tables)
24
-
25
- each_glyph_bitmap(file, tables, glyph_index, &block)
26
- end
27
- end
28
-
29
- def extract!
30
- each do |glyph_name, type, binread|
31
- if emoji = glyph_name_to_emoji(glyph_name)
32
- image_filename = "#{images_path}/#{emoji.image_filename}"
33
- FileUtils.mkdir_p(File.dirname(image_filename))
34
- File.open(image_filename, 'wb') { |f| f.write binread.call }
35
- end
36
- end
37
- end
38
-
39
- private
40
-
41
- GENDER_MAP = {
42
- "M" => "\u{2642}",
43
- "W" => "\u{2640}",
44
- }
45
-
46
- FAMILY_MAP = {
47
- "B" => "\u{1f466}",
48
- "G" => "\u{1f467}",
49
- "M" => "\u{1f468}",
50
- "W" => "\u{1f469}",
51
- }.freeze
52
-
53
- FAMILY = "1F46A"
54
- COUPLE = "1F491"
55
- KISS = "1F48F"
56
-
57
- def glyph_name_to_emoji(glyph_name)
58
- return if glyph_name =~ /\.[1-5]($|\.)/
59
- zwj = Emoji::ZERO_WIDTH_JOINER
60
- v16 = Emoji::VARIATION_SELECTOR_16
61
-
62
- if glyph_name =~ /^u(#{FAMILY}|#{COUPLE}|#{KISS})\.([#{FAMILY_MAP.keys.join('')}]+)$/
63
- if $1 == FAMILY ? $2 == "MWB" : $2 == "WM"
64
- raw = [$1.hex].pack('U')
65
- else
66
- if $1 == COUPLE
67
- middle = "#{zwj}\u{2764}#{v16}#{zwj}" # heavy black heart
68
- elsif $1 == KISS
69
- middle = "#{zwj}\u{2764}#{v16}#{zwj}\u{1F48B}#{zwj}" # heart + kiss mark
70
- else
71
- middle = zwj
72
- end
73
- raw = $2.split('').map { |c| FAMILY_MAP.fetch(c) }.join(middle)
74
- end
75
- candidates = [raw]
76
- else
77
- raw = glyph_name.gsub(/(^|_)u([0-9A-F]+)/) { ($1.empty?? $1 : zwj) + [$2.hex].pack('U') }
78
- raw.sub!(/\.0\b/, '')
79
- raw.sub!(/\.(#{GENDER_MAP.keys.join('|')})$/) { v16 + zwj + GENDER_MAP.fetch($1) }
80
- candidates = [raw]
81
- candidates << raw.sub(v16, '') if raw.include?(v16)
82
- candidates << raw.gsub(zwj, '') if raw.include?(zwj)
83
- candidates.dup.each { |c| candidates << (c + v16) }
84
- end
85
-
86
- candidates.map { |c| Emoji.find_by_unicode(c) }.compact.first
87
- end
88
-
89
- # https://www.microsoft.com/typography/otspec/otff.htm
90
- def parse_ttc(io)
91
- header_name = io.read(4).unpack('a*')[0]
92
- raise unless "ttcf" == header_name
93
- header_version, num_fonts = io.read(4*2).unpack('l>N')
94
- # parse_version(header_version) #=> 2.0
95
- io.read(4 * num_fonts).unpack('N*')
96
- end
97
-
98
- def parse_tables(io)
99
- sfnt_version, num_tables = io.read(4 + 2*4).unpack('Nn')
100
- # sfnt_version #=> 0x00010000
101
- num_tables.times.each_with_object({}) do |_, tables|
102
- tag, checksum, offset, length = io.read(4 + 4*3).unpack('a4N*')
103
- tables[tag] = {
104
- checksum: checksum,
105
- offset: offset,
106
- length: length,
107
- }
108
- end
109
- end
110
-
111
- GlyphIndex = Struct.new(:length, :name_index, :names) do
112
- def name_for(glyph_id)
113
- index = name_index[glyph_id]
114
- names[index - 257]
115
- end
116
-
117
- def each(&block)
118
- length.times(&block)
119
- end
120
-
121
- def each_with_name
122
- each do |glyph_id|
123
- yield glyph_id, name_for(glyph_id)
124
- end
125
- end
126
- end
127
-
128
- def extract_glyph_index(io, tables)
129
- postscript_table = tables.fetch('post')
130
- io.pos = postscript_table[:offset]
131
- end_pos = io.pos + postscript_table[:length]
132
-
133
- parse_version(io.read(32).unpack('l>')[0]) #=> 2.0
134
- num_glyphs = io.read(2).unpack('n')[0]
135
- glyph_name_index = io.read(2*num_glyphs).unpack('n*')
136
-
137
- glyph_names = []
138
- while io.pos < end_pos
139
- length = io.read(1).unpack('C')[0]
140
- glyph_names << io.read(length)
141
- end
142
-
143
- GlyphIndex.new(num_glyphs, glyph_name_index, glyph_names)
144
- end
145
-
146
- # https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6sbix.html
147
- def each_glyph_bitmap(io, tables, glyph_index)
148
- io.pos = sbix_offset = tables.fetch('sbix')[:offset]
149
- strike = extract_sbix_strike(io, glyph_index.length, size)
150
-
151
- glyph_index.each_with_name do |glyph_id, glyph_name|
152
- glyph_offset = strike[:glyph_data_offset][glyph_id]
153
- next_glyph_offset = strike[:glyph_data_offset][glyph_id + 1]
154
-
155
- if glyph_offset && next_glyph_offset && glyph_offset < next_glyph_offset
156
- io.pos = sbix_offset + strike[:offset] + glyph_offset
157
- x, y, type = io.read(2*2 + 4).unpack('s2A4')
158
- yield glyph_name, type, -> { io.read(next_glyph_offset - glyph_offset - 8) }
159
- end
160
- end
161
- end
162
-
163
- def extract_sbix_strike(io, num_glyphs, image_size)
164
- sbix_offset = io.pos
165
- version, flags, num_strikes = io.read(2*2 + 4).unpack('n2N')
166
- strike_offsets = num_strikes.times.map { io.read(4).unpack('N')[0] }
167
-
168
- strike_offsets.each do |strike_offset|
169
- io.pos = sbix_offset + strike_offset
170
- ppem, resolution = io.read(4*2).unpack('n2')
171
- next unless ppem == size
172
-
173
- data_offsets = io.read(4 * (num_glyphs+1)).unpack('N*')
174
- return {
175
- ppem: ppem,
176
- resolution: resolution,
177
- offset: strike_offset,
178
- glyph_data_offset: data_offsets,
179
- }
180
- end
181
- return nil
182
- end
183
-
184
- def parse_version(num)
185
- major = num >> 16
186
- minor = num & 0xFFFF
187
- "#{major}.#{minor}"
188
- end
189
- end
190
- end