@eslint-sh/eslint-plugin 0.3.0 → 0.4.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.
Files changed (38) hide show
  1. package/README.md +10 -6
  2. package/dist/eslint-plugin.d.ts +91 -68
  3. package/dist/index.d.ts +12 -26
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +10 -26
  6. package/dist/index.js.map +1 -1
  7. package/dist/language/selector-classes.d.ts +6 -10
  8. package/dist/language/selector-classes.d.ts.map +1 -1
  9. package/dist/language/selector-classes.js +6 -9
  10. package/dist/language/selector-classes.js.map +1 -1
  11. package/dist/language/shell-language-options.d.ts +9 -11
  12. package/dist/language/shell-language-options.d.ts.map +1 -1
  13. package/dist/language/shell-language-options.js +7 -11
  14. package/dist/language/shell-language-options.js.map +1 -1
  15. package/dist/language/shell-language.d.ts +10 -12
  16. package/dist/language/shell-language.d.ts.map +1 -1
  17. package/dist/language/shell-language.js +45 -79
  18. package/dist/language/shell-language.js.map +1 -1
  19. package/dist/language/shell-source-code.d.ts +10 -19
  20. package/dist/language/shell-source-code.d.ts.map +1 -1
  21. package/dist/language/shell-source-code.js +165 -62
  22. package/dist/language/shell-source-code.js.map +1 -1
  23. package/dist/language/source-coordinates.d.ts +23 -0
  24. package/dist/language/source-coordinates.d.ts.map +1 -0
  25. package/dist/language/source-coordinates.js +58 -0
  26. package/dist/language/source-coordinates.js.map +1 -0
  27. package/dist/language/syntax-view.d.ts +60 -0
  28. package/dist/language/syntax-view.d.ts.map +1 -0
  29. package/dist/language/syntax-view.js +164 -0
  30. package/dist/language/syntax-view.js.map +1 -0
  31. package/dist/language/word-resolution.d.ts +11 -0
  32. package/dist/language/word-resolution.d.ts.map +1 -0
  33. package/dist/language/word-resolution.js +18 -0
  34. package/dist/language/word-resolution.js.map +1 -0
  35. package/docs/custom-rule-tutorial.md +4 -4
  36. package/docs/examples/no-rm-rf-rule.mjs +2 -2
  37. package/docs/selectors.md +9 -0
  38. package/package.json +9 -3
package/README.md CHANGED
@@ -27,14 +27,14 @@ suppress it: for a rule you've configured as `sh/your-rule`,
27
27
  - `plugin` (default export) — `{ meta: { name, version, namespace: "sh" }, languages: { sh:
28
28
  ShellLanguage }, rules: {} }`. `meta.version` always matches this package's `package.json`.
29
29
  - `ShellLanguage` — the `@eslint/core` `Language` implementation: `fileType: "text"`,
30
- `lineStart`/`columnStart: 1`, `nodeTypeKey: "type"`, the bridge's generated `visitorKeys`,
30
+ `lineStart`/`columnStart: 1`, `nodeTypeKey: "type"`, the consumer's schema-derived `visitorKeys`,
31
31
  `validateLanguageOptions`/`normalizeLanguageOptions` for the
32
32
  `{dialect, shellVersion, directivePrefix}` schema, `parse`/`createSourceCode`, and
33
33
  `matchesSelectorClass` for the six launch esquery selector classes (`:command`, `:loop`,
34
34
  `:conditional`, `:expansion`, `:quoted`, `:function` — see the
35
35
  [selector cookbook](./docs/selectors.md)).
36
36
  - `ShellSourceCode` — extends `@eslint/plugin-kit`'s `TextSourceCodeBase`; implements `traverse()`
37
- (driven by the bridge's `visitorKeys`, yielding two-phase `VisitNodeStep`s), `getParent()`, and
37
+ (driven by the consumer's `visitorKeys`, yielding two-phase `VisitNodeStep`s), `getParent()`, and
38
38
  the disable-directive surface (`getDisableDirectives()`, `getInlineConfigNodes()`,
39
39
  `applyInlineConfig()`).
40
40
  - `ShellLanguageOptions` / `NormalizedShellLanguageOptions` / `ShellLanguageOptionsJSON` — the
@@ -42,13 +42,17 @@ ShellLanguage }, rules: {} }`. `meta.version` always matches this package's `pac
42
42
  prefix directive/inline-config comments must start with — e.g. the default `"eslint"` recognizes
43
43
  `# eslint-disable-next-line ...`; consumers who already overload `# eslint-*` comments for
44
44
  something else can configure a different prefix (e.g. `directivePrefix: 'shellcheck-sh'`).
45
- - `resolveWord` — re-export of `sh-ast`'s word-resolution helper, so a project that installs only
45
+ - `ShellNode` / `ShellFile` / `ShellComment` / `ShellPosition` — the plugin's lint view: lowercase
46
+ fields, UTF-16 ranges, and one-based UTF-16 locations, independent of the raw parser syntax.
47
+ Locations come from one parse-time position snapshot and remain bound to that original source;
48
+ projecting the view does not run live bounds operations on every syntax subtree.
49
+ - `resolveWord` — adapts a parsed lint Word to `sh-ast`'s word-resolution helper, so a project that installs only
46
50
  this package can write custom rules that resolve static shell words (e.g. the `no-rm-rf` example
47
51
  in the [custom-rule tutorial](./docs/custom-rule-tutorial.md)) without a separate `sh-ast`
48
- install.
52
+ install. Fabricated nodes are rejected because they have no original syntax association.
49
53
 
50
- Parse failures surface as fatal lint messages at mvdan/sh's real reported position (never a 1:1
51
- placeholder) — see `ShParseError` in `sh-ast`.
54
+ Syntax failures surface as fatal lint messages at mvdan/sh's reported byte offset, converted to
55
+ the source's UTF-16 location. Failures without a valid syntax position use a 1:1 fallback.
52
56
 
53
57
  ## Writing your own rules
54
58
 
@@ -4,32 +4,26 @@ import type { FileProblem } from '@eslint/core';
4
4
  import type { Language } from '@eslint/core';
5
5
  import type { OkParseResult } from '@eslint/core';
6
6
  import type { ParseResult } from '@eslint/core';
7
- import { resolveWord as resolveWord_2 } from 'sh-ast/analyze';
7
+ import type { ResolveWordOptions } from 'sh-ast/analyze';
8
8
  import type { RulesConfig } from '@eslint/core';
9
- import type { ShellDialect } from 'sh-ast';
10
- import type { ShFile } from 'sh-ast';
11
- import type { ShNode } from 'sh-ast';
12
- import type { ShNodes } from 'sh-ast';
13
9
  import type { SourceLocation } from '@eslint/core';
14
10
  import { TextSourceCodeBase } from '@eslint/plugin-kit';
15
11
  import type { TraversalStep } from '@eslint/core';
12
+ import type { WordResolution } from 'sh-ast/analyze';
16
13
 
17
14
  /**
18
- * The `@eslint-sh/eslint-plugin` plugin object (design/PACKAGES.md,
19
- * `@eslint-sh/eslint-plugin`): `languages.sh` provides `ShellLanguage` /
20
- * `ShellSourceCode` (design/ARCHITECTURE.md, "SourceCode and Language
21
- * objects"), selected in a flat config via `language: "sh/sh"`
22
- * (`namespace: "sh"`). `meta.version` is read from this package's own
23
- * `package.json` at runtime — never hardcoded (see `version.ts`).
15
+ * The `@eslint-sh/eslint-plugin` plugin object: `languages.sh` provides
16
+ * `ShellLanguage` / `ShellSourceCode`, selected in a flat config via
17
+ * `language: "sh/sh"` (`namespace: "sh"`). `meta.version` is read from this
18
+ * package's own `package.json` at runtime — never hardcoded (see
19
+ * `version.ts`).
24
20
  *
25
- * `rules` is empty at this milestone (M2 — `ShellLanguage`/`ShellSourceCode`
26
- * core, plus the six launch esquery selector classes); rules and shared
27
- * `configs` are Milestone 3 (design/MILESTONES.md). Adding them later is
28
- * additive, not a breaking change to this object's shape.
21
+ * The empty `rules` registry lets consumers supply their own rules while
22
+ * sharing parsing, selectors, source coordinates, and directive semantics.
29
23
  *
30
24
  * Re-exported, unchanged, as the default export of the `eslint-sh` umbrella
31
- * package (design/PACKAGES.md's Naming decision): importing this package or
32
- * the umbrella package both yield the same plugin object.
25
+ * package: importing this package or the umbrella package both yield the
26
+ * same plugin object.
33
27
  */
34
28
  declare const _default: {
35
29
  meta: {
@@ -64,24 +58,38 @@ export declare interface NormalizedShellLanguageOptions extends Record<string, u
64
58
  }
65
59
 
66
60
  /**
67
- * Re-exported from `sh-ast/analyze` so a project that installs only
68
- * `@eslint-sh/eslint-plugin` can write custom rules that resolve static
69
- * shell words (e.g. `docs/custom-rule-tutorial.md`'s `no-rm-rf` example)
70
- * without a separate `sh-ast` install or relying on npm hoisting to make
71
- * `sh-ast` resolvable from the consumer's own `node_modules`. Declared
72
- * locally (instead of a bare re-export statement) so API Extractor
73
- * attaches this doc comment and its public release tag to the committed
74
- * api-report instead of emitting it as an untagged export.
75
- *
61
+ * Resolves a parsed lint Word using the upstream-shaped syntax associated with it.
62
+ * The view supplies locations and selector fields; sh-ast/analyze owns the word
63
+ * interpretation. Fabricated or synthetic view nodes have no source syntax and
64
+ * are rejected instead of being treated as known or unknown shell values.
76
65
  * @public
77
66
  */
78
- export declare const resolveWord: typeof resolveWord_2;
67
+ export declare function resolveWord(word: ShellNode, options?: ResolveWordOptions): WordResolution;
68
+
69
+ /** Directive processing uses the comment text without its leading shell hash. @public */
70
+ export declare interface ShellComment extends ShellNode {
71
+ /** Comment discriminator used by directive collection. */
72
+ readonly type: 'Comment';
73
+ /** Decoded comment content after the leading hash, preserving its whitespace. */
74
+ readonly text: string;
75
+ }
76
+
77
+ /** Owns ESLint configuration labels and validates their consumer-facing meaning before parsing. */
78
+ /** The dialect labels understood by ESLint configuration, mapped to upstream numeric variants when parsing. @public */
79
+ export declare type ShellDialect = 'bash' | 'posix' | 'mksh' | 'bats' | 'zsh';
80
+
81
+ /** The lint root has a statement collection even when upstream represents it as nil. @public */
82
+ export declare interface ShellFile extends ShellNode {
83
+ /** Root discriminator retained for selectors. */
84
+ readonly type: 'File';
85
+ /** Top-level statements in source order; nil upstream slices become an empty view. */
86
+ readonly stmts: readonly ShellNode[];
87
+ }
79
88
 
80
89
  /**
81
90
  * `ShellLanguage` — the `@eslint/core` `Language` implementation for shell
82
- * scripts (design/ARCHITECTURE.md, "SourceCode and Language objects";
83
- * design/PACKAGES.md, `@eslint-sh/eslint-plugin`). Registered by the plugin
84
- * as `languages.sh`, so consumers select it via `language: "sh/sh"`.
91
+ * scripts. Registered by the plugin as `languages.sh`, so consumers select
92
+ * it via `language: "sh/sh"`.
85
93
  *
86
94
  * Implements `matchesSelectorClass` (the six launch esquery selector
87
95
  * classes — see `./selector-classes.js`), so rules and end users can write
@@ -124,23 +132,22 @@ export declare class ShellLanguage implements Language {
124
132
  * needed there, but `:loop :command` is) match a whole family of node
125
133
  * types instead of one literal type name. Delegates to
126
134
  * `./selector-classes.js`'s `SELECTOR_CLASS_NODE_TYPES` table for the six
127
- * launch classes (design/ARCHITECTURE.md, "SourceCode and Language
128
- * objects"); `ancestry` is unused today because none of the six launch
135
+ * launch classes; `ancestry` is unused today because none of the six launch
129
136
  * classes need ancestor context, but the parameter is accepted to match
130
137
  * `Language.matchesSelectorClass`'s signature exactly.
131
138
  */
132
- matchesSelectorClass(className: string, node: ShNode, _ancestry: ShNode[]): boolean;
139
+ matchesSelectorClass(className: string, node: ShellNode, _ancestry: ShellNode[]): boolean;
133
140
  /**
134
141
  * Parses `file.body` (guaranteed to be a `string`, since `fileType` is
135
- * `"text"`) via `sh-ast`'s `parseSync`, mapping the result to
142
+ * `"text"`) with one synchronous parse and its original-position snapshot,
143
+ * mapping the result to
136
144
  * the `{ok: true, ast}` / `{ok: false, errors}` shape `Language.parse` is
137
145
  * required to return. Never throws — parse failures are reported as
138
- * fatal lint messages, per the `Language` contract
139
- * (design/ARCHITECTURE.md, "Parse errors and dialects").
146
+ * fatal lint messages, per the `Language` contract.
140
147
  */
141
148
  parse(file: File_2, context: {
142
149
  languageOptions: ShellLanguageOptions;
143
- }): ParseResult<ShFile>;
150
+ }): ParseResult<ShellFile>;
144
151
  /**
145
152
  * Creates the `ShellSourceCode` ESLint uses to run rules against `ast`.
146
153
  * `context.languageOptions` is ESLint's already-normalized copy (see
@@ -152,18 +159,16 @@ export declare class ShellLanguage implements Language {
152
159
  * direct construction (e.g. tests that skip the `Language` normalization
153
160
  * step), mirroring `parse()`'s `dialect` default above.
154
161
  */
155
- createSourceCode(file: File_2, parseResult: OkParseResult<ShFile>, context: {
162
+ createSourceCode(file: File_2, parseResult: OkParseResult<ShellFile>, context: {
156
163
  languageOptions: ShellLanguageOptions;
157
164
  }): ShellSourceCode;
158
165
  }
159
166
 
160
167
  /**
161
- * `languageOptions` accepted by {@link ShellLanguage} (design/PACKAGES.md's
162
- * `languageOptions` schema): `dialect` selects mvdan/sh's `LangVariant` by
163
- * string name (default `"bash"`); `shellVersion` is consumed by the
164
- * rule layer (e.g. the bash-3.2 compatibility pack), never by the parser
165
- * itself (see design/ARCHITECTURE.md, "A verified nuance worth stating
166
- * loudly").
168
+ * `languageOptions` accepted by {@link ShellLanguage}: `dialect` selects
169
+ * mvdan/sh's `LangVariant` through a consumer-owned mapping (default `"bash"`); `shellVersion`
170
+ * is consumed by the rule layer (e.g. the bash-3.2 compatibility pack),
171
+ * never by the parser itself.
167
172
  *
168
173
  * Extends `Record<string, unknown>` (rather than a bare interface) so this
169
174
  * type satisfies the `@eslint/core` package's `LanguageOptions` bound
@@ -182,8 +187,7 @@ export declare interface ShellLanguageOptions extends Record<string, unknown> {
182
187
  * default `"eslint"` recognizes `# eslint-disable-next-line ...` and
183
188
  * `# eslint <rule-config>`. Consumers who embed shell-linting inside a
184
189
  * larger toolchain that already overloads `#eslint-*` comments for
185
- * something else can configure a different prefix (design/ARCHITECTURE.md,
186
- * "SourceCode and Language objects").
190
+ * something else can configure a different prefix.
187
191
  * @defaultValue `"eslint"`
188
192
  */
189
193
  readonly directivePrefix?: string;
@@ -212,13 +216,40 @@ export declare interface ShellLanguageOptionsJSON {
212
216
  readonly shellVersion?: string;
213
217
  }
214
218
 
219
+ /**
220
+ * A node in the consumer's lint view. Scalar/child fields use lowercase upstream
221
+ * spellings; syntax fidelity belongs to the associated upstream tree. Auxiliary
222
+ * view nodes may have spans derived from children and are not upstream Nodes.
223
+ * @public
224
+ */
225
+ export declare interface ShellNode {
226
+ /** Original syntax kind retained as the discriminator for lint selectors. */
227
+ readonly type: string;
228
+ /** Half-open UTF-16 span used to slice source and place fixes. */
229
+ readonly range: readonly [number, number];
230
+ /** Source-derived endpoints for ESLint diagnostics. */
231
+ readonly loc: {
232
+ readonly start: ShellPosition;
233
+ readonly end: ShellPosition;
234
+ };
235
+ /** Lowercase syntax fields containing consumer children or decoded scalar values. */
236
+ readonly [field: string]: unknown;
237
+ }
238
+
239
+ /** An ESLint location counts UTF-16 units, with both line and column starting at one. @public */
240
+ export declare interface ShellPosition {
241
+ /** One-based source line, with CRLF treated as one line break. */
242
+ readonly line: number;
243
+ /** One-based UTF-16 column; tabs and grapheme widths are not expanded. */
244
+ readonly column: number;
245
+ }
246
+
215
247
  /**
216
248
  * `ShellSourceCode` — the `SourceCode` object ESLint uses to work with a
217
- * parsed shell file (design/ARCHITECTURE.md, "SourceCode and Language
218
- * objects"). Extends `@eslint/plugin-kit`'s `TextSourceCodeBase`, which
249
+ * parsed shell file. Extends `@eslint/plugin-kit`'s `TextSourceCodeBase`, which
219
250
  * already implements `getLoc`/`getRange`/`getText`/`lines` (both by reading
220
251
  * the normalized node's own `loc`/`range` fields — see
221
- * `sh-ast`'s "Normalized node shape"), `getLocFromIndex`, and
252
+ * the consumer's source-view contract), `getLocFromIndex`, and
222
253
  * `getIndexFromLoc`; this class adds the two members the base class
223
254
  * deliberately leaves unimplemented: `traverse()` (base throws "Not
224
255
  * implemented") and `getParent()` (base throws "Not implemented", and
@@ -230,7 +261,7 @@ export declare interface ShellLanguageOptionsJSON {
230
261
  * (`<prefix>-disable`, `<prefix>-enable`, `<prefix>-disable-line`,
231
262
  * `<prefix>-disable-next-line`) plus whole-file inline rule config
232
263
  * (bare `<prefix> <rule-config>`), sourced from `Comment` nodes gathered via
233
- * `sh-ast`'s structural `walk()` and parsed with
264
+ * the consumer's `walkShell()` and parsed with
234
265
  * `@eslint/plugin-kit`'s `ConfigCommentParser` — the same building blocks
235
266
  * `@eslint/json`'s `JSONSourceCode` uses, generalized so the `<prefix>` is
236
267
  * configurable (default `"eslint"`; see `ShellLanguageOptions.directivePrefix`)
@@ -244,14 +275,14 @@ export declare interface ShellLanguageOptionsJSON {
244
275
  */
245
276
  export declare class ShellSourceCode extends TextSourceCodeBase<{
246
277
  LangOptions: ShellLanguageOptions;
247
- RootNode: ShFile;
248
- SyntaxElementWithLoc: ShNode;
249
- ConfigNode: ShNodes.ShCommentNode;
278
+ RootNode: ShellFile;
279
+ SyntaxElementWithLoc: ShellNode;
280
+ ConfigNode: ShellComment;
250
281
  }> {
251
282
  #private;
252
283
  constructor(options: {
253
284
  text: string;
254
- ast: ShFile;
285
+ ast: ShellFile;
255
286
  directivePrefix?: string;
256
287
  });
257
288
  /**
@@ -261,19 +292,11 @@ export declare class ShellSourceCode extends TextSourceCodeBase<{
261
292
  * so in practice the map is always populated by the time a rule observes
262
293
  * it.
263
294
  */
264
- getParent(node: ShNode): ShNode | undefined;
295
+ getParent(node: ShellNode): ShellNode | undefined;
265
296
  /**
266
- * Traverses the AST pre-order, yielding a `VisitNodeStep` on node enter
267
- * (`phase: 1`) and another on node exit (`phase: 2`) for every node —
268
- * exactly the two-phase shape `@eslint/json`/`@eslint/css` produce, which
269
- * is what lets rule listeners use `NodeType` and `NodeType:exit` esquery
270
- * selectors. Children are discovered via `sh-ast`'s generated,
271
- * frozen `visitorKeys` table (per node `type`) — **not** structurally
272
- * (contrast `sh-ast`'s own `walk()`, which deliberately walks
273
- * structurally so its correctness never depends on that table) — because
274
- * ESLint's traversal contract is defined in terms of a language's
275
- * declared `visitorKeys`, and this class's whole job is to honor that
276
- * contract for shell ASTs.
297
+ * Produces the enter/exit steps ESLint uses for selectors and ancestor lookup.
298
+ * Child keys describe the consumer view, including its auxiliary records.
299
+ * This callback protocol is ESLint's, independent of upstream syntax.Walk.
277
300
  */
278
301
  traverse(): Iterable<TraversalStep>;
279
302
  /**
@@ -284,7 +307,7 @@ export declare class ShellSourceCode extends TextSourceCodeBase<{
284
307
  * effect" when `linterOptions.noInlineConfig` is set — see
285
308
  * `eslint`'s `lib/linter/linter.js`, the `warnInlineConfig` branch).
286
309
  */
287
- getInlineConfigNodes(): ShNodes.ShCommentNode[];
310
+ getInlineConfigNodes(): ShellComment[];
288
311
  /**
289
312
  * Returns the disable/enable directives found among
290
313
  * {@link ShellSourceCode.getInlineConfigNodes}'s comments, recognizing all four forms —
@@ -316,7 +339,7 @@ export declare class ShellSourceCode extends TextSourceCodeBase<{
316
339
  * calling this method — and `getDisableDirectives`, together, since both
317
340
  * are gated by the same flag in `eslint`'s own `linter.js` — and instead
318
341
  * calls `getInlineConfigNodes` to emit a "has no effect" warning per
319
- * comment; see design/ARCHITECTURE.md, "SourceCode and Language objects").
342
+ * comment).
320
343
  */
321
344
  applyInlineConfig(): {
322
345
  configs: {
package/dist/index.d.ts CHANGED
@@ -1,37 +1,23 @@
1
- import { resolveWord as shAstResolveWord } from 'sh-ast/analyze';
2
1
  import { ShellLanguage } from './language/shell-language.js';
3
2
  export { ShellLanguage } from './language/shell-language.js';
4
3
  export { ShellSourceCode } from './language/shell-source-code.js';
5
4
  export type { NormalizedShellLanguageOptions, ShellLanguageOptions, ShellLanguageOptionsJSON, } from './language/shell-language-options.js';
5
+ export { resolveWord } from './language/word-resolution.js';
6
+ export type { ShellFile, ShellNode, ShellComment, ShellPosition } from './language/syntax-view.js';
7
+ export type { ShellDialect } from './language/shell-language-options.js';
6
8
  /**
7
- * Re-exported from `sh-ast/analyze` so a project that installs only
8
- * `@eslint-sh/eslint-plugin` can write custom rules that resolve static
9
- * shell words (e.g. `docs/custom-rule-tutorial.md`'s `no-rm-rf` example)
10
- * without a separate `sh-ast` install or relying on npm hoisting to make
11
- * `sh-ast` resolvable from the consumer's own `node_modules`. Declared
12
- * locally (instead of a bare re-export statement) so API Extractor
13
- * attaches this doc comment and its public release tag to the committed
14
- * api-report instead of emitting it as an untagged export.
9
+ * The `@eslint-sh/eslint-plugin` plugin object: `languages.sh` provides
10
+ * `ShellLanguage` / `ShellSourceCode`, selected in a flat config via
11
+ * `language: "sh/sh"` (`namespace: "sh"`). `meta.version` is read from this
12
+ * package's own `package.json` at runtime — never hardcoded (see
13
+ * `version.ts`).
15
14
  *
16
- * @public
17
- */
18
- export declare const resolveWord: typeof shAstResolveWord;
19
- /**
20
- * The `@eslint-sh/eslint-plugin` plugin object (design/PACKAGES.md,
21
- * `@eslint-sh/eslint-plugin`): `languages.sh` provides `ShellLanguage` /
22
- * `ShellSourceCode` (design/ARCHITECTURE.md, "SourceCode and Language
23
- * objects"), selected in a flat config via `language: "sh/sh"`
24
- * (`namespace: "sh"`). `meta.version` is read from this package's own
25
- * `package.json` at runtime — never hardcoded (see `version.ts`).
26
- *
27
- * `rules` is empty at this milestone (M2 — `ShellLanguage`/`ShellSourceCode`
28
- * core, plus the six launch esquery selector classes); rules and shared
29
- * `configs` are Milestone 3 (design/MILESTONES.md). Adding them later is
30
- * additive, not a breaking change to this object's shape.
15
+ * The empty `rules` registry lets consumers supply their own rules while
16
+ * sharing parsing, selectors, source coordinates, and directive semantics.
31
17
  *
32
18
  * Re-exported, unchanged, as the default export of the `eslint-sh` umbrella
33
- * package (design/PACKAGES.md's Naming decision): importing this package or
34
- * the umbrella package both yield the same plugin object.
19
+ * package: importing this package or the umbrella package both yield the
20
+ * same plugin object.
35
21
  */
36
22
  declare const _default: {
37
23
  meta: {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,IAAI,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAG7D,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAClE,YAAY,EACV,8BAA8B,EAC9B,oBAAoB,EACpB,wBAAwB,GACzB,MAAM,sCAAsC,CAAC;AAE9C;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,WAAW,yBAAmB,CAAC;AAE5C;;;;;;;;;;;;;;;;GAgBG;;;;;;;;;;;;AACH,wBAUmB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAG7D,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAClE,YAAY,EACV,8BAA8B,EAC9B,oBAAoB,EACpB,wBAAwB,GACzB,MAAM,sCAAsC,CAAC;AAE9C,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAC5D,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AACnG,YAAY,EAAE,YAAY,EAAE,MAAM,sCAAsC,CAAC;AAEzE;;;;;;;;;;;;;GAaG;;;;;;;;;;;;AACH,wBAUmB"}
package/dist/index.js CHANGED
@@ -1,37 +1,21 @@
1
- import { resolveWord as shAstResolveWord } from 'sh-ast/analyze';
2
1
  import { ShellLanguage } from './language/shell-language.js';
3
2
  import { readPackageVersion } from './version.js';
4
3
  export { ShellLanguage } from './language/shell-language.js';
5
4
  export { ShellSourceCode } from './language/shell-source-code.js';
5
+ export { resolveWord } from './language/word-resolution.js';
6
6
  /**
7
- * Re-exported from `sh-ast/analyze` so a project that installs only
8
- * `@eslint-sh/eslint-plugin` can write custom rules that resolve static
9
- * shell words (e.g. `docs/custom-rule-tutorial.md`'s `no-rm-rf` example)
10
- * without a separate `sh-ast` install or relying on npm hoisting to make
11
- * `sh-ast` resolvable from the consumer's own `node_modules`. Declared
12
- * locally (instead of a bare re-export statement) so API Extractor
13
- * attaches this doc comment and its public release tag to the committed
14
- * api-report instead of emitting it as an untagged export.
7
+ * The `@eslint-sh/eslint-plugin` plugin object: `languages.sh` provides
8
+ * `ShellLanguage` / `ShellSourceCode`, selected in a flat config via
9
+ * `language: "sh/sh"` (`namespace: "sh"`). `meta.version` is read from this
10
+ * package's own `package.json` at runtime — never hardcoded (see
11
+ * `version.ts`).
15
12
  *
16
- * @public
17
- */
18
- export const resolveWord = shAstResolveWord;
19
- /**
20
- * The `@eslint-sh/eslint-plugin` plugin object (design/PACKAGES.md,
21
- * `@eslint-sh/eslint-plugin`): `languages.sh` provides `ShellLanguage` /
22
- * `ShellSourceCode` (design/ARCHITECTURE.md, "SourceCode and Language
23
- * objects"), selected in a flat config via `language: "sh/sh"`
24
- * (`namespace: "sh"`). `meta.version` is read from this package's own
25
- * `package.json` at runtime — never hardcoded (see `version.ts`).
26
- *
27
- * `rules` is empty at this milestone (M2 — `ShellLanguage`/`ShellSourceCode`
28
- * core, plus the six launch esquery selector classes); rules and shared
29
- * `configs` are Milestone 3 (design/MILESTONES.md). Adding them later is
30
- * additive, not a breaking change to this object's shape.
13
+ * The empty `rules` registry lets consumers supply their own rules while
14
+ * sharing parsing, selectors, source coordinates, and directive semantics.
31
15
  *
32
16
  * Re-exported, unchanged, as the default export of the `eslint-sh` umbrella
33
- * package (design/PACKAGES.md's Naming decision): importing this package or
34
- * the umbrella package both yield the same plugin object.
17
+ * package: importing this package or the umbrella package both yield the
18
+ * same plugin object.
35
19
  */
36
20
  export default {
37
21
  meta: {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,IAAI,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAElD,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAOlE;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,gBAAgB,CAAC;AAE5C;;;;;;;;;;;;;;;;GAgBG;AACH,eAAe;IACb,IAAI,EAAE;QACJ,IAAI,EAAE,0BAA0B;QAChC,OAAO,EAAE,kBAAkB,EAAE;QAC7B,SAAS,EAAE,IAAI;KAChB;IACD,SAAS,EAAE;QACT,EAAE,EAAE,IAAI,aAAa,EAAE;KACxB;IACD,KAAK,EAAE,EAAE;CACO,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAElD,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAOlE,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAI5D;;;;;;;;;;;;;GAaG;AACH,eAAe;IACb,IAAI,EAAE;QACJ,IAAI,EAAE,0BAA0B;QAChC,OAAO,EAAE,kBAAkB,EAAE;QAC7B,SAAS,EAAE,IAAI;KAChB;IACD,SAAS,EAAE;QACT,EAAE,EAAE,IAAI,aAAa,EAAE;KACxB;IACD,KAAK,EAAE,EAAE;CACO,CAAC"}
@@ -1,8 +1,7 @@
1
- import type { ShNode } from 'sh-ast';
1
+ import type { ShellNode as ShNode } from './syntax-view.js';
2
2
  /**
3
3
  * The six launch esquery selector classes `ShellLanguage.matchesSelectorClass`
4
- * implements (design/ARCHITECTURE.md, "SourceCode and Language objects";
5
- * the issue that introduced this module). Keys are the *bare* class name —
4
+ * implements. Keys are the *bare* class name —
6
5
  * esquery strips the leading `:` before invoking a language's
7
6
  * `matchesSelectorClass` (confirmed against `esquery`'s own `case 'class'`
8
7
  * matcher, which calls `options.matchClass(selector.name, node, ancestry)`
@@ -10,18 +9,15 @@ import type { ShNode } from 'sh-ast';
10
9
  * `:command` calls this table with `"command"`, not `":command"`.
11
10
  *
12
11
  * `:loop` intentionally matches only `ForClause` and `WhileClause` — the
13
- * two loop *statement* nodes, exactly as the bridge's generated schema
14
- * names them (`packages/bridge/generated/visitor-keys.js`), even though
15
- * design/ARCHITECTURE.md's prose shorthand says "For/While". `CStyleLoop`
12
+ * two loop *statement* nodes in the upstream syntax schema. `CStyleLoop`
16
13
  * is deliberately excluded from `:loop`: it is `ForClause.loop`'s nested
17
- * C-style arithmetic header (`init`/`cond`/`post` — see
18
- * `packages/bridge/generated/node-types.d.ts`'s `ShCStyleLoopNode`), not a
14
+ * C-style arithmetic header (`init`/`cond`/`post`), not a
19
15
  * loop statement in its own right. A `for ((i=0;i<3;i++))` loop's outer
20
16
  * node is still `ForClause`, so `:loop` already reaches every C-style loop
21
17
  * without needing to include `CStyleLoop` itself.
22
18
  *
23
- * `as const satisfies Record<string, readonly ShNodes.ShNodeTypeName[]>`
24
- * pins every listed node type to a real member of the bridge's generated
19
+ * `as const satisfies Record<string, readonly Node['Type'][]>`
20
+ * pins every listed node type to a real member of the parser's generated
25
21
  * type union — a typo or a since-renamed node type here is a compile error,
26
22
  * not a silent no-op match.
27
23
  *
@@ -1 +1 @@
1
- {"version":3,"file":"selector-classes.d.ts","sourceRoot":"","sources":["../../src/language/selector-classes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAW,MAAM,QAAQ,CAAC;AAE9C;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,eAAO,MAAM,yBAAyB;;;;;;;CAOgC,CAAC;AAEvE;;;;;GAKG;AACH,MAAM,MAAM,iBAAiB,GAAG,MAAM,OAAO,yBAAyB,CAAC;AASvE;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAE7E"}
1
+ {"version":3,"file":"selector-classes.d.ts","sourceRoot":"","sources":["../../src/language/selector-classes.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,IAAI,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE5D;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,yBAAyB;;;;;;;CAOsB,CAAC;AAE7D;;;;;GAKG;AACH,MAAM,MAAM,iBAAiB,GAAG,MAAM,OAAO,yBAAyB,CAAC;AAUvE;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAE7E"}
@@ -1,7 +1,6 @@
1
1
  /**
2
2
  * The six launch esquery selector classes `ShellLanguage.matchesSelectorClass`
3
- * implements (design/ARCHITECTURE.md, "SourceCode and Language objects";
4
- * the issue that introduced this module). Keys are the *bare* class name —
3
+ * implements. Keys are the *bare* class name —
5
4
  * esquery strips the leading `:` before invoking a language's
6
5
  * `matchesSelectorClass` (confirmed against `esquery`'s own `case 'class'`
7
6
  * matcher, which calls `options.matchClass(selector.name, node, ancestry)`
@@ -9,18 +8,15 @@
9
8
  * `:command` calls this table with `"command"`, not `":command"`.
10
9
  *
11
10
  * `:loop` intentionally matches only `ForClause` and `WhileClause` — the
12
- * two loop *statement* nodes, exactly as the bridge's generated schema
13
- * names them (`packages/bridge/generated/visitor-keys.js`), even though
14
- * design/ARCHITECTURE.md's prose shorthand says "For/While". `CStyleLoop`
11
+ * two loop *statement* nodes in the upstream syntax schema. `CStyleLoop`
15
12
  * is deliberately excluded from `:loop`: it is `ForClause.loop`'s nested
16
- * C-style arithmetic header (`init`/`cond`/`post` — see
17
- * `packages/bridge/generated/node-types.d.ts`'s `ShCStyleLoopNode`), not a
13
+ * C-style arithmetic header (`init`/`cond`/`post`), not a
18
14
  * loop statement in its own right. A `for ((i=0;i<3;i++))` loop's outer
19
15
  * node is still `ForClause`, so `:loop` already reaches every C-style loop
20
16
  * without needing to include `CStyleLoop` itself.
21
17
  *
22
- * `as const satisfies Record<string, readonly ShNodes.ShNodeTypeName[]>`
23
- * pins every listed node type to a real member of the bridge's generated
18
+ * `as const satisfies Record<string, readonly Node['Type'][]>`
19
+ * pins every listed node type to a real member of the parser's generated
24
20
  * type union — a typo or a since-renamed node type here is a compile error,
25
21
  * not a silent no-op match.
26
22
  *
@@ -34,6 +30,7 @@ export const SELECTOR_CLASS_NODE_TYPES = {
34
30
  quoted: ['SglQuoted', 'DblQuoted'],
35
31
  function: ['FuncDecl'],
36
32
  };
33
+ /** Membership is independent of syntax field values or source positions. */
37
34
  const nodeTypesByClassName = new Map(Object.entries(SELECTOR_CLASS_NODE_TYPES).map(([className, nodeTypes]) => [
38
35
  className,
39
36
  new Set(nodeTypes),
@@ -1 +1 @@
1
- {"version":3,"file":"selector-classes.js","sourceRoot":"","sources":["../../src/language/selector-classes.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG;IACvC,OAAO,EAAE,CAAC,UAAU,CAAC;IACrB,IAAI,EAAE,CAAC,WAAW,EAAE,aAAa,CAAC;IAClC,WAAW,EAAE,CAAC,UAAU,EAAE,YAAY,CAAC;IACvC,SAAS,EAAE,CAAC,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,CAAC;IAC7D,MAAM,EAAE,CAAC,WAAW,EAAE,WAAW,CAAC;IAClC,QAAQ,EAAE,CAAC,UAAU,CAAC;CAC8C,CAAC;AAUvE,MAAM,oBAAoB,GAA6C,IAAI,GAAG,CAC5E,MAAM,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,EAAE,SAAS,CAAC,EAAE,EAAE,CAAC;IACxE,SAAS;IACT,IAAI,GAAG,CAAS,SAAS,CAAC;CAC3B,CAAC,CACH,CAAC;AAEF;;;;;;;;;;GAUG;AACH,MAAM,UAAU,oBAAoB,CAAC,SAAiB,EAAE,IAAY;IAClE,OAAO,oBAAoB,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC;AACtE,CAAC"}
1
+ {"version":3,"file":"selector-classes.js","sourceRoot":"","sources":["../../src/language/selector-classes.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG;IACvC,OAAO,EAAE,CAAC,UAAU,CAAC;IACrB,IAAI,EAAE,CAAC,WAAW,EAAE,aAAa,CAAC;IAClC,WAAW,EAAE,CAAC,UAAU,EAAE,YAAY,CAAC;IACvC,SAAS,EAAE,CAAC,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,CAAC;IAC7D,MAAM,EAAE,CAAC,WAAW,EAAE,WAAW,CAAC;IAClC,QAAQ,EAAE,CAAC,UAAU,CAAC;CACoC,CAAC;AAU7D,4EAA4E;AAC5E,MAAM,oBAAoB,GAA6C,IAAI,GAAG,CAC5E,MAAM,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,EAAE,SAAS,CAAC,EAAE,EAAE,CAAC;IACxE,SAAS;IACT,IAAI,GAAG,CAAS,SAAS,CAAC;CAC3B,CAAC,CACH,CAAC;AAEF;;;;;;;;;;GAUG;AACH,MAAM,UAAU,oBAAoB,CAAC,SAAiB,EAAE,IAAY;IAClE,OAAO,oBAAoB,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC;AACtE,CAAC"}
@@ -1,11 +1,11 @@
1
- import type { ShellDialect } from 'sh-ast';
1
+ /** Owns ESLint configuration labels and validates their consumer-facing meaning before parsing. */
2
+ /** The dialect labels understood by ESLint configuration, mapped to upstream numeric variants when parsing. @public */
3
+ export type ShellDialect = 'bash' | 'posix' | 'mksh' | 'bats' | 'zsh';
2
4
  /**
3
- * `languageOptions` accepted by {@link ShellLanguage} (design/PACKAGES.md's
4
- * `languageOptions` schema): `dialect` selects mvdan/sh's `LangVariant` by
5
- * string name (default `"bash"`); `shellVersion` is consumed by the
6
- * rule layer (e.g. the bash-3.2 compatibility pack), never by the parser
7
- * itself (see design/ARCHITECTURE.md, "A verified nuance worth stating
8
- * loudly").
5
+ * `languageOptions` accepted by {@link ShellLanguage}: `dialect` selects
6
+ * mvdan/sh's `LangVariant` through a consumer-owned mapping (default `"bash"`); `shellVersion`
7
+ * is consumed by the rule layer (e.g. the bash-3.2 compatibility pack),
8
+ * never by the parser itself.
9
9
  *
10
10
  * Extends `Record<string, unknown>` (rather than a bare interface) so this
11
11
  * type satisfies the `@eslint/core` package's `LanguageOptions` bound
@@ -24,8 +24,7 @@ export interface ShellLanguageOptions extends Record<string, unknown> {
24
24
  * default `"eslint"` recognizes `# eslint-disable-next-line ...` and
25
25
  * `# eslint <rule-config>`. Consumers who embed shell-linting inside a
26
26
  * larger toolchain that already overloads `#eslint-*` comments for
27
- * something else can configure a different prefix (design/ARCHITECTURE.md,
28
- * "SourceCode and Language objects").
27
+ * something else can configure a different prefix.
29
28
  * @defaultValue `"eslint"`
30
29
  */
31
30
  readonly directivePrefix?: string;
@@ -79,8 +78,7 @@ export interface NormalizedShellLanguageOptions extends Record<string, unknown>
79
78
  * nonexistent version like `'99.99'` is accepted — shape is validated, not
80
79
  * membership in a known-versions list), or when `directivePrefix` is present
81
80
  * but not a valid directive-comment label (see {@link DIRECTIVE_PREFIX_PATTERN}).
82
- * Unknown keys are silently ignored, per the ESLint `Language` contract
83
- * (design/ARCHITECTURE.md's `languageOptions` schema comment).
81
+ * Unknown keys are silently ignored, per the ESLint `Language` contract.
84
82
  *
85
83
  * The parameter is treated as `Record<string, unknown>` internally (rather
86
84
  * than trusting {@link ShellLanguageOptions}'s declared field types) because
@@ -1 +1 @@
1
- {"version":3,"file":"shell-language-options.d.ts","sourceRoot":"","sources":["../../src/language/shell-language-options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AA4D3C;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,oBAAqB,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IACnE,QAAQ,CAAC,OAAO,CAAC,EAAE,YAAY,CAAC;IAChC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAE/B;;;;;;;;OAQG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;CACnC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAC/B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAChC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,8BAA+B,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC7E,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAC/B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,MAAM,IAAI,wBAAwB,CAAC;CACpC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,4BAA4B,CAAC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CA8B3F;AAED;;;;;;;;;GASG;AACH,wBAAgB,6BAA6B,CAC3C,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACvC,8BAA8B,CAkBhC"}
1
+ {"version":3,"file":"shell-language-options.d.ts","sourceRoot":"","sources":["../../src/language/shell-language-options.ts"],"names":[],"mappings":"AAAA,mGAAmG;AACnG,uHAAuH;AACvH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,CAAC;AAyDtE;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,oBAAqB,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IACnE,QAAQ,CAAC,OAAO,CAAC,EAAE,YAAY,CAAC;IAChC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAE/B;;;;;;;OAOG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;CACnC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAC/B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAChC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,8BAA+B,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC7E,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAC/B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,MAAM,IAAI,wBAAwB,CAAC;CACpC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,4BAA4B,CAAC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CA8B3F;AAED;;;;;;;;;GASG;AACH,wBAAgB,6BAA6B,CAC3C,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACvC,8BAA8B,CAkBhC"}
@@ -1,22 +1,18 @@
1
1
  /**
2
2
  * The full set of dialects {@link ShellLanguage.validateLanguageOptions}
3
3
  * accepts, in the order surfaced by its error message. Mirrors
4
- * `sh-ast`'s `SUPPORTED_SHELL_DIALECTS` (see
5
- * design/ARCHITECTURE.md, "Parse errors and dialects", and
6
- * design/PACKAGES.md's `languageOptions` schema) — kept as an independent
7
- * constant here (rather than imported) because the bridge does not export
8
- * its internal list; both lists are exercised by tests that pin the same
9
- * five dialect names.
4
+ * the consumer's configuration labels; the syntax interface itself accepts
5
+ * upstream numeric constants rather than these configuration strings.
10
6
  */
11
7
  const SUPPORTED_SHELL_DIALECTS = ['bash', 'posix', 'mksh', 'bats', 'zsh'];
8
+ /** Narrows configuration labels without treating arbitrary strings as parser variants. */
12
9
  function isShellDialect(value) {
13
10
  return (typeof value === 'string' && SUPPORTED_SHELL_DIALECTS.includes(value));
14
11
  }
15
12
  /**
16
13
  * Default for {@link ShellLanguageOptions.directivePrefix} — the
17
- * ESLint-conventional spelling (design/ARCHITECTURE.md, "SourceCode and
18
- * Language objects": "The directive prefix is configurable but defaults to
19
- * the ESLint-conventional spelling").
14
+ * ESLint-conventional spelling. The directive prefix is configurable but
15
+ * defaults to the ESLint-conventional spelling.
20
16
  */
21
17
  const DEFAULT_DIRECTIVE_PREFIX = 'eslint';
22
18
  /**
@@ -29,6 +25,7 @@ const DEFAULT_DIRECTIVE_PREFIX = 'eslint';
29
25
  * is a strict improvement.
30
26
  */
31
27
  const DIRECTIVE_PREFIX_PATTERN = /^[a-z]+(?:-[a-z]+)*$/u;
28
+ /** Requires a label that the directive parser can recognize once a command suffix is appended. */
32
29
  function isValidDirectivePrefix(value) {
33
30
  return typeof value === 'string' && DIRECTIVE_PREFIX_PATTERN.test(value);
34
31
  }
@@ -56,8 +53,7 @@ function isValidShellVersionShape(value) {
56
53
  * nonexistent version like `'99.99'` is accepted — shape is validated, not
57
54
  * membership in a known-versions list), or when `directivePrefix` is present
58
55
  * but not a valid directive-comment label (see {@link DIRECTIVE_PREFIX_PATTERN}).
59
- * Unknown keys are silently ignored, per the ESLint `Language` contract
60
- * (design/ARCHITECTURE.md's `languageOptions` schema comment).
56
+ * Unknown keys are silently ignored, per the ESLint `Language` contract.
61
57
  *
62
58
  * The parameter is treated as `Record<string, unknown>` internally (rather
63
59
  * than trusting {@link ShellLanguageOptions}'s declared field types) because
@@ -1 +1 @@
1
- {"version":3,"file":"shell-language-options.js","sourceRoot":"","sources":["../../src/language/shell-language-options.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AACH,MAAM,wBAAwB,GAA4B,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;AAEnG,SAAS,cAAc,CAAC,KAAc;IACpC,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ,IAAK,wBAA8C,CAAC,QAAQ,CAAC,KAAK,CAAC,CAC7F,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,wBAAwB,GAAG,QAAQ,CAAC;AAE1C;;;;;;;;GAQG;AACH,MAAM,wBAAwB,GAAG,uBAAuB,CAAC;AAEzD,SAAS,sBAAsB,CAAC,KAAc;IAC5C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,wBAAwB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC3E,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,qBAAqB,GAAG,kBAAkB,CAAC;AAEjD,SAAS,wBAAwB,CAAC,KAAa;IAC7C,OAAO,qBAAqB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC3C,CAAC;AA6ED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,4BAA4B,CAAC,eAAwC;IACnF,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,GAAG,eAAe,CAAC;IACnE,IAAI,OAAO,KAAK,SAAS,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,CAAC;QACtD,MAAM,IAAI,SAAS,CACjB,oEAAoE,wBAAwB,CAAC,IAAI,CAC/F,IAAI,CACL,cAAc,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,CAC1C,CAAC;IACJ,CAAC;IACD,IAAI,YAAY,KAAK,SAAS,IAAI,OAAO,YAAY,KAAK,QAAQ,EAAE,CAAC;QACnE,MAAM,IAAI,SAAS,CACjB,kGAAkG,IAAI,CAAC,SAAS,CAC9G,YAAY,CACb,GAAG,CACL,CAAC;IACJ,CAAC;IACD,IAAI,OAAO,YAAY,KAAK,QAAQ,IAAI,CAAC,wBAAwB,CAAC,YAAY,CAAC,EAAE,CAAC;QAChF,MAAM,IAAI,SAAS,CACjB,yHAAyH,IAAI,CAAC,SAAS,CACrI,YAAY,CACb,GAAG,CACL,CAAC;IACJ,CAAC;IACD,IAAI,eAAe,KAAK,SAAS,IAAI,CAAC,sBAAsB,CAAC,eAAe,CAAC,EAAE,CAAC;QAC9E,MAAM,IAAI,SAAS,CACjB,8JAA8J,IAAI,CAAC,SAAS,CAC1K,eAAe,CAChB,GAAG,CACL,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,6BAA6B,CAC3C,eAAwC;IAExC,MAAM,OAAO,GAAI,eAAe,CAAC,OAAoC,IAAI,MAAM,CAAC;IAChF,MAAM,eAAe,GAClB,eAAe,CAAC,eAAsC,IAAI,wBAAwB,CAAC;IACtF,MAAM,YAAY,GAAG,eAAe,CAAC,YAAkC,CAAC;IACxE,OAAO;QACL,OAAO;QACP,eAAe;QACf,mEAAmE;QACnE,wEAAwE;QACxE,+DAA+D;QAC/D,GAAG,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC;QACvD,MAAM;YACJ,OAAO,YAAY,KAAK,SAAS;gBAC/B,CAAC,CAAC,EAAE,OAAO,EAAE,eAAe,EAAE;gBAC9B,CAAC,CAAC,EAAE,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,CAAC;QACjD,CAAC;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"shell-language-options.js","sourceRoot":"","sources":["../../src/language/shell-language-options.ts"],"names":[],"mappings":"AAIA;;;;;GAKG;AACH,MAAM,wBAAwB,GAA4B,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;AAEnG,0FAA0F;AAC1F,SAAS,cAAc,CAAC,KAAc;IACpC,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ,IAAK,wBAA8C,CAAC,QAAQ,CAAC,KAAK,CAAC,CAC7F,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,wBAAwB,GAAG,QAAQ,CAAC;AAE1C;;;;;;;;GAQG;AACH,MAAM,wBAAwB,GAAG,uBAAuB,CAAC;AAEzD,kGAAkG;AAClG,SAAS,sBAAsB,CAAC,KAAc;IAC5C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,wBAAwB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC3E,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,qBAAqB,GAAG,kBAAkB,CAAC;AAEjD,SAAS,wBAAwB,CAAC,KAAa;IAC7C,OAAO,qBAAqB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC3C,CAAC;AA0ED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,4BAA4B,CAAC,eAAwC;IACnF,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,GAAG,eAAe,CAAC;IACnE,IAAI,OAAO,KAAK,SAAS,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,CAAC;QACtD,MAAM,IAAI,SAAS,CACjB,oEAAoE,wBAAwB,CAAC,IAAI,CAC/F,IAAI,CACL,cAAc,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,CAC1C,CAAC;IACJ,CAAC;IACD,IAAI,YAAY,KAAK,SAAS,IAAI,OAAO,YAAY,KAAK,QAAQ,EAAE,CAAC;QACnE,MAAM,IAAI,SAAS,CACjB,kGAAkG,IAAI,CAAC,SAAS,CAC9G,YAAY,CACb,GAAG,CACL,CAAC;IACJ,CAAC;IACD,IAAI,OAAO,YAAY,KAAK,QAAQ,IAAI,CAAC,wBAAwB,CAAC,YAAY,CAAC,EAAE,CAAC;QAChF,MAAM,IAAI,SAAS,CACjB,yHAAyH,IAAI,CAAC,SAAS,CACrI,YAAY,CACb,GAAG,CACL,CAAC;IACJ,CAAC;IACD,IAAI,eAAe,KAAK,SAAS,IAAI,CAAC,sBAAsB,CAAC,eAAe,CAAC,EAAE,CAAC;QAC9E,MAAM,IAAI,SAAS,CACjB,8JAA8J,IAAI,CAAC,SAAS,CAC1K,eAAe,CAChB,GAAG,CACL,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,6BAA6B,CAC3C,eAAwC;IAExC,MAAM,OAAO,GAAI,eAAe,CAAC,OAAoC,IAAI,MAAM,CAAC;IAChF,MAAM,eAAe,GAClB,eAAe,CAAC,eAAsC,IAAI,wBAAwB,CAAC;IACtF,MAAM,YAAY,GAAG,eAAe,CAAC,YAAkC,CAAC;IACxE,OAAO;QACL,OAAO;QACP,eAAe;QACf,mEAAmE;QACnE,wEAAwE;QACxE,+DAA+D;QAC/D,GAAG,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC;QACvD,MAAM;YACJ,OAAO,YAAY,KAAK,SAAS;gBAC/B,CAAC,CAAC,EAAE,OAAO,EAAE,eAAe,EAAE;gBAC9B,CAAC,CAAC,EAAE,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,CAAC;QACjD,CAAC;KACF,CAAC;AACJ,CAAC"}