Skip to content

Commit

Permalink
Work in progress, display emojis
Browse files Browse the repository at this point in the history
  • Loading branch information
danon committed Nov 21, 2023
1 parent 9adaefb commit 92ea27f
Show file tree
Hide file tree
Showing 9 changed files with 26,365 additions and 2 deletions.
29 changes: 29 additions & 0 deletions app/Services/Parser/Extensions/Emoji.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php
namespace Coyote\Services\Parser\Extensions;

use League\CommonMark\Node\Block\AbstractBlock;

class Emoji extends AbstractBlock
{
private static ?array $resourceFile = null;

public string $code;
public string $unified;
public string $name;

public function __construct(string $code)
{
parent::__construct();
$this->code = $code;

if (self::$resourceFile === null) {
self::$resourceFile = \json_decode(\file_get_contents(__DIR__ . DIRECTORY_SEPARATOR . 'emoji.json'), true);
}
$resourceFile = self::$resourceFile;

$emoji = $resourceFile['emoticons'][$code];

$this->unified = $emoji['unified'];
$this->name = $emoji['name'];
}
}
46 changes: 46 additions & 0 deletions app/Services/Parser/Extensions/EmojiParser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php
namespace Coyote\Services\Parser\Extensions;

use League\CommonMark\Parser\Cursor;
use League\CommonMark\Parser\Inline\InlineParserInterface;
use League\CommonMark\Parser\Inline\InlineParserMatch;
use League\CommonMark\Parser\InlineParserContext;

class EmojiParser implements InlineParserInterface
{
public function getMatchDefinition(): InlineParserMatch
{
return InlineParserMatch::join(
InlineParserMatch::string(':'),
InlineParserMatch::regex('\w+'),
InlineParserMatch::string(':'));
}

public function parse(InlineParserContext $inlineContext): bool
{
$cursor = $inlineContext->getCursor();
$previous = $cursor->peek(-1);
if ($previous === null || $previous === ' ') {
return $this->appendEmoji($cursor, $inlineContext);
}
return false;
}

private function appendEmoji(Cursor $cursor, InlineParserContext $context): bool
{
$previousState = $cursor->saveState();
$emoji = $cursor->match('/^:[\w+-]+:/i');
if ($emoji === null) {
$cursor->restoreState($previousState);
return false;
}
$emoji = \subStr($emoji, 1, -1);
if (\array_key_exists($emoji, Emojis::$codes)) {
$container = $context->getContainer();
$container->appendChild(new Emoji($emoji));
return true;
}
$cursor->restoreState($previousState);
return false;
}
}
32 changes: 32 additions & 0 deletions app/Services/Parser/Extensions/EmojiRenderer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php
namespace Coyote\Services\Parser\Extensions;

use League\CommonMark\Node\Node;
use League\CommonMark\Renderer\ChildNodeRendererInterface;
use League\CommonMark\Renderer\NodeRendererInterface;
use League\CommonMark\Util\HtmlElement;

class EmojiRenderer implements NodeRendererInterface
{
public function render(Node $node, ChildNodeRendererInterface $childRenderer): HtmlElement
{
if ($node instanceof Emoji) {
return $this->renderEmoji($node);
}
throw new \LogicException('Failed to parse markdown emoticons');
}

private function renderEmoji(Emoji $emoji): HtmlElement
{
return new HtmlElement('img', [
'class' => 'img-smile',
'src' => $this->cdnUrl($emoji),
'alt' => ":$emoji->code:, $emoji->name",
]);
}

private function cdnUrl(Emoji $emoji): string
{
return "https://cdn.jsdelivr.net/gh/twitter/[email protected]/assets/svg/$emoji->unified.svg";
}
}
1,788 changes: 1,788 additions & 0 deletions app/Services/Parser/Extensions/Emojis.php

Large diffs are not rendered by default.

Loading

0 comments on commit 92ea27f

Please sign in to comment.