From bd07130fe151120b1bc6bb4adf822286cda94680 Mon Sep 17 00:00:00 2001 From: Forget Date: Tue, 17 Dec 2024 18:06:00 +0800 Subject: [PATCH 1/5] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=E6=B3=A8?= =?UTF-8?q?=E5=85=A5=E4=BB=A3=E7=A0=81=E6=89=A7=E8=A1=8C=E9=A1=BA=E5=BA=8F?= =?UTF-8?q?=20=E6=B7=BB=E5=8A=A0=E8=87=AA=E5=AE=9A=E4=B9=89=E6=B3=A8?= =?UTF-8?q?=E5=85=A5=E6=A0=87=E8=AF=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.tsx | 36 +--------------- src/lib/inject.ts | 108 ++++++++++++++++++++++++++++++++++++++++++++++ vite.config.ts | 4 +- 3 files changed, 112 insertions(+), 36 deletions(-) create mode 100644 src/lib/inject.ts diff --git a/src/App.tsx b/src/App.tsx index b949bd9..825b8f3 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,6 +1,7 @@ import { useQuery } from "@tanstack/react-query" -import React, { useCallback, useEffect } from "react" +import React, { useEffect } from "react" import { useTranslation } from "react-i18next" +import {InjectContext} from "./lib/inject" import { Route, BrowserRouter as Router, Routes } from "react-router-dom" import Footer from "./components/Footer" @@ -21,39 +22,6 @@ const App: React.FC = () => { }) const { i18n } = useTranslation() - const InjectContext = useCallback((content: string) => { - const tempDiv = document.createElement("div") - tempDiv.innerHTML = content - - const handlers: { [key: string]: (element: HTMLElement) => void } = { - SCRIPT: (element) => { - const script = document.createElement("script") - if ((element as HTMLScriptElement).src) { - script.src = (element as HTMLScriptElement).src - } else { - script.textContent = element.textContent - } - document.body.appendChild(script) - }, - STYLE: (element) => { - const style = document.createElement("style") - style.textContent = element.textContent - document.head.appendChild(style) - }, - DEFAULT: (element) => { - document.body.appendChild(element) - }, - } - - Array.from(tempDiv.childNodes).forEach((node) => { - if (node.nodeType === Node.ELEMENT_NODE) { - const element = node as HTMLElement - ;(handlers[element.tagName] || handlers.DEFAULT)(element) - } else if (node.nodeType === Node.TEXT_NODE) { - document.body.appendChild(document.createTextNode(node.textContent || "")) - } - }) - }, []) useEffect(() => { if (settingData?.data?.custom_code) { diff --git a/src/lib/inject.ts b/src/lib/inject.ts new file mode 100644 index 0000000..76d80b9 --- /dev/null +++ b/src/lib/inject.ts @@ -0,0 +1,108 @@ +export const InjectContext = (content: string) => { + const tempDiv = document.createElement("div"); + tempDiv.innerHTML = content; + + const INJECTION_MARK = "data-injected"; // 自定义属性标识 + + // 清理已有的注入资源 + const cleanInjectedResources = () => { + document.querySelectorAll(`[${INJECTION_MARK}]`).forEach((node) => node.remove()); + }; + + const loadExternalScript = (scriptElement: HTMLScriptElement): Promise => { + return new Promise((resolve, reject) => { + const script = document.createElement("script"); + script.src = scriptElement.src; + script.async = false; // 保持顺序执行 + script.setAttribute(INJECTION_MARK, "true"); // 添加标识 + script.onload = () => resolve() + script.onerror = () => reject(new Error(`Failed to load script: ${scriptElement.src}`)); + document.head.appendChild(script); + }); + }; + + const executeInlineScript = (scriptElement: HTMLScriptElement): void => { + const script = document.createElement("script"); + script.textContent = scriptElement.textContent; + script.setAttribute(INJECTION_MARK, "true"); // 添加标识 + document.body.appendChild(script); + }; + + const loadStyle = (styleElement: HTMLStyleElement): Promise => { + return new Promise((resolve, reject) => { + if ((styleElement as any).href) { // 处理 + const link = document.createElement("link"); + link.rel = "stylesheet"; + link.href = (styleElement as any).href; + link.setAttribute(INJECTION_MARK, "true"); // 添加标识 + link.onload = () => resolve(); + link.onerror = () => reject(new Error(`Failed to load stylesheet: ${link.href}`)); + document.head.appendChild(link); + } else { + const style = document.createElement("style"); + style.textContent = styleElement.textContent; + style.setAttribute(INJECTION_MARK, "true"); // 添加标识 + document.head.appendChild(style); + resolve(); + } + }); + }; + + const handlers: { [key: string]: (element: HTMLElement) => Promise } = { + SCRIPT: (element) => { + const scriptElement = element as HTMLScriptElement; + if (scriptElement.src) { + // 加载外部脚本 + return loadExternalScript(scriptElement); + } else { + // 推迟执行内联脚本,后续手动执行 + return Promise.resolve(); + } + }, + STYLE: (element) => loadStyle(element as HTMLStyleElement), + META: (element) => { + const meta = element.cloneNode(true) as HTMLElement; + meta.setAttribute(INJECTION_MARK, "true"); // 添加标识 + document.head.appendChild(meta); // 将 meta 标签插入到 + return Promise.resolve(); + }, + DEFAULT: (element) => { + element.setAttribute(INJECTION_MARK, "true"); // 添加标识 + document.body.appendChild(element); + return Promise.resolve(); + }, + }; + + // 开始注入前清理已有资源 + cleanInjectedResources(); + + const externalScriptQueue: Promise[] = []; + const inlineScripts: HTMLScriptElement[] = []; + + Array.from(tempDiv.childNodes).forEach((node) => { + if (node.nodeType === Node.ELEMENT_NODE) { + const element = node as HTMLElement; + if (element.tagName === "SCRIPT" && !(element as HTMLScriptElement).src) { + // 收集内联脚本,稍后执行 + inlineScripts.push(element as HTMLScriptElement); + } else { + const handler = handlers[element.tagName] || handlers.DEFAULT; + externalScriptQueue.push(handler(element)); + } + } else if (node.nodeType === Node.TEXT_NODE) { + document.body.appendChild(document.createTextNode(node.textContent || "")); + } + }); + + // 等待外部脚本加载完成后再执行内联脚本 + return Promise.all(externalScriptQueue) + .then(() => { + inlineScripts.forEach((script) => executeInlineScript(script)); + }) + .then(() => { + console.log("All resources have been injected successfully."); + }) + .catch((error) => { + console.error("Error during resource injection:", error); + }); + }; \ No newline at end of file diff --git a/vite.config.ts b/vite.config.ts index e9011f8..a2423c9 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -28,12 +28,12 @@ export default defineConfig({ server: { proxy: { "/api/v1/ws/server": { - target: "ws://localhost:8008", + target: "ws://192.168.5.20:8008", changeOrigin: true, ws: true, }, "/api/v1/": { - target: "http://localhost:8008", + target: "http://192.168.5.20:8008", changeOrigin: true, }, }, From ca2600cbaa84565f45719d7f16241ab3b6571c0d Mon Sep 17 00:00:00 2001 From: dr-forget Date: Tue, 17 Dec 2024 10:09:13 +0000 Subject: [PATCH 2/5] chore: auto-fix linting and formatting issues --- bun.lockb | Bin 184880 -> 184880 bytes src/App.tsx | 5 +- src/lib/inject.ts | 213 +++++++++++++++++++++++----------------------- 3 files changed, 109 insertions(+), 109 deletions(-) diff --git a/bun.lockb b/bun.lockb index f7597274fa2315a542c116291daf37c20ff47051..9041504de22748fc6a89cdc58f84cfbd88651c31 100755 GIT binary patch delta 59 zcmV-B0L1^Wqzka53xKo%D%k-smn+!;nj16#04o6i0384TfISxDj2IOt5CQ>SGA=PL RG?(Dn0W$$Kw-nj|9QYLO5oG`X delta 59 zcmV-B0L1^Wqzka53xKo%D%k-rmn+!;nj13!04o6i0384TfISxDj2IOt5CQ>SGA=PL RGne4m0W$$Jw-nj|9QYK15n%uT diff --git a/src/App.tsx b/src/App.tsx index 825b8f3..93500e5 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,11 +1,11 @@ import { useQuery } from "@tanstack/react-query" -import React, { useEffect } from "react" +import React, { useEffect } from "react" import { useTranslation } from "react-i18next" -import {InjectContext} from "./lib/inject" import { Route, BrowserRouter as Router, Routes } from "react-router-dom" import Footer from "./components/Footer" import Header from "./components/Header" +import { InjectContext } from "./lib/inject" import { fetchSetting } from "./lib/nezha-api" import { cn } from "./lib/utils" import ErrorPage from "./pages/ErrorPage" @@ -22,7 +22,6 @@ const App: React.FC = () => { }) const { i18n } = useTranslation() - useEffect(() => { if (settingData?.data?.custom_code) { InjectContext(settingData?.data?.custom_code) diff --git a/src/lib/inject.ts b/src/lib/inject.ts index 76d80b9..494fca3 100644 --- a/src/lib/inject.ts +++ b/src/lib/inject.ts @@ -1,108 +1,109 @@ export const InjectContext = (content: string) => { - const tempDiv = document.createElement("div"); - tempDiv.innerHTML = content; - - const INJECTION_MARK = "data-injected"; // 自定义属性标识 - - // 清理已有的注入资源 - const cleanInjectedResources = () => { - document.querySelectorAll(`[${INJECTION_MARK}]`).forEach((node) => node.remove()); - }; - - const loadExternalScript = (scriptElement: HTMLScriptElement): Promise => { - return new Promise((resolve, reject) => { - const script = document.createElement("script"); - script.src = scriptElement.src; - script.async = false; // 保持顺序执行 - script.setAttribute(INJECTION_MARK, "true"); // 添加标识 - script.onload = () => resolve() - script.onerror = () => reject(new Error(`Failed to load script: ${scriptElement.src}`)); - document.head.appendChild(script); - }); - }; - - const executeInlineScript = (scriptElement: HTMLScriptElement): void => { - const script = document.createElement("script"); - script.textContent = scriptElement.textContent; - script.setAttribute(INJECTION_MARK, "true"); // 添加标识 - document.body.appendChild(script); - }; - - const loadStyle = (styleElement: HTMLStyleElement): Promise => { - return new Promise((resolve, reject) => { - if ((styleElement as any).href) { // 处理 - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = (styleElement as any).href; - link.setAttribute(INJECTION_MARK, "true"); // 添加标识 - link.onload = () => resolve(); - link.onerror = () => reject(new Error(`Failed to load stylesheet: ${link.href}`)); - document.head.appendChild(link); - } else { - const style = document.createElement("style"); - style.textContent = styleElement.textContent; - style.setAttribute(INJECTION_MARK, "true"); // 添加标识 - document.head.appendChild(style); - resolve(); - } - }); - }; - - const handlers: { [key: string]: (element: HTMLElement) => Promise } = { - SCRIPT: (element) => { - const scriptElement = element as HTMLScriptElement; - if (scriptElement.src) { - // 加载外部脚本 - return loadExternalScript(scriptElement); - } else { - // 推迟执行内联脚本,后续手动执行 - return Promise.resolve(); - } - }, - STYLE: (element) => loadStyle(element as HTMLStyleElement), - META: (element) => { - const meta = element.cloneNode(true) as HTMLElement; - meta.setAttribute(INJECTION_MARK, "true"); // 添加标识 - document.head.appendChild(meta); // 将 meta 标签插入到 - return Promise.resolve(); - }, - DEFAULT: (element) => { - element.setAttribute(INJECTION_MARK, "true"); // 添加标识 - document.body.appendChild(element); - return Promise.resolve(); - }, - }; - - // 开始注入前清理已有资源 - cleanInjectedResources(); - - const externalScriptQueue: Promise[] = []; - const inlineScripts: HTMLScriptElement[] = []; - - Array.from(tempDiv.childNodes).forEach((node) => { - if (node.nodeType === Node.ELEMENT_NODE) { - const element = node as HTMLElement; - if (element.tagName === "SCRIPT" && !(element as HTMLScriptElement).src) { - // 收集内联脚本,稍后执行 - inlineScripts.push(element as HTMLScriptElement); - } else { - const handler = handlers[element.tagName] || handlers.DEFAULT; - externalScriptQueue.push(handler(element)); - } - } else if (node.nodeType === Node.TEXT_NODE) { - document.body.appendChild(document.createTextNode(node.textContent || "")); + const tempDiv = document.createElement("div") + tempDiv.innerHTML = content + + const INJECTION_MARK = "data-injected" // 自定义属性标识 + + // 清理已有的注入资源 + const cleanInjectedResources = () => { + document.querySelectorAll(`[${INJECTION_MARK}]`).forEach((node) => node.remove()) + } + + const loadExternalScript = (scriptElement: HTMLScriptElement): Promise => { + return new Promise((resolve, reject) => { + const script = document.createElement("script") + script.src = scriptElement.src + script.async = false // 保持顺序执行 + script.setAttribute(INJECTION_MARK, "true") // 添加标识 + script.onload = () => resolve() + script.onerror = () => reject(new Error(`Failed to load script: ${scriptElement.src}`)) + document.head.appendChild(script) + }) + } + + const executeInlineScript = (scriptElement: HTMLScriptElement): void => { + const script = document.createElement("script") + script.textContent = scriptElement.textContent + script.setAttribute(INJECTION_MARK, "true") // 添加标识 + document.body.appendChild(script) + } + + const loadStyle = (styleElement: HTMLStyleElement): Promise => { + return new Promise((resolve, reject) => { + if ((styleElement as any).href) { + // 处理 + const link = document.createElement("link") + link.rel = "stylesheet" + link.href = (styleElement as any).href + link.setAttribute(INJECTION_MARK, "true") // 添加标识 + link.onload = () => resolve() + link.onerror = () => reject(new Error(`Failed to load stylesheet: ${link.href}`)) + document.head.appendChild(link) + } else { + const style = document.createElement("style") + style.textContent = styleElement.textContent + style.setAttribute(INJECTION_MARK, "true") // 添加标识 + document.head.appendChild(style) + resolve() } - }); - - // 等待外部脚本加载完成后再执行内联脚本 - return Promise.all(externalScriptQueue) - .then(() => { - inlineScripts.forEach((script) => executeInlineScript(script)); - }) - .then(() => { - console.log("All resources have been injected successfully."); - }) - .catch((error) => { - console.error("Error during resource injection:", error); - }); - }; \ No newline at end of file + }) + } + + const handlers: { [key: string]: (element: HTMLElement) => Promise } = { + SCRIPT: (element) => { + const scriptElement = element as HTMLScriptElement + if (scriptElement.src) { + // 加载外部脚本 + return loadExternalScript(scriptElement) + } else { + // 推迟执行内联脚本,后续手动执行 + return Promise.resolve() + } + }, + STYLE: (element) => loadStyle(element as HTMLStyleElement), + META: (element) => { + const meta = element.cloneNode(true) as HTMLElement + meta.setAttribute(INJECTION_MARK, "true") // 添加标识 + document.head.appendChild(meta) // 将 meta 标签插入到 + return Promise.resolve() + }, + DEFAULT: (element) => { + element.setAttribute(INJECTION_MARK, "true") // 添加标识 + document.body.appendChild(element) + return Promise.resolve() + }, + } + + // 开始注入前清理已有资源 + cleanInjectedResources() + + const externalScriptQueue: Promise[] = [] + const inlineScripts: HTMLScriptElement[] = [] + + Array.from(tempDiv.childNodes).forEach((node) => { + if (node.nodeType === Node.ELEMENT_NODE) { + const element = node as HTMLElement + if (element.tagName === "SCRIPT" && !(element as HTMLScriptElement).src) { + // 收集内联脚本,稍后执行 + inlineScripts.push(element as HTMLScriptElement) + } else { + const handler = handlers[element.tagName] || handlers.DEFAULT + externalScriptQueue.push(handler(element)) + } + } else if (node.nodeType === Node.TEXT_NODE) { + document.body.appendChild(document.createTextNode(node.textContent || "")) + } + }) + + // 等待外部脚本加载完成后再执行内联脚本 + return Promise.all(externalScriptQueue) + .then(() => { + inlineScripts.forEach((script) => executeInlineScript(script)) + }) + .then(() => { + console.log("All resources have been injected successfully.") + }) + .catch((error) => { + console.error("Error during resource injection:", error) + }) +} From 6e4597d724aad0813966ac012a59632456bde9a5 Mon Sep 17 00:00:00 2001 From: Forget Date: Tue, 17 Dec 2024 18:11:44 +0800 Subject: [PATCH 3/5] =?UTF-8?q?feat:=20=E8=BF=98=E5=8E=9Fvite.config.ts?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vite.config.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vite.config.ts b/vite.config.ts index a2423c9..e9011f8 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -28,12 +28,12 @@ export default defineConfig({ server: { proxy: { "/api/v1/ws/server": { - target: "ws://192.168.5.20:8008", + target: "ws://localhost:8008", changeOrigin: true, ws: true, }, "/api/v1/": { - target: "http://192.168.5.20:8008", + target: "http://localhost:8008", changeOrigin: true, }, }, From 2a6b4a1cf0c079368bff802054f9a353a1c9b294 Mon Sep 17 00:00:00 2001 From: Forget Date: Tue, 17 Dec 2024 18:13:56 +0800 Subject: [PATCH 4/5] =?UTF-8?q?feat:=20=E8=BF=98=E5=8E=9Fvite.config.ts?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/App.tsx b/src/App.tsx index 93500e5..f37cfd1 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -2,7 +2,6 @@ import { useQuery } from "@tanstack/react-query" import React, { useEffect } from "react" import { useTranslation } from "react-i18next" import { Route, BrowserRouter as Router, Routes } from "react-router-dom" - import Footer from "./components/Footer" import Header from "./components/Header" import { InjectContext } from "./lib/inject" From f77a3255beaa26bda6e894ee240e90f39c75e683 Mon Sep 17 00:00:00 2001 From: dr-forget Date: Tue, 17 Dec 2024 10:14:24 +0000 Subject: [PATCH 5/5] chore: auto-fix linting and formatting issues --- src/App.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/App.tsx b/src/App.tsx index f37cfd1..93500e5 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -2,6 +2,7 @@ import { useQuery } from "@tanstack/react-query" import React, { useEffect } from "react" import { useTranslation } from "react-i18next" import { Route, BrowserRouter as Router, Routes } from "react-router-dom" + import Footer from "./components/Footer" import Header from "./components/Header" import { InjectContext } from "./lib/inject"