@rmdes/indiekit-endpoint-microsub 1.0.45 → 1.0.46

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rmdes/indiekit-endpoint-microsub",
3
- "version": "1.0.45",
3
+ "version": "1.0.46",
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
@@ -1,33 +1,32 @@
1
1
  {% extends "layouts/reader.njk" %}
2
2
 
3
3
  {% block reader %}
4
- <div class="channel">
5
- <header class="channel__header">
4
+ <div class="ms-channel">
5
+ <header class="ms-channel__header">
6
6
  <a href="{{ baseUrl }}/channels/activitypub" class="back-link">
7
7
  {{ icon("previous") }} Fediverse
8
8
  </a>
9
9
  </header>
10
10
 
11
11
  {# Actor profile card #}
12
- <div class="actor-profile">
13
- <div class="actor-profile__header">
12
+ <div class="ms-actor-profile">
13
+ <div class="ms-actor-profile__header">
14
14
  {% if actor.photo %}
15
15
  <img src="{{ actor.photo }}"
16
16
  alt=""
17
- class="actor-profile__avatar"
17
+ class="ms-actor-profile__avatar"
18
18
  width="80"
19
- height="80"
20
- onerror="this.style.display='none'">
19
+ height="80">
21
20
  {% endif %}
22
- <div class="actor-profile__info">
23
- <h2 class="actor-profile__name">{{ actor.name }}</h2>
21
+ <div class="ms-actor-profile__info">
22
+ <h2 class="ms-actor-profile__name">{{ actor.name }}</h2>
24
23
  {% if actor.handle %}
25
- <span class="actor-profile__handle">@{{ actor.handle }}</span>
24
+ <span class="ms-actor-profile__handle">@{{ actor.handle }}</span>
26
25
  {% endif %}
27
26
  {% if actor.summary %}
28
- <p class="actor-profile__summary">{{ actor.summary }}</p>
27
+ <p class="ms-actor-profile__summary">{{ actor.summary }}</p>
29
28
  {% endif %}
30
- <div class="actor-profile__stats">
29
+ <div class="ms-actor-profile__stats">
31
30
  {% if actor.followersCount %}
32
31
  <span>{{ actor.followersCount }} followers</span>
33
32
  {% endif %}
@@ -37,7 +36,7 @@
37
36
  </div>
38
37
  </div>
39
38
  </div>
40
- <div class="actor-profile__actions">
39
+ <div class="ms-actor-profile__actions">
41
40
  <a href="{{ actor.url }}" class="button button--secondary button--small" target="_blank" rel="noopener">
42
41
  {{ icon("external") }} View profile
43
42
  </a>
@@ -63,39 +62,38 @@
63
62
  </div>
64
63
 
65
64
  {% if error %}
66
- <div class="reader__empty">
65
+ <div class="ms-reader__empty">
67
66
  {{ icon("warning") }}
68
67
  <p>{{ error }}</p>
69
68
  </div>
70
69
  {% elif items.length > 0 %}
71
- <div class="timeline" id="timeline">
70
+ <div class="ms-timeline" id="timeline">
72
71
  {% for item in items %}
73
- <article class="item-card">
72
+ <article class="ms-item-card">
74
73
  {# Author #}
75
74
  {% if item.author %}
76
- <div class="item-card__author" style="padding: 12px 16px 0;">
75
+ <div class="ms-item-card__author" style="padding: 12px 16px 0;">
77
76
  {% if item.author.photo %}
78
77
  <img src="{{ item.author.photo }}"
79
78
  alt=""
80
- class="item-card__author-photo"
79
+ class="ms-item-card__author-photo"
81
80
  width="40"
82
81
  height="40"
83
- loading="lazy"
84
- onerror="this.style.display='none'">
82
+ loading="lazy">
85
83
  {% endif %}
86
- <div class="item-card__author-info">
87
- <span class="item-card__author-name">{{ item.author.name or "Unknown" }}</span>
84
+ <div class="ms-item-card__author-info">
85
+ <span class="ms-item-card__author-name">{{ item.author.name or "Unknown" }}</span>
88
86
  {% if item.author.url %}
89
- <span class="item-card__source">{{ item.author.url | replace("https://", "") | replace("http://", "") }}</span>
87
+ <span class="ms-item-card__source">{{ item.author.url | replace("https://", "") | replace("http://", "") }}</span>
90
88
  {% endif %}
91
89
  </div>
92
90
  </div>
93
91
  {% endif %}
94
92
 
95
- <a href="{{ item.url }}" class="item-card__link" target="_blank" rel="noopener">
93
+ <a href="{{ item.url }}" class="ms-item-card__link" target="_blank" rel="noopener">
96
94
  {# Reply context #}
97
95
  {% if item["in-reply-to"] and item["in-reply-to"].length > 0 %}
98
- <div class="item-card__context">
96
+ <div class="ms-item-card__context">
99
97
  {{ icon("reply") }}
100
98
  <span>Reply to</span>
101
99
  <span>{{ item["in-reply-to"][0] | replace("https://", "") | replace("http://", "") | truncate(50) }}</span>
@@ -104,12 +102,12 @@
104
102
 
105
103
  {# Title #}
106
104
  {% if item.name %}
107
- <h3 class="item-card__title">{{ item.name }}</h3>
105
+ <h3 class="ms-item-card__title">{{ item.name }}</h3>
108
106
  {% endif %}
109
107
 
110
108
  {# Content #}
111
109
  {% if item.content %}
112
- <div class="item-card__content{% if (item.content.text or '') | length > 300 %} item-card__content--truncated{% endif %}">
110
+ <div class="ms-item-card__content{% if (item.content.text or '') | length > 300 %} ms-item-card__content--truncated{% endif %}">
113
111
  {% if item.content.html %}
114
112
  {{ item.content.html | safe | striptags | truncate(400) }}
115
113
  {% elif item.content.text %}
@@ -120,10 +118,10 @@
120
118
 
121
119
  {# Tags #}
122
120
  {% if item.category and item.category.length > 0 %}
123
- <div class="item-card__categories">
121
+ <div class="ms-item-card__categories">
124
122
  {% for cat in item.category %}
125
123
  {% if loop.index0 < 5 %}
126
- <span class="item-card__category">#{{ cat }}</span>
124
+ <span class="ms-item-card__category">#{{ cat }}</span>
127
125
  {% endif %}
128
126
  {% endfor %}
129
127
  </div>
@@ -132,20 +130,19 @@
132
130
  {# Photos #}
133
131
  {% if item.photo and item.photo.length > 0 %}
134
132
  {% set photoCount = item.photo.length if item.photo.length <= 4 else 4 %}
135
- <div class="item-card__photos item-card__photos--{{ photoCount }}">
133
+ <div class="ms-item-card__photos ms-item-card__photos--{{ photoCount }}">
136
134
  {% for photo in item.photo %}
137
135
  {% if loop.index0 < 4 %}
138
- <img src="{{ photo }}" alt="" class="item-card__photo" loading="lazy"
139
- onerror="this.parentElement.removeChild(this)">
136
+ <img src="{{ photo }}" alt="" class="ms-item-card__photo" loading="lazy">
140
137
  {% endif %}
141
138
  {% endfor %}
142
139
  </div>
143
140
  {% endif %}
144
141
 
145
142
  {# Footer #}
146
- <footer class="item-card__footer">
143
+ <footer class="ms-item-card__footer">
147
144
  {% if item.published %}
148
- <time datetime="{{ item.published }}" class="item-card__date">
145
+ <time datetime="{{ item.published }}" class="ms-item-card__date">
149
146
  {{ item.published | date("PP", { locale: locale, timeZone: application.timeZone }) }}
150
147
  </time>
151
148
  {% endif %}
@@ -153,20 +150,20 @@
153
150
  </a>
154
151
 
155
152
  {# Actions #}
156
- <div class="item-actions">
157
- <a href="{{ item.url }}" class="item-actions__button" target="_blank" rel="noopener" title="View original">
153
+ <div class="ms-item-actions">
154
+ <a href="{{ item.url }}" class="ms-item-actions__button" target="_blank" rel="noopener" title="View original">
158
155
  {{ icon("external") }}
159
156
  </a>
160
- <a href="{{ baseUrl }}/compose?reply={{ item.url | urlencode }}" class="item-actions__button" title="Reply">
157
+ <a href="{{ baseUrl }}/compose?reply={{ item.url | urlencode }}" class="ms-item-actions__button" title="Reply">
161
158
  {{ icon("reply") }}
162
159
  </a>
163
- <a href="{{ baseUrl }}/compose?like={{ item.url | urlencode }}" class="item-actions__button" title="Like">
160
+ <a href="{{ baseUrl }}/compose?like={{ item.url | urlencode }}" class="ms-item-actions__button" title="Like">
164
161
  {{ icon("like") }}
165
162
  </a>
166
- <a href="{{ baseUrl }}/compose?repost={{ item.url | urlencode }}" class="item-actions__button" title="Repost">
163
+ <a href="{{ baseUrl }}/compose?repost={{ item.url | urlencode }}" class="ms-item-actions__button" title="Repost">
167
164
  {{ icon("repost") }}
168
165
  </a>
169
- <a href="{{ baseUrl }}/compose?bookmark={{ item.url | urlencode }}" class="item-actions__button" title="Bookmark">
166
+ <a href="{{ baseUrl }}/compose?bookmark={{ item.url | urlencode }}" class="ms-item-actions__button" title="Bookmark">
170
167
  {{ icon("bookmark") }}
171
168
  </a>
172
169
  </div>
@@ -174,7 +171,7 @@
174
171
  {% endfor %}
175
172
  </div>
176
173
  {% else %}
177
- <div class="reader__empty">
174
+ <div class="ms-reader__empty">
178
175
  {{ icon("syndicate") }}
179
176
  <p>No posts found for this actor.</p>
180
177
  </div>
package/views/channel.njk CHANGED
@@ -1,10 +1,10 @@
1
1
  {% extends "layouts/reader.njk" %}
2
2
 
3
3
  {% block reader %}
4
- <div class="channel">
5
- <header class="channel__header">
4
+ <div class="ms-channel">
5
+ <header class="ms-channel__header">
6
6
  <h1>{{ channel.name }}</h1>
7
- <div class="channel__actions">
7
+ <div class="ms-channel__actions">
8
8
  {% if not showRead and items.length > 0 %}
9
9
  <form action="{{ baseUrl }}/api/mark-read" method="POST" style="display: inline;">
10
10
  <input type="hidden" name="channel" value="{{ channel.uid }}">
@@ -33,14 +33,14 @@
33
33
  </header>
34
34
 
35
35
  {% if items.length > 0 %}
36
- <div class="timeline" id="timeline" data-channel="{{ channel.uid }}">
36
+ <div class="ms-timeline" id="timeline" data-channel="{{ channel.uid }}">
37
37
  {% for item in items %}
38
38
  {% include "partials/item-card.njk" %}
39
39
  {% endfor %}
40
40
  </div>
41
41
 
42
42
  {% if paging %}
43
- <nav class="timeline__paging" aria-label="Pagination">
43
+ <nav class="ms-timeline__paging" aria-label="Pagination">
44
44
  {% if paging.before %}
45
45
  <a href="?before={{ paging.before }}{% if showRead %}&showRead=true{% endif %}" class="button button--secondary">
46
46
  {{ icon("previous") }} {{ __("microsub.reader.newer") }}
@@ -56,7 +56,7 @@
56
56
  </nav>
57
57
  {% endif %}
58
58
  {% else %}
59
- <div class="reader__empty">
59
+ <div class="ms-reader__empty">
60
60
  {% if readCount > 0 and not showRead %}
61
61
  {{ icon("checkboxChecked") }}
62
62
  <p>{{ __("microsub.reader.allRead") }}</p>
@@ -78,16 +78,16 @@
78
78
  // Keyboard navigation (j/k for items, o to open)
79
79
  const timeline = document.getElementById('timeline');
80
80
  if (timeline) {
81
- const items = Array.from(timeline.querySelectorAll('.item-card'));
81
+ const items = Array.from(timeline.querySelectorAll('.ms-item-card'));
82
82
  let currentIndex = -1;
83
83
 
84
84
  function focusItem(index) {
85
85
  if (items[currentIndex]) {
86
- items[currentIndex].classList.remove('item-card--focused');
86
+ items[currentIndex].classList.remove('ms-item-card--focused');
87
87
  }
88
88
  currentIndex = Math.max(0, Math.min(index, items.length - 1));
89
89
  if (items[currentIndex]) {
90
- items[currentIndex].classList.add('item-card--focused');
90
+ items[currentIndex].classList.add('ms-item-card--focused');
91
91
  items[currentIndex].scrollIntoView({ behavior: 'smooth', block: 'center' });
92
92
  }
93
93
  }
@@ -108,7 +108,7 @@
108
108
  case 'Enter':
109
109
  e.preventDefault();
110
110
  if (items[currentIndex]) {
111
- const link = items[currentIndex].querySelector('.item-card__link');
111
+ const link = items[currentIndex].querySelector('.ms-item-card__link');
112
112
  if (link) link.click();
113
113
  }
114
114
  break;
@@ -121,7 +121,7 @@
121
121
  const microsubApiUrl = '{{ baseUrl }}'.replace(/\/reader$/, '');
122
122
 
123
123
  timeline.addEventListener('click', async (e) => {
124
- const button = e.target.closest('.item-actions__mark-read');
124
+ const button = e.target.closest('.ms-item-actions__mark-read');
125
125
  if (!button) return;
126
126
 
127
127
  e.preventDefault();
@@ -151,7 +151,7 @@
151
151
 
152
152
  if (response.ok) {
153
153
  // Hide the item with animation
154
- const card = button.closest('.item-card');
154
+ const card = button.closest('.ms-item-card');
155
155
  if (card) {
156
156
  card.style.transition = 'opacity 0.3s ease, transform 0.3s ease';
157
157
  card.style.opacity = '0';
@@ -159,7 +159,7 @@
159
159
  setTimeout(() => {
160
160
  card.remove();
161
161
  // Check if timeline is now empty
162
- if (timeline.querySelectorAll('.item-card').length === 0) {
162
+ if (timeline.querySelectorAll('.ms-item-card').length === 0) {
163
163
  location.reload();
164
164
  }
165
165
  }, 300);
@@ -176,14 +176,14 @@
176
176
 
177
177
  // Handle caret toggle for mark-source-read popover
178
178
  timeline.addEventListener('click', (e) => {
179
- const caret = e.target.closest('.item-actions__mark-read-caret');
179
+ const caret = e.target.closest('.ms-item-actions__mark-read-caret');
180
180
  if (!caret) return;
181
181
 
182
182
  e.preventDefault();
183
183
  e.stopPropagation();
184
184
 
185
185
  // Close other open popovers
186
- for (const p of timeline.querySelectorAll('.item-actions__mark-read-popover:not([hidden])')) {
186
+ for (const p of timeline.querySelectorAll('.ms-item-actions__mark-read-popover:not([hidden])')) {
187
187
  if (p !== caret.nextElementSibling) p.hidden = true;
188
188
  }
189
189
 
@@ -193,7 +193,7 @@
193
193
 
194
194
  // Handle mark-source-read button
195
195
  timeline.addEventListener('click', async (e) => {
196
- const button = e.target.closest('.item-actions__mark-source-read');
196
+ const button = e.target.closest('.ms-item-actions__mark-source-read');
197
197
  if (!button) return;
198
198
 
199
199
  e.preventDefault();
@@ -220,7 +220,7 @@
220
220
 
221
221
  if (response.ok) {
222
222
  // Animate out all cards from this feed
223
- const cards = timeline.querySelectorAll(`.item-card[data-feed-id="${feedId}"]`);
223
+ const cards = timeline.querySelectorAll(`.ms-item-card[data-feed-id="${feedId}"]`);
224
224
  for (const card of cards) {
225
225
  card.style.transition = 'opacity 0.3s ease, transform 0.3s ease';
226
226
  card.style.opacity = '0';
@@ -230,7 +230,7 @@
230
230
  for (const card of [...cards]) {
231
231
  card.remove();
232
232
  }
233
- if (timeline.querySelectorAll('.item-card').length === 0) {
233
+ if (timeline.querySelectorAll('.ms-item-card').length === 0) {
234
234
  location.reload();
235
235
  }
236
236
  }, 300);
@@ -245,8 +245,8 @@
245
245
 
246
246
  // Close popovers on outside click
247
247
  document.addEventListener('click', (e) => {
248
- if (!e.target.closest('.item-actions__mark-read-group')) {
249
- for (const p of timeline.querySelectorAll('.item-actions__mark-read-popover:not([hidden])')) {
248
+ if (!e.target.closest('.ms-item-actions__mark-read-group')) {
249
+ for (const p of timeline.querySelectorAll('.ms-item-actions__mark-read-popover:not([hidden])')) {
250
250
  p.hidden = true;
251
251
  }
252
252
  }
@@ -254,7 +254,7 @@
254
254
 
255
255
  // Handle save-for-later buttons
256
256
  timeline.addEventListener('click', async (e) => {
257
- const button = e.target.closest('.item-actions__save-later');
257
+ const button = e.target.closest('.ms-item-actions__save-later');
258
258
  if (!button) return;
259
259
 
260
260
  e.preventDefault();
@@ -275,7 +275,7 @@
275
275
  });
276
276
 
277
277
  if (response.ok) {
278
- button.classList.add('item-actions__save-later--saved');
278
+ button.classList.add('ms-item-actions__save-later--saved');
279
279
  button.title = 'Saved';
280
280
  } else {
281
281
  button.disabled = false;
package/views/compose.njk CHANGED
@@ -1,7 +1,7 @@
1
1
  {% extends "layouts/reader.njk" %}
2
2
 
3
3
  {% block reader %}
4
- <div class="compose">
4
+ <div class="ms-compose">
5
5
  <a href="{{ backUrl or (baseUrl + '/channels') }}" class="back-link">
6
6
  {{ icon("previous") }} {{ __("Back") }}
7
7
  </a>
@@ -9,7 +9,7 @@
9
9
  <h2>{{ __("microsub.compose.title") }}</h2>
10
10
 
11
11
  {% if replyTo and replyTo is string %}
12
- <div class="compose__context">
12
+ <div class="ms-compose__context">
13
13
  {{ icon("reply") }} {{ __("microsub.compose.replyTo") }}:
14
14
  <a href="{{ replyTo }}" target="_blank" rel="noopener">
15
15
  {{ replyTo | replace("https://", "") | replace("http://", "") }}
@@ -18,7 +18,7 @@
18
18
  {% endif %}
19
19
 
20
20
  {% if likeOf and likeOf is string %}
21
- <div class="compose__context">
21
+ <div class="ms-compose__context">
22
22
  {{ icon("like") }} {{ __("microsub.compose.likeOf") }}:
23
23
  <a href="{{ likeOf }}" target="_blank" rel="noopener">
24
24
  {{ likeOf | replace("https://", "") | replace("http://", "") }}
@@ -27,7 +27,7 @@
27
27
  {% endif %}
28
28
 
29
29
  {% if repostOf and repostOf is string %}
30
- <div class="compose__context">
30
+ <div class="ms-compose__context">
31
31
  {{ icon("repost") }} {{ __("microsub.compose.repostOf") }}:
32
32
  <a href="{{ repostOf }}" target="_blank" rel="noopener">
33
33
  {{ repostOf | replace("https://", "") | replace("http://", "") }}
@@ -36,7 +36,7 @@
36
36
  {% endif %}
37
37
 
38
38
  {% if bookmarkOf and bookmarkOf is string %}
39
- <div class="compose__context">
39
+ <div class="ms-compose__context">
40
40
  {{ icon("bookmark") }} {{ __("microsub.compose.bookmarkOf") }}:
41
41
  <a href="{{ bookmarkOf }}" target="_blank" rel="noopener">
42
42
  {{ bookmarkOf | replace("https://", "") | replace("http://", "") }}
@@ -68,13 +68,13 @@
68
68
  attributes: { autofocus: true },
69
69
  hint: __("microsub.compose.commentHint") if isAction else false
70
70
  }) }}
71
- <div class="compose__counter">
71
+ <div class="ms-compose__counter">
72
72
  <span id="char-count">0</span> characters
73
73
  </div>
74
74
 
75
75
  {# Syndication targets #}
76
76
  {% if syndicationTargets and syndicationTargets.length %}
77
- <fieldset class="compose__syndication">
77
+ <fieldset class="ms-compose__syndication">
78
78
  <legend>{{ __("microsub.compose.syndicateTo") }}</legend>
79
79
  <p class="hint">{{ __("microsub.compose.syndicateHint") }}</p>
80
80
  {% for target in syndicationTargets %}
@@ -1,7 +1,7 @@
1
1
  {% extends "layouts/reader.njk" %}
2
2
 
3
3
  {% block reader %}
4
- <div class="settings">
4
+ <div class="ms-settings">
5
5
  <header>
6
6
  <a href="{{ baseUrl }}/deck" class="back-link">
7
7
  {{ __("microsub.views.deck") }}
@@ -12,13 +12,13 @@
12
12
  <form action="{{ baseUrl }}/deck/settings" method="POST">
13
13
  <p>Select which channels appear as columns in your deck, and their order.</p>
14
14
 
15
- <div class="deck-settings__channels">
15
+ <div class="ms-deck-settings__channels">
16
16
  {% for channel in channels %}
17
17
  {% if channel.uid !== "notifications" %}
18
- <label class="deck-settings__channel">
18
+ <label class="ms-deck-settings__channel">
19
19
  <input type="checkbox" name="columns" value="{{ channel._id }}"
20
20
  {% if channel._id.toString() in selectedIds %}checked{% endif %}>
21
- <span class="timeline-view__filter-color" style="background: {{ channel.color }}"></span>
21
+ <span class="ms-timeline-view__filter-color" style="background: {{ channel.color }}"></span>
22
22
  {{ channel.name }}
23
23
  </label>
24
24
  {% endif %}
package/views/deck.njk CHANGED
@@ -1,8 +1,8 @@
1
1
  {% extends "layouts/reader.njk" %}
2
2
 
3
3
  {% block reader %}
4
- <div class="deck">
5
- <header class="deck__header">
4
+ <div class="ms-deck">
5
+ <header class="ms-deck__header">
6
6
  <h1>{{ __("microsub.views.deck") }}</h1>
7
7
  <a href="{{ baseUrl }}/deck/settings" class="button button--secondary button--small">
8
8
  Configure columns
@@ -10,29 +10,29 @@
10
10
  </header>
11
11
 
12
12
  {% if columns.length > 0 %}
13
- <div class="deck__columns">
13
+ <div class="ms-deck__columns">
14
14
  {% for col in columns %}
15
- <div class="deck__column" data-channel-uid="{{ col.channel.uid }}">
16
- <div class="deck__column-header" style="border-top: 3px solid {{ col.channel.color or '#ccc' }}">
17
- <a href="{{ baseUrl }}/channels/{{ col.channel.uid }}" class="deck__column-name">
15
+ <div class="ms-deck__column" data-channel-uid="{{ col.channel.uid }}">
16
+ <div class="ms-deck__column-header" style="border-top: 3px solid {{ col.channel.color or '#ccc' }}">
17
+ <a href="{{ baseUrl }}/channels/{{ col.channel.uid }}" class="ms-deck__column-name">
18
18
  {{ col.channel.name }}
19
19
  </a>
20
20
  {% if col.channel.unread %}
21
- <span class="reader__channel-badge{% if col.channel.unread === true %} reader__channel-badge--dot{% endif %}">
21
+ <span class="ms-reader__channel-badge{% if col.channel.unread === true %} ms-reader__channel-badge--dot{% endif %}">
22
22
  {% if col.channel.unread !== true %}{{ col.channel.unread }}{% endif %}
23
23
  </span>
24
24
  {% endif %}
25
25
  </div>
26
- <div class="deck__column-items">
26
+ <div class="ms-deck__column-items">
27
27
  {% for item in col.items %}
28
28
  {% include "partials/item-card-compact.njk" %}
29
29
  {% endfor %}
30
30
  {% if col.items.length === 0 %}
31
- <p class="deck__column-empty">No unread items</p>
31
+ <p class="ms-deck__column-empty">No unread items</p>
32
32
  {% endif %}
33
33
  {% if col.paging and col.paging.after %}
34
34
  <a href="{{ baseUrl }}/channels/{{ col.channel.uid }}"
35
- class="deck__column-more button button--secondary button--small">
35
+ class="ms-deck__column-more button button--secondary button--small">
36
36
  View more
37
37
  </a>
38
38
  {% endif %}
@@ -41,7 +41,7 @@
41
41
  {% endfor %}
42
42
  </div>
43
43
  {% else %}
44
- <div class="reader__empty">
44
+ <div class="ms-reader__empty">
45
45
  <p>No columns configured. Add channels to your deck.</p>
46
46
  <a href="{{ baseUrl }}/deck/settings" class="button button--primary">
47
47
  Configure deck
@@ -1,7 +1,7 @@
1
1
  {% extends "layouts/reader.njk" %}
2
2
 
3
3
  {% block reader %}
4
- <div class="settings">
4
+ <div class="ms-settings">
5
5
  <a href="{{ baseUrl }}/channels/{{ channel.uid }}/feeds" class="back-link">
6
6
  {{ icon("previous") }} {{ __("microsub.feeds.title") }}
7
7
  </a>
@@ -9,20 +9,20 @@
9
9
  <h2>{{ __("microsub.feeds.edit") }}</h2>
10
10
 
11
11
  {% if error %}
12
- <div class="notice notice--error">
12
+ <div class="ms-notice ms-notice--error">
13
13
  <p>{{ error }}</p>
14
14
  </div>
15
15
  {% endif %}
16
16
 
17
- <div class="feed-edit">
18
- <div class="feed-edit__current">
17
+ <div class="ms-feed-edit">
18
+ <div class="ms-feed-edit__current">
19
19
  <h3>Current Feed</h3>
20
- <p class="feed-edit__url">{{ feed.url }}</p>
20
+ <p class="ms-feed-edit__url">{{ feed.url }}</p>
21
21
  {% if feed.title %}
22
- <p class="feed-edit__title">{{ feed.title }}</p>
22
+ <p class="ms-feed-edit__title">{{ feed.title }}</p>
23
23
  {% endif %}
24
24
  {% if feed.status == 'error' %}
25
- <div class="notice notice--error">
25
+ <div class="ms-notice ms-notice--error">
26
26
  <p><strong>Status:</strong> Error</p>
27
27
  {% if feed.lastError %}
28
28
  <p><strong>Last error:</strong> {{ feed.lastError }}</p>
@@ -34,7 +34,7 @@
34
34
  {% endif %}
35
35
  </div>
36
36
 
37
- <form method="post" action="{{ baseUrl }}/channels/{{ channel.uid }}/feeds/{{ feed._id }}/edit" class="feed-edit__form">
37
+ <form method="post" action="{{ baseUrl }}/channels/{{ channel.uid }}/feeds/{{ feed._id }}/edit" class="ms-feed-edit__form">
38
38
  {{ input({
39
39
  id: "url",
40
40
  name: "url",
@@ -46,7 +46,7 @@
46
46
  autocomplete: "off"
47
47
  }) }}
48
48
 
49
- <p class="feed-edit__help">
49
+ <p class="ms-feed-edit__help">
50
50
  Enter the direct URL to the RSS, Atom, or JSON Feed. The URL will be validated before updating.
51
51
  </p>
52
52
 
@@ -60,10 +60,10 @@
60
60
 
61
61
  <div class="divider"></div>
62
62
 
63
- <div class="feed-edit__actions">
63
+ <div class="ms-feed-edit__actions">
64
64
  <h3>Other Actions</h3>
65
65
 
66
- <form method="post" action="{{ baseUrl }}/channels/{{ channel.uid }}/feeds/{{ feed._id }}/rediscover" class="feed-edit__action">
66
+ <form method="post" action="{{ baseUrl }}/channels/{{ channel.uid }}/feeds/{{ feed._id }}/rediscover" class="ms-feed-edit__action">
67
67
  <p>Run feed discovery on the current URL to find the actual RSS/Atom feed.</p>
68
68
  {{ button({
69
69
  text: "Rediscover Feed",
@@ -71,7 +71,7 @@
71
71
  }) }}
72
72
  </form>
73
73
 
74
- <form method="post" action="{{ baseUrl }}/channels/{{ channel.uid }}/feeds/{{ feed._id }}/refresh" class="feed-edit__action">
74
+ <form method="post" action="{{ baseUrl }}/channels/{{ channel.uid }}/feeds/{{ feed._id }}/refresh" class="ms-feed-edit__action">
75
75
  <p>Force refresh this feed now.</p>
76
76
  {{ button({
77
77
  text: "Refresh Now",