inject builtin rules

This commit is contained in:
Gabe Yuan
2023-08-17 15:55:44 +08:00
parent bd45947d68
commit 0b9fe65833
7 changed files with 119 additions and 60 deletions

View File

@@ -104,6 +104,10 @@ export const I18N = {
zh: `添加`,
en: `Add`,
},
inject_rules: {
zh: `注入内置规则`,
en: `Inject Built-in Rules`,
},
sync_warn: {
zh: `如果服务器存在其他客户端同步的数据,第一次同步将直接覆盖本地配置,后面则根据修改时间,新的覆盖旧的。`,
en: `If the server has data synchronized by other clients, the first synchronization will directly overwrite the local configuration, and later, according to the modification time, the new one will overwrite the old one.`,
@@ -153,8 +157,8 @@ export const I18N = {
en: `Multiple URLs can be separated by English commas ","`,
},
selector_helper: {
zh: `1、遵循CSS选择器规则,但不同浏览器,支持写法不尽相同。2、留空表示采用全局设置。`,
en: `1. Follow CSS selector rules, but different browsers support different writing methods. 2. Leave blank to adopt the global setting.`,
zh: `1、遵循CSS选择器规则。2、留空表示采用全局设置。`,
en: `1. Follow CSS selector rules. 2. Leave blank to adopt the global setting.`,
},
translate_switch: {
zh: `开启翻译`,

View File

@@ -161,6 +161,7 @@ export const DEFAULT_SETTING = {
fetchLimit: DEFAULT_FETCH_LIMIT, // 最大任务数量
fetchInterval: DEFAULT_FETCH_INTERVAL, // 任务间隔时间
clearCache: false, // 是否在浏览器下次启动时清除缓存
injectRules: true, // 是否注入内置规则
googleUrl: "https://translate.googleapis.com/translate_a/single", // 谷歌翻译接口
openaiUrl: "https://api.openai.com/v1/chat/completions",
openaiKey: "",
@@ -169,14 +170,20 @@ export const DEFAULT_SETTING = {
};
export const DEFAULT_RULES = [
...RULES.map((item) => ({
{
...DEFAULT_RULE,
...item,
...RULES[0],
transOpen: "true",
})),
},
GLOBLA_RULE,
];
export const BUILTIN_RULES = RULES.map((item) => ({
...DEFAULT_RULE,
...item,
transOpen: "true",
}));
export const TRANS_MIN_LENGTH = 5; // 最短翻译长度
export const TRANS_MAX_LENGTH = 5000; // 最长翻译长度

View File

@@ -4,13 +4,17 @@ export const DEFAULT_SELECTOR = `:is(${els})`;
export const RULES = [
{
pattern: `bearblog.dev, www.theverge.com, www.tampermonkey.net/documentation.php`,
selector: DEFAULT_SELECTOR,
pattern: `www.google.com/search`,
selector: `h3, .IsZvec, .VwiC3b`,
},
{
pattern: `https://news.google.com/`,
selector: `h4`,
},
{
pattern: `bearblog.dev, www.theverge.com, www.tampermonkey.net/documentation.php`,
selector: DEFAULT_SELECTOR,
},
{
pattern: `themessenger.com`,
selector: `.leading-tight, .leading-tighter, .my-2 p, .font-body p, article ${DEFAULT_SELECTOR}`,
@@ -127,8 +131,4 @@ export const RULES = [
pattern: `youtube.com`,
selector: `h1, #video-title, #content-text, #title, yt-attributed-string>span>span`,
},
{
pattern: `www.google.com/search`,
selector: `h3, .IsZvec, .VwiC3b`,
},
];

View File

@@ -13,7 +13,7 @@ import { Translator } from "./libs/translator";
(async () => {
const setting = await getSetting();
const rules = await getRules();
const rule = matchRule(rules, document.location.href);
const rule = matchRule(rules, document.location.href, setting);
const translator = new Translator(rule, setting);
// 监听消息

View File

@@ -6,6 +6,7 @@ import {
STOKEY_FAB,
GLOBLA_RULE,
GLOBAL_KEY,
BUILTIN_RULES,
} from "../config";
import { browser } from "./browser";
@@ -52,7 +53,11 @@ export const setFab = async (obj) => await storage.setObj(STOKEY_FAB, obj);
* @param {string} href
* @returns
*/
export const matchRule = (rules, href) => {
export const matchRule = (rules, href, { injectRules }) => {
if (injectRules) {
rules.splice(-1, 0, ...BUILTIN_RULES);
}
const rule = rules.find((rule) =>
rule.pattern.split(",").some((p) => href.includes(p.trim()))
);

View File

@@ -29,7 +29,7 @@ import { Translator } from "./libs/translator";
// 翻译页面
const setting = await getSetting();
const rules = await getRules();
const rule = matchRule(rules, document.location.href);
const rule = matchRule(rules, document.location.href, setting);
const translator = new Translator(rule, setting);
// 浮球按钮

View File

@@ -9,6 +9,7 @@ import {
OPT_LANGS_TO,
OPT_TRANS_ALL,
OPT_STYLE_ALL,
BUILTIN_RULES,
} from "../../config";
import { useState, useRef } from "react";
import { useI18n } from "../../hooks/I18n";
@@ -22,6 +23,9 @@ import MenuItem from "@mui/material/MenuItem";
import Grid from "@mui/material/Grid";
import FileDownloadIcon from "@mui/icons-material/FileDownload";
import FileUploadIcon from "@mui/icons-material/FileUpload";
import { useSetting, useSettingUpdate } from "../../hooks/Setting";
import FormControlLabel from "@mui/material/FormControlLabel";
import Switch from "@mui/material/Switch";
function RuleFields({ rule, rules, setShow }) {
const initFormValues = rule || { ...DEFAULT_RULE, transOpen: "true" };
@@ -245,56 +249,61 @@ function RuleFields({ rule, rules, setShow }) {
</Grid>
</Box>
{editMode ? (
// 编辑
<Stack direction="row" spacing={2}>
{disabled ? (
<>
<Button
size="small"
variant="contained"
onClick={(e) => {
e.preventDefault();
setDisabled(false);
}}
>
{i18n("edit")}
</Button>
{rule?.pattern !== "*" && (
{rules &&
(editMode ? (
// 编辑
<Stack direction="row" spacing={2}>
{disabled ? (
<>
<Button
size="small"
variant="contained"
onClick={(e) => {
e.preventDefault();
setDisabled(false);
}}
>
{i18n("edit")}
</Button>
{rule?.pattern !== "*" && (
<Button
size="small"
variant="outlined"
onClick={(e) => {
e.preventDefault();
rules.del(rule.pattern);
}}
>
{i18n("delete")}
</Button>
)}
</>
) : (
<>
<Button size="small" variant="contained" type="submit">
{i18n("save")}
</Button>
<Button
size="small"
variant="outlined"
onClick={(e) => {
e.preventDefault();
rules.del(rule.pattern);
}}
onClick={handleCancel}
>
{i18n("delete")}
{i18n("cancel")}
</Button>
)}
</>
) : (
<>
<Button size="small" variant="contained" type="submit">
{i18n("save")}
</Button>
<Button size="small" variant="outlined" onClick={handleCancel}>
{i18n("cancel")}
</Button>
</>
)}
</Stack>
) : (
// 添加
<Stack direction="row" spacing={2}>
<Button size="small" variant="contained" type="submit">
{i18n("save")}
</Button>
<Button size="small" variant="outlined" onClick={handleCancel}>
{i18n("cancel")}
</Button>
</Stack>
)}
</>
)}
</Stack>
) : (
// 添加
<Stack direction="row" spacing={2}>
<Button size="small" variant="contained" type="submit">
{i18n("save")}
</Button>
<Button size="small" variant="outlined" onClick={handleCancel}>
{i18n("cancel")}
</Button>
</Stack>
))}
</Stack>
</form>
);
@@ -310,7 +319,13 @@ function RuleAccordion({ rule, rules }) {
return (
<Accordion expanded={expanded} onChange={handleChange}>
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
<Typography>{rule.pattern}</Typography>
<Typography
style={{
opacity: rules ? 1 : 0.5,
}}
>
{rule.pattern}
</Typography>
</AccordionSummary>
<AccordionDetails>
{expanded && <RuleFields rule={rule} rules={rules} />}
@@ -373,6 +388,9 @@ export default function Rules() {
const i18n = useI18n();
const rules = useRules();
const [showAdd, setShowAdd] = useState(false);
const setting = useSetting();
const updateSetting = useSettingUpdate();
const injectRules = !!setting?.injectRules;
const handleImport = (e) => {
const file = e.target.files[0];
@@ -396,6 +414,12 @@ export default function Rules() {
reader.readAsText(file);
};
const handleInject = () => {
updateSetting({
injectRules: !injectRules,
});
};
return (
<Box>
<Stack spacing={3}>
@@ -417,6 +441,17 @@ export default function Rules() {
data={JSON.stringify([...rules.list].reverse(), null, "\t")}
text={i18n("export")}
/>
<FormControlLabel
control={
<Switch
size="small"
checked={injectRules}
onChange={handleInject}
/>
}
label={i18n("inject_rules")}
/>
</Stack>
{showAdd && <RuleFields rules={rules} setShow={setShowAdd} />}
@@ -426,6 +461,14 @@ export default function Rules() {
<RuleAccordion key={rule.pattern} rule={rule} rules={rules} />
))}
</Box>
{injectRules && (
<Box>
{BUILTIN_RULES.map((rule) => (
<RuleAccordion key={rule.pattern} rule={rule} />
))}
</Box>
)}
</Stack>
</Box>
);