Now that I have pages showing all posts that use a specific emoji such as š, I found myself wanting to be able to click the emoji in my posts to see other posts with that emoji. This is the same as how my autolinked hashtags work, where you can click on any hashtag in a post and see other posts with that hashtag.
This was relatively straightforward to accomplish with my new Emoji Detector library, there was only one trick needed. Because some emoji are composed of others (such as š³ļøāš being composed of š plus š³), the particular byte sequence for š actually appears twice in a string that has both of those emoji. Once for the standalone rainbow, and another as part of the rainbow flag. This means if we tried to replace all instances of š with a hyperlink, we'd actually catch the š byte in š³ļøāš as well, breaking it into separate emoji!
So to avoid this problem, I used two tricks.Ā
First, since the Emoji Detector library returns the number of code points in each emoji found, I first sort the list so that the longer emoji strings are first in the list.
$emojis = \Emoji\detect_emoji($text); usort($emojis, function($a,$b){ return $a['num_points'] < $b['num_points']; });
Second, instead of doing an inline replace of the post text with the hyperlink, I create a mapping of placeholder strings for each emoji found, and replace the emoji with those placeholders instead.
$map = []; foreach($emojis as $emoji) { if($emoji['short_name']) { $k = md5(mt_rand().$emoji['emoji']); $map[$k] = $emoji['emoji']; $text = str_replace($emoji['emoji'], $k, $text); } }
Then, in a separate loop, I loop through the mapping and replace each random string with the emoji including a hyperlink wrapping it.
foreach($map as $k=>$emoji) { $text = str_replace($k, '<a href="/emoji/'.$emoji.'" class="emoji">'.$emoji.'</a>', $text); }
This way, I avoid the "clobbering" issue of double matching the duplicate byte sequences.
Lastly, I noticed that when I use several emoji in a row, they end up appearing squished together like this:
Since I was already wrapping each emoji with a hyperlink, I was then able to style them to add a bit of spacing around them, so now they appear a little nicer: