@jrc03c/gtlint 0.12.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.
Files changed (152) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +235 -0
  3. package/bin/gtlint.js +4 -0
  4. package/dist/cli.d.ts +3 -0
  5. package/dist/cli.d.ts.map +1 -0
  6. package/dist/cli.js +248 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/config.d.ts +32 -0
  9. package/dist/config.d.ts.map +1 -0
  10. package/dist/config.js +112 -0
  11. package/dist/config.js.map +1 -0
  12. package/dist/formatter/formatter.d.ts +22 -0
  13. package/dist/formatter/formatter.d.ts.map +1 -0
  14. package/dist/formatter/formatter.js +376 -0
  15. package/dist/formatter/formatter.js.map +1 -0
  16. package/dist/formatter/index.d.ts +2 -0
  17. package/dist/formatter/index.d.ts.map +1 -0
  18. package/dist/formatter/index.js +2 -0
  19. package/dist/formatter/index.js.map +1 -0
  20. package/dist/index.d.ts +11 -0
  21. package/dist/index.d.ts.map +1 -0
  22. package/dist/index.js +12 -0
  23. package/dist/index.js.map +1 -0
  24. package/dist/language/index.d.ts +8 -0
  25. package/dist/language/index.d.ts.map +1 -0
  26. package/dist/language/index.js +8 -0
  27. package/dist/language/index.js.map +1 -0
  28. package/dist/language/keyword-spec.d.ts +87 -0
  29. package/dist/language/keyword-spec.d.ts.map +1 -0
  30. package/dist/language/keyword-spec.js +772 -0
  31. package/dist/language/keyword-spec.js.map +1 -0
  32. package/dist/lexer/index.d.ts +3 -0
  33. package/dist/lexer/index.d.ts.map +1 -0
  34. package/dist/lexer/index.js +3 -0
  35. package/dist/lexer/index.js.map +1 -0
  36. package/dist/lexer/lexer.d.ts +36 -0
  37. package/dist/lexer/lexer.d.ts.map +1 -0
  38. package/dist/lexer/lexer.js +709 -0
  39. package/dist/lexer/lexer.js.map +1 -0
  40. package/dist/lexer/tokens.d.ts +45 -0
  41. package/dist/lexer/tokens.d.ts.map +1 -0
  42. package/dist/lexer/tokens.js +170 -0
  43. package/dist/lexer/tokens.js.map +1 -0
  44. package/dist/linter/directives.d.ts +71 -0
  45. package/dist/linter/directives.d.ts.map +1 -0
  46. package/dist/linter/directives.js +329 -0
  47. package/dist/linter/directives.js.map +1 -0
  48. package/dist/linter/index.d.ts +6 -0
  49. package/dist/linter/index.d.ts.map +1 -0
  50. package/dist/linter/index.js +4 -0
  51. package/dist/linter/index.js.map +1 -0
  52. package/dist/linter/linter.d.ts +39 -0
  53. package/dist/linter/linter.d.ts.map +1 -0
  54. package/dist/linter/linter.js +292 -0
  55. package/dist/linter/linter.js.map +1 -0
  56. package/dist/linter/rules/correct-indentation.d.ts +22 -0
  57. package/dist/linter/rules/correct-indentation.d.ts.map +1 -0
  58. package/dist/linter/rules/correct-indentation.js +111 -0
  59. package/dist/linter/rules/correct-indentation.js.map +1 -0
  60. package/dist/linter/rules/goto-needs-reset-in-events.d.ts +28 -0
  61. package/dist/linter/rules/goto-needs-reset-in-events.d.ts.map +1 -0
  62. package/dist/linter/rules/goto-needs-reset-in-events.js +88 -0
  63. package/dist/linter/rules/goto-needs-reset-in-events.js.map +1 -0
  64. package/dist/linter/rules/indent-style.d.ts +3 -0
  65. package/dist/linter/rules/indent-style.d.ts.map +1 -0
  66. package/dist/linter/rules/indent-style.js +41 -0
  67. package/dist/linter/rules/indent-style.js.map +1 -0
  68. package/dist/linter/rules/index.d.ts +5 -0
  69. package/dist/linter/rules/index.d.ts.map +1 -0
  70. package/dist/linter/rules/index.js +47 -0
  71. package/dist/linter/rules/index.js.map +1 -0
  72. package/dist/linter/rules/no-duplicate-labels.d.ts +3 -0
  73. package/dist/linter/rules/no-duplicate-labels.d.ts.map +1 -0
  74. package/dist/linter/rules/no-duplicate-labels.js +75 -0
  75. package/dist/linter/rules/no-duplicate-labels.js.map +1 -0
  76. package/dist/linter/rules/no-empty-blocks.d.ts +15 -0
  77. package/dist/linter/rules/no-empty-blocks.d.ts.map +1 -0
  78. package/dist/linter/rules/no-empty-blocks.js +45 -0
  79. package/dist/linter/rules/no-empty-blocks.js.map +1 -0
  80. package/dist/linter/rules/no-inline-argument.d.ts +14 -0
  81. package/dist/linter/rules/no-inline-argument.d.ts.map +1 -0
  82. package/dist/linter/rules/no-inline-argument.js +56 -0
  83. package/dist/linter/rules/no-inline-argument.js.map +1 -0
  84. package/dist/linter/rules/no-invalid-goto.d.ts +3 -0
  85. package/dist/linter/rules/no-invalid-goto.d.ts.map +1 -0
  86. package/dist/linter/rules/no-invalid-goto.js +92 -0
  87. package/dist/linter/rules/no-invalid-goto.js.map +1 -0
  88. package/dist/linter/rules/no-single-quotes.d.ts +3 -0
  89. package/dist/linter/rules/no-single-quotes.d.ts.map +1 -0
  90. package/dist/linter/rules/no-single-quotes.js +73 -0
  91. package/dist/linter/rules/no-single-quotes.js.map +1 -0
  92. package/dist/linter/rules/no-unclosed-bracket.d.ts +3 -0
  93. package/dist/linter/rules/no-unclosed-bracket.d.ts.map +1 -0
  94. package/dist/linter/rules/no-unclosed-bracket.js +108 -0
  95. package/dist/linter/rules/no-unclosed-bracket.js.map +1 -0
  96. package/dist/linter/rules/no-unclosed-string.d.ts +3 -0
  97. package/dist/linter/rules/no-unclosed-string.d.ts.map +1 -0
  98. package/dist/linter/rules/no-unclosed-string.js +48 -0
  99. package/dist/linter/rules/no-unclosed-string.js.map +1 -0
  100. package/dist/linter/rules/no-undefined-vars.d.ts +3 -0
  101. package/dist/linter/rules/no-undefined-vars.d.ts.map +1 -0
  102. package/dist/linter/rules/no-undefined-vars.js +257 -0
  103. package/dist/linter/rules/no-undefined-vars.js.map +1 -0
  104. package/dist/linter/rules/no-unreachable-code.d.ts +3 -0
  105. package/dist/linter/rules/no-unreachable-code.d.ts.map +1 -0
  106. package/dist/linter/rules/no-unreachable-code.js +215 -0
  107. package/dist/linter/rules/no-unreachable-code.js.map +1 -0
  108. package/dist/linter/rules/no-unused-labels.d.ts +3 -0
  109. package/dist/linter/rules/no-unused-labels.d.ts.map +1 -0
  110. package/dist/linter/rules/no-unused-labels.js +77 -0
  111. package/dist/linter/rules/no-unused-labels.js.map +1 -0
  112. package/dist/linter/rules/no-unused-vars.d.ts +3 -0
  113. package/dist/linter/rules/no-unused-vars.d.ts.map +1 -0
  114. package/dist/linter/rules/no-unused-vars.js +288 -0
  115. package/dist/linter/rules/no-unused-vars.js.map +1 -0
  116. package/dist/linter/rules/purchase-subkeyword-constraints.d.ts +15 -0
  117. package/dist/linter/rules/purchase-subkeyword-constraints.d.ts.map +1 -0
  118. package/dist/linter/rules/purchase-subkeyword-constraints.js +88 -0
  119. package/dist/linter/rules/purchase-subkeyword-constraints.js.map +1 -0
  120. package/dist/linter/rules/required-subkeywords.d.ts +14 -0
  121. package/dist/linter/rules/required-subkeywords.d.ts.map +1 -0
  122. package/dist/linter/rules/required-subkeywords.js +64 -0
  123. package/dist/linter/rules/required-subkeywords.js.map +1 -0
  124. package/dist/linter/rules/valid-keyword.d.ts +3 -0
  125. package/dist/linter/rules/valid-keyword.d.ts.map +1 -0
  126. package/dist/linter/rules/valid-keyword.js +41 -0
  127. package/dist/linter/rules/valid-keyword.js.map +1 -0
  128. package/dist/linter/rules/valid-sub-keyword.d.ts +3 -0
  129. package/dist/linter/rules/valid-sub-keyword.d.ts.map +1 -0
  130. package/dist/linter/rules/valid-sub-keyword.js +89 -0
  131. package/dist/linter/rules/valid-sub-keyword.js.map +1 -0
  132. package/dist/linter/rules/valid-subkeyword-value.d.ts +16 -0
  133. package/dist/linter/rules/valid-subkeyword-value.d.ts.map +1 -0
  134. package/dist/linter/rules/valid-subkeyword-value.js +100 -0
  135. package/dist/linter/rules/valid-subkeyword-value.js.map +1 -0
  136. package/dist/parser/ast.d.ts +119 -0
  137. package/dist/parser/ast.d.ts.map +1 -0
  138. package/dist/parser/ast.js +58 -0
  139. package/dist/parser/ast.js.map +1 -0
  140. package/dist/parser/index.d.ts +3 -0
  141. package/dist/parser/index.d.ts.map +1 -0
  142. package/dist/parser/index.js +3 -0
  143. package/dist/parser/index.js.map +1 -0
  144. package/dist/parser/parser.d.ts +55 -0
  145. package/dist/parser/parser.d.ts.map +1 -0
  146. package/dist/parser/parser.js +608 -0
  147. package/dist/parser/parser.js.map +1 -0
  148. package/dist/types.d.ts +44 -0
  149. package/dist/types.d.ts.map +1 -0
  150. package/dist/types.js +36 -0
  151. package/dist/types.js.map +1 -0
  152. package/package.json +49 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Spark Wave
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,235 @@
1
+ # GTLint ✨
2
+
3
+ **GTLint** is a linter, formatter, and syntax highlighter for the [GuidedTrack](https://guidedtrack.com) language, inspired by ESLint and Prettier. It can be used at the command line or installed as a VSCode extension.
4
+
5
+ - [Disclaimer](#disclaimer)
6
+ - [VSCode extension](#vscode-extension)
7
+ - [Installation](#installation)
8
+ - [Usage](#usage)
9
+ - [Command Line](#command-line)
10
+ - [Installation](#installation-1)
11
+ - [Usage](#usage-1)
12
+ - [Configuration](#configuration) (i.e., project-wide settings)
13
+ - [Directives](#directives) (i.e., inline settings)
14
+ - [Tests](#tests)
15
+ - [License](#license)
16
+
17
+ ![VSCode extension](https://github.com/user-attachments/assets/71fc166f-1980-4e2d-a84f-41188f6e0dbe)
18
+
19
+ ![CLI tool](https://github.com/user-attachments/assets/06734d44-794c-475c-b5e2-c389a5f5a34c)
20
+
21
+ # Disclaimer
22
+
23
+ This tool was written almost exclusively by [Claude Code](https://claude.com/product/claude-code). [Josh Castle](https://github.com/jrc03c) directed Claude Code and made a few small changes to `CLAUDE.md`, `README.md`, and the GuidedTrack files in the `samples` directory; but virtually everything else was written by Claude Code.
24
+
25
+ # VSCode extension
26
+
27
+ ## Installation
28
+
29
+ (1) Download the `.vsix` file from here:
30
+
31
+ [https://github.com/jrc03c/gtlint/releases/latest/download/gtlint.vsix](https://github.com/jrc03c/gtlint/releases/latest/download/gtlint.vsix)
32
+
33
+ (2) In VSCode, open the command palette and search for "vsix":
34
+
35
+ ![](https://github.com/user-attachments/assets/03128194-04c5-4991-9acd-e9efb3e38ec9)
36
+
37
+ Select "Extensions: Install from VSIX...".
38
+
39
+ (3) Select the `gtlint.vsix` file that you downloaded in the first step.
40
+
41
+ ## Usage
42
+
43
+ The linter works while you write code in `.gt` files and will show errors as soon as it detects them. The formatter will format code in `.gt` files on save.
44
+
45
+ See the [Configuration](#configuration) section below for more info about how to control the extension's behavior.
46
+
47
+ # Command Line
48
+
49
+ ## Installation
50
+
51
+ > **NOTE:** Requires [Node](https://nodejs.org/en).
52
+
53
+ In a specific project:
54
+
55
+ ```bash
56
+ npm install --save-dev @jrc03c/gtlint
57
+ ```
58
+
59
+ Or globally:
60
+
61
+ ```bash
62
+ npm install -g @jrc03c/gtlint
63
+ ```
64
+
65
+ ## Usage
66
+
67
+ > **NOTE:** When installed in a specific project, GTLint must be invoked with `npx gtlint`. When installed globally, it can be invoked with just `gtlint`. The examples below assume that it has been installed in a specific project.
68
+
69
+ **Syntax:**
70
+
71
+ ```
72
+ # lint:
73
+ npx gtlint lint [options] [files]
74
+
75
+ # format:
76
+ npx gtlint format [options] [files]
77
+ ```
78
+
79
+ **Show help:**
80
+
81
+ ```bash
82
+ npx gtlint
83
+ ```
84
+
85
+ **Lint:**
86
+
87
+ ```bash
88
+ # show errors and warnings in a particular file
89
+ npx gtlint lint path/to/some-file.gt
90
+
91
+ # show all errors and warnings in all *.gt files in a directory (recursive)
92
+ npx gtlint lint path/to/some-dir
93
+ ```
94
+
95
+ **Format:**
96
+
97
+ ```bash
98
+ # format a specific file
99
+ npx gtlint format path/to/some-file.gt
100
+
101
+ # format all *.gt files in a directory (recursive)
102
+ npx gtlint format path/to/some-dir
103
+ ```
104
+
105
+ See the [Configuration](#configuration) section below for more info about how to control the command line tool's behavior.
106
+
107
+ # Configuration
108
+
109
+ The linter's and formatter's default behaviors can be controlled by settings in a `gtlint.config.js` file at the root of a repository. Here's a sample configuration file containing all of the default values:
110
+
111
+ ```js
112
+ export default {
113
+ // formatter settings
114
+ format: {
115
+ insertFinalNewline: true,
116
+ spaceAfterComma: true,
117
+ spaceAroundArrow: true,
118
+ spaceAroundOperators: true,
119
+ trimTrailingWhitespace: true,
120
+ },
121
+
122
+ // linter settings
123
+ rules: {
124
+ correctIndentation: "error",
125
+ indentStyle: "error",
126
+ noDuplicateLabels: "error",
127
+ noInvalidGoto: "error",
128
+ noSingleQuotes: "warn",
129
+ noUnclosedBracket: "error",
130
+ noUnclosedString: "error",
131
+ noUndefinedVars: "error",
132
+ noUnusedVars: "warn",
133
+ validKeyword: "error",
134
+ validSubKeyword: "error",
135
+ },
136
+ }
137
+ ```
138
+
139
+ Linter rules can have these values:
140
+
141
+ - `"off"` or `0` - Disable the rule
142
+ - `"warn"` or `1` - Show as warning (doesn't fail linting)
143
+ - `"error"` or `2` - Show as error (fails linting)
144
+
145
+ # Directives
146
+
147
+ The linter's and formatter's behaviors can also be overridden by inline _directives_ written directly into `.gt` files. Directives are always commented out. For example:
148
+
149
+ ```
150
+ -- @to-child: email_address
151
+ >> email_address = "someone@example.com"
152
+ *program: Add to Mailing List
153
+ ```
154
+
155
+ Here are the available directives and what they do:
156
+
157
+ **Combined (lint + format):**
158
+
159
+ - **`@gt-disable`**<br>
160
+ Disable lint + format until `@gt-enable` or EOF
161
+
162
+ - **`@gt-enable`**<br>
163
+ Re-enable lint + format
164
+
165
+ - **`@gt-disable-next-line`**<br>
166
+ Disable lint + format for next line only
167
+
168
+ - **`@gt-disable-next-line rule1, rule2`**<br>
169
+ Disable specific lint rules + format for next line
170
+
171
+ **Lint-only:**
172
+
173
+ - **`@gtlint-disable`**<br>
174
+ Disable all lint rules until `@gtlint-enable` or EOF
175
+
176
+ - **`@gtlint-disable rule1, rule2`**<br>
177
+ Disable specific lint rules
178
+
179
+ - **`@gtlint-enable`**<br>
180
+ Re-enable all lint rules
181
+
182
+ - **`@gtlint-enable rule1`**<br>
183
+ Re-enable specific lint rule
184
+
185
+ - **`@gtlint-disable-next-line`**<br>
186
+ Disable all lint rules for next line
187
+
188
+ - **`@gtlint-disable-next-line rule1, rule2`**<br>
189
+ Disable specific rules for next line
190
+
191
+ - **`@from-child: var1, var2, ...`**<br>
192
+ Do not mark listed variables as undefined (because they are defined in a child program); warns if a listed variable is never used
193
+
194
+ - **`@from-parent: var1, var2, ...`**<br>
195
+ Do not mark listed variables as undefined (because they are defined in a parent program); warns if a listed variable is never used or if its value is overwritten before being read
196
+
197
+ - **`@from-url: var1, var2, ...`**<br>
198
+ Do not mark listed variables as undefined (because they are defined in URL query string parameters); warns if a listed variable is never used or if its value is overwritten before being read
199
+
200
+ - **`@to-child: var1, var2, ...`**<br>
201
+ Do not mark listed variables as unused (because they will be used in a child program)
202
+
203
+ - **`@to-parent: var1, var2, ...`**<br>
204
+ Do not mark listed variables as unused (because they will be used in a parent program)
205
+
206
+ - **`@to-csv: var1, var2, ...`**<br>
207
+ Do not mark listed variables as unused (because they will be saved in the root program's CSV)
208
+
209
+ > **NOTE:** Inline directive rule names always use kebab-case (e.g., `no-unused-vars`), even though config files use camelCase.
210
+
211
+ **Format-only:**
212
+
213
+ - **`@gtformat-disable`**<br>
214
+ Disable formatting until `@gtformat-enable` or EOF
215
+
216
+ - **`@gtformat-enable`**<br>
217
+ Re-enable formatting
218
+
219
+ > **NOTE:** `@gtformat-*` directives don't support rule lists since formatting isn't rule-based.
220
+
221
+ # Tests
222
+
223
+ ```bash
224
+ pnpm test
225
+ ```
226
+
227
+ The test suite includes integration tests that exercise real GuidedTrack programs from a git submodule (`submodules/gt-lib`). This submodule points to a private repository and is optional. If it's not initialized, those tests are skipped automatically. All other tests will run normally.
228
+
229
+ # Feedback
230
+
231
+ If you run into bugs or have feature requests, please [open an issue](https://github.com/jrc03c/gtlint/issues).
232
+
233
+ # License
234
+
235
+ MIT
package/bin/gtlint.js ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ import { main } from '../dist/cli.js';
3
+
4
+ main(process.argv.slice(2));
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export declare function main(args?: string[]): Promise<void>;
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAgQA,wBAAsB,IAAI,CAAC,IAAI,GAAE,MAAM,EAA0B,GAAG,OAAO,CAAC,IAAI,CAAC,CAkChF"}
package/dist/cli.js ADDED
@@ -0,0 +1,248 @@
1
+ #!/usr/bin/env node
2
+ import { readFileSync, writeFileSync, existsSync, statSync } from 'fs';
3
+ import { resolve, relative, extname, dirname, join } from 'path';
4
+ import { fileURLToPath } from 'url';
5
+ import { globSync } from 'glob';
6
+ import { Linter } from './linter/index.js';
7
+ import { Formatter } from './formatter/index.js';
8
+ import { loadConfig } from './config.js';
9
+ const __dirname = dirname(fileURLToPath(import.meta.url));
10
+ const { version } = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf-8'));
11
+ function printHelp() {
12
+ console.log(`
13
+ gtlint - A linter and formatter for GuidedTrack
14
+
15
+ Usage:
16
+ gtlint lint [options] [files...] Lint GuidedTrack files
17
+ gtlint format [options] [files...] Format GuidedTrack files
18
+
19
+ Lint Options:
20
+ --quiet Only report errors, not warnings
21
+ --format <type> Output format: stylish (default), json, compact
22
+
23
+ Format Options:
24
+ --write Format and write back to files
25
+
26
+ Common Options:
27
+ --config <path> Path to config file
28
+ --help, -h Show this help message
29
+ --version, -v Show version number
30
+
31
+ Examples:
32
+ gtlint lint . Lint all .gt files in current directory
33
+ gtlint lint src/ Lint all .gt files in src directory
34
+ gtlint lint program.gt Lint a specific file
35
+ gtlint format . Print formatted output to stdout
36
+ gtlint format --write . Format all files in place
37
+ `);
38
+ }
39
+ function printVersion() {
40
+ console.log(`gtlint v${version}`);
41
+ }
42
+ function parseArgs(args) {
43
+ const options = {};
44
+ const files = [];
45
+ let command = '';
46
+ let i = 0;
47
+ while (i < args.length) {
48
+ const arg = args[i];
49
+ if (arg === 'lint' || arg === 'format') {
50
+ command = arg;
51
+ }
52
+ else if (arg === '--config' && args[i + 1]) {
53
+ options.config = args[++i];
54
+ }
55
+ else if (arg === '--write') {
56
+ options.write = true;
57
+ }
58
+ else if (arg === '--quiet') {
59
+ options.quiet = true;
60
+ }
61
+ else if (arg === '--format' && args[i + 1]) {
62
+ options.format = args[++i];
63
+ }
64
+ else if (arg === '--help' || arg === '-h') {
65
+ options.help = true;
66
+ }
67
+ else if (arg === '--version' || arg === '-v') {
68
+ options.version = true;
69
+ }
70
+ else if (!arg.startsWith('-')) {
71
+ files.push(arg);
72
+ }
73
+ i++;
74
+ }
75
+ return { command, files, options };
76
+ }
77
+ function findFiles(patterns, ignore) {
78
+ const files = [];
79
+ for (const pattern of patterns) {
80
+ const resolved = resolve(pattern);
81
+ if (existsSync(resolved) && statSync(resolved).isFile()) {
82
+ if (extname(resolved) === '.gt') {
83
+ files.push(resolved);
84
+ }
85
+ }
86
+ else if (existsSync(resolved) && statSync(resolved).isDirectory()) {
87
+ // Find all .gt files in directory
88
+ const globPattern = `${resolved}/**/*.gt`;
89
+ const found = globSync(globPattern, { ignore });
90
+ files.push(...found);
91
+ }
92
+ else {
93
+ // Treat as glob pattern
94
+ const found = globSync(pattern, { ignore });
95
+ files.push(...found.filter(f => extname(f) === '.gt'));
96
+ }
97
+ }
98
+ return [...new Set(files)]; // Remove duplicates
99
+ }
100
+ function formatStylish(results) {
101
+ const lines = [];
102
+ let totalErrors = 0;
103
+ let totalWarnings = 0;
104
+ for (const result of results) {
105
+ if (result.messages.length === 0)
106
+ continue;
107
+ lines.push('');
108
+ lines.push(result.filePath);
109
+ for (const msg of result.messages) {
110
+ const severity = msg.severity === 'error' ? '\x1b[31merror\x1b[0m' : '\x1b[33mwarning\x1b[0m';
111
+ const location = `${msg.line}:${msg.column}`;
112
+ lines.push(` ${location.padEnd(8)} ${severity.padEnd(17)} ${msg.message} \x1b[90m${msg.ruleId}\x1b[0m`);
113
+ }
114
+ totalErrors += result.errorCount;
115
+ totalWarnings += result.warningCount;
116
+ }
117
+ if (totalErrors > 0 || totalWarnings > 0) {
118
+ lines.push('');
119
+ const summary = [];
120
+ if (totalErrors > 0)
121
+ summary.push(`${totalErrors} error${totalErrors === 1 ? '' : 's'}`);
122
+ if (totalWarnings > 0)
123
+ summary.push(`${totalWarnings} warning${totalWarnings === 1 ? '' : 's'}`);
124
+ lines.push(`\x1b[1m${summary.join(', ')}\x1b[0m`);
125
+ }
126
+ return lines.join('\n');
127
+ }
128
+ function formatCompact(results) {
129
+ const lines = [];
130
+ for (const result of results) {
131
+ for (const msg of result.messages) {
132
+ lines.push(`${result.filePath}:${msg.line}:${msg.column}: ${msg.severity}: ${msg.message} [${msg.ruleId}]`);
133
+ }
134
+ }
135
+ return lines.join('\n');
136
+ }
137
+ function formatJson(results) {
138
+ const sanitized = results.map(({ source, output, ...rest }) => rest);
139
+ return JSON.stringify(sanitized, null, 2);
140
+ }
141
+ async function runLint(files, options) {
142
+ const cwd = process.cwd();
143
+ const configPath = options.config || cwd;
144
+ const { linter: linterConfig, ignore } = await loadConfig(configPath);
145
+ const targetFiles = files.length > 0 ? files : ['.'];
146
+ const filePaths = findFiles(targetFiles, ignore);
147
+ if (filePaths.length === 0) {
148
+ console.log('No .gt files found');
149
+ return 0;
150
+ }
151
+ const linter = new Linter(linterConfig);
152
+ const results = [];
153
+ for (const filePath of filePaths) {
154
+ const source = readFileSync(filePath, 'utf-8');
155
+ const relativePath = relative(cwd, filePath);
156
+ const result = linter.lint(source, relativePath);
157
+ results.push(result);
158
+ }
159
+ // Filter warnings if quiet mode
160
+ if (options.quiet) {
161
+ for (const result of results) {
162
+ result.messages = result.messages.filter(m => m.severity === 'error');
163
+ result.warningCount = 0;
164
+ }
165
+ }
166
+ // Format output
167
+ let output;
168
+ switch (options.format) {
169
+ case 'json':
170
+ output = formatJson(results);
171
+ break;
172
+ case 'compact':
173
+ output = formatCompact(results);
174
+ break;
175
+ default:
176
+ output = formatStylish(results);
177
+ }
178
+ if (output.trim()) {
179
+ console.log(output);
180
+ }
181
+ // Return exit code
182
+ const hasErrors = results.some(r => r.errorCount > 0);
183
+ return hasErrors ? 1 : 0;
184
+ }
185
+ async function runFormat(files, options) {
186
+ const cwd = process.cwd();
187
+ const configPath = options.config || cwd;
188
+ const { formatter: formatterConfig, ignore } = await loadConfig(configPath);
189
+ const targetFiles = files.length > 0 ? files : ['.'];
190
+ const filePaths = findFiles(targetFiles, ignore);
191
+ if (filePaths.length === 0) {
192
+ console.log('No .gt files found');
193
+ return 0;
194
+ }
195
+ const formatter = new Formatter(formatterConfig);
196
+ let changedCount = 0;
197
+ for (const filePath of filePaths) {
198
+ const source = readFileSync(filePath, 'utf-8');
199
+ const formatted = formatter.format(source);
200
+ const relativePath = relative(cwd, filePath);
201
+ if (options.write) {
202
+ if (source !== formatted) {
203
+ writeFileSync(filePath, formatted, 'utf-8');
204
+ changedCount++;
205
+ console.log(`Formatted: ${relativePath}`);
206
+ }
207
+ }
208
+ else {
209
+ process.stdout.write(formatted);
210
+ }
211
+ }
212
+ if (options.write && changedCount === 0) {
213
+ console.log('All files are already properly formatted');
214
+ }
215
+ return 0;
216
+ }
217
+ export async function main(args = process.argv.slice(2)) {
218
+ const { command, files, options } = parseArgs(args);
219
+ if (options.help || (!command && !options.version)) {
220
+ printHelp();
221
+ process.exit(0);
222
+ }
223
+ if (options.version) {
224
+ printVersion();
225
+ process.exit(0);
226
+ }
227
+ try {
228
+ let exitCode = 0;
229
+ switch (command) {
230
+ case 'lint':
231
+ exitCode = await runLint(files, options);
232
+ break;
233
+ case 'format':
234
+ exitCode = await runFormat(files, options);
235
+ break;
236
+ default:
237
+ console.error(`Unknown command: ${command}`);
238
+ printHelp();
239
+ exitCode = 1;
240
+ }
241
+ process.exit(exitCode);
242
+ }
243
+ catch (error) {
244
+ console.error('Error:', error instanceof Error ? error.message : error);
245
+ process.exit(1);
246
+ }
247
+ }
248
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ import type { LinterConfig, FormatterConfig } from './types.js';
2
+ export interface GTLintConfig {
3
+ rules?: LinterConfig['rules'];
4
+ format?: Partial<FormatterConfig>;
5
+ ignore?: string[];
6
+ }
7
+ /**
8
+ * Find a config file by searching up the directory tree
9
+ */
10
+ export declare function findConfigFile(startDir: string): string | null;
11
+ /**
12
+ * Load a config file
13
+ */
14
+ export declare function loadConfigFile(configPath: string): Promise<GTLintConfig>;
15
+ /**
16
+ * Merge user config with defaults
17
+ */
18
+ export declare function mergeConfig(userConfig: GTLintConfig): {
19
+ linter: LinterConfig;
20
+ formatter: FormatterConfig;
21
+ ignore: string[];
22
+ };
23
+ /**
24
+ * Load config from a directory or specific file path
25
+ */
26
+ export declare function loadConfig(pathOrDir: string): Promise<{
27
+ linter: LinterConfig;
28
+ formatter: FormatterConfig;
29
+ ignore: string[];
30
+ configPath: string | null;
31
+ }>;
32
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AA4BhE,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC;IAC9B,MAAM,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC;IAClC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAOD;;GAEG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAyB9D;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAQ9E;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,UAAU,EAAE,YAAY,GAAG;IACrD,MAAM,EAAE,YAAY,CAAC;IACrB,SAAS,EAAE,eAAe,CAAC;IAC3B,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CAqBA;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;IAC3D,MAAM,EAAE,YAAY,CAAC;IACrB,SAAS,EAAE,eAAe,CAAC;IAC3B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B,CAAC,CAyBD"}
package/dist/config.js ADDED
@@ -0,0 +1,112 @@
1
+ import { existsSync } from 'fs';
2
+ import { resolve, dirname } from 'path';
3
+ import { pathToFileURL } from 'url';
4
+ import { DEFAULT_LINTER_CONFIG, DEFAULT_FORMATTER_CONFIG } from './types.js';
5
+ /**
6
+ * Convert camelCase to kebab-case (e.g., noUnusedVars → no-unused-vars).
7
+ * Strings that are already kebab-case pass through unchanged.
8
+ */
9
+ function camelToKebab(str) {
10
+ return str.replace(/[A-Z]/g, m => '-' + m.toLowerCase());
11
+ }
12
+ function normalizeRuleKeys(rules) {
13
+ const normalized = {};
14
+ for (const [key, value] of Object.entries(rules)) {
15
+ normalized[camelToKebab(key)] = value;
16
+ }
17
+ return normalized;
18
+ }
19
+ const CONFIG_FILENAMES = [
20
+ 'gtlint.config.js',
21
+ 'gtlint.config.mjs',
22
+ ];
23
+ /**
24
+ * Find a config file by searching up the directory tree
25
+ */
26
+ export function findConfigFile(startDir) {
27
+ let currentDir = resolve(startDir);
28
+ const root = dirname(currentDir);
29
+ while (currentDir !== root) {
30
+ for (const filename of CONFIG_FILENAMES) {
31
+ const configPath = resolve(currentDir, filename);
32
+ if (existsSync(configPath)) {
33
+ return configPath;
34
+ }
35
+ }
36
+ const parentDir = dirname(currentDir);
37
+ if (parentDir === currentDir)
38
+ break;
39
+ currentDir = parentDir;
40
+ }
41
+ // Check root directory
42
+ for (const filename of CONFIG_FILENAMES) {
43
+ const configPath = resolve(currentDir, filename);
44
+ if (existsSync(configPath)) {
45
+ return configPath;
46
+ }
47
+ }
48
+ return null;
49
+ }
50
+ /**
51
+ * Load a config file
52
+ */
53
+ export async function loadConfigFile(configPath) {
54
+ try {
55
+ const fileUrl = pathToFileURL(resolve(configPath)).href;
56
+ const module = await import(fileUrl);
57
+ return module.default || module;
58
+ }
59
+ catch (error) {
60
+ throw new Error(`Failed to load config file: ${configPath}\n${error}`);
61
+ }
62
+ }
63
+ /**
64
+ * Merge user config with defaults
65
+ */
66
+ export function mergeConfig(userConfig) {
67
+ const linterConfig = {
68
+ ...DEFAULT_LINTER_CONFIG,
69
+ rules: {
70
+ ...DEFAULT_LINTER_CONFIG.rules,
71
+ ...(userConfig.rules ? normalizeRuleKeys(userConfig.rules) : {}),
72
+ },
73
+ format: {
74
+ ...DEFAULT_LINTER_CONFIG.format,
75
+ ...userConfig.format,
76
+ },
77
+ };
78
+ const formatterConfig = {
79
+ ...DEFAULT_FORMATTER_CONFIG,
80
+ ...userConfig.format,
81
+ };
82
+ const ignore = userConfig.ignore || ['**/node_modules/**', '**/dist/**'];
83
+ return { linter: linterConfig, formatter: formatterConfig, ignore };
84
+ }
85
+ /**
86
+ * Load config from a directory or specific file path
87
+ */
88
+ export async function loadConfig(pathOrDir) {
89
+ let configPath = null;
90
+ // If path points to a config file, use it directly
91
+ if (pathOrDir.endsWith('.js') || pathOrDir.endsWith('.mjs')) {
92
+ if (existsSync(pathOrDir)) {
93
+ configPath = pathOrDir;
94
+ }
95
+ }
96
+ else {
97
+ // Search for config file
98
+ configPath = findConfigFile(pathOrDir);
99
+ }
100
+ if (configPath) {
101
+ const userConfig = await loadConfigFile(configPath);
102
+ return { ...mergeConfig(userConfig), configPath };
103
+ }
104
+ // No config file found, use defaults
105
+ return {
106
+ linter: DEFAULT_LINTER_CONFIG,
107
+ formatter: DEFAULT_FORMATTER_CONFIG,
108
+ ignore: ['**/node_modules/**', '**/dist/**'],
109
+ configPath: null,
110
+ };
111
+ }
112
+ //# sourceMappingURL=config.js.map