@rmdes/indiekit-endpoint-activitypub 2.8.0 → 2.8.1

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.
@@ -15,8 +15,8 @@
15
15
  .ap-link-preview {
16
16
  display: flex;
17
17
  overflow: hidden;
18
- border-radius: 8px;
19
- border: 1px solid var(--color-outline);
18
+ border-radius: var(--border-radius-small);
19
+ border: var(--border-width-thin) solid var(--color-outline);
20
20
  background-color: var(--color-offset);
21
21
  text-decoration: none;
22
22
  color: inherit;
@@ -121,7 +121,7 @@
121
121
  letter-spacing: 0.05em;
122
122
  margin: var(--space-l) 0 var(--space-s);
123
123
  padding-bottom: var(--space-xs);
124
- border-bottom: 1px solid var(--color-outline);
124
+ border-bottom: var(--border-width-thin) solid var(--color-outline);
125
125
  }
126
126
 
127
127
  .ap-post-detail__main {
package/assets/reader.css CHANGED
@@ -32,7 +32,7 @@
32
32
 
33
33
  .ap-breadcrumb__current {
34
34
  color: var(--color-on-background);
35
- font-weight: var(--font-weight-bold);
35
+ font-weight: 600;
36
36
  }
37
37
 
38
38
  /* ==========================================================================
@@ -151,10 +151,10 @@
151
151
  background: var(--color-offset);
152
152
  border: var(--border-width-thin) solid var(--color-outline);
153
153
  border-left: 3px solid var(--color-outline);
154
- border-radius: 8px;
154
+ border-radius: var(--border-radius-small);
155
155
  overflow: hidden;
156
156
  padding: var(--space-m);
157
- box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
157
+ box-shadow: 0 1px 2px hsl(var(--tint-neutral) 10% / 0.04);
158
158
  transition:
159
159
  box-shadow 0.2s ease,
160
160
  border-color 0.2s ease;
@@ -163,7 +163,7 @@
163
163
  .ap-card:hover {
164
164
  border-color: var(--color-outline-variant);
165
165
  border-left-color: var(--color-outline-variant);
166
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
166
+ box-shadow: 0 2px 8px hsl(var(--tint-neutral) 10% / 0.08);
167
167
  }
168
168
 
169
169
  /* ==========================================================================
@@ -261,15 +261,27 @@
261
261
  margin-bottom: var(--space-s);
262
262
  }
263
263
 
264
+ .ap-card__avatar-wrap {
265
+ flex-shrink: 0;
266
+ height: 44px;
267
+ position: relative;
268
+ width: 44px;
269
+ }
270
+
264
271
  .ap-card__avatar {
265
272
  border: var(--border-width-thin) solid var(--color-outline);
266
273
  border-radius: 50%;
267
- flex-shrink: 0;
268
274
  height: 44px;
269
275
  object-fit: cover;
270
276
  width: 44px;
271
277
  }
272
278
 
279
+ .ap-card__avatar-wrap > img {
280
+ position: absolute;
281
+ inset: 0;
282
+ z-index: 1;
283
+ }
284
+
273
285
  .ap-card__avatar--default {
274
286
  align-items: center;
275
287
  background: var(--color-offset-variant);
@@ -411,7 +423,7 @@
411
423
 
412
424
  .ap-card__content code {
413
425
  background: var(--color-offset-variant);
414
- border-radius: 3px;
426
+ border-radius: var(--border-radius-small);
415
427
  font-size: 0.9em;
416
428
  padding: 1px 4px;
417
429
  }
@@ -508,7 +520,7 @@
508
520
  ========================================================================== */
509
521
 
510
522
  .ap-card__gallery {
511
- border-radius: 6px;
523
+ border-radius: var(--border-radius-small);
512
524
  display: grid;
513
525
  gap: 2px;
514
526
  margin-bottom: var(--space-s);
@@ -607,7 +619,7 @@
607
619
 
608
620
  .ap-lightbox {
609
621
  align-items: center;
610
- background: rgba(0, 0, 0, 0.92);
622
+ background: hsl(var(--tint-neutral) 10% / 0.92);
611
623
  display: flex;
612
624
  inset: 0;
613
625
  justify-content: center;
@@ -707,7 +719,7 @@
707
719
  }
708
720
 
709
721
  .ap-link-preview__title {
710
- font-weight: var(--font-weight-bold);
722
+ font-weight: 600;
711
723
  font-size: var(--font-size-s);
712
724
  margin: 0;
713
725
  overflow: hidden;
@@ -861,7 +873,7 @@
861
873
  align-items: center;
862
874
  background: transparent;
863
875
  border: 0;
864
- border-radius: 6px;
876
+ border-radius: var(--border-radius-small);
865
877
  color: var(--color-on-offset);
866
878
  cursor: pointer;
867
879
  display: inline-flex;
@@ -1188,6 +1200,11 @@
1188
1200
  position: relative;
1189
1201
  }
1190
1202
 
1203
+ .ap-notification__avatar-wrap {
1204
+ height: 40px;
1205
+ width: 40px;
1206
+ }
1207
+
1191
1208
  .ap-notification__avatar {
1192
1209
  border: var(--border-width-thin) solid var(--color-outline);
1193
1210
  border-radius: 50%;
@@ -1196,6 +1213,12 @@
1196
1213
  width: 40px;
1197
1214
  }
1198
1215
 
1216
+ .ap-notification__avatar-wrap > img {
1217
+ position: absolute;
1218
+ inset: 0;
1219
+ z-index: 1;
1220
+ }
1221
+
1199
1222
  .ap-notification__avatar--default {
1200
1223
  align-items: center;
1201
1224
  background: var(--color-offset-variant);
@@ -1319,7 +1342,16 @@
1319
1342
  }
1320
1343
 
1321
1344
  .ap-profile__avatar-wrap {
1345
+ height: 80px;
1322
1346
  margin-bottom: var(--space-s);
1347
+ position: relative;
1348
+ width: 80px;
1349
+ }
1350
+
1351
+ .ap-profile__avatar-wrap > img {
1352
+ position: absolute;
1353
+ inset: 0;
1354
+ z-index: 1;
1323
1355
  }
1324
1356
 
1325
1357
  .ap-profile__avatar {
@@ -1901,7 +1933,7 @@
1901
1933
 
1902
1934
  .ap-tag-header__title {
1903
1935
  font-size: var(--font-size-xl);
1904
- font-weight: var(--font-weight-bold);
1936
+ font-weight: 600;
1905
1937
  margin: 0 0 var(--space-xs);
1906
1938
  }
1907
1939
 
@@ -2028,7 +2060,7 @@
2028
2060
  border: var(--border-width-thin) solid var(--color-outline);
2029
2061
  border-radius: var(--border-radius-small);
2030
2062
  box-sizing: border-box;
2031
- font-size: var(--font-size-base);
2063
+ font-size: var(--font-size-m);
2032
2064
  min-width: 0;
2033
2065
  padding: var(--space-xs) var(--space-s);
2034
2066
  width: 100%;
@@ -2094,7 +2126,7 @@
2094
2126
  background: var(--color-background);
2095
2127
  border: var(--border-width-thin) solid var(--color-outline);
2096
2128
  border-radius: var(--border-radius-small);
2097
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
2129
+ box-shadow: 0 4px 12px hsl(var(--tint-neutral) 10% / 0.15);
2098
2130
  left: 0;
2099
2131
  max-height: 320px;
2100
2132
  overflow-y: auto;
@@ -2171,7 +2203,7 @@
2171
2203
  background: var(--color-background);
2172
2204
  border: var(--border-width-thin) solid var(--color-outline);
2173
2205
  border-radius: var(--border-radius-small);
2174
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
2206
+ box-shadow: 0 4px 12px hsl(var(--tint-neutral) 10% / 0.15);
2175
2207
  left: 0;
2176
2208
  max-height: 320px;
2177
2209
  overflow-y: auto;
@@ -2281,7 +2313,7 @@
2281
2313
  }
2282
2314
 
2283
2315
  .ap-explore-tabs-nav::after {
2284
- background: linear-gradient(to right, transparent, var(--color-background, #fff) 80%);
2316
+ background: linear-gradient(to right, transparent, var(--color-background) 80%);
2285
2317
  content: "";
2286
2318
  height: 100%;
2287
2319
  pointer-events: none;
@@ -2350,7 +2382,7 @@
2350
2382
 
2351
2383
  /* Scope badges on instance tabs */
2352
2384
  .ap-tab__badge {
2353
- border-radius: 3px;
2385
+ border-radius: var(--border-radius-small);
2354
2386
  font-size: 0.65em;
2355
2387
  font-weight: 700;
2356
2388
  letter-spacing: 0.02em;
@@ -2522,7 +2554,7 @@
2522
2554
 
2523
2555
  .ap-explore-tab-error__retry {
2524
2556
  background: none;
2525
- border: 1px solid var(--color-primary-on-background);
2557
+ border: var(--border-width-thin) solid var(--color-primary-on-background);
2526
2558
  border-radius: var(--border-radius-small);
2527
2559
  color: var(--color-primary-on-background);
2528
2560
  cursor: pointer;
@@ -2602,7 +2634,7 @@
2602
2634
 
2603
2635
  .ap-unread-toggle--active {
2604
2636
  background: color-mix(in srgb, var(--color-primary) 12%, transparent);
2605
- font-weight: var(--font-weight-bold);
2637
+ font-weight: 600;
2606
2638
  }
2607
2639
 
2608
2640
  /* ==========================================================================
@@ -2611,7 +2643,7 @@
2611
2643
 
2612
2644
  .ap-quote-embed {
2613
2645
  border: var(--border-width-thin) solid var(--color-outline);
2614
- border-radius: 8px;
2646
+ border-radius: var(--border-radius-small);
2615
2647
  margin-top: var(--space-s);
2616
2648
  overflow: hidden;
2617
2649
  transition: border-color 0.15s ease;
@@ -2657,7 +2689,7 @@
2657
2689
  color: var(--color-on-offset);
2658
2690
  display: inline-flex;
2659
2691
  font-size: var(--font-size-xs);
2660
- font-weight: var(--font-weight-bold);
2692
+ font-weight: 600;
2661
2693
  justify-content: center;
2662
2694
  }
2663
2695
 
@@ -2668,7 +2700,7 @@
2668
2700
 
2669
2701
  .ap-quote-embed__name {
2670
2702
  font-size: var(--font-size-s);
2671
- font-weight: var(--font-weight-bold);
2703
+ font-weight: 600;
2672
2704
  overflow: hidden;
2673
2705
  text-overflow: ellipsis;
2674
2706
  white-space: nowrap;
@@ -2691,7 +2723,7 @@
2691
2723
 
2692
2724
  .ap-quote-embed__title {
2693
2725
  font-size: var(--font-size-s);
2694
- font-weight: var(--font-weight-bold);
2726
+ font-weight: 600;
2695
2727
  margin: 0 0 var(--space-xs);
2696
2728
  }
2697
2729
 
@@ -2757,8 +2789,8 @@
2757
2789
  position: absolute;
2758
2790
  bottom: 0.5rem;
2759
2791
  left: 0.5rem;
2760
- background: rgba(0, 0, 0, 0.7);
2761
- color: white;
2792
+ background: hsl(var(--tint-neutral) 10% / 0.7);
2793
+ color: var(--color-neutral99);
2762
2794
  font-size: 0.65rem;
2763
2795
  font-weight: 700;
2764
2796
  padding: 0.15rem 0.35rem;
@@ -2771,7 +2803,7 @@
2771
2803
  }
2772
2804
 
2773
2805
  .ap-media__alt-badge:hover {
2774
- background: rgba(0, 0, 0, 0.9);
2806
+ background: hsl(var(--tint-neutral) 10% / 0.9);
2775
2807
  }
2776
2808
 
2777
2809
  .ap-media__alt-text {
@@ -2779,8 +2811,8 @@
2779
2811
  bottom: 2.2rem;
2780
2812
  left: 0.5rem;
2781
2813
  right: 0.5rem;
2782
- background: rgba(0, 0, 0, 0.85);
2783
- color: white;
2814
+ background: hsl(var(--tint-neutral) 10% / 0.85);
2815
+ color: var(--color-neutral99);
2784
2816
  font-size: var(--font-size-s);
2785
2817
  padding: 0.5rem;
2786
2818
  border-radius: var(--border-radius-small);
@@ -2870,11 +2902,11 @@
2870
2902
 
2871
2903
  /* --- Card shadows: use light tint instead of black --- */
2872
2904
  .ap-card {
2873
- box-shadow: 0 1px 2px rgba(255, 255, 255, 0.04);
2905
+ box-shadow: 0 1px 2px hsl(var(--tint-neutral) 90% / 0.04);
2874
2906
  }
2875
2907
 
2876
2908
  .ap-card:hover {
2877
- box-shadow: 0 2px 8px rgba(255, 255, 255, 0.06);
2909
+ box-shadow: 0 2px 8px hsl(var(--tint-neutral) 90% / 0.06);
2878
2910
  }
2879
2911
 
2880
2912
  /* --- Tab badge federated: soften purple --- */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rmdes/indiekit-endpoint-activitypub",
3
- "version": "2.8.0",
3
+ "version": "2.8.1",
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",
@@ -91,7 +91,7 @@
91
91
  <label class="label" for="link_value_{{ loop.index }}">{{ __("activitypub.profile.linkValueLabel") }}</label>
92
92
  <input class="input" type="url" id="link_value_{{ loop.index }}" name="link_value[]" value="{{ att.value }}" placeholder="https://example.com">
93
93
  </div>
94
- <button type="button" class="button button--small" onclick="this.closest('.profile-link-row').remove()" style="margin-block-end: 4px;">{{ __("activitypub.profile.removeLink") }}</button>
94
+ <button type="button" class="button button--small profile-link-remove" style="margin-block-end: 4px;">{{ __("activitypub.profile.removeLink") }}</button>
95
95
  </div>
96
96
  {% endfor %}
97
97
  {% endif %}
@@ -129,6 +129,11 @@
129
129
 
130
130
  <script>
131
131
  (function() {
132
+ document.getElementById('profile-links').addEventListener('click', function(e) {
133
+ var btn = e.target.closest('.profile-link-remove');
134
+ if (btn) btn.closest('.profile-link-row').remove();
135
+ });
136
+
132
137
  var linkCount = {{ (profile.attachments.length if profile.attachments) or 0 }};
133
138
  document.getElementById('add-link-btn').addEventListener('click', function() {
134
139
  linkCount++;
@@ -167,10 +172,9 @@
167
172
 
168
173
  var removeBtn = document.createElement('button');
169
174
  removeBtn.type = 'button';
170
- removeBtn.className = 'button button--small';
175
+ removeBtn.className = 'button button--small profile-link-remove';
171
176
  removeBtn.style.cssText = 'margin-block-end: 4px;';
172
177
  removeBtn.textContent = 'Remove';
173
- removeBtn.addEventListener('click', function() { row.remove(); });
174
178
 
175
179
  row.appendChild(nameDiv);
176
180
  row.appendChild(valueDiv);
@@ -47,8 +47,7 @@
47
47
  :class="{ 'ap-lookup-autocomplete__item--highlighted': index === highlighted }"
48
48
  @click="selectItem(item)"
49
49
  @mouseenter="highlighted = index">
50
- <img :src="item.avatar" :alt="item.name" class="ap-lookup-autocomplete__avatar"
51
- onerror="this.style.display='none'">
50
+ <img :src="item.avatar" :alt="item.name" class="ap-lookup-autocomplete__avatar">
52
51
  <span class="ap-lookup-autocomplete__info">
53
52
  <span class="ap-lookup-autocomplete__name" x-text="item.name"></span>
54
53
  <span class="ap-lookup-autocomplete__handle" x-text="item.handle"></span>
@@ -38,13 +38,11 @@
38
38
 
39
39
  {# Profile info #}
40
40
  <div class="ap-profile__info">
41
- <div class="ap-profile__avatar-wrap">
41
+ <div class="ap-profile__avatar-wrap" data-avatar-fallback>
42
42
  {% if icon %}
43
- <img src="{{ icon }}" alt="{{ name }}" class="ap-profile__avatar"
44
- onerror="this.replaceWith(Object.assign(document.createElement('div'),{className:'ap-profile__avatar ap-profile__avatar--placeholder',textContent:'{{ name[0] }}'}))">
45
- {% else %}
46
- <div class="ap-profile__avatar ap-profile__avatar--placeholder">{{ name[0] }}</div>
43
+ <img src="{{ icon }}" alt="{{ name }}" class="ap-profile__avatar">
47
44
  {% endif %}
45
+ <div class="ap-profile__avatar ap-profile__avatar--placeholder">{{ name[0] }}</div>
48
46
  </div>
49
47
 
50
48
  <div class="ap-profile__details">
@@ -10,8 +10,10 @@
10
10
  {# Relative timestamps — converts absolute dates to "5m", "3h", "2d" etc. #}
11
11
  <script defer src="/assets/@rmdes-indiekit-endpoint-activitypub/reader-relative-time.js"></script>
12
12
 
13
- {# Alpine.js for client-side reactivity (CW toggles, interaction buttons, infinite scroll) #}
14
- <script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.14.9/dist/cdn.min.js"></script>
13
+ {# Avatar fallback remove broken images to reveal initials fallback underneath #}
14
+ <script>document.addEventListener("error",function(e){var t=e.target;if(t.tagName==="IMG"&&t.closest("[data-avatar-fallback]"))t.remove()},true)</script>
15
+
16
+ {# Alpine.js loaded by default.njk — AP scripts register via alpine:init before it initializes #}
15
17
 
16
18
  {# Reader stylesheet — loaded in body is fine for modern browsers #}
17
19
  <link rel="stylesheet" href="/assets/@rmdes-indiekit-endpoint-activitypub/reader.css">
@@ -39,13 +39,12 @@
39
39
 
40
40
  {# Author header #}
41
41
  <header class="ap-card__author">
42
- {% if item.author.photo %}
43
- <img src="{{ item.author.photo }}" alt="{{ item.author.name }}" class="ap-card__avatar" loading="lazy" crossorigin="anonymous"
44
- onerror="this.style.display='none';this.nextElementSibling.style.display=''">
45
- <span class="ap-card__avatar ap-card__avatar--default" style="display:none" aria-hidden="true">{{ item.author.name[0] | upper if item.author.name else "?" }}</span>
46
- {% else %}
42
+ <div class="ap-card__avatar-wrap" data-avatar-fallback>
43
+ {% if item.author.photo %}
44
+ <img src="{{ item.author.photo }}" alt="{{ item.author.name }}" class="ap-card__avatar" loading="lazy" crossorigin="anonymous">
45
+ {% endif %}
47
46
  <span class="ap-card__avatar ap-card__avatar--default" aria-hidden="true">{{ item.author.name[0] | upper if item.author.name else "?" }}</span>
48
- {% endif %}
47
+ </div>
49
48
  <div class="ap-card__author-info">
50
49
  <div class="ap-card__author-name">
51
50
  {% if item.author.url %}
@@ -9,14 +9,11 @@
9
9
  </form>
10
10
 
11
11
  {# Actor avatar with type badge #}
12
- <div class="ap-notification__avatar-wrap">
12
+ <div class="ap-notification__avatar-wrap" data-avatar-fallback>
13
13
  {% if item.actorPhoto %}
14
- <img src="{{ item.actorPhoto }}" alt="{{ item.actorName }}" class="ap-notification__avatar" loading="lazy" crossorigin="anonymous"
15
- onerror="this.style.display='none';this.nextElementSibling.style.display=''">
16
- <span class="ap-notification__avatar ap-notification__avatar--default" style="display:none" aria-hidden="true">{{ item.actorName[0] | upper if item.actorName else "?" }}</span>
17
- {% else %}
18
- <span class="ap-notification__avatar ap-notification__avatar--default" aria-hidden="true">{{ item.actorName[0] | upper if item.actorName else "?" }}</span>
14
+ <img src="{{ item.actorPhoto }}" alt="{{ item.actorName }}" class="ap-notification__avatar" loading="lazy" crossorigin="anonymous">
19
15
  {% endif %}
16
+ <span class="ap-notification__avatar ap-notification__avatar--default" aria-hidden="true">{{ item.actorName[0] | upper if item.actorName else "?" }}</span>
20
17
  <span class="ap-notification__type-badge">
21
18
  {% if item.type == "like" %}❤{% elif item.type == "boost" %}🔁{% elif item.type == "follow" %}👤{% elif item.type == "reply" %}💬{% elif item.type == "mention" %}@{% endif %}
22
19
  </span>