import { createRoot } from "react-dom/client"; import { APP_LCNAME, TRANS_MIN_LENGTH, TRANS_MAX_LENGTH, EVENT_KISS, MSG_TRANS_CURRULE, } from "../config"; import { queryEls } from "."; import Content from "../views/Content"; import { fetchUpdate, fetchClear } from "./fetch"; /** * 翻译类 */ export class Translator { _rule = {}; _interseObserver = new IntersectionObserver( (intersections) => { intersections.forEach((intersection) => { if (intersection.isIntersecting) { this._render(intersection.target); this._interseObserver.unobserve(intersection.target); } }); }, { threshold: 0.1, } ); _mutaObserver = new MutationObserver((mutations) => { mutations.forEach((mutation) => { mutation.addedNodes.forEach((node) => { try { queryEls(this.rule.selector, node).forEach((el) => { this._interseObserver.observe(el); }); } catch (err) { // } }); }); }); constructor(rule, { fetchInterval, fetchLimit }) { fetchUpdate(fetchInterval, fetchLimit); this.rule = rule; if (rule.transOpen === "true") { this._register(); } } get rule() { // console.log("get rule", this._rule); return this._rule; } set rule(rule) { // console.log("set rule", rule); this._rule = rule; // 广播消息 window.dispatchEvent( new CustomEvent(EVENT_KISS, { detail: { action: MSG_TRANS_CURRULE, args: rule, }, }) ); } updateRule = (obj) => { this.rule = { ...this.rule, ...obj }; }; toggle = () => { if (this.rule.transOpen === "true") { this.rule = { ...this.rule, transOpen: "false" }; this._unRegister(); } else { this.rule = { ...this.rule, transOpen: "true" }; this._register(); } }; _register = () => { // 监听节点变化 this._mutaObserver.observe(document, { childList: true, subtree: true, }); // 监听节点显示 queryEls(this.rule.selector).forEach((el) => { this._interseObserver.observe(el); }); }; _unRegister = () => { // 解除节点变化监听 this._mutaObserver.disconnect(); // 解除节点显示监听 queryEls(this.rule.selector).forEach((el) => this._interseObserver.unobserve(el) ); // 移除已插入元素 queryEls(APP_LCNAME).forEach((el) => el.remove()); // 清空任务池 fetchClear(); }; _render = (el) => { // 含子元素 if (el.querySelector(this.rule.selector)) { return; } // 已翻译 if (el.querySelector(APP_LCNAME)) { return; } // 太长或太短 const q = el.innerText.trim(); if (!q || q.length < TRANS_MIN_LENGTH || q.length > TRANS_MAX_LENGTH) { return; } // console.log("---> ", q); const span = document.createElement(APP_LCNAME); span.style.visibility = "visible"; el.appendChild(span); el.style.cssText += "-webkit-line-clamp: unset; max-height: none; height: auto;"; el.parentElement.style.cssText += "-webkit-line-clamp: unset; max-height: none; height: auto;"; const root = createRoot(span); root.render(); }; }