@rmdes/indiekit-endpoint-microsub 1.0.47 → 1.0.49

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/styles.css CHANGED
@@ -154,15 +154,40 @@
154
154
  margin-bottom: var(--space-s);
155
155
  }
156
156
 
157
+ .ms-item-card__avatar-wrap {
158
+ flex-shrink: 0;
159
+ height: 40px;
160
+ position: relative;
161
+ width: 40px;
162
+ }
163
+
164
+ .ms-item-card__avatar-wrap > img {
165
+ position: absolute;
166
+ inset: 0;
167
+ z-index: 1;
168
+ }
169
+
157
170
  .ms-item-card__author-photo {
158
171
  border: var(--border-width-thin) solid var(--color-offset);
159
172
  border-radius: 50%;
160
- flex-shrink: 0;
161
173
  height: 40px;
162
174
  object-fit: cover;
163
175
  width: 40px;
164
176
  }
165
177
 
178
+ .ms-item-card__author-photo--default {
179
+ align-items: center;
180
+ background: var(--color-offset);
181
+ border-radius: 50%;
182
+ color: var(--color-on-offset);
183
+ display: flex;
184
+ font-size: var(--font-size-s);
185
+ font-weight: 600;
186
+ height: 40px;
187
+ justify-content: center;
188
+ width: 40px;
189
+ }
190
+
166
191
  .ms-item-card__author-info {
167
192
  display: flex;
168
193
  flex-direction: column;
@@ -496,6 +521,19 @@
496
521
  margin-bottom: var(--space-m);
497
522
  }
498
523
 
524
+ .ms-item__avatar-wrap {
525
+ flex-shrink: 0;
526
+ height: 48px;
527
+ position: relative;
528
+ width: 48px;
529
+ }
530
+
531
+ .ms-item__avatar-wrap > img {
532
+ position: absolute;
533
+ inset: 0;
534
+ z-index: 1;
535
+ }
536
+
499
537
  .ms-item__author-photo {
500
538
  border-radius: 50%;
501
539
  height: 48px;
@@ -503,6 +541,19 @@
503
541
  width: 48px;
504
542
  }
505
543
 
544
+ .ms-item__author-photo--default {
545
+ align-items: center;
546
+ background: var(--color-offset);
547
+ border-radius: 50%;
548
+ color: var(--color-on-offset);
549
+ display: flex;
550
+ font-size: var(--font-size-m);
551
+ font-weight: 600;
552
+ height: 48px;
553
+ justify-content: center;
554
+ width: 48px;
555
+ }
556
+
506
557
  .ms-item__author-info {
507
558
  display: flex;
508
559
  flex-direction: column;
@@ -1010,12 +1061,37 @@
1010
1061
  gap: var(--space-m);
1011
1062
  }
1012
1063
 
1064
+ .ms-actor-profile__avatar-wrap {
1065
+ flex-shrink: 0;
1066
+ height: 80px;
1067
+ position: relative;
1068
+ width: 80px;
1069
+ }
1070
+
1071
+ .ms-actor-profile__avatar-wrap > img {
1072
+ position: absolute;
1073
+ inset: 0;
1074
+ z-index: 1;
1075
+ }
1076
+
1013
1077
  .ms-actor-profile__avatar {
1014
1078
  border-radius: 50%;
1015
- flex-shrink: 0;
1016
1079
  object-fit: cover;
1017
1080
  }
1018
1081
 
1082
+ .ms-actor-profile__avatar--default {
1083
+ align-items: center;
1084
+ background: var(--color-offset);
1085
+ border-radius: 50%;
1086
+ color: var(--color-on-offset);
1087
+ display: flex;
1088
+ font-size: var(--font-size-xl);
1089
+ font-weight: 600;
1090
+ height: 80px;
1091
+ justify-content: center;
1092
+ width: 80px;
1093
+ }
1094
+
1019
1095
  .ms-actor-profile__info {
1020
1096
  flex: 1;
1021
1097
  min-width: 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rmdes/indiekit-endpoint-microsub",
3
- "version": "1.0.47",
3
+ "version": "1.0.49",
4
4
  "description": "Microsub endpoint for Indiekit. Enables subscribing to feeds and reading content using the Microsub protocol.",
5
5
  "keywords": [
6
6
  "indiekit",
package/views/actor.njk CHANGED
@@ -11,13 +11,16 @@
11
11
  {# Actor profile card #}
12
12
  <div class="ms-actor-profile">
13
13
  <div class="ms-actor-profile__header">
14
- {% if actor.photo %}
15
- <img src="{{ actor.photo }}"
16
- alt=""
17
- class="ms-actor-profile__avatar"
18
- width="80"
19
- height="80">
20
- {% endif %}
14
+ <div class="ms-actor-profile__avatar-wrap" data-avatar-fallback>
15
+ {% if actor.photo %}
16
+ <img src="{{ actor.photo }}"
17
+ alt=""
18
+ class="ms-actor-profile__avatar"
19
+ width="80"
20
+ height="80">
21
+ {% endif %}
22
+ <span class="ms-actor-profile__avatar ms-actor-profile__avatar--default" aria-hidden="true">{{ actor.name[0] | upper if actor.name else "?" }}</span>
23
+ </div>
21
24
  <div class="ms-actor-profile__info">
22
25
  <h2 class="ms-actor-profile__name">{{ actor.name }}</h2>
23
26
  {% if actor.handle %}
@@ -38,14 +41,14 @@
38
41
  </div>
39
42
  <div class="ms-actor-profile__actions">
40
43
  <a href="{{ actor.url }}" class="button button--secondary button--small" target="_blank" rel="noopener">
41
- {{ icon("external") }} View profile
44
+ {{ icon("syndicate") }} View profile
42
45
  </a>
43
46
  {% if canFollow %}
44
47
  {% if isFollowing %}
45
48
  <form action="{{ baseUrl }}/actor/unfollow" method="POST" style="display: inline;">
46
49
  <input type="hidden" name="actorUrl" value="{{ actorUrl }}">
47
50
  <button type="submit" class="button button--secondary button--small">
48
- {{ icon("checkboxChecked") }} Following
51
+ {{ icon("tick") }} Following
49
52
  </button>
50
53
  </form>
51
54
  {% else %}
@@ -73,14 +76,17 @@
73
76
  {# Author #}
74
77
  {% if item.author %}
75
78
  <div class="ms-item-card__author" style="padding: 12px 16px 0;">
76
- {% if item.author.photo %}
77
- <img src="{{ item.author.photo }}"
78
- alt=""
79
- class="ms-item-card__author-photo"
80
- width="40"
81
- height="40"
82
- loading="lazy">
83
- {% endif %}
79
+ <div class="ms-item-card__avatar-wrap" data-avatar-fallback>
80
+ {% if item.author.photo %}
81
+ <img src="{{ item.author.photo }}"
82
+ alt=""
83
+ class="ms-item-card__author-photo"
84
+ width="40"
85
+ height="40"
86
+ loading="lazy">
87
+ {% endif %}
88
+ <span class="ms-item-card__author-photo ms-item-card__author-photo--default" aria-hidden="true">{{ item.author.name[0] | upper if item.author.name else "?" }}</span>
89
+ </div>
84
90
  <div class="ms-item-card__author-info">
85
91
  <span class="ms-item-card__author-name">{{ item.author.name or "Unknown" }}</span>
86
92
  {% if item.author.url %}
@@ -152,7 +158,7 @@
152
158
  {# Actions #}
153
159
  <div class="ms-item-actions">
154
160
  <a href="{{ item.url }}" class="ms-item-actions__button" target="_blank" rel="noopener" title="View original">
155
- {{ icon("external") }}
161
+ {{ icon("syndicate") }}
156
162
  </a>
157
163
  <a href="{{ baseUrl }}/compose?reply={{ item.url | urlencode }}" class="ms-item-actions__button" title="Reply">
158
164
  {{ icon("reply") }}
package/views/channel.njk CHANGED
@@ -10,7 +10,7 @@
10
10
  <input type="hidden" name="channel" value="{{ channel.uid }}">
11
11
  <input type="hidden" name="entry" value="last-read-entry">
12
12
  <button type="submit" class="button button--secondary button--small">
13
- {{ icon("checkboxChecked") }} {{ __("microsub.reader.markAllRead") }}
13
+ {{ icon("tick") }} {{ __("microsub.reader.markAllRead") }}
14
14
  </button>
15
15
  </form>
16
16
  {% endif %}
@@ -58,7 +58,7 @@
58
58
  {% else %}
59
59
  <div class="ms-reader__empty">
60
60
  {% if readCount > 0 and not showRead %}
61
- {{ icon("checkboxChecked") }}
61
+ {{ icon("tick") }}
62
62
  <p>{{ __("microsub.reader.allRead") }}</p>
63
63
  <a href="{{ baseUrl }}/channels/{{ channel.uid }}?showRead=true" class="button button--secondary">
64
64
  {{ icon("show") }} {{ __("microsub.reader.showRead", { count: readCount }) }}
package/views/item.njk CHANGED
@@ -8,14 +8,17 @@
8
8
 
9
9
  {% if item.author %}
10
10
  <header class="ms-item__author">
11
- {% if item.author.photo %}
12
- <img src="{{ item.author.photo }}"
13
- alt=""
14
- class="ms-item__author-photo"
15
- width="48"
16
- height="48"
17
- loading="lazy">
18
- {% endif %}
11
+ <div class="ms-item__avatar-wrap" data-avatar-fallback>
12
+ {% if item.author.photo %}
13
+ <img src="{{ item.author.photo }}"
14
+ alt=""
15
+ class="ms-item__author-photo"
16
+ width="48"
17
+ height="48"
18
+ loading="lazy">
19
+ {% endif %}
20
+ <span class="ms-item__author-photo ms-item__author-photo--default" aria-hidden="true">{{ item.author.name[0] | upper if item.author.name else "?" }}</span>
21
+ </div>
19
22
  <div class="ms-item__author-info">
20
23
  <span class="ms-item__author-name">
21
24
  {% if item.author.url %}
@@ -130,7 +133,7 @@
130
133
  <footer class="ms-item__actions">
131
134
  {% if item.url %}
132
135
  <a href="{{ item.url }}" class="button button--secondary button--small" target="_blank" rel="noopener">
133
- {{ icon("external") }} {{ __("microsub.item.viewOriginal") }}
136
+ {{ icon("syndicate") }} {{ __("microsub.item.viewOriginal") }}
134
137
  </a>
135
138
  {% endif %}
136
139
  <a href="{{ baseUrl }}/compose?reply={{ item.url | urlencode }}" class="button button--secondary button--small">
@@ -150,7 +153,7 @@
150
153
  class="button button--secondary button--small ms-item__mark-read"
151
154
  data-item-id="{{ item._id }}"
152
155
  data-channel="{{ channel.uid }}">
153
- {{ icon("checkboxChecked") }} {{ __("microsub.timeline.markRead") }}
156
+ {{ icon("tick") }} {{ __("microsub.timeline.markRead") }}
154
157
  </button>
155
158
  {% endif %}
156
159
  </footer>
@@ -9,4 +9,6 @@
9
9
  {% include "partials/breadcrumbs.njk" %}
10
10
  {% include "partials/view-switcher.njk" %}
11
11
  {% block reader %}{% endblock %}
12
+ {# Avatar fallback — remove broken images to reveal initials fallback underneath #}
13
+ <script>document.addEventListener("error",function(e){var t=e.target;if(t.tagName==="IMG"&&t.closest("[data-avatar-fallback]"))t.remove()},true)</script>
12
14
  {% endblock %}
@@ -1,9 +1,12 @@
1
1
  {# Author display #}
2
2
  {% if author %}
3
3
  <div class="author">
4
- {% if author.photo %}
5
- <img src="{{ author.photo }}" alt="" class="author__photo" width="48" height="48" loading="lazy">
6
- {% endif %}
4
+ <div class="ms-item__avatar-wrap" data-avatar-fallback>
5
+ {% if author.photo %}
6
+ <img src="{{ author.photo }}" alt="" class="author__photo" width="48" height="48" loading="lazy">
7
+ {% endif %}
8
+ <span class="ms-item__author-photo ms-item__author-photo--default" aria-hidden="true">{{ author.name[0] | upper if author.name else "?" }}</span>
9
+ </div>
7
10
  <div class="author__info">
8
11
  <span class="author__name">
9
12
  {% if author.url %}
@@ -53,14 +53,17 @@
53
53
  {# Author #}
54
54
  {% if item.author %}
55
55
  <div class="ms-item-card__author">
56
- {% if item.author.photo %}
57
- <img src="{{ item.author.photo }}"
58
- alt=""
59
- class="ms-item-card__author-photo"
60
- width="40"
61
- height="40"
62
- loading="lazy">
63
- {% endif %}
56
+ <div class="ms-item-card__avatar-wrap" data-avatar-fallback>
57
+ {% if item.author.photo %}
58
+ <img src="{{ item.author.photo }}"
59
+ alt=""
60
+ class="ms-item-card__author-photo"
61
+ width="40"
62
+ height="40"
63
+ loading="lazy">
64
+ {% endif %}
65
+ <span class="ms-item-card__author-photo ms-item-card__author-photo--default" aria-hidden="true">{{ item.author.name[0] | upper if item.author.name else "?" }}</span>
66
+ </div>
64
67
  <div class="ms-item-card__author-info">
65
68
  <span class="ms-item-card__author-name">{{ item.author.name or "Unknown" }}</span>
66
69
  {% if item._source %}
@@ -158,7 +161,7 @@
158
161
  {% endif %}
159
162
  {% if item.url %}
160
163
  <a href="{{ item.url }}" class="ms-item-actions__button" target="_blank" rel="noopener" title="View original">
161
- {{ icon("external") }}
164
+ {{ icon("syndicate") }}
162
165
  <span class="-!-visually-hidden">Original</span>
163
166
  </a>
164
167
  {% endif %}
@@ -188,7 +191,7 @@
188
191
  {% if item._channelUid %}data-channel-uid="{{ item._channelUid }}"{% endif %}
189
192
  {% if item._channelId %}data-channel-id="{{ item._channelId }}"{% endif %}
190
193
  title="Mark as read">
191
- {{ icon("checkboxChecked") }}
194
+ {{ icon("tick") }}
192
195
  <span class="-!-visually-hidden">Mark read</span>
193
196
  </button>
194
197
  <button type="button"
@@ -213,7 +216,7 @@
213
216
  {% if item._channelUid %}data-channel-uid="{{ item._channelUid }}"{% endif %}
214
217
  {% if item._channelId %}data-channel-id="{{ item._channelId }}"{% endif %}
215
218
  title="Mark as read">
216
- {{ icon("checkboxChecked") }}
219
+ {{ icon("tick") }}
217
220
  <span class="-!-visually-hidden">Mark read</span>
218
221
  </button>
219
222
  {% endif %}