diff --git a/README.md b/README.md
index 230aef34..2873db27 100644
--- a/README.md
+++ b/README.md
@@ -114,6 +114,7 @@ For [Shareable Configs](https://eslint.org/docs/latest/developer-guide/shareable
| [file-extension-in-import](docs/rules/file-extension-in-import.md) | enforce the style of file extensions in `import` declarations | | 🔧 | |
| [global-require](docs/rules/global-require.md) | require `require()` calls to be placed at top-level module scope | | | |
| [handle-callback-err](docs/rules/handle-callback-err.md) | require error handling in callbacks | | | |
+| [hashbang](docs/rules/hashbang.md) | require correct usage of hashbang | ☑️ 🟢 ✅ ☑️ 🟢 ✅ | 🔧 | |
| [no-callback-literal](docs/rules/no-callback-literal.md) | enforce Node.js-style error-first callback pattern is followed | | | |
| [no-deprecated-api](docs/rules/no-deprecated-api.md) | disallow deprecated APIs | ☑️ 🟢 ✅ ☑️ 🟢 ✅ | | |
| [no-exports-assign](docs/rules/no-exports-assign.md) | disallow the assignment to `exports` | ☑️ 🟢 ✅ ☑️ 🟢 ✅ | | |
@@ -147,7 +148,7 @@ For [Shareable Configs](https://eslint.org/docs/latest/developer-guide/shareable
| [prefer-promises/dns](docs/rules/prefer-promises/dns.md) | enforce `require("dns").promises` | | | |
| [prefer-promises/fs](docs/rules/prefer-promises/fs.md) | enforce `require("fs").promises` | | | |
| [process-exit-as-throw](docs/rules/process-exit-as-throw.md) | require that `process.exit()` expressions use the same code path as `throw` | ☑️ 🟢 ✅ ☑️ 🟢 ✅ | | |
-| [shebang](docs/rules/shebang.md) | require correct usage of shebang | ☑️ 🟢 ✅ ☑️ 🟢 ✅ | 🔧 | |
+| [shebang](docs/rules/shebang.md) | require correct usage of hashbang | | 🔧 | ❌ |
diff --git a/docs/rules/hashbang.md b/docs/rules/hashbang.md
new file mode 100644
index 00000000..7e35aa7b
--- /dev/null
+++ b/docs/rules/hashbang.md
@@ -0,0 +1,88 @@
+# Require correct usage of hashbang (`n/hashbang`)
+
+💼 This rule is enabled in the following [configs](https://github.com/eslint-community/eslint-plugin-n#-configs): ☑️ `flat/recommended`, 🟢 `flat/recommended-module`, ✅ `flat/recommended-script`, ☑️ `recommended`, 🟢 `recommended-module`, ✅ `recommended-script`.
+
+🔧 This rule is automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix).
+
+
+
+When we make a CLI tool with Node.js, we add `bin` field to `package.json`, then we add a hashbang the entry file.
+This rule suggests correct usage of hashbang.
+
+## 📖 Rule Details
+
+This rule looks up `package.json` file from each linting target file.
+Starting from the directory of the target file, it goes up ancestor directories until found.
+
+If `package.json` was not found, this rule does nothing.
+
+This rule checks `bin` field of `package.json`, then if a target file matches one of `bin` files, it checks whether or not there is a correct hashbang.
+Otherwise it checks whether or not there is not a hashbang.
+
+The following patterns are considered problems for files in `bin` field of `package.json`:
+
+```js
+console.log("hello"); /*error This file needs hashbang "#!/usr/bin/env node".*/
+```
+
+```js
+#!/usr/bin/env node /*error This file must not have Unicode BOM.*/
+console.log("hello");
+// If this file has Unicode BOM.
+```
+
+```js
+#!/usr/bin/env node /*error This file must have Unix linebreaks (LF).*/
+console.log("hello");
+// If this file has Windows' linebreaks (CRLF).
+```
+
+The following patterns are considered problems for other files:
+
+```js
+#!/usr/bin/env node /*error This file needs no hashbang.*/
+console.log("hello");
+```
+
+The following patterns are not considered problems for files in `bin` field of `package.json`:
+
+```js
+#!/usr/bin/env node
+console.log("hello");
+```
+
+The following patterns are not considered problems for other files:
+
+```js
+console.log("hello");
+```
+
+### Options
+
+```json
+{
+ "n/hashbang": ["error", {
+ "convertPath": null,
+ "ignoreUnpublished": false,
+ "additionalExecutables": [],
+ }]
+}
+```
+
+#### convertPath
+
+This can be configured in the rule options or as a shared setting [`settings.convertPath`](../shared-settings.md#convertpath).
+Please see the shared settings documentation for more information.
+
+#### ignoreUnpublished
+
+Allow for files that are not published to npm to be ignored by this rule.
+
+#### additionalExecutables
+
+Mark files as executable that are not referenced by the package.json#bin property
+
+## 🔎 Implementation
+
+- [Rule source](../../lib/rules/hashbang.js)
+- [Test source](../../tests/lib/rules/hashbang.js)
diff --git a/docs/rules/shebang.md b/docs/rules/shebang.md
index 126daea5..67739614 100644
--- a/docs/rules/shebang.md
+++ b/docs/rules/shebang.md
@@ -1,6 +1,6 @@
-# Require correct usage of shebang (`n/shebang`)
+# Require correct usage of hashbang (`n/shebang`)
-💼 This rule is enabled in the following [configs](https://github.com/eslint-community/eslint-plugin-n#-configs): ☑️ `flat/recommended`, 🟢 `flat/recommended-module`, ✅ `flat/recommended-script`, ☑️ `recommended`, 🟢 `recommended-module`, ✅ `recommended-script`.
+❌ This rule is deprecated. It was replaced by [`n/hashbang`](hashbang.md).
🔧 This rule is automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix).
diff --git a/lib/configs/_commons.js b/lib/configs/_commons.js
index 86ae6d0c..1e2b070d 100644
--- a/lib/configs/_commons.js
+++ b/lib/configs/_commons.js
@@ -16,6 +16,6 @@ module.exports = {
"n/no-unsupported-features/es-syntax": "error",
"n/no-unsupported-features/node-builtins": "error",
"n/process-exit-as-throw": "error",
- "n/shebang": "error",
+ "n/hashbang": "error",
},
}
diff --git a/lib/index.js b/lib/index.js
index 6497d227..39331a60 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -43,10 +43,11 @@ const rules = {
"prefer-promises/dns": require("./rules/prefer-promises/dns"),
"prefer-promises/fs": require("./rules/prefer-promises/fs"),
"process-exit-as-throw": require("./rules/process-exit-as-throw"),
- shebang: require("./rules/shebang"),
+ hashbang: require("./rules/hashbang"),
// Deprecated rules.
"no-hide-core-modules": require("./rules/no-hide-core-modules"),
+ shebang: require("./rules/shebang"),
}
const mod = {
diff --git a/lib/rules/hashbang.js b/lib/rules/hashbang.js
new file mode 100644
index 00000000..8baee0a0
--- /dev/null
+++ b/lib/rules/hashbang.js
@@ -0,0 +1,212 @@
+/**
+ * @author Toru Nagashima
+ * See LICENSE file in root directory for full license.
+ */
+"use strict"
+
+const path = require("path")
+const matcher = require("ignore")
+
+const getConvertPath = require("../util/get-convert-path")
+const getPackageJson = require("../util/get-package-json")
+const getNpmignore = require("../util/get-npmignore")
+
+const NODE_SHEBANG = "#!/usr/bin/env node\n"
+const SHEBANG_PATTERN = /^(#!.+?)?(\r)?\n/u
+const NODE_SHEBANG_PATTERN =
+ /^#!\/usr\/bin\/env(?: -\S+)*(?: [^\s=-]+=\S+)* node(?: [^\r\n]+?)?\n/u
+
+function simulateNodeResolutionAlgorithm(filePath, binField) {
+ const possibilities = [filePath]
+ let newFilePath = filePath.replace(/\.js$/u, "")
+ possibilities.push(newFilePath)
+ newFilePath = newFilePath.replace(/[/\\]index$/u, "")
+ possibilities.push(newFilePath)
+ return possibilities.includes(binField)
+}
+
+/**
+ * Checks whether or not a given path is a `bin` file.
+ *
+ * @param {string} filePath - A file path to check.
+ * @param {string|object|undefined} binField - A value of the `bin` field of `package.json`.
+ * @param {string} basedir - A directory path that `package.json` exists.
+ * @returns {boolean} `true` if the file is a `bin` file.
+ */
+function isBinFile(filePath, binField, basedir) {
+ if (!binField) {
+ return false
+ }
+ if (typeof binField === "string") {
+ return simulateNodeResolutionAlgorithm(
+ filePath,
+ path.resolve(basedir, binField)
+ )
+ }
+ return Object.keys(binField).some(key =>
+ simulateNodeResolutionAlgorithm(
+ filePath,
+ path.resolve(basedir, binField[key])
+ )
+ )
+}
+
+/**
+ * Gets the shebang line (includes a line ending) from a given code.
+ *
+ * @param {SourceCode} sourceCode - A source code object to check.
+ * @returns {{length: number, bom: boolean, shebang: string, cr: boolean}}
+ * shebang's information.
+ * `retv.shebang` is an empty string if shebang doesn't exist.
+ */
+function getShebangInfo(sourceCode) {
+ const m = SHEBANG_PATTERN.exec(sourceCode.text)
+
+ return {
+ bom: sourceCode.hasBOM,
+ cr: Boolean(m && m[2]),
+ length: (m && m[0].length) || 0,
+ shebang: (m && m[1] && `${m[1]}\n`) || "",
+ }
+}
+
+/** @type {import('eslint').Rule.RuleModule} */
+module.exports = {
+ meta: {
+ docs: {
+ description: "require correct usage of hashbang",
+ recommended: true,
+ url: "https://github.com/eslint-community/eslint-plugin-n/blob/HEAD/docs/rules/hashbang.md",
+ },
+ type: "problem",
+ fixable: "code",
+ schema: [
+ {
+ type: "object",
+ properties: {
+ convertPath: getConvertPath.schema,
+ ignoreUnpublished: { type: "boolean" },
+ additionalExecutables: {
+ type: "array",
+ items: { type: "string" },
+ },
+ },
+ additionalProperties: false,
+ },
+ ],
+ messages: {
+ unexpectedBOM: "This file must not have Unicode BOM.",
+ expectedLF: "This file must have Unix linebreaks (LF).",
+ expectedHashbangNode:
+ 'This file needs shebang "#!/usr/bin/env node".',
+ expectedHashbang: "This file needs no shebang.",
+ },
+ },
+ create(context) {
+ const sourceCode = context.sourceCode ?? context.getSourceCode() // TODO: just use context.sourceCode when dropping eslint < v9
+ const filePath = context.filename ?? context.getFilename()
+ if (filePath === "") {
+ return {}
+ }
+
+ const p = getPackageJson(filePath)
+ if (!p) {
+ return {}
+ }
+
+ const packageDirectory = path.dirname(p.filePath)
+
+ const originalAbsolutePath = path.resolve(filePath)
+ const originalRelativePath = path
+ .relative(packageDirectory, originalAbsolutePath)
+ .replace(/\\/gu, "/")
+
+ const convertedRelativePath =
+ getConvertPath(context)(originalRelativePath)
+ const convertedAbsolutePath = path.resolve(
+ packageDirectory,
+ convertedRelativePath
+ )
+
+ const { additionalExecutables = [] } = context.options?.[0] ?? {}
+
+ const executable = matcher()
+ executable.add(additionalExecutables)
+ const isExecutable = executable.test(convertedRelativePath)
+
+ if (
+ (additionalExecutables.length === 0 ||
+ isExecutable.ignored === false) &&
+ context.options?.[0]?.ignoreUnpublished === true
+ ) {
+ const npmignore = getNpmignore(convertedAbsolutePath)
+
+ if (npmignore.match(convertedRelativePath)) {
+ return {}
+ }
+ }
+
+ const needsShebang =
+ isExecutable.ignored === true ||
+ isBinFile(convertedAbsolutePath, p.bin, packageDirectory)
+ const info = getShebangInfo(sourceCode)
+
+ return {
+ Program() {
+ const loc = {
+ start: { line: 1, column: 0 },
+ end: { line: 1, column: sourceCode.lines.at(0).length },
+ }
+
+ if (
+ needsShebang
+ ? NODE_SHEBANG_PATTERN.test(info.shebang)
+ : !info.shebang
+ ) {
+ // Good the shebang target.
+ // Checks BOM and \r.
+ if (needsShebang && info.bom) {
+ context.report({
+ loc,
+ messageId: "unexpectedBOM",
+ fix(fixer) {
+ return fixer.removeRange([-1, 0])
+ },
+ })
+ }
+ if (needsShebang && info.cr) {
+ context.report({
+ loc,
+ messageId: "expectedLF",
+ fix(fixer) {
+ const index = sourceCode.text.indexOf("\r")
+ return fixer.removeRange([index, index + 1])
+ },
+ })
+ }
+ } else if (needsShebang) {
+ // Shebang is lacking.
+ context.report({
+ loc,
+ messageId: "expectedHashbangNode",
+ fix(fixer) {
+ return fixer.replaceTextRange(
+ [-1, info.length],
+ NODE_SHEBANG
+ )
+ },
+ })
+ } else {
+ // Shebang is extra.
+ context.report({
+ loc,
+ messageId: "expectedHashbang",
+ fix(fixer) {
+ return fixer.removeRange([0, info.length])
+ },
+ })
+ }
+ },
+ }
+ },
+}
diff --git a/lib/rules/shebang.js b/lib/rules/shebang.js
index 0989d50d..86ac0236 100644
--- a/lib/rules/shebang.js
+++ b/lib/rules/shebang.js
@@ -1,212 +1,18 @@
/**
- * @author Toru Nagashima
- * See LICENSE file in root directory for full license.
+ * @fileoverview the rule has been renamed to `hashbang`. Please use `hashbang` instead.
+ * @deprecated
+ * @author 唯然
*/
"use strict"
-const path = require("path")
-const matcher = require("ignore")
+const hashbang = require("./hashbang.js")
-const getConvertPath = require("../util/get-convert-path")
-const getPackageJson = require("../util/get-package-json")
-const getNpmignore = require("../util/get-npmignore")
-
-const NODE_SHEBANG = "#!/usr/bin/env node\n"
-const SHEBANG_PATTERN = /^(#!.+?)?(\r)?\n/u
-const NODE_SHEBANG_PATTERN =
- /^#!\/usr\/bin\/env(?: -\S+)*(?: [^\s=-]+=\S+)* node(?: [^\r\n]+?)?\n/u
-
-function simulateNodeResolutionAlgorithm(filePath, binField) {
- const possibilities = [filePath]
- let newFilePath = filePath.replace(/\.js$/u, "")
- possibilities.push(newFilePath)
- newFilePath = newFilePath.replace(/[/\\]index$/u, "")
- possibilities.push(newFilePath)
- return possibilities.includes(binField)
-}
-
-/**
- * Checks whether or not a given path is a `bin` file.
- *
- * @param {string} filePath - A file path to check.
- * @param {string|object|undefined} binField - A value of the `bin` field of `package.json`.
- * @param {string} basedir - A directory path that `package.json` exists.
- * @returns {boolean} `true` if the file is a `bin` file.
- */
-function isBinFile(filePath, binField, basedir) {
- if (!binField) {
- return false
- }
- if (typeof binField === "string") {
- return simulateNodeResolutionAlgorithm(
- filePath,
- path.resolve(basedir, binField)
- )
- }
- return Object.keys(binField).some(key =>
- simulateNodeResolutionAlgorithm(
- filePath,
- path.resolve(basedir, binField[key])
- )
- )
-}
-
-/**
- * Gets the shebang line (includes a line ending) from a given code.
- *
- * @param {SourceCode} sourceCode - A source code object to check.
- * @returns {{length: number, bom: boolean, shebang: string, cr: boolean}}
- * shebang's information.
- * `retv.shebang` is an empty string if shebang doesn't exist.
- */
-function getShebangInfo(sourceCode) {
- const m = SHEBANG_PATTERN.exec(sourceCode.text)
-
- return {
- bom: sourceCode.hasBOM,
- cr: Boolean(m && m[2]),
- length: (m && m[0].length) || 0,
- shebang: (m && m[1] && `${m[1]}\n`) || "",
- }
-}
-
-/** @type {import('eslint').Rule.RuleModule} */
module.exports = {
meta: {
- docs: {
- description: "require correct usage of shebang",
- recommended: true,
- url: "https://github.com/eslint-community/eslint-plugin-n/blob/HEAD/docs/rules/shebang.md",
- },
- type: "problem",
- fixable: "code",
- schema: [
- {
- type: "object",
- properties: {
- convertPath: getConvertPath.schema,
- ignoreUnpublished: { type: "boolean" },
- additionalExecutables: {
- type: "array",
- items: { type: "string" },
- },
- },
- additionalProperties: false,
- },
- ],
- messages: {
- unexpectedBOM: "This file must not have Unicode BOM.",
- expectedLF: "This file must have Unix linebreaks (LF).",
- expectedHashbangNode:
- 'This file needs shebang "#!/usr/bin/env node".',
- expectedHashbang: "This file needs no shebang.",
- },
- },
- create(context) {
- const sourceCode = context.sourceCode ?? context.getSourceCode() // TODO: just use context.sourceCode when dropping eslint < v9
- const filePath = context.filename ?? context.getFilename()
- if (filePath === "") {
- return {}
- }
-
- const p = getPackageJson(filePath)
- if (!p) {
- return {}
- }
-
- const packageDirectory = path.dirname(p.filePath)
-
- const originalAbsolutePath = path.resolve(filePath)
- const originalRelativePath = path
- .relative(packageDirectory, originalAbsolutePath)
- .replace(/\\/gu, "/")
-
- const convertedRelativePath =
- getConvertPath(context)(originalRelativePath)
- const convertedAbsolutePath = path.resolve(
- packageDirectory,
- convertedRelativePath
- )
-
- const { additionalExecutables = [] } = context.options?.[0] ?? {}
-
- const executable = matcher()
- executable.add(additionalExecutables)
- const isExecutable = executable.test(convertedRelativePath)
-
- if (
- (additionalExecutables.length === 0 ||
- isExecutable.ignored === false) &&
- context.options?.[0]?.ignoreUnpublished === true
- ) {
- const npmignore = getNpmignore(convertedAbsolutePath)
-
- if (npmignore.match(convertedRelativePath)) {
- return {}
- }
- }
-
- const needsShebang =
- isExecutable.ignored === true ||
- isBinFile(convertedAbsolutePath, p.bin, packageDirectory)
- const info = getShebangInfo(sourceCode)
-
- return {
- Program() {
- const loc = {
- start: { line: 1, column: 0 },
- end: { line: 1, column: sourceCode.lines.at(0).length },
- }
-
- if (
- needsShebang
- ? NODE_SHEBANG_PATTERN.test(info.shebang)
- : !info.shebang
- ) {
- // Good the shebang target.
- // Checks BOM and \r.
- if (needsShebang && info.bom) {
- context.report({
- loc,
- messageId: "unexpectedBOM",
- fix(fixer) {
- return fixer.removeRange([-1, 0])
- },
- })
- }
- if (needsShebang && info.cr) {
- context.report({
- loc,
- messageId: "expectedLF",
- fix(fixer) {
- const index = sourceCode.text.indexOf("\r")
- return fixer.removeRange([index, index + 1])
- },
- })
- }
- } else if (needsShebang) {
- // Shebang is lacking.
- context.report({
- loc,
- messageId: "expectedHashbangNode",
- fix(fixer) {
- return fixer.replaceTextRange(
- [-1, info.length],
- NODE_SHEBANG
- )
- },
- })
- } else {
- // Shebang is extra.
- context.report({
- loc,
- messageId: "expectedHashbang",
- fix(fixer) {
- return fixer.removeRange([0, info.length])
- },
- })
- }
- },
- }
+ ...hashbang.meta,
+ deprecated: true,
+ replacedBy: ["n/hashbang"],
+ docs: { ...hashbang.meta.docs, recommended: false },
},
+ create: hashbang.create,
}
diff --git a/tests/lib/rules/hashbang.js b/tests/lib/rules/hashbang.js
new file mode 100644
index 00000000..f2640679
--- /dev/null
+++ b/tests/lib/rules/hashbang.js
@@ -0,0 +1,465 @@
+/**
+ * @author Toru Nagashima
+ * See LICENSE file in root directory for full license.
+ */
+"use strict"
+
+const path = require("path")
+const RuleTester = require("#eslint-rule-tester").RuleTester
+const rule = require("../../../lib/rules/shebang")
+
+/**
+ * Makes a file path to a fixture.
+ * @param {string} name - A name.
+ * @returns {string} A file path to a fixture.
+ */
+function fixture(name) {
+ return path.resolve(__dirname, "../../fixtures/shebang", name)
+}
+
+/** @type {import('eslint').RuleTester} */
+const ruleTester = new RuleTester()
+ruleTester.run("shebang", rule, {
+ valid: [
+ {
+ name: "string-bin/bin/test.js",
+ filename: fixture("string-bin/bin/test.js"),
+ code: "#!/usr/bin/env node\nhello();",
+ },
+ {
+ name: "string-bin/lib/test.js",
+ filename: fixture("string-bin/lib/test.js"),
+ code: "hello();",
+ },
+ {
+ name: "object-bin/bin/a.js",
+ filename: fixture("object-bin/bin/a.js"),
+ code: "#!/usr/bin/env node\nhello();",
+ },
+ {
+ name: "object-bin/bin/b.js",
+ filename: fixture("object-bin/bin/b.js"),
+ code: "#!/usr/bin/env node\nhello();",
+ },
+ {
+ name: "string-bin/bin/test.js",
+ filename: fixture("string-bin/bin/test.js"),
+ code: "#!/usr/bin/env -S node\nhello();",
+ },
+ {
+ name: "string-bin/bin/test.js",
+ filename: fixture("string-bin/bin/test.js"),
+ code: "#!/usr/bin/env -S node --loader tsm\nhello();",
+ },
+ {
+ name: "string-bin/bin/test.js",
+ filename: fixture("string-bin/bin/test.js"),
+ code: "#!/usr/bin/env --ignore-environment node\nhello();",
+ },
+ {
+ name: "string-bin/bin/test.js",
+ filename: fixture("string-bin/bin/test.js"),
+ code: "#!/usr/bin/env -i -S node --loader tsm\nhello();",
+ },
+ {
+ name: "string-bin/bin/test.js",
+ filename: fixture("string-bin/bin/test.js"),
+ code: "#!/usr/bin/env --block-signal=SIGINT -S FOO=bar node --loader tsm\nhello();",
+ },
+ {
+ name: "object-bin/bin/c.js",
+ filename: fixture("object-bin/bin/c.js"),
+ code: "hello();",
+ },
+ {
+ name: "no-bin-field/lib/test.js",
+ filename: fixture("no-bin-field/lib/test.js"),
+ code: "hello();",
+ },
+ {
+ name: " with shebang",
+ code: "#!/usr/bin/env node\nhello();",
+ },
+ {
+ name: " without shebang",
+ code: "hello();",
+ },
+
+ // convertPath
+ {
+ name: "convertPath - string-bin/src/bin/test.js",
+ filename: fixture("string-bin/src/bin/test.js"),
+ code: "#!/usr/bin/env node\nhello();",
+ options: [{ convertPath: { "src/**": ["^src/(.+)$", "$1"] } }],
+ },
+ {
+ name: "convertPath - string-bin/src/lib/test.js",
+ filename: fixture("string-bin/src/lib/test.js"),
+ code: "hello();",
+ options: [{ convertPath: { "src/**": ["^src/(.+)$", "$1"] } }],
+ },
+ {
+ name: "convertPath - object-bin/src/bin/a.js",
+ filename: fixture("object-bin/src/bin/a.js"),
+ code: "#!/usr/bin/env node\nhello();",
+ options: [{ convertPath: { "src/**": ["^src/(.+)$", "$1"] } }],
+ },
+ {
+ name: "convertPath - object-bin/src/bin/b.js",
+ filename: fixture("object-bin/src/bin/b.js"),
+ code: "#!/usr/bin/env node\nhello();",
+ options: [{ convertPath: { "src/**": ["^src/(.+)$", "$1"] } }],
+ },
+ {
+ name: "convertPath - object-bin/src/bin/c.js",
+ filename: fixture("object-bin/src/bin/c.js"),
+ code: "hello();",
+ options: [{ convertPath: { "src/**": ["^src/(.+)$", "$1"] } }],
+ },
+ {
+ name: "convertPath - no-bin-field/src/lib/test.js",
+ filename: fixture("no-bin-field/src/lib/test.js"),
+ code: "hello();",
+ options: [{ convertPath: { "src/**": ["^src/(.+)$", "$1"] } }],
+ },
+
+ // Should work fine if the filename is relative.
+ {
+ name: "relative path - string-bin/bin/test.js",
+ filename: "tests/fixtures/shebang/string-bin/bin/test.js",
+ code: "#!/usr/bin/env node\nhello();",
+ },
+ {
+ name: "relative path - string-bin/lib/test.js",
+ filename: "tests/fixtures/shebang/string-bin/lib/test.js",
+ code: "hello();",
+ },
+
+ // BOM and \r\n
+ {
+ name: "BOM without newline",
+ filename: fixture("string-bin/lib/test.js"),
+ code: "\uFEFFhello();",
+ },
+ {
+ name: "BOM with newline",
+ filename: fixture("string-bin/lib/test.js"),
+ code: "\uFEFFhello();\n",
+ },
+ {
+ name: "with windows newline",
+ filename: fixture("string-bin/lib/test.js"),
+ code: "hello();\r\n",
+ },
+ {
+ name: "BOM with windows newline",
+ filename: fixture("string-bin/lib/test.js"),
+ code: "\uFEFFhello();\r\n",
+ },
+
+ // blank lines on the top of files.
+ {
+ name: "blank lines on the top of files.",
+ filename: fixture("string-bin/lib/test.js"),
+ code: "\n\n\nhello();",
+ },
+
+ // https://github.com/mysticatea/eslint-plugin-node/issues/51
+ {
+ name: "Shebang with CLI flags",
+ filename: fixture("string-bin/bin/test.js"),
+ code: "#!/usr/bin/env node --harmony\nhello();",
+ },
+
+ // use node resolution
+ {
+ name: "use node resolution",
+ filename: fixture("object-bin/bin/index.js"),
+ code: "#!/usr/bin/env node\nhello();",
+ },
+
+ // npm unpublished files are ignored
+ {
+ name: "published file cant have shebang",
+ filename: fixture("unpublished/published.js"),
+ code: "hello();",
+ options: [{ ignoreUnpublished: true }],
+ },
+ {
+ name: "unpublished file can have shebang",
+ filename: fixture("unpublished/unpublished.js"),
+ code: "#!/usr/bin/env node\nhello();",
+ options: [{ ignoreUnpublished: true }],
+ },
+ {
+ name: "unpublished file can have noshebang",
+ filename: fixture("unpublished/unpublished.js"),
+ code: "hello();",
+ options: [{ ignoreUnpublished: true }],
+ },
+
+ {
+ name: "file matching additionalExecutables",
+ filename: fixture("unpublished/something.test.js"),
+ code: "#!/usr/bin/env node\nhello();",
+ options: [{ additionalExecutables: ["*.test.js"] }],
+ },
+ ],
+ invalid: [
+ {
+ name: "bin: string - match - no shebang",
+ filename: fixture("string-bin/bin/test.js"),
+ code: "hello();",
+ output: "#!/usr/bin/env node\nhello();",
+ errors: ['This file needs shebang "#!/usr/bin/env node".'],
+ },
+ {
+ name: "bin: string - match - incorrect shebang",
+ filename: fixture("string-bin/bin/test.js"),
+ code: "#!/usr/bin/node\nhello();",
+ output: "#!/usr/bin/env node\nhello();",
+ errors: ['This file needs shebang "#!/usr/bin/env node".'],
+ },
+ {
+ name: "bin: string - no match - with shebang",
+ filename: fixture("string-bin/lib/test.js"),
+ code: "#!/usr/bin/env node\nhello();",
+ output: "hello();",
+ errors: ["This file needs no shebang."],
+ },
+ {
+ name: 'bin: {a: "./bin/a.js"} - match - no shebang',
+ filename: fixture("object-bin/bin/a.js"),
+ code: "hello();",
+ output: "#!/usr/bin/env node\nhello();",
+ errors: ['This file needs shebang "#!/usr/bin/env node".'],
+ },
+ {
+ name: 'bin: {b: "./bin/b.js"} - match - no shebang',
+ filename: fixture("object-bin/bin/b.js"),
+ code: "#!/usr/bin/node\nhello();",
+ output: "#!/usr/bin/env node\nhello();",
+ errors: ['This file needs shebang "#!/usr/bin/env node".'],
+ },
+ {
+ name: 'bin: {c: "./bin"} - no match - with shebang',
+ filename: fixture("object-bin/bin/c.js"),
+ code: "#!/usr/bin/env node\nhello();",
+ output: "hello();",
+ errors: ["This file needs no shebang."],
+ },
+ {
+ name: "bin: undefined - no match - with shebang",
+ filename: fixture("no-bin-field/lib/test.js"),
+ code: "#!/usr/bin/env node\nhello();",
+ output: "hello();",
+ errors: ["This file needs no shebang."],
+ },
+
+ // convertPath
+ {
+ name: "convertPath in options",
+ filename: fixture("string-bin/src/bin/test.js"),
+ code: "hello();",
+ output: "#!/usr/bin/env node\nhello();",
+ options: [{ convertPath: { "src/**": ["^src/(.+)$", "$1"] } }],
+ errors: ['This file needs shebang "#!/usr/bin/env node".'],
+ },
+ {
+ name: "convertPath in settings",
+ filename: fixture("string-bin/src/bin/test.js"),
+ code: "hello();",
+ output: "#!/usr/bin/env node\nhello();",
+ errors: ['This file needs shebang "#!/usr/bin/env node".'],
+ settings: {
+ node: { convertPath: { "src/**": ["^src/(.+)$", "$1"] } },
+ },
+ },
+ {
+ name: "converted path - string-bin/src/bin/test.js",
+ filename: fixture("string-bin/src/bin/test.js"),
+ code: "#!/usr/bin/node\nhello();",
+ output: "#!/usr/bin/env node\nhello();",
+ options: [{ convertPath: { "src/**": ["^src/(.+)$", "$1"] } }],
+ errors: ['This file needs shebang "#!/usr/bin/env node".'],
+ },
+ {
+ name: "converted path - string-bin/src/lib/test.js",
+ filename: fixture("string-bin/src/lib/test.js"),
+ code: "#!/usr/bin/env node\nhello();",
+ output: "hello();",
+ options: [{ convertPath: { "src/**": ["^src/(.+)$", "$1"] } }],
+ errors: ["This file needs no shebang."],
+ },
+ {
+ name: "converted path - object-bin/src/bin/a.js",
+ filename: fixture("object-bin/src/bin/a.js"),
+ code: "hello();",
+ output: "#!/usr/bin/env node\nhello();",
+ options: [{ convertPath: { "src/**": ["^src/(.+)$", "$1"] } }],
+ errors: ['This file needs shebang "#!/usr/bin/env node".'],
+ },
+ {
+ name: "converted path - object-bin/src/bin/b.js",
+ filename: fixture("object-bin/src/bin/b.js"),
+ code: "#!/usr/bin/node\nhello();",
+ output: "#!/usr/bin/env node\nhello();",
+ options: [{ convertPath: { "src/**": ["^src/(.+)$", "$1"] } }],
+ errors: ['This file needs shebang "#!/usr/bin/env node".'],
+ },
+ {
+ name: "converted path - object-bin/src/bin/c.js",
+ filename: fixture("object-bin/src/bin/c.js"),
+ code: "#!/usr/bin/env node\nhello();",
+ output: "hello();",
+ options: [{ convertPath: { "src/**": ["^src/(.+)$", "$1"] } }],
+ errors: ["This file needs no shebang."],
+ },
+ {
+ name: "converted path - no-bin-field/src/lib/test.js",
+ filename: fixture("no-bin-field/src/lib/test.js"),
+ code: "#!/usr/bin/env node\nhello();",
+ output: "hello();",
+ options: [{ convertPath: { "src/**": ["^src/(.+)$", "$1"] } }],
+ errors: ["This file needs no shebang."],
+ },
+
+ // Should work fine if the filename is relative.
+ {
+ name: "relative path - string-bin/bin/test.js",
+ filename: "tests/fixtures/shebang/string-bin/bin/test.js",
+ code: "hello();",
+ output: "#!/usr/bin/env node\nhello();",
+ errors: ['This file needs shebang "#!/usr/bin/env node".'],
+ },
+ {
+ name: "relative path - string-bin/lib/test.js",
+ filename: "tests/fixtures/shebang/string-bin/lib/test.js",
+ code: "#!/usr/bin/env node\nhello();",
+ output: "hello();",
+ errors: ["This file needs no shebang."],
+ },
+
+ // header comments
+ {
+ name: "header comments",
+ filename: fixture("string-bin/bin/test.js"),
+ code: "/* header */\nhello();",
+ output: "#!/usr/bin/env node\n/* header */\nhello();",
+ errors: ['This file needs shebang "#!/usr/bin/env node".'],
+ },
+
+ // BOM and \r\n
+ {
+ filename: fixture("string-bin/bin/test.js"),
+ code: "\uFEFFhello();",
+ output: "#!/usr/bin/env node\nhello();",
+ errors: ['This file needs shebang "#!/usr/bin/env node".'],
+ },
+ {
+ filename: fixture("string-bin/bin/test.js"),
+ code: "hello();\n",
+ output: "#!/usr/bin/env node\nhello();\n",
+ errors: ['This file needs shebang "#!/usr/bin/env node".'],
+ },
+ {
+ filename: fixture("string-bin/bin/test.js"),
+ code: "hello();\r\n",
+ output: "#!/usr/bin/env node\nhello();\r\n",
+ errors: ['This file needs shebang "#!/usr/bin/env node".'],
+ },
+ {
+ filename: fixture("string-bin/bin/test.js"),
+ code: "\uFEFFhello();\n",
+ output: "#!/usr/bin/env node\nhello();\n",
+ errors: ['This file needs shebang "#!/usr/bin/env node".'],
+ },
+ {
+ filename: fixture("string-bin/bin/test.js"),
+ code: "\uFEFFhello();\r\n",
+ output: "#!/usr/bin/env node\nhello();\r\n",
+ errors: ['This file needs shebang "#!/usr/bin/env node".'],
+ },
+ {
+ filename: fixture("string-bin/bin/test.js"),
+ code: "#!/usr/bin/env node\r\nhello();",
+ output: "#!/usr/bin/env node\nhello();",
+ errors: ["This file must have Unix linebreaks (LF)."],
+ },
+ {
+ filename: fixture("string-bin/bin/test.js"),
+ code: "\uFEFF#!/usr/bin/env node\nhello();",
+ output: "#!/usr/bin/env node\nhello();",
+ errors: ["This file must not have Unicode BOM."],
+ },
+ {
+ filename: fixture("string-bin/bin/test.js"),
+ code: "\uFEFF#!/usr/bin/env node\r\nhello();",
+ output: "#!/usr/bin/env node\nhello();",
+ errors: [
+ "This file must not have Unicode BOM.",
+ "This file must have Unix linebreaks (LF).",
+ ],
+ },
+
+ // https://github.com/mysticatea/eslint-plugin-node/issues/51
+ {
+ name: "Shebang with CLI flags",
+ filename: fixture("string-bin/lib/test.js"),
+ code: "#!/usr/bin/env node --harmony\nhello();",
+ output: "hello();",
+ errors: ["This file needs no shebang."],
+ },
+
+ // use node resolution
+ {
+ name: "use node resolution",
+ filename: fixture("object-bin/bin/index.js"),
+ code: "hello();",
+ output: "#!/usr/bin/env node\nhello();",
+ errors: ['This file needs shebang "#!/usr/bin/env node".'],
+ },
+
+ // npm unpublished files are ignored
+ {
+ name: "unpublished file should not have shebang",
+ filename: fixture("unpublished/unpublished.js"),
+ code: "#!/usr/bin/env node\nhello();",
+ output: "hello();",
+ errors: ["This file needs no shebang."],
+ },
+ {
+ name: "published file should have shebang",
+ filename: fixture("unpublished/published.js"),
+ code: "#!/usr/bin/env node\nhello();",
+ output: "hello();",
+ errors: ["This file needs no shebang."],
+ },
+
+ {
+ name: "unpublished file shebang ignored",
+ filename: fixture("unpublished/published.js"),
+ code: "#!/usr/bin/env node\nhello();",
+ options: [{ ignoreUnpublished: true }],
+ output: "hello();",
+ errors: ["This file needs no shebang."],
+ },
+
+ {
+ name: "executable in additionalExecutables without shebang",
+ filename: fixture("unpublished/something.test.js"),
+ code: "hello();",
+ options: [{ additionalExecutables: ["*.test.js"] }],
+ output: "#!/usr/bin/env node\nhello();",
+ errors: ['This file needs shebang "#!/usr/bin/env node".'],
+ },
+ {
+ name: "file not in additionalExecutables with shebang",
+ filename: fixture("unpublished/not-a-test.js"),
+ code: "#!/usr/bin/env node\nhello();",
+ options: [{ additionalExecutables: ["*.test.js"] }],
+ output: "hello();",
+ errors: ["This file needs no shebang."],
+ },
+ ],
+})
diff --git a/tests/lib/rules/shebang.js b/tests/lib/rules/shebang.js
index f2640679..7e096606 100644
--- a/tests/lib/rules/shebang.js
+++ b/tests/lib/rules/shebang.js
@@ -1,465 +1,11 @@
-/**
- * @author Toru Nagashima
- * See LICENSE file in root directory for full license.
- */
"use strict"
+const assert = require("assert/strict")
-const path = require("path")
-const RuleTester = require("#eslint-rule-tester").RuleTester
-const rule = require("../../../lib/rules/shebang")
+it("should export shebang as alias ", () => {
+ const shebang = require("../../../lib/rules/shebang.js")
+ const hashbang = require("../../../lib/rules/hashbang.js")
-/**
- * Makes a file path to a fixture.
- * @param {string} name - A name.
- * @returns {string} A file path to a fixture.
- */
-function fixture(name) {
- return path.resolve(__dirname, "../../fixtures/shebang", name)
-}
-
-/** @type {import('eslint').RuleTester} */
-const ruleTester = new RuleTester()
-ruleTester.run("shebang", rule, {
- valid: [
- {
- name: "string-bin/bin/test.js",
- filename: fixture("string-bin/bin/test.js"),
- code: "#!/usr/bin/env node\nhello();",
- },
- {
- name: "string-bin/lib/test.js",
- filename: fixture("string-bin/lib/test.js"),
- code: "hello();",
- },
- {
- name: "object-bin/bin/a.js",
- filename: fixture("object-bin/bin/a.js"),
- code: "#!/usr/bin/env node\nhello();",
- },
- {
- name: "object-bin/bin/b.js",
- filename: fixture("object-bin/bin/b.js"),
- code: "#!/usr/bin/env node\nhello();",
- },
- {
- name: "string-bin/bin/test.js",
- filename: fixture("string-bin/bin/test.js"),
- code: "#!/usr/bin/env -S node\nhello();",
- },
- {
- name: "string-bin/bin/test.js",
- filename: fixture("string-bin/bin/test.js"),
- code: "#!/usr/bin/env -S node --loader tsm\nhello();",
- },
- {
- name: "string-bin/bin/test.js",
- filename: fixture("string-bin/bin/test.js"),
- code: "#!/usr/bin/env --ignore-environment node\nhello();",
- },
- {
- name: "string-bin/bin/test.js",
- filename: fixture("string-bin/bin/test.js"),
- code: "#!/usr/bin/env -i -S node --loader tsm\nhello();",
- },
- {
- name: "string-bin/bin/test.js",
- filename: fixture("string-bin/bin/test.js"),
- code: "#!/usr/bin/env --block-signal=SIGINT -S FOO=bar node --loader tsm\nhello();",
- },
- {
- name: "object-bin/bin/c.js",
- filename: fixture("object-bin/bin/c.js"),
- code: "hello();",
- },
- {
- name: "no-bin-field/lib/test.js",
- filename: fixture("no-bin-field/lib/test.js"),
- code: "hello();",
- },
- {
- name: " with shebang",
- code: "#!/usr/bin/env node\nhello();",
- },
- {
- name: " without shebang",
- code: "hello();",
- },
-
- // convertPath
- {
- name: "convertPath - string-bin/src/bin/test.js",
- filename: fixture("string-bin/src/bin/test.js"),
- code: "#!/usr/bin/env node\nhello();",
- options: [{ convertPath: { "src/**": ["^src/(.+)$", "$1"] } }],
- },
- {
- name: "convertPath - string-bin/src/lib/test.js",
- filename: fixture("string-bin/src/lib/test.js"),
- code: "hello();",
- options: [{ convertPath: { "src/**": ["^src/(.+)$", "$1"] } }],
- },
- {
- name: "convertPath - object-bin/src/bin/a.js",
- filename: fixture("object-bin/src/bin/a.js"),
- code: "#!/usr/bin/env node\nhello();",
- options: [{ convertPath: { "src/**": ["^src/(.+)$", "$1"] } }],
- },
- {
- name: "convertPath - object-bin/src/bin/b.js",
- filename: fixture("object-bin/src/bin/b.js"),
- code: "#!/usr/bin/env node\nhello();",
- options: [{ convertPath: { "src/**": ["^src/(.+)$", "$1"] } }],
- },
- {
- name: "convertPath - object-bin/src/bin/c.js",
- filename: fixture("object-bin/src/bin/c.js"),
- code: "hello();",
- options: [{ convertPath: { "src/**": ["^src/(.+)$", "$1"] } }],
- },
- {
- name: "convertPath - no-bin-field/src/lib/test.js",
- filename: fixture("no-bin-field/src/lib/test.js"),
- code: "hello();",
- options: [{ convertPath: { "src/**": ["^src/(.+)$", "$1"] } }],
- },
-
- // Should work fine if the filename is relative.
- {
- name: "relative path - string-bin/bin/test.js",
- filename: "tests/fixtures/shebang/string-bin/bin/test.js",
- code: "#!/usr/bin/env node\nhello();",
- },
- {
- name: "relative path - string-bin/lib/test.js",
- filename: "tests/fixtures/shebang/string-bin/lib/test.js",
- code: "hello();",
- },
-
- // BOM and \r\n
- {
- name: "BOM without newline",
- filename: fixture("string-bin/lib/test.js"),
- code: "\uFEFFhello();",
- },
- {
- name: "BOM with newline",
- filename: fixture("string-bin/lib/test.js"),
- code: "\uFEFFhello();\n",
- },
- {
- name: "with windows newline",
- filename: fixture("string-bin/lib/test.js"),
- code: "hello();\r\n",
- },
- {
- name: "BOM with windows newline",
- filename: fixture("string-bin/lib/test.js"),
- code: "\uFEFFhello();\r\n",
- },
-
- // blank lines on the top of files.
- {
- name: "blank lines on the top of files.",
- filename: fixture("string-bin/lib/test.js"),
- code: "\n\n\nhello();",
- },
-
- // https://github.com/mysticatea/eslint-plugin-node/issues/51
- {
- name: "Shebang with CLI flags",
- filename: fixture("string-bin/bin/test.js"),
- code: "#!/usr/bin/env node --harmony\nhello();",
- },
-
- // use node resolution
- {
- name: "use node resolution",
- filename: fixture("object-bin/bin/index.js"),
- code: "#!/usr/bin/env node\nhello();",
- },
-
- // npm unpublished files are ignored
- {
- name: "published file cant have shebang",
- filename: fixture("unpublished/published.js"),
- code: "hello();",
- options: [{ ignoreUnpublished: true }],
- },
- {
- name: "unpublished file can have shebang",
- filename: fixture("unpublished/unpublished.js"),
- code: "#!/usr/bin/env node\nhello();",
- options: [{ ignoreUnpublished: true }],
- },
- {
- name: "unpublished file can have noshebang",
- filename: fixture("unpublished/unpublished.js"),
- code: "hello();",
- options: [{ ignoreUnpublished: true }],
- },
-
- {
- name: "file matching additionalExecutables",
- filename: fixture("unpublished/something.test.js"),
- code: "#!/usr/bin/env node\nhello();",
- options: [{ additionalExecutables: ["*.test.js"] }],
- },
- ],
- invalid: [
- {
- name: "bin: string - match - no shebang",
- filename: fixture("string-bin/bin/test.js"),
- code: "hello();",
- output: "#!/usr/bin/env node\nhello();",
- errors: ['This file needs shebang "#!/usr/bin/env node".'],
- },
- {
- name: "bin: string - match - incorrect shebang",
- filename: fixture("string-bin/bin/test.js"),
- code: "#!/usr/bin/node\nhello();",
- output: "#!/usr/bin/env node\nhello();",
- errors: ['This file needs shebang "#!/usr/bin/env node".'],
- },
- {
- name: "bin: string - no match - with shebang",
- filename: fixture("string-bin/lib/test.js"),
- code: "#!/usr/bin/env node\nhello();",
- output: "hello();",
- errors: ["This file needs no shebang."],
- },
- {
- name: 'bin: {a: "./bin/a.js"} - match - no shebang',
- filename: fixture("object-bin/bin/a.js"),
- code: "hello();",
- output: "#!/usr/bin/env node\nhello();",
- errors: ['This file needs shebang "#!/usr/bin/env node".'],
- },
- {
- name: 'bin: {b: "./bin/b.js"} - match - no shebang',
- filename: fixture("object-bin/bin/b.js"),
- code: "#!/usr/bin/node\nhello();",
- output: "#!/usr/bin/env node\nhello();",
- errors: ['This file needs shebang "#!/usr/bin/env node".'],
- },
- {
- name: 'bin: {c: "./bin"} - no match - with shebang',
- filename: fixture("object-bin/bin/c.js"),
- code: "#!/usr/bin/env node\nhello();",
- output: "hello();",
- errors: ["This file needs no shebang."],
- },
- {
- name: "bin: undefined - no match - with shebang",
- filename: fixture("no-bin-field/lib/test.js"),
- code: "#!/usr/bin/env node\nhello();",
- output: "hello();",
- errors: ["This file needs no shebang."],
- },
-
- // convertPath
- {
- name: "convertPath in options",
- filename: fixture("string-bin/src/bin/test.js"),
- code: "hello();",
- output: "#!/usr/bin/env node\nhello();",
- options: [{ convertPath: { "src/**": ["^src/(.+)$", "$1"] } }],
- errors: ['This file needs shebang "#!/usr/bin/env node".'],
- },
- {
- name: "convertPath in settings",
- filename: fixture("string-bin/src/bin/test.js"),
- code: "hello();",
- output: "#!/usr/bin/env node\nhello();",
- errors: ['This file needs shebang "#!/usr/bin/env node".'],
- settings: {
- node: { convertPath: { "src/**": ["^src/(.+)$", "$1"] } },
- },
- },
- {
- name: "converted path - string-bin/src/bin/test.js",
- filename: fixture("string-bin/src/bin/test.js"),
- code: "#!/usr/bin/node\nhello();",
- output: "#!/usr/bin/env node\nhello();",
- options: [{ convertPath: { "src/**": ["^src/(.+)$", "$1"] } }],
- errors: ['This file needs shebang "#!/usr/bin/env node".'],
- },
- {
- name: "converted path - string-bin/src/lib/test.js",
- filename: fixture("string-bin/src/lib/test.js"),
- code: "#!/usr/bin/env node\nhello();",
- output: "hello();",
- options: [{ convertPath: { "src/**": ["^src/(.+)$", "$1"] } }],
- errors: ["This file needs no shebang."],
- },
- {
- name: "converted path - object-bin/src/bin/a.js",
- filename: fixture("object-bin/src/bin/a.js"),
- code: "hello();",
- output: "#!/usr/bin/env node\nhello();",
- options: [{ convertPath: { "src/**": ["^src/(.+)$", "$1"] } }],
- errors: ['This file needs shebang "#!/usr/bin/env node".'],
- },
- {
- name: "converted path - object-bin/src/bin/b.js",
- filename: fixture("object-bin/src/bin/b.js"),
- code: "#!/usr/bin/node\nhello();",
- output: "#!/usr/bin/env node\nhello();",
- options: [{ convertPath: { "src/**": ["^src/(.+)$", "$1"] } }],
- errors: ['This file needs shebang "#!/usr/bin/env node".'],
- },
- {
- name: "converted path - object-bin/src/bin/c.js",
- filename: fixture("object-bin/src/bin/c.js"),
- code: "#!/usr/bin/env node\nhello();",
- output: "hello();",
- options: [{ convertPath: { "src/**": ["^src/(.+)$", "$1"] } }],
- errors: ["This file needs no shebang."],
- },
- {
- name: "converted path - no-bin-field/src/lib/test.js",
- filename: fixture("no-bin-field/src/lib/test.js"),
- code: "#!/usr/bin/env node\nhello();",
- output: "hello();",
- options: [{ convertPath: { "src/**": ["^src/(.+)$", "$1"] } }],
- errors: ["This file needs no shebang."],
- },
-
- // Should work fine if the filename is relative.
- {
- name: "relative path - string-bin/bin/test.js",
- filename: "tests/fixtures/shebang/string-bin/bin/test.js",
- code: "hello();",
- output: "#!/usr/bin/env node\nhello();",
- errors: ['This file needs shebang "#!/usr/bin/env node".'],
- },
- {
- name: "relative path - string-bin/lib/test.js",
- filename: "tests/fixtures/shebang/string-bin/lib/test.js",
- code: "#!/usr/bin/env node\nhello();",
- output: "hello();",
- errors: ["This file needs no shebang."],
- },
-
- // header comments
- {
- name: "header comments",
- filename: fixture("string-bin/bin/test.js"),
- code: "/* header */\nhello();",
- output: "#!/usr/bin/env node\n/* header */\nhello();",
- errors: ['This file needs shebang "#!/usr/bin/env node".'],
- },
-
- // BOM and \r\n
- {
- filename: fixture("string-bin/bin/test.js"),
- code: "\uFEFFhello();",
- output: "#!/usr/bin/env node\nhello();",
- errors: ['This file needs shebang "#!/usr/bin/env node".'],
- },
- {
- filename: fixture("string-bin/bin/test.js"),
- code: "hello();\n",
- output: "#!/usr/bin/env node\nhello();\n",
- errors: ['This file needs shebang "#!/usr/bin/env node".'],
- },
- {
- filename: fixture("string-bin/bin/test.js"),
- code: "hello();\r\n",
- output: "#!/usr/bin/env node\nhello();\r\n",
- errors: ['This file needs shebang "#!/usr/bin/env node".'],
- },
- {
- filename: fixture("string-bin/bin/test.js"),
- code: "\uFEFFhello();\n",
- output: "#!/usr/bin/env node\nhello();\n",
- errors: ['This file needs shebang "#!/usr/bin/env node".'],
- },
- {
- filename: fixture("string-bin/bin/test.js"),
- code: "\uFEFFhello();\r\n",
- output: "#!/usr/bin/env node\nhello();\r\n",
- errors: ['This file needs shebang "#!/usr/bin/env node".'],
- },
- {
- filename: fixture("string-bin/bin/test.js"),
- code: "#!/usr/bin/env node\r\nhello();",
- output: "#!/usr/bin/env node\nhello();",
- errors: ["This file must have Unix linebreaks (LF)."],
- },
- {
- filename: fixture("string-bin/bin/test.js"),
- code: "\uFEFF#!/usr/bin/env node\nhello();",
- output: "#!/usr/bin/env node\nhello();",
- errors: ["This file must not have Unicode BOM."],
- },
- {
- filename: fixture("string-bin/bin/test.js"),
- code: "\uFEFF#!/usr/bin/env node\r\nhello();",
- output: "#!/usr/bin/env node\nhello();",
- errors: [
- "This file must not have Unicode BOM.",
- "This file must have Unix linebreaks (LF).",
- ],
- },
-
- // https://github.com/mysticatea/eslint-plugin-node/issues/51
- {
- name: "Shebang with CLI flags",
- filename: fixture("string-bin/lib/test.js"),
- code: "#!/usr/bin/env node --harmony\nhello();",
- output: "hello();",
- errors: ["This file needs no shebang."],
- },
-
- // use node resolution
- {
- name: "use node resolution",
- filename: fixture("object-bin/bin/index.js"),
- code: "hello();",
- output: "#!/usr/bin/env node\nhello();",
- errors: ['This file needs shebang "#!/usr/bin/env node".'],
- },
-
- // npm unpublished files are ignored
- {
- name: "unpublished file should not have shebang",
- filename: fixture("unpublished/unpublished.js"),
- code: "#!/usr/bin/env node\nhello();",
- output: "hello();",
- errors: ["This file needs no shebang."],
- },
- {
- name: "published file should have shebang",
- filename: fixture("unpublished/published.js"),
- code: "#!/usr/bin/env node\nhello();",
- output: "hello();",
- errors: ["This file needs no shebang."],
- },
-
- {
- name: "unpublished file shebang ignored",
- filename: fixture("unpublished/published.js"),
- code: "#!/usr/bin/env node\nhello();",
- options: [{ ignoreUnpublished: true }],
- output: "hello();",
- errors: ["This file needs no shebang."],
- },
-
- {
- name: "executable in additionalExecutables without shebang",
- filename: fixture("unpublished/something.test.js"),
- code: "hello();",
- options: [{ additionalExecutables: ["*.test.js"] }],
- output: "#!/usr/bin/env node\nhello();",
- errors: ['This file needs shebang "#!/usr/bin/env node".'],
- },
- {
- name: "file not in additionalExecutables with shebang",
- filename: fixture("unpublished/not-a-test.js"),
- code: "#!/usr/bin/env node\nhello();",
- options: [{ additionalExecutables: ["*.test.js"] }],
- output: "hello();",
- errors: ["This file needs no shebang."],
- },
- ],
+ assert.strictEqual(shebang.meta.deprecated, true)
+ assert.deepStrictEqual(shebang.meta.replacedBy, ["n/hashbang"])
+ assert.strictEqual(shebang.create, hashbang.create)
})