@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.mjs
CHANGED
|
@@ -164,10 +164,11 @@ var ALLOWED_ATTRIBUTES = {
|
|
|
164
164
|
"del": [],
|
|
165
165
|
"ins": []
|
|
166
166
|
};
|
|
167
|
-
var lenientErrorHandler = (level, msg) => {
|
|
168
|
-
if (process.env.NODE_ENV === "development"
|
|
167
|
+
var lenientErrorHandler = (level, msg, context) => {
|
|
168
|
+
if (process.env.NODE_ENV === "development") {
|
|
169
169
|
console.warn("[DOMParser]", level, msg);
|
|
170
170
|
}
|
|
171
|
+
return void 0;
|
|
171
172
|
};
|
|
172
173
|
var DOMParser = new DOMParser$1({
|
|
173
174
|
// Use onError instead of deprecated errorHandler
|
|
@@ -176,11 +177,30 @@ var DOMParser = new DOMParser$1({
|
|
|
176
177
|
});
|
|
177
178
|
|
|
178
179
|
// src/helper.ts
|
|
180
|
+
function removeDuplicateAttributes(html) {
|
|
181
|
+
const tagRegex = /<([a-zA-Z][a-zA-Z0-9]*)\s+((?:[^>"']+|"[^"]*"|'[^']*')*?)\s*(\/?)>/g;
|
|
182
|
+
return html.replace(tagRegex, (match, tagName, attrsString, selfClose) => {
|
|
183
|
+
const seenAttrs = /* @__PURE__ */ new Set();
|
|
184
|
+
const cleanedAttrs = [];
|
|
185
|
+
const attrRegex = /([a-zA-Z_:][-a-zA-Z0-9_:.]*)\s*(?:=\s*(?:"[^"]*"|'[^']*'|[^\s/>]+))?/g;
|
|
186
|
+
let attrMatch;
|
|
187
|
+
while ((attrMatch = attrRegex.exec(attrsString)) !== null) {
|
|
188
|
+
const attrName = attrMatch[1].toLowerCase();
|
|
189
|
+
if (!seenAttrs.has(attrName)) {
|
|
190
|
+
seenAttrs.add(attrName);
|
|
191
|
+
cleanedAttrs.push(attrMatch[0]);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
const attrsJoined = cleanedAttrs.length > 0 ? ` ${cleanedAttrs.join(" ")}` : "";
|
|
195
|
+
return `<${tagName}${attrsJoined}${selfClose ? " /" : ""}>`;
|
|
196
|
+
});
|
|
197
|
+
}
|
|
179
198
|
function createDoc(html) {
|
|
180
199
|
if (html.trim() === "") {
|
|
181
200
|
return null;
|
|
182
201
|
}
|
|
183
|
-
const
|
|
202
|
+
const cleanedHtml = removeDuplicateAttributes(html);
|
|
203
|
+
const doc = DOMParser.parseFromString(`<body>${cleanedHtml}</body>`, "text/html");
|
|
184
204
|
return doc;
|
|
185
205
|
}
|
|
186
206
|
function makeEntryCacheKey(entry) {
|
|
@@ -371,6 +391,14 @@ function createImageHTML(src, isLCP, webp) {
|
|
|
371
391
|
}
|
|
372
392
|
|
|
373
393
|
// src/methods/a.method.ts
|
|
394
|
+
var NOFOLLOW_REPUTATION_THRESHOLD = 40;
|
|
395
|
+
var FOLLOW_PAYOUT_THRESHOLD = 5;
|
|
396
|
+
function getExternalLinkRel(seoContext) {
|
|
397
|
+
if (seoContext?.authorReputation !== void 0 && seoContext?.postPayout !== void 0 && seoContext.authorReputation >= NOFOLLOW_REPUTATION_THRESHOLD && seoContext.postPayout > FOLLOW_PAYOUT_THRESHOLD) {
|
|
398
|
+
return "noopener";
|
|
399
|
+
}
|
|
400
|
+
return "nofollow ugc noopener";
|
|
401
|
+
}
|
|
374
402
|
var normalizeValue = (value) => value ? value.trim() : "";
|
|
375
403
|
var matchesHref = (href, value) => {
|
|
376
404
|
const normalizedHref = normalizeValue(href);
|
|
@@ -404,7 +432,7 @@ var addLineBreakBeforePostLink = (el, forApp, isInline) => {
|
|
|
404
432
|
el.parentNode.insertBefore(br, el);
|
|
405
433
|
}
|
|
406
434
|
};
|
|
407
|
-
function a(el, forApp, webp, parentDomain = "ecency.com") {
|
|
435
|
+
function a(el, forApp, webp, parentDomain = "ecency.com", seoContext) {
|
|
408
436
|
if (!el || !el.parentNode) {
|
|
409
437
|
return;
|
|
410
438
|
}
|
|
@@ -964,7 +992,7 @@ function a(el, forApp, webp, parentDomain = "ecency.com") {
|
|
|
964
992
|
el.setAttribute("class", "markdown-internal-link");
|
|
965
993
|
} else {
|
|
966
994
|
el.setAttribute("target", "_blank");
|
|
967
|
-
el.setAttribute("rel",
|
|
995
|
+
el.setAttribute("rel", getExternalLinkRel(seoContext));
|
|
968
996
|
}
|
|
969
997
|
el.setAttribute("href", href);
|
|
970
998
|
}
|
|
@@ -1253,7 +1281,7 @@ function text(node, forApp, webp) {
|
|
|
1253
1281
|
}
|
|
1254
1282
|
|
|
1255
1283
|
// src/methods/traverse.method.ts
|
|
1256
|
-
function traverse(node, forApp, depth = 0, webp = false, state = { firstImageFound: false }, parentDomain = "ecency.com") {
|
|
1284
|
+
function traverse(node, forApp, depth = 0, webp = false, state = { firstImageFound: false }, parentDomain = "ecency.com", seoContext) {
|
|
1257
1285
|
if (!node || !node.childNodes) {
|
|
1258
1286
|
return;
|
|
1259
1287
|
}
|
|
@@ -1261,7 +1289,7 @@ function traverse(node, forApp, depth = 0, webp = false, state = { firstImageFou
|
|
|
1261
1289
|
const child = node.childNodes[i];
|
|
1262
1290
|
if (!child) return;
|
|
1263
1291
|
if (child.nodeName.toLowerCase() === "a") {
|
|
1264
|
-
a(child, forApp, webp, parentDomain);
|
|
1292
|
+
a(child, forApp, webp, parentDomain, seoContext);
|
|
1265
1293
|
}
|
|
1266
1294
|
if (child.nodeName.toLowerCase() === "iframe") {
|
|
1267
1295
|
iframe(child, parentDomain);
|
|
@@ -1277,7 +1305,7 @@ function traverse(node, forApp, depth = 0, webp = false, state = { firstImageFou
|
|
|
1277
1305
|
}
|
|
1278
1306
|
const currentChild = node.childNodes[i];
|
|
1279
1307
|
if (currentChild) {
|
|
1280
|
-
traverse(currentChild, forApp, depth + 1, webp, state, parentDomain);
|
|
1308
|
+
traverse(currentChild, forApp, depth + 1, webp, state, parentDomain, seoContext);
|
|
1281
1309
|
}
|
|
1282
1310
|
});
|
|
1283
1311
|
}
|
|
@@ -1328,7 +1356,7 @@ function fixBlockLevelTagsInParagraphs(html) {
|
|
|
1328
1356
|
html = html.replace(/<p><br>\s*<\/p>/g, "");
|
|
1329
1357
|
return html;
|
|
1330
1358
|
}
|
|
1331
|
-
function markdownToHTML(input, forApp, webp, parentDomain = "ecency.com") {
|
|
1359
|
+
function markdownToHTML(input, forApp, webp, parentDomain = "ecency.com", seoContext) {
|
|
1332
1360
|
input = input.replace(new RegExp("https://leofinance.io/threads/view/", "g"), "/@");
|
|
1333
1361
|
input = input.replace(new RegExp("https://leofinance.io/posts/", "g"), "/@");
|
|
1334
1362
|
input = input.replace(new RegExp("https://leofinance.io/threads/", "g"), "/@");
|
|
@@ -1387,8 +1415,8 @@ function markdownToHTML(input, forApp, webp, parentDomain = "ecency.com") {
|
|
|
1387
1415
|
try {
|
|
1388
1416
|
output = md.render(input);
|
|
1389
1417
|
output = fixBlockLevelTagsInParagraphs(output);
|
|
1390
|
-
const doc = DOMParser.parseFromString(`<body id="root">${output}</body>`, "text/html");
|
|
1391
|
-
traverse(doc, forApp, 0, webp, { firstImageFound: false }, parentDomain);
|
|
1418
|
+
const doc = DOMParser.parseFromString(`<body id="root">${removeDuplicateAttributes(output)}</body>`, "text/html");
|
|
1419
|
+
traverse(doc, forApp, 0, webp, { firstImageFound: false }, parentDomain, seoContext);
|
|
1392
1420
|
output = serializer.serializeToString(doc);
|
|
1393
1421
|
} catch (error) {
|
|
1394
1422
|
try {
|
|
@@ -1400,8 +1428,8 @@ function markdownToHTML(input, forApp, webp, parentDomain = "ecency.com") {
|
|
|
1400
1428
|
lowerCaseAttributeNames: false
|
|
1401
1429
|
});
|
|
1402
1430
|
const repairedHtml = domSerializer(dom.children);
|
|
1403
|
-
const doc = DOMParser.parseFromString(`<body id="root">${repairedHtml}</body>`, "text/html");
|
|
1404
|
-
traverse(doc, forApp, 0, webp, { firstImageFound: false }, parentDomain);
|
|
1431
|
+
const doc = DOMParser.parseFromString(`<body id="root">${removeDuplicateAttributes(repairedHtml)}</body>`, "text/html");
|
|
1432
|
+
traverse(doc, forApp, 0, webp, { firstImageFound: false }, parentDomain, seoContext);
|
|
1405
1433
|
output = serializer.serializeToString(doc);
|
|
1406
1434
|
} catch (fallbackError) {
|
|
1407
1435
|
const escapedContent = he2.encode(output || md.render(input));
|
|
@@ -1429,18 +1457,18 @@ function cacheSet(key, value) {
|
|
|
1429
1457
|
}
|
|
1430
1458
|
|
|
1431
1459
|
// src/markdown-2-html.ts
|
|
1432
|
-
function markdown2Html(obj, forApp = true, webp = false, parentDomain = "ecency.com") {
|
|
1460
|
+
function markdown2Html(obj, forApp = true, webp = false, parentDomain = "ecency.com", seoContext) {
|
|
1433
1461
|
if (typeof obj === "string") {
|
|
1434
1462
|
const cleanedStr = cleanReply(obj);
|
|
1435
|
-
return markdownToHTML(cleanedStr, forApp, webp, parentDomain);
|
|
1463
|
+
return markdownToHTML(cleanedStr, forApp, webp, parentDomain, seoContext);
|
|
1436
1464
|
}
|
|
1437
|
-
const key = `${makeEntryCacheKey(obj)}-md${webp ? "-webp" : ""}-${forApp ? "app" : "site"}-${parentDomain}`;
|
|
1465
|
+
const key = `${makeEntryCacheKey(obj)}-md${webp ? "-webp" : ""}-${forApp ? "app" : "site"}-${parentDomain}${seoContext ? `-seo${seoContext.authorReputation ?? ""}-${seoContext.postPayout ?? ""}` : ""}`;
|
|
1438
1466
|
const item = cacheGet(key);
|
|
1439
1467
|
if (item) {
|
|
1440
1468
|
return item;
|
|
1441
1469
|
}
|
|
1442
1470
|
const cleanBody = cleanReply(obj.body);
|
|
1443
|
-
const res = markdownToHTML(cleanBody, forApp, webp, parentDomain);
|
|
1471
|
+
const res = markdownToHTML(cleanBody, forApp, webp, parentDomain, seoContext);
|
|
1444
1472
|
cacheSet(key, res);
|
|
1445
1473
|
return res;
|
|
1446
1474
|
}
|