@ecency/render-helper 2.5.25 → 2.5.26

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/consts/white-list.const.ts","../../src/consts/section-list.const.ts","../../src/consts/regexes.const.ts","../../src/consts/allowed-attributes.const.ts","../../src/consts/embed-hosts.const.ts","../../src/consts/dom-parser.const.ts","../../src/helper.ts","../../src/methods/get-inner-html.method.ts","../../src/methods/remove-child-nodes.method.ts","../../src/proxify-image-src.ts","../../src/methods/sanitize-html.method.ts","../../src/methods/img.method.ts","../../src/methods/a.method.ts","../../src/methods/iframe.method.ts","../../src/methods/p.method.ts","../../src/methods/linkify.method.ts","../../src/methods/text.method.ts","../../src/methods/traverse.method.ts","../../src/methods/clean-reply.method.ts","../../src/methods/markdown-to-html.method.ts","../../src/methods/simple-markdown-to-html.method.ts","../../src/cache.ts","../../src/markdown-2-html.ts","../../src/catch-post-image.ts","../../src/post-body-summary.ts"],"names":["XMLDOMParser","he","p","XMLDOMSerializer","text","img","iframe","imgEls","a","match","linkify","Remarkable","LRUCache","t0","res"],"mappings":"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","file":"index.mjs","sourcesContent":["export const WHITE_LIST = [\n 'ecency.com',\n 'hive.blog',\n 'peakd.com',\n 'snapie.io',\n 'hivesuite.app',\n 'travelfeed.io',\n 'dapplr.in',\n 'leofinance.io',\n 'inleo.io',\n 'proofofbrain.io',\n 'stemgeeks.net',\n 'hiveblockexplorer.com',\n 'proofofbrain.blog',\n 'weedcash.network',\n 'dapplr.in',\n 'liketu.com',\n 'bilpcoin.com',\n 'inji.com'\n]\nexport const OLD_LIST = [\n 'busy.org',\n 'steemit.com',\n 'esteem.app',\n 'steempeak.com',\n 'partiko.app',\n 'chainbb.com',\n 'utopian.io',\n 'steemkr.com',\n 'strimi.pl',\n 'steemhunt.com',\n 'ulogs.org',\n 'hede.io',\n 'naturalmedicine.io'\n]\n","export const SECTION_LIST = [\n 'wallet',\n 'feed',\n 'followers',\n 'following',\n 'points',\n 'communities',\n 'posts',\n 'blog',\n 'comments',\n 'replies',\n 'settings',\n 'engine',\n 'permissions',\n 'referrals',\n 'payout',\n 'activities',\n 'spk',\n 'trail'\n]\n","// link regex\nexport const URL_REGEX = /(https?:\\/\\/[^\\s]+)/g\nexport const IMG_REGEX = /(https?:\\/\\/.*\\.(?:tiff?|jpe?g|gif|png|svg|ico|heic|webp|arw))(.*)/gim\nexport const ECENCY_IMG_REGEX = /https?:\\/\\/images\\.ecency\\.com\\/(?:(?:p|DQm[a-zA-Z0-9]+)\\/)?[^\\s\"'<>]+/gi\nexport const IPFS_REGEX = /^https?:\\/\\/[^/]+\\/(ip[fn]s)\\/([^/?#]+)/gim\n// Matches Hive post URLs: scheme://domain/tag/@author/permlink.\n// Both path segments are pinned to `[^/]+` (no `/`), and both ends are\n// anchored. The previous form `^https?://(.*)/(.*)/(@…)/(.*)` had three\n// `.*` quantifiers that could exchange characters, triggering\n// super-linear backtracking on adversarial hrefs. Matching is now O(n)\n// and the captured `domain`/`tag` shape is unchanged — in particular,\n// multi-segment-middle URLs like `host/foo/bar/@user/perm` still don't\n// match, preserving the old whitelist-rejection behaviour (the previous\n// greedy form put `host/foo` in capture 1, which then failed the\n// WHITE_LIST check in a.method.ts; this stricter form fails the regex\n// outright, with the same downstream outcome).\nexport const POST_REGEX = /^https?:\\/\\/([^/]+)\\/([^/]+)\\/(@[\\w.\\d-]+)\\/(.+)$/i\nexport const CCC_REGEX = /^https?:\\/\\/(.*)\\/ccc\\/([\\w.\\d-]+)\\/(.*)/i\nexport const MENTION_REGEX = /^https?:\\/\\/(.*)\\/(@[\\w.\\d-]+)$/i\nexport const TOPIC_REGEX = /^https?:\\/\\/(.*)\\/(trending|hot|created|promoted|muted|payout)\\/(.*)$/i\nexport const INTERNAL_MENTION_REGEX = /^\\/@[\\w.\\d-]+$/i\nexport const INTERNAL_TOPIC_REGEX = /^\\/(trending|hot|created|promoted|muted|payout)\\/(.*)$/i\n// Matches both internal `/tag/@author/permlink` and external\n// `https://host/tag/@author/permlink` hrefs. Group 1 must be allowed\n// to contain `/` so we keep `.+?` (lazy, anchored start). The previous\n// form `(.*)/(@…)/(.*)` was unanchored with two `.*` quantifiers, so\n// `regexp/no-super-linear-move` flagged it as quadratic on hrefs\n// without a `/@user/` substring (engine retried at every starting\n// position). The lazy + anchored variant keeps matching attempts O(n).\nexport const INTERNAL_POST_TAG_REGEX = /^(.+?)\\/(@[\\w.\\d-]+)\\/(.*)$/i\nexport const INTERNAL_POST_REGEX = /^\\/(@[\\w.\\d-]+)\\/(.*)$/i\nexport const CUSTOM_COMMUNITY_REGEX = /^https?:\\/\\/(.*)\\/c\\/(hive-\\d+)(.*)/i\nexport const YOUTUBE_REGEX = /(?:youtube\\.com\\/(?:[^\\/]+\\/.+\\/|(?:v|e(?:mbed)?)\\/|shorts\\/|.*[?&]v=)|youtu\\.be\\/)([^\"&?\\/\\s]{11})/i\nexport const YOUTUBE_EMBED_REGEX = /^(https?:)?\\/\\/www\\.youtube\\.com\\/(embed|shorts)\\/.*/i\nexport const VIMEO_REGEX = /(https?:\\/\\/)?(www\\.)?(?:vimeo)\\.com.*(?:videos|video|channels|)\\/([\\d]+)/i\nexport const VIMEO_EMBED_REGEX = /https:\\/\\/player\\.vimeo\\.com\\/video\\/([0-9]+)(?:$|[?#])/\nexport const BITCHUTE_REGEX = /^(?:https?:\\/\\/)?(?:www\\.)?bitchute\\.com\\/(?:video|embed)\\/([a-z0-9]+)/i\nexport const D_TUBE_REGEX = /(https?:\\/\\/d\\.tube\\/#!\\/v\\/)(\\w+)\\/(\\w+)/g\nexport const D_TUBE_REGEX2 = /(https?:\\/\\/d\\.tube\\/v\\/)(\\w+)\\/(\\w+)/g\nexport const D_TUBE_EMBED_REGEX = /^https:\\/\\/emb\\.d\\.tube\\/#!\\/[^/?#]+\\/[^/?#]+(?:$|[?#])/i\nexport const TWITCH_REGEX = /https?:\\/\\/(?:www\\.)?twitch\\.tv\\/(?:(videos)\\/)?([a-zA-Z0-9][\\w]{3,24})/i\nexport const DAPPLR_REGEX = /^(https?:)?\\/\\/[a-z]*\\.dapplr\\.in\\/file\\/dapplr-videos\\/.*/i\nexport const TRUVVL_REGEX = /^https?:\\/\\/embed\\.truvvl\\.com\\/(@[\\w.\\d-]+)\\/(.*)/i\nexport const LBRY_REGEX = /^(https?:)?\\/\\/lbry\\.tv\\/\\$\\/embed\\/[^?#]+(?:$|[?#])/i\nexport const ODYSEE_REGEX = /^(https?:)?\\/\\/odysee\\.com\\/(?:\\$|%24)\\/embed\\/[^?#]+(?:$|[?#])/i\n// Odysee \"watch\" URLs — the canonical form a user copies from the address bar,\n// e.g. https://odysee.com/@channel:2/video-title:e (or https://odysee.com/video-title:e\n// for a claim posted outside a channel). Odysee's embed route mirrors the watch\n// path (/$/embed/<path>), so the mapping is deterministic and needs no network\n// lookup; capture group 1 is that path.\n//\n// Two alternatives rather than one optional-channel form, because the collapsed\n// version also matches a bare channel page (/@channel:2), which is not a video.\n// The first alternative requires both segments; the second forbids a leading `@`.\n// Special routes (/$/embed, /$/download, and their %24 spellings) are excluded\n// for free: their first segment carries no `:`.\n// Each segment class excludes the URL structural characters plus quote/angle/\n// backslash, so a captured path can never break out of the attribute it is\n// written into, and excludes `:` so the `+` cannot exchange characters with the\n// following separator (keeps matching linear).\nexport const ODYSEE_WATCH_REGEX =\n /^(?:https?:)?\\/\\/odysee\\.com\\/(@[^/?#\\s:\"'<>\\\\]+:[^/?#\\s:\"'<>\\\\]+\\/[^/?#\\s:\"'<>\\\\]+:[^/?#\\s:\"'<>\\\\]+|[^@/?#\\s:\"'<>\\\\][^/?#\\s:\"'<>\\\\]*:[^/?#\\s:\"'<>\\\\]+)(?:$|[?#])/i\nexport const SKATEHIVE_IPFS_REGEX = /^https?:\\/\\/ipfs\\.skatehive\\.app\\/ipfs\\/([^/?#]+)/i\nexport const SKATEHYPE_EMBED_REGEX = /^(https?:)?\\/\\/(www\\.)?skatehype\\.com\\/ifplay\\.php\\?v=\\d+(?:$|[&#])/i\nexport const ARCH_REGEX = /^(https?:)?\\/\\/archive\\.org\\/embed\\/[^/?#]+(?:$|[?#])/i\nexport const SPEAK_REGEX = /(?:https?:\\/\\/(?:(?:play\\.)?3speak\\.([a-z]+)\\/watch\\?v=)|(?:(?:play\\.)?3speak\\.([a-z]+)\\/embed\\?v=))([A-Za-z0-9_\\-\\.\\/]+)(&.*)?/i\nexport const SPEAK_EMBED_REGEX = /^(https?:)?\\/\\/(?:play\\.)?3speak\\.([a-z]+)\\/(?:embed|watch)\\?.+$/i\nexport const SPEAK_AUDIO_REGEX = /https?:\\/\\/audio\\.3speak\\.tv\\/play\\?[^\\s]+/i\nexport const SPEAK_AUDIO_EMBED_REGEX = /^https?:\\/\\/audio\\.3speak\\.tv\\/play\\?.+$/i\n// Liketu Speak voice posts link the original audio on cdn.liketu.com (.webm etc).\n// Note: matches .webm/.mp3/.m4a/.ogg/.wav but NOT .webp image thumbnails.\nexport const LIKETU_AUDIO_REGEX = /^https?:\\/\\/cdn\\.liketu\\.com\\/.+\\.(?:webm|mp3|m4a|ogg|wav)(?:\\?.*)?$/i\nexport const TWITTER_REGEX = /(?:https?:\\/\\/(?:(?:twitter\\.com\\/(.*?)\\/status\\/(.*))))/gi\nexport const SPOTIFY_REGEX = /^https:\\/\\/open\\.spotify\\.com\\/playlist\\/(.*)?$/gi\nexport const RUMBLE_REGEX = /^https:\\/\\/rumble\\.com\\/embed\\/([a-zA-Z0-9-]+)\\/\\?pub=\\w+/\nexport const BRIGHTEON_REGEX = /^https?:\\/\\/(www\\.)?brighteon\\.com\\/(?:embed\\/)?(.*[0-9].*)/i\nexport const VIMM_EMBED_REGEX = /^https:\\/\\/www\\.vimm\\.tv\\/[^?#]+(?:$|[?#])/i\nexport const SPOTIFY_EMBED_REGEX = /^https:\\/\\/open\\.spotify\\.com\\/(embed|embed-podcast)\\/(playlist|show|episode|track|album)\\/([^/?#]+)(?:$|[?#])/i\nexport const SOUNDCLOUD_EMBED_REGEX = /^https:\\/\\/w\\.soundcloud\\.com\\/player\\/\\?[^#]+$/i\nexport const TWITCH_EMBED_REGEX = /^(https?:)?\\/\\/player\\.twitch\\.tv\\/(?:\\?[^/]+)?$/i\nexport const BRAND_NEW_TUBE_REGEX = /^https:\\/\\/brandnewtube\\.com\\/embed\\/[a-z0-9]+$/i\nexport const LOOM_REGEX = /^(https?:)?\\/\\/www\\.loom\\.com\\/share\\/([^/?#]+)(?:$|[?#])/i\nexport const LOOM_EMBED_REGEX = /^(https?:)?\\/\\/www\\.loom\\.com\\/embed\\/([^/?#]+)(?:$|[?#])/i\nexport const AUREAL_EMBED_REGEX = /^(https?:)?\\/\\/(www\\.)?(?:aureal-embed)\\.web\\.app\\/([0-9]+)(?:$|[?#])/i\nexport const ENTITY_REGEX = /&([a-z0-9]+|#[0-9]{1,6}|#x[0-9a-fA-F]{1,6});/ig\nexport const SECTION_REGEX = /\\B(\\#[\\da-zA-Z-_]+\\b)(?!;)/i\nexport const ID_WHITELIST = /^[A-Za-z][-A-Za-z0-9_]*$/\n\n","import { XSSWhiteList } from '../types'\n\nexport const ALLOWED_ATTRIBUTES: XSSWhiteList = {\n 'a': [\n 'href',\n 'target',\n 'rel',\n 'data-permlink',\n 'data-tag',\n 'data-author',\n 'data-href',\n 'data-community',\n 'data-filter',\n 'data-embed-src',\n 'data-youtube',\n 'data-start-time',\n 'data-video-href',\n 'data-proposal',\n 'data-is-inline',\n 'class',\n 'title',\n 'data-id',\n 'id'\n ],\n 'img': [\n 'src',\n 'srcset',\n 'sizes',\n 'alt',\n 'class',\n 'loading',\n 'fetchpriority',\n 'decoding',\n 'itemprop'\n ],\n // Responsive image content-negotiation wrapper emitted for web/self-hosted\n // (forApp === false). Without these entries `xss` silently collapses the\n // <picture>/<source> to a bare <img>. `source` attrs are further constrained\n // in sanitize-html (srcset must be a proxy /p/ URL; type must be avif/webp;\n // a type-less <source> is dropped post-pass).\n 'picture': [],\n 'source': ['type', 'srcset', 'sizes'],\n 'span': ['class', 'id', 'data-align'],\n 'iframe': ['src', 'class', 'frameborder', 'allowfullscreen', 'webkitallowfullscreen', 'mozallowfullscreen', 'sandbox'],\n 'video': ['src', 'controls', 'poster'],\n 'audio': ['src', 'controls', 'preload'],\n 'div': ['class', 'id', 'data-align'],\n 'strong': [],\n 'b': [],\n 'i': [],\n 'strike': [],\n 'em': [],\n 'code': [],\n 'pre': [],\n 'blockquote': ['class'],\n 'sup': [],\n 'sub': [],\n 'h1': ['dir', 'id', 'data-align'],\n 'h2': ['dir', 'id', 'data-align'],\n 'h3': ['dir', 'id', 'data-align'],\n 'h4': ['dir', 'id', 'data-align'],\n 'h5': ['dir', 'id', 'data-align'],\n 'h6': ['dir', 'id', 'data-align'],\n 'p': ['dir', 'id', 'data-align'],\n 'center': [],\n 'ul': [],\n 'ol': [],\n 'li': [],\n 'table': [],\n 'thead': [],\n 'tbody': [],\n 'tr': [],\n 'td': [],\n 'th': [],\n 'hr': [],\n 'br': [],\n 'del': [],\n 'ins': []\n}\n","// Authoritative allowlist of hosts the renderer is allowed to embed in an\n// <iframe>. This is the SAME trust boundary that iframe.method.ts and\n// a.method.ts already enforce via per-provider regexes — it is consolidated\n// here so the sanitizer (central, authoritative) and the client video\n// extensions (belt-and-suspenders) validate against ONE list instead of\n// diverging copies.\n//\n// Every host listed here is one that a.method.ts / iframe.method.ts can emit\n// as an https embed target. Subdomain-suffix tricks (play.3speak.tv.evil.com)\n// fail because we compare the parsed hostname for EXACT equality, and\n// protocol-relative / http / javascript: / data: values fail the https check.\nexport const ALLOWED_EMBED_HOSTS: ReadonlySet<string> = new Set([\n // YouTube\n 'www.youtube.com',\n 'youtube.com',\n 'www.youtube-nocookie.com',\n 'youtube-nocookie.com',\n // Vimeo\n 'player.vimeo.com',\n // Twitch\n 'player.twitch.tv',\n // DTube\n 'emb.d.tube',\n // 3Speak (video + audio)\n 'play.3speak.tv',\n '3speak.tv',\n 'audio.3speak.tv',\n // Loom\n 'www.loom.com',\n // Spotify\n 'open.spotify.com',\n // SoundCloud\n 'w.soundcloud.com',\n // BitChute\n 'www.bitchute.com',\n 'bitchute.com',\n // Rumble\n 'www.rumble.com',\n 'rumble.com',\n // Brighteon\n 'www.brighteon.com',\n 'brighteon.com',\n // VIMM\n 'www.vimm.tv',\n // BrandNewTube\n 'brandnewtube.com',\n // LBRY / Odysee\n 'lbry.tv',\n 'odysee.com',\n // Skatehive / Skatehype\n 'ipfs.skatehive.app',\n 'www.skatehype.com',\n 'skatehype.com',\n // archive.org\n 'archive.org',\n // Truvvl\n 'embed.truvvl.com',\n // Aureal\n 'aureal-embed.web.app',\n 'www.aureal-embed.web.app',\n // Dapplr (player.*.dapplr.in / *.dapplr.in) — host suffix, handled below\n])\n\n// Dapplr embeds come from arbitrary `<region>.dapplr.in` subdomains (see\n// DAPPLR_REGEX), so they need a suffix check rather than an exact-host entry.\nconst ALLOWED_EMBED_HOST_SUFFIXES: readonly string[] = ['.dapplr.in']\n\n// Per-host embed PATH requirement. Host allowlisting alone still lets a hostile\n// post point an allowed-host iframe at a non-embed path on that host (e.g. an\n// open-redirect endpoint, or a user-content page that — in an un-sandboxed\n// frame — could hijack top-navigation). For the providers whose embed URL shape\n// the renderer controls (a.method.ts), require the pathname to match that shape\n// too. Each pattern is permissive enough to pass every value the renderer\n// emits. Hosts absent from this map fall back to host-only (their embed paths\n// vary and they are not consumed by the un-sandboxed client video extensions).\nconst EMBED_HOST_PATH_PATTERNS: Record<string, RegExp> = {\n 'www.youtube.com': /^\\/embed\\//,\n 'youtube.com': /^\\/embed\\//,\n 'www.youtube-nocookie.com': /^\\/embed\\//,\n 'youtube-nocookie.com': /^\\/embed\\//,\n 'player.vimeo.com': /^\\/video\\//,\n 'player.twitch.tv': /^\\/$/, // channel/video carried in the query string\n 'emb.d.tube': /^\\/$/, // dtube carries the ref in the #! fragment\n 'play.3speak.tv': /^\\/(watch|embed)/,\n 'open.spotify.com': /^\\/embed\\//,\n 'www.loom.com': /^\\/embed\\//,\n 'www.bitchute.com': /^\\/embed\\//,\n 'bitchute.com': /^\\/embed\\//,\n 'www.rumble.com': /^\\/embed\\//,\n 'rumble.com': /^\\/embed\\//,\n 'www.brighteon.com': /^\\/embed\\//,\n 'brighteon.com': /^\\/embed\\//,\n // Odysee's embed route is /$/embed/<claim path>. Both the literal `$` and its\n // percent-encoded spelling occur in the wild: the renderer emits the literal\n // form, while Odysee's own share dialog hands out fully-encoded URLs, and\n // `URL.pathname` does not decode either. ODYSEE_REGEX accepts both for the\n // same reason.\n 'odysee.com': /^\\/(?:\\$|%24)\\/embed\\//\n}\n\n/**\n * True iff `value` is an absolute https:// URL whose host is one the renderer\n * is permitted to embed AND (for hosts with a known embed-path shape) whose\n * path matches that shape. Used to validate data-embed-src / data-video-href in\n * the sanitizer and the iframe `src` the client video extensions assign.\n *\n * Defensive: never throws (a malformed URL returns false), rejects every\n * non-https scheme (javascript:, data:, http:, protocol-relative //host),\n * compares the parsed hostname so an attacker can't smuggle an allowed host as\n * a path/query/userinfo/subdomain-suffix segment, and constrains the path so an\n * allowed host can't be aimed at a non-embed route.\n */\nexport function isAllowedEmbedSrc(value?: string | null): boolean {\n if (!value) return false\n let url: URL\n try {\n url = new URL(value.trim())\n } catch {\n return false\n }\n if (url.protocol !== 'https:') return false\n const host = url.hostname.toLowerCase()\n const hostAllowed =\n ALLOWED_EMBED_HOSTS.has(host) ||\n ALLOWED_EMBED_HOST_SUFFIXES.some(suffix => host.endsWith(suffix))\n if (!hostAllowed) return false\n const pathPattern = EMBED_HOST_PATH_PATTERNS[host]\n if (pathPattern && !pathPattern.test(url.pathname)) return false\n return true\n}\n","import { DOMParser as XMLDOMParser, XMLSerializer as XMLDOMSerializer } from '@xmldom/xmldom'\n\n// Lenient error handler for xmldom - suppresses ALL parse errors without throwing.\n// This is critical: xmldom 0.9+ throws on fatalError by default, which causes the\n// render pipeline to fall through to the HTML-escaping fallback, showing raw tags.\nfunction createParser() {\n return new XMLDOMParser({\n onError(level: string, msg: string) {\n void level\n void msg\n },\n })\n}\n\nexport const DOMParser = createParser()\n\nexport { XMLDOMSerializer as XMLSerializer }\n","import { DOMParser } from './consts'\nimport type { Document } from '@xmldom/xmldom'\nimport he from 'he'\n\n/**\n * Decode an image URL the way the renderer does before proxifying, so a URL's\n * proxy hash (base58 of the exact string) is identical whether it came from the\n * rendered <img> (img.method) or from raw discovery (getEntryImageRawUrl) — i.e.\n * the LCP preload byte-matches the in-body <picture> avif <source>. Decodes HTML\n * entities (&amp;, &#NN;, &#xNN;) then percent-encoding (%XX / non-ASCII).\n * Percent-decoding is guarded so a malformed `%` in user content can't throw\n * (callers run at SSR time).\n */\nexport function decodeImageSrc(src: string): string {\n const entityDecoded = he.decode(src)\n try {\n return decodeURIComponent(entityDecoded).trim()\n } catch {\n return entityDecoded.trim()\n }\n}\n\n/**\n * Removes duplicate attributes from HTML tags.\n * @xmldom/xmldom 0.9+ throws fatalError on duplicate attributes (e.g., <iframe allowfullscreen allowfullscreen>).\n *\n * Single-pass tokenizer. The previous regex-based implementation had\n * catastrophic backtracking on malformed inputs such as\n * <div style=background-color:yellow;\">\n * (unquoted attribute value followed by a stray quote, no closing `>` for the\n * tag in the immediate vicinity). The nested alternation\n * (?:[^>\"']+|\"[^\"]*\"|'[^']*')*?\n * combined with a greedy `+` inside the non-greedy `*?` produced O(n²+)\n * backtracking that pinned a 6 KB body for >30 seconds, tripping the watchdog\n * and killing the container.\n */\nfunction isSpaceChar(c: number): boolean {\n return c === 0x20 || c === 0x09 || c === 0x0a || c === 0x0d || c === 0x0c\n}\n\nfunction isAsciiLetter(c: number): boolean {\n return (c >= 0x41 && c <= 0x5a) || (c >= 0x61 && c <= 0x7a)\n}\n\nfunction isTagNameChar(c: number): boolean {\n return isAsciiLetter(c) || (c >= 0x30 && c <= 0x39)\n}\n\nfunction isAttrNameChar(c: number): boolean {\n // a-zA-Z, 0-9, '-', '_', ':', '.'\n return (\n isAsciiLetter(c) ||\n (c >= 0x30 && c <= 0x39) ||\n c === 0x2d ||\n c === 0x5f ||\n c === 0x3a ||\n c === 0x2e\n )\n}\n\nexport function removeDuplicateAttributes(html: string): string {\n const n = html.length\n let out = ''\n let i = 0\n\n while (i < n) {\n const lt = html.indexOf('<', i)\n if (lt < 0) {\n out += html.slice(i)\n break\n }\n out += html.slice(i, lt)\n\n // Only opening tags that start with an ASCII letter and have at least\n // one whitespace before the attributes are normalised — matches the\n // scope of the prior regex (closing tags, comments, doctypes, and bare\n // `<` characters are left untouched).\n if (lt + 1 >= n || !isAsciiLetter(html.charCodeAt(lt + 1))) {\n out += '<'\n i = lt + 1\n continue\n }\n\n let p = lt + 1\n while (p < n && isTagNameChar(html.charCodeAt(p))) p++\n const tagName = html.slice(lt + 1, p)\n\n if (p >= n || !isSpaceChar(html.charCodeAt(p))) {\n out += '<'\n i = lt + 1\n continue\n }\n\n const attrs: string[] = []\n const seen = new Set<string>()\n let q = p\n\n while (q < n) {\n while (q < n && isSpaceChar(html.charCodeAt(q))) q++\n if (q >= n) break\n\n const ch = html.charCodeAt(q)\n if (ch === 0x3e) break // '>'\n if (ch === 0x2f && q + 1 < n && html.charCodeAt(q + 1) === 0x3e) break // '/>'\n\n const nameStart = q\n while (q < n && isAttrNameChar(html.charCodeAt(q))) q++\n if (q === nameStart) {\n // Stray character that can't start an attribute name. Skip it so\n // we make progress; the original tag bytes are preserved verbatim\n // below if we ultimately can't close the tag.\n q++\n continue\n }\n const attrName = html.slice(nameStart, q)\n\n let r = q\n while (r < n && isSpaceChar(html.charCodeAt(r))) r++\n\n let valueEnd = q\n if (r < n && html.charCodeAt(r) === 0x3d /* '=' */) {\n r++\n while (r < n && isSpaceChar(html.charCodeAt(r))) r++\n if (r < n) {\n const v = html.charCodeAt(r)\n if (v === 0x22 || v === 0x27) {\n // Quoted value\n const quote = html[r]\n const end = html.indexOf(quote, r + 1)\n if (end < 0) {\n // Unterminated quote — bail to the next `>` to avoid eating\n // the rest of the document.\n const gt = html.indexOf('>', r + 1)\n valueEnd = gt < 0 ? n : gt\n } else {\n valueEnd = end + 1\n }\n } else {\n // Unquoted value: read until whitespace or `>`\n let s = r\n while (s < n) {\n const k = html.charCodeAt(s)\n if (isSpaceChar(k) || k === 0x3e) break\n s++\n }\n valueEnd = s\n }\n } else {\n valueEnd = r\n }\n }\n\n const fullAttr = html.slice(nameStart, valueEnd)\n q = valueEnd\n\n const key = attrName.toLowerCase()\n if (!seen.has(key)) {\n seen.add(key)\n attrs.push(fullAttr)\n }\n }\n\n let selfClose = false\n if (q < n && html.charCodeAt(q) === 0x2f /* '/' */) {\n selfClose = true\n q++\n }\n if (q >= n || html.charCodeAt(q) !== 0x3e /* '>' */) {\n // Unterminated tag — leave the original input alone past the `<` and\n // continue scanning. This mirrors the prior regex's behaviour of not\n // matching such fragments.\n out += '<'\n i = lt + 1\n continue\n }\n q++\n\n const attrsJoined = attrs.length > 0 ? ' ' + attrs.join(' ') : ''\n out += '<' + tagName + attrsJoined + (selfClose ? ' /' : '') + '>'\n i = q\n }\n\n return out\n}\n\nexport function createDoc(html: string): Document | null {\n if (html.trim() === '') {\n return null\n }\n\n // Preprocess to remove duplicate attributes which cause @xmldom/xmldom 0.9+ to throw fatalError\n const cleanedHtml = removeDuplicateAttributes(html)\n\n // Wrap in body tag to handle multiple root elements\n // This is needed because markdownToHTML can generate multiple top-level elements\n // (e.g., <center>...</center><hr />) which DOMParser doesn't accept without a wrapper\n // Using <body> instead of <div> prevents conflicts with <div> elements in the content\n //\n // @xmldom/xmldom 0.9+ always throws a ParseError from its internal fatalError() path\n // (see dom-parser.js:490) for severely malformed HTML — e.g., mismatched tags like\n // <body>...<p>...</body> — regardless of the onError handler returning undefined.\n // The onError handler only gets to observe; the throw still happens.\n //\n // Wrap in try/catch so that pathologically-malformed post bodies degrade gracefully\n // (no image preload hint) instead of crashing the SSR render of /entry/[...]. Both\n // callers in catch-post-image.ts already handle a null return.\n try {\n return DOMParser.parseFromString(`<body>${cleanedHtml}</body>`, 'text/html')\n } catch {\n return null\n }\n}\n\nexport function makeEntryCacheKey(entry: any): string {\n return `${entry.author}-${entry.permlink}-${entry.last_update}-${entry.updated}`\n}\n\n/**\n * Linear-time HTML-tag stripper. Replaces the regex\n * /(<([^>]+)>)/gi\n * which `regexp/no-super-linear-move` flags as quadratic on inputs with\n * many `<`s that never close. Mirrors the regex's behaviour: matches\n * `<tag...>` with at least one character between the angle brackets and\n * removes it, but leaves bare `<` (with no `>` to close it) and `<>`\n * (empty content) in place.\n */\nexport function stripHtmlTags(s: string): string {\n const n = s.length\n let out = ''\n let i = 0\n while (i < n) {\n const lt = s.indexOf('<', i)\n if (lt < 0) {\n out += s.slice(i)\n break\n }\n out += s.slice(i, lt)\n const gt = s.indexOf('>', lt + 1)\n if (gt < 0) {\n // Unclosed `<` — original regex required a `>` to match, so keep\n // the remaining text intact.\n out += s.slice(lt)\n break\n }\n if (gt === lt + 1) {\n // `<>` empty — original `[^>]+` required at least one inner char,\n // so preserve the literal `<>`.\n out += s.slice(lt, gt + 1)\n i = gt + 1\n continue\n }\n i = gt + 1\n }\n return out\n}\n\n/**\n * Linear-time trailing-`/` strip. Replaces the regex\n * /\\/+$/\n * which `regexp/no-super-linear-move` flags as quadratic on inputs\n * that end in a long run of slashes followed by anything else (the\n * engine retries at every starting position).\n */\nexport function trimTrailingSlash(s: string): string {\n let end = s.length\n while (end > 0 && s.charCodeAt(end - 1) === 0x2f /* '/' */) end--\n return s.slice(0, end)\n}\n\n/**\n * Linear-time query-string strip. Replaces the regex\n * /\\?.+$/\n * with a simple `indexOf` + `slice`. Matches the regex's behaviour:\n * strips only if `?` exists *and* at least one character follows it\n * (`?` at end-of-string leaves the input unchanged).\n */\nexport function stripQueryString(s: string): string {\n const q = s.indexOf('?')\n return q >= 0 && q < s.length - 1 ? s.slice(0, q) : s\n}\n\n// HTML ASCII whitespace per WHATWG/HTML spec\n// (https://infra.spec.whatwg.org/#ascii-whitespace):\n// U+0009 TAB, U+000A LF, U+000C FF, U+000D CR, U+0020 SPACE.\n// Narrower than JS regex `\\s` (which also matches U+000B VT, NBSP,\n// the U+2000–U+200A run, U+2028/U+2029, U+202F, U+205F, U+3000, BOM).\n// See `moveBlockClosingTagOutOfParagraph` below for the rationale.\nfunction isHtmlWhitespace(c: number): boolean {\n return c === 0x20 || c === 0x09 || c === 0x0a || c === 0x0d || c === 0x0c\n}\n\n/**\n * Linear-time replacement for the `endPattern` regex in\n * `markdown-to-html.method.ts`:\n *\n * /(?:\\s*<br>)?\\s*(<\\/(?:tagA|tagB|…)>)<\\/p>/gi → '</p>$1'\n *\n * Anchors on `</p>` (rare, found via `indexOf`), checks that the\n * character immediately before is `>`, walks back to find the matching\n * `</tag…>`, and — if `tag` is one of the configured block tags —\n * rewrites the run to `</p></tag…>` while stripping any preceding\n * HTML-ASCII-whitespace + optional `<br>` + more HTML-ASCII-whitespace.\n *\n * The regex form had two unanchored `\\s*` quantifiers that\n * `regexp/no-super-linear-move` flagged as quadratic on whitespace-heavy\n * inputs without a matching closing tag (engine retried at every\n * starting position). This pass is O(n).\n *\n * **Intentional divergence from the regex's `\\s` class.** The regex\n * stripped JS-regex whitespace (which includes U+000B VT, NBSP, em\n * space, etc.); this helper only strips HTML-spec ASCII whitespace.\n * Markdown→HTML output doesn't insert those characters around `<br>`\n * in practice, so the behavioural difference is theoretical; when it\n * does happen the worst-case outcome is suboptimal HTML (a block\n * closing tag stays inside `<p>`), not invalid HTML or a security\n * issue. Aligning the whitespace class with the HTML spec is a\n * deliberate correctness choice, not an oversight — if a future\n * regression test wants exact `\\s` parity, expand `isHtmlWhitespace`\n * accordingly.\n */\nexport function moveBlockClosingTagOutOfParagraph(html: string, blockTags: Set<string>): string {\n const n = html.length\n let out = ''\n let i = 0\n\n while (i < n) {\n const pStart = html.indexOf('</p>', i)\n if (pStart < 0) {\n out += html.slice(i)\n break\n }\n\n // The closing block tag must end immediately before `</p>` (i.e. the\n // char before `</p>` is `>`). Anything else means there's nothing\n // for this pass to do at this position.\n if (pStart === i || html.charCodeAt(pStart - 1) !== 0x3e /* '>' */) {\n out += html.slice(i, pStart + 4)\n i = pStart + 4\n continue\n }\n\n // Find the matching `</` for that closing `>`. Worst-case scans\n // back to the previous match boundary `i` when the run before\n // `</p>` contains no `</`; total work across the whole input is\n // still amortised O(n) because each character is visited at most\n // twice (once forward by `indexOf`, once backward here).\n const closingStart = html.lastIndexOf('</', pStart - 2)\n if (closingStart < i) {\n out += html.slice(i, pStart + 4)\n i = pStart + 4\n continue\n }\n const tagName = html.slice(closingStart + 2, pStart - 1).toLowerCase()\n if (!blockTags.has(tagName)) {\n out += html.slice(i, pStart + 4)\n i = pStart + 4\n continue\n }\n\n // Walk back from `closingStart` over whitespace, optionally one\n // `<br>`, and more whitespace — mirroring the regex's stripping\n // semantics exactly.\n let k = closingStart\n while (k > i && isHtmlWhitespace(html.charCodeAt(k - 1))) k--\n if (k - 4 >= i && html.slice(k - 4, k).toLowerCase() === '<br>') {\n k -= 4\n while (k > i && isHtmlWhitespace(html.charCodeAt(k - 1))) k--\n }\n\n out += html.slice(i, k) + '</p>' + html.slice(closingStart, pStart)\n i = pStart + 4\n }\n\n return out\n}\n\nexport function extractYtStartTime(url:string):string {\n try {\n const urlObj = new URL(url);\n const params = new URLSearchParams(urlObj.search);\n if(params.has('t')){\n const t = params.get('t');\n return '' + parseInt(t || '0'); //parsing is important as sometimes t is famated '123s';\n }else if (params.has('start')){\n return params.get('start') || '';\n }\n return '';\n } catch (error) {\n return '';\n }\n}\nexport function sanitizePermlink(permlink: string): string {\n if (!permlink || typeof permlink !== 'string') {\n return ''\n }\n\n const [withoutQuery] = permlink.split('?')\n const [cleaned] = withoutQuery.split('#')\n\n return cleaned\n}\n\nexport function isValidPermlink(permlink: string): boolean {\n const sanitized = sanitizePermlink(permlink)\n\n if (!sanitized) {\n return false\n }\n\n // Should not contain image extensions, query params, or fragments\n const isImage = /\\.(jpg|jpeg|png|webp|gif|svg)$/i.test(sanitized)\n const isCleanFormat = /^[a-z0-9-]+$/.test(sanitized) // Hive standard\n\n return isCleanFormat && !isImage\n}\n\n// Reference: https://en.wikipedia.org/wiki/Domain_Name_System#Domain_name_syntax\n// Hive account names must follow similar rules to DNS (RFC 1035)\nconst LABEL_REGEX = /^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/;\n\nexport function isValidUsername(username: string): boolean {\n if (!username || typeof username !== 'string') return false;\n if (username.length > 16) return false;\n\n const labels = username.split('.');\n\n return labels.every(label => {\n return (\n label.length >= 3 &&\n label.length <= 16 &&\n /^[a-z]/.test(label) && // must start with a letter\n LABEL_REGEX.test(label) && // a-z0-9, hyphens, no start/end hyphen\n !label.includes('..') // double dots are impossible after split, but just in case\n );\n });\n}\n\n\n\n","import { XMLSerializer } from '../consts'\n\nexport function getSerializedInnerHTML(node: Node): string {\n const serializer = new XMLSerializer()\n\n if (node.childNodes[0]) {\n // xmldom's ChildNode isn't structurally assignable to its Node param type; it is a Node.\n return serializer.serializeToString(node.childNodes[0] as any)\n }\n\n return ''\n}\n","export function removeChildNodes(node: Node): void {\n // Remove children using stable snapshot to avoid live collection issues\n while (node.firstChild) {\n node.removeChild(node.firstChild)\n }\n}\n","import querystring from 'querystring'\nimport { LRUCache } from 'lru-cache'\n\nlet proxyBase = 'https://i.ecency.com'\n\n// base58 encoding of the source URL is the dominant cost in proxifyImageSrc.\n// The same URL is encoded repeatedly: once per srcset width (5×), once per\n// image size variant (blur/grid/row), and across requests (trending posts\n// repeat). Caching by URL collapses all of those to a single encode.\nconst urlHashCache = new LRUCache<string, string>({ max: 500 })\n\nconst BASE58_ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'\n\n// base58btc, byte-for-byte what multihashes' toB58String produced (that function was\n// `bs58.encode` behind a Buffer type-check — no multihash prefix). Inlined because the\n// Buffer it demanded is a Node global: bundlers that do not shim it (the self-hosted\n// blog SPA's, for one) shipped a `Buffer is not defined` crash into the browser on any\n// post carrying an image. The output is the image proxy's cache key and appears in\n// every image URL, so it must not change; proxify-image-src.spec.ts pins it.\nfunction base58Encode(bytes: Uint8Array): string {\n if (bytes.length === 0) return ''\n const digits: number[] = [0]\n for (let i = 0; i < bytes.length; i++) {\n let carry = bytes[i]\n for (let j = 0; j < digits.length; j++) {\n carry += digits[j] << 8\n digits[j] = carry % 58\n carry = (carry / 58) | 0\n }\n while (carry > 0) {\n digits.push(carry % 58)\n carry = (carry / 58) | 0\n }\n }\n let out = ''\n // Each leading zero byte encodes as a literal '1' rather than as a digit.\n for (let k = 0; k < bytes.length && bytes[k] === 0; k++) out += BASE58_ALPHABET[0]\n for (let q = digits.length - 1; q >= 0; q--) out += BASE58_ALPHABET[digits[q]]\n return out\n}\n\nfunction utf8Bytes(url: string): Uint8Array {\n // TextEncoder is standard in browsers and Node >= 11; Buffer stays as the fallback so\n // any runtime without it (older React Native) keeps the behaviour it has today.\n if (typeof TextEncoder !== 'undefined') return new TextEncoder().encode(url)\n return Uint8Array.from(Buffer.from(url, 'utf8'))\n}\n\nfunction getUrlHash(url: string): string {\n const cached = urlHashCache.get(url)\n if (cached) return cached\n const hash = base58Encode(utf8Bytes(url))\n urlHashCache.set(url, hash)\n return hash\n}\n\nexport function setProxyBase(p: string): void {\n proxyBase = p\n}\n\nexport function getProxyBase(): string {\n return proxyBase\n}\n\n// The image proxy's own /p/ route, on the active base and the legacy\n// images.ecency.com origin (the base before the i.ecency.com SNI migration).\n// Recognizing both lets a transform on an already-proxified URL reuse the\n// existing hash instead of re-encoding the whole URL into a proxy-of-a-proxy.\nconst PROXY_P_PREFIXES = (): string[] => [`${proxyBase}/p/`, 'https://images.ecency.com/p/']\n\nexport function extractPHash(url: string): string | null {\n const prefix = PROXY_P_PREFIXES().find((p) => url.startsWith(p))\n if (prefix) {\n const [hash] = url.slice(prefix.length).split('?')\n return hash.replace(/\\.(webp|png)$/,'')\n }\n return null\n}\n\nexport function isValidUrl(url: string): boolean {\n try {\n return Boolean(new URL(url));\n }\n catch(e){\n return false;\n }\n}\n\n/**\n * Longest image URL we will base58-encode. See the guard in proxifyForFormat:\n * the encoder is quadratic, so this bounds per-render CPU on user-authored\n * input. Observed maximum in real post bodies is ~234 characters.\n */\nconst MAX_PROXIED_URL_LENGTH = 2048\n\n/**\n * A legacy foreign SIZED proxy URL: `images.hive.blog/<WxH>/<inner>` or the\n * steemitimages equivalent — the only shape that carries a nested source URL\n * for getLatestUrl to unwrap.\n *\n * Deliberately narrower than {@link isLegacyForeignProxyUrl}: other non-`/D`\n * paths on those hosts (notably their own `/p/<hash>` proxy route) name a hash\n * in a foreign hash space, so routing them through our `/p/` would proxy a\n * proxy, and their content type is genuinely unknown.\n *\n * Shared by the proxify routing and the `<picture>` eligibility gate so the two\n * cannot disagree about which URLs reach the /p/ route.\n */\nconst LEGACY_SIZED_PROXY_RE = /^https:\\/\\/(?:images\\.hive\\.blog|steemitimages\\.com)\\/\\d+x\\d+\\/(.+)$/\n\nexport function isLegacySizedProxyUrl(url?: string): boolean {\n if (!url || typeof url !== 'string') return false\n return LEGACY_SIZED_PROXY_RE.test(url)\n}\n\n/**\n * The nested source of a legacy sized proxy URL — everything after the `<WxH>/`\n * segment, query string included — or null when the URL is not that shape.\n *\n * Positional, not a search for the last `http(s)://`: the nested source may\n * itself carry a URL-valued query parameter, and picking the last URL in the\n * string would resolve to that parameter's target instead of the image.\n *\n * Normalised exactly the way the imagehoster's legacy handler does it, because\n * both sides base58-encode this string and any divergence means two different\n * hashes for the same image: parse the path segment (trailing slashes stripped)\n * as a URL, then re-attach the query through searchParams — which percent-\n * encodes a URL-valued parameter — and re-serialise.\n */\nfunction extractLegacySizedSource(url: string): string | null {\n const m = LEGACY_SIZED_PROXY_RE.exec(url)\n if (!m) return null\n\n // Drop the fragment FIRST, and before splitting off the query. A browser\n // never sends anything from the first '#' onward, so the imagehoster resolves\n // `…/image.png` and `…/image.png#frag` to one hash; keeping it here would\n // mint a separate proxy hash — and therefore a separate CDN entry — per\n // fragment, letting arbitrary `#…` variants miss an already-cached image.\n // Order matters too: a '?' inside a fragment (`…/image.png#a?b=c`) is part of\n // the fragment, so splitting on '?' first would invent a query from it.\n const rest = m[1]\n const hashIndex = rest.indexOf('#')\n const addressable = hashIndex >= 0 ? rest.slice(0, hashIndex) : rest\n\n const qIndex = addressable.indexOf('?')\n const path = qIndex >= 0 ? addressable.slice(0, qIndex) : addressable\n const query = qIndex >= 0 ? addressable.slice(qIndex + 1) : ''\n\n // Trailing slashes are trimmed with a scan, not /\\/+$/: post bodies are\n // user-authored, so a crafted URL ending in thousands of slashes would make\n // that regex backtrack quadratically on every render, including SSR.\n let end = path.length\n while (end > 0 && path.charCodeAt(end - 1) === 47 /* '/' */) {\n end--\n }\n\n try {\n const inner = new URL(path.slice(0, end))\n if (query) {\n // append, not set: the handler preserves repeated keys\n for (const [key, value] of new URLSearchParams(query)) {\n inner.searchParams.append(key, value)\n }\n }\n return inner.toString()\n } catch {\n return null\n }\n}\n\n/**\n * Any legacy foreign proxy URL that has historically been served by swapping\n * the hostname onto our proxy base. Kept broad on purpose — this is the\n * long-standing behaviour for these hosts and narrowing it is out of scope.\n * `/D…` (stored upload) URLs are excluded: those go through the normal /p/\n * path so they can be resized and format-negotiated.\n */\nfunction isLegacyForeignProxyUrl(url: string): boolean {\n return (\n (url.indexOf('https://images.hive.blog/') === 0 && url.indexOf('https://images.hive.blog/D') !== 0) ||\n (url.indexOf('https://steemitimages.com/') === 0 && url.indexOf('https://steemitimages.com/D') !== 0)\n )\n}\n\nexport function getLatestUrl(str: string): string {\n const [last] = [...str.replace(/https?:\\/\\//g, '\\n$&').trim().split('\\n')].reverse()\n return last\n}\n\nexport interface ProxifyOptions {\n /**\n * Request a tiny blurred LQIP placeholder. The proxy resizes to ~20px and\n * gaussian-blurs it (a few hundred bytes), for use behind the real image\n * while it loads.\n */\n blur?: boolean\n /**\n * Route on-host uploads through the /p/ proxy even when no width/height is\n * requested, so the server still negotiates WebP/AVIF via the Accept header\n * (instead of streaming the original bytes from direct-serve). Use for\n * displayed `<img>` sources; leave off for OG/social images, where the\n * original format is safest.\n */\n forceProxy?: boolean\n}\n\n// Internal format-aware proxify. The public proxifyImageSrc (below) locks the\n// format to 'match' (Accept-negotiated at the origin). Explicit per-format\n// variants (avif/webp) for <picture> are built via this + buildSrcSetForFormat,\n// which keep the chosen format in the URL — cache-safe behind a CDN that does\n// NOT vary its cache on the Accept header (so the negotiated variant can't be\n// cross-served to a client that requested a different one).\nfunction proxifyForFormat(\n url?: string,\n width = 0,\n height = 0,\n format = 'match',\n opts: ProxifyOptions = {}\n) {\n if (!url || typeof url !== 'string' || !isValidUrl(url)) {\n return ''\n }\n\n // base58 encoding is quadratic in the input length, and post bodies are\n // user-authored: a single crafted 60KB image URL costs ~12.6s of CPU per\n // render, on the SSR path. Real image URLs are nowhere near this — across 374\n // in-body URLs from 60 live posts the longest was 234 characters — so cap it\n // with generous headroom and treat anything longer as unusable, exactly like\n // a malformed URL. Applies to every shape, including the legacy sized route\n // that previously short-circuited to a hostname swap before any hashing.\n if (url.length > MAX_PROXIED_URL_LENGTH) {\n return ''\n }\n\n // The /p/ route is the only one that transforms (resize/blur) or negotiates\n // WebP/AVIF; the direct-serve route streams the stored original bytes as-is.\n // Route through /p/ when a transform is requested, or when the caller opts in\n // to format negotiation on an otherwise-unsized image (forceProxy). Otherwise\n // keep the lightweight hostname-swap — no proxy self-fetch, original format\n // preserved (which matters for OG/social where AVIF may be unsupported).\n const routeThroughProxy = width > 0 || height > 0 || !!opts.blur || !!opts.forceProxy\n\n // Legacy sized proxy URLs (`images.hive.blog/<WxH>/<inner>`, same for\n // steemitimages). The bare hostname swap keeps them on our own domain but\n // lands on the direct-serve route, which the imagehoster answers with a 301\n // to the /p/ form. Two costs: the extra round trip, and the redirect carries\n // the width baked into the URL path (`.../1536x0/...` -> `width=1536`) rather\n // than the width the caller asked for — so a 600px thumbnail was served the\n // 1536px rendition (measured on a real post photo: 17,027 bytes via the\n // redirect vs 3,316 bytes going straight to /p/ at width=600).\n //\n // The redirect target is the hash of the INNER source URL — the imagehoster\n // unwraps the nested URL itself (verified: its Location header is byte-equal\n // to the /p/ URL this function now returns). So routing here directly changes\n // no image identity and no cache entry: if the inner source is gone, both\n // paths fall back to the same placeholder.\n //\n // So keep the swap only when nothing is being requested of the proxy (OG and\n // social images, where the original format is safest). Once a transform or\n // format negotiation is wanted, fall through: getLatestUrl() unwraps the\n // nested source URL, so the image is fetched from its origin through our own\n // /p/ route in one hop, resized, and format-negotiated.\n // Only the sized `<WxH>/<inner>` shape changes: it falls through to /p/ once\n // something is actually asked of the proxy. Every other legacy foreign URL\n // keeps the hostname swap exactly as before, transform or not.\n if (isLegacyForeignProxyUrl(url) && !(isLegacySizedProxyUrl(url) && routeThroughProxy)) {\n return url\n .replace('https://images.hive.blog', proxyBase)\n .replace('https://steemitimages.com', proxyBase)\n }\n\n // Legacy on-chain content embeds images.ecency.com URLs directly. With no\n // transform or format negotiation requested, re-point them to the active\n // proxy base — the same imagehoster backend, just an SNI-resilient hostname\n // (some ISPs, e.g. Virgin Media UK, SNI-filter the images.ecency.com\n // hostname) — and serve the stored bytes directly (no proxy self-fetch).\n // Otherwise fall through to the /p/ proxy: the bare hostname swap yields a\n // direct-serve URL that ignores ?width / ?blur and does no WebP/AVIF\n // negotiation, shipping the full-size original in its original format.\n if (url.indexOf('https://images.ecency.com/') === 0 && !routeThroughProxy) {\n return url.replace('https://images.ecency.com', proxyBase)\n }\n\n // For a legacy sized URL take everything after the `<WxH>/` segment verbatim.\n // getLatestUrl() picks the LAST http(s):// substring anywhere in the string,\n // so a nested source carrying a URL-valued query parameter\n // (`/60x70/http://host/image.png?redirect=https://other/x.png`) would resolve\n // to the parameter's URL instead of the image. The imagehoster extracts the\n // path segment and keeps the query — verified against its Location header —\n // so match that exactly or the two disagree about which image this is.\n const realUrl = extractLegacySizedSource(url) ?? getLatestUrl(url)\n const pHash = extractPHash(realUrl)\n\n const options: Record<string, string | number> = {\n format,\n mode: 'fit',\n }\n\n if (width > 0) {\n options.width = width\n }\n\n if (height > 0) {\n options.height = height\n }\n\n if (opts.blur) {\n options.blur = 1\n }\n\n const qs = querystring.stringify(options)\n\n if (pHash) {\n return `${proxyBase}/p/${pHash}?${qs}`\n }\n\n const b58url = getUrlHash(realUrl.toString())\n\n return `${proxyBase}/p/${b58url}?${qs}`\n}\n\n/**\n * @param _format - @deprecated Ignored. The public API always requests 'match'\n * so the origin negotiates WebP/AVIF via the Accept header. Explicit per-format\n * renditions (for `<picture>`) are built via buildSrcSetForFormat /\n * buildPictureSources, which keep the format in the URL (cache-safe behind a CDN\n * that ignores Accept).\n */\nexport function proxifyImageSrc(\n url?: string,\n width = 0,\n height = 0,\n _format = 'match',\n opts: ProxifyOptions = {}\n) {\n return proxifyForFormat(url, width, height, 'match', opts)\n}\n\n// Widths chosen to align with sizes already cached by the image proxy\n// (600 used by OG/deck thumbnails, 800 by self-hosted thumbnails)\nconst SRCSET_WIDTHS = [320, 600, 800, 1024, 1280];\n\n/**\n * Builds a srcset string with multiple width variants for responsive images.\n * Uses the image proxy's width parameter to serve appropriately sized images.\n * Format is locked to 'match' (Accept-negotiated) — see buildSrcSetForFormat\n * for explicit per-format renditions.\n */\nexport function buildSrcSet(url?: string): string {\n return buildSrcSetForFormat(url, 'match');\n}\n\n/**\n * Like buildSrcSet but pins an explicit output format in the URL (avif/webp/\n * match). Used to build the per-format `<source>` srcsets of a `<picture>`: a\n * format baked into the URL is cache-safe behind a CDN that ignores the Accept\n * header, whereas a single 'match' URL gets one negotiated variant cached and\n * cross-served to every client. Byte-identical to buildSrcSet when format is\n * 'match'.\n */\nexport function buildSrcSetForFormat(\n url?: string,\n format: 'avif' | 'webp' | 'match' = 'match'\n): string {\n if (!url || typeof url !== 'string') return '';\n\n // For already-proxied URLs, extract the hash and rebuild with widths.\n // Use plain string operations rather than RegExp(`^${proxyBase}/p/...`)\n // so proxyBase (a user-settable hostname) never reaches a regex compile\n // path — keeps CodeQL's hostname-regex analysis clean.\n const proxyPrefix = `${proxyBase}/p/`;\n let result: string;\n if (url.startsWith(proxyPrefix)) {\n const rest = url.slice(proxyPrefix.length);\n const q = rest.indexOf('?');\n const phash = extractPHash(url) || (q >= 0 ? rest.slice(0, q) : rest);\n result = SRCSET_WIDTHS\n .map(w => `${proxyBase}/p/${phash}?format=${format}&mode=fit&width=${w} ${w}w`)\n .join(', ');\n } else {\n // For non-proxified URLs, proxify at each width with the requested format\n result = SRCSET_WIDTHS\n .map(w => {\n const proxied = proxifyForFormat(url, w, 0, format);\n return proxied ? `${proxied} ${w}w` : '';\n })\n .filter(Boolean)\n .join(', ');\n }\n\n // Honor the contract (\"pins an explicit output format in the URL\"): only\n // return a srcset that actually carries the requested format. Legacy\n // direct-serve hosts (images.hive.blog/WxH, steemitimages) host-swap WITHOUT\n // routing through the /p/ transform, so they can't be transcoded — return ''\n // rather than a srcset that silently ignores the requested avif/webp.\n if (format !== 'match' && result && !result.split(',').every(c => c.includes(`format=${format}`))) {\n return '';\n }\n return result;\n}\n\n// Static raster formats the imagehoster reliably transcodes to avif/webp.\n// Animated (gif/apng), vector (svg) and exotic (heic/ico/tiff/arw) are excluded:\n// the origin returns the ORIGINAL bytes for ?format=avif on an animated source,\n// which a <source type=\"image/avif\"> would mislabel (the browser commits to that\n// source and never reaches the <img> fallback). Checked against the URL PATHNAME\n// only — a static-looking extension in the query/fragment (e.g. `?file=a.png`,\n// `x.svg#thumb.png`) does not prove the fetched resource is a static raster.\nconst STATIC_RASTER_PATH_EXT = /\\.(?:jpe?g|png|webp)$/i;\n// Image-proxy sized route, e.g. /600x500/<url> — already-proxified, extension lost.\nconst SIZED_PROXY_PATH = /^\\/\\d+x\\d+\\//;\n\n/**\n * Whether a RAW (pre-proxify) image URL is safe to offer avif/webp `<source>`\n * renditions for. Requires an http(s) URL whose PATHNAME ends in a static-raster\n * extension and that is NOT already proxified — already-proxified routes (`/p/`\n * base58 hash, `/u/` avatars, `WxH` sized) have the original extension stripped,\n * so we can't prove the underlying bytes aren't an animated gif and must fall\n * back to a bare img. URL parsing (not string regex on the host) keeps the host\n * comparison exact and avoids an interpolated-hostname regex.\n */\nexport function isPictureEligibleRawUrl(rawUrl?: string): boolean {\n if (!rawUrl || typeof rawUrl !== 'string') return false;\n let u: URL;\n try {\n u = new URL(rawUrl);\n } catch {\n return false;\n }\n if (u.protocol !== 'http:' && u.protocol !== 'https:') return false;\n\n // Legacy sized-proxy URLs now reach the /p/ route (see proxifyForFormat), so a\n // format CAN be pinned for them. Their path hides the original extension, but\n // that no longer decides anything: an animated source is returned untouched\n // whatever format is requested (verified on a live 44-frame gif — match, avif\n // and webp all return the same 1,001,718 bytes), and an SVG is already\n // rasterised by the /p/ route under format=match (verified: match and avif\n // return byte-identical output). So a pinned <source> cannot change what the\n // reader sees. These are ~5% of in-body images overall but cluster in\n // photo-heavy posts, where a big image is usually the LCP element.\n if (isLegacySizedProxyUrl(rawUrl)) return true;\n\n const host = `${u.protocol}//${u.host}`;\n const isProxyHost = host === proxyBase || host === 'https://images.ecency.com';\n if (\n isProxyHost &&\n (u.pathname.startsWith('/p/') || u.pathname.startsWith('/u/') || SIZED_PROXY_PATH.test(u.pathname))\n ) {\n return false;\n }\n return STATIC_RASTER_PATH_EXT.test(u.pathname);\n}\n\n/**\n * Build the avif + webp `<source>` srcsets for a `<picture>` around a RAW image\n * URL, or null when the URL is ineligible (non-raster, animated, already\n * proxified, or a legacy host that bypasses the /p/ transform). Single\n * eligibility gate shared by the renderer so the decision can't diverge.\n */\nexport function buildPictureSources(\n rawUrl?: string\n): { avif: string; webp: string } | null {\n if (!isPictureEligibleRawUrl(rawUrl)) return null;\n // buildSrcSetForFormat returns '' when it can't honor the requested format\n // (legacy direct-serve hosts that bypass the /p/ transform), so a non-empty\n // pair guarantees every candidate is a proxied /p/ URL carrying the format.\n const avif = buildSrcSetForFormat(rawUrl, 'avif');\n const webp = buildSrcSetForFormat(rawUrl, 'webp');\n if (!avif || !webp) return null;\n return { avif, webp };\n}\n","import xss from 'xss'\nimport {ALLOWED_ATTRIBUTES, ID_WHITELIST, isAllowedEmbedSrc} from '../consts'\nimport { getProxyBase } from '../proxify-image-src'\nimport { trimTrailingSlash } from '../helper'\n\n// data-* attributes whose value is later consumed as an <iframe> src by the\n// client video extensions (dataset.embedSrc / dataset.videoHref). They MUST be\n// an absolute https:// URL on an allowed embed host — anything else (a\n// javascript:/data: same-origin XSS, or an arbitrary off-allowlist origin used\n// for phishing/redirect inside a non-sandboxed frame) is blanked here, the\n// authoritative layer. The renderer only ever emits allowlisted https values\n// (see a.method.ts), so legitimate embeds are unaffected.\nconst EMBED_SRC_DATA_ATTRS = new Set(['data-embed-src', 'data-video-href'])\n\n// data-href carries a navigation target (mobile post/community/hivesigner links\n// and arbitrary external links), NOT an iframe src, so it is held to the same\n// scheme policy a.method.ts already applies to href — block javascript:, data:,\n// vbscript:, file:, etc. while allowing http(s)/mailto/hive/tel/relative.\n// Whitespace/control chars browsers ignore inside the scheme are stripped first.\nconst isSafeNavValue = (value: string): boolean => {\n const trimmed = value.trim().replace(/[\\t\\n\\r\\f\\v\\0]/g, '').toLowerCase()\n if (!trimmed) return false\n const isSafeScheme = /^(https?|mailto|hive|tel|web\\+[a-z0-9.+-]+):/i.test(trimmed)\n const isRelative = /^(\\/\\/|\\/[^/]?|#|\\?|[a-z0-9._\\-]+(\\/|$))/i.test(trimmed)\n return isSafeScheme || isRelative\n}\n\nconst decodeEntities = (input: string): string =>\n input\n .replace(/&#(\\d+);?/g, (_, dec) => String.fromCodePoint(Number(dec)))\n .replace(/&#x([0-9a-f]+);?/gi, (_, hex) => String.fromCodePoint(parseInt(hex, 16)));\n\n// A <source> in a <picture> may only point at the image proxy's /p/ route. This\n// blocks a malicious on-chain <source srcset=\"...\"> from beaconing to an\n// external host or using a non-http scheme (the <img> src/srcset already get\n// the http(s) check below). Our renderer only ever emits proxyBase /p/ srcsets.\nconst isProxyPSrcset = (srcset: string): boolean => {\n const base = trimTrailingSlash(getProxyBase());\n const candidates = srcset.split(',').map(c => c.trim().split(/\\s+/)[0]).filter(Boolean);\n return candidates.length > 0 && candidates.every(url => url.startsWith(`${base}/p/`));\n};\n\nexport function sanitizeHtml(html: string): string {\n const cleaned = xss(html, {\n whiteList: ALLOWED_ATTRIBUTES,\n stripIgnoreTag: true,\n stripIgnoreTagBody: ['style'],\n css: false, // block style attrs entirely for safety\n onTagAttr: (tag, name, value) => {\n const decoded = decodeEntities(value.trim());\n const decodedLower = decoded.toLowerCase();\n\n if (name.startsWith('on')) return ''; // 🛡 event handlers\n // Positive-whitelist: only http(s) is accepted. Any other scheme\n // (javascript:, data:, vbscript:, file:, etc.) is rejected by the\n // negation. We don't need an explicit blocklist alongside.\n if (tag === 'img' && name === 'src' && !/^https?:\\/\\//.test(decodedLower)) return '';\n // Validate srcset: reject if any candidate URL uses a non-http(s) protocol\n if (tag === 'img' && name === 'srcset') {\n const candidates = decoded.split(',').map(c => c.trim().split(/\\s+/)[0]);\n if (candidates.some(url => !/^https?:\\/\\//i.test(url))) return '';\n }\n // <picture><source>: srcset is restricted to the proxy /p/ route, and type\n // to the two formats we emit. Anything else is blanked (and a then\n // type-less <source> is dropped wholesale in the post-pass below).\n if (tag === 'source' && name === 'srcset' && !isProxyPSrcset(decoded)) return '';\n if (tag === 'source' && name === 'type' && decodedLower !== 'image/avif' && decodedLower !== 'image/webp') return '';\n if (\n (tag === 'video' || tag === 'audio') && ['src', 'poster'].includes(name) &&\n !/^https?:\\/\\//.test(decodedLower)\n ) return '';\n // Clamp audio preload to a lightweight hint: our player emits\n // preload=\"metadata\", and an author-supplied preload=\"auto\" on untrusted\n // posts would eagerly fetch large third-party audio before any click.\n if (tag === 'audio' && name === 'preload' &&\n decodedLower !== 'metadata' && decodedLower !== 'none') return '';\n if (tag === 'img' && ['dynsrc', 'lowsrc'].includes(name)) return '';\n if (tag === 'span' && name === 'class' && decoded.toLowerCase().trim() === 'wr') return '';\n // iframe-src data-* attrs: must resolve to an https:// allowed-embed-host\n // URL or they are blanked (stored HTML/iframe injection — CVE class).\n if (EMBED_SRC_DATA_ATTRS.has(name) && !isAllowedEmbedSrc(decoded)) return '';\n // data-href is a navigation target; block dangerous schemes only.\n if (name === 'data-href' && !isSafeNavValue(decoded)) return '';\n if (name === 'id') {\n if (!ID_WHITELIST.test(decoded)) return '';\n }\n return undefined;\n }\n });\n\n // Drop any <source> that lacks a valid avif/webp type. onTagAttr can blank an\n // attribute but can't remove an element, and a type-less <source> with a\n // surviving srcset would match ALL browsers (overriding the <img>). Our\n // renderer always emits a typed <source>, so this only fires on hostile input.\n // The tag matcher tolerates a literal '>' inside a quoted attribute value\n // (xss escapes '>' to '&gt;' in output, so this is belt-and-suspenders) by\n // consuming quoted spans whole rather than stopping at the first '>'.\n return cleaned.replace(/<source\\b(?:[^>\"']|\"[^\"]*\"|'[^']*')*>/gi, (t) =>\n /\\btype\\s*=\\s*[\"'](?:image\\/avif|image\\/webp)[\"']/i.test(t) ? t : ''\n );\n}\n","import { proxifyImageSrc, buildSrcSet, getProxyBase, buildPictureSources } from \"../proxify-image-src\";\nimport { trimTrailingSlash, decodeImageSrc } from \"../helper\";\n\n/**\n * The `sizes` value the renderer applies to in-body post images (see `img()`\n * and `createImageHTML()`). Exported as the single source of truth so consumers\n * preloading the LCP image (`<link rel=\"preload\" as=\"image\" imagesizes>`) can\n * match the exact srcset candidate the rendered <img> selects.\n */\nexport const IMAGE_SIZES = \"(max-width: 768px) 100vw, 700px\";\n\n/**\n * Wrap a displayed <img> (DOM path) in a <picture> with explicit avif/webp\n * <source>s, so the browser negotiates format client-side via distinct,\n * cache-safe URLs (the format lives in the URL, not the Accept header that the\n * CDN cache ignores). No-op when the raw URL is not picture-eligible, or when\n * the <img> is already inside a <picture> (traverse can re-enter the inner <img>\n * of a string-path <picture>). Web/self-hosted only — the caller gates on\n * `forApp === false` because React Native cannot render <picture>.\n */\nfunction wrapInPicture(el: HTMLElement, rawUrl: string): void {\n const parent = el.parentNode;\n if (!parent) return;\n if (parent.nodeName && parent.nodeName.toLowerCase() === \"picture\") return;\n const sources = buildPictureSources(rawUrl);\n if (!sources) return;\n const doc = el.ownerDocument;\n if (!doc) return;\n const sizes = el.getAttribute(\"sizes\") || IMAGE_SIZES;\n const picture = doc.createElement(\"picture\");\n const avif = doc.createElement(\"source\");\n avif.setAttribute(\"type\", \"image/avif\");\n avif.setAttribute(\"srcset\", sources.avif);\n avif.setAttribute(\"sizes\", sizes);\n const webp = doc.createElement(\"source\");\n webp.setAttribute(\"type\", \"image/webp\");\n webp.setAttribute(\"srcset\", sources.webp);\n webp.setAttribute(\"sizes\", sizes);\n // avif first — the browser picks the first <source> it supports.\n parent.insertBefore(picture, el);\n picture.appendChild(avif);\n picture.appendChild(webp);\n picture.appendChild(el);\n}\n\nexport function img(el: HTMLElement, state?: { firstImageFound: boolean }, forApp = true): void {\n const src = el.getAttribute(\"src\") || \"\";\n\n // Normalize encoded characters (shared with getEntryImageRawUrl so the LCP\n // preload's proxy hash byte-matches this rendered <img>/<picture>).\n const decodedSrc = decodeImageSrc(src);\n\n // Sanitize dangerous attributes regardless of validity\n [\"onerror\", \"dynsrc\", \"lowsrc\", \"width\", \"height\"].forEach(attr => el.removeAttribute(attr));\n\n // ❌ Remove if javascript or empty/invalid\n const isInvalid = !src || decodedSrc.startsWith(\"javascript\") || decodedSrc.startsWith(\"vbscript\") || decodedSrc === \"x\";\n if (isInvalid) {\n el.removeAttribute(\"src\");\n el.removeAttribute(\"srcset\");\n el.removeAttribute(\"sizes\");\n return;\n }\n\n // ❌ Skip relative paths (e.g., `photo.jpg`, `./photo.png`, `assets/pic.jpeg`)\n // Use trimmed decodedSrc for protocol check to handle leading/trailing whitespace\n const isRelative = !/^https?:\\/\\//i.test(decodedSrc) && !decodedSrc.startsWith(\"/\");\n if (isRelative) {\n el.removeAttribute(\"src\");\n el.removeAttribute(\"srcset\");\n el.removeAttribute(\"sizes\");\n return;\n }\n\n el.setAttribute(\"itemprop\", \"image\");\n const isLCP = state && !state.firstImageFound;\n\n if (isLCP) {\n el.setAttribute(\"loading\", \"eager\");\n el.setAttribute(\"fetchpriority\", \"high\");\n state.firstImageFound = true;\n } else {\n el.setAttribute(\"loading\", \"lazy\");\n el.setAttribute(\"decoding\", \"async\");\n }\n\n const cls = el.getAttribute(\"class\") || \"\";\n const shouldReplace = !cls.includes(\"no-replace\");\n // Only skip re-proxification for URLs already going through proxy/avatar/cover routes\n // Direct upload URLs (e.g. /DQm...) should still be proxified for resizing & format optimization\n const base = trimTrailingSlash(getProxyBase());\n const hasAlreadyProxied = src.startsWith(`${base}/p/`)\n || src.startsWith(`${base}/u/`)\n || new RegExp(`^${base.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}/\\\\d+x\\\\d+/`).test(src);\n\n if (shouldReplace && !hasAlreadyProxied) {\n // forceProxy: route the fallback src through /p/ even though no width is set,\n // so uploads still get WebP/AVIF via Accept negotiation instead of the\n // original-format direct-serve bytes. (srcset carries the resized variants.)\n const proxified = proxifyImageSrc(decodedSrc, 0, 0, \"match\", { forceProxy: true });\n if (proxified) {\n el.setAttribute(\"src\", proxified);\n const srcset = buildSrcSet(decodedSrc);\n if (srcset) {\n el.setAttribute(\"srcset\", srcset);\n el.setAttribute(\"sizes\", IMAGE_SIZES);\n }\n // Web/self-hosted: offer avif/webp via <picture>. The raw decodedSrc still\n // carries the original extension here (pre-proxify), which the eligibility\n // gate needs. The <img> above stays the format=match fallback.\n if (!forApp) {\n wrapInPicture(el, decodedSrc);\n }\n }\n } else if (shouldReplace && hasAlreadyProxied) {\n // Only /p/ URLs have extractable hashes for srcset; /u/ and /WxH/ routes\n // are avatar/cover URLs that shouldn't get responsive srcset\n if (src.startsWith(`${base}/p/`)) {\n const srcset = buildSrcSet(src);\n if (srcset) {\n el.setAttribute(\"srcset\", srcset);\n el.setAttribute(\"sizes\", IMAGE_SIZES);\n }\n }\n }\n}\n\nexport function createImageHTML(src: string, isLCP: boolean, forApp = true): string {\n // Decode with the same pipeline as the DOM path img() so the same source URL\n // hashes to the same proxy /p/ URL regardless of which render path produced it\n // (and so the LCP preload, which decodes via getEntryImageRawUrl, matches).\n const decoded = decodeImageSrc(src);\n // forceProxy: see img() — keep the fallback src unsized but proxied so uploads\n // are served WebP/AVIF rather than the original-format direct-serve bytes.\n const proxified = proxifyImageSrc(decoded, 0, 0, \"match\", { forceProxy: true });\n if (!proxified) return '';\n\n const base = trimTrailingSlash(getProxyBase());\n const isAlreadyProxied = decoded.startsWith(`${base}/u/`)\n || new RegExp(`^${base.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}/\\\\d+x\\\\d+/`).test(decoded);\n const srcset = isAlreadyProxied ? '' : buildSrcSet(decoded);\n const loading = isLCP ? 'eager' : 'lazy';\n const fetch = isLCP ? 'fetchpriority=\"high\"' : 'decoding=\"async\"';\n const srcsetAttr = srcset ? `srcset=\"${srcset}\" sizes=\"${IMAGE_SIZES}\"` : '';\n const imgTag = `<img\n class=\"markdown-img-link\"\n src=\"${proxified}\"\n ${srcsetAttr}\n loading=\"${loading}\"\n ${fetch}\n itemprop=\"image\"\n />`;\n\n // Web/self-hosted: wrap in <picture> with explicit avif/webp <source>s when\n // the source is picture-eligible. Self-closing <source/> — an explicit\n // </source> throws in the downstream xmldom re-parse. The <img> stays the\n // format=match fallback. App path (forApp) keeps the bare <img> (no <picture>\n // in React Native).\n if (!forApp) {\n const sources = buildPictureSources(decoded);\n if (sources) {\n return `<picture><source type=\"image/avif\" srcset=\"${sources.avif}\" sizes=\"${IMAGE_SIZES}\" /><source type=\"image/webp\" srcset=\"${sources.webp}\" sizes=\"${IMAGE_SIZES}\" />${imgTag}</picture>`;\n }\n }\n return imgTag;\n}\n","import {\n BITCHUTE_REGEX,\n CUSTOM_COMMUNITY_REGEX,\n INTERNAL_POST_REGEX,\n INTERNAL_POST_TAG_REGEX,\n D_TUBE_REGEX,\n D_TUBE_REGEX2,\n IMG_REGEX,\n IPFS_REGEX,\n MENTION_REGEX,\n INTERNAL_MENTION_REGEX,\n TOPIC_REGEX,\n INTERNAL_TOPIC_REGEX,\n POST_REGEX,\n CCC_REGEX,\n SPEAK_REGEX,\n SPEAK_AUDIO_REGEX,\n LIKETU_AUDIO_REGEX,\n TWITCH_REGEX,\n TWITTER_REGEX,\n VIMEO_REGEX,\n WHITE_LIST,\n YOUTUBE_REGEX,\n SPOTIFY_REGEX,\n RUMBLE_REGEX,\n BRIGHTEON_REGEX,\n ODYSEE_WATCH_REGEX,\n DOMParser,\n LOOM_REGEX,\n SECTION_LIST\n} from '../consts'\nimport { getSerializedInnerHTML } from './get-inner-html.method'\nimport { proxifyImageSrc } from '../proxify-image-src'\nimport { removeChildNodes } from './remove-child-nodes.method'\nimport { extractYtStartTime, isValidPermlink, isValidUsername, sanitizePermlink, stripHtmlTags, trimTrailingSlash } from '../helper'\nimport { createImageHTML } from \"./img.method\";\nimport { RenderOptions, SeoContext } from '../types'\n\nconst NOFOLLOW_REPUTATION_THRESHOLD = 40;\nconst FOLLOW_PAYOUT_THRESHOLD = 5;\n\n/**\n * Determines the rel attribute for external links based on SEO context.\n *\n * Default: \"nofollow ugc noopener\" for all user-generated external links.\n * Exception: \"noopener\" only (followed) when author reputation >= 40 AND post payout > $5.\n */\nfunction getExternalLinkRel(seoContext?: SeoContext): string {\n if (\n seoContext?.authorReputation !== undefined &&\n seoContext?.postPayout !== undefined &&\n seoContext.authorReputation >= NOFOLLOW_REPUTATION_THRESHOLD &&\n seoContext.postPayout > FOLLOW_PAYOUT_THRESHOLD\n ) {\n return 'noopener';\n }\n return 'nofollow ugc noopener';\n}\n\n/**\n * Turns a video link into a player for the providers we cannot derive a\n * thumbnail for synchronously (BitChute, Rumble, Brighteon, Odysee). YouTube and\n * 3Speak stay hand-written because each carries provider-specific work (start\n * time, portrait detection, thumbnail from post metadata).\n *\n * The per-provider modifier class matters: both the stylesheet and the\n * click-to-play extension select on it, so an anchor carrying only the base\n * class is unstyled (zero height, no play icon) and unhandled — which is why a\n * posted BitChute link used to render as nothing at all.\n *\n * `embedVideosDirectly` (waves feed, self-hosted blog) mounts no client\n * enhancer, so there a placeholder would stay inert forever; emit a real iframe\n * instead, mirroring the YouTube branch. It is never autoplayed: a feed\n * scrolling past several videos that all start at once is disorienting.\n */\nfunction renderPlainVideoLink(\n el: HTMLElement,\n provider: string,\n embedSrc: string,\n renderOptions?: RenderOptions\n): void {\n const baseClass = `markdown-video-link markdown-video-link-${provider}`\n // Attribute order below matches what these branches emitted before they were\n // folded together, so the serialized-output fixtures stay stable.\n el.setAttribute('class', baseClass)\n el.removeAttribute('href')\n el.textContent = ''\n el.setAttribute('data-embed-src', embedSrc)\n\n if (renderOptions?.embedVideosDirectly) {\n const wrapper = el.ownerDocument.createElement('span')\n wrapper.setAttribute('class', 'er-embed-frame')\n wrapper.setAttribute('style', 'display:block')\n\n const frame = el.ownerDocument.createElement('iframe')\n frame.setAttribute('src', embedSrc)\n frame.setAttribute('title', 'Video player')\n frame.setAttribute(\n 'allow',\n 'accelerometer; encrypted-media; gyroscope; picture-in-picture; web-share'\n )\n frame.setAttribute('allowfullscreen', '')\n\n wrapper.appendChild(frame)\n el.appendChild(wrapper)\n // `er-embed` marks this as already enhanced so the click-to-play extension\n // skips it if both paths ever run over the same document.\n el.setAttribute('class', `${baseClass} er-embed`)\n return\n }\n\n const play = el.ownerDocument.createElement('span')\n play.setAttribute('class', 'markdown-video-play')\n el.appendChild(play)\n}\n\nconst normalizeValue = (value?: string | null): string => (value ? value.trim() : '')\n\nconst matchesHref = (href: string, value?: string | null): boolean => {\n const normalizedHref = normalizeValue(href)\n if (!normalizedHref) {\n return false\n }\n\n return normalizeValue(value) === normalizedHref\n}\n\n/**\n * Normalizes display text for inline detection by:\n * - Stripping protocol and domain (ecency.com, peakd.com, hive.blog, leofinance.io, inleo.io, snapie.io, hivesuite.app)\n * - Removing leading/trailing slashes\n * - Removing query parameters\n * - Removing comment hashes (#@...)\n * - Converting to lowercase\n */\nconst normalizeDisplayText = (text: string): string => {\n const beforeTrailingSlash = text\n .trim()\n .replace(/^https?:\\/\\/(www\\.)?(ecency\\.com|peakd\\.com|hive\\.blog|leofinance\\.io|inleo\\.io|snapie\\.io|hivesuite\\.app)/i, \"\")\n .replace(/^\\/+/, \"\")\n .split(\"?\")[0]\n .replace(/#@.*$/i, \"\");\n return trimTrailingSlash(beforeTrailingSlash).toLowerCase();\n}\n\n/**\n * Enhanced inline detection that handles edge cases like:\n * - Full URLs: https://ecency.com/@author/permlink\n * - Relative URLs: /@author/permlink\n * - With community tags: hive-123456/@author/permlink\n * - With query params: @author/permlink?ref=twitter\n * - With trailing slashes: @author/permlink/\n */\nconst getInlineMeta = (el: HTMLElement, href: string, author: string, permlink: string, communityTag?: string) => {\n // Simple exact match (original behavior)\n const textMatches = matchesHref(href, el.textContent)\n const titleMatches = matchesHref(href, el.getAttribute('title'))\n\n // Sophisticated normalized matching\n const normalizedDisplay = normalizeDisplayText(el.textContent || \"\");\n const normalizedTarget = `@${author}/${permlink}`.toLowerCase();\n\n // Build expected display patterns\n const expectedDisplays = new Set([normalizedTarget]);\n if (communityTag) {\n expectedDisplays.add(`${communityTag.toLowerCase()}/${normalizedTarget}`);\n }\n\n const sophisticatedMatch =\n normalizedDisplay === normalizedTarget ||\n (communityTag ? normalizedDisplay === `${communityTag.toLowerCase()}/${normalizedTarget}` : false);\n\n return {\n textMatches,\n titleMatches,\n isInline: textMatches || titleMatches || sophisticatedMatch\n }\n}\n\n/**\n * Adds a line break before inline post links in mobile app mode\n * This ensures enhanced post links (where the raw URL is displayed) render on separate lines\n * in React Native where CSS display properties don't work the same way as in browsers\n */\nconst addLineBreakBeforePostLink = (el: HTMLElement, forApp: boolean, isInline: boolean): void => {\n if (forApp && isInline && el.parentNode) {\n const br = el.ownerDocument.createElement('br')\n el.parentNode.insertBefore(br, el)\n }\n}\n\nexport function a(el: HTMLElement | null, forApp: boolean, parentDomain: string = 'ecency.com', seoContext?: SeoContext, renderOptions?: RenderOptions): void {\n if (!el || !el.parentNode) {\n return\n }\n let href = el.getAttribute('href')\n\n // Continue if href has no value\n if (!href) {\n return\n }\n\n // Positive scheme whitelist. Anything that isn't http(s)/mailto/hive/\n // tel/web+ext or a same-document/relative reference is stripped — this\n // rejects javascript:, data:, vbscript:, file: and also less-common\n // exploit vectors like ms-its:, mk:, res:, intent:. Case-insensitive\n // and tolerant of whitespace/control chars browsers ignore inside the\n // scheme (\\t \\n \\r \\f \\v \\0).\n // Runs before the author/tag short-circuit below: that short-circuit keys off\n // `class`, which an author can set on raw HTML, so it must not be reachable with\n // an unvalidated href.\n const trimmed = href.trim().replace(/[\\t\\n\\r\\f\\v\\0]/g, '').toLowerCase()\n const isSafeScheme = /^(https?|mailto|hive|tel|web\\+[a-z0-9.+-]+):/i.test(trimmed)\n // `\\/[^/]?` matches both bare `/` (site-root link) and `/path…`;\n // alongside protocol-relative `//host`, fragment `#…`, query `?…`,\n // and document-relative `name.ext`/`name/`/bare `name`.\n const isRelative = /^(\\/\\/|\\/[^/]?|#|\\?|[a-z0-9._\\-]+(\\/|$))/i.test(trimmed)\n if (!isSafeScheme && !isRelative) {\n el.removeAttribute('href')\n return\n }\n\n const className = el.getAttribute('class')\n\n // Don't re-process user and hashtag links (original or enhanced). The marker is an\n // attacker-writable attribute rather than proof the renderer built this link, so a\n // crafted `<a class=\"er-author\" target=\"_blank\" rel=\"opener\">` would otherwise keep\n // its own rel and re-enable window.opener on the landing page. Skipping the rewrite\n // is fine; skipping the link policy is not, so re-assert it here.\n if (className && (\n ['markdown-author-link', 'markdown-tag-link'].includes(className) ||\n className.includes('er-author') ||\n className.includes('er-tag')\n )) {\n if (el.getAttribute('target')) {\n el.setAttribute('rel', getExternalLinkRel(seoContext))\n }\n return\n }\n\n // if href is an image url and innerHTML same with href then mark it as image\n // & => &amp; can break equality\n if (\n href.match(IMG_REGEX) &&\n href.trim().replace(/&amp;/g, '&') ===\n getSerializedInnerHTML(el).trim().replace(/&amp;/g, '&')\n ) {\n const isLCP = false; // LCP handled elsewhere\n const imgHTML = createImageHTML(href, isLCP, forApp);\n const doc = DOMParser.parseFromString(imgHTML, 'text/html');\n const replaceNode = (doc as any).body?.firstChild || doc.firstChild\n\n if (replaceNode && el.parentNode) {\n const importedNode = el.ownerDocument.importNode(replaceNode, true)\n el.parentNode.replaceChild(importedNode, el)\n }\n\n return\n }\n\n if (\n href.match(IPFS_REGEX) &&\n href.trim().replace(/&amp;/g, '&') ===\n getSerializedInnerHTML(el).trim().replace(/&amp;/g, '&') &&\n href.indexOf('#') === -1\n ) {\n if (forApp) {\n el.setAttribute('data-href', href)\n el.removeAttribute('href')\n }\n\n el.setAttribute('class', 'markdown-img-link')\n\n removeChildNodes(el)\n\n const img = el.ownerDocument.createElement('img')\n img.setAttribute('src', href)\n el.appendChild(img)\n\n return\n }\n\n // If a hive post\n const postMatch = href.match(POST_REGEX)\n if (postMatch && WHITE_LIST.includes(postMatch[1].replace(/^www\\./,''))) {\n el.setAttribute('class', 'markdown-post-link')\n\n const tag = postMatch[2]\n const author = postMatch[3].replace('@', '')\n const permlink = sanitizePermlink(postMatch[4])\n\n if (!isValidPermlink(permlink)) return;\n\n const inlineMeta = getInlineMeta(el, href, author, permlink)\n if (inlineMeta.textMatches) {\n el.textContent = `@${author}/${permlink}`\n }\n const isInline = inlineMeta.isInline\n if (forApp) {\n el.removeAttribute('href')\n\n el.setAttribute('data-href', href)\n el.setAttribute('data-is-inline', '' + isInline)\n el.setAttribute('data-tag', tag)\n el.setAttribute('data-author', author)\n el.setAttribute('data-permlink', permlink)\n\n } else {\n const h = `/@${author}/${permlink}`\n el.setAttribute('href', h)\n el.setAttribute('data-is-inline', '' + isInline)\n }\n\n addLineBreakBeforePostLink(el, forApp, isInline)\n return\n }\n\n // If a hive user with url\n const mentionMatch = href.match(MENTION_REGEX)\n if (mentionMatch && WHITE_LIST.includes(mentionMatch[1].replace(/^www\\./,'')) && mentionMatch.length === 3) {\n const _author = mentionMatch[2].replace('@', '')\n if (!isValidUsername(_author)) return\n const author = _author.toLowerCase()\n\n el.setAttribute('class', 'markdown-author-link')\n\n if (author.indexOf('/')===-1) {\n if (el.textContent === href) {\n el.textContent = `@${author}`\n }\n if (forApp) {\n el.removeAttribute('href')\n\n el.setAttribute('data-author', author)\n } else {\n const h = `/@${author}`\n el.setAttribute('href', h)\n }\n }\n return\n }\n\n // If a tagged post and profile section links\n const tpostMatch = href.match(INTERNAL_POST_TAG_REGEX)\n\n // Extract and validate domain from tpostMatch[1]\n let isValidDomain = false;\n if (tpostMatch && tpostMatch.length === 4) {\n if (tpostMatch[1].indexOf('/') === 0) {\n // Internal path like /ecency/@user/post\n isValidDomain = true;\n } else if (tpostMatch[1].includes('.')) {\n // Extract domain from URL (strip protocol and www.)\n const domain = tpostMatch[1]\n .replace(/^https?:\\/\\//, '') // Remove protocol\n .replace(/^www\\./, '') // Remove www. prefix\n isValidDomain = WHITE_LIST.includes(domain);\n }\n }\n\n // isValidDomain is only ever set true inside the `tpostMatch && length === 4` block above,\n // so tpostMatch is non-null here — asserted with `!` (type-only, erased at emit) at each use\n // to keep the emitted JS byte-identical.\n if (isValidDomain) {\n // check if permlink is section or section with params ?q=xyz\n // Split on '?' first to get path segment\n const pathSegment = tpostMatch![3].split('?')[0]\n if (SECTION_LIST.some(v => pathSegment === v || pathSegment.startsWith(v + '/'))) {\n el.setAttribute('class', 'markdown-profile-link')\n const author = tpostMatch![2].replace('@', '').toLowerCase()\n const section = tpostMatch![3]\n\n if (!isValidPermlink(section)) return;\n if (el.textContent === href) {\n el.textContent = `@${author}/${section}`\n }\n if (forApp) {\n const ha = `https://ecency.com/@${author}/${section}`\n el.setAttribute('href', ha)\n } else {\n const h = `/@${author}/${section}`\n el.setAttribute('href', h)\n }\n return\n } else {\n // Domain already validated in outer if condition\n let tag = 'post'\n // check if tag does exist and doesn't include dot likely word/tag\n if (tpostMatch![1] && !tpostMatch![1].includes('.')) {\n [, tag] = tpostMatch!\n tag = tag.replace('/', '')\n }\n\n el.setAttribute('class', 'markdown-post-link')\n const author = tpostMatch![2].replace('@', '')\n const permlink = sanitizePermlink(tpostMatch![3])\n\n if (!isValidPermlink(permlink)) return;\n\n // Pass community tag if it starts with \"hive-\"\n const communityTag = tag.toLowerCase().startsWith('hive-') ? tag : undefined\n const inlineMeta = getInlineMeta(el, href, author, permlink, communityTag)\n if (inlineMeta.textMatches) {\n el.textContent = `@${author}/${permlink}`\n }\n const isInline = inlineMeta.isInline\n if (forApp) {\n el.removeAttribute('href')\n\n el.setAttribute('data-href', href)\n el.setAttribute('data-is-inline', '' + isInline)\n el.setAttribute('data-tag', tag)\n el.setAttribute('data-author', author)\n el.setAttribute('data-permlink', permlink)\n\n } else {\n const h = `/@${author}/${permlink}`\n el.setAttribute('href', h)\n el.setAttribute('data-is-inline', '' + isInline)\n }\n\n addLineBreakBeforePostLink(el, forApp, isInline)\n return\n }\n }\n\n // If a hive user with internal url\n const imentionMatch = href.match(INTERNAL_MENTION_REGEX)\n if (imentionMatch) {\n const _author = imentionMatch[0].replace('/@', '')\n if (!isValidUsername(_author)) return\n const author = _author.toLowerCase()\n\n el.setAttribute('class', 'markdown-author-link')\n if (author.indexOf('/')===-1) {\n if (el.textContent === href) {\n el.textContent = `@${author}`\n }\n if (forApp) {\n el.removeAttribute('href')\n\n el.setAttribute('data-author', author)\n } else {\n const h = `/@${author}`\n el.setAttribute('href', h)\n }\n }\n return\n }\n\n // If a copied post and profile section links\n const cpostMatch = href.match(INTERNAL_POST_REGEX)\n if (\n (cpostMatch && cpostMatch.length === 3 && cpostMatch[1].indexOf('@') === 0)\n ) {\n // Split on '?' first to get path segment\n const pathSegment2 = cpostMatch[2].split('?')[0]\n if (SECTION_LIST.some(v => pathSegment2 === v || pathSegment2.startsWith(v + '/'))) {\n el.setAttribute('class', 'markdown-profile-link')\n const author = cpostMatch[1].replace('@', '').toLowerCase()\n const section = cpostMatch[2]\n\n if (el.textContent === href) {\n el.textContent = `@${author}/${section}`\n }\n if (forApp) {\n const ha = `https://ecency.com/@${author}/${section}`\n el.setAttribute('href', ha)\n } else {\n const h = `/@${author}/${section}`\n el.setAttribute('href', h)\n }\n return\n } else {\n el.setAttribute('class', 'markdown-post-link')\n\n const tag = 'post'\n\n const author = cpostMatch[1].replace('@', '')\n const permlink = sanitizePermlink(cpostMatch[2])\n\n if (!isValidPermlink(permlink)) return;\n\n const inlineMeta = getInlineMeta(el, href, author, permlink)\n\n if (inlineMeta.textMatches) {\n el.textContent = `@${author}/${permlink}`\n }\n const isInline = inlineMeta.isInline\n if (forApp) {\n el.removeAttribute('href')\n\n el.setAttribute('data-href', href)\n el.setAttribute('data-is-inline', '' + isInline)\n el.setAttribute('data-tag', tag)\n el.setAttribute('data-author', author)\n el.setAttribute('data-permlink', permlink)\n } else {\n const h = `/@${author}/${permlink}`\n el.setAttribute('href', h)\n el.setAttribute('data-is-inline', '' + isInline)\n }\n\n addLineBreakBeforePostLink(el, forApp, isInline)\n return\n }\n }\n\n // If topic with filters url\n const topicMatch = href.match(TOPIC_REGEX)\n if (topicMatch && WHITE_LIST.includes(topicMatch[1].replace(/^www\\./,'')) && topicMatch.length === 4) {\n el.setAttribute('class', 'markdown-tag-link')\n const filter = topicMatch[2]\n const tag = topicMatch[3]\n\n if (el.textContent === href) {\n el.textContent = `/${filter}/${tag}`\n }\n if (forApp) {\n el.removeAttribute('href')\n\n el.setAttribute('data-filter', filter)\n el.setAttribute('data-tag', tag)\n } else {\n const h = `/${filter}/${tag}`\n el.setAttribute('href', h)\n }\n return\n }\n\n // If topic with filters internal url\n const itopicMatch = href.match(INTERNAL_TOPIC_REGEX)\n if (itopicMatch && itopicMatch.length === 3) {\n el.setAttribute('class', 'markdown-tag-link')\n const filter = itopicMatch[1]\n const tag = itopicMatch[2]\n\n if (el.textContent === href) {\n el.textContent = `/${filter}/${tag}`\n }\n if (forApp) {\n el.removeAttribute('href')\n\n el.setAttribute('data-filter', filter)\n el.setAttribute('data-tag', tag)\n } else {\n const h = `/${filter}/${tag}`\n el.setAttribute('href', h)\n }\n return\n }\n\n // If a custom hive community link\n const comMatch = href.match(CUSTOM_COMMUNITY_REGEX)\n if (comMatch && WHITE_LIST.includes(comMatch[1].replace(/^www\\./,''))) {\n el.setAttribute('class', 'markdown-community-link')\n\n const community = comMatch[2]\n let filter = comMatch[3].substring(1)\n if (!filter) filter = 'created'\n if (filter === 'about' || filter === 'discord') {\n filter = 'created'\n }\n if (el.textContent === href) {\n el.textContent = `${filter}/${community}`\n }\n\n if (forApp) {\n el.removeAttribute('href')\n\n el.setAttribute('data-community', community)\n el.setAttribute('data-filter', filter)\n } else {\n const h = `/${filter}/${community}`\n el.setAttribute('href', h)\n }\n return\n }\n\n // If a collections post\n const cccMatch = href.match(CCC_REGEX)\n if (cccMatch && WHITE_LIST.includes(cccMatch[1].replace(/^www\\./,''))) {\n el.setAttribute('class', 'markdown-post-link')\n\n const tag = 'ccc'\n const author = cccMatch[2].replace('@', '')\n const permlink = sanitizePermlink(cccMatch[3])\n\n if (!isValidPermlink(permlink)) return;\n\n const inlineMeta = getInlineMeta(el, href, author, permlink)\n\n if (inlineMeta.textMatches) {\n el.textContent = `@${author}/${permlink}`\n }\n const isInline = inlineMeta.isInline\n if (forApp) {\n el.removeAttribute('href')\n\n el.setAttribute('data-href', href)\n el.setAttribute('data-is-inline', '' + isInline)\n el.setAttribute('data-tag', tag)\n el.setAttribute('data-author', author)\n el.setAttribute('data-permlink', permlink)\n } else {\n const h = `/@${author}/${permlink}`\n el.setAttribute('href', h)\n el.setAttribute('data-is-inline', '' + isInline)\n }\n addLineBreakBeforePostLink(el, forApp, isInline)\n return\n }\n\n\n const BCmatch = href.match(BITCHUTE_REGEX)\n if (BCmatch && BCmatch[1] && el.textContent.trim() === href) {\n renderPlainVideoLink(el, 'bitchute', `https://www.bitchute.com/embed/${BCmatch[1]}/`, renderOptions)\n return\n }\n\n const RBmatch = href.match(RUMBLE_REGEX)\n if (RBmatch && RBmatch[1] && el.textContent.trim() === href) {\n renderPlainVideoLink(el, 'rumble', `https://www.rumble.com/embed/${RBmatch[1]}/?pub=4`, renderOptions)\n return\n }\n\n const BNmatch = href.match(BRIGHTEON_REGEX)\n if (BNmatch && BNmatch[2] && el.textContent.trim() === href) {\n renderPlainVideoLink(el, 'brighteon', `https://www.brighteon.com/embed/${BNmatch[2]}`, renderOptions)\n return\n }\n\n // Odysee watch links. Odysee mirrors the watch path under /$/embed/, so a\n // posted video URL maps to a playable embed with no network lookup.\n const ODmatch = href.match(ODYSEE_WATCH_REGEX)\n if (ODmatch && ODmatch[1] && el.textContent.trim() === href) {\n renderPlainVideoLink(el, 'odysee', `https://odysee.com/$/embed/${ODmatch[1]}`, renderOptions)\n return\n }\n\n // If a youtube video\n let match = href.match(YOUTUBE_REGEX)\n if (match && match[1] && el.textContent.trim() === href) {\n el.setAttribute('class', 'markdown-video-link markdown-video-link-youtube')\n el.removeAttribute('href')\n\n const vid = match[1]\n const thumbnail = proxifyImageSrc(`https://img.youtube.com/vi/${vid.split('?')[0]}/hqdefault.jpg`, 0, 0, 'match')\n const embedSrc = `https://www.youtube.com/embed/${vid}?autoplay=1`\n\n el.textContent = ''\n\n el.setAttribute('data-embed-src', embedSrc);\n el.setAttribute('data-youtube', vid);\n\n //extract start time if available\n const startTime = extractYtStartTime(href);\n if(startTime){\n el.setAttribute('data-start-time', startTime);\n }\n\n if (renderOptions?.embedVideosDirectly) {\n // Waves/thread feed: embed inline but never autoplay. A feed scrolling\n // past several videos that all start playing at once is disorienting, so\n // load the player paused (no autoplay=1, no autoplay permission). The\n // click-to-play path elsewhere keeps using embedSrc via data-embed-src.\n const directSrc = `https://www.youtube.com/embed/${vid}`\n const wrapper = el.ownerDocument.createElement('span')\n wrapper.setAttribute('class', 'er-youtube-frame')\n wrapper.setAttribute('style', 'display:block')\n const iframe = el.ownerDocument.createElement('iframe')\n iframe.setAttribute('class', 'youtube-player')\n iframe.setAttribute('src', directSrc)\n iframe.setAttribute('title', 'YouTube video')\n iframe.setAttribute('allow', 'accelerometer; encrypted-media; gyroscope; picture-in-picture; web-share')\n iframe.setAttribute('allowfullscreen', '')\n wrapper.appendChild(iframe)\n el.appendChild(wrapper)\n el.setAttribute('class', 'markdown-video-link markdown-video-link-youtube er-youtube')\n } else {\n const thumbImg = el.ownerDocument.createElement('img')\n thumbImg.setAttribute('class', 'no-replace video-thumbnail')\n thumbImg.setAttribute('itemprop', 'thumbnailUrl')\n thumbImg.setAttribute('src', thumbnail)\n\n const play = el.ownerDocument.createElement('span')\n play.setAttribute('class', 'markdown-video-play')\n\n el.appendChild(thumbImg)\n el.appendChild(play)\n }\n\n return\n }\n\n // If vimeo video\n match = href.match(VIMEO_REGEX)\n if (match && match[3] && href === el.textContent) {\n el.setAttribute('class', 'markdown-video-link markdown-video-link-vimeo')\n el.removeAttribute('href')\n\n const embedSrc = `https://player.vimeo.com/video/${match[3]}`\n\n el.textContent = ''\n\n const ifr = el.ownerDocument.createElement('iframe')\n ifr.setAttribute('frameborder', '0')\n ifr.setAttribute('allowfullscreen', 'true')\n ifr.setAttribute('src', embedSrc)\n el.appendChild(ifr)\n\n return\n }\n\n // If twitch video\n match = href.match(TWITCH_REGEX)\n if (match && match[2] && href === el.textContent) {\n el.setAttribute('class', 'markdown-video-link markdown-video-link-twitch')\n el.removeAttribute('href')\n\n let embedSrc = ''\n const parent = parentDomain ? `&parent=${parentDomain}` : ''\n\n if (match[1] === undefined) {\n // No \"videos\" in URL, match[2] is the channel name\n embedSrc = `https://player.twitch.tv/?channel=${match[2]}${parent}`\n } else if (match[1] === 'videos') {\n // URL contains \"videos/\", match[2] is the video ID\n embedSrc = `https://player.twitch.tv/?video=${match[2]}${parent}`\n } else {\n // Fallback (shouldn't happen with current regex)\n embedSrc = `https://player.twitch.tv/?channel=${match[2]}${parent}`\n }\n\n el.textContent = ''\n\n const ifr = el.ownerDocument.createElement('iframe')\n ifr.setAttribute('frameborder', '0')\n ifr.setAttribute('allowfullscreen', 'true')\n ifr.setAttribute('src', embedSrc)\n el.appendChild(ifr)\n\n return\n }\n\n // If a spotify audio\n if (el.textContent.trim() === href) {\n SPOTIFY_REGEX.lastIndex = 0 // Reset regex state\n match = SPOTIFY_REGEX.exec(href)\n if (match && match[1]) {\n el.setAttribute('class', 'markdown-audio-link markdown-audio-link-spotify')\n el.removeAttribute('href')\n\n const embedSrc = `https://open.spotify.com/embed/playlist/${match[1]}`\n\n el.textContent = ''\n\n const ifr = el.ownerDocument.createElement('iframe')\n ifr.setAttribute('frameborder', '0')\n ifr.setAttribute('allowfullscreen', 'true')\n ifr.setAttribute('src', embedSrc)\n ifr.setAttribute('sandbox', 'allow-scripts allow-same-origin allow-popups')\n el.appendChild(ifr)\n\n return\n }\n }\n\n // If a Loom video\n match = href.match(LOOM_REGEX)\n if (match && match[2] && el.textContent.trim() === href) {\n el.setAttribute('class', 'markdown-video-link markdown-video-link-loom')\n el.removeAttribute('href')\n\n const embedSrc = `https://www.loom.com/embed/${match[2]}`\n\n el.textContent = ''\n\n const ifr = el.ownerDocument.createElement('iframe')\n ifr.setAttribute('frameborder', '0')\n ifr.setAttribute('allowfullscreen', 'true')\n ifr.setAttribute('src', embedSrc)\n ifr.setAttribute('sandbox', 'allow-scripts allow-same-origin allow-popups')\n el.appendChild(ifr)\n\n return\n }\n\n // If a d.tube video\n // Only d.tube links contains an image\n const imgEls = el.getElementsByTagName('img')\n\n if (imgEls.length === 1 || el.textContent.trim() === href) {\n D_TUBE_REGEX.lastIndex = 0 // Reset regex state\n match = D_TUBE_REGEX.exec(href)\n // match[2] = username, match[3] object id\n if (match && match[2] && match[3]) {\n el.setAttribute('class', 'markdown-video-link markdown-video-link-dtube')\n el.removeAttribute('href')\n\n const videoHref = `https://emb.d.tube/#!/${match[2]}/${match[3]}`\n\n // el.setAttribute('data-video-href', videoHref)\n el.setAttribute('data-embed-src', videoHref)\n\n //process thumb img element\n if (imgEls.length === 1) {\n const src = imgEls[0].getAttribute('src')\n if (src) {\n const thumbnail = proxifyImageSrc(src.replace(/\\s+/g, ''), 0, 0, 'match')\n const thumbImg = el.ownerDocument.createElement('img')\n\n thumbImg.setAttribute('class', 'no-replace video-thumbnail')\n thumbImg.setAttribute('itemprop', 'thumbnailUrl')\n\n thumbImg.setAttribute('src', thumbnail)\n el.appendChild(thumbImg)\n\n // Remove image.\n el.removeChild(imgEls[0])\n }\n } else {\n el.textContent = '';\n }\n\n const play = el.ownerDocument.createElement('span')\n play.setAttribute('class', 'markdown-video-play')\n\n el.appendChild(play)\n\n return\n }\n }\n D_TUBE_REGEX2.lastIndex = 0 // Reset regex state\n match = D_TUBE_REGEX2.exec(href)\n if (match && match[2] && match[3]) {\n // match[2] = username, match[3] object id\n el.setAttribute('class', 'markdown-video-link markdown-video-link-dtube')\n el.removeAttribute('href')\n el.textContent = '';\n\n const videoHref = `https://emb.d.tube/#!/${match[2]}/${match[3]}`\n\n // el.setAttribute('data-video-href', videoHref);\n el.setAttribute('data-embed-src', videoHref)\n const play = el.ownerDocument.createElement('span')\n play.setAttribute('class', 'markdown-video-play')\n\n el.appendChild(play)\n\n return\n }\n\n // Detect 3Speak\n match = href.match(SPEAK_REGEX)\n if (match) {\n const imgEls = el.getElementsByTagName('img')\n if (imgEls.length === 1 || el.textContent.trim() === href) {\n // match[1] / match[2] = tld , match[3] = embed address\n if ((match[1] || match[2]) && match[3]) {\n const videoHref = `https://play.3speak.tv/watch?v=${match[3]}&mode=iframe`\n el.setAttribute('class', 'markdown-video-link markdown-video-link-speak')\n el.removeAttribute('href')\n el.setAttribute('data-embed-src', videoHref)\n if (el.textContent.trim() === href) {\n el.textContent = ''\n }\n\n if (renderOptions?.embedVideosDirectly) {\n // Waves/thread feed: embed inline but never autoplay. The 3Speak\n // player autoplays by default, which is disorienting in a feed of\n // many videos, so request autoplay=false explicitly. The\n // click-to-play path elsewhere keeps using videoHref via\n // data-embed-src (autoplay after the user clicks is fine).\n const directSrc = `${videoHref}&autoplay=false`\n // Use span (not div) to avoid invalid nesting inside <p> tags\n const wrapper = el.ownerDocument.createElement('span')\n wrapper.setAttribute('class', 'er-speak-frame')\n wrapper.setAttribute('style', 'display:block')\n const iframe = el.ownerDocument.createElement('iframe')\n iframe.setAttribute('class', 'speak-iframe')\n iframe.setAttribute('src', directSrc)\n iframe.setAttribute('title', '3Speak video')\n iframe.setAttribute('allow', 'accelerometer; encrypted-media; gyroscope; picture-in-picture; web-share')\n iframe.setAttribute('allowfullscreen', '')\n wrapper.appendChild(iframe)\n el.appendChild(wrapper)\n el.setAttribute('class', 'markdown-video-link markdown-video-link-speak er-speak')\n } else {\n if (imgEls.length === 1) {\n const src = imgEls[0].getAttribute('src')\n if (src) {\n const thumbnail = proxifyImageSrc(src.replace(/\\s+/g, ''), 0, 0, 'match')\n const thumbImg = el.ownerDocument.createElement('img')\n thumbImg.setAttribute('class', 'no-replace video-thumbnail')\n thumbImg.setAttribute('itemprop', 'thumbnailUrl')\n thumbImg.setAttribute('src', thumbnail)\n el.appendChild(thumbImg)\n // Remove image.\n el.removeChild(imgEls[0])\n }\n }\n\n const play = el.ownerDocument.createElement('span')\n play.setAttribute('class', 'markdown-video-play')\n el.appendChild(play)\n }\n return\n }\n }\n }\n\n // Detect 3Speak Audio\n if (href.match(SPEAK_AUDIO_REGEX) && el.textContent.trim() === href) {\n el.setAttribute('class', 'markdown-audio-link markdown-audio-link-speak')\n el.removeAttribute('href')\n\n const embedSrc = /[?&]iframe=/.test(href) ? href : `${href}&iframe=1`\n const finalSrc = /[?&]mode=/.test(embedSrc) ? embedSrc : `${embedSrc}&mode=compact`\n\n el.textContent = ''\n\n const ifr = el.ownerDocument.createElement('iframe')\n ifr.setAttribute('frameborder', '0')\n ifr.setAttribute('src', finalSrc)\n ifr.setAttribute('sandbox', 'allow-scripts allow-same-origin allow-popups')\n el.appendChild(ifr)\n\n return\n }\n\n // Detect Liketu Speak voice posts: render the cdn.liketu.com audio file as a\n // native player. The link text is descriptive (\"Listen to the original\n // voice\"), so match on the href only, not textContent.\n if (href.match(LIKETU_AUDIO_REGEX)) {\n el.setAttribute('class', 'markdown-audio-link markdown-audio-link-liketu')\n el.removeAttribute('href')\n el.textContent = ''\n\n const audio = el.ownerDocument.createElement('audio')\n audio.setAttribute('controls', '')\n audio.setAttribute('preload', 'metadata')\n audio.setAttribute('src', href)\n el.appendChild(audio)\n\n return\n }\n\n // If tweets\n const matchT = href.match(TWITTER_REGEX)\n if (matchT && el.textContent.trim() === href) {\n TWITTER_REGEX.lastIndex = 0 // Reset for exec() after match()\n const e = TWITTER_REGEX.exec(href)\n if (e) {\n const url = stripHtmlTags(e[0])\n const author = stripHtmlTags(e[1])\n\n // Use proper DOM construction to avoid XSS from unescaped url/author\n const blockquote = el.ownerDocument.createElement('blockquote')\n blockquote.setAttribute('class', 'twitter-tweet')\n\n const p = el.ownerDocument.createElement('p')\n p.textContent = url // textContent automatically escapes\n\n const textNode = el.ownerDocument.createTextNode('- ')\n\n const a = el.ownerDocument.createElement('a')\n a.setAttribute('href', url) // setAttribute escapes automatically\n a.textContent = author // textContent automatically escapes\n\n blockquote.appendChild(p)\n blockquote.appendChild(textNode)\n blockquote.appendChild(a)\n\n if (el.parentNode) {\n el.parentNode.replaceChild(blockquote, el)\n }\n return\n }\n }\n\n if (href.indexOf('https://hivesigner.com/sign/account-witness-vote?witness=') === 0 && forApp) {\n el.setAttribute('class', 'markdown-witnesses-link')\n el.setAttribute('data-href', href)\n el.removeAttribute('href')\n return\n }\n\n if (href.indexOf('hivesigner.com/sign/update-proposal-votes?proposal_ids') >= 0 && forApp) {\n try {\n const m = decodeURI(href).match(/proposal_ids=\\[(\\d+)]/)\n if (m) {\n el.setAttribute('class', 'markdown-proposal-link')\n el.setAttribute('data-href', href)\n el.setAttribute('data-proposal', m[1])\n el.removeAttribute('href')\n return\n }\n } catch (e) {\n // Invalid URI encoding, skip processing\n }\n }\n\n // If nothing matched element as external link so it will be opened in external window\n el.setAttribute('class', 'markdown-external-link')\n\n // Prepend https if no scheme provided.\n // Case-insensitive: schemes are case-insensitive per RFC 3986, so a\n // mixed-case `Https://` must not be treated as scheme-less (which would\n // double-prepend and yield `https://Https://...`).\n if (!(/^((#)|(mailto:)|(\\/(?!\\/))|(((steem|hive|esteem|ecency|https?):)?\\/\\/))/i.test(href))) {\n href = `https://${href}`\n }\n\n if (forApp) {\n el.setAttribute('data-href', href)\n const match = href.match(YOUTUBE_REGEX)\n if (match && match[1]) {\n const vid = match[1]\n el.setAttribute('data-youtube', vid);\n\n //extract start time if available\n const startTime = extractYtStartTime(href);\n if(startTime){\n el.setAttribute('data-start-time', startTime);\n }\n }\n el.removeAttribute('href')\n } else {\n // Same-document links only. This used to match a `#` anywhere in the URL, so any\n // external link ending in `/#anything` was treated as internal: it lost\n // `rel=\"nofollow ugc noopener\"` and opened in the same tab, turning every rendered\n // page into a dofollow link farm for anyone appending a fragment.\n const matchS = href.trim().startsWith('#')\n if(matchS) {\n el.setAttribute('class', 'markdown-internal-link');\n } else {\n el.setAttribute('target', '_blank');\n el.setAttribute('rel', getExternalLinkRel(seoContext));\n }\n el.setAttribute('href', href)\n }\n}\n\n\n\n","import { ARCH_REGEX, DAPPLR_REGEX, LBRY_REGEX, TRUVVL_REGEX, ODYSEE_REGEX, SKATEHIVE_IPFS_REGEX, SKATEHYPE_EMBED_REGEX, BITCHUTE_REGEX, RUMBLE_REGEX, BRIGHTEON_REGEX, VIMEO_EMBED_REGEX, SPEAK_EMBED_REGEX, SPEAK_AUDIO_EMBED_REGEX, VIMM_EMBED_REGEX, D_TUBE_EMBED_REGEX, SPOTIFY_EMBED_REGEX, SOUNDCLOUD_EMBED_REGEX, TWITCH_EMBED_REGEX, YOUTUBE_EMBED_REGEX, BRAND_NEW_TUBE_REGEX, LOOM_EMBED_REGEX, AUREAL_EMBED_REGEX } from '../consts'\nimport { stripQueryString } from '../helper'\nimport { RenderOptions } from '../types'\n\nexport function iframe(el: HTMLElement | null, parentDomain: string = 'ecency.com', forApp: boolean = false, renderOptions?: RenderOptions): void {\n if (!el || !el.parentNode) {\n return;\n }\n const src = el.getAttribute('src');\n if (!src) {\n el.parentNode.removeChild(el);\n return;\n }\n\n // Youtube\n if (src.match(YOUTUBE_EMBED_REGEX)) {\n // strip query string (yt: autoplay=1,controls=0,showinfo=0, etc)\n el.setAttribute('src', stripQueryString(src));\n return;\n }\n\n if (src.match(BITCHUTE_REGEX)) {\n return;\n }\n\n // Vimeo\n const m = src.match(VIMEO_EMBED_REGEX);\n if (m && m.length === 2) {\n const s = `https://player.vimeo.com/video/${m[1]}`;\n el.setAttribute('src', s);\n return;\n }\n\n // Twitch\n if (src.match(TWITCH_EMBED_REGEX)) {\n let s = src;\n // Only add parent if not present\n if (!s.includes('parent=')) {\n const separator = s.includes('?') ? '&' : '?';\n s = `${s}${separator}parent=${parentDomain}`;\n }\n // Only add autoplay if not present\n if (!s.includes('autoplay=')) {\n const separator = s.includes('?') ? '&' : '?';\n s = `${s}${separator}autoplay=false`;\n }\n el.setAttribute('src', s);\n return;\n }\n\n // 3Speak\n if (src.match(SPEAK_EMBED_REGEX)) {\n // Normalize domain to play.3speak.tv for new embed player\n // Use (?:play\\.)? to avoid doubling the prefix on already-correct URLs\n let normalizedSrc = src.replace(/(?:play\\.)?3speak\\.[a-z]+/i, 'play.3speak.tv');\n\n // Normalize /embed? to /watch? for proper embed endpoint\n normalizedSrc = normalizedSrc.replace(/\\/embed\\?/, '/watch?');\n\n // Ensure mode=iframe parameter is present for minimal embed UI\n const hasMode = /[?&]mode=/.test(normalizedSrc);\n if (!hasMode) {\n normalizedSrc = `${normalizedSrc}&mode=iframe`;\n }\n\n // Waves/thread feeds embed inline (embedVideosDirectly) and must never\n // autoplay: force autoplay=false even when the src already carries\n // autoplay=true. Everywhere else, add autoplay=true only when absent so\n // an author-supplied value is preserved.\n const hasAutoplay = /[?&]autoplay=/.test(normalizedSrc);\n let s: string;\n if (renderOptions?.embedVideosDirectly) {\n s = hasAutoplay\n ? normalizedSrc.replace(/([?&]autoplay=)[^&]*/i, '$1false')\n : `${normalizedSrc}&autoplay=false`;\n } else {\n s = hasAutoplay ? normalizedSrc : `${normalizedSrc}&autoplay=true`;\n }\n\n // Add mobile layout parameter when rendering for app\n if (forApp && !/[?&]layout=/.test(s)) {\n s = `${s}&layout=mobile`;\n }\n\n el.setAttribute('src', s);\n el.setAttribute('class', 'speak-iframe');\n return;\n }\n\n // 3Speak Audio\n if (src.match(SPEAK_AUDIO_EMBED_REGEX)) {\n let normalizedSrc = src;\n\n // Ensure iframe=1 parameter for clean embedding\n if (!/[?&]iframe=/.test(normalizedSrc)) {\n normalizedSrc = `${normalizedSrc}&iframe=1`;\n }\n\n // Default to compact mode if no mode specified\n if (!/[?&]mode=/.test(normalizedSrc)) {\n normalizedSrc = `${normalizedSrc}&mode=compact`;\n }\n\n el.setAttribute('src', normalizedSrc);\n el.setAttribute('class', 'speak-audio-iframe');\n el.setAttribute('frameborder', '0');\n el.setAttribute('sandbox', 'allow-scripts allow-same-origin allow-popups');\n return;\n }\n\n // Spotify\n if (src.match(SPOTIFY_EMBED_REGEX)) {\n el.setAttribute('src', src);\n el.setAttribute('sandbox', 'allow-scripts allow-same-origin allow-popups');\n el.setAttribute('frameborder', '0');\n return;\n }\n\n // Soundcloud\n if (src.match(SOUNDCLOUD_EMBED_REGEX)) {\n const match = src.match(/url=(.+?)(?:&|$)/); // Handle & or end of string\n if (match && match[1]) {\n 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`;\n el.setAttribute('src', s);\n }\n return; // Always return, even if match fails\n }\n\n // Dtube\n if (src.match(D_TUBE_EMBED_REGEX)) {\n el.setAttribute('src', src);\n el.setAttribute('sandbox', 'allow-scripts allow-same-origin');\n el.setAttribute('frameborder', '0');\n el.setAttribute('allowfullscreen', 'true');\n return;\n }\n\n // VIMM\n if (src.match(VIMM_EMBED_REGEX)) {\n el.setAttribute('src', src);\n el.setAttribute('sandbox', 'allow-scripts allow-same-origin allow-popups');\n el.setAttribute('frameborder', '0');\n el.setAttribute('allowfullscreen', 'true');\n return;\n }\n\n // Dapplr\n if (src.match(DAPPLR_REGEX)) {\n el.setAttribute('src', src);\n el.setAttribute('sandbox', 'allow-scripts allow-same-origin');\n el.setAttribute('frameborder', '0');\n el.setAttribute('allowfullscreen', 'true');\n return;\n }\n\n // Truvvl\n if (src.match(TRUVVL_REGEX)) {\n el.setAttribute('src', src);\n el.setAttribute('sandbox', 'allow-scripts allow-same-origin allow-popups');\n el.setAttribute('frameborder', '0');\n el.setAttribute('class', 'portrait-embed');\n el.setAttribute('allowfullscreen', 'true');\n return;\n }\n\n // LBRY.tv\n if (src.match(LBRY_REGEX)) {\n el.setAttribute('src', src);\n el.setAttribute('frameborder', '0');\n return;\n }\n\n // ODYSEE\n if (src.match(ODYSEE_REGEX)) {\n el.setAttribute('src', src);\n el.setAttribute('frameborder', '0');\n return;\n }\n\n // IPFS Skatehive\n // The skatehive IPFS gateway serves the raw video file directly (content-type\n // video/mp4), so an <iframe src=…> loads a browser *media document*, which\n // Chrome autoplays on load regardless of the `allow` attribute. Render a real\n // <video controls> instead so playback is user-initiated and never autoplays\n // (the sanitizer keeps only src/controls/poster on <video>, so an autoplay\n // attribute could not survive here anyway). Same behaviour in waves and posts.\n if (src.match(SKATEHIVE_IPFS_REGEX)) {\n const video = el.ownerDocument.createElement('video');\n video.setAttribute('src', src);\n video.setAttribute('controls', '');\n el.parentNode.insertBefore(video, el);\n el.parentNode.removeChild(el);\n return;\n }\n\n // Skatehype\n if (src.match(SKATEHYPE_EMBED_REGEX)) {\n // Force https:// for http:// and protocol-relative URLs so the embed\n // isn't blocked as mixed content on the https app.\n const normalizedSrc = src.replace(/^(https?:)?\\/\\//i, 'https://');\n el.setAttribute('src', normalizedSrc);\n el.setAttribute('frameborder', '0');\n el.setAttribute('allowfullscreen', 'true');\n return;\n }\n\n // archive.org\n if (src.match(ARCH_REGEX)) {\n el.setAttribute('src', src);\n return;\n }\n\n // Rumble\n if (src.match(RUMBLE_REGEX)) {\n el.setAttribute('src', src);\n el.setAttribute('frameborder', '0');\n return;\n }\n\n // Brighteon\n if (src.match(BRIGHTEON_REGEX)) {\n el.setAttribute('src', src);\n el.setAttribute('frameborder', '0');\n return;\n }\n\n // Brandnew Tube\n if (src.match(BRAND_NEW_TUBE_REGEX)) {\n el.setAttribute('src', src);\n el.setAttribute('frameborder', '0');\n return;\n }\n\n // Loom\n if (src.match(LOOM_EMBED_REGEX)) {\n el.setAttribute('src', src);\n el.setAttribute('frameborder', '0');\n return;\n }\n\n // Aureal\n if (src.match(AUREAL_EMBED_REGEX)) {\n // Normalize protocol-relative URLs to https://\n const normalizedSrc = src.startsWith('//') ? `https:${src}` : src;\n el.setAttribute('src', normalizedSrc);\n el.setAttribute('frameborder', '0');\n return;\n }\n\n const replaceNode = el.ownerDocument.createElement('div');\n replaceNode.setAttribute('class', 'unsupported-iframe');\n replaceNode.textContent = `(Unsupported ${src})`;\n if (el.parentNode) {\n el.parentNode.insertBefore(replaceNode, el);\n el.parentNode.removeChild(el);\n }\n}\n","export function p(el: HTMLElement): void {\n const dir = el.getAttribute('dir')\n if (!dir) {\n el.setAttribute('dir', 'auto')\n }\n}\n","import { IMG_REGEX, SECTION_LIST } from '../consts'\nimport { proxifyImageSrc, getProxyBase } from '../proxify-image-src'\nimport { isValidPermlink, isValidUsername, sanitizePermlink } from \"../helper\";\nimport { createImageHTML } from \"./img.method\";\nimport { RenderOptions } from \"../types\";\n\nexport function linkify(content: string, forApp: boolean, renderOptions?: RenderOptions): string {\n // Tags\n content = content.replace(/(^|\\s|>)(#[-a-z\\d]+)/gi, tag => {\n if (/#[\\d]+$/.test(tag)) return tag // do not allow only numbers (like #1)\n const preceding = /^\\s|>/.test(tag) ? tag[0] : '' // space or closing tag (>)\n tag = tag.replace(/^>/, '') // strip the leading > we captured as the precursor\n const tag2 = tag.trim().substring(1)\n const tagLower = tag2.toLowerCase()\n\n if (!forApp) {\n // No tag route to land on -> inert span rather than a dead, crawlable /trending link.\n if (renderOptions?.inertAuthorAndTagChips) {\n return `${preceding}<span class=\"er-tag er-tag-link\">${tag.trim()}</span>`\n }\n return `${preceding}<a class=\"er-tag er-tag-link\" href=\"/trending/${tagLower}\">${tag.trim()}</a>`\n }\n return `${preceding}<a class=\"markdown-tag-link\" data-tag=\"${tagLower}\">${tag.trim()}</a>`\n })\n\n // User mentions - use placeholders for enhanced HTML to prevent image regex\n // from matching URLs inside the avatar <img src=\"...\"> attribute\n const authorPlaceholders: { placeholder: string; html: string }[] = []\n\n content = content.replace(\n /(^|[^a-zA-Z0-9_!#$%&*@@/]|(^|[^a-zA-Z0-9_+~.-/]))[@@]([a-z][-.a-z\\d^/]+[a-z\\d])/gi,\n (match, preceeding1, preceeding2, user) => {\n const userLower = user.toLowerCase()\n const preceedings = (preceeding1 || '') + (preceeding2 || '')\n if (userLower.indexOf('/') === -1 && isValidUsername(user)) {\n if (!forApp) {\n const avatarSrc = `${getProxyBase()}/u/${userLower}/avatar/small`\n const inner = `<img class=\"er-author-link-image\" src=\"${avatarSrc}\" alt=\"${userLower}\"/>@${userLower}`\n // No profile route to land on -> inert span rather than a dead, crawlable /@user link.\n const html = renderOptions?.inertAuthorAndTagChips\n ? `${preceedings}<span class=\"er-author er-author-link\">${inner}</span>`\n : `${preceedings}<a class=\"er-author er-author-link\" href=\"/@${userLower}\">${inner}</a>`\n const placeholder = `\\u200C${authorPlaceholders.length}\\u200C`\n authorPlaceholders.push({ placeholder, html })\n return placeholder\n }\n return `${preceedings}<a class=\"markdown-author-link\" data-author=\"${userLower}\">@${user}</a>`\n } else {\n return match\n }\n }\n )\n\n // internal links with category: /category/@user/permlink\n content = content.replace(\n /(^|\\s)\\/([a-z0-9-]+)\\/@([\\w.\\d-]+)\\/(\\S+)/gi, (match, preceding, tag, author, p3) => {\n const authorLower = author.toLowerCase();\n if (!isValidUsername(authorLower)) return match;\n const permlink = sanitizePermlink(p3);\n if (!isValidPermlink(permlink)) return match;\n\n if (SECTION_LIST.includes(permlink)) {\n const attrs = forApp ? `href=\"https://ecency.com/@${authorLower}/${permlink}\"` : `href=\"/@${authorLower}/${permlink}\"`\n return `${preceding}<a class=\"markdown-profile-link\" ${attrs}>@${authorLower}/${permlink}</a>`\n } else {\n const attrs = forApp ? `data-author=\"${authorLower}\" data-tag=\"${tag}\" data-permlink=\"${permlink}\"` : `href=\"/@${authorLower}/${permlink}\"`\n return `${preceding}<a class=\"markdown-post-link\" ${attrs}>@${authorLower}/${permlink}</a>`\n }\n }\n )\n\n // internal links — require leading / to distinguish /@user/permlink (Hive links)\n // from @scope/package (npm packages, GitHub orgs, etc.)\n content = content.replace(\n /((^|\\s)\\/@[\\w.\\d-]+)\\/(\\S+)/gi, (match, u, _p1, p3) => {\n const uu = u.trim().toLowerCase().replace('/@', '').replace('@', '');\n const permlink = sanitizePermlink(p3);\n if (!isValidPermlink(permlink)) return match;\n\n if (SECTION_LIST.includes(permlink)) {\n const attrs = forApp ? `href=\"https://ecency.com/@${uu}/${permlink}\"` : `href=\"/@${uu}/${permlink}\"`\n return ` <a class=\"markdown-profile-link\" ${attrs}>@${uu}/${permlink}</a>`\n } else {\n const attrs = forApp ? `data-author=\"${uu}\" data-tag=\"post\" data-permlink=\"${permlink}\"` : `href=\"/@${uu}/${permlink}\"`\n return ` <a class=\"markdown-post-link\" ${attrs}>@${uu}/${permlink}</a>`\n }\n }\n )\n\n // Image links\n // Process images before restoring author placeholders to avoid\n // the image regex matching URLs inside enhanced author HTML\n let firstImageUsed = false;\n\n content = content.replace(IMG_REGEX, (imglink) => {\n const isLCP = !firstImageUsed;\n firstImageUsed = true;\n return createImageHTML(imglink, isLCP, forApp);\n });\n\n // Restore author placeholders\n authorPlaceholders.forEach(({ placeholder, html }) => {\n content = content.replace(placeholder, html);\n });\n\n return content\n}\n","import { IMG_REGEX, YOUTUBE_REGEX, WHITE_LIST, DOMParser, POST_REGEX } from '../consts'\nimport { extractYtStartTime, isValidPermlink, isValidUsername, sanitizePermlink } from '../helper'\nimport { proxifyImageSrc } from '../proxify-image-src'\nimport { linkify } from './linkify.method'\nimport {createImageHTML} from \"./img.method\";\nimport { RenderOptions } from \"../types\";\n\nfunction hasAncestor(node: Node, tagNames: string[]): boolean {\n let current = node.parentNode\n while (current) {\n if (tagNames.includes(current.nodeName.toLowerCase())) {\n return true\n }\n current = current.parentNode\n }\n return false\n}\n\nconst CHIP_CLASSES = ['er-author-link', 'er-tag-link']\n\n/**\n * True when the node already sits inside a rendered `@user` / `#tag` chip.\n *\n * The `'a'` guard below is what normally stops a chip's own `@user` text from\n * being linkified again: traverse() recurses into the node text() inserted, so\n * without a stop condition the chip's label is re-linkified into a nested chip\n * on every pass, forever. With `RenderOptions.inertAuthorAndTagChips` the chip\n * is a `<span>`, which the tag-name guard does not catch, so match on the chip\n * classes instead. a.method.ts uses the same class-based \"already processed\"\n * signal.\n *\n * Only consulted on inert renders. `class` is author-writable (the sanitizer\n * allows it on `span` and runs *after* traverse), so a post body containing\n * `<span class=\"er-tag-link\">@alice</span>` would otherwise let an author\n * suppress linkification, and the later bare-image and video enhancements, for\n * every reader on the default render path. Gating keeps that reachable only\n * where the inert chips actually need it. Tokens are compared exactly so\n * unrelated names like `custom-er-tag-link-label` do not match.\n */\nfunction hasChipAncestor(node: Node): boolean {\n let current: Node | null = node.parentNode\n while (current) {\n const el = current as HTMLElement\n const className =\n typeof el.getAttribute === 'function' ? el.getAttribute('class') : null\n if (className && className.split(/\\s+/).some((token) => CHIP_CLASSES.includes(token))) {\n return true\n }\n current = current.parentNode\n }\n return false\n}\n\nexport function text(node: HTMLElement | null, forApp: boolean, renderOptions?: RenderOptions): void {\n if (!node || !node.parentNode) {\n return\n }\n\n // Skip text nodes inside links, inline code, or code blocks (check all ancestors)\n if (hasAncestor(node, ['a', 'code', 'pre'])) {\n return\n }\n\n // Inert chips are spans, so they need the class-based guard too. Kept behind\n // the option so the default render path is untouched — see hasChipAncestor.\n if (renderOptions?.inertAuthorAndTagChips && hasChipAncestor(node)) {\n return\n }\n\n const nodeValue = node.nodeValue || ''\n const linkified = linkify(nodeValue, forApp, renderOptions)\n if (linkified !== nodeValue) {\n const doc = DOMParser.parseFromString(\n `<span class=\"wr\">${linkified}</span>`,\n 'text/html'\n )\n const replaceNode = (doc as any).body?.firstChild || doc.firstChild\n\n if (replaceNode) {\n node.parentNode.insertBefore(replaceNode, node)\n node.parentNode.removeChild(node)\n }\n return\n }\n\n if (nodeValue.match(IMG_REGEX)) {\n const isLCP = false; // Traverse handles LCP; no need to double-count\n const imageHTML = createImageHTML(nodeValue, isLCP, forApp);\n const doc = DOMParser.parseFromString(imageHTML, 'text/html');\n const replaceNode = (doc as any).body?.firstChild || doc.firstChild\n if (replaceNode) {\n node.parentNode.replaceChild(replaceNode, node);\n }\n return; // Early return after replacing node\n }\n // If a youtube video\n if (nodeValue.match(YOUTUBE_REGEX)) {\n const e = YOUTUBE_REGEX.exec(nodeValue)\n if (e && e[1]) {\n const vid = e[1]\n const thumbnail = proxifyImageSrc(`https://img.youtube.com/vi/${vid.split('?')[0]}/hqdefault.jpg`, 0, 0, 'match')\n const embedSrc = `https://www.youtube.com/embed/${vid}?autoplay=1`\n const startTime = extractYtStartTime(nodeValue);\n\n // Create container paragraph\n const container = node.ownerDocument.createElement('p')\n\n // Create anchor element\n const anchor = node.ownerDocument.createElement('a')\n anchor.setAttribute('class', 'markdown-video-link markdown-video-link-youtube')\n anchor.setAttribute('data-embed-src', embedSrc)\n anchor.setAttribute('data-youtube', vid)\n if (startTime) {\n anchor.setAttribute('data-start-time', startTime)\n }\n\n // Create and append thumbnail image\n const thumbImg = node.ownerDocument.createElement('img')\n thumbImg.setAttribute('class', 'no-replace video-thumbnail')\n thumbImg.setAttribute('src', thumbnail)\n anchor.appendChild(thumbImg)\n\n // Create and append play button\n const play = node.ownerDocument.createElement('span')\n play.setAttribute('class', 'markdown-video-play')\n anchor.appendChild(play)\n\n // Assemble and replace\n container.appendChild(anchor)\n node.parentNode.replaceChild(container, node)\n return; // Early return after replacing node\n }\n }\n if (nodeValue && typeof nodeValue === 'string') {\n const postMatch = nodeValue.trim().match(POST_REGEX)\n if (postMatch && WHITE_LIST.includes(postMatch[1].replace(/^www\\./,''))) {\n const tag = postMatch[2]\n const author = postMatch[3].replace('@', '')\n const permlink = sanitizePermlink(postMatch[4])\n\n // Validate tag to prevent attribute breakout XSS\n // Allow only alphanumeric, hyphens, and underscores\n if (!tag || !/^[a-z0-9_-]+$/i.test(tag)) return\n if (!isValidUsername(author)) return\n if (!isValidPermlink(permlink)) return\n\n const attrs = forApp ? `data-tag=\"${tag}\" data-author=\"${author}\" data-permlink=\"${permlink}\" class=\"markdown-post-link\"` : `class=\"markdown-post-link\" href=\"/@${author}/${permlink}\"`\n const doc = DOMParser.parseFromString(\n `<a ${attrs}>/@${author}/${permlink}</a>`,\n 'text/html'\n )\n const replaceNode = (doc as any).body?.firstChild || doc.firstChild\n if (replaceNode) {\n node.parentNode.replaceChild(replaceNode, node)\n }\n }\n }\n}\n","import { a } from './a.method'\nimport { iframe } from './iframe.method'\nimport { img } from './img.method'\nimport { p } from './p.method'\nimport { text } from './text.method'\nimport { RenderOptions, SeoContext } from '../types'\n\nexport function traverse(node: Node, forApp: boolean, depth = 0, state = { firstImageFound: false }, parentDomain: string = 'ecency.com', seoContext?: SeoContext, renderOptions?: RenderOptions): void {\n if (!node || !node.childNodes) {\n return\n }\n\n // Walk siblings using nextSibling instead of indexing into the live NodeList.\n // node.childNodes is live: when a handler removes or replaces a child the\n // indices shift, causing index-based loops to skip nodes. Capturing\n // nextSibling before running handlers gives a stable \"next\" pointer that\n // isn't affected by mutations to the current child.\n let child = node.firstChild\n while (child) {\n const next = child.nextSibling\n const prev = child.previousSibling\n\n if (child.nodeName.toLowerCase() === 'a') {\n a(<HTMLElement>child, forApp, parentDomain, seoContext, renderOptions)\n }\n if (child.nodeName.toLowerCase() === 'iframe') {\n iframe(<HTMLElement>child, parentDomain, forApp, renderOptions)\n }\n if (child.nodeName === '#text') {\n text(<HTMLElement>child, forApp, renderOptions)\n }\n if (child.nodeName.toLowerCase() === 'img') {\n img(<HTMLElement>child, state, forApp)\n }\n if (child.nodeName.toLowerCase() === 'p') {\n p(<HTMLElement>child)\n }\n\n if (child.parentNode) {\n // Child is still in the DOM — recurse into it normally\n traverse(child, forApp, depth + 1, state, parentDomain, seoContext, renderOptions)\n } else {\n // Child was removed or replaced by a handler. If a replacement was\n // inserted (e.g. text() wraps a URL in <span>, a() swaps a tweet link\n // for <blockquote>), it now sits between `prev` and `next` in the live\n // childNodes. Detect it by comparing next.previousSibling to the\n // captured `prev` — if they differ a new node was inserted.\n const possibleReplacement = next ? next.previousSibling : node.lastChild\n if (possibleReplacement && possibleReplacement !== prev && possibleReplacement.parentNode === node) {\n traverse(possibleReplacement, forApp, depth + 1, state, parentDomain, seoContext, renderOptions)\n }\n }\n\n child = next\n }\n}\n","export function cleanReply(s: string): string {\n return (s ? s.split('\\n')\n .filter(item => item.toLowerCase().includes('posted using [partiko') === false)\n .filter(item => item.toLowerCase().includes('posted using [dapplr') === false)\n .filter(item => item.toLowerCase().includes('posted using [leofinance') === false)\n .filter(item => item.toLowerCase().includes('posted via [neoxian') === false)\n .filter(item => item.toLowerCase().includes('posted using [neoxian') === false)\n .filter(item => item.toLowerCase().includes('posted via [first context') === false)\n .filter(item => item.toLowerCase().includes('posted with [stemgeeks') === false)\n .filter(item => item.toLowerCase().includes('posted using [bilpcoin') === false)\n .filter(item => item.toLowerCase().includes('posted using [inleo') === false)\n .filter(item => item.toLowerCase().includes('posted using [sportstalksocial]') === false)\n .filter(item => item.toLowerCase().includes('<center><sub>[posted using aeneas.blog') === false)\n .filter(item => item.toLowerCase().includes('<center><sub>posted via [proofofbrain.io') === false)\n .filter(item => item.toLowerCase().includes('<center>posted on [hypnochain') === false)\n .filter(item => item.toLowerCase().includes('<center><sub>posted via [weedcash.network') === false)\n .filter(item => item.toLowerCase().includes('<center>posted on [naturalmedicine.io') === false)\n .filter(item => item.toLowerCase().includes('<center><sub>posted via [musicforlife.io') === false)\n .filter(item => item.toLowerCase().includes('if the truvvl embed is unsupported by your current frontend, click this link to view this story') === false)\n .filter(item => item.toLowerCase().includes('<center><em>posted from truvvl') === false)\n .filter(item => item.toLowerCase().includes('view this post <a href=\"https://travelfeed.io/') === false)\n .filter(item => item.toLowerCase().includes('read this post on travelfeed.io for the best experience') === false)\n .filter(item => item.toLowerCase().includes('posted via <a href=\"https://www.dporn.co/\"') === false)\n .filter(item => item.toLowerCase().includes('▶️ [watch on 3speak](https://3speak') === false)\n .filter(item => item.toLowerCase().includes('<sup><sub>posted via [inji.com]') === false)\n .filter(item => item.toLowerCase().includes('view this post on [liketu]') === false)\n .filter(item => {\n // Match the actual Liketu Speak boilerplate footer (both distinctive\n // parts) so a legitimate reply that merely mentions the phrase survives.\n const l = item.toLowerCase();\n return !(l.includes('posted from liketu speak') && l.includes('auto-transcrib'));\n })\n .filter(item => item.toLowerCase().includes('[via Inbox]') === false)\n .filter(item => item.toLowerCase().includes('<sub>[via apps from](') === false)\n .join('\\n') : '')\n .replace('Posted via <a href=\"https://d.buzz\" data-link=\"promote-link\">D.Buzz</a>', '')\n .replace('<div class=\"pull-right\"><a href=\"/@hive.engage\">![](https://i.imgur.com/XsrNmcl.png)</a></div>', '')\n .replace('<div><a href=\"https://engage.hivechain.app\">![](https://i.imgur.com/XsrNmcl.png)</a></div>', '')\n .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>`, '')\n}\n","import { traverse } from './traverse.method'\nimport { sanitizeHtml } from './sanitize-html.method'\nimport { moveBlockClosingTagOutOfParagraph, removeDuplicateAttributes } from '../helper'\nimport { DOMParser, XMLSerializer, ENTITY_REGEX } from '../consts'\nimport { Remarkable } from 'remarkable'\nimport { linkify } from 'remarkable/linkify'\nimport * as htmlparser2 from 'htmlparser2'\nimport * as domSerializerModule from 'dom-serializer'\nimport { RenderOptions, SeoContext } from '../types'\n\nconst domSerializer = (domSerializerModule as any).default || domSerializerModule\n\n// Conditionally load lolight for syntax highlighting (Node.js only)\n// Browser builds will gracefully handle missing lolight by using fallback\ntype Lolight = typeof import('lolight').default\nlet lolightPromise: Promise<Lolight | null> | null = null\nlet lolightModule: Lolight | null = null\n\nasync function loadLolight() {\n if (typeof window !== 'undefined') {\n // Skip in browser environment\n return null\n }\n\n if (lolightModule) {\n return lolightModule\n }\n\n if (!lolightPromise) {\n lolightPromise = import('lolight')\n .then((mod) => {\n lolightModule = mod.default || mod\n return lolightModule\n })\n .catch(() => {\n lolightModule = null\n return null\n })\n }\n\n return lolightPromise\n}\n\n// Synchronous wrapper for backward compatibility\nfunction getLolightInstance() {\n return lolightModule\n}\n\n// Pre-load lolight when module is imported (Node.js only)\nif (typeof window === 'undefined') {\n loadLolight().catch(() => {\n // Silently fail if lolight is not available\n })\n}\n\n/**\n * Fixes block-level HTML tags that Remarkable incorrectly wraps inside <p> tags.\n *\n * Problem: When Remarkable encounters block-level HTML tags (like <center>, <div>)\n * with blank lines after them, it generates malformed HTML like:\n * <p><center></p>\n * <p>content</p>\n * <p></center></p>\n *\n * This function repairs such patterns by:\n * 1. Extracting block-level tags from paragraph wrappers\n * 2. Removing empty paragraphs created by this mismatch\n *\n * @param html - The HTML string to fix\n * @returns The repaired HTML string\n */\n// Block-level tags that should never be wrapped in <p> tags. Defined at\n// module scope so the alternation string and the Set used by the\n// non-regex closing pass stay in sync.\nconst BLOCK_TAGS_ALTERNATION = 'center|div|table|figure|section|article|aside|header|footer|nav|main'\nconst BLOCK_TAGS_SET = new Set(BLOCK_TAGS_ALTERNATION.split('|'))\n\nfunction fixBlockLevelTagsInParagraphs(html: string): string {\n // Pattern 1: <p><tag></p> - opening tag wrapped in <p>\n // Replace with just <tag> (remove the wrapping <p>)\n const openingPattern = new RegExp(`<p>(<(?:${BLOCK_TAGS_ALTERNATION})(?:\\\\s[^>]*)?>)<\\\\/p>`, 'gi')\n html = html.replace(openingPattern, '$1')\n\n // Pattern 2: <p></tag></p> - closing tag wrapped in <p>\n // Replace with just </tag> (remove the wrapping <p>)\n const closingPattern = new RegExp(`<p>(<\\\\/(?:${BLOCK_TAGS_ALTERNATION})>)<\\\\/p>`, 'gi')\n html = html.replace(closingPattern, '$1')\n\n // Pattern 3: <p><tag><br> or <p><tag> at start of <p>\n // This handles cases where the tag is at the start but followed by content\n const startPattern = new RegExp(`<p>(<(?:${BLOCK_TAGS_ALTERNATION})(?:\\\\s[^>]*)?>)(?:<br>)?\\\\s*`, 'gi')\n html = html.replace(startPattern, '$1<p>')\n\n // Pattern 4: </tag></p> or <br>\\n</tag></p> - closing tag at end of <p>\n // Done as a single linear pass instead of a regex. The previous form\n // `\\s*(?:<br>)?\\s*(<\\/(?:…)>)<\\/p>` had two unanchored `\\s*`\n // quantifiers that backtracked quadratically on whitespace-heavy\n // inputs with no matching closing tag.\n html = moveBlockClosingTagOutOfParagraph(html, BLOCK_TAGS_SET)\n\n // Clean up any empty paragraphs that may have been created\n html = html.replace(/<p>\\s*<\\/p>/g, '')\n html = html.replace(/<p><br>\\s*<\\/p>/g, '')\n\n return html\n}\n\nexport function markdownToHTML(input: string, forApp: boolean, parentDomain: string = 'ecency.com', seoContext?: SeoContext, renderOptions?: RenderOptions): string {\n // Internalize leofinance.io links\n input = input.replace(new RegExp(\"https://leofinance.io/threads/view/\",\"g\"), \"/@\");\n input = input.replace(new RegExp(\"https://leofinance.io/posts/\",\"g\"), \"/@\");\n input = input.replace(new RegExp(\"https://leofinance.io/threads/\",\"g\"), \"/@\");\n input = input.replace(new RegExp(\"https://inleo.io/threads/view/\",\"g\"), \"/@\");\n input = input.replace(new RegExp(\"https://inleo.io/posts/\",\"g\"), \"/@\");\n input = input.replace(new RegExp(\"https://inleo.io/threads/\",\"g\"), \"/@\");\n\n\n const md = new Remarkable({\n html: true,\n breaks: true,\n typographer: false,\n highlight: function (str: string) {\n const lolightInstance = getLolightInstance()\n if (!lolightInstance) {\n // Fallback when lolight is not available\n return str\n }\n\n try {\n const tokens = lolightInstance.tok(str);\n return tokens.map(\n (token: string[]) => `<span class=\"ll-${token[0]}\">${token[1]}</span>`\n ).join('')\n } catch (err) { console.error(err) }\n\n return str\n }\n }).use(linkify)\n md.core.ruler.enable([\n 'abbr'\n ]);\n md.block.ruler.enable([\n 'footnote',\n 'deflist'\n ]);\n md.inline.ruler.enable([\n 'footnote_inline',\n 'ins',\n 'mark',\n 'sub',\n 'sup'\n ]);\n const serializer = new XMLSerializer()\n\n if (!input) {\n return ''\n }\n\n let output = '';\n\n // Replace entities with deterministic placeholders to preserve them during rendering\n const entities = input.match(ENTITY_REGEX);\n const entityPlaceholders: string[] = [];\n\n if (entities && forApp) {\n // Deduplicate entities to avoid duplicate placeholders\n const uniqueEntities = [...new Set(entities)];\n uniqueEntities.forEach((entity, index) => {\n // Use markdown-inert Unicode placeholder (zero-width spaces)\n const placeholder = `\\u200B${index}\\u200B`;\n entityPlaceholders.push(entity);\n // Replace all occurrences of this entity\n input = input.split(entity).join(placeholder);\n })\n }\n\n\n try {\n output = md.render(input)\n\n // Fix malformed block-level HTML tags that Remarkable wraps in <p> tags\n // This prevents \"Opening and ending tag mismatch\" errors from DOMParser\n output = fixBlockLevelTagsInParagraphs(output)\n\n const doc = DOMParser.parseFromString(`<body id=\"root\">${removeDuplicateAttributes(output)}</body>`, 'text/html')\n\n traverse(doc as any, forApp, 0, { firstImageFound: false }, parentDomain, seoContext, renderOptions)\n\n output = serializer.serializeToString(doc)\n } catch (error) {\n // @xmldom/xmldom is stricter than old xmldom and throws ParseError for malformed HTML\n // Instead of returning empty string (bad UX), attempt graceful recovery\n try {\n // Strategy:\n // 1. Pre-sanitize to remove XSS vectors\n // 2. Use lenient htmlparser2 to auto-repair malformed HTML (auto-close unclosed tags)\n // 3. Serialize the repaired HTML\n // 4. Re-parse with @xmldom/xmldom (now well-formed)\n // 5. Traverse and serialize as normal\n // Reuse the markdown output already produced before the failing\n // DOMParser pass — `md.render(input)` is the expensive step and\n // re-running it costs ~100 ms per fallback hit on a 60 KB body.\n const preSanitized = sanitizeHtml(output)\n\n // Use htmlparser2 to parse malformed HTML leniently\n const dom = htmlparser2.parseDocument(preSanitized, {\n // lenient options - don't throw on malformed HTML\n lowerCaseTags: false,\n lowerCaseAttributeNames: false,\n })\n\n // Serialize back to well-formed HTML (htmlparser2 auto-closes tags)\n const repairedHtml = domSerializer(dom.children)\n\n // Now parse the well-formed HTML with @xmldom/xmldom\n const doc = DOMParser.parseFromString(`<body id=\"root\">${removeDuplicateAttributes(repairedHtml)}</body>`, 'text/html')\n\n traverse(doc as any, forApp, 0, { firstImageFound: false }, parentDomain, seoContext, renderOptions)\n\n output = serializer.serializeToString(doc)\n } catch (fallbackError) {\n // If DOM parsing fails, sanitize the Remarkable HTML output directly.\n // This skips the traverse() image proxy/link rewriting but preserves\n // readable HTML content instead of showing escaped tags.\n output = sanitizeHtml(output || md.render(input))\n }\n }\n\n // Restore original entities from placeholders\n if (forApp && output && entityPlaceholders.length > 0) {\n entityPlaceholders.forEach((entity, index) => {\n const placeholder = `\\u200B${index}\\u200B`;\n // Replace all occurrences of the placeholder\n output = output.split(placeholder).join(entity);\n })\n }\n\n output = output\n .replace(/ xmlns=\"http:\\/\\/www.w3.org\\/1999\\/xhtml\"/g, '')\n // Strip full HTML document wrapper (native browser DOMParser wraps in <html><head><body>)\n .replace(/^<\\?xml[^?]*\\?>/, '')\n .replace(/^<!DOCTYPE[^>]*>/i, '')\n .replace(/<\\/?html[^>]*>/g, '')\n .replace(/<head[^>]*>[\\s\\S]*?<\\/head>/g, '')\n .replace('<body id=\"root\">', '')\n .replace('</body>', '')\n .trim()\n\n return sanitizeHtml(output)\n}\n","import { Remarkable } from 'remarkable'\nimport { linkify } from 'remarkable/linkify'\nimport { sanitizeHtml } from './sanitize-html.method'\n\nlet mdInstance: Remarkable | null = null\n\nfunction getMd(): Remarkable {\n if (!mdInstance) {\n mdInstance = new Remarkable({\n html: true,\n breaks: true,\n typographer: false\n }).use(linkify)\n }\n return mdInstance\n}\n\n/**\n * Lightweight markdown-to-HTML conversion with sanitization.\n * Unlike the full `markdownToHTML`, this skips Hive-specific transforms\n * (image proxying, link internalizing, DOM traversal, etc.).\n *\n * Intended for editor input (TipTap), chat messages, and other contexts\n * where simple markdown rendering is sufficient.\n */\nexport function simpleMarkdownToHTML(input: string): string {\n if (!input) return ''\n\n const html = getMd().render(input)\n return sanitizeHtml(html)\n}\n","import { LRUCache } from 'lru-cache'\n\n// A single feed page calls catchPostImage 3× per entry (blur 0×0, grid, row)\n// plus postBodySummary, so 20 entries already produce ~80 keys. The previous\n// max of 60 caused constant eviction and forced re-rendering of full markdown\n// during SSR fan-out.\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nlet cache = new LRUCache<string, any>({ max: 500 })\n\nexport function setCacheSize(size: number): void {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n cache = new LRUCache<string, any>({ max: size })\n}\n\nexport function cacheGet<T extends unknown>(key: string): T {\n return cache.get(key) as T\n}\n\nexport function cacheSet(key: string, value: unknown): void {\n cache.set(key, value)\n}\n","import { makeEntryCacheKey } from './helper'\nimport { cleanReply, markdownToHTML } from './methods'\nimport { cacheGet, cacheSet } from './cache'\nimport { Entry, RenderOptions, SeoContext } from './types'\n\n// Warn when a single markdown render exceeds this threshold. Surfaces both\n// pathological inputs (e.g. ReDoS-prone tag attributes) and merely-slow ones\n// (huge bodies hitting the xmldom fallback) so they can be triaged from\n// container logs without waiting for the SSR watchdog to kill a replica.\n//\n// Default is **Node-on, everything-else-off**. The string overload of\n// `markdown2Html` is called from comment/reply preview paths with\n// unpublished user input — warnings firing on the client would (a) leak\n// draft content into the console and any client telemetry pipeline, and\n// (b) repeat on every keystroke (the string path is uncached). Restricting\n// the default to Node specifically also keeps React Native bundles\n// (Metro/Hermes), edge runtimes (Workers, Deno, Bun) and arbitrary\n// downstream consumers silent unless they opt in.\n//\n// Opt in from any non-Node runtime by calling `setSlowRenderThresholdMs(500)`\n// during init; pass 0 to disable everywhere.\nconst isNodeRuntime =\n typeof process !== 'undefined' && typeof process?.versions?.node === 'string'\nlet slowRenderThresholdMs = isNodeRuntime ? 500 : 0\n\nexport function setSlowRenderThresholdMs(ms: number): void {\n slowRenderThresholdMs = Math.max(0, ms)\n}\n\nfunction logIfSlow(durationMs: number, context: string): void {\n if (slowRenderThresholdMs > 0 && durationMs >= slowRenderThresholdMs) {\n // Grep-friendly prefix: \"[render-helper] slow markdown render\" is a\n // unique substring that doesn't collide with anything else in the code\n // base. We intentionally do not include a content excerpt — the\n // body_len + (when available) author/permlink is enough to triage, and\n // the string overload can carry unpublished user-authored text from\n // comment/draft preview paths.\n // eslint-disable-next-line no-console\n console.warn(\n `[render-helper] slow markdown render: ${durationMs.toFixed(0)}ms ${context}`\n )\n }\n}\n\n/**\n * @param obj - Entry object or raw markdown string\n * @param forApp - Whether rendering for app context\n * @param _webp - @deprecated Ignored. Format is now handled server-side via Accept header content negotiation.\n * @param parentDomain - Parent domain for iframe embed parameters\n * @param seoContext - Optional SEO context for structured data\n * @param renderOptions - Optional rendering options (e.g. embedVideosDirectly)\n */\nexport function markdown2Html(obj: Entry | string, forApp = true, _webp = false, parentDomain: string = 'ecency.com', seoContext?: SeoContext, renderOptions?: RenderOptions): string {\n if (typeof obj === 'string') {\n const cleanedStr = cleanReply(obj)\n const t0 = performance.now()\n const res = markdownToHTML(cleanedStr, forApp, parentDomain, seoContext, renderOptions)\n logIfSlow(performance.now() - t0, `body_len=${obj.length}`)\n return res\n }\n\n // Every RenderOptions flag that changes the output must appear in the key, or\n // two callers rendering the same entry with different options serve each\n // other's HTML from cache.\n const key = `${makeEntryCacheKey(obj)}-md-${forApp ? 'app' : 'site'}-${parentDomain}${seoContext ? `-seo${seoContext.authorReputation ?? ''}-${seoContext.postPayout ?? ''}` : ''}${renderOptions?.embedVideosDirectly ? '-embed' : ''}${renderOptions?.inertAuthorAndTagChips ? '-inert' : ''}`\n\n const item = cacheGet<string>(key)\n if (item) {\n return item\n }\n\n const cleanBody = cleanReply(obj.body)\n\n const t0 = performance.now()\n const res = markdownToHTML(cleanBody, forApp, parentDomain, seoContext, renderOptions)\n logIfSlow(\n performance.now() - t0,\n `author=@${obj.author} permlink=${obj.permlink} body_len=${obj.body?.length ?? 0}`\n )\n cacheSet(key, res)\n\n return res\n}\n","import { proxifyImageSrc } from './proxify-image-src'\nimport { markdown2Html } from './markdown-2-html'\nimport { createDoc, makeEntryCacheKey, decodeImageSrc } from './helper'\nimport { cacheGet, cacheSet } from './cache'\nimport { Entry } from './types'\nimport he from 'he'\n\nconst gifLinkRegex = /\\.(gif)$/i;\n\nfunction isGifLink(link: string) {\n return gifLinkRegex.test(link);\n}\n\n// Strip code regions so that ![alt](url) inside a code block is not mistaken\n// for a real image. The full markdown renderer turns these into <pre><code>\n// with no <img>, so we mirror that behavior here.\n// - backtick fences ``` … ``` (with optional language hint)\n// - tilde fences ~~~ … ~~~ (CommonMark also accepts these)\n// - inline code `…`\n// - indented code blocks (4 spaces or a tab at line start) — over-strips\n// a little (e.g., deeply nested list continuation lines), which is fine:\n// a missed match just falls back to the full parser.\nconst BACKTICK_FENCE_RE = /```[\\s\\S]*?```/g\nconst TILDE_FENCE_RE = /~~~[\\s\\S]*?~~~/g\nconst INLINE_CODE_RE = /`[^`\\n]*`/g\nconst INDENTED_CODE_RE = /^(?: {4}|\\t).+$/gm\n// Requires a closing `)` so broken syntax like `![](url` (no close) doesn't\n// match. Also tolerates the optional title form `![](url \"title\")`. The alt-text\n// class excludes `[` (so a `![a](`/`![[[…` run can't be re-scanned at every start),\n// while the href quantifier is LENGTH-BOUNDED rather than `[`-excluding so it still\n// matches image URLs that legitimately contain a literal `[` (e.g. array query params\n// like `?w[]=600`) — the per-position scan stays capped, so it's sub-quadratic on\n// untrusted input.\nconst MD_IMAGE_RE = /!\\[[^[\\]]*\\]\\(\\s*([^)\\s]{1,2048})(?:\\s+[\"'][^\"']*[\"'])?\\s*\\)/\n// A markdown image whose URL exceeds MD_IMAGE_RE's length bound (or whose syntax is broken)\n// isn't captured by it — leaving `mdMatch` null, or (MD_IMAGE_RE is unanchored) matching a\n// *later* image instead. This linear detector (label excludes `[`; no closing `)` required)\n// still spots the uncaptured image so findFirstImageUrl can bail to the full parser rather\n// than promoting a later HTML/bare/markdown candidate over it.\nconst MD_IMAGE_PRESENT_RE = /!\\[[^[\\]]*\\]\\(\\s*[^\\s)]/\nconst HTML_IMAGE_RE = /<img\\b[^>]*?\\bsrc\\s*=\\s*[\"']([^\"']+)[\"']/i\n// A standalone (auto-linkified) image URL the renderer turns into an <img> via\n// text.method / linkify (IMG_REGEX). Required to sit at a line start or after\n// whitespace (group 1) so it is NOT a URL already inside ![](), <img src=\"\">, or\n// a [label](href) link — avoiding false positives on image-extension URLs that\n// the renderer does NOT surface as a standalone image. Same extension set as the\n// renderer's IMG_REGEX. Linear-time: one bounded char class + a single greedy\n// `+`, no nested quantifier.\nconst BARE_IMAGE_RE = /(^|\\s)(https?:\\/\\/[^\\s<>\"'()[\\]]+\\.(?:tiff?|jpe?g|gif|png|svg|ico|heic|webp|arw)(?:[?#][^\\s<>\"'()[\\]]*)?)/im\n// Markdown link `[label](href)` (NOT an image — the `!` is excluded by the\n// caller). The renderer (a.method) promotes such a link to an image only when\n// the href is an image URL AND the label text equals the href. Used to find the\n// `[url](url)` image-link cover form. Global, capture label + href.\n// Both the label and href classes exclude `[` so a run of `[`, `[a](`, or `![a](` can't be\n// re-scanned to the end of the body at every start position — linear on untrusted content.\n// Unlike the image href above, a `[`-containing URL is irrelevant here: this cover form\n// requires the label to equal the href, and an unescaped `[`/`]` in a URL breaks the label\n// match regardless — so excluding `[` loses nothing and keeps this O(1) per failed start.\nconst MD_LINK_RE = /\\[([^[\\]]*)\\]\\(\\s*([^)\\s[]+)(?:\\s+[\"'][^\"']*[\"'])?\\s*\\)/g\n// Mirrors a.method's `href.match(IMG_REGEX)` — an image URL by extension\n// (anywhere after the dot, matching the renderer). Eligibility for an avif\n// <source> is then decided separately by isPictureEligibleRawUrl.\nconst IMG_HREF_RE = /https?:\\/\\/.*\\.(?:tiff?|jpe?g|gif|png|svg|ico|heic|webp|arw)/i\n\n// The fast-path bypasses sanitize-html (which the full markdown pipeline\n// applies). The sanitizer only preserves http/https <img> sources — ftp,\n// data, javascript, relative, etc. are all dropped. Mirror that policy here\n// so the fast-path can never surface an image the full path would have\n// dropped. Anything else returns null and falls back to the sanitized parse.\nconst SAFE_URL_RE = /^https?:\\/\\//i\n\n/**\n * Fast-path: extract the first image URL from raw markdown without rendering\n * the whole post. Returns null if nothing matches *unambiguously* — when in\n * doubt, the caller falls back to the full markdown2Html → DOM parse path.\n *\n * @param includeBareUrls when true (only getEntryImageRawUrl, for the LCP\n * preload), also consider standalone bare image URLs the renderer\n * auto-linkifies into images — so a post whose first body image is a bare URL\n * (and which has no json_metadata.image thumbnail) is still discovered. The\n * default (false) keeps catchPostImage / getImage / og-image behavior\n * byte-identical.\n */\nfunction findFirstImageUrl(body: string, includeBareUrls = false): string | null {\n if (!body) return null\n const cleaned = body\n .replace(BACKTICK_FENCE_RE, '')\n .replace(TILDE_FENCE_RE, '')\n .replace(INLINE_CODE_RE, '')\n .replace(INDENTED_CODE_RE, '')\n\n const mdMatch = cleaned.match(MD_IMAGE_RE)\n const htmlMatch = cleaned.match(HTML_IMAGE_RE)\n\n // If markdown image syntax is present at all, it must be unambiguous. The\n // capture class `[^)\\s]+` excludes `)`, so a captured URL containing `(`\n // means the URL was truncated mid-paren (e.g., a real\n // `https://x.com/path_(a)_full.jpg`). When ambiguous, bail and let the full\n // markdown parser handle it — returning a truncated URL would be wrong.\n if (mdMatch) {\n const url = mdMatch[1]\n if (!url || !SAFE_URL_RE.test(url) || url.includes('(')) {\n return null\n }\n }\n // MD_IMAGE_RE is unanchored, so a markdown image can go uncaptured (URL over the length\n // bound, or broken syntax) while `mdMatch` is null OR is a *later* image. If any such\n // uncaptured image sits before what we captured (or nothing was captured), bail to the full\n // parser so it resolves the true first image rather than promoting a later HTML/bare/markdown\n // candidate.\n const priorRegion = mdMatch ? cleaned.slice(0, mdMatch.index ?? 0) : cleaned\n if (MD_IMAGE_PRESENT_RE.test(priorRegion)) {\n return null\n }\n\n // Collect valid candidates with their source position; the rendered document\n // surfaces whichever image appears first in source order.\n const candidates: { url: string; pos: number }[] = []\n if (mdMatch) candidates.push({ url: mdMatch[1], pos: mdMatch.index ?? 0 })\n if (htmlMatch && htmlMatch[1] && SAFE_URL_RE.test(htmlMatch[1])) {\n candidates.push({ url: htmlMatch[1], pos: htmlMatch.index ?? 0 })\n }\n if (includeBareUrls) {\n const bareMatch = cleaned.match(BARE_IMAGE_RE)\n if (bareMatch && bareMatch[2] && SAFE_URL_RE.test(bareMatch[2])) {\n // position of the URL itself, past the leading start/whitespace (group 1)\n candidates.push({ url: bareMatch[2], pos: (bareMatch.index ?? 0) + bareMatch[1].length })\n }\n // `[url](url)` image-link form: a markdown link the renderer promotes to an\n // image (a.method) — href is an image URL and the label text equals it.\n // Skip `![...]()` images (preceding `!`). Take the earliest such link.\n const deAmp = (s: string) => s.trim().replace(/&amp;/g, '&')\n for (const m of cleaned.matchAll(MD_LINK_RE)) {\n const idx = m.index ?? 0\n if (idx > 0 && cleaned[idx - 1] === '!') continue // it's an image ![](), handled above\n const href = m[2]\n if (href && SAFE_URL_RE.test(href) && IMG_HREF_RE.test(href) && deAmp(m[1]) === deAmp(href)) {\n candidates.push({ url: href, pos: idx })\n break\n }\n }\n }\n\n if (candidates.length === 0) return null\n candidates.sort((a, b) => a.pos - b.pos)\n return candidates[0].url\n}\n\nfunction proxifyFound(src: string, width: number, height: number, format: string): string {\n const decoded = he.decode(src)\n if (isGifLink(decoded)) {\n return proxifyImageSrc(decoded, 0, 0, format)\n }\n return proxifyImageSrc(decoded, width, height, format)\n}\n\nfunction getImage(entry: Entry, width = 0, height = 0, format = 'match'): string | null {\n /*\n * Return from json metadata if exists\n * */\n let meta: Entry['json_metadata'] | null\n\n if (typeof entry.json_metadata === 'object') {\n meta = entry.json_metadata\n } else {\n try {\n meta = JSON.parse(entry.json_metadata as string)\n } catch (e) {\n meta = null\n }\n }\n\n if (meta && typeof meta.image === 'string' && meta.image.length > 0) {\n // Decode HTML entities (e.g., &amp; -> &) before proxifying\n const decodedImage = he.decode(meta.image)\n if (isGifLink(decodedImage)) {\n return proxifyImageSrc(decodedImage, 0, 0, format)\n }\n return proxifyImageSrc(decodedImage, width, height, format)\n }\n\n if (meta && meta.image && !!meta.image.length && meta.image[0]) {\n // Only decode if it's a string, otherwise pass through to proxifyImageSrc which will return ''\n if (typeof meta.image[0] === 'string') {\n // Decode HTML entities (e.g., &amp; -> &) before proxifying\n const decodedImage = he.decode(meta.image[0])\n if (isGifLink(decodedImage)) {\n return proxifyImageSrc(decodedImage, 0, 0, format)\n }\n return proxifyImageSrc(decodedImage, width, height, format)\n }\n // For non-string types, let proxifyImageSrc handle it (returns '')\n if (isGifLink(meta.image[0])) {\n return proxifyImageSrc(meta.image[0], 0, 0, format)\n }\n return proxifyImageSrc(meta.image[0], width, height, format)\n }\n\n // Fast-path: try to find the first image with a regex over the raw body.\n // Avoids the cost of full markdown2Html + DOM parsing for the common case.\n const fast = findFirstImageUrl(entry.body)\n if (fast) {\n return proxifyFound(fast, width, height, format)\n }\n\n // Fall back to the full markdown render (handles edge cases the regex missed)\n const html = markdown2Html(entry)\n const doc = createDoc(html)\n if (!doc) {\n return null\n }\n\n const imgEls = doc.getElementsByTagName('img')\n if (imgEls.length >= 1) {\n const src = imgEls[0].getAttribute('src')\n if (!src) {\n return null\n }\n return proxifyFound(src, width, height, format)\n }\n\n return null\n}\n\n/**\n * The RAW (pre-proxify) URL of an entry's primary image, using the same\n * discovery order as catchPostImage (json_metadata.image, then the first body\n * image). Unlike catchPostImage it does NOT proxify — callers need the original\n * URL (e.g. to test picture-eligibility for an LCP preload, since catchPostImage\n * returns an already-proxified /p/ URL). Returns null when the fast path finds\n * no unambiguous image (the caller can fall back to catchPostImage).\n */\nexport function getEntryImageRawUrl(obj: Entry | string): string | null {\n // Decode with the SAME pipeline the renderer applies to the in-body <img>\n // (decodeImageSrc: entities then percent-encoding), so the LCP preload's\n // proxy hash byte-matches the body's <picture> avif <source> for &amp; /\n // %-encoded / non-ASCII cover URLs (otherwise the preload is wasted and the\n // LCP image double-downloads).\n if (typeof obj === 'string') {\n const src = findFirstImageUrl(obj, true)\n return src ? decodeImageSrc(src) : null\n }\n let meta: Entry['json_metadata'] | null\n if (typeof obj.json_metadata === 'object') {\n meta = obj.json_metadata\n } else {\n try {\n meta = JSON.parse(obj.json_metadata as string)\n } catch (e) {\n meta = null\n }\n }\n if (meta && typeof meta.image === 'string' && meta.image.length > 0) {\n return decodeImageSrc(meta.image)\n }\n if (meta && meta.image && !!meta.image.length && typeof meta.image[0] === 'string' && meta.image[0].length > 0) {\n return decodeImageSrc(meta.image[0])\n }\n const bodySrc = findFirstImageUrl(obj.body, true)\n return bodySrc ? decodeImageSrc(bodySrc) : null\n}\n\nexport function catchPostImage(obj: Entry | string, width = 0, height = 0, format = 'match'): string | null {\n if (typeof obj === 'string') {\n // Process string directly to avoid cache key collision\n // Don't create Entry wrapper as it would generate invalid cache keys\n\n // Fast-path: regex over raw markdown\n const fast = findFirstImageUrl(obj)\n if (fast) {\n return proxifyFound(fast, width, height, format)\n }\n\n const html = markdown2Html(obj)\n const doc = createDoc(html)\n if (!doc) {\n return null\n }\n\n const imgEls = doc.getElementsByTagName('img')\n if (imgEls.length >= 1) {\n const src = imgEls[0].getAttribute('src')\n if (!src) {\n return null\n }\n return proxifyFound(src, width, height, format)\n }\n\n return null\n }\n const key = `${makeEntryCacheKey(obj)}-${width}x${height}-${format}`\n\n const item = cacheGet<string | null>(key)\n if (item) {\n return item\n }\n\n const res = getImage(obj, width, height, format)\n cacheSet(key, res)\n\n return res\n}\n\n","import he from 'he'\nimport { makeEntryCacheKey, stripHtmlTags } from './helper'\nimport { cacheGet, cacheSet } from './cache'\nimport { Entry } from './types'\nimport { cleanReply } from './methods'\nimport { ENTITY_REGEX } from './consts'\nimport { Remarkable } from 'remarkable'\n\n// Reused across all calls — config is constant and Remarkable construction\n// (rule registration via ruler.enable) is non-trivial under SSR fan-out.\n//\n// linkify is intentionally omitted: the post-processing pass below strips bare\n// URLs from the final text, so auto-linking them just to discard the <a>\n// wrapper is wasted CPU during SSR.\nconst summaryRenderer = new Remarkable({\n html: true,\n breaks: true,\n typographer: false,\n})\nsummaryRenderer.core.ruler.enable(['abbr'])\nsummaryRenderer.block.ruler.enable(['footnote', 'deflist'])\nsummaryRenderer.inline.ruler.enable([\n 'footnote_inline',\n 'ins',\n 'mark',\n 'sub',\n 'sup',\n])\n\nconst joint = (arr: string[], limit = 200) => {\n let result = '';\n if (arr) {\n for (let i = 0; i < arr.length; i++) {\n // join array with space separator\n if (result) {\n result += \" \";\n }\n // break with length reaches limit\n if (result.length > limit) {\n break;\n } else {\n // make sure last join doesn't break the limit too much\n if ((result + arr[i]).length < limit + 10) {\n result += arr[i];\n } else {\n break;\n }\n }\n }\n }\n return result.trim();\n};\n\n/**\n * Generate a text summary from post body content\n * @param entryBody - The post body content to summarize\n * @param length - Maximum length of the summary (default: 200, use 0 for no truncation)\n * @param platform - Target platform: 'web' for browser/Node.js, 'ios'/'android' for React Native (default: 'web')\n * Controls entity/placeholder handling - 'web' skips placeholder substitution, other values enable it\n */\nfunction postBodySummary(entryBody: string, length: number = 200, platform:'ios'|'android'|'web' = 'web'): string {\n if (!entryBody) {\n return ''\n }\n entryBody = cleanReply(entryBody)\n\n // Replace entities with deterministic placeholders to preserve them during rendering\n const entities = entryBody.match(ENTITY_REGEX);\n const entityPlaceholders: string[] = [];\n if (entities && platform !== 'web') {\n // Deduplicate entities to avoid duplicate placeholders\n const uniqueEntities = [...new Set(entities)];\n uniqueEntities.forEach((entity, index) => {\n // Use markdown-inert Unicode placeholder (zero-width spaces)\n const placeholder = `\\u200B${index}\\u200B`;\n entityPlaceholders.push(entity);\n // Replace all occurrences of this entity\n entryBody = entryBody.split(entity).join(placeholder);\n })\n }\n\n // Convert markdown to html\n let text = '';\n try {\n text = summaryRenderer.render(entryBody)\n } catch (err) {\n // Log error with context for debugging\n console.error('[postBodySummary] Failed to render markdown:', {\n error: err instanceof Error ? err.message : String(err),\n entryBodyLength: entryBody?.length || 0,\n platform\n })\n // Set empty text on error - caller receives empty summary\n text = ''\n }\n\n\n // Restore original entities from placeholders\n if (platform !== 'web' && entityPlaceholders.length > 0) {\n entityPlaceholders.forEach((entity, index) => {\n const placeholder = `\\u200B${index}\\u200B`;\n // Replace all occurrences of the placeholder\n text = text.split(placeholder).join(entity);\n })\n }\n\n\n text = stripHtmlTags(text)\n .replace(/\\r?\\n|\\r/g, ' ') // Remove new lines\n .replace(/(?:https?|ftp):\\/\\/[\\n\\S]+/g, '') // Remove urls\n .trim()\n // Collapse runs of 2+ spaces to a single space. Equivalent to the\n // previous `' +(?= )'` form (which deleted all-but-one space in a\n // run) but matches the whole run greedily without backtracking, so\n // it stays linear on long whitespace runs.\n .replace(/ {2,}/g, ' ')\n\n // Truncate if length > 0 (length === 0 means no truncation)\n if (length > 0) {\n text = joint(text.split(' '), length)\n }\n\n if (text) {\n text = he.decode(text) // decode html entities \n }\n\n return text\n}\n\n/**\n * Generate a text summary from an Entry object or raw string\n * @param obj - Entry object or raw post body string\n * @param length - Maximum length of the summary (default: 200, use 0 for no truncation)\n * @param platform - Target platform: 'web' for browser/Node.js, 'ios'/'android' for React Native (default: 'web')\n * Controls entity/placeholder handling - 'web' skips placeholder substitution, other values enable it\n * @returns Text summary of the post body\n */\nexport function getPostBodySummary(obj: Entry | string, length?: number, platform?:'ios'|'android'|'web'): string {\n // Normalize parameters at function start for consistent behavior and caching\n const normalizedLength = length ?? 200\n const normalizedPlatform = platform || 'web'\n\n if (typeof obj === 'string') {\n return postBodySummary(obj as string, normalizedLength, normalizedPlatform)\n }\n\n const key = `${makeEntryCacheKey(obj)}-sum-${normalizedLength}-${normalizedPlatform}`\n\n const item = cacheGet<string>(key)\n if (item) {\n return item\n }\n\n const res = postBodySummary(obj.body, normalizedLength, normalizedPlatform)\n cacheSet(key, res)\n\n return res\n}\n"]}
1
+ {"version":3,"sources":["../../src/consts/white-list.const.ts","../../src/consts/section-list.const.ts","../../src/consts/regexes.const.ts","../../src/consts/allowed-attributes.const.ts","../../src/consts/embed-hosts.const.ts","../../src/consts/dom-parser.const.ts","../../src/helper.ts","../../src/methods/get-inner-html.method.ts","../../src/methods/remove-child-nodes.method.ts","../../src/proxify-image-src.ts","../../src/methods/sanitize-html.method.ts","../../src/methods/img.method.ts","../../src/methods/a.method.ts","../../src/methods/iframe.method.ts","../../src/methods/p.method.ts","../../src/methods/linkify.method.ts","../../src/methods/text.method.ts","../../src/methods/traverse.method.ts","../../src/methods/clean-reply.method.ts","../../src/methods/markdown-to-html.method.ts","../../src/methods/simple-markdown-to-html.method.ts","../../src/cache.ts","../../src/markdown-2-html.ts","../../src/catch-post-image.ts","../../src/post-body-summary.ts"],"names":["XMLDOMParser","he","p","XMLDOMSerializer","text","img","iframe","imgEls","a","match","linkify","Remarkable","LRUCache","t0","res"],"mappings":"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","file":"index.mjs","sourcesContent":["export const WHITE_LIST = [\n 'ecency.com',\n 'hive.blog',\n 'peakd.com',\n 'snapie.io',\n 'hivesuite.app',\n 'travelfeed.io',\n 'dapplr.in',\n 'leofinance.io',\n 'inleo.io',\n 'proofofbrain.io',\n 'stemgeeks.net',\n 'hiveblockexplorer.com',\n 'proofofbrain.blog',\n 'weedcash.network',\n 'dapplr.in',\n 'liketu.com',\n 'bilpcoin.com',\n 'inji.com'\n]\nexport const OLD_LIST = [\n 'busy.org',\n 'steemit.com',\n 'esteem.app',\n 'steempeak.com',\n 'partiko.app',\n 'chainbb.com',\n 'utopian.io',\n 'steemkr.com',\n 'strimi.pl',\n 'steemhunt.com',\n 'ulogs.org',\n 'hede.io',\n 'naturalmedicine.io'\n]\n","export const SECTION_LIST = [\n 'wallet',\n 'feed',\n 'followers',\n 'following',\n 'points',\n 'communities',\n 'posts',\n 'blog',\n 'comments',\n 'replies',\n 'settings',\n 'engine',\n 'permissions',\n 'referrals',\n 'payout',\n 'activities',\n 'spk',\n 'trail'\n]\n","// link regex\nexport const URL_REGEX = /(https?:\\/\\/[^\\s]+)/g\nexport const IMG_REGEX = /(https?:\\/\\/.*\\.(?:tiff?|jpe?g|gif|png|svg|ico|heic|webp|arw))(.*)/gim\nexport const ECENCY_IMG_REGEX = /https?:\\/\\/images\\.ecency\\.com\\/(?:(?:p|DQm[a-zA-Z0-9]+)\\/)?[^\\s\"'<>]+/gi\nexport const IPFS_REGEX = /^https?:\\/\\/[^/]+\\/(ip[fn]s)\\/([^/?#]+)/gim\n// Matches Hive post URLs: scheme://domain/tag/@author/permlink.\n// Both path segments are pinned to `[^/]+` (no `/`), and both ends are\n// anchored. The previous form `^https?://(.*)/(.*)/(@…)/(.*)` had three\n// `.*` quantifiers that could exchange characters, triggering\n// super-linear backtracking on adversarial hrefs. Matching is now O(n)\n// and the captured `domain`/`tag` shape is unchanged — in particular,\n// multi-segment-middle URLs like `host/foo/bar/@user/perm` still don't\n// match, preserving the old whitelist-rejection behaviour (the previous\n// greedy form put `host/foo` in capture 1, which then failed the\n// WHITE_LIST check in a.method.ts; this stricter form fails the regex\n// outright, with the same downstream outcome).\nexport const POST_REGEX = /^https?:\\/\\/([^/]+)\\/([^/]+)\\/(@[\\w.\\d-]+)\\/(.+)$/i\nexport const CCC_REGEX = /^https?:\\/\\/(.*)\\/ccc\\/([\\w.\\d-]+)\\/(.*)/i\nexport const MENTION_REGEX = /^https?:\\/\\/(.*)\\/(@[\\w.\\d-]+)$/i\nexport const TOPIC_REGEX = /^https?:\\/\\/(.*)\\/(trending|hot|created|promoted|muted|payout)\\/(.*)$/i\nexport const INTERNAL_MENTION_REGEX = /^\\/@[\\w.\\d-]+$/i\nexport const INTERNAL_TOPIC_REGEX = /^\\/(trending|hot|created|promoted|muted|payout)\\/(.*)$/i\n// Matches both internal `/tag/@author/permlink` and external\n// `https://host/tag/@author/permlink` hrefs. Group 1 must be allowed\n// to contain `/` so we keep `.+?` (lazy, anchored start). The previous\n// form `(.*)/(@…)/(.*)` was unanchored with two `.*` quantifiers, so\n// `regexp/no-super-linear-move` flagged it as quadratic on hrefs\n// without a `/@user/` substring (engine retried at every starting\n// position). The lazy + anchored variant keeps matching attempts O(n).\nexport const INTERNAL_POST_TAG_REGEX = /^(.+?)\\/(@[\\w.\\d-]+)\\/(.*)$/i\nexport const INTERNAL_POST_REGEX = /^\\/(@[\\w.\\d-]+)\\/(.*)$/i\nexport const CUSTOM_COMMUNITY_REGEX = /^https?:\\/\\/(.*)\\/c\\/(hive-\\d+)(.*)/i\nexport const YOUTUBE_REGEX = /(?:youtube\\.com\\/(?:[^\\/]+\\/.+\\/|(?:v|e(?:mbed)?)\\/|shorts\\/|.*[?&]v=)|youtu\\.be\\/)([^\"&?\\/\\s]{11})/i\nexport const YOUTUBE_EMBED_REGEX = /^(https?:)?\\/\\/www\\.youtube\\.com\\/(embed|shorts)\\/.*/i\nexport const VIMEO_REGEX = /(https?:\\/\\/)?(www\\.)?(?:vimeo)\\.com.*(?:videos|video|channels|)\\/([\\d]+)/i\nexport const VIMEO_EMBED_REGEX = /https:\\/\\/player\\.vimeo\\.com\\/video\\/([0-9]+)(?:$|[?#])/\nexport const BITCHUTE_REGEX = /^(?:https?:\\/\\/)?(?:www\\.)?bitchute\\.com\\/(?:video|embed)\\/([a-z0-9]+)/i\nexport const D_TUBE_REGEX = /(https?:\\/\\/d\\.tube\\/#!\\/v\\/)(\\w+)\\/(\\w+)/g\nexport const D_TUBE_REGEX2 = /(https?:\\/\\/d\\.tube\\/v\\/)(\\w+)\\/(\\w+)/g\nexport const D_TUBE_EMBED_REGEX = /^https:\\/\\/emb\\.d\\.tube\\/#!\\/[^/?#]+\\/[^/?#]+(?:$|[?#])/i\nexport const TWITCH_REGEX = /https?:\\/\\/(?:www\\.)?twitch\\.tv\\/(?:(videos)\\/)?([a-zA-Z0-9][\\w]{3,24})/i\nexport const DAPPLR_REGEX = /^(https?:)?\\/\\/[a-z]*\\.dapplr\\.in\\/file\\/dapplr-videos\\/.*/i\nexport const TRUVVL_REGEX = /^https?:\\/\\/embed\\.truvvl\\.com\\/(@[\\w.\\d-]+)\\/(.*)/i\nexport const LBRY_REGEX = /^(https?:)?\\/\\/lbry\\.tv\\/\\$\\/embed\\/[^?#]+(?:$|[?#])/i\nexport const ODYSEE_REGEX = /^(https?:)?\\/\\/odysee\\.com\\/(?:\\$|%24)\\/embed\\/[^?#]+(?:$|[?#])/i\n// Odysee \"watch\" URLs — the canonical form a user copies from the address bar,\n// e.g. https://odysee.com/@channel:2/video-title:e (or https://odysee.com/video-title:e\n// for a claim posted outside a channel). Odysee's embed route mirrors the watch\n// path (/$/embed/<path>), so the mapping is deterministic and needs no network\n// lookup; capture group 1 is that path.\n//\n// Two alternatives rather than one optional-channel form, because the collapsed\n// version also matches a bare channel page (/@channel:2), which is not a video.\n// The first alternative requires both segments; the second forbids a leading `@`.\n// Special routes (/$/embed, /$/download, and their %24 spellings) are excluded\n// for free: their first segment carries no `:`.\n// Each segment class excludes the URL structural characters plus quote/angle/\n// backslash, so a captured path can never break out of the attribute it is\n// written into, and excludes `:` so the `+` cannot exchange characters with the\n// following separator (keeps matching linear).\nexport const ODYSEE_WATCH_REGEX =\n /^(?:https?:)?\\/\\/odysee\\.com\\/(@[^/?#\\s:\"'<>\\\\]+:[^/?#\\s:\"'<>\\\\]+\\/[^/?#\\s:\"'<>\\\\]+:[^/?#\\s:\"'<>\\\\]+|[^@/?#\\s:\"'<>\\\\][^/?#\\s:\"'<>\\\\]*:[^/?#\\s:\"'<>\\\\]+)(?:$|[?#])/i\nexport const SKATEHIVE_IPFS_REGEX = /^https?:\\/\\/ipfs\\.skatehive\\.app\\/ipfs\\/([^/?#]+)/i\nexport const SKATEHYPE_EMBED_REGEX = /^(https?:)?\\/\\/(www\\.)?skatehype\\.com\\/ifplay\\.php\\?v=\\d+(?:$|[&#])/i\nexport const ARCH_REGEX = /^(https?:)?\\/\\/archive\\.org\\/embed\\/[^/?#]+(?:$|[?#])/i\nexport const SPEAK_REGEX = /(?:https?:\\/\\/(?:(?:play\\.)?3speak\\.([a-z]+)\\/watch\\?v=)|(?:(?:play\\.)?3speak\\.([a-z]+)\\/embed\\?v=))([A-Za-z0-9_\\-\\.\\/]+)(&.*)?/i\nexport const SPEAK_EMBED_REGEX = /^(https?:)?\\/\\/(?:play\\.)?3speak\\.([a-z]+)\\/(?:embed|watch)\\?.+$/i\nexport const SPEAK_AUDIO_REGEX = /https?:\\/\\/audio\\.3speak\\.tv\\/play\\?[^\\s]+/i\nexport const SPEAK_AUDIO_EMBED_REGEX = /^https?:\\/\\/audio\\.3speak\\.tv\\/play\\?.+$/i\n// Liketu Speak voice posts link the original audio on cdn.liketu.com (.webm etc).\n// Note: matches .webm/.mp3/.m4a/.ogg/.wav but NOT .webp image thumbnails.\nexport const LIKETU_AUDIO_REGEX = /^https?:\\/\\/cdn\\.liketu\\.com\\/.+\\.(?:webm|mp3|m4a|ogg|wav)(?:\\?.*)?$/i\nexport const TWITTER_REGEX = /(?:https?:\\/\\/(?:(?:twitter\\.com\\/(.*?)\\/status\\/(.*))))/gi\nexport const SPOTIFY_REGEX = /^https:\\/\\/open\\.spotify\\.com\\/playlist\\/(.*)?$/gi\nexport const RUMBLE_REGEX = /^https:\\/\\/rumble\\.com\\/embed\\/([a-zA-Z0-9-]+)\\/\\?pub=\\w+/\nexport const BRIGHTEON_REGEX = /^https?:\\/\\/(www\\.)?brighteon\\.com\\/(?:embed\\/)?(.*[0-9].*)/i\nexport const VIMM_EMBED_REGEX = /^https:\\/\\/www\\.vimm\\.tv\\/[^?#]+(?:$|[?#])/i\nexport const SPOTIFY_EMBED_REGEX = /^https:\\/\\/open\\.spotify\\.com\\/(embed|embed-podcast)\\/(playlist|show|episode|track|album)\\/([^/?#]+)(?:$|[?#])/i\nexport const SOUNDCLOUD_EMBED_REGEX = /^https:\\/\\/w\\.soundcloud\\.com\\/player\\/\\?[^#]+$/i\nexport const TWITCH_EMBED_REGEX = /^(https?:)?\\/\\/player\\.twitch\\.tv\\/(?:\\?[^/]+)?$/i\nexport const BRAND_NEW_TUBE_REGEX = /^https:\\/\\/brandnewtube\\.com\\/embed\\/[a-z0-9]+$/i\nexport const LOOM_REGEX = /^(https?:)?\\/\\/www\\.loom\\.com\\/share\\/([^/?#]+)(?:$|[?#])/i\nexport const LOOM_EMBED_REGEX = /^(https?:)?\\/\\/www\\.loom\\.com\\/embed\\/([^/?#]+)(?:$|[?#])/i\nexport const AUREAL_EMBED_REGEX = /^(https?:)?\\/\\/(www\\.)?(?:aureal-embed)\\.web\\.app\\/([0-9]+)(?:$|[?#])/i\nexport const ENTITY_REGEX = /&([a-z0-9]+|#[0-9]{1,6}|#x[0-9a-fA-F]{1,6});/ig\nexport const SECTION_REGEX = /\\B(\\#[\\da-zA-Z-_]+\\b)(?!;)/i\nexport const ID_WHITELIST = /^[A-Za-z][-A-Za-z0-9_]*$/\n\n","import { XSSWhiteList } from '../types'\n\nexport const ALLOWED_ATTRIBUTES: XSSWhiteList = {\n 'a': [\n 'href',\n 'target',\n 'rel',\n 'data-permlink',\n 'data-tag',\n 'data-author',\n 'data-href',\n 'data-community',\n 'data-filter',\n 'data-embed-src',\n 'data-youtube',\n 'data-start-time',\n 'data-video-href',\n 'data-proposal',\n 'data-is-inline',\n 'class',\n 'title',\n 'data-id',\n 'id'\n ],\n 'img': [\n 'src',\n 'srcset',\n 'sizes',\n 'alt',\n 'class',\n 'loading',\n 'fetchpriority',\n 'decoding',\n 'itemprop'\n ],\n // Responsive image content-negotiation wrapper emitted for web/self-hosted\n // (forApp === false). Without these entries `xss` silently collapses the\n // <picture>/<source> to a bare <img>. `source` attrs are further constrained\n // in sanitize-html (srcset must be a proxy /p/ URL; type must be avif/webp;\n // a type-less <source> is dropped post-pass).\n 'picture': [],\n 'source': ['type', 'srcset', 'sizes'],\n 'span': ['class', 'id', 'data-align'],\n 'iframe': ['src', 'class', 'frameborder', 'allowfullscreen', 'webkitallowfullscreen', 'mozallowfullscreen', 'sandbox'],\n 'video': ['src', 'controls', 'poster'],\n 'audio': ['src', 'controls', 'preload'],\n 'div': ['class', 'id', 'data-align'],\n 'strong': [],\n 'b': [],\n 'i': [],\n 'strike': [],\n 'em': [],\n 'code': [],\n 'pre': [],\n 'blockquote': ['class'],\n 'sup': [],\n 'sub': [],\n 'h1': ['dir', 'id', 'data-align'],\n 'h2': ['dir', 'id', 'data-align'],\n 'h3': ['dir', 'id', 'data-align'],\n 'h4': ['dir', 'id', 'data-align'],\n 'h5': ['dir', 'id', 'data-align'],\n 'h6': ['dir', 'id', 'data-align'],\n 'p': ['dir', 'id', 'data-align'],\n 'center': [],\n 'ul': [],\n 'ol': [],\n 'li': [],\n 'table': [],\n 'thead': [],\n 'tbody': [],\n 'tr': [],\n 'td': [],\n 'th': [],\n 'hr': [],\n 'br': [],\n 'del': [],\n 'ins': []\n}\n","// Authoritative allowlist of hosts the renderer is allowed to embed in an\n// <iframe>. This is the SAME trust boundary that iframe.method.ts and\n// a.method.ts already enforce via per-provider regexes — it is consolidated\n// here so the sanitizer (central, authoritative) and the client video\n// extensions (belt-and-suspenders) validate against ONE list instead of\n// diverging copies.\n//\n// Every host listed here is one that a.method.ts / iframe.method.ts can emit\n// as an https embed target. Subdomain-suffix tricks (play.3speak.tv.evil.com)\n// fail because we compare the parsed hostname for EXACT equality, and\n// protocol-relative / http / javascript: / data: values fail the https check.\nexport const ALLOWED_EMBED_HOSTS: ReadonlySet<string> = new Set([\n // YouTube\n 'www.youtube.com',\n 'youtube.com',\n 'www.youtube-nocookie.com',\n 'youtube-nocookie.com',\n // Vimeo\n 'player.vimeo.com',\n // Twitch\n 'player.twitch.tv',\n // DTube\n 'emb.d.tube',\n // 3Speak (video + audio)\n 'play.3speak.tv',\n '3speak.tv',\n 'audio.3speak.tv',\n // Loom\n 'www.loom.com',\n // Spotify\n 'open.spotify.com',\n // SoundCloud\n 'w.soundcloud.com',\n // BitChute\n 'www.bitchute.com',\n 'bitchute.com',\n // Rumble\n 'www.rumble.com',\n 'rumble.com',\n // Brighteon\n 'www.brighteon.com',\n 'brighteon.com',\n // VIMM\n 'www.vimm.tv',\n // BrandNewTube\n 'brandnewtube.com',\n // LBRY / Odysee\n 'lbry.tv',\n 'odysee.com',\n // Skatehive / Skatehype\n 'ipfs.skatehive.app',\n 'www.skatehype.com',\n 'skatehype.com',\n // archive.org\n 'archive.org',\n // Truvvl\n 'embed.truvvl.com',\n // Aureal\n 'aureal-embed.web.app',\n 'www.aureal-embed.web.app',\n // Dapplr (player.*.dapplr.in / *.dapplr.in) — host suffix, handled below\n])\n\n// Dapplr embeds come from arbitrary `<region>.dapplr.in` subdomains (see\n// DAPPLR_REGEX), so they need a suffix check rather than an exact-host entry.\nconst ALLOWED_EMBED_HOST_SUFFIXES: readonly string[] = ['.dapplr.in']\n\n// Per-host embed PATH requirement. Host allowlisting alone still lets a hostile\n// post point an allowed-host iframe at a non-embed path on that host (e.g. an\n// open-redirect endpoint, or a user-content page that — in an un-sandboxed\n// frame — could hijack top-navigation). For the providers whose embed URL shape\n// the renderer controls (a.method.ts), require the pathname to match that shape\n// too. Each pattern is permissive enough to pass every value the renderer\n// emits. Hosts absent from this map fall back to host-only (their embed paths\n// vary and they are not consumed by the un-sandboxed client video extensions).\nconst EMBED_HOST_PATH_PATTERNS: Record<string, RegExp> = {\n 'www.youtube.com': /^\\/embed\\//,\n 'youtube.com': /^\\/embed\\//,\n 'www.youtube-nocookie.com': /^\\/embed\\//,\n 'youtube-nocookie.com': /^\\/embed\\//,\n 'player.vimeo.com': /^\\/video\\//,\n 'player.twitch.tv': /^\\/$/, // channel/video carried in the query string\n 'emb.d.tube': /^\\/$/, // dtube carries the ref in the #! fragment\n 'play.3speak.tv': /^\\/(watch|embed)/,\n 'open.spotify.com': /^\\/embed\\//,\n 'www.loom.com': /^\\/embed\\//,\n 'www.bitchute.com': /^\\/embed\\//,\n 'bitchute.com': /^\\/embed\\//,\n 'www.rumble.com': /^\\/embed\\//,\n 'rumble.com': /^\\/embed\\//,\n 'www.brighteon.com': /^\\/embed\\//,\n 'brighteon.com': /^\\/embed\\//,\n // Odysee's embed route is /$/embed/<claim path>. Both the literal `$` and its\n // percent-encoded spelling occur in the wild: the renderer emits the literal\n // form, while Odysee's own share dialog hands out fully-encoded URLs, and\n // `URL.pathname` does not decode either. ODYSEE_REGEX accepts both for the\n // same reason.\n 'odysee.com': /^\\/(?:\\$|%24)\\/embed\\//\n}\n\n/**\n * True iff `value` is an absolute https:// URL whose host is one the renderer\n * is permitted to embed AND (for hosts with a known embed-path shape) whose\n * path matches that shape. Used to validate data-embed-src / data-video-href in\n * the sanitizer and the iframe `src` the client video extensions assign.\n *\n * Defensive: never throws (a malformed URL returns false), rejects every\n * non-https scheme (javascript:, data:, http:, protocol-relative //host),\n * compares the parsed hostname so an attacker can't smuggle an allowed host as\n * a path/query/userinfo/subdomain-suffix segment, and constrains the path so an\n * allowed host can't be aimed at a non-embed route.\n */\nexport function isAllowedEmbedSrc(value?: string | null): boolean {\n if (!value) return false\n let url: URL\n try {\n url = new URL(value.trim())\n } catch {\n return false\n }\n if (url.protocol !== 'https:') return false\n const host = url.hostname.toLowerCase()\n const hostAllowed =\n ALLOWED_EMBED_HOSTS.has(host) ||\n ALLOWED_EMBED_HOST_SUFFIXES.some(suffix => host.endsWith(suffix))\n if (!hostAllowed) return false\n const pathPattern = EMBED_HOST_PATH_PATTERNS[host]\n if (pathPattern && !pathPattern.test(url.pathname)) return false\n return true\n}\n","import { DOMParser as XMLDOMParser, XMLSerializer as XMLDOMSerializer } from '@xmldom/xmldom'\n\n// Lenient error handler for xmldom - suppresses ALL parse errors without throwing.\n// This is critical: xmldom 0.9+ throws on fatalError by default, which causes the\n// render pipeline to fall through to the HTML-escaping fallback, showing raw tags.\nfunction createParser() {\n return new XMLDOMParser({\n onError(level: string, msg: string) {\n void level\n void msg\n },\n })\n}\n\nexport const DOMParser = createParser()\n\nexport { XMLDOMSerializer as XMLSerializer }\n","import { DOMParser } from './consts'\nimport type { Document } from '@xmldom/xmldom'\nimport he from 'he'\n\n/**\n * Decode an image URL the way the renderer does before proxifying, so a URL's\n * proxy hash (base58 of the exact string) is identical whether it came from the\n * rendered <img> (img.method) or from raw discovery (getEntryImageRawUrl) — i.e.\n * the LCP preload byte-matches the in-body <picture> avif <source>. Decodes HTML\n * entities (&amp;, &#NN;, &#xNN;) then percent-encoding (%XX / non-ASCII).\n * Percent-decoding is guarded so a malformed `%` in user content can't throw\n * (callers run at SSR time).\n */\nexport function decodeImageSrc(src: string): string {\n const entityDecoded = he.decode(src)\n try {\n return decodeURIComponent(entityDecoded).trim()\n } catch {\n return entityDecoded.trim()\n }\n}\n\n/**\n * Removes duplicate attributes from HTML tags.\n * @xmldom/xmldom 0.9+ throws fatalError on duplicate attributes (e.g., <iframe allowfullscreen allowfullscreen>).\n *\n * Single-pass tokenizer. The previous regex-based implementation had\n * catastrophic backtracking on malformed inputs such as\n * <div style=background-color:yellow;\">\n * (unquoted attribute value followed by a stray quote, no closing `>` for the\n * tag in the immediate vicinity). The nested alternation\n * (?:[^>\"']+|\"[^\"]*\"|'[^']*')*?\n * combined with a greedy `+` inside the non-greedy `*?` produced O(n²+)\n * backtracking that pinned a 6 KB body for >30 seconds, tripping the watchdog\n * and killing the container.\n */\nfunction isSpaceChar(c: number): boolean {\n return c === 0x20 || c === 0x09 || c === 0x0a || c === 0x0d || c === 0x0c\n}\n\nfunction isAsciiLetter(c: number): boolean {\n return (c >= 0x41 && c <= 0x5a) || (c >= 0x61 && c <= 0x7a)\n}\n\nfunction isTagNameChar(c: number): boolean {\n return isAsciiLetter(c) || (c >= 0x30 && c <= 0x39)\n}\n\nfunction isAttrNameChar(c: number): boolean {\n // a-zA-Z, 0-9, '-', '_', ':', '.'\n return (\n isAsciiLetter(c) ||\n (c >= 0x30 && c <= 0x39) ||\n c === 0x2d ||\n c === 0x5f ||\n c === 0x3a ||\n c === 0x2e\n )\n}\n\nexport function removeDuplicateAttributes(html: string): string {\n const n = html.length\n let out = ''\n let i = 0\n\n while (i < n) {\n const lt = html.indexOf('<', i)\n if (lt < 0) {\n out += html.slice(i)\n break\n }\n out += html.slice(i, lt)\n\n // Only opening tags that start with an ASCII letter and have at least\n // one whitespace before the attributes are normalised — matches the\n // scope of the prior regex (closing tags, comments, doctypes, and bare\n // `<` characters are left untouched).\n if (lt + 1 >= n || !isAsciiLetter(html.charCodeAt(lt + 1))) {\n out += '<'\n i = lt + 1\n continue\n }\n\n let p = lt + 1\n while (p < n && isTagNameChar(html.charCodeAt(p))) p++\n const tagName = html.slice(lt + 1, p)\n\n if (p >= n || !isSpaceChar(html.charCodeAt(p))) {\n out += '<'\n i = lt + 1\n continue\n }\n\n const attrs: string[] = []\n const seen = new Set<string>()\n let q = p\n\n while (q < n) {\n while (q < n && isSpaceChar(html.charCodeAt(q))) q++\n if (q >= n) break\n\n const ch = html.charCodeAt(q)\n if (ch === 0x3e) break // '>'\n if (ch === 0x2f && q + 1 < n && html.charCodeAt(q + 1) === 0x3e) break // '/>'\n\n const nameStart = q\n while (q < n && isAttrNameChar(html.charCodeAt(q))) q++\n if (q === nameStart) {\n // Stray character that can't start an attribute name. Skip it so\n // we make progress; the original tag bytes are preserved verbatim\n // below if we ultimately can't close the tag.\n q++\n continue\n }\n const attrName = html.slice(nameStart, q)\n\n let r = q\n while (r < n && isSpaceChar(html.charCodeAt(r))) r++\n\n let valueEnd = q\n if (r < n && html.charCodeAt(r) === 0x3d /* '=' */) {\n r++\n while (r < n && isSpaceChar(html.charCodeAt(r))) r++\n if (r < n) {\n const v = html.charCodeAt(r)\n if (v === 0x22 || v === 0x27) {\n // Quoted value\n const quote = html[r]\n const end = html.indexOf(quote, r + 1)\n if (end < 0) {\n // Unterminated quote — bail to the next `>` to avoid eating\n // the rest of the document.\n const gt = html.indexOf('>', r + 1)\n valueEnd = gt < 0 ? n : gt\n } else {\n valueEnd = end + 1\n }\n } else {\n // Unquoted value: read until whitespace or `>`\n let s = r\n while (s < n) {\n const k = html.charCodeAt(s)\n if (isSpaceChar(k) || k === 0x3e) break\n s++\n }\n valueEnd = s\n }\n } else {\n valueEnd = r\n }\n }\n\n const fullAttr = html.slice(nameStart, valueEnd)\n q = valueEnd\n\n const key = attrName.toLowerCase()\n if (!seen.has(key)) {\n seen.add(key)\n attrs.push(fullAttr)\n }\n }\n\n let selfClose = false\n if (q < n && html.charCodeAt(q) === 0x2f /* '/' */) {\n selfClose = true\n q++\n }\n if (q >= n || html.charCodeAt(q) !== 0x3e /* '>' */) {\n // Unterminated tag — leave the original input alone past the `<` and\n // continue scanning. This mirrors the prior regex's behaviour of not\n // matching such fragments.\n out += '<'\n i = lt + 1\n continue\n }\n q++\n\n const attrsJoined = attrs.length > 0 ? ' ' + attrs.join(' ') : ''\n out += '<' + tagName + attrsJoined + (selfClose ? ' /' : '') + '>'\n i = q\n }\n\n return out\n}\n\nexport function createDoc(html: string): Document | null {\n if (html.trim() === '') {\n return null\n }\n\n // Preprocess to remove duplicate attributes which cause @xmldom/xmldom 0.9+ to throw fatalError\n const cleanedHtml = removeDuplicateAttributes(html)\n\n // Wrap in body tag to handle multiple root elements\n // This is needed because markdownToHTML can generate multiple top-level elements\n // (e.g., <center>...</center><hr />) which DOMParser doesn't accept without a wrapper\n // Using <body> instead of <div> prevents conflicts with <div> elements in the content\n //\n // @xmldom/xmldom 0.9+ always throws a ParseError from its internal fatalError() path\n // (see dom-parser.js:490) for severely malformed HTML — e.g., mismatched tags like\n // <body>...<p>...</body> — regardless of the onError handler returning undefined.\n // The onError handler only gets to observe; the throw still happens.\n //\n // Wrap in try/catch so that pathologically-malformed post bodies degrade gracefully\n // (no image preload hint) instead of crashing the SSR render of /entry/[...]. Both\n // callers in catch-post-image.ts already handle a null return.\n try {\n return DOMParser.parseFromString(`<body>${cleanedHtml}</body>`, 'text/html')\n } catch {\n return null\n }\n}\n\nexport function makeEntryCacheKey(entry: any): string {\n return `${entry.author}-${entry.permlink}-${entry.last_update}-${entry.updated}`\n}\n\n/**\n * Linear-time HTML-tag stripper. Replaces the regex\n * /(<([^>]+)>)/gi\n * which `regexp/no-super-linear-move` flags as quadratic on inputs with\n * many `<`s that never close. Mirrors the regex's behaviour: matches\n * `<tag...>` with at least one character between the angle brackets and\n * removes it, but leaves bare `<` (with no `>` to close it) and `<>`\n * (empty content) in place.\n */\nexport function stripHtmlTags(s: string): string {\n const n = s.length\n let out = ''\n let i = 0\n while (i < n) {\n const lt = s.indexOf('<', i)\n if (lt < 0) {\n out += s.slice(i)\n break\n }\n out += s.slice(i, lt)\n const gt = s.indexOf('>', lt + 1)\n if (gt < 0) {\n // Unclosed `<` — original regex required a `>` to match, so keep\n // the remaining text intact.\n out += s.slice(lt)\n break\n }\n if (gt === lt + 1) {\n // `<>` empty — original `[^>]+` required at least one inner char,\n // so preserve the literal `<>`.\n out += s.slice(lt, gt + 1)\n i = gt + 1\n continue\n }\n i = gt + 1\n }\n return out\n}\n\n/**\n * Linear-time trailing-`/` strip. Replaces the regex\n * /\\/+$/\n * which `regexp/no-super-linear-move` flags as quadratic on inputs\n * that end in a long run of slashes followed by anything else (the\n * engine retries at every starting position).\n */\nexport function trimTrailingSlash(s: string): string {\n let end = s.length\n while (end > 0 && s.charCodeAt(end - 1) === 0x2f /* '/' */) end--\n return s.slice(0, end)\n}\n\n/**\n * Linear-time query-string strip. Replaces the regex\n * /\\?.+$/\n * with a simple `indexOf` + `slice`. Matches the regex's behaviour:\n * strips only if `?` exists *and* at least one character follows it\n * (`?` at end-of-string leaves the input unchanged).\n */\nexport function stripQueryString(s: string): string {\n const q = s.indexOf('?')\n return q >= 0 && q < s.length - 1 ? s.slice(0, q) : s\n}\n\n// HTML ASCII whitespace per WHATWG/HTML spec\n// (https://infra.spec.whatwg.org/#ascii-whitespace):\n// U+0009 TAB, U+000A LF, U+000C FF, U+000D CR, U+0020 SPACE.\n// Narrower than JS regex `\\s` (which also matches U+000B VT, NBSP,\n// the U+2000–U+200A run, U+2028/U+2029, U+202F, U+205F, U+3000, BOM).\n// See `moveBlockClosingTagOutOfParagraph` below for the rationale.\nfunction isHtmlWhitespace(c: number): boolean {\n return c === 0x20 || c === 0x09 || c === 0x0a || c === 0x0d || c === 0x0c\n}\n\n/**\n * Linear-time replacement for the `endPattern` regex in\n * `markdown-to-html.method.ts`:\n *\n * /(?:\\s*<br>)?\\s*(<\\/(?:tagA|tagB|…)>)<\\/p>/gi → '</p>$1'\n *\n * Anchors on `</p>` (rare, found via `indexOf`), checks that the\n * character immediately before is `>`, walks back to find the matching\n * `</tag…>`, and — if `tag` is one of the configured block tags —\n * rewrites the run to `</p></tag…>` while stripping any preceding\n * HTML-ASCII-whitespace + optional `<br>` + more HTML-ASCII-whitespace.\n *\n * The regex form had two unanchored `\\s*` quantifiers that\n * `regexp/no-super-linear-move` flagged as quadratic on whitespace-heavy\n * inputs without a matching closing tag (engine retried at every\n * starting position). This pass is O(n).\n *\n * **Intentional divergence from the regex's `\\s` class.** The regex\n * stripped JS-regex whitespace (which includes U+000B VT, NBSP, em\n * space, etc.); this helper only strips HTML-spec ASCII whitespace.\n * Markdown→HTML output doesn't insert those characters around `<br>`\n * in practice, so the behavioural difference is theoretical; when it\n * does happen the worst-case outcome is suboptimal HTML (a block\n * closing tag stays inside `<p>`), not invalid HTML or a security\n * issue. Aligning the whitespace class with the HTML spec is a\n * deliberate correctness choice, not an oversight — if a future\n * regression test wants exact `\\s` parity, expand `isHtmlWhitespace`\n * accordingly.\n */\nexport function moveBlockClosingTagOutOfParagraph(html: string, blockTags: Set<string>): string {\n const n = html.length\n let out = ''\n let i = 0\n\n while (i < n) {\n const pStart = html.indexOf('</p>', i)\n if (pStart < 0) {\n out += html.slice(i)\n break\n }\n\n // The closing block tag must end immediately before `</p>` (i.e. the\n // char before `</p>` is `>`). Anything else means there's nothing\n // for this pass to do at this position.\n if (pStart === i || html.charCodeAt(pStart - 1) !== 0x3e /* '>' */) {\n out += html.slice(i, pStart + 4)\n i = pStart + 4\n continue\n }\n\n // Find the matching `</` for that closing `>`. Worst-case scans\n // back to the previous match boundary `i` when the run before\n // `</p>` contains no `</`; total work across the whole input is\n // still amortised O(n) because each character is visited at most\n // twice (once forward by `indexOf`, once backward here).\n const closingStart = html.lastIndexOf('</', pStart - 2)\n if (closingStart < i) {\n out += html.slice(i, pStart + 4)\n i = pStart + 4\n continue\n }\n const tagName = html.slice(closingStart + 2, pStart - 1).toLowerCase()\n if (!blockTags.has(tagName)) {\n out += html.slice(i, pStart + 4)\n i = pStart + 4\n continue\n }\n\n // Walk back from `closingStart` over whitespace, optionally one\n // `<br>`, and more whitespace — mirroring the regex's stripping\n // semantics exactly.\n let k = closingStart\n while (k > i && isHtmlWhitespace(html.charCodeAt(k - 1))) k--\n if (k - 4 >= i && html.slice(k - 4, k).toLowerCase() === '<br>') {\n k -= 4\n while (k > i && isHtmlWhitespace(html.charCodeAt(k - 1))) k--\n }\n\n out += html.slice(i, k) + '</p>' + html.slice(closingStart, pStart)\n i = pStart + 4\n }\n\n return out\n}\n\nexport function extractYtStartTime(url:string):string {\n try {\n const urlObj = new URL(url);\n const params = new URLSearchParams(urlObj.search);\n if(params.has('t')){\n const t = params.get('t');\n return '' + parseInt(t || '0'); //parsing is important as sometimes t is famated '123s';\n }else if (params.has('start')){\n return params.get('start') || '';\n }\n return '';\n } catch (error) {\n return '';\n }\n}\nexport function sanitizePermlink(permlink: string): string {\n if (!permlink || typeof permlink !== 'string') {\n return ''\n }\n\n const [withoutQuery] = permlink.split('?')\n const [cleaned] = withoutQuery.split('#')\n\n return cleaned\n}\n\nexport function isValidPermlink(permlink: string): boolean {\n const sanitized = sanitizePermlink(permlink)\n\n if (!sanitized) {\n return false\n }\n\n // Should not contain image extensions, query params, or fragments\n const isImage = /\\.(jpg|jpeg|png|webp|gif|svg)$/i.test(sanitized)\n const isCleanFormat = /^[a-z0-9-]+$/.test(sanitized) // Hive standard\n\n return isCleanFormat && !isImage\n}\n\n// Reference: https://en.wikipedia.org/wiki/Domain_Name_System#Domain_name_syntax\n// Hive account names must follow similar rules to DNS (RFC 1035)\nconst LABEL_REGEX = /^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/;\n\nexport function isValidUsername(username: string): boolean {\n if (!username || typeof username !== 'string') return false;\n if (username.length > 16) return false;\n\n const labels = username.split('.');\n\n return labels.every(label => {\n return (\n label.length >= 3 &&\n label.length <= 16 &&\n /^[a-z]/.test(label) && // must start with a letter\n LABEL_REGEX.test(label) && // a-z0-9, hyphens, no start/end hyphen\n !label.includes('..') // double dots are impossible after split, but just in case\n );\n });\n}\n\n\n\n","import { XMLSerializer } from '../consts'\n\nexport function getSerializedInnerHTML(node: Node): string {\n const serializer = new XMLSerializer()\n\n if (node.childNodes[0]) {\n // xmldom's ChildNode isn't structurally assignable to its Node param type; it is a Node.\n return serializer.serializeToString(node.childNodes[0] as any)\n }\n\n return ''\n}\n","export function removeChildNodes(node: Node): void {\n // Remove children using stable snapshot to avoid live collection issues\n while (node.firstChild) {\n node.removeChild(node.firstChild)\n }\n}\n","import querystring from 'querystring'\nimport { LRUCache } from 'lru-cache'\n\nlet proxyBase = 'https://i.ecency.com'\n\n// base58 encoding of the source URL is the dominant cost in proxifyImageSrc.\n// The same URL is encoded repeatedly: once per srcset width (5×), once per\n// image size variant (blur/grid/row), and across requests (trending posts\n// repeat). Caching by URL collapses all of those to a single encode.\nconst urlHashCache = new LRUCache<string, string>({ max: 500 })\n\nconst BASE58_ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'\n\n// base58btc, byte-for-byte what multihashes' toB58String produced (that function was\n// `bs58.encode` behind a Buffer type-check — no multihash prefix). Inlined because the\n// Buffer it demanded is a Node global: bundlers that do not shim it (the self-hosted\n// blog SPA's, for one) shipped a `Buffer is not defined` crash into the browser on any\n// post carrying an image. The output is the image proxy's cache key and appears in\n// every image URL, so it must not change; proxify-image-src.spec.ts pins it.\nfunction base58Encode(bytes: Uint8Array): string {\n if (bytes.length === 0) return ''\n const digits: number[] = [0]\n for (let i = 0; i < bytes.length; i++) {\n let carry = bytes[i]\n for (let j = 0; j < digits.length; j++) {\n carry += digits[j] << 8\n digits[j] = carry % 58\n carry = (carry / 58) | 0\n }\n while (carry > 0) {\n digits.push(carry % 58)\n carry = (carry / 58) | 0\n }\n }\n let out = ''\n // Each leading zero byte encodes as a literal '1' rather than as a digit.\n for (let k = 0; k < bytes.length && bytes[k] === 0; k++) out += BASE58_ALPHABET[0]\n for (let q = digits.length - 1; q >= 0; q--) out += BASE58_ALPHABET[digits[q]]\n return out\n}\n\nfunction utf8Bytes(url: string): Uint8Array {\n // TextEncoder is standard in browsers and Node >= 11; Buffer stays as the fallback so\n // any runtime without it (older React Native) keeps the behaviour it has today.\n if (typeof TextEncoder !== 'undefined') return new TextEncoder().encode(url)\n return Uint8Array.from(Buffer.from(url, 'utf8'))\n}\n\nfunction getUrlHash(url: string): string {\n const cached = urlHashCache.get(url)\n if (cached) return cached\n const hash = base58Encode(utf8Bytes(url))\n urlHashCache.set(url, hash)\n return hash\n}\n\nexport function setProxyBase(p: string): void {\n proxyBase = p\n}\n\nexport function getProxyBase(): string {\n return proxyBase\n}\n\n// The image proxy's own /p/ route, on the active base and the legacy\n// images.ecency.com origin (the base before the i.ecency.com SNI migration).\n// Recognizing both lets a transform on an already-proxified URL reuse the\n// existing hash instead of re-encoding the whole URL into a proxy-of-a-proxy.\nconst PROXY_P_PREFIXES = (): string[] => [`${proxyBase}/p/`, 'https://images.ecency.com/p/']\n\nexport function extractPHash(url: string): string | null {\n const prefix = PROXY_P_PREFIXES().find((p) => url.startsWith(p))\n if (prefix) {\n const [hash] = url.slice(prefix.length).split('?')\n return hash.replace(/\\.(webp|png)$/,'')\n }\n return null\n}\n\nexport function isValidUrl(url: string): boolean {\n try {\n return Boolean(new URL(url));\n }\n catch(e){\n return false;\n }\n}\n\n/**\n * Longest image URL we will base58-encode. See the guard in proxifyForFormat:\n * the encoder is quadratic, so this bounds per-render CPU on user-authored\n * input. Observed maximum in real post bodies is ~234 characters.\n */\nconst MAX_PROXIED_URL_LENGTH = 2048\n\n/**\n * A legacy foreign SIZED proxy URL: `images.hive.blog/<WxH>/<inner>` or the\n * steemitimages equivalent — the only shape that carries a nested source URL\n * for getLatestUrl to unwrap.\n *\n * Deliberately narrower than {@link isLegacyForeignProxyUrl}: other non-`/D`\n * paths on those hosts (notably their own `/p/<hash>` proxy route) name a hash\n * in a foreign hash space, so routing them through our `/p/` would proxy a\n * proxy, and their content type is genuinely unknown.\n *\n * Shared by the proxify routing and the `<picture>` eligibility gate so the two\n * cannot disagree about which URLs reach the /p/ route.\n */\nconst LEGACY_SIZED_PROXY_RE = /^https:\\/\\/(?:images\\.hive\\.blog|steemitimages\\.com)\\/\\d+x\\d+\\/(.+)$/\n\nexport function isLegacySizedProxyUrl(url?: string): boolean {\n if (!url || typeof url !== 'string') return false\n return LEGACY_SIZED_PROXY_RE.test(url)\n}\n\n/**\n * The nested source of a legacy sized proxy URL — everything after the `<WxH>/`\n * segment, query string included — or null when the URL is not that shape.\n *\n * Positional, not a search for the last `http(s)://`: the nested source may\n * itself carry a URL-valued query parameter, and picking the last URL in the\n * string would resolve to that parameter's target instead of the image.\n *\n * Normalised exactly the way the imagehoster's legacy handler does it, because\n * both sides base58-encode this string and any divergence means two different\n * hashes for the same image: parse the path segment (trailing slashes stripped)\n * as a URL, then re-attach the query through searchParams — which percent-\n * encodes a URL-valued parameter — and re-serialise.\n */\nfunction extractLegacySizedSource(url: string): string | null {\n const m = LEGACY_SIZED_PROXY_RE.exec(url)\n if (!m) return null\n\n // Drop the fragment FIRST, and before splitting off the query. A browser\n // never sends anything from the first '#' onward, so the imagehoster resolves\n // `…/image.png` and `…/image.png#frag` to one hash; keeping it here would\n // mint a separate proxy hash — and therefore a separate CDN entry — per\n // fragment, letting arbitrary `#…` variants miss an already-cached image.\n // Order matters too: a '?' inside a fragment (`…/image.png#a?b=c`) is part of\n // the fragment, so splitting on '?' first would invent a query from it.\n const rest = m[1]\n const hashIndex = rest.indexOf('#')\n const addressable = hashIndex >= 0 ? rest.slice(0, hashIndex) : rest\n\n const qIndex = addressable.indexOf('?')\n const path = qIndex >= 0 ? addressable.slice(0, qIndex) : addressable\n const query = qIndex >= 0 ? addressable.slice(qIndex + 1) : ''\n\n // Trailing slashes are trimmed with a scan, not /\\/+$/: post bodies are\n // user-authored, so a crafted URL ending in thousands of slashes would make\n // that regex backtrack quadratically on every render, including SSR.\n let end = path.length\n while (end > 0 && path.charCodeAt(end - 1) === 47 /* '/' */) {\n end--\n }\n\n try {\n const inner = new URL(path.slice(0, end))\n if (query) {\n // append, not set: the handler preserves repeated keys\n for (const [key, value] of new URLSearchParams(query)) {\n inner.searchParams.append(key, value)\n }\n }\n return inner.toString()\n } catch {\n return null\n }\n}\n\n/**\n * Any legacy foreign proxy URL that has historically been served by swapping\n * the hostname onto our proxy base. Kept broad on purpose — this is the\n * long-standing behaviour for these hosts and narrowing it is out of scope.\n * `/D…` (stored upload) URLs are excluded: those go through the normal /p/\n * path so they can be resized and format-negotiated.\n */\nfunction isLegacyForeignProxyUrl(url: string): boolean {\n return (\n (url.indexOf('https://images.hive.blog/') === 0 && url.indexOf('https://images.hive.blog/D') !== 0) ||\n (url.indexOf('https://steemitimages.com/') === 0 && url.indexOf('https://steemitimages.com/D') !== 0)\n )\n}\n\nexport function getLatestUrl(str: string): string {\n const [last] = [...str.replace(/https?:\\/\\//g, '\\n$&').trim().split('\\n')].reverse()\n return last\n}\n\nexport interface ProxifyOptions {\n /**\n * Request a tiny blurred LQIP placeholder. The proxy resizes to ~20px and\n * gaussian-blurs it (a few hundred bytes), for use behind the real image\n * while it loads.\n */\n blur?: boolean\n /**\n * Route on-host uploads through the /p/ proxy even when no width/height is\n * requested, so the server still negotiates WebP/AVIF via the Accept header\n * (instead of streaming the original bytes from direct-serve). Use for\n * displayed `<img>` sources; leave off for OG/social images, where the\n * original format is safest.\n */\n forceProxy?: boolean\n}\n\n// Internal format-aware proxify. The public proxifyImageSrc (below) locks the\n// format to 'match' (Accept-negotiated at the origin). Explicit per-format\n// variants (avif/webp) for <picture> are built via this + buildSrcSetForFormat,\n// which keep the chosen format in the URL — cache-safe behind a CDN that does\n// NOT vary its cache on the Accept header (so the negotiated variant can't be\n// cross-served to a client that requested a different one).\nfunction proxifyForFormat(\n url?: string,\n width = 0,\n height = 0,\n format = 'match',\n opts: ProxifyOptions = {}\n) {\n if (!url || typeof url !== 'string' || !isValidUrl(url)) {\n return ''\n }\n\n // base58 encoding is quadratic in the input length, and post bodies are\n // user-authored: a single crafted 60KB image URL costs ~12.6s of CPU per\n // render, on the SSR path. Real image URLs are nowhere near this — across 374\n // in-body URLs from 60 live posts the longest was 234 characters — so cap it\n // with generous headroom and treat anything longer as unusable, exactly like\n // a malformed URL. Applies to every shape, including the legacy sized route\n // that previously short-circuited to a hostname swap before any hashing.\n if (url.length > MAX_PROXIED_URL_LENGTH) {\n return ''\n }\n\n // The /p/ route is the only one that transforms (resize/blur) or negotiates\n // WebP/AVIF; the direct-serve route streams the stored original bytes as-is.\n // Route through /p/ when a transform is requested, or when the caller opts in\n // to format negotiation on an otherwise-unsized image (forceProxy). Otherwise\n // keep the lightweight hostname-swap — no proxy self-fetch, original format\n // preserved (which matters for OG/social where AVIF may be unsupported).\n const routeThroughProxy = width > 0 || height > 0 || !!opts.blur || !!opts.forceProxy\n\n // Legacy sized proxy URLs (`images.hive.blog/<WxH>/<inner>`, same for\n // steemitimages). The bare hostname swap keeps them on our own domain but\n // lands on the direct-serve route, which the imagehoster answers with a 301\n // to the /p/ form. Two costs: the extra round trip, and the redirect carries\n // the width baked into the URL path (`.../1536x0/...` -> `width=1536`) rather\n // than the width the caller asked for — so a 600px thumbnail was served the\n // 1536px rendition (measured on a real post photo: 17,027 bytes via the\n // redirect vs 3,316 bytes going straight to /p/ at width=600).\n //\n // The redirect target is the hash of the INNER source URL — the imagehoster\n // unwraps the nested URL itself (verified: its Location header is byte-equal\n // to the /p/ URL this function now returns). So routing here directly changes\n // no image identity and no cache entry: if the inner source is gone, both\n // paths fall back to the same placeholder.\n //\n // So keep the swap only when nothing is being requested of the proxy (OG and\n // social images, where the original format is safest). Once a transform or\n // format negotiation is wanted, fall through: getLatestUrl() unwraps the\n // nested source URL, so the image is fetched from its origin through our own\n // /p/ route in one hop, resized, and format-negotiated.\n // Only the sized `<WxH>/<inner>` shape changes: it falls through to /p/ once\n // something is actually asked of the proxy. Every other legacy foreign URL\n // keeps the hostname swap exactly as before, transform or not.\n if (isLegacyForeignProxyUrl(url) && !(isLegacySizedProxyUrl(url) && routeThroughProxy)) {\n return url\n .replace('https://images.hive.blog', proxyBase)\n .replace('https://steemitimages.com', proxyBase)\n }\n\n // Legacy on-chain content embeds images.ecency.com URLs directly. With no\n // transform or format negotiation requested, re-point them to the active\n // proxy base — the same imagehoster backend, just an SNI-resilient hostname\n // (some ISPs, e.g. Virgin Media UK, SNI-filter the images.ecency.com\n // hostname) — and serve the stored bytes directly (no proxy self-fetch).\n // Otherwise fall through to the /p/ proxy: the bare hostname swap yields a\n // direct-serve URL that ignores ?width / ?blur and does no WebP/AVIF\n // negotiation, shipping the full-size original in its original format.\n if (url.indexOf('https://images.ecency.com/') === 0 && !routeThroughProxy) {\n return url.replace('https://images.ecency.com', proxyBase)\n }\n\n // For a legacy sized URL take everything after the `<WxH>/` segment verbatim.\n // getLatestUrl() picks the LAST http(s):// substring anywhere in the string,\n // so a nested source carrying a URL-valued query parameter\n // (`/60x70/http://host/image.png?redirect=https://other/x.png`) would resolve\n // to the parameter's URL instead of the image. The imagehoster extracts the\n // path segment and keeps the query — verified against its Location header —\n // so match that exactly or the two disagree about which image this is.\n const realUrl = extractLegacySizedSource(url) ?? getLatestUrl(url)\n const pHash = extractPHash(realUrl)\n\n const options: Record<string, string | number> = {\n format,\n mode: 'fit',\n }\n\n if (width > 0) {\n options.width = width\n }\n\n if (height > 0) {\n options.height = height\n }\n\n if (opts.blur) {\n options.blur = 1\n }\n\n const qs = querystring.stringify(options)\n\n if (pHash) {\n return `${proxyBase}/p/${pHash}?${qs}`\n }\n\n const b58url = getUrlHash(realUrl.toString())\n\n return `${proxyBase}/p/${b58url}?${qs}`\n}\n\n/**\n * @param _format - @deprecated Ignored. The public API always requests 'match'\n * so the origin negotiates WebP/AVIF via the Accept header. Explicit per-format\n * renditions (for `<picture>`) are built via buildSrcSetForFormat /\n * buildPictureSources, which keep the format in the URL (cache-safe behind a CDN\n * that ignores Accept).\n */\nexport function proxifyImageSrc(\n url?: string,\n width = 0,\n height = 0,\n _format = 'match',\n opts: ProxifyOptions = {}\n) {\n return proxifyForFormat(url, width, height, 'match', opts)\n}\n\n// Widths chosen to align with sizes already cached by the image proxy\n// (600 used by OG/deck thumbnails, 800 by self-hosted thumbnails)\nconst SRCSET_WIDTHS = [320, 600, 800, 1024, 1280];\n\n/**\n * Builds a srcset string with multiple width variants for responsive images.\n * Uses the image proxy's width parameter to serve appropriately sized images.\n * Format is locked to 'match' (Accept-negotiated) — see buildSrcSetForFormat\n * for explicit per-format renditions.\n */\nexport function buildSrcSet(url?: string): string {\n return buildSrcSetForFormat(url, 'match');\n}\n\n/**\n * Like buildSrcSet but pins an explicit output format in the URL (avif/webp/\n * match). Used to build the per-format `<source>` srcsets of a `<picture>`: a\n * format baked into the URL is cache-safe behind a CDN that ignores the Accept\n * header, whereas a single 'match' URL gets one negotiated variant cached and\n * cross-served to every client. Byte-identical to buildSrcSet when format is\n * 'match'.\n */\nexport function buildSrcSetForFormat(\n url?: string,\n format: 'avif' | 'webp' | 'match' = 'match'\n): string {\n if (!url || typeof url !== 'string') return '';\n\n // For already-proxied URLs, extract the hash and rebuild with widths.\n // Use plain string operations rather than RegExp(`^${proxyBase}/p/...`)\n // so proxyBase (a user-settable hostname) never reaches a regex compile\n // path — keeps CodeQL's hostname-regex analysis clean.\n const proxyPrefix = `${proxyBase}/p/`;\n let result: string;\n if (url.startsWith(proxyPrefix)) {\n const rest = url.slice(proxyPrefix.length);\n const q = rest.indexOf('?');\n const phash = extractPHash(url) || (q >= 0 ? rest.slice(0, q) : rest);\n result = SRCSET_WIDTHS\n .map(w => `${proxyBase}/p/${phash}?format=${format}&mode=fit&width=${w} ${w}w`)\n .join(', ');\n } else {\n // For non-proxified URLs, proxify at each width with the requested format\n result = SRCSET_WIDTHS\n .map(w => {\n const proxied = proxifyForFormat(url, w, 0, format);\n return proxied ? `${proxied} ${w}w` : '';\n })\n .filter(Boolean)\n .join(', ');\n }\n\n // Honor the contract (\"pins an explicit output format in the URL\"): only\n // return a srcset that actually carries the requested format. Legacy\n // direct-serve hosts (images.hive.blog/WxH, steemitimages) host-swap WITHOUT\n // routing through the /p/ transform, so they can't be transcoded — return ''\n // rather than a srcset that silently ignores the requested avif/webp.\n if (format !== 'match' && result && !result.split(',').every(c => c.includes(`format=${format}`))) {\n return '';\n }\n return result;\n}\n\n// Static raster formats the imagehoster reliably transcodes to avif/webp.\n// Animated (gif/apng), vector (svg) and exotic (heic/ico/tiff/arw) are excluded:\n// the origin returns the ORIGINAL bytes for ?format=avif on an animated source,\n// which a <source type=\"image/avif\"> would mislabel (the browser commits to that\n// source and never reaches the <img> fallback). Checked against the URL PATHNAME\n// only — a static-looking extension in the query/fragment (e.g. `?file=a.png`,\n// `x.svg#thumb.png`) does not prove the fetched resource is a static raster.\nconst STATIC_RASTER_PATH_EXT = /\\.(?:jpe?g|png|webp)$/i;\n// Image-proxy sized route, e.g. /600x500/<url> — already-proxified, extension lost.\nconst SIZED_PROXY_PATH = /^\\/\\d+x\\d+\\//;\n\n/**\n * Whether a RAW (pre-proxify) image URL is safe to offer avif/webp `<source>`\n * renditions for. Requires an http(s) URL whose PATHNAME ends in a static-raster\n * extension and that is NOT already proxified — already-proxified routes (`/p/`\n * base58 hash, `/u/` avatars, `WxH` sized) have the original extension stripped,\n * so we can't prove the underlying bytes aren't an animated gif and must fall\n * back to a bare img. URL parsing (not string regex on the host) keeps the host\n * comparison exact and avoids an interpolated-hostname regex.\n */\nexport function isPictureEligibleRawUrl(rawUrl?: string): boolean {\n if (!rawUrl || typeof rawUrl !== 'string') return false;\n let u: URL;\n try {\n u = new URL(rawUrl);\n } catch {\n return false;\n }\n if (u.protocol !== 'http:' && u.protocol !== 'https:') return false;\n\n // Legacy sized-proxy URLs now reach the /p/ route (see proxifyForFormat), so a\n // format CAN be pinned for them. Their path hides the original extension, but\n // that no longer decides anything: an animated source is returned untouched\n // whatever format is requested (verified on a live 44-frame gif — match, avif\n // and webp all return the same 1,001,718 bytes), and an SVG is already\n // rasterised by the /p/ route under format=match (verified: match and avif\n // return byte-identical output). So a pinned <source> cannot change what the\n // reader sees. These are ~5% of in-body images overall but cluster in\n // photo-heavy posts, where a big image is usually the LCP element.\n if (isLegacySizedProxyUrl(rawUrl)) return true;\n\n const host = `${u.protocol}//${u.host}`;\n const isProxyHost = host === proxyBase || host === 'https://images.ecency.com';\n if (\n isProxyHost &&\n (u.pathname.startsWith('/p/') || u.pathname.startsWith('/u/') || SIZED_PROXY_PATH.test(u.pathname))\n ) {\n return false;\n }\n return STATIC_RASTER_PATH_EXT.test(u.pathname);\n}\n\n/**\n * Build the avif + webp `<source>` srcsets for a `<picture>` around a RAW image\n * URL, or null when the URL is ineligible (non-raster, animated, already\n * proxified, or a legacy host that bypasses the /p/ transform). Single\n * eligibility gate shared by the renderer so the decision can't diverge.\n */\nexport function buildPictureSources(\n rawUrl?: string\n): { avif: string; webp: string } | null {\n if (!isPictureEligibleRawUrl(rawUrl)) return null;\n // buildSrcSetForFormat returns '' when it can't honor the requested format\n // (legacy direct-serve hosts that bypass the /p/ transform), so a non-empty\n // pair guarantees every candidate is a proxied /p/ URL carrying the format.\n const avif = buildSrcSetForFormat(rawUrl, 'avif');\n const webp = buildSrcSetForFormat(rawUrl, 'webp');\n if (!avif || !webp) return null;\n return { avif, webp };\n}\n","import xss from 'xss'\nimport {ALLOWED_ATTRIBUTES, ID_WHITELIST, isAllowedEmbedSrc} from '../consts'\nimport { getProxyBase } from '../proxify-image-src'\nimport { trimTrailingSlash } from '../helper'\n\n// data-* attributes whose value is later consumed as an <iframe> src by the\n// client video extensions (dataset.embedSrc / dataset.videoHref). They MUST be\n// an absolute https:// URL on an allowed embed host — anything else (a\n// javascript:/data: same-origin XSS, or an arbitrary off-allowlist origin used\n// for phishing/redirect inside a non-sandboxed frame) is blanked here, the\n// authoritative layer. The renderer only ever emits allowlisted https values\n// (see a.method.ts), so legitimate embeds are unaffected.\nconst EMBED_SRC_DATA_ATTRS = new Set(['data-embed-src', 'data-video-href'])\n\n// data-href carries a navigation target (mobile post/community/hivesigner links\n// and arbitrary external links), NOT an iframe src, so it is held to the same\n// scheme policy a.method.ts already applies to href — block javascript:, data:,\n// vbscript:, file:, etc. while allowing http(s)/mailto/hive/tel/relative.\n// Whitespace/control chars browsers ignore inside the scheme are stripped first.\nconst isSafeNavValue = (value: string): boolean => {\n const trimmed = value.trim().replace(/[\\t\\n\\r\\f\\v\\0]/g, '').toLowerCase()\n if (!trimmed) return false\n const isSafeScheme = /^(https?|mailto|hive|tel|web\\+[a-z0-9.+-]+):/i.test(trimmed)\n const isRelative = /^(\\/\\/|\\/[^/]?|#|\\?|[a-z0-9._\\-]+(\\/|$))/i.test(trimmed)\n return isSafeScheme || isRelative\n}\n\nconst decodeEntities = (input: string): string =>\n input\n .replace(/&#(\\d+);?/g, (_, dec) => String.fromCodePoint(Number(dec)))\n .replace(/&#x([0-9a-f]+);?/gi, (_, hex) => String.fromCodePoint(parseInt(hex, 16)));\n\n// A <source> in a <picture> may only point at the image proxy's /p/ route. This\n// blocks a malicious on-chain <source srcset=\"...\"> from beaconing to an\n// external host or using a non-http scheme (the <img> src/srcset already get\n// the http(s) check below). Our renderer only ever emits proxyBase /p/ srcsets.\nconst isProxyPSrcset = (srcset: string): boolean => {\n const base = trimTrailingSlash(getProxyBase());\n const candidates = srcset.split(',').map(c => c.trim().split(/\\s+/)[0]).filter(Boolean);\n return candidates.length > 0 && candidates.every(url => url.startsWith(`${base}/p/`));\n};\n\nexport function sanitizeHtml(html: string): string {\n const cleaned = xss(html, {\n whiteList: ALLOWED_ATTRIBUTES,\n stripIgnoreTag: true,\n stripIgnoreTagBody: ['style'],\n css: false, // block style attrs entirely for safety\n onTagAttr: (tag, name, value) => {\n const decoded = decodeEntities(value.trim());\n const decodedLower = decoded.toLowerCase();\n\n if (name.startsWith('on')) return ''; // 🛡 event handlers\n // Positive-whitelist: only http(s) is accepted. Any other scheme\n // (javascript:, data:, vbscript:, file:, etc.) is rejected by the\n // negation. We don't need an explicit blocklist alongside.\n if (tag === 'img' && name === 'src' && !/^https?:\\/\\//.test(decodedLower)) return '';\n // Validate srcset: reject if any candidate URL uses a non-http(s) protocol\n if (tag === 'img' && name === 'srcset') {\n const candidates = decoded.split(',').map(c => c.trim().split(/\\s+/)[0]);\n if (candidates.some(url => !/^https?:\\/\\//i.test(url))) return '';\n }\n // <picture><source>: srcset is restricted to the proxy /p/ route, and type\n // to the two formats we emit. Anything else is blanked (and a then\n // type-less <source> is dropped wholesale in the post-pass below).\n if (tag === 'source' && name === 'srcset' && !isProxyPSrcset(decoded)) return '';\n if (tag === 'source' && name === 'type' && decodedLower !== 'image/avif' && decodedLower !== 'image/webp') return '';\n if (\n (tag === 'video' || tag === 'audio') && ['src', 'poster'].includes(name) &&\n !/^https?:\\/\\//.test(decodedLower)\n ) return '';\n // Clamp audio preload to a lightweight hint: our player emits\n // preload=\"metadata\", and an author-supplied preload=\"auto\" on untrusted\n // posts would eagerly fetch large third-party audio before any click.\n if (tag === 'audio' && name === 'preload' &&\n decodedLower !== 'metadata' && decodedLower !== 'none') return '';\n if (tag === 'img' && ['dynsrc', 'lowsrc'].includes(name)) return '';\n if (tag === 'span' && name === 'class' && decoded.toLowerCase().trim() === 'wr') return '';\n // iframe-src data-* attrs: must resolve to an https:// allowed-embed-host\n // URL or they are blanked (stored HTML/iframe injection — CVE class).\n if (EMBED_SRC_DATA_ATTRS.has(name) && !isAllowedEmbedSrc(decoded)) return '';\n // data-href is a navigation target; block dangerous schemes only.\n if (name === 'data-href' && !isSafeNavValue(decoded)) return '';\n if (name === 'id') {\n if (!ID_WHITELIST.test(decoded)) return '';\n }\n return undefined;\n }\n });\n\n // Drop any <source> that lacks a valid avif/webp type. onTagAttr can blank an\n // attribute but can't remove an element, and a type-less <source> with a\n // surviving srcset would match ALL browsers (overriding the <img>). Our\n // renderer always emits a typed <source>, so this only fires on hostile input.\n // The tag matcher tolerates a literal '>' inside a quoted attribute value\n // (xss escapes '>' to '&gt;' in output, so this is belt-and-suspenders) by\n // consuming quoted spans whole rather than stopping at the first '>'.\n return cleaned.replace(/<source\\b(?:[^>\"']|\"[^\"]*\"|'[^']*')*>/gi, (t) =>\n /\\btype\\s*=\\s*[\"'](?:image\\/avif|image\\/webp)[\"']/i.test(t) ? t : ''\n );\n}\n","import { proxifyImageSrc, buildSrcSet, getProxyBase, buildPictureSources } from \"../proxify-image-src\";\nimport { trimTrailingSlash, decodeImageSrc } from \"../helper\";\n\n/**\n * The `sizes` value the renderer applies to in-body post images (see `img()`\n * and `createImageHTML()`). Exported as the single source of truth so consumers\n * preloading the LCP image (`<link rel=\"preload\" as=\"image\" imagesizes>`) can\n * match the exact srcset candidate the rendered <img> selects.\n */\nexport const IMAGE_SIZES = \"(max-width: 768px) 100vw, 700px\";\n\n/**\n * Wrap a displayed <img> (DOM path) in a <picture> with explicit avif/webp\n * <source>s, so the browser negotiates format client-side via distinct,\n * cache-safe URLs (the format lives in the URL, not the Accept header that the\n * CDN cache ignores). No-op when the raw URL is not picture-eligible, or when\n * the <img> is already inside a <picture> (traverse can re-enter the inner <img>\n * of a string-path <picture>). Web/self-hosted only — the caller gates on\n * `forApp === false` because React Native cannot render <picture>.\n */\nfunction wrapInPicture(el: HTMLElement, rawUrl: string): void {\n const parent = el.parentNode;\n if (!parent) return;\n if (parent.nodeName && parent.nodeName.toLowerCase() === \"picture\") return;\n const sources = buildPictureSources(rawUrl);\n if (!sources) return;\n const doc = el.ownerDocument;\n if (!doc) return;\n const sizes = el.getAttribute(\"sizes\") || IMAGE_SIZES;\n const picture = doc.createElement(\"picture\");\n const avif = doc.createElement(\"source\");\n avif.setAttribute(\"type\", \"image/avif\");\n avif.setAttribute(\"srcset\", sources.avif);\n avif.setAttribute(\"sizes\", sizes);\n const webp = doc.createElement(\"source\");\n webp.setAttribute(\"type\", \"image/webp\");\n webp.setAttribute(\"srcset\", sources.webp);\n webp.setAttribute(\"sizes\", sizes);\n // avif first — the browser picks the first <source> it supports.\n parent.insertBefore(picture, el);\n picture.appendChild(avif);\n picture.appendChild(webp);\n picture.appendChild(el);\n}\n\nexport function img(el: HTMLElement, state?: { firstImageFound: boolean }, forApp = true): void {\n const src = el.getAttribute(\"src\") || \"\";\n\n // Normalize encoded characters (shared with getEntryImageRawUrl so the LCP\n // preload's proxy hash byte-matches this rendered <img>/<picture>).\n const decodedSrc = decodeImageSrc(src);\n\n // Sanitize dangerous attributes regardless of validity\n [\"onerror\", \"dynsrc\", \"lowsrc\", \"width\", \"height\"].forEach(attr => el.removeAttribute(attr));\n\n // ❌ Remove if javascript or empty/invalid\n const isInvalid = !src || decodedSrc.startsWith(\"javascript\") || decodedSrc.startsWith(\"vbscript\") || decodedSrc === \"x\";\n if (isInvalid) {\n el.removeAttribute(\"src\");\n el.removeAttribute(\"srcset\");\n el.removeAttribute(\"sizes\");\n return;\n }\n\n // ❌ Skip relative paths (e.g., `photo.jpg`, `./photo.png`, `assets/pic.jpeg`)\n // Use trimmed decodedSrc for protocol check to handle leading/trailing whitespace\n const isRelative = !/^https?:\\/\\//i.test(decodedSrc) && !decodedSrc.startsWith(\"/\");\n if (isRelative) {\n el.removeAttribute(\"src\");\n el.removeAttribute(\"srcset\");\n el.removeAttribute(\"sizes\");\n return;\n }\n\n el.setAttribute(\"itemprop\", \"image\");\n const isLCP = state && !state.firstImageFound;\n\n if (isLCP) {\n el.setAttribute(\"loading\", \"eager\");\n el.setAttribute(\"fetchpriority\", \"high\");\n state.firstImageFound = true;\n } else {\n el.setAttribute(\"loading\", \"lazy\");\n el.setAttribute(\"decoding\", \"async\");\n }\n\n const cls = el.getAttribute(\"class\") || \"\";\n const shouldReplace = !cls.includes(\"no-replace\");\n // Only skip re-proxification for URLs already going through proxy/avatar/cover routes\n // Direct upload URLs (e.g. /DQm...) should still be proxified for resizing & format optimization\n const base = trimTrailingSlash(getProxyBase());\n const hasAlreadyProxied = src.startsWith(`${base}/p/`)\n || src.startsWith(`${base}/u/`)\n || new RegExp(`^${base.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}/\\\\d+x\\\\d+/`).test(src);\n\n if (shouldReplace && !hasAlreadyProxied) {\n // forceProxy: route the fallback src through /p/ even though no width is set,\n // so uploads still get WebP/AVIF via Accept negotiation instead of the\n // original-format direct-serve bytes. (srcset carries the resized variants.)\n const proxified = proxifyImageSrc(decodedSrc, 0, 0, \"match\", { forceProxy: true });\n if (proxified) {\n el.setAttribute(\"src\", proxified);\n const srcset = buildSrcSet(decodedSrc);\n if (srcset) {\n el.setAttribute(\"srcset\", srcset);\n el.setAttribute(\"sizes\", IMAGE_SIZES);\n }\n // Web/self-hosted: offer avif/webp via <picture>. The raw decodedSrc still\n // carries the original extension here (pre-proxify), which the eligibility\n // gate needs. The <img> above stays the format=match fallback.\n if (!forApp) {\n wrapInPicture(el, decodedSrc);\n }\n }\n } else if (shouldReplace && hasAlreadyProxied) {\n // Only /p/ URLs have extractable hashes for srcset; /u/ and /WxH/ routes\n // are avatar/cover URLs that shouldn't get responsive srcset\n if (src.startsWith(`${base}/p/`)) {\n const srcset = buildSrcSet(src);\n if (srcset) {\n el.setAttribute(\"srcset\", srcset);\n el.setAttribute(\"sizes\", IMAGE_SIZES);\n }\n }\n }\n}\n\nexport function createImageHTML(src: string, isLCP: boolean, forApp = true): string {\n // Decode with the same pipeline as the DOM path img() so the same source URL\n // hashes to the same proxy /p/ URL regardless of which render path produced it\n // (and so the LCP preload, which decodes via getEntryImageRawUrl, matches).\n const decoded = decodeImageSrc(src);\n // forceProxy: see img() — keep the fallback src unsized but proxied so uploads\n // are served WebP/AVIF rather than the original-format direct-serve bytes.\n const proxified = proxifyImageSrc(decoded, 0, 0, \"match\", { forceProxy: true });\n if (!proxified) return '';\n\n const base = trimTrailingSlash(getProxyBase());\n const isAlreadyProxied = decoded.startsWith(`${base}/u/`)\n || new RegExp(`^${base.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}/\\\\d+x\\\\d+/`).test(decoded);\n const srcset = isAlreadyProxied ? '' : buildSrcSet(decoded);\n const loading = isLCP ? 'eager' : 'lazy';\n const fetch = isLCP ? 'fetchpriority=\"high\"' : 'decoding=\"async\"';\n const srcsetAttr = srcset ? `srcset=\"${srcset}\" sizes=\"${IMAGE_SIZES}\"` : '';\n const imgTag = `<img\n class=\"markdown-img-link\"\n src=\"${proxified}\"\n ${srcsetAttr}\n loading=\"${loading}\"\n ${fetch}\n itemprop=\"image\"\n />`;\n\n // Web/self-hosted: wrap in <picture> with explicit avif/webp <source>s when\n // the source is picture-eligible. Self-closing <source/> — an explicit\n // </source> throws in the downstream xmldom re-parse. The <img> stays the\n // format=match fallback. App path (forApp) keeps the bare <img> (no <picture>\n // in React Native).\n if (!forApp) {\n const sources = buildPictureSources(decoded);\n if (sources) {\n return `<picture><source type=\"image/avif\" srcset=\"${sources.avif}\" sizes=\"${IMAGE_SIZES}\" /><source type=\"image/webp\" srcset=\"${sources.webp}\" sizes=\"${IMAGE_SIZES}\" />${imgTag}</picture>`;\n }\n }\n return imgTag;\n}\n","import {\n BITCHUTE_REGEX,\n CUSTOM_COMMUNITY_REGEX,\n INTERNAL_POST_REGEX,\n INTERNAL_POST_TAG_REGEX,\n D_TUBE_REGEX,\n D_TUBE_REGEX2,\n IMG_REGEX,\n IPFS_REGEX,\n MENTION_REGEX,\n INTERNAL_MENTION_REGEX,\n TOPIC_REGEX,\n INTERNAL_TOPIC_REGEX,\n POST_REGEX,\n CCC_REGEX,\n SPEAK_REGEX,\n SPEAK_AUDIO_REGEX,\n LIKETU_AUDIO_REGEX,\n TWITCH_REGEX,\n TWITTER_REGEX,\n VIMEO_REGEX,\n WHITE_LIST,\n YOUTUBE_REGEX,\n SPOTIFY_REGEX,\n RUMBLE_REGEX,\n BRIGHTEON_REGEX,\n ODYSEE_WATCH_REGEX,\n DOMParser,\n LOOM_REGEX,\n SECTION_LIST\n} from '../consts'\nimport { getSerializedInnerHTML } from './get-inner-html.method'\nimport { proxifyImageSrc } from '../proxify-image-src'\nimport { removeChildNodes } from './remove-child-nodes.method'\nimport { extractYtStartTime, isValidPermlink, isValidUsername, sanitizePermlink, stripHtmlTags, trimTrailingSlash } from '../helper'\nimport { createImageHTML } from \"./img.method\";\nimport { RenderOptions, SeoContext } from '../types'\n\nconst NOFOLLOW_REPUTATION_THRESHOLD = 40;\nconst FOLLOW_PAYOUT_THRESHOLD = 5;\n\n/**\n * Determines the rel attribute for external links based on SEO context.\n *\n * Default: \"nofollow ugc noopener\" for all user-generated external links.\n * Exception: \"noopener\" only (followed) when author reputation >= 40 AND post payout > $5.\n */\nfunction getExternalLinkRel(seoContext?: SeoContext): string {\n if (\n seoContext?.authorReputation !== undefined &&\n seoContext?.postPayout !== undefined &&\n seoContext.authorReputation >= NOFOLLOW_REPUTATION_THRESHOLD &&\n seoContext.postPayout > FOLLOW_PAYOUT_THRESHOLD\n ) {\n return 'noopener';\n }\n return 'nofollow ugc noopener';\n}\n\n/**\n * Turns a video link into a player for the providers we cannot derive a\n * thumbnail for synchronously (BitChute, Rumble, Brighteon, Odysee). YouTube and\n * 3Speak stay hand-written because each carries provider-specific work (start\n * time, portrait detection, thumbnail from post metadata).\n *\n * The per-provider modifier class matters: both the stylesheet and the\n * click-to-play extension select on it, so an anchor carrying only the base\n * class is unstyled (zero height, no play icon) and unhandled — which is why a\n * posted BitChute link used to render as nothing at all.\n *\n * `embedVideosDirectly` (waves feed, self-hosted blog) mounts no client\n * enhancer, so there a placeholder would stay inert forever; emit a real iframe\n * instead, mirroring the YouTube branch. It is never autoplayed: a feed\n * scrolling past several videos that all start at once is disorienting.\n */\nfunction renderPlainVideoLink(\n el: HTMLElement,\n provider: string,\n embedSrc: string,\n renderOptions?: RenderOptions\n): void {\n const baseClass = `markdown-video-link markdown-video-link-${provider}`\n // Attribute order below matches what these branches emitted before they were\n // folded together, so the serialized-output fixtures stay stable.\n el.setAttribute('class', baseClass)\n el.removeAttribute('href')\n el.textContent = ''\n el.setAttribute('data-embed-src', embedSrc)\n\n if (renderOptions?.embedVideosDirectly) {\n const wrapper = el.ownerDocument.createElement('span')\n wrapper.setAttribute('class', 'er-embed-frame')\n wrapper.setAttribute('style', 'display:block')\n\n const frame = el.ownerDocument.createElement('iframe')\n frame.setAttribute('src', embedSrc)\n frame.setAttribute('title', 'Video player')\n frame.setAttribute(\n 'allow',\n 'accelerometer; encrypted-media; gyroscope; picture-in-picture; web-share'\n )\n frame.setAttribute('allowfullscreen', '')\n\n wrapper.appendChild(frame)\n el.appendChild(wrapper)\n // `er-embed` marks this as already enhanced so the click-to-play extension\n // skips it if both paths ever run over the same document.\n el.setAttribute('class', `${baseClass} er-embed`)\n return\n }\n\n const play = el.ownerDocument.createElement('span')\n play.setAttribute('class', 'markdown-video-play')\n el.appendChild(play)\n}\n\nconst normalizeValue = (value?: string | null): string => (value ? value.trim() : '')\n\nconst matchesHref = (href: string, value?: string | null): boolean => {\n const normalizedHref = normalizeValue(href)\n if (!normalizedHref) {\n return false\n }\n\n return normalizeValue(value) === normalizedHref\n}\n\n/**\n * Normalizes display text for inline detection by:\n * - Stripping protocol and domain (ecency.com, peakd.com, hive.blog, leofinance.io, inleo.io, snapie.io, hivesuite.app)\n * - Removing leading/trailing slashes\n * - Removing query parameters\n * - Removing comment hashes (#@...)\n * - Converting to lowercase\n */\nconst normalizeDisplayText = (text: string): string => {\n const beforeTrailingSlash = text\n .trim()\n .replace(/^https?:\\/\\/(www\\.)?(ecency\\.com|peakd\\.com|hive\\.blog|leofinance\\.io|inleo\\.io|snapie\\.io|hivesuite\\.app)/i, \"\")\n .replace(/^\\/+/, \"\")\n .split(\"?\")[0]\n .replace(/#@.*$/i, \"\");\n return trimTrailingSlash(beforeTrailingSlash).toLowerCase();\n}\n\n/**\n * Enhanced inline detection that handles edge cases like:\n * - Full URLs: https://ecency.com/@author/permlink\n * - Relative URLs: /@author/permlink\n * - With community tags: hive-123456/@author/permlink\n * - With query params: @author/permlink?ref=twitter\n * - With trailing slashes: @author/permlink/\n */\nconst getInlineMeta = (el: HTMLElement, href: string, author: string, permlink: string, communityTag?: string) => {\n // Simple exact match (original behavior)\n const textMatches = matchesHref(href, el.textContent)\n const titleMatches = matchesHref(href, el.getAttribute('title'))\n\n // Sophisticated normalized matching\n const normalizedDisplay = normalizeDisplayText(el.textContent || \"\");\n const normalizedTarget = `@${author}/${permlink}`.toLowerCase();\n\n // Build expected display patterns\n const expectedDisplays = new Set([normalizedTarget]);\n if (communityTag) {\n expectedDisplays.add(`${communityTag.toLowerCase()}/${normalizedTarget}`);\n }\n\n const sophisticatedMatch =\n normalizedDisplay === normalizedTarget ||\n (communityTag ? normalizedDisplay === `${communityTag.toLowerCase()}/${normalizedTarget}` : false);\n\n return {\n textMatches,\n titleMatches,\n isInline: textMatches || titleMatches || sophisticatedMatch\n }\n}\n\n/**\n * Adds a line break before inline post links in mobile app mode\n * This ensures enhanced post links (where the raw URL is displayed) render on separate lines\n * in React Native where CSS display properties don't work the same way as in browsers\n */\nconst addLineBreakBeforePostLink = (el: HTMLElement, forApp: boolean, isInline: boolean): void => {\n if (forApp && isInline && el.parentNode) {\n const br = el.ownerDocument.createElement('br')\n el.parentNode.insertBefore(br, el)\n }\n}\n\nexport function a(el: HTMLElement | null, forApp: boolean, parentDomain: string = 'ecency.com', seoContext?: SeoContext, renderOptions?: RenderOptions): void {\n if (!el || !el.parentNode) {\n return\n }\n let href = el.getAttribute('href')\n\n // Continue if href has no value\n if (!href) {\n return\n }\n\n // Positive scheme whitelist. Anything that isn't http(s)/mailto/hive/\n // tel/web+ext or a same-document/relative reference is stripped — this\n // rejects javascript:, data:, vbscript:, file: and also less-common\n // exploit vectors like ms-its:, mk:, res:, intent:. Case-insensitive\n // and tolerant of whitespace/control chars browsers ignore inside the\n // scheme (\\t \\n \\r \\f \\v \\0).\n // Runs before the author/tag short-circuit below: that short-circuit keys off\n // `class`, which an author can set on raw HTML, so it must not be reachable with\n // an unvalidated href.\n const trimmed = href.trim().replace(/[\\t\\n\\r\\f\\v\\0]/g, '').toLowerCase()\n const isSafeScheme = /^(https?|mailto|hive|tel|web\\+[a-z0-9.+-]+):/i.test(trimmed)\n // `\\/[^/]?` matches both bare `/` (site-root link) and `/path…`;\n // alongside protocol-relative `//host`, fragment `#…`, query `?…`,\n // and document-relative `name.ext`/`name/`/bare `name`.\n const isRelative = /^(\\/\\/|\\/[^/]?|#|\\?|[a-z0-9._\\-]+(\\/|$))/i.test(trimmed)\n if (!isSafeScheme && !isRelative) {\n el.removeAttribute('href')\n return\n }\n\n const className = el.getAttribute('class')\n\n // Don't re-process user and hashtag links (original or enhanced). The marker is an\n // attacker-writable attribute rather than proof the renderer built this link, so a\n // crafted `<a class=\"er-author\" target=\"_blank\" rel=\"opener\">` would otherwise keep\n // its own rel and re-enable window.opener on the landing page. Skipping the rewrite\n // is fine; skipping the link policy is not, so re-assert it here.\n if (className && (\n ['markdown-author-link', 'markdown-tag-link'].includes(className) ||\n className.includes('er-author') ||\n className.includes('er-tag')\n )) {\n if (el.getAttribute('target')) {\n el.setAttribute('rel', getExternalLinkRel(seoContext))\n }\n return\n }\n\n // if href is an image url and innerHTML same with href then mark it as image\n // & => &amp; can break equality\n if (\n href.match(IMG_REGEX) &&\n href.trim().replace(/&amp;/g, '&') ===\n getSerializedInnerHTML(el).trim().replace(/&amp;/g, '&')\n ) {\n const isLCP = false; // LCP handled elsewhere\n const imgHTML = createImageHTML(href, isLCP, forApp);\n const doc = DOMParser.parseFromString(imgHTML, 'text/html');\n const replaceNode = (doc as any).body?.firstChild || doc.firstChild\n\n if (replaceNode && el.parentNode) {\n const importedNode = el.ownerDocument.importNode(replaceNode, true)\n el.parentNode.replaceChild(importedNode, el)\n }\n\n return\n }\n\n if (\n href.match(IPFS_REGEX) &&\n href.trim().replace(/&amp;/g, '&') ===\n getSerializedInnerHTML(el).trim().replace(/&amp;/g, '&') &&\n href.indexOf('#') === -1\n ) {\n if (forApp) {\n el.setAttribute('data-href', href)\n el.removeAttribute('href')\n }\n\n el.setAttribute('class', 'markdown-img-link')\n\n removeChildNodes(el)\n\n const img = el.ownerDocument.createElement('img')\n img.setAttribute('src', href)\n el.appendChild(img)\n\n return\n }\n\n // If a hive post\n const postMatch = href.match(POST_REGEX)\n if (postMatch && WHITE_LIST.includes(postMatch[1].replace(/^www\\./,''))) {\n el.setAttribute('class', 'markdown-post-link')\n\n const tag = postMatch[2]\n const author = postMatch[3].replace('@', '')\n const permlink = sanitizePermlink(postMatch[4])\n\n if (!isValidPermlink(permlink)) return;\n\n const inlineMeta = getInlineMeta(el, href, author, permlink)\n if (inlineMeta.textMatches) {\n el.textContent = `@${author}/${permlink}`\n }\n const isInline = inlineMeta.isInline\n if (forApp) {\n el.removeAttribute('href')\n\n el.setAttribute('data-href', href)\n el.setAttribute('data-is-inline', '' + isInline)\n el.setAttribute('data-tag', tag)\n el.setAttribute('data-author', author)\n el.setAttribute('data-permlink', permlink)\n\n } else {\n const h = `/@${author}/${permlink}`\n el.setAttribute('href', h)\n el.setAttribute('data-is-inline', '' + isInline)\n }\n\n addLineBreakBeforePostLink(el, forApp, isInline)\n return\n }\n\n // If a hive user with url\n const mentionMatch = href.match(MENTION_REGEX)\n if (mentionMatch && WHITE_LIST.includes(mentionMatch[1].replace(/^www\\./,'')) && mentionMatch.length === 3) {\n const _author = mentionMatch[2].replace('@', '')\n if (!isValidUsername(_author)) return\n const author = _author.toLowerCase()\n\n el.setAttribute('class', 'markdown-author-link')\n\n if (author.indexOf('/')===-1) {\n if (el.textContent === href) {\n el.textContent = `@${author}`\n }\n if (forApp) {\n el.removeAttribute('href')\n\n el.setAttribute('data-author', author)\n } else {\n const h = `/@${author}`\n el.setAttribute('href', h)\n }\n }\n return\n }\n\n // If a tagged post and profile section links\n const tpostMatch = href.match(INTERNAL_POST_TAG_REGEX)\n\n // Extract and validate domain from tpostMatch[1]\n let isValidDomain = false;\n if (tpostMatch && tpostMatch.length === 4) {\n if (tpostMatch[1].indexOf('/') === 0) {\n // Internal path like /ecency/@user/post\n isValidDomain = true;\n } else if (tpostMatch[1].includes('.')) {\n // Extract domain from URL (strip protocol and www.)\n const domain = tpostMatch[1]\n .replace(/^https?:\\/\\//, '') // Remove protocol\n .replace(/^www\\./, '') // Remove www. prefix\n isValidDomain = WHITE_LIST.includes(domain);\n }\n }\n\n // isValidDomain is only ever set true inside the `tpostMatch && length === 4` block above,\n // so tpostMatch is non-null here — asserted with `!` (type-only, erased at emit) at each use\n // to keep the emitted JS byte-identical.\n if (isValidDomain) {\n // check if permlink is section or section with params ?q=xyz\n // Split on '?' first to get path segment\n const pathSegment = tpostMatch![3].split('?')[0]\n if (SECTION_LIST.some(v => pathSegment === v || pathSegment.startsWith(v + '/'))) {\n el.setAttribute('class', 'markdown-profile-link')\n const author = tpostMatch![2].replace('@', '').toLowerCase()\n const section = tpostMatch![3]\n\n if (!isValidPermlink(section)) return;\n if (el.textContent === href) {\n el.textContent = `@${author}/${section}`\n }\n // A section, not a permlink. A consumer whose only matching route is\n // /:author/:permlink routes this as a post and tries to load one called\n // `wallet`, so it needs an origin it can actually serve.\n const external1 = renderOptions?.externalProfileBase\n if (forApp || external1) {\n el.setAttribute('href', `${external1 ?? 'https://ecency.com'}/@${author}/${section}`)\n } else {\n const h = `/@${author}/${section}`\n el.setAttribute('href', h)\n }\n return\n } else {\n // Domain already validated in outer if condition\n let tag = 'post'\n // check if tag does exist and doesn't include dot likely word/tag\n if (tpostMatch![1] && !tpostMatch![1].includes('.')) {\n [, tag] = tpostMatch!\n tag = tag.replace('/', '')\n }\n\n el.setAttribute('class', 'markdown-post-link')\n const author = tpostMatch![2].replace('@', '')\n const permlink = sanitizePermlink(tpostMatch![3])\n\n if (!isValidPermlink(permlink)) return;\n\n // Pass community tag if it starts with \"hive-\"\n const communityTag = tag.toLowerCase().startsWith('hive-') ? tag : undefined\n const inlineMeta = getInlineMeta(el, href, author, permlink, communityTag)\n if (inlineMeta.textMatches) {\n el.textContent = `@${author}/${permlink}`\n }\n const isInline = inlineMeta.isInline\n if (forApp) {\n el.removeAttribute('href')\n\n el.setAttribute('data-href', href)\n el.setAttribute('data-is-inline', '' + isInline)\n el.setAttribute('data-tag', tag)\n el.setAttribute('data-author', author)\n el.setAttribute('data-permlink', permlink)\n\n } else {\n const h = `/@${author}/${permlink}`\n el.setAttribute('href', h)\n el.setAttribute('data-is-inline', '' + isInline)\n }\n\n addLineBreakBeforePostLink(el, forApp, isInline)\n return\n }\n }\n\n // If a hive user with internal url\n const imentionMatch = href.match(INTERNAL_MENTION_REGEX)\n if (imentionMatch) {\n const _author = imentionMatch[0].replace('/@', '')\n if (!isValidUsername(_author)) return\n const author = _author.toLowerCase()\n\n el.setAttribute('class', 'markdown-author-link')\n if (author.indexOf('/')===-1) {\n if (el.textContent === href) {\n el.textContent = `@${author}`\n }\n if (forApp) {\n el.removeAttribute('href')\n\n el.setAttribute('data-author', author)\n } else {\n const h = `/@${author}`\n el.setAttribute('href', h)\n }\n }\n return\n }\n\n // If a copied post and profile section links\n const cpostMatch = href.match(INTERNAL_POST_REGEX)\n if (\n (cpostMatch && cpostMatch.length === 3 && cpostMatch[1].indexOf('@') === 0)\n ) {\n // Split on '?' first to get path segment\n const pathSegment2 = cpostMatch[2].split('?')[0]\n if (SECTION_LIST.some(v => pathSegment2 === v || pathSegment2.startsWith(v + '/'))) {\n el.setAttribute('class', 'markdown-profile-link')\n const author = cpostMatch[1].replace('@', '').toLowerCase()\n const section = cpostMatch[2]\n\n if (el.textContent === href) {\n el.textContent = `@${author}/${section}`\n }\n // A section, not a permlink. A consumer whose only matching route is\n // /:author/:permlink routes this as a post and tries to load one called\n // `wallet`, so it needs an origin it can actually serve.\n const external2 = renderOptions?.externalProfileBase\n if (forApp || external2) {\n el.setAttribute('href', `${external2 ?? 'https://ecency.com'}/@${author}/${section}`)\n } else {\n const h = `/@${author}/${section}`\n el.setAttribute('href', h)\n }\n return\n } else {\n el.setAttribute('class', 'markdown-post-link')\n\n const tag = 'post'\n\n const author = cpostMatch[1].replace('@', '')\n const permlink = sanitizePermlink(cpostMatch[2])\n\n if (!isValidPermlink(permlink)) return;\n\n const inlineMeta = getInlineMeta(el, href, author, permlink)\n\n if (inlineMeta.textMatches) {\n el.textContent = `@${author}/${permlink}`\n }\n const isInline = inlineMeta.isInline\n if (forApp) {\n el.removeAttribute('href')\n\n el.setAttribute('data-href', href)\n el.setAttribute('data-is-inline', '' + isInline)\n el.setAttribute('data-tag', tag)\n el.setAttribute('data-author', author)\n el.setAttribute('data-permlink', permlink)\n } else {\n const h = `/@${author}/${permlink}`\n el.setAttribute('href', h)\n el.setAttribute('data-is-inline', '' + isInline)\n }\n\n addLineBreakBeforePostLink(el, forApp, isInline)\n return\n }\n }\n\n // If topic with filters url\n const topicMatch = href.match(TOPIC_REGEX)\n if (topicMatch && WHITE_LIST.includes(topicMatch[1].replace(/^www\\./,'')) && topicMatch.length === 4) {\n el.setAttribute('class', 'markdown-tag-link')\n const filter = topicMatch[2]\n const tag = topicMatch[3]\n\n if (el.textContent === href) {\n el.textContent = `/${filter}/${tag}`\n }\n if (forApp) {\n el.removeAttribute('href')\n\n el.setAttribute('data-filter', filter)\n el.setAttribute('data-tag', tag)\n } else {\n const h = `/${filter}/${tag}`\n el.setAttribute('href', h)\n }\n return\n }\n\n // If topic with filters internal url\n const itopicMatch = href.match(INTERNAL_TOPIC_REGEX)\n if (itopicMatch && itopicMatch.length === 3) {\n el.setAttribute('class', 'markdown-tag-link')\n const filter = itopicMatch[1]\n const tag = itopicMatch[2]\n\n if (el.textContent === href) {\n el.textContent = `/${filter}/${tag}`\n }\n if (forApp) {\n el.removeAttribute('href')\n\n el.setAttribute('data-filter', filter)\n el.setAttribute('data-tag', tag)\n } else {\n const h = `/${filter}/${tag}`\n el.setAttribute('href', h)\n }\n return\n }\n\n // If a custom hive community link\n const comMatch = href.match(CUSTOM_COMMUNITY_REGEX)\n if (comMatch && WHITE_LIST.includes(comMatch[1].replace(/^www\\./,''))) {\n el.setAttribute('class', 'markdown-community-link')\n\n const community = comMatch[2]\n let filter = comMatch[3].substring(1)\n if (!filter) filter = 'created'\n if (filter === 'about' || filter === 'discord') {\n filter = 'created'\n }\n if (el.textContent === href) {\n el.textContent = `${filter}/${community}`\n }\n\n if (forApp) {\n el.removeAttribute('href')\n\n el.setAttribute('data-community', community)\n el.setAttribute('data-filter', filter)\n } else {\n const h = `/${filter}/${community}`\n el.setAttribute('href', h)\n }\n return\n }\n\n // If a collections post\n const cccMatch = href.match(CCC_REGEX)\n if (cccMatch && WHITE_LIST.includes(cccMatch[1].replace(/^www\\./,''))) {\n el.setAttribute('class', 'markdown-post-link')\n\n const tag = 'ccc'\n const author = cccMatch[2].replace('@', '')\n const permlink = sanitizePermlink(cccMatch[3])\n\n if (!isValidPermlink(permlink)) return;\n\n const inlineMeta = getInlineMeta(el, href, author, permlink)\n\n if (inlineMeta.textMatches) {\n el.textContent = `@${author}/${permlink}`\n }\n const isInline = inlineMeta.isInline\n if (forApp) {\n el.removeAttribute('href')\n\n el.setAttribute('data-href', href)\n el.setAttribute('data-is-inline', '' + isInline)\n el.setAttribute('data-tag', tag)\n el.setAttribute('data-author', author)\n el.setAttribute('data-permlink', permlink)\n } else {\n const h = `/@${author}/${permlink}`\n el.setAttribute('href', h)\n el.setAttribute('data-is-inline', '' + isInline)\n }\n addLineBreakBeforePostLink(el, forApp, isInline)\n return\n }\n\n\n const BCmatch = href.match(BITCHUTE_REGEX)\n if (BCmatch && BCmatch[1] && el.textContent.trim() === href) {\n renderPlainVideoLink(el, 'bitchute', `https://www.bitchute.com/embed/${BCmatch[1]}/`, renderOptions)\n return\n }\n\n const RBmatch = href.match(RUMBLE_REGEX)\n if (RBmatch && RBmatch[1] && el.textContent.trim() === href) {\n renderPlainVideoLink(el, 'rumble', `https://www.rumble.com/embed/${RBmatch[1]}/?pub=4`, renderOptions)\n return\n }\n\n const BNmatch = href.match(BRIGHTEON_REGEX)\n if (BNmatch && BNmatch[2] && el.textContent.trim() === href) {\n renderPlainVideoLink(el, 'brighteon', `https://www.brighteon.com/embed/${BNmatch[2]}`, renderOptions)\n return\n }\n\n // Odysee watch links. Odysee mirrors the watch path under /$/embed/, so a\n // posted video URL maps to a playable embed with no network lookup.\n const ODmatch = href.match(ODYSEE_WATCH_REGEX)\n if (ODmatch && ODmatch[1] && el.textContent.trim() === href) {\n renderPlainVideoLink(el, 'odysee', `https://odysee.com/$/embed/${ODmatch[1]}`, renderOptions)\n return\n }\n\n // If a youtube video\n let match = href.match(YOUTUBE_REGEX)\n if (match && match[1] && el.textContent.trim() === href) {\n el.setAttribute('class', 'markdown-video-link markdown-video-link-youtube')\n el.removeAttribute('href')\n\n const vid = match[1]\n const thumbnail = proxifyImageSrc(`https://img.youtube.com/vi/${vid.split('?')[0]}/hqdefault.jpg`, 0, 0, 'match')\n const embedSrc = `https://www.youtube.com/embed/${vid}?autoplay=1`\n\n el.textContent = ''\n\n el.setAttribute('data-embed-src', embedSrc);\n el.setAttribute('data-youtube', vid);\n\n //extract start time if available\n const startTime = extractYtStartTime(href);\n if(startTime){\n el.setAttribute('data-start-time', startTime);\n }\n\n if (renderOptions?.embedVideosDirectly) {\n // Waves/thread feed: embed inline but never autoplay. A feed scrolling\n // past several videos that all start playing at once is disorienting, so\n // load the player paused (no autoplay=1, no autoplay permission). The\n // click-to-play path elsewhere keeps using embedSrc via data-embed-src.\n const directSrc = `https://www.youtube.com/embed/${vid}`\n const wrapper = el.ownerDocument.createElement('span')\n wrapper.setAttribute('class', 'er-youtube-frame')\n wrapper.setAttribute('style', 'display:block')\n const iframe = el.ownerDocument.createElement('iframe')\n iframe.setAttribute('class', 'youtube-player')\n iframe.setAttribute('src', directSrc)\n iframe.setAttribute('title', 'YouTube video')\n iframe.setAttribute('allow', 'accelerometer; encrypted-media; gyroscope; picture-in-picture; web-share')\n iframe.setAttribute('allowfullscreen', '')\n wrapper.appendChild(iframe)\n el.appendChild(wrapper)\n el.setAttribute('class', 'markdown-video-link markdown-video-link-youtube er-youtube')\n } else {\n const thumbImg = el.ownerDocument.createElement('img')\n thumbImg.setAttribute('class', 'no-replace video-thumbnail')\n thumbImg.setAttribute('itemprop', 'thumbnailUrl')\n thumbImg.setAttribute('src', thumbnail)\n\n const play = el.ownerDocument.createElement('span')\n play.setAttribute('class', 'markdown-video-play')\n\n el.appendChild(thumbImg)\n el.appendChild(play)\n }\n\n return\n }\n\n // If vimeo video\n match = href.match(VIMEO_REGEX)\n if (match && match[3] && href === el.textContent) {\n el.setAttribute('class', 'markdown-video-link markdown-video-link-vimeo')\n el.removeAttribute('href')\n\n const embedSrc = `https://player.vimeo.com/video/${match[3]}`\n\n el.textContent = ''\n\n const ifr = el.ownerDocument.createElement('iframe')\n ifr.setAttribute('frameborder', '0')\n ifr.setAttribute('allowfullscreen', 'true')\n ifr.setAttribute('src', embedSrc)\n el.appendChild(ifr)\n\n return\n }\n\n // If twitch video\n match = href.match(TWITCH_REGEX)\n if (match && match[2] && href === el.textContent) {\n el.setAttribute('class', 'markdown-video-link markdown-video-link-twitch')\n el.removeAttribute('href')\n\n let embedSrc = ''\n const parent = parentDomain ? `&parent=${parentDomain}` : ''\n\n if (match[1] === undefined) {\n // No \"videos\" in URL, match[2] is the channel name\n embedSrc = `https://player.twitch.tv/?channel=${match[2]}${parent}`\n } else if (match[1] === 'videos') {\n // URL contains \"videos/\", match[2] is the video ID\n embedSrc = `https://player.twitch.tv/?video=${match[2]}${parent}`\n } else {\n // Fallback (shouldn't happen with current regex)\n embedSrc = `https://player.twitch.tv/?channel=${match[2]}${parent}`\n }\n\n el.textContent = ''\n\n const ifr = el.ownerDocument.createElement('iframe')\n ifr.setAttribute('frameborder', '0')\n ifr.setAttribute('allowfullscreen', 'true')\n ifr.setAttribute('src', embedSrc)\n el.appendChild(ifr)\n\n return\n }\n\n // If a spotify audio\n if (el.textContent.trim() === href) {\n SPOTIFY_REGEX.lastIndex = 0 // Reset regex state\n match = SPOTIFY_REGEX.exec(href)\n if (match && match[1]) {\n el.setAttribute('class', 'markdown-audio-link markdown-audio-link-spotify')\n el.removeAttribute('href')\n\n const embedSrc = `https://open.spotify.com/embed/playlist/${match[1]}`\n\n el.textContent = ''\n\n const ifr = el.ownerDocument.createElement('iframe')\n ifr.setAttribute('frameborder', '0')\n ifr.setAttribute('allowfullscreen', 'true')\n ifr.setAttribute('src', embedSrc)\n ifr.setAttribute('sandbox', 'allow-scripts allow-same-origin allow-popups')\n el.appendChild(ifr)\n\n return\n }\n }\n\n // If a Loom video\n match = href.match(LOOM_REGEX)\n if (match && match[2] && el.textContent.trim() === href) {\n el.setAttribute('class', 'markdown-video-link markdown-video-link-loom')\n el.removeAttribute('href')\n\n const embedSrc = `https://www.loom.com/embed/${match[2]}`\n\n el.textContent = ''\n\n const ifr = el.ownerDocument.createElement('iframe')\n ifr.setAttribute('frameborder', '0')\n ifr.setAttribute('allowfullscreen', 'true')\n ifr.setAttribute('src', embedSrc)\n ifr.setAttribute('sandbox', 'allow-scripts allow-same-origin allow-popups')\n el.appendChild(ifr)\n\n return\n }\n\n // If a d.tube video\n // Only d.tube links contains an image\n const imgEls = el.getElementsByTagName('img')\n\n if (imgEls.length === 1 || el.textContent.trim() === href) {\n D_TUBE_REGEX.lastIndex = 0 // Reset regex state\n match = D_TUBE_REGEX.exec(href)\n // match[2] = username, match[3] object id\n if (match && match[2] && match[3]) {\n el.setAttribute('class', 'markdown-video-link markdown-video-link-dtube')\n el.removeAttribute('href')\n\n const videoHref = `https://emb.d.tube/#!/${match[2]}/${match[3]}`\n\n // el.setAttribute('data-video-href', videoHref)\n el.setAttribute('data-embed-src', videoHref)\n\n //process thumb img element\n if (imgEls.length === 1) {\n const src = imgEls[0].getAttribute('src')\n if (src) {\n const thumbnail = proxifyImageSrc(src.replace(/\\s+/g, ''), 0, 0, 'match')\n const thumbImg = el.ownerDocument.createElement('img')\n\n thumbImg.setAttribute('class', 'no-replace video-thumbnail')\n thumbImg.setAttribute('itemprop', 'thumbnailUrl')\n\n thumbImg.setAttribute('src', thumbnail)\n el.appendChild(thumbImg)\n\n // Remove image.\n el.removeChild(imgEls[0])\n }\n } else {\n el.textContent = '';\n }\n\n const play = el.ownerDocument.createElement('span')\n play.setAttribute('class', 'markdown-video-play')\n\n el.appendChild(play)\n\n return\n }\n }\n D_TUBE_REGEX2.lastIndex = 0 // Reset regex state\n match = D_TUBE_REGEX2.exec(href)\n if (match && match[2] && match[3]) {\n // match[2] = username, match[3] object id\n el.setAttribute('class', 'markdown-video-link markdown-video-link-dtube')\n el.removeAttribute('href')\n el.textContent = '';\n\n const videoHref = `https://emb.d.tube/#!/${match[2]}/${match[3]}`\n\n // el.setAttribute('data-video-href', videoHref);\n el.setAttribute('data-embed-src', videoHref)\n const play = el.ownerDocument.createElement('span')\n play.setAttribute('class', 'markdown-video-play')\n\n el.appendChild(play)\n\n return\n }\n\n // Detect 3Speak\n match = href.match(SPEAK_REGEX)\n if (match) {\n const imgEls = el.getElementsByTagName('img')\n if (imgEls.length === 1 || el.textContent.trim() === href) {\n // match[1] / match[2] = tld , match[3] = embed address\n if ((match[1] || match[2]) && match[3]) {\n const videoHref = `https://play.3speak.tv/watch?v=${match[3]}&mode=iframe`\n el.setAttribute('class', 'markdown-video-link markdown-video-link-speak')\n el.removeAttribute('href')\n el.setAttribute('data-embed-src', videoHref)\n if (el.textContent.trim() === href) {\n el.textContent = ''\n }\n\n if (renderOptions?.embedVideosDirectly) {\n // Waves/thread feed: embed inline but never autoplay. The 3Speak\n // player autoplays by default, which is disorienting in a feed of\n // many videos, so request autoplay=false explicitly. The\n // click-to-play path elsewhere keeps using videoHref via\n // data-embed-src (autoplay after the user clicks is fine).\n const directSrc = `${videoHref}&autoplay=false`\n // Use span (not div) to avoid invalid nesting inside <p> tags\n const wrapper = el.ownerDocument.createElement('span')\n wrapper.setAttribute('class', 'er-speak-frame')\n wrapper.setAttribute('style', 'display:block')\n const iframe = el.ownerDocument.createElement('iframe')\n iframe.setAttribute('class', 'speak-iframe')\n iframe.setAttribute('src', directSrc)\n iframe.setAttribute('title', '3Speak video')\n iframe.setAttribute('allow', 'accelerometer; encrypted-media; gyroscope; picture-in-picture; web-share')\n iframe.setAttribute('allowfullscreen', '')\n wrapper.appendChild(iframe)\n el.appendChild(wrapper)\n el.setAttribute('class', 'markdown-video-link markdown-video-link-speak er-speak')\n } else {\n if (imgEls.length === 1) {\n const src = imgEls[0].getAttribute('src')\n if (src) {\n const thumbnail = proxifyImageSrc(src.replace(/\\s+/g, ''), 0, 0, 'match')\n const thumbImg = el.ownerDocument.createElement('img')\n thumbImg.setAttribute('class', 'no-replace video-thumbnail')\n thumbImg.setAttribute('itemprop', 'thumbnailUrl')\n thumbImg.setAttribute('src', thumbnail)\n el.appendChild(thumbImg)\n // Remove image.\n el.removeChild(imgEls[0])\n }\n }\n\n const play = el.ownerDocument.createElement('span')\n play.setAttribute('class', 'markdown-video-play')\n el.appendChild(play)\n }\n return\n }\n }\n }\n\n // Detect 3Speak Audio\n if (href.match(SPEAK_AUDIO_REGEX) && el.textContent.trim() === href) {\n el.setAttribute('class', 'markdown-audio-link markdown-audio-link-speak')\n el.removeAttribute('href')\n\n const embedSrc = /[?&]iframe=/.test(href) ? href : `${href}&iframe=1`\n const finalSrc = /[?&]mode=/.test(embedSrc) ? embedSrc : `${embedSrc}&mode=compact`\n\n el.textContent = ''\n\n const ifr = el.ownerDocument.createElement('iframe')\n ifr.setAttribute('frameborder', '0')\n ifr.setAttribute('src', finalSrc)\n ifr.setAttribute('sandbox', 'allow-scripts allow-same-origin allow-popups')\n el.appendChild(ifr)\n\n return\n }\n\n // Detect Liketu Speak voice posts: render the cdn.liketu.com audio file as a\n // native player. The link text is descriptive (\"Listen to the original\n // voice\"), so match on the href only, not textContent.\n if (href.match(LIKETU_AUDIO_REGEX)) {\n el.setAttribute('class', 'markdown-audio-link markdown-audio-link-liketu')\n el.removeAttribute('href')\n el.textContent = ''\n\n const audio = el.ownerDocument.createElement('audio')\n audio.setAttribute('controls', '')\n audio.setAttribute('preload', 'metadata')\n audio.setAttribute('src', href)\n el.appendChild(audio)\n\n return\n }\n\n // If tweets\n const matchT = href.match(TWITTER_REGEX)\n if (matchT && el.textContent.trim() === href) {\n TWITTER_REGEX.lastIndex = 0 // Reset for exec() after match()\n const e = TWITTER_REGEX.exec(href)\n if (e) {\n const url = stripHtmlTags(e[0])\n const author = stripHtmlTags(e[1])\n\n // Use proper DOM construction to avoid XSS from unescaped url/author\n const blockquote = el.ownerDocument.createElement('blockquote')\n blockquote.setAttribute('class', 'twitter-tweet')\n\n const p = el.ownerDocument.createElement('p')\n p.textContent = url // textContent automatically escapes\n\n const textNode = el.ownerDocument.createTextNode('- ')\n\n const a = el.ownerDocument.createElement('a')\n a.setAttribute('href', url) // setAttribute escapes automatically\n a.textContent = author // textContent automatically escapes\n\n blockquote.appendChild(p)\n blockquote.appendChild(textNode)\n blockquote.appendChild(a)\n\n if (el.parentNode) {\n el.parentNode.replaceChild(blockquote, el)\n }\n return\n }\n }\n\n if (href.indexOf('https://hivesigner.com/sign/account-witness-vote?witness=') === 0 && forApp) {\n el.setAttribute('class', 'markdown-witnesses-link')\n el.setAttribute('data-href', href)\n el.removeAttribute('href')\n return\n }\n\n if (href.indexOf('hivesigner.com/sign/update-proposal-votes?proposal_ids') >= 0 && forApp) {\n try {\n const m = decodeURI(href).match(/proposal_ids=\\[(\\d+)]/)\n if (m) {\n el.setAttribute('class', 'markdown-proposal-link')\n el.setAttribute('data-href', href)\n el.setAttribute('data-proposal', m[1])\n el.removeAttribute('href')\n return\n }\n } catch (e) {\n // Invalid URI encoding, skip processing\n }\n }\n\n // If nothing matched element as external link so it will be opened in external window\n el.setAttribute('class', 'markdown-external-link')\n\n // Prepend https if no scheme provided.\n // Case-insensitive: schemes are case-insensitive per RFC 3986, so a\n // mixed-case `Https://` must not be treated as scheme-less (which would\n // double-prepend and yield `https://Https://...`).\n if (!(/^((#)|(mailto:)|(\\/(?!\\/))|(((steem|hive|esteem|ecency|https?):)?\\/\\/))/i.test(href))) {\n href = `https://${href}`\n }\n\n if (forApp) {\n el.setAttribute('data-href', href)\n const match = href.match(YOUTUBE_REGEX)\n if (match && match[1]) {\n const vid = match[1]\n el.setAttribute('data-youtube', vid);\n\n //extract start time if available\n const startTime = extractYtStartTime(href);\n if(startTime){\n el.setAttribute('data-start-time', startTime);\n }\n }\n el.removeAttribute('href')\n } else {\n // Same-document links only. This used to match a `#` anywhere in the URL, so any\n // external link ending in `/#anything` was treated as internal: it lost\n // `rel=\"nofollow ugc noopener\"` and opened in the same tab, turning every rendered\n // page into a dofollow link farm for anyone appending a fragment.\n const matchS = href.trim().startsWith('#')\n if(matchS) {\n el.setAttribute('class', 'markdown-internal-link');\n } else {\n el.setAttribute('target', '_blank');\n el.setAttribute('rel', getExternalLinkRel(seoContext));\n }\n el.setAttribute('href', href)\n }\n}\n\n\n\n","import { ARCH_REGEX, DAPPLR_REGEX, LBRY_REGEX, TRUVVL_REGEX, ODYSEE_REGEX, SKATEHIVE_IPFS_REGEX, SKATEHYPE_EMBED_REGEX, BITCHUTE_REGEX, RUMBLE_REGEX, BRIGHTEON_REGEX, VIMEO_EMBED_REGEX, SPEAK_EMBED_REGEX, SPEAK_AUDIO_EMBED_REGEX, VIMM_EMBED_REGEX, D_TUBE_EMBED_REGEX, SPOTIFY_EMBED_REGEX, SOUNDCLOUD_EMBED_REGEX, TWITCH_EMBED_REGEX, YOUTUBE_EMBED_REGEX, BRAND_NEW_TUBE_REGEX, LOOM_EMBED_REGEX, AUREAL_EMBED_REGEX } from '../consts'\nimport { stripQueryString } from '../helper'\nimport { RenderOptions } from '../types'\n\nexport function iframe(el: HTMLElement | null, parentDomain: string = 'ecency.com', forApp: boolean = false, renderOptions?: RenderOptions): void {\n if (!el || !el.parentNode) {\n return;\n }\n const src = el.getAttribute('src');\n if (!src) {\n el.parentNode.removeChild(el);\n return;\n }\n\n // Youtube\n if (src.match(YOUTUBE_EMBED_REGEX)) {\n // strip query string (yt: autoplay=1,controls=0,showinfo=0, etc)\n el.setAttribute('src', stripQueryString(src));\n return;\n }\n\n if (src.match(BITCHUTE_REGEX)) {\n return;\n }\n\n // Vimeo\n const m = src.match(VIMEO_EMBED_REGEX);\n if (m && m.length === 2) {\n const s = `https://player.vimeo.com/video/${m[1]}`;\n el.setAttribute('src', s);\n return;\n }\n\n // Twitch\n if (src.match(TWITCH_EMBED_REGEX)) {\n let s = src;\n // Only add parent if not present\n if (!s.includes('parent=')) {\n const separator = s.includes('?') ? '&' : '?';\n s = `${s}${separator}parent=${parentDomain}`;\n }\n // Only add autoplay if not present\n if (!s.includes('autoplay=')) {\n const separator = s.includes('?') ? '&' : '?';\n s = `${s}${separator}autoplay=false`;\n }\n el.setAttribute('src', s);\n return;\n }\n\n // 3Speak\n if (src.match(SPEAK_EMBED_REGEX)) {\n // Normalize domain to play.3speak.tv for new embed player\n // Use (?:play\\.)? to avoid doubling the prefix on already-correct URLs\n let normalizedSrc = src.replace(/(?:play\\.)?3speak\\.[a-z]+/i, 'play.3speak.tv');\n\n // Normalize /embed? to /watch? for proper embed endpoint\n normalizedSrc = normalizedSrc.replace(/\\/embed\\?/, '/watch?');\n\n // Ensure mode=iframe parameter is present for minimal embed UI\n const hasMode = /[?&]mode=/.test(normalizedSrc);\n if (!hasMode) {\n normalizedSrc = `${normalizedSrc}&mode=iframe`;\n }\n\n // Waves/thread feeds embed inline (embedVideosDirectly) and must never\n // autoplay: force autoplay=false even when the src already carries\n // autoplay=true. Everywhere else, add autoplay=true only when absent so\n // an author-supplied value is preserved.\n const hasAutoplay = /[?&]autoplay=/.test(normalizedSrc);\n let s: string;\n if (renderOptions?.embedVideosDirectly) {\n s = hasAutoplay\n ? normalizedSrc.replace(/([?&]autoplay=)[^&]*/i, '$1false')\n : `${normalizedSrc}&autoplay=false`;\n } else {\n s = hasAutoplay ? normalizedSrc : `${normalizedSrc}&autoplay=true`;\n }\n\n // Add mobile layout parameter when rendering for app\n if (forApp && !/[?&]layout=/.test(s)) {\n s = `${s}&layout=mobile`;\n }\n\n el.setAttribute('src', s);\n el.setAttribute('class', 'speak-iframe');\n return;\n }\n\n // 3Speak Audio\n if (src.match(SPEAK_AUDIO_EMBED_REGEX)) {\n let normalizedSrc = src;\n\n // Ensure iframe=1 parameter for clean embedding\n if (!/[?&]iframe=/.test(normalizedSrc)) {\n normalizedSrc = `${normalizedSrc}&iframe=1`;\n }\n\n // Default to compact mode if no mode specified\n if (!/[?&]mode=/.test(normalizedSrc)) {\n normalizedSrc = `${normalizedSrc}&mode=compact`;\n }\n\n el.setAttribute('src', normalizedSrc);\n el.setAttribute('class', 'speak-audio-iframe');\n el.setAttribute('frameborder', '0');\n el.setAttribute('sandbox', 'allow-scripts allow-same-origin allow-popups');\n return;\n }\n\n // Spotify\n if (src.match(SPOTIFY_EMBED_REGEX)) {\n el.setAttribute('src', src);\n el.setAttribute('sandbox', 'allow-scripts allow-same-origin allow-popups');\n el.setAttribute('frameborder', '0');\n return;\n }\n\n // Soundcloud\n if (src.match(SOUNDCLOUD_EMBED_REGEX)) {\n const match = src.match(/url=(.+?)(?:&|$)/); // Handle & or end of string\n if (match && match[1]) {\n 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`;\n el.setAttribute('src', s);\n }\n return; // Always return, even if match fails\n }\n\n // Dtube\n if (src.match(D_TUBE_EMBED_REGEX)) {\n el.setAttribute('src', src);\n el.setAttribute('sandbox', 'allow-scripts allow-same-origin');\n el.setAttribute('frameborder', '0');\n el.setAttribute('allowfullscreen', 'true');\n return;\n }\n\n // VIMM\n if (src.match(VIMM_EMBED_REGEX)) {\n el.setAttribute('src', src);\n el.setAttribute('sandbox', 'allow-scripts allow-same-origin allow-popups');\n el.setAttribute('frameborder', '0');\n el.setAttribute('allowfullscreen', 'true');\n return;\n }\n\n // Dapplr\n if (src.match(DAPPLR_REGEX)) {\n el.setAttribute('src', src);\n el.setAttribute('sandbox', 'allow-scripts allow-same-origin');\n el.setAttribute('frameborder', '0');\n el.setAttribute('allowfullscreen', 'true');\n return;\n }\n\n // Truvvl\n if (src.match(TRUVVL_REGEX)) {\n el.setAttribute('src', src);\n el.setAttribute('sandbox', 'allow-scripts allow-same-origin allow-popups');\n el.setAttribute('frameborder', '0');\n el.setAttribute('class', 'portrait-embed');\n el.setAttribute('allowfullscreen', 'true');\n return;\n }\n\n // LBRY.tv\n if (src.match(LBRY_REGEX)) {\n el.setAttribute('src', src);\n el.setAttribute('frameborder', '0');\n return;\n }\n\n // ODYSEE\n if (src.match(ODYSEE_REGEX)) {\n el.setAttribute('src', src);\n el.setAttribute('frameborder', '0');\n return;\n }\n\n // IPFS Skatehive\n // The skatehive IPFS gateway serves the raw video file directly (content-type\n // video/mp4), so an <iframe src=…> loads a browser *media document*, which\n // Chrome autoplays on load regardless of the `allow` attribute. Render a real\n // <video controls> instead so playback is user-initiated and never autoplays\n // (the sanitizer keeps only src/controls/poster on <video>, so an autoplay\n // attribute could not survive here anyway). Same behaviour in waves and posts.\n if (src.match(SKATEHIVE_IPFS_REGEX)) {\n const video = el.ownerDocument.createElement('video');\n video.setAttribute('src', src);\n video.setAttribute('controls', '');\n el.parentNode.insertBefore(video, el);\n el.parentNode.removeChild(el);\n return;\n }\n\n // Skatehype\n if (src.match(SKATEHYPE_EMBED_REGEX)) {\n // Force https:// for http:// and protocol-relative URLs so the embed\n // isn't blocked as mixed content on the https app.\n const normalizedSrc = src.replace(/^(https?:)?\\/\\//i, 'https://');\n el.setAttribute('src', normalizedSrc);\n el.setAttribute('frameborder', '0');\n el.setAttribute('allowfullscreen', 'true');\n return;\n }\n\n // archive.org\n if (src.match(ARCH_REGEX)) {\n el.setAttribute('src', src);\n return;\n }\n\n // Rumble\n if (src.match(RUMBLE_REGEX)) {\n el.setAttribute('src', src);\n el.setAttribute('frameborder', '0');\n return;\n }\n\n // Brighteon\n if (src.match(BRIGHTEON_REGEX)) {\n el.setAttribute('src', src);\n el.setAttribute('frameborder', '0');\n return;\n }\n\n // Brandnew Tube\n if (src.match(BRAND_NEW_TUBE_REGEX)) {\n el.setAttribute('src', src);\n el.setAttribute('frameborder', '0');\n return;\n }\n\n // Loom\n if (src.match(LOOM_EMBED_REGEX)) {\n el.setAttribute('src', src);\n el.setAttribute('frameborder', '0');\n return;\n }\n\n // Aureal\n if (src.match(AUREAL_EMBED_REGEX)) {\n // Normalize protocol-relative URLs to https://\n const normalizedSrc = src.startsWith('//') ? `https:${src}` : src;\n el.setAttribute('src', normalizedSrc);\n el.setAttribute('frameborder', '0');\n return;\n }\n\n const replaceNode = el.ownerDocument.createElement('div');\n replaceNode.setAttribute('class', 'unsupported-iframe');\n replaceNode.textContent = `(Unsupported ${src})`;\n if (el.parentNode) {\n el.parentNode.insertBefore(replaceNode, el);\n el.parentNode.removeChild(el);\n }\n}\n","export function p(el: HTMLElement): void {\n const dir = el.getAttribute('dir')\n if (!dir) {\n el.setAttribute('dir', 'auto')\n }\n}\n","import { IMG_REGEX, SECTION_LIST } from '../consts'\nimport { proxifyImageSrc, getProxyBase } from '../proxify-image-src'\nimport { isValidPermlink, isValidUsername, sanitizePermlink } from \"../helper\";\nimport { createImageHTML } from \"./img.method\";\nimport { RenderOptions } from \"../types\";\n\nexport function linkify(content: string, forApp: boolean, renderOptions?: RenderOptions): string {\n // Tags\n content = content.replace(/(^|\\s|>)(#[-a-z\\d]+)/gi, tag => {\n if (/#[\\d]+$/.test(tag)) return tag // do not allow only numbers (like #1)\n const preceding = /^\\s|>/.test(tag) ? tag[0] : '' // space or closing tag (>)\n tag = tag.replace(/^>/, '') // strip the leading > we captured as the precursor\n const tag2 = tag.trim().substring(1)\n const tagLower = tag2.toLowerCase()\n\n if (!forApp) {\n // No tag route to land on -> inert span rather than a dead, crawlable /trending link.\n if (renderOptions?.inertAuthorAndTagChips) {\n return `${preceding}<span class=\"er-tag er-tag-link\">${tag.trim()}</span>`\n }\n return `${preceding}<a class=\"er-tag er-tag-link\" href=\"/trending/${tagLower}\">${tag.trim()}</a>`\n }\n return `${preceding}<a class=\"markdown-tag-link\" data-tag=\"${tagLower}\">${tag.trim()}</a>`\n })\n\n // User mentions - use placeholders for enhanced HTML to prevent image regex\n // from matching URLs inside the avatar <img src=\"...\"> attribute\n const authorPlaceholders: { placeholder: string; html: string }[] = []\n\n content = content.replace(\n /(^|[^a-zA-Z0-9_!#$%&*@@/]|(^|[^a-zA-Z0-9_+~.-/]))[@@]([a-z][-.a-z\\d^/]+[a-z\\d])/gi,\n (match, preceeding1, preceeding2, user) => {\n const userLower = user.toLowerCase()\n const preceedings = (preceeding1 || '') + (preceeding2 || '')\n if (userLower.indexOf('/') === -1 && isValidUsername(user)) {\n if (!forApp) {\n const avatarSrc = `${getProxyBase()}/u/${userLower}/avatar/small`\n const inner = `<img class=\"er-author-link-image\" src=\"${avatarSrc}\" alt=\"${userLower}\"/>@${userLower}`\n // No profile route to land on -> inert span rather than a dead, crawlable /@user link.\n const html = renderOptions?.inertAuthorAndTagChips\n ? `${preceedings}<span class=\"er-author er-author-link\">${inner}</span>`\n : `${preceedings}<a class=\"er-author er-author-link\" href=\"/@${userLower}\">${inner}</a>`\n const placeholder = `\\u200C${authorPlaceholders.length}\\u200C`\n authorPlaceholders.push({ placeholder, html })\n return placeholder\n }\n return `${preceedings}<a class=\"markdown-author-link\" data-author=\"${userLower}\">@${user}</a>`\n } else {\n return match\n }\n }\n )\n\n // internal links with category: /category/@user/permlink\n content = content.replace(\n /(^|\\s)\\/([a-z0-9-]+)\\/@([\\w.\\d-]+)\\/(\\S+)/gi, (match, preceding, tag, author, p3) => {\n const authorLower = author.toLowerCase();\n if (!isValidUsername(authorLower)) return match;\n const permlink = sanitizePermlink(p3);\n if (!isValidPermlink(permlink)) return match;\n\n if (SECTION_LIST.includes(permlink)) {\n // A profile section, not a post. A consumer with no profile route sends\n // it to `/:author/:permlink` and tries to load a post called `wallet`.\n const external = renderOptions?.externalProfileBase\n const attrs = forApp || external\n ? `href=\"${external ?? 'https://ecency.com'}/@${authorLower}/${permlink}\"`\n : `href=\"/@${authorLower}/${permlink}\"`\n return `${preceding}<a class=\"markdown-profile-link\" ${attrs}>@${authorLower}/${permlink}</a>`\n } else {\n const attrs = forApp ? `data-author=\"${authorLower}\" data-tag=\"${tag}\" data-permlink=\"${permlink}\"` : `href=\"/@${authorLower}/${permlink}\"`\n return `${preceding}<a class=\"markdown-post-link\" ${attrs}>@${authorLower}/${permlink}</a>`\n }\n }\n )\n\n // internal links — require leading / to distinguish /@user/permlink (Hive links)\n // from @scope/package (npm packages, GitHub orgs, etc.)\n content = content.replace(\n /((^|\\s)\\/@[\\w.\\d-]+)\\/(\\S+)/gi, (match, u, _p1, p3) => {\n const uu = u.trim().toLowerCase().replace('/@', '').replace('@', '');\n const permlink = sanitizePermlink(p3);\n if (!isValidPermlink(permlink)) return match;\n\n if (SECTION_LIST.includes(permlink)) {\n // Same as above: a section name, routed as a permlink by any consumer\n // whose only match is `/:author/:permlink`.\n const external = renderOptions?.externalProfileBase\n const attrs = forApp || external\n ? `href=\"${external ?? 'https://ecency.com'}/@${uu}/${permlink}\"`\n : `href=\"/@${uu}/${permlink}\"`\n return ` <a class=\"markdown-profile-link\" ${attrs}>@${uu}/${permlink}</a>`\n } else {\n const attrs = forApp ? `data-author=\"${uu}\" data-tag=\"post\" data-permlink=\"${permlink}\"` : `href=\"/@${uu}/${permlink}\"`\n return ` <a class=\"markdown-post-link\" ${attrs}>@${uu}/${permlink}</a>`\n }\n }\n )\n\n // Image links\n // Process images before restoring author placeholders to avoid\n // the image regex matching URLs inside enhanced author HTML\n let firstImageUsed = false;\n\n content = content.replace(IMG_REGEX, (imglink) => {\n const isLCP = !firstImageUsed;\n firstImageUsed = true;\n return createImageHTML(imglink, isLCP, forApp);\n });\n\n // Restore author placeholders\n authorPlaceholders.forEach(({ placeholder, html }) => {\n content = content.replace(placeholder, html);\n });\n\n return content\n}\n","import { IMG_REGEX, YOUTUBE_REGEX, WHITE_LIST, DOMParser, POST_REGEX } from '../consts'\nimport { extractYtStartTime, isValidPermlink, isValidUsername, sanitizePermlink } from '../helper'\nimport { proxifyImageSrc } from '../proxify-image-src'\nimport { linkify } from './linkify.method'\nimport {createImageHTML} from \"./img.method\";\nimport { RenderOptions } from \"../types\";\n\nfunction hasAncestor(node: Node, tagNames: string[]): boolean {\n let current = node.parentNode\n while (current) {\n if (tagNames.includes(current.nodeName.toLowerCase())) {\n return true\n }\n current = current.parentNode\n }\n return false\n}\n\nconst CHIP_CLASSES = ['er-author-link', 'er-tag-link']\n\n/**\n * True when the node already sits inside a rendered `@user` / `#tag` chip.\n *\n * The `'a'` guard below is what normally stops a chip's own `@user` text from\n * being linkified again: traverse() recurses into the node text() inserted, so\n * without a stop condition the chip's label is re-linkified into a nested chip\n * on every pass, forever. With `RenderOptions.inertAuthorAndTagChips` the chip\n * is a `<span>`, which the tag-name guard does not catch, so match on the chip\n * classes instead. a.method.ts uses the same class-based \"already processed\"\n * signal.\n *\n * Only consulted on inert renders. `class` is author-writable (the sanitizer\n * allows it on `span` and runs *after* traverse), so a post body containing\n * `<span class=\"er-tag-link\">@alice</span>` would otherwise let an author\n * suppress linkification, and the later bare-image and video enhancements, for\n * every reader on the default render path. Gating keeps that reachable only\n * where the inert chips actually need it. Tokens are compared exactly so\n * unrelated names like `custom-er-tag-link-label` do not match.\n */\nfunction hasChipAncestor(node: Node): boolean {\n let current: Node | null = node.parentNode\n while (current) {\n const el = current as HTMLElement\n const className =\n typeof el.getAttribute === 'function' ? el.getAttribute('class') : null\n if (className && className.split(/\\s+/).some((token) => CHIP_CLASSES.includes(token))) {\n return true\n }\n current = current.parentNode\n }\n return false\n}\n\nexport function text(node: HTMLElement | null, forApp: boolean, renderOptions?: RenderOptions): void {\n if (!node || !node.parentNode) {\n return\n }\n\n // Skip text nodes inside links, inline code, or code blocks (check all ancestors)\n if (hasAncestor(node, ['a', 'code', 'pre'])) {\n return\n }\n\n // Inert chips are spans, so they need the class-based guard too. Kept behind\n // the option so the default render path is untouched — see hasChipAncestor.\n if (renderOptions?.inertAuthorAndTagChips && hasChipAncestor(node)) {\n return\n }\n\n const nodeValue = node.nodeValue || ''\n const linkified = linkify(nodeValue, forApp, renderOptions)\n if (linkified !== nodeValue) {\n const doc = DOMParser.parseFromString(\n `<span class=\"wr\">${linkified}</span>`,\n 'text/html'\n )\n const replaceNode = (doc as any).body?.firstChild || doc.firstChild\n\n if (replaceNode) {\n node.parentNode.insertBefore(replaceNode, node)\n node.parentNode.removeChild(node)\n }\n return\n }\n\n if (nodeValue.match(IMG_REGEX)) {\n const isLCP = false; // Traverse handles LCP; no need to double-count\n const imageHTML = createImageHTML(nodeValue, isLCP, forApp);\n const doc = DOMParser.parseFromString(imageHTML, 'text/html');\n const replaceNode = (doc as any).body?.firstChild || doc.firstChild\n if (replaceNode) {\n node.parentNode.replaceChild(replaceNode, node);\n }\n return; // Early return after replacing node\n }\n // If a youtube video\n if (nodeValue.match(YOUTUBE_REGEX)) {\n const e = YOUTUBE_REGEX.exec(nodeValue)\n if (e && e[1]) {\n const vid = e[1]\n const thumbnail = proxifyImageSrc(`https://img.youtube.com/vi/${vid.split('?')[0]}/hqdefault.jpg`, 0, 0, 'match')\n const embedSrc = `https://www.youtube.com/embed/${vid}?autoplay=1`\n const startTime = extractYtStartTime(nodeValue);\n\n // Create container paragraph\n const container = node.ownerDocument.createElement('p')\n\n // Create anchor element\n const anchor = node.ownerDocument.createElement('a')\n anchor.setAttribute('class', 'markdown-video-link markdown-video-link-youtube')\n anchor.setAttribute('data-embed-src', embedSrc)\n anchor.setAttribute('data-youtube', vid)\n if (startTime) {\n anchor.setAttribute('data-start-time', startTime)\n }\n\n // Create and append thumbnail image\n const thumbImg = node.ownerDocument.createElement('img')\n thumbImg.setAttribute('class', 'no-replace video-thumbnail')\n thumbImg.setAttribute('src', thumbnail)\n anchor.appendChild(thumbImg)\n\n // Create and append play button\n const play = node.ownerDocument.createElement('span')\n play.setAttribute('class', 'markdown-video-play')\n anchor.appendChild(play)\n\n // Assemble and replace\n container.appendChild(anchor)\n node.parentNode.replaceChild(container, node)\n return; // Early return after replacing node\n }\n }\n if (nodeValue && typeof nodeValue === 'string') {\n const postMatch = nodeValue.trim().match(POST_REGEX)\n if (postMatch && WHITE_LIST.includes(postMatch[1].replace(/^www\\./,''))) {\n const tag = postMatch[2]\n const author = postMatch[3].replace('@', '')\n const permlink = sanitizePermlink(postMatch[4])\n\n // Validate tag to prevent attribute breakout XSS\n // Allow only alphanumeric, hyphens, and underscores\n if (!tag || !/^[a-z0-9_-]+$/i.test(tag)) return\n if (!isValidUsername(author)) return\n if (!isValidPermlink(permlink)) return\n\n const attrs = forApp ? `data-tag=\"${tag}\" data-author=\"${author}\" data-permlink=\"${permlink}\" class=\"markdown-post-link\"` : `class=\"markdown-post-link\" href=\"/@${author}/${permlink}\"`\n const doc = DOMParser.parseFromString(\n `<a ${attrs}>/@${author}/${permlink}</a>`,\n 'text/html'\n )\n const replaceNode = (doc as any).body?.firstChild || doc.firstChild\n if (replaceNode) {\n node.parentNode.replaceChild(replaceNode, node)\n }\n }\n }\n}\n","import { a } from './a.method'\nimport { iframe } from './iframe.method'\nimport { img } from './img.method'\nimport { p } from './p.method'\nimport { text } from './text.method'\nimport { RenderOptions, SeoContext } from '../types'\n\nexport function traverse(node: Node, forApp: boolean, depth = 0, state = { firstImageFound: false }, parentDomain: string = 'ecency.com', seoContext?: SeoContext, renderOptions?: RenderOptions): void {\n if (!node || !node.childNodes) {\n return\n }\n\n // Walk siblings using nextSibling instead of indexing into the live NodeList.\n // node.childNodes is live: when a handler removes or replaces a child the\n // indices shift, causing index-based loops to skip nodes. Capturing\n // nextSibling before running handlers gives a stable \"next\" pointer that\n // isn't affected by mutations to the current child.\n let child = node.firstChild\n while (child) {\n const next = child.nextSibling\n const prev = child.previousSibling\n\n if (child.nodeName.toLowerCase() === 'a') {\n a(<HTMLElement>child, forApp, parentDomain, seoContext, renderOptions)\n }\n if (child.nodeName.toLowerCase() === 'iframe') {\n iframe(<HTMLElement>child, parentDomain, forApp, renderOptions)\n }\n if (child.nodeName === '#text') {\n text(<HTMLElement>child, forApp, renderOptions)\n }\n if (child.nodeName.toLowerCase() === 'img') {\n img(<HTMLElement>child, state, forApp)\n }\n if (child.nodeName.toLowerCase() === 'p') {\n p(<HTMLElement>child)\n }\n\n if (child.parentNode) {\n // Child is still in the DOM — recurse into it normally\n traverse(child, forApp, depth + 1, state, parentDomain, seoContext, renderOptions)\n } else {\n // Child was removed or replaced by a handler. If a replacement was\n // inserted (e.g. text() wraps a URL in <span>, a() swaps a tweet link\n // for <blockquote>), it now sits between `prev` and `next` in the live\n // childNodes. Detect it by comparing next.previousSibling to the\n // captured `prev` — if they differ a new node was inserted.\n const possibleReplacement = next ? next.previousSibling : node.lastChild\n if (possibleReplacement && possibleReplacement !== prev && possibleReplacement.parentNode === node) {\n traverse(possibleReplacement, forApp, depth + 1, state, parentDomain, seoContext, renderOptions)\n }\n }\n\n child = next\n }\n}\n","export function cleanReply(s: string): string {\n return (s ? s.split('\\n')\n .filter(item => item.toLowerCase().includes('posted using [partiko') === false)\n .filter(item => item.toLowerCase().includes('posted using [dapplr') === false)\n .filter(item => item.toLowerCase().includes('posted using [leofinance') === false)\n .filter(item => item.toLowerCase().includes('posted via [neoxian') === false)\n .filter(item => item.toLowerCase().includes('posted using [neoxian') === false)\n .filter(item => item.toLowerCase().includes('posted via [first context') === false)\n .filter(item => item.toLowerCase().includes('posted with [stemgeeks') === false)\n .filter(item => item.toLowerCase().includes('posted using [bilpcoin') === false)\n .filter(item => item.toLowerCase().includes('posted using [inleo') === false)\n .filter(item => item.toLowerCase().includes('posted using [sportstalksocial]') === false)\n .filter(item => item.toLowerCase().includes('<center><sub>[posted using aeneas.blog') === false)\n .filter(item => item.toLowerCase().includes('<center><sub>posted via [proofofbrain.io') === false)\n .filter(item => item.toLowerCase().includes('<center>posted on [hypnochain') === false)\n .filter(item => item.toLowerCase().includes('<center><sub>posted via [weedcash.network') === false)\n .filter(item => item.toLowerCase().includes('<center>posted on [naturalmedicine.io') === false)\n .filter(item => item.toLowerCase().includes('<center><sub>posted via [musicforlife.io') === false)\n .filter(item => item.toLowerCase().includes('if the truvvl embed is unsupported by your current frontend, click this link to view this story') === false)\n .filter(item => item.toLowerCase().includes('<center><em>posted from truvvl') === false)\n .filter(item => item.toLowerCase().includes('view this post <a href=\"https://travelfeed.io/') === false)\n .filter(item => item.toLowerCase().includes('read this post on travelfeed.io for the best experience') === false)\n .filter(item => item.toLowerCase().includes('posted via <a href=\"https://www.dporn.co/\"') === false)\n .filter(item => item.toLowerCase().includes('▶️ [watch on 3speak](https://3speak') === false)\n .filter(item => item.toLowerCase().includes('<sup><sub>posted via [inji.com]') === false)\n .filter(item => item.toLowerCase().includes('view this post on [liketu]') === false)\n .filter(item => {\n // Match the actual Liketu Speak boilerplate footer (both distinctive\n // parts) so a legitimate reply that merely mentions the phrase survives.\n const l = item.toLowerCase();\n return !(l.includes('posted from liketu speak') && l.includes('auto-transcrib'));\n })\n .filter(item => item.toLowerCase().includes('[via Inbox]') === false)\n .filter(item => item.toLowerCase().includes('<sub>[via apps from](') === false)\n .join('\\n') : '')\n .replace('Posted via <a href=\"https://d.buzz\" data-link=\"promote-link\">D.Buzz</a>', '')\n .replace('<div class=\"pull-right\"><a href=\"/@hive.engage\">![](https://i.imgur.com/XsrNmcl.png)</a></div>', '')\n .replace('<div><a href=\"https://engage.hivechain.app\">![](https://i.imgur.com/XsrNmcl.png)</a></div>', '')\n .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>`, '')\n}\n","import { traverse } from './traverse.method'\nimport { sanitizeHtml } from './sanitize-html.method'\nimport { moveBlockClosingTagOutOfParagraph, removeDuplicateAttributes } from '../helper'\nimport { DOMParser, XMLSerializer, ENTITY_REGEX } from '../consts'\nimport { Remarkable } from 'remarkable'\nimport { linkify } from 'remarkable/linkify'\nimport * as htmlparser2 from 'htmlparser2'\nimport * as domSerializerModule from 'dom-serializer'\nimport { RenderOptions, SeoContext } from '../types'\n\nconst domSerializer = (domSerializerModule as any).default || domSerializerModule\n\n// Conditionally load lolight for syntax highlighting (Node.js only)\n// Browser builds will gracefully handle missing lolight by using fallback\ntype Lolight = typeof import('lolight').default\nlet lolightPromise: Promise<Lolight | null> | null = null\nlet lolightModule: Lolight | null = null\n\nasync function loadLolight() {\n if (typeof window !== 'undefined') {\n // Skip in browser environment\n return null\n }\n\n if (lolightModule) {\n return lolightModule\n }\n\n if (!lolightPromise) {\n lolightPromise = import('lolight')\n .then((mod) => {\n lolightModule = mod.default || mod\n return lolightModule\n })\n .catch(() => {\n lolightModule = null\n return null\n })\n }\n\n return lolightPromise\n}\n\n// Synchronous wrapper for backward compatibility\nfunction getLolightInstance() {\n return lolightModule\n}\n\n// Pre-load lolight when module is imported (Node.js only)\nif (typeof window === 'undefined') {\n loadLolight().catch(() => {\n // Silently fail if lolight is not available\n })\n}\n\n/**\n * Fixes block-level HTML tags that Remarkable incorrectly wraps inside <p> tags.\n *\n * Problem: When Remarkable encounters block-level HTML tags (like <center>, <div>)\n * with blank lines after them, it generates malformed HTML like:\n * <p><center></p>\n * <p>content</p>\n * <p></center></p>\n *\n * This function repairs such patterns by:\n * 1. Extracting block-level tags from paragraph wrappers\n * 2. Removing empty paragraphs created by this mismatch\n *\n * @param html - The HTML string to fix\n * @returns The repaired HTML string\n */\n// Block-level tags that should never be wrapped in <p> tags. Defined at\n// module scope so the alternation string and the Set used by the\n// non-regex closing pass stay in sync.\nconst BLOCK_TAGS_ALTERNATION = 'center|div|table|figure|section|article|aside|header|footer|nav|main'\nconst BLOCK_TAGS_SET = new Set(BLOCK_TAGS_ALTERNATION.split('|'))\n\nfunction fixBlockLevelTagsInParagraphs(html: string): string {\n // Pattern 1: <p><tag></p> - opening tag wrapped in <p>\n // Replace with just <tag> (remove the wrapping <p>)\n const openingPattern = new RegExp(`<p>(<(?:${BLOCK_TAGS_ALTERNATION})(?:\\\\s[^>]*)?>)<\\\\/p>`, 'gi')\n html = html.replace(openingPattern, '$1')\n\n // Pattern 2: <p></tag></p> - closing tag wrapped in <p>\n // Replace with just </tag> (remove the wrapping <p>)\n const closingPattern = new RegExp(`<p>(<\\\\/(?:${BLOCK_TAGS_ALTERNATION})>)<\\\\/p>`, 'gi')\n html = html.replace(closingPattern, '$1')\n\n // Pattern 3: <p><tag><br> or <p><tag> at start of <p>\n // This handles cases where the tag is at the start but followed by content\n const startPattern = new RegExp(`<p>(<(?:${BLOCK_TAGS_ALTERNATION})(?:\\\\s[^>]*)?>)(?:<br>)?\\\\s*`, 'gi')\n html = html.replace(startPattern, '$1<p>')\n\n // Pattern 4: </tag></p> or <br>\\n</tag></p> - closing tag at end of <p>\n // Done as a single linear pass instead of a regex. The previous form\n // `\\s*(?:<br>)?\\s*(<\\/(?:…)>)<\\/p>` had two unanchored `\\s*`\n // quantifiers that backtracked quadratically on whitespace-heavy\n // inputs with no matching closing tag.\n html = moveBlockClosingTagOutOfParagraph(html, BLOCK_TAGS_SET)\n\n // Clean up any empty paragraphs that may have been created\n html = html.replace(/<p>\\s*<\\/p>/g, '')\n html = html.replace(/<p><br>\\s*<\\/p>/g, '')\n\n return html\n}\n\nexport function markdownToHTML(input: string, forApp: boolean, parentDomain: string = 'ecency.com', seoContext?: SeoContext, renderOptions?: RenderOptions): string {\n // Internalize leofinance.io links\n input = input.replace(new RegExp(\"https://leofinance.io/threads/view/\",\"g\"), \"/@\");\n input = input.replace(new RegExp(\"https://leofinance.io/posts/\",\"g\"), \"/@\");\n input = input.replace(new RegExp(\"https://leofinance.io/threads/\",\"g\"), \"/@\");\n input = input.replace(new RegExp(\"https://inleo.io/threads/view/\",\"g\"), \"/@\");\n input = input.replace(new RegExp(\"https://inleo.io/posts/\",\"g\"), \"/@\");\n input = input.replace(new RegExp(\"https://inleo.io/threads/\",\"g\"), \"/@\");\n\n\n const md = new Remarkable({\n html: true,\n breaks: true,\n typographer: false,\n highlight: function (str: string) {\n const lolightInstance = getLolightInstance()\n if (!lolightInstance) {\n // Fallback when lolight is not available\n return str\n }\n\n try {\n const tokens = lolightInstance.tok(str);\n return tokens.map(\n (token: string[]) => `<span class=\"ll-${token[0]}\">${token[1]}</span>`\n ).join('')\n } catch (err) { console.error(err) }\n\n return str\n }\n }).use(linkify)\n md.core.ruler.enable([\n 'abbr'\n ]);\n md.block.ruler.enable([\n 'footnote',\n 'deflist'\n ]);\n md.inline.ruler.enable([\n 'footnote_inline',\n 'ins',\n 'mark',\n 'sub',\n 'sup'\n ]);\n const serializer = new XMLSerializer()\n\n if (!input) {\n return ''\n }\n\n let output = '';\n\n // Replace entities with deterministic placeholders to preserve them during rendering\n const entities = input.match(ENTITY_REGEX);\n const entityPlaceholders: string[] = [];\n\n if (entities && forApp) {\n // Deduplicate entities to avoid duplicate placeholders\n const uniqueEntities = [...new Set(entities)];\n uniqueEntities.forEach((entity, index) => {\n // Use markdown-inert Unicode placeholder (zero-width spaces)\n const placeholder = `\\u200B${index}\\u200B`;\n entityPlaceholders.push(entity);\n // Replace all occurrences of this entity\n input = input.split(entity).join(placeholder);\n })\n }\n\n\n try {\n output = md.render(input)\n\n // Fix malformed block-level HTML tags that Remarkable wraps in <p> tags\n // This prevents \"Opening and ending tag mismatch\" errors from DOMParser\n output = fixBlockLevelTagsInParagraphs(output)\n\n const doc = DOMParser.parseFromString(`<body id=\"root\">${removeDuplicateAttributes(output)}</body>`, 'text/html')\n\n traverse(doc as any, forApp, 0, { firstImageFound: false }, parentDomain, seoContext, renderOptions)\n\n output = serializer.serializeToString(doc)\n } catch (error) {\n // @xmldom/xmldom is stricter than old xmldom and throws ParseError for malformed HTML\n // Instead of returning empty string (bad UX), attempt graceful recovery\n try {\n // Strategy:\n // 1. Pre-sanitize to remove XSS vectors\n // 2. Use lenient htmlparser2 to auto-repair malformed HTML (auto-close unclosed tags)\n // 3. Serialize the repaired HTML\n // 4. Re-parse with @xmldom/xmldom (now well-formed)\n // 5. Traverse and serialize as normal\n // Reuse the markdown output already produced before the failing\n // DOMParser pass — `md.render(input)` is the expensive step and\n // re-running it costs ~100 ms per fallback hit on a 60 KB body.\n const preSanitized = sanitizeHtml(output)\n\n // Use htmlparser2 to parse malformed HTML leniently\n const dom = htmlparser2.parseDocument(preSanitized, {\n // lenient options - don't throw on malformed HTML\n lowerCaseTags: false,\n lowerCaseAttributeNames: false,\n })\n\n // Serialize back to well-formed HTML (htmlparser2 auto-closes tags)\n const repairedHtml = domSerializer(dom.children)\n\n // Now parse the well-formed HTML with @xmldom/xmldom\n const doc = DOMParser.parseFromString(`<body id=\"root\">${removeDuplicateAttributes(repairedHtml)}</body>`, 'text/html')\n\n traverse(doc as any, forApp, 0, { firstImageFound: false }, parentDomain, seoContext, renderOptions)\n\n output = serializer.serializeToString(doc)\n } catch (fallbackError) {\n // If DOM parsing fails, sanitize the Remarkable HTML output directly.\n // This skips the traverse() image proxy/link rewriting but preserves\n // readable HTML content instead of showing escaped tags.\n output = sanitizeHtml(output || md.render(input))\n }\n }\n\n // Restore original entities from placeholders\n if (forApp && output && entityPlaceholders.length > 0) {\n entityPlaceholders.forEach((entity, index) => {\n const placeholder = `\\u200B${index}\\u200B`;\n // Replace all occurrences of the placeholder\n output = output.split(placeholder).join(entity);\n })\n }\n\n output = output\n .replace(/ xmlns=\"http:\\/\\/www.w3.org\\/1999\\/xhtml\"/g, '')\n // Strip full HTML document wrapper (native browser DOMParser wraps in <html><head><body>)\n .replace(/^<\\?xml[^?]*\\?>/, '')\n .replace(/^<!DOCTYPE[^>]*>/i, '')\n .replace(/<\\/?html[^>]*>/g, '')\n .replace(/<head[^>]*>[\\s\\S]*?<\\/head>/g, '')\n .replace('<body id=\"root\">', '')\n .replace('</body>', '')\n .trim()\n\n return sanitizeHtml(output)\n}\n","import { Remarkable } from 'remarkable'\nimport { linkify } from 'remarkable/linkify'\nimport { sanitizeHtml } from './sanitize-html.method'\n\nlet mdInstance: Remarkable | null = null\n\nfunction getMd(): Remarkable {\n if (!mdInstance) {\n mdInstance = new Remarkable({\n html: true,\n breaks: true,\n typographer: false\n }).use(linkify)\n }\n return mdInstance\n}\n\n/**\n * Lightweight markdown-to-HTML conversion with sanitization.\n * Unlike the full `markdownToHTML`, this skips Hive-specific transforms\n * (image proxying, link internalizing, DOM traversal, etc.).\n *\n * Intended for editor input (TipTap), chat messages, and other contexts\n * where simple markdown rendering is sufficient.\n */\nexport function simpleMarkdownToHTML(input: string): string {\n if (!input) return ''\n\n const html = getMd().render(input)\n return sanitizeHtml(html)\n}\n","import { LRUCache } from 'lru-cache'\n\n// A single feed page calls catchPostImage 3× per entry (blur 0×0, grid, row)\n// plus postBodySummary, so 20 entries already produce ~80 keys. The previous\n// max of 60 caused constant eviction and forced re-rendering of full markdown\n// during SSR fan-out.\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nlet cache = new LRUCache<string, any>({ max: 500 })\n\nexport function setCacheSize(size: number): void {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n cache = new LRUCache<string, any>({ max: size })\n}\n\nexport function cacheGet<T extends unknown>(key: string): T {\n return cache.get(key) as T\n}\n\nexport function cacheSet(key: string, value: unknown): void {\n cache.set(key, value)\n}\n","import { makeEntryCacheKey } from './helper'\nimport { cleanReply, markdownToHTML } from './methods'\nimport { cacheGet, cacheSet } from './cache'\nimport { Entry, RenderOptions, SeoContext } from './types'\n\n// Warn when a single markdown render exceeds this threshold. Surfaces both\n// pathological inputs (e.g. ReDoS-prone tag attributes) and merely-slow ones\n// (huge bodies hitting the xmldom fallback) so they can be triaged from\n// container logs without waiting for the SSR watchdog to kill a replica.\n//\n// Default is **Node-on, everything-else-off**. The string overload of\n// `markdown2Html` is called from comment/reply preview paths with\n// unpublished user input — warnings firing on the client would (a) leak\n// draft content into the console and any client telemetry pipeline, and\n// (b) repeat on every keystroke (the string path is uncached). Restricting\n// the default to Node specifically also keeps React Native bundles\n// (Metro/Hermes), edge runtimes (Workers, Deno, Bun) and arbitrary\n// downstream consumers silent unless they opt in.\n//\n// Opt in from any non-Node runtime by calling `setSlowRenderThresholdMs(500)`\n// during init; pass 0 to disable everywhere.\nconst isNodeRuntime =\n typeof process !== 'undefined' && typeof process?.versions?.node === 'string'\nlet slowRenderThresholdMs = isNodeRuntime ? 500 : 0\n\nexport function setSlowRenderThresholdMs(ms: number): void {\n slowRenderThresholdMs = Math.max(0, ms)\n}\n\nfunction logIfSlow(durationMs: number, context: string): void {\n if (slowRenderThresholdMs > 0 && durationMs >= slowRenderThresholdMs) {\n // Grep-friendly prefix: \"[render-helper] slow markdown render\" is a\n // unique substring that doesn't collide with anything else in the code\n // base. We intentionally do not include a content excerpt — the\n // body_len + (when available) author/permlink is enough to triage, and\n // the string overload can carry unpublished user-authored text from\n // comment/draft preview paths.\n // eslint-disable-next-line no-console\n console.warn(\n `[render-helper] slow markdown render: ${durationMs.toFixed(0)}ms ${context}`\n )\n }\n}\n\n/**\n * @param obj - Entry object or raw markdown string\n * @param forApp - Whether rendering for app context\n * @param _webp - @deprecated Ignored. Format is now handled server-side via Accept header content negotiation.\n * @param parentDomain - Parent domain for iframe embed parameters\n * @param seoContext - Optional SEO context for structured data\n * @param renderOptions - Optional rendering options (e.g. embedVideosDirectly)\n */\nexport function markdown2Html(obj: Entry | string, forApp = true, _webp = false, parentDomain: string = 'ecency.com', seoContext?: SeoContext, renderOptions?: RenderOptions): string {\n if (typeof obj === 'string') {\n const cleanedStr = cleanReply(obj)\n const t0 = performance.now()\n const res = markdownToHTML(cleanedStr, forApp, parentDomain, seoContext, renderOptions)\n logIfSlow(performance.now() - t0, `body_len=${obj.length}`)\n return res\n }\n\n // Every RenderOptions flag that changes the output must appear in the key, or\n // two callers rendering the same entry with different options serve each\n // other's HTML from cache.\n const key = `${makeEntryCacheKey(obj)}-md-${forApp ? 'app' : 'site'}-${parentDomain}${seoContext ? `-seo${seoContext.authorReputation ?? ''}-${seoContext.postPayout ?? ''}` : ''}${renderOptions?.embedVideosDirectly ? '-embed' : ''}${renderOptions?.inertAuthorAndTagChips ? '-inert' : ''}${renderOptions?.externalProfileBase ? '-ext' + renderOptions.externalProfileBase : ''}`\n\n const item = cacheGet<string>(key)\n if (item) {\n return item\n }\n\n const cleanBody = cleanReply(obj.body)\n\n const t0 = performance.now()\n const res = markdownToHTML(cleanBody, forApp, parentDomain, seoContext, renderOptions)\n logIfSlow(\n performance.now() - t0,\n `author=@${obj.author} permlink=${obj.permlink} body_len=${obj.body?.length ?? 0}`\n )\n cacheSet(key, res)\n\n return res\n}\n","import { proxifyImageSrc } from './proxify-image-src'\nimport { markdown2Html } from './markdown-2-html'\nimport { createDoc, makeEntryCacheKey, decodeImageSrc } from './helper'\nimport { cacheGet, cacheSet } from './cache'\nimport { Entry } from './types'\nimport he from 'he'\n\nconst gifLinkRegex = /\\.(gif)$/i;\n\nfunction isGifLink(link: string) {\n return gifLinkRegex.test(link);\n}\n\n// Strip code regions so that ![alt](url) inside a code block is not mistaken\n// for a real image. The full markdown renderer turns these into <pre><code>\n// with no <img>, so we mirror that behavior here.\n// - backtick fences ``` … ``` (with optional language hint)\n// - tilde fences ~~~ … ~~~ (CommonMark also accepts these)\n// - inline code `…`\n// - indented code blocks (4 spaces or a tab at line start) — over-strips\n// a little (e.g., deeply nested list continuation lines), which is fine:\n// a missed match just falls back to the full parser.\nconst BACKTICK_FENCE_RE = /```[\\s\\S]*?```/g\nconst TILDE_FENCE_RE = /~~~[\\s\\S]*?~~~/g\nconst INLINE_CODE_RE = /`[^`\\n]*`/g\nconst INDENTED_CODE_RE = /^(?: {4}|\\t).+$/gm\n// Requires a closing `)` so broken syntax like `![](url` (no close) doesn't\n// match. Also tolerates the optional title form `![](url \"title\")`. The alt-text\n// class excludes `[` (so a `![a](`/`![[[…` run can't be re-scanned at every start),\n// while the href quantifier is LENGTH-BOUNDED rather than `[`-excluding so it still\n// matches image URLs that legitimately contain a literal `[` (e.g. array query params\n// like `?w[]=600`) — the per-position scan stays capped, so it's sub-quadratic on\n// untrusted input.\nconst MD_IMAGE_RE = /!\\[[^[\\]]*\\]\\(\\s*([^)\\s]{1,2048})(?:\\s+[\"'][^\"']*[\"'])?\\s*\\)/\n// A markdown image whose URL exceeds MD_IMAGE_RE's length bound (or whose syntax is broken)\n// isn't captured by it — leaving `mdMatch` null, or (MD_IMAGE_RE is unanchored) matching a\n// *later* image instead. This linear detector (label excludes `[`; no closing `)` required)\n// still spots the uncaptured image so findFirstImageUrl can bail to the full parser rather\n// than promoting a later HTML/bare/markdown candidate over it.\nconst MD_IMAGE_PRESENT_RE = /!\\[[^[\\]]*\\]\\(\\s*[^\\s)]/\nconst HTML_IMAGE_RE = /<img\\b[^>]*?\\bsrc\\s*=\\s*[\"']([^\"']+)[\"']/i\n// A standalone (auto-linkified) image URL the renderer turns into an <img> via\n// text.method / linkify (IMG_REGEX). Required to sit at a line start or after\n// whitespace (group 1) so it is NOT a URL already inside ![](), <img src=\"\">, or\n// a [label](href) link — avoiding false positives on image-extension URLs that\n// the renderer does NOT surface as a standalone image. Same extension set as the\n// renderer's IMG_REGEX. Linear-time: one bounded char class + a single greedy\n// `+`, no nested quantifier.\nconst BARE_IMAGE_RE = /(^|\\s)(https?:\\/\\/[^\\s<>\"'()[\\]]+\\.(?:tiff?|jpe?g|gif|png|svg|ico|heic|webp|arw)(?:[?#][^\\s<>\"'()[\\]]*)?)/im\n// Markdown link `[label](href)` (NOT an image — the `!` is excluded by the\n// caller). The renderer (a.method) promotes such a link to an image only when\n// the href is an image URL AND the label text equals the href. Used to find the\n// `[url](url)` image-link cover form. Global, capture label + href.\n// Both the label and href classes exclude `[` so a run of `[`, `[a](`, or `![a](` can't be\n// re-scanned to the end of the body at every start position — linear on untrusted content.\n// Unlike the image href above, a `[`-containing URL is irrelevant here: this cover form\n// requires the label to equal the href, and an unescaped `[`/`]` in a URL breaks the label\n// match regardless — so excluding `[` loses nothing and keeps this O(1) per failed start.\nconst MD_LINK_RE = /\\[([^[\\]]*)\\]\\(\\s*([^)\\s[]+)(?:\\s+[\"'][^\"']*[\"'])?\\s*\\)/g\n// Mirrors a.method's `href.match(IMG_REGEX)` — an image URL by extension\n// (anywhere after the dot, matching the renderer). Eligibility for an avif\n// <source> is then decided separately by isPictureEligibleRawUrl.\nconst IMG_HREF_RE = /https?:\\/\\/.*\\.(?:tiff?|jpe?g|gif|png|svg|ico|heic|webp|arw)/i\n\n// The fast-path bypasses sanitize-html (which the full markdown pipeline\n// applies). The sanitizer only preserves http/https <img> sources — ftp,\n// data, javascript, relative, etc. are all dropped. Mirror that policy here\n// so the fast-path can never surface an image the full path would have\n// dropped. Anything else returns null and falls back to the sanitized parse.\nconst SAFE_URL_RE = /^https?:\\/\\//i\n\n/**\n * Fast-path: extract the first image URL from raw markdown without rendering\n * the whole post. Returns null if nothing matches *unambiguously* — when in\n * doubt, the caller falls back to the full markdown2Html → DOM parse path.\n *\n * @param includeBareUrls when true (only getEntryImageRawUrl, for the LCP\n * preload), also consider standalone bare image URLs the renderer\n * auto-linkifies into images — so a post whose first body image is a bare URL\n * (and which has no json_metadata.image thumbnail) is still discovered. The\n * default (false) keeps catchPostImage / getImage / og-image behavior\n * byte-identical.\n */\nfunction findFirstImageUrl(body: string, includeBareUrls = false): string | null {\n if (!body) return null\n const cleaned = body\n .replace(BACKTICK_FENCE_RE, '')\n .replace(TILDE_FENCE_RE, '')\n .replace(INLINE_CODE_RE, '')\n .replace(INDENTED_CODE_RE, '')\n\n const mdMatch = cleaned.match(MD_IMAGE_RE)\n const htmlMatch = cleaned.match(HTML_IMAGE_RE)\n\n // If markdown image syntax is present at all, it must be unambiguous. The\n // capture class `[^)\\s]+` excludes `)`, so a captured URL containing `(`\n // means the URL was truncated mid-paren (e.g., a real\n // `https://x.com/path_(a)_full.jpg`). When ambiguous, bail and let the full\n // markdown parser handle it — returning a truncated URL would be wrong.\n if (mdMatch) {\n const url = mdMatch[1]\n if (!url || !SAFE_URL_RE.test(url) || url.includes('(')) {\n return null\n }\n }\n // MD_IMAGE_RE is unanchored, so a markdown image can go uncaptured (URL over the length\n // bound, or broken syntax) while `mdMatch` is null OR is a *later* image. If any such\n // uncaptured image sits before what we captured (or nothing was captured), bail to the full\n // parser so it resolves the true first image rather than promoting a later HTML/bare/markdown\n // candidate.\n const priorRegion = mdMatch ? cleaned.slice(0, mdMatch.index ?? 0) : cleaned\n if (MD_IMAGE_PRESENT_RE.test(priorRegion)) {\n return null\n }\n\n // Collect valid candidates with their source position; the rendered document\n // surfaces whichever image appears first in source order.\n const candidates: { url: string; pos: number }[] = []\n if (mdMatch) candidates.push({ url: mdMatch[1], pos: mdMatch.index ?? 0 })\n if (htmlMatch && htmlMatch[1] && SAFE_URL_RE.test(htmlMatch[1])) {\n candidates.push({ url: htmlMatch[1], pos: htmlMatch.index ?? 0 })\n }\n if (includeBareUrls) {\n const bareMatch = cleaned.match(BARE_IMAGE_RE)\n if (bareMatch && bareMatch[2] && SAFE_URL_RE.test(bareMatch[2])) {\n // position of the URL itself, past the leading start/whitespace (group 1)\n candidates.push({ url: bareMatch[2], pos: (bareMatch.index ?? 0) + bareMatch[1].length })\n }\n // `[url](url)` image-link form: a markdown link the renderer promotes to an\n // image (a.method) — href is an image URL and the label text equals it.\n // Skip `![...]()` images (preceding `!`). Take the earliest such link.\n const deAmp = (s: string) => s.trim().replace(/&amp;/g, '&')\n for (const m of cleaned.matchAll(MD_LINK_RE)) {\n const idx = m.index ?? 0\n if (idx > 0 && cleaned[idx - 1] === '!') continue // it's an image ![](), handled above\n const href = m[2]\n if (href && SAFE_URL_RE.test(href) && IMG_HREF_RE.test(href) && deAmp(m[1]) === deAmp(href)) {\n candidates.push({ url: href, pos: idx })\n break\n }\n }\n }\n\n if (candidates.length === 0) return null\n candidates.sort((a, b) => a.pos - b.pos)\n return candidates[0].url\n}\n\nfunction proxifyFound(src: string, width: number, height: number, format: string): string {\n const decoded = he.decode(src)\n if (isGifLink(decoded)) {\n return proxifyImageSrc(decoded, 0, 0, format)\n }\n return proxifyImageSrc(decoded, width, height, format)\n}\n\nfunction getImage(entry: Entry, width = 0, height = 0, format = 'match'): string | null {\n /*\n * Return from json metadata if exists\n * */\n let meta: Entry['json_metadata'] | null\n\n if (typeof entry.json_metadata === 'object') {\n meta = entry.json_metadata\n } else {\n try {\n meta = JSON.parse(entry.json_metadata as string)\n } catch (e) {\n meta = null\n }\n }\n\n if (meta && typeof meta.image === 'string' && meta.image.length > 0) {\n // Decode HTML entities (e.g., &amp; -> &) before proxifying\n const decodedImage = he.decode(meta.image)\n if (isGifLink(decodedImage)) {\n return proxifyImageSrc(decodedImage, 0, 0, format)\n }\n return proxifyImageSrc(decodedImage, width, height, format)\n }\n\n if (meta && meta.image && !!meta.image.length && meta.image[0]) {\n // Only decode if it's a string, otherwise pass through to proxifyImageSrc which will return ''\n if (typeof meta.image[0] === 'string') {\n // Decode HTML entities (e.g., &amp; -> &) before proxifying\n const decodedImage = he.decode(meta.image[0])\n if (isGifLink(decodedImage)) {\n return proxifyImageSrc(decodedImage, 0, 0, format)\n }\n return proxifyImageSrc(decodedImage, width, height, format)\n }\n // For non-string types, let proxifyImageSrc handle it (returns '')\n if (isGifLink(meta.image[0])) {\n return proxifyImageSrc(meta.image[0], 0, 0, format)\n }\n return proxifyImageSrc(meta.image[0], width, height, format)\n }\n\n // Fast-path: try to find the first image with a regex over the raw body.\n // Avoids the cost of full markdown2Html + DOM parsing for the common case.\n const fast = findFirstImageUrl(entry.body)\n if (fast) {\n return proxifyFound(fast, width, height, format)\n }\n\n // Fall back to the full markdown render (handles edge cases the regex missed)\n const html = markdown2Html(entry)\n const doc = createDoc(html)\n if (!doc) {\n return null\n }\n\n const imgEls = doc.getElementsByTagName('img')\n if (imgEls.length >= 1) {\n const src = imgEls[0].getAttribute('src')\n if (!src) {\n return null\n }\n return proxifyFound(src, width, height, format)\n }\n\n return null\n}\n\n/**\n * The RAW (pre-proxify) URL of an entry's primary image, using the same\n * discovery order as catchPostImage (json_metadata.image, then the first body\n * image). Unlike catchPostImage it does NOT proxify — callers need the original\n * URL (e.g. to test picture-eligibility for an LCP preload, since catchPostImage\n * returns an already-proxified /p/ URL). Returns null when the fast path finds\n * no unambiguous image (the caller can fall back to catchPostImage).\n */\nexport function getEntryImageRawUrl(obj: Entry | string): string | null {\n // Decode with the SAME pipeline the renderer applies to the in-body <img>\n // (decodeImageSrc: entities then percent-encoding), so the LCP preload's\n // proxy hash byte-matches the body's <picture> avif <source> for &amp; /\n // %-encoded / non-ASCII cover URLs (otherwise the preload is wasted and the\n // LCP image double-downloads).\n if (typeof obj === 'string') {\n const src = findFirstImageUrl(obj, true)\n return src ? decodeImageSrc(src) : null\n }\n let meta: Entry['json_metadata'] | null\n if (typeof obj.json_metadata === 'object') {\n meta = obj.json_metadata\n } else {\n try {\n meta = JSON.parse(obj.json_metadata as string)\n } catch (e) {\n meta = null\n }\n }\n if (meta && typeof meta.image === 'string' && meta.image.length > 0) {\n return decodeImageSrc(meta.image)\n }\n if (meta && meta.image && !!meta.image.length && typeof meta.image[0] === 'string' && meta.image[0].length > 0) {\n return decodeImageSrc(meta.image[0])\n }\n const bodySrc = findFirstImageUrl(obj.body, true)\n return bodySrc ? decodeImageSrc(bodySrc) : null\n}\n\nexport function catchPostImage(obj: Entry | string, width = 0, height = 0, format = 'match'): string | null {\n if (typeof obj === 'string') {\n // Process string directly to avoid cache key collision\n // Don't create Entry wrapper as it would generate invalid cache keys\n\n // Fast-path: regex over raw markdown\n const fast = findFirstImageUrl(obj)\n if (fast) {\n return proxifyFound(fast, width, height, format)\n }\n\n const html = markdown2Html(obj)\n const doc = createDoc(html)\n if (!doc) {\n return null\n }\n\n const imgEls = doc.getElementsByTagName('img')\n if (imgEls.length >= 1) {\n const src = imgEls[0].getAttribute('src')\n if (!src) {\n return null\n }\n return proxifyFound(src, width, height, format)\n }\n\n return null\n }\n const key = `${makeEntryCacheKey(obj)}-${width}x${height}-${format}`\n\n const item = cacheGet<string | null>(key)\n if (item) {\n return item\n }\n\n const res = getImage(obj, width, height, format)\n cacheSet(key, res)\n\n return res\n}\n\n","import he from 'he'\nimport { makeEntryCacheKey, stripHtmlTags } from './helper'\nimport { cacheGet, cacheSet } from './cache'\nimport { Entry } from './types'\nimport { cleanReply } from './methods'\nimport { ENTITY_REGEX } from './consts'\nimport { Remarkable } from 'remarkable'\n\n// Reused across all calls — config is constant and Remarkable construction\n// (rule registration via ruler.enable) is non-trivial under SSR fan-out.\n//\n// linkify is intentionally omitted: the post-processing pass below strips bare\n// URLs from the final text, so auto-linking them just to discard the <a>\n// wrapper is wasted CPU during SSR.\nconst summaryRenderer = new Remarkable({\n html: true,\n breaks: true,\n typographer: false,\n})\nsummaryRenderer.core.ruler.enable(['abbr'])\nsummaryRenderer.block.ruler.enable(['footnote', 'deflist'])\nsummaryRenderer.inline.ruler.enable([\n 'footnote_inline',\n 'ins',\n 'mark',\n 'sub',\n 'sup',\n])\n\nconst joint = (arr: string[], limit = 200) => {\n let result = '';\n if (arr) {\n for (let i = 0; i < arr.length; i++) {\n // join array with space separator\n if (result) {\n result += \" \";\n }\n // break with length reaches limit\n if (result.length > limit) {\n break;\n } else {\n // make sure last join doesn't break the limit too much\n if ((result + arr[i]).length < limit + 10) {\n result += arr[i];\n } else {\n break;\n }\n }\n }\n }\n return result.trim();\n};\n\n/**\n * Generate a text summary from post body content\n * @param entryBody - The post body content to summarize\n * @param length - Maximum length of the summary (default: 200, use 0 for no truncation)\n * @param platform - Target platform: 'web' for browser/Node.js, 'ios'/'android' for React Native (default: 'web')\n * Controls entity/placeholder handling - 'web' skips placeholder substitution, other values enable it\n */\nfunction postBodySummary(entryBody: string, length: number = 200, platform:'ios'|'android'|'web' = 'web'): string {\n if (!entryBody) {\n return ''\n }\n entryBody = cleanReply(entryBody)\n\n // Replace entities with deterministic placeholders to preserve them during rendering\n const entities = entryBody.match(ENTITY_REGEX);\n const entityPlaceholders: string[] = [];\n if (entities && platform !== 'web') {\n // Deduplicate entities to avoid duplicate placeholders\n const uniqueEntities = [...new Set(entities)];\n uniqueEntities.forEach((entity, index) => {\n // Use markdown-inert Unicode placeholder (zero-width spaces)\n const placeholder = `\\u200B${index}\\u200B`;\n entityPlaceholders.push(entity);\n // Replace all occurrences of this entity\n entryBody = entryBody.split(entity).join(placeholder);\n })\n }\n\n // Convert markdown to html\n let text = '';\n try {\n text = summaryRenderer.render(entryBody)\n } catch (err) {\n // Log error with context for debugging\n console.error('[postBodySummary] Failed to render markdown:', {\n error: err instanceof Error ? err.message : String(err),\n entryBodyLength: entryBody?.length || 0,\n platform\n })\n // Set empty text on error - caller receives empty summary\n text = ''\n }\n\n\n // Restore original entities from placeholders\n if (platform !== 'web' && entityPlaceholders.length > 0) {\n entityPlaceholders.forEach((entity, index) => {\n const placeholder = `\\u200B${index}\\u200B`;\n // Replace all occurrences of the placeholder\n text = text.split(placeholder).join(entity);\n })\n }\n\n\n text = stripHtmlTags(text)\n .replace(/\\r?\\n|\\r/g, ' ') // Remove new lines\n .replace(/(?:https?|ftp):\\/\\/[\\n\\S]+/g, '') // Remove urls\n .trim()\n // Collapse runs of 2+ spaces to a single space. Equivalent to the\n // previous `' +(?= )'` form (which deleted all-but-one space in a\n // run) but matches the whole run greedily without backtracking, so\n // it stays linear on long whitespace runs.\n .replace(/ {2,}/g, ' ')\n\n // Truncate if length > 0 (length === 0 means no truncation)\n if (length > 0) {\n text = joint(text.split(' '), length)\n }\n\n if (text) {\n text = he.decode(text) // decode html entities \n }\n\n return text\n}\n\n/**\n * Generate a text summary from an Entry object or raw string\n * @param obj - Entry object or raw post body string\n * @param length - Maximum length of the summary (default: 200, use 0 for no truncation)\n * @param platform - Target platform: 'web' for browser/Node.js, 'ios'/'android' for React Native (default: 'web')\n * Controls entity/placeholder handling - 'web' skips placeholder substitution, other values enable it\n * @returns Text summary of the post body\n */\nexport function getPostBodySummary(obj: Entry | string, length?: number, platform?:'ios'|'android'|'web'): string {\n // Normalize parameters at function start for consistent behavior and caching\n const normalizedLength = length ?? 200\n const normalizedPlatform = platform || 'web'\n\n if (typeof obj === 'string') {\n return postBodySummary(obj as string, normalizedLength, normalizedPlatform)\n }\n\n const key = `${makeEntryCacheKey(obj)}-sum-${normalizedLength}-${normalizedPlatform}`\n\n const item = cacheGet<string>(key)\n if (item) {\n return item\n }\n\n const res = postBodySummary(obj.body, normalizedLength, normalizedPlatform)\n cacheSet(key, res)\n\n return res\n}\n"]}