Files
kiss-translator/src/libs/webfix.js

223 lines
4.5 KiB
JavaScript
Raw Normal View History

2023-09-08 16:56:00 +08:00
import { isMatch } from "./utils";
2023-09-08 21:41:32 +08:00
import { getWebfix, setWebfix } from "./storage";
import { apiFetch } from "../apis";
/**
* 修复程序类型
*/
2023-09-09 23:32:17 +08:00
const FIXER_BR = "br";
2023-10-16 15:48:53 +08:00
const FIXER_BN = "bn";
2023-09-09 23:32:17 +08:00
const FIXER_FONTSIZE = "fontSize";
2023-09-08 16:56:00 +08:00
/**
* 需要修复的站点列表
* - pattern 匹配网址
* - selector 需要修复的选择器
2023-09-11 16:12:37 +08:00
* - rootSelector 需要监听的选择器可留空
2023-09-08 16:56:00 +08:00
* - fixer 修复函数可针对不同网址选用不同修复函数
*/
2023-09-08 21:41:32 +08:00
const DEFAULT_SITES = [
2023-09-08 16:56:00 +08:00
{
pattern: "www.phoronix.com",
selector: ".content",
2023-09-11 16:12:37 +08:00
rootSelector: "",
2023-09-09 23:32:17 +08:00
fixer: FIXER_BR,
2023-09-08 16:56:00 +08:00
},
{
2023-09-09 23:32:17 +08:00
pattern: "t.me/s/",
2023-09-08 16:56:00 +08:00
selector: ".tgme_widget_message_text",
2023-09-11 16:12:37 +08:00
rootSelector: ".tgme_channel_history",
2023-09-09 23:32:17 +08:00
fixer: FIXER_BR,
},
{
pattern: "baidu.com",
selector: "html",
2023-09-11 16:12:37 +08:00
rootSelector: "",
2023-09-09 23:32:17 +08:00
fixer: FIXER_FONTSIZE,
2023-09-08 16:56:00 +08:00
},
2023-10-16 15:48:53 +08:00
{
pattern: "chat.openai.com",
selector: "div[data-testid^=conversation-turn] .items-start > div",
rootSelector: "",
fixer: FIXER_BN,
},
2023-09-08 16:56:00 +08:00
];
/**
* 修复过的标记
*/
const fixedSign = "kissfixed";
/**
* 采用 `br` 换行网站的修复函数
* 目标是将 `br` 替换成 `p`
* @param {*} node
* @returns
*/
function brFixer(node) {
if (node.hasAttribute(fixedSign)) {
return;
}
node.setAttribute(fixedSign, "true");
var gapTags = ["BR", "WBR"];
var newlineTags = [
"DIV",
"UL",
"OL",
"LI",
"H1",
"H2",
"H3",
"H4",
"H5",
"H6",
"P",
"HR",
"PRE",
"TABLE",
];
var html = "";
node.childNodes.forEach(function (child, index) {
if (index === 0) {
html += "<p>";
}
if (gapTags.indexOf(child.nodeName) !== -1) {
html += "</p><p>";
} else if (newlineTags.indexOf(child.nodeName) !== -1) {
html += "</p>" + child.outerHTML + "<p>";
} else if (child.outerHTML) {
html += child.outerHTML;
} else if (child.nodeValue) {
html += child.nodeValue;
}
if (index === node.childNodes.length - 1) {
html += "</p>";
}
});
node.innerHTML = html;
}
2023-10-16 15:48:53 +08:00
/**
* 目标是将 `\n` 替换成 `p`
* @param {*} node
* @returns
*/
function bnFixer(node) {
if (node.hasAttribute(fixedSign)) {
return;
}
node.setAttribute(fixedSign, "true");
const childs = node.childNodes;
if (childs.length === 1 && childs[0].nodeName === "#text") {
node.innerHTML = node.innerHTML
.split("\n")
.map((item) => `<p>${item || "&nbsp;"}</p>`)
.join("");
}
}
2023-09-09 23:32:17 +08:00
/**
* 修复字体大小问题 baidu.com
* @param {*} node
*/
function fontSizeFixer(node) {
node.style.cssText += "font-size:1em;";
}
2023-09-08 21:41:32 +08:00
/**
* 修复程序映射
*/
const fixerMap = {
2023-09-09 23:32:17 +08:00
[FIXER_BR]: brFixer,
2023-10-16 15:48:53 +08:00
[FIXER_BN]: bnFixer,
2023-09-09 23:32:17 +08:00
[FIXER_FONTSIZE]: fontSizeFixer,
2023-09-08 21:41:32 +08:00
};
2023-09-08 16:56:00 +08:00
/**
* 查找监听节点并执行修复函数
* @param {*} selector
* @param {*} fixer
2023-09-11 16:12:37 +08:00
* @param {*} rootSelector
2023-09-08 16:56:00 +08:00
*/
2023-09-11 16:12:37 +08:00
function run(selector, fixer, rootSelector) {
2023-09-08 16:56:00 +08:00
var mutaObserver = new MutationObserver(function (mutations) {
mutations.forEach(function (mutation) {
mutation.addedNodes.forEach(function (addNode) {
2023-11-07 17:57:17 +08:00
addNode?.querySelectorAll(selector)?.forEach(fixer);
2023-09-08 16:56:00 +08:00
});
});
});
var rootNodes = [document];
2023-09-11 16:12:37 +08:00
if (rootSelector) {
rootNodes = document.querySelectorAll(rootSelector);
2023-09-08 16:56:00 +08:00
}
rootNodes.forEach(function (rootNode) {
rootNode.querySelectorAll(selector).forEach(fixer);
mutaObserver.observe(rootNode, {
childList: true,
2023-10-16 15:48:53 +08:00
subtree: true,
2023-09-08 16:56:00 +08:00
});
});
}
2023-09-08 21:41:32 +08:00
/**
* 同步远程数据
* @param {*} url
* @returns
*/
export const syncWebfix = async (url) => {
const sites = await apiFetch(url);
await setWebfix(url, sites);
return sites;
};
/**
* 从缓存或远程加载修复站点
* @param {*} url
* @returns
*/
export const loadOrFetchWebfix = async (url) => {
try {
let sites = await getWebfix(url);
if (sites?.length) {
return sites;
}
return syncWebfix(url);
} catch (err) {
console.log("[load webfix]", err.message);
return DEFAULT_SITES;
}
};
2023-09-08 16:56:00 +08:00
/**
* 匹配站点
*/
2023-10-23 13:35:57 +08:00
export async function runWebfix({ injectWebfix }) {
2023-09-08 16:56:00 +08:00
try {
if (!injectWebfix) {
return;
}
2023-10-23 13:35:57 +08:00
const href = document.location.href;
2023-09-08 21:41:32 +08:00
const sites = await loadOrFetchWebfix(process.env.REACT_APP_WEBFIXURL);
2023-09-08 16:56:00 +08:00
for (var i = 0; i < sites.length; i++) {
var site = sites[i];
if (isMatch(href, site.pattern)) {
2023-09-08 21:41:32 +08:00
if (fixerMap[site.fixer]) {
2023-09-11 16:12:37 +08:00
run(site.selector, fixerMap[site.fixer], site.rootSelector);
2023-09-08 21:41:32 +08:00
}
2023-09-08 16:56:00 +08:00
break;
}
}
} catch (err) {
console.error(`[kiss-webfix]: ${err.message}`);
}
}