Compare commits

..
8 Commits
Author SHA1 Message Date
Paul 6f245b14ea Update dependencies and add pnpm workspace configuration 2026-10-12 18:18:04 +08:00
Paul 834048c8ba Fix get BiliBili toy issues
修复获取失败问题
2026-05-21 17:57:25 +08:00
Paul cdcc2c3172 Add fuck tencent logic 2026-05-15 10:33:27 +08:00
Paul df179792e7 Update BiliBili toy capture 2025-12-06 15:41:05 +08:00
Paul daad7aeecd Fix image relative url error
修复相对链接图片无法显示问题
2025-06-02 11:54:12 +08:00
Paul c252ceafb2 Add toy form values
增加手办表单信息
2025-02-01 14:32:00 +08:00
Paul 3733461807 Update say form values
更新语录表单
2024-10-25 00:44:31 +08:00
Paul ea1fe98c20 Add clipboardWrite permissions
似乎增加权限可以避开申请提示
2024-09-05 02:23:38 +08:00
14 changed files with 4686 additions and 3391 deletions
+2 -2
View File
@@ -5,9 +5,9 @@ export default {
printWidth: 80, printWidth: 80,
tabWidth: 2, tabWidth: 2,
useTabs: false, useTabs: false,
semi: false, semi: true,
singleQuote: false, singleQuote: false,
trailingComma: "none", trailingComma: "all",
bracketSpacing: true, bracketSpacing: true,
bracketSameLine: true, bracketSameLine: true,
plugins: ["@ianvs/prettier-plugin-sort-imports"], plugins: ["@ianvs/prettier-plugin-sort-imports"],
+4
View File
@@ -3,6 +3,10 @@ import type { PlasmoMessaging } from "@plasmohq/messaging";
const handler: PlasmoMessaging.MessageHandler = async (req, res) => { const handler: PlasmoMessaging.MessageHandler = async (req, res) => {
const { token, siteUrl } = await chrome.storage.local.get(["token", "siteUrl"]); const { token, siteUrl } = await chrome.storage.local.get(["token", "siteUrl"]);
if (!token || !siteUrl) {
throw new Error("未指定 Token 或站点地址");
}
// 更新追番进度 // 更新追番进度
if (req.body.action === "updateBangumiProgress") { if (req.body.action === "updateBangumiProgress") {
const { values } = req.body; const { values } = req.body;
+4
View File
@@ -3,6 +3,10 @@ import type { PlasmoMessaging } from "@plasmohq/messaging";
const handler: PlasmoMessaging.MessageHandler = async (req, res) => { const handler: PlasmoMessaging.MessageHandler = async (req, res) => {
const { token, siteUrl } = await chrome.storage.local.get(["token", "siteUrl"]); const { token, siteUrl } = await chrome.storage.local.get(["token", "siteUrl"]);
if (!token || !siteUrl) {
throw new Error("未指定 Token 或站点地址");
}
if (req.body.action === "addRead") { if (req.body.action === "addRead") {
const { values } = req.body; const { values } = req.body;
const formData = new FormData(); const formData = new FormData();
+4
View File
@@ -3,6 +3,10 @@ import type { PlasmoMessaging } from "@plasmohq/messaging";
const handler: PlasmoMessaging.MessageHandler = async (req, res) => { const handler: PlasmoMessaging.MessageHandler = async (req, res) => {
const { token, siteUrl } = await chrome.storage.local.get(["token", "siteUrl"]); const { token, siteUrl } = await chrome.storage.local.get(["token", "siteUrl"]);
if (!token || !siteUrl) {
throw new Error("未指定 Token 或站点地址");
}
if (req.body.action === "addSay") { if (req.body.action === "addSay") {
const { values } = req.body; const { values } = req.body;
const formData = new FormData(); const formData = new FormData();
+4
View File
@@ -3,6 +3,10 @@ import type { PlasmoMessaging } from "@plasmohq/messaging";
const handler: PlasmoMessaging.MessageHandler = async (req, res) => { const handler: PlasmoMessaging.MessageHandler = async (req, res) => {
const { token, siteUrl } = await chrome.storage.local.get(["token", "siteUrl"]); const { token, siteUrl } = await chrome.storage.local.get(["token", "siteUrl"]);
if (!token || !siteUrl) {
throw new Error("未指定 Token 或站点地址");
}
// 添加手办 // 添加手办
if (req.body.action === "addToy") { if (req.body.action === "addToy") {
const { values } = req.body; const { values } = req.body;
+7 -3
View File
@@ -9,7 +9,7 @@ interface FormValue {
content: string; content: string;
author: string; author: string;
origin: string; origin: string;
links: string; link: string;
is_comment: boolean; is_comment: boolean;
} }
@@ -55,8 +55,12 @@ function Say() {
<input {...bindInput("author")} placeholder="作者" /> <input {...bindInput("author")} placeholder="作者" />
</div> </div>
<div> <div>
<label htmlFor="links">链接</label> <label htmlFor="origin">来源</label>
<input {...bindInput("links")} placeholder="链接" /> <input {...bindInput("origin")} placeholder="来源" />
</div>
<div>
<label htmlFor="link">链接</label>
<input {...bindInput("link")} placeholder="链接" />
</div> </div>
<div> <div>
<label htmlFor="is_comment">摘抄</label> <label htmlFor="is_comment">摘抄</label>
+5
View File
@@ -17,6 +17,7 @@ interface FormValue {
type: number; type: number;
desc: string; desc: string;
productId: string; productId: string;
link: string;
} }
const getInfo = async () => { const getInfo = async () => {
@@ -127,6 +128,10 @@ function Toy() {
<label htmlFor="productId">B 站产品 ID</label> <label htmlFor="productId">B 站产品 ID</label>
<input {...bindInput("productId")} placeholder="B 站产品 ID" /> <input {...bindInput("productId")} placeholder="B 站产品 ID" />
</div> </div>
<div>
<label htmlFor="link">手办维基链接</label>
<input {...bindInput("link")} placeholder="https://www.hpoi.net/hobby/xxxxx" />
</div>
<div> <div>
<label htmlFor="desc">描述</label> <label htmlFor="desc">描述</label>
<textarea {...bindInput("desc")} rows={5} placeholder="描述"></textarea> <textarea {...bindInput("desc")} rows={5} placeholder="描述"></textarea>
+41
View File
@@ -6,6 +6,47 @@ export const config: PlasmoCSConfig = {
chrome.runtime.onMessage.addListener((req, sender, send) => { chrome.runtime.onMessage.addListener((req, sender, send) => {
if (req.type === "toolbox:getBiliToy") { if (req.type === "toolbox:getBiliToy") {
// 疑似新版?
if (window.location.pathname.includes("neul-next")) {
const item = document.querySelectorAll<HTMLDivElement>(".franky-swiper-item.image-list");
if (!item.length) {
send(false);
return;
}
const project = document.querySelector<HTMLDivElement>(".tagC-ip .tagC-ip-con")?.innerText || "";
const made = document.querySelector<HTMLDivElement>(".tagC-ip .tagC-ip-con-brand")?.innerText || "";
const sale = document.querySelector<HTMLDivElement>(".item-complex:nth-child(4) .item-complex-value")?.innerText || "";
const projectExp = new RegExp(`\s?${project}\s?`);
const madeExp = new RegExp(`\s?${made}\s?`);
const name = document.querySelector<HTMLDivElement>(".clamp-real-text")
.innerText.replace(/\[\S+\]/, "")
.replace(projectExp, "")
.replace(madeExp, "")
.replaceAll(/\s?Q版手办\s?|\s?粘土人\s?/g, "")
.trim();
const images = [];
item.forEach((item) => {
images.push(
item.querySelector("img").src
);
});
send({
name,
project: project.replace(":", ":"),
made,
sale: sale.replace("-", "/"),
images,
productId: new URLSearchParams(location.search).get("itemsId"),
});
}
// 旧版,不确定是否还在使用
const item = document.querySelectorAll<HTMLDivElement>(".silde-item"); const item = document.querySelectorAll<HTMLDivElement>(".silde-item");
if (item.length) { if (item.length) {
+27
View File
@@ -0,0 +1,27 @@
import type { PlasmoCSConfig } from "plasmo";
export const config: PlasmoCSConfig = {
matches: ["https://c.pc.qq.com/*"],
};
const url = new URL(location.href);
const redirectUrl = url.searchParams.get("url");
const titleEl = document.querySelector(".container .title");
const descEl = document.querySelector(".container .p");
if (titleEl) {
if (titleEl.innerHTML === "已停止访问该网页") {
titleEl.innerHTML = "傻逼腾讯,我就要访问这个网页!";
}
}
if (descEl) {
descEl.innerHTML = "小窝工具箱扩展,将自动为你跳转到对应的链接";
}
setTimeout(() => {
if (redirectUrl) {
window.location.href = redirectUrl;
}
}, 1000);
+30 -17
View File
@@ -121,26 +121,31 @@ const getHTML = () => {
if (location.host === "mp.weixin.qq.com") { if (location.host === "mp.weixin.qq.com") {
console.log("微信"); 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") { if (location.host === "cloud.tencent.com") {
console.log("腾讯云"); console.log("腾讯云");
return formatHTML(document.querySelector(".rno-markdown").innerHTML, (doc) => { return formatHTML(document.querySelector(".rno-markdown").innerHTML, {
// 替换掉腾讯云自己的链接 formatter: (doc) => {
const qcloudLinkEl = doc.querySelectorAll("a"); // 替换掉腾讯云自己的链接
qcloudLinkEl.forEach((el) => { const qcloudLinkEl = doc.querySelectorAll("a");
if (el.href.includes("qcloud")) { qcloudLinkEl.forEach((el) => {
el.parentNode.replaceChild(document.createTextNode(el.innerText), el); if (el.href.includes("qcloud")) {
} el.parentNode.replaceChild(document.createTextNode(el.innerText), el);
}); }
});
const mdTextEl = doc.querySelectorAll(".rno-markdown__textlink-new") as NodeListOf<HTMLElement>; const mdTextEl = doc.querySelectorAll(".rno-markdown__textlink-new") as NodeListOf<HTMLElement>;
mdTextEl.forEach((el) => { mdTextEl.forEach((el) => {
el.parentNode.replaceChild(document.createTextNode(el.innerText), el); el.parentNode.replaceChild(document.createTextNode(el.innerText), el);
}); });
},
baseURL: location.origin,
}); });
} }
@@ -150,7 +155,9 @@ const getHTML = () => {
if (itemPropArticle) { if (itemPropArticle) {
console.log("掘金"); console.log("掘金");
return formatHTML(itemPropArticle.innerHTML); return formatHTML(itemPropArticle.innerHTML, {
baseURL: location.origin,
});
} }
// CSDN // CSDN
@@ -159,7 +166,9 @@ const getHTML = () => {
if (contentViews) { if (contentViews) {
console.log("CSDN"); console.log("CSDN");
return formatHTML(contentViews.innerHTML); return formatHTML(contentViews.innerHTML, {
baseURL: location.origin,
});
} }
// 通用模式 // 通用模式
@@ -168,7 +177,9 @@ const getHTML = () => {
if (articleEl) { if (articleEl) {
console.log("文章标签"); 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 ""; return "";
+9 -9
View File
@@ -11,23 +11,23 @@
}, },
"dependencies": { "dependencies": {
"@plasmohq/messaging": "^0.6.2", "@plasmohq/messaging": "^0.6.2",
"plasmo": "0.85.2", "plasmo": "0.90.5",
"react": "18.2.0", "react": "18.2.0",
"react-dom": "18.2.0" "react-dom": "18.2.0"
}, },
"devDependencies": { "devDependencies": {
"@ianvs/prettier-plugin-sort-imports": "4.1.0", "@ianvs/prettier-plugin-sort-imports": "4.1.1",
"@types/chrome": "0.0.266", "@types/chrome": "0.0.258",
"@types/node": "20.5.0", "@types/node": "20.11.5",
"@types/react": "18.2.20", "@types/react": "18.2.48",
"@types/react-dom": "18.2.7", "@types/react-dom": "18.2.18",
"less": "^4.2.0", "less": "^4.2.0",
"prettier": "3.0.2", "prettier": "3.2.4",
"typescript": "5.1.6" "typescript": "5.3.3"
}, },
"manifest": { "manifest": {
"permissions": [ "permissions": [
"tabs", "storage", "scripting", "contextMenus" "tabs", "storage", "scripting", "contextMenus", "clipboardWrite"
], ],
"host_permissions": [ "host_permissions": [
"https://*/*" "https://*/*"
+4503 -3353
View File
File diff suppressed because it is too large Load Diff
+7
View File
@@ -0,0 +1,7 @@
allowBuilds:
'@parcel/watcher': true
'@swc/core': true
esbuild: true
lmdb: true
msgpackr-extract: true
sharp: true
+39 -7
View File
@@ -25,8 +25,15 @@ const removeAttributes = (el: HTMLElement) => {
}); });
} }
interface FormatHTMLOptions {
formatter?: (doc: Document) => void;
baseURL?: string;
}
// 格式化 HTML 内容 // 格式化 HTML 内容
export const formatHTML = (html: string, extraFormatter?: (doc: Document) => void) => { export const formatHTML = (html: string, options: FormatHTMLOptions = {}) => {
const { formatter, baseURL } = options;
// 删除空格 // 删除空格
html = html.replaceAll("&nbsp;", ""); html = html.replaceAll("&nbsp;", "");
@@ -64,11 +71,30 @@ export const formatHTML = (html: string, extraFormatter?: (doc: Document) => voi
// 优化 img 标签,仅保留有效内容 // 优化 img 标签,仅保留有效内容
const imgEl = nextDocument.querySelectorAll("img") as NodeListOf<HTMLImageElement>; const imgEl = nextDocument.querySelectorAll("img") as NodeListOf<HTMLImageElement>;
imgEl.forEach((el) => { imgEl.forEach((el) => {
const nextImgEl = document.createElement("img"); const tempImg = document.createElement("img");
nextImgEl.src = el.src;
nextImgEl.alt = el.alt;
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 标签 // 删除 figure 标签
@@ -88,6 +114,12 @@ export const formatHTML = (html: string, extraFormatter?: (doc: Document) => voi
el.remove(); el.remove();
}); });
// 删除 script 标签
const scriptEl = nextDocument.querySelectorAll("script");
scriptEl.forEach((el) => {
el.remove();
});
// 提取 pre 下面的内容 // 提取 pre 下面的内容
const preEl = nextDocument.querySelectorAll("pre"); const preEl = nextDocument.querySelectorAll("pre");
preEl.forEach((el) => { preEl.forEach((el) => {
@@ -105,8 +137,8 @@ export const formatHTML = (html: string, extraFormatter?: (doc: Document) => voi
} }
}); });
if (extraFormatter) { if (formatter) {
extraFormatter(nextDocument); formatter(nextDocument);
} }
return nextDocument.documentElement.innerHTML; return nextDocument.documentElement.innerHTML;