From 88f1eb3d037c7214421f9d72940e94f62548a45c Mon Sep 17 00:00:00 2001 From: khannurien Date: Sat, 27 Jun 2026 14:34:47 +0000 Subject: [PATCH] v3: rich content meta regex improvements --- api/services/rich-content-service.ts | 57 +++++++++++++--------------- 1 file changed, 26 insertions(+), 31 deletions(-) diff --git a/api/services/rich-content-service.ts b/api/services/rich-content-service.ts index f00dca8..977a505 100644 --- a/api/services/rich-content-service.ts +++ b/api/services/rich-content-service.ts @@ -139,25 +139,35 @@ function decodeHtmlEntities(str: string): string { ); } +/** + * Find the first `` tag whose `attr` equals `value` and return its + * `content` (either attribute ordering). Each tag is matched in isolation so + * the `content` capture can never span across tag boundaries. + */ +function extractMetaContent( + html: string, + attr: string, + value: string, +): string | undefined { + const escaped = value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); + const keyRe = new RegExp(`\\b${attr}=["']${escaped}["']`, "i"); + const contentRe = /\bcontent=(["'])([\s\S]*?)\1/i; + const tagRe = /]*>/gi; + let m: RegExpExecArray | null; + while ((m = tagRe.exec(html)) !== null) { + const tag = m[0]; + if (!keyRe.test(tag)) continue; + const content = contentRe.exec(tag); + if (content) return decodeHtmlEntities(content[2]); + } + return undefined; +} + export function extractOgTag( html: string, tag: string, ): string | undefined { - const patterns = [ - new RegExp( - `]+property=["']og:${tag}["'][^>]+content=(["'])([\\s\\S]*?)\\1`, - "i", - ), - new RegExp( - `]+content=(["'])([\\s\\S]*?)\\1[^>]+property=["']og:${tag}["']`, - "i", - ), - ]; - for (const pattern of patterns) { - const match = html.match(pattern); - if (match) return decodeHtmlEntities(match[2]); - } - return undefined; + return extractMetaContent(html, "property", `og:${tag}`); } /** Extract content from `` (both attribute orderings). */ @@ -165,22 +175,7 @@ export function extractMetaName( html: string, name: string, ): string | undefined { - const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); - const patterns = [ - new RegExp( - `]+name=["']${escaped}["'][^>]+content=(["'])([\\s\\S]*?)\\1`, - "i", - ), - new RegExp( - `]+content=(["'])([\\s\\S]*?)\\1[^>]+name=["']${escaped}["']`, - "i", - ), - ]; - for (const pattern of patterns) { - const match = html.match(pattern); - if (match) return decodeHtmlEntities(match[2]); - } - return undefined; + return extractMetaContent(html, "name", name); } /** Extract the text content of the `` element. */