20
20
$ emojisCodePoints = Builder::getEmojisCodePoints ();
21
21
Builder::saveRules (Builder::buildRules ($ emojisCodePoints ));
22
22
Builder::saveRules (Builder::buildStripRules ($ emojisCodePoints ));
23
- Builder::saveRules (Builder::buildGitHubRules ($ emojisCodePoints ));
24
- Builder::saveRules (Builder::buildGitlabRules ($ emojisCodePoints ));
25
- Builder::saveRules (Builder::buildSlackRules ($ emojisCodePoints ));
23
+
24
+ $ emojiMaps = ['slack ' , 'github ' , 'gitlab ' ];
25
+
26
+ foreach ($ emojiMaps as $ map ) {
27
+ $ maps = Builder::{"build {$ map }Maps " }($ emojisCodePoints );
28
+ Builder::saveRules (array_combine (["emoji- $ map " , "$ map-emoji " ], Builder::createRules ($ maps , true )));
29
+ }
30
+
31
+ Builder::saveRules (Builder::buildTextRules ($ emojisCodePoints , $ emojiMaps ));
26
32
27
33
final class Builder
28
34
{
@@ -45,10 +51,10 @@ public static function getEmojisCodePoints(): array
45
51
throw new \DomainException ("Could not parse line: \"$ line \". " );
46
52
}
47
53
48
- $ codePoints = strtolower ( trim ($ matches ['codePoints ' ]));
54
+ $ codePoints = str_replace ( ' ' , ' - ' , trim ($ matches ['codePoints ' ]));
49
55
$ emojisCodePoints [$ codePoints ] = $ matches ['emoji ' ];
50
56
// We also add a version without the "Zero Width Joiner"
51
- $ codePoints = str_replace ('200d ' , '' , $ codePoints );
57
+ $ codePoints = str_replace ('-200D- ' , '- ' , $ codePoints );
52
58
$ emojisCodePoints [$ codePoints ] = $ matches ['emoji ' ];
53
59
}
54
60
@@ -67,7 +73,6 @@ public static function buildRules(array $emojisCodePoints): Generator
67
73
->name ('*.xml ' )
68
74
;
69
75
70
- $ ignored = [];
71
76
$ mapsByLocale = [];
72
77
73
78
foreach ($ files as $ file ) {
@@ -89,16 +94,8 @@ public static function buildRules(array $emojisCodePoints): Generator
89
94
continue ;
90
95
}
91
96
$ parts = preg_split ('//u ' , $ emoji , -1 , \PREG_SPLIT_NO_EMPTY );
92
- $ emojiCodePoints = implode (' ' , array_map ('dechex ' , array_map ('mb_ord ' , $ parts )));
97
+ $ emojiCodePoints = strtoupper ( implode ('- ' , array_map ('dechex ' , array_map ('mb_ord ' , $ parts) )));
93
98
if (!array_key_exists ($ emojiCodePoints , $ emojisCodePoints )) {
94
- $ ignored [] = [
95
- 'locale ' => $ locale ,
96
- 'emoji ' => $ emoji ,
97
- 'name ' => $ name ,
98
- ];
99
- continue ;
100
- }
101
- if (!self ::testEmoji ($ emoji , $ locale , $ emojiCodePoints )) {
102
99
continue ;
103
100
}
104
101
$ codePointsCount = mb_strlen ($ emoji );
@@ -128,108 +125,83 @@ public static function buildRules(array $emojisCodePoints): Generator
128
125
}
129
126
}
130
127
131
- public static function buildGitHubRules (array $ emojisCodePoints ): iterable
128
+ public static function buildGitHubMaps (array $ emojisCodePoints ): array
132
129
{
133
130
$ emojis = json_decode ((new Filesystem ())->readFile (__DIR__ .'/vendor/github-emojis.json ' ), true , flags: JSON_THROW_ON_ERROR );
134
-
135
- $ ignored = [];
136
131
$ maps = [];
137
132
138
133
foreach ($ emojis as $ shortCode => $ url ) {
139
- $ emojiCodePoints = str_replace ('- ' , ' ' , strtolower (basename (parse_url ($ url , \PHP_URL_PATH ), '.png ' )));
134
+ $ emojiCodePoints = strtoupper (basename (parse_url ($ url , \PHP_URL_PATH ), '.png ' ));
135
+
140
136
if (!array_key_exists ($ emojiCodePoints , $ emojisCodePoints )) {
141
- $ ignored [] = [
142
- 'emojiCodePoints ' => $ emojiCodePoints ,
143
- 'shortCode ' => $ shortCode ,
144
- ];
145
137
continue ;
146
138
}
147
139
$ emoji = $ emojisCodePoints [$ emojiCodePoints ];
148
- if (!self ::testEmoji ($ emoji , 'github ' , $ emojiCodePoints )) {
149
- continue ;
150
- }
151
- $ codePointsCount = mb_strlen ($ emoji );
152
- $ maps [$ codePointsCount ][$ emoji ] = ": $ shortCode: " ;
140
+ $ emojiPriority = mb_strlen ($ emoji ) << 1 ;
141
+ $ maps [$ emojiPriority + 1 ][": $ shortCode: " ] = $ emoji ;
153
142
}
154
143
155
- $ maps = self ::createRules ($ maps );
156
-
157
- return ['emoji-github ' => $ maps , 'github-emoji ' => array_flip ($ maps )];
144
+ return $ maps ;
158
145
}
159
146
160
- public static function buildGitlabRules (array $ emojisCodePoints ): iterable
147
+ public static function buildGitlabMaps (array $ emojisCodePoints ): array
161
148
{
162
149
$ emojis = json_decode ((new Filesystem ())->readFile (__DIR__ .'/vendor/gitlab-emojis.json ' ), true , flags: JSON_THROW_ON_ERROR );
163
-
164
- $ ignored = [];
165
150
$ maps = [];
166
151
167
152
foreach ($ emojis as $ emojiItem ) {
168
- $ emojiCodePoints = strtolower ($ emojiItem ['unicode ' ]);
169
- if (!array_key_exists ($ emojiCodePoints , $ emojisCodePoints )) {
170
- $ ignored [] = [
171
- 'emojiCodePoints ' => $ emojiCodePoints ,
172
- 'name ' => $ emojiItem ['name ' ],
173
- ];
174
- continue ;
175
- }
176
- $ emoji = $ emojisCodePoints [$ emojiCodePoints ];
177
- if (!self ::testEmoji ($ emoji , 'gitlab ' , $ emojiCodePoints )) {
178
- continue ;
153
+ $ emoji = $ emojiItem ['moji ' ];
154
+ $ emojiPriority = mb_strlen ($ emoji ) << 1 ;
155
+ $ maps [$ emojiPriority + 1 ][$ emojiItem ['shortname ' ]] = $ emoji ;
156
+
157
+ foreach ($ emojiItem ['aliases ' ] as $ alias ) {
158
+ $ maps [$ emojiPriority ][$ alias ] = $ emoji ;
179
159
}
180
- $ codePointsCount = mb_strlen ($ emoji );
181
- $ maps [$ codePointsCount ][$ emoji ] = $ emojiItem ['shortname ' ];
182
160
}
183
161
184
- $ maps = self ::createRules ($ maps );
185
-
186
- return ['emoji-gitlab ' => $ maps , 'gitlab-emoji ' => array_flip ($ maps )];
162
+ return $ maps ;
187
163
}
188
164
189
- public static function buildSlackRules (array $ emojisCodePoints ): iterable
165
+ public static function buildSlackMaps (array $ emojisCodePoints ): array
190
166
{
191
167
$ emojis = json_decode ((new Filesystem ())->readFile (__DIR__ .'/vendor/slack-emojis.json ' ), true , flags: JSON_THROW_ON_ERROR );
192
-
193
- $ ignored = [];
194
- $ emojiSlackMaps = [];
195
- $ slackEmojiMaps = [];
168
+ $ maps = [];
196
169
197
170
foreach ($ emojis as $ data ) {
198
- $ emojiCodePoints = str_replace ('- ' , ' ' , strtolower ($ data ['unified ' ]));
199
- $ shortCode = $ data ['short_name ' ];
200
- $ shortCodes = $ data ['short_names ' ];
201
- $ shortCodes = array_map (fn ($ v ) => ": $ v: " , $ shortCodes );
171
+ $ emoji = $ emojisCodePoints [$ data ['unified ' ]];
172
+ $ emojiPriority = mb_strlen ($ emoji ) << 1 ;
173
+ $ maps [$ emojiPriority + 1 ][": {$ data ['short_name ' ]}: " ] = $ emoji ;
202
174
203
- if (!array_key_exists ($ emojiCodePoints , $ emojisCodePoints )) {
204
- $ ignored [] = [
205
- 'emojiCodePoints ' => $ emojiCodePoints ,
206
- 'shortCode ' => $ shortCode ,
207
- ];
208
- continue ;
175
+ foreach ($ data ['short_names ' ] as $ shortName ) {
176
+ $ maps [$ emojiPriority ][": $ shortName: " ] = $ emoji ;
209
177
}
210
- $ emoji = $ emojisCodePoints [$ emojiCodePoints ];
211
- if (!self ::testEmoji ($ emoji , 'slack ' , $ emojiCodePoints )) {
212
- continue ;
213
- }
214
- $ codePointsCount = mb_strlen ($ emoji );
215
- $ emojiSlackMaps [$ codePointsCount ][$ emoji ] = ": $ shortCode: " ;
216
- foreach ($ shortCodes as $ short_name ) {
217
- $ slackEmojiMaps [$ codePointsCount ][$ short_name ] = $ emoji ;
178
+ }
179
+
180
+ return $ maps ;
181
+ }
182
+
183
+ public static function buildTextRules (array $ emojiCodePoints , array $ locales ): iterable
184
+ {
185
+ $ maps = [];
186
+
187
+ foreach ($ locales as $ locale ) {
188
+ foreach (self ::{"build {$ locale }Maps " }($ emojiCodePoints ) as $ emojiPriority => $ map ) {
189
+ foreach ($ map as $ text => $ emoji ) {
190
+ $ maps [$ emojiPriority ][str_replace ('_ ' , '- ' , $ text )] ??= $ emoji ;
191
+ }
218
192
}
219
193
}
220
194
221
- return ['emoji-slack ' => self ::createRules ($ emojiSlackMaps ), 'slack-emoji ' => self ::createRules ($ slackEmojiMaps )];
195
+ [$ map , $ reverse ] = self ::createRules ($ maps , true );
196
+
197
+ return ['emoji-text ' => $ map , 'text-emoji ' => $ reverse ];
222
198
}
223
199
224
200
public static function buildStripRules (array $ emojisCodePoints ): iterable
225
201
{
226
202
$ maps = [];
227
- foreach ($ emojisCodePoints as $ codePoints => $ emoji ) {
228
- if (!self ::testEmoji ($ emoji , 'strip ' , $ codePoints )) {
229
- continue ;
230
- }
231
- $ codePointsCount = mb_strlen ($ emoji );
232
- $ maps [$ codePointsCount ][$ emoji ] = '' ;
203
+ foreach ($ emojisCodePoints as $ emoji ) {
204
+ $ maps [mb_strlen ($ emoji )][$ emoji ] = '' ;
233
205
}
234
206
235
207
return ['emoji-strip ' => self ::createRules ($ maps )];
@@ -269,24 +241,26 @@ public static function saveRules(iterable $rulesByLocale): void
269
241
$ fs ->dumpFile ($ file , preg_replace ('/QUICK_CHECK = .*;/m ' , "QUICK_CHECK = {$ quickCheck }; " , $ fs ->readFile ($ file )));
270
242
}
271
243
272
- private static function testEmoji ( string $ emoji , string $ locale , string $ codePoints ): bool
244
+ public static function createRules ( array $ maps , bool $ reverse = false ): array
273
245
{
274
- if (!Transliterator::createFromRules ("\\$ emoji > test ; " )) {
275
- printf ('Could not create transliterator for "%s" in "%s" locale. Code Point: "%s". Error: "%s". ' ."\n" , $ emoji , $ locale , $ codePoints , intl_get_error_message ());
246
+ // We must sort the maps by the number of code points, because the order really matters:
247
+ // 🫶🏼 must be before 🫶
248
+ krsort ($ maps );
276
249
277
- return false ;
250
+ if (!$ reverse ) {
251
+ return array_merge (...$ maps );
278
252
}
279
253
280
- return true ;
281
- }
254
+ $ emojiText = $ textEmoji = [];
282
255
283
- private static function createRules (array $ maps ): array
284
- {
285
- // We must sort the maps by the number of code points, because the order really matters:
286
- // 🫶🏼 must be before 🫶
287
- krsort ($ maps );
288
- $ maps = array_merge (...$ maps );
256
+ foreach ($ maps as $ map ) {
257
+ uksort ($ map , static fn ($ a , $ b ) => strnatcmp (substr ($ a , 1 , -1 ), substr ($ b , 1 , -1 )));
258
+ $ textEmoji = array_merge ($ map , $ textEmoji );
289
259
290
- return $ maps ;
260
+ $ map = array_flip ($ map );
261
+ $ emojiText += $ map ;
262
+ }
263
+
264
+ return [$ emojiText , $ textEmoji ];
291
265
}
292
266
}
0 commit comments