Skip to content

Commit f57931f

Browse files
authored
Inline all content previews (#1526)
1 parent ae758d1 commit f57931f

File tree

8 files changed

+113
-15
lines changed

8 files changed

+113
-15
lines changed

assets/styles/components/_inline_md.scss

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
.entry-comment-inline,
33
.post-inline,
44
.post-comment-inline {
5+
display: inline-block;
56
font-weight: bold;
67
border: var(--kbin-section-border);
78
padding: .25em;

src/Markdown/CommonMark/ExternalLinkRenderer.php

+19-7
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
use App\Service\ImageManager;
2929
use App\Service\SettingsManager;
3030
use App\Utils\Embed;
31-
use App\Utils\UrlUtils;
3231
use Doctrine\ORM\EntityManagerInterface;
3332
use League\CommonMark\Extension\CommonMark\Node\Inline\Link;
3433
use League\CommonMark\Node\Inline\Text;
@@ -69,12 +68,27 @@ public function setConfiguration(ConfigurationInterface $configuration): void
6968
$this->config = $configuration;
7069
}
7170

72-
public function render(Node $node, ChildNodeRendererInterface $childRenderer): HtmlElement
71+
private function getRenderTarget(): RenderTarget
72+
{
73+
try {
74+
$kbinConfig = $this->config->get('kbin');
75+
$renderTarget = $kbinConfig[MarkdownConverter::RENDER_TARGET];
76+
if ($renderTarget instanceof RenderTarget) {
77+
return $renderTarget;
78+
}
79+
} catch (\Throwable $e) {
80+
}
81+
82+
return RenderTarget::ActivityPub;
83+
}
84+
85+
public function render(Node $node, ChildNodeRendererInterface $childRenderer): HtmlElement|string
7386
{
7487
/* @var Link $node */
7588
Link::assertInstanceOf($node);
7689

77-
$isApRequest = UrlUtils::isActivityPubRequest($this->requestStack->getCurrentRequest());
90+
$renderTarget = $this->getRenderTarget();
91+
$isApRequest = RenderTarget::ActivityPub === $renderTarget;
7892
if (!$isApRequest && $node instanceof MentionLink && $this->isExistingMentionType($node)) {
7993
$this->logger->debug("Got node of class {c}: username: '{k}', title: '{t}', type: '{ty}', url: '{url}'", [
8094
'c' => \get_class($node),
@@ -119,7 +133,7 @@ public function render(Node $node, ChildNodeRendererInterface $childRenderer): H
119133
} catch (\Error|\Exception $e) {
120134
$this->logger->warning("There was an error finding the activity pub object for url '{q}': {e}", ['q' => $url, 'e' => \get_class($e).' - '.$e->getMessage()]);
121135
}
122-
if (!$isApRequest && null !== $apActivity && Message::class !== $apActivity['type']) {
136+
if (!$isApRequest && null !== $apActivity && 0 !== $apActivity['id'] && Message::class !== $apActivity['type']) {
123137
$this->logger->debug('Found activity with url {u}: {t} - {id}', [
124138
'u' => $node->getUrl(),
125139
't' => $apActivity['type'],
@@ -130,7 +144,7 @@ public function render(Node $node, ChildNodeRendererInterface $childRenderer): H
130144

131145
if (null !== $entity) {
132146
if (null === $node->getTitle() && (null === $childContent || $url === $childContent)) {
133-
return new HtmlElement('div', contents: $this->renderInlineEntity($entity));
147+
return $this->renderInlineEntity($entity);
134148
} else {
135149
$apLink = $this->activityRepository->getLocalUrlOfEntity($entity);
136150
}
@@ -144,8 +158,6 @@ public function render(Node $node, ChildNodeRendererInterface $childRenderer): H
144158
$this->logger->debug('Got an invalid url {u}', ['u' => $url]);
145159
}
146160

147-
$renderTarget = $this->config->get('kbin')[MarkdownConverter::RENDER_TARGET];
148-
149161
$url = match ($node::class) {
150162
RoutedMentionLink::class => $this->generateUrlForRoute($node, $renderTarget),
151163
default => $apLink ?? $node->getUrl(),

src/Repository/ApActivityRepository.php

+22
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,18 @@ public function findLocalByApId(string $apId): ?array
9494
'id' => $id,
9595
'type' => Post::class,
9696
];
97+
} elseif (5 === \count($exploded)) {
98+
// post url with slug (non-ap route)
99+
return [
100+
'id' => \intval($exploded[4]),
101+
'type' => Post::class,
102+
];
97103
} else {
104+
// since the id is just the intval of the last part in the url it will be 0 if that was not a number
105+
if (0 === $id) {
106+
return null;
107+
}
108+
98109
return [
99110
'id' => $id,
100111
'type' => PostComment::class,
@@ -108,7 +119,18 @@ public function findLocalByApId(string $apId): ?array
108119
'id' => $id,
109120
'type' => Entry::class,
110121
];
122+
} elseif (5 === \count($exploded)) {
123+
// entry url with slug (non-ap route)
124+
return [
125+
'id' => \intval($exploded[4]),
126+
'type' => Entry::class,
127+
];
111128
} else {
129+
// since the id is just the intval of the last part in the url it will be 0 if that was not a number
130+
if (0 === $id) {
131+
return null;
132+
}
133+
112134
return [
113135
'id' => $id,
114136
'type' => EntryComment::class,

templates/components/entry_comment_inline_md.html.twig

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<div class="entry-comment-inline">
1+
<span class="entry-comment-inline">
22
{{ component('user_inline', {user: comment.user, fullName: userFullName, showNewIcon: true}) }}:
33
<a href="{{ path('entry_comment_view', {magazine_name: comment.magazine.name, entry_id: comment.entry.id, comment_id: comment.id, slug: comment.entry.slug|length ? comment.entry.slug : '-'}) }}">
44
{% if comment.image is not same as null %}
@@ -27,4 +27,4 @@
2727
{{ 'in'|trans }}
2828
{{ component('magazine_inline', {magazine: comment.magazine, fullName: magazineFullName, showNewIcon: true}) }}
2929
{% endif %}
30-
</div>
30+
</span>

templates/components/entry_inline_md.html.twig

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<div class="entry-inline">
1+
<span class="entry-inline">
22
{{ component('user_inline', {user: entry.user, fullName: userFullName, showNewIcon: true}) }}:
33
<a href="{{ path('entry_single', {magazine_name: entry.magazine.name, entry_id: entry.id, slug: entry.slug|length ? entry.slug : '-'}) }}">
44
{% if entry.image is not same as null %}
@@ -10,4 +10,4 @@
1010
{{ 'in'|trans }}
1111
{{ component('magazine_inline', {magazine: entry.magazine, fullName: magazineFullName, showNewIcon: true}) }}
1212
{% endif %}
13-
</div>
13+
</span>

templates/components/post_comment_inline_md.html.twig

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<div class="post-comment-inline">
1+
<span class="post-comment-inline">
22
{{ component('user_inline', {user: comment.user, fullName: userFullName, showNewIcon: true}) }}:
33
<a href="{{ path('post_single', {magazine_name: comment.magazine.name, post_id: comment.post.id, slug: comment.post.slug|length ? comment.post.slug : '-'}) }}#post-comment-{{ comment.id }}">
44
{% if comment.image is not same as null %}
@@ -27,4 +27,4 @@
2727
{{ 'in'|trans }}
2828
{{ component('magazine_inline', {magazine: comment.magazine, fullName: magazineFullName, showNewIcon: true}) }}
2929
{% endif %}
30-
</div>
30+
</span>

templates/components/post_inline_md.html.twig

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<div class="post-inline">
1+
<span class="post-inline">
22
{{ component('user_inline', {user: post.user, fullName: userFullName, showNewIcon: true}) }}:
33
<a href="{{ path('post_single', {magazine_name: post.magazine.name, post_id: post.id, slug: post.slug|length ? post.slug : '-'}) }}">
44
{% if post.image is not same as null %}
@@ -10,4 +10,4 @@
1010
{{ 'in'|trans }}
1111
{{ component('magazine_inline', {magazine: post.magazine, fullName: magazineFullName}) }}
1212
{% endif %}
13-
</div>
13+
</span>

tests/Unit/Utils/MarkdownTest.php

+63
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,13 @@
44

55
namespace App\Tests\Unit\Utils;
66

7+
use App\Entity\Magazine;
78
use App\Markdown\MarkdownConverter;
89
use App\Markdown\RenderTarget;
910
use App\Tests\WebTestCase;
1011

12+
use function PHPUnit\Framework\assertStringContainsString;
13+
1114
class MarkdownTest extends WebTestCase
1215
{
1316
public function testMagazineLinks(): void
@@ -89,4 +92,64 @@ public function testExternalMentionLink(): void
8992
// assert that this community does not exist, and we get a search link for it that does not link to the external instance
9093
self::assertStringContainsString('https://kbin.test2', $markdown);
9194
}
95+
96+
public function testExternalMagazineLocalEntryLink(): void
97+
{
98+
$m = new Magazine('[email protected]', 'test', null, null, null, false, false, null);
99+
$m->apId = '[email protected]';
100+
$m->apInboxUrl = 'https://kbin.test2/inbox';
101+
$m->apPublicUrl = 'https://kbin.test2/m/test';
102+
$m->apProfileId = 'https://kbin.test2/m/test';
103+
$this->entityManager->persist($m);
104+
$entry = $this->getEntryByTitle('test', magazine: $m);
105+
$this->entityManager->flush();
106+
$text = "Look at my post at https://kbin.test/m/[email protected]/t/{$entry->getId()}/some-slug";
107+
$markdown = $this->markdownConverter->convertToHtml($text, [MarkdownConverter::RENDER_TARGET => RenderTarget::Page]);
108+
assertStringContainsString('entry-inline', $markdown);
109+
}
110+
111+
public function testExternalMagazineLocalPostLink(): void
112+
{
113+
$m = new Magazine('[email protected]', 'test', null, null, null, false, false, null);
114+
$m->apId = '[email protected]';
115+
$m->apInboxUrl = 'https://kbin.test2/inbox';
116+
$m->apPublicUrl = 'https://kbin.test2/m/test';
117+
$m->apProfileId = 'https://kbin.test2/m/test';
118+
$this->entityManager->persist($m);
119+
$post = $this->createPost('test', magazine: $m);
120+
$this->entityManager->flush();
121+
$text = "Look at my post at https://kbin.test/m/[email protected]/p/{$post->getId()}/some-slug";
122+
$markdown = $this->markdownConverter->convertToHtml($text, [MarkdownConverter::RENDER_TARGET => RenderTarget::Page]);
123+
assertStringContainsString('post-inline', $markdown);
124+
}
125+
126+
public function testLocalNotMatchingUrl(): void
127+
{
128+
$m = new Magazine('[email protected]', 'test', null, null, null, false, false, null);
129+
$m->apId = '[email protected]';
130+
$m->apInboxUrl = 'https://kbin.test2/inbox';
131+
$m->apPublicUrl = 'https://kbin.test2/m/test';
132+
$m->apProfileId = 'https://kbin.test2/m/test';
133+
$this->entityManager->persist($m);
134+
$entry = $this->getEntryByTitle('test', magazine: $m);
135+
$this->entityManager->flush();
136+
$text = "Look at my post at https://kbin.test/m/[email protected]/t/{$entry->getId()}/some-slug/votes";
137+
$markdown = $this->markdownConverter->convertToHtml($text, [MarkdownConverter::RENDER_TARGET => RenderTarget::Page]);
138+
assertStringContainsString("https://kbin.test/m/[email protected]/t/{$entry->getId()}/some-slug/votes", $markdown);
139+
}
140+
141+
public function testBracketsInLinkTitle(): void
142+
{
143+
$m = new Magazine('[email protected]', 'test', null, null, null, false, false, null);
144+
$m->apId = '[email protected]';
145+
$m->apInboxUrl = 'https://kbin.test2/inbox';
146+
$m->apPublicUrl = 'https://kbin.test2/m/test';
147+
$m->apProfileId = 'https://kbin.test2/m/test';
148+
$this->entityManager->persist($m);
149+
$entry = $this->getEntryByTitle('test', magazine: $m);
150+
$this->entityManager->flush();
151+
$text = "[Look at my post (or not, your choice)](https://kbin.test/m/[email protected]/t/{$entry->getId()}/some-slug/favourites)";
152+
$markdown = $this->markdownConverter->convertToHtml($text, [MarkdownConverter::RENDER_TARGET => RenderTarget::Page]);
153+
assertStringContainsString("https://kbin.test/m/[email protected]/t/{$entry->getId()}/some-slug/favourites", $markdown);
154+
}
92155
}

0 commit comments

Comments
 (0)