@rmdes/indiekit-endpoint-webmention-io 1.0.1 → 1.0.2

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.
@@ -5,6 +5,26 @@
5
5
  import { getBlocklist, unblockDomain } from "../storage/blocklist.js";
6
6
  import { unhideByDomain } from "../storage/webmentions.js";
7
7
 
8
+ /**
9
+ * Format a date for display. Returns a human-readable string or null.
10
+ * NEVER pass raw Date objects to Nunjucks templates — the | date filter
11
+ * crashes on both Date objects and undefined/null.
12
+ * @param {*} value
13
+ * @returns {string|null}
14
+ */
15
+ function formatDate(value) {
16
+ if (!value) return null;
17
+ const d = value instanceof Date ? value : new Date(value);
18
+ if (Number.isNaN(d.getTime())) return null;
19
+ return d.toLocaleDateString("en-GB", {
20
+ year: "numeric",
21
+ month: "short",
22
+ day: "numeric",
23
+ hour: "2-digit",
24
+ minute: "2-digit",
25
+ });
26
+ }
27
+
8
28
  export const blocklistController = {
9
29
  /**
10
30
  * GET /blocklist - Blocklist management page
@@ -21,9 +41,7 @@ export const blocklistController = {
21
41
  const raw = await getBlocklist(collection);
22
42
  entries = raw.map((entry) => ({
23
43
  ...entry,
24
- blockedAt: entry.blockedAt instanceof Date
25
- ? entry.blockedAt.toISOString()
26
- : entry.blockedAt,
44
+ blockedAt: formatDate(entry.blockedAt),
27
45
  }));
28
46
  }
29
47
 
@@ -16,14 +16,37 @@ import { getSyncState } from "../sync.js";
16
16
  import { getMentionType, getMentionTitle, getAuthorName } from "../utils.js";
17
17
 
18
18
  /**
19
- * Convert Date objects to ISO strings for Nunjucks date filter
19
+ * Format a date for direct display in templates (NOT through macros).
20
+ * Returns a human-readable string or null.
20
21
  * @param {*} value
21
- * @returns {string|undefined}
22
+ * @returns {string|null}
22
23
  */
23
- function toDateString(value) {
24
- if (!value) return undefined;
24
+ function formatDate(value) {
25
+ if (!value) return null;
26
+ const d = value instanceof Date ? value : new Date(value);
27
+ if (Number.isNaN(d.getTime())) return null;
28
+ return d.toLocaleDateString("en-GB", {
29
+ year: "numeric",
30
+ month: "short",
31
+ day: "numeric",
32
+ hour: "2-digit",
33
+ minute: "2-digit",
34
+ });
35
+ }
36
+
37
+ /**
38
+ * Convert any date value to an ISO 8601 string safe for the Nunjucks | date
39
+ * filter (which calls date-fns parseISO — crashes on Date objects, null, and
40
+ * undefined). Use this for values that pass through mention()/card() macros.
41
+ * @param {*} value
42
+ * @returns {string|null}
43
+ */
44
+ function toISO(value) {
45
+ if (!value) return null;
25
46
  if (value instanceof Date) return value.toISOString();
26
- return String(value);
47
+ const d = new Date(value);
48
+ if (Number.isNaN(d.getTime())) return null;
49
+ return d.toISOString();
27
50
  }
28
51
 
29
52
  export const dashboardController = {
@@ -42,7 +65,7 @@ export const dashboardController = {
42
65
  counts: { total: 0, hidden: 0, visible: 0 },
43
66
  syncState: {
44
67
  ...getSyncState(),
45
- lastSync: toDateString(getSyncState().lastSync),
68
+ lastSync: formatDate(getSyncState().lastSync),
46
69
  },
47
70
  cursor: {},
48
71
  filter: "all",
@@ -96,7 +119,7 @@ export const dashboardController = {
96
119
  locale: application.locale,
97
120
  title: getMentionTitle({ name: item.name, "wm-property": item.wmProperty }),
98
121
  description: html ? { html } : undefined,
99
- published: toDateString(item.published || item.wmReceived),
122
+ published: toISO(item.published || item.wmReceived),
100
123
  url: item.sourceUrl,
101
124
  user: {
102
125
  avatar: { src: item.authorPhoto },
@@ -127,7 +150,7 @@ export const dashboardController = {
127
150
  counts,
128
151
  syncState: {
129
152
  ...getSyncState(),
130
- lastSync: toDateString(getSyncState().lastSync),
153
+ lastSync: formatDate(getSyncState().lastSync),
131
154
  },
132
155
  cursor,
133
156
  filter,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rmdes/indiekit-endpoint-webmention-io",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "Webmention moderation endpoint for Indiekit. Syncs webmentions from webmention.io into MongoDB with delete, block, and privacy removal capabilities.",
5
5
  "keywords": [
6
6
  "indiekit",
@@ -173,7 +173,7 @@
173
173
  </span>
174
174
  </td>
175
175
  <td>{{ entry.mentionsHidden or 0 }}</td>
176
- <td>{{ entry.blockedAt | date }}</td>
176
+ <td>{{ entry.blockedAt }}</td>
177
177
  <td>
178
178
  <form method="post" action="{{ wmEndpoint }}/blocklist/{{ entry.domain | urlencode }}/delete" style="display:inline">
179
179
  <button type="submit" class="button button--small button--secondary"
@@ -139,7 +139,7 @@
139
139
  <div class="wm-actions-bar">
140
140
  <span class="wm-sync-info">
141
141
  {% if syncState.lastSync %}
142
- {{ __("webmention-io.sync.lastSync") }}: {{ syncState.lastSync | date }}
142
+ {{ __("webmention-io.sync.lastSync") }}: {{ syncState.lastSync }}
143
143
  {% else %}
144
144
  {{ __("webmention-io.sync.never") }}
145
145
  {% endif %}