fix: hooks & injectjs
This commit is contained in:
@@ -14,9 +14,9 @@ import {
|
||||
MSG_BUILTINAI_TRANSLATE,
|
||||
OPT_TRANS_BUILTINAI,
|
||||
URL_CACHE_SUBTITLE,
|
||||
OPT_LANGS_TO_CODE,
|
||||
} from "../config";
|
||||
import { sha256, withTimeout } from "../libs/utils";
|
||||
import { kissLog } from "../libs/log";
|
||||
import {
|
||||
handleTranslate,
|
||||
handleSubtitle,
|
||||
@@ -424,7 +424,7 @@ export const apiTranslate = async ({
|
||||
usePool = true,
|
||||
}) => {
|
||||
if (!text) {
|
||||
return ["", false];
|
||||
throw new Error("The text cannot be empty.");
|
||||
}
|
||||
|
||||
const { apiType, apiSlug, useBatchFetch } = apiSetting;
|
||||
@@ -432,8 +432,7 @@ export const apiTranslate = async ({
|
||||
const from = langMap.get(fromLang);
|
||||
const to = langMap.get(toLang);
|
||||
if (!to) {
|
||||
kissLog(`target lang: ${toLang} not support`);
|
||||
return ["", false];
|
||||
throw new Error(`The target lang: ${toLang} not support`);
|
||||
}
|
||||
|
||||
// todo: 优化缓存失效因素
|
||||
@@ -451,7 +450,7 @@ export const apiTranslate = async ({
|
||||
if (useCache) {
|
||||
const cache = await getHttpCachePolyfill(cacheInput);
|
||||
if (cache?.trText) {
|
||||
return [cache.trText, cache.isSame];
|
||||
return cache;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -499,8 +498,12 @@ export const apiTranslate = async ({
|
||||
|
||||
let trText = "";
|
||||
let srLang = "";
|
||||
let srCode = "";
|
||||
if (Array.isArray(tranlation)) {
|
||||
[trText, srLang = ""] = tranlation;
|
||||
if (srLang) {
|
||||
srCode = OPT_LANGS_TO_CODE[apiType].get(srLang) || "";
|
||||
}
|
||||
} else if (typeof tranlation === "string") {
|
||||
trText = tranlation;
|
||||
}
|
||||
@@ -513,10 +516,10 @@ export const apiTranslate = async ({
|
||||
|
||||
// 插入缓存
|
||||
if (useCache) {
|
||||
putHttpCachePolyfill(cacheInput, null, { trText, isSame, srLang });
|
||||
putHttpCachePolyfill(cacheInput, null, { trText, isSame, srLang, srCode });
|
||||
}
|
||||
|
||||
return [trText, isSame];
|
||||
return { trText, srLang, srCode, isSame };
|
||||
};
|
||||
|
||||
// 字幕处理/翻译
|
||||
|
||||
@@ -32,7 +32,7 @@ import {
|
||||
import { msAuth } from "../libs/auth";
|
||||
import { genDeeplFree } from "./deepl";
|
||||
import { genBaidu } from "./baidu";
|
||||
import interpreter from "../libs/interpreter";
|
||||
import { interpreter } from "../libs/interpreter";
|
||||
import { parseJsonObj, extractJson } from "../libs/utils";
|
||||
import { kissLog } from "../libs/log";
|
||||
import { fetchData } from "../libs/fetch";
|
||||
|
||||
@@ -33,7 +33,7 @@ import { sendTabMsg } from "./libs/msg";
|
||||
import { trySyncAllSubRules } from "./libs/subRules";
|
||||
import { saveRule } from "./libs/rules";
|
||||
import { getCurTabId } from "./libs/msg";
|
||||
import { injectInlineJs, injectInternalCss } from "./libs/injector";
|
||||
import { injectInlineJsBg, injectInternalCss } from "./libs/injector";
|
||||
import { kissLog, logger } from "./libs/log";
|
||||
import { chromeDetect, chromeTranslate } from "./libs/builtinAI";
|
||||
|
||||
@@ -268,7 +268,7 @@ const messageHandlers = {
|
||||
[MSG_PUT_HTTPCACHE]: (args) => putHttpCache(args),
|
||||
[MSG_OPEN_OPTIONS]: () => browser.runtime.openOptionsPage(),
|
||||
[MSG_SAVE_RULE]: (args) => saveRule(args),
|
||||
[MSG_INJECT_JS]: (args) => injectToCurrentTab(injectInlineJs, args),
|
||||
[MSG_INJECT_JS]: (args) => injectToCurrentTab(injectInlineJsBg, args),
|
||||
[MSG_INJECT_CSS]: (args) => injectToCurrentTab(injectInternalCss, args),
|
||||
[MSG_UPDATE_CSP]: (args) => updateCspRules(args),
|
||||
[MSG_CONTEXT_MENUS]: (args) => addContextMenus(args),
|
||||
|
||||
@@ -46,7 +46,7 @@ export const OPT_TRANS_OPENROUTER = "OpenRouter";
|
||||
export const OPT_TRANS_CUSTOMIZE = "Custom";
|
||||
|
||||
// 内置支持的翻译引擎
|
||||
export const OPT_ALL_TYPES = [
|
||||
export const OPT_ALL_TRANS_TYPES = [
|
||||
OPT_TRANS_BUILTINAI,
|
||||
OPT_TRANS_GOOGLE,
|
||||
OPT_TRANS_GOOGLE_2,
|
||||
@@ -82,7 +82,7 @@ export const OPT_LANGDETECTOR_MAP = new Set(OPT_LANGDETECTOR_ALL);
|
||||
// 翻译引擎特殊集合
|
||||
export const API_SPE_TYPES = {
|
||||
// 内置翻译
|
||||
builtin: new Set(OPT_ALL_TYPES),
|
||||
builtin: new Set(OPT_ALL_TRANS_TYPES),
|
||||
// 机器翻译
|
||||
machine: new Set([
|
||||
OPT_TRANS_MICROSOFT,
|
||||
@@ -557,7 +557,7 @@ const defaultApiOpts = {
|
||||
};
|
||||
|
||||
// 内置翻译接口列表(带参数)
|
||||
export const DEFAULT_API_LIST = OPT_ALL_TYPES.map((apiType) => ({
|
||||
export const DEFAULT_API_LIST = OPT_ALL_TRANS_TYPES.map((apiType) => ({
|
||||
...defaultApiOpts[apiType],
|
||||
apiSlug: apiType,
|
||||
apiName: apiType,
|
||||
@@ -565,4 +565,6 @@ export const DEFAULT_API_LIST = OPT_ALL_TYPES.map((apiType) => ({
|
||||
}));
|
||||
|
||||
export const DEFAULT_API_TYPE = OPT_TRANS_MICROSOFT;
|
||||
export const DEFAULT_API_SETTING = DEFAULT_API_LIST[DEFAULT_API_TYPE];
|
||||
export const DEFAULT_API_SETTING = DEFAULT_API_LIST.find(
|
||||
(a) => a.apiType === DEFAULT_API_TYPE
|
||||
);
|
||||
|
||||
@@ -745,9 +745,33 @@ export const I18N = {
|
||||
zh_TW: `注入 JS`,
|
||||
},
|
||||
inject_js_helper: {
|
||||
zh: `初始化时注入运行,一个页面仅运行一次。`,
|
||||
en: `Injected and run at initialization, and only run once per page.`,
|
||||
zh_TW: `初始化時注入運行,一個頁面僅運行一次。`,
|
||||
zh: `预加载时注入,一个页面仅运行一次。内置全局对象 KT: {
|
||||
apiTranslate,
|
||||
apiDectect,
|
||||
apiSetting,
|
||||
apisMap,
|
||||
toLang,
|
||||
docInfo,
|
||||
glossary,
|
||||
}`,
|
||||
en: `Injected during preload, runs only once per page. Built-in global object KT: {
|
||||
apiTranslate,
|
||||
apiDectect,
|
||||
apiSetting,
|
||||
apisMap,
|
||||
toLang,
|
||||
docInfo,
|
||||
glossary,
|
||||
}`,
|
||||
zh_TW: `預先載入時注入,一個頁面僅運行一次。內建全域物件 KT: {
|
||||
apiTranslate,
|
||||
apiDectect,
|
||||
apiSetting,
|
||||
apisMap,
|
||||
toLang,
|
||||
docInfo,
|
||||
glossary,
|
||||
}`,
|
||||
},
|
||||
inject_css: {
|
||||
zh: `注入CSS`,
|
||||
@@ -1360,9 +1384,24 @@ export const I18N = {
|
||||
zh_TW: `翻譯開始 Hook`,
|
||||
},
|
||||
translate_start_hook_helper: {
|
||||
zh: `翻译前时运行,入参为: ({hostNode, parentNode, nodes})`,
|
||||
en: `Run before translation, input parameters are: ({hostNode, parentNode, nodes})`,
|
||||
zh_TW: `翻譯前時運行,入參為: ({hostNode, parentNode, nodes})`,
|
||||
zh: `翻译前时运行,入参为: {text,
|
||||
fromLang,
|
||||
toLang,
|
||||
apiSetting,
|
||||
docInfo,
|
||||
glossary,}`,
|
||||
en: `Run before translation, input parameters are: {text,
|
||||
fromLang,
|
||||
toLang,
|
||||
apiSetting,
|
||||
docInfo,
|
||||
glossary,}`,
|
||||
zh_TW: `翻譯前時運行,入參為: {text,
|
||||
fromLang,
|
||||
toLang,
|
||||
apiSetting,
|
||||
docInfo,
|
||||
glossary,}`,
|
||||
},
|
||||
translate_end_hook: {
|
||||
zh: `翻译完成钩子函数`,
|
||||
|
||||
@@ -117,7 +117,7 @@ export const DEFAULT_RULE = {
|
||||
parentStyle: "", // 选择器父节点样式
|
||||
grandStyle: "", // 选择器父节点样式
|
||||
injectJs: "", // 注入JS
|
||||
injectCss: "", // 注入CSS
|
||||
// injectCss: "", // 注入CSS (作废)
|
||||
transOnly: GLOBAL_KEY, // 是否仅显示译文
|
||||
// transTiming: GLOBAL_KEY, // 翻译时机/鼠标悬停翻译 (暂时作废)
|
||||
transTag: GLOBAL_KEY, // 译文元素标签
|
||||
@@ -160,7 +160,7 @@ export const GLOBLA_RULE = {
|
||||
parentStyle: DEFAULT_SELECT_STYLE, // 选择器父节点样式
|
||||
grandStyle: DEFAULT_SELECT_STYLE, // 选择器祖节点样式
|
||||
injectJs: "", // 注入JS
|
||||
injectCss: "", // 注入CSS
|
||||
// injectCss: "", // 注入CSS(作废)
|
||||
transOnly: "false", // 是否仅显示译文
|
||||
// transTiming: OPT_TIMING_PAGESCROLL, // 翻译时机/鼠标悬停翻译 (暂时作废)
|
||||
transTag: DEFAULT_TRANS_TAG, // 译文元素标签
|
||||
|
||||
@@ -13,6 +13,18 @@ export const injectInlineJs = (code, id = "kiss-translator-inline-js") => {
|
||||
(document.head || document.documentElement).appendChild(el);
|
||||
};
|
||||
|
||||
export const injectInlineJsBg = (code, id = "kiss-translator-inline-js") => {
|
||||
if (document.getElementById(id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const el = document.createElement("script");
|
||||
el.type = "text/javascript";
|
||||
el.id = id;
|
||||
el.textContent = code;
|
||||
(document.head || document.documentElement).appendChild(el);
|
||||
};
|
||||
|
||||
// Function to inject external JavaScript file
|
||||
export const injectExternalJs = (src, id = "kiss-translator-external-js") => {
|
||||
if (document.getElementById(id)) {
|
||||
|
||||
@@ -193,7 +193,7 @@ export class InputTranslator {
|
||||
try {
|
||||
addLoading(node, loadingId);
|
||||
|
||||
const [trText, isSame] = await apiTranslate({
|
||||
const { trText, isSame } = await apiTranslate({
|
||||
text,
|
||||
fromLang,
|
||||
toLang,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import Sval from "sval";
|
||||
|
||||
const interpreter = new Sval({
|
||||
export const interpreter = new Sval({
|
||||
// ECMA Version of the code
|
||||
// 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15
|
||||
// or 2015 | 2016 | 2017 | 2018 | 2019 | 2020 | 2021 | 2022 | 2023 | 2024
|
||||
@@ -12,5 +12,3 @@ const interpreter = new Sval({
|
||||
// Whether the code runs in a sandbox
|
||||
sandBox: true,
|
||||
});
|
||||
|
||||
export default interpreter;
|
||||
|
||||
@@ -60,7 +60,7 @@ export const matchRule = async (href, { injectRules, subrulesList }) => {
|
||||
"parentStyle",
|
||||
"grandStyle",
|
||||
"injectJs",
|
||||
"injectCss",
|
||||
// "injectCss",
|
||||
// "fixerSelector",
|
||||
"transStartHook",
|
||||
"transEndHook",
|
||||
@@ -154,7 +154,7 @@ export const checkRules = (rules) => {
|
||||
parentStyle,
|
||||
grandStyle,
|
||||
injectJs,
|
||||
injectCss,
|
||||
// injectCss,
|
||||
apiSlug,
|
||||
fromLang,
|
||||
toLang,
|
||||
@@ -193,7 +193,7 @@ export const checkRules = (rules) => {
|
||||
parentStyle: type(parentStyle) === "string" ? parentStyle : "",
|
||||
grandStyle: type(grandStyle) === "string" ? grandStyle : "",
|
||||
injectJs: type(injectJs) === "string" ? injectJs : "",
|
||||
injectCss: type(injectCss) === "string" ? injectCss : "",
|
||||
// injectCss: type(injectCss) === "string" ? injectCss : "",
|
||||
bgColor: type(bgColor) === "string" ? bgColor : "",
|
||||
textDiyStyle: type(textDiyStyle) === "string" ? textDiyStyle : "",
|
||||
apiSlug:
|
||||
|
||||
@@ -2,8 +2,6 @@ import {
|
||||
APP_UPNAME,
|
||||
APP_LCNAME,
|
||||
APP_CONSTS,
|
||||
MSG_INJECT_JS,
|
||||
MSG_INJECT_CSS,
|
||||
OPT_STYLE_FUZZY,
|
||||
GLOBLA_RULE,
|
||||
DEFAULT_SETTING,
|
||||
@@ -16,13 +14,10 @@ import {
|
||||
OPT_SPLIT_PARAGRAPH_DISABLE,
|
||||
OPT_SPLIT_PARAGRAPH_TEXTLENGTH,
|
||||
} from "../config";
|
||||
import interpreter from "./interpreter";
|
||||
import { interpreter } from "./interpreter";
|
||||
import { clearFetchPool } from "./pool";
|
||||
import { debounce, scheduleIdle, genEventName, truncateWords } from "./utils";
|
||||
import { apiTranslate } from "../apis";
|
||||
import { sendBgMsg } from "./msg";
|
||||
import { isExt } from "./client";
|
||||
import { injectInlineJs, injectInternalCss } from "./injector";
|
||||
import { kissLog } from "./log";
|
||||
import { clearAllBatchQueue } from "./batchQueue";
|
||||
import { genTextClass } from "./style";
|
||||
@@ -1145,7 +1140,6 @@ export class Translator {
|
||||
const {
|
||||
transTag,
|
||||
textStyle,
|
||||
transStartHook,
|
||||
transEndHook,
|
||||
transOnly,
|
||||
termsStyle,
|
||||
@@ -1164,20 +1158,6 @@ export class Translator {
|
||||
const parentNode = hostNode.parentElement;
|
||||
const hideOrigin = transOnly === "true";
|
||||
|
||||
// 翻译开始钩子函数
|
||||
if (transStartHook?.trim()) {
|
||||
try {
|
||||
interpreter.run(`exports.transStartHook = ${transStartHook}`);
|
||||
interpreter.exports.transStartHook({
|
||||
hostNode,
|
||||
parentNode,
|
||||
nodes,
|
||||
});
|
||||
} catch (err) {
|
||||
kissLog("transStartHook", err);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const [processedString, placeholderMap] = this.#serializeForTranslation(
|
||||
nodes,
|
||||
@@ -1202,10 +1182,8 @@ export class Translator {
|
||||
nodes[nodes.length - 1].after(wrapper);
|
||||
|
||||
const currentRunId = this.#runId;
|
||||
const [translatedText, isSameLang] = await this.#translateFetch(
|
||||
processedString,
|
||||
deLang
|
||||
);
|
||||
const { trText: translatedText, isSame: isSameLang } =
|
||||
await this.#translateFetch(processedString, deLang);
|
||||
if (this.#runId !== currentRunId) {
|
||||
throw new Error("Request terminated");
|
||||
}
|
||||
@@ -1391,16 +1369,39 @@ export class Translator {
|
||||
|
||||
// 发起翻译请求
|
||||
#translateFetch(text, deLang = "") {
|
||||
const { fromLang, toLang } = this.#rule;
|
||||
const { toLang, transStartHook } = this.#rule;
|
||||
const fromLang = deLang || this.#rule.fromLang;
|
||||
const apiSetting = { ...this.#apiSetting };
|
||||
const docInfo = { ...this.#docInfo };
|
||||
const glossary = { ...this.#glossary };
|
||||
const apisMap = this.#apisMap;
|
||||
|
||||
return apiTranslate({
|
||||
const args = {
|
||||
text,
|
||||
fromLang: deLang || fromLang,
|
||||
fromLang,
|
||||
toLang,
|
||||
apiSetting: this.#apiSetting,
|
||||
docInfo: this.#docInfo,
|
||||
glossary: this.#glossary,
|
||||
apiSetting,
|
||||
docInfo,
|
||||
glossary,
|
||||
};
|
||||
|
||||
// 翻译开始钩子函数
|
||||
if (transStartHook?.trim()) {
|
||||
try {
|
||||
interpreter.run(`exports.transStartHook = ${transStartHook}`);
|
||||
const hookResult = interpreter.exports.transStartHook({
|
||||
...args,
|
||||
apisMap,
|
||||
});
|
||||
if (hookResult) {
|
||||
Object.assign(args, ...hookResult);
|
||||
}
|
||||
} catch (err) {
|
||||
kissLog("transStartHook", err);
|
||||
}
|
||||
}
|
||||
|
||||
return apiTranslate(args);
|
||||
}
|
||||
|
||||
// 查找指定节点下所有译文节点
|
||||
@@ -1596,14 +1597,35 @@ export class Translator {
|
||||
this.#isJsInjected = true;
|
||||
|
||||
try {
|
||||
const { injectJs, injectCss } = this.#rule;
|
||||
if (isExt) {
|
||||
injectJs && sendBgMsg(MSG_INJECT_JS, injectJs);
|
||||
injectCss && sendBgMsg(MSG_INJECT_CSS, injectCss);
|
||||
} else {
|
||||
injectJs &&
|
||||
injectInlineJs(injectJs, "kiss-translator-userinit-injector");
|
||||
injectCss && injectInternalCss(injectCss);
|
||||
// const { injectJs, injectCss } = this.#rule;
|
||||
// if (isExt) {
|
||||
// injectJs && sendBgMsg(MSG_INJECT_JS, injectJs);
|
||||
// injectCss && sendBgMsg(MSG_INJECT_CSS, injectCss);
|
||||
// } else {
|
||||
// injectJs &&
|
||||
// injectInlineJs(injectJs, "kiss-translator-userinit-injector");
|
||||
// injectCss && injectInternalCss(injectCss);
|
||||
// }
|
||||
|
||||
const { injectJs, toLang } = this.#rule;
|
||||
if (injectJs?.trim()) {
|
||||
const apiSetting = { ...this.#apiSetting };
|
||||
const docInfo = { ...this.#docInfo };
|
||||
const glossary = { ...this.#glossary };
|
||||
const apisMap = this.#apisMap;
|
||||
const apiDectect = tryDetectLang;
|
||||
interpreter.import({
|
||||
KT: {
|
||||
apiTranslate,
|
||||
apiDectect,
|
||||
apiSetting,
|
||||
apisMap,
|
||||
toLang,
|
||||
docInfo,
|
||||
glossary,
|
||||
},
|
||||
});
|
||||
interpreter.run(injectJs);
|
||||
}
|
||||
} catch (err) {
|
||||
kissLog("inject js", err);
|
||||
@@ -1654,8 +1676,8 @@ export class Translator {
|
||||
|
||||
try {
|
||||
const deLang = await tryDetectLang(title);
|
||||
const [translatedTitle] = await this.#translateFetch(title, deLang);
|
||||
document.title = translatedTitle || title;
|
||||
const { trText } = await this.#translateFetch(title, deLang);
|
||||
document.title = trText || title;
|
||||
} catch (err) {
|
||||
kissLog("tanslate title", err);
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ import {
|
||||
DEFAULT_BATCH_SIZE,
|
||||
DEFAULT_BATCH_LENGTH,
|
||||
DEFAULT_CONTEXT_SIZE,
|
||||
OPT_ALL_TYPES,
|
||||
OPT_ALL_TRANS_TYPES,
|
||||
API_SPE_TYPES,
|
||||
BUILTIN_STONES,
|
||||
BUILTIN_PLACEHOLDERS,
|
||||
@@ -54,7 +54,7 @@ function TestButton({ api }) {
|
||||
const handleApiTest = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const [text] = await apiTranslate({
|
||||
const { trText } = await apiTranslate({
|
||||
text: "hello world",
|
||||
fromLang: "en",
|
||||
toLang: "zh-CN",
|
||||
@@ -62,7 +62,7 @@ function TestButton({ api }) {
|
||||
useCache: false,
|
||||
usePool: false,
|
||||
});
|
||||
if (!text) {
|
||||
if (!trText) {
|
||||
throw new Error("empty result");
|
||||
}
|
||||
alert.success(i18n("test_success"));
|
||||
@@ -775,7 +775,7 @@ export default function Apis() {
|
||||
|
||||
const apiTypes = useMemo(
|
||||
() =>
|
||||
OPT_ALL_TYPES.map((type) => ({
|
||||
OPT_ALL_TRANS_TYPES.map((type) => ({
|
||||
type,
|
||||
label: type,
|
||||
})),
|
||||
|
||||
@@ -108,7 +108,7 @@ function RuleFields({ rule, rules, setShow, setKeyword }) {
|
||||
parentStyle = "",
|
||||
grandStyle = "",
|
||||
injectJs = "",
|
||||
injectCss = "",
|
||||
// injectCss = "",
|
||||
apiSlug,
|
||||
fromLang,
|
||||
toLang,
|
||||
@@ -695,7 +695,7 @@ function RuleFields({ rule, rules, setShow, setKeyword }) {
|
||||
maxRows={10}
|
||||
/> */}
|
||||
|
||||
<TextField
|
||||
{/* <TextField
|
||||
size="small"
|
||||
label={i18n("inject_css")}
|
||||
helperText={i18n("inject_css_helper")}
|
||||
@@ -705,7 +705,7 @@ function RuleFields({ rule, rules, setShow, setKeyword }) {
|
||||
onChange={handleChange}
|
||||
maxRows={10}
|
||||
multiline
|
||||
/>
|
||||
/> */}
|
||||
<TextField
|
||||
size="small"
|
||||
label={i18n("inject_js")}
|
||||
|
||||
@@ -38,7 +38,7 @@ export default function TranCont({
|
||||
setTrText("");
|
||||
setError("");
|
||||
|
||||
const [trText] = await apiTranslate({
|
||||
const { trText } = await apiTranslate({
|
||||
text,
|
||||
fromLang,
|
||||
toLang,
|
||||
|
||||
Reference in New Issue
Block a user