@ecency/render-helper 2.4.25 → 2.4.27

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.
@@ -433,7 +433,7 @@ var addLineBreakBeforePostLink = (el, forApp, isInline) => {
433
433
  el.parentNode.insertBefore(br, el);
434
434
  }
435
435
  };
436
- function a(el, forApp, parentDomain = "ecency.com", seoContext) {
436
+ function a(el, forApp, parentDomain = "ecency.com", seoContext, renderOptions) {
437
437
  if (!el || !el.parentNode) {
438
438
  return;
439
439
  }
@@ -442,7 +442,7 @@ function a(el, forApp, parentDomain = "ecency.com", seoContext) {
442
442
  return;
443
443
  }
444
444
  const className = el.getAttribute("class");
445
- if (["markdown-author-link", "markdown-tag-link"].indexOf(className) !== -1) {
445
+ if (className && (["markdown-author-link", "markdown-tag-link"].includes(className) || className.includes("er-author") || className.includes("er-tag"))) {
446
446
  return;
447
447
  }
448
448
  if (href && href.trim().toLowerCase().startsWith("javascript:")) {
@@ -782,14 +782,29 @@ function a(el, forApp, parentDomain = "ecency.com", seoContext) {
782
782
  if (startTime) {
783
783
  el.setAttribute("data-start-time", startTime);
784
784
  }
785
- const thumbImg = el.ownerDocument.createElement("img");
786
- thumbImg.setAttribute("class", "no-replace video-thumbnail");
787
- thumbImg.setAttribute("itemprop", "thumbnailUrl");
788
- thumbImg.setAttribute("src", thumbnail);
789
- const play = el.ownerDocument.createElement("span");
790
- play.setAttribute("class", "markdown-video-play");
791
- el.appendChild(thumbImg);
792
- el.appendChild(play);
785
+ if (renderOptions?.embedVideosDirectly) {
786
+ const wrapper = el.ownerDocument.createElement("span");
787
+ wrapper.setAttribute("class", "er-youtube-frame");
788
+ wrapper.setAttribute("style", "display:block");
789
+ const iframe2 = el.ownerDocument.createElement("iframe");
790
+ iframe2.setAttribute("class", "youtube-player");
791
+ iframe2.setAttribute("src", embedSrc);
792
+ iframe2.setAttribute("title", "YouTube video");
793
+ iframe2.setAttribute("allow", "accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture; web-share");
794
+ iframe2.setAttribute("allowfullscreen", "");
795
+ wrapper.appendChild(iframe2);
796
+ el.appendChild(wrapper);
797
+ el.setAttribute("class", "markdown-video-link markdown-video-link-youtube er-youtube");
798
+ } else {
799
+ const thumbImg = el.ownerDocument.createElement("img");
800
+ thumbImg.setAttribute("class", "no-replace video-thumbnail");
801
+ thumbImg.setAttribute("itemprop", "thumbnailUrl");
802
+ thumbImg.setAttribute("src", thumbnail);
803
+ const play = el.ownerDocument.createElement("span");
804
+ play.setAttribute("class", "markdown-video-play");
805
+ el.appendChild(thumbImg);
806
+ el.appendChild(play);
807
+ }
793
808
  return;
794
809
  }
795
810
  match = href.match(VIMEO_REGEX);
@@ -911,21 +926,36 @@ function a(el, forApp, parentDomain = "ecency.com", seoContext) {
911
926
  if (el.textContent.trim() === href) {
912
927
  el.textContent = "";
913
928
  }
914
- if (imgEls2.length === 1) {
915
- const src = imgEls2[0].getAttribute("src");
916
- if (src) {
917
- const thumbnail = proxifyImageSrc(src.replace(/\s+/g, ""), 0, 0, "match");
918
- const thumbImg = el.ownerDocument.createElement("img");
919
- thumbImg.setAttribute("class", "no-replace video-thumbnail");
920
- thumbImg.setAttribute("itemprop", "thumbnailUrl");
921
- thumbImg.setAttribute("src", thumbnail);
922
- el.appendChild(thumbImg);
923
- el.removeChild(imgEls2[0]);
929
+ if (renderOptions?.embedVideosDirectly) {
930
+ const wrapper = el.ownerDocument.createElement("span");
931
+ wrapper.setAttribute("class", "er-speak-frame");
932
+ wrapper.setAttribute("style", "display:block");
933
+ const iframe2 = el.ownerDocument.createElement("iframe");
934
+ iframe2.setAttribute("class", "speak-iframe");
935
+ iframe2.setAttribute("src", videoHref);
936
+ iframe2.setAttribute("title", "3Speak video");
937
+ iframe2.setAttribute("allow", "accelerometer; encrypted-media; gyroscope; picture-in-picture; web-share");
938
+ iframe2.setAttribute("allowfullscreen", "");
939
+ wrapper.appendChild(iframe2);
940
+ el.appendChild(wrapper);
941
+ el.setAttribute("class", "markdown-video-link markdown-video-link-speak er-speak");
942
+ } else {
943
+ if (imgEls2.length === 1) {
944
+ const src = imgEls2[0].getAttribute("src");
945
+ if (src) {
946
+ const thumbnail = proxifyImageSrc(src.replace(/\s+/g, ""), 0, 0, "match");
947
+ const thumbImg = el.ownerDocument.createElement("img");
948
+ thumbImg.setAttribute("class", "no-replace video-thumbnail");
949
+ thumbImg.setAttribute("itemprop", "thumbnailUrl");
950
+ thumbImg.setAttribute("src", thumbnail);
951
+ el.appendChild(thumbImg);
952
+ el.removeChild(imgEls2[0]);
953
+ }
924
954
  }
955
+ const play = el.ownerDocument.createElement("span");
956
+ play.setAttribute("class", "markdown-video-play");
957
+ el.appendChild(play);
925
958
  }
926
- const play = el.ownerDocument.createElement("span");
927
- play.setAttribute("class", "markdown-video-play");
928
- el.appendChild(play);
929
959
  return;
930
960
  }
931
961
  }
@@ -1187,24 +1217,33 @@ function p(el) {
1187
1217
  }
1188
1218
 
1189
1219
  // src/methods/linkify.method.ts
1190
- function linkify(content, forApp) {
1220
+ function linkify(content, forApp, renderOptions) {
1191
1221
  content = content.replace(/(^|\s|>)(#[-a-z\d]+)/gi, (tag) => {
1192
1222
  if (/#[\d]+$/.test(tag)) return tag;
1193
1223
  const preceding = /^\s|>/.test(tag) ? tag[0] : "";
1194
1224
  tag = tag.replace(">", "");
1195
1225
  const tag2 = tag.trim().substring(1);
1196
1226
  const tagLower = tag2.toLowerCase();
1197
- const attrs = forApp ? `data-tag="${tagLower}"` : `href="/trending/${tagLower}"`;
1198
- return `${preceding}<a class="markdown-tag-link" ${attrs}>${tag.trim()}</a>`;
1227
+ if (!forApp) {
1228
+ return `${preceding}<a class="er-tag er-tag-link" href="/trending/${tagLower}">${tag.trim()}</a>`;
1229
+ }
1230
+ return `${preceding}<a class="markdown-tag-link" data-tag="${tagLower}">${tag.trim()}</a>`;
1199
1231
  });
1232
+ const authorPlaceholders = [];
1200
1233
  content = content.replace(
1201
1234
  /(^|[^a-zA-Z0-9_!#$%&*@@/]|(^|[^a-zA-Z0-9_+~.-/]))[@@]([a-z][-.a-z\d^/]+[a-z\d])/gi,
1202
1235
  (match, preceeding1, preceeding2, user) => {
1203
1236
  const userLower = user.toLowerCase();
1204
1237
  const preceedings = (preceeding1 || "") + (preceeding2 || "");
1205
1238
  if (userLower.indexOf("/") === -1 && isValidUsername(user)) {
1206
- const attrs = forApp ? `data-author="${userLower}"` : `href="/@${userLower}"`;
1207
- return `${preceedings}<a class="markdown-author-link" ${attrs}>@${user}</a>`;
1239
+ if (!forApp) {
1240
+ const avatarSrc = `https://images.ecency.com/u/${userLower}/avatar/small`;
1241
+ const html = `${preceedings}<a class="er-author er-author-link" href="/@${userLower}"><img class="er-author-link-image" src="${avatarSrc}" alt="${userLower}"/><span class="er-author-link-content"><span class="er-author-link-label">Hive account</span><span>@${userLower}</span></span></a>`;
1242
+ const placeholder = `\u200C${authorPlaceholders.length}\u200C`;
1243
+ authorPlaceholders.push({ placeholder, html });
1244
+ return placeholder;
1245
+ }
1246
+ return `${preceedings}<a class="markdown-author-link" data-author="${userLower}">@${user}</a>`;
1208
1247
  } else {
1209
1248
  return match;
1210
1249
  }
@@ -1247,6 +1286,9 @@ function linkify(content, forApp) {
1247
1286
  firstImageUsed = true;
1248
1287
  return createImageHTML(imglink, isLCP);
1249
1288
  });
1289
+ authorPlaceholders.forEach(({ placeholder, html }) => {
1290
+ content = content.replace(placeholder, html);
1291
+ });
1250
1292
  return content;
1251
1293
  }
1252
1294
 
@@ -1261,7 +1303,7 @@ function hasAncestor(node, tagNames) {
1261
1303
  }
1262
1304
  return false;
1263
1305
  }
1264
- function text(node, forApp) {
1306
+ function text(node, forApp, renderOptions) {
1265
1307
  if (!node || !node.parentNode) {
1266
1308
  return;
1267
1309
  }
@@ -1342,7 +1384,7 @@ function text(node, forApp) {
1342
1384
  }
1343
1385
 
1344
1386
  // src/methods/traverse.method.ts
1345
- function traverse(node, forApp, depth = 0, state = { firstImageFound: false }, parentDomain = "ecency.com", seoContext) {
1387
+ function traverse(node, forApp, depth = 0, state = { firstImageFound: false }, parentDomain = "ecency.com", seoContext, renderOptions) {
1346
1388
  if (!node || !node.childNodes) {
1347
1389
  return;
1348
1390
  }
@@ -1351,7 +1393,7 @@ function traverse(node, forApp, depth = 0, state = { firstImageFound: false }, p
1351
1393
  const next = child.nextSibling;
1352
1394
  const prev = child.previousSibling;
1353
1395
  if (child.nodeName.toLowerCase() === "a") {
1354
- a(child, forApp, parentDomain, seoContext);
1396
+ a(child, forApp, parentDomain, seoContext, renderOptions);
1355
1397
  }
1356
1398
  if (child.nodeName.toLowerCase() === "iframe") {
1357
1399
  iframe(child, parentDomain, forApp);
@@ -1366,11 +1408,11 @@ function traverse(node, forApp, depth = 0, state = { firstImageFound: false }, p
1366
1408
  p(child);
1367
1409
  }
1368
1410
  if (child.parentNode) {
1369
- traverse(child, forApp, depth + 1, state, parentDomain, seoContext);
1411
+ traverse(child, forApp, depth + 1, state, parentDomain, seoContext, renderOptions);
1370
1412
  } else {
1371
1413
  const possibleReplacement = next ? next.previousSibling : node.lastChild;
1372
1414
  if (possibleReplacement && possibleReplacement !== prev && possibleReplacement.parentNode === node) {
1373
- traverse(possibleReplacement, forApp, depth + 1, state, parentDomain, seoContext);
1415
+ traverse(possibleReplacement, forApp, depth + 1, state, parentDomain, seoContext, renderOptions);
1374
1416
  }
1375
1417
  }
1376
1418
  child = next;
@@ -1423,7 +1465,7 @@ function fixBlockLevelTagsInParagraphs(html) {
1423
1465
  html = html.replace(/<p><br>\s*<\/p>/g, "");
1424
1466
  return html;
1425
1467
  }
1426
- function markdownToHTML(input, forApp, parentDomain = "ecency.com", seoContext) {
1468
+ function markdownToHTML(input, forApp, parentDomain = "ecency.com", seoContext, renderOptions) {
1427
1469
  input = input.replace(new RegExp("https://leofinance.io/threads/view/", "g"), "/@");
1428
1470
  input = input.replace(new RegExp("https://leofinance.io/posts/", "g"), "/@");
1429
1471
  input = input.replace(new RegExp("https://leofinance.io/threads/", "g"), "/@");
@@ -1483,7 +1525,7 @@ function markdownToHTML(input, forApp, parentDomain = "ecency.com", seoContext)
1483
1525
  output = md.render(input);
1484
1526
  output = fixBlockLevelTagsInParagraphs(output);
1485
1527
  const doc = DOMParser.parseFromString(`<body id="root">${removeDuplicateAttributes(output)}</body>`, "text/html");
1486
- traverse(doc, forApp, 0, { firstImageFound: false }, parentDomain, seoContext);
1528
+ traverse(doc, forApp, 0, { firstImageFound: false }, parentDomain, seoContext, renderOptions);
1487
1529
  output = serializer.serializeToString(doc);
1488
1530
  } catch (error) {
1489
1531
  try {
@@ -1496,7 +1538,7 @@ function markdownToHTML(input, forApp, parentDomain = "ecency.com", seoContext)
1496
1538
  });
1497
1539
  const repairedHtml = domSerializer(dom.children);
1498
1540
  const doc = DOMParser.parseFromString(`<body id="root">${removeDuplicateAttributes(repairedHtml)}</body>`, "text/html");
1499
- traverse(doc, forApp, 0, { firstImageFound: false }, parentDomain, seoContext);
1541
+ traverse(doc, forApp, 0, { firstImageFound: false }, parentDomain, seoContext, renderOptions);
1500
1542
  output = serializer.serializeToString(doc);
1501
1543
  } catch (fallbackError) {
1502
1544
  const escapedContent = he2.encode(output || md.render(input));
@@ -1524,18 +1566,18 @@ function cacheSet(key, value) {
1524
1566
  }
1525
1567
 
1526
1568
  // src/markdown-2-html.ts
1527
- function markdown2Html(obj, forApp = true, _webp = false, parentDomain = "ecency.com", seoContext) {
1569
+ function markdown2Html(obj, forApp = true, _webp = false, parentDomain = "ecency.com", seoContext, renderOptions) {
1528
1570
  if (typeof obj === "string") {
1529
1571
  const cleanedStr = cleanReply(obj);
1530
- return markdownToHTML(cleanedStr, forApp, parentDomain, seoContext);
1572
+ return markdownToHTML(cleanedStr, forApp, parentDomain, seoContext, renderOptions);
1531
1573
  }
1532
- const key = `${makeEntryCacheKey(obj)}-md-${forApp ? "app" : "site"}-${parentDomain}${seoContext ? `-seo${seoContext.authorReputation ?? ""}-${seoContext.postPayout ?? ""}` : ""}`;
1574
+ const key = `${makeEntryCacheKey(obj)}-md-${forApp ? "app" : "site"}-${parentDomain}${seoContext ? `-seo${seoContext.authorReputation ?? ""}-${seoContext.postPayout ?? ""}` : ""}${renderOptions?.embedVideosDirectly ? "-embed" : ""}`;
1533
1575
  const item = cacheGet(key);
1534
1576
  if (item) {
1535
1577
  return item;
1536
1578
  }
1537
1579
  const cleanBody = cleanReply(obj.body);
1538
- const res = markdownToHTML(cleanBody, forApp, parentDomain, seoContext);
1580
+ const res = markdownToHTML(cleanBody, forApp, parentDomain, seoContext, renderOptions);
1539
1581
  cacheSet(key, res);
1540
1582
  return res;
1541
1583
  }