feat: support custom terms

This commit is contained in:
Gabe Yuan
2024-01-19 16:02:53 +08:00
parent 59f9dd697f
commit d5fc69e210
13 changed files with 85 additions and 32 deletions

View File

@@ -10,4 +10,4 @@ import { DEFAULT_BLACKLIST } from "../config";
export const isInBlacklist = (
href,
{ blacklist = DEFAULT_BLACKLIST.join(",\n") }
) => blacklist.split(",").some((url) => isMatch(href, url.trim()));
) => blacklist.split(/\n|,/).some((url) => isMatch(href, url.trim()));

View File

@@ -26,7 +26,7 @@ const keyMap = new Map();
// 轮询key
const keyPick = (translator, key = "") => {
const keys = key
.split(",")
.split(/\n|,/)
.map((item) => item.trim())
.filter(Boolean);

View File

@@ -67,6 +67,7 @@ export const matchRule = async (
rule.selector = rule.selector?.trim() || globalRule.selector;
rule.keepSelector = rule.keepSelector?.trim() || globalRule.keepSelector;
rule.terms = rule.terms?.trim() || globalRule.terms;
if (rule.textStyle === GLOBAL_KEY) {
rule.textStyle = globalRule.textStyle;
rule.bgColor = globalRule.bgColor;
@@ -114,6 +115,7 @@ export const checkRules = (rules) => {
pattern,
selector,
keepSelector,
terms,
translator,
fromLang,
toLang,
@@ -125,6 +127,7 @@ export const checkRules = (rules) => {
pattern: pattern.trim(),
selector: type(selector) === "string" ? selector : "",
keepSelector: type(keepSelector) === "string" ? keepSelector : "",
terms: type(terms) === "string" ? terms : "",
bgColor: type(bgColor) === "string" ? bgColor : "",
textDiyStyle: type(textDiyStyle) === "string" ? textDiyStyle : "",
translator: matchValue([GLOBAL_KEY, ...OPT_TRANS_ALL], translator),

View File

@@ -42,6 +42,8 @@ export class Translator {
];
_eventName = genEventName();
_mouseoverNode = null;
_keepSelector = [null, null];
_terms = new Map();
// 显示
_interseObserver = new IntersectionObserver(
@@ -102,6 +104,17 @@ export class Translator {
this._rule = rule;
this._fixerSetting = fixerSetting;
this._keepSelector = (rule.keepSelector || "")
.split(SHADOW_KEY)
.map((item) => item.trim());
const terms = (rule.terms || "")
.split(/\n|;/)
.map((item) => item.split(",").map((item) => item.trim()))
.filter(([term]) => Boolean(term));
if (terms.length > 0) {
this._terms = new Map(terms);
}
if (rule.transOpen === "true") {
this._register();
}
@@ -386,47 +399,48 @@ export class Translator {
let q = el.innerText.trim();
this._tranNodes.set(el, q);
// 太长或太短
if (this._invalidLength(q)) {
return;
}
// console.log("---> ", q);
const keepSelector = this._rule.keepSelector || "";
const keeps = [];
const [matchSelector, subSelector] = keepSelector.split(SHADOW_KEY);
if (matchSelector.trim() || subSelector?.trim()) {
// 保留元素
const [matchSelector, subSelector] = this._keepSelector;
if (matchSelector || subSelector) {
let text = "";
el.childNodes.forEach((child) => {
if (
child.nodeType === 1 &&
((matchSelector.trim() && child.matches(matchSelector)) ||
(subSelector?.trim() && child.querySelector(subSelector)))
((matchSelector && child.matches(matchSelector)) ||
(subSelector && child.querySelector(subSelector)))
) {
if (child.nodeName === "IMG") {
child.style.cssText += `width: ${child.width}px;`;
child.style.cssText += `height: ${child.height}px;`;
}
text += `#${keeps.length}#`;
text += `[${keeps.length}]`;
keeps.push(child.outerHTML);
} else {
text += child.textContent;
}
});
// 太长或太短
if (this._invalidLength(text.replace(/#(\d+)#/g, "").trim())) {
return;
}
if (keeps.length > 0) {
q = text;
}
}
// console.log("---> ", q);
// 太长或太短
if (this._invalidLength(q.replace(/\[(\d+)\]/g, "").trim())) {
return;
}
// 专业术语
if (this._terms.size > 0) {
const re = new RegExp([...this._terms.keys()].join("|"), "g");
q = q.replace(re, (term) => {
const text = `[${keeps.length}]`;
keeps.push(this._terms.get(term) || term);
return text;
});
}
traEl = document.createElement(APP_LCNAME);
traEl.style.visibility = "visible";
@@ -438,6 +452,8 @@ export class Translator {
"-webkit-line-clamp: unset; max-height: none; height: auto;";
}
// console.log({ q, keeps });
const root = createRoot(traEl);
root.render(<Content q={q} keeps={keeps} translator={this} />);
};