@ecency/render-helper 2.4.15 → 2.4.16
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/dist/browser/index.d.ts +12 -2
- package/dist/browser/index.js +49 -48
- package/dist/browser/index.js.map +1 -1
- package/dist/node/index.cjs +49 -48
- package/dist/node/index.cjs.map +1 -1
- package/dist/node/index.mjs +49 -48
- package/dist/node/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/node/index.mjs
CHANGED
|
@@ -78,8 +78,8 @@ var LBRY_REGEX = /^(https?:)?\/\/lbry.tv\/\$\/embed\/[^?#]+(?:$|[?#])/i;
|
|
|
78
78
|
var ODYSEE_REGEX = /^(https?:)?\/\/odysee\.com\/(?:\$|%24)\/embed\/[^/?#]+(?:$|[?#])/i;
|
|
79
79
|
var SKATEHIVE_IPFS_REGEX = /^https?:\/\/ipfs\.skatehive\.app\/ipfs\/([^/?#]+)/i;
|
|
80
80
|
var ARCH_REGEX = /^(https?:)?\/\/archive.org\/embed\/[^/?#]+(?:$|[?#])/i;
|
|
81
|
-
var SPEAK_REGEX = /(?:https?:\/\/(?:(?:play\.)?3speak
|
|
82
|
-
var SPEAK_EMBED_REGEX = /^(https?:)?\/\/(?:play\.)?3speak
|
|
81
|
+
var SPEAK_REGEX = /(?:https?:\/\/(?:(?:play\.)?3speak\.([a-z]+)\/watch\?v=)|(?:(?:play\.)?3speak\.([a-z]+)\/embed\?v=))([A-Za-z0-9_\-\.\/]+)(&.*)?/i;
|
|
82
|
+
var SPEAK_EMBED_REGEX = /^(https?:)?\/\/(?:play\.)?3speak\.([a-z]+)\/(?:embed|watch)\?.+$/i;
|
|
83
83
|
var TWITTER_REGEX = /(?:https?:\/\/(?:(?:twitter\.com\/(.*?)\/status\/(.*))))/gi;
|
|
84
84
|
var SPOTIFY_REGEX = /^https:\/\/open\.spotify\.com\/playlist\/(.*)?$/gi;
|
|
85
85
|
var RUMBLE_REGEX = /^https:\/\/rumble.com\/embed\/([a-zA-Z0-9-]+)\/\?pub=\w+/;
|
|
@@ -287,15 +287,13 @@ function sanitizeHtml(html) {
|
|
|
287
287
|
});
|
|
288
288
|
}
|
|
289
289
|
var proxyBase = "https://images.ecency.com";
|
|
290
|
-
var fileExtension = true;
|
|
291
290
|
function setProxyBase(p2) {
|
|
292
291
|
proxyBase = p2;
|
|
293
|
-
fileExtension = proxyBase == "https://images.ecency.com";
|
|
294
292
|
}
|
|
295
293
|
function extractPHash(url) {
|
|
296
294
|
if (url.startsWith(`${proxyBase}/p/`)) {
|
|
297
295
|
const [hash] = url.split("/p/")[1].split("?");
|
|
298
|
-
return hash.replace(
|
|
296
|
+
return hash.replace(/\.(webp|png)$/, "");
|
|
299
297
|
}
|
|
300
298
|
return null;
|
|
301
299
|
}
|
|
@@ -310,7 +308,7 @@ function getLatestUrl(str) {
|
|
|
310
308
|
const [last] = [...str.replace(/https?:\/\//g, "\n$&").trim().split("\n")].reverse();
|
|
311
309
|
return last;
|
|
312
310
|
}
|
|
313
|
-
function proxifyImageSrc(url, width = 0, height = 0,
|
|
311
|
+
function proxifyImageSrc(url, width = 0, height = 0, _format = "match") {
|
|
314
312
|
if (!url || typeof url !== "string" || !isValidUrl(url)) {
|
|
315
313
|
return "";
|
|
316
314
|
}
|
|
@@ -323,7 +321,7 @@ function proxifyImageSrc(url, width = 0, height = 0, format = "match") {
|
|
|
323
321
|
const realUrl = getLatestUrl(url);
|
|
324
322
|
const pHash = extractPHash(realUrl);
|
|
325
323
|
const options = {
|
|
326
|
-
format,
|
|
324
|
+
format: "match",
|
|
327
325
|
mode: "fit"
|
|
328
326
|
};
|
|
329
327
|
if (width > 0) {
|
|
@@ -334,31 +332,29 @@ function proxifyImageSrc(url, width = 0, height = 0, format = "match") {
|
|
|
334
332
|
}
|
|
335
333
|
const qs = querystring.stringify(options);
|
|
336
334
|
if (pHash) {
|
|
337
|
-
|
|
338
|
-
return `${proxyBase}/p/${pHash}${format === "webp" ? ".webp" : ".png"}?${qs}`;
|
|
339
|
-
} else {
|
|
340
|
-
return `${proxyBase}/p/${pHash}?${qs}`;
|
|
341
|
-
}
|
|
335
|
+
return `${proxyBase}/p/${pHash}?${qs}`;
|
|
342
336
|
}
|
|
343
337
|
const b58url = multihash.toB58String(Buffer.from(realUrl.toString()));
|
|
344
|
-
return `${proxyBase}/p/${b58url}
|
|
338
|
+
return `${proxyBase}/p/${b58url}?${qs}`;
|
|
345
339
|
}
|
|
346
340
|
|
|
347
341
|
// src/methods/img.method.ts
|
|
348
|
-
function img(el,
|
|
349
|
-
|
|
342
|
+
function img(el, state) {
|
|
343
|
+
const src = el.getAttribute("src") || "";
|
|
350
344
|
const decodedSrc = decodeURIComponent(
|
|
351
345
|
src.replace(/&#(\d+);/g, (_, dec) => String.fromCharCode(dec)).replace(/&#x([0-9a-f]+);/gi, (_, hex) => String.fromCharCode(parseInt(hex, 16)))
|
|
352
346
|
).trim();
|
|
347
|
+
["onerror", "dynsrc", "lowsrc", "width", "height"].forEach((attr) => el.removeAttribute(attr));
|
|
353
348
|
const isInvalid = !src || decodedSrc.startsWith("javascript") || decodedSrc.startsWith("vbscript") || decodedSrc === "x";
|
|
354
349
|
if (isInvalid) {
|
|
355
|
-
src
|
|
350
|
+
el.removeAttribute("src");
|
|
351
|
+
return;
|
|
356
352
|
}
|
|
357
353
|
const isRelative = !/^https?:\/\//i.test(decodedSrc) && !decodedSrc.startsWith("/");
|
|
358
354
|
if (isRelative) {
|
|
359
|
-
src
|
|
355
|
+
el.removeAttribute("src");
|
|
356
|
+
return;
|
|
360
357
|
}
|
|
361
|
-
["onerror", "dynsrc", "lowsrc", "width", "height"].forEach((attr) => el.removeAttribute(attr));
|
|
362
358
|
el.setAttribute("itemprop", "image");
|
|
363
359
|
const isLCP = state && !state.firstImageFound;
|
|
364
360
|
if (isLCP) {
|
|
@@ -373,14 +369,17 @@ function img(el, webp, state) {
|
|
|
373
369
|
const shouldReplace = !cls.includes("no-replace");
|
|
374
370
|
const hasAlreadyProxied = src.startsWith("https://images.ecency.com");
|
|
375
371
|
if (shouldReplace && !hasAlreadyProxied) {
|
|
376
|
-
const proxified = proxifyImageSrc(
|
|
377
|
-
|
|
372
|
+
const proxified = proxifyImageSrc(decodedSrc);
|
|
373
|
+
if (proxified) {
|
|
374
|
+
el.setAttribute("src", proxified);
|
|
375
|
+
}
|
|
378
376
|
}
|
|
379
377
|
}
|
|
380
|
-
function createImageHTML(src, isLCP
|
|
378
|
+
function createImageHTML(src, isLCP) {
|
|
379
|
+
const proxified = proxifyImageSrc(src);
|
|
380
|
+
if (!proxified) return "";
|
|
381
381
|
const loading = isLCP ? "eager" : "lazy";
|
|
382
382
|
const fetch = isLCP ? 'fetchpriority="high"' : 'decoding="async"';
|
|
383
|
-
const proxified = proxifyImageSrc(src, 0, 0, webp ? "webp" : "match");
|
|
384
383
|
return `<img
|
|
385
384
|
class="markdown-img-link"
|
|
386
385
|
src="${proxified}"
|
|
@@ -432,7 +431,7 @@ var addLineBreakBeforePostLink = (el, forApp, isInline) => {
|
|
|
432
431
|
el.parentNode.insertBefore(br, el);
|
|
433
432
|
}
|
|
434
433
|
};
|
|
435
|
-
function a(el, forApp,
|
|
434
|
+
function a(el, forApp, parentDomain = "ecency.com", seoContext) {
|
|
436
435
|
if (!el || !el.parentNode) {
|
|
437
436
|
return;
|
|
438
437
|
}
|
|
@@ -450,7 +449,7 @@ function a(el, forApp, webp, parentDomain = "ecency.com", seoContext) {
|
|
|
450
449
|
}
|
|
451
450
|
if (href.match(IMG_REGEX) && href.trim().replace(/&/g, "&") === getSerializedInnerHTML(el).trim().replace(/&/g, "&")) {
|
|
452
451
|
const isLCP = false;
|
|
453
|
-
const imgHTML = createImageHTML(href, isLCP
|
|
452
|
+
const imgHTML = createImageHTML(href, isLCP);
|
|
454
453
|
const doc = DOMParser.parseFromString(imgHTML, "text/html");
|
|
455
454
|
const replaceNode = doc.body?.firstChild || doc.firstChild;
|
|
456
455
|
if (replaceNode) {
|
|
@@ -772,7 +771,7 @@ function a(el, forApp, webp, parentDomain = "ecency.com", seoContext) {
|
|
|
772
771
|
el.setAttribute("class", "markdown-video-link markdown-video-link-youtube");
|
|
773
772
|
el.removeAttribute("href");
|
|
774
773
|
const vid = match[1];
|
|
775
|
-
const thumbnail = proxifyImageSrc(`https://img.youtube.com/vi/${vid.split("?")[0]}/hqdefault.jpg`, 0, 0,
|
|
774
|
+
const thumbnail = proxifyImageSrc(`https://img.youtube.com/vi/${vid.split("?")[0]}/hqdefault.jpg`, 0, 0, "match");
|
|
776
775
|
const embedSrc = `https://www.youtube.com/embed/${vid}?autoplay=1`;
|
|
777
776
|
el.textContent = "";
|
|
778
777
|
el.setAttribute("data-embed-src", embedSrc);
|
|
@@ -868,7 +867,7 @@ function a(el, forApp, webp, parentDomain = "ecency.com", seoContext) {
|
|
|
868
867
|
if (imgEls.length === 1) {
|
|
869
868
|
const src = imgEls[0].getAttribute("src");
|
|
870
869
|
if (src) {
|
|
871
|
-
const thumbnail = proxifyImageSrc(src.replace(/\s+/g, ""), 0, 0,
|
|
870
|
+
const thumbnail = proxifyImageSrc(src.replace(/\s+/g, ""), 0, 0, "match");
|
|
872
871
|
const thumbImg = el.ownerDocument.createElement("img");
|
|
873
872
|
thumbImg.setAttribute("class", "no-replace video-thumbnail");
|
|
874
873
|
thumbImg.setAttribute("itemprop", "thumbnailUrl");
|
|
@@ -903,7 +902,7 @@ function a(el, forApp, webp, parentDomain = "ecency.com", seoContext) {
|
|
|
903
902
|
const imgEls2 = el.getElementsByTagName("img");
|
|
904
903
|
if (imgEls2.length === 1 || el.textContent.trim() === href) {
|
|
905
904
|
if ((match[1] || match[2]) && match[3]) {
|
|
906
|
-
const videoHref = `https://play.3speak.tv/
|
|
905
|
+
const videoHref = `https://play.3speak.tv/embed?v=${match[3]}&mode=iframe`;
|
|
907
906
|
el.setAttribute("class", "markdown-video-link markdown-video-link-speak");
|
|
908
907
|
el.removeAttribute("href");
|
|
909
908
|
el.setAttribute("data-embed-src", videoHref);
|
|
@@ -913,7 +912,7 @@ function a(el, forApp, webp, parentDomain = "ecency.com", seoContext) {
|
|
|
913
912
|
if (imgEls2.length === 1) {
|
|
914
913
|
const src = imgEls2[0].getAttribute("src");
|
|
915
914
|
if (src) {
|
|
916
|
-
const thumbnail = proxifyImageSrc(src.replace(/\s+/g, ""), 0, 0,
|
|
915
|
+
const thumbnail = proxifyImageSrc(src.replace(/\s+/g, ""), 0, 0, "match");
|
|
917
916
|
const thumbImg = el.ownerDocument.createElement("img");
|
|
918
917
|
thumbImg.setAttribute("class", "no-replace video-thumbnail");
|
|
919
918
|
thumbImg.setAttribute("itemprop", "thumbnailUrl");
|
|
@@ -1036,7 +1035,8 @@ function iframe(el, parentDomain = "ecency.com") {
|
|
|
1036
1035
|
return;
|
|
1037
1036
|
}
|
|
1038
1037
|
if (src.match(SPEAK_EMBED_REGEX)) {
|
|
1039
|
-
let normalizedSrc = src.replace(/3speak\.[a-z]+/i, "play.3speak.tv");
|
|
1038
|
+
let normalizedSrc = src.replace(/(?:play\.)?3speak\.[a-z]+/i, "play.3speak.tv");
|
|
1039
|
+
normalizedSrc = normalizedSrc.replace(/\/watch\?/, "/embed?");
|
|
1040
1040
|
const hasMode = /[?&]mode=/.test(normalizedSrc);
|
|
1041
1041
|
if (!hasMode) {
|
|
1042
1042
|
normalizedSrc = `${normalizedSrc}&mode=iframe`;
|
|
@@ -1044,6 +1044,7 @@ function iframe(el, parentDomain = "ecency.com") {
|
|
|
1044
1044
|
const hasAutoplay = /[?&]autoplay=/.test(normalizedSrc);
|
|
1045
1045
|
const s = hasAutoplay ? normalizedSrc : `${normalizedSrc}&autoplay=true`;
|
|
1046
1046
|
el.setAttribute("src", s);
|
|
1047
|
+
el.setAttribute("class", "speak-iframe");
|
|
1047
1048
|
return;
|
|
1048
1049
|
}
|
|
1049
1050
|
if (src.match(SPOTIFY_EMBED_REGEX)) {
|
|
@@ -1152,7 +1153,7 @@ function p(el) {
|
|
|
1152
1153
|
}
|
|
1153
1154
|
|
|
1154
1155
|
// src/methods/linkify.method.ts
|
|
1155
|
-
function linkify(content, forApp
|
|
1156
|
+
function linkify(content, forApp) {
|
|
1156
1157
|
content = content.replace(/(^|\s|>)(#[-a-z\d]+)/gi, (tag) => {
|
|
1157
1158
|
if (/#[\d]+$/.test(tag)) return tag;
|
|
1158
1159
|
const preceding = /^\s|>/.test(tag) ? tag[0] : "";
|
|
@@ -1194,21 +1195,21 @@ function linkify(content, forApp, webp) {
|
|
|
1194
1195
|
content = content.replace(IMG_REGEX, (imglink) => {
|
|
1195
1196
|
const isLCP = !firstImageUsed;
|
|
1196
1197
|
firstImageUsed = true;
|
|
1197
|
-
return createImageHTML(imglink, isLCP
|
|
1198
|
+
return createImageHTML(imglink, isLCP);
|
|
1198
1199
|
});
|
|
1199
1200
|
return content;
|
|
1200
1201
|
}
|
|
1201
1202
|
|
|
1202
1203
|
// src/methods/text.method.ts
|
|
1203
|
-
function text(node, forApp
|
|
1204
|
+
function text(node, forApp) {
|
|
1204
1205
|
if (!node || !node.parentNode) {
|
|
1205
1206
|
return;
|
|
1206
1207
|
}
|
|
1207
|
-
if (
|
|
1208
|
+
if (["a", "code"].includes(node.parentNode.nodeName.toLowerCase())) {
|
|
1208
1209
|
return;
|
|
1209
1210
|
}
|
|
1210
1211
|
const nodeValue = node.nodeValue || "";
|
|
1211
|
-
const linkified = linkify(nodeValue, forApp
|
|
1212
|
+
const linkified = linkify(nodeValue, forApp);
|
|
1212
1213
|
if (linkified !== nodeValue) {
|
|
1213
1214
|
const doc = DOMParser.parseFromString(
|
|
1214
1215
|
`<span class="wr">${linkified}</span>`,
|
|
@@ -1223,7 +1224,7 @@ function text(node, forApp, webp) {
|
|
|
1223
1224
|
}
|
|
1224
1225
|
if (nodeValue.match(IMG_REGEX)) {
|
|
1225
1226
|
const isLCP = false;
|
|
1226
|
-
const imageHTML = createImageHTML(nodeValue, isLCP
|
|
1227
|
+
const imageHTML = createImageHTML(nodeValue, isLCP);
|
|
1227
1228
|
const doc = DOMParser.parseFromString(imageHTML, "text/html");
|
|
1228
1229
|
const replaceNode = doc.body?.firstChild || doc.firstChild;
|
|
1229
1230
|
if (replaceNode) {
|
|
@@ -1235,7 +1236,7 @@ function text(node, forApp, webp) {
|
|
|
1235
1236
|
const e = YOUTUBE_REGEX.exec(nodeValue);
|
|
1236
1237
|
if (e && e[1]) {
|
|
1237
1238
|
const vid = e[1];
|
|
1238
|
-
const thumbnail = proxifyImageSrc(`https://img.youtube.com/vi/${vid.split("?")[0]}/hqdefault.jpg`, 0, 0,
|
|
1239
|
+
const thumbnail = proxifyImageSrc(`https://img.youtube.com/vi/${vid.split("?")[0]}/hqdefault.jpg`, 0, 0, "match");
|
|
1239
1240
|
const embedSrc = `https://www.youtube.com/embed/${vid}?autoplay=1`;
|
|
1240
1241
|
const startTime = extractYtStartTime(nodeValue);
|
|
1241
1242
|
const container = node.ownerDocument.createElement("p");
|
|
@@ -1281,7 +1282,7 @@ function text(node, forApp, webp) {
|
|
|
1281
1282
|
}
|
|
1282
1283
|
|
|
1283
1284
|
// src/methods/traverse.method.ts
|
|
1284
|
-
function traverse(node, forApp, depth = 0,
|
|
1285
|
+
function traverse(node, forApp, depth = 0, state = { firstImageFound: false }, parentDomain = "ecency.com", seoContext) {
|
|
1285
1286
|
if (!node || !node.childNodes) {
|
|
1286
1287
|
return;
|
|
1287
1288
|
}
|
|
@@ -1289,23 +1290,23 @@ function traverse(node, forApp, depth = 0, webp = false, state = { firstImageFou
|
|
|
1289
1290
|
const child = node.childNodes[i];
|
|
1290
1291
|
if (!child) return;
|
|
1291
1292
|
if (child.nodeName.toLowerCase() === "a") {
|
|
1292
|
-
a(child, forApp,
|
|
1293
|
+
a(child, forApp, parentDomain, seoContext);
|
|
1293
1294
|
}
|
|
1294
1295
|
if (child.nodeName.toLowerCase() === "iframe") {
|
|
1295
1296
|
iframe(child, parentDomain);
|
|
1296
1297
|
}
|
|
1297
1298
|
if (child.nodeName === "#text") {
|
|
1298
|
-
text(child, forApp
|
|
1299
|
+
text(child, forApp);
|
|
1299
1300
|
}
|
|
1300
1301
|
if (child.nodeName.toLowerCase() === "img") {
|
|
1301
|
-
img(child,
|
|
1302
|
+
img(child, state);
|
|
1302
1303
|
}
|
|
1303
1304
|
if (child.nodeName.toLowerCase() === "p") {
|
|
1304
1305
|
p(child);
|
|
1305
1306
|
}
|
|
1306
1307
|
const currentChild = node.childNodes[i];
|
|
1307
1308
|
if (currentChild) {
|
|
1308
|
-
traverse(currentChild, forApp, depth + 1,
|
|
1309
|
+
traverse(currentChild, forApp, depth + 1, state, parentDomain, seoContext);
|
|
1309
1310
|
}
|
|
1310
1311
|
});
|
|
1311
1312
|
}
|
|
@@ -1356,7 +1357,7 @@ function fixBlockLevelTagsInParagraphs(html) {
|
|
|
1356
1357
|
html = html.replace(/<p><br>\s*<\/p>/g, "");
|
|
1357
1358
|
return html;
|
|
1358
1359
|
}
|
|
1359
|
-
function markdownToHTML(input, forApp,
|
|
1360
|
+
function markdownToHTML(input, forApp, parentDomain = "ecency.com", seoContext) {
|
|
1360
1361
|
input = input.replace(new RegExp("https://leofinance.io/threads/view/", "g"), "/@");
|
|
1361
1362
|
input = input.replace(new RegExp("https://leofinance.io/posts/", "g"), "/@");
|
|
1362
1363
|
input = input.replace(new RegExp("https://leofinance.io/threads/", "g"), "/@");
|
|
@@ -1416,7 +1417,7 @@ function markdownToHTML(input, forApp, webp, parentDomain = "ecency.com", seoCon
|
|
|
1416
1417
|
output = md.render(input);
|
|
1417
1418
|
output = fixBlockLevelTagsInParagraphs(output);
|
|
1418
1419
|
const doc = DOMParser.parseFromString(`<body id="root">${removeDuplicateAttributes(output)}</body>`, "text/html");
|
|
1419
|
-
traverse(doc, forApp, 0,
|
|
1420
|
+
traverse(doc, forApp, 0, { firstImageFound: false }, parentDomain, seoContext);
|
|
1420
1421
|
output = serializer.serializeToString(doc);
|
|
1421
1422
|
} catch (error) {
|
|
1422
1423
|
try {
|
|
@@ -1429,7 +1430,7 @@ function markdownToHTML(input, forApp, webp, parentDomain = "ecency.com", seoCon
|
|
|
1429
1430
|
});
|
|
1430
1431
|
const repairedHtml = domSerializer(dom.children);
|
|
1431
1432
|
const doc = DOMParser.parseFromString(`<body id="root">${removeDuplicateAttributes(repairedHtml)}</body>`, "text/html");
|
|
1432
|
-
traverse(doc, forApp, 0,
|
|
1433
|
+
traverse(doc, forApp, 0, { firstImageFound: false }, parentDomain, seoContext);
|
|
1433
1434
|
output = serializer.serializeToString(doc);
|
|
1434
1435
|
} catch (fallbackError) {
|
|
1435
1436
|
const escapedContent = he2.encode(output || md.render(input));
|
|
@@ -1457,18 +1458,18 @@ function cacheSet(key, value) {
|
|
|
1457
1458
|
}
|
|
1458
1459
|
|
|
1459
1460
|
// src/markdown-2-html.ts
|
|
1460
|
-
function markdown2Html(obj, forApp = true,
|
|
1461
|
+
function markdown2Html(obj, forApp = true, _webp = false, parentDomain = "ecency.com", seoContext) {
|
|
1461
1462
|
if (typeof obj === "string") {
|
|
1462
1463
|
const cleanedStr = cleanReply(obj);
|
|
1463
|
-
return markdownToHTML(cleanedStr, forApp,
|
|
1464
|
+
return markdownToHTML(cleanedStr, forApp, parentDomain, seoContext);
|
|
1464
1465
|
}
|
|
1465
|
-
const key = `${makeEntryCacheKey(obj)}-md
|
|
1466
|
+
const key = `${makeEntryCacheKey(obj)}-md-${forApp ? "app" : "site"}-${parentDomain}${seoContext ? `-seo${seoContext.authorReputation ?? ""}-${seoContext.postPayout ?? ""}` : ""}`;
|
|
1466
1467
|
const item = cacheGet(key);
|
|
1467
1468
|
if (item) {
|
|
1468
1469
|
return item;
|
|
1469
1470
|
}
|
|
1470
1471
|
const cleanBody = cleanReply(obj.body);
|
|
1471
|
-
const res = markdownToHTML(cleanBody, forApp,
|
|
1472
|
+
const res = markdownToHTML(cleanBody, forApp, parentDomain, seoContext);
|
|
1472
1473
|
cacheSet(key, res);
|
|
1473
1474
|
return res;
|
|
1474
1475
|
}
|