Spaces:
Sleeping
Sleeping
| /** | |
| * @fileoverview Require or disallow newline at the end of files | |
| * @author Nodeca Team <https://github.com/nodeca> | |
| * @deprecated in ESLint v8.53.0 | |
| */ | |
| ; | |
| //------------------------------------------------------------------------------ | |
| // Rule Definition | |
| //------------------------------------------------------------------------------ | |
| /** @type {import('../types').Rule.RuleModule} */ | |
| module.exports = { | |
| meta: { | |
| deprecated: { | |
| message: "Formatting rules are being moved out of ESLint core.", | |
| url: "https://eslint.org/blog/2023/10/deprecating-formatting-rules/", | |
| deprecatedSince: "8.53.0", | |
| availableUntil: "11.0.0", | |
| replacedBy: [ | |
| { | |
| message: | |
| "ESLint Stylistic now maintains deprecated stylistic core rules.", | |
| url: "https://eslint.style/guide/migration", | |
| plugin: { | |
| name: "@stylistic/eslint-plugin", | |
| url: "https://eslint.style", | |
| }, | |
| rule: { | |
| name: "eol-last", | |
| url: "https://eslint.style/rules/eol-last", | |
| }, | |
| }, | |
| ], | |
| }, | |
| type: "layout", | |
| docs: { | |
| description: "Require or disallow newline at the end of files", | |
| recommended: false, | |
| url: "https://eslint.org/docs/latest/rules/eol-last", | |
| }, | |
| fixable: "whitespace", | |
| schema: [ | |
| { | |
| enum: ["always", "never", "unix", "windows"], | |
| }, | |
| ], | |
| messages: { | |
| missing: "Newline required at end of file but not found.", | |
| unexpected: "Newline not allowed at end of file.", | |
| }, | |
| }, | |
| create(context) { | |
| //-------------------------------------------------------------------------- | |
| // Public | |
| //-------------------------------------------------------------------------- | |
| return { | |
| Program: function checkBadEOF(node) { | |
| const sourceCode = context.sourceCode, | |
| src = sourceCode.getText(), | |
| lastLine = sourceCode.lines.at(-1), | |
| location = { | |
| column: lastLine.length, | |
| line: sourceCode.lines.length, | |
| }, | |
| LF = "\n", | |
| CRLF = `\r${LF}`, | |
| endsWithNewline = src.endsWith(LF); | |
| /* | |
| * Empty source is always valid: No content in file so we don't | |
| * need to lint for a newline on the last line of content. | |
| */ | |
| if (!src.length) { | |
| return; | |
| } | |
| let mode = context.options[0] || "always", | |
| appendCRLF = false; | |
| if (mode === "unix") { | |
| // `"unix"` should behave exactly as `"always"` | |
| mode = "always"; | |
| } | |
| if (mode === "windows") { | |
| // `"windows"` should behave exactly as `"always"`, but append CRLF in the fixer for backwards compatibility | |
| mode = "always"; | |
| appendCRLF = true; | |
| } | |
| if (mode === "always" && !endsWithNewline) { | |
| // File is not newline-terminated, but should be | |
| context.report({ | |
| node, | |
| loc: location, | |
| messageId: "missing", | |
| fix(fixer) { | |
| return fixer.insertTextAfterRange( | |
| [0, src.length], | |
| appendCRLF ? CRLF : LF, | |
| ); | |
| }, | |
| }); | |
| } else if (mode === "never" && endsWithNewline) { | |
| const secondLastLine = sourceCode.lines.at(-2); | |
| // File is newline-terminated, but shouldn't be | |
| context.report({ | |
| node, | |
| loc: { | |
| start: { | |
| line: sourceCode.lines.length - 1, | |
| column: secondLastLine.length, | |
| }, | |
| end: { line: sourceCode.lines.length, column: 0 }, | |
| }, | |
| messageId: "unexpected", | |
| fix(fixer) { | |
| const finalEOLs = /(?:\r?\n)+$/u, | |
| match = finalEOLs.exec(sourceCode.text), | |
| start = match.index, | |
| end = sourceCode.text.length; | |
| return fixer.replaceTextRange([start, end], ""); | |
| }, | |
| }); | |
| } | |
| }, | |
| }; | |
| }, | |
| }; | |