dsh-modern-web-guidance 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -7
- package/README.ru.md +9 -6
- package/README.zh.md +7 -6
- package/index.js +36 -14
- package/lib/scan-rules.js +27 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -68,8 +68,9 @@ calls. Usage counters have existed since 0.2.0, but they never leave the machine
|
|
|
68
68
|
| Skill | `chrome-extensions` | Manifest V3 engineering and Chrome Web Store submission guidance |
|
|
69
69
|
|
|
70
70
|
The scanner is report-only. `web_guidance_legacy_scan` takes `paths` (1–16 files or directories, no default target), an
|
|
71
|
-
optional `rules` list of up to
|
|
72
|
-
and 8 MB per call, and returns at most 200 findings.
|
|
71
|
+
optional `rules` list of up to 33 rule ids, and `format: 'summary' | 'json'`; it reads at most 200 files, 512 kB per file
|
|
72
|
+
and 8 MB per call, and returns at most 200 findings. It carries 33 rules, 30 of them upstream's; the
|
|
73
|
+
[parity note](docs/notes/legacy-scan-parity.md) accounts for what is still missing and for the one real debt.
|
|
73
74
|
|
|
74
75
|
The catalog covers `css`, `ui-atoms`, `ui-components`, `ui-behaviors`, `forms`, `html`, `js`, `accessibility`,
|
|
75
76
|
`visual-design`, `security`, `performance`, `built-in-ai`, `pwa`, `wasm`, `webmcp`, `privacy`, and `user-experience`.
|
|
@@ -187,11 +188,11 @@ and security budget. The honest split:
|
|
|
187
188
|
| Lookup | precomputed assets in `gen/` — quantized word vectors (`query-words.i8`, 7.47 MB) and chunk embeddings, 9.16 MB together | BM25 built in-process from `guides.json` and the guide bodies: no assets, no model download (measured 29/30 top-1 on a 30-query probe) |
|
|
188
189
|
| Runtime dependencies | Node plus the CLI engines shipped in the package | none |
|
|
189
190
|
| Network | `npx` fetches the package, then works locally | never — the corpus is inside the package |
|
|
190
|
-
| Legacy scan | a 4.99 MB `legacy-scan` engine with a four-step scan → verify → report → modernize workflow | shipped
|
|
191
|
+
| Legacy scan | a 4.99 MB `legacy-scan` engine with a four-step scan → verify → report → modernize workflow | shipped since 0.5.0: a dependency-free regex scanner over 33 rules, 30 of them upstream's, explicit paths only, report only |
|
|
191
192
|
| Experimental guides | gated inside the CLI | `[experimental]` marker in `web_guidance_search`, warning banner in `web_guidance_retrieve` |
|
|
192
193
|
| Usage insight | none | local counters, `/guidance-stats`, and the sidebar panel |
|
|
193
194
|
| Languages | English guides | the same guides; docs in EN/RU/ZH, panel in EN/RU/ZH |
|
|
194
|
-
| Size | — | 256 files,
|
|
195
|
+
| Size | — | 256 files, 874 kB packed, 2.5 MB unpacked |
|
|
195
196
|
|
|
196
197
|
What this means in practice: if you work outside DeepSeek Harness, use their package — it is the
|
|
197
198
|
reference implementation and it owns the corpus. Inside Harness you want the tools in the model's tool
|
|
@@ -397,8 +398,8 @@ dialog", "view transition", "container query"), not sentences. If a query still
|
|
|
397
398
|
is volatile in one engine — see [Experimental guides](#experimental-guides). The guide is still the
|
|
398
399
|
right shape; feature-detect it before shipping.
|
|
399
400
|
|
|
400
|
-
**What can the legacy scanner actually do?** It is a regex marker scan, not a parser:
|
|
401
|
-
line by line, covering
|
|
401
|
+
**What can the legacy scanner actually do?** It is a regex marker scan, not a parser: 33 rules matched
|
|
402
|
+
line by line, covering 33 of the 208 guides (15.9 %), with no AST, no data-flow analysis and no autofix —
|
|
402
403
|
it reports and stops. It makes no parity claim with Chrome's own `legacy-scan`, a 4.99 MB engine with a
|
|
403
404
|
bundled TypeScript compiler; this one is a dependency-free pass that can produce false positives and
|
|
404
405
|
misses, so treat a finding as a lead to verify, not as a verdict.
|
|
@@ -422,7 +423,8 @@ work on their own; the panel additionally needs the host's `slots`, `locale` and
|
|
|
422
423
|
| --- | --- | --- |
|
|
423
424
|
| 0.4.0 | shipped | the upstream v1.0.0 corpus (208 guides) plus experimental marking |
|
|
424
425
|
| 0.4.1 | shipped | docs: navigation, the comparison, the catalog map |
|
|
425
|
-
| 0.5.0 |
|
|
426
|
+
| 0.5.0 | shipped | `legacy-scan` as the fourth tool: 30 regex rules, explicit paths only, report only — `web_guidance_legacy_scan`, with a fourth counter and a findings total in the panel. Design and verdict: [docs/notes/legacy-scan-feasibility.md](docs/notes/legacy-scan-feasibility.md) |
|
|
427
|
+
| 0.6.0 | this release | three more rules (`:host-context()`, text balancing, `select:invalid`) take the table to 33 rules, 30 of them upstream's, and a guide-hash guard keeps a rule honest after a corpus refresh |
|
|
426
428
|
|
|
427
429
|
Deliberately **not** planned: shipping upstream's 9.16 MB embedding tables, or its 4.99 MB
|
|
428
430
|
`legacy-scan` engine with a bundled TypeScript compiler. Both would break "zero runtime dependencies,
|
package/README.ru.md
CHANGED
|
@@ -69,7 +69,9 @@ API платформы (нативные `<dialog>`/popover, anchor positioning,
|
|
|
69
69
|
|
|
70
70
|
Сканер работает только на чтение. `web_guidance_legacy_scan` принимает `paths` (1–16 файлов или каталогов, цели по
|
|
71
71
|
умолчанию нет), необязательный список `rules` до 30 id правил и `format: 'summary' | 'json'`; за вызов он читает не
|
|
72
|
-
более 200 файлов, до 512 kB на файл и 8 MB суммарно, и возвращает не более 200 находок.
|
|
72
|
+
более 200 файлов, до 512 kB на файл и 8 MB суммарно, и возвращает не более 200 находок. В таблице 33 правила, из них
|
|
73
|
+
30 — правила апстрима; чего до сих пор не хватает и в чём единственный настоящий долг — в
|
|
74
|
+
[заметке о соответствии](docs/notes/legacy-scan-parity.md).
|
|
73
75
|
|
|
74
76
|
Каталог покрывает `css`, `ui-atoms`, `ui-components`, `ui-behaviors`, `forms`, `html`, `js`, `accessibility`,
|
|
75
77
|
`visual-design`, `security`, `performance`, `built-in-ai`, `pwa`, `wasm`, `webmcp`, `privacy` и `user-experience`.
|
|
@@ -185,11 +187,11 @@ DeepSeek Harness: инструменты для модели, боковую п
|
|
|
185
187
|
| Поиск | предвычисленные ассеты в `gen/` — квантованные векторы слов (`query-words.i8`, 7.47 MB) и эмбеддинги чанков, 9.16 MB вместе | BM25 строится в процессе из `guides.json` и тел гайдов: без ассетов, без скачивания модели (измерено 29/30 top-1 на пробе из 30 запросов) |
|
|
186
188
|
| Зависимости рантайма | Node плюс движки CLI, поставляемые в пакете | нет |
|
|
187
189
|
| Сеть | `npx` скачивает пакет, дальше всё локально | никогда — корпус лежит внутри пакета |
|
|
188
|
-
| Сканер legacy | движок `legacy-scan` на 4.99 MB с четырёхшаговым процессом scan → verify → report → modernize |
|
|
190
|
+
| Сканер legacy | движок `legacy-scan` на 4.99 MB с четырёхшаговым процессом scan → verify → report → modernize | поставляется с 0.5.0: сканер регулярными выражениями без зависимостей, 33 правила, из них 30 — правила апстрима, только явные пути, только отчёт |
|
|
189
191
|
| Экспериментальные гайды | закрыты внутри CLI | маркер `[experimental]` в `web_guidance_search`, предупреждающий баннер в `web_guidance_retrieve` |
|
|
190
192
|
| Анализ использования | нет | локальные счётчики, `/guidance-stats` и боковая панель |
|
|
191
193
|
| Языки | гайды на английском | те же гайды; документация на EN/RU/ZH, панель на EN/RU/ZH |
|
|
192
|
-
| Размер | — | 256 файлов,
|
|
194
|
+
| Размер | — | 256 файлов, 874 kB в упаковке, 2.5 MB распакованного |
|
|
193
195
|
|
|
194
196
|
Что это значит на практике: если вы работаете вне DeepSeek Harness, берите их пакет — это референсная реализация, и
|
|
195
197
|
корпус принадлежит им. Внутри Harness нужны инструменты в списке инструментов модели, установка без сборки и без сети и
|
|
@@ -396,8 +398,8 @@ CLI через `npx`, сохраняет заметки про фреймвор
|
|
|
396
398
|
движке — см. [Экспериментальные гайды](#experimental-guides). Гайд всё равно задаёт правильную форму; проверьте её
|
|
397
399
|
фича-детектом, прежде чем отгружать.
|
|
398
400
|
|
|
399
|
-
**Что сканер legacy вообще умеет?** Это маркерный скан регулярными выражениями, а не парсер:
|
|
400
|
-
построчно и покрывают
|
|
401
|
+
**Что сканер legacy вообще умеет?** Это маркерный скан регулярными выражениями, а не парсер: 33 правила проверяются
|
|
402
|
+
построчно и покрывают 33 из 208 гайдов (15,9 %), без AST, без анализа потока данных и без автоисправлений — он
|
|
401
403
|
отчитывается и останавливается. Паритета с собственным `legacy-scan` Chrome он не заявляет: там движок на 4.99 MB со
|
|
402
404
|
встроенным компилятором TypeScript, здесь — проход без зависимостей, который может и ошибиться, и пропустить; считайте
|
|
403
405
|
находку зацепкой для проверки, а не вердиктом.
|
|
@@ -421,7 +423,8 @@ CLI через `npx`, сохраняет заметки про фреймвор
|
|
|
421
423
|
| --- | --- | --- |
|
|
422
424
|
| 0.4.0 | вышел | корпус апстрима v1.0.0 (208 гайдов) плюс пометка экспериментальных |
|
|
423
425
|
| 0.4.1 | вышел | документация: навигация, сравнение, карта каталога |
|
|
424
|
-
| 0.5.0 |
|
|
426
|
+
| 0.5.0 | вышел | `legacy-scan` четвёртым инструментом: 30 правил-регулярок, только явные пути, только отчёт — `web_guidance_legacy_scan`, с четвёртым счётчиком и итогом по находкам в панели. Дизайн и вердикт: [docs/notes/legacy-scan-feasibility.md](docs/notes/legacy-scan-feasibility.md) |
|
|
427
|
+
| 0.6.0 | этот выпуск | ещё три правила (`:host-context()`, балансировка текста, `select:invalid`) — в таблице 33 правила, 30 из них апстрима, плюс страховка по хешам гайдов: после обновления корпуса правило не устареет молча |
|
|
425
428
|
|
|
426
429
|
Намеренно **не** планируется: поставлять таблицы эмбеддингов апстрима на 9.16 MB или его движок `legacy-scan` на
|
|
427
430
|
4.99 MB со встроенным компилятором TypeScript. И то и другое сломало бы «ноль зависимостей рантайма, никакой сети,
|
package/README.zh.md
CHANGED
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
|
|
69
69
|
扫描器只读不写。`web_guidance_legacy_scan` 接受 `paths`(1–16 个文件或目录,没有默认目标)、可选的 `rules`(最多
|
|
70
70
|
30 个规则 id)和 `format: 'summary' | 'json'`;每次调用最多读 200 个文件、单文件 512 kB、合计 8 MB,最多返回
|
|
71
|
-
200
|
|
71
|
+
200 条发现。表里一共 33 条规则,覆盖上游 35 条中的 30 条;剩下没覆盖的规则、以及唯一真正的一笔技术债,都记在[对照说明](docs/notes/legacy-scan-parity.md)里。
|
|
72
72
|
|
|
73
73
|
目录覆盖 `css`、`ui-atoms`、`ui-components`、`ui-behaviors`、`forms`、`html`、`js`、`accessibility`、
|
|
74
74
|
`visual-design`、`security`、`performance`、`built-in-ai`、`pwa`、`wasm`、`webmcp`、`privacy` 和
|
|
@@ -182,11 +182,11 @@ web_guidance_search({"query": "view transition"}) → 取回之前的排序候
|
|
|
182
182
|
| 检索方式 | `gen/` 里预计算好的资源 —— 量化词向量(`query-words.i8`,7.47 MB)与分块 embedding,合计 9.16 MB | 在进程内用 `guides.json` 和指南正文构建 BM25:没有资源文件,不下载模型(在 30 条查询的探针上测得 29/30 的 top-1) |
|
|
183
183
|
| 运行时依赖 | Node 加上包里附带的 CLI 引擎 | 无 |
|
|
184
184
|
| 网络 | `npx` 先取包,之后本地运行 | 从不联网 —— 语料就在包里 |
|
|
185
|
-
| legacy-scan 扫描 | 4.99 MB 的 `legacy-scan` 引擎,带扫描 → 校验 → 报告 → 现代化四步工作流 | 0.5.0 起内置:零依赖的正则扫描器,30
|
|
185
|
+
| legacy-scan 扫描 | 4.99 MB 的 `legacy-scan` 引擎,带扫描 → 校验 → 报告 → 现代化四步工作流 | 0.5.0 起内置:零依赖的正则扫描器,33 条规则(其中 30 条对应上游规则),只接受显式路径,只输出报告 |
|
|
186
186
|
| 实验性指南 | 在 CLI 内部做门控 | `web_guidance_search` 结果里的 `[experimental]` 标记,`web_guidance_retrieve` 开头的警告横幅 |
|
|
187
187
|
| 使用情况洞察 | 无 | 本地计数、`/guidance-stats` 和侧边栏面板 |
|
|
188
188
|
| 语言 | 英文指南 | 同样的指南;文档 EN/RU/ZH,面板 EN/RU/ZH |
|
|
189
|
-
| 体积 | — | 256 个文件,打包
|
|
189
|
+
| 体积 | — | 256 个文件,打包 874 kB,解包 2.5 MB |
|
|
190
190
|
|
|
191
191
|
实际意味着:如果你在 DeepSeek Harness 之外工作,就用他们的包 —— 它是参考实现,语料也归它所有。在 Harness
|
|
192
192
|
里面,你要的是工具出现在模型的工具列表里、安装不需要构建步骤也不联网,以及一个能看出指南到底有没有人在用的
|
|
@@ -374,8 +374,8 @@ web_guidance_search({"query": "view transition"}) → 取回之前的排序候
|
|
|
374
374
|
**为什么结果里写着 `[experimental]`?** 指南讲的平台特性挂在 Origin Trial 后面,或者只在单一引擎里实现、仍
|
|
375
375
|
不稳定 —— 见[实验性指南](#experimental-guides)。指南本身仍然是正确的方向;上线前先做特性检测。
|
|
376
376
|
|
|
377
|
-
**legacy 扫描器到底能做什么?** 它是正则标记扫描,不是解析器:
|
|
378
|
-
(
|
|
377
|
+
**legacy 扫描器到底能做什么?** 它是正则标记扫描,不是解析器:33 条规则逐行匹配,覆盖 208 篇指南中的 33 篇
|
|
378
|
+
(15.9%),没有 AST、没有数据流分析、也不自动修复 —— 它只报告,然后停下。它不声称与 Chrome 自己的
|
|
379
379
|
`legacy-scan` 等价:那边是 4.99 MB、内置 TypeScript 编译器的引擎,这里是零依赖的扫描过程,既可能误报也可能漏报,
|
|
380
380
|
所以把发现当成待核实的线索,而不是结论。
|
|
381
381
|
|
|
@@ -396,7 +396,8 @@ web_guidance_search({"query": "view transition"}) → 取回之前的排序候
|
|
|
396
396
|
| --- | --- | --- |
|
|
397
397
|
| 0.4.0 | 已发布 | 上游 v1.0.0 语料(208 篇指南)加实验性标记 |
|
|
398
398
|
| 0.4.1 | 已发布 | 文档:导航、对比表、目录地图 |
|
|
399
|
-
| 0.5.0 |
|
|
399
|
+
| 0.5.0 | 已发布 | `legacy-scan` 作为第四个工具:30 条正则规则,只接受显式路径,只输出报告 —— `web_guidance_legacy_scan`,面板里多一个计数器和一个发现总数。设计与结论:[docs/notes/legacy-scan-feasibility.md](docs/notes/legacy-scan-feasibility.md) |
|
|
400
|
+
| 0.6.0 | 本次发布 | 再多三条规则(`:host-context()`、文本平衡、`select:invalid`),规则表增至 33 条,其中 30 条对应上游规则;另加指南哈希校验,语料更新后规则不会悄悄过期 |
|
|
400
401
|
|
|
401
402
|
刻意**不**做的:内置上游那 9.16 MB 的 embedding 表,或者它那个附带 TypeScript 编译器的 4.99 MB `legacy-scan`
|
|
402
403
|
引擎。两者都会破坏“零运行时依赖、不联网、不生成代码”,而换来的收益在词法索引上根本看不出来。
|
package/index.js
CHANGED
|
@@ -51,14 +51,22 @@ const LIST_DESCRIPTION = [
|
|
|
51
51
|
'Use it when search phrasing did not match and you want to see what the catalog covers.',
|
|
52
52
|
].join(' ')
|
|
53
53
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
54
|
+
/**
|
|
55
|
+
* The scanner's model-facing description. The rule count is interpolated rather than written
|
|
56
|
+
* out: the table grows, and a hand-written number would quietly start lying about its width.
|
|
57
|
+
* @param {number} ruleCount how many rules the table carries.
|
|
58
|
+
* @returns {string} the description the tool registers with.
|
|
59
|
+
*/
|
|
60
|
+
function scanDescription(ruleCount) {
|
|
61
|
+
return [
|
|
62
|
+
'Scan the files you name for legacy web-platform patterns (jQuery-era DOM helpers, execCommand, document.write,',
|
|
63
|
+
'deprecated APIs) and map every finding to the Modern Web Guidance guide that replaces it. Pass 1-16 relative paths',
|
|
64
|
+
'inside the session workspace: directories are walked, and the scan stops at 200 files, 512 kB per file and 8 MB',
|
|
65
|
+
`total. This is a line-based marker scanner over ${ruleCount} rules, not an AST analyzer, so treat each finding as a lead and`,
|
|
66
|
+
'load the guide with web_guidance_retrieve before changing code. Report-only: it never writes, never spawns a',
|
|
67
|
+
'process and never touches the network.',
|
|
68
|
+
].join(' ')
|
|
69
|
+
}
|
|
62
70
|
|
|
63
71
|
function textBlock(text) {
|
|
64
72
|
return [{ type: 'text', text }]
|
|
@@ -146,13 +154,27 @@ function formatBytes(bytes) {
|
|
|
146
154
|
return `${(size / (1024 * 1024)).toFixed(1)} MB`
|
|
147
155
|
}
|
|
148
156
|
|
|
149
|
-
|
|
157
|
+
/**
|
|
158
|
+
* The id range a report quotes as "valid ids run …". Derived from the tool's own rule list so a
|
|
159
|
+
* new rule cannot leave a stale span in the text.
|
|
160
|
+
* @param {readonly string[]} ids rule ids in table order.
|
|
161
|
+
* @returns {string} `ls-01 … ls-33`, or an empty string when the list is empty.
|
|
162
|
+
*/
|
|
163
|
+
function ruleSpan(ids) {
|
|
164
|
+
if (!Array.isArray(ids) || ids.length === 0) return ''
|
|
165
|
+
return `${ids[0]} … ${ids[ids.length - 1]}`
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/** Fallback id list for a rendered refusal that arrived without one: the shipped table. */
|
|
169
|
+
const ALL_RULE_IDS = RULES.map((rule) => rule.id)
|
|
170
|
+
|
|
171
|
+
function renderScan(_args, value, ruleIds = ALL_RULE_IDS) {
|
|
150
172
|
// A refusal is rendered as a result: the model needs the code and what to pass instead, not a stack.
|
|
151
173
|
if (value?.error !== undefined) {
|
|
152
174
|
if (value.error === 'unknown-rules') {
|
|
153
175
|
const unknown = Array.isArray(value.unknown) ? value.unknown : []
|
|
154
|
-
const ids = Array.isArray(value.rules) ? value.rules :
|
|
155
|
-
const span = ids
|
|
176
|
+
const ids = Array.isArray(value.rules) && value.rules.length > 0 ? value.rules : ruleIds
|
|
177
|
+
const span = ruleSpan(ids)
|
|
156
178
|
return textBlock([
|
|
157
179
|
`Error: unknown-rules — unknown rule id(s): ${unknown.join(', ')}.`,
|
|
158
180
|
`Valid ids run ${span}. Omit "rules" to apply every rule.`,
|
|
@@ -316,7 +338,7 @@ function buildScanTool(scanner, ruleSet) {
|
|
|
316
338
|
const allRuleIds = ruleSet.RULES.map((rule) => rule.id)
|
|
317
339
|
return {
|
|
318
340
|
name: 'web_guidance_legacy_scan',
|
|
319
|
-
description:
|
|
341
|
+
description: scanDescription(allRuleIds.length),
|
|
320
342
|
parameters: {
|
|
321
343
|
type: 'object',
|
|
322
344
|
properties: {
|
|
@@ -326,13 +348,13 @@ function buildScanTool(scanner, ruleSet) {
|
|
|
326
348
|
maxItems: 16,
|
|
327
349
|
items: { type: 'string', maxLength: 512 },
|
|
328
350
|
},
|
|
329
|
-
rules: { type: 'array', maxItems:
|
|
351
|
+
rules: { type: 'array', maxItems: allRuleIds.length, items: { type: 'string', maxLength: 40 } },
|
|
330
352
|
format: { type: 'string', enum: ['summary', 'json'] },
|
|
331
353
|
},
|
|
332
354
|
required: ['paths'],
|
|
333
355
|
additionalProperties: false,
|
|
334
356
|
},
|
|
335
|
-
output: { schema: { type: 'object' }, render: renderScan },
|
|
357
|
+
output: { schema: { type: 'object' }, render: (args, value) => renderScan(args, value, allRuleIds) },
|
|
336
358
|
async execute(args, exec) {
|
|
337
359
|
exec?.signal?.throwIfAborted?.()
|
|
338
360
|
const cwd = exec?.agent?.session?.header?.cwd ?? process.cwd()
|
package/lib/scan-rules.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The legacy-scan rule table for `web_guidance_legacy_scan`.
|
|
3
3
|
*
|
|
4
|
-
* Thirty hand-written markers, each pointing at the guide that explains the modern
|
|
4
|
+
* Thirty-three hand-written markers, each pointing at the guide that explains the modern
|
|
5
5
|
* replacement. This is deliberately not a port of upstream's analyzer: upstream detects
|
|
6
6
|
* these patterns with the TypeScript compiler, so its rules cannot be reused as data —
|
|
7
7
|
* see `docs/notes/legacy-scan-feasibility.md` for the measurement behind that claim.
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* @typedef {object} ScanRule
|
|
19
|
-
* @property {string} id stable rule id, `ls-01` … `ls-
|
|
19
|
+
* @property {string} id stable rule id, `ls-01` … `ls-33`
|
|
20
20
|
* @property {string | null} guideId guide in `data/guides.json`, or null when no guide owns the marker
|
|
21
21
|
* @property {'high' | 'medium' | 'low'} confidence `high` when the marker alone is conclusive
|
|
22
22
|
* @property {string} message one imperative sentence naming the modern replacement
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
export const CONFIDENCE_ORDER = Object.freeze(['high', 'medium', 'low'])
|
|
28
28
|
|
|
29
29
|
/**
|
|
30
|
-
* Ordered rule table. Ids run `ls-01` … `ls-
|
|
30
|
+
* Ordered rule table. Ids run `ls-01` … `ls-33`; CSS markers come first, then HTML/DOM
|
|
31
31
|
* structure, then the JavaScript library and API markers, so a report reads top-down by
|
|
32
32
|
* layer. Every non-null `guideId` is a real catalog entry — `test/scan-rules.test.mjs`
|
|
33
33
|
* fails if a rename ever breaks that.
|
|
@@ -89,7 +89,7 @@ export const RULES = Object.freeze([
|
|
|
89
89
|
guideId: 'validate-input-after-interaction',
|
|
90
90
|
confidence: 'medium',
|
|
91
91
|
message: 'Use :user-invalid so error styling appears only after interaction instead of styling :invalid (including :not(:focus):invalid workarounds).',
|
|
92
|
-
source: '
|
|
92
|
+
source: '(?:input|textarea)\\b[^;{},]*?:invalid\\b',
|
|
93
93
|
},
|
|
94
94
|
{
|
|
95
95
|
id: 'ls-09',
|
|
@@ -186,8 +186,8 @@ export const RULES = Object.freeze([
|
|
|
186
186
|
id: 'ls-22',
|
|
187
187
|
guideId: 'equal-width-text-lines',
|
|
188
188
|
confidence: 'high',
|
|
189
|
-
message: 'Use text-wrap: balance or text-wrap: pretty instead of fitty
|
|
190
|
-
source: '\\b(?:fitty|fitText
|
|
189
|
+
message: 'Use text-wrap: balance or text-wrap: pretty instead of fitty or fitText measuring text in JavaScript.',
|
|
190
|
+
source: '\\b(?:fitty|fitText)\\s*\\(',
|
|
191
191
|
},
|
|
192
192
|
{
|
|
193
193
|
id: 'ls-23',
|
|
@@ -245,6 +245,27 @@ export const RULES = Object.freeze([
|
|
|
245
245
|
message: 'Define custom elements with customElements.define() instead of the removed document.registerElement().',
|
|
246
246
|
source: 'document\\.registerElement\\s*\\(',
|
|
247
247
|
},
|
|
248
|
+
{
|
|
249
|
+
id: 'ls-31',
|
|
250
|
+
guideId: 'styling-web-components',
|
|
251
|
+
confidence: 'high',
|
|
252
|
+
message: 'Use inherited CSS custom properties or container style queries instead of the non-standard :host-context(), which Firefox and Safari do not implement.',
|
|
253
|
+
source: ':host-context\\s*\\(',
|
|
254
|
+
},
|
|
255
|
+
{
|
|
256
|
+
id: 'ls-32',
|
|
257
|
+
guideId: 'improve-text-layout-and-legibility',
|
|
258
|
+
confidence: 'high',
|
|
259
|
+
message: 'Use CSS text-wrap: balance or text-wrap: pretty instead of JavaScript line balancing with balanceText() or <Balancer>.',
|
|
260
|
+
source: '\\bbalanceText\\s*\\(|<Balancer[\\s>/]',
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
id: 'ls-33',
|
|
264
|
+
guideId: 'select-menu-interaction',
|
|
265
|
+
confidence: 'high',
|
|
266
|
+
message: 'Use select:user-invalid so a required dropdown only shows error styling after the user interacts with it.',
|
|
267
|
+
source: 'select\\b[^;{},]*?:invalid\\b',
|
|
268
|
+
},
|
|
248
269
|
])
|
|
249
270
|
|
|
250
271
|
/** Id → rule lookup, so `ruleById` and `selectRules` stay linear. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-modern-web-guidance",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Modern web platform guidance for DeepSeek Harness agents: Google Chrome's 208-guide catalog with offline search and retrieve tools, a report-only legacy-pattern scanner, plus a Chrome extensions (MV3) skill.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|