@rmdes/indiekit-endpoint-activitypub 2.7.0 → 2.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/assets/reader.css
CHANGED
|
@@ -528,12 +528,18 @@
|
|
|
528
528
|
.ap-card__gallery img {
|
|
529
529
|
background: var(--color-offset-variant);
|
|
530
530
|
display: block;
|
|
531
|
-
height:
|
|
531
|
+
height: 280px;
|
|
532
532
|
object-fit: cover;
|
|
533
533
|
width: 100%;
|
|
534
534
|
transition: filter 0.2s ease;
|
|
535
535
|
}
|
|
536
536
|
|
|
537
|
+
@media (max-width: 480px) {
|
|
538
|
+
.ap-card__gallery img {
|
|
539
|
+
height: 180px;
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
|
|
537
543
|
.ap-card__gallery-link:hover img {
|
|
538
544
|
filter: brightness(0.92);
|
|
539
545
|
}
|
|
@@ -668,6 +674,83 @@
|
|
|
668
674
|
transform: translateX(-50%);
|
|
669
675
|
}
|
|
670
676
|
|
|
677
|
+
/* ==========================================================================
|
|
678
|
+
Link Preview Card
|
|
679
|
+
========================================================================== */
|
|
680
|
+
|
|
681
|
+
.ap-link-previews {
|
|
682
|
+
margin-bottom: var(--space-s);
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
.ap-link-preview {
|
|
686
|
+
display: flex;
|
|
687
|
+
border: var(--border-width-thin) solid var(--color-outline);
|
|
688
|
+
border-radius: var(--border-radius-small);
|
|
689
|
+
overflow: hidden;
|
|
690
|
+
text-decoration: none;
|
|
691
|
+
color: inherit;
|
|
692
|
+
transition: border-color 0.2s ease;
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
.ap-link-preview:hover {
|
|
696
|
+
border-color: var(--color-primary);
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
.ap-link-preview__text {
|
|
700
|
+
flex: 1;
|
|
701
|
+
min-width: 0;
|
|
702
|
+
padding: var(--space-s) var(--space-m);
|
|
703
|
+
display: flex;
|
|
704
|
+
flex-direction: column;
|
|
705
|
+
justify-content: center;
|
|
706
|
+
gap: 0.2em;
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
.ap-link-preview__title {
|
|
710
|
+
font-weight: var(--font-weight-bold);
|
|
711
|
+
font-size: var(--font-size-s);
|
|
712
|
+
margin: 0;
|
|
713
|
+
overflow: hidden;
|
|
714
|
+
text-overflow: ellipsis;
|
|
715
|
+
white-space: nowrap;
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
.ap-link-preview__desc {
|
|
719
|
+
font-size: var(--font-size-s);
|
|
720
|
+
color: var(--color-on-offset);
|
|
721
|
+
margin: 0;
|
|
722
|
+
display: -webkit-box;
|
|
723
|
+
-webkit-line-clamp: 2;
|
|
724
|
+
-webkit-box-orient: vertical;
|
|
725
|
+
overflow: hidden;
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
.ap-link-preview__domain {
|
|
729
|
+
font-size: var(--font-size-xs);
|
|
730
|
+
color: var(--color-on-offset);
|
|
731
|
+
margin: 0;
|
|
732
|
+
display: flex;
|
|
733
|
+
align-items: center;
|
|
734
|
+
gap: 0.3em;
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
.ap-link-preview__favicon {
|
|
738
|
+
width: 14px;
|
|
739
|
+
height: 14px;
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
.ap-link-preview__image {
|
|
743
|
+
flex-shrink: 0;
|
|
744
|
+
width: 120px;
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
.ap-link-preview__image img {
|
|
748
|
+
display: block;
|
|
749
|
+
width: 100%;
|
|
750
|
+
height: 100%;
|
|
751
|
+
object-fit: cover;
|
|
752
|
+
}
|
|
753
|
+
|
|
671
754
|
/* ==========================================================================
|
|
672
755
|
Video Embed
|
|
673
756
|
========================================================================== */
|
package/lib/inbox-listeners.js
CHANGED
|
@@ -431,6 +431,7 @@ export function registerInboxListeners(inboxChain, options) {
|
|
|
431
431
|
|
|
432
432
|
await addNotification(collections, {
|
|
433
433
|
uid: object.id?.href || `reply:${actorUrl}:${inReplyTo}`,
|
|
434
|
+
url: object.url?.href || object.id?.href || "",
|
|
434
435
|
type: "reply",
|
|
435
436
|
actorUrl: actorInfo.url,
|
|
436
437
|
actorName: actorInfo.name,
|
|
@@ -462,6 +463,7 @@ export function registerInboxListeners(inboxChain, options) {
|
|
|
462
463
|
|
|
463
464
|
await addNotification(collections, {
|
|
464
465
|
uid: object.id?.href || `mention:${actorUrl}:${object.id?.href}`,
|
|
466
|
+
url: object.url?.href || object.id?.href || "",
|
|
465
467
|
type: "mention",
|
|
466
468
|
actorUrl: actorInfo.url,
|
|
467
469
|
actorName: actorInfo.name,
|
package/lib/jf2-to-as2.js
CHANGED
|
@@ -20,6 +20,22 @@ import {
|
|
|
20
20
|
Video,
|
|
21
21
|
} from "@fedify/fedify/vocab";
|
|
22
22
|
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
// Content helpers
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Convert bare URLs in HTML content to clickable links.
|
|
29
|
+
* Skips URLs already inside href attributes or anchor tag text.
|
|
30
|
+
*/
|
|
31
|
+
function linkifyUrls(html) {
|
|
32
|
+
if (!html) return html;
|
|
33
|
+
return html.replace(
|
|
34
|
+
/(?<![=">])(https?:\/\/[^\s<"]+)/g,
|
|
35
|
+
'<a href="$1">$1</a>',
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
23
39
|
// ---------------------------------------------------------------------------
|
|
24
40
|
// Plain JSON-LD (content negotiation on individual post URLs)
|
|
25
41
|
// ---------------------------------------------------------------------------
|
|
@@ -68,7 +84,7 @@ export function jf2ToActivityStreams(properties, actorUrl, publicationUrl) {
|
|
|
68
84
|
|
|
69
85
|
if (postType === "bookmark") {
|
|
70
86
|
const bookmarkUrl = properties["bookmark-of"];
|
|
71
|
-
const commentary = properties.content?.html || properties.content || "";
|
|
87
|
+
const commentary = linkifyUrls(properties.content?.html || properties.content || "");
|
|
72
88
|
object.content = commentary
|
|
73
89
|
? `${commentary}<br><br>\u{1F516} <a href="${bookmarkUrl}">${bookmarkUrl}</a>`
|
|
74
90
|
: `\u{1F516} <a href="${bookmarkUrl}">${bookmarkUrl}</a>`;
|
|
@@ -80,7 +96,7 @@ export function jf2ToActivityStreams(properties, actorUrl, publicationUrl) {
|
|
|
80
96
|
},
|
|
81
97
|
];
|
|
82
98
|
} else {
|
|
83
|
-
object.content = properties.content?.html || properties.content || "";
|
|
99
|
+
object.content = linkifyUrls(properties.content?.html || properties.content || "");
|
|
84
100
|
}
|
|
85
101
|
|
|
86
102
|
// Append permalink to content so fediverse clients show a clickable link
|
|
@@ -193,12 +209,12 @@ export function jf2ToAS2Activity(properties, actorUrl, publicationUrl, options =
|
|
|
193
209
|
// Content
|
|
194
210
|
if (postType === "bookmark") {
|
|
195
211
|
const bookmarkUrl = properties["bookmark-of"];
|
|
196
|
-
const commentary = properties.content?.html || properties.content || "";
|
|
212
|
+
const commentary = linkifyUrls(properties.content?.html || properties.content || "");
|
|
197
213
|
noteOptions.content = commentary
|
|
198
214
|
? `${commentary}<br><br>\u{1F516} <a href="${bookmarkUrl}">${bookmarkUrl}</a>`
|
|
199
215
|
: `\u{1F516} <a href="${bookmarkUrl}">${bookmarkUrl}</a>`;
|
|
200
216
|
} else {
|
|
201
|
-
noteOptions.content = properties.content?.html || properties.content || "";
|
|
217
|
+
noteOptions.content = linkifyUrls(properties.content?.html || properties.content || "");
|
|
202
218
|
}
|
|
203
219
|
|
|
204
220
|
// Append permalink to content so fediverse clients show a clickable link
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rmdes/indiekit-endpoint-activitypub",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.8.0",
|
|
4
4
|
"description": "ActivityPub federation endpoint for Indiekit via Fedify. Adds full fediverse support: actor, inbox, outbox, followers, following, syndication, and Mastodon migration.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"indiekit",
|
|
@@ -230,7 +230,7 @@
|
|
|
230
230
|
if (this.error) setTimeout(() => this.error = '', 3000);
|
|
231
231
|
}
|
|
232
232
|
}">
|
|
233
|
-
<a href="{{ mountPath }}/admin/reader/compose?replyTo={{ itemUid | urlencode }}"
|
|
233
|
+
<a href="{{ mountPath }}/admin/reader/compose?replyTo={{ (itemUrl or itemUid) | urlencode }}"
|
|
234
234
|
class="ap-card__action ap-card__action--reply"
|
|
235
235
|
title="{{ __('activitypub.reader.actions.reply') }}">
|
|
236
236
|
↩ {{ __("activitypub.reader.actions.reply") }}{% if replyCount != null %}<span class="ap-card__count">{{ replyCount }}</span>{% endif %}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
{% set displayCount = item.photo.length if item.photo.length < 4 else 4 %}
|
|
6
6
|
{% set extraCount = item.photo.length - 4 %}
|
|
7
7
|
{% set totalPhotos = item.photo.length %}
|
|
8
|
-
<div x-data="{ lightbox: false, idx: 0 }" class="ap-card__gallery ap-card__gallery--{{ displayCount }}">
|
|
8
|
+
<div x-data="{ lightbox: false, idx: 0, touchX: 0 }" class="ap-card__gallery ap-card__gallery--{{ displayCount }}">
|
|
9
9
|
{% for photo in item.photo %}
|
|
10
10
|
{# Support both old string format and new object format #}
|
|
11
11
|
{% set photoSrc = photo.url if photo.url else photo %}
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
|
|
37
37
|
{# Lightbox modal — teleported to body to prevent overflow clipping #}
|
|
38
38
|
<template x-teleport="body">
|
|
39
|
-
<div x-show="lightbox" x-cloak @keydown.escape.window="lightbox = false" @click.self="lightbox = false" class="ap-lightbox" role="dialog" aria-modal="true">
|
|
39
|
+
<div x-show="lightbox" x-cloak @keydown.escape.window="lightbox = false" @click.self="lightbox = false" @touchstart="touchX = $event.changedTouches[0].clientX" @touchend="let dx = $event.changedTouches[0].clientX - touchX; if (dx < -50) idx = (idx + 1) % {{ totalPhotos }}; else if (dx > 50) idx = (idx - 1 + {{ totalPhotos }}) % {{ totalPhotos }}" class="ap-lightbox" role="dialog" aria-modal="true">
|
|
40
40
|
<button type="button" @click="lightbox = false" class="ap-lightbox__close" aria-label="Close">×</button>
|
|
41
41
|
{% if totalPhotos > 1 %}
|
|
42
42
|
<button type="button" @click="idx = (idx - 1 + {{ totalPhotos }}) % {{ totalPhotos }}" class="ap-lightbox__prev" aria-label="Previous image">‹</button>
|
|
@@ -56,10 +56,10 @@
|
|
|
56
56
|
|
|
57
57
|
{% if item.type == "reply" or item.type == "mention" %}
|
|
58
58
|
<div class="ap-notification__actions">
|
|
59
|
-
<a href="{{ mountPath }}/admin/reader/compose?replyTo={{ item.uid | urlencode }}" class="ap-notification__reply-btn" title="{{ __('activitypub.reader.actions.reply') }}">
|
|
59
|
+
<a href="{{ mountPath }}/admin/reader/compose?replyTo={{ (item.url or item.uid) | urlencode }}" class="ap-notification__reply-btn" title="{{ __('activitypub.reader.actions.reply') }}">
|
|
60
60
|
↩ {{ __("activitypub.reader.actions.reply") }}
|
|
61
61
|
</a>
|
|
62
|
-
<a href="{{ mountPath }}/admin/reader/post?url={{ item.uid | urlencode }}" class="ap-notification__thread-btn" title="{{ __('activitypub.reader.post.title') }}">
|
|
62
|
+
<a href="{{ mountPath }}/admin/reader/post?url={{ (item.url or item.uid) | urlencode }}" class="ap-notification__thread-btn" title="{{ __('activitypub.reader.post.title') }}">
|
|
63
63
|
💬 {{ __("activitypub.notifications.viewThread") }}
|
|
64
64
|
</a>
|
|
65
65
|
</div>
|