@eslint-sh/eslint-plugin 0.5.0 → 0.6.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/README.md +223 -17
- package/dist/command-harvest/builtins/bash.d.ts +36 -0
- package/dist/command-harvest/builtins/bash.js +98 -0
- package/dist/command-harvest/builtins/bats.d.ts +45 -0
- package/dist/command-harvest/builtins/bats.js +33 -0
- package/dist/command-harvest/builtins/index.d.ts +18 -0
- package/dist/command-harvest/builtins/index.js +39 -0
- package/dist/command-harvest/builtins/posix.d.ts +51 -0
- package/dist/command-harvest/builtins/posix.js +93 -0
- package/dist/command-harvest/harvest-commands.d.ts +66 -0
- package/dist/command-harvest/harvest-commands.js +97 -0
- package/dist/command-harvest/wrapper-table.d.ts +24 -0
- package/dist/command-harvest/wrapper-table.js +49 -0
- package/dist/configs/agent-authored.d.ts +41 -0
- package/dist/configs/agent-authored.js +33 -0
- package/dist/configs/bash-3-2.d.ts +28 -0
- package/dist/configs/bash-3-2.js +50 -0
- package/dist/configs/posix-portable.d.ts +40 -0
- package/dist/configs/posix-portable.js +52 -0
- package/dist/configs/recommended.d.ts +52 -0
- package/dist/configs/recommended.js +34 -0
- package/dist/declaration-conventions/comment-pragma.d.ts +33 -0
- package/dist/declaration-conventions/comment-pragma.js +153 -0
- package/dist/declaration-conventions/declaration-convention.d.ts +189 -0
- package/dist/declaration-conventions/declaration-convention.js +1 -0
- package/dist/declaration-conventions/read-declared-commands.d.ts +70 -0
- package/dist/declaration-conventions/read-declared-commands.js +128 -0
- package/dist/eslint-plugin-syntax-analyze.d.ts +23 -0
- package/dist/eslint-plugin-syntax.d.ts +27 -0
- package/dist/eslint-plugin.d.ts +1211 -52
- package/dist/index.d.ts +56 -8
- package/dist/index.js +53 -6
- package/dist/language/command-resolution.d.ts +124 -0
- package/dist/language/command-resolution.js +120 -0
- package/dist/language/end-of-input-marker.d.ts +29 -0
- package/dist/language/end-of-input-marker.js +88 -0
- package/dist/language/line-breaks.d.ts +18 -0
- package/dist/language/line-breaks.js +22 -0
- package/dist/language/lint-view-types.d.ts +104 -0
- package/dist/language/lint-view-types.js +1 -0
- package/dist/language/non-shell-file-guard.d.ts +35 -0
- package/dist/language/non-shell-file-guard.js +59 -0
- package/dist/language/selector-classes.d.ts +0 -1
- package/dist/language/selector-classes.js +0 -1
- package/dist/language/shell-language-options.d.ts +7 -1
- package/dist/language/shell-language-options.js +4 -4
- package/dist/language/shell-language.d.ts +10 -2
- package/dist/language/shell-language.js +59 -8
- package/dist/language/shell-source-code.d.ts +342 -5
- package/dist/language/shell-source-code.js +559 -30
- package/dist/language/source-coordinates.d.ts +13 -2
- package/dist/language/source-coordinates.js +68 -14
- package/dist/language/syntax-view.d.ts +60 -39
- package/dist/language/syntax-view.js +200 -45
- package/dist/language/word-resolution.d.ts +4 -3
- package/dist/language/word-resolution.js +4 -3
- package/dist/rules/compat/create-compat-rule.d.ts +59 -0
- package/dist/rules/compat/create-compat-rule.js +65 -0
- package/dist/rules/compat/declaration-options.d.ts +19 -0
- package/dist/rules/compat/declaration-options.js +110 -0
- package/dist/rules/compat/no-append-all-redirect.d.ts +13 -0
- package/dist/rules/compat/no-append-all-redirect.js +73 -0
- package/dist/rules/compat/no-associative-arrays.d.ts +12 -0
- package/dist/rules/compat/no-associative-arrays.js +39 -0
- package/dist/rules/compat/no-case-attributes.d.ts +12 -0
- package/dist/rules/compat/no-case-attributes.js +63 -0
- package/dist/rules/compat/no-case-fallthrough.d.ts +12 -0
- package/dist/rules/compat/no-case-fallthrough.js +67 -0
- package/dist/rules/compat/no-case-modification.d.ts +35 -0
- package/dist/rules/compat/no-case-modification.js +86 -0
- package/dist/rules/compat/no-coproc.d.ts +12 -0
- package/dist/rules/compat/no-coproc.js +47 -0
- package/dist/rules/compat/no-declare-g.d.ts +12 -0
- package/dist/rules/compat/no-declare-g.js +59 -0
- package/dist/rules/compat/no-double-bracket.d.ts +12 -0
- package/dist/rules/compat/no-double-bracket.js +52 -0
- package/dist/rules/compat/no-epoch-variables.d.ts +12 -0
- package/dist/rules/compat/no-epoch-variables.js +57 -0
- package/dist/rules/compat/no-fd-variable.d.ts +12 -0
- package/dist/rules/compat/no-fd-variable.js +48 -0
- package/dist/rules/compat/no-globstar.d.ts +12 -0
- package/dist/rules/compat/no-globstar.js +39 -0
- package/dist/rules/compat/no-lastpipe-semantics.d.ts +12 -0
- package/dist/rules/compat/no-lastpipe-semantics.js +53 -0
- package/dist/rules/compat/no-let.d.ts +12 -0
- package/dist/rules/compat/no-let.js +62 -0
- package/dist/rules/compat/no-mapfile.d.ts +13 -0
- package/dist/rules/compat/no-mapfile.js +122 -0
- package/dist/rules/compat/no-nameref.d.ts +12 -0
- package/dist/rules/compat/no-nameref.js +44 -0
- package/dist/rules/compat/no-negative-array-index.d.ts +13 -0
- package/dist/rules/compat/no-negative-array-index.js +123 -0
- package/dist/rules/compat/no-nounset-empty-array.d.ts +13 -0
- package/dist/rules/compat/no-nounset-empty-array.js +158 -0
- package/dist/rules/compat/no-parameter-transformation.d.ts +13 -0
- package/dist/rules/compat/no-parameter-transformation.js +123 -0
- package/dist/rules/compat/no-pipe-all.d.ts +13 -0
- package/dist/rules/compat/no-pipe-all.js +68 -0
- package/dist/rules/compat/no-printf-time-format.d.ts +12 -0
- package/dist/rules/compat/no-printf-time-format.js +99 -0
- package/dist/rules/compat/no-source.d.ts +13 -0
- package/dist/rules/compat/no-source.js +103 -0
- package/dist/rules/compat/no-test-v.d.ts +12 -0
- package/dist/rules/compat/no-test-v.js +280 -0
- package/dist/rules/compat/no-unicode-escape.d.ts +14 -0
- package/dist/rules/compat/no-unicode-escape.js +120 -0
- package/dist/rules/compat/no-wait-n.d.ts +12 -0
- package/dist/rules/compat/no-wait-n.js +73 -0
- package/dist/rules/compat/operator-range.d.ts +10 -0
- package/dist/rules/compat/operator-range.js +15 -0
- package/dist/rules/compat/posix-absent-command.d.ts +12 -0
- package/dist/rules/compat/posix-absent-command.js +134 -0
- package/dist/rules/compat/shopt-options.d.ts +9 -0
- package/dist/rules/compat/shopt-options.js +63 -0
- package/dist/rules/compat/version-gates.d.ts +76 -0
- package/dist/rules/compat/version-gates.js +197 -0
- package/dist/rules/create-rule.d.ts +91 -0
- package/dist/rules/create-rule.js +51 -0
- package/dist/rules/create-wrapper-rule.d.ts +166 -0
- package/dist/rules/create-wrapper-rule.js +407 -0
- package/dist/rules/define-shell-rule.d.ts +184 -0
- package/dist/rules/define-shell-rule.js +56 -0
- package/dist/rules/index.d.ts +26 -0
- package/dist/rules/index.js +88 -0
- package/dist/rules/max-script-complexity.d.ts +28 -0
- package/dist/rules/max-script-complexity.js +130 -0
- package/dist/rules/no-dynamic-invocation.d.ts +35 -0
- package/dist/rules/no-dynamic-invocation.js +117 -0
- package/dist/rules/no-eval.d.ts +13 -0
- package/dist/rules/no-eval.js +89 -0
- package/dist/rules/no-masked-exit-status.d.ts +21 -0
- package/dist/rules/no-masked-exit-status.js +667 -0
- package/dist/rules/no-secret-env-reads.d.ts +24 -0
- package/dist/rules/no-secret-env-reads.js +133 -0
- package/dist/rules/no-secret-flags.d.ts +32 -0
- package/dist/rules/no-secret-flags.js +162 -0
- package/dist/rules/no-unchecked-cd.d.ts +44 -0
- package/dist/rules/no-unchecked-cd.js +250 -0
- package/dist/rules/no-undeclared-commands.d.ts +20 -0
- package/dist/rules/no-undeclared-commands.js +115 -0
- package/dist/rules/no-unused-declarations.d.ts +23 -0
- package/dist/rules/no-unused-declarations.js +259 -0
- package/dist/rules/prefer-local.d.ts +16 -0
- package/dist/rules/prefer-local.js +249 -0
- package/dist/rules/quote-expansions.d.ts +13 -0
- package/dist/rules/quote-expansions.js +229 -0
- package/dist/rules/require-network-wrapper.d.ts +40 -0
- package/dist/rules/require-network-wrapper.js +244 -0
- package/dist/rules/require-shebang.d.ts +29 -0
- package/dist/rules/require-shebang.js +101 -0
- package/dist/rules/require-strict-mode.d.ts +52 -0
- package/dist/rules/require-strict-mode.js +177 -0
- package/dist/rules/require-tty-guard.d.ts +13 -0
- package/dist/rules/require-tty-guard.js +289 -0
- package/dist/rules/resolve-declaration-convention.d.ts +96 -0
- package/dist/rules/resolve-declaration-convention.js +109 -0
- package/dist/rules/resolve-network-wrapper.d.ts +19 -0
- package/dist/rules/resolve-network-wrapper.js +116 -0
- package/dist/rules/set-options.d.ts +109 -0
- package/dist/rules/set-options.js +201 -0
- package/dist/rules/shebang-interpreter.d.ts +18 -0
- package/dist/rules/shebang-interpreter.js +81 -0
- package/dist/rules/shebang-matches-dialect.d.ts +12 -0
- package/dist/rules/shebang-matches-dialect.js +69 -0
- package/dist/rules/transparent-wrappers.d.ts +52 -0
- package/dist/rules/transparent-wrappers.js +99 -0
- package/dist/rules/user-pattern.d.ts +63 -0
- package/dist/rules/user-pattern.js +184 -0
- package/dist/syntax/analyze.d.ts +19 -0
- package/dist/syntax/analyze.js +21 -0
- package/dist/syntax/index.d.ts +23 -0
- package/dist/syntax/index.js +25 -0
- package/dist/version.d.ts +0 -1
- package/dist/version.js +0 -1
- package/docs/compat.md +347 -0
- package/docs/custom-rule-tutorial.md +780 -34
- package/docs/declaration-conventions.md +478 -0
- package/docs/examples/audit-wrapper-pack.mjs +15 -0
- package/docs/examples/dep-line-convention.mjs +22 -0
- package/docs/examples/eslint.config.mjs +3 -2
- package/docs/examples/no-and-or-as-if-rule.mjs +61 -0
- package/docs/examples/no-backticks-rule-tester.mjs +106 -0
- package/docs/examples/no-backticks-rule.mjs +60 -0
- package/docs/examples/no-curl-in-functions-rule.mjs +53 -0
- package/docs/examples/no-function-keyword-rule.mjs +59 -0
- package/docs/examples/no-listed-commands-rule.ts +63 -0
- package/docs/examples/no-rm-rf-rule.mjs +26 -15
- package/docs/examples/no-unquoted-rm-variable-rule.ts +54 -0
- package/docs/examples/sidecar-convention.mjs +38 -0
- package/docs/examples/sidecar-snapshot-convention.mjs +26 -0
- package/docs/examples/sorted-declarations-rule.mjs +52 -0
- package/docs/reading-nodes.md +159 -0
- package/docs/rules/README.md +78 -0
- package/docs/rules/_template.md +83 -0
- package/docs/rules/compat/no-append-all-redirect.md +87 -0
- package/docs/rules/compat/no-associative-arrays.md +95 -0
- package/docs/rules/compat/no-case-attributes.md +82 -0
- package/docs/rules/compat/no-case-fallthrough.md +90 -0
- package/docs/rules/compat/no-case-modification.md +74 -0
- package/docs/rules/compat/no-coproc.md +76 -0
- package/docs/rules/compat/no-declare-g.md +80 -0
- package/docs/rules/compat/no-double-bracket.md +72 -0
- package/docs/rules/compat/no-epoch-variables.md +79 -0
- package/docs/rules/compat/no-fd-variable.md +78 -0
- package/docs/rules/compat/no-globstar.md +74 -0
- package/docs/rules/compat/no-lastpipe-semantics.md +73 -0
- package/docs/rules/compat/no-let.md +78 -0
- package/docs/rules/compat/no-mapfile.md +118 -0
- package/docs/rules/compat/no-nameref.md +81 -0
- package/docs/rules/compat/no-negative-array-index.md +87 -0
- package/docs/rules/compat/no-nounset-empty-array.md +103 -0
- package/docs/rules/compat/no-parameter-transformation.md +94 -0
- package/docs/rules/compat/no-pipe-all.md +85 -0
- package/docs/rules/compat/no-printf-time-format.md +75 -0
- package/docs/rules/compat/no-source.md +98 -0
- package/docs/rules/compat/no-test-v.md +82 -0
- package/docs/rules/compat/no-unicode-escape.md +91 -0
- package/docs/rules/compat/no-wait-n.md +85 -0
- package/docs/rules/max-script-complexity.md +109 -0
- package/docs/rules/no-dynamic-invocation.md +139 -0
- package/docs/rules/no-eval.md +106 -0
- package/docs/rules/no-masked-exit-status.md +239 -0
- package/docs/rules/no-secret-env-reads.md +173 -0
- package/docs/rules/no-secret-flags.md +169 -0
- package/docs/rules/no-unchecked-cd.md +146 -0
- package/docs/rules/no-undeclared-commands.md +141 -0
- package/docs/rules/no-unused-declarations.md +216 -0
- package/docs/rules/prefer-local.md +221 -0
- package/docs/rules/quote-expansions.md +157 -0
- package/docs/rules/require-network-wrapper.md +171 -0
- package/docs/rules/require-shebang.md +157 -0
- package/docs/rules/require-strict-mode.md +253 -0
- package/docs/rules/require-tty-guard.md +128 -0
- package/docs/rules/shebang-matches-dialect.md +120 -0
- package/docs/selectors.md +2 -2
- package/docs/shellcheck.md +86 -0
- package/docs/wrapper-rules.md +206 -0
- package/package.json +26 -20
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/language/selector-classes.d.ts.map +0 -1
- package/dist/language/selector-classes.js.map +0 -1
- package/dist/language/shell-language-options.d.ts.map +0 -1
- package/dist/language/shell-language-options.js.map +0 -1
- package/dist/language/shell-language.d.ts.map +0 -1
- package/dist/language/shell-language.js.map +0 -1
- package/dist/language/shell-source-code.d.ts.map +0 -1
- package/dist/language/shell-source-code.js.map +0 -1
- package/dist/language/source-coordinates.d.ts.map +0 -1
- package/dist/language/source-coordinates.js.map +0 -1
- package/dist/language/syntax-view.d.ts.map +0 -1
- package/dist/language/syntax-view.js.map +0 -1
- package/dist/language/word-resolution.d.ts.map +0 -1
- package/dist/language/word-resolution.js.map +0 -1
- package/dist/version.d.ts.map +0 -1
- package/dist/version.js.map +0 -1
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Every gated feature, keyed by the name rules pass to
|
|
3
|
+
* {@link isFeatureAvailable}.
|
|
4
|
+
*/
|
|
5
|
+
const FEATURE_GATES = Object.freeze({
|
|
6
|
+
/**
|
|
7
|
+
* The `&>>` redirection, appending both stdout and stderr: Bash 4.0 NEWS,
|
|
8
|
+
* "the new `&>>` redirection operator". Bash 3.2 rejects it as a syntax
|
|
9
|
+
* error, so the whole script fails to parse.
|
|
10
|
+
*/
|
|
11
|
+
appendAllRedirect: Object.freeze({ bash: '4.0', posix: false }),
|
|
12
|
+
/** `declare -A` / `typeset -A`: Bash 4.0 NEWS, "associative arrays". */
|
|
13
|
+
associativeArrays: Object.freeze({ bash: '4.0', posix: false }),
|
|
14
|
+
/**
|
|
15
|
+
* The case-modifying expansions `${v^}`, `${v^^}`, `${v,}`, `${v,,}`: Bash
|
|
16
|
+
* 4.0 NEWS, "new case-modifying word expansions".
|
|
17
|
+
*/
|
|
18
|
+
caseModification: Object.freeze({ bash: '4.0', posix: false }),
|
|
19
|
+
/**
|
|
20
|
+
* The case-converting attributes `declare -l` / `-u` (and through
|
|
21
|
+
* `typeset` and `local`): Bash 4.0 NEWS, "new `-l` and `-u` options to
|
|
22
|
+
* declare/typeset/local".
|
|
23
|
+
*/
|
|
24
|
+
caseAttributes: Object.freeze({ bash: '4.0', posix: false }),
|
|
25
|
+
/**
|
|
26
|
+
* The `case` terminators `;&` (fall through) and `;;&` (test the next
|
|
27
|
+
* pattern): Bash 4.0 NEWS. POSIX.1-2024 adds `;&`, but dash 0.5.12 still
|
|
28
|
+
* rejects it, so a POSIX target does not have it.
|
|
29
|
+
*/
|
|
30
|
+
caseFallthrough: Object.freeze({ bash: '4.0', posix: false }),
|
|
31
|
+
/** The `coproc` reserved word: Bash 4.0 NEWS, "a new `coproc` reserved word". */
|
|
32
|
+
coproc: Object.freeze({ bash: '4.0', posix: false }),
|
|
33
|
+
/**
|
|
34
|
+
* `declare -g` / `typeset -g`: Bash 4.2 NEWS, "declare/typeset has a new
|
|
35
|
+
* `-g` option".
|
|
36
|
+
*/
|
|
37
|
+
declareGlobal: Object.freeze({ bash: '4.2', posix: false }),
|
|
38
|
+
/**
|
|
39
|
+
* The `[[ … ]]` conditional. POSIX section 2.4 lists `[[` and `]]` among the
|
|
40
|
+
* words whose results are unspecified; every Bash has it, and dash runs it
|
|
41
|
+
* as a command that does not exist.
|
|
42
|
+
*/
|
|
43
|
+
doubleBracket: Object.freeze({ bash: null, posix: false }),
|
|
44
|
+
/** `$EPOCHSECONDS` and `$EPOCHREALTIME`: Bash 5.0 NEWS. */
|
|
45
|
+
epochVariables: Object.freeze({ bash: '5.0', posix: false }),
|
|
46
|
+
/**
|
|
47
|
+
* A `{varname}` redirection that allocates a descriptor into a variable
|
|
48
|
+
* (`exec {fd}>file`): Bash 4.1 NEWS. Bash 4.0 runs `{fd}` as a command.
|
|
49
|
+
*/
|
|
50
|
+
fdVariable: Object.freeze({ bash: '4.1', posix: false }),
|
|
51
|
+
/** `shopt -s globstar` (recursive `**`): Bash 4.0 NEWS. */
|
|
52
|
+
globstar: Object.freeze({ bash: '4.0', posix: false }),
|
|
53
|
+
/** `shopt -s lastpipe`: Bash 4.2 NEWS, "a new `lastpipe` shell option". */
|
|
54
|
+
lastpipe: Object.freeze({ bash: '4.2', posix: false }),
|
|
55
|
+
/**
|
|
56
|
+
* The `let` builtin. POSIX section 2.9.1.4 lists `let` among the command
|
|
57
|
+
* names whose results are unspecified; every Bash has it, and dash has no
|
|
58
|
+
* such command.
|
|
59
|
+
*/
|
|
60
|
+
letCommand: Object.freeze({ bash: null, posix: false }),
|
|
61
|
+
/** The `mapfile` builtin and its `readarray` synonym: Bash 4.0 NEWS. */
|
|
62
|
+
mapfile: Object.freeze({ bash: '4.0', posix: false }),
|
|
63
|
+
/** Namerefs, `declare -n` / `typeset -n` / `local -n`: Bash 4.3 NEWS. */
|
|
64
|
+
nameref: Object.freeze({ bash: '4.3', posix: false }),
|
|
65
|
+
/**
|
|
66
|
+
* Negative indexed-array subscripts (`${a[-1]}`, `a[-1]=x`): Bash 4.3 NEWS,
|
|
67
|
+
* "assigning, referencing, and unsetting elements of indexed arrays using
|
|
68
|
+
* negative subscripts". Bash 4.2 already reads `${a[-1]}`, but rejects the
|
|
69
|
+
* element length `${#a[-1]}`, assignment and unset, so 4.3 is the first
|
|
70
|
+
* release where every use works.
|
|
71
|
+
*/
|
|
72
|
+
negativeArrayIndex: Object.freeze({ bash: '4.3', posix: false }),
|
|
73
|
+
/**
|
|
74
|
+
* Expanding an empty array (`"${a[@]}"`, `${a[*]}`) while `set -u` is on:
|
|
75
|
+
* the syntax is in every Bash, but through 4.3 it aborts with "unbound
|
|
76
|
+
* variable"; Bash 4.4 is the first release where it expands to nothing.
|
|
77
|
+
*/
|
|
78
|
+
nounsetEmptyArray: Object.freeze({ bash: '4.4', posix: false }),
|
|
79
|
+
/**
|
|
80
|
+
* The parameter transformations `${v@Q}`, `${v@E}`, `${v@P}`, `${v@A}` and
|
|
81
|
+
* `${v@a}`: Bash 4.4 NEWS.
|
|
82
|
+
*/
|
|
83
|
+
parameterTransformation: Object.freeze({ bash: '4.4', posix: false }),
|
|
84
|
+
/** The case transformations `${v@U}`, `${v@u}` and `${v@L}`: Bash 5.1 NEWS. */
|
|
85
|
+
parameterTransformationCase: Object.freeze({ bash: '5.1', posix: false }),
|
|
86
|
+
/** `${a[@]@k}`, key-value pairs as separate words: Bash 5.2 NEWS. */
|
|
87
|
+
parameterTransformationKeys: Object.freeze({ bash: '5.2', posix: false }),
|
|
88
|
+
/** `${a[@]@K}`, quoted key-value pairs: Bash 5.1 NEWS. */
|
|
89
|
+
parameterTransformationQuotedKeys: Object.freeze({ bash: '5.1', posix: false }),
|
|
90
|
+
/**
|
|
91
|
+
* The `|&` pipe, shorthand for `2>&1 |`: Bash 4.0 NEWS. Bash 3.2 rejects
|
|
92
|
+
* it as a syntax error.
|
|
93
|
+
*/
|
|
94
|
+
pipeAll: Object.freeze({ bash: '4.0', posix: false }),
|
|
95
|
+
/** `printf`'s `%(fmt)T` date format: Bash 4.2 NEWS. */
|
|
96
|
+
printfTimeFormat: Object.freeze({ bash: '4.2', posix: false }),
|
|
97
|
+
/**
|
|
98
|
+
* The `source` builtin, Bash's name for `.`. POSIX section 2.9.1.4 lists
|
|
99
|
+
* `source` among the command names whose results are unspecified; every Bash
|
|
100
|
+
* has it, and dash has no such command.
|
|
101
|
+
*/
|
|
102
|
+
sourceCommand: Object.freeze({ bash: null, posix: false }),
|
|
103
|
+
/**
|
|
104
|
+
* The `-v name` test (`[[ -v x ]]`, `test -v x`, `[ -v x ]`): Bash 4.2
|
|
105
|
+
* NEWS. In older Bash, `[[ -v x ]]` is a syntax error.
|
|
106
|
+
*/
|
|
107
|
+
testVariableSet: Object.freeze({ bash: '4.2', posix: false }),
|
|
108
|
+
/**
|
|
109
|
+
* The `\u`/`\U` escapes in `$'…'` strings: Bash 4.2 NEWS. Earlier releases
|
|
110
|
+
* leave the escape as literal text. See `unicodeEscapeLatin1` for the one
|
|
111
|
+
* range the 4.2 release decodes wrongly.
|
|
112
|
+
*/
|
|
113
|
+
unicodeEscape: Object.freeze({ bash: '4.2', posix: false }),
|
|
114
|
+
/**
|
|
115
|
+
* A `\u`/`\U` escape for a code point from U+0080 to U+00FF: the Bash 4.2
|
|
116
|
+
* release tarball writes these as a single Latin-1 byte even in a UTF-8
|
|
117
|
+
* locale (observed: `e9` for U+00E9, where UTF-8 is `c3 a9`), while every
|
|
118
|
+
* other code point is UTF-8. Bash 4.3 is the first release that writes all
|
|
119
|
+
* of them as UTF-8.
|
|
120
|
+
*/
|
|
121
|
+
unicodeEscapeLatin1: Object.freeze({ bash: '4.3', posix: false }),
|
|
122
|
+
/** `wait -n`, waiting for the next job to finish: Bash 4.3 NEWS. */
|
|
123
|
+
waitNext: Object.freeze({ bash: '4.3', posix: false }),
|
|
124
|
+
});
|
|
125
|
+
/**
|
|
126
|
+
* Splits a `MAJOR[.MINOR]` string into numbers, so `"4"` is `[4, 0]` and
|
|
127
|
+
* `"3.10"` is `[3, 10]`. Returns `undefined` for any other shape; the
|
|
128
|
+
* language's option validation already rejects those, so the gate never
|
|
129
|
+
* sees one from a real config.
|
|
130
|
+
*/
|
|
131
|
+
function parseVersion(version) {
|
|
132
|
+
if (!/^\d+(?:\.\d+)?$/u.test(version))
|
|
133
|
+
return undefined;
|
|
134
|
+
const [major, minor = '0'] = version.split('.');
|
|
135
|
+
return [Number(major), Number(minor)];
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Compares two `MAJOR[.MINOR]` versions numerically, major first, then minor:
|
|
139
|
+
* negative when `a` is older, `0` when equal, positive when `a` is newer. So
|
|
140
|
+
* `"3.10"` is newer than `"3.2"`, and `"4"` equals `"4.0"`.
|
|
141
|
+
*/
|
|
142
|
+
function compareVersions(a, b) {
|
|
143
|
+
return a[0] !== b[0] ? a[0] - b[0] : a[1] - b[1];
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* The dialects whose `shellVersion` is a Bash version. `bats` test files run
|
|
147
|
+
* under Bash, so they are gated exactly like `bash` files.
|
|
148
|
+
*/
|
|
149
|
+
const BASH_DIALECTS = new Set(['bash', 'bats']);
|
|
150
|
+
/**
|
|
151
|
+
* Whether `feature` is available to a file linted with `languageOptions`.
|
|
152
|
+
*
|
|
153
|
+
* - `dialect: "posix"`: available only when the gate's `posix` is `true`,
|
|
154
|
+
* at any `shellVersion` (a Bash-only feature is never available).
|
|
155
|
+
* - `dialect: "bash"` (the default) or `"bats"`: an unset `shellVersion`
|
|
156
|
+
* means the newest Bash, so every Bash feature is available. A set
|
|
157
|
+
* `shellVersion` makes the feature available when it is the gate's `bash`
|
|
158
|
+
* minimum or newer, comparing major then minor numerically (`"4"` is
|
|
159
|
+
* `4.0`; `"3.10"` is newer than `"3.2"`). A `null` minimum is available at
|
|
160
|
+
* every version.
|
|
161
|
+
* - `dialect: "mksh"` or `"zsh"`: the table carries no data for these
|
|
162
|
+
* shells, and their `shellVersion` numbers their own releases, not Bash's,
|
|
163
|
+
* so no gate applies and every feature is available.
|
|
164
|
+
*
|
|
165
|
+
* @internal
|
|
166
|
+
*/
|
|
167
|
+
export function isFeatureAvailable(feature, languageOptions) {
|
|
168
|
+
const gate = FEATURE_GATES[feature];
|
|
169
|
+
const dialect = languageOptions.dialect ?? 'bash';
|
|
170
|
+
if (dialect === 'posix')
|
|
171
|
+
return gate.posix;
|
|
172
|
+
if (!BASH_DIALECTS.has(dialect))
|
|
173
|
+
return true;
|
|
174
|
+
const { shellVersion } = languageOptions;
|
|
175
|
+
if (shellVersion === undefined || gate.bash === null)
|
|
176
|
+
return true;
|
|
177
|
+
const target = parseVersion(shellVersion);
|
|
178
|
+
const minimum = parseVersion(gate.bash);
|
|
179
|
+
if (target === undefined || minimum === undefined)
|
|
180
|
+
return true;
|
|
181
|
+
return compareVersions(target, minimum) >= 0;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Describes why `feature` is unavailable under `languageOptions`, for a
|
|
185
|
+
* report's message data. Call it only when {@link isFeatureAvailable} is
|
|
186
|
+
* `false`.
|
|
187
|
+
*
|
|
188
|
+
* @internal
|
|
189
|
+
*/
|
|
190
|
+
export function describeGate(feature, languageOptions) {
|
|
191
|
+
const gate = FEATURE_GATES[feature];
|
|
192
|
+
const required = gate.bash === null ? 'bash' : `bash ${gate.bash} or newer`;
|
|
193
|
+
const target = (languageOptions.dialect ?? 'bash') === 'posix'
|
|
194
|
+
? 'POSIX sh'
|
|
195
|
+
: `bash ${languageOptions.shellVersion ?? ''}`.trim();
|
|
196
|
+
return { required, target };
|
|
197
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The factory for this plugin's built-in rules: the public
|
|
3
|
+
* {@link defineShellRule} plus the one piece of metadata that only built-in
|
|
4
|
+
* rules share.
|
|
5
|
+
*
|
|
6
|
+
* `meta.docs.url` is derived from the rule name and always points at the
|
|
7
|
+
* rule's committed docs page, so the link a user follows from a lint report
|
|
8
|
+
* can never be hand-mistyped or left stale after a rename. Everything else —
|
|
9
|
+
* `meta.languages: ["sh/sh"]` and the shell-typed context, nodes and visitor —
|
|
10
|
+
* comes from `defineShellRule`, so built-in and third-party rules share one
|
|
11
|
+
* implementation of that guarantee.
|
|
12
|
+
*
|
|
13
|
+
* This module is internal (not re-exported from the package entry point): the
|
|
14
|
+
* docs URL scheme is this repository's. Rule packs use `defineShellRule` and
|
|
15
|
+
* write their own `meta.docs.url`.
|
|
16
|
+
*/
|
|
17
|
+
import type { RulesMetaDocs } from '@eslint/core';
|
|
18
|
+
import type { ShellRule, ShellRuleContext, ShellRuleMeta, ShellRuleVisitor } from './define-shell-rule.js';
|
|
19
|
+
/**
|
|
20
|
+
* The canonical documentation URL for the built-in rule `name`. This is the
|
|
21
|
+
* single place the URL scheme is spelled; the factory uses it to fill
|
|
22
|
+
* `meta.docs.url`, and the docs-page tests use it to check each registered
|
|
23
|
+
* rule points at its own committed page.
|
|
24
|
+
*
|
|
25
|
+
* @internal
|
|
26
|
+
*/
|
|
27
|
+
export declare function ruleDocsUrl(name: string): string;
|
|
28
|
+
/**
|
|
29
|
+
* The documentation URL for `page`, a path relative to this package's `docs/`
|
|
30
|
+
* directory (`wrapper-rules.md` is the committed file
|
|
31
|
+
* `packages/eslint-plugin/docs/wrapper-rules.md`). Used for rules that are not
|
|
32
|
+
* in the registry, which have no `docs/rules/<name>.md` page of their own.
|
|
33
|
+
*
|
|
34
|
+
* @internal
|
|
35
|
+
*/
|
|
36
|
+
export declare function packageDocsUrl(page: string): string;
|
|
37
|
+
/**
|
|
38
|
+
* The `meta.docs` an author writes: everything ESLint accepts except `url`,
|
|
39
|
+
* which the factory derives from the rule name. Typed `never` so supplying a
|
|
40
|
+
* URL by hand is a compile error rather than a silently-overwritten value.
|
|
41
|
+
*
|
|
42
|
+
* @internal
|
|
43
|
+
*/
|
|
44
|
+
export type BuiltInRuleDocs = Omit<RulesMetaDocs, 'url'> & {
|
|
45
|
+
readonly url?: never;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* The `meta` a built-in rule writes: {@link ShellRuleMeta} (so the language
|
|
49
|
+
* fields are already forbidden), with `docs` narrowed to
|
|
50
|
+
* {@link BuiltInRuleDocs} because the factory derives `docs.url`.
|
|
51
|
+
*
|
|
52
|
+
* @internal
|
|
53
|
+
*/
|
|
54
|
+
export type BuiltInRuleMeta<RuleOptions extends unknown[], MessageIds extends string> = Omit<ShellRuleMeta<RuleOptions, MessageIds>, 'docs'> & {
|
|
55
|
+
readonly docs?: BuiltInRuleDocs;
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* What an author hands to {@link createRule}: the rule's registry name (used
|
|
59
|
+
* to derive its docs URL), its author-owned metadata, and its `create()`.
|
|
60
|
+
*
|
|
61
|
+
* @internal
|
|
62
|
+
*/
|
|
63
|
+
export interface BuiltInRuleSpec<RuleOptions extends unknown[], MessageIds extends string> {
|
|
64
|
+
/**
|
|
65
|
+
* The rule's name without the plugin namespace (`require-shebang`, not
|
|
66
|
+
* `sh/require-shebang`). For a built-in rule it must equal the rule's key in
|
|
67
|
+
* the registry and the basename of its docs page.
|
|
68
|
+
*/
|
|
69
|
+
readonly name: string;
|
|
70
|
+
/**
|
|
71
|
+
* The docs URL of a rule that is not in the registry. A rule made by one of
|
|
72
|
+
* this package's public factories (for example `createWrapperRule`) has no
|
|
73
|
+
* `docs/rules/<name>.md` page: it links its factory's page
|
|
74
|
+
* ({@link packageDocsUrl}), or the page its rule pack supplies. Omit it for
|
|
75
|
+
* a built-in rule, whose page is always `docs/rules/<name>.md`.
|
|
76
|
+
*/
|
|
77
|
+
readonly docsUrl?: string;
|
|
78
|
+
readonly meta: BuiltInRuleMeta<RuleOptions, MessageIds>;
|
|
79
|
+
/** Builds the rule's listeners for one file; receives the shell-typed context. */
|
|
80
|
+
readonly create: (context: ShellRuleContext<RuleOptions, MessageIds>) => ShellRuleVisitor;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Builds a built-in shell rule from its spec with {@link defineShellRule},
|
|
84
|
+
* after setting `meta.docs.url` to the rule's docs page ({@link ruleDocsUrl},
|
|
85
|
+
* or the spec's `docsUrl` for a rule outside the registry). The URL is
|
|
86
|
+
* written after the author's `docs`, so even an untyped caller cannot
|
|
87
|
+
* override it; `defineShellRule` does the same for `meta.languages`.
|
|
88
|
+
*
|
|
89
|
+
* @internal
|
|
90
|
+
*/
|
|
91
|
+
export declare function createRule<RuleOptions extends unknown[] = [], MessageIds extends string = string>(spec: BuiltInRuleSpec<RuleOptions, MessageIds>): ShellRule<RuleOptions, MessageIds>;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { defineShellRule } from './define-shell-rule.js';
|
|
2
|
+
/**
|
|
3
|
+
* Where this package's shipped docs live in the source repository: the
|
|
4
|
+
* committed `packages/eslint-plugin/docs/` directory.
|
|
5
|
+
*/
|
|
6
|
+
const PACKAGE_DOCS_BASE_URL = 'https://github.com/mike-north/eslint-sh/blob/main/packages/eslint-plugin/docs/';
|
|
7
|
+
/**
|
|
8
|
+
* Where built-in rule docs pages live in the source repository. A rule named
|
|
9
|
+
* `foo` is documented at `<this>/foo.md`, i.e. the committed file
|
|
10
|
+
* `packages/eslint-plugin/docs/rules/foo.md`.
|
|
11
|
+
*/
|
|
12
|
+
const RULE_DOCS_BASE_URL = `${PACKAGE_DOCS_BASE_URL}rules/`;
|
|
13
|
+
/**
|
|
14
|
+
* The canonical documentation URL for the built-in rule `name`. This is the
|
|
15
|
+
* single place the URL scheme is spelled; the factory uses it to fill
|
|
16
|
+
* `meta.docs.url`, and the docs-page tests use it to check each registered
|
|
17
|
+
* rule points at its own committed page.
|
|
18
|
+
*
|
|
19
|
+
* @internal
|
|
20
|
+
*/
|
|
21
|
+
export function ruleDocsUrl(name) {
|
|
22
|
+
return `${RULE_DOCS_BASE_URL}${name}.md`;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* The documentation URL for `page`, a path relative to this package's `docs/`
|
|
26
|
+
* directory (`wrapper-rules.md` is the committed file
|
|
27
|
+
* `packages/eslint-plugin/docs/wrapper-rules.md`). Used for rules that are not
|
|
28
|
+
* in the registry, which have no `docs/rules/<name>.md` page of their own.
|
|
29
|
+
*
|
|
30
|
+
* @internal
|
|
31
|
+
*/
|
|
32
|
+
export function packageDocsUrl(page) {
|
|
33
|
+
return `${PACKAGE_DOCS_BASE_URL}${page}`;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Builds a built-in shell rule from its spec with {@link defineShellRule},
|
|
37
|
+
* after setting `meta.docs.url` to the rule's docs page ({@link ruleDocsUrl},
|
|
38
|
+
* or the spec's `docsUrl` for a rule outside the registry). The URL is
|
|
39
|
+
* written after the author's `docs`, so even an untyped caller cannot
|
|
40
|
+
* override it; `defineShellRule` does the same for `meta.languages`.
|
|
41
|
+
*
|
|
42
|
+
* @internal
|
|
43
|
+
*/
|
|
44
|
+
export function createRule(spec) {
|
|
45
|
+
const { name, docsUrl, meta, create } = spec;
|
|
46
|
+
const url = docsUrl ?? ruleDocsUrl(name);
|
|
47
|
+
return defineShellRule({
|
|
48
|
+
meta: { ...meta, docs: { ...meta.docs, url } },
|
|
49
|
+
create,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import type { WrapperSpec } from 'sh-ast/analyze';
|
|
2
|
+
import type { ShellRule } from './define-shell-rule.js';
|
|
3
|
+
/**
|
|
4
|
+
* Restricts a listed command to some of its subcommands, for commands such as
|
|
5
|
+
* `git` where only some subcommands are in scope (`git fetch` is a network
|
|
6
|
+
* call, `git status` is not).
|
|
7
|
+
*
|
|
8
|
+
* The flag fields are `WrapperSpec`'s own, picked from it so the two cannot
|
|
9
|
+
* drift, and describe the command's options that may appear before the
|
|
10
|
+
* subcommand (`git -C dir fetch`): `noArgFlags` take no operand (`--bare`),
|
|
11
|
+
* `argFlags` take one (`-C <dir>`), and `stopsChainFlags` mean the command
|
|
12
|
+
* runs no subcommand at all (`git --version fetch` prints the version, and is
|
|
13
|
+
* never reported). The subcommand is found the way a wrapped command is:
|
|
14
|
+
* declared options are skipped, and a flag the command does not declare
|
|
15
|
+
* leaves the subcommand unknown, so the invocation is not reported.
|
|
16
|
+
*
|
|
17
|
+
* @public
|
|
18
|
+
*/
|
|
19
|
+
export interface WrapperRuleSubcommands extends Pick<WrapperSpec, 'noArgFlags' | 'argFlags' | 'stopsChainFlags'> {
|
|
20
|
+
/** The subcommands that make an invocation of the command count, such as `['fetch', 'push']`. */
|
|
21
|
+
readonly names: readonly string[];
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Names the operand of a listed command whose value decides whether the
|
|
25
|
+
* invocation can leave the machine, such as the source of `git clone`.
|
|
26
|
+
*
|
|
27
|
+
* The flags describe the options that may precede the operand, with the same
|
|
28
|
+
* meaning as {@link WrapperRuleSubcommands}'s: `noArgFlags` take no value and
|
|
29
|
+
* `argFlags` take one (as `--depth 1`, or `--depth=1` in one word). The
|
|
30
|
+
* operand is the first word after them, or after a `--`. A flag that is not
|
|
31
|
+
* declared leaves the operand unknown, and an unknown operand is never taken
|
|
32
|
+
* as local.
|
|
33
|
+
*
|
|
34
|
+
* @public
|
|
35
|
+
*/
|
|
36
|
+
export interface WrapperRuleLocalOperand extends Pick<WrapperSpec, 'noArgFlags' | 'argFlags'> {
|
|
37
|
+
/**
|
|
38
|
+
* The operand counts as local when it is a static word starting with one
|
|
39
|
+
* of these, such as `['./', '../', '/', 'file://']`.
|
|
40
|
+
*/
|
|
41
|
+
readonly localPrefixes: readonly string[];
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Ways to invoke one listed command that only act locally, so the policy has
|
|
45
|
+
* nothing to guard. An invocation matching either field is not reported.
|
|
46
|
+
*
|
|
47
|
+
* @public
|
|
48
|
+
*/
|
|
49
|
+
export interface WrapperRuleLocalInvocation {
|
|
50
|
+
/**
|
|
51
|
+
* Complete argument lists, after the command (and its subcommand, if it has
|
|
52
|
+
* one), that make the invocation local. They match exactly: with
|
|
53
|
+
* `[['--version']]`, `curl --version` is local and
|
|
54
|
+
* `curl --version https://example.com` is not.
|
|
55
|
+
*/
|
|
56
|
+
readonly argLists?: readonly (readonly string[])[];
|
|
57
|
+
/** Local when the command's source operand is a local path. */
|
|
58
|
+
readonly localOperand?: WrapperRuleLocalOperand;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* What a "must be run through a wrapper" rule enforces. Passed to
|
|
62
|
+
* {@link createWrapperRule}.
|
|
63
|
+
*
|
|
64
|
+
* @public
|
|
65
|
+
*/
|
|
66
|
+
export interface WrapperRuleConfig {
|
|
67
|
+
/**
|
|
68
|
+
* The command names that must be run through the wrapper. A static command
|
|
69
|
+
* word matches a name when it equals it, or when it contains a slash and
|
|
70
|
+
* its basename equals it (`/usr/bin/curl` and `./bin/curl` match `curl`).
|
|
71
|
+
*/
|
|
72
|
+
readonly commands: readonly string[];
|
|
73
|
+
/**
|
|
74
|
+
* The wrapper the commands must be run through. A string names a wrapper
|
|
75
|
+
* that takes no options of its own (`retry curl x`), unless it names one of
|
|
76
|
+
* `sh-ast/analyze`'s default transparent wrappers (`timeout`, `nice`, …),
|
|
77
|
+
* whose known option shape is used. A `WrapperSpec` declares the wrapper's
|
|
78
|
+
* option shape, so that `retry -n 3 curl x` is recognized as `curl` run
|
|
79
|
+
* through `retry`; any of its `names` counts as the wrapper. Like
|
|
80
|
+
* `commands`, a wrapper run by path matches by basename
|
|
81
|
+
* (`/usr/local/bin/retry curl x`).
|
|
82
|
+
*/
|
|
83
|
+
readonly wrapper: string | WrapperSpec;
|
|
84
|
+
/**
|
|
85
|
+
* Listed commands that count only with some subcommands, keyed by command
|
|
86
|
+
* name. A listed command with no entry here counts with any arguments.
|
|
87
|
+
*/
|
|
88
|
+
readonly subcommands?: Readonly<Record<string, WrapperRuleSubcommands>>;
|
|
89
|
+
/**
|
|
90
|
+
* Invocations of a listed command that only act locally and so are not
|
|
91
|
+
* reported, keyed by the command as the rule's message names it: the listed
|
|
92
|
+
* name (`curl`), or the name with its subcommand (`git clone`).
|
|
93
|
+
*/
|
|
94
|
+
readonly localInvocations?: Readonly<Record<string, WrapperRuleLocalInvocation>>;
|
|
95
|
+
/**
|
|
96
|
+
* The rule's `meta.docs` fields a rule pack owns. `url` defaults to this
|
|
97
|
+
* package's wrapper-rules docs page, and `description` to a sentence naming
|
|
98
|
+
* the commands and the wrapper. Set them to point users at the pack's own
|
|
99
|
+
* documentation.
|
|
100
|
+
*/
|
|
101
|
+
readonly docs?: {
|
|
102
|
+
readonly url?: string;
|
|
103
|
+
readonly description?: string;
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* The message ids a wrapper rule reports with: `unwrappedCommand` names the
|
|
108
|
+
* command (with its subcommand, when one was matched) and the wrapper.
|
|
109
|
+
*
|
|
110
|
+
* @internal
|
|
111
|
+
*/
|
|
112
|
+
export type WrapperRuleMessageId = 'unwrappedCommand';
|
|
113
|
+
/**
|
|
114
|
+
* The messages every wrapper rule reports with. Shared so that a rule which
|
|
115
|
+
* delegates to the factory (`sh/require-network-wrapper`) declares exactly the
|
|
116
|
+
* messages the factory's listeners report.
|
|
117
|
+
*
|
|
118
|
+
* @internal
|
|
119
|
+
*/
|
|
120
|
+
export declare const WRAPPER_RULE_MESSAGES: Readonly<Record<WrapperRuleMessageId, string>>;
|
|
121
|
+
/**
|
|
122
|
+
* The wrapper-rule factory, typed for this package's rules: it is what
|
|
123
|
+
* {@link createWrapperRule} returns, with the shell-specific rule type and an
|
|
124
|
+
* options tuple chosen by the caller. A built-in rule whose config comes from
|
|
125
|
+
* its own options (`sh/require-network-wrapper`) builds the factory's rule
|
|
126
|
+
* per config and calls its `create` with its own context, so the options
|
|
127
|
+
* tuple is that rule's. The factory's rule itself reads no options.
|
|
128
|
+
*
|
|
129
|
+
* @internal
|
|
130
|
+
*/
|
|
131
|
+
export declare function buildWrapperRule<RuleOptions extends unknown[] = []>(config: WrapperRuleConfig): ShellRule<RuleOptions, WrapperRuleMessageId>;
|
|
132
|
+
/**
|
|
133
|
+
* Creates a rule that reports every listed command that is not run through
|
|
134
|
+
* `config.wrapper`, for a rule pack's "must be wrapped by X" policies:
|
|
135
|
+
*
|
|
136
|
+
* ```js
|
|
137
|
+
* import { createWrapperRule } from '@eslint-sh/eslint-plugin';
|
|
138
|
+
*
|
|
139
|
+
* export const requireAudit = createWrapperRule({
|
|
140
|
+
* commands: ['kubectl', 'terraform'],
|
|
141
|
+
* wrapper: 'audit-run',
|
|
142
|
+
* });
|
|
143
|
+
* ```
|
|
144
|
+
*
|
|
145
|
+
* The rule declares `meta.languages: ["sh/sh"]`, takes no options (the
|
|
146
|
+
* config is bound here), and reports with message id `unwrappedCommand`,
|
|
147
|
+
* naming the command and the wrapper. Its `meta.docs.url` and
|
|
148
|
+
* `meta.docs.description` default to this package's wrapper-rules page and a
|
|
149
|
+
* sentence naming the policy; `config.docs` overrides either. A listed
|
|
150
|
+
* command is wrapped when the wrapper encloses it in `sh-ast/analyze`'s
|
|
151
|
+
* transparent-wrapper chain, so `audit-run sudo kubectl apply` is wrapped.
|
|
152
|
+
* Command and wrapper words written as paths match by basename
|
|
153
|
+
* (`/usr/bin/kubectl`). Commands inside `$(…)`, functions, and pipelines are
|
|
154
|
+
* checked; a command whose name or subcommand is not static is not reported.
|
|
155
|
+
*
|
|
156
|
+
* @param config - The commands, the wrapper they must be run through, any
|
|
157
|
+
* subcommand restrictions, and optional `meta.docs` overrides.
|
|
158
|
+
* @returns A {@link ShellRule}: an ESLint rule for the `sh/sh` language,
|
|
159
|
+
* typed so a pack's own declarations need no `@eslint/core` import to name it.
|
|
160
|
+
* @throws TypeError when `config` is malformed (no `commands` array, an empty
|
|
161
|
+
* wrapper name, a subcommand restriction without `names`, or an empty or
|
|
162
|
+
* non-string `docs.url` / `docs.description`).
|
|
163
|
+
*
|
|
164
|
+
* @public
|
|
165
|
+
*/
|
|
166
|
+
export declare function createWrapperRule(config: WrapperRuleConfig): ShellRule<[], 'unwrappedCommand'>;
|