mirror of
https://github.com/svemagie/indiekit-endpoint-activitypub.git
synced 2026-04-02 15:44:58 +02:00
feat: add internal AP link resolution and OpenGraph card unfurling (v1.1.14)
Reader now resolves ActivityPub links internally instead of navigating to external instances. Actor links open the profile view, post links open a new post detail view with thread context (parent chain + replies). External links in post content get rich preview cards (title, description, image, favicon) fetched via unfurl.js at ingest time with fire-and-forget async processing and concurrency limiting. New files: post-detail controller, og-unfurl module, lookup-cache, link preview template/CSS, client-side link interception JS. Includes SSRF protection for OG fetching and GoToSocial URL support.
This commit is contained in:
@@ -17,14 +17,15 @@
|
||||
{# Reply context if this is a reply #}
|
||||
{% if item.inReplyTo %}
|
||||
<div class="ap-card__reply-to">
|
||||
↩ {{ __("activitypub.reader.replyingTo") }} <a href="{{ item.inReplyTo }}">{{ item.inReplyTo }}</a>
|
||||
↩ {{ __("activitypub.reader.replyingTo") }} <a href="{{ mountPath }}/admin/reader/post?url={{ item.inReplyTo | urlencode }}">{{ item.inReplyTo }}</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{# Author header #}
|
||||
<header class="ap-card__author">
|
||||
{% if item.author.photo %}
|
||||
<img src="{{ item.author.photo }}" alt="{{ item.author.name }}" class="ap-card__avatar" loading="lazy">
|
||||
<img src="{{ item.author.photo }}" alt="{{ item.author.name }}" class="ap-card__avatar"
|
||||
onerror="this.replaceWith(Object.assign(document.createElement('span'),{className:'ap-card__avatar ap-card__avatar--default',textContent:'{{ item.author.name[0] | upper if item.author.name else "?" }}'}))">
|
||||
{% else %}
|
||||
<span class="ap-card__avatar ap-card__avatar--default" aria-hidden="true">{{ item.author.name[0] | upper if item.author.name else "?" }}</span>
|
||||
{% endif %}
|
||||
@@ -50,7 +51,7 @@
|
||||
{# Post title (articles only) #}
|
||||
{% if item.name %}
|
||||
<h2 class="ap-card__title">
|
||||
<a href="{{ item.url }}">{{ item.name }}</a>
|
||||
<a href="{{ mountPath }}/admin/reader/post?url={{ item.uid | urlencode }}">{{ item.name }}</a>
|
||||
</h2>
|
||||
{% endif %}
|
||||
|
||||
@@ -71,6 +72,9 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{# Link previews #}
|
||||
{% include "partials/ap-link-preview.njk" %}
|
||||
|
||||
{# Media hidden behind CW #}
|
||||
{% include "partials/ap-item-media.njk" %}
|
||||
</div>
|
||||
@@ -83,6 +87,9 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{# Link previews #}
|
||||
{% include "partials/ap-link-preview.njk" %}
|
||||
|
||||
{# Media visible directly #}
|
||||
{% include "partials/ap-item-media.njk" %}
|
||||
{% endif %}
|
||||
|
||||
34
views/partials/ap-link-preview.njk
Normal file
34
views/partials/ap-link-preview.njk
Normal file
@@ -0,0 +1,34 @@
|
||||
{# Link preview cards for external links (OpenGraph) #}
|
||||
{% if item.linkPreviews and item.linkPreviews.length > 0 %}
|
||||
<div class="ap-link-previews">
|
||||
{% for preview in item.linkPreviews %}
|
||||
<a href="{{ preview.url }}"
|
||||
rel="noopener"
|
||||
target="_blank"
|
||||
class="ap-link-preview"
|
||||
aria-label="{{ __('activitypub.reader.linkPreview.label') }}: {{ preview.title }}">
|
||||
|
||||
<div class="ap-link-preview__text">
|
||||
<p class="ap-link-preview__title">{{ preview.title }}</p>
|
||||
|
||||
{% if preview.description %}
|
||||
<p class="ap-link-preview__desc">{{ preview.description }}</p>
|
||||
{% endif %}
|
||||
|
||||
<p class="ap-link-preview__domain">
|
||||
{% if preview.favicon %}
|
||||
<img src="{{ preview.favicon }}" alt="" class="ap-link-preview__favicon" loading="lazy" />
|
||||
{% endif %}
|
||||
{{ preview.domain }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{% if preview.image %}
|
||||
<div class="ap-link-preview__image">
|
||||
<img src="{{ preview.image }}" alt="" loading="lazy" decoding="async" />
|
||||
</div>
|
||||
{% endif %}
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
Reference in New Issue
Block a user