@ecency/render-helper 2.4.13 → 2.4.15
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 +15 -2
- package/dist/browser/index.js +44 -16
- package/dist/browser/index.js.map +1 -1
- package/dist/node/index.cjs +45 -17
- package/dist/node/index.cjs.map +1 -1
- package/dist/node/index.mjs +45 -17
- package/dist/node/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/node/index.cjs
CHANGED
|
@@ -193,10 +193,11 @@ var ALLOWED_ATTRIBUTES = {
|
|
|
193
193
|
"del": [],
|
|
194
194
|
"ins": []
|
|
195
195
|
};
|
|
196
|
-
var lenientErrorHandler = (level, msg) => {
|
|
197
|
-
if (process.env.NODE_ENV === "development"
|
|
196
|
+
var lenientErrorHandler = (level, msg, context) => {
|
|
197
|
+
if (process.env.NODE_ENV === "development") {
|
|
198
198
|
console.warn("[DOMParser]", level, msg);
|
|
199
199
|
}
|
|
200
|
+
return void 0;
|
|
200
201
|
};
|
|
201
202
|
var DOMParser = new xmldom.DOMParser({
|
|
202
203
|
// Use onError instead of deprecated errorHandler
|
|
@@ -205,11 +206,30 @@ var DOMParser = new xmldom.DOMParser({
|
|
|
205
206
|
});
|
|
206
207
|
|
|
207
208
|
// src/helper.ts
|
|
209
|
+
function removeDuplicateAttributes(html) {
|
|
210
|
+
const tagRegex = /<([a-zA-Z][a-zA-Z0-9]*)\s+((?:[^>"']+|"[^"]*"|'[^']*')*?)\s*(\/?)>/g;
|
|
211
|
+
return html.replace(tagRegex, (match, tagName, attrsString, selfClose) => {
|
|
212
|
+
const seenAttrs = /* @__PURE__ */ new Set();
|
|
213
|
+
const cleanedAttrs = [];
|
|
214
|
+
const attrRegex = /([a-zA-Z_:][-a-zA-Z0-9_:.]*)\s*(?:=\s*(?:"[^"]*"|'[^']*'|[^\s/>]+))?/g;
|
|
215
|
+
let attrMatch;
|
|
216
|
+
while ((attrMatch = attrRegex.exec(attrsString)) !== null) {
|
|
217
|
+
const attrName = attrMatch[1].toLowerCase();
|
|
218
|
+
if (!seenAttrs.has(attrName)) {
|
|
219
|
+
seenAttrs.add(attrName);
|
|
220
|
+
cleanedAttrs.push(attrMatch[0]);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
const attrsJoined = cleanedAttrs.length > 0 ? ` ${cleanedAttrs.join(" ")}` : "";
|
|
224
|
+
return `<${tagName}${attrsJoined}${selfClose ? " /" : ""}>`;
|
|
225
|
+
});
|
|
226
|
+
}
|
|
208
227
|
function createDoc(html) {
|
|
209
228
|
if (html.trim() === "") {
|
|
210
229
|
return null;
|
|
211
230
|
}
|
|
212
|
-
const
|
|
231
|
+
const cleanedHtml = removeDuplicateAttributes(html);
|
|
232
|
+
const doc = DOMParser.parseFromString(`<body>${cleanedHtml}</body>`, "text/html");
|
|
213
233
|
return doc;
|
|
214
234
|
}
|
|
215
235
|
function makeEntryCacheKey(entry) {
|
|
@@ -400,6 +420,14 @@ function createImageHTML(src, isLCP, webp) {
|
|
|
400
420
|
}
|
|
401
421
|
|
|
402
422
|
// src/methods/a.method.ts
|
|
423
|
+
var NOFOLLOW_REPUTATION_THRESHOLD = 40;
|
|
424
|
+
var FOLLOW_PAYOUT_THRESHOLD = 5;
|
|
425
|
+
function getExternalLinkRel(seoContext) {
|
|
426
|
+
if (seoContext?.authorReputation !== void 0 && seoContext?.postPayout !== void 0 && seoContext.authorReputation >= NOFOLLOW_REPUTATION_THRESHOLD && seoContext.postPayout > FOLLOW_PAYOUT_THRESHOLD) {
|
|
427
|
+
return "noopener";
|
|
428
|
+
}
|
|
429
|
+
return "nofollow ugc noopener";
|
|
430
|
+
}
|
|
403
431
|
var normalizeValue = (value) => value ? value.trim() : "";
|
|
404
432
|
var matchesHref = (href, value) => {
|
|
405
433
|
const normalizedHref = normalizeValue(href);
|
|
@@ -433,7 +461,7 @@ var addLineBreakBeforePostLink = (el, forApp, isInline) => {
|
|
|
433
461
|
el.parentNode.insertBefore(br, el);
|
|
434
462
|
}
|
|
435
463
|
};
|
|
436
|
-
function a(el, forApp, webp, parentDomain = "ecency.com") {
|
|
464
|
+
function a(el, forApp, webp, parentDomain = "ecency.com", seoContext) {
|
|
437
465
|
if (!el || !el.parentNode) {
|
|
438
466
|
return;
|
|
439
467
|
}
|
|
@@ -993,7 +1021,7 @@ function a(el, forApp, webp, parentDomain = "ecency.com") {
|
|
|
993
1021
|
el.setAttribute("class", "markdown-internal-link");
|
|
994
1022
|
} else {
|
|
995
1023
|
el.setAttribute("target", "_blank");
|
|
996
|
-
el.setAttribute("rel",
|
|
1024
|
+
el.setAttribute("rel", getExternalLinkRel(seoContext));
|
|
997
1025
|
}
|
|
998
1026
|
el.setAttribute("href", href);
|
|
999
1027
|
}
|
|
@@ -1282,7 +1310,7 @@ function text(node, forApp, webp) {
|
|
|
1282
1310
|
}
|
|
1283
1311
|
|
|
1284
1312
|
// src/methods/traverse.method.ts
|
|
1285
|
-
function traverse(node, forApp, depth = 0, webp = false, state = { firstImageFound: false }, parentDomain = "ecency.com") {
|
|
1313
|
+
function traverse(node, forApp, depth = 0, webp = false, state = { firstImageFound: false }, parentDomain = "ecency.com", seoContext) {
|
|
1286
1314
|
if (!node || !node.childNodes) {
|
|
1287
1315
|
return;
|
|
1288
1316
|
}
|
|
@@ -1290,7 +1318,7 @@ function traverse(node, forApp, depth = 0, webp = false, state = { firstImageFou
|
|
|
1290
1318
|
const child = node.childNodes[i];
|
|
1291
1319
|
if (!child) return;
|
|
1292
1320
|
if (child.nodeName.toLowerCase() === "a") {
|
|
1293
|
-
a(child, forApp, webp, parentDomain);
|
|
1321
|
+
a(child, forApp, webp, parentDomain, seoContext);
|
|
1294
1322
|
}
|
|
1295
1323
|
if (child.nodeName.toLowerCase() === "iframe") {
|
|
1296
1324
|
iframe(child, parentDomain);
|
|
@@ -1306,7 +1334,7 @@ function traverse(node, forApp, depth = 0, webp = false, state = { firstImageFou
|
|
|
1306
1334
|
}
|
|
1307
1335
|
const currentChild = node.childNodes[i];
|
|
1308
1336
|
if (currentChild) {
|
|
1309
|
-
traverse(currentChild, forApp, depth + 1, webp, state, parentDomain);
|
|
1337
|
+
traverse(currentChild, forApp, depth + 1, webp, state, parentDomain, seoContext);
|
|
1310
1338
|
}
|
|
1311
1339
|
});
|
|
1312
1340
|
}
|
|
@@ -1357,7 +1385,7 @@ function fixBlockLevelTagsInParagraphs(html) {
|
|
|
1357
1385
|
html = html.replace(/<p><br>\s*<\/p>/g, "");
|
|
1358
1386
|
return html;
|
|
1359
1387
|
}
|
|
1360
|
-
function markdownToHTML(input, forApp, webp, parentDomain = "ecency.com") {
|
|
1388
|
+
function markdownToHTML(input, forApp, webp, parentDomain = "ecency.com", seoContext) {
|
|
1361
1389
|
input = input.replace(new RegExp("https://leofinance.io/threads/view/", "g"), "/@");
|
|
1362
1390
|
input = input.replace(new RegExp("https://leofinance.io/posts/", "g"), "/@");
|
|
1363
1391
|
input = input.replace(new RegExp("https://leofinance.io/threads/", "g"), "/@");
|
|
@@ -1416,8 +1444,8 @@ function markdownToHTML(input, forApp, webp, parentDomain = "ecency.com") {
|
|
|
1416
1444
|
try {
|
|
1417
1445
|
output = md.render(input);
|
|
1418
1446
|
output = fixBlockLevelTagsInParagraphs(output);
|
|
1419
|
-
const doc = DOMParser.parseFromString(`<body id="root">${output}</body>`, "text/html");
|
|
1420
|
-
traverse(doc, forApp, 0, webp, { firstImageFound: false }, parentDomain);
|
|
1447
|
+
const doc = DOMParser.parseFromString(`<body id="root">${removeDuplicateAttributes(output)}</body>`, "text/html");
|
|
1448
|
+
traverse(doc, forApp, 0, webp, { firstImageFound: false }, parentDomain, seoContext);
|
|
1421
1449
|
output = serializer.serializeToString(doc);
|
|
1422
1450
|
} catch (error) {
|
|
1423
1451
|
try {
|
|
@@ -1429,8 +1457,8 @@ function markdownToHTML(input, forApp, webp, parentDomain = "ecency.com") {
|
|
|
1429
1457
|
lowerCaseAttributeNames: false
|
|
1430
1458
|
});
|
|
1431
1459
|
const repairedHtml = domSerializer(dom.children);
|
|
1432
|
-
const doc = DOMParser.parseFromString(`<body id="root">${repairedHtml}</body>`, "text/html");
|
|
1433
|
-
traverse(doc, forApp, 0, webp, { firstImageFound: false }, parentDomain);
|
|
1460
|
+
const doc = DOMParser.parseFromString(`<body id="root">${removeDuplicateAttributes(repairedHtml)}</body>`, "text/html");
|
|
1461
|
+
traverse(doc, forApp, 0, webp, { firstImageFound: false }, parentDomain, seoContext);
|
|
1434
1462
|
output = serializer.serializeToString(doc);
|
|
1435
1463
|
} catch (fallbackError) {
|
|
1436
1464
|
const escapedContent = he2__default.default.encode(output || md.render(input));
|
|
@@ -1458,18 +1486,18 @@ function cacheSet(key, value) {
|
|
|
1458
1486
|
}
|
|
1459
1487
|
|
|
1460
1488
|
// src/markdown-2-html.ts
|
|
1461
|
-
function markdown2Html(obj, forApp = true, webp = false, parentDomain = "ecency.com") {
|
|
1489
|
+
function markdown2Html(obj, forApp = true, webp = false, parentDomain = "ecency.com", seoContext) {
|
|
1462
1490
|
if (typeof obj === "string") {
|
|
1463
1491
|
const cleanedStr = cleanReply(obj);
|
|
1464
|
-
return markdownToHTML(cleanedStr, forApp, webp, parentDomain);
|
|
1492
|
+
return markdownToHTML(cleanedStr, forApp, webp, parentDomain, seoContext);
|
|
1465
1493
|
}
|
|
1466
|
-
const key = `${makeEntryCacheKey(obj)}-md${webp ? "-webp" : ""}-${forApp ? "app" : "site"}-${parentDomain}`;
|
|
1494
|
+
const key = `${makeEntryCacheKey(obj)}-md${webp ? "-webp" : ""}-${forApp ? "app" : "site"}-${parentDomain}${seoContext ? `-seo${seoContext.authorReputation ?? ""}-${seoContext.postPayout ?? ""}` : ""}`;
|
|
1467
1495
|
const item = cacheGet(key);
|
|
1468
1496
|
if (item) {
|
|
1469
1497
|
return item;
|
|
1470
1498
|
}
|
|
1471
1499
|
const cleanBody = cleanReply(obj.body);
|
|
1472
|
-
const res = markdownToHTML(cleanBody, forApp, webp, parentDomain);
|
|
1500
|
+
const res = markdownToHTML(cleanBody, forApp, webp, parentDomain, seoContext);
|
|
1473
1501
|
cacheSet(key, res);
|
|
1474
1502
|
return res;
|
|
1475
1503
|
}
|