@ecency/render-helper 2.5.30 → 2.5.32
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","p","XMLDOMSerializer","decodeEntities","text","img","iframe","imgEls","a","match","linkify","Remarkable","LRUCache","t0","res","from"],"mappings":"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","file":"index.js","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 { decodeHTML } from 'entities'\n\n/**\n * Decode HTML character references in user-authored text.\n *\n * `entities.decodeHTML` throws a RangeError on a numeric reference whose digit\n * string overflows a double (309+ decimal or 256+ hex digits, leading zeros\n * included: 0 * Infinity = NaN -> String.fromCodePoint(NaN)). Post bodies and\n * json_metadata come straight from the chain, so a crafted reference must\n * never take a feed page down. Leading zeros are dropped first (they carry no\n * value, and `A` must still be \"A\"); a reference that is still overlong\n * after that cannot be a code point and becomes U+FFFD, which is what the HTML\n * spec and the previous decoder (he) produce for an out-of-range value.\n * Anything else the decoder rejects is returned as-is.\n */\nconst LEADING_ZEROS_DEC = /�+(?=[0-9])/g\nconst LEADING_ZEROS_HEX = /�+(?=[0-9a-f])/gi\nconst OVERLONG_NUMERIC_REF = /&#(?:x[0-9a-f]{256,}|[0-9]{309,});?/gi\n\nexport function decodeEntities(value: string): string {\n const safe = value\n .replace(LEADING_ZEROS_DEC, '&#')\n .replace(LEADING_ZEROS_HEX, (m) => m.slice(0, 3))\n .replace(OVERLONG_NUMERIC_REF, '\\uFFFD')\n try {\n return decodeHTML(safe)\n } catch {\n return safe\n }\n}\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 (&, &#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 = decodeEntities(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 '>' 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; imageCount?: number }, 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\n /*\n Tiered loading (#1672). Index 0 is the LCP candidate: eager + high, and the\n entry page separately preloads it. Index 1 is very likely inside or near\n the first viewport on multi-image posts; plain lazy put it at priority Low\n behind the script wave, so its blur-up placeholder sharpened seconds after\n the page looked settled. It loads eager at default priority, which keeps\n the high hint exclusive to the LCP image. Index 2 onward stays lazy: eager\n is not free (it fetches unconditionally, even for images never scrolled\n to), so the eager set is kept to the two images that plausibly pay off.\n imageCount falls back to firstImageFound so callers passing the old state\n shape keep the old first-image behavior.\n */\n // Avatars (mention bylines, tiny inline profile images) neither deserve an\n // eager slot nor should they consume one that a content image needs. Match\n // ONLY the proxy avatar route and the exact author-link class token: a\n // substring test on arbitrary URLs would misclassify legitimate content\n // like https://cdn.example/avatar/art.jpg, lazy-load a real LCP candidate\n // and hand the high hint to the wrong image.\n const avatarRoute = new RegExp(`^${trimTrailingSlash(getProxyBase()).replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\")}/u/[^/]+/avatar(?:/[a-z]+)?$`);\n const classTokens = (el.getAttribute(\"class\") || \"\").split(/\\s+/);\n const isAvatar = avatarRoute.test(decodedSrc) || classTokens.includes(\"er-author-link-image\");\n if (isAvatar) {\n el.setAttribute(\"loading\", \"lazy\");\n el.setAttribute(\"decoding\", \"async\");\n }\n const imageIndex = !state || isAvatar ? 3 : (state.imageCount ?? (state.firstImageFound ? 1 : 0));\n if (state && !isAvatar) {\n state.imageCount = imageIndex + 1;\n state.firstImageFound = true;\n }\n if (isAvatar) {\n // attributes already set above; skip the tier\n } else if (imageIndex === 0) {\n el.setAttribute(\"loading\", \"eager\");\n el.setAttribute(\"fetchpriority\", \"high\");\n } else if (imageIndex === 1) {\n el.setAttribute(\"loading\", \"eager\");\n el.setAttribute(\"decoding\", \"async\");\n } else {\n el.setAttribute(\"loading\", \"lazy\");\n el.setAttribute(\"decoding\", \"async\");\n }\n // The high hint is EXCLUSIVE to index 0. Anything else that arrives with\n // one (author HTML passes the sanitizer; linkify grants a \"first image\"\n // high per text node) would compete with the real LCP request.\n if (isAvatar || imageIndex !== 0) {\n el.removeAttribute(\"fetchpriority\");\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 // & => & can break equality\n if (\n href.match(IMG_REGEX) &&\n href.trim().replace(/&/g, '&') ===\n getSerializedInnerHTML(el).trim().replace(/&/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(/&/g, '&') ===\n getSerializedInnerHTML(el).trim().replace(/&/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\"></a></div>', '')\n .replace('<div><a href=\"https://engage.hivechain.app\"></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, decodeEntities, stripHtmlTags } from './helper'\nimport { cacheGet, cacheSet } from './cache'\nimport { Entry } from './types'\n\nconst gifLinkRegex = /\\.(gif)$/i;\n\nfunction isGifLink(link: string) {\n return gifLinkRegex.test(link);\n}\n\n// Strip code regions so that  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\n// HTML regions whose text never reaches the page as an image: <style> (dropped\n// by the sanitizer) and <pre> in block context (the renderer leaves its text\n// alone), plus HTML comments. Verified against the renderer: a URL inside\n// <code> or <script> text IS linkified into an image, so those are not listed.\n//\n// Plain index scans rather than regex replaces: the text is only ever searched\n// for image URLs, never emitted, so this is candidate extraction and not\n// sanitization, but the scans are also linear and leave nothing behind (an\n// unterminated region runs to the end, as in HTML).\n\n// What may follow a tag name, as the renderer reads it (probed, not the HTML\n// spec): on an opening tag, space, tab, form feed or carriage return, `/` or\n// `>`. A line feed anywhere inside the tag breaks the tag for the renderer and\n// the content renders as prose (see findOpenTagEnd). `<prefix>` is not `<pre`.\nconst OPEN_TAG_NAME_END = /[\\t\\f\\r />]/\n// A closing tag tolerates any whitespace before its `>`; `</prelude>` does not\n// close `<pre>`.\nconst CLOSE_TAG_NAME_END = /[\\s>]/\n\nfunction isWholeTagName(lower: string, idx: number, end: RegExp): boolean {\n const next = lower[idx]\n return next === undefined || end.test(next)\n}\n\n// Index of the next `<tag` / `</tag` occurrence at or after `from` whose tag\n// name is whole, or -1.\nfunction findTag(lower: string, tag: string, from: number, end: RegExp): number {\n let at = lower.indexOf(tag, from)\n while (at !== -1 && !isWholeTagName(lower, at + tag.length, end)) {\n at = lower.indexOf(tag, at + tag.length)\n }\n return at\n}\n\n// Where an opening tag that starts at `openAt` ends, read the way the renderer\n// reads it: the first `>` outside quotes closes it; a line feed before that\n// breaks the tag (it is then prose, not a tag); a `/` right before the `>`\n// makes it self-closing, which opens nothing. Returns the index of the `>`\n// for a real opening tag, -1 for an unterminated one (taken as open to the\n// end), and NaN for a broken or self-closing one, which is skipped.\nfunction findOpenTagEnd(lower: string, openAt: number): number {\n let quote = ''\n for (let i = openAt + 1; i < lower.length; i++) {\n const c = lower[i]\n if (c === '\\n') return NaN\n if (quote) {\n if (c === quote) quote = ''\n } else if (c === '\"' || c === \"'\") {\n quote = c\n } else if (c === '>') {\n return lower[i - 1] === '/' ? NaN : i\n }\n }\n return -1\n}\n\n// The markdown parser's HTML block tags (remarkable `html_blocks`). A line\n// indented at most three spaces that starts with `<` plus one of these (or a\n// closing tag of one, or `<!`/`<?`) is an HTML block, kept raw; any other line\n// is a paragraph and an element in it is inline content whose text is\n// linkified like prose. That is why `<pre>` hides its content only in block\n// context: `<code><pre>URL</pre></code>` renders the image, `<div><pre>` does\n// not. Verified against the renderer for both.\nconst HTML_BLOCK_TAGS = new Set([\n 'article', 'aside', 'button', 'blockquote', 'body', 'canvas', 'caption', 'col', 'colgroup', 'dd', 'div',\n 'dl', 'dt', 'embed', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5',\n 'h6', 'header', 'hgroup', 'hr', 'iframe', 'li', 'map', 'object', 'ol', 'output', 'p', 'pre', 'progress',\n 'script', 'section', 'style', 'table', 'tbody', 'td', 'textarea', 'tfoot', 'th', 'tr', 'thead', 'ul', 'video'\n])\n// The parser's own tag patterns: letters only, so `<h1>` never opens a block\n// (and a heading's content is linkified like prose); an opening tag needs\n// whitespace, `/` or `>` after the name on the same line, a closing tag\n// whitespace or `>`.\nconst HTML_BLOCK_LINE_RE = /^ {0,3}<(?:[!?]|([a-z]{1,15})[\\s/>]|\\/([a-z]{1,15})[\\s>])/\n\n// Markdown container prefixes the parser strips before it looks at a line:\n// blockquote markers (`>` with an optional space, nestable, up to three spaces\n// of indent) and, at column 0 only, a list marker with its following spaces.\n// An indented list marker is not a container for the renderer (` - <pre>`\n// renders the content inline), hence column 0.\nconst BLOCKQUOTE_PREFIX_RE = /^ {0,3}> ?/\nconst LIST_PREFIX_RE = /^(?:[-*+]|\\d{1,9}[.)]) +/\n\ninterface LineMasks {\n /** Offsets inside a markdown HTML block (raw HTML, <pre>/<code> honoured). */\n block: Uint8Array\n /** Offsets on an indented code line inside a container (nothing renders). */\n code: Uint8Array\n}\n\n// Per-offset masks over the ORIGINAL body, computed once before any region is\n// blanked, because the parser decides on the original lines: removing a\n// leading comment or <style> would otherwise reclassify what follows as\n// inline content. Per line: strip the container prefixes, then a line that\n// opens a block (see HTML_BLOCK_LINE_RE) and every following line up to the\n// next blank one is a block; a remainder indented four spaces inside a\n// container is an indented code block. Linear.\nfunction markLines(lower: string): LineMasks {\n const block = new Uint8Array(lower.length)\n const code = new Uint8Array(lower.length)\n let inBlock = false\n // Width of the current list item's content indent, for its continuation\n // lines, and whether that item is a nested one (inline continuation).\n let listIndent = 0\n let nestedItem = false\n let lineStart = 0\n while (lineStart <= lower.length) {\n let lineEnd = lower.indexOf('\\n', lineStart)\n if (lineEnd === -1) lineEnd = lower.length\n let line = lower.slice(lineStart, lineEnd)\n // An open HTML block is raw until its blank-line terminator: container\n // markers inside it are text, not markers, so nothing below applies.\n if (inBlock) {\n if (line.trim() === '') {\n inBlock = false\n listIndent = 0\n nestedItem = false\n } else {\n block.fill(1, lineStart, lineEnd)\n }\n lineStart = lineEnd + 1\n continue\n }\n let inContainer = false\n // Container prefixes, in any alternation (`- > <pre>`, `> - <pre>`,\n // `> > - > <pre>`, `- - > <pre>`), all probed: blockquote and list\n // markers strip in any order and any depth, and the remainder is block\n // context, EXCEPT that content directly after a nested list marker (a\n // list marker following a list marker, `- - <pre>`, `> - - <pre>`) is\n // inline, as are the continuation lines of that nested item; a blockquote\n // marker after the nested marker restores block context (`- - > <pre>`).\n let stripped = 0\n let sawList = false\n let lastWasList = false\n let inlineRemainder = false\n for (;;) {\n const bq = BLOCKQUOTE_PREFIX_RE.exec(line)\n if (bq) {\n line = line.slice(bq[0].length)\n stripped += bq[0].length\n lastWasList = false\n inlineRemainder = false\n inContainer = true\n continue\n }\n const lm = LIST_PREFIX_RE.exec(line)\n if (lm) {\n line = line.slice(lm[0].length)\n stripped += lm[0].length\n if (lastWasList) inlineRemainder = true\n sawList = true\n lastWasList = true\n inContainer = true\n continue\n }\n break\n }\n if (sawList) {\n listIndent = stripped\n nestedItem = inlineRemainder\n } else if (listIndent > 0 && line.trim() !== '') {\n let indent = 0\n while (indent < listIndent && line[indent] === ' ') indent++\n if (indent >= Math.min(listIndent, 2)) {\n line = line.slice(indent)\n inContainer = true\n // A nested item's continuation line is inline content too.\n inlineRemainder = nestedItem\n } else {\n listIndent = 0\n nestedItem = false\n }\n }\n const blank = line.trim() === ''\n if (blank) {\n inBlock = false\n listIndent = 0\n nestedItem = false\n } else if (inlineRemainder) {\n // Inline content: neither opens nor continues a block.\n inBlock = false\n } else if (!inBlock && /^(?: {4}|\\t)/.test(line)) {\n // An indented code block, judged after the container prefixes and the\n // list item's content indent are gone: four spaces at top level or\n // inside a blockquote are code, while a list item's continuation line\n // indented to its content is not.\n code.fill(1, lineStart, lineEnd)\n } else if (!inBlock) {\n const m = HTML_BLOCK_LINE_RE.exec(line)\n if (m) {\n const tag = m[1] ?? m[2]\n inBlock = tag === undefined || HTML_BLOCK_TAGS.has(tag)\n }\n }\n if (inBlock && !blank) block.fill(1, lineStart, lineEnd)\n lineStart = lineEnd + 1\n }\n return { block, code }\n}\n\n// Every strip below is offset-preserving (a blanked character becomes a space,\n// newlines stay), so the block mask and every later position stay valid.\nconst blankChars = (s: string): string => s.replace(/[^\\n]/g, ' ')\n\nfunction blankMatches(text: string, re: RegExp): string {\n return text.replace(re, blankChars)\n}\n\n/** One text in two spellings, kept in step: blanking one blanks the other. */\ninterface Spellings {\n text: string\n lower: string\n}\n\nfunction blankSpans(input: Spellings, open: string, close: string, tagNames: boolean, blockMask: Uint8Array | null): Spellings {\n const { text, lower } = input\n const findOpen = (from: number): number => {\n if (!tagNames) return lower.indexOf(open, from)\n let at = findTag(lower, open, from, OPEN_TAG_NAME_END)\n while (at !== -1 && (Number.isNaN(findOpenTagEnd(lower, at)) || (blockMask !== null && !blockMask[at]))) {\n at = findTag(lower, open, at + open.length, OPEN_TAG_NAME_END)\n }\n return at\n }\n const findClose = (from: number): number =>\n tagNames ? findTag(lower, close, from, CLOSE_TAG_NAME_END) : lower.indexOf(close, from)\n let start = findOpen(0)\n if (start === -1) return input\n // Collect the spans, then rebuild both spellings in one pass.\n const textParts: string[] = []\n const lowerParts: string[] = []\n let from = 0\n while (start !== -1) {\n const end = findClose(start + open.length)\n let to: number\n if (end === -1) {\n to = text.length\n } else if (tagNames) {\n // Through the closing tag's `>` (`</pre>`, `</pre >`).\n const gt = lower.indexOf('>', end + close.length)\n to = gt === -1 ? text.length : gt + 1\n } else {\n to = end + close.length\n }\n const blanked = blankChars(lower.slice(start, to))\n textParts.push(text.slice(from, start), blanked)\n lowerParts.push(lower.slice(from, start), blanked)\n from = to\n start = to >= text.length ? -1 : findOpen(to)\n }\n textParts.push(text.slice(from))\n lowerParts.push(lower.slice(from))\n return { text: textParts.join(''), lower: lowerParts.join('') }\n}\n\nfunction blankMasked(input: Spellings, mask: Uint8Array): Spellings {\n let text = ''\n let lower = ''\n let from = 0\n for (let i = 0; i < mask.length; i++) {\n if (!mask[i]) continue\n let j = i\n while (j < mask.length && mask[j]) j++\n text += input.text.slice(from, i) + blankChars(input.text.slice(i, j))\n lower += input.lower.slice(from, i) + blankChars(input.lower.slice(i, j))\n from = j\n i = j\n }\n if (from === 0) return input\n return { text: text + input.text.slice(from), lower: lower + input.lower.slice(from) }\n}\n\nfunction stripHiddenRegions(text: string): string {\n let spellings: Spellings = { text, lower: text.toLowerCase() }\n const { block: blockMask, code: codeMask } = markLines(spellings.lower)\n spellings = blankMasked(spellings, codeMask)\n spellings = blankSpans(spellings, '<!--', '-->', false, null)\n // <style> is dropped by the sanitizer wherever it sits. <pre> and <code> keep\n // their text from being linkified only inside a markdown HTML block; in a\n // paragraph both are inline content and their text renders as prose.\n spellings = blankSpans(spellings, '<style', '</style', true, null)\n spellings = blankSpans(spellings, '<pre', '</pre', true, blockMask)\n spellings = blankSpans(spellings, '<code', '</code', true, blockMask)\n return spellings.text\n}\n// Requires a closing `)` so broken syntax like ` doesn't\n// match. Also tolerates the optional title form ``. The alt-text\n// class excludes `[` (so a `,\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, or the `>` that closes a wrapping tag such as <center> (group 1),\n// so it is NOT a URL already inside ![](), <img src=\"\">, or a [label](href)\n// link — avoiding false positives on image-extension URLs that the renderer\n// does NOT surface as a standalone image. Same extension set as the renderer's\n// IMG_REGEX. Linear-time: one bounded char class + a single greedy `+`, no\n// nested quantifier.\n// Every http(s) URL token is a candidate; isStandalone() then rejects the\n// ones that sit inside another construct, and a classifier decides whether a\n// token is an image (by extension) or a YouTube link (by host), in code rather\n// than in the pattern: a class followed by a literal it also matches, or a\n// repeated group before a literal, is polynomial on crafted input. The token\n// pattern itself is one class run, linear on any input. Global, so matchAll\n// can walk the tokens in source order.\nconst URL_TOKEN_RE = /https?:\\/\\/[^\\s<>\"'()[\\]]+/gi\n// An image extension, the same set the renderer's IMG_REGEX uses. Global and\n// without a wildcard before it: every occurrence is found in one linear pass.\nconst IMAGE_EXT_G = /\\.(?:tiff?|jpe?g|gif|png|svg|ico|heic|webp|arw)/gi\n// A YouTube video id as the renderer's YOUTUBE_REGEX captures it.\nconst YOUTUBE_ID_RE = /^[^\"&?/\\s]{11}$/\n\n/**\n * The image URL a bare token denotes, or null: the token up to its last image\n * extension, extended through the query or fragment when one follows, which\n * is what the earlier greedy pattern matched (prose punctuation or emphasis\n * after the extension is left out, a URL carried in another URL's query is\n * taken whole).\n */\nfunction imageToken(token: string): string | null {\n let end = -1\n for (const m of token.matchAll(IMAGE_EXT_G)) {\n end = (m.index ?? 0) + m[0].length\n }\n if (end === -1) return null\n if (end < token.length && (token[end] === '?' || token[end] === '#')) end = token.length\n const url = token.slice(0, end)\n return SAFE_URL_RE.test(url) ? url : null\n}\n\n/**\n * The video id of a YouTube URL, read the way the renderer's YOUTUBE_REGEX\n * reads it (`v=` query, `/v/`, `/e/`, `/embed/`, `/shorts/`, `youtu.be/`, or the\n * last segment of a deeper path), with plain string operations so the check is\n * linear on any input. Any subdomain (music., m., www.) counts. Null when the\n * URL is not a YouTube video link.\n */\nfunction youtubeIdOf(url: string): string | null {\n const m = /^https?:\\/\\/([^/?#]+)/i.exec(url)\n if (!m) return null\n const host = m[1].toLowerCase()\n const isShort = host === 'youtu.be'\n const isFull = host === 'youtube.com' || host.endsWith('.youtube.com')\n if (!isShort && !isFull) return null\n const rest = url.slice(m[0].length)\n const hashAt = rest.indexOf('#')\n const beforeHash = hashAt === -1 ? rest : rest.slice(0, hashAt)\n const qAt = beforeHash.indexOf('?')\n const path = qAt === -1 ? beforeHash : beforeHash.slice(0, qAt)\n const query = qAt === -1 ? '' : beforeHash.slice(qAt + 1)\n const candidate = (value: string | undefined): string | null => {\n const id = value === undefined ? '' : value.slice(0, 11)\n return YOUTUBE_ID_RE.test(id) ? id : null\n }\n if (isFull && query) {\n for (const part of query.split('&')) {\n if (part.startsWith('v=')) {\n const id = candidate(part.slice(2))\n if (id) return id\n }\n }\n }\n const segments = path.split('/').filter((seg) => seg.length > 0)\n if (isShort) return candidate(segments[0])\n if (segments.length >= 2 && ['v', 'e', 'embed', 'shorts'].includes(segments[0].toLowerCase())) {\n return candidate(segments[1])\n }\n if (segments.length >= 3) return candidate(segments[segments.length - 1])\n return null\n}\n\n// One linear pass marking every offset that sits inside an HTML tag (between\n// a `<` that opens a tag and its closing `>`, quotes respected so a `>` inside\n// an attribute value does not end the tag early). A URL in there is an\n// attribute value of some shape (`src=\"...\"`, `style=\"url(...)\"`, JSON in a\n// `data-*` attribute, `poster=`) and never prose the renderer would linkify.\nfunction isAutolinkAt(text: string, idx: number): boolean {\n // Schemes are case-insensitive: <HTTPS://...> autolinks like <https://...>.\n return /^https?:\\/\\//i.test(text.slice(idx, idx + 8))\n}\n\nfunction markInsideTags(text: string): Uint8Array {\n const marks = new Uint8Array(text.length)\n let inTag = false\n let quote = ''\n for (let i = 0; i < text.length; i++) {\n const c = text[i]\n if (!inTag) {\n // A markdown autolink `<https://...>` is not a tag: the renderer turns\n // it into a link, and an image or video URL in it into an image.\n if (c === '<' && i + 1 < text.length && /[A-Za-z/!?]/.test(text[i + 1]) && !isAutolinkAt(text, i + 1)) {\n inTag = true\n marks[i] = 1\n }\n continue\n }\n marks[i] = 1\n if (quote) {\n if (c === quote) quote = ''\n } else if (c === '\"' || c === \"'\") {\n quote = c\n } else if (c === '>') {\n inTag = false\n }\n }\n return marks\n}\n\n// Whether a URL found at `idx` stands on its own in prose, which is what the\n// renderer linkifies into an image or a video poster. Verified against the\n// renderer: it does so after whitespace, a closing `>`, and inside\n// parentheses, emphasis or quotes alike. It does NOT when the URL is:\n// - anywhere inside a tag (an attribute value of any shape), or\n// - glued to another token (a longer URL, a word, `=`), or\n// - the href of a markdown link `[label](href)`, or the label's start `[`\n// (the `[url](url)` image-link form is found by the link scan instead), or\n// - a markdown image `` (its href follows `](`, handled above;\n// a bare `!` before a URL is prose and the renderer linkifies the URL).\nfunction isStandalone(scan: ScanText, idx: number): boolean {\n if (scan.inTag[idx]) return false\n if (idx === 0) return true\n const text = scan.text\n const prev = text[idx - 1]\n if (/[\\w/.:%?&=#[-]/.test(prev)) return false\n const prev2 = idx > 1 ? text[idx - 2] : ''\n if (prev === '(' && prev2 === ']') return false\n return true\n}\n\n// Standalone URL tokens in source order, each reduced by `classify` (image\n// URL, video id); tokens the classifier rejects are skipped.\nfunction* standaloneMatches(\n scan: ScanText,\n classify: (token: string) => string | null\n): Generator<{ url: string; pos: number }> {\n for (const m of scan.text.matchAll(URL_TOKEN_RE)) {\n const idx = m.index ?? 0\n if (!isStandalone(scan, idx)) continue\n const value = classify(m[0])\n if (value !== null) yield { url: value, pos: idx }\n }\n}\n\nfunction firstStandalone(scan: ScanText, classify: (token: string) => string | null): { url: string; pos: number } | null {\n for (const hit of standaloneMatches(scan, classify)) return hit\n return null\n}\n// The href of an anchor's opening tag, quoted either way or bare. Preceded by\n// whitespace, never by `-`: `data-href` is not the href.\nconst HREF_ATTR_RE = /\\shref\\s*=\\s*(?:\"([^\"]*)\"|'([^']*)'|([^\\s\"'>]+))/i\n// Whether a quoted attribute value runs straight into the next attribute\n// name (`title=\"x\"href=`). The renderer does not read such a tag as an anchor\n// at all: it escapes the tag as text and linkifies the URL inside, so the\n// scans must leave it alone rather than blank it. A quote-state walk: only a\n// CLOSING quote followed by a letter counts.\nfunction hasGluedAttribute(tag: string): boolean {\n let quote = ''\n for (let i = 0; i < tag.length; i++) {\n const c = tag[i]\n if (quote) {\n if (c === quote) {\n quote = ''\n const next = tag[i + 1]\n if (next !== undefined && /[A-Za-z]/.test(next)) return true\n }\n } else if (c === '\"' || c === \"'\") {\n quote = c\n }\n }\n return false\n}\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 ` per failed start.\nconst MD_LINK_RE = /\\[([^[\\]]*)\\]\\(\\s*([^)\\s[]+)(?:\\s+[\"'][^\"']*[\"'])?\\s*\\)/g\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// Mirrors a.method's `href.match(IMG_REGEX)` — an http(s) URL with an image\n// extension anywhere after a dot, matching the renderer. Two anchored tests\n// rather than one `.*\\.` pattern, so the check is linear on any input.\n// Eligibility for an avif <source> is then decided separately by\n// isPictureEligibleRawUrl.\nconst IMG_EXT_RE = /\\.(?:tiff?|jpe?g|gif|png|svg|ico|heic|webp|arw)/i\nconst isImageHref = (href: string): boolean => SAFE_URL_RE.test(href) && IMG_EXT_RE.test(href)\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 return findFirstImageCandidate(prepareBody(body), includeBareUrls).candidate?.url ?? null\n}\n\nfunction stripCodeRegions(body: string): string {\n let text = blankMatches(body, BACKTICK_FENCE_RE)\n text = blankMatches(text, TILDE_FENCE_RE)\n text = blankMatches(text, INLINE_CODE_RE)\n // Indented code blocks are blanked by the line model (markLines), which\n // knows the container context a four-space indent has to be read in.\n return stripHiddenRegions(text)\n}\n\n// Blank (offset-preserving, so positions stay comparable) every anchor the\n// renderer would not promote. Verified against the renderer, the two\n// promotions use different tests: a video link is promoted when the anchor's\n// textContent equals its href (nested <span> and the like allowed), an image\n// link when the anchor's FIRST text child equals its href (`URL<span>x</span>`\n// is promoted, `URL caption` and `<span>x</span>URL` are not). Entities are\n// decoded on both sides, as the DOM exposes them. See HTML_ANCHOR_RE.\n// An HTML anchor's text sits right after a `>`, so the standalone-position rule\n// would read an image or video URL used as link TEXT as a bare URL. The\n// renderer only promotes such an anchor when the text equals the href\n// (a.method), so anchors whose text differs are blanked before the bare scans.\n// A scan rather than a regex: the opening tag's end is found quote-aware (a\n// `>` inside a title must not end it), and the href may be quoted or bare.\nfunction blankUnequalAnchors(cleaned: string, textContent: boolean): string {\n const lower = cleaned.toLowerCase()\n // Output chunks, joined once: rebuilding the string per anchor is quadratic\n // on a body with thousands of anchors.\n const parts: string[] = []\n let from = 0\n let at = findTag(lower, '<a', 0, OPEN_TAG_NAME_END)\n while (at !== -1) {\n const gt = findOpenTagEnd(lower, at)\n if (Number.isNaN(gt) || gt === -1 || hasGluedAttribute(cleaned.slice(at, gt))) {\n // Broken, self-closing or malformed: not an anchor around any text.\n at = findTag(lower, '<a', at + 2, OPEN_TAG_NAME_END)\n continue\n }\n const closeAt = findTag(lower, '</a', gt + 1, CLOSE_TAG_NAME_END)\n const innerEnd = closeAt === -1 ? cleaned.length : closeAt\n let spanEnd = cleaned.length\n if (closeAt !== -1) {\n const closeGt = lower.indexOf('>', closeAt + 3)\n spanEnd = closeGt === -1 ? cleaned.length : closeGt + 1\n }\n const hrefMatch = HREF_ATTR_RE.exec(cleaned.slice(at, gt))\n const href = hrefMatch ? (hrefMatch[1] ?? hrefMatch[2] ?? hrefMatch[3] ?? '') : ''\n const inner = cleaned.slice(gt + 1, innerEnd)\n let text: string\n if (textContent) {\n text = stripHtmlTags(inner)\n } else {\n // The first text child ends at the first real tag start; a literal `<`\n // in prose (`URL < caption`) is part of that text and breaks equality.\n const firstTag = inner.search(/<[A-Za-z/!]/)\n text = firstTag === -1 ? inner : inner.slice(0, firstTag)\n }\n if (!href || decodeEntities(text.trim()) !== decodeEntities(href.trim())) {\n parts.push(cleaned.slice(from, at), blankChars(cleaned.slice(at, spanEnd)))\n from = spanEnd\n }\n at = spanEnd >= cleaned.length ? -1 : findTag(lower, '<a', spanEnd, OPEN_TAG_NAME_END)\n }\n if (parts.length === 0) return cleaned\n parts.push(cleaned.slice(from))\n return parts.join('')\n}\n\n/** One scan text plus its inside-a-tag marks. */\ninterface ScanText {\n text: string\n inTag: Uint8Array\n}\n\n/**\n * The body with every region the page never shows removed, plus the two\n * anchor-blanked variants the bare scans need (image rule and video rule, see\n * blankUnequalAnchors), each with its inside-a-tag marks. Computed once per\n * lookup; every scan below works on these.\n */\ninterface PreparedBody {\n cleaned: string\n image: ScanText\n video: ScanText\n}\n\nconst EMPTY_SCAN: ScanText = { text: '', inTag: new Uint8Array(0) }\n\nfunction prepareBody(body: string): PreparedBody {\n const cleaned = body ? stripCodeRegions(body) : ''\n if (!cleaned) return { cleaned, image: EMPTY_SCAN, video: EMPTY_SCAN }\n const imageText = blankUnequalAnchors(cleaned, false)\n const videoText = blankUnequalAnchors(cleaned, true)\n return {\n cleaned,\n image: { text: imageText, inTag: markInsideTags(imageText) },\n video: { text: videoText, inTag: markInsideTags(videoText) }\n }\n}\n\ninterface ImageCandidate {\n url: string\n /** Offset in the code-stripped body, for source-order comparisons. */\n pos: number\n}\n\n/**\n * The poster image the renderer would produce for the first standalone YouTube\n * URL in the body, with its position, or null. Fast-mode only: the full render\n * discovers these itself through text.method / a.method.\n */\nfunction findFirstVideoPoster(prepared: PreparedBody): ImageCandidate | null {\n const { cleaned } = prepared\n if (!cleaned) return null\n let best: ImageCandidate | null = null\n // The first YouTube URL that actually carries a video id: a channel or\n // playlist link earlier in the body must not hide a later watch link.\n for (const hit of standaloneMatches(prepared.video, youtubeIdOf)) {\n best = { url: hit.url, pos: hit.pos }\n break\n }\n // `[url](url)` form: a.method turns a link whose text equals its href into\n // the same poster. Take it only when it comes before the bare form.\n for (const m of cleaned.matchAll(MD_LINK_RE)) {\n const idx = m.index ?? 0\n if (idx > 0 && cleaned[idx - 1] === '!') continue\n if (best && idx >= best.pos) break\n const href = m[2]\n if (href && m[1].trim() === href) {\n const id = youtubeIdOf(href)\n if (id) {\n best = { url: id, pos: idx }\n break\n }\n }\n }\n if (!best) return null\n // Byte-identical to text.method / a.method: id without a trailing query.\n return { url: `https://img.youtube.com/vi/${best.url.split('?')[0]}/hqdefault.jpg`, pos: best.pos }\n}\n\ninterface CandidateResult {\n candidate: ImageCandidate | null\n /**\n * A markdown image is present but the regex refused to decide (a URL with a\n * parenthesis, one over the length bound, broken syntax before the capture).\n * The full render resolves it; a regex-only caller must not pick anything\n * else in its place.\n */\n ambiguous: boolean\n}\n\nconst NONE: CandidateResult = { candidate: null, ambiguous: false }\nconst AMBIGUOUS: CandidateResult = { candidate: null, ambiguous: true }\n\nfunction findFirstImageCandidate(prepared: PreparedBody, includeBareUrls = false): CandidateResult {\n const { cleaned } = prepared\n if (!cleaned) return NONE\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 AMBIGUOUS\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 AMBIGUOUS\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 = firstStandalone(prepared.image, imageToken)\n if (bareMatch && SAFE_URL_RE.test(bareMatch.url)) {\n candidates.push(bareMatch)\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(/&/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 && isImageHref(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 NONE\n candidates.sort((a, b) => a.pos - b.pos)\n return { candidate: candidates[0], ambiguous: false }\n}\n\n/**\n * Everything fast mode can find without rendering markdown: the regex tiers\n * including standalone bare image URLs, plus the YouTube poster the full render\n * would have produced, whichever comes first in the source. Returns the same\n * proxied URL the full render's first <img> would have carried, or null.\n */\nfunction fastBodyImage(body: string, width: number, height: number, format: string): string | null {\n const prepared = prepareBody(body)\n // Same precedence as the full lookup: a markdown or HTML image found by the\n // regex wins outright, because the full lookup returns it before it would\n // ever render the markdown and notice an earlier poster or bare URL.\n const strict = findFirstImageCandidate(prepared, false)\n if (strict.candidate) {\n return proxifyFound(strict.candidate.url, width, height, format)\n }\n // A markdown image the regex could not decide on: the full render would\n // resolve it, and it may well come first. Nothing else may stand in for it.\n if (strict.ambiguous) {\n return null\n }\n // Otherwise the full lookup would render and take the first <img> in source\n // order, which is a bare image URL or a video poster.\n const bare = findFirstImageCandidate(prepared, true).candidate\n const poster = findFirstVideoPoster(prepared)\n if (poster && (!bare || poster.pos < bare.pos)) {\n // The rendered poster <img> carries the 0x0 proxied URL; re-proxying it at\n // the requested size is exactly what the full render path does with it.\n return proxifyFound(proxifyImageSrc(poster.url, 0, 0, 'match'), width, height, format)\n }\n return bare ? proxifyFound(bare.url, width, height, format) : null\n}\n\n// json_metadata is whatever the publishing client wrote: `thumbnails` has been\n// seen as a string, an array of strings, an array with junk in it, and a\n// non-array. Return the first usable URL or undefined, never throw.\nfunction firstMetaUrl(value: unknown): string | undefined {\n if (typeof value === 'string' && value.trim().length > 0) {\n return value\n }\n if (Array.isArray(value)) {\n return value.find((url): url is string => typeof url === 'string' && url.trim().length > 0)\n }\n return undefined\n}\n\nfunction proxifyFound(src: string, width: number, height: number, format: string): string {\n const decoded = decodeEntities(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', fastMode = false): 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 // An explicit thumbnail wins over the cover image: `thumbnails` exists for\n // exactly this purpose (3Speak, Liketu, the editor's thumbnail picker) and\n // publishers do set it to something other than the first body image.\n // A thumbnail that does not proxify (malformed, over the length bound) must\n // not suppress a valid cover below, so only a non-empty result is returned.\n const thumbnail = firstMetaUrl(meta?.thumbnails)\n if (thumbnail) {\n const decodedThumbnail = decodeEntities(thumbnail)\n const proxied = isGifLink(decodedThumbnail)\n ? proxifyImageSrc(decodedThumbnail, 0, 0, format)\n : proxifyImageSrc(decodedThumbnail, width, height, format)\n if (proxied) {\n return proxied\n }\n }\n\n if (meta && typeof meta.image === 'string' && meta.image.length > 0) {\n // Decode HTML entities (e.g., & -> &) before proxifying\n const decodedImage = decodeEntities(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., & -> &) before proxifying\n const decodedImage = decodeEntities(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 mode never renders markdown: regex tiers (bare URLs included) and the\n // YouTube poster, or null. The caller would rather show no thumbnail than pay\n // for a full markdown render on a body none of that found an image in.\n if (fastMode) {\n return fastBodyImage(entry.body, 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 the image an entry's BODY renders first:\n * json_metadata.image, then the first body image. Deliberately NOT the same\n * order as catchPostImage, which reads json_metadata.thumbnails ahead of\n * image: a thumbnail is a card concern and the post body never renders it, so\n * a preload built from it would be wasted. Unlike catchPostImage it does NOT\n * proxify — callers need the original URL (e.g. to test picture-eligibility\n * for an LCP preload, since catchPostImage returns an already-proxified /p/\n * URL). Returns null when the fast path finds no unambiguous image (the caller\n * 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 & /\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 interface CatchPostImageOptions {\n /**\n * Stop after the metadata and regex tiers. The last tier is a full\n * markdown2Html + DOM parse, which on a long body with no image at all costs\n * hundreds of milliseconds of synchronous CPU; a feed of such rows can hold a\n * server's event loop for seconds. Callers that can live without the rare\n * markdown-only finds (video embed posters, for instance) set this and get\n * null back instead. Default false keeps every existing caller byte-identical.\n */\n fast?: boolean\n}\n\nexport function catchPostImage(\n obj: Entry | string,\n width = 0,\n height = 0,\n format = 'match',\n options: CatchPostImageOptions = {}\n): string | null {\n const fastMode = options.fast === true\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 if (fastMode) {\n return fastBodyImage(obj, width, height, format)\n }\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 // Fast and full lookups can legitimately disagree (null vs a markdown-only\n // find), so they get separate slots rather than the first caller deciding for\n // both.\n const key = `${makeEntryCacheKey(obj)}-${width}x${height}-${format}${fastMode ? '-fast' : ''}`\n\n // A null result is memoized too. Recomputing it is the expensive case: the\n // markdown tier ran, found nothing, and would run again on the next request.\n const item = cacheGet<string | null | undefined>(key)\n if (item !== undefined) {\n return item\n }\n\n const res = getImage(obj, width, height, format, fastMode)\n cacheSet(key, res)\n\n return res\n}\n\n","import { decodeEntities, 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 = decodeEntities(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","p","XMLDOMSerializer","decodeEntities","text","img","iframe","imgEls","a","match","linkify","Remarkable","LRUCache","t0","res","from"],"mappings":"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","file":"index.js","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 { decodeHTML } from 'entities'\n\n/**\n * Decode HTML character references in user-authored text.\n *\n * `entities.decodeHTML` throws a RangeError on a numeric reference whose digit\n * string overflows a double (309+ decimal or 256+ hex digits, leading zeros\n * included: 0 * Infinity = NaN -> String.fromCodePoint(NaN)). Post bodies and\n * json_metadata come straight from the chain, so a crafted reference must\n * never take a feed page down. Leading zeros are dropped first (they carry no\n * value, and `A` must still be \"A\"); a reference that is still overlong\n * after that cannot be a code point and becomes U+FFFD, which is what the HTML\n * spec and the previous decoder (he) produce for an out-of-range value.\n * Anything else the decoder rejects is returned as-is.\n */\nconst LEADING_ZEROS_DEC = /�+(?=[0-9])/g\nconst LEADING_ZEROS_HEX = /�+(?=[0-9a-f])/gi\nconst OVERLONG_NUMERIC_REF = /&#(?:x[0-9a-f]{256,}|[0-9]{309,});?/gi\n\nexport function decodeEntities(value: string): string {\n const safe = value\n .replace(LEADING_ZEROS_DEC, '&#')\n .replace(LEADING_ZEROS_HEX, (m) => m.slice(0, 3))\n .replace(OVERLONG_NUMERIC_REF, '\\uFFFD')\n try {\n return decodeHTML(safe)\n } catch {\n return safe\n }\n}\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 (&, &#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 = decodeEntities(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 '>' 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; imageCount?: number }, 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\n /*\n Tiered loading (#1672). Index 0 is the LCP candidate: eager + high, and the\n entry page separately preloads it. Index 1 is very likely inside or near\n the first viewport on multi-image posts; plain lazy put it at priority Low\n behind the script wave, so its blur-up placeholder sharpened seconds after\n the page looked settled. It loads eager at default priority, which keeps\n the high hint exclusive to the LCP image. Index 2 onward stays lazy: eager\n is not free (it fetches unconditionally, even for images never scrolled\n to), so the eager set is kept to the two images that plausibly pay off.\n imageCount falls back to firstImageFound so callers passing the old state\n shape keep the old first-image behavior.\n */\n // Avatars (mention bylines, tiny inline profile images) neither deserve an\n // eager slot nor should they consume one that a content image needs. Match\n // ONLY the proxy avatar route and the exact author-link class token: a\n // substring test on arbitrary URLs would misclassify legitimate content\n // like https://cdn.example/avatar/art.jpg, lazy-load a real LCP candidate\n // and hand the high hint to the wrong image.\n const avatarRoute = new RegExp(`^${trimTrailingSlash(getProxyBase()).replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\")}/u/[^/]+/avatar(?:/[a-z]+)?$`);\n const classTokens = (el.getAttribute(\"class\") || \"\").split(/\\s+/);\n const isAvatar = avatarRoute.test(decodedSrc) || classTokens.includes(\"er-author-link-image\");\n if (isAvatar) {\n el.setAttribute(\"loading\", \"lazy\");\n el.setAttribute(\"decoding\", \"async\");\n }\n const imageIndex = !state || isAvatar ? 3 : (state.imageCount ?? (state.firstImageFound ? 1 : 0));\n if (state && !isAvatar) {\n state.imageCount = imageIndex + 1;\n state.firstImageFound = true;\n }\n if (isAvatar) {\n // attributes already set above; skip the tier\n } else if (imageIndex === 0) {\n el.setAttribute(\"loading\", \"eager\");\n el.setAttribute(\"fetchpriority\", \"high\");\n } else if (imageIndex === 1) {\n el.setAttribute(\"loading\", \"eager\");\n el.setAttribute(\"decoding\", \"async\");\n } else {\n el.setAttribute(\"loading\", \"lazy\");\n el.setAttribute(\"decoding\", \"async\");\n }\n // The high hint is EXCLUSIVE to index 0. Anything else that arrives with\n // one (author HTML passes the sanitizer; linkify grants a \"first image\"\n // high per text node) would compete with the real LCP request.\n if (isAvatar || imageIndex !== 0) {\n el.removeAttribute(\"fetchpriority\");\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 // & => & can break equality\n if (\n href.match(IMG_REGEX) &&\n href.trim().replace(/&/g, '&') ===\n getSerializedInnerHTML(el).trim().replace(/&/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(/&/g, '&') ===\n getSerializedInnerHTML(el).trim().replace(/&/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 // scrobble.life (\"---\\n_Originally posted through [scrobble.life/...\") and Lumen\n // (\"---\\n*Posted via Lumen*\" or \"---\\n*Posted via Lumen by <user>*\") both put a separator\n // right before their byline; drop it too (lookahead keeps unrelated horizontal rules),\n // otherwise the line filters below leave a dangling <hr> at the end of the post.\n const pre = s\n ? s.replace(\n /(^|\\n)-{3,}[ \\t]*\\n+(?=[^\\n]*(?:originally posted through \\[scrobble\\.life|\\*posted via lumen))/i,\n '$1'\n )\n : s\n return (pre ? pre.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('originally posted through [scrobble.life') === false)\n .filter(item => item.toLowerCase().includes('*posted via lumen') === false)\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\"></a></div>', '')\n .replace('<div><a href=\"https://engage.hivechain.app\"></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, decodeEntities, stripHtmlTags } from './helper'\nimport { cacheGet, cacheSet } from './cache'\nimport { Entry } from './types'\n\nconst gifLinkRegex = /\\.(gif)$/i;\n\nfunction isGifLink(link: string) {\n return gifLinkRegex.test(link);\n}\n\n// Strip code regions so that  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\n// HTML regions whose text never reaches the page as an image: <style> (dropped\n// by the sanitizer) and <pre> in block context (the renderer leaves its text\n// alone), plus HTML comments. Verified against the renderer: a URL inside\n// <code> or <script> text IS linkified into an image, so those are not listed.\n//\n// Plain index scans rather than regex replaces: the text is only ever searched\n// for image URLs, never emitted, so this is candidate extraction and not\n// sanitization, but the scans are also linear and leave nothing behind (an\n// unterminated region runs to the end, as in HTML).\n\n// What may follow a tag name, as the renderer reads it (probed, not the HTML\n// spec): on an opening tag, space, tab, form feed or carriage return, `/` or\n// `>`. A line feed anywhere inside the tag breaks the tag for the renderer and\n// the content renders as prose (see findOpenTagEnd). `<prefix>` is not `<pre`.\nconst OPEN_TAG_NAME_END = /[\\t\\f\\r />]/\n// A closing tag tolerates any whitespace before its `>`; `</prelude>` does not\n// close `<pre>`.\nconst CLOSE_TAG_NAME_END = /[\\s>]/\n\nfunction isWholeTagName(lower: string, idx: number, end: RegExp): boolean {\n const next = lower[idx]\n return next === undefined || end.test(next)\n}\n\n// Index of the next `<tag` / `</tag` occurrence at or after `from` whose tag\n// name is whole, or -1.\nfunction findTag(lower: string, tag: string, from: number, end: RegExp): number {\n let at = lower.indexOf(tag, from)\n while (at !== -1 && !isWholeTagName(lower, at + tag.length, end)) {\n at = lower.indexOf(tag, at + tag.length)\n }\n return at\n}\n\n// Where an opening tag that starts at `openAt` ends, read the way the renderer\n// reads it: the first `>` outside quotes closes it; a line feed before that\n// breaks the tag (it is then prose, not a tag); a `/` right before the `>`\n// makes it self-closing, which opens nothing. Returns the index of the `>`\n// for a real opening tag, -1 for an unterminated one (taken as open to the\n// end), and NaN for a broken or self-closing one, which is skipped.\nfunction findOpenTagEnd(lower: string, openAt: number): number {\n let quote = ''\n for (let i = openAt + 1; i < lower.length; i++) {\n const c = lower[i]\n if (c === '\\n') return NaN\n if (quote) {\n if (c === quote) quote = ''\n } else if (c === '\"' || c === \"'\") {\n quote = c\n } else if (c === '>') {\n return lower[i - 1] === '/' ? NaN : i\n }\n }\n return -1\n}\n\n// The markdown parser's HTML block tags (remarkable `html_blocks`). A line\n// indented at most three spaces that starts with `<` plus one of these (or a\n// closing tag of one, or `<!`/`<?`) is an HTML block, kept raw; any other line\n// is a paragraph and an element in it is inline content whose text is\n// linkified like prose. That is why `<pre>` hides its content only in block\n// context: `<code><pre>URL</pre></code>` renders the image, `<div><pre>` does\n// not. Verified against the renderer for both.\nconst HTML_BLOCK_TAGS = new Set([\n 'article', 'aside', 'button', 'blockquote', 'body', 'canvas', 'caption', 'col', 'colgroup', 'dd', 'div',\n 'dl', 'dt', 'embed', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5',\n 'h6', 'header', 'hgroup', 'hr', 'iframe', 'li', 'map', 'object', 'ol', 'output', 'p', 'pre', 'progress',\n 'script', 'section', 'style', 'table', 'tbody', 'td', 'textarea', 'tfoot', 'th', 'tr', 'thead', 'ul', 'video'\n])\n// The parser's own tag patterns: letters only, so `<h1>` never opens a block\n// (and a heading's content is linkified like prose); an opening tag needs\n// whitespace, `/` or `>` after the name on the same line, a closing tag\n// whitespace or `>`.\nconst HTML_BLOCK_LINE_RE = /^ {0,3}<(?:[!?]|([a-z]{1,15})[\\s/>]|\\/([a-z]{1,15})[\\s>])/\n\n// Markdown container prefixes the parser strips before it looks at a line:\n// blockquote markers (`>` with an optional space, nestable, up to three spaces\n// of indent) and, at column 0 only, a list marker with its following spaces.\n// An indented list marker is not a container for the renderer (` - <pre>`\n// renders the content inline), hence column 0.\nconst BLOCKQUOTE_PREFIX_RE = /^ {0,3}> ?/\nconst LIST_PREFIX_RE = /^(?:[-*+]|\\d{1,9}[.)]) +/\n\ninterface LineMasks {\n /** Offsets inside a markdown HTML block (raw HTML, <pre>/<code> honoured). */\n block: Uint8Array\n /** Offsets on an indented code line inside a container (nothing renders). */\n code: Uint8Array\n}\n\n// Per-offset masks over the ORIGINAL body, computed once before any region is\n// blanked, because the parser decides on the original lines: removing a\n// leading comment or <style> would otherwise reclassify what follows as\n// inline content. Per line: strip the container prefixes, then a line that\n// opens a block (see HTML_BLOCK_LINE_RE) and every following line up to the\n// next blank one is a block; a remainder indented four spaces inside a\n// container is an indented code block. Linear.\nfunction markLines(lower: string): LineMasks {\n const block = new Uint8Array(lower.length)\n const code = new Uint8Array(lower.length)\n let inBlock = false\n // Width of the current list item's content indent, for its continuation\n // lines, and whether that item is a nested one (inline continuation).\n let listIndent = 0\n let nestedItem = false\n let lineStart = 0\n while (lineStart <= lower.length) {\n let lineEnd = lower.indexOf('\\n', lineStart)\n if (lineEnd === -1) lineEnd = lower.length\n let line = lower.slice(lineStart, lineEnd)\n // An open HTML block is raw until its blank-line terminator: container\n // markers inside it are text, not markers, so nothing below applies.\n if (inBlock) {\n if (line.trim() === '') {\n inBlock = false\n listIndent = 0\n nestedItem = false\n } else {\n block.fill(1, lineStart, lineEnd)\n }\n lineStart = lineEnd + 1\n continue\n }\n let inContainer = false\n // Container prefixes, in any alternation (`- > <pre>`, `> - <pre>`,\n // `> > - > <pre>`, `- - > <pre>`), all probed: blockquote and list\n // markers strip in any order and any depth, and the remainder is block\n // context, EXCEPT that content directly after a nested list marker (a\n // list marker following a list marker, `- - <pre>`, `> - - <pre>`) is\n // inline, as are the continuation lines of that nested item; a blockquote\n // marker after the nested marker restores block context (`- - > <pre>`).\n let stripped = 0\n let sawList = false\n let lastWasList = false\n let inlineRemainder = false\n for (;;) {\n const bq = BLOCKQUOTE_PREFIX_RE.exec(line)\n if (bq) {\n line = line.slice(bq[0].length)\n stripped += bq[0].length\n lastWasList = false\n inlineRemainder = false\n inContainer = true\n continue\n }\n const lm = LIST_PREFIX_RE.exec(line)\n if (lm) {\n line = line.slice(lm[0].length)\n stripped += lm[0].length\n if (lastWasList) inlineRemainder = true\n sawList = true\n lastWasList = true\n inContainer = true\n continue\n }\n break\n }\n if (sawList) {\n listIndent = stripped\n nestedItem = inlineRemainder\n } else if (listIndent > 0 && line.trim() !== '') {\n let indent = 0\n while (indent < listIndent && line[indent] === ' ') indent++\n if (indent >= Math.min(listIndent, 2)) {\n line = line.slice(indent)\n inContainer = true\n // A nested item's continuation line is inline content too.\n inlineRemainder = nestedItem\n } else {\n listIndent = 0\n nestedItem = false\n }\n }\n const blank = line.trim() === ''\n if (blank) {\n inBlock = false\n listIndent = 0\n nestedItem = false\n } else if (inlineRemainder) {\n // Inline content: neither opens nor continues a block.\n inBlock = false\n } else if (!inBlock && /^(?: {4}|\\t)/.test(line)) {\n // An indented code block, judged after the container prefixes and the\n // list item's content indent are gone: four spaces at top level or\n // inside a blockquote are code, while a list item's continuation line\n // indented to its content is not.\n code.fill(1, lineStart, lineEnd)\n } else if (!inBlock) {\n const m = HTML_BLOCK_LINE_RE.exec(line)\n if (m) {\n const tag = m[1] ?? m[2]\n inBlock = tag === undefined || HTML_BLOCK_TAGS.has(tag)\n }\n }\n if (inBlock && !blank) block.fill(1, lineStart, lineEnd)\n lineStart = lineEnd + 1\n }\n return { block, code }\n}\n\n// Every strip below is offset-preserving (a blanked character becomes a space,\n// newlines stay), so the block mask and every later position stay valid.\nconst blankChars = (s: string): string => s.replace(/[^\\n]/g, ' ')\n\nfunction blankMatches(text: string, re: RegExp): string {\n return text.replace(re, blankChars)\n}\n\n/** One text in two spellings, kept in step: blanking one blanks the other. */\ninterface Spellings {\n text: string\n lower: string\n}\n\nfunction blankSpans(input: Spellings, open: string, close: string, tagNames: boolean, blockMask: Uint8Array | null): Spellings {\n const { text, lower } = input\n const findOpen = (from: number): number => {\n if (!tagNames) return lower.indexOf(open, from)\n let at = findTag(lower, open, from, OPEN_TAG_NAME_END)\n while (at !== -1 && (Number.isNaN(findOpenTagEnd(lower, at)) || (blockMask !== null && !blockMask[at]))) {\n at = findTag(lower, open, at + open.length, OPEN_TAG_NAME_END)\n }\n return at\n }\n const findClose = (from: number): number =>\n tagNames ? findTag(lower, close, from, CLOSE_TAG_NAME_END) : lower.indexOf(close, from)\n let start = findOpen(0)\n if (start === -1) return input\n // Collect the spans, then rebuild both spellings in one pass.\n const textParts: string[] = []\n const lowerParts: string[] = []\n let from = 0\n while (start !== -1) {\n const end = findClose(start + open.length)\n let to: number\n if (end === -1) {\n to = text.length\n } else if (tagNames) {\n // Through the closing tag's `>` (`</pre>`, `</pre >`).\n const gt = lower.indexOf('>', end + close.length)\n to = gt === -1 ? text.length : gt + 1\n } else {\n to = end + close.length\n }\n const blanked = blankChars(lower.slice(start, to))\n textParts.push(text.slice(from, start), blanked)\n lowerParts.push(lower.slice(from, start), blanked)\n from = to\n start = to >= text.length ? -1 : findOpen(to)\n }\n textParts.push(text.slice(from))\n lowerParts.push(lower.slice(from))\n return { text: textParts.join(''), lower: lowerParts.join('') }\n}\n\nfunction blankMasked(input: Spellings, mask: Uint8Array): Spellings {\n let text = ''\n let lower = ''\n let from = 0\n for (let i = 0; i < mask.length; i++) {\n if (!mask[i]) continue\n let j = i\n while (j < mask.length && mask[j]) j++\n text += input.text.slice(from, i) + blankChars(input.text.slice(i, j))\n lower += input.lower.slice(from, i) + blankChars(input.lower.slice(i, j))\n from = j\n i = j\n }\n if (from === 0) return input\n return { text: text + input.text.slice(from), lower: lower + input.lower.slice(from) }\n}\n\nfunction stripHiddenRegions(text: string): string {\n let spellings: Spellings = { text, lower: text.toLowerCase() }\n const { block: blockMask, code: codeMask } = markLines(spellings.lower)\n spellings = blankMasked(spellings, codeMask)\n spellings = blankSpans(spellings, '<!--', '-->', false, null)\n // <style> is dropped by the sanitizer wherever it sits. <pre> and <code> keep\n // their text from being linkified only inside a markdown HTML block; in a\n // paragraph both are inline content and their text renders as prose.\n spellings = blankSpans(spellings, '<style', '</style', true, null)\n spellings = blankSpans(spellings, '<pre', '</pre', true, blockMask)\n spellings = blankSpans(spellings, '<code', '</code', true, blockMask)\n return spellings.text\n}\n// Requires a closing `)` so broken syntax like ` doesn't\n// match. Also tolerates the optional title form ``. The alt-text\n// class excludes `[` (so a `,\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, or the `>` that closes a wrapping tag such as <center> (group 1),\n// so it is NOT a URL already inside ![](), <img src=\"\">, or a [label](href)\n// link — avoiding false positives on image-extension URLs that the renderer\n// does NOT surface as a standalone image. Same extension set as the renderer's\n// IMG_REGEX. Linear-time: one bounded char class + a single greedy `+`, no\n// nested quantifier.\n// Every http(s) URL token is a candidate; isStandalone() then rejects the\n// ones that sit inside another construct, and a classifier decides whether a\n// token is an image (by extension) or a YouTube link (by host), in code rather\n// than in the pattern: a class followed by a literal it also matches, or a\n// repeated group before a literal, is polynomial on crafted input. The token\n// pattern itself is one class run, linear on any input. Global, so matchAll\n// can walk the tokens in source order.\nconst URL_TOKEN_RE = /https?:\\/\\/[^\\s<>\"'()[\\]]+/gi\n// An image extension, the same set the renderer's IMG_REGEX uses. Global and\n// without a wildcard before it: every occurrence is found in one linear pass.\nconst IMAGE_EXT_G = /\\.(?:tiff?|jpe?g|gif|png|svg|ico|heic|webp|arw)/gi\n// A YouTube video id as the renderer's YOUTUBE_REGEX captures it.\nconst YOUTUBE_ID_RE = /^[^\"&?/\\s]{11}$/\n\n/**\n * The image URL a bare token denotes, or null: the token up to its last image\n * extension, extended through the query or fragment when one follows, which\n * is what the earlier greedy pattern matched (prose punctuation or emphasis\n * after the extension is left out, a URL carried in another URL's query is\n * taken whole).\n */\nfunction imageToken(token: string): string | null {\n let end = -1\n for (const m of token.matchAll(IMAGE_EXT_G)) {\n end = (m.index ?? 0) + m[0].length\n }\n if (end === -1) return null\n if (end < token.length && (token[end] === '?' || token[end] === '#')) end = token.length\n const url = token.slice(0, end)\n return SAFE_URL_RE.test(url) ? url : null\n}\n\n/**\n * The video id of a YouTube URL, read the way the renderer's YOUTUBE_REGEX\n * reads it (`v=` query, `/v/`, `/e/`, `/embed/`, `/shorts/`, `youtu.be/`, or the\n * last segment of a deeper path), with plain string operations so the check is\n * linear on any input. Any subdomain (music., m., www.) counts. Null when the\n * URL is not a YouTube video link.\n */\nfunction youtubeIdOf(url: string): string | null {\n const m = /^https?:\\/\\/([^/?#]+)/i.exec(url)\n if (!m) return null\n const host = m[1].toLowerCase()\n const isShort = host === 'youtu.be'\n const isFull = host === 'youtube.com' || host.endsWith('.youtube.com')\n if (!isShort && !isFull) return null\n const rest = url.slice(m[0].length)\n const hashAt = rest.indexOf('#')\n const beforeHash = hashAt === -1 ? rest : rest.slice(0, hashAt)\n const qAt = beforeHash.indexOf('?')\n const path = qAt === -1 ? beforeHash : beforeHash.slice(0, qAt)\n const query = qAt === -1 ? '' : beforeHash.slice(qAt + 1)\n const candidate = (value: string | undefined): string | null => {\n const id = value === undefined ? '' : value.slice(0, 11)\n return YOUTUBE_ID_RE.test(id) ? id : null\n }\n if (isFull && query) {\n for (const part of query.split('&')) {\n if (part.startsWith('v=')) {\n const id = candidate(part.slice(2))\n if (id) return id\n }\n }\n }\n const segments = path.split('/').filter((seg) => seg.length > 0)\n if (isShort) return candidate(segments[0])\n if (segments.length >= 2 && ['v', 'e', 'embed', 'shorts'].includes(segments[0].toLowerCase())) {\n return candidate(segments[1])\n }\n if (segments.length >= 3) return candidate(segments[segments.length - 1])\n return null\n}\n\n// One linear pass marking every offset that sits inside an HTML tag (between\n// a `<` that opens a tag and its closing `>`, quotes respected so a `>` inside\n// an attribute value does not end the tag early). A URL in there is an\n// attribute value of some shape (`src=\"...\"`, `style=\"url(...)\"`, JSON in a\n// `data-*` attribute, `poster=`) and never prose the renderer would linkify.\nfunction isAutolinkAt(text: string, idx: number): boolean {\n // Schemes are case-insensitive: <HTTPS://...> autolinks like <https://...>.\n return /^https?:\\/\\//i.test(text.slice(idx, idx + 8))\n}\n\nfunction markInsideTags(text: string): Uint8Array {\n const marks = new Uint8Array(text.length)\n let inTag = false\n let quote = ''\n for (let i = 0; i < text.length; i++) {\n const c = text[i]\n if (!inTag) {\n // A markdown autolink `<https://...>` is not a tag: the renderer turns\n // it into a link, and an image or video URL in it into an image.\n if (c === '<' && i + 1 < text.length && /[A-Za-z/!?]/.test(text[i + 1]) && !isAutolinkAt(text, i + 1)) {\n inTag = true\n marks[i] = 1\n }\n continue\n }\n marks[i] = 1\n if (quote) {\n if (c === quote) quote = ''\n } else if (c === '\"' || c === \"'\") {\n quote = c\n } else if (c === '>') {\n inTag = false\n }\n }\n return marks\n}\n\n// Whether a URL found at `idx` stands on its own in prose, which is what the\n// renderer linkifies into an image or a video poster. Verified against the\n// renderer: it does so after whitespace, a closing `>`, and inside\n// parentheses, emphasis or quotes alike. It does NOT when the URL is:\n// - anywhere inside a tag (an attribute value of any shape), or\n// - glued to another token (a longer URL, a word, `=`), or\n// - the href of a markdown link `[label](href)`, or the label's start `[`\n// (the `[url](url)` image-link form is found by the link scan instead), or\n// - a markdown image `` (its href follows `](`, handled above;\n// a bare `!` before a URL is prose and the renderer linkifies the URL).\nfunction isStandalone(scan: ScanText, idx: number): boolean {\n if (scan.inTag[idx]) return false\n if (idx === 0) return true\n const text = scan.text\n const prev = text[idx - 1]\n if (/[\\w/.:%?&=#[-]/.test(prev)) return false\n const prev2 = idx > 1 ? text[idx - 2] : ''\n if (prev === '(' && prev2 === ']') return false\n return true\n}\n\n// Standalone URL tokens in source order, each reduced by `classify` (image\n// URL, video id); tokens the classifier rejects are skipped.\nfunction* standaloneMatches(\n scan: ScanText,\n classify: (token: string) => string | null\n): Generator<{ url: string; pos: number }> {\n for (const m of scan.text.matchAll(URL_TOKEN_RE)) {\n const idx = m.index ?? 0\n if (!isStandalone(scan, idx)) continue\n const value = classify(m[0])\n if (value !== null) yield { url: value, pos: idx }\n }\n}\n\nfunction firstStandalone(scan: ScanText, classify: (token: string) => string | null): { url: string; pos: number } | null {\n for (const hit of standaloneMatches(scan, classify)) return hit\n return null\n}\n// The href of an anchor's opening tag, quoted either way or bare. Preceded by\n// whitespace, never by `-`: `data-href` is not the href.\nconst HREF_ATTR_RE = /\\shref\\s*=\\s*(?:\"([^\"]*)\"|'([^']*)'|([^\\s\"'>]+))/i\n// Whether a quoted attribute value runs straight into the next attribute\n// name (`title=\"x\"href=`). The renderer does not read such a tag as an anchor\n// at all: it escapes the tag as text and linkifies the URL inside, so the\n// scans must leave it alone rather than blank it. A quote-state walk: only a\n// CLOSING quote followed by a letter counts.\nfunction hasGluedAttribute(tag: string): boolean {\n let quote = ''\n for (let i = 0; i < tag.length; i++) {\n const c = tag[i]\n if (quote) {\n if (c === quote) {\n quote = ''\n const next = tag[i + 1]\n if (next !== undefined && /[A-Za-z]/.test(next)) return true\n }\n } else if (c === '\"' || c === \"'\") {\n quote = c\n }\n }\n return false\n}\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 ` per failed start.\nconst MD_LINK_RE = /\\[([^[\\]]*)\\]\\(\\s*([^)\\s[]+)(?:\\s+[\"'][^\"']*[\"'])?\\s*\\)/g\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// Mirrors a.method's `href.match(IMG_REGEX)` — an http(s) URL with an image\n// extension anywhere after a dot, matching the renderer. Two anchored tests\n// rather than one `.*\\.` pattern, so the check is linear on any input.\n// Eligibility for an avif <source> is then decided separately by\n// isPictureEligibleRawUrl.\nconst IMG_EXT_RE = /\\.(?:tiff?|jpe?g|gif|png|svg|ico|heic|webp|arw)/i\nconst isImageHref = (href: string): boolean => SAFE_URL_RE.test(href) && IMG_EXT_RE.test(href)\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 return findFirstImageCandidate(prepareBody(body), includeBareUrls).candidate?.url ?? null\n}\n\nfunction stripCodeRegions(body: string): string {\n let text = blankMatches(body, BACKTICK_FENCE_RE)\n text = blankMatches(text, TILDE_FENCE_RE)\n text = blankMatches(text, INLINE_CODE_RE)\n // Indented code blocks are blanked by the line model (markLines), which\n // knows the container context a four-space indent has to be read in.\n return stripHiddenRegions(text)\n}\n\n// Blank (offset-preserving, so positions stay comparable) every anchor the\n// renderer would not promote. Verified against the renderer, the two\n// promotions use different tests: a video link is promoted when the anchor's\n// textContent equals its href (nested <span> and the like allowed), an image\n// link when the anchor's FIRST text child equals its href (`URL<span>x</span>`\n// is promoted, `URL caption` and `<span>x</span>URL` are not). Entities are\n// decoded on both sides, as the DOM exposes them. See HTML_ANCHOR_RE.\n// An HTML anchor's text sits right after a `>`, so the standalone-position rule\n// would read an image or video URL used as link TEXT as a bare URL. The\n// renderer only promotes such an anchor when the text equals the href\n// (a.method), so anchors whose text differs are blanked before the bare scans.\n// A scan rather than a regex: the opening tag's end is found quote-aware (a\n// `>` inside a title must not end it), and the href may be quoted or bare.\nfunction blankUnequalAnchors(cleaned: string, textContent: boolean): string {\n const lower = cleaned.toLowerCase()\n // Output chunks, joined once: rebuilding the string per anchor is quadratic\n // on a body with thousands of anchors.\n const parts: string[] = []\n let from = 0\n let at = findTag(lower, '<a', 0, OPEN_TAG_NAME_END)\n while (at !== -1) {\n const gt = findOpenTagEnd(lower, at)\n if (Number.isNaN(gt) || gt === -1 || hasGluedAttribute(cleaned.slice(at, gt))) {\n // Broken, self-closing or malformed: not an anchor around any text.\n at = findTag(lower, '<a', at + 2, OPEN_TAG_NAME_END)\n continue\n }\n const closeAt = findTag(lower, '</a', gt + 1, CLOSE_TAG_NAME_END)\n const innerEnd = closeAt === -1 ? cleaned.length : closeAt\n let spanEnd = cleaned.length\n if (closeAt !== -1) {\n const closeGt = lower.indexOf('>', closeAt + 3)\n spanEnd = closeGt === -1 ? cleaned.length : closeGt + 1\n }\n const hrefMatch = HREF_ATTR_RE.exec(cleaned.slice(at, gt))\n const href = hrefMatch ? (hrefMatch[1] ?? hrefMatch[2] ?? hrefMatch[3] ?? '') : ''\n const inner = cleaned.slice(gt + 1, innerEnd)\n let text: string\n if (textContent) {\n text = stripHtmlTags(inner)\n } else {\n // The first text child ends at the first real tag start; a literal `<`\n // in prose (`URL < caption`) is part of that text and breaks equality.\n const firstTag = inner.search(/<[A-Za-z/!]/)\n text = firstTag === -1 ? inner : inner.slice(0, firstTag)\n }\n if (!href || decodeEntities(text.trim()) !== decodeEntities(href.trim())) {\n parts.push(cleaned.slice(from, at), blankChars(cleaned.slice(at, spanEnd)))\n from = spanEnd\n }\n at = spanEnd >= cleaned.length ? -1 : findTag(lower, '<a', spanEnd, OPEN_TAG_NAME_END)\n }\n if (parts.length === 0) return cleaned\n parts.push(cleaned.slice(from))\n return parts.join('')\n}\n\n/** One scan text plus its inside-a-tag marks. */\ninterface ScanText {\n text: string\n inTag: Uint8Array\n}\n\n/**\n * The body with every region the page never shows removed, plus the two\n * anchor-blanked variants the bare scans need (image rule and video rule, see\n * blankUnequalAnchors), each with its inside-a-tag marks. Computed once per\n * lookup; every scan below works on these.\n */\ninterface PreparedBody {\n cleaned: string\n image: ScanText\n video: ScanText\n}\n\nconst EMPTY_SCAN: ScanText = { text: '', inTag: new Uint8Array(0) }\n\nfunction prepareBody(body: string): PreparedBody {\n const cleaned = body ? stripCodeRegions(body) : ''\n if (!cleaned) return { cleaned, image: EMPTY_SCAN, video: EMPTY_SCAN }\n const imageText = blankUnequalAnchors(cleaned, false)\n const videoText = blankUnequalAnchors(cleaned, true)\n return {\n cleaned,\n image: { text: imageText, inTag: markInsideTags(imageText) },\n video: { text: videoText, inTag: markInsideTags(videoText) }\n }\n}\n\ninterface ImageCandidate {\n url: string\n /** Offset in the code-stripped body, for source-order comparisons. */\n pos: number\n}\n\n/**\n * The poster image the renderer would produce for the first standalone YouTube\n * URL in the body, with its position, or null. Fast-mode only: the full render\n * discovers these itself through text.method / a.method.\n */\nfunction findFirstVideoPoster(prepared: PreparedBody): ImageCandidate | null {\n const { cleaned } = prepared\n if (!cleaned) return null\n let best: ImageCandidate | null = null\n // The first YouTube URL that actually carries a video id: a channel or\n // playlist link earlier in the body must not hide a later watch link.\n for (const hit of standaloneMatches(prepared.video, youtubeIdOf)) {\n best = { url: hit.url, pos: hit.pos }\n break\n }\n // `[url](url)` form: a.method turns a link whose text equals its href into\n // the same poster. Take it only when it comes before the bare form.\n for (const m of cleaned.matchAll(MD_LINK_RE)) {\n const idx = m.index ?? 0\n if (idx > 0 && cleaned[idx - 1] === '!') continue\n if (best && idx >= best.pos) break\n const href = m[2]\n if (href && m[1].trim() === href) {\n const id = youtubeIdOf(href)\n if (id) {\n best = { url: id, pos: idx }\n break\n }\n }\n }\n if (!best) return null\n // Byte-identical to text.method / a.method: id without a trailing query.\n return { url: `https://img.youtube.com/vi/${best.url.split('?')[0]}/hqdefault.jpg`, pos: best.pos }\n}\n\ninterface CandidateResult {\n candidate: ImageCandidate | null\n /**\n * A markdown image is present but the regex refused to decide (a URL with a\n * parenthesis, one over the length bound, broken syntax before the capture).\n * The full render resolves it; a regex-only caller must not pick anything\n * else in its place.\n */\n ambiguous: boolean\n}\n\nconst NONE: CandidateResult = { candidate: null, ambiguous: false }\nconst AMBIGUOUS: CandidateResult = { candidate: null, ambiguous: true }\n\nfunction findFirstImageCandidate(prepared: PreparedBody, includeBareUrls = false): CandidateResult {\n const { cleaned } = prepared\n if (!cleaned) return NONE\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 AMBIGUOUS\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 AMBIGUOUS\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 = firstStandalone(prepared.image, imageToken)\n if (bareMatch && SAFE_URL_RE.test(bareMatch.url)) {\n candidates.push(bareMatch)\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(/&/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 && isImageHref(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 NONE\n candidates.sort((a, b) => a.pos - b.pos)\n return { candidate: candidates[0], ambiguous: false }\n}\n\n/**\n * Everything fast mode can find without rendering markdown: the regex tiers\n * including standalone bare image URLs, plus the YouTube poster the full render\n * would have produced, whichever comes first in the source. Returns the same\n * proxied URL the full render's first <img> would have carried, or null.\n */\nfunction fastBodyImage(body: string, width: number, height: number, format: string): string | null {\n const prepared = prepareBody(body)\n // Same precedence as the full lookup: a markdown or HTML image found by the\n // regex wins outright, because the full lookup returns it before it would\n // ever render the markdown and notice an earlier poster or bare URL.\n const strict = findFirstImageCandidate(prepared, false)\n if (strict.candidate) {\n return proxifyFound(strict.candidate.url, width, height, format)\n }\n // A markdown image the regex could not decide on: the full render would\n // resolve it, and it may well come first. Nothing else may stand in for it.\n if (strict.ambiguous) {\n return null\n }\n // Otherwise the full lookup would render and take the first <img> in source\n // order, which is a bare image URL or a video poster.\n const bare = findFirstImageCandidate(prepared, true).candidate\n const poster = findFirstVideoPoster(prepared)\n if (poster && (!bare || poster.pos < bare.pos)) {\n // The rendered poster <img> carries the 0x0 proxied URL; re-proxying it at\n // the requested size is exactly what the full render path does with it.\n return proxifyFound(proxifyImageSrc(poster.url, 0, 0, 'match'), width, height, format)\n }\n return bare ? proxifyFound(bare.url, width, height, format) : null\n}\n\n// json_metadata is whatever the publishing client wrote: `thumbnails` has been\n// seen as a string, an array of strings, an array with junk in it, and a\n// non-array. Return the first usable URL or undefined, never throw.\nfunction firstMetaUrl(value: unknown): string | undefined {\n if (typeof value === 'string' && value.trim().length > 0) {\n return value\n }\n if (Array.isArray(value)) {\n return value.find((url): url is string => typeof url === 'string' && url.trim().length > 0)\n }\n return undefined\n}\n\nfunction proxifyFound(src: string, width: number, height: number, format: string): string {\n const decoded = decodeEntities(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', fastMode = false): 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 // An explicit thumbnail wins over the cover image: `thumbnails` exists for\n // exactly this purpose (3Speak, Liketu, the editor's thumbnail picker) and\n // publishers do set it to something other than the first body image.\n // A thumbnail that does not proxify (malformed, over the length bound) must\n // not suppress a valid cover below, so only a non-empty result is returned.\n const thumbnail = firstMetaUrl(meta?.thumbnails)\n if (thumbnail) {\n const decodedThumbnail = decodeEntities(thumbnail)\n const proxied = isGifLink(decodedThumbnail)\n ? proxifyImageSrc(decodedThumbnail, 0, 0, format)\n : proxifyImageSrc(decodedThumbnail, width, height, format)\n if (proxied) {\n return proxied\n }\n }\n\n if (meta && typeof meta.image === 'string' && meta.image.length > 0) {\n // Decode HTML entities (e.g., & -> &) before proxifying\n const decodedImage = decodeEntities(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., & -> &) before proxifying\n const decodedImage = decodeEntities(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 mode never renders markdown: regex tiers (bare URLs included) and the\n // YouTube poster, or null. The caller would rather show no thumbnail than pay\n // for a full markdown render on a body none of that found an image in.\n if (fastMode) {\n return fastBodyImage(entry.body, 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 the image an entry's BODY renders first:\n * json_metadata.image, then the first body image. Deliberately NOT the same\n * order as catchPostImage, which reads json_metadata.thumbnails ahead of\n * image: a thumbnail is a card concern and the post body never renders it, so\n * a preload built from it would be wasted. Unlike catchPostImage it does NOT\n * proxify — callers need the original URL (e.g. to test picture-eligibility\n * for an LCP preload, since catchPostImage returns an already-proxified /p/\n * URL). Returns null when the fast path finds no unambiguous image (the caller\n * 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 & /\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 interface CatchPostImageOptions {\n /**\n * Stop after the metadata and regex tiers. The last tier is a full\n * markdown2Html + DOM parse, which on a long body with no image at all costs\n * hundreds of milliseconds of synchronous CPU; a feed of such rows can hold a\n * server's event loop for seconds. Callers that can live without the rare\n * markdown-only finds (video embed posters, for instance) set this and get\n * null back instead. Default false keeps every existing caller byte-identical.\n */\n fast?: boolean\n}\n\nexport function catchPostImage(\n obj: Entry | string,\n width = 0,\n height = 0,\n format = 'match',\n options: CatchPostImageOptions = {}\n): string | null {\n const fastMode = options.fast === true\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 if (fastMode) {\n return fastBodyImage(obj, width, height, format)\n }\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 // Fast and full lookups can legitimately disagree (null vs a markdown-only\n // find), so they get separate slots rather than the first caller deciding for\n // both.\n const key = `${makeEntryCacheKey(obj)}-${width}x${height}-${format}${fastMode ? '-fast' : ''}`\n\n // A null result is memoized too. Recomputing it is the expensive case: the\n // markdown tier ran, found nothing, and would run again on the next request.\n const item = cacheGet<string | null | undefined>(key)\n if (item !== undefined) {\n return item\n }\n\n const res = getImage(obj, width, height, format, fastMode)\n cacheSet(key, res)\n\n return res\n}\n\n","import { decodeEntities, 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 = decodeEntities(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"]}
|