@weareikko/eslint-plugin-skill 0.0.1 → 0.1.1
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 +162 -2
- package/configs/check-refs.workflow.yml +25 -0
- package/configs/eslint.config.example.js +23 -0
- package/configs/lint-skills.workflow.yml +26 -0
- package/dist/dedup/analyze.d.ts +26 -0
- package/dist/dedup/analyze.d.ts.map +1 -0
- package/dist/dedup/cli.d.ts +10 -0
- package/dist/dedup/cli.d.ts.map +1 -0
- package/dist/dedup/cli.js +37 -0
- package/dist/dedup/cli.js.map +1 -0
- package/dist/dedup/discover.d.ts +16 -0
- package/dist/dedup/discover.d.ts.map +1 -0
- package/dist/dedup/hash.d.ts +17 -0
- package/dist/dedup/hash.d.ts.map +1 -0
- package/dist/dedup/index.d.ts +4 -0
- package/dist/dedup/index.d.ts.map +1 -0
- package/dist/dedup/index.js +2 -0
- package/dist/dedup/report.d.ts +6 -0
- package/dist/dedup/report.d.ts.map +1 -0
- package/dist/dedup/types.d.ts +92 -0
- package/dist/dedup/types.d.ts.map +1 -0
- package/dist/index.d.ts +109 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1236 -0
- package/dist/index.js.map +1 -0
- package/dist/report-ClPKWYJy.js +266 -0
- package/dist/report-ClPKWYJy.js.map +1 -0
- package/dist/rules/body-max-length.d.ts +16 -0
- package/dist/rules/body-max-length.d.ts.map +1 -0
- package/dist/rules/description-has-trigger.d.ts +16 -0
- package/dist/rules/description-has-trigger.d.ts.map +1 -0
- package/dist/rules/description-length.d.ts +16 -0
- package/dist/rules/description-length.d.ts.map +1 -0
- package/dist/rules/description-no-html.d.ts +13 -0
- package/dist/rules/description-no-html.d.ts.map +1 -0
- package/dist/rules/descriptive-reference-filenames.d.ts +15 -0
- package/dist/rules/descriptive-reference-filenames.d.ts.map +1 -0
- package/dist/rules/h1-matches-name.d.ts +13 -0
- package/dist/rules/h1-matches-name.d.ts.map +1 -0
- package/dist/rules/large-reference-toc.d.ts +16 -0
- package/dist/rules/large-reference-toc.d.ts.map +1 -0
- package/dist/rules/meta-prefers-dispatch-table.d.ts +19 -0
- package/dist/rules/meta-prefers-dispatch-table.d.ts.map +1 -0
- package/dist/rules/multi-domain-has-variants.d.ts +16 -0
- package/dist/rules/multi-domain-has-variants.d.ts.map +1 -0
- package/dist/rules/name-kebab-case.d.ts +10 -0
- package/dist/rules/name-kebab-case.d.ts.map +1 -0
- package/dist/rules/name-matches-dir.d.ts +10 -0
- package/dist/rules/name-matches-dir.d.ts.map +1 -0
- package/dist/rules/no-broken-relative-links.d.ts +14 -0
- package/dist/rules/no-broken-relative-links.d.ts.map +1 -0
- package/dist/rules/no-multiple-h1.d.ts +15 -0
- package/dist/rules/no-multiple-h1.d.ts.map +1 -0
- package/dist/rules/no-orphan-references.d.ts +15 -0
- package/dist/rules/no-orphan-references.d.ts.map +1 -0
- package/dist/rules/no-unknown-frontmatter-keys.d.ts +18 -0
- package/dist/rules/no-unknown-frontmatter-keys.d.ts.map +1 -0
- package/dist/rules/procedural-has-steps.d.ts +15 -0
- package/dist/rules/procedural-has-steps.d.ts.map +1 -0
- package/dist/rules/reference-has-content.d.ts +15 -0
- package/dist/rules/reference-has-content.d.ts.map +1 -0
- package/dist/rules/refs-one-level-deep.d.ts +15 -0
- package/dist/rules/refs-one-level-deep.d.ts.map +1 -0
- package/dist/rules/require-frontmatter.d.ts +11 -0
- package/dist/rules/require-frontmatter.d.ts.map +1 -0
- package/dist/rules/valid-allowed-tools.d.ts +15 -0
- package/dist/rules/valid-allowed-tools.d.ts.map +1 -0
- package/dist/types.d.ts +15 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/utils/ast.d.ts +21 -0
- package/dist/utils/ast.d.ts.map +1 -0
- package/dist/utils/frontmatter.d.ts +24 -0
- package/dist/utils/frontmatter.d.ts.map +1 -0
- package/dist/utils/kind.d.ts +41 -0
- package/dist/utils/kind.d.ts.map +1 -0
- package/dist/utils/links.d.ts +23 -0
- package/dist/utils/links.d.ts.map +1 -0
- package/dist/utils/references.d.ts +7 -0
- package/dist/utils/references.d.ts.map +1 -0
- package/dist/utils/skill-file.d.ts +32 -0
- package/dist/utils/skill-file.d.ts.map +1 -0
- package/dist/utils/skill-fs.d.ts +30 -0
- package/dist/utils/skill-fs.d.ts.map +1 -0
- package/docs/check-refs.md +60 -0
- package/docs/rules/body-max-length.md +23 -0
- package/docs/rules/description-has-trigger.md +28 -0
- package/docs/rules/description-length.md +27 -0
- package/docs/rules/description-no-html.md +22 -0
- package/docs/rules/descriptive-reference-filenames.md +26 -0
- package/docs/rules/h1-matches-name.md +36 -0
- package/docs/rules/large-reference-toc.md +26 -0
- package/docs/rules/meta-prefers-dispatch-table.md +30 -0
- package/docs/rules/multi-domain-has-variants.md +26 -0
- package/docs/rules/name-kebab-case.md +31 -0
- package/docs/rules/name-matches-dir.md +29 -0
- package/docs/rules/no-broken-relative-links.md +25 -0
- package/docs/rules/no-multiple-h1.md +31 -0
- package/docs/rules/no-orphan-references.md +25 -0
- package/docs/rules/no-unknown-frontmatter-keys.md +37 -0
- package/docs/rules/procedural-has-steps.md +43 -0
- package/docs/rules/reference-has-content.md +26 -0
- package/docs/rules/refs-one-level-deep.md +26 -0
- package/docs/rules/require-frontmatter.md +34 -0
- package/docs/rules/valid-allowed-tools.md +27 -0
- package/package.json +55 -3
package/README.md
CHANGED
|
@@ -1,5 +1,165 @@
|
|
|
1
1
|
# @weareikko/eslint-plugin-skill
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/@weareikko/eslint-plugin-skill/)
|
|
4
|
+
[](https://www.npmjs.com/package/@weareikko/eslint-plugin-skill/)
|
|
5
|
+
[](https://bundlephobia.com/package/@weareikko/eslint-plugin-skill)
|
|
6
|
+

|
|
4
7
|
|
|
5
|
-
|
|
8
|
+
An ESLint plugin that lints [Claude Code Agent Skills](https://docs.claude.com/en/docs/claude-code/skills) (`SKILL.md` files) for quality.
|
|
9
|
+
|
|
10
|
+
> This package moved from `@ikko-dev/eslint-plugin-skill` to `@weareikko/eslint-plugin-skill`. The old package (last version 0.0.1) will be deprecated: install `@weareikko/eslint-plugin-skill` instead.
|
|
11
|
+
|
|
12
|
+
## Rules
|
|
13
|
+
|
|
14
|
+
The linter targets the standard Claude Code skill format: `name` + `description` YAML frontmatter, a concise Markdown body, and bundled reference files under `references/`.
|
|
15
|
+
|
|
16
|
+
**Skill (`SKILL.md`) rules:**
|
|
17
|
+
|
|
18
|
+
| Rule | What it enforces | `recommended` |
|
|
19
|
+
| --- | --- | --- |
|
|
20
|
+
| [`require-frontmatter`](docs/rules/require-frontmatter.md) | `name` and `description` present and non-empty | error |
|
|
21
|
+
| [`name-kebab-case`](docs/rules/name-kebab-case.md) | `name` is valid: kebab-case, ≤ 64 chars, no reserved words | error |
|
|
22
|
+
| [`name-matches-dir`](docs/rules/name-matches-dir.md) | `name` equals the skill's folder name | error |
|
|
23
|
+
| [`description-length`](docs/rules/description-length.md) | `description` ≤ 1024 chars (configurable) | error |
|
|
24
|
+
| [`description-no-html`](docs/rules/description-no-html.md) | no HTML/XML tags in `description` | error |
|
|
25
|
+
| [`no-unknown-frontmatter-keys`](docs/rules/no-unknown-frontmatter-keys.md) | frontmatter keys are known spec fields (catches typos) | error |
|
|
26
|
+
| [`no-multiple-h1`](docs/rules/no-multiple-h1.md) | at most one top-level `#` H1 in the body | error |
|
|
27
|
+
| [`no-broken-relative-links`](docs/rules/no-broken-relative-links.md) | relative links/images resolve on disk | error |
|
|
28
|
+
| [`refs-one-level-deep`](docs/rules/refs-one-level-deep.md) | reference links stay one directory below `SKILL.md` | error |
|
|
29
|
+
| [`valid-allowed-tools`](docs/rules/valid-allowed-tools.md) | `allowed-tools`, if present, is a non-empty array of tool names | error |
|
|
30
|
+
| [`description-has-trigger`](docs/rules/description-has-trigger.md) | `description` says *when* to use the skill | warn |
|
|
31
|
+
| [`body-max-length`](docs/rules/body-max-length.md) | body stays short (progressive disclosure) | warn |
|
|
32
|
+
| [`no-orphan-references`](docs/rules/no-orphan-references.md) | every `references/` file is linked from `SKILL.md` | warn |
|
|
33
|
+
|
|
34
|
+
**Reference file (`references/**/*.md`) rules:**
|
|
35
|
+
|
|
36
|
+
| Rule | What it enforces | `recommended` |
|
|
37
|
+
| --- | --- | --- |
|
|
38
|
+
| [`descriptive-reference-filenames`](docs/rules/descriptive-reference-filenames.md) | reference files avoid generic names (`doc2.md`) | warn |
|
|
39
|
+
| [`large-reference-toc`](docs/rules/large-reference-toc.md) | reference files > 300 lines carry a table of contents | warn |
|
|
40
|
+
|
|
41
|
+
`recommended` fails on structural errors and nudges on quality with warnings. `strict` promotes every rule to `error`. The preset globs both `**/SKILL.md` and `**/references/**/*.md`.
|
|
42
|
+
|
|
43
|
+
### Opt-in rules
|
|
44
|
+
|
|
45
|
+
Not enabled by any preset — the standard skill format does not require an H1, and `name` is a display label rather than the body title. Turn it on if your team adopts the convention:
|
|
46
|
+
|
|
47
|
+
| Rule | What it enforces |
|
|
48
|
+
| --- | --- |
|
|
49
|
+
| [`h1-matches-name`](docs/rules/h1-matches-name.md) | the body H1 corresponds to `name` |
|
|
50
|
+
|
|
51
|
+
### Skill kinds (opt-in)
|
|
52
|
+
|
|
53
|
+
A skill can declare what *kind* it is via `metadata.kind` in frontmatter (`procedural`, `reference`, `multi-domain`, `tool-wrapper`, or `meta` — see [the taxonomy](docs/design/skill-taxonomy-and-rules.md)). These rules only fire on an **explicit** declaration — never on a guess — so enabling them is safe even if most of your skills haven't declared a kind yet:
|
|
54
|
+
|
|
55
|
+
| Rule | Fires when declared… | What it enforces |
|
|
56
|
+
| --- | --- | --- |
|
|
57
|
+
| [`procedural-has-steps`](docs/rules/procedural-has-steps.md) | `kind: procedural` | body contains an ordered (numbered) list |
|
|
58
|
+
| [`reference-has-content`](docs/rules/reference-has-content.md) | `kind: reference` | `references/` has at least one file |
|
|
59
|
+
| [`multi-domain-has-variants`](docs/rules/multi-domain-has-variants.md) | `kind: multi-domain` | `references/` has at least two files |
|
|
60
|
+
| [`meta-prefers-dispatch-table`](docs/rules/meta-prefers-dispatch-table.md) | `kind: meta` | suggests a markdown table over prose for the dispatch list ([evidence](docs/research/meta-dispatch-table-vs-prose.md): ~21% cheaper, no accuracy difference) |
|
|
61
|
+
|
|
62
|
+
```js
|
|
63
|
+
{
|
|
64
|
+
files: ["**/SKILL.md"],
|
|
65
|
+
rules: {
|
|
66
|
+
"skill/procedural-has-steps": "warn",
|
|
67
|
+
"skill/reference-has-content": "warn",
|
|
68
|
+
"skill/multi-domain-has-variants": "warn",
|
|
69
|
+
},
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Install
|
|
74
|
+
|
|
75
|
+
```sh
|
|
76
|
+
npm install --save-dev eslint @weareikko/eslint-plugin-skill
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Usage
|
|
80
|
+
|
|
81
|
+
Add a flat config at the root of your skills repo (`eslint.config.js`):
|
|
82
|
+
|
|
83
|
+
```js
|
|
84
|
+
import skill from "@weareikko/eslint-plugin-skill";
|
|
85
|
+
|
|
86
|
+
export default [skill.configs.recommended];
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
The preset already globs `**/SKILL.md`, loads the markdown language with YAML frontmatter, and enables the rules. Then:
|
|
90
|
+
|
|
91
|
+
```sh
|
|
92
|
+
npx eslint "**/SKILL.md"
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
A ready-to-copy config lives in [`configs/eslint.config.example.js`](configs/eslint.config.example.js), and a GitHub Actions workflow that lints skills on every PR is in [`configs/lint-skills.workflow.yml`](configs/lint-skills.workflow.yml) — drop it into your skills repo at `.github/workflows/lint-skills.yml`.
|
|
96
|
+
|
|
97
|
+
### Configuring rules
|
|
98
|
+
|
|
99
|
+
Rules with options can be tuned:
|
|
100
|
+
|
|
101
|
+
```js
|
|
102
|
+
import skill from "@weareikko/eslint-plugin-skill";
|
|
103
|
+
|
|
104
|
+
export default [
|
|
105
|
+
skill.configs.recommended,
|
|
106
|
+
{
|
|
107
|
+
files: ["**/SKILL.md"],
|
|
108
|
+
rules: {
|
|
109
|
+
"skill/description-length": ["error", { max: 800 }],
|
|
110
|
+
"skill/body-max-length": ["warn", { maxLines: 400 }],
|
|
111
|
+
"skill/description-has-trigger": [
|
|
112
|
+
"warn",
|
|
113
|
+
{ patterns: ["use when", "trigger", "when the user"] },
|
|
114
|
+
],
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
];
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Cross-skill reference duplication
|
|
121
|
+
|
|
122
|
+
`SKILL.md` rules see one file at a time — they can't tell that two *different* skills carry the same reference content, copied or drifted. That's a separate, repo-level check:
|
|
123
|
+
|
|
124
|
+
```sh
|
|
125
|
+
npx skill-check-refs .
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
It groups sibling skills (by default, those sharing a plugin's `skills/` directory), hashes their `references/**/*.md` files, and reports **duplicates** (byte-identical across skills — a maintenance burden) and **divergences** (same filename, different content — a silent correctness hazard, and the only case that fails CI by default). See [`docs/check-refs.md`](docs/check-refs.md) for options (`--near-duplicates`, `--scope`, `--ignore`) and an example CI workflow at [`configs/check-refs.workflow.yml`](configs/check-refs.workflow.yml).
|
|
129
|
+
|
|
130
|
+
## Skills held in memory
|
|
131
|
+
|
|
132
|
+
A host that keeps its skills off disk (a database, a remote store) lints them with ESLint's `Linter` and passes every file of the skills in the shared setting `settings.skill.files`, a map from path to content. The rules that look past the linted file (`no-broken-relative-links`, `no-orphan-references`, the `kind` rules) then read that map instead of the disk. A flat config matches only files under the linter's `cwd`, so the virtual root is the `cwd`:
|
|
133
|
+
|
|
134
|
+
```js
|
|
135
|
+
import { Linter } from "eslint";
|
|
136
|
+
import skill from "@weareikko/eslint-plugin-skill";
|
|
137
|
+
|
|
138
|
+
const files = {
|
|
139
|
+
"/skills/demo/SKILL.md": skillMd,
|
|
140
|
+
"/skills/demo/references/query.md": queryMd,
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
const messages = new Linter({ cwd: "/skills" }).verify(
|
|
144
|
+
files["/skills/demo/SKILL.md"],
|
|
145
|
+
[skill.configs.recommended, { settings: { skill: { files } } }],
|
|
146
|
+
{ filename: "/skills/demo/SKILL.md" },
|
|
147
|
+
);
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
The cross-skill analysis has the same in-memory entry point, `analyzeSkills` from `@weareikko/eslint-plugin-skill/dedup`:
|
|
151
|
+
|
|
152
|
+
```js
|
|
153
|
+
import { analyzeSkills } from "@weareikko/eslint-plugin-skill/dedup";
|
|
154
|
+
|
|
155
|
+
const { duplicates, divergences } = analyzeSkills([
|
|
156
|
+
{ name: "skill-a", references: [{ relPath: "tone.md", content: toneA }] },
|
|
157
|
+
{ name: "skill-b", references: [{ relPath: "tone.md", content: toneB }] },
|
|
158
|
+
]);
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Run the plugin with ESLint. oxlint runs ESLint-compatible JS plugins only on the JavaScript and TypeScript files it parses; it does not lint Markdown, so it does not see `SKILL.md`.
|
|
162
|
+
|
|
163
|
+
## Changelog
|
|
164
|
+
|
|
165
|
+
The changes are in the [`CHANGELOG.md`](https://github.com/weareikko/motto/blob/main/CHANGELOG.md) of the repository: each pull request adds a fragment in `.changelog/`, and each merge into `main` folds them into a new release with [`@weareikko/changelog`](https://github.com/weareikko/changelog).
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
name: Check skill reference duplication
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
paths:
|
|
6
|
+
- "**/SKILL.md"
|
|
7
|
+
- "**/references/**"
|
|
8
|
+
pull_request:
|
|
9
|
+
paths:
|
|
10
|
+
- "**/SKILL.md"
|
|
11
|
+
- "**/references/**"
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
check-refs:
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
- uses: actions/setup-node@v4
|
|
19
|
+
with:
|
|
20
|
+
node-version: 20
|
|
21
|
+
cache: npm
|
|
22
|
+
- run: npm ci
|
|
23
|
+
# Fails only on divergence (same filename, different content across
|
|
24
|
+
# sibling skills) — duplicates are printed but non-blocking by default.
|
|
25
|
+
- run: npx skill-check-refs .
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// Drop-in ESLint flat config for a repository of Claude Code skills.
|
|
2
|
+
//
|
|
3
|
+
// Copy this to `eslint.config.js` at the root of your skills repo, then run:
|
|
4
|
+
//
|
|
5
|
+
// npx eslint "**/SKILL.md"
|
|
6
|
+
//
|
|
7
|
+
// The `recommended` preset already targets `**/SKILL.md`, loads the markdown
|
|
8
|
+
// language with YAML frontmatter, and enables the rule set. Swap it for
|
|
9
|
+
// `skill.configs.strict` to fail CI on quality warnings too.
|
|
10
|
+
|
|
11
|
+
import skill from "@weareikko/eslint-plugin-skill";
|
|
12
|
+
|
|
13
|
+
export default [
|
|
14
|
+
skill.configs.recommended,
|
|
15
|
+
|
|
16
|
+
// Example override: raise a cap or silence a rule for your house style.
|
|
17
|
+
// {
|
|
18
|
+
// files: ["**/SKILL.md"],
|
|
19
|
+
// rules: {
|
|
20
|
+
// "skill/body-max-length": ["warn", { maxLines: 400 }],
|
|
21
|
+
// },
|
|
22
|
+
// },
|
|
23
|
+
];
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
name: Lint skills
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
paths:
|
|
6
|
+
- "**/SKILL.md"
|
|
7
|
+
- "eslint.config.*"
|
|
8
|
+
- ".github/workflows/lint-skills.yml"
|
|
9
|
+
pull_request:
|
|
10
|
+
paths:
|
|
11
|
+
- "**/SKILL.md"
|
|
12
|
+
- "eslint.config.*"
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
lint:
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v4
|
|
19
|
+
- uses: actions/setup-node@v4
|
|
20
|
+
with:
|
|
21
|
+
node-version: 20
|
|
22
|
+
cache: npm
|
|
23
|
+
- run: npm ci
|
|
24
|
+
# Fails the job on any error-severity finding. Add `--max-warnings 0`
|
|
25
|
+
# to also fail on quality warnings, or point at the `strict` preset.
|
|
26
|
+
- run: npx eslint "**/SKILL.md"
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-skill reference de-duplication analysis.
|
|
3
|
+
*
|
|
4
|
+
* ESLint (and oxlint) rules see one file at a time, so they cannot reliably
|
|
5
|
+
* detect that two DIFFERENT skills carry duplicated or drifted copies of the
|
|
6
|
+
* same reference content — that is a repo/collection-level analysis. This
|
|
7
|
+
* module implements it directly: group sibling skills into a comparison
|
|
8
|
+
* scope, hash their `references/**/*.md` files, and classify:
|
|
9
|
+
*
|
|
10
|
+
* - byte-identical content across skills → `duplicate` (maintenance burden)
|
|
11
|
+
* - same filename, different content across skills → `divergence` (the
|
|
12
|
+
* copies forked — a silent correctness hazard, since a fix to one will not
|
|
13
|
+
* reach the other)
|
|
14
|
+
* - (opt-in) different filenames, highly similar content → `near-duplicate`
|
|
15
|
+
* (a possible copy that was renamed instead of shared)
|
|
16
|
+
*/
|
|
17
|
+
import type { AnalyzeOptions, AnalyzeResult, SkillReferences } from "./types";
|
|
18
|
+
export declare function analyzeReferences(root: string, options?: AnalyzeOptions): AnalyzeResult;
|
|
19
|
+
/**
|
|
20
|
+
* The same analysis over skills held in memory (a database, a remote store),
|
|
21
|
+
* for hosts that never write their skills to disk. Each skill is compared
|
|
22
|
+
* within its `scope` (default: one scope for every skill passed). A file's
|
|
23
|
+
* `absPath` in the findings is `<name>/references/<relPath>`.
|
|
24
|
+
*/
|
|
25
|
+
export declare function analyzeSkills(skills: SkillReferences[], options?: Omit<AnalyzeOptions, "scope">): AnalyzeResult;
|
|
26
|
+
//# sourceMappingURL=analyze.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyze.d.ts","sourceRoot":"","sources":["../../src/dedup/analyze.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAMH,OAAO,KAAK,EACX,cAAc,EACd,aAAa,EAKb,eAAe,EACf,MAAM,SAAS,CAAC;AAKjB,wBAAgB,iBAAiB,CAChC,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,cAAmB,GAC1B,aAAa,CAWf;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAC5B,MAAM,EAAE,eAAe,EAAE,EACzB,OAAO,GAAE,IAAI,CAAC,cAAc,EAAE,OAAO,CAAM,GACzC,aAAa,CAkBf"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* `skill-check-refs` — CLI for cross-skill reference de-duplication.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* skill-check-refs [root] [--scope=plugin|repo] [--near-duplicates]
|
|
7
|
+
* [--threshold=0.75] [--ignore=a.md,b.md] [--json]
|
|
8
|
+
*/
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/dedup/cli.ts"],"names":[],"mappings":";AACA;;;;;;GAMG"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { n as analyzeReferences, t as formatReport } from "../report-ClPKWYJy.js";
|
|
3
|
+
//#region src/dedup/cli.ts
|
|
4
|
+
/**
|
|
5
|
+
* `skill-check-refs` — CLI for cross-skill reference de-duplication.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* skill-check-refs [root] [--scope=plugin|repo] [--near-duplicates]
|
|
9
|
+
* [--threshold=0.75] [--ignore=a.md,b.md] [--json]
|
|
10
|
+
*/
|
|
11
|
+
function parseArgs(argv) {
|
|
12
|
+
let root = ".";
|
|
13
|
+
const options = {};
|
|
14
|
+
let json = false;
|
|
15
|
+
for (const arg of argv) if (arg === "--near-duplicates") options.nearDuplicates = true;
|
|
16
|
+
else if (arg === "--json") json = true;
|
|
17
|
+
else if (arg.startsWith("--scope=")) options.scope = arg.slice(8) === "repo" ? "repo" : "plugin";
|
|
18
|
+
else if (arg.startsWith("--threshold=")) options.nearDuplicateThreshold = Number(arg.slice(12));
|
|
19
|
+
else if (arg.startsWith("--ignore=")) options.ignoreRelPaths = arg.slice(9).split(",").map((s) => s.trim()).filter(Boolean);
|
|
20
|
+
else if (!arg.startsWith("--")) root = arg;
|
|
21
|
+
return {
|
|
22
|
+
root,
|
|
23
|
+
options,
|
|
24
|
+
json
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function main() {
|
|
28
|
+
const { root, options, json } = parseArgs(process.argv.slice(2));
|
|
29
|
+
const result = analyzeReferences(root, options);
|
|
30
|
+
if (json) console.log(JSON.stringify(result, null, 2));
|
|
31
|
+
else console.log(formatReport(result));
|
|
32
|
+
if (result.divergences.length > 0) process.exitCode = 1;
|
|
33
|
+
}
|
|
34
|
+
main();
|
|
35
|
+
//#endregion
|
|
36
|
+
|
|
37
|
+
//# sourceMappingURL=cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","names":[],"sources":["../../src/dedup/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * `skill-check-refs` — CLI for cross-skill reference de-duplication.\n *\n * Usage:\n * skill-check-refs [root] [--scope=plugin|repo] [--near-duplicates]\n * [--threshold=0.75] [--ignore=a.md,b.md] [--json]\n */\n\nimport { analyzeReferences } from \"./analyze\";\nimport { formatReport } from \"./report\";\nimport type { AnalyzeOptions } from \"./types\";\n\nfunction parseArgs(argv: string[]): { root: string; options: AnalyzeOptions; json: boolean } {\n\tlet root = \".\";\n\tconst options: AnalyzeOptions = {};\n\tlet json = false;\n\n\tfor (const arg of argv) {\n\t\tif (arg === \"--near-duplicates\") {\n\t\t\toptions.nearDuplicates = true;\n\t\t} else if (arg === \"--json\") {\n\t\t\tjson = true;\n\t\t} else if (arg.startsWith(\"--scope=\")) {\n\t\t\tconst value = arg.slice(\"--scope=\".length);\n\t\t\toptions.scope = value === \"repo\" ? \"repo\" : \"plugin\";\n\t\t} else if (arg.startsWith(\"--threshold=\")) {\n\t\t\toptions.nearDuplicateThreshold = Number(arg.slice(\"--threshold=\".length));\n\t\t} else if (arg.startsWith(\"--ignore=\")) {\n\t\t\toptions.ignoreRelPaths = arg\n\t\t\t\t.slice(\"--ignore=\".length)\n\t\t\t\t.split(\",\")\n\t\t\t\t.map((s) => s.trim())\n\t\t\t\t.filter(Boolean);\n\t\t} else if (!arg.startsWith(\"--\")) {\n\t\t\troot = arg;\n\t\t}\n\t}\n\n\treturn { root, options, json };\n}\n\nfunction main(): void {\n\tconst { root, options, json } = parseArgs(process.argv.slice(2));\n\tconst result = analyzeReferences(root, options);\n\n\tif (json) {\n\t\tconsole.log(JSON.stringify(result, null, 2));\n\t} else {\n\t\tconsole.log(formatReport(result));\n\t}\n\n\t// Divergence is a correctness hazard — fail CI on it. Duplicates and\n\t// near-duplicates are advisory (maintenance suggestions), non-blocking.\n\tif (result.divergences.length > 0) {\n\t\tprocess.exitCode = 1;\n\t}\n}\n\nmain();\n"],"mappings":";;;;;;;;;;AAaA,SAAS,UAAU,MAA0E;CAC5F,IAAI,OAAO;CACX,MAAM,UAA0B,CAAC;CACjC,IAAI,OAAO;CAEX,KAAK,MAAM,OAAO,MACjB,IAAI,QAAQ,qBACX,QAAQ,iBAAiB;MACnB,IAAI,QAAQ,UAClB,OAAO;MACD,IAAI,IAAI,WAAW,UAAU,GAEnC,QAAQ,QADM,IAAI,MAAM,CACR,MAAU,SAAS,SAAS;MACtC,IAAI,IAAI,WAAW,cAAc,GACvC,QAAQ,yBAAyB,OAAO,IAAI,MAAM,EAAqB,CAAC;MAClE,IAAI,IAAI,WAAW,WAAW,GACpC,QAAQ,iBAAiB,IACvB,MAAM,CAAkB,CAAC,CACzB,MAAM,GAAG,CAAC,CACV,KAAK,MAAM,EAAE,KAAK,CAAC,CAAC,CACpB,OAAO,OAAO;MACV,IAAI,CAAC,IAAI,WAAW,IAAI,GAC9B,OAAO;CAIT,OAAO;EAAE;EAAM;EAAS;CAAK;AAC9B;AAEA,SAAS,OAAa;CACrB,MAAM,EAAE,MAAM,SAAS,SAAS,UAAU,QAAQ,KAAK,MAAM,CAAC,CAAC;CAC/D,MAAM,SAAS,kBAAkB,MAAM,OAAO;CAE9C,IAAI,MACH,QAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;MAE3C,QAAQ,IAAI,aAAa,MAAM,CAAC;CAKjC,IAAI,OAAO,YAAY,SAAS,GAC/B,QAAQ,WAAW;AAErB;AAEA,KAAK"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Discover skills and their reference files under a root directory.
|
|
3
|
+
*/
|
|
4
|
+
import type { ReferenceFile } from "./types";
|
|
5
|
+
/** Recursively find every directory containing a `SKILL.md` file. */
|
|
6
|
+
export declare function findSkillDirs(root: string): string[];
|
|
7
|
+
/**
|
|
8
|
+
* The comparison scope a skill belongs to under the "plugin" strategy: the
|
|
9
|
+
* parent of the nearest ancestor directory literally named `skills` (i.e. the
|
|
10
|
+
* plugin directory for sibling skills under `plugins/<x>/skills/*`). Skills
|
|
11
|
+
* with no such ancestor fall back to `root`.
|
|
12
|
+
*/
|
|
13
|
+
export declare function scopeKeyFor(skillDir: string, root: string): string;
|
|
14
|
+
/** Gather every reference file for a skill, with content + hash loaded. */
|
|
15
|
+
export declare function referenceFilesFor(skillDir: string): ReferenceFile[];
|
|
16
|
+
//# sourceMappingURL=discover.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discover.d.ts","sourceRoot":"","sources":["../../src/dedup/discover.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAI7C,qEAAqE;AACrE,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAoBpD;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAMlE;AAsBD,2EAA2E;AAC3E,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,EAAE,CAgBnE"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Content normalization and hashing for cross-skill reference comparison.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Normalize markdown content so incidental formatting differences (line
|
|
6
|
+
* endings, trailing whitespace, a stray blank line) don't defeat
|
|
7
|
+
* identical-content detection.
|
|
8
|
+
*/
|
|
9
|
+
export declare function normalize(content: string): string;
|
|
10
|
+
/** SHA-1 hash of the normalized content. */
|
|
11
|
+
export declare function hashContent(content: string): string;
|
|
12
|
+
/**
|
|
13
|
+
* Word-shingle Jaccard similarity between two texts, for near-duplicate
|
|
14
|
+
* detection. Returns a value in [0, 1].
|
|
15
|
+
*/
|
|
16
|
+
export declare function similarity(a: string, b: string, shingleSize?: number): number;
|
|
17
|
+
//# sourceMappingURL=hash.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../../src/dedup/hash.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAQjD;AAED,4CAA4C;AAC5C,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,WAAW,SAAI,GAAG,MAAM,CAuBxE"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { analyzeReferences, analyzeSkills } from "./analyze";
|
|
2
|
+
export { formatReport } from "./report";
|
|
3
|
+
export type { AnalyzeOptions, AnalyzeResult, DivergenceFinding, DuplicateFinding, Finding, NearDuplicateFinding, SkillReferences, } from "./types";
|
|
4
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/dedup/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,YAAY,EACX,cAAc,EACd,aAAa,EACb,iBAAiB,EACjB,gBAAgB,EAChB,OAAO,EACP,oBAAoB,EACpB,eAAe,GACf,MAAM,SAAS,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/dedup/report.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7C,wBAAgB,YAAY,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAgC1D"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared types for cross-skill reference de-duplication analysis.
|
|
3
|
+
*/
|
|
4
|
+
export interface ReferenceFile {
|
|
5
|
+
/** Skill directory name (matches the skill's `name`/folder). */
|
|
6
|
+
skillName: string;
|
|
7
|
+
/** Absolute path to the skill's directory. */
|
|
8
|
+
skillDir: string;
|
|
9
|
+
/** Path of the reference file relative to its skill's `references/` dir. */
|
|
10
|
+
relPath: string;
|
|
11
|
+
/** Absolute path to the reference file. */
|
|
12
|
+
absPath: string;
|
|
13
|
+
/** Hash of the normalized content. */
|
|
14
|
+
hash: string;
|
|
15
|
+
/** Raw file content. */
|
|
16
|
+
raw: string;
|
|
17
|
+
}
|
|
18
|
+
/** One skill held in memory, as `analyzeSkills` takes it. */
|
|
19
|
+
export interface SkillReferences {
|
|
20
|
+
/** The skill's name; it stands for the skill directory in the findings. */
|
|
21
|
+
name: string;
|
|
22
|
+
/** Comparison scope. Skills are compared only with skills of the same scope. */
|
|
23
|
+
scope?: string;
|
|
24
|
+
/** The skill's reference files, `relPath` relative to its `references/` directory. */
|
|
25
|
+
references: {
|
|
26
|
+
relPath: string;
|
|
27
|
+
content: string;
|
|
28
|
+
}[];
|
|
29
|
+
}
|
|
30
|
+
export interface FileRef {
|
|
31
|
+
skillName: string;
|
|
32
|
+
absPath: string;
|
|
33
|
+
}
|
|
34
|
+
export interface DuplicateFinding {
|
|
35
|
+
type: "duplicate";
|
|
36
|
+
severity: "warn";
|
|
37
|
+
scope: string;
|
|
38
|
+
relPath: string;
|
|
39
|
+
hash: string;
|
|
40
|
+
files: FileRef[];
|
|
41
|
+
}
|
|
42
|
+
export interface DivergenceFinding {
|
|
43
|
+
type: "divergence";
|
|
44
|
+
severity: "error";
|
|
45
|
+
scope: string;
|
|
46
|
+
relPath: string;
|
|
47
|
+
/** One entry per distinct content hash found under this filename. */
|
|
48
|
+
groups: {
|
|
49
|
+
hash: string;
|
|
50
|
+
files: FileRef[];
|
|
51
|
+
}[];
|
|
52
|
+
}
|
|
53
|
+
export interface NearDuplicateFinding {
|
|
54
|
+
type: "near-duplicate";
|
|
55
|
+
severity: "warn";
|
|
56
|
+
scope: string;
|
|
57
|
+
fileA: FileRef & {
|
|
58
|
+
relPath: string;
|
|
59
|
+
};
|
|
60
|
+
fileB: FileRef & {
|
|
61
|
+
relPath: string;
|
|
62
|
+
};
|
|
63
|
+
similarity: number;
|
|
64
|
+
}
|
|
65
|
+
export type Finding = DuplicateFinding | DivergenceFinding | NearDuplicateFinding;
|
|
66
|
+
export interface AnalyzeOptions {
|
|
67
|
+
/**
|
|
68
|
+
* How to group skills into comparison scopes.
|
|
69
|
+
* - "plugin" (default): skills sharing the same parent of the nearest
|
|
70
|
+
* ancestor directory literally named `skills` are compared together
|
|
71
|
+
* (e.g. sibling skills under one plugin's `skills/` dir). Skills with no
|
|
72
|
+
* such ancestor fall back to a single scope keyed by the analysis root.
|
|
73
|
+
* - "repo": every discovered skill is compared in one global scope.
|
|
74
|
+
*/
|
|
75
|
+
scope?: "plugin" | "repo";
|
|
76
|
+
/**
|
|
77
|
+
* Reference filenames (relative to each skill's `references/` dir) to
|
|
78
|
+
* exclude from duplicate/divergence detection — the escape hatch for
|
|
79
|
+
* deliberate, intentional divergence.
|
|
80
|
+
*/
|
|
81
|
+
ignoreRelPaths?: string[];
|
|
82
|
+
/** Compute near-duplicate findings (different filenames, similar content). Off by default. */
|
|
83
|
+
nearDuplicates?: boolean;
|
|
84
|
+
/** Jaccard similarity threshold (0-1) above which two files are near-duplicates. */
|
|
85
|
+
nearDuplicateThreshold?: number;
|
|
86
|
+
}
|
|
87
|
+
export interface AnalyzeResult {
|
|
88
|
+
duplicates: DuplicateFinding[];
|
|
89
|
+
divergences: DivergenceFinding[];
|
|
90
|
+
nearDuplicates: NearDuplicateFinding[];
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/dedup/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,aAAa;IAC7B,gEAAgE;IAChE,SAAS,EAAE,MAAM,CAAC;IAClB,8CAA8C;IAC9C,QAAQ,EAAE,MAAM,CAAC;IACjB,4EAA4E;IAC5E,OAAO,EAAE,MAAM,CAAC;IAChB,2CAA2C;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,sCAAsC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,wBAAwB;IACxB,GAAG,EAAE,MAAM,CAAC;CACZ;AAED,6DAA6D;AAC7D,MAAM,WAAW,eAAe;IAC/B,2EAA2E;IAC3E,IAAI,EAAE,MAAM,CAAC;IACb,gFAAgF;IAChF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sFAAsF;IACtF,UAAU,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACnD;AAED,MAAM,WAAW,OAAO;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE,WAAW,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,OAAO,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IACjC,IAAI,EAAE,YAAY,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,qEAAqE;IACrE,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,EAAE,CAAA;KAAE,EAAE,CAAC;CAC7C;AAED,MAAM,WAAW,oBAAoB;IACpC,IAAI,EAAE,gBAAgB,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,OAAO,GAAG;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IACrC,KAAK,EAAE,OAAO,GAAG;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IACrC,UAAU,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,OAAO,GAAG,gBAAgB,GAAG,iBAAiB,GAAG,oBAAoB,CAAC;AAElF,MAAM,WAAW,cAAc;IAC9B;;;;;;;OAOG;IACH,KAAK,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC;IAC1B;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,8FAA8F;IAC9F,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,oFAAoF;IACpF,sBAAsB,CAAC,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,aAAa;IAC7B,UAAU,EAAE,gBAAgB,EAAE,CAAC;IAC/B,WAAW,EAAE,iBAAiB,EAAE,CAAC;IACjC,cAAc,EAAE,oBAAoB,EAAE,CAAC;CACvC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @weareikko/eslint-plugin-skill — lint Claude Code Agent Skills (`SKILL.md`).
|
|
3
|
+
*
|
|
4
|
+
* The plugin exposes a set of rules plus two ready-to-use flat configs. Each
|
|
5
|
+
* config is self-contained: it targets `**/SKILL.md`, wires up the
|
|
6
|
+
* `@eslint/markdown` language with YAML frontmatter, and turns on the rules.
|
|
7
|
+
*/
|
|
8
|
+
import type { Linter } from "eslint";
|
|
9
|
+
declare const plugin: {
|
|
10
|
+
meta: {
|
|
11
|
+
name: string;
|
|
12
|
+
version: string;
|
|
13
|
+
};
|
|
14
|
+
rules: {
|
|
15
|
+
"require-frontmatter": import("@eslint/markdown").MarkdownRuleDefinition<{
|
|
16
|
+
RuleOptions: [];
|
|
17
|
+
MessageIds: "emptyKey" | "invalidFrontmatter" | "missingFrontmatter" | "missingKey";
|
|
18
|
+
}>;
|
|
19
|
+
"name-kebab-case": import("@eslint/markdown").MarkdownRuleDefinition<{
|
|
20
|
+
RuleOptions: [];
|
|
21
|
+
MessageIds: "notKebab" | "tooLong" | "reservedWord";
|
|
22
|
+
}>;
|
|
23
|
+
"name-matches-dir": import("@eslint/markdown").MarkdownRuleDefinition<{
|
|
24
|
+
RuleOptions: [];
|
|
25
|
+
MessageIds: "mismatch";
|
|
26
|
+
}>;
|
|
27
|
+
"description-length": import("@eslint/markdown").MarkdownRuleDefinition<{
|
|
28
|
+
RuleOptions: [{
|
|
29
|
+
max?: number;
|
|
30
|
+
}?];
|
|
31
|
+
MessageIds: "tooLong";
|
|
32
|
+
}>;
|
|
33
|
+
"description-has-trigger": import("@eslint/markdown").MarkdownRuleDefinition<{
|
|
34
|
+
RuleOptions: [{
|
|
35
|
+
patterns?: string[];
|
|
36
|
+
}?];
|
|
37
|
+
MessageIds: "noTrigger";
|
|
38
|
+
}>;
|
|
39
|
+
"description-no-html": import("@eslint/markdown").MarkdownRuleDefinition<{
|
|
40
|
+
RuleOptions: [];
|
|
41
|
+
MessageIds: "hasTag";
|
|
42
|
+
}>;
|
|
43
|
+
"no-multiple-h1": import("@eslint/markdown").MarkdownRuleDefinition<{
|
|
44
|
+
RuleOptions: [];
|
|
45
|
+
MessageIds: "multiple";
|
|
46
|
+
}>;
|
|
47
|
+
"h1-matches-name": import("@eslint/markdown").MarkdownRuleDefinition<{
|
|
48
|
+
RuleOptions: [];
|
|
49
|
+
MessageIds: "mismatch";
|
|
50
|
+
}>;
|
|
51
|
+
"body-max-length": import("@eslint/markdown").MarkdownRuleDefinition<{
|
|
52
|
+
RuleOptions: [{
|
|
53
|
+
maxLines?: number;
|
|
54
|
+
}?];
|
|
55
|
+
MessageIds: "tooLong";
|
|
56
|
+
}>;
|
|
57
|
+
"no-broken-relative-links": import("@eslint/markdown").MarkdownRuleDefinition<{
|
|
58
|
+
RuleOptions: [];
|
|
59
|
+
MessageIds: "broken";
|
|
60
|
+
}>;
|
|
61
|
+
"no-unknown-frontmatter-keys": import("@eslint/markdown").MarkdownRuleDefinition<{
|
|
62
|
+
RuleOptions: [{
|
|
63
|
+
allow?: string[];
|
|
64
|
+
}?];
|
|
65
|
+
MessageIds: "unknownKey";
|
|
66
|
+
}>;
|
|
67
|
+
"refs-one-level-deep": import("@eslint/markdown").MarkdownRuleDefinition<{
|
|
68
|
+
RuleOptions: [];
|
|
69
|
+
MessageIds: "tooDeep" | "escapes";
|
|
70
|
+
}>;
|
|
71
|
+
"no-orphan-references": import("@eslint/markdown").MarkdownRuleDefinition<{
|
|
72
|
+
RuleOptions: [];
|
|
73
|
+
MessageIds: "orphan";
|
|
74
|
+
}>;
|
|
75
|
+
"descriptive-reference-filenames": import("@eslint/markdown").MarkdownRuleDefinition<{
|
|
76
|
+
RuleOptions: [];
|
|
77
|
+
MessageIds: "generic";
|
|
78
|
+
}>;
|
|
79
|
+
"large-reference-toc": import("@eslint/markdown").MarkdownRuleDefinition<{
|
|
80
|
+
RuleOptions: [{
|
|
81
|
+
maxLines?: number;
|
|
82
|
+
}?];
|
|
83
|
+
MessageIds: "missingToc";
|
|
84
|
+
}>;
|
|
85
|
+
"valid-allowed-tools": import("@eslint/markdown").MarkdownRuleDefinition<{
|
|
86
|
+
RuleOptions: [];
|
|
87
|
+
MessageIds: "notArray" | "empty" | "invalidEntry";
|
|
88
|
+
}>;
|
|
89
|
+
"procedural-has-steps": import("@eslint/markdown").MarkdownRuleDefinition<{
|
|
90
|
+
RuleOptions: [];
|
|
91
|
+
MessageIds: "noSteps";
|
|
92
|
+
}>;
|
|
93
|
+
"reference-has-content": import("@eslint/markdown").MarkdownRuleDefinition<{
|
|
94
|
+
RuleOptions: [];
|
|
95
|
+
MessageIds: "noReferences";
|
|
96
|
+
}>;
|
|
97
|
+
"multi-domain-has-variants": import("@eslint/markdown").MarkdownRuleDefinition<{
|
|
98
|
+
RuleOptions: [];
|
|
99
|
+
MessageIds: "tooFewVariants";
|
|
100
|
+
}>;
|
|
101
|
+
"meta-prefers-dispatch-table": import("@eslint/markdown").MarkdownRuleDefinition<{
|
|
102
|
+
RuleOptions: [];
|
|
103
|
+
MessageIds: "preferTable";
|
|
104
|
+
}>;
|
|
105
|
+
};
|
|
106
|
+
configs: Record<string, Linter.Config>;
|
|
107
|
+
};
|
|
108
|
+
export default plugin;
|
|
109
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAU,MAAM,EAAE,MAAM,QAAQ,CAAC;AAuB7C,QAAA,MAAM,MAAM;;QAEV,IAAI;QACJ,OAAO;;;QAGP,qBAAqB;;;;QACrB,iBAAiB;;;;QACjB,kBAAkB;;;;QAClB,oBAAoB;;;;;;QACpB,yBAAyB;;;;;;QACzB,qBAAqB;;;;QACrB,gBAAgB;;;;QAChB,iBAAiB;;;;QACjB,iBAAiB;;;;;;QACjB,0BAA0B;;;;QAC1B,6BAA6B;;;;;;QAC7B,qBAAqB;;;;QACrB,sBAAsB;;;;QACtB,iCAAiC;;;;QACjC,qBAAqB;;;;;;QACrB,qBAAqB;;;;QACrB,sBAAsB;;;;QACtB,uBAAuB;;;;QACvB,2BAA2B;;;;QAC3B,6BAA6B;;;;;aAEf,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC;CACpB,CAAC;eAgDX,MAAM"}
|