@rmdes/indiekit-endpoint-microsub 1.0.51 → 1.0.54

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.
@@ -902,33 +902,18 @@ export async function channelHtml(request, response) {
902
902
  );
903
903
  }
904
904
 
905
- // Render each item card to HTML using the existing partial
906
- const renderLocals = {
907
- channel: channelDocument,
908
- baseUrl: request.baseUrl,
909
- __: request.__,
910
- icon: response.locals.icon,
911
- application,
912
- };
913
-
914
- const htmlParts = await Promise.all(
915
- timeline.items.map(
916
- (item) =>
917
- new Promise((resolve, reject) => {
918
- request.app.render(
919
- "partials/item-card.njk",
920
- { ...renderLocals, item },
921
- (error, html) => {
922
- if (error) reject(error);
923
- else resolve(html);
924
- },
925
- );
926
- }),
927
- ),
928
- );
905
+ // Render items via layout-less fragment template (standard response.render
906
+ // with callback returns HTML string without sending a response)
907
+ const fragmentHtml = await new Promise((resolve, reject) => {
908
+ response.render("partials/items-fragment", {
909
+ items: timeline.items,
910
+ channel: channelDocument,
911
+ baseUrl: request.baseUrl,
912
+ }, (error, html) => error ? reject(error) : resolve(html));
913
+ });
929
914
 
930
915
  response.json({
931
- html: htmlParts.join(""),
916
+ html: fragmentHtml,
932
917
  paging: timeline.paging,
933
918
  count: timeline.items.length,
934
919
  });
@@ -985,37 +970,15 @@ export async function timelineHtml(request, response) {
985
970
  }
986
971
  }
987
972
 
988
- const renderLocals = {
989
- baseUrl: request.baseUrl,
990
- __: request.__,
991
- icon: response.locals.icon,
992
- application,
993
- };
994
-
995
- const htmlParts = await Promise.all(
996
- result.items.map(
997
- (item) =>
998
- new Promise((resolve, reject) => {
999
- request.app.render(
1000
- "partials/item-card.njk",
1001
- { ...renderLocals, item },
1002
- (error, cardHtml) => {
1003
- if (error) {
1004
- reject(error);
1005
- } else {
1006
- const badge = item._channelName
1007
- ? `<span class="ms-timeline-view__channel-badge" style="background: ${item._channelColor || "#888"}">${item._channelName}</span>`
1008
- : "";
1009
- resolve(`<div class="ms-timeline-view__item">${badge}${cardHtml}</div>`);
1010
- }
1011
- },
1012
- );
1013
- }),
1014
- ),
1015
- );
973
+ const fragmentHtml = await new Promise((resolve, reject) => {
974
+ response.render("partials/items-fragment-timeline", {
975
+ items: result.items,
976
+ baseUrl: request.baseUrl,
977
+ }, (error, html) => error ? reject(error) : resolve(html));
978
+ });
1016
979
 
1017
980
  response.json({
1018
- html: htmlParts.join(""),
981
+ html: fragmentHtml,
1019
982
  paging: result.paging,
1020
983
  count: result.items.length,
1021
984
  });
package/locales/en.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "title": "Reader",
5
5
  "empty": "No items to display",
6
6
  "markAllRead": "Mark all as read",
7
- "markViewRead": "Mark view as read",
7
+ "markViewRead": "Mark current view as read",
8
8
  "showRead": "Show read ({{count}})",
9
9
  "hideRead": "Hide read items",
10
10
  "allRead": "All caught up!",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rmdes/indiekit-endpoint-microsub",
3
- "version": "1.0.51",
3
+ "version": "1.0.54",
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/channel.njk CHANGED
@@ -381,10 +381,11 @@
381
381
  window.__microsubLoadMore = loadMore;
382
382
  }
383
383
 
384
- // === Mark view as read button ===
384
+ // === Mark current view as read button ===
385
385
  const markViewBtn = document.querySelector('.js-mark-view-read');
386
386
  if (markViewBtn && timeline) {
387
387
  markViewBtn.style.display = '';
388
+ const markViewApiUrl = '{{ baseUrl }}'.replace(/\/reader$/, '');
388
389
 
389
390
  markViewBtn.addEventListener('click', async () => {
390
391
  const unreadCards = timeline.querySelectorAll('.ms-item-card:not(.ms-item-card--read)');
@@ -403,7 +404,7 @@
403
404
  }
404
405
 
405
406
  try {
406
- const response = await fetch(microsubApiUrl, {
407
+ const response = await fetch(markViewApiUrl, {
407
408
  method: 'POST',
408
409
  headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
409
410
  body: formData.toString(),
@@ -431,7 +432,7 @@
431
432
  markViewBtn.disabled = false;
432
433
  }
433
434
  } catch (error) {
434
- console.error('Error marking view as read:', error);
435
+ console.error('Error marking current view as read:', error);
435
436
  markViewBtn.disabled = false;
436
437
  }
437
438
  });
@@ -0,0 +1,11 @@
1
+ {# Layout-less fragment for AJAX infinite scroll in timeline view #}
2
+ {% for item in items %}
3
+ <div class="ms-timeline-view__item">
4
+ {% if item._channelName %}
5
+ <span class="ms-timeline-view__channel-badge" style="background: {{ item._channelColor or '#888' }}">
6
+ {{ item._channelName }}
7
+ </span>
8
+ {% endif %}
9
+ {% include "partials/item-card.njk" %}
10
+ </div>
11
+ {% endfor %}
@@ -0,0 +1,4 @@
1
+ {# Layout-less fragment for AJAX infinite scroll responses #}
2
+ {% for item in items %}
3
+ {% include "partials/item-card.njk" %}
4
+ {% endfor %}