From daad7aeecd9336b8bdb20deec788c4314c6ff891 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A5=87=E8=B6=A3=E4=BF=9D=E7=BD=97?= Date: Mon, 2 Jun 2025 11:54:12 +0800 Subject: [PATCH] Fix image relative url error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复相对链接图片无法显示问题 --- contents/read.ts | 47 ++++++++++++++++++++++++++++++----------------- utils/html.ts | 46 +++++++++++++++++++++++++++++++++++++++------- 2 files changed, 69 insertions(+), 24 deletions(-) diff --git a/contents/read.ts b/contents/read.ts index 988623d..50aa7f2 100644 --- a/contents/read.ts +++ b/contents/read.ts @@ -121,26 +121,31 @@ const getHTML = () => { if (location.host === "mp.weixin.qq.com") { console.log("微信"); - return formatHTML(document.querySelector(".rich_media_content").innerHTML); + return formatHTML(document.querySelector(".rich_media_content").innerHTML, { + baseURL: location.origin, + }); } // 腾讯云开发者社区 if (location.host === "cloud.tencent.com") { console.log("腾讯云"); - return formatHTML(document.querySelector(".rno-markdown").innerHTML, (doc) => { - // 替换掉腾讯云自己的链接 - const qcloudLinkEl = doc.querySelectorAll("a"); - qcloudLinkEl.forEach((el) => { - if (el.href.includes("qcloud")) { - el.parentNode.replaceChild(document.createTextNode(el.innerText), el); - } - }); + return formatHTML(document.querySelector(".rno-markdown").innerHTML, { + formatter: (doc) => { + // 替换掉腾讯云自己的链接 + const qcloudLinkEl = doc.querySelectorAll("a"); + qcloudLinkEl.forEach((el) => { + if (el.href.includes("qcloud")) { + el.parentNode.replaceChild(document.createTextNode(el.innerText), el); + } + }); - const mdTextEl = doc.querySelectorAll(".rno-markdown__textlink-new") as NodeListOf; - mdTextEl.forEach((el) => { - el.parentNode.replaceChild(document.createTextNode(el.innerText), el); - }); + const mdTextEl = doc.querySelectorAll(".rno-markdown__textlink-new") as NodeListOf; + mdTextEl.forEach((el) => { + el.parentNode.replaceChild(document.createTextNode(el.innerText), el); + }); + }, + baseURL: location.origin, }); } @@ -150,7 +155,9 @@ const getHTML = () => { if (itemPropArticle) { console.log("掘金"); - return formatHTML(itemPropArticle.innerHTML); + return formatHTML(itemPropArticle.innerHTML, { + baseURL: location.origin, + }); } // CSDN @@ -159,7 +166,9 @@ const getHTML = () => { if (contentViews) { console.log("CSDN"); - return formatHTML(contentViews.innerHTML); + return formatHTML(contentViews.innerHTML, { + baseURL: location.origin, + }); } // 通用模式 @@ -168,7 +177,9 @@ const getHTML = () => { if (articleEl) { console.log("文章标签"); - return formatHTML(articleEl.innerHTML); + return formatHTML(articleEl.innerHTML, { + baseURL: location.origin, + }); } // 尝试匹配到文章 @@ -196,7 +207,9 @@ const getHTML = () => { } } - return formatHTML(parentEl.innerHTML); + return formatHTML(parentEl.innerHTML, { + baseURL: location.origin, + }); } return ""; diff --git a/utils/html.ts b/utils/html.ts index c290a32..9fc9357 100644 --- a/utils/html.ts +++ b/utils/html.ts @@ -25,8 +25,15 @@ const removeAttributes = (el: HTMLElement) => { }); } +interface FormatHTMLOptions { + formatter?: (doc: Document) => void; + baseURL?: string; +} + // 格式化 HTML 内容 -export const formatHTML = (html: string, extraFormatter?: (doc: Document) => void) => { +export const formatHTML = (html: string, options: FormatHTMLOptions = {}) => { + const { formatter, baseURL } = options; + // 删除空格 html = html.replaceAll(" ", ""); @@ -64,11 +71,30 @@ export const formatHTML = (html: string, extraFormatter?: (doc: Document) => voi // 优化 img 标签,仅保留有效内容 const imgEl = nextDocument.querySelectorAll("img") as NodeListOf; imgEl.forEach((el) => { - const nextImgEl = document.createElement("img"); - nextImgEl.src = el.src; - nextImgEl.alt = el.alt; + const tempImg = document.createElement("img"); - el.parentNode.replaceChild(nextImgEl, el); + // 创建一个临时的 a 元素来解析相对路径 + const tempLink = document.createElement("a"); + tempLink.href = el.src; + + // 如果提供了 baseURL 且图片链接是相对路径,则使用 baseURL 构建完整链接 + if (baseURL && !tempLink.href.startsWith('http')) { + tempImg.src = new URL(el.src, baseURL).href; + } else { + tempImg.src = tempLink.href; + } + + tempImg.alt = el.alt; + + // 复制 width 和 height 属性 + if (el.width) { + tempImg.width = el.width; + } + if (el.height) { + tempImg.height = el.height; + } + + el.parentNode.replaceChild(tempImg, el); }); // 删除 figure 标签 @@ -88,6 +114,12 @@ export const formatHTML = (html: string, extraFormatter?: (doc: Document) => voi el.remove(); }); + // 删除 script 标签 + const scriptEl = nextDocument.querySelectorAll("script"); + scriptEl.forEach((el) => { + el.remove(); + }); + // 提取 pre 下面的内容 const preEl = nextDocument.querySelectorAll("pre"); preEl.forEach((el) => { @@ -105,8 +137,8 @@ export const formatHTML = (html: string, extraFormatter?: (doc: Document) => voi } }); - if (extraFormatter) { - extraFormatter(nextDocument); + if (formatter) { + formatter(nextDocument); } return nextDocument.documentElement.innerHTML;