Compare commits

..

8 Commits

Author SHA1 Message Date
Gabe Yuan
3dece4fcdb add version tag to loading page 2023-08-29 01:35:09 +08:00
Gabe Yuan
df950a1bd2 use createElement script 2023-08-29 01:17:22 +08:00
Gabe Yuan
74b9ee31fa eslint-disable-line 2023-08-29 00:52:37 +08:00
Gabe Yuan
64cd55fe58 set no-eval 2023-08-29 00:42:11 +08:00
Gabe Yuan
e80ede14fb v1.5.7 2023-08-29 00:09:09 +08:00
Gabe Yuan
45ba9d3320 use inject-into replace unsafeWindow 2023-08-29 00:06:50 +08:00
Gabe Yuan
47c7048538 injectscript... 2023-08-28 17:59:51 +08:00
Gabe Yuan
f9bfa8101f fix detectLanguage 2023-08-28 11:14:03 +08:00
11 changed files with 134 additions and 18 deletions

2
.env
View File

@@ -2,7 +2,7 @@ GENERATE_SOURCEMAP=false
REACT_APP_NAME=KISS Translator
REACT_APP_NAME_CN=简约翻译
REACT_APP_VERSION=1.5.6
REACT_APP_VERSION=1.5.7
REACT_APP_HOMEPAGE=https://github.com/fishjar/kiss-translator
REACT_APP_OPTIONSPAGE=https://kiss-translator.rayjar.com/options
REACT_APP_OPTIONSPAGE2=https://fishjar.github.io/kiss-translator/options.html

View File

@@ -89,7 +89,7 @@ const userscriptWebpack = (config, env) => {
// @grant GM.getValue
// @grant GM.deleteValue
// @grant GM.info
// @grant unsafeWindow
// @inject-into content
// @connect translate.googleapis.com
// @connect api-edge.cognitive.microsofttranslator.com
// @connect edge.microsoft.com

View File

@@ -1,7 +1,7 @@
{
"name": "kiss-translator",
"description": "A minimalist bilingual translation Extension & Greasemonkey Script",
"version": "1.5.6",
"version": "1.5.7",
"author": "Gabe<yugang2002@gmail.com>",
"private": true,
"dependencies": {
@@ -37,8 +37,7 @@
"react-app/jest"
],
"globals": {
"GM": true,
"unsafeWindow": true
"GM": true
}
},
"browserslist": {

View File

@@ -2,7 +2,7 @@
"manifest_version": 2,
"name": "__MSG_app_name__",
"description": "__MSG_app_description__",
"version": "1.5.6",
"version": "1.5.7",
"default_locale": "en",
"author": "Gabe<yugang2002@gmail.com>",
"homepage_url": "https://github.com/fishjar/kiss-translator",

View File

@@ -2,7 +2,7 @@
"manifest_version": 3,
"name": "__MSG_app_name__",
"description": "__MSG_app_description__",
"version": "1.5.6",
"version": "1.5.7",
"default_locale": "en",
"author": "Gabe<yugang2002@gmail.com>",
"homepage_url": "https://github.com/fishjar/kiss-translator",

View File

@@ -19,7 +19,7 @@ import { msAuth } from "./auth";
* @param {*} init
* @returns
*/
const fetchGM = async (input, { method = "GET", headers, body } = {}) =>
export const fetchGM = async (input, { method = "GET", headers, body } = {}) =>
new Promise((resolve, reject) => {
GM.xmlHttpRequest({
method,
@@ -74,11 +74,21 @@ const fetchApi = async ({ input, init = {}, translator, token }) => {
}
if (isGm) {
const connects = GM?.info?.script?.connects || [];
let info;
if (window.KISS_GM) {
info = await window.KISS_GM.getInfo();
} else {
info = GM.info;
}
const connects = info?.script?.connects || [];
const url = new URL(input);
const isSafe = connects.find((item) => url.hostname.endsWith(item));
if (isSafe) {
return fetchGM(input, init);
if (window.KISS_GM) {
return window.KISS_GM.fetch(input, init);
} else {
return fetchGM(input, init);
}
}
}
return fetch(input, init);

97
src/libs/gm.js Normal file
View File

@@ -0,0 +1,97 @@
import { fetchGM } from "./fetch";
/**
* 注入页面的脚本请求并接受GM接口信息
* @param {*} param0
*/
export const injectScript = (ping) => {
const MSG_GM_xmlHttpRequest = "xmlHttpRequest";
const MSG_GM_setValue = "setValue";
const MSG_GM_getValue = "getValue";
const MSG_GM_deleteValue = "deleteValue";
const MSG_GM_info = "info";
let GM_info;
const promiseGM = (action, args, timeout = 5000) =>
new Promise((resolve, reject) => {
const pong = btoa(Math.random()).slice(3, 11);
const handleEvent = (e) => {
window.removeEventListener(pong, handleEvent);
const { data, error } = e.detail;
if (error) {
reject(new Error(error));
} else {
resolve(data);
}
};
window.addEventListener(pong, handleEvent);
window.dispatchEvent(
new CustomEvent(ping, { detail: { action, args, pong } })
);
setTimeout(() => {
window.removeEventListener(pong, handleEvent);
reject(new Error("timeout"));
}, timeout);
});
window.KISS_GM = {
fetch: (input, init) => promiseGM(MSG_GM_xmlHttpRequest, { input, init }),
setValue: (key, val) => promiseGM(MSG_GM_setValue, { key, val }),
getValue: (key) => promiseGM(MSG_GM_getValue, { key }),
deleteValue: (key) => promiseGM(MSG_GM_deleteValue, { key }),
getInfo: () => {
if (GM_info) {
return GM_info;
}
return promiseGM(MSG_GM_info);
},
};
window.APP_NAME = process.env.REACT_APP_NAME;
};
/**
* 监听并回应页面对GM接口的请求
* @param {*} param0
*/
export const handlePing = async (e) => {
const MSG_GM_xmlHttpRequest = "xmlHttpRequest";
const MSG_GM_setValue = "setValue";
const MSG_GM_getValue = "getValue";
const MSG_GM_deleteValue = "deleteValue";
const MSG_GM_info = "info";
const { action, args, pong } = e.detail;
let res;
try {
switch (action) {
case MSG_GM_xmlHttpRequest:
const { input, init } = args;
res = await fetchGM(input, init);
break;
case MSG_GM_setValue:
const { key, val } = args;
await GM.setValue(key, val);
res = val;
break;
case MSG_GM_getValue:
res = await GM.getValue(args.key);
break;
case MSG_GM_deleteValue:
await GM.deleteValue(args.key);
res = "ok";
break;
case MSG_GM_info:
res = GM.info;
break;
default:
throw new Error(`message action is unavailable: ${action}`);
}
window.dispatchEvent(new CustomEvent(pong, { detail: { data: res } }));
} catch (err) {
window.dispatchEvent(
new CustomEvent(pong, { detail: { error: err.message } })
);
}
};

View File

@@ -100,7 +100,7 @@ export const matchRule = async (
*/
export const detectLang = async (q) => {
try {
const res = await browser?.i18n.detectLanguage(q);
const res = await browser?.i18n?.detectLanguage(q);
return res?.languages?.[0]?.language;
} catch (err) {
console.log("[detect lang]", err);

View File

@@ -4,8 +4,8 @@ async function set(key, val) {
if (isExt) {
await browser.storage.local.set({ [key]: val });
} else if (isGm) {
const oldValue = await GM.getValue(key);
await GM.setValue(key, val);
const oldValue = await (window.KISS_GM || GM).getValue(key);
await (window.KISS_GM || GM).setValue(key, val);
window.dispatchEvent(
new StorageEvent("storage", {
key,
@@ -31,7 +31,7 @@ async function get(key) {
const val = await browser.storage.local.get([key]);
return val[key];
} else if (isGm) {
const val = await GM.getValue(key);
const val = await (window.KISS_GM || GM).getValue(key);
return val;
}
return window.localStorage.getItem(key);
@@ -41,8 +41,8 @@ async function del(key) {
if (isExt) {
await browser.storage.local.remove([key]);
} else if (isGm) {
const oldValue = await GM.getValue(key);
await GM.deleteValue(key);
const oldValue = await (window.KISS_GM || GM).getValue(key);
await (window.KISS_GM || GM).deleteValue(key);
window.dispatchEvent(
new StorageEvent("storage", {
key,

View File

@@ -9,6 +9,7 @@ import { trySyncAllSubRules } from "./libs/rules";
import { isGm } from "./libs/browser";
import { MSG_TRANS_TOGGLE, MSG_TRANS_PUTRULE } from "./config";
import { isIframe } from "./libs/iframe";
import { handlePing, injectScript } from "./libs/gm";
/**
* 入口函数
@@ -20,8 +21,16 @@ const init = async () => {
document.location.href.includes(process.env.REACT_APP_OPTIONSPAGE) ||
document.location.href.includes(process.env.REACT_APP_OPTIONSPAGE2)
) {
unsafeWindow.GM = GM;
unsafeWindow.APP_NAME = process.env.REACT_APP_NAME;
// unsafeWindow.GM = GM;
// unsafeWindow.APP_NAME = process.env.REACT_APP_NAME;
const ping = btoa(Math.random()).slice(3, 11);
window.addEventListener(ping, handlePing);
// window.eval(`(${injectScript})("${ping}")`); // eslint-disable-line
const script = document.createElement("script");
script.textContent = `(${injectScript})("${ping}")`;
if (document.head) {
document.head.append(script);
}
return;
}

View File

@@ -62,6 +62,7 @@ export default function Options() {
if (isGm && !ready) {
return (
<center>
<p>{`KISS Translator v${process.env.REACT_APP_VERSION}`}</p>
<CircularProgress />
</center>
);