feedkeeper 0.26.3 → 0.26.5

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": "feedkeeper",
3
- "version": "0.26.3",
3
+ "version": "0.26.5",
4
4
  "description": "A lightweight, self-hosted RSS reader and remote MCP server for your news, blogs, and AI workflows.",
5
5
  "keywords": [
6
6
  "rss",
@@ -244,9 +244,37 @@ export function cleanReaderHtml(html, title, stats = {}) {
244
244
  if (!html)
245
245
  return html;
246
246
  const root = JSDOM.fragment(html);
247
+ const images = resolveCustomImages(root, stats);
247
248
  const noise = removeReaderNoise(root, title, stats);
248
249
  const typography = removeTypography(root, stats);
249
- return noise || typography ? serialize(root) : html;
250
+ return images || noise || typography ? serialize(root) : html;
251
+ }
252
+ /**
253
+ * Some publishers wrap a picture in their own element and let a script fill the image: `<a-img src="/imgs/…">`
254
+ * around an `<img>` that only holds a grey placeholder. Without the script no reader would ever show the picture, so
255
+ * the wrapper's address takes the placeholder's place and the wrapper, which means nothing outside the page, goes.
256
+ */
257
+ function resolveCustomImages(root, stats) {
258
+ let changed = false;
259
+ for (const wrapper of [...root.querySelectorAll("a-img")]) {
260
+ const source = (wrapper.getAttribute("src") ?? "").trim();
261
+ if (source && !/^data:/i.test(source)) {
262
+ let image = wrapper.querySelector("img");
263
+ if (!image) {
264
+ image = wrapper.ownerDocument.createElement("img");
265
+ image.setAttribute("alt", wrapper.getAttribute("alt") ?? "");
266
+ wrapper.append(image);
267
+ }
268
+ const current = (image.getAttribute("src") ?? "").trim();
269
+ if (!current || /^data:/i.test(current))
270
+ image.setAttribute("src", source);
271
+ }
272
+ wrapper.replaceWith(...wrapper.childNodes);
273
+ changed = true;
274
+ }
275
+ if (changed)
276
+ stats["custom-image"] = (stats["custom-image"] ?? 0) + 1;
277
+ return changed;
250
278
  }
251
279
  const CREDIT_PATTERNS = [
252
280
  /^(©|\(c\)\s|copyright\b)/i,
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@feedkeeper/server",
3
- "version": "0.26.3",
3
+ "version": "0.26.5",
4
4
  "private": true,
5
5
  "type": "module"
6
6
  }