From 3ff41493049255958aaa72b66e239f7482f5e39c Mon Sep 17 00:00:00 2001 From: Jonny Barnes Date: Fri, 8 Jul 2022 16:37:38 +0100 Subject: [PATCH] Use CommonMark plugin for @-mentions --- .../Generators/ContactMentionGenerator.php | 17 ++++++++++ .../Renderers/ContactMentionRenderer.php | 24 +++++++++++++ app/Models/Contact.php | 19 +++++++++-- app/Models/Note.php | 34 ++++++++++++++----- resources/views/templates/note.blade.php | 10 +++--- tests/Feature/BridgyPosseTest.php | 2 +- 6 files changed, 89 insertions(+), 17 deletions(-) create mode 100644 app/CommonMark/Generators/ContactMentionGenerator.php create mode 100644 app/CommonMark/Renderers/ContactMentionRenderer.php diff --git a/app/CommonMark/Generators/ContactMentionGenerator.php b/app/CommonMark/Generators/ContactMentionGenerator.php new file mode 100644 index 00000000..507f2a0f --- /dev/null +++ b/app/CommonMark/Generators/ContactMentionGenerator.php @@ -0,0 +1,17 @@ +getIdentifier())->first(); + + if ($contact === null) { + return '@' . $node->getIdentifier() . ''; + } + + return trim(view('templates.mini-hcard', ['contact' => $contact])->render()); + } +} diff --git a/app/Models/Contact.php b/app/Models/Contact.php index f05505b2..54d9b400 100644 --- a/app/Models/Contact.php +++ b/app/Models/Contact.php @@ -4,10 +4,9 @@ declare(strict_types=1); namespace App\Models; -use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; -use Illuminate\Support\Carbon; class Contact extends Model { @@ -26,4 +25,20 @@ class Contact extends Model * @var array */ protected $fillable = ['nick', 'name', 'homepage', 'twitter', 'facebook']; + + protected function photo(): Attribute + { + $photo = '/assets/profile-images/default-image'; + + if (array_key_exists('homepage', $this->attributes) && !empty($this->attributes['homepage'])) { + $host = parse_url($this->attributes['homepage'], PHP_URL_HOST); + if (file_exists(public_path() . '/assets/profile-images/' . $host . '/image')) { + $photo = '/assets/profile-images/' . $host . '/image'; + } + } + + return Attribute::make( + get: fn () => $photo, + ); + } } diff --git a/app/Models/Note.php b/app/Models/Note.php index ab9e2f19..a664dbfc 100644 --- a/app/Models/Note.php +++ b/app/Models/Note.php @@ -4,13 +4,14 @@ declare(strict_types=1); namespace App\Models; +use App\CommonMark\Generators\ContactMentionGenerator; +use App\CommonMark\Renderers\ContactMentionRenderer; use App\Exceptions\TwitterContentException; -use Barryvdh\LaravelIdeHelper\Eloquent; use Codebird\Codebird; use Exception; use GuzzleHttp\Client; -use Illuminate\Database\Eloquent\Relations\{BelongsTo, BelongsToMany, HasMany, MorphMany}; use Illuminate\Database\Eloquent\{Builder, Factories\HasFactory, Model, SoftDeletes}; +use Illuminate\Database\Eloquent\Relations\{BelongsTo, BelongsToMany, HasMany, MorphMany}; use Illuminate\Support\Facades\Cache; use JetBrains\PhpStorm\ArrayShape; use Jonnybarnes\IndieWeb\Numbers; @@ -19,6 +20,8 @@ use League\CommonMark\Extension\Autolink\AutolinkExtension; use League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension; use League\CommonMark\Extension\CommonMark\Node\Block\FencedCode; use League\CommonMark\Extension\CommonMark\Node\Block\IndentedCode; +use League\CommonMark\Extension\Mention\Mention; +use League\CommonMark\Extension\Mention\MentionExtension; use League\CommonMark\MarkdownConverter; use Normalizer; use Spatie\CommonMarkHighlighter\{FencedCodeRenderer, IndentedCodeRenderer}; @@ -172,8 +175,7 @@ class Note extends Model return null; } - $hcards = $this->makeHCards($value); - $hashtags = $this->autoLinkHashtag($hcards); + $hashtags = $this->autoLinkHashtag($value); return $this->convertMarkdown($hashtags); } @@ -377,9 +379,11 @@ class Note extends Model */ public function getTwitterContentAttribute(): string { + $this->getContacts(); + // check for contacts if ($this->contacts === null || count($this->contacts) === 0) { - throw new TwitterContentException('There are no contacts for this note'); + return ''; } // here we check the matched contact from the note corresponds to a contact @@ -388,10 +392,10 @@ class Note extends Model count(array_unique(array_values($this->contacts))) === 1 && array_unique(array_values($this->contacts))[0] === null ) { - throw new TwitterContentException('The matched contact is not in the database'); + return ''; } - // swap in twitter usernames + // swap in Twitter usernames $swapped = preg_replace_callback( self::USERNAMES_REGEX, function ($matches) { @@ -406,7 +410,7 @@ class Note extends Model return $contact->name; }, - $this->getOriginal('note') + $this->getRawOriginal('note') ); return $this->convertMarkdown($swapped); @@ -527,9 +531,21 @@ class Note extends Model */ private function convertMarkdown(string $note): string { - $environment = new Environment(); + $config = [ + 'mentions' => [ + 'contacts_handle' => [ + 'prefix' => '@', + 'pattern' => '[a-z\d](?:[a-z\d]|-(?=[a-z\d])){0,38}(?!\w)', + 'generator' => new ContactMentionGenerator(), + ], + ], + ]; + + $environment = new Environment($config); $environment->addExtension(new CommonMarkCoreExtension()); $environment->addExtension(new AutolinkExtension()); + $environment->addExtension(new MentionExtension()); + $environment->addRenderer(Mention::class, new ContactMentionRenderer()); $environment->addRenderer(FencedCode::class, new FencedCodeRenderer()); $environment->addRenderer(IndentedCode::class, new IndentedCodeRenderer()); $markdownConverter = new MarkdownConverter($environment); diff --git a/resources/views/templates/note.blade.php b/resources/views/templates/note.blade.php index 0ab9d4c2..20309057 100644 --- a/resources/views/templates/note.blade.php +++ b/resources/views/templates/note.blade.php @@ -15,11 +15,11 @@ @if($media->type == 'download')

Download the attached media

@endif @endforeach -@php -try { - echo '
' . $note->twitter_content . '
'; -} catch (App\Exceptions\TwitterContentException $exception) {} -@endphp + @if ($note->twitter_content) +
+ {!! $note->twitter_content !!} +
+ @endif
@if($note->client) via {{ $note->client->client_name }}@endif diff --git a/tests/Feature/BridgyPosseTest.php b/tests/Feature/BridgyPosseTest.php index 3cb891a1..885fb99c 100644 --- a/tests/Feature/BridgyPosseTest.php +++ b/tests/Feature/BridgyPosseTest.php @@ -25,6 +25,6 @@ class BridgyPosseTest extends TestCase $response = $this->get($note->longurl); $html = $response->content(); - $this->assertStringContainsString('p-bridgy-twitter-content', $html); + $this->assertStringContainsString('Hi @joe__', $html); } }