@ecency/render-helper 2.5.21 → 2.5.23

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.
@@ -71,15 +71,16 @@ var VIMEO_EMBED_REGEX = /https:\/\/player\.vimeo\.com\/video\/([0-9]+)(?:$|[?#])
71
71
  var BITCHUTE_REGEX = /^(?:https?:\/\/)?(?:www\.)?bitchute\.com\/(?:video|embed)\/([a-z0-9]+)/i;
72
72
  var D_TUBE_REGEX = /(https?:\/\/d\.tube\/#!\/v\/)(\w+)\/(\w+)/g;
73
73
  var D_TUBE_REGEX2 = /(https?:\/\/d\.tube\/v\/)(\w+)\/(\w+)/g;
74
- var D_TUBE_EMBED_REGEX = /^https:\/\/emb.d.tube\/#!\/[^/?#]+\/[^/?#]+(?:$|[?#])/i;
74
+ var D_TUBE_EMBED_REGEX = /^https:\/\/emb\.d\.tube\/#!\/[^/?#]+\/[^/?#]+(?:$|[?#])/i;
75
75
  var TWITCH_REGEX = /https?:\/\/(?:www\.)?twitch\.tv\/(?:(videos)\/)?([a-zA-Z0-9][\w]{3,24})/i;
76
- var DAPPLR_REGEX = /^(https?:)?\/\/[a-z]*\.dapplr.in\/file\/dapplr-videos\/.*/i;
77
- var TRUVVL_REGEX = /^https?:\/\/embed.truvvl.com\/(@[\w.\d-]+)\/(.*)/i;
78
- var LBRY_REGEX = /^(https?:)?\/\/lbry.tv\/\$\/embed\/[^?#]+(?:$|[?#])/i;
76
+ var DAPPLR_REGEX = /^(https?:)?\/\/[a-z]*\.dapplr\.in\/file\/dapplr-videos\/.*/i;
77
+ var TRUVVL_REGEX = /^https?:\/\/embed\.truvvl\.com\/(@[\w.\d-]+)\/(.*)/i;
78
+ var LBRY_REGEX = /^(https?:)?\/\/lbry\.tv\/\$\/embed\/[^?#]+(?:$|[?#])/i;
79
79
  var ODYSEE_REGEX = /^(https?:)?\/\/odysee\.com\/(?:\$|%24)\/embed\/[^?#]+(?:$|[?#])/i;
80
+ var ODYSEE_WATCH_REGEX = /^(?:https?:)?\/\/odysee\.com\/(@[^/?#\s:"'<>\\]+:[^/?#\s:"'<>\\]+\/[^/?#\s:"'<>\\]+:[^/?#\s:"'<>\\]+|[^@/?#\s:"'<>\\][^/?#\s:"'<>\\]*:[^/?#\s:"'<>\\]+)(?:$|[?#])/i;
80
81
  var SKATEHIVE_IPFS_REGEX = /^https?:\/\/ipfs\.skatehive\.app\/ipfs\/([^/?#]+)/i;
81
82
  var SKATEHYPE_EMBED_REGEX = /^(https?:)?\/\/(www\.)?skatehype\.com\/ifplay\.php\?v=\d+(?:$|[&#])/i;
82
- var ARCH_REGEX = /^(https?:)?\/\/archive.org\/embed\/[^/?#]+(?:$|[?#])/i;
83
+ var ARCH_REGEX = /^(https?:)?\/\/archive\.org\/embed\/[^/?#]+(?:$|[?#])/i;
83
84
  var SPEAK_REGEX = /(?:https?:\/\/(?:(?:play\.)?3speak\.([a-z]+)\/watch\?v=)|(?:(?:play\.)?3speak\.([a-z]+)\/embed\?v=))([A-Za-z0-9_\-\.\/]+)(&.*)?/i;
84
85
  var SPEAK_EMBED_REGEX = /^(https?:)?\/\/(?:play\.)?3speak\.([a-z]+)\/(?:embed|watch)\?.+$/i;
85
86
  var SPEAK_AUDIO_REGEX = /https?:\/\/audio\.3speak\.tv\/play\?[^\s]+/i;
@@ -98,7 +99,6 @@ var LOOM_REGEX = /^(https?:)?\/\/www\.loom\.com\/share\/([^/?#]+)(?:$|[?#])/i;
98
99
  var LOOM_EMBED_REGEX = /^(https?:)?\/\/www\.loom\.com\/embed\/([^/?#]+)(?:$|[?#])/i;
99
100
  var AUREAL_EMBED_REGEX = /^(https?:)?\/\/(www\.)?(?:aureal-embed)\.web\.app\/([0-9]+)(?:$|[?#])/i;
100
101
  var ENTITY_REGEX = /&([a-z0-9]+|#[0-9]{1,6}|#x[0-9a-fA-F]{1,6});/ig;
101
- var SECTION_REGEX = /\B(\#[\da-zA-Z-_]+\b)(?!;)/i;
102
102
  var ID_WHITELIST = /^[A-Za-z][-A-Za-z0-9_]*$/;
103
103
 
104
104
  // src/consts/allowed-attributes.const.ts
@@ -251,7 +251,13 @@ var EMBED_HOST_PATH_PATTERNS = {
251
251
  "www.rumble.com": /^\/embed\//,
252
252
  "rumble.com": /^\/embed\//,
253
253
  "www.brighteon.com": /^\/embed\//,
254
- "brighteon.com": /^\/embed\//
254
+ "brighteon.com": /^\/embed\//,
255
+ // Odysee's embed route is /$/embed/<claim path>. Both the literal `$` and its
256
+ // percent-encoded spelling occur in the wild: the renderer emits the literal
257
+ // form, while Odysee's own share dialog hands out fully-encoded URLs, and
258
+ // `URL.pathname` does not decode either. ODYSEE_REGEX accepts both for the
259
+ // same reason.
260
+ "odysee.com": /^\/(?:\$|%24)\/embed\//
255
261
  };
256
262
  function isAllowedEmbedSrc(value) {
257
263
  if (!value) return false;
@@ -855,6 +861,33 @@ function getExternalLinkRel(seoContext) {
855
861
  }
856
862
  return "nofollow ugc noopener";
857
863
  }
864
+ function renderPlainVideoLink(el, provider, embedSrc, renderOptions) {
865
+ const baseClass = `markdown-video-link markdown-video-link-${provider}`;
866
+ el.setAttribute("class", baseClass);
867
+ el.removeAttribute("href");
868
+ el.textContent = "";
869
+ el.setAttribute("data-embed-src", embedSrc);
870
+ if (renderOptions?.embedVideosDirectly) {
871
+ const wrapper = el.ownerDocument.createElement("span");
872
+ wrapper.setAttribute("class", "er-embed-frame");
873
+ wrapper.setAttribute("style", "display:block");
874
+ const frame = el.ownerDocument.createElement("iframe");
875
+ frame.setAttribute("src", embedSrc);
876
+ frame.setAttribute("title", "Video player");
877
+ frame.setAttribute(
878
+ "allow",
879
+ "accelerometer; encrypted-media; gyroscope; picture-in-picture; web-share"
880
+ );
881
+ frame.setAttribute("allowfullscreen", "");
882
+ wrapper.appendChild(frame);
883
+ el.appendChild(wrapper);
884
+ el.setAttribute("class", `${baseClass} er-embed`);
885
+ return;
886
+ }
887
+ const play = el.ownerDocument.createElement("span");
888
+ play.setAttribute("class", "markdown-video-play");
889
+ el.appendChild(play);
890
+ }
858
891
  var normalizeValue = (value) => value ? value.trim() : "";
859
892
  var matchesHref = (href, value) => {
860
893
  const normalizedHref = normalizeValue(href);
@@ -897,10 +930,6 @@ function a(el, forApp, parentDomain = "ecency.com", seoContext, renderOptions) {
897
930
  if (!href) {
898
931
  return;
899
932
  }
900
- const className = el.getAttribute("class");
901
- if (className && (["markdown-author-link", "markdown-tag-link"].includes(className) || className.includes("er-author") || className.includes("er-tag"))) {
902
- return;
903
- }
904
933
  const trimmed = href.trim().replace(/[\t\n\r\f\v\0]/g, "").toLowerCase();
905
934
  const isSafeScheme = /^(https?|mailto|hive|tel|web\+[a-z0-9.+-]+):/i.test(trimmed);
906
935
  const isRelative = /^(\/\/|\/[^/]?|#|\?|[a-z0-9._\-]+(\/|$))/i.test(trimmed);
@@ -908,6 +937,13 @@ function a(el, forApp, parentDomain = "ecency.com", seoContext, renderOptions) {
908
937
  el.removeAttribute("href");
909
938
  return;
910
939
  }
940
+ const className = el.getAttribute("class");
941
+ if (className && (["markdown-author-link", "markdown-tag-link"].includes(className) || className.includes("er-author") || className.includes("er-tag"))) {
942
+ if (el.getAttribute("target")) {
943
+ el.setAttribute("rel", getExternalLinkRel(seoContext));
944
+ }
945
+ return;
946
+ }
911
947
  if (href.match(IMG_REGEX) && href.trim().replace(/&amp;/g, "&") === getSerializedInnerHTML(el).trim().replace(/&amp;/g, "&")) {
912
948
  const isLCP = false;
913
949
  const imgHTML = createImageHTML(href, isLCP, forApp);
@@ -1190,41 +1226,22 @@ function a(el, forApp, parentDomain = "ecency.com", seoContext, renderOptions) {
1190
1226
  }
1191
1227
  const BCmatch = href.match(BITCHUTE_REGEX);
1192
1228
  if (BCmatch && BCmatch[1] && el.textContent.trim() === href) {
1193
- const vid = BCmatch[1];
1194
- el.setAttribute("class", "markdown-video-link");
1195
- el.removeAttribute("href");
1196
- const embedSrc = `https://www.bitchute.com/embed/${vid}/`;
1197
- el.textContent = "";
1198
- el.setAttribute("data-embed-src", embedSrc);
1199
- const play = el.ownerDocument.createElement("span");
1200
- play.setAttribute("class", "markdown-video-play");
1201
- el.appendChild(play);
1229
+ renderPlainVideoLink(el, "bitchute", `https://www.bitchute.com/embed/${BCmatch[1]}/`, renderOptions);
1202
1230
  return;
1203
1231
  }
1204
1232
  const RBmatch = href.match(RUMBLE_REGEX);
1205
1233
  if (RBmatch && RBmatch[1] && el.textContent.trim() === href) {
1206
- const vid = RBmatch[1];
1207
- const embedSrc = `https://www.rumble.com/embed/${vid}/?pub=4`;
1208
- el.setAttribute("class", "markdown-video-link");
1209
- el.removeAttribute("href");
1210
- el.textContent = "";
1211
- el.setAttribute("data-embed-src", embedSrc);
1212
- const play = el.ownerDocument.createElement("span");
1213
- play.setAttribute("class", "markdown-video-play");
1214
- el.appendChild(play);
1234
+ renderPlainVideoLink(el, "rumble", `https://www.rumble.com/embed/${RBmatch[1]}/?pub=4`, renderOptions);
1215
1235
  return;
1216
1236
  }
1217
1237
  const BNmatch = href.match(BRIGHTEON_REGEX);
1218
1238
  if (BNmatch && BNmatch[2] && el.textContent.trim() === href) {
1219
- const vid = BNmatch[2];
1220
- const embedSrc = `https://www.brighteon.com/embed/${vid}`;
1221
- el.setAttribute("class", "markdown-video-link");
1222
- el.removeAttribute("href");
1223
- el.textContent = "";
1224
- el.setAttribute("data-embed-src", embedSrc);
1225
- const play = el.ownerDocument.createElement("span");
1226
- play.setAttribute("class", "markdown-video-play");
1227
- el.appendChild(play);
1239
+ renderPlainVideoLink(el, "brighteon", `https://www.brighteon.com/embed/${BNmatch[2]}`, renderOptions);
1240
+ return;
1241
+ }
1242
+ const ODmatch = href.match(ODYSEE_WATCH_REGEX);
1243
+ if (ODmatch && ODmatch[1] && el.textContent.trim() === href) {
1244
+ renderPlainVideoLink(el, "odysee", `https://odysee.com/$/embed/${ODmatch[1]}`, renderOptions);
1228
1245
  return;
1229
1246
  }
1230
1247
  let match = href.match(YOUTUBE_REGEX);
@@ -1505,7 +1522,7 @@ function a(el, forApp, parentDomain = "ecency.com", seoContext, renderOptions) {
1505
1522
  }
1506
1523
  el.removeAttribute("href");
1507
1524
  } else {
1508
- const matchS = href.match(SECTION_REGEX);
1525
+ const matchS = href.trim().startsWith("#");
1509
1526
  if (matchS) {
1510
1527
  el.setAttribute("class", "markdown-internal-link");
1511
1528
  } else {