@useinsider/eslint-config 3.0.2-beta.1 → 4.0.0-beta.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 +285 -64
- package/dist/builders/configFiles.d.ts +13 -0
- package/dist/builders/oxlint.d.ts +51 -0
- package/dist/builders/oxlintOwnership.d.ts +43 -0
- package/dist/cli.cjs +584 -27
- package/dist/cli.cjs.map +1 -1
- package/dist/configs/dependencies.d.ts +3 -0
- package/dist/{javascript-VBXqjVi8.cjs → javascript-DH8-N38w.cjs} +5 -5
- package/dist/{javascript-VBXqjVi8.cjs.map → javascript-DH8-N38w.cjs.map} +1 -1
- package/dist/{javascript-dom-5jRL_yKP.cjs → javascript-dom-CvtQ6_9W.cjs} +4 -4
- package/dist/{javascript-dom-5jRL_yKP.cjs.map → javascript-dom-CvtQ6_9W.cjs.map} +1 -1
- package/dist/{javascript-node-C1AU_4X2.cjs → javascript-node-BNsy3loY.cjs} +4 -4
- package/dist/{javascript-node-C1AU_4X2.cjs.map → javascript-node-BNsy3loY.cjs.map} +1 -1
- package/dist/{jest-CHzjzBtf.cjs → jest-4Es9Ggaa.cjs} +3 -3
- package/dist/{jest-CHzjzBtf.cjs.map → jest-4Es9Ggaa.cjs.map} +1 -1
- package/dist/main.cjs +452 -73
- package/dist/main.cjs.map +1 -1
- package/dist/main.d.ts +9 -2
- package/dist/main.js +435 -56
- package/dist/main.js.map +1 -1
- package/dist/oxlintOwnership-7hpdB3d1.cjs +199 -0
- package/dist/oxlintOwnership-7hpdB3d1.cjs.map +1 -0
- package/dist/oxlintOwnership-Cx0hgA_J.js +127 -0
- package/dist/oxlintOwnership-Cx0hgA_J.js.map +1 -0
- package/dist/removePluginsFromConfigs-D0oSUj2C.cjs.map +1 -1
- package/dist/removePluginsFromConfigs-DzqX2Ju2.js.map +1 -1
- package/dist/{stylistic-Dio0AM2E.cjs → stylistic-CoP3MT1Y.cjs} +4 -4
- package/dist/{stylistic-Dio0AM2E.cjs.map → stylistic-CoP3MT1Y.cjs.map} +1 -1
- package/dist/{typescript-C1icmOxY.cjs → typescript-D3VeLnpn.cjs} +7 -7
- package/dist/{typescript-C1icmOxY.cjs.map → typescript-D3VeLnpn.cjs.map} +1 -1
- package/dist/{typescript-dom-RUJn2WCZ.cjs → typescript-dom-iB_xBTAD.cjs} +4 -4
- package/dist/{typescript-dom-RUJn2WCZ.cjs.map → typescript-dom-iB_xBTAD.cjs.map} +1 -1
- package/dist/{typescript-node-CBEzcc56.cjs → typescript-node-Cq6qhj53.cjs} +4 -4
- package/dist/{typescript-node-CBEzcc56.cjs.map → typescript-node-Cq6qhj53.cjs.map} +1 -1
- package/dist/utils/ensureConfigStructure.d.ts +9 -4
- package/dist/utils/ensureOxlintConfig.d.ts +9 -0
- package/dist/utils/silenceRules.d.ts +9 -0
- package/dist/{vitest-BomI8gtu.cjs → vitest-BlGQswK2.cjs} +3 -3
- package/dist/{vitest-BomI8gtu.cjs.map → vitest-BlGQswK2.cjs.map} +1 -1
- package/dist/{vue2-azKwRgaJ.cjs → vue2-Da1i_oVn.cjs} +8 -8
- package/dist/{vue2-azKwRgaJ.cjs.map → vue2-Da1i_oVn.cjs.map} +1 -1
- package/dist/{vue2-options-api-ma3J-bvM.cjs → vue2-options-api-BSdrUm8H.cjs} +8 -8
- package/dist/{vue2-options-api-ma3J-bvM.cjs.map → vue2-options-api-BSdrUm8H.cjs.map} +1 -1
- package/dist/{vue2-typescript-CZSHzp7I.cjs → vue2-typescript-dXLRSGNP.cjs} +10 -10
- package/dist/{vue2-typescript-CZSHzp7I.cjs.map → vue2-typescript-dXLRSGNP.cjs.map} +1 -1
- package/dist/{vue2-typescript-options-api-B8OzZlje.cjs → vue2-typescript-options-api-LM7U5dWq.cjs} +10 -10
- package/dist/{vue2-typescript-options-api-B8OzZlje.cjs.map → vue2-typescript-options-api-LM7U5dWq.cjs.map} +1 -1
- package/dist/{vue3-Df5UQ1Ys.cjs → vue3-621EM2Ii.cjs} +8 -8
- package/dist/{vue3-Df5UQ1Ys.cjs.map → vue3-621EM2Ii.cjs.map} +1 -1
- package/dist/{vue3-options-api-Bx7yYHza.cjs → vue3-options-api-CC9_fAiq.cjs} +8 -8
- package/dist/{vue3-options-api-Bx7yYHza.cjs.map → vue3-options-api-CC9_fAiq.cjs.map} +1 -1
- package/dist/{vue3-typescript-C0O1JZlk.cjs → vue3-typescript-DONe-IKz.cjs} +10 -10
- package/dist/{vue3-typescript-C0O1JZlk.cjs.map → vue3-typescript-DONe-IKz.cjs.map} +1 -1
- package/dist/{vue3-typescript-options-api-cPal4O-K.cjs → vue3-typescript-options-api-D4pqpDFs.cjs} +10 -10
- package/dist/{vue3-typescript-options-api-cPal4O-K.cjs.map → vue3-typescript-options-api-D4pqpDFs.cjs.map} +1 -1
- package/package.json +8 -5
- package/dist/rolldown-runtime-VH7oDXx4.cjs +0 -28
package/dist/main.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import { a as isVueUnsafeRule, i as isRuleDisabled, n as VUE_LIKE_GLOBS, o as toOxlintPluginName, r as isOxlintOwned, s as toOxlintRuleName, t as OXLINT_CATEGORIES } from "./oxlintOwnership-Cx0hgA_J.js";
|
|
1
2
|
import { t as merge } from "./merge-R5ZHqMsV.js";
|
|
2
3
|
import { t as mergeAll } from "./mergeAllConfig-B2rSXCdn.js";
|
|
3
4
|
import { defineConfig } from "eslint/config";
|
|
4
5
|
import globals from "globals";
|
|
5
6
|
import { existsSync, readFileSync, realpathSync } from "node:fs";
|
|
6
7
|
import { createRequire } from "node:module";
|
|
7
|
-
import { dirname, resolve } from "node:path";
|
|
8
|
+
import { dirname, join, resolve } from "node:path";
|
|
8
9
|
import { fileURLToPath } from "node:url";
|
|
9
10
|
import { AST_NODE_TYPES } from "@typescript-eslint/types";
|
|
10
11
|
import { installPackage } from "@antfu/install-pkg";
|
|
@@ -29,6 +30,33 @@ var configFileRules = {
|
|
|
29
30
|
"import-x/no-extraneous-dependencies": "off",
|
|
30
31
|
"import-x/prefer-default-export": "off"
|
|
31
32
|
};
|
|
33
|
+
var LINT_TOPOLOGY_NAME = "insider/lint-topology";
|
|
34
|
+
/**
|
|
35
|
+
* The three files `useInsider()` requires a consumer to own. They are always linted with
|
|
36
|
+
* {@link buildLintTopologyBlocks}, independently of the `configFiles` option.
|
|
37
|
+
*/
|
|
38
|
+
var LINT_TOPOLOGY_GLOBS = [
|
|
39
|
+
"**/insider.lint.{ts,mts,cts,js,mjs,cjs}",
|
|
40
|
+
"**/eslint.config.{ts,mts,cts,js,mjs,cjs}",
|
|
41
|
+
"**/oxlint.config.{ts,mts,cts,js,mjs,cjs}"
|
|
42
|
+
];
|
|
43
|
+
var lintTopologyRules = {
|
|
44
|
+
...configFileRules,
|
|
45
|
+
"import-x/extensions": "off"
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Relaxations the mandated three-file layout needs in order to lint clean. Emitted unconditionally
|
|
49
|
+
* because the layout exists whether or not the consumer passes `configFiles`.
|
|
50
|
+
* @example
|
|
51
|
+
* buildLintTopologyBlocks()[0].rules['import-x/extensions']; // 'off'
|
|
52
|
+
*/
|
|
53
|
+
function buildLintTopologyBlocks() {
|
|
54
|
+
return [{
|
|
55
|
+
name: LINT_TOPOLOGY_NAME,
|
|
56
|
+
files: [...LINT_TOPOLOGY_GLOBS],
|
|
57
|
+
rules: { ...lintTopologyRules }
|
|
58
|
+
}];
|
|
59
|
+
}
|
|
32
60
|
function mergeGlobs(userGlobs) {
|
|
33
61
|
const seen = /* @__PURE__ */ new Set();
|
|
34
62
|
const merged = [];
|
|
@@ -58,17 +86,148 @@ function buildConfigFilesBlocks(value) {
|
|
|
58
86
|
function buildJqueryBlocks(entries) {
|
|
59
87
|
if (!entries || entries.length === 0) return [];
|
|
60
88
|
return entries.map((entry) => ({
|
|
61
|
-
files: entry.files,
|
|
89
|
+
files: [...entry.files],
|
|
62
90
|
languageOptions: { globals: { ...globals.jquery } }
|
|
63
91
|
}));
|
|
64
92
|
}
|
|
65
93
|
//#endregion
|
|
94
|
+
//#region src/builders/oxlint.ts
|
|
95
|
+
var OXLINT_SUPPRESSION_NAME = "insider/oxlint-suppression";
|
|
96
|
+
var OXLINT_SFC_EXCEPTION_NAME = "insider/oxlint-suppression-sfc-exception";
|
|
97
|
+
var UNUSED_DIRECTIVE_BLOCK_NAME = "insider/unused-disable-directives";
|
|
98
|
+
var UNUSED_DIRECTIVE_SEVERITY = "warn";
|
|
99
|
+
var OXLINT_DIRECTIVE_OPTIONS = {
|
|
100
|
+
respectEslintDisableDirectives: false,
|
|
101
|
+
reportUnusedDisableDirectives: UNUSED_DIRECTIVE_SEVERITY
|
|
102
|
+
};
|
|
103
|
+
/**
|
|
104
|
+
* The always-on ESLint block that makes a stale `eslint-disable` visible. ESLint 9 defaults this to
|
|
105
|
+
* `warn`, but the split relies on it, so it is pinned rather than inherited.
|
|
106
|
+
* @example
|
|
107
|
+
* buildUnusedDirectiveBlocks()[0].linterOptions; // { reportUnusedDisableDirectives: 'warn' }
|
|
108
|
+
*/
|
|
109
|
+
function buildUnusedDirectiveBlocks() {
|
|
110
|
+
return [{
|
|
111
|
+
name: UNUSED_DIRECTIVE_BLOCK_NAME,
|
|
112
|
+
linterOptions: { reportUnusedDisableDirectives: UNUSED_DIRECTIVE_SEVERITY }
|
|
113
|
+
}];
|
|
114
|
+
}
|
|
115
|
+
function ownedRuleNames(rules) {
|
|
116
|
+
return Object.keys(rules).filter((name) => isOxlintOwned(name) && !isRuleDisabled(rules[name]));
|
|
117
|
+
}
|
|
118
|
+
function translatableRuleNames(rules) {
|
|
119
|
+
return Object.keys(rules).filter(isOxlintOwned);
|
|
120
|
+
}
|
|
121
|
+
function toOffRecord(ruleNames) {
|
|
122
|
+
return Object.fromEntries(ruleNames.map((name) => [name, "off"]));
|
|
123
|
+
}
|
|
124
|
+
function suppressionFor(block) {
|
|
125
|
+
if (!block.rules) return [];
|
|
126
|
+
const owned = ownedRuleNames(block.rules);
|
|
127
|
+
if (owned.length === 0) return [];
|
|
128
|
+
const files = block.files ? { files: [...block.files] } : {};
|
|
129
|
+
const blockIgnores = block.ignores ? [...block.ignores] : [];
|
|
130
|
+
const vueSafe = owned.filter((name) => !isVueUnsafeRule(name));
|
|
131
|
+
const vueUnsafe = owned.filter((name) => isVueUnsafeRule(name));
|
|
132
|
+
const suppressions = [];
|
|
133
|
+
if (vueSafe.length > 0) suppressions.push({
|
|
134
|
+
name: OXLINT_SUPPRESSION_NAME,
|
|
135
|
+
...files,
|
|
136
|
+
...blockIgnores.length > 0 ? { ignores: blockIgnores } : {},
|
|
137
|
+
rules: toOffRecord(vueSafe)
|
|
138
|
+
});
|
|
139
|
+
if (vueUnsafe.length > 0) suppressions.push({
|
|
140
|
+
name: OXLINT_SFC_EXCEPTION_NAME,
|
|
141
|
+
...files,
|
|
142
|
+
ignores: [...blockIgnores, ...VUE_LIKE_GLOBS],
|
|
143
|
+
rules: toOffRecord(vueUnsafe)
|
|
144
|
+
});
|
|
145
|
+
return suppressions;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* ESLint blocks that turn off every rule the emitted oxlint config takes over. Rules oxlint cannot
|
|
149
|
+
* check inside an SFC are suppressed everywhere except `.vue`/`.svelte`/`.astro`, so a Vue consumer
|
|
150
|
+
* keeps them.
|
|
151
|
+
* @example
|
|
152
|
+
* buildOxlintSuppressionBlocks([{ files: ['src/**\/*.ts'], rules: { 'no-var': 'error' } }]);
|
|
153
|
+
* // [{ files: ['src/**\/*.ts'], rules: { 'no-var': 'off' } }]
|
|
154
|
+
*/
|
|
155
|
+
function buildOxlintSuppressionBlocks(blocks) {
|
|
156
|
+
return blocks.flatMap(suppressionFor);
|
|
157
|
+
}
|
|
158
|
+
function translateRules(rules, plugins) {
|
|
159
|
+
return translatableRuleNames(rules).reduce((accumulator, name) => {
|
|
160
|
+
plugins.add(toOxlintPluginName(name));
|
|
161
|
+
accumulator[toOxlintRuleName(name)] = rules[name];
|
|
162
|
+
return accumulator;
|
|
163
|
+
}, {});
|
|
164
|
+
}
|
|
165
|
+
function anchorOxlintGlob(glob) {
|
|
166
|
+
return glob.startsWith("**") || glob.startsWith("./") || glob.startsWith("/") ? glob : `./${glob}`;
|
|
167
|
+
}
|
|
168
|
+
function anchorGlobs(globs) {
|
|
169
|
+
return globs.map(anchorOxlintGlob);
|
|
170
|
+
}
|
|
171
|
+
function anchorOxlintIgnorePattern(pattern) {
|
|
172
|
+
const negated = pattern.startsWith("!");
|
|
173
|
+
const body = negated ? pattern.slice(1) : pattern;
|
|
174
|
+
const anchored = body.startsWith("/") || body.startsWith("**") ? body : `/${body}`;
|
|
175
|
+
return negated ? `!${anchored}` : anchored;
|
|
176
|
+
}
|
|
177
|
+
function overrideFor(block, plugins) {
|
|
178
|
+
if (!block.files || !block.rules) return [];
|
|
179
|
+
const translated = translateRules(block.rules, plugins);
|
|
180
|
+
if (Object.keys(translated).length === 0) return [];
|
|
181
|
+
return [{
|
|
182
|
+
files: anchorGlobs(block.files),
|
|
183
|
+
...block.ignores && block.ignores.length > 0 ? { excludeFiles: anchorGlobs(block.ignores) } : {},
|
|
184
|
+
rules: translated
|
|
185
|
+
}];
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* The oxlint half of the split, derived from the same emitted ESLint blocks the suppression layer
|
|
189
|
+
* reads. Every oxlint category is pinned off so the config enables exactly the preset's own rules
|
|
190
|
+
* and nothing oxlint would otherwise turn on by default.
|
|
191
|
+
* @example
|
|
192
|
+
* buildOxlintConfig([{ files: ['src/**\/*.ts'], rules: { 'no-var': 'error' } }], ['dist']);
|
|
193
|
+
* // { plugins: ['eslint'], categories: { correctness: 'off', ... }, ignorePatterns: ['/dist'], ... }
|
|
194
|
+
*/
|
|
195
|
+
function buildOxlintConfig(blocks, ignores) {
|
|
196
|
+
const plugins = /* @__PURE__ */ new Set(["eslint"]);
|
|
197
|
+
const overrides = blocks.flatMap((block) => overrideFor(block, plugins));
|
|
198
|
+
const globalRules = blocks.filter((block) => !block.files && block.rules).reduce((accumulator, block) => ({
|
|
199
|
+
...accumulator,
|
|
200
|
+
...translateRules(block.rules, plugins)
|
|
201
|
+
}), {});
|
|
202
|
+
return {
|
|
203
|
+
plugins: [...plugins].sort((left, right) => left.localeCompare(right)),
|
|
204
|
+
categories: Object.fromEntries(OXLINT_CATEGORIES.map((name) => [name, "off"])),
|
|
205
|
+
...ignores && ignores.length > 0 ? { ignorePatterns: ignores.map(anchorOxlintIgnorePattern) } : {},
|
|
206
|
+
options: { ...OXLINT_DIRECTIVE_OPTIONS },
|
|
207
|
+
rules: globalRules,
|
|
208
|
+
overrides
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
//#endregion
|
|
66
212
|
//#region src/utils/ensureConfigStructure.ts
|
|
67
|
-
var
|
|
68
|
-
var OPT_OUT_ENV = "INSIDER_SKIP_CONFIG_VALIDATION";
|
|
213
|
+
var ANCHOR_FILE_REGEX = /(?:insider\.lint|eslint\.config)\.[mc]?[jt]s(?:$|\?)/;
|
|
214
|
+
var OPT_OUT_ENV$1 = "INSIDER_SKIP_CONFIG_VALIDATION";
|
|
69
215
|
var FILE_URL_PREFIX = "file://";
|
|
70
216
|
var TARGET_CALLEE_NAME = "useInsider";
|
|
217
|
+
var ESLINT_RENDERER_NAME = "useInsiderESLint";
|
|
218
|
+
var OXC_RENDERER_NAME = "useInsiderOXC";
|
|
71
219
|
var INSIDER_IMPORT_SOURCE = "@useinsider/eslint-config";
|
|
220
|
+
var MODULE_EXTENSIONS = [
|
|
221
|
+
"ts",
|
|
222
|
+
"mts",
|
|
223
|
+
"cts",
|
|
224
|
+
"js",
|
|
225
|
+
"mjs",
|
|
226
|
+
"cjs"
|
|
227
|
+
];
|
|
228
|
+
var RENDERER_EXPORT = `export const ${`{ ${ESLINT_RENDERER_NAME}, ${OXC_RENDERER_NAME} }`} = ${TARGET_CALLEE_NAME}({ ... })`;
|
|
229
|
+
var LINT_MODULE_FILENAMES = MODULE_EXTENSIONS.map((ext) => `insider.lint.${ext}`);
|
|
230
|
+
var ESLINT_CONFIG_FILENAMES = MODULE_EXTENSIONS.map((ext) => `eslint.config.${ext}`);
|
|
72
231
|
var bypassWarnEmitted = false;
|
|
73
232
|
function computeSelfModulePath() {
|
|
74
233
|
const raw = fileURLToPath(import.meta.url);
|
|
@@ -98,24 +257,24 @@ function locOf(node) {
|
|
|
98
257
|
column: node.loc.start.column
|
|
99
258
|
};
|
|
100
259
|
}
|
|
101
|
-
function validateCallExpression(callExpr) {
|
|
260
|
+
function validateCallExpression(callExpr, expectedCallee) {
|
|
102
261
|
const { callee } = callExpr;
|
|
103
|
-
if (callee.type !== AST_NODE_TYPES.Identifier || callee.name !==
|
|
262
|
+
if (callee.type !== AST_NODE_TYPES.Identifier || callee.name !== expectedCallee) return [{
|
|
104
263
|
...locOf(callExpr),
|
|
105
|
-
reason:
|
|
264
|
+
reason: `Default export must call \`${expectedCallee}(...)\` directly.`
|
|
106
265
|
}];
|
|
107
266
|
return [];
|
|
108
267
|
}
|
|
109
|
-
function validateExportedCall(callee, fallbackLoc) {
|
|
268
|
+
function validateExportedCall(callee, fallbackLoc, expectedCallee) {
|
|
110
269
|
let target = callee;
|
|
111
270
|
if (target.type === AST_NODE_TYPES.AwaitExpression) target = target.argument;
|
|
112
|
-
if (target.type === AST_NODE_TYPES.CallExpression) return validateCallExpression(target);
|
|
271
|
+
if (target.type === AST_NODE_TYPES.CallExpression) return validateCallExpression(target, expectedCallee);
|
|
113
272
|
if (target.type === AST_NODE_TYPES.ArrayExpression) return [{
|
|
114
273
|
...locOf(target),
|
|
115
|
-
reason:
|
|
274
|
+
reason: `Default export must not wrap \`${expectedCallee}(...)\` in an array.`
|
|
116
275
|
}];
|
|
117
276
|
if (target.type === AST_NODE_TYPES.LogicalExpression || target.type === AST_NODE_TYPES.ConditionalExpression) {
|
|
118
|
-
const reason = [
|
|
277
|
+
const reason = [`Default export must not gate \`${expectedCallee}(...)\` behind a logical/conditional expression.`, "Use the typed options object instead."].join(" ");
|
|
119
278
|
return [{
|
|
120
279
|
...locOf(target),
|
|
121
280
|
reason
|
|
@@ -123,7 +282,7 @@ function validateExportedCall(callee, fallbackLoc) {
|
|
|
123
282
|
}
|
|
124
283
|
return [{
|
|
125
284
|
...fallbackLoc,
|
|
126
|
-
reason:
|
|
285
|
+
reason: `Default export must be a direct call to \`${expectedCallee}(...)\`.`
|
|
127
286
|
}];
|
|
128
287
|
}
|
|
129
288
|
function collectInsiderBindings(node, bindings, isInsiderSource) {
|
|
@@ -144,7 +303,7 @@ function classifyExpressionStatement(node, insiderBindings) {
|
|
|
144
303
|
}
|
|
145
304
|
};
|
|
146
305
|
}
|
|
147
|
-
function classifyStatement(node, exportSeen, insiderBindings) {
|
|
306
|
+
function classifyStatement(node, exportSeen, insiderBindings, expectedCallee) {
|
|
148
307
|
if (node.type === AST_NODE_TYPES.ImportDeclaration || node.type === AST_NODE_TYPES.VariableDeclaration) return { type: "ignore" };
|
|
149
308
|
if (node.type === AST_NODE_TYPES.ExpressionStatement) return classifyExpressionStatement(node, insiderBindings);
|
|
150
309
|
if (node.type === AST_NODE_TYPES.ExportDefaultDeclaration) {
|
|
@@ -158,13 +317,13 @@ function classifyStatement(node, exportSeen, insiderBindings) {
|
|
|
158
317
|
const declaration = node.declaration;
|
|
159
318
|
return {
|
|
160
319
|
type: "export",
|
|
161
|
-
violations: validateExportedCall(declaration, locOf(node))
|
|
320
|
+
violations: validateExportedCall(declaration, locOf(node), expectedCallee)
|
|
162
321
|
};
|
|
163
322
|
}
|
|
164
323
|
const reason = [
|
|
165
324
|
`Disallowed top-level statement \`${node.type}\`.`,
|
|
166
325
|
"Only imports, variable declarations, helper calls from `@useinsider/eslint-config`,",
|
|
167
|
-
|
|
326
|
+
`and one \`export default ${expectedCallee}()\` are allowed.`
|
|
168
327
|
].join(" ");
|
|
169
328
|
return {
|
|
170
329
|
type: "disallowed",
|
|
@@ -179,18 +338,112 @@ function validateProgramStructure(program, configPath = "", options = {}) {
|
|
|
179
338
|
const insiderBindings = /* @__PURE__ */ new Set();
|
|
180
339
|
const resolver = options.isInsiderImportSource ?? defaultIsInsiderImportSource;
|
|
181
340
|
const isInsiderSource = (source) => resolver(source, configPath);
|
|
341
|
+
const expectedCallee = options.expectedCallee ?? ESLINT_RENDERER_NAME;
|
|
182
342
|
let exportSeen = false;
|
|
183
343
|
program.body.forEach((node) => {
|
|
184
344
|
if (node.type === AST_NODE_TYPES.ImportDeclaration) collectInsiderBindings(node, insiderBindings, isInsiderSource);
|
|
185
|
-
const result = classifyStatement(node, exportSeen, insiderBindings);
|
|
345
|
+
const result = classifyStatement(node, exportSeen, insiderBindings, expectedCallee);
|
|
186
346
|
if (result.type === "ignore") return;
|
|
187
347
|
if (result.type === "export") {
|
|
188
348
|
exportSeen = true;
|
|
189
349
|
violations.push(...result.violations);
|
|
190
350
|
return;
|
|
191
351
|
}
|
|
192
|
-
|
|
193
|
-
|
|
352
|
+
violations.push(result.violation);
|
|
353
|
+
});
|
|
354
|
+
if (!exportSeen) violations.push({
|
|
355
|
+
line: 1,
|
|
356
|
+
column: 0,
|
|
357
|
+
reason: `Missing \`export default ${options.expectedCallee ?? ESLINT_RENDERER_NAME}()\`.`
|
|
358
|
+
});
|
|
359
|
+
return violations;
|
|
360
|
+
}
|
|
361
|
+
function validateRendererPattern(pattern) {
|
|
362
|
+
const bound = /* @__PURE__ */ new Set();
|
|
363
|
+
const violations = [];
|
|
364
|
+
pattern.properties.forEach((property) => {
|
|
365
|
+
if (property.type !== AST_NODE_TYPES.Property || property.computed || !property.shorthand) {
|
|
366
|
+
violations.push({
|
|
367
|
+
...locOf(property),
|
|
368
|
+
reason: `Destructure \`${ESLINT_RENDERER_NAME}\` and \`${OXC_RENDERER_NAME}\` by name, without renaming or spreading.`
|
|
369
|
+
});
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
bound.add(property.key.name);
|
|
373
|
+
});
|
|
374
|
+
[ESLINT_RENDERER_NAME, OXC_RENDERER_NAME].forEach((name) => {
|
|
375
|
+
if (!bound.has(name)) violations.push({
|
|
376
|
+
...locOf(pattern),
|
|
377
|
+
reason: `Missing \`${name}\` in the destructured \`${TARGET_CALLEE_NAME}(...)\` result.`
|
|
378
|
+
});
|
|
379
|
+
});
|
|
380
|
+
return violations;
|
|
381
|
+
}
|
|
382
|
+
function validateRendererExport(node) {
|
|
383
|
+
const { declaration } = node;
|
|
384
|
+
if (!declaration || declaration.type !== AST_NODE_TYPES.VariableDeclaration || declaration.kind !== "const") return [{
|
|
385
|
+
...locOf(node),
|
|
386
|
+
reason: `Renderer export must be \`${RENDERER_EXPORT};\`.`
|
|
387
|
+
}];
|
|
388
|
+
if (declaration.declarations.length !== 1) return [{
|
|
389
|
+
...locOf(declaration),
|
|
390
|
+
reason: "Renderer export must declare exactly one binding."
|
|
391
|
+
}];
|
|
392
|
+
const [declarator] = declaration.declarations;
|
|
393
|
+
if (declarator.id.type !== AST_NODE_TYPES.ObjectPattern) return [{
|
|
394
|
+
...locOf(declarator.id),
|
|
395
|
+
reason: `Renderer export must destructure \`${ESLINT_RENDERER_NAME}\` and \`${OXC_RENDERER_NAME}\`.`
|
|
396
|
+
}];
|
|
397
|
+
const patternViolations = validateRendererPattern(declarator.id);
|
|
398
|
+
const { init } = declarator;
|
|
399
|
+
if (!init) return [...patternViolations, {
|
|
400
|
+
...locOf(declarator),
|
|
401
|
+
reason: `Renderer export must be initialized by a direct \`${TARGET_CALLEE_NAME}(...)\` call.`
|
|
402
|
+
}];
|
|
403
|
+
return [...patternViolations, ...validateExportedCall(init, locOf(declarator), TARGET_CALLEE_NAME)];
|
|
404
|
+
}
|
|
405
|
+
function classifyLintModuleStatement(node, exportSeen, insiderBindings) {
|
|
406
|
+
if (node.type === AST_NODE_TYPES.ImportDeclaration || node.type === AST_NODE_TYPES.VariableDeclaration) return { type: "ignore" };
|
|
407
|
+
if (node.type === AST_NODE_TYPES.ExpressionStatement) return classifyExpressionStatement(node, insiderBindings);
|
|
408
|
+
if (node.type === AST_NODE_TYPES.ExportNamedDeclaration) {
|
|
409
|
+
if (exportSeen) return {
|
|
410
|
+
type: "duplicateExport",
|
|
411
|
+
violation: {
|
|
412
|
+
...locOf(node),
|
|
413
|
+
reason: "Only one export is allowed."
|
|
414
|
+
}
|
|
415
|
+
};
|
|
416
|
+
return {
|
|
417
|
+
type: "export",
|
|
418
|
+
violations: validateRendererExport(node)
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
const reason = [
|
|
422
|
+
`Disallowed top-level statement \`${node.type}\`.`,
|
|
423
|
+
"Only imports, variable declarations, helper calls from `@useinsider/eslint-config`,",
|
|
424
|
+
`and one \`${RENDERER_EXPORT}\` are allowed.`
|
|
425
|
+
].join(" ");
|
|
426
|
+
return {
|
|
427
|
+
type: "disallowed",
|
|
428
|
+
violation: {
|
|
429
|
+
...locOf(node),
|
|
430
|
+
reason
|
|
431
|
+
}
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
function validateLintModuleStructure(program, configPath = "", options = {}) {
|
|
435
|
+
const violations = [];
|
|
436
|
+
const insiderBindings = /* @__PURE__ */ new Set();
|
|
437
|
+
const resolver = options.isInsiderImportSource ?? defaultIsInsiderImportSource;
|
|
438
|
+
const isInsiderSource = (source) => resolver(source, configPath);
|
|
439
|
+
let exportSeen = false;
|
|
440
|
+
program.body.forEach((node) => {
|
|
441
|
+
if (node.type === AST_NODE_TYPES.ImportDeclaration) collectInsiderBindings(node, insiderBindings, isInsiderSource);
|
|
442
|
+
const result = classifyLintModuleStatement(node, exportSeen, insiderBindings);
|
|
443
|
+
if (result.type === "ignore") return;
|
|
444
|
+
if (result.type === "export") {
|
|
445
|
+
exportSeen = true;
|
|
446
|
+
violations.push(...result.violations);
|
|
194
447
|
return;
|
|
195
448
|
}
|
|
196
449
|
violations.push(result.violation);
|
|
@@ -198,7 +451,7 @@ function validateProgramStructure(program, configPath = "", options = {}) {
|
|
|
198
451
|
if (!exportSeen) violations.push({
|
|
199
452
|
line: 1,
|
|
200
453
|
column: 0,
|
|
201
|
-
reason:
|
|
454
|
+
reason: `Missing \`${RENDERER_EXPORT};\`.`
|
|
202
455
|
});
|
|
203
456
|
return violations;
|
|
204
457
|
}
|
|
@@ -222,7 +475,7 @@ function extractMatchesFromStack(frames) {
|
|
|
222
475
|
const matches = /* @__PURE__ */ new Set();
|
|
223
476
|
frames.forEach((frame) => {
|
|
224
477
|
const name = normalizeFrameFilename(frame.getFileName());
|
|
225
|
-
if (name &&
|
|
478
|
+
if (name && ANCHOR_FILE_REGEX.test(name)) matches.add(name);
|
|
226
479
|
});
|
|
227
480
|
return Array.from(matches);
|
|
228
481
|
}
|
|
@@ -235,13 +488,16 @@ function argvCandidateAt(argv, index) {
|
|
|
235
488
|
function extractConfigFromArgv(argv) {
|
|
236
489
|
for (let i = 0; i < argv.length; i += 1) {
|
|
237
490
|
const candidate = argvCandidateAt(argv, i);
|
|
238
|
-
if (candidate &&
|
|
491
|
+
if (candidate && ANCHOR_FILE_REGEX.test(candidate)) return candidate;
|
|
239
492
|
}
|
|
240
493
|
return null;
|
|
241
494
|
}
|
|
495
|
+
var LINT_MODULE_REGEX = /insider\.lint\.[mc]?[jt]s(?:$|\?)/;
|
|
242
496
|
function getConsumerConfigPath(frames = readStackFrames(), argv = process.argv) {
|
|
243
497
|
const stackMatches = extractMatchesFromStack(frames);
|
|
244
498
|
if (stackMatches.length === 1) return stackMatches[0];
|
|
499
|
+
const lintModules = stackMatches.filter((match) => LINT_MODULE_REGEX.test(match));
|
|
500
|
+
if (lintModules.length === 1) return lintModules[0];
|
|
245
501
|
const fromArgv = extractConfigFromArgv(argv);
|
|
246
502
|
if (fromArgv) return fromArgv;
|
|
247
503
|
return null;
|
|
@@ -251,27 +507,46 @@ function captureConsumerConfigDir(configPath) {
|
|
|
251
507
|
consumerConfigDir = configPath === null ? null : dirname(resolve(configPath));
|
|
252
508
|
}
|
|
253
509
|
/**
|
|
254
|
-
* Directory holding the consumer's `
|
|
255
|
-
* This is the anchor `tsconfigPaths` entries are written against
|
|
256
|
-
*
|
|
510
|
+
* Directory holding the consumer's `insider.lint.*` module and its sibling linter configs, captured
|
|
511
|
+
* by {@link ensureConfigStructure}. This is the anchor `tsconfigPaths` entries are written against,
|
|
512
|
+
* and where {@link import('./ensureOxlintConfig').ensureOxlintConfig} looks for the oxlint config;
|
|
513
|
+
* it falls back to `process.cwd()` when the module could not be located.
|
|
257
514
|
* @example
|
|
258
|
-
* // consumer
|
|
515
|
+
* // consumer module at /repo/insider.lint.ts, `eslint` launched from /repo/app
|
|
259
516
|
* getConsumerConfigDir(); // '/repo'
|
|
260
517
|
*/
|
|
261
518
|
function getConsumerConfigDir() {
|
|
262
519
|
return consumerConfigDir ?? process.cwd();
|
|
263
520
|
}
|
|
521
|
+
var EXPECTED_LAYOUT = [
|
|
522
|
+
"Expected layout (three sibling files):",
|
|
523
|
+
"",
|
|
524
|
+
" // insider.lint.ts",
|
|
525
|
+
" import { useInsider } from '@useinsider/eslint-config';",
|
|
526
|
+
"",
|
|
527
|
+
` ${RENDERER_EXPORT};`,
|
|
528
|
+
"",
|
|
529
|
+
" // eslint.config.ts",
|
|
530
|
+
` import { ${ESLINT_RENDERER_NAME} } from './insider.lint.ts';`,
|
|
531
|
+
"",
|
|
532
|
+
` export default ${ESLINT_RENDERER_NAME}();`,
|
|
533
|
+
"",
|
|
534
|
+
" // oxlint.config.ts",
|
|
535
|
+
` import { ${OXC_RENDERER_NAME} } from './insider.lint.ts';`,
|
|
536
|
+
"",
|
|
537
|
+
` export default await ${OXC_RENDERER_NAME}();`
|
|
538
|
+
].join("\n");
|
|
264
539
|
function formatReport(configPath, violations) {
|
|
265
540
|
const header = ["@useinsider/eslint-config: protected configuration structure violated in:", ` ${configPath}`].join("\n");
|
|
266
541
|
const lines = violations.map((violation) => ` - [${violation.line}:${violation.column}] ${violation.reason}`);
|
|
267
542
|
const footer = [
|
|
268
543
|
"",
|
|
269
|
-
"
|
|
270
|
-
"
|
|
271
|
-
" - const/let/var declarations",
|
|
272
|
-
" - exactly one `export default useInsider({ ... })`",
|
|
544
|
+
"Alongside the export, only import statements, const/let/var declarations and helper calls",
|
|
545
|
+
"imported from `@useinsider/eslint-config` are allowed.",
|
|
273
546
|
"",
|
|
274
|
-
|
|
547
|
+
EXPECTED_LAYOUT,
|
|
548
|
+
"",
|
|
549
|
+
`Emergency bypass: set ${OPT_OUT_ENV$1}=true (do not commit).`
|
|
275
550
|
].join("\n");
|
|
276
551
|
return `${header}\n${lines.join("\n")}\n${footer}`;
|
|
277
552
|
}
|
|
@@ -312,16 +587,50 @@ function parseConsumerSource(configPath, source) {
|
|
|
312
587
|
return fail(`@useinsider/eslint-config: failed to parse consumer config at ${configPath}: ${message}`);
|
|
313
588
|
}
|
|
314
589
|
}
|
|
315
|
-
function
|
|
316
|
-
|
|
317
|
-
|
|
590
|
+
function resolveSibling(directory, filenames) {
|
|
591
|
+
const found = filenames.find((filename) => existsSync(resolve(directory, filename)));
|
|
592
|
+
return found ? resolve(directory, found) : null;
|
|
593
|
+
}
|
|
594
|
+
function validateFile(filePath, validator, options) {
|
|
595
|
+
const violations = validator(parseConsumerSource(filePath, readConsumerSource(filePath)), filePath, options);
|
|
318
596
|
if (violations.length === 0) return;
|
|
319
|
-
fail(formatReport(
|
|
597
|
+
fail(formatReport(filePath, violations));
|
|
598
|
+
}
|
|
599
|
+
function runValidation(anchorPath) {
|
|
600
|
+
if (!anchorPath) fail([
|
|
601
|
+
"@useinsider/eslint-config: unable to locate the consumer `insider.lint.*` module for structure validation.",
|
|
602
|
+
"",
|
|
603
|
+
EXPECTED_LAYOUT,
|
|
604
|
+
"",
|
|
605
|
+
`If this is an unexpected environment, set ${OPT_OUT_ENV$1}=true (do not commit).`
|
|
606
|
+
].join("\n"));
|
|
607
|
+
const directory = dirname(resolve(anchorPath));
|
|
608
|
+
const lintModulePath = resolveSibling(directory, LINT_MODULE_FILENAMES);
|
|
609
|
+
if (!lintModulePath) fail([
|
|
610
|
+
`@useinsider/eslint-config: no \`insider.lint.*\` module found in ${directory}.`,
|
|
611
|
+
"",
|
|
612
|
+
`\`${TARGET_CALLEE_NAME}()\` now returns the two renderers instead of a flat-config array,`,
|
|
613
|
+
"so the config it is called from must be a module both linters can import.",
|
|
614
|
+
"",
|
|
615
|
+
EXPECTED_LAYOUT,
|
|
616
|
+
"",
|
|
617
|
+
`Emergency bypass: set ${OPT_OUT_ENV$1}=true (do not commit).`
|
|
618
|
+
].join("\n"));
|
|
619
|
+
validateFile(lintModulePath, validateLintModuleStructure, {});
|
|
620
|
+
const eslintConfigPath = resolveSibling(directory, ESLINT_CONFIG_FILENAMES);
|
|
621
|
+
if (!eslintConfigPath) fail([
|
|
622
|
+
`@useinsider/eslint-config: no \`eslint.config.*\` file found in ${directory}.`,
|
|
623
|
+
"",
|
|
624
|
+
EXPECTED_LAYOUT,
|
|
625
|
+
"",
|
|
626
|
+
`Emergency bypass: set ${OPT_OUT_ENV$1}=true (do not commit).`
|
|
627
|
+
].join("\n"));
|
|
628
|
+
validateFile(eslintConfigPath, validateProgramStructure, { expectedCallee: ESLINT_RENDERER_NAME });
|
|
320
629
|
}
|
|
321
630
|
function ensureConfigStructure(overridePath) {
|
|
322
631
|
const configPath = overridePath === void 0 ? getConsumerConfigPath() : overridePath;
|
|
323
632
|
captureConsumerConfigDir(configPath);
|
|
324
|
-
if (process.env[OPT_OUT_ENV] === "true") {
|
|
633
|
+
if (process.env[OPT_OUT_ENV$1] === "true") {
|
|
325
634
|
emitBypassWarning();
|
|
326
635
|
return;
|
|
327
636
|
}
|
|
@@ -465,7 +774,7 @@ async function buildScopeBlocks(scope, entries) {
|
|
|
465
774
|
const preset = (await scopeMap[scope]()).default;
|
|
466
775
|
return entries.map((entry) => {
|
|
467
776
|
const block = clonePreset(preset);
|
|
468
|
-
block.files = entry.files;
|
|
777
|
+
block.files = [...entry.files];
|
|
469
778
|
if (tsScopes.has(scope)) {
|
|
470
779
|
const { tsconfigPaths } = entry;
|
|
471
780
|
if (tsconfigPaths) applyTypescriptOverrides(block, { tsconfigPaths });
|
|
@@ -499,7 +808,7 @@ async function buildStrictBlocks(value) {
|
|
|
499
808
|
const { default: strictConfig } = await import("./strict-BHw_cKrv.js");
|
|
500
809
|
const clone = { ...strictConfig };
|
|
501
810
|
if (clone.rules) clone.rules = { ...clone.rules };
|
|
502
|
-
if (isFileScoped) clone.files = value;
|
|
811
|
+
if (isFileScoped) clone.files = [...value];
|
|
503
812
|
else delete clone.files;
|
|
504
813
|
return [clone];
|
|
505
814
|
}
|
|
@@ -508,7 +817,11 @@ async function buildStrictBlocks(value) {
|
|
|
508
817
|
var turnOff = false;
|
|
509
818
|
var scanned = false;
|
|
510
819
|
var silencedDependencies = /* @__PURE__ */ new Set();
|
|
511
|
-
var fixedDependencies = [
|
|
820
|
+
var fixedDependencies = [
|
|
821
|
+
"eslint",
|
|
822
|
+
"globals",
|
|
823
|
+
"oxlint"
|
|
824
|
+
];
|
|
512
825
|
var require = createRequire(import.meta.url);
|
|
513
826
|
function getPackageJSONPath(currentDir) {
|
|
514
827
|
const fileLocation = resolve(currentDir, "package.json");
|
|
@@ -564,6 +877,46 @@ function silenceDependencyWarning(input) {
|
|
|
564
877
|
input.forEach((dependency) => silencedDependencies.add(String(dependency)));
|
|
565
878
|
}
|
|
566
879
|
//#endregion
|
|
880
|
+
//#region src/utils/ensureOxlintConfig.ts
|
|
881
|
+
var OPT_OUT_ENV = "INSIDER_SKIP_CONFIG_VALIDATION";
|
|
882
|
+
var OXLINT_CONFIG_FILENAMES = ["oxlint.config.ts", "oxlint.config.mts"];
|
|
883
|
+
function lintModuleSpecifier(directory) {
|
|
884
|
+
return `./${LINT_MODULE_FILENAMES.find((filename) => existsSync(join(directory, filename))) ?? "insider.lint.ts"}`;
|
|
885
|
+
}
|
|
886
|
+
function formatMessage(directory) {
|
|
887
|
+
return [
|
|
888
|
+
"@useinsider/eslint-config: no oxlint config found in",
|
|
889
|
+
` ${directory}`,
|
|
890
|
+
"",
|
|
891
|
+
"useInsiderESLint() turns off every rule oxlint owns, so running ESLint alone would silently",
|
|
892
|
+
"drop those checks. Create the sibling oxlint config:",
|
|
893
|
+
"",
|
|
894
|
+
" // oxlint.config.ts",
|
|
895
|
+
` import { useInsiderOXC } from '${lintModuleSpecifier(directory)}';`,
|
|
896
|
+
"",
|
|
897
|
+
" export default await useInsiderOXC();",
|
|
898
|
+
"",
|
|
899
|
+
"and run both linters:",
|
|
900
|
+
"",
|
|
901
|
+
" \"lint\": \"oxlint --disable-nested-config && eslint .\"",
|
|
902
|
+
"",
|
|
903
|
+
`Expected one of: ${OXLINT_CONFIG_FILENAMES.join(", ")}.`,
|
|
904
|
+
`Emergency bypass: set ${OPT_OUT_ENV}=true (do not commit).`
|
|
905
|
+
].join("\n");
|
|
906
|
+
}
|
|
907
|
+
/**
|
|
908
|
+
* Fails when the consumer enabled the ESLint-side oxlint suppression without a sibling oxlint
|
|
909
|
+
* config to run the suppressed rules. Resolved against the directory
|
|
910
|
+
* {@link getConsumerConfigDir} captured during `useInsider()`.
|
|
911
|
+
* @example
|
|
912
|
+
* ensureOxlintConfig(); // throws unless oxlint.config.{ts,mts} sits beside insider.lint.*
|
|
913
|
+
*/
|
|
914
|
+
function ensureOxlintConfig(directory = getConsumerConfigDir()) {
|
|
915
|
+
if (process.env[OPT_OUT_ENV] === "true") return;
|
|
916
|
+
if (OXLINT_CONFIG_FILENAMES.some((filename) => existsSync(join(directory, filename)))) return;
|
|
917
|
+
throw new Error(formatMessage(directory));
|
|
918
|
+
}
|
|
919
|
+
//#endregion
|
|
567
920
|
//#region src/utils/silenceRules.ts
|
|
568
921
|
var globallySilencedRules = /* @__PURE__ */ new Set();
|
|
569
922
|
/**
|
|
@@ -583,14 +936,25 @@ function silenceRule(config) {
|
|
|
583
936
|
const [, ...restConfig] = Array.isArray(config) ? config : [];
|
|
584
937
|
return ["warn", ...restConfig];
|
|
585
938
|
}
|
|
939
|
+
/**
|
|
940
|
+
* Reports a silenced rule name that no emitted block declares, which is how a typo in
|
|
941
|
+
* `silenceRules` stays visible. The caller passes the union of every block's rule keys: a single
|
|
942
|
+
* block is not evidence, because the emission is many narrow blocks and a correctly spelled rule is
|
|
943
|
+
* absent from nearly all of them.
|
|
944
|
+
* @example
|
|
945
|
+
* warnUnknownSilencedRules(['no-console'], ['no-unknown-rule']); // warns once
|
|
946
|
+
*/
|
|
947
|
+
function warnUnknownSilencedRules(knownRules, silencedRules) {
|
|
948
|
+
const known = new Set(knownRules);
|
|
949
|
+
new Set(silencedRules).forEach((rule) => {
|
|
950
|
+
if (known.has(rule)) return;
|
|
951
|
+
warn(`Unknown rule "${rule}". Please remove it from the silenced rules list.`);
|
|
952
|
+
});
|
|
953
|
+
}
|
|
586
954
|
function filterSilencedRules(rules, silencedRules) {
|
|
587
955
|
let targetSilencedRules = silencedRules || globallySilencedRules;
|
|
588
956
|
if (Array.isArray(targetSilencedRules)) targetSilencedRules = new Set(targetSilencedRules);
|
|
589
957
|
if (!rules || !targetSilencedRules.size) return rules;
|
|
590
|
-
if (silencedRules) targetSilencedRules.forEach((rule) => {
|
|
591
|
-
if (rules[rule]) return;
|
|
592
|
-
warn(`Unknown rule "${rule}". Please remove it from the silenced rules list.`);
|
|
593
|
-
});
|
|
594
958
|
return Object.entries(rules).reduce((newRules, [key, value]) => {
|
|
595
959
|
if (value) newRules[key] = targetSilencedRules.has(key) && !isDisabled(value) ? silenceRule(value) : value;
|
|
596
960
|
return newRules;
|
|
@@ -626,6 +990,7 @@ async function collectScopeBlocks(config) {
|
|
|
626
990
|
}, Promise.resolve([]));
|
|
627
991
|
}
|
|
628
992
|
function applySilenceRules(blocks, perCallSilence) {
|
|
993
|
+
if (perCallSilence) warnUnknownSilencedRules(blocks.flatMap((block) => Object.keys(block.rules ?? {})), perCallSilence);
|
|
629
994
|
blocks.forEach((block) => {
|
|
630
995
|
if (!block.rules) return;
|
|
631
996
|
block.rules = perCallSilence ? filterSilencedRules(block.rules, perCallSilence) : filterSilencedRules(block.rules);
|
|
@@ -635,28 +1000,42 @@ function buildIgnoresBlocks(ignores) {
|
|
|
635
1000
|
if (!ignores || ignores.length === 0) return [];
|
|
636
1001
|
return [{ ignores: [...ignores] }];
|
|
637
1002
|
}
|
|
638
|
-
async function
|
|
639
|
-
assertNoRemovedKeys(config);
|
|
640
|
-
ensureConfigStructure();
|
|
641
|
-
await ensureDependencies();
|
|
642
|
-
const ignoresBlocks = buildIgnoresBlocks(config.ignores);
|
|
1003
|
+
async function buildBaseBlocks(config) {
|
|
643
1004
|
const scopeBlocks = await collectScopeBlocks(config);
|
|
644
|
-
const jqueryBlocks = buildJqueryBlocks(config.jquery);
|
|
645
|
-
const configFilesBlocks = buildConfigFilesBlocks(config.configFiles);
|
|
646
1005
|
const strictBlocks = await buildStrictBlocks(config.strict);
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
...
|
|
1006
|
+
return [
|
|
1007
|
+
...buildIgnoresBlocks(config.ignores),
|
|
1008
|
+
...buildUnusedDirectiveBlocks(),
|
|
650
1009
|
...scopeBlocks,
|
|
651
|
-
...
|
|
652
|
-
...
|
|
1010
|
+
...buildJqueryBlocks(config.jquery),
|
|
1011
|
+
...buildConfigFilesBlocks(config.configFiles),
|
|
653
1012
|
...strictBlocks,
|
|
654
|
-
...
|
|
1013
|
+
...buildLintTopologyBlocks(),
|
|
1014
|
+
...buildSpellCheckerBlocks(config.spellChecker)
|
|
655
1015
|
];
|
|
1016
|
+
}
|
|
1017
|
+
async function renderEslint(config) {
|
|
1018
|
+
await ensureDependencies();
|
|
1019
|
+
ensureOxlintConfig();
|
|
1020
|
+
const baseBlocks = await buildBaseBlocks(config);
|
|
1021
|
+
const blocks = [...baseBlocks, ...buildOxlintSuppressionBlocks(baseBlocks)];
|
|
656
1022
|
applySilenceRules(blocks, config.silenceRules);
|
|
657
1023
|
return defineConfig(blocks);
|
|
658
1024
|
}
|
|
1025
|
+
async function renderOxlint(config) {
|
|
1026
|
+
const baseBlocks = await buildBaseBlocks(config);
|
|
1027
|
+
applySilenceRules(baseBlocks, config.silenceRules);
|
|
1028
|
+
return buildOxlintConfig(baseBlocks, config.ignores);
|
|
1029
|
+
}
|
|
1030
|
+
function useInsider(config) {
|
|
1031
|
+
assertNoRemovedKeys(config);
|
|
1032
|
+
ensureConfigStructure();
|
|
1033
|
+
return {
|
|
1034
|
+
useInsiderESLint: () => renderEslint(config),
|
|
1035
|
+
useInsiderOXC: () => renderOxlint(config)
|
|
1036
|
+
};
|
|
1037
|
+
}
|
|
659
1038
|
//#endregion
|
|
660
|
-
export { ensureConfigStructure, merge, mergeAll, silenceDependencyWarning, silenceRules, useInsider };
|
|
1039
|
+
export { ensureConfigStructure, ensureOxlintConfig, merge, mergeAll, silenceDependencyWarning, silenceRules, useInsider };
|
|
661
1040
|
|
|
662
1041
|
//# sourceMappingURL=main.js.map
|