@ecency/render-helper 2.4.29 → 2.4.31

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.
@@ -123,6 +123,8 @@ var ALLOWED_ATTRIBUTES = {
123
123
  ],
124
124
  "img": [
125
125
  "src",
126
+ "srcset",
127
+ "sizes",
126
128
  "alt",
127
129
  "class",
128
130
  "loading",
@@ -202,8 +204,11 @@ function createDoc(html) {
202
204
  return null;
203
205
  }
204
206
  const cleanedHtml = removeDuplicateAttributes(html);
205
- const doc = DOMParser.parseFromString(`<body>${cleanedHtml}</body>`, "text/html");
206
- return doc;
207
+ try {
208
+ return DOMParser.parseFromString(`<body>${cleanedHtml}</body>`, "text/html");
209
+ } catch {
210
+ return null;
211
+ }
207
212
  }
208
213
  function makeEntryCacheKey(entry) {
209
214
  return `${entry.author}-${entry.permlink}-${entry.last_update}-${entry.updated}`;
@@ -278,6 +283,10 @@ function sanitizeHtml(html) {
278
283
  const decodedLower = decoded.toLowerCase();
279
284
  if (name.startsWith("on")) return "";
280
285
  if (tag === "img" && name === "src" && (!/^https?:\/\//.test(decodedLower) || decodedLower.startsWith("javascript:"))) return "";
286
+ if (tag === "img" && name === "srcset") {
287
+ const candidates = decoded.split(",").map((c) => c.trim().split(/\s+/)[0]);
288
+ if (candidates.some((url) => !/^https?:\/\//.test(url))) return "";
289
+ }
281
290
  if (tag === "video" && ["src", "poster"].includes(name) && (!/^https?:\/\//.test(decodedLower) || decodedLower.startsWith("javascript:"))) return "";
282
291
  if (tag === "img" && ["dynsrc", "lowsrc"].includes(name)) return "";
283
292
  if (tag === "span" && name === "class" && decoded.toLowerCase().trim() === "wr") return "";
@@ -292,6 +301,9 @@ var proxyBase = "https://images.ecency.com";
292
301
  function setProxyBase(p2) {
293
302
  proxyBase = p2;
294
303
  }
304
+ function getProxyBase() {
305
+ return proxyBase;
306
+ }
295
307
  function extractPHash(url) {
296
308
  if (url.startsWith(`${proxyBase}/p/`)) {
297
309
  const [hash] = url.split("/p/")[1].split("?");
@@ -339,8 +351,24 @@ function proxifyImageSrc(url, width = 0, height = 0, _format = "match") {
339
351
  const b58url = multihash.toB58String(Buffer.from(realUrl.toString()));
340
352
  return `${proxyBase}/p/${b58url}?${qs}`;
341
353
  }
354
+ var SRCSET_WIDTHS = [320, 600, 800, 1024, 1280];
355
+ function buildSrcSet(url) {
356
+ if (!url || typeof url !== "string") return "";
357
+ const escapedBase = proxyBase.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
358
+ const proxyPattern = new RegExp(`^${escapedBase}/p/([^?]+)`);
359
+ const match = url.match(proxyPattern);
360
+ if (match) {
361
+ const phash = extractPHash(url) || match[1];
362
+ return SRCSET_WIDTHS.map((w) => `${proxyBase}/p/${phash}?format=match&mode=fit&width=${w} ${w}w`).join(", ");
363
+ }
364
+ return SRCSET_WIDTHS.map((w) => {
365
+ const proxied = proxifyImageSrc(url, w);
366
+ return proxied ? `${proxied} ${w}w` : "";
367
+ }).filter(Boolean).join(", ");
368
+ }
342
369
 
343
370
  // src/methods/img.method.ts
371
+ var IMAGE_SIZES = "(max-width: 768px) 100vw, 700px";
344
372
  function img(el, state) {
345
373
  const src = el.getAttribute("src") || "";
346
374
  const decodedSrc = decodeURIComponent(
@@ -350,11 +378,15 @@ function img(el, state) {
350
378
  const isInvalid = !src || decodedSrc.startsWith("javascript") || decodedSrc.startsWith("vbscript") || decodedSrc === "x";
351
379
  if (isInvalid) {
352
380
  el.removeAttribute("src");
381
+ el.removeAttribute("srcset");
382
+ el.removeAttribute("sizes");
353
383
  return;
354
384
  }
355
385
  const isRelative = !/^https?:\/\//i.test(decodedSrc) && !decodedSrc.startsWith("/");
356
386
  if (isRelative) {
357
387
  el.removeAttribute("src");
388
+ el.removeAttribute("srcset");
389
+ el.removeAttribute("sizes");
358
390
  return;
359
391
  }
360
392
  el.setAttribute("itemprop", "image");
@@ -369,22 +401,41 @@ function img(el, state) {
369
401
  }
370
402
  const cls = el.getAttribute("class") || "";
371
403
  const shouldReplace = !cls.includes("no-replace");
372
- const hasAlreadyProxied = src.startsWith("https://images.ecency.com/p/") || src.startsWith("https://images.ecency.com/u/") || /^https:\/\/images\.ecency\.com\/\d+x\d+\//.test(src);
404
+ const base = getProxyBase().replace(/\/+$/, "");
405
+ const hasAlreadyProxied = src.startsWith(`${base}/p/`) || src.startsWith(`${base}/u/`) || new RegExp(`^${base.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}/\\d+x\\d+/`).test(src);
373
406
  if (shouldReplace && !hasAlreadyProxied) {
374
407
  const proxified = proxifyImageSrc(decodedSrc);
375
408
  if (proxified) {
376
409
  el.setAttribute("src", proxified);
410
+ const srcset = buildSrcSet(decodedSrc);
411
+ if (srcset) {
412
+ el.setAttribute("srcset", srcset);
413
+ el.setAttribute("sizes", IMAGE_SIZES);
414
+ }
415
+ }
416
+ } else if (shouldReplace && hasAlreadyProxied) {
417
+ if (src.startsWith(`${base}/p/`)) {
418
+ const srcset = buildSrcSet(src);
419
+ if (srcset) {
420
+ el.setAttribute("srcset", srcset);
421
+ el.setAttribute("sizes", IMAGE_SIZES);
422
+ }
377
423
  }
378
424
  }
379
425
  }
380
426
  function createImageHTML(src, isLCP) {
381
427
  const proxified = proxifyImageSrc(src);
382
428
  if (!proxified) return "";
429
+ const base = getProxyBase().replace(/\/+$/, "");
430
+ const isAlreadyProxied = src.startsWith(`${base}/u/`) || new RegExp(`^${base.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}/\\d+x\\d+/`).test(src);
431
+ const srcset = isAlreadyProxied ? "" : buildSrcSet(src);
383
432
  const loading = isLCP ? "eager" : "lazy";
384
433
  const fetch = isLCP ? 'fetchpriority="high"' : 'decoding="async"';
434
+ const srcsetAttr = srcset ? `srcset="${srcset}" sizes="${IMAGE_SIZES}"` : "";
385
435
  return `<img
386
436
  class="markdown-img-link"
387
437
  src="${proxified}"
438
+ ${srcsetAttr}
388
439
  loading="${loading}"
389
440
  ${fetch}
390
441
  itemprop="image"
@@ -1777,6 +1828,6 @@ function getPostBodySummary(obj, length, platform) {
1777
1828
  return res;
1778
1829
  }
1779
1830
 
1780
- export { SECTION_LIST, catchPostImage, isValidPermlink, getPostBodySummary as postBodySummary, proxifyImageSrc, markdown2Html as renderPostBody, setCacheSize, setProxyBase, simpleMarkdownToHTML };
1831
+ export { SECTION_LIST, buildSrcSet, catchPostImage, isValidPermlink, getPostBodySummary as postBodySummary, proxifyImageSrc, markdown2Html as renderPostBody, setCacheSize, setProxyBase, simpleMarkdownToHTML };
1781
1832
  //# sourceMappingURL=index.mjs.map
1782
1833
  //# sourceMappingURL=index.mjs.map