@bitwisedesign/xanoscriptlint 0.1.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 +128 -0
- package/dist/cli.d.ts +6 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +121 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +43 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +239 -0
- package/dist/config.js.map +1 -0
- package/dist/customRules.d.ts +4 -0
- package/dist/customRules.d.ts.map +1 -0
- package/dist/customRules.js +43 -0
- package/dist/customRules.js.map +1 -0
- package/dist/discover.d.ts +7 -0
- package/dist/discover.d.ts.map +1 -0
- package/dist/discover.js +70 -0
- package/dist/discover.js.map +1 -0
- package/dist/lint.d.ts +14 -0
- package/dist/lint.d.ts.map +1 -0
- package/dist/lint.js +64 -0
- package/dist/lint.js.map +1 -0
- package/dist/report.d.ts +7 -0
- package/dist/report.d.ts.map +1 -0
- package/dist/report.js +86 -0
- package/dist/report.js.map +1 -0
- package/dist/rules/empty_function_run.d.ts +3 -0
- package/dist/rules/empty_function_run.d.ts.map +1 -0
- package/dist/rules/empty_function_run.js +32 -0
- package/dist/rules/empty_function_run.js.map +1 -0
- package/dist/rules/index.d.ts +5 -0
- package/dist/rules/index.d.ts.map +1 -0
- package/dist/rules/index.js +12 -0
- package/dist/rules/index.js.map +1 -0
- package/dist/rules/no_trailing_newline.d.ts +3 -0
- package/dist/rules/no_trailing_newline.d.ts.map +1 -0
- package/dist/rules/no_trailing_newline.js +34 -0
- package/dist/rules/no_trailing_newline.js.map +1 -0
- package/dist/rules/no_var_response.d.ts +3 -0
- package/dist/rules/no_var_response.d.ts.map +1 -0
- package/dist/rules/no_var_response.js +32 -0
- package/dist/rules/no_var_response.js.map +1 -0
- package/dist/rules/types.d.ts +30 -0
- package/dist/rules/types.d.ts.map +1 -0
- package/dist/rules/types.js +2 -0
- package/dist/rules/types.js.map +1 -0
- package/dist/suppress.d.ts +8 -0
- package/dist/suppress.d.ts.map +1 -0
- package/dist/suppress.js +107 -0
- package/dist/suppress.js.map +1 -0
- package/dist/util.d.ts +9 -0
- package/dist/util.d.ts.map +1 -0
- package/dist/util.js +37 -0
- package/dist/util.js.map +1 -0
- package/package.json +65 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Bitwise Design
|
|
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,128 @@
|
|
|
1
|
+
# xanoscriptlint
|
|
2
|
+
|
|
3
|
+
A linter for [XanoScript](https://docs.xano.com/xanoscript/key-concepts).
|
|
4
|
+
|
|
5
|
+
xanoscriptlint is a style and convention linter, not a compiler. Syntax and semantics stay with Xano (`@xano/xanoscript-language-server`, `xano_validate_xanoscript`). This tool owns convention and pitfall rules, project configuration, path filters, and custom regex rules.
|
|
6
|
+
|
|
7
|
+
Requires Node.js 20 or later. Runs on linux and macOS (Windows is untested but not blocked).
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install --save-dev @bitwisedesign/xanoscriptlint
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npx @bitwisedesign/xanoscriptlint
|
|
17
|
+
npx @bitwisedesign/xanoscriptlint rules
|
|
18
|
+
npx @bitwisedesign/xanoscriptlint path/to/file.xs
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
`npx` is optional. After a local install, npm puts the binary on `PATH` for scripts:
|
|
22
|
+
|
|
23
|
+
```json
|
|
24
|
+
"scripts": {
|
|
25
|
+
"lint:xs": "xanoscriptlint"
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Then `npm run lint:xs` runs `xanoscriptlint` with no `npx`.
|
|
30
|
+
|
|
31
|
+
`npm install -g @bitwisedesign/xanoscriptlint` (no path) only works after the package is published to npm. To put the command on your PATH from a git checkout:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npm install
|
|
35
|
+
npm run build
|
|
36
|
+
npm link
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Or `npm install -g /path/to/xanoscriptlint`. Remove a link with `npm unlink -g @bitwisedesign/xanoscriptlint`.
|
|
40
|
+
|
|
41
|
+
## Configuration
|
|
42
|
+
|
|
43
|
+
Place `.xanoscriptlint.yml` at the project root (or pass `--config`). With no file, built-in defaults apply.
|
|
44
|
+
|
|
45
|
+
```yaml
|
|
46
|
+
disabled_rules:
|
|
47
|
+
- no_trailing_newline
|
|
48
|
+
opt_in_rules:
|
|
49
|
+
- no_var_response
|
|
50
|
+
# only_rules: [empty_function_run] # exclusive; cannot mix with the two above
|
|
51
|
+
|
|
52
|
+
included:
|
|
53
|
+
- "**/*.xs"
|
|
54
|
+
excluded:
|
|
55
|
+
- ".xano/**"
|
|
56
|
+
- "**/node_modules/**"
|
|
57
|
+
|
|
58
|
+
empty_function_run:
|
|
59
|
+
severity: error
|
|
60
|
+
|
|
61
|
+
custom_rules:
|
|
62
|
+
no_todo_in_stack:
|
|
63
|
+
name: No TODO
|
|
64
|
+
regex: "TODO"
|
|
65
|
+
message: "Remove TODO before shipping."
|
|
66
|
+
severity: warning
|
|
67
|
+
excluded:
|
|
68
|
+
- ".*Test\\.xs"
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
- Built-in rules with `defaultEnabled: true` are on unless listed in `disabled_rules`.
|
|
72
|
+
- Off-by-default rules are enabled with `opt_in_rules`.
|
|
73
|
+
- `only_rules` is an exclusive allowlist and cannot be combined with `disabled_rules` or `opt_in_rules`.
|
|
74
|
+
- `custom_rules` run when defined, unless `only_rules` is set and does not include `custom_rules` or that rule id.
|
|
75
|
+
- `excluded` always wins over `included`. Paths are relative to the config file directory.
|
|
76
|
+
|
|
77
|
+
See [docs/configuration.md](docs/configuration.md) and [docs/rules.md](docs/rules.md).
|
|
78
|
+
|
|
79
|
+
## Built-in rules
|
|
80
|
+
|
|
81
|
+
| Id | Default | Severity | What it catches |
|
|
82
|
+
| --- | --- | --- | --- |
|
|
83
|
+
| `empty_function_run` | on | error | `function.run ""` / `function.run ''` |
|
|
84
|
+
| `no_trailing_newline` | on | error | File does not end with `}` (Xano pull strips trailing newlines); auto-fixable with `--fix` |
|
|
85
|
+
| `no_var_response` | opt-in | warning | `var $response` (Xano rewrites it) |
|
|
86
|
+
|
|
87
|
+
House style such as a `// Modified:` timestamp belongs in `custom_rules`, not in the default catalog:
|
|
88
|
+
|
|
89
|
+
```yaml
|
|
90
|
+
custom_rules:
|
|
91
|
+
modified_stamp:
|
|
92
|
+
name: Modified stamp
|
|
93
|
+
regex: "^// Modified: \\d{2}-\\d{2}-\\d{4} \\d{2}:\\d{2}$"
|
|
94
|
+
message: "Use this only as an example of a team-specific custom rule."
|
|
95
|
+
severity: warning
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
(That example matches a stamp line; requiring it as the last header comment is left to your team.)
|
|
99
|
+
|
|
100
|
+
## Suppressions
|
|
101
|
+
|
|
102
|
+
XanoScript comments must be on their own line, so suppressions cannot trail a statement.
|
|
103
|
+
|
|
104
|
+
```xs
|
|
105
|
+
// xanoscriptlint:disable empty_function_run
|
|
106
|
+
// xanoscriptlint:enable empty_function_run
|
|
107
|
+
// xanoscriptlint:disable:next empty_function_run
|
|
108
|
+
// xanoscriptlint:disable:previous empty_function_run
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
`disable` without `next`/`previous` lasts until a matching `enable` or end of file. A `disable` at the top of the file is the file-wide form.
|
|
112
|
+
|
|
113
|
+
## CLI
|
|
114
|
+
|
|
115
|
+
```text
|
|
116
|
+
xanoscriptlint [paths…]
|
|
117
|
+
xanoscriptlint rules
|
|
118
|
+
xanoscriptlint --config path/to/.xanoscriptlint.yml
|
|
119
|
+
xanoscriptlint --reporter json
|
|
120
|
+
xanoscriptlint --strict
|
|
121
|
+
xanoscriptlint --fix
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Exit `0` when there are no error-severity violations. Exit `2` when there is at least one error. Warnings alone do not fail CI unless `--strict`.
|
|
125
|
+
|
|
126
|
+
## License
|
|
127
|
+
|
|
128
|
+
MIT
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAuBA,wBAAsB,MAAM,CAC1B,IAAI,EAAE,MAAM,EAAE,EACd,EAAE,GAAE;IAAE,MAAM,EAAE,MAAM,CAAC,cAAc,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC,cAAc,CAAA;CAAY,GAC7E,OAAO,CAAC,MAAM,CAAC,CAiDjB"}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { writeFileSync } from "node:fs";
|
|
3
|
+
import { createRequire } from "node:module";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { Command, CommanderError } from "commander";
|
|
6
|
+
import { ConfigError, loadConfig } from "./config.js";
|
|
7
|
+
import { discoverXsFiles } from "./discover.js";
|
|
8
|
+
import { fixFile, lintFiles, readSourceFile } from "./lint.js";
|
|
9
|
+
import { builtinRules } from "./rules/index.js";
|
|
10
|
+
import { applyStrict, exitCodeFor, formatFixSummary, formatReport, } from "./report.js";
|
|
11
|
+
import { isMainModule } from "./util.js";
|
|
12
|
+
const require = createRequire(import.meta.url);
|
|
13
|
+
const { version } = require("../package.json");
|
|
14
|
+
export async function runCli(argv, io = process) {
|
|
15
|
+
let exitCode = 0;
|
|
16
|
+
const program = new Command();
|
|
17
|
+
program
|
|
18
|
+
.name("xanoscriptlint")
|
|
19
|
+
.description("A linter for XanoScript")
|
|
20
|
+
.version(version)
|
|
21
|
+
.option("-c, --config <path>", "path to .xanoscriptlint.yml")
|
|
22
|
+
.option("--reporter <name>", "stylish or json", "stylish")
|
|
23
|
+
.option("--strict", "treat warnings as errors", false)
|
|
24
|
+
.option("--fix", "automatically fix violations where possible", false)
|
|
25
|
+
.exitOverride()
|
|
26
|
+
.configureOutput({
|
|
27
|
+
writeOut: (str) => io.stdout.write(str),
|
|
28
|
+
writeErr: (str) => io.stderr.write(str),
|
|
29
|
+
});
|
|
30
|
+
program
|
|
31
|
+
.command("lint", { isDefault: true })
|
|
32
|
+
.description("Lint XanoScript files")
|
|
33
|
+
.argument("[paths...]", "files or directories to lint")
|
|
34
|
+
.action(async (paths) => {
|
|
35
|
+
const opts = program.opts();
|
|
36
|
+
exitCode = await runLint(paths, opts, io);
|
|
37
|
+
});
|
|
38
|
+
program
|
|
39
|
+
.command("rules")
|
|
40
|
+
.description("List built-in rules")
|
|
41
|
+
.action(() => {
|
|
42
|
+
io.stdout.write(formatRulesList());
|
|
43
|
+
});
|
|
44
|
+
try {
|
|
45
|
+
await program.parseAsync(argv);
|
|
46
|
+
return exitCode;
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
if (error instanceof CommanderError) {
|
|
50
|
+
return error.exitCode;
|
|
51
|
+
}
|
|
52
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
53
|
+
io.stderr.write(`${message}\n`);
|
|
54
|
+
return 1;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
async function runLint(paths, opts, io) {
|
|
58
|
+
const reporter = parseReporter(opts.reporter);
|
|
59
|
+
if (!reporter) {
|
|
60
|
+
io.stderr.write(`unknown reporter: ${opts.reporter}\n`);
|
|
61
|
+
return 1;
|
|
62
|
+
}
|
|
63
|
+
try {
|
|
64
|
+
const cwd = process.cwd();
|
|
65
|
+
const config = loadConfig({ cwd, configPath: opts.config });
|
|
66
|
+
const files = await discoverXsFiles({ config, cwd, cliPaths: paths });
|
|
67
|
+
let sources = files.map((filePath) => readSourceFile(filePath));
|
|
68
|
+
if (opts.fix) {
|
|
69
|
+
const corrections = [];
|
|
70
|
+
const fixed = [];
|
|
71
|
+
for (const source of sources) {
|
|
72
|
+
const result = fixFile(source, config);
|
|
73
|
+
if (result.changed) {
|
|
74
|
+
writeFileSync(source.path, result.text, "utf8");
|
|
75
|
+
}
|
|
76
|
+
corrections.push(...result.corrections);
|
|
77
|
+
fixed.push({ path: source.path, text: result.text });
|
|
78
|
+
}
|
|
79
|
+
sources = fixed;
|
|
80
|
+
const summary = formatFixSummary(corrections, cwd);
|
|
81
|
+
if (summary.length > 0) {
|
|
82
|
+
const text = summary.endsWith("\n") ? summary : `${summary}\n`;
|
|
83
|
+
const stream = reporter === "json" ? io.stderr : io.stdout;
|
|
84
|
+
stream.write(text);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
const violations = applyStrict(lintFiles(sources, config), opts.strict);
|
|
88
|
+
const report = formatReport(violations, reporter, cwd);
|
|
89
|
+
if (report.length > 0) {
|
|
90
|
+
io.stdout.write(report.endsWith("\n") ? report : `${report}\n`);
|
|
91
|
+
}
|
|
92
|
+
return exitCodeFor(violations);
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
if (error instanceof ConfigError) {
|
|
96
|
+
io.stderr.write(`${error.message}\n`);
|
|
97
|
+
return 1;
|
|
98
|
+
}
|
|
99
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
100
|
+
io.stderr.write(`${message}\n`);
|
|
101
|
+
return 1;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
function formatRulesList() {
|
|
105
|
+
const lines = ["id default severity description", "-".repeat(90)];
|
|
106
|
+
for (const rule of builtinRules) {
|
|
107
|
+
const enabled = rule.defaultEnabled ? "on" : "opt-in";
|
|
108
|
+
lines.push(`${rule.id.padEnd(26)}${enabled.padEnd(11)}${rule.defaultSeverity.padEnd(11)}${rule.description}`);
|
|
109
|
+
}
|
|
110
|
+
return `${lines.join("\n")}\n`;
|
|
111
|
+
}
|
|
112
|
+
function parseReporter(name) {
|
|
113
|
+
if (name === "stylish" || name === "json") {
|
|
114
|
+
return name;
|
|
115
|
+
}
|
|
116
|
+
return undefined;
|
|
117
|
+
}
|
|
118
|
+
if (isMainModule(process.argv[1], fileURLToPath(import.meta.url))) {
|
|
119
|
+
process.exitCode = await runCli(process.argv);
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { RuleOptions, Severity } from "./rules/types.js";
|
|
2
|
+
export declare class ConfigError extends Error {
|
|
3
|
+
constructor(message: string);
|
|
4
|
+
}
|
|
5
|
+
export declare const CONFIG_FILENAME = ".xanoscriptlint.yml";
|
|
6
|
+
export interface CustomRuleConfig {
|
|
7
|
+
id: string;
|
|
8
|
+
name: string;
|
|
9
|
+
regex: string;
|
|
10
|
+
pattern: RegExp;
|
|
11
|
+
message: string;
|
|
12
|
+
severity: Severity;
|
|
13
|
+
included?: string[];
|
|
14
|
+
excluded?: string[];
|
|
15
|
+
}
|
|
16
|
+
export interface ResolvedConfig {
|
|
17
|
+
configDir: string;
|
|
18
|
+
configPath: string | null;
|
|
19
|
+
enabledRuleIds: Set<string>;
|
|
20
|
+
ruleOptions: Map<string, RuleOptions>;
|
|
21
|
+
included: string[];
|
|
22
|
+
excluded: string[];
|
|
23
|
+
customRules: CustomRuleConfig[];
|
|
24
|
+
}
|
|
25
|
+
interface RawConfig {
|
|
26
|
+
disabled_rules?: unknown;
|
|
27
|
+
opt_in_rules?: unknown;
|
|
28
|
+
only_rules?: unknown;
|
|
29
|
+
included?: unknown;
|
|
30
|
+
excluded?: unknown;
|
|
31
|
+
custom_rules?: unknown;
|
|
32
|
+
[key: string]: unknown;
|
|
33
|
+
}
|
|
34
|
+
export declare function findConfigPath(startDir: string): string | null;
|
|
35
|
+
export declare function loadConfig(options: {
|
|
36
|
+
cwd: string;
|
|
37
|
+
configPath?: string;
|
|
38
|
+
}): ResolvedConfig;
|
|
39
|
+
export declare function loadConfigFile(configPath: string): ResolvedConfig;
|
|
40
|
+
export declare function loadConfigText(text: string, configDir: string, configPath: string | null): ResolvedConfig;
|
|
41
|
+
export declare function resolveConfig(raw: RawConfig, configDir: string, configPath: string | null): ResolvedConfig;
|
|
42
|
+
export {};
|
|
43
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE9D,qBAAa,WAAY,SAAQ,KAAK;gBACxB,OAAO,EAAE,MAAM;CAI5B;AAED,eAAO,MAAM,eAAe,wBAAwB,CAAC;AAWrD,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,QAAQ,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC5B,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACtC,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,WAAW,EAAE,gBAAgB,EAAE,CAAC;CACjC;AAWD,UAAU,SAAS;IACjB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAa9D;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,GAAG,cAAc,CAajB;AAED,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,cAAc,CAGjE;AAED,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,GAAG,IAAI,GACxB,cAAc,CAYhB;AAED,wBAAgB,aAAa,CAC3B,GAAG,EAAE,SAAS,EACd,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,GAAG,IAAI,GACxB,cAAc,CA6FhB"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { parse as parseYaml } from "yaml";
|
|
4
|
+
import { builtinRules } from "./rules/index.js";
|
|
5
|
+
export class ConfigError extends Error {
|
|
6
|
+
constructor(message) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.name = "ConfigError";
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export const CONFIG_FILENAME = ".xanoscriptlint.yml";
|
|
12
|
+
const KNOWN_KEYS = new Set([
|
|
13
|
+
"disabled_rules",
|
|
14
|
+
"opt_in_rules",
|
|
15
|
+
"only_rules",
|
|
16
|
+
"included",
|
|
17
|
+
"excluded",
|
|
18
|
+
"custom_rules",
|
|
19
|
+
]);
|
|
20
|
+
export function findConfigPath(startDir) {
|
|
21
|
+
let dir = path.resolve(startDir);
|
|
22
|
+
while (true) {
|
|
23
|
+
const candidate = path.join(dir, CONFIG_FILENAME);
|
|
24
|
+
if (existsSync(candidate)) {
|
|
25
|
+
return candidate;
|
|
26
|
+
}
|
|
27
|
+
const parent = path.dirname(dir);
|
|
28
|
+
if (parent === dir) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
dir = parent;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
export function loadConfig(options) {
|
|
35
|
+
if (options.configPath) {
|
|
36
|
+
const configPath = path.resolve(options.cwd, options.configPath);
|
|
37
|
+
if (!existsSync(configPath)) {
|
|
38
|
+
throw new ConfigError(`config file not found: ${configPath}`);
|
|
39
|
+
}
|
|
40
|
+
return loadConfigFile(configPath);
|
|
41
|
+
}
|
|
42
|
+
const found = findConfigPath(options.cwd);
|
|
43
|
+
if (!found) {
|
|
44
|
+
return resolveConfig({}, path.resolve(options.cwd), null);
|
|
45
|
+
}
|
|
46
|
+
return loadConfigFile(found);
|
|
47
|
+
}
|
|
48
|
+
export function loadConfigFile(configPath) {
|
|
49
|
+
const text = readFileSync(configPath, "utf8");
|
|
50
|
+
return loadConfigText(text, path.dirname(configPath), configPath);
|
|
51
|
+
}
|
|
52
|
+
export function loadConfigText(text, configDir, configPath) {
|
|
53
|
+
let raw;
|
|
54
|
+
try {
|
|
55
|
+
raw = parseYaml(text) ?? {};
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
59
|
+
throw new ConfigError(`invalid YAML: ${detail}`);
|
|
60
|
+
}
|
|
61
|
+
if (raw === null || typeof raw !== "object" || Array.isArray(raw)) {
|
|
62
|
+
throw new ConfigError("config must be a YAML mapping");
|
|
63
|
+
}
|
|
64
|
+
return resolveConfig(raw, configDir, configPath);
|
|
65
|
+
}
|
|
66
|
+
export function resolveConfig(raw, configDir, configPath) {
|
|
67
|
+
const builtinIds = new Set(builtinRules.map((rule) => rule.id));
|
|
68
|
+
const disabledRules = optionalStringList(raw.disabled_rules, "disabled_rules");
|
|
69
|
+
const optInRules = optionalStringList(raw.opt_in_rules, "opt_in_rules");
|
|
70
|
+
const onlyRules = optionalStringList(raw.only_rules, "only_rules");
|
|
71
|
+
const included = optionalStringList(raw.included, "included") ?? ["**/*.xs"];
|
|
72
|
+
const excluded = optionalStringList(raw.excluded, "excluded") ?? [];
|
|
73
|
+
const customRules = parseCustomRules(raw.custom_rules);
|
|
74
|
+
const customIds = new Set(customRules.map((rule) => rule.id));
|
|
75
|
+
for (const key of Object.keys(raw)) {
|
|
76
|
+
if (KNOWN_KEYS.has(key) || builtinIds.has(key) || customIds.has(key)) {
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
throw new ConfigError(`unknown config key: ${key}`);
|
|
80
|
+
}
|
|
81
|
+
if (onlyRules !== undefined) {
|
|
82
|
+
if (disabledRules !== undefined || optInRules !== undefined) {
|
|
83
|
+
throw new ConfigError("only_rules cannot be combined with disabled_rules or opt_in_rules");
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
const knownIds = new Set([...builtinIds, ...customIds]);
|
|
87
|
+
for (const [listName, list] of [
|
|
88
|
+
["disabled_rules", disabledRules],
|
|
89
|
+
["opt_in_rules", optInRules],
|
|
90
|
+
["only_rules", onlyRules],
|
|
91
|
+
]) {
|
|
92
|
+
if (!list) {
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
for (const id of list) {
|
|
96
|
+
if (id === "custom_rules") {
|
|
97
|
+
if (listName !== "only_rules") {
|
|
98
|
+
throw new ConfigError("custom_rules is only valid in only_rules");
|
|
99
|
+
}
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
if (!knownIds.has(id)) {
|
|
103
|
+
throw new ConfigError(`unknown rule id in ${listName}: ${id}`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
const enabledRuleIds = new Set();
|
|
108
|
+
if (onlyRules !== undefined) {
|
|
109
|
+
for (const id of onlyRules) {
|
|
110
|
+
if (id === "custom_rules") {
|
|
111
|
+
for (const customId of customIds) {
|
|
112
|
+
enabledRuleIds.add(customId);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
enabledRuleIds.add(id);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
for (const rule of builtinRules) {
|
|
122
|
+
if (rule.defaultEnabled && !disabledRules?.includes(rule.id)) {
|
|
123
|
+
enabledRuleIds.add(rule.id);
|
|
124
|
+
}
|
|
125
|
+
if (!rule.defaultEnabled && optInRules?.includes(rule.id)) {
|
|
126
|
+
enabledRuleIds.add(rule.id);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
for (const custom of customRules) {
|
|
130
|
+
if (!disabledRules?.includes(custom.id)) {
|
|
131
|
+
enabledRuleIds.add(custom.id);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
const ruleOptions = new Map();
|
|
136
|
+
for (const rule of builtinRules) {
|
|
137
|
+
if (rule.id in raw) {
|
|
138
|
+
ruleOptions.set(rule.id, parseRuleOptions(raw[rule.id], rule.id));
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
const activeCustomRules = customRules.filter((rule) => enabledRuleIds.has(rule.id));
|
|
142
|
+
return {
|
|
143
|
+
configDir,
|
|
144
|
+
configPath,
|
|
145
|
+
enabledRuleIds,
|
|
146
|
+
ruleOptions,
|
|
147
|
+
included,
|
|
148
|
+
excluded,
|
|
149
|
+
customRules: activeCustomRules,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
function parseCustomRules(value) {
|
|
153
|
+
if (value === undefined || value === null) {
|
|
154
|
+
return [];
|
|
155
|
+
}
|
|
156
|
+
if (typeof value !== "object" || Array.isArray(value)) {
|
|
157
|
+
throw new ConfigError("custom_rules must be a mapping of id to rule");
|
|
158
|
+
}
|
|
159
|
+
const result = [];
|
|
160
|
+
for (const [id, spec] of Object.entries(value)) {
|
|
161
|
+
if (typeof spec !== "object" || spec === null || Array.isArray(spec)) {
|
|
162
|
+
throw new ConfigError(`custom_rules.${id} must be a mapping`);
|
|
163
|
+
}
|
|
164
|
+
const raw = spec;
|
|
165
|
+
if (typeof raw.regex !== "string" || raw.regex.length === 0) {
|
|
166
|
+
throw new ConfigError(`custom_rules.${id}.regex is required`);
|
|
167
|
+
}
|
|
168
|
+
let pattern;
|
|
169
|
+
try {
|
|
170
|
+
pattern = new RegExp(raw.regex);
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
174
|
+
throw new ConfigError(`custom_rules.${id}.regex is invalid: ${detail}`);
|
|
175
|
+
}
|
|
176
|
+
result.push({
|
|
177
|
+
id,
|
|
178
|
+
name: optionalString(raw.name, `custom_rules.${id}.name`) ?? id,
|
|
179
|
+
regex: raw.regex,
|
|
180
|
+
pattern,
|
|
181
|
+
message: optionalString(raw.message, `custom_rules.${id}.message`) ??
|
|
182
|
+
`custom rule ${id} matched`,
|
|
183
|
+
severity: optionalSeverity(raw.severity, `custom_rules.${id}.severity`) ?? "warning",
|
|
184
|
+
included: optionalStringList(raw.included, `custom_rules.${id}.included`),
|
|
185
|
+
excluded: optionalStringList(raw.excluded, `custom_rules.${id}.excluded`),
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
return result;
|
|
189
|
+
}
|
|
190
|
+
function parseRuleOptions(value, id) {
|
|
191
|
+
if (typeof value === "string") {
|
|
192
|
+
return { severity: asSeverity(value, id) };
|
|
193
|
+
}
|
|
194
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
195
|
+
throw new ConfigError(`${id} must be a severity or a mapping`);
|
|
196
|
+
}
|
|
197
|
+
const record = value;
|
|
198
|
+
const options = {};
|
|
199
|
+
if (record.severity !== undefined) {
|
|
200
|
+
options.severity = asSeverity(record.severity, `${id}.severity`);
|
|
201
|
+
}
|
|
202
|
+
for (const key of Object.keys(record)) {
|
|
203
|
+
if (key !== "severity") {
|
|
204
|
+
throw new ConfigError(`unknown option for ${id}: ${key}`);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return options;
|
|
208
|
+
}
|
|
209
|
+
function optionalStringList(value, label) {
|
|
210
|
+
if (value === undefined || value === null) {
|
|
211
|
+
return undefined;
|
|
212
|
+
}
|
|
213
|
+
if (!Array.isArray(value) || value.some((item) => typeof item !== "string")) {
|
|
214
|
+
throw new ConfigError(`${label} must be a list of strings`);
|
|
215
|
+
}
|
|
216
|
+
return value;
|
|
217
|
+
}
|
|
218
|
+
function optionalString(value, label) {
|
|
219
|
+
if (value === undefined || value === null) {
|
|
220
|
+
return undefined;
|
|
221
|
+
}
|
|
222
|
+
if (typeof value !== "string") {
|
|
223
|
+
throw new ConfigError(`${label} must be a string`);
|
|
224
|
+
}
|
|
225
|
+
return value;
|
|
226
|
+
}
|
|
227
|
+
function optionalSeverity(value, label) {
|
|
228
|
+
if (value === undefined || value === null) {
|
|
229
|
+
return undefined;
|
|
230
|
+
}
|
|
231
|
+
return asSeverity(value, label);
|
|
232
|
+
}
|
|
233
|
+
function asSeverity(value, label) {
|
|
234
|
+
if (value === "error" || value === "warning") {
|
|
235
|
+
return value;
|
|
236
|
+
}
|
|
237
|
+
throw new ConfigError(`${label} must be "error" or "warning"`);
|
|
238
|
+
}
|
|
239
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"customRules.d.ts","sourceRoot":"","sources":["../src/customRules.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAG9D,wBAAgB,cAAc,CAC5B,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,gBAAgB,EAAE,GACxB,SAAS,EAAE,CA2Bb"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { isCommentLine, splitLines } from "./util.js";
|
|
3
|
+
export function runCustomRules(file, rules) {
|
|
4
|
+
const violations = [];
|
|
5
|
+
const posixPath = file.path.split(path.sep).join("/");
|
|
6
|
+
for (const rule of rules) {
|
|
7
|
+
if (!pathAllowed(posixPath, rule)) {
|
|
8
|
+
continue;
|
|
9
|
+
}
|
|
10
|
+
const lines = splitLines(file.text);
|
|
11
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
12
|
+
const line = lines[i];
|
|
13
|
+
if (isCommentLine(line)) {
|
|
14
|
+
continue;
|
|
15
|
+
}
|
|
16
|
+
const match = rule.pattern.exec(line);
|
|
17
|
+
if (match) {
|
|
18
|
+
violations.push({
|
|
19
|
+
ruleId: rule.id,
|
|
20
|
+
message: rule.message,
|
|
21
|
+
severity: rule.severity,
|
|
22
|
+
file: file.path,
|
|
23
|
+
line: i + 1,
|
|
24
|
+
column: match.index + 1,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return violations;
|
|
30
|
+
}
|
|
31
|
+
function pathAllowed(posixPath, rule) {
|
|
32
|
+
if (rule.excluded?.some((pattern) => matchesPathRegex(posixPath, pattern))) {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
if (rule.included && rule.included.length > 0) {
|
|
36
|
+
return rule.included.some((pattern) => matchesPathRegex(posixPath, pattern));
|
|
37
|
+
}
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
function matchesPathRegex(posixPath, pattern) {
|
|
41
|
+
return new RegExp(pattern).test(posixPath);
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=customRules.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"customRules.js","sourceRoot":"","sources":["../src/customRules.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEtD,MAAM,UAAU,cAAc,CAC5B,IAAgB,EAChB,KAAyB;IAEzB,MAAM,UAAU,GAAgB,EAAE,CAAC;IACnC,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACtD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,WAAW,CAAC,SAAS,EAAE,IAAI,CAAC,EAAE,CAAC;YAClC,SAAS;QACX,CAAC;QACD,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;YACzC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YACtB,IAAI,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC;gBACxB,SAAS;YACX,CAAC;YACD,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACtC,IAAI,KAAK,EAAE,CAAC;gBACV,UAAU,CAAC,IAAI,CAAC;oBACd,MAAM,EAAE,IAAI,CAAC,EAAE;oBACf,OAAO,EAAE,IAAI,CAAC,OAAO;oBACrB,QAAQ,EAAE,IAAI,CAAC,QAAQ;oBACvB,IAAI,EAAE,IAAI,CAAC,IAAI;oBACf,IAAI,EAAE,CAAC,GAAG,CAAC;oBACX,MAAM,EAAE,KAAK,CAAC,KAAK,GAAG,CAAC;iBACxB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,SAAS,WAAW,CAAC,SAAiB,EAAE,IAAsB;IAC5D,IAAI,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,gBAAgB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC;QAC3E,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9C,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,gBAAgB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC;IAC/E,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,gBAAgB,CAAC,SAAiB,EAAE,OAAe;IAC1D,OAAO,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AAC7C,CAAC"}
|