feat: Refactor mention rendering and generator classes
- Add support for Mastodon username mentions - Add test for parsing Mastodon usernames in notes - Modify namespace and class imports for `MentionGenerator` and `MentionRenderer` in `Note.php` - Rename `ContactMentionGenerator.php` to `MentionGenerator.php`
This commit is contained in:
parent
3817545cf3
commit
05c63b241d
5 changed files with 55 additions and 31 deletions
|
@ -8,7 +8,7 @@ use League\CommonMark\Extension\Mention\Generator\MentionGeneratorInterface;
|
||||||
use League\CommonMark\Extension\Mention\Mention;
|
use League\CommonMark\Extension\Mention\Mention;
|
||||||
use League\CommonMark\Node\Inline\AbstractInline;
|
use League\CommonMark\Node\Inline\AbstractInline;
|
||||||
|
|
||||||
class ContactMentionGenerator implements MentionGeneratorInterface
|
class MentionGenerator implements MentionGeneratorInterface
|
||||||
{
|
{
|
||||||
public function generateMention(Mention $mention): ?AbstractInline
|
public function generateMention(Mention $mention): ?AbstractInline
|
||||||
{
|
{
|
|
@ -1,24 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace App\CommonMark\Renderers;
|
|
||||||
|
|
||||||
use App\Models\Contact;
|
|
||||||
use League\CommonMark\Node\Node;
|
|
||||||
use League\CommonMark\Renderer\ChildNodeRendererInterface;
|
|
||||||
use League\CommonMark\Renderer\NodeRendererInterface;
|
|
||||||
|
|
||||||
class ContactMentionRenderer implements NodeRendererInterface
|
|
||||||
{
|
|
||||||
public function render(Node $node, ChildNodeRendererInterface $childRenderer): string
|
|
||||||
{
|
|
||||||
$contact = Contact::where('nick', $node->getIdentifier())->first();
|
|
||||||
|
|
||||||
if ($contact === null) {
|
|
||||||
return '<a href="https://twitter.com/' . $node->getIdentifier() . '">@' . $node->getIdentifier() . '</a>';
|
|
||||||
}
|
|
||||||
|
|
||||||
return trim(view('templates.mini-hcard', ['contact' => $contact])->render());
|
|
||||||
}
|
|
||||||
}
|
|
37
app/CommonMark/Renderers/MentionRenderer.php
Normal file
37
app/CommonMark/Renderers/MentionRenderer.php
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\CommonMark\Renderers;
|
||||||
|
|
||||||
|
use App\Models\Contact;
|
||||||
|
use League\CommonMark\Node\Node;
|
||||||
|
use League\CommonMark\Renderer\ChildNodeRendererInterface;
|
||||||
|
use League\CommonMark\Renderer\NodeRendererInterface;
|
||||||
|
use League\CommonMark\Util\HtmlElement;
|
||||||
|
|
||||||
|
class MentionRenderer implements NodeRendererInterface
|
||||||
|
{
|
||||||
|
public function render(Node $node, ChildNodeRendererInterface $childRenderer): HtmlElement|string
|
||||||
|
{
|
||||||
|
$contact = Contact::where('nick', $node->getIdentifier())->first();
|
||||||
|
|
||||||
|
// If we have a contact, render a mini-hcard
|
||||||
|
if ($contact) {
|
||||||
|
// rendering a blade template to a string, so can’t be an HtmlElement
|
||||||
|
return trim(view('templates.mini-hcard', ['contact' => $contact])->render());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, check the link is to the Mastodon profile
|
||||||
|
$mentionText = $node->getIdentifier();
|
||||||
|
$parts = explode('@', $mentionText);
|
||||||
|
|
||||||
|
// This is not [@]handle@instance, so return a Twitter link
|
||||||
|
if (count($parts) === 1) {
|
||||||
|
return new HtmlElement('a', ['href' => 'https://twitter.com/' . $parts[0]], '@' . $mentionText);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render the Mastodon profile link
|
||||||
|
return new HtmlElement('a', ['href' => 'https://' . $parts[1] . '/@' . $parts[0]], '@' . $mentionText);
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,8 +4,8 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
use App\CommonMark\Generators\ContactMentionGenerator;
|
use App\CommonMark\Generators\MentionGenerator;
|
||||||
use App\CommonMark\Renderers\ContactMentionRenderer;
|
use App\CommonMark\Renderers\MentionRenderer;
|
||||||
use Codebird\Codebird;
|
use Codebird\Codebird;
|
||||||
use Exception;
|
use Exception;
|
||||||
use GuzzleHttp\Client;
|
use GuzzleHttp\Client;
|
||||||
|
@ -385,10 +385,10 @@ class Note extends Model
|
||||||
{
|
{
|
||||||
$config = [
|
$config = [
|
||||||
'mentions' => [
|
'mentions' => [
|
||||||
'contacts_handle' => [
|
'mentions_handle' => [
|
||||||
'prefix' => '@',
|
'prefix' => '@',
|
||||||
'pattern' => '[a-z\d](?:[a-z\d]|-(?=[a-z\d])){0,38}(?!\w)',
|
'pattern' => '([\w@.])+(\b)',
|
||||||
'generator' => new ContactMentionGenerator(),
|
'generator' => new MentionGenerator(),
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
@ -397,7 +397,7 @@ class Note extends Model
|
||||||
$environment->addExtension(new CommonMarkCoreExtension());
|
$environment->addExtension(new CommonMarkCoreExtension());
|
||||||
$environment->addExtension(new AutolinkExtension());
|
$environment->addExtension(new AutolinkExtension());
|
||||||
$environment->addExtension(new MentionExtension());
|
$environment->addExtension(new MentionExtension());
|
||||||
$environment->addRenderer(Mention::class, new ContactMentionRenderer());
|
$environment->addRenderer(Mention::class, new MentionRenderer());
|
||||||
$environment->addRenderer(FencedCode::class, new FencedCodeRenderer());
|
$environment->addRenderer(FencedCode::class, new FencedCodeRenderer());
|
||||||
$environment->addRenderer(IndentedCode::class, new IndentedCodeRenderer());
|
$environment->addRenderer(IndentedCode::class, new IndentedCodeRenderer());
|
||||||
$markdownConverter = new MarkdownConverter($environment);
|
$markdownConverter = new MarkdownConverter($environment);
|
||||||
|
|
|
@ -437,4 +437,15 @@ class NotesTest extends TestCase
|
||||||
|
|
||||||
$this->assertSame('<span class="p-country-name">Antarctica</span>', $note->address);
|
$this->assertSame('<span class="p-country-name">Antarctica</span>', $note->address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @test */
|
||||||
|
public function mastodonUsernamesAreParsedCorrectly(): void
|
||||||
|
{
|
||||||
|
$expected = '<p>Hi <a href="https://phpc.social/@freekmurze">@freekmurze@phpc.social</a> how are you?</p>' . PHP_EOL;
|
||||||
|
$note = Note::factory()->create([
|
||||||
|
'note' => 'Hi @freekmurze@phpc.social how are you?',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->assertSame($expected, $note->note);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue