@geoql/eslint-plugin-vue-doctor 1.0.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/LICENSE +21 -0
- package/README.md +79 -0
- package/dist/index.d.ts +47 -0
- package/dist/index.js +128 -0
- package/dist/index.js.map +1 -0
- package/package.json +69 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Vinayak Kulkarni
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# @geoql/eslint-plugin-vue-doctor
|
|
2
|
+
|
|
3
|
+
ESLint **flat-config** plugin that flags Vue 3 anti-patterns, AI-slop, reactivity
|
|
4
|
+
leaks, composition mistakes, and security issues — the same detection logic that
|
|
5
|
+
powers [`@geoql/oxlint-plugin-vue-doctor`](../oxlint-plugin-vue-doctor), exposed
|
|
6
|
+
for teams whose lint pipeline is ESLint rather than oxlint.
|
|
7
|
+
|
|
8
|
+
## Install
|
|
9
|
+
|
|
10
|
+
```sh
|
|
11
|
+
pnpm add -D @geoql/eslint-plugin-vue-doctor eslint
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Usage (flat config)
|
|
15
|
+
|
|
16
|
+
```js
|
|
17
|
+
// eslint.config.js
|
|
18
|
+
import vueDoctor from '@geoql/eslint-plugin-vue-doctor';
|
|
19
|
+
|
|
20
|
+
export default [vueDoctor.configs.recommended];
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Or wire individual rules:
|
|
24
|
+
|
|
25
|
+
```js
|
|
26
|
+
import vueDoctor from '@geoql/eslint-plugin-vue-doctor';
|
|
27
|
+
|
|
28
|
+
export default [
|
|
29
|
+
{
|
|
30
|
+
plugins: { 'vue-doctor': vueDoctor },
|
|
31
|
+
rules: {
|
|
32
|
+
'vue-doctor/security/no-eval-like': 'error',
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
];
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Presets
|
|
39
|
+
|
|
40
|
+
- `configs.recommended` — every rule flagged `recommended` in the shared registry,
|
|
41
|
+
wired at its registry severity (`error`/`warn`).
|
|
42
|
+
- `configs.all` — every script rule the plugin ships, all at `error`.
|
|
43
|
+
|
|
44
|
+
### Capabilities (`settings`)
|
|
45
|
+
|
|
46
|
+
Some rules only fire when the project has a matching capability. Provide them via
|
|
47
|
+
the `vue-doctor` settings namespace:
|
|
48
|
+
|
|
49
|
+
```js
|
|
50
|
+
export default [
|
|
51
|
+
{
|
|
52
|
+
plugins: { 'vue-doctor': vueDoctor },
|
|
53
|
+
settings: { 'vue-doctor': { capabilities: ['auto-imports:vue'] } },
|
|
54
|
+
rules: { 'vue-doctor/no-imports-from-vue-when-auto-imported': 'warn' },
|
|
55
|
+
},
|
|
56
|
+
];
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Scope — script rules only (deliberate)
|
|
60
|
+
|
|
61
|
+
This plugin wires **every ESTree/JavaScript-AST rule core** from
|
|
62
|
+
`@geoql/doctor-rule-core` (the same cores oxlint uses). Each ESLint rule is a thin
|
|
63
|
+
adapter: it imports the shared core and forwards the core's visitor and message
|
|
64
|
+
into ESLint's `create` / `context.report` API. There is **no duplicated detection
|
|
65
|
+
logic** — a rule's behavior is identical across oxlint and ESLint because both
|
|
66
|
+
consume the same core.
|
|
67
|
+
|
|
68
|
+
**Template-AST rules are intentionally not included.** Rules such as
|
|
69
|
+
`v-for-has-key` operate on the `@vue/compiler-sfc` template AST, which has a
|
|
70
|
+
completely different node shape from ESLint's JavaScript AST. Surfacing them in
|
|
71
|
+
ESLint would require a `vue-eslint-parser` `defineTemplateBodyVisitor` bridge over
|
|
72
|
+
a different AST — a separate, non-mechanical adapter. Those template rules remain
|
|
73
|
+
available through `@geoql/oxlint-plugin-vue-doctor` and the `@geoql/vue-doctor`
|
|
74
|
+
CLI. This plugin ships a complete, correct adapter for the script-rule surface
|
|
75
|
+
rather than a half-built template bridge.
|
|
76
|
+
|
|
77
|
+
## License
|
|
78
|
+
|
|
79
|
+
MIT © [Vinayak Kulkarni](https://vinayakkulkarni.dev)
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { CoreRule, CoreRule as CoreRule$1, Severity, Severity as Severity$1, VUE_AUTO_IMPORTED, VUE_RULES } from "@geoql/doctor-rule-core";
|
|
2
|
+
import { Rule } from "eslint";
|
|
3
|
+
|
|
4
|
+
//#region src/to-eslint-rule.d.ts
|
|
5
|
+
type ESLintSeverity$1 = 'error' | 'warn';
|
|
6
|
+
interface ESLintRule extends Rule.RuleModule<ESLintSeverity$1> {
|
|
7
|
+
readonly id: string;
|
|
8
|
+
}
|
|
9
|
+
declare function toESLintRule(core: CoreRule$1): ESLintRule;
|
|
10
|
+
declare function deriveCapabilities(settings: Record<string, unknown> | undefined, namespace?: string): Set<string>;
|
|
11
|
+
//#endregion
|
|
12
|
+
//#region src/plugin.d.ts
|
|
13
|
+
type ESLintSeverity = 'error' | 'warn';
|
|
14
|
+
interface VueDoctorRuleModule {
|
|
15
|
+
readonly id: string;
|
|
16
|
+
readonly severity: Severity$1;
|
|
17
|
+
readonly recommended: boolean;
|
|
18
|
+
readonly category: string;
|
|
19
|
+
}
|
|
20
|
+
interface VueDoctorConfig {
|
|
21
|
+
readonly files: ReadonlyArray<string>;
|
|
22
|
+
readonly plugins: {
|
|
23
|
+
readonly 'vue-doctor': VueDoctorPlugin;
|
|
24
|
+
};
|
|
25
|
+
readonly rules: Readonly<Record<string, ESLintSeverity>>;
|
|
26
|
+
readonly settings?: {
|
|
27
|
+
readonly 'vue-doctor': {
|
|
28
|
+
readonly capabilities: string[];
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
interface VueDoctorPlugin {
|
|
33
|
+
readonly meta: {
|
|
34
|
+
readonly name: 'vue-doctor';
|
|
35
|
+
readonly version: string;
|
|
36
|
+
};
|
|
37
|
+
readonly rules: Readonly<Record<string, ReturnType<typeof toESLintRule>>>;
|
|
38
|
+
readonly ruleMeta: Readonly<Record<string, VueDoctorRuleModule>>;
|
|
39
|
+
readonly configs: {
|
|
40
|
+
readonly recommended: ReadonlyArray<VueDoctorConfig>;
|
|
41
|
+
readonly all: ReadonlyArray<VueDoctorConfig>;
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
declare const finalPlugin: VueDoctorPlugin;
|
|
45
|
+
//#endregion
|
|
46
|
+
export { type CoreRule, type ESLintRule, type Severity, VUE_AUTO_IMPORTED, VUE_RULES, type VueDoctorPlugin, type VueDoctorRuleModule, finalPlugin as default, finalPlugin as plugin, deriveCapabilities, toESLintRule };
|
|
47
|
+
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { VUE_AUTO_IMPORTED, VUE_RULES, VUE_RULES as VUE_RULES$1 } from "@geoql/doctor-rule-core";
|
|
2
|
+
//#region src/to-eslint-rule.ts
|
|
3
|
+
function toESLintRule(core) {
|
|
4
|
+
const meta = {
|
|
5
|
+
type: "problem",
|
|
6
|
+
schema: [],
|
|
7
|
+
messages: { default: "" }
|
|
8
|
+
};
|
|
9
|
+
if (core.meta?.fixable) meta.fixable = "code";
|
|
10
|
+
return {
|
|
11
|
+
id: core.id,
|
|
12
|
+
meta,
|
|
13
|
+
create(context) {
|
|
14
|
+
const settings = context.settings;
|
|
15
|
+
const coreContext = {
|
|
16
|
+
report(descriptor) {
|
|
17
|
+
const node = descriptor.node;
|
|
18
|
+
if (!descriptor.fix) {
|
|
19
|
+
context.report({
|
|
20
|
+
node,
|
|
21
|
+
message: descriptor.message
|
|
22
|
+
});
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
context.report({
|
|
26
|
+
node,
|
|
27
|
+
message: descriptor.message,
|
|
28
|
+
fix(fixer) {
|
|
29
|
+
const replacement = descriptor.fix({ replaceText: (n, text) => {
|
|
30
|
+
return {
|
|
31
|
+
range: [n.range?.[0] ?? 0, n.range?.[1] ?? 0],
|
|
32
|
+
text,
|
|
33
|
+
node: n
|
|
34
|
+
};
|
|
35
|
+
} });
|
|
36
|
+
return fixer.replaceTextRange(replacement.range, replacement.text);
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
},
|
|
40
|
+
getFilename: () => context.filename,
|
|
41
|
+
settings,
|
|
42
|
+
capabilities: deriveCapabilities(settings)
|
|
43
|
+
};
|
|
44
|
+
const coreVisitors = core.create(coreContext);
|
|
45
|
+
const eslintVisitors = {};
|
|
46
|
+
for (const key of Object.keys(coreVisitors)) {
|
|
47
|
+
const fn = coreVisitors[key];
|
|
48
|
+
if (typeof fn !== "function") continue;
|
|
49
|
+
eslintVisitors[key] = fn;
|
|
50
|
+
}
|
|
51
|
+
return eslintVisitors;
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function deriveCapabilities(settings, namespace = "vue-doctor") {
|
|
56
|
+
if (!settings) return /* @__PURE__ */ new Set();
|
|
57
|
+
const inner = settings[namespace];
|
|
58
|
+
if (!inner) return /* @__PURE__ */ new Set();
|
|
59
|
+
const value = inner["capabilities"];
|
|
60
|
+
if (!Array.isArray(value)) return /* @__PURE__ */ new Set();
|
|
61
|
+
return new Set(value.filter((v) => typeof v === "string"));
|
|
62
|
+
}
|
|
63
|
+
//#endregion
|
|
64
|
+
//#region src/plugin.ts
|
|
65
|
+
const SEVERITY_TO_ESLINT = {
|
|
66
|
+
error: "error",
|
|
67
|
+
warn: "warn",
|
|
68
|
+
info: "warn"
|
|
69
|
+
};
|
|
70
|
+
function toRecord(rules) {
|
|
71
|
+
const out = {};
|
|
72
|
+
for (const core of rules) out[core.id] = toESLintRule(core);
|
|
73
|
+
return out;
|
|
74
|
+
}
|
|
75
|
+
function toMetaRecord(rules) {
|
|
76
|
+
const out = {};
|
|
77
|
+
for (const core of rules) out[core.id] = {
|
|
78
|
+
id: core.id,
|
|
79
|
+
severity: core.severity,
|
|
80
|
+
recommended: core.recommended,
|
|
81
|
+
category: core.category
|
|
82
|
+
};
|
|
83
|
+
return out;
|
|
84
|
+
}
|
|
85
|
+
const VUE_DOCTOR_VERSION = "1.0.0";
|
|
86
|
+
const rules = toRecord(VUE_RULES$1);
|
|
87
|
+
const ruleMeta = toMetaRecord(VUE_RULES$1);
|
|
88
|
+
function buildConfigs(self) {
|
|
89
|
+
const recommendedConfig = {
|
|
90
|
+
files: ["**/*.{js,jsx,ts,tsx,vue}"],
|
|
91
|
+
plugins: { "vue-doctor": self },
|
|
92
|
+
rules: Object.fromEntries(VUE_RULES$1.filter((r) => r.recommended).map((r) => [`vue-doctor/${r.id}`, SEVERITY_TO_ESLINT[r.severity]])),
|
|
93
|
+
settings: { "vue-doctor": { capabilities: [] } }
|
|
94
|
+
};
|
|
95
|
+
const allConfig = {
|
|
96
|
+
files: ["**/*.{js,jsx,ts,tsx,vue}"],
|
|
97
|
+
plugins: { "vue-doctor": self },
|
|
98
|
+
rules: Object.fromEntries(VUE_RULES$1.map((r) => [`vue-doctor/${r.id}`, SEVERITY_TO_ESLINT[r.severity]]))
|
|
99
|
+
};
|
|
100
|
+
return {
|
|
101
|
+
recommended: [recommendedConfig],
|
|
102
|
+
all: [allConfig]
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
const finalPlugin = {
|
|
106
|
+
meta: {
|
|
107
|
+
name: "vue-doctor",
|
|
108
|
+
version: VUE_DOCTOR_VERSION
|
|
109
|
+
},
|
|
110
|
+
rules,
|
|
111
|
+
ruleMeta,
|
|
112
|
+
configs: buildConfigs({
|
|
113
|
+
meta: {
|
|
114
|
+
name: "vue-doctor",
|
|
115
|
+
version: VUE_DOCTOR_VERSION
|
|
116
|
+
},
|
|
117
|
+
rules,
|
|
118
|
+
ruleMeta,
|
|
119
|
+
configs: {
|
|
120
|
+
recommended: [],
|
|
121
|
+
all: []
|
|
122
|
+
}
|
|
123
|
+
})
|
|
124
|
+
};
|
|
125
|
+
//#endregion
|
|
126
|
+
export { VUE_AUTO_IMPORTED, VUE_RULES, finalPlugin as default, finalPlugin as plugin, deriveCapabilities, toESLintRule };
|
|
127
|
+
|
|
128
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["VUE_RULES"],"sources":["../src/to-eslint-rule.ts","../src/plugin.ts"],"sourcesContent":["import type { Rule } from 'eslint';\nimport type { CoreRule, RuleContext, AstNode } from '@geoql/doctor-rule-core';\n\ntype ESLintSeverity = 'error' | 'warn';\n\nexport interface ESLintRule extends Rule.RuleModule<ESLintSeverity> {\n readonly id: string;\n}\n\nexport function toESLintRule(core: CoreRule): ESLintRule {\n const meta: Rule.RuleMetaData<ESLintSeverity> = {\n type: 'problem',\n schema: [],\n messages: { default: '' },\n };\n if (core.meta?.fixable) {\n meta.fixable = 'code';\n }\n\n return {\n id: core.id,\n meta,\n create(context) {\n const settings = context.settings as Record<string, unknown> | undefined;\n const coreContext: RuleContext = {\n report(descriptor) {\n const node = descriptor.node as unknown as Parameters<\n typeof context.report\n >[0]['node'];\n if (!descriptor.fix) {\n context.report({ node, message: descriptor.message });\n return;\n }\n context.report({\n node,\n message: descriptor.message,\n fix(fixer) {\n const replacement = descriptor.fix!({\n replaceText: (n: AstNode, text: string) => {\n const rangeStart =\n (n as unknown as { range?: [number, number] }).range?.[0] ??\n 0;\n const rangeEnd =\n (n as unknown as { range?: [number, number] }).range?.[1] ??\n 0;\n return { range: [rangeStart, rangeEnd], text, node: n };\n },\n });\n return fixer.replaceTextRange(\n replacement.range,\n replacement.text,\n );\n },\n });\n },\n getFilename: () => context.filename,\n settings,\n capabilities: deriveCapabilities(settings),\n };\n const coreVisitors = core.create(coreContext);\n const eslintVisitors: Record<string, (node: unknown) => void> = {};\n for (const key of Object.keys(coreVisitors)) {\n const fn = coreVisitors[key];\n if (typeof fn !== 'function') continue;\n eslintVisitors[key] = fn as (node: unknown) => void;\n }\n return eslintVisitors as unknown as ReturnType<typeof core.create>;\n },\n };\n}\n\nexport function deriveCapabilities(\n settings: Record<string, unknown> | undefined,\n namespace: string = 'vue-doctor',\n): Set<string> {\n if (!settings) return new Set();\n const inner = settings[namespace] as Record<string, unknown> | undefined;\n if (!inner) return new Set();\n const value = inner['capabilities'];\n if (!Array.isArray(value)) return new Set();\n return new Set(value.filter((v): v is string => typeof v === 'string'));\n}\n","import {\n type CoreRule,\n type Severity,\n VUE_RULES,\n} from '@geoql/doctor-rule-core';\nimport { toESLintRule } from './to-eslint-rule.js';\n\ntype ESLintSeverity = 'error' | 'warn';\n\nexport interface VueDoctorRuleModule {\n readonly id: string;\n readonly severity: Severity;\n readonly recommended: boolean;\n readonly category: string;\n}\n\nexport interface VueDoctorConfig {\n readonly files: ReadonlyArray<string>;\n readonly plugins: { readonly 'vue-doctor': VueDoctorPlugin };\n readonly rules: Readonly<Record<string, ESLintSeverity>>;\n readonly settings?: {\n readonly 'vue-doctor': { readonly capabilities: string[] };\n };\n}\n\nexport interface VueDoctorPlugin {\n readonly meta: { readonly name: 'vue-doctor'; readonly version: string };\n readonly rules: Readonly<Record<string, ReturnType<typeof toESLintRule>>>;\n readonly ruleMeta: Readonly<Record<string, VueDoctorRuleModule>>;\n readonly configs: {\n readonly recommended: ReadonlyArray<VueDoctorConfig>;\n readonly all: ReadonlyArray<VueDoctorConfig>;\n };\n}\n\nconst SEVERITY_TO_ESLINT: Readonly<Record<Severity, ESLintSeverity>> = {\n error: 'error',\n warn: 'warn',\n info: 'warn',\n};\n\nfunction toRecord(\n rules: readonly CoreRule[],\n): Record<string, ReturnType<typeof toESLintRule>> {\n const out: Record<string, ReturnType<typeof toESLintRule>> = {};\n for (const core of rules) {\n out[core.id] = toESLintRule(core);\n }\n return out;\n}\n\nfunction toMetaRecord(\n rules: readonly CoreRule[],\n): Record<string, VueDoctorRuleModule> {\n const out: Record<string, VueDoctorRuleModule> = {};\n for (const core of rules) {\n out[core.id] = {\n id: core.id,\n severity: core.severity,\n recommended: core.recommended,\n category: core.category,\n };\n }\n return out;\n}\n\nconst VUE_DOCTOR_VERSION = '1.0.0';\n\nconst rules = toRecord(VUE_RULES);\nconst ruleMeta = toMetaRecord(VUE_RULES);\n\nfunction buildConfigs(self: VueDoctorPlugin): VueDoctorPlugin['configs'] {\n const recommendedConfig: VueDoctorConfig = {\n files: ['**/*.{js,jsx,ts,tsx,vue}'],\n plugins: { 'vue-doctor': self },\n rules: Object.fromEntries(\n VUE_RULES.filter((r) => r.recommended).map((r) => [\n `vue-doctor/${r.id}`,\n SEVERITY_TO_ESLINT[r.severity],\n ]),\n ),\n settings: { 'vue-doctor': { capabilities: [] } },\n };\n const allConfig: VueDoctorConfig = {\n files: ['**/*.{js,jsx,ts,tsx,vue}'],\n plugins: { 'vue-doctor': self },\n rules: Object.fromEntries(\n VUE_RULES.map((r) => [\n `vue-doctor/${r.id}`,\n SEVERITY_TO_ESLINT[r.severity],\n ]),\n ),\n };\n return {\n recommended: [recommendedConfig],\n all: [allConfig],\n };\n}\n\nconst plugin: VueDoctorPlugin = {\n meta: { name: 'vue-doctor', version: VUE_DOCTOR_VERSION },\n rules,\n ruleMeta,\n configs: { recommended: [], all: [] },\n};\n\nconst finalPlugin: VueDoctorPlugin = {\n meta: { name: 'vue-doctor', version: VUE_DOCTOR_VERSION },\n rules,\n ruleMeta,\n configs: buildConfigs(plugin),\n};\n\nexport default finalPlugin;\nexport { finalPlugin as plugin };\n"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@geoql/eslint-plugin-vue-doctor",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"private": false,
|
|
5
|
+
"description": "ESLint flat-config plugin for Vue 3 anti-patterns and AI-slop detection. Shares the same rule cores as @geoql/oxlint-plugin-vue-doctor. TypeScript, ESM.",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"ai-slop",
|
|
8
|
+
"eslint",
|
|
9
|
+
"eslint-plugin",
|
|
10
|
+
"geoql",
|
|
11
|
+
"lint",
|
|
12
|
+
"vue",
|
|
13
|
+
"vue3"
|
|
14
|
+
],
|
|
15
|
+
"homepage": "https://github.com/geoql/doctor#readme",
|
|
16
|
+
"bugs": {
|
|
17
|
+
"url": "https://github.com/geoql/doctor/issues"
|
|
18
|
+
},
|
|
19
|
+
"license": "MIT",
|
|
20
|
+
"author": {
|
|
21
|
+
"name": "Vinayak Kulkarni",
|
|
22
|
+
"email": "inbox.vinayak@gmail.com",
|
|
23
|
+
"url": "https://vinayakkulkarni.dev"
|
|
24
|
+
},
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "git+https://github.com/geoql/doctor.git",
|
|
28
|
+
"directory": "packages/eslint-plugin-vue-doctor"
|
|
29
|
+
},
|
|
30
|
+
"files": [
|
|
31
|
+
"dist"
|
|
32
|
+
],
|
|
33
|
+
"type": "module",
|
|
34
|
+
"types": "./dist/index.d.ts",
|
|
35
|
+
"exports": {
|
|
36
|
+
".": {
|
|
37
|
+
"import": "./dist/index.js",
|
|
38
|
+
"types": "./dist/index.d.ts"
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
"publishConfig": {
|
|
42
|
+
"access": "public"
|
|
43
|
+
},
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"@geoql/doctor-rule-core": "1.0.0"
|
|
46
|
+
},
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"@types/node": "^25.9.3",
|
|
49
|
+
"@typescript-eslint/parser": "^8.61.1",
|
|
50
|
+
"eslint": "^10.5.0",
|
|
51
|
+
"typescript": "^6.0.3",
|
|
52
|
+
"vitest": "^4.1.9",
|
|
53
|
+
"@geoql/doctor-core": "1.1.1"
|
|
54
|
+
},
|
|
55
|
+
"peerDependencies": {
|
|
56
|
+
"eslint": ">=9.0.0"
|
|
57
|
+
},
|
|
58
|
+
"engines": {
|
|
59
|
+
"node": ">=24"
|
|
60
|
+
},
|
|
61
|
+
"scripts": {
|
|
62
|
+
"lint": "vp lint src",
|
|
63
|
+
"lint:fix": "vp lint src --fix",
|
|
64
|
+
"format": "vp fmt",
|
|
65
|
+
"format:check": "vp fmt --check",
|
|
66
|
+
"build": "vp pack",
|
|
67
|
+
"test": "vitest run"
|
|
68
|
+
}
|
|
69
|
+
}
|