diff --git a/.env b/.env deleted file mode 100644 index bd4e16c..0000000 --- a/.env +++ /dev/null @@ -1 +0,0 @@ -#GITHUB_TOKEN=xxx diff --git a/.env.production b/.env.production new file mode 100644 index 0000000..f4cb322 --- /dev/null +++ b/.env.production @@ -0,0 +1,2 @@ +#GITHUB_TOKEN=xxx +VITE_RESOLVE_URL=https://cdn.jsdelivr.net/gh/Whilconn/one-toc/src/shared/resolve-rules.json diff --git a/src/background/background.ts b/src/background/background.ts index 2ff3117..5bdd5c8 100644 --- a/src/background/background.ts +++ b/src/background/background.ts @@ -20,19 +20,19 @@ import { // 将变更的配置项重置为默认值,仅用于插件更新的场景 // 当配置项的选项值发生变化,原来的值在现有备选项中不存在,则将该配置项重置为默认的选项值 -function fixSettings(st: Settings) { - if (!st) return st; +function fixSettings(localSettings: Settings): Settings { + if (!localSettings) return localSettings; - const list: [Key1, Option[]][] = [ + const keyAndOptions: [Key1, Option[]][] = [ ['position', POSITION_OPTIONS], ['theme', THEME_OPTIONS], ['strategy', STRATEGY_OPTIONS], ]; - const settings = { ...st }; + const settings = { ...DEFAULT_SETTINGS, ...localSettings }; - for (const [key, opts] of list) { - if (opts.some((o) => o.value === st[key])) continue; + for (const [key, opts] of keyAndOptions) { + if (opts.some((o) => o.value === localSettings[key])) continue; settings[key] = DEFAULT_SETTINGS[key]; } diff --git a/src/content-view/content.tsx b/src/content-view/content.tsx index ac7b101..ba063ed 100644 --- a/src/content-view/content.tsx +++ b/src/content-view/content.tsx @@ -7,6 +7,7 @@ import { ErrorBoundary } from '../shared/error-boundary'; import { addMessageListener, Message } from '../extension-utils/api'; import { loadSettings, Settings } from '../extension-utils/settings'; import { splitTextByLine } from '../content-utils/text-util'; +import { updateResolveRules } from '../shared/resolve-rules'; let visible = false; let reactRoot: Root | null = null; @@ -70,6 +71,8 @@ function findAutoOpenRule(settings: Settings): [string, number] | void { } void loadSettings().then((s) => { + void updateResolveRules(); + const rule = findAutoOpenRule(s); if (!rule) return; diff --git a/src/extension-utils/api.ts b/src/extension-utils/api.ts index 4bbcbb7..fb1dcee 100644 --- a/src/extension-utils/api.ts +++ b/src/extension-utils/api.ts @@ -50,7 +50,7 @@ export function sendTabMessage(tab: Tab, name: string) { chrome.tabs .sendMessage(tab.id, { name }) .then((response: any) => { - if (import.meta.env.DEV) console.log('[sendTabMessage Success]:', response.response); + if (import.meta.env.DEV) console.log('[sendTabMessage Success]:', response); }) .catch((error: any) => { if (import.meta.env.DEV) console.error('[sendTabMessage Error]:', error); diff --git a/src/extension-utils/settings.ts b/src/extension-utils/settings.ts index 1b2dfdf..bf405d3 100644 --- a/src/extension-utils/settings.ts +++ b/src/extension-utils/settings.ts @@ -1,5 +1,5 @@ import { loadStorage, saveStorage } from './api'; -import { RESOLVE_RULES, ResolveRule } from '../shared/resolve-rules'; +import { RESOLVE_RULES, RESOLVE_RULES_VERSION, ResolveRule } from '../shared/resolve-rules'; export interface Settings { position: string; @@ -9,6 +9,7 @@ export interface Settings { // 已读版本号,用于判断是否已经查看releaseNote knownVersion: string; resolveRules: ResolveRule[]; + resolveRulesVersion: string; } export const THEME_OPTIONS = [ @@ -37,6 +38,7 @@ export const DEFAULT_SETTINGS: Settings = { autoOpenRules: import.meta.env.DEV ? '**' : '', knownVersion: '', resolveRules: RESOLVE_RULES, + resolveRulesVersion: RESOLVE_RULES_VERSION, }; export const SETTINGS_KEYS = Object.keys(DEFAULT_SETTINGS); @@ -48,6 +50,6 @@ export function loadSettings() { return loadStorage(SETTINGS_KEYS) as Promise; } -export function saveSettings(settings: Settings) { +export function saveSettings(settings: Partial) { return saveStorage(settings) as Promise; } diff --git a/src/options-view/options.tsx b/src/options-view/options.tsx index 49a9c9c..17e07ad 100644 --- a/src/options-view/options.tsx +++ b/src/options-view/options.tsx @@ -14,6 +14,7 @@ import { saveSettings, STRATEGY_OPTIONS, } from '../extension-utils/settings'; +import { updateResolveRules } from '../shared/resolve-rules'; import pkg from '../../package.json'; import './options.less'; @@ -21,6 +22,16 @@ function openShortcutsPage() { createTab('chrome://extensions/shortcuts'); } +function onUpdateResolveRules() { + updateResolveRules() + .then(() => { + return message.success('更新成功'); + }) + .catch((err: Error) => { + return message.error(err.message || '更新失败'); + }); +} + function Options() { const ua = window.navigator.userAgent; @@ -93,6 +104,12 @@ function Options() { ); })} + + + +

🚁 自动打开规则

diff --git a/src/shared/resolve-rules.json b/src/shared/resolve-rules.json new file mode 100644 index 0000000..1207d04 --- /dev/null +++ b/src/shared/resolve-rules.json @@ -0,0 +1,35 @@ +{ + "version": "1.0.0", + "rules": [ + { + "pages": ["https://www.huxiu.com/article/**"], + "article": "#article-content", + "headings": ["#article-content [label*=标题][class*=title]"] + }, + { + "pages": ["https://my.oschina.net/u/**"], + "article": ".article-detail .content", + "headings": [] + }, + { + "pages": ["https://mp.weixin.qq.com/s/**"], + "article": "#js_content", + "headings": [] + }, + { + "pages": ["https://www.iteye.com/blog/**"], + "article": ".iteye-blog-content-contain", + "headings": [] + }, + { + "pages": ["https://www.iteye.com/news/**"], + "article": "#news_content", + "headings": [] + }, + { + "pages": ["https://zhuanlan.zhihu.com/p/**"], + "article": ".Post-RichText", + "headings": [] + } + ] +} diff --git a/src/shared/resolve-rules.ts b/src/shared/resolve-rules.ts index c9f8138..179b60d 100644 --- a/src/shared/resolve-rules.ts +++ b/src/shared/resolve-rules.ts @@ -1,37 +1,9 @@ import * as micromatch from 'micromatch'; +import resolveRuleJson from './resolve-rules.json'; +import { loadSettings, saveSettings, Settings } from '../extension-utils/settings'; -export const RESOLVE_RULES: ResolveRule[] = [ - { - pages: ['https://www.huxiu.com/article/**'], - article: '#article-content', - headings: ['#article-content [label*=标题][class*=title]'], - }, - { - pages: ['https://my.oschina.net/u/**'], - article: '.article-detail .content', - headings: [], - }, - { - pages: ['https://mp.weixin.qq.com/s/**'], - article: '#js_content', - headings: [], - }, - { - pages: ['https://www.iteye.com/blog/**'], - article: '.iteye-blog-content-contain', - headings: [], - }, - { - pages: ['https://www.iteye.com/news/**'], - article: '#news_content', - headings: [], - }, - { - pages: ['https://zhuanlan.zhihu.com/p/**'], - article: '.Post-RichText', - headings: [], - }, -]; +export const RESOLVE_RULES_VERSION = resolveRuleJson.version as string; +export const RESOLVE_RULES: ResolveRule[] = resolveRuleJson.rules; export function matchResolveRule(rules: ResolveRule[]) { const pathInUrl = location.host + location.pathname; @@ -40,6 +12,27 @@ export function matchResolveRule(rules: ResolveRule[]) { return rules.find((c) => micromatch.some([location.href, pathInUrl], c.pages)); } +/** 更新解析规则 **/ +export async function updateResolveRules() { + const settings: Settings = await loadSettings(); + + const resolveConfigUrl = import.meta.env.VITE_RESOLVE_URL as string; + const resolveConfigJson = (await fetch(resolveConfigUrl).then((r) => { + return r.ok ? r.json() : new Error(`${r.status} ${r.statusText}`); + })) as { version: string; rules: ResolveRule[] }; + + if (!resolveConfigJson?.version) return Promise.reject(resolveConfigJson); + + if (!settings?.resolveRulesVersion || resolveConfigJson.version > settings.resolveRulesVersion) { + return saveSettings({ + resolveRules: resolveConfigJson.rules, + resolveRulesVersion: resolveConfigJson.version, + }); + } + + return Promise.reject(new Error('更新失败')); +} + export type ResolveRule = { // 网页匹配规则 pages: string[];