✨ 安装页标出不生效的指令与 GM 能力 - #1742
Open
CodFrm wants to merge 3 commits into
Open
✨ 安装页标出不生效的指令与 GM 能力#1742CodFrm wants to merge 3 commits into
CodFrm wants to merge 3 commits into
Conversation
安装页要标出「写了但不会生效」的指令与 GM 能力,但仓库里没有一份「脚本猫支持 什么」的数据:编辑器的未定义标签判定取自悬浮提示表(langs/*.ts 的 prompt 键, 一张翻译表),ESLint 的合法 header 集合取自 packages/eslint 对 eslint-plugin- userscripts 的覆盖,两者互不相识且已经漂移;GM 能力的真相只在 GMContext 注册表 里,而注册表由装饰器在 content 上下文载入时填充,安装页不可能为查一次支持性把 整套 GM 实现拉进包。 新增 src/pkg/utils/script_compat.ts 作为唯一判定来源。判定是二元的:指令要么被 脚本猫消费,要么写了也不生效。收录标准写在文件头——「会被消费」或「不消费但也 不改变脚本运行行为」,只有会改变别家管理器下脚本行为、而脚本猫没实现的指令才刻 意留在表外。GM 能力静态镜像注册表,由 GMContextApiNames() 双向守卫,新增 API 漏 进表会让测试转红;不经注册表、由上下文恒定提供的 unsafeWindow / GM_info / window.onurlchange / none 单独登记,便于审阅。 编辑器的已知标签集合改用这张表,不再随语言包重建——一条指令是否被支持与界面语言 无关。随之修正两处既有误报:@antifeature:<locale> 此前不在本地化后缀规则内被当成 未定义标签;@Definition 是脚本猫自有指令却不在 ESLint 的合法 header 集合里,编辑 器会报「不是合法 userscript header」。 另加 parseMetadataLines:与 parseMetadata 共用 HEADER_BLOCK / META_LINE,逐条保留 行号。诊断必须与运行时解析看到同一批指令,否则会对着一条运行时根本没读到的行报警。
用户安装前看不出脚本里哪些声明脚本猫不会执行。以 @exclude-match 为例:脚本猫 只识别 @match/@include/@exclude,这条声明被原样保留却从不参与匹配,本该被排除 的页面照样会运行脚本,而安装页对此只字不提,装完也不会有任何提示(#1713)。 判定沿用支持表,是二元的:脚本猫不消费就是不生效,不再分兼容程度。标记就近长在 它所属的权限行上,不另起一张卡——不受支持的 @grant 直接替换权限行里原有的 chip, 匹配类声明(@exclude-match)追加到「运行网站」行,归不到任何权限类别的(@sandbox、 @top-level-await 等)落在新增的「其他声明」行。说明走浮层,鼠标移入与键盘聚焦都能 打开;点击 chip 本身恒为跳转,展开代码卡并滚动到该声明所在行并选中。含义不只靠颜色 传达:每枚 chip 带禁止图标与「不生效」的无障碍名。 两处折叠形态会藏掉标记,一并处理:权限一项没变时整卡本会塌成一行,有不生效项时 不塌(折叠的是上次已确认过的权限,而标记是这次才出现的新信息);移动端有标记的 类别默认展开。全都没有时安装页与今天一字不改。 代码定位要求 diff 预览也能拿到实例,为此 CodeEditor 新增 onReady(普通与 diff 两条 分支都触发),revealLine 在 diff 预览里定位到修改侧。这连带修掉一个既有缺陷:此前 onEditorMount 只在普通分支触发,更新安装页(有 diff)的代码骨架永远收不起来——真实 浏览器确认过它被 monaco 盖住不影响观感,但 role=status + aria-busy 会一直留在无障碍 树里说「正在加载代码」。tests/mocks/CodeEditor.tsx 此前无视 diff 一律回调,正是它让 这个缺陷在单元测试里看不出来,现已与真实实现对齐。
真实会话验证时发现两处:浮层里有「兼容性文档」链接,但只有 chip 自己在跟踪悬停, 鼠标一离开 chip 去点链接浮层就关了,链接实际上点不到;标记 chip 常常并排,浮层宽 288px,切换悬停时旧浮层要等关闭延迟才收,两枚会同时开着互相盖住。 改用仓库已有的 useHoverMenu,把浮层本体一并纳入悬停范围;再以模块级「当前开着的 浮层」做互斥,悬停切换时立刻收掉上一枚。
Collaborator
|
这个做法有点古怪吧 但看截图来说,你是用记录「不支持」的方式来实现。不然怎么知道「 「 |
cyfung1031
reviewed
Sep 14, 2026
Comment on lines
+23
to
+26
| const TAG_GROUP: Readonly<Record<string, IneffectiveTagGroup>> = { | ||
| "exclude-match": "match", | ||
| matchaboutblank: "match", | ||
| }; |
Collaborator
There was a problem hiding this comment.
记录不支持的syntax这个做法超白痴
不支持的有无数的多
说不定明天 TM FM 又会加一堆新syntax
这种列表的更新一定不会追得上实际
Collaborator
|
另外,如果要标记「不支持」,应该也要标记「仅限ScriptCat」(那堆CAT_XXXXXX) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Checklist / 检查清单
背景
安装前看不出脚本里哪些声明脚本猫不会执行。以 issue 里的
@exclude-match为例:脚本猫的匹配链路只认@match/@include/@exclude(src/pkg/utils/url_matcher.ts),这条声明被 metadata 原样保留却从不参与匹配,本该被排除的页面照样会运行脚本;安装页对此只字不提,装完也不会有任何提示。#931 的反馈者正是「翻文档才发现原来不兼容」。
动手时发现真正缺的不是 UI,而是没有一份「脚本猫支持什么」的数据,现有三份东西互不相识:
monaco-editor/langs/*.ts的prompt键,一张翻译表);packages/eslint/对eslint-plugin-userscripts的覆盖,描述的是 TM/VM/GM 的支持情况;GMContext注册表里,而它由装饰器在 content 上下文载入时填充。两份列表已经漂移(
allFrames/require-css在 ESLint 覆盖里、不在悬浮提示表里)。另外userscripts/compat-grant与
compat-headers两条规则在 plugin 的configs.recommended里是off,仓库也从没设settings.userscriptVersions,所以那两个覆盖文件今天只影响「名字合不合法」,并不做兼容性判定。
本次改动
三个提交,可分开审:
1.
♻️ 兼容性判定收敛为一张支持表— 新增src/pkg/utils/script_compat.ts作为唯一判定来源。判定是二元的:指令要么被脚本猫消费,要么写了也不生效,不分兼容程度。收录标准写在文件头——「会被消费」或「不消费但也不改变脚本
运行行为」(著作信息、脚本站元数据),只有会改变别家管理器下脚本行为、而脚本猫没实现的指令才刻意留在表外。
GM 能力静态镜像注册表,由新增的
GMContextApiNames()双向守卫。编辑器的已知标签集合改用这张表,不再随语言包重建。随之修正两处既有误报:
@antifeature:<locale>此前不在本地化后缀规则内被当成未定义标签;@definition是脚本猫自有指令却不在 ESLint 的合法 header 集合里。另加
parseMetadataLines,与parseMetadata共用HEADER_BLOCK/META_LINE但逐条保留行号——诊断必须与运行时解析看到同一批指令。
2.
✨ 安装页标出不生效的指令与 GM 能力— 标记就近长在它所属的权限行上,不另起一张卡:不受支持的@grant直接替换权限行里原有的 chip,匹配类声明(
@exclude-match)追加到「运行网站」行,归不到任何权限类别的(
@sandbox、@top-level-await)落在新增的「其他声明」行。说明走浮层(鼠标移入与键盘聚焦都能开),点击 chip恒为跳转:展开代码卡、滚动到该行并选中。含义不只靠颜色传达,每枚 chip 带禁止图标与「不生效」的无障碍名。
两处折叠形态会藏掉标记,一并处理:权限一项没变时整卡本会塌成一行,有不生效项时不塌;移动端有标记的类别默认展开。
文案补齐 10 个语言包。
3.
🐛 不生效标记的浮层不再吞掉文档链接与相邻浮层— 真实会话验证时发现的两处交互缺陷,见下。实现考虑
不在安装页跑 ESLint worker。 issue 的 implementation guidance 提到复用编辑器的 lint 链路,没有采用:
eslint_config是用户可改的(
src/pkg/config/config.ts),用户关掉规则提示就没了——把安全相关的提示挂在用户的 lint 偏好上是错的;安装页是信任决策页,要确定、要快,不该为此拉进 linter worker bundle。标记全部由 metadata 静态派生。
不扫描正文里的 GM 调用。
@grant本来就写在 metadata 里,不需要扫正文;正则扫GM_xxx误报率高,属于编辑器那侧的事。@definition按信息类处理(不标记)。 它是脚本猫自己文档化的编辑器指令,但全仓库没有任何消费方。在它被实现或从文档撤下之前,对着脚本猫自己的文档报警只会让人以为是 bug。这条在
script_compat.ts里写了注释,属于已知的待决项。代码定位要求 diff 预览也能拿到实例,为此
CodeEditor新增onReady(普通与 diff 两条分支都触发),revealLine在 diff 预览里定位到修改侧。这连带修掉一个既有缺陷:此前
onEditorMount只在普通分支触发,更新安装页(有 diff)的代码骨架永远收不起来。真实浏览器确认它被 monaco 盖住、不影响观感,问题在
role=status+aria-busy一直留在无障碍树里说「正在加载代码」。
tests/mocks/CodeEditor.tsx此前无视 diff 一律回调,正是它让这个缺陷在单元测试里看不出来,现已与真实实现对齐。
已知限制
GM_setClipboard只支持字符串这类行为差异不会在安装页出现。安装后会被忽略」,对信息类不算错,但是噪音)。新增时往
INFORMATIONAL_TAGS补一行即可。@exclude-match([Compatibility] Add support for@exclude-match#1714 单独跟踪)。标记不阻断安装。@grant不区分「别家有但脚本猫没实现」和「拼写错误」,统一一句文案。要区分需把eslint-plugin-userscripts的grant 数据带进安装页 bundle,收益不抵成本。
建议审查重点
src/pkg/utils/script_compat.ts的CONSUMED_TAGS/INFORMATIONAL_TAGS两份名单——这是全部判定的根,逐条都值得看一眼。deriveCompatMarks里 metadata 键与代码行的对齐方式(src/pages/install/compat.ts)。CodeEditor新增onReady与onEditorMount的职责划分。关联
close #1713
相关:#931(兼容性跟踪)、#1714(
@exclude-match支持本身)验证
pnpm run lint:prettier / tsc / check:i18n / check:issue-templates / eslint 全通过。pnpm run test:ci:4781 passed(空载)。并行满载时src/pages/options/routes/Tools/NetworkRules/的850ms UI budget 用例会超时(观察到 3~19 例不等),同一批用例空载连续三次全绿;这是 ⚡️ 降低网络规则跨页测试成本并固化测试约束 #1734 自己记录的既有限制
(「本地并行运行整个 NetworkRules 目录时…会出现 worker contention 超时」),与本次改动无关。另外
useInstallData.test.ts的「技能安装成功后同样走按钮状态机与延时关闭」在满载下出现过一次超时,未再复现。script_compat.test.ts(支持判定 + 与注册表/ESLint header 集合的双向一致性守卫)、script.test.ts的parseMetadataLines、install/compat.test.ts(派生与定位)、CompatChip.test.tsx(浮层、跳转、互斥、无行号兜底)、
PermissionRow/PermissionCard/CodePreview/CodeEditor/App的接线与折叠形态。pnpm run build后加载dist/ext,Playwright 驱动安装页)覆盖:三枚标记分别落在正确的权限行、卡头徽章计数、受支持能力不带标记、悬停浮层、鼠标移入浮层后文档链接可达、悬停切换只保留一枚浮层、点击跳转在普通
预览与更新态内联 diff 下都滚动并选中目标行(diff 下 monaco 会自动展开折叠的 unchanged region)、更新态代码骨架
已收起、暗色主题、全部受支持的脚本零标记。
code-skeletonisVisible()恒为true。Screenshots / 截图