@ecency/render-helper 2.3.17 → 2.4.2
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/LICENSE +1 -1
- package/README.md +171 -17
- package/dist/browser/index.d.ts +32 -0
- package/dist/browser/index.js +1556 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/node/index.cjs +1575 -0
- package/dist/node/index.cjs.map +1 -0
- package/dist/node/index.mjs +1559 -0
- package/dist/node/index.mjs.map +1 -0
- package/package.json +49 -47
- package/lib/cache.d.ts +0 -3
- package/lib/cache.js +0 -21
- package/lib/cache.js.map +0 -1
- package/lib/catch-post-image.d.ts +0 -2
- package/lib/catch-post-image.js +0 -76
- package/lib/catch-post-image.js.map +0 -1
- package/lib/consts/allowed-attributes.const.d.ts +0 -2
- package/lib/consts/allowed-attributes.const.js +0 -71
- package/lib/consts/allowed-attributes.const.js.map +0 -1
- package/lib/consts/dom-parser.const.d.ts +0 -2
- package/lib/consts/dom-parser.const.js +0 -12
- package/lib/consts/dom-parser.const.js.map +0 -1
- package/lib/consts/index.d.ts +0 -5
- package/lib/consts/index.js +0 -22
- package/lib/consts/index.js.map +0 -1
- package/lib/consts/regexes.const.d.ts +0 -44
- package/lib/consts/regexes.const.js +0 -49
- package/lib/consts/regexes.const.js.map +0 -1
- package/lib/consts/section-list.const.d.ts +0 -1
- package/lib/consts/section-list.const.js +0 -24
- package/lib/consts/section-list.const.js.map +0 -1
- package/lib/consts/white-list.const.d.ts +0 -2
- package/lib/consts/white-list.const.js +0 -37
- package/lib/consts/white-list.const.js.map +0 -1
- package/lib/helper.d.ts +0 -6
- package/lib/helper.js +0 -72
- package/lib/helper.js.map +0 -1
- package/lib/index.d.ts +0 -8
- package/lib/index.js +0 -19
- package/lib/index.js.map +0 -1
- package/lib/markdown-2-html.d.ts +0 -2
- package/lib/markdown-2-html.js +0 -25
- package/lib/markdown-2-html.js.map +0 -1
- package/lib/methods/a.method.d.ts +0 -1
- package/lib/methods/a.method.js +0 -647
- package/lib/methods/a.method.js.map +0 -1
- package/lib/methods/clean-reply.method.d.ts +0 -1
- package/lib/methods/clean-reply.method.js +0 -37
- package/lib/methods/clean-reply.method.js.map +0 -1
- package/lib/methods/get-inner-html.method.d.ts +0 -1
- package/lib/methods/get-inner-html.method.js +0 -16
- package/lib/methods/get-inner-html.method.js.map +0 -1
- package/lib/methods/iframe.method.d.ts +0 -1
- package/lib/methods/iframe.method.js +0 -159
- package/lib/methods/iframe.method.js.map +0 -1
- package/lib/methods/img.method.d.ts +0 -4
- package/lib/methods/img.method.js +0 -50
- package/lib/methods/img.method.js.map +0 -1
- package/lib/methods/index.d.ts +0 -7
- package/lib/methods/index.js +0 -24
- package/lib/methods/index.js.map +0 -1
- package/lib/methods/linkify.method.d.ts +0 -1
- package/lib/methods/linkify.method.js +0 -56
- package/lib/methods/linkify.method.js.map +0 -1
- package/lib/methods/markdown-to-html.method.d.ts +0 -1
- package/lib/methods/markdown-to-html.method.js +0 -98
- package/lib/methods/markdown-to-html.method.js.map +0 -1
- package/lib/methods/noop.method.d.ts +0 -1
- package/lib/methods/noop.method.js +0 -6
- package/lib/methods/noop.method.js.map +0 -1
- package/lib/methods/p.method.d.ts +0 -1
- package/lib/methods/p.method.js +0 -11
- package/lib/methods/p.method.js.map +0 -1
- package/lib/methods/remove-child-nodes.method.d.ts +0 -1
- package/lib/methods/remove-child-nodes.method.js +0 -10
- package/lib/methods/remove-child-nodes.method.js.map +0 -1
- package/lib/methods/sanitize-html.method.d.ts +0 -1
- package/lib/methods/sanitize-html.method.js +0 -42
- package/lib/methods/sanitize-html.method.js.map +0 -1
- package/lib/methods/text.method.d.ts +0 -1
- package/lib/methods/text.method.js +0 -69
- package/lib/methods/text.method.js.map +0 -1
- package/lib/methods/traverse.method.d.ts +0 -3
- package/lib/methods/traverse.method.js +0 -38
- package/lib/methods/traverse.method.js.map +0 -1
- package/lib/post-body-summary.d.ts +0 -2
- package/lib/post-body-summary.js +0 -123
- package/lib/post-body-summary.js.map +0 -1
- package/lib/proxify-image-src.d.ts +0 -5
- package/lib/proxify-image-src.js +0 -86
- package/lib/proxify-image-src.js.map +0 -1
- package/lib/render-helper.js +0 -1
- package/lib/types/entry.interface.d.ts +0 -7
- package/lib/types/entry.interface.js +0 -3
- package/lib/types/entry.interface.js.map +0 -1
- package/lib/types/index.d.ts +0 -2
- package/lib/types/index.js +0 -19
- package/lib/types/index.js.map +0 -1
- package/lib/types/xss-white-list.interface.d.ts +0 -6
- package/lib/types/xss-white-list.interface.js +0 -3
- package/lib/types/xss-white-list.interface.js.map +0 -1
- package/src/cache.ts +0 -15
- package/src/catch-post-image.spec.ts +0 -144
- package/src/catch-post-image.ts +0 -78
- package/src/consts/allowed-attributes.const.ts +0 -69
- package/src/consts/dom-parser.const.ts +0 -6
- package/src/consts/index.ts +0 -5
- package/src/consts/regexes.const.ts +0 -46
- package/src/consts/section-list.const.ts +0 -20
- package/src/consts/white-list.const.ts +0 -33
- package/src/external-types/multihashes.d.ts +0 -3
- package/src/helper.spec.ts +0 -16
- package/src/helper.ts +0 -77
- package/src/index.ts +0 -18
- package/src/markdown-2-html.spec.ts +0 -1251
- package/src/markdown-2-html.ts +0 -25
- package/src/methods/a.method.ts +0 -791
- package/src/methods/clean-reply.method.ts +0 -32
- package/src/methods/get-inner-html.method.ts +0 -11
- package/src/methods/iframe.method.ts +0 -176
- package/src/methods/img.method.ts +0 -62
- package/src/methods/index.ts +0 -7
- package/src/methods/linkify.method.ts +0 -61
- package/src/methods/markdown-to-html.method.ts +0 -104
- package/src/methods/noop.method.ts +0 -1
- package/src/methods/p.method.ts +0 -6
- package/src/methods/remove-child-nodes.method.ts +0 -5
- package/src/methods/sanitize-html.method.ts +0 -32
- package/src/methods/text.method.ts +0 -77
- package/src/methods/traverse.method.ts +0 -33
- package/src/post-body-summary.spec.ts +0 -150
- package/src/post-body-summary.ts +0 -130
- package/src/proxify-image-src.spec.ts +0 -76
- package/src/proxify-image-src.ts +0 -77
- package/src/sanitize-html.spec.ts +0 -15
- package/src/test/data/index.ts +0 -12
- package/src/test/data/json/muratkbesiroglu____sci-fi-novel-underground-city-part-13.json +0 -2120
- package/src/test/data/json/steemitboard____steemitboard-notify-dunsky-20181210t153450000z.json +0 -47
- package/src/test/data/legacy/10.json +0 -5
- package/src/test/data/legacy/20.json +0 -5
- package/src/test/data/legacy/21.json +0 -5
- package/src/test/data/legacy/2112524.json +0 -5
- package/src/test/data/legacy/22.json +0 -5
- package/src/test/data/legacy/23.json +0 -5
- package/src/test/data/legacy/24.json +0 -5
- package/src/test/data/legacy/25.json +0 -5
- package/src/test/data/legacy/26.json +0 -5
- package/src/test/data/legacy/27.JSON +0 -5
- package/src/test/data/legacy/28.json +0 -5
- package/src/test/data/legacy/29.json +0 -5
- package/src/test/data/legacy/31.json +0 -5
- package/src/test/snaps.json +0 -8
- package/src/types/entry.interface.ts +0 -7
- package/src/types/index.ts +0 -2
- package/src/types/xss-white-list.interface.ts +0 -7
|
@@ -0,0 +1,1559 @@
|
|
|
1
|
+
import { DOMParser as DOMParser$1, XMLSerializer } from '@xmldom/xmldom';
|
|
2
|
+
import xss from 'xss';
|
|
3
|
+
import multihash from 'multihashes';
|
|
4
|
+
import querystring from 'querystring';
|
|
5
|
+
import { Remarkable } from 'remarkable';
|
|
6
|
+
import { linkify as linkify$1 } from 'remarkable/linkify';
|
|
7
|
+
import { LRUCache } from 'lru-cache';
|
|
8
|
+
import he from 'he';
|
|
9
|
+
|
|
10
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
11
|
+
get: (a2, b) => (typeof require !== "undefined" ? require : a2)[b]
|
|
12
|
+
}) : x)(function(x) {
|
|
13
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
14
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
// src/consts/white-list.const.ts
|
|
18
|
+
var WHITE_LIST = [
|
|
19
|
+
"ecency.com",
|
|
20
|
+
"hive.blog",
|
|
21
|
+
"peakd.com",
|
|
22
|
+
"travelfeed.io",
|
|
23
|
+
"dapplr.in",
|
|
24
|
+
"leofinance.io",
|
|
25
|
+
"inleo.io",
|
|
26
|
+
"proofofbrain.io",
|
|
27
|
+
"stemgeeks.net",
|
|
28
|
+
"hiveblockexplorer.com",
|
|
29
|
+
"proofofbrain.blog",
|
|
30
|
+
"weedcash.network",
|
|
31
|
+
"dapplr.in",
|
|
32
|
+
"liketu.com",
|
|
33
|
+
"bilpcoin.com",
|
|
34
|
+
"inji.com"
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
// src/consts/section-list.const.ts
|
|
38
|
+
var SECTION_LIST = [
|
|
39
|
+
"wallet",
|
|
40
|
+
"feed",
|
|
41
|
+
"followers",
|
|
42
|
+
"following",
|
|
43
|
+
"points",
|
|
44
|
+
"communities",
|
|
45
|
+
"posts",
|
|
46
|
+
"blog",
|
|
47
|
+
"comments",
|
|
48
|
+
"replies",
|
|
49
|
+
"settings",
|
|
50
|
+
"engine",
|
|
51
|
+
"permissions",
|
|
52
|
+
"referrals",
|
|
53
|
+
"payout",
|
|
54
|
+
"activities",
|
|
55
|
+
"spk",
|
|
56
|
+
"trail"
|
|
57
|
+
];
|
|
58
|
+
|
|
59
|
+
// src/consts/regexes.const.ts
|
|
60
|
+
var IMG_REGEX = /(https?:\/\/.*\.(?:tiff?|jpe?g|gif|png|svg|ico|heic|webp))(.*)/gim;
|
|
61
|
+
var IPFS_REGEX = /^https?:\/\/[^/]+\/(ip[fn]s)\/([^/?#]+)/gim;
|
|
62
|
+
var POST_REGEX = /^https?:\/\/(.*)\/(.*)\/(@[\w.\d-]+)\/(.*)/i;
|
|
63
|
+
var CCC_REGEX = /^https?:\/\/(.*)\/ccc\/([\w.\d-]+)\/(.*)/i;
|
|
64
|
+
var MENTION_REGEX = /^https?:\/\/(.*)\/(@[\w.\d-]+)$/i;
|
|
65
|
+
var TOPIC_REGEX = /^https?:\/\/(.*)\/(trending|hot|created|promoted|muted|payout)\/(.*)$/i;
|
|
66
|
+
var INTERNAL_MENTION_REGEX = /^\/@[\w.\d-]+$/i;
|
|
67
|
+
var INTERNAL_TOPIC_REGEX = /^\/(trending|hot|created|promoted|muted|payout)\/(.*)$/i;
|
|
68
|
+
var INTERNAL_POST_TAG_REGEX = /(.*)\/(@[\w.\d-]+)\/(.*)/i;
|
|
69
|
+
var INTERNAL_POST_REGEX = /^\/(@[\w.\d-]+)\/(.*)$/i;
|
|
70
|
+
var CUSTOM_COMMUNITY_REGEX = /^https?:\/\/(.*)\/c\/(hive-\d+)(.*)/i;
|
|
71
|
+
var YOUTUBE_REGEX = /(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|shorts\/|.*[?&]v=)|youtu\.be\/)([^"&?\/\s]{11})/i;
|
|
72
|
+
var YOUTUBE_EMBED_REGEX = /^(https?:)?\/\/www.youtube.com\/(embed|shorts)\/.*/i;
|
|
73
|
+
var VIMEO_REGEX = /(https?:\/\/)?(www\.)?(?:vimeo)\.com.*(?:videos|video|channels|)\/([\d]+)/i;
|
|
74
|
+
var VIMEO_EMBED_REGEX = /https:\/\/player\.vimeo\.com\/video\/([0-9]+)(?:$|[?#])/;
|
|
75
|
+
var BITCHUTE_REGEX = /^(?:https?:\/\/)?(?:www\.)?bitchute.com\/(?:video|embed)\/([a-z0-9]+)/i;
|
|
76
|
+
var D_TUBE_REGEX = /(https?:\/\/d\.tube\/#!\/v\/)(\w+)\/(\w+)/g;
|
|
77
|
+
var D_TUBE_REGEX2 = /(https?:\/\/d\.tube\/v\/)(\w+)\/(\w+)/g;
|
|
78
|
+
var D_TUBE_EMBED_REGEX = /^https:\/\/emb.d.tube\/#!\/[^/?#]+\/[^/?#]+(?:$|[?#])/i;
|
|
79
|
+
var TWITCH_REGEX = /https?:\/\/(?:www.)?twitch.tv\/(?:(videos)\/)?([a-zA-Z0-9][\w]{3,24})/i;
|
|
80
|
+
var DAPPLR_REGEX = /^(https?:)?\/\/[a-z]*\.dapplr.in\/file\/dapplr-videos\/.*/i;
|
|
81
|
+
var TRUVVL_REGEX = /^https?:\/\/embed.truvvl.com\/(@[\w.\d-]+)\/(.*)/i;
|
|
82
|
+
var LBRY_REGEX = /^(https?:)?\/\/lbry.tv\/\$\/embed\/[^?#]+(?:$|[?#])/i;
|
|
83
|
+
var ODYSEE_REGEX = /^(https?:)?\/\/odysee\.com\/(?:\$|%24)\/embed\/[^/?#]+(?:$|[?#])/i;
|
|
84
|
+
var SKATEHIVE_IPFS_REGEX = /^https?:\/\/ipfs\.skatehive\.app\/ipfs\/([^/?#]+)/i;
|
|
85
|
+
var ARCH_REGEX = /^(https?:)?\/\/archive.org\/embed\/[^/?#]+(?:$|[?#])/i;
|
|
86
|
+
var SPEAK_REGEX = /(?:https?:\/\/(?:3speak.([a-z]+)\/watch\?v=)|(?:3speak.([a-z]+)\/embed\?v=))([A-Za-z0-9\_\-\.\/]+)(&.*)?/i;
|
|
87
|
+
var SPEAK_EMBED_REGEX = /^(https?:)?\/\/3speak.([a-z]+)\/embed\?[^/]+$/i;
|
|
88
|
+
var TWITTER_REGEX = /(?:https?:\/\/(?:(?:twitter\.com\/(.*?)\/status\/(.*))))/gi;
|
|
89
|
+
var SPOTIFY_REGEX = /^https:\/\/open\.spotify\.com\/playlist\/(.*)?$/gi;
|
|
90
|
+
var RUMBLE_REGEX = /^https:\/\/rumble.com\/embed\/([a-zA-Z0-9-]+)\/\?pub=\w+/;
|
|
91
|
+
var BRIGHTEON_REGEX = /^https?:\/\/(www\.)?brighteon\.com\/(?:embed\/)?(.*[0-9].*)/i;
|
|
92
|
+
var VIMM_EMBED_REGEX = /^https:\/\/www.vimm.tv\/[^?#]+(?:$|[?#])/i;
|
|
93
|
+
var SPOTIFY_EMBED_REGEX = /^https:\/\/open\.spotify\.com\/(embed|embed-podcast)\/(playlist|show|episode|track|album)\/([^/?#]+)(?:$|[?#])/i;
|
|
94
|
+
var SOUNDCLOUD_EMBED_REGEX = /^https:\/\/w.soundcloud.com\/player\/\?[^#]+$/i;
|
|
95
|
+
var TWITCH_EMBED_REGEX = /^(https?:)?\/\/player.twitch.tv\/(?:\?[^/]+)?$/i;
|
|
96
|
+
var BRAND_NEW_TUBE_REGEX = /^https:\/\/brandnewtube\.com\/embed\/[a-z0-9]+$/i;
|
|
97
|
+
var LOOM_REGEX = /^(https?:)?\/\/www.loom.com\/share\/([^/?#]+)(?:$|[?#])/i;
|
|
98
|
+
var LOOM_EMBED_REGEX = /^(https?:)?\/\/www.loom.com\/embed\/([^/?#]+)(?:$|[?#])/i;
|
|
99
|
+
var AUREAL_EMBED_REGEX = /^(https?:\/\/)?(www\.)?(?:aureal-embed)\.web\.app\/([0-9]+)(?:$|[?#])/i;
|
|
100
|
+
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
|
+
var ID_WHITELIST = /^[A-Za-z][-A-Za-z0-9_]*$/;
|
|
103
|
+
|
|
104
|
+
// src/consts/allowed-attributes.const.ts
|
|
105
|
+
var ALLOWED_ATTRIBUTES = {
|
|
106
|
+
"a": [
|
|
107
|
+
"href",
|
|
108
|
+
"target",
|
|
109
|
+
"rel",
|
|
110
|
+
"data-permlink",
|
|
111
|
+
"data-tag",
|
|
112
|
+
"data-author",
|
|
113
|
+
"data-href",
|
|
114
|
+
"data-community",
|
|
115
|
+
"data-filter",
|
|
116
|
+
"data-embed-src",
|
|
117
|
+
"data-youtube",
|
|
118
|
+
"data-start-time",
|
|
119
|
+
"data-video-href",
|
|
120
|
+
"data-proposal",
|
|
121
|
+
"data-is-inline",
|
|
122
|
+
"class",
|
|
123
|
+
"title",
|
|
124
|
+
"data-id",
|
|
125
|
+
"id"
|
|
126
|
+
],
|
|
127
|
+
"img": [
|
|
128
|
+
"src",
|
|
129
|
+
"alt",
|
|
130
|
+
"class",
|
|
131
|
+
"loading",
|
|
132
|
+
"fetchpriority",
|
|
133
|
+
"decoding",
|
|
134
|
+
"itemprop"
|
|
135
|
+
],
|
|
136
|
+
"span": ["class", "id", "data-align"],
|
|
137
|
+
"iframe": ["src", "class", "frameborder", "allowfullscreen", "webkitallowfullscreen", "mozallowfullscreen", "sandbox"],
|
|
138
|
+
"video": ["src", "controls", "poster"],
|
|
139
|
+
"div": ["class", "id", "data-align"],
|
|
140
|
+
"strong": [],
|
|
141
|
+
"b": [],
|
|
142
|
+
"i": [],
|
|
143
|
+
"strike": [],
|
|
144
|
+
"em": [],
|
|
145
|
+
"code": [],
|
|
146
|
+
"pre": [],
|
|
147
|
+
"blockquote": ["class"],
|
|
148
|
+
"sup": [],
|
|
149
|
+
"sub": [],
|
|
150
|
+
"h1": ["dir", "id", "data-align"],
|
|
151
|
+
"h2": ["dir", "id", "data-align"],
|
|
152
|
+
"h3": ["dir", "id", "data-align"],
|
|
153
|
+
"h4": ["dir", "id", "data-align"],
|
|
154
|
+
"h5": ["dir", "id", "data-align"],
|
|
155
|
+
"h6": ["dir", "id", "data-align"],
|
|
156
|
+
"p": ["dir", "id", "data-align"],
|
|
157
|
+
"center": [],
|
|
158
|
+
"ul": [],
|
|
159
|
+
"ol": [],
|
|
160
|
+
"li": [],
|
|
161
|
+
"table": [],
|
|
162
|
+
"thead": [],
|
|
163
|
+
"tbody": [],
|
|
164
|
+
"tr": [],
|
|
165
|
+
"td": [],
|
|
166
|
+
"th": [],
|
|
167
|
+
"hr": [],
|
|
168
|
+
"br": [],
|
|
169
|
+
"del": [],
|
|
170
|
+
"ins": []
|
|
171
|
+
};
|
|
172
|
+
var lenientErrorHandler = (level, msg) => {
|
|
173
|
+
if (process.env.NODE_ENV === "development" && level === "fatalError") {
|
|
174
|
+
console.warn("[DOMParser]", level, msg);
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
var DOMParser = new DOMParser$1({
|
|
178
|
+
// Use onError instead of deprecated errorHandler
|
|
179
|
+
// By providing a non-throwing error handler, parsing continues despite malformed HTML
|
|
180
|
+
onError: lenientErrorHandler
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
// src/helper.ts
|
|
184
|
+
function createDoc(html) {
|
|
185
|
+
if (html.trim() === "") {
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
const doc = DOMParser.parseFromString(html, "text/html");
|
|
189
|
+
return doc;
|
|
190
|
+
}
|
|
191
|
+
function makeEntryCacheKey(entry) {
|
|
192
|
+
return `${entry.author}-${entry.permlink}-${entry.last_update}-${entry.updated}`;
|
|
193
|
+
}
|
|
194
|
+
function extractYtStartTime(url) {
|
|
195
|
+
try {
|
|
196
|
+
const urlObj = new URL(url);
|
|
197
|
+
const params = new URLSearchParams(urlObj.search);
|
|
198
|
+
if (params.has("t")) {
|
|
199
|
+
const t = params.get("t");
|
|
200
|
+
return "" + parseInt(t || "0");
|
|
201
|
+
} else if (params.has("start")) {
|
|
202
|
+
return params.get("start") || "";
|
|
203
|
+
}
|
|
204
|
+
return "";
|
|
205
|
+
} catch (error) {
|
|
206
|
+
return "";
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
function sanitizePermlink(permlink) {
|
|
210
|
+
if (!permlink || typeof permlink !== "string") {
|
|
211
|
+
return "";
|
|
212
|
+
}
|
|
213
|
+
const [withoutQuery] = permlink.split("?");
|
|
214
|
+
const [cleaned] = withoutQuery.split("#");
|
|
215
|
+
return cleaned;
|
|
216
|
+
}
|
|
217
|
+
function isValidPermlink(permlink) {
|
|
218
|
+
const sanitized = sanitizePermlink(permlink);
|
|
219
|
+
if (!sanitized) {
|
|
220
|
+
return false;
|
|
221
|
+
}
|
|
222
|
+
const isImage = /\.(jpg|jpeg|png|webp|gif|svg)$/i.test(sanitized);
|
|
223
|
+
const isCleanFormat = /^[a-z0-9-]+$/.test(sanitized);
|
|
224
|
+
return isCleanFormat && !isImage;
|
|
225
|
+
}
|
|
226
|
+
var LABEL_REGEX = /^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/;
|
|
227
|
+
function isValidUsername(username) {
|
|
228
|
+
if (!username || typeof username !== "string") return false;
|
|
229
|
+
if (username.length > 16) return false;
|
|
230
|
+
const labels = username.split(".");
|
|
231
|
+
return labels.every((label) => {
|
|
232
|
+
return label.length >= 3 && label.length <= 16 && /^[a-z]/.test(label) && // must start with a letter
|
|
233
|
+
LABEL_REGEX.test(label) && // a-z0-9, hyphens, no start/end hyphen
|
|
234
|
+
!label.includes("..");
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
function getSerializedInnerHTML(node) {
|
|
238
|
+
const serializer = new XMLSerializer();
|
|
239
|
+
if (node.childNodes[0]) {
|
|
240
|
+
return serializer.serializeToString(node.childNodes[0]);
|
|
241
|
+
}
|
|
242
|
+
return "";
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// src/methods/remove-child-nodes.method.ts
|
|
246
|
+
function removeChildNodes(node) {
|
|
247
|
+
while (node.firstChild) {
|
|
248
|
+
node.removeChild(node.firstChild);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
var decodeEntities = (input) => input.replace(/&#(\d+);?/g, (_, dec) => String.fromCodePoint(Number(dec))).replace(/&#x([0-9a-f]+);?/gi, (_, hex) => String.fromCodePoint(parseInt(hex, 16)));
|
|
252
|
+
function sanitizeHtml(html) {
|
|
253
|
+
return xss(html, {
|
|
254
|
+
whiteList: ALLOWED_ATTRIBUTES,
|
|
255
|
+
stripIgnoreTag: true,
|
|
256
|
+
stripIgnoreTagBody: ["style"],
|
|
257
|
+
css: false,
|
|
258
|
+
// block style attrs entirely for safety
|
|
259
|
+
onTagAttr: (tag, name, value) => {
|
|
260
|
+
const decoded = decodeEntities(value.trim());
|
|
261
|
+
const decodedLower = decoded.toLowerCase();
|
|
262
|
+
if (name.startsWith("on")) return "";
|
|
263
|
+
if (tag === "img" && name === "src" && (!/^https?:\/\//.test(decodedLower) || decodedLower.startsWith("javascript:"))) return "";
|
|
264
|
+
if (tag === "video" && ["src", "poster"].includes(name) && (!/^https?:\/\//.test(decodedLower) || decodedLower.startsWith("javascript:"))) return "";
|
|
265
|
+
if (tag === "img" && ["dynsrc", "lowsrc"].includes(name)) return "";
|
|
266
|
+
if (tag === "span" && name === "class" && decoded.toLowerCase().trim() === "wr") return "";
|
|
267
|
+
if (name === "id") {
|
|
268
|
+
if (!ID_WHITELIST.test(decoded)) return "";
|
|
269
|
+
}
|
|
270
|
+
return void 0;
|
|
271
|
+
}
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
var proxyBase = "https://images.ecency.com";
|
|
275
|
+
var fileExtension = true;
|
|
276
|
+
function setProxyBase(p2) {
|
|
277
|
+
proxyBase = p2;
|
|
278
|
+
fileExtension = proxyBase == "https://images.ecency.com";
|
|
279
|
+
}
|
|
280
|
+
function extractPHash(url) {
|
|
281
|
+
if (url.startsWith(`${proxyBase}/p/`)) {
|
|
282
|
+
const [hash] = url.split("/p/")[1].split("?");
|
|
283
|
+
return hash.replace(/.webp/, "").replace(/.png/, "");
|
|
284
|
+
}
|
|
285
|
+
return null;
|
|
286
|
+
}
|
|
287
|
+
function isValidUrl(url) {
|
|
288
|
+
try {
|
|
289
|
+
return Boolean(new URL(url));
|
|
290
|
+
} catch (e) {
|
|
291
|
+
return false;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
function getLatestUrl(str) {
|
|
295
|
+
const [last] = [...str.replace(/https?:\/\//g, "\n$&").trim().split("\n")].reverse();
|
|
296
|
+
return last;
|
|
297
|
+
}
|
|
298
|
+
function proxifyImageSrc(url, width = 0, height = 0, format = "match") {
|
|
299
|
+
if (!url || typeof url !== "string" || !isValidUrl(url)) {
|
|
300
|
+
return "";
|
|
301
|
+
}
|
|
302
|
+
if (url.indexOf("https://images.hive.blog/") === 0 && url.indexOf("https://images.hive.blog/D") !== 0) {
|
|
303
|
+
return url.replace("https://images.hive.blog", proxyBase);
|
|
304
|
+
}
|
|
305
|
+
if (url.indexOf("https://steemitimages.com/") === 0 && url.indexOf("https://steemitimages.com/D") !== 0) {
|
|
306
|
+
return url.replace("https://steemitimages.com", proxyBase);
|
|
307
|
+
}
|
|
308
|
+
const realUrl = getLatestUrl(url);
|
|
309
|
+
const pHash = extractPHash(realUrl);
|
|
310
|
+
const options = {
|
|
311
|
+
format,
|
|
312
|
+
mode: "fit"
|
|
313
|
+
};
|
|
314
|
+
if (width > 0) {
|
|
315
|
+
options.width = width;
|
|
316
|
+
}
|
|
317
|
+
if (height > 0) {
|
|
318
|
+
options.height = height;
|
|
319
|
+
}
|
|
320
|
+
const qs = querystring.stringify(options);
|
|
321
|
+
if (pHash) {
|
|
322
|
+
if (fileExtension) {
|
|
323
|
+
return `${proxyBase}/p/${pHash}${format === "webp" ? ".webp" : ".png"}?${qs}`;
|
|
324
|
+
} else {
|
|
325
|
+
return `${proxyBase}/p/${pHash}?${qs}`;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
const b58url = multihash.toB58String(Buffer.from(realUrl.toString()));
|
|
329
|
+
return `${proxyBase}/p/${b58url}${fileExtension ? format === "webp" ? ".webp" : ".png" : ""}?${qs}`;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// src/methods/img.method.ts
|
|
333
|
+
function img(el, webp, state) {
|
|
334
|
+
let src = el.getAttribute("src") || "";
|
|
335
|
+
const decodedSrc = decodeURIComponent(
|
|
336
|
+
src.replace(/&#(\d+);/g, (_, dec) => String.fromCharCode(dec)).replace(/&#x([0-9a-f]+);/gi, (_, hex) => String.fromCharCode(parseInt(hex, 16)))
|
|
337
|
+
).trim();
|
|
338
|
+
const isInvalid = !src || decodedSrc.startsWith("javascript") || decodedSrc.startsWith("vbscript") || decodedSrc === "x";
|
|
339
|
+
if (isInvalid) {
|
|
340
|
+
src = "";
|
|
341
|
+
}
|
|
342
|
+
const isRelative = !/^https?:\/\//i.test(src) && !src.startsWith("/");
|
|
343
|
+
if (isRelative) {
|
|
344
|
+
src = "";
|
|
345
|
+
}
|
|
346
|
+
["onerror", "dynsrc", "lowsrc", "width", "height"].forEach((attr) => el.removeAttribute(attr));
|
|
347
|
+
el.setAttribute("itemprop", "image");
|
|
348
|
+
const isLCP = state && !state.firstImageFound;
|
|
349
|
+
if (isLCP) {
|
|
350
|
+
el.setAttribute("loading", "eager");
|
|
351
|
+
el.setAttribute("fetchpriority", "high");
|
|
352
|
+
state.firstImageFound = true;
|
|
353
|
+
} else {
|
|
354
|
+
el.setAttribute("loading", "lazy");
|
|
355
|
+
el.setAttribute("decoding", "async");
|
|
356
|
+
}
|
|
357
|
+
const cls = el.getAttribute("class") || "";
|
|
358
|
+
const shouldReplace = !cls.includes("no-replace");
|
|
359
|
+
const hasAlreadyProxied = src.startsWith("https://images.ecency.com");
|
|
360
|
+
if (shouldReplace && !hasAlreadyProxied) {
|
|
361
|
+
const proxified = proxifyImageSrc(src, 0, 0, webp ? "webp" : "match");
|
|
362
|
+
el.setAttribute("src", proxified);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
function createImageHTML(src, isLCP, webp) {
|
|
366
|
+
const loading = isLCP ? "eager" : "lazy";
|
|
367
|
+
const fetch = isLCP ? 'fetchpriority="high"' : 'decoding="async"';
|
|
368
|
+
const proxified = proxifyImageSrc(src, 0, 0, webp ? "webp" : "match");
|
|
369
|
+
return `<img
|
|
370
|
+
class="markdown-img-link"
|
|
371
|
+
src="${proxified}"
|
|
372
|
+
loading="${loading}"
|
|
373
|
+
${fetch}
|
|
374
|
+
itemprop="image"
|
|
375
|
+
/>`;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// src/methods/a.method.ts
|
|
379
|
+
var normalizeValue = (value) => value ? value.trim() : "";
|
|
380
|
+
var matchesHref = (href, value) => {
|
|
381
|
+
const normalizedHref = normalizeValue(href);
|
|
382
|
+
if (!normalizedHref) {
|
|
383
|
+
return false;
|
|
384
|
+
}
|
|
385
|
+
return normalizeValue(value) === normalizedHref;
|
|
386
|
+
};
|
|
387
|
+
var getInlineMeta = (el, href) => {
|
|
388
|
+
const textMatches = matchesHref(href, el.textContent);
|
|
389
|
+
const titleMatches = matchesHref(href, el.getAttribute("title"));
|
|
390
|
+
return {
|
|
391
|
+
textMatches,
|
|
392
|
+
titleMatches,
|
|
393
|
+
isInline: textMatches || titleMatches
|
|
394
|
+
};
|
|
395
|
+
};
|
|
396
|
+
function a(el, forApp, webp, parentDomain = "ecency.com") {
|
|
397
|
+
if (!el || !el.parentNode) {
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
let href = el.getAttribute("href");
|
|
401
|
+
if (!href) {
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
const className = el.getAttribute("class");
|
|
405
|
+
if (["markdown-author-link", "markdown-tag-link"].indexOf(className) !== -1) {
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
408
|
+
if (href && href.trim().toLowerCase().startsWith("javascript:")) {
|
|
409
|
+
el.removeAttribute("href");
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
if (href.match(IMG_REGEX) && href.trim().replace(/&/g, "&") === getSerializedInnerHTML(el).trim().replace(/&/g, "&")) {
|
|
413
|
+
const isLCP = false;
|
|
414
|
+
const imgHTML = createImageHTML(href, isLCP, webp);
|
|
415
|
+
const doc = DOMParser.parseFromString(imgHTML, "text/html");
|
|
416
|
+
const replaceNode = doc.body?.firstChild || doc.firstChild;
|
|
417
|
+
if (replaceNode) {
|
|
418
|
+
const importedNode = el.ownerDocument.importNode(replaceNode, true);
|
|
419
|
+
el.parentNode.replaceChild(importedNode, el);
|
|
420
|
+
}
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
423
|
+
if (href.match(IPFS_REGEX) && href.trim().replace(/&/g, "&") === getSerializedInnerHTML(el).trim().replace(/&/g, "&") && href.indexOf("#") === -1) {
|
|
424
|
+
if (forApp) {
|
|
425
|
+
el.setAttribute("data-href", href);
|
|
426
|
+
el.removeAttribute("href");
|
|
427
|
+
}
|
|
428
|
+
el.setAttribute("class", "markdown-img-link");
|
|
429
|
+
removeChildNodes(el);
|
|
430
|
+
const img2 = el.ownerDocument.createElement("img");
|
|
431
|
+
img2.setAttribute("src", href);
|
|
432
|
+
el.appendChild(img2);
|
|
433
|
+
return;
|
|
434
|
+
}
|
|
435
|
+
const postMatch = href.match(POST_REGEX);
|
|
436
|
+
if (postMatch && WHITE_LIST.includes(postMatch[1].replace(/^www\./, ""))) {
|
|
437
|
+
el.setAttribute("class", "markdown-post-link");
|
|
438
|
+
const tag = postMatch[2];
|
|
439
|
+
const author = postMatch[3].replace("@", "");
|
|
440
|
+
const permlink = sanitizePermlink(postMatch[4]);
|
|
441
|
+
if (!isValidPermlink(permlink)) return;
|
|
442
|
+
const inlineMeta = getInlineMeta(el, href);
|
|
443
|
+
if (inlineMeta.textMatches) {
|
|
444
|
+
el.textContent = `@${author}/${permlink}`;
|
|
445
|
+
}
|
|
446
|
+
const isInline = inlineMeta.isInline;
|
|
447
|
+
if (forApp) {
|
|
448
|
+
el.removeAttribute("href");
|
|
449
|
+
el.setAttribute("data-href", href);
|
|
450
|
+
el.setAttribute("data-is-inline", "" + isInline);
|
|
451
|
+
el.setAttribute("data-tag", tag);
|
|
452
|
+
el.setAttribute("data-author", author);
|
|
453
|
+
el.setAttribute("data-permlink", permlink);
|
|
454
|
+
} else {
|
|
455
|
+
const h = `/${tag}/@${author}/${permlink}`;
|
|
456
|
+
el.setAttribute("href", h);
|
|
457
|
+
el.setAttribute("data-is-inline", "" + isInline);
|
|
458
|
+
}
|
|
459
|
+
return;
|
|
460
|
+
}
|
|
461
|
+
const mentionMatch = href.match(MENTION_REGEX);
|
|
462
|
+
if (mentionMatch && WHITE_LIST.includes(mentionMatch[1].replace(/^www\./, "")) && mentionMatch.length === 3) {
|
|
463
|
+
const _author = mentionMatch[2].replace("@", "");
|
|
464
|
+
if (!isValidUsername(_author)) return;
|
|
465
|
+
const author = _author.toLowerCase();
|
|
466
|
+
el.setAttribute("class", "markdown-author-link");
|
|
467
|
+
if (author.indexOf("/") === -1) {
|
|
468
|
+
if (el.textContent === href) {
|
|
469
|
+
el.textContent = `@${author}`;
|
|
470
|
+
}
|
|
471
|
+
if (forApp) {
|
|
472
|
+
el.removeAttribute("href");
|
|
473
|
+
el.setAttribute("data-author", author);
|
|
474
|
+
} else {
|
|
475
|
+
const h = `/@${author}`;
|
|
476
|
+
el.setAttribute("href", h);
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
return;
|
|
480
|
+
}
|
|
481
|
+
const tpostMatch = href.match(INTERNAL_POST_TAG_REGEX);
|
|
482
|
+
let isValidDomain = false;
|
|
483
|
+
if (tpostMatch && tpostMatch.length === 4) {
|
|
484
|
+
if (tpostMatch[1].indexOf("/") === 0) {
|
|
485
|
+
isValidDomain = true;
|
|
486
|
+
} else if (tpostMatch[1].includes(".")) {
|
|
487
|
+
const domain = tpostMatch[1].replace(/^https?:\/\//, "").replace(/^www\./, "");
|
|
488
|
+
isValidDomain = WHITE_LIST.includes(domain);
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
if (isValidDomain) {
|
|
492
|
+
const pathSegment = tpostMatch[3].split("?")[0];
|
|
493
|
+
if (SECTION_LIST.some((v) => pathSegment === v || pathSegment.startsWith(v + "/"))) {
|
|
494
|
+
el.setAttribute("class", "markdown-profile-link");
|
|
495
|
+
const author = tpostMatch[2].replace("@", "").toLowerCase();
|
|
496
|
+
const section = tpostMatch[3];
|
|
497
|
+
if (!isValidPermlink(section)) return;
|
|
498
|
+
if (el.textContent === href) {
|
|
499
|
+
el.textContent = `@${author}/${section}`;
|
|
500
|
+
}
|
|
501
|
+
if (forApp) {
|
|
502
|
+
const ha = `https://ecency.com/@${author}/${section}`;
|
|
503
|
+
el.setAttribute("href", ha);
|
|
504
|
+
} else {
|
|
505
|
+
const h = `/@${author}/${section}`;
|
|
506
|
+
el.setAttribute("href", h);
|
|
507
|
+
}
|
|
508
|
+
return;
|
|
509
|
+
} else {
|
|
510
|
+
let tag = "post";
|
|
511
|
+
if (tpostMatch[1] && !tpostMatch[1].includes(".")) {
|
|
512
|
+
[, tag] = tpostMatch;
|
|
513
|
+
tag = tag.replace("/", "");
|
|
514
|
+
}
|
|
515
|
+
el.setAttribute("class", "markdown-post-link");
|
|
516
|
+
const author = tpostMatch[2].replace("@", "");
|
|
517
|
+
const permlink = sanitizePermlink(tpostMatch[3]);
|
|
518
|
+
if (!isValidPermlink(permlink)) return;
|
|
519
|
+
const inlineMeta = getInlineMeta(el, href);
|
|
520
|
+
if (inlineMeta.textMatches) {
|
|
521
|
+
el.textContent = `@${author}/${permlink}`;
|
|
522
|
+
}
|
|
523
|
+
const isInline = inlineMeta.isInline;
|
|
524
|
+
if (forApp) {
|
|
525
|
+
el.removeAttribute("href");
|
|
526
|
+
el.setAttribute("data-href", href);
|
|
527
|
+
el.setAttribute("data-is-inline", "" + isInline);
|
|
528
|
+
el.setAttribute("data-tag", tag);
|
|
529
|
+
el.setAttribute("data-author", author);
|
|
530
|
+
el.setAttribute("data-permlink", permlink);
|
|
531
|
+
} else {
|
|
532
|
+
const h = `/${tag}/@${author}/${permlink}`;
|
|
533
|
+
el.setAttribute("href", h);
|
|
534
|
+
el.setAttribute("data-is-inline", "" + isInline);
|
|
535
|
+
}
|
|
536
|
+
return;
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
const imentionMatch = href.match(INTERNAL_MENTION_REGEX);
|
|
540
|
+
if (imentionMatch) {
|
|
541
|
+
const _author = imentionMatch[0].replace("/@", "");
|
|
542
|
+
if (!isValidUsername(_author)) return;
|
|
543
|
+
const author = _author.toLowerCase();
|
|
544
|
+
el.setAttribute("class", "markdown-author-link");
|
|
545
|
+
if (author.indexOf("/") === -1) {
|
|
546
|
+
if (el.textContent === href) {
|
|
547
|
+
el.textContent = `@${author}`;
|
|
548
|
+
}
|
|
549
|
+
if (forApp) {
|
|
550
|
+
el.removeAttribute("href");
|
|
551
|
+
el.setAttribute("data-author", author);
|
|
552
|
+
} else {
|
|
553
|
+
const h = `/@${author}`;
|
|
554
|
+
el.setAttribute("href", h);
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
return;
|
|
558
|
+
}
|
|
559
|
+
const cpostMatch = href.match(INTERNAL_POST_REGEX);
|
|
560
|
+
if (cpostMatch && cpostMatch.length === 3 && cpostMatch[1].indexOf("@") === 0) {
|
|
561
|
+
const pathSegment2 = cpostMatch[2].split("?")[0];
|
|
562
|
+
if (SECTION_LIST.some((v) => pathSegment2 === v || pathSegment2.startsWith(v + "/"))) {
|
|
563
|
+
el.setAttribute("class", "markdown-profile-link");
|
|
564
|
+
const author = cpostMatch[1].replace("@", "").toLowerCase();
|
|
565
|
+
const section = cpostMatch[2];
|
|
566
|
+
if (el.textContent === href) {
|
|
567
|
+
el.textContent = `@${author}/${section}`;
|
|
568
|
+
}
|
|
569
|
+
if (forApp) {
|
|
570
|
+
const ha = `https://ecency.com/@${author}/${section}`;
|
|
571
|
+
el.setAttribute("href", ha);
|
|
572
|
+
} else {
|
|
573
|
+
const h = `/@${author}/${section}`;
|
|
574
|
+
el.setAttribute("href", h);
|
|
575
|
+
}
|
|
576
|
+
return;
|
|
577
|
+
} else {
|
|
578
|
+
el.setAttribute("class", "markdown-post-link");
|
|
579
|
+
const tag = "post";
|
|
580
|
+
const author = cpostMatch[1].replace("@", "");
|
|
581
|
+
const permlink = sanitizePermlink(cpostMatch[2]);
|
|
582
|
+
if (!isValidPermlink(permlink)) return;
|
|
583
|
+
const inlineMeta = getInlineMeta(el, href);
|
|
584
|
+
if (inlineMeta.textMatches) {
|
|
585
|
+
el.textContent = `@${author}/${permlink}`;
|
|
586
|
+
}
|
|
587
|
+
const isInline = inlineMeta.isInline;
|
|
588
|
+
if (forApp) {
|
|
589
|
+
el.removeAttribute("href");
|
|
590
|
+
el.setAttribute("data-href", href);
|
|
591
|
+
el.setAttribute("data-is-inline", "" + isInline);
|
|
592
|
+
el.setAttribute("data-tag", tag);
|
|
593
|
+
el.setAttribute("data-author", author);
|
|
594
|
+
el.setAttribute("data-permlink", permlink);
|
|
595
|
+
} else {
|
|
596
|
+
const h = `/${tag}/@${author}/${permlink}`;
|
|
597
|
+
el.setAttribute("href", h);
|
|
598
|
+
el.setAttribute("data-is-inline", "" + isInline);
|
|
599
|
+
}
|
|
600
|
+
return;
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
const topicMatch = href.match(TOPIC_REGEX);
|
|
604
|
+
if (topicMatch && WHITE_LIST.includes(topicMatch[1].replace(/^www\./, "")) && topicMatch.length === 4) {
|
|
605
|
+
el.setAttribute("class", "markdown-tag-link");
|
|
606
|
+
const filter = topicMatch[2];
|
|
607
|
+
const tag = topicMatch[3];
|
|
608
|
+
if (el.textContent === href) {
|
|
609
|
+
el.textContent = `/${filter}/${tag}`;
|
|
610
|
+
}
|
|
611
|
+
if (forApp) {
|
|
612
|
+
el.removeAttribute("href");
|
|
613
|
+
el.setAttribute("data-filter", filter);
|
|
614
|
+
el.setAttribute("data-tag", tag);
|
|
615
|
+
} else {
|
|
616
|
+
const h = `/${filter}/${tag}`;
|
|
617
|
+
el.setAttribute("href", h);
|
|
618
|
+
}
|
|
619
|
+
return;
|
|
620
|
+
}
|
|
621
|
+
const itopicMatch = href.match(INTERNAL_TOPIC_REGEX);
|
|
622
|
+
if (itopicMatch && itopicMatch.length === 3) {
|
|
623
|
+
el.setAttribute("class", "markdown-tag-link");
|
|
624
|
+
const filter = itopicMatch[1];
|
|
625
|
+
const tag = itopicMatch[2];
|
|
626
|
+
if (el.textContent === href) {
|
|
627
|
+
el.textContent = `/${filter}/${tag}`;
|
|
628
|
+
}
|
|
629
|
+
if (forApp) {
|
|
630
|
+
el.removeAttribute("href");
|
|
631
|
+
el.setAttribute("data-filter", filter);
|
|
632
|
+
el.setAttribute("data-tag", tag);
|
|
633
|
+
} else {
|
|
634
|
+
const h = `/${filter}/${tag}`;
|
|
635
|
+
el.setAttribute("href", h);
|
|
636
|
+
}
|
|
637
|
+
return;
|
|
638
|
+
}
|
|
639
|
+
const comMatch = href.match(CUSTOM_COMMUNITY_REGEX);
|
|
640
|
+
if (comMatch && WHITE_LIST.includes(comMatch[1].replace(/^www\./, ""))) {
|
|
641
|
+
el.setAttribute("class", "markdown-community-link");
|
|
642
|
+
const community = comMatch[2];
|
|
643
|
+
let filter = comMatch[3].substring(1);
|
|
644
|
+
if (!filter) filter = "created";
|
|
645
|
+
if (filter === "about" || filter === "discord") {
|
|
646
|
+
filter = "created";
|
|
647
|
+
}
|
|
648
|
+
if (el.textContent === href) {
|
|
649
|
+
el.textContent = `${filter}/${community}`;
|
|
650
|
+
}
|
|
651
|
+
if (forApp) {
|
|
652
|
+
el.removeAttribute("href");
|
|
653
|
+
el.setAttribute("data-community", community);
|
|
654
|
+
el.setAttribute("data-filter", filter);
|
|
655
|
+
} else {
|
|
656
|
+
const h = `/${filter}/${community}`;
|
|
657
|
+
el.setAttribute("href", h);
|
|
658
|
+
}
|
|
659
|
+
return;
|
|
660
|
+
}
|
|
661
|
+
const cccMatch = href.match(CCC_REGEX);
|
|
662
|
+
if (cccMatch && WHITE_LIST.includes(cccMatch[1].replace(/^www\./, ""))) {
|
|
663
|
+
el.setAttribute("class", "markdown-post-link");
|
|
664
|
+
const tag = "ccc";
|
|
665
|
+
const author = cccMatch[2].replace("@", "");
|
|
666
|
+
const permlink = sanitizePermlink(cccMatch[3]);
|
|
667
|
+
if (!isValidPermlink(permlink)) return;
|
|
668
|
+
const inlineMeta = getInlineMeta(el, href);
|
|
669
|
+
if (inlineMeta.textMatches) {
|
|
670
|
+
el.textContent = `@${author}/${permlink}`;
|
|
671
|
+
}
|
|
672
|
+
const isInline = inlineMeta.isInline;
|
|
673
|
+
if (forApp) {
|
|
674
|
+
el.removeAttribute("href");
|
|
675
|
+
el.setAttribute("data-href", href);
|
|
676
|
+
el.setAttribute("data-is-inline", "" + isInline);
|
|
677
|
+
el.setAttribute("data-tag", tag);
|
|
678
|
+
el.setAttribute("data-author", author);
|
|
679
|
+
el.setAttribute("data-permlink", permlink);
|
|
680
|
+
} else {
|
|
681
|
+
const h = `/${tag}/@${author}/${permlink}`;
|
|
682
|
+
el.setAttribute("href", h);
|
|
683
|
+
el.setAttribute("data-is-inline", "" + isInline);
|
|
684
|
+
}
|
|
685
|
+
return;
|
|
686
|
+
}
|
|
687
|
+
const BCmatch = href.match(BITCHUTE_REGEX);
|
|
688
|
+
if (BCmatch && BCmatch[1] && el.textContent.trim() === href) {
|
|
689
|
+
const vid = BCmatch[1];
|
|
690
|
+
el.setAttribute("class", "markdown-video-link");
|
|
691
|
+
el.removeAttribute("href");
|
|
692
|
+
const embedSrc = `https://www.bitchute.com/embed/${vid}/`;
|
|
693
|
+
el.textContent = "";
|
|
694
|
+
el.setAttribute("data-embed-src", embedSrc);
|
|
695
|
+
const play = el.ownerDocument.createElement("span");
|
|
696
|
+
play.setAttribute("class", "markdown-video-play");
|
|
697
|
+
el.appendChild(play);
|
|
698
|
+
return;
|
|
699
|
+
}
|
|
700
|
+
const RBmatch = href.match(RUMBLE_REGEX);
|
|
701
|
+
if (RBmatch && RBmatch[1] && el.textContent.trim() === href) {
|
|
702
|
+
const vid = RBmatch[1];
|
|
703
|
+
const embedSrc = `https://www.rumble.com/embed/${vid}/?pub=4`;
|
|
704
|
+
el.setAttribute("class", "markdown-video-link");
|
|
705
|
+
el.removeAttribute("href");
|
|
706
|
+
el.textContent = "";
|
|
707
|
+
el.setAttribute("data-embed-src", embedSrc);
|
|
708
|
+
const play = el.ownerDocument.createElement("span");
|
|
709
|
+
play.setAttribute("class", "markdown-video-play");
|
|
710
|
+
el.appendChild(play);
|
|
711
|
+
return;
|
|
712
|
+
}
|
|
713
|
+
const BNmatch = href.match(BRIGHTEON_REGEX);
|
|
714
|
+
if (BNmatch && BNmatch[2] && el.textContent.trim() === href) {
|
|
715
|
+
const vid = BNmatch[2];
|
|
716
|
+
const embedSrc = `https://www.brighteon.com/embed/${vid}`;
|
|
717
|
+
el.setAttribute("class", "markdown-video-link");
|
|
718
|
+
el.removeAttribute("href");
|
|
719
|
+
el.textContent = "";
|
|
720
|
+
el.setAttribute("data-embed-src", embedSrc);
|
|
721
|
+
const play = el.ownerDocument.createElement("span");
|
|
722
|
+
play.setAttribute("class", "markdown-video-play");
|
|
723
|
+
el.appendChild(play);
|
|
724
|
+
return;
|
|
725
|
+
}
|
|
726
|
+
let match = href.match(YOUTUBE_REGEX);
|
|
727
|
+
if (match && match[1] && el.textContent.trim() === href) {
|
|
728
|
+
el.setAttribute("class", "markdown-video-link markdown-video-link-youtube");
|
|
729
|
+
el.removeAttribute("href");
|
|
730
|
+
const vid = match[1];
|
|
731
|
+
const thumbnail = proxifyImageSrc(`https://img.youtube.com/vi/${vid.split("?")[0]}/hqdefault.jpg`, 0, 0, webp ? "webp" : "match");
|
|
732
|
+
const embedSrc = `https://www.youtube.com/embed/${vid}?autoplay=1`;
|
|
733
|
+
el.textContent = "";
|
|
734
|
+
el.setAttribute("data-embed-src", embedSrc);
|
|
735
|
+
el.setAttribute("data-youtube", vid);
|
|
736
|
+
const startTime = extractYtStartTime(href);
|
|
737
|
+
if (startTime) {
|
|
738
|
+
el.setAttribute("data-start-time", startTime);
|
|
739
|
+
}
|
|
740
|
+
const thumbImg = el.ownerDocument.createElement("img");
|
|
741
|
+
thumbImg.setAttribute("class", "no-replace video-thumbnail");
|
|
742
|
+
thumbImg.setAttribute("itemprop", "thumbnailUrl");
|
|
743
|
+
thumbImg.setAttribute("src", thumbnail);
|
|
744
|
+
const play = el.ownerDocument.createElement("span");
|
|
745
|
+
play.setAttribute("class", "markdown-video-play");
|
|
746
|
+
el.appendChild(thumbImg);
|
|
747
|
+
el.appendChild(play);
|
|
748
|
+
return;
|
|
749
|
+
}
|
|
750
|
+
match = href.match(VIMEO_REGEX);
|
|
751
|
+
if (match && match[3] && href === el.textContent) {
|
|
752
|
+
el.setAttribute("class", "markdown-video-link markdown-video-link-vimeo");
|
|
753
|
+
el.removeAttribute("href");
|
|
754
|
+
const embedSrc = `https://player.vimeo.com/video/${match[3]}`;
|
|
755
|
+
el.textContent = "";
|
|
756
|
+
const ifr = el.ownerDocument.createElement("iframe");
|
|
757
|
+
ifr.setAttribute("frameborder", "0");
|
|
758
|
+
ifr.setAttribute("allowfullscreen", "true");
|
|
759
|
+
ifr.setAttribute("src", embedSrc);
|
|
760
|
+
el.appendChild(ifr);
|
|
761
|
+
return;
|
|
762
|
+
}
|
|
763
|
+
match = href.match(TWITCH_REGEX);
|
|
764
|
+
if (match && match[2] && href === el.textContent) {
|
|
765
|
+
el.setAttribute("class", "markdown-video-link markdown-video-link-twitch");
|
|
766
|
+
el.removeAttribute("href");
|
|
767
|
+
let embedSrc = "";
|
|
768
|
+
const parent = parentDomain ? `&parent=${parentDomain}` : "";
|
|
769
|
+
if (match[1] === void 0) {
|
|
770
|
+
embedSrc = `https://player.twitch.tv/?channel=${match[2]}${parent}`;
|
|
771
|
+
} else if (match[1] === "videos") {
|
|
772
|
+
embedSrc = `https://player.twitch.tv/?video=${match[2]}${parent}`;
|
|
773
|
+
} else {
|
|
774
|
+
embedSrc = `https://player.twitch.tv/?channel=${match[2]}${parent}`;
|
|
775
|
+
}
|
|
776
|
+
el.textContent = "";
|
|
777
|
+
const ifr = el.ownerDocument.createElement("iframe");
|
|
778
|
+
ifr.setAttribute("frameborder", "0");
|
|
779
|
+
ifr.setAttribute("allowfullscreen", "true");
|
|
780
|
+
ifr.setAttribute("src", embedSrc);
|
|
781
|
+
el.appendChild(ifr);
|
|
782
|
+
return;
|
|
783
|
+
}
|
|
784
|
+
if (el.textContent.trim() === href) {
|
|
785
|
+
SPOTIFY_REGEX.lastIndex = 0;
|
|
786
|
+
match = SPOTIFY_REGEX.exec(href);
|
|
787
|
+
if (match && match[1]) {
|
|
788
|
+
el.setAttribute("class", "markdown-audio-link markdown-audio-link-spotify");
|
|
789
|
+
el.removeAttribute("href");
|
|
790
|
+
const embedSrc = `https://open.spotify.com/embed/playlist/${match[1]}`;
|
|
791
|
+
el.textContent = "";
|
|
792
|
+
const ifr = el.ownerDocument.createElement("iframe");
|
|
793
|
+
ifr.setAttribute("frameborder", "0");
|
|
794
|
+
ifr.setAttribute("allowfullscreen", "true");
|
|
795
|
+
ifr.setAttribute("src", embedSrc);
|
|
796
|
+
ifr.setAttribute("sandbox", "allow-scripts allow-same-origin allow-popups");
|
|
797
|
+
el.appendChild(ifr);
|
|
798
|
+
return;
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
match = href.match(LOOM_REGEX);
|
|
802
|
+
if (match && match[2] && el.textContent.trim() === href) {
|
|
803
|
+
el.setAttribute("class", "markdown-video-link markdown-video-link-loom");
|
|
804
|
+
el.removeAttribute("href");
|
|
805
|
+
const embedSrc = `https://www.loom.com/embed/${match[2]}`;
|
|
806
|
+
el.textContent = "";
|
|
807
|
+
const ifr = el.ownerDocument.createElement("iframe");
|
|
808
|
+
ifr.setAttribute("frameborder", "0");
|
|
809
|
+
ifr.setAttribute("allowfullscreen", "true");
|
|
810
|
+
ifr.setAttribute("src", embedSrc);
|
|
811
|
+
ifr.setAttribute("sandbox", "allow-scripts allow-same-origin allow-popups");
|
|
812
|
+
el.appendChild(ifr);
|
|
813
|
+
return;
|
|
814
|
+
}
|
|
815
|
+
const imgEls = el.getElementsByTagName("img");
|
|
816
|
+
if (imgEls.length === 1 || el.textContent.trim() === href) {
|
|
817
|
+
D_TUBE_REGEX.lastIndex = 0;
|
|
818
|
+
match = D_TUBE_REGEX.exec(href);
|
|
819
|
+
if (match && match[2] && match[3]) {
|
|
820
|
+
el.setAttribute("class", "markdown-video-link markdown-video-link-dtube");
|
|
821
|
+
el.removeAttribute("href");
|
|
822
|
+
const videoHref = `https://emb.d.tube/#!/${match[2]}/${match[3]}`;
|
|
823
|
+
el.setAttribute("data-embed-src", videoHref);
|
|
824
|
+
if (imgEls.length === 1) {
|
|
825
|
+
const src = imgEls[0].getAttribute("src");
|
|
826
|
+
if (src) {
|
|
827
|
+
const thumbnail = proxifyImageSrc(src.replace(/\s+/g, ""), 0, 0, webp ? "webp" : "match");
|
|
828
|
+
const thumbImg = el.ownerDocument.createElement("img");
|
|
829
|
+
thumbImg.setAttribute("class", "no-replace video-thumbnail");
|
|
830
|
+
thumbImg.setAttribute("itemprop", "thumbnailUrl");
|
|
831
|
+
thumbImg.setAttribute("src", thumbnail);
|
|
832
|
+
el.appendChild(thumbImg);
|
|
833
|
+
el.removeChild(imgEls[0]);
|
|
834
|
+
}
|
|
835
|
+
} else {
|
|
836
|
+
el.textContent = "";
|
|
837
|
+
}
|
|
838
|
+
const play = el.ownerDocument.createElement("span");
|
|
839
|
+
play.setAttribute("class", "markdown-video-play");
|
|
840
|
+
el.appendChild(play);
|
|
841
|
+
return;
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
D_TUBE_REGEX2.lastIndex = 0;
|
|
845
|
+
match = D_TUBE_REGEX2.exec(href);
|
|
846
|
+
if (match && match[2] && match[3]) {
|
|
847
|
+
el.setAttribute("class", "markdown-video-link markdown-video-link-dtube");
|
|
848
|
+
el.removeAttribute("href");
|
|
849
|
+
el.textContent = "";
|
|
850
|
+
const videoHref = `https://emb.d.tube/#!/${match[2]}/${match[3]}`;
|
|
851
|
+
el.setAttribute("data-embed-src", videoHref);
|
|
852
|
+
const play = el.ownerDocument.createElement("span");
|
|
853
|
+
play.setAttribute("class", "markdown-video-play");
|
|
854
|
+
el.appendChild(play);
|
|
855
|
+
return;
|
|
856
|
+
}
|
|
857
|
+
match = href.match(SPEAK_REGEX);
|
|
858
|
+
if (match) {
|
|
859
|
+
const imgEls2 = el.getElementsByTagName("img");
|
|
860
|
+
if (imgEls2.length === 1 || el.textContent.trim() === href) {
|
|
861
|
+
if ((match[1] || match[2]) && match[3]) {
|
|
862
|
+
const videoHref = `https://3speak.tv/embed?v=${match[3]}`;
|
|
863
|
+
el.setAttribute("class", "markdown-video-link markdown-video-link-speak");
|
|
864
|
+
el.removeAttribute("href");
|
|
865
|
+
el.setAttribute("data-embed-src", videoHref);
|
|
866
|
+
if (el.textContent.trim() === href) {
|
|
867
|
+
el.textContent = "";
|
|
868
|
+
}
|
|
869
|
+
if (imgEls2.length === 1) {
|
|
870
|
+
const src = imgEls2[0].getAttribute("src");
|
|
871
|
+
if (src) {
|
|
872
|
+
const thumbnail = proxifyImageSrc(src.replace(/\s+/g, ""), 0, 0, webp ? "webp" : "match");
|
|
873
|
+
const thumbImg = el.ownerDocument.createElement("img");
|
|
874
|
+
thumbImg.setAttribute("class", "no-replace video-thumbnail");
|
|
875
|
+
thumbImg.setAttribute("itemprop", "thumbnailUrl");
|
|
876
|
+
thumbImg.setAttribute("src", thumbnail);
|
|
877
|
+
el.appendChild(thumbImg);
|
|
878
|
+
el.removeChild(imgEls2[0]);
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
const play = el.ownerDocument.createElement("span");
|
|
882
|
+
play.setAttribute("class", "markdown-video-play");
|
|
883
|
+
el.appendChild(play);
|
|
884
|
+
return;
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
const matchT = href.match(TWITTER_REGEX);
|
|
889
|
+
if (matchT && el.textContent.trim() === href) {
|
|
890
|
+
TWITTER_REGEX.lastIndex = 0;
|
|
891
|
+
const e = TWITTER_REGEX.exec(href);
|
|
892
|
+
if (e) {
|
|
893
|
+
const url = e[0].replace(/(<([^>]+)>)/gi, "");
|
|
894
|
+
const author = e[1].replace(/(<([^>]+)>)/gi, "");
|
|
895
|
+
const blockquote = el.ownerDocument.createElement("blockquote");
|
|
896
|
+
blockquote.setAttribute("class", "twitter-tweet");
|
|
897
|
+
const p2 = el.ownerDocument.createElement("p");
|
|
898
|
+
p2.textContent = url;
|
|
899
|
+
const textNode = el.ownerDocument.createTextNode("- ");
|
|
900
|
+
const a2 = el.ownerDocument.createElement("a");
|
|
901
|
+
a2.setAttribute("href", url);
|
|
902
|
+
a2.textContent = author;
|
|
903
|
+
blockquote.appendChild(p2);
|
|
904
|
+
blockquote.appendChild(textNode);
|
|
905
|
+
blockquote.appendChild(a2);
|
|
906
|
+
el.parentNode.replaceChild(blockquote, el);
|
|
907
|
+
return;
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
if (href.indexOf("https://hivesigner.com/sign/account-witness-vote?witness=") === 0 && forApp) {
|
|
911
|
+
el.setAttribute("class", "markdown-witnesses-link");
|
|
912
|
+
el.setAttribute("data-href", href);
|
|
913
|
+
el.removeAttribute("href");
|
|
914
|
+
return;
|
|
915
|
+
}
|
|
916
|
+
if (href.indexOf("hivesigner.com/sign/update-proposal-votes?proposal_ids") >= 0 && forApp) {
|
|
917
|
+
try {
|
|
918
|
+
const m = decodeURI(href).match(/proposal_ids=\[(\d+)]/);
|
|
919
|
+
if (m) {
|
|
920
|
+
el.setAttribute("class", "markdown-proposal-link");
|
|
921
|
+
el.setAttribute("data-href", href);
|
|
922
|
+
el.setAttribute("data-proposal", m[1]);
|
|
923
|
+
el.removeAttribute("href");
|
|
924
|
+
return;
|
|
925
|
+
}
|
|
926
|
+
} catch (e) {
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
el.setAttribute("class", "markdown-external-link");
|
|
930
|
+
if (!/^((#)|(mailto:)|(\/(?!\/))|(((steem|hive|esteem|ecency|https?):)?\/\/))/.test(href)) {
|
|
931
|
+
href = `https://${href}`;
|
|
932
|
+
}
|
|
933
|
+
if (forApp) {
|
|
934
|
+
el.setAttribute("data-href", href);
|
|
935
|
+
const match2 = href.match(YOUTUBE_REGEX);
|
|
936
|
+
if (match2 && match2[1]) {
|
|
937
|
+
const vid = match2[1];
|
|
938
|
+
el.setAttribute("data-youtube", vid);
|
|
939
|
+
const startTime = extractYtStartTime(href);
|
|
940
|
+
if (startTime) {
|
|
941
|
+
el.setAttribute("data-start-time", startTime);
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
el.removeAttribute("href");
|
|
945
|
+
} else {
|
|
946
|
+
const matchS = href.match(SECTION_REGEX);
|
|
947
|
+
if (matchS) {
|
|
948
|
+
el.setAttribute("class", "markdown-internal-link");
|
|
949
|
+
} else {
|
|
950
|
+
el.setAttribute("target", "_blank");
|
|
951
|
+
el.setAttribute("rel", "noopener");
|
|
952
|
+
}
|
|
953
|
+
el.setAttribute("href", href);
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
// src/methods/iframe.method.ts
|
|
958
|
+
function iframe(el, parentDomain = "ecency.com") {
|
|
959
|
+
if (!el || !el.parentNode) {
|
|
960
|
+
return;
|
|
961
|
+
}
|
|
962
|
+
const src = el.getAttribute("src");
|
|
963
|
+
if (!src) {
|
|
964
|
+
el.parentNode.removeChild(el);
|
|
965
|
+
return;
|
|
966
|
+
}
|
|
967
|
+
if (src.match(YOUTUBE_EMBED_REGEX)) {
|
|
968
|
+
const s = src.replace(/\?.+$/, "");
|
|
969
|
+
el.setAttribute("src", s);
|
|
970
|
+
return;
|
|
971
|
+
}
|
|
972
|
+
if (src.match(BITCHUTE_REGEX)) {
|
|
973
|
+
return;
|
|
974
|
+
}
|
|
975
|
+
const m = src.match(VIMEO_EMBED_REGEX);
|
|
976
|
+
if (m && m.length === 2) {
|
|
977
|
+
const s = `https://player.vimeo.com/video/${m[1]}`;
|
|
978
|
+
el.setAttribute("src", s);
|
|
979
|
+
return;
|
|
980
|
+
}
|
|
981
|
+
if (src.match(TWITCH_EMBED_REGEX)) {
|
|
982
|
+
let s = src;
|
|
983
|
+
if (!s.includes("parent=")) {
|
|
984
|
+
const separator = s.includes("?") ? "&" : "?";
|
|
985
|
+
s = `${s}${separator}parent=${parentDomain}`;
|
|
986
|
+
}
|
|
987
|
+
if (!s.includes("autoplay=")) {
|
|
988
|
+
const separator = s.includes("?") ? "&" : "?";
|
|
989
|
+
s = `${s}${separator}autoplay=false`;
|
|
990
|
+
}
|
|
991
|
+
el.setAttribute("src", s);
|
|
992
|
+
return;
|
|
993
|
+
}
|
|
994
|
+
if (src.match(SPEAK_EMBED_REGEX)) {
|
|
995
|
+
const normalizedSrc = src.replace(/3speak\.[a-z]+/i, "3speak.tv");
|
|
996
|
+
const hasAutoplay = /[?&]autoplay=/.test(normalizedSrc);
|
|
997
|
+
const s = hasAutoplay ? normalizedSrc : `${normalizedSrc}${normalizedSrc.includes("?") ? "&" : "?"}autoplay=true`;
|
|
998
|
+
el.setAttribute("src", s);
|
|
999
|
+
return;
|
|
1000
|
+
}
|
|
1001
|
+
if (src.match(SPOTIFY_EMBED_REGEX)) {
|
|
1002
|
+
el.setAttribute("src", src);
|
|
1003
|
+
el.setAttribute("sandbox", "allow-scripts allow-same-origin allow-popups");
|
|
1004
|
+
el.setAttribute("frameborder", "0");
|
|
1005
|
+
return;
|
|
1006
|
+
}
|
|
1007
|
+
if (src.match(SOUNDCLOUD_EMBED_REGEX)) {
|
|
1008
|
+
const match = src.match(/url=(.+?)(?:&|$)/);
|
|
1009
|
+
if (match && match[1]) {
|
|
1010
|
+
const s = `https://w.soundcloud.com/player/?url=${match[1]}&auto_play=false&hide_related=false&show_comments=true&show_user=true&show_reposts=false&visual=true`;
|
|
1011
|
+
el.setAttribute("src", s);
|
|
1012
|
+
}
|
|
1013
|
+
return;
|
|
1014
|
+
}
|
|
1015
|
+
if (src.match(D_TUBE_EMBED_REGEX)) {
|
|
1016
|
+
el.setAttribute("src", src);
|
|
1017
|
+
el.setAttribute("sandbox", "allow-scripts allow-same-origin");
|
|
1018
|
+
el.setAttribute("frameborder", "0");
|
|
1019
|
+
el.setAttribute("allowfullscreen", "true");
|
|
1020
|
+
return;
|
|
1021
|
+
}
|
|
1022
|
+
if (src.match(VIMM_EMBED_REGEX)) {
|
|
1023
|
+
el.setAttribute("src", src);
|
|
1024
|
+
el.setAttribute("sandbox", "allow-scripts allow-same-origin allow-popups");
|
|
1025
|
+
el.setAttribute("frameborder", "0");
|
|
1026
|
+
el.setAttribute("allowfullscreen", "true");
|
|
1027
|
+
return;
|
|
1028
|
+
}
|
|
1029
|
+
if (src.match(DAPPLR_REGEX)) {
|
|
1030
|
+
el.setAttribute("src", src);
|
|
1031
|
+
el.setAttribute("sandbox", "allow-scripts allow-same-origin");
|
|
1032
|
+
el.setAttribute("frameborder", "0");
|
|
1033
|
+
el.setAttribute("allowfullscreen", "true");
|
|
1034
|
+
return;
|
|
1035
|
+
}
|
|
1036
|
+
if (src.match(TRUVVL_REGEX)) {
|
|
1037
|
+
el.setAttribute("src", src);
|
|
1038
|
+
el.setAttribute("sandbox", "allow-scripts allow-same-origin allow-popups");
|
|
1039
|
+
el.setAttribute("frameborder", "0");
|
|
1040
|
+
el.setAttribute("class", "portrait-embed");
|
|
1041
|
+
el.setAttribute("allowfullscreen", "true");
|
|
1042
|
+
return;
|
|
1043
|
+
}
|
|
1044
|
+
if (src.match(LBRY_REGEX)) {
|
|
1045
|
+
el.setAttribute("src", src);
|
|
1046
|
+
el.setAttribute("frameborder", "0");
|
|
1047
|
+
return;
|
|
1048
|
+
}
|
|
1049
|
+
if (src.match(ODYSEE_REGEX)) {
|
|
1050
|
+
el.setAttribute("src", src);
|
|
1051
|
+
el.setAttribute("frameborder", "0");
|
|
1052
|
+
return;
|
|
1053
|
+
}
|
|
1054
|
+
if (src.match(SKATEHIVE_IPFS_REGEX)) {
|
|
1055
|
+
el.setAttribute("src", src);
|
|
1056
|
+
el.setAttribute("allowfullscreen", "true");
|
|
1057
|
+
return;
|
|
1058
|
+
}
|
|
1059
|
+
if (src.match(ARCH_REGEX)) {
|
|
1060
|
+
el.setAttribute("src", src);
|
|
1061
|
+
return;
|
|
1062
|
+
}
|
|
1063
|
+
if (src.match(RUMBLE_REGEX)) {
|
|
1064
|
+
el.setAttribute("src", src);
|
|
1065
|
+
el.setAttribute("frameborder", "0");
|
|
1066
|
+
return;
|
|
1067
|
+
}
|
|
1068
|
+
if (src.match(BRIGHTEON_REGEX)) {
|
|
1069
|
+
el.setAttribute("src", src);
|
|
1070
|
+
el.setAttribute("frameborder", "0");
|
|
1071
|
+
return;
|
|
1072
|
+
}
|
|
1073
|
+
if (src.match(BRAND_NEW_TUBE_REGEX)) {
|
|
1074
|
+
el.setAttribute("src", src);
|
|
1075
|
+
el.setAttribute("frameborder", "0");
|
|
1076
|
+
return;
|
|
1077
|
+
}
|
|
1078
|
+
if (src.match(LOOM_EMBED_REGEX)) {
|
|
1079
|
+
el.setAttribute("src", src);
|
|
1080
|
+
el.setAttribute("frameborder", "0");
|
|
1081
|
+
return;
|
|
1082
|
+
}
|
|
1083
|
+
if (src.match(AUREAL_EMBED_REGEX)) {
|
|
1084
|
+
el.setAttribute("src", src);
|
|
1085
|
+
el.setAttribute("frameborder", "0");
|
|
1086
|
+
return;
|
|
1087
|
+
}
|
|
1088
|
+
const replaceNode = el.ownerDocument.createElement("div");
|
|
1089
|
+
replaceNode.setAttribute("class", "unsupported-iframe");
|
|
1090
|
+
replaceNode.textContent = `(Unsupported ${src})`;
|
|
1091
|
+
if (el.parentNode) {
|
|
1092
|
+
el.parentNode.insertBefore(replaceNode, el);
|
|
1093
|
+
el.parentNode.removeChild(el);
|
|
1094
|
+
}
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
// src/methods/p.method.ts
|
|
1098
|
+
function p(el) {
|
|
1099
|
+
const dir = el.getAttribute("dir");
|
|
1100
|
+
if (!dir) {
|
|
1101
|
+
el.setAttribute("dir", "auto");
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
// src/methods/linkify.method.ts
|
|
1106
|
+
function linkify(content, forApp, webp) {
|
|
1107
|
+
content = content.replace(/(^|\s|>)(#[-a-z\d]+)/gi, (tag) => {
|
|
1108
|
+
if (/#[\d]+$/.test(tag)) return tag;
|
|
1109
|
+
const preceding = /^\s|>/.test(tag) ? tag[0] : "";
|
|
1110
|
+
tag = tag.replace(">", "");
|
|
1111
|
+
const tag2 = tag.trim().substring(1);
|
|
1112
|
+
const tagLower = tag2.toLowerCase();
|
|
1113
|
+
const attrs = forApp ? `data-tag="${tagLower}"` : `href="/trending/${tagLower}"`;
|
|
1114
|
+
return `${preceding}<a class="markdown-tag-link" ${attrs}>${tag.trim()}</a>`;
|
|
1115
|
+
});
|
|
1116
|
+
content = content.replace(
|
|
1117
|
+
/(^|[^a-zA-Z0-9_!#$%&*@@/]|(^|[^a-zA-Z0-9_+~.-/]))[@@]([a-z][-.a-z\d^/]+[a-z\d])/gi,
|
|
1118
|
+
(match, preceeding1, preceeding2, user) => {
|
|
1119
|
+
const userLower = user.toLowerCase();
|
|
1120
|
+
const preceedings = (preceeding1 || "") + (preceeding2 || "");
|
|
1121
|
+
if (userLower.indexOf("/") === -1 && isValidUsername(user)) {
|
|
1122
|
+
const attrs = forApp ? `data-author="${userLower}"` : `href="/@${userLower}"`;
|
|
1123
|
+
return `${preceedings}<a class="markdown-author-link" ${attrs}>@${user}</a>`;
|
|
1124
|
+
} else {
|
|
1125
|
+
return match;
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1128
|
+
);
|
|
1129
|
+
content = content.replace(
|
|
1130
|
+
/((^|\s)(\/|)@[\w.\d-]+)\/(\S+)/gi,
|
|
1131
|
+
(match, u, p1, p2, p3) => {
|
|
1132
|
+
const uu = u.trim().toLowerCase().replace("/@", "").replace("@", "");
|
|
1133
|
+
const permlink = sanitizePermlink(p3);
|
|
1134
|
+
if (!isValidPermlink(permlink)) return match;
|
|
1135
|
+
if (SECTION_LIST.some((v) => p3.includes(v))) {
|
|
1136
|
+
const attrs = forApp ? `href="https://ecency.com/@${uu}/${permlink}"` : `href="/@${uu}/${permlink}"`;
|
|
1137
|
+
return ` <a class="markdown-profile-link" ${attrs}>@${uu}/${permlink}</a>`;
|
|
1138
|
+
} else {
|
|
1139
|
+
const attrs = forApp ? `data-author="${uu}" data-tag="post" data-permlink="${permlink}"` : `href="/post/@${uu}/${permlink}"`;
|
|
1140
|
+
return ` <a class="markdown-post-link" ${attrs}>@${uu}/${permlink}</a>`;
|
|
1141
|
+
}
|
|
1142
|
+
}
|
|
1143
|
+
);
|
|
1144
|
+
let firstImageUsed = false;
|
|
1145
|
+
content = content.replace(IMG_REGEX, (imglink) => {
|
|
1146
|
+
const isLCP = !firstImageUsed;
|
|
1147
|
+
firstImageUsed = true;
|
|
1148
|
+
return createImageHTML(imglink, isLCP, webp);
|
|
1149
|
+
});
|
|
1150
|
+
return content;
|
|
1151
|
+
}
|
|
1152
|
+
|
|
1153
|
+
// src/methods/text.method.ts
|
|
1154
|
+
function text(node, forApp, webp) {
|
|
1155
|
+
if (!node || !node.parentNode) {
|
|
1156
|
+
return;
|
|
1157
|
+
}
|
|
1158
|
+
if (node.parentNode && ["a", "code"].includes(node.parentNode.nodeName.toLowerCase())) {
|
|
1159
|
+
return;
|
|
1160
|
+
}
|
|
1161
|
+
const nodeValue = node.nodeValue || "";
|
|
1162
|
+
const linkified = linkify(nodeValue, forApp, webp);
|
|
1163
|
+
if (linkified !== nodeValue) {
|
|
1164
|
+
const doc = DOMParser.parseFromString(
|
|
1165
|
+
`<span class="wr">${linkified}</span>`,
|
|
1166
|
+
"text/html"
|
|
1167
|
+
);
|
|
1168
|
+
const replaceNode = doc.body?.firstChild || doc.firstChild;
|
|
1169
|
+
if (replaceNode) {
|
|
1170
|
+
node.parentNode.insertBefore(replaceNode, node);
|
|
1171
|
+
node.parentNode.removeChild(node);
|
|
1172
|
+
}
|
|
1173
|
+
return;
|
|
1174
|
+
}
|
|
1175
|
+
if (nodeValue.match(IMG_REGEX)) {
|
|
1176
|
+
const isLCP = false;
|
|
1177
|
+
const imageHTML = createImageHTML(nodeValue, isLCP, webp);
|
|
1178
|
+
const doc = DOMParser.parseFromString(imageHTML, "text/html");
|
|
1179
|
+
const replaceNode = doc.body?.firstChild || doc.firstChild;
|
|
1180
|
+
if (replaceNode) {
|
|
1181
|
+
node.parentNode.replaceChild(replaceNode, node);
|
|
1182
|
+
}
|
|
1183
|
+
return;
|
|
1184
|
+
}
|
|
1185
|
+
if (nodeValue.match(YOUTUBE_REGEX)) {
|
|
1186
|
+
const e = YOUTUBE_REGEX.exec(nodeValue);
|
|
1187
|
+
if (e && e[1]) {
|
|
1188
|
+
const vid = e[1];
|
|
1189
|
+
const thumbnail = proxifyImageSrc(`https://img.youtube.com/vi/${vid.split("?")[0]}/hqdefault.jpg`, 0, 0, webp ? "webp" : "match");
|
|
1190
|
+
const embedSrc = `https://www.youtube.com/embed/${vid}?autoplay=1`;
|
|
1191
|
+
const startTime = extractYtStartTime(nodeValue);
|
|
1192
|
+
const container = node.ownerDocument.createElement("p");
|
|
1193
|
+
const anchor = node.ownerDocument.createElement("a");
|
|
1194
|
+
anchor.setAttribute("class", "markdown-video-link markdown-video-link-youtube");
|
|
1195
|
+
anchor.setAttribute("data-embed-src", embedSrc);
|
|
1196
|
+
anchor.setAttribute("data-youtube", vid);
|
|
1197
|
+
if (startTime) {
|
|
1198
|
+
anchor.setAttribute("data-start-time", startTime);
|
|
1199
|
+
}
|
|
1200
|
+
const thumbImg = node.ownerDocument.createElement("img");
|
|
1201
|
+
thumbImg.setAttribute("class", "no-replace video-thumbnail");
|
|
1202
|
+
thumbImg.setAttribute("src", thumbnail);
|
|
1203
|
+
anchor.appendChild(thumbImg);
|
|
1204
|
+
const play = node.ownerDocument.createElement("span");
|
|
1205
|
+
play.setAttribute("class", "markdown-video-play");
|
|
1206
|
+
anchor.appendChild(play);
|
|
1207
|
+
container.appendChild(anchor);
|
|
1208
|
+
node.parentNode.replaceChild(container, node);
|
|
1209
|
+
return;
|
|
1210
|
+
}
|
|
1211
|
+
}
|
|
1212
|
+
if (nodeValue && typeof nodeValue === "string") {
|
|
1213
|
+
const postMatch = nodeValue.trim().match(POST_REGEX);
|
|
1214
|
+
if (postMatch && WHITE_LIST.includes(postMatch[1].replace(/^www\./, ""))) {
|
|
1215
|
+
const tag = postMatch[2];
|
|
1216
|
+
const author = postMatch[3].replace("@", "");
|
|
1217
|
+
const permlink = sanitizePermlink(postMatch[4]);
|
|
1218
|
+
if (!tag || !/^[a-z0-9_-]+$/i.test(tag)) return;
|
|
1219
|
+
if (!isValidUsername(author)) return;
|
|
1220
|
+
if (!isValidPermlink(permlink)) return;
|
|
1221
|
+
const attrs = forApp ? `data-tag="${tag}" data-author="${author}" data-permlink="${permlink}" class="markdown-post-link"` : `class="markdown-post-link" href="/${tag}/@${author}/${permlink}"`;
|
|
1222
|
+
const doc = DOMParser.parseFromString(
|
|
1223
|
+
`<a ${attrs}>/@${author}/${permlink}</a>`,
|
|
1224
|
+
"text/html"
|
|
1225
|
+
);
|
|
1226
|
+
const replaceNode = doc.body?.firstChild || doc.firstChild;
|
|
1227
|
+
if (replaceNode) {
|
|
1228
|
+
node.parentNode.replaceChild(replaceNode, node);
|
|
1229
|
+
}
|
|
1230
|
+
}
|
|
1231
|
+
}
|
|
1232
|
+
}
|
|
1233
|
+
|
|
1234
|
+
// src/methods/traverse.method.ts
|
|
1235
|
+
function traverse(node, forApp, depth = 0, webp = false, state = { firstImageFound: false }, parentDomain = "ecency.com") {
|
|
1236
|
+
if (!node || !node.childNodes) {
|
|
1237
|
+
return;
|
|
1238
|
+
}
|
|
1239
|
+
Array.from(Array(node.childNodes.length).keys()).forEach((i) => {
|
|
1240
|
+
const child = node.childNodes[i];
|
|
1241
|
+
if (!child) return;
|
|
1242
|
+
if (child.nodeName.toLowerCase() === "a") {
|
|
1243
|
+
a(child, forApp, webp, parentDomain);
|
|
1244
|
+
}
|
|
1245
|
+
if (child.nodeName.toLowerCase() === "iframe") {
|
|
1246
|
+
iframe(child, parentDomain);
|
|
1247
|
+
}
|
|
1248
|
+
if (child.nodeName === "#text") {
|
|
1249
|
+
text(child, forApp, webp);
|
|
1250
|
+
}
|
|
1251
|
+
if (child.nodeName.toLowerCase() === "img") {
|
|
1252
|
+
img(child, webp, state);
|
|
1253
|
+
}
|
|
1254
|
+
if (child.nodeName.toLowerCase() === "p") {
|
|
1255
|
+
p(child);
|
|
1256
|
+
}
|
|
1257
|
+
const currentChild = node.childNodes[i];
|
|
1258
|
+
if (currentChild) {
|
|
1259
|
+
traverse(currentChild, forApp, depth + 1, webp, state, parentDomain);
|
|
1260
|
+
}
|
|
1261
|
+
});
|
|
1262
|
+
}
|
|
1263
|
+
|
|
1264
|
+
// src/methods/clean-reply.method.ts
|
|
1265
|
+
function cleanReply(s) {
|
|
1266
|
+
return (s ? s.split("\n").filter((item) => item.toLowerCase().includes("posted using [partiko") === false).filter((item) => item.toLowerCase().includes("posted using [dapplr") === false).filter((item) => item.toLowerCase().includes("posted using [leofinance") === false).filter((item) => item.toLowerCase().includes("posted via [neoxian") === false).filter((item) => item.toLowerCase().includes("posted using [neoxian") === false).filter((item) => item.toLowerCase().includes("posted with [stemgeeks") === false).filter((item) => item.toLowerCase().includes("posted using [bilpcoin") === false).filter((item) => item.toLowerCase().includes("posted using [inleo") === false).filter((item) => item.toLowerCase().includes("posted using [sportstalksocial]") === false).filter((item) => item.toLowerCase().includes("<center><sub>[posted using aeneas.blog") === false).filter((item) => item.toLowerCase().includes("<center><sub>posted via [proofofbrain.io") === false).filter((item) => item.toLowerCase().includes("<center>posted on [hypnochain") === false).filter((item) => item.toLowerCase().includes("<center><sub>posted via [weedcash.network") === false).filter((item) => item.toLowerCase().includes("<center>posted on [naturalmedicine.io") === false).filter((item) => item.toLowerCase().includes("<center><sub>posted via [musicforlife.io") === false).filter((item) => item.toLowerCase().includes("if the truvvl embed is unsupported by your current frontend, click this link to view this story") === false).filter((item) => item.toLowerCase().includes("<center><em>posted from truvvl") === false).filter((item) => item.toLowerCase().includes('view this post <a href="https://travelfeed.io/') === false).filter((item) => item.toLowerCase().includes("read this post on travelfeed.io for the best experience") === false).filter((item) => item.toLowerCase().includes('posted via <a href="https://www.dporn.co/"') === false).filter((item) => item.toLowerCase().includes("\u25B6\uFE0F [watch on 3speak](https://3speak") === false).filter((item) => item.toLowerCase().includes("<sup><sub>posted via [inji.com]") === false).filter((item) => item.toLowerCase().includes("view this post on [liketu]") === false).filter((item) => item.toLowerCase().includes("[via Inbox]") === false).join("\n") : "").replace('Posted via <a href="https://d.buzz" data-link="promote-link">D.Buzz</a>', "").replace('<div class="pull-right"><a href="/@hive.engage"></a></div>', "").replace('<div><a href="https://engage.hivechain.app"></a></div>', "").replace(`<div class="text-center"><img src="https://cdn.steemitimages.com/DQmNp6YwAm2qwquALZw8PdcovDorwaBSFuxQ38TrYziGT6b/A-20.png"><a href="https://bit.ly/actifit-app"><img src="https://cdn.steemitimages.com/DQmQqfpSmcQtfrHAtzfBtVccXwUL9vKNgZJ2j93m8WNjizw/l5.png"></a><a href="https://bit.ly/actifit-ios"><img src="https://cdn.steemitimages.com/DQmbWy8KzKT1UvCvznUTaFPw6wBUcyLtBT5XL9wdbB7Hfmn/l6.png"></a></div>`, "");
|
|
1267
|
+
}
|
|
1268
|
+
var lolight = null;
|
|
1269
|
+
function getLolightInstance() {
|
|
1270
|
+
if (!lolight) {
|
|
1271
|
+
try {
|
|
1272
|
+
lolight = __require("lolight");
|
|
1273
|
+
} catch (e) {
|
|
1274
|
+
return null;
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
1277
|
+
return lolight;
|
|
1278
|
+
}
|
|
1279
|
+
function markdownToHTML(input, forApp, webp, parentDomain = "ecency.com") {
|
|
1280
|
+
input = input.replace(new RegExp("https://leofinance.io/threads/view/", "g"), "/@");
|
|
1281
|
+
input = input.replace(new RegExp("https://leofinance.io/posts/", "g"), "/@");
|
|
1282
|
+
input = input.replace(new RegExp("https://leofinance.io/threads/", "g"), "/@");
|
|
1283
|
+
input = input.replace(new RegExp("https://inleo.io/threads/view/", "g"), "/@");
|
|
1284
|
+
input = input.replace(new RegExp("https://inleo.io/posts/", "g"), "/@");
|
|
1285
|
+
input = input.replace(new RegExp("https://inleo.io/threads/", "g"), "/@");
|
|
1286
|
+
const md = new Remarkable({
|
|
1287
|
+
html: true,
|
|
1288
|
+
breaks: true,
|
|
1289
|
+
typographer: false,
|
|
1290
|
+
highlight: function(str) {
|
|
1291
|
+
const lolightInstance = getLolightInstance();
|
|
1292
|
+
if (!lolightInstance) {
|
|
1293
|
+
return str;
|
|
1294
|
+
}
|
|
1295
|
+
try {
|
|
1296
|
+
const tokens = lolightInstance.tok(str);
|
|
1297
|
+
return tokens.map(
|
|
1298
|
+
(token) => `<span class="ll-${token[0]}">${token[1]}</span>`
|
|
1299
|
+
).join("");
|
|
1300
|
+
} catch (err) {
|
|
1301
|
+
console.error(err);
|
|
1302
|
+
}
|
|
1303
|
+
return str;
|
|
1304
|
+
}
|
|
1305
|
+
}).use(linkify$1);
|
|
1306
|
+
md.core.ruler.enable([
|
|
1307
|
+
"abbr"
|
|
1308
|
+
]);
|
|
1309
|
+
md.block.ruler.enable([
|
|
1310
|
+
"footnote",
|
|
1311
|
+
"deflist"
|
|
1312
|
+
]);
|
|
1313
|
+
md.inline.ruler.enable([
|
|
1314
|
+
"footnote_inline",
|
|
1315
|
+
"ins",
|
|
1316
|
+
"mark",
|
|
1317
|
+
"sub",
|
|
1318
|
+
"sup"
|
|
1319
|
+
]);
|
|
1320
|
+
const serializer = new XMLSerializer();
|
|
1321
|
+
if (!input) {
|
|
1322
|
+
return "";
|
|
1323
|
+
}
|
|
1324
|
+
let output = "";
|
|
1325
|
+
const entities = input.match(ENTITY_REGEX);
|
|
1326
|
+
const entityPlaceholders = [];
|
|
1327
|
+
if (entities && forApp) {
|
|
1328
|
+
const uniqueEntities = [...new Set(entities)];
|
|
1329
|
+
uniqueEntities.forEach((entity, index) => {
|
|
1330
|
+
const placeholder = `\u200B${index}\u200B`;
|
|
1331
|
+
entityPlaceholders.push(entity);
|
|
1332
|
+
input = input.split(entity).join(placeholder);
|
|
1333
|
+
});
|
|
1334
|
+
}
|
|
1335
|
+
try {
|
|
1336
|
+
output = md.render(input);
|
|
1337
|
+
const doc = DOMParser.parseFromString(`<body id="root">${output}</body>`, "text/html");
|
|
1338
|
+
traverse(doc, forApp, 0, webp, { firstImageFound: false }, parentDomain);
|
|
1339
|
+
output = serializer.serializeToString(doc);
|
|
1340
|
+
} catch (error) {
|
|
1341
|
+
try {
|
|
1342
|
+
output = md.render(input);
|
|
1343
|
+
const preSanitized = sanitizeHtml(output);
|
|
1344
|
+
const htmlparser2 = __require("htmlparser2");
|
|
1345
|
+
const domSerializer = __require("dom-serializer").default;
|
|
1346
|
+
const dom = htmlparser2.parseDocument(preSanitized, {
|
|
1347
|
+
// lenient options - don't throw on malformed HTML
|
|
1348
|
+
lowerCaseTags: false,
|
|
1349
|
+
lowerCaseAttributeNames: false
|
|
1350
|
+
});
|
|
1351
|
+
const repairedHtml = domSerializer(dom.children);
|
|
1352
|
+
const doc = DOMParser.parseFromString(`<body id="root">${repairedHtml}</body>`, "text/html");
|
|
1353
|
+
traverse(doc, forApp, 0, webp, { firstImageFound: false }, parentDomain);
|
|
1354
|
+
output = serializer.serializeToString(doc);
|
|
1355
|
+
} catch (fallbackError) {
|
|
1356
|
+
const he2 = __require("he");
|
|
1357
|
+
const escapedContent = he2.encode(output || md.render(input));
|
|
1358
|
+
output = `<p dir="auto">${escapedContent}</p>`;
|
|
1359
|
+
}
|
|
1360
|
+
}
|
|
1361
|
+
if (forApp && output && entityPlaceholders.length > 0) {
|
|
1362
|
+
entityPlaceholders.forEach((entity, index) => {
|
|
1363
|
+
const placeholder = `\u200B${index}\u200B`;
|
|
1364
|
+
output = output.split(placeholder).join(entity);
|
|
1365
|
+
});
|
|
1366
|
+
}
|
|
1367
|
+
output = output.replace(/ xmlns="http:\/\/www.w3.org\/1999\/xhtml"/g, "").replace('<body id="root">', "").replace("</body>", "").trim();
|
|
1368
|
+
return sanitizeHtml(output);
|
|
1369
|
+
}
|
|
1370
|
+
var cache = new LRUCache({ max: 60 });
|
|
1371
|
+
function setCacheSize(size) {
|
|
1372
|
+
cache = new LRUCache({ max: size });
|
|
1373
|
+
}
|
|
1374
|
+
function cacheGet(key) {
|
|
1375
|
+
return cache.get(key);
|
|
1376
|
+
}
|
|
1377
|
+
function cacheSet(key, value) {
|
|
1378
|
+
cache.set(key, value);
|
|
1379
|
+
}
|
|
1380
|
+
|
|
1381
|
+
// src/markdown-2-html.ts
|
|
1382
|
+
function markdown2Html(obj, forApp = true, webp = false, parentDomain = "ecency.com") {
|
|
1383
|
+
if (typeof obj === "string") {
|
|
1384
|
+
const cleanedStr = cleanReply(obj);
|
|
1385
|
+
return markdownToHTML(cleanedStr, forApp, webp, parentDomain);
|
|
1386
|
+
}
|
|
1387
|
+
const key = `${makeEntryCacheKey(obj)}-md${webp ? "-webp" : ""}-${forApp ? "app" : "site"}-${parentDomain}`;
|
|
1388
|
+
const item = cacheGet(key);
|
|
1389
|
+
if (item) {
|
|
1390
|
+
return item;
|
|
1391
|
+
}
|
|
1392
|
+
const cleanBody = cleanReply(obj.body);
|
|
1393
|
+
const res = markdownToHTML(cleanBody, forApp, webp, parentDomain);
|
|
1394
|
+
cacheSet(key, res);
|
|
1395
|
+
return res;
|
|
1396
|
+
}
|
|
1397
|
+
|
|
1398
|
+
// src/catch-post-image.ts
|
|
1399
|
+
var gifLinkRegex = /\.(gif)$/i;
|
|
1400
|
+
function isGifLink(link) {
|
|
1401
|
+
return gifLinkRegex.test(link);
|
|
1402
|
+
}
|
|
1403
|
+
function getImage(entry, width = 0, height = 0, format = "match") {
|
|
1404
|
+
let meta;
|
|
1405
|
+
if (typeof entry.json_metadata === "object") {
|
|
1406
|
+
meta = entry.json_metadata;
|
|
1407
|
+
} else {
|
|
1408
|
+
try {
|
|
1409
|
+
meta = JSON.parse(entry.json_metadata);
|
|
1410
|
+
} catch (e) {
|
|
1411
|
+
meta = null;
|
|
1412
|
+
}
|
|
1413
|
+
}
|
|
1414
|
+
if (meta && typeof meta.image === "string" && meta.image.length > 0) {
|
|
1415
|
+
if (isGifLink(meta.image)) {
|
|
1416
|
+
return proxifyImageSrc(meta.image, 0, 0, format);
|
|
1417
|
+
}
|
|
1418
|
+
return proxifyImageSrc(meta.image, width, height, format);
|
|
1419
|
+
}
|
|
1420
|
+
if (meta && meta.image && !!meta.image.length && meta.image[0]) {
|
|
1421
|
+
if (isGifLink(meta.image[0])) {
|
|
1422
|
+
return proxifyImageSrc(meta.image[0], 0, 0, format);
|
|
1423
|
+
}
|
|
1424
|
+
return proxifyImageSrc(meta.image[0], width, height, format);
|
|
1425
|
+
}
|
|
1426
|
+
const html = markdown2Html(entry);
|
|
1427
|
+
const doc = createDoc(html);
|
|
1428
|
+
if (!doc) {
|
|
1429
|
+
return null;
|
|
1430
|
+
}
|
|
1431
|
+
const imgEls = doc.getElementsByTagName("img");
|
|
1432
|
+
if (imgEls.length >= 1) {
|
|
1433
|
+
const src = imgEls[0].getAttribute("src");
|
|
1434
|
+
if (!src) {
|
|
1435
|
+
return null;
|
|
1436
|
+
}
|
|
1437
|
+
if (isGifLink(src)) {
|
|
1438
|
+
return proxifyImageSrc(src, 0, 0, format);
|
|
1439
|
+
}
|
|
1440
|
+
return proxifyImageSrc(src, width, height, format);
|
|
1441
|
+
}
|
|
1442
|
+
return null;
|
|
1443
|
+
}
|
|
1444
|
+
function catchPostImage(obj, width = 0, height = 0, format = "match") {
|
|
1445
|
+
if (typeof obj === "string") {
|
|
1446
|
+
const entryWrapper = {
|
|
1447
|
+
body: obj,
|
|
1448
|
+
json_metadata: "{}"
|
|
1449
|
+
};
|
|
1450
|
+
return getImage(entryWrapper, width, height, format);
|
|
1451
|
+
}
|
|
1452
|
+
const key = `${makeEntryCacheKey(obj)}-${width}x${height}-${format}`;
|
|
1453
|
+
const item = cacheGet(key);
|
|
1454
|
+
if (item) {
|
|
1455
|
+
return item;
|
|
1456
|
+
}
|
|
1457
|
+
const res = getImage(obj, width, height, format);
|
|
1458
|
+
cacheSet(key, res);
|
|
1459
|
+
return res;
|
|
1460
|
+
}
|
|
1461
|
+
var joint = (arr, limit = 200) => {
|
|
1462
|
+
let result = "";
|
|
1463
|
+
if (arr) {
|
|
1464
|
+
for (let i = 0; i < arr.length; i++) {
|
|
1465
|
+
if (result) {
|
|
1466
|
+
result += " ";
|
|
1467
|
+
}
|
|
1468
|
+
if (result.length > limit) {
|
|
1469
|
+
break;
|
|
1470
|
+
} else {
|
|
1471
|
+
if ((result + arr[i]).length < limit + 10) {
|
|
1472
|
+
result += arr[i];
|
|
1473
|
+
} else {
|
|
1474
|
+
break;
|
|
1475
|
+
}
|
|
1476
|
+
}
|
|
1477
|
+
}
|
|
1478
|
+
}
|
|
1479
|
+
return result.trim();
|
|
1480
|
+
};
|
|
1481
|
+
function postBodySummary(entryBody, length = 200, platform = "web") {
|
|
1482
|
+
if (!entryBody) {
|
|
1483
|
+
return "";
|
|
1484
|
+
}
|
|
1485
|
+
entryBody = cleanReply(entryBody);
|
|
1486
|
+
const mdd = new Remarkable({
|
|
1487
|
+
html: true,
|
|
1488
|
+
breaks: true,
|
|
1489
|
+
typographer: false
|
|
1490
|
+
}).use(linkify$1);
|
|
1491
|
+
mdd.core.ruler.enable([
|
|
1492
|
+
"abbr"
|
|
1493
|
+
]);
|
|
1494
|
+
mdd.block.ruler.enable([
|
|
1495
|
+
"footnote",
|
|
1496
|
+
"deflist"
|
|
1497
|
+
]);
|
|
1498
|
+
mdd.inline.ruler.enable([
|
|
1499
|
+
"footnote_inline",
|
|
1500
|
+
"ins",
|
|
1501
|
+
"mark",
|
|
1502
|
+
"sub",
|
|
1503
|
+
"sup"
|
|
1504
|
+
]);
|
|
1505
|
+
const entities = entryBody.match(ENTITY_REGEX);
|
|
1506
|
+
const entityPlaceholders = [];
|
|
1507
|
+
if (entities && platform !== "web") {
|
|
1508
|
+
const uniqueEntities = [...new Set(entities)];
|
|
1509
|
+
uniqueEntities.forEach((entity, index) => {
|
|
1510
|
+
const placeholder = `\u200B${index}\u200B`;
|
|
1511
|
+
entityPlaceholders.push(entity);
|
|
1512
|
+
entryBody = entryBody.split(entity).join(placeholder);
|
|
1513
|
+
});
|
|
1514
|
+
}
|
|
1515
|
+
let text2 = "";
|
|
1516
|
+
try {
|
|
1517
|
+
text2 = mdd.render(entryBody);
|
|
1518
|
+
} catch (err) {
|
|
1519
|
+
console.error("[postBodySummary] Failed to render markdown:", {
|
|
1520
|
+
error: err instanceof Error ? err.message : String(err),
|
|
1521
|
+
entryBodyLength: entryBody?.length || 0,
|
|
1522
|
+
platform
|
|
1523
|
+
});
|
|
1524
|
+
text2 = "";
|
|
1525
|
+
}
|
|
1526
|
+
if (platform !== "web" && entityPlaceholders.length > 0) {
|
|
1527
|
+
entityPlaceholders.forEach((entity, index) => {
|
|
1528
|
+
const placeholder = `\u200B${index}\u200B`;
|
|
1529
|
+
text2 = text2.split(placeholder).join(entity);
|
|
1530
|
+
});
|
|
1531
|
+
}
|
|
1532
|
+
text2 = text2.replace(/(<([^>]+)>)/gi, "").replace(/\r?\n|\r/g, " ").replace(/(?:https?|ftp):\/\/[\n\S]+/g, "").trim().replace(/ +(?= )/g, "");
|
|
1533
|
+
if (length > 0) {
|
|
1534
|
+
text2 = joint(text2.split(" "), length);
|
|
1535
|
+
}
|
|
1536
|
+
if (text2) {
|
|
1537
|
+
text2 = he.decode(text2);
|
|
1538
|
+
}
|
|
1539
|
+
return text2;
|
|
1540
|
+
}
|
|
1541
|
+
function getPostBodySummary(obj, length, platform) {
|
|
1542
|
+
const normalizedLength = length ?? 200;
|
|
1543
|
+
const normalizedPlatform = platform || "web";
|
|
1544
|
+
if (typeof obj === "string") {
|
|
1545
|
+
return postBodySummary(obj, normalizedLength, normalizedPlatform);
|
|
1546
|
+
}
|
|
1547
|
+
const key = `${makeEntryCacheKey(obj)}-sum-${normalizedLength}-${normalizedPlatform}`;
|
|
1548
|
+
const item = cacheGet(key);
|
|
1549
|
+
if (item) {
|
|
1550
|
+
return item;
|
|
1551
|
+
}
|
|
1552
|
+
const res = postBodySummary(obj.body, normalizedLength, normalizedPlatform);
|
|
1553
|
+
cacheSet(key, res);
|
|
1554
|
+
return res;
|
|
1555
|
+
}
|
|
1556
|
+
|
|
1557
|
+
export { SECTION_LIST, catchPostImage, isValidPermlink, getPostBodySummary as postBodySummary, proxifyImageSrc, markdown2Html as renderPostBody, setCacheSize, setProxyBase };
|
|
1558
|
+
//# sourceMappingURL=index.mjs.map
|
|
1559
|
+
//# sourceMappingURL=index.mjs.map
|