diff --git a/etc/eslint/rules/stdlib.js b/etc/eslint/rules/stdlib.js index 06fab9b03564..cfc51e8e65b8 100644 --- a/etc/eslint/rules/stdlib.js +++ b/etc/eslint/rules/stdlib.js @@ -4186,6 +4186,27 @@ rules[ 'stdlib/no-dynamic-require' ] = 'error'; */ rules[ 'stdlib/no-empty-comments' ] = 'error'; +/** +* Enforce no empty lines between module-level require statements. +* +* @name no-empty-lines-between-requires +* @memberof rules +* @type {string} +* @default 'error' +* +* @example +* // Bad... +* var foo = require( 'foo' ); +* +* var bar = require( 'bar' ); +* +* @example +* // Good... +* var foo = require( 'foo' ); +* var bar = require( 'bar' ); +*/ +rules[ 'stdlib/no-empty-lines-between-requires' ] = 'error'; + /** * Disallow string concatenation in error messages. * diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/lib/index.js b/lib/node_modules/@stdlib/_tools/eslint/rules/lib/index.js index 976b805fae13..fcf6e671c4c9 100644 --- a/lib/node_modules/@stdlib/_tools/eslint/rules/lib/index.js +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/lib/index.js @@ -900,6 +900,15 @@ setReadOnly( rules, 'no-dynamic-require', require( '@stdlib/_tools/eslint/rules/ */ setReadOnly( rules, 'no-empty-comments', require( '@stdlib/_tools/eslint/rules/no-empty-comments' ) ); +/** +* @name no-empty-lines-between-requires +* @memberof rules +* @readonly +* @type {Function} +* @see {@link module:@stdlib/_tools/eslint/rules/no-empty-lines-between-requires} +*/ +setReadOnly( rules, 'no-empty-lines-between-requires', require( '@stdlib/_tools/eslint/rules/no-empty-lines-between-requires' ) ); + /** * @name no-error-string-concat * @memberof rules diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/no-empty-lines-between-requires/README.md b/lib/node_modules/@stdlib/_tools/eslint/rules/no-empty-lines-between-requires/README.md new file mode 100644 index 000000000000..fab46cd1a572 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/no-empty-lines-between-requires/README.md @@ -0,0 +1,159 @@ + + +# no-empty-lines-between-requires + +> [ESLint rule][eslint-rules] to enforce no empty lines between module-level require statements. + +
+ +
+ + + +
+ +## Usage + +```javascript +var rule = require( '@stdlib/_tools/eslint/rules/no-empty-lines-between-requires' ); +``` + +#### rule + +[ESLint rule][eslint-rules] to enforce no empty lines between module-level require statements. Section header comments (such as `// FIXTURES //`) are allowed to separate groups of require statements. + +This rule only applies to top-level (module-level) require statements. Require statements inside functions or blocks are not checked. + +**Bad**: + + + + + +```javascript +var tape = require( 'tape' ); + +var isnan = require( '@stdlib/math/base/assert/is-nan' ); + +var abs = require( '@stdlib/math/base/special/abs' ); +``` + +**Good**: + + + + + +```javascript +var tape = require( 'tape' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var abs = require( '@stdlib/math/base/special/abs' ); +``` + +**Good** (section headers separate groups): + + + + + +```javascript +var tape = require( 'tape' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); + + +// FIXTURES // + +var data = require( './fixtures/data.json' ); +var expected = require( './fixtures/expected.json' ); +``` + +
+ + + +
+ +## Examples + + + +```javascript +var Linter = require( 'eslint' ).Linter; +var rule = require( '@stdlib/_tools/eslint/rules/no-empty-lines-between-requires' ); + +var linter = new Linter(); + +var opts = { + 'rules': { + 'no-empty-lines-between-requires': 'error' + } +}; +linter.defineRule( 'no-empty-lines-between-requires', rule ); + +var code = [ + '\'use strict\';', + '', + '// MODULES //', + '', + 'var tape = require( \'tape\' );', + '', + 'var isnan = require( \'@stdlib/math/base/assert/is-nan\' );' +].join( '\n' ); + +var result = linter.verify( code, opts ); +console.log( result ); +/* => + [ + { + 'ruleId': 'no-empty-lines-between-requires', + 'severity': 2, + 'message': 'Unexpected empty line between require statements.', + 'line': 6, + 'column': 0, + 'nodeType': null, + 'endLine': 7, + 'endColumn': 0 + } + ] +*/ +``` + +
+ + + + + + + + + + + + + + diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/no-empty-lines-between-requires/examples/index.js b/lib/node_modules/@stdlib/_tools/eslint/rules/no-empty-lines-between-requires/examples/index.js new file mode 100644 index 000000000000..8bed0b78776c --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/no-empty-lines-between-requires/examples/index.js @@ -0,0 +1,56 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2026 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +var Linter = require( 'eslint' ).Linter; +var rule = require( './../lib' ); + +var linter = new Linter(); + +var opts = { + 'rules': { + 'no-empty-lines-between-requires': 'error' + } +}; +linter.defineRule( 'no-empty-lines-between-requires', rule ); + +var code = [ + '\'use strict\';', + '', + '// MODULES //', + '', + 'var tape = require( \'tape\' );', + '', + 'var isnan = require( \'@stdlib/math/base/assert/is-nan\' );', + '', + '', + '// TESTS //', + '', + 'tape( \'test\', function() {} );' +].join( '\n' ); + +var result = linter.verifyAndFix( code, opts ); +console.log( result ); +/* => + { + 'fixed': true, + 'messages': [], + 'output': '\'use strict\';\n\n// MODULES //\n\nvar tape = require( \'tape\' );\nvar isnan = require( \'@stdlib/math/base/assert/is-nan\' );\n\n\n// TESTS //\n\ntape( \'test\', function() {} );' + } +*/ diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/no-empty-lines-between-requires/lib/index.js b/lib/node_modules/@stdlib/_tools/eslint/rules/no-empty-lines-between-requires/lib/index.js new file mode 100644 index 000000000000..a182a71f00de --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/no-empty-lines-between-requires/lib/index.js @@ -0,0 +1,39 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2026 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +/** +* ESLint rule to enforce no empty lines between module-level require statements. +* +* @module @stdlib/_tools/eslint/rules/no-empty-lines-between-requires +* +* @example +* var rule = require( '@stdlib/_tools/eslint/rules/no-empty-lines-between-requires' ); +* +* console.log( rule ); +*/ + +// MODULES // + +var main = require( './main.js' ); + + +// EXPORTS // + +module.exports = main; diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/no-empty-lines-between-requires/lib/main.js b/lib/node_modules/@stdlib/_tools/eslint/rules/no-empty-lines-between-requires/lib/main.js new file mode 100644 index 000000000000..77418adfd7ff --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/no-empty-lines-between-requires/lib/main.js @@ -0,0 +1,288 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2026 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var endsWith = require( '@stdlib/string/ends-with' ); +var trim = require( '@stdlib/string/trim' ); + + +// VARIABLES // + +var REGEXP_HEADER = /^( )*[A-Z][A-Z0-9 ]+( )*(\/\/)?$/; +var rule; + + +// FUNCTIONS // + +/** +* Checks whether a comment is a section header. +* +* @private +* @param {Object} comment - comment object +* @returns {boolean} boolean indicating if a comment denotes a section header +*/ +function isSectionHeader( comment ) { + var val; + if ( + comment.type !== 'Line' || + comment.loc.start.column !== 0 + ) { + return false; + } + val = comment.value; + return REGEXP_HEADER.test( val ) || endsWith( val, '//' ); +} + +/** +* Checks whether a VariableDeclaration contains a require call. +* +* @private +* @param {ASTNode} node - AST node +* @returns {boolean} boolean indicating if node is a require declaration +*/ +function isRequireDeclaration( node ) { + var init; + var decl; + if ( + node.type !== 'VariableDeclaration' || + !node.declarations || + node.declarations.length === 0 + ) { + return false; + } + decl = node.declarations[ 0 ]; + init = decl.init; + if ( !init ) { + return false; + } + // Handle: var foo = require( 'bar' ); + if ( + init.type === 'CallExpression' && + init.callee && + init.callee.type === 'Identifier' && + init.callee.name === 'require' + ) { + return true; + } + // Handle: var foo = require( 'bar' ).baz; + if ( + init.type === 'MemberExpression' && + init.object && + init.object.type === 'CallExpression' && + init.object.callee && + init.object.callee.type === 'Identifier' && + init.object.callee.name === 'require' + ) { + return true; + } + return false; +} + +/** +* Rule for validating that there are no empty lines between module-level require statements. +* +* @param {Object} context - ESLint context +* @returns {Object} validators +*/ +function main( context ) { + var source = context.getSourceCode(); + var lines = source.lines; + + /** + * Checks whether there is a section header comment between two nodes. + * + * @private + * @param {ASTNode} prevNode - previous node + * @param {ASTNode} currNode - current node + * @returns {boolean} boolean indicating if a section header exists between nodes + */ + function hasSectionHeaderBetween( prevNode, currNode ) { + var comments; + var i; + + comments = source.getCommentsBefore( currNode ); + for ( i = 0; i < comments.length; i++ ) { + if ( + comments[ i ].loc.start.line > prevNode.loc.end.line && + isSectionHeader( comments[ i ] ) + ) { + return true; + } + } + return false; + } + + /** + * Checks whether there are empty lines between two nodes. + * + * @private + * @param {ASTNode} prevNode - previous node + * @param {ASTNode} currNode - current node + * @returns {boolean} boolean indicating if empty lines exist between the nodes + */ + function hasEmptyLinesBetween( prevNode, currNode ) { + var startLine; + var endLine; + var line; + var i; + + startLine = prevNode.loc.end.line; + endLine = currNode.loc.start.line; + + // Check each line between the two nodes... + for ( i = startLine; i < endLine-1; i++ ) { + line = lines[ i ]; + if ( trim( line ) === '' ) { + return true; + } + } + return false; + } + + /** + * Reports the error message. + * + * @private + * @param {ASTNode} prevNode - previous require node + * @param {ASTNode} currNode - current require node + */ + function report( prevNode, currNode ) { + var loc = { + 'start': { + 'line': prevNode.loc.end.line + 1, + 'column': 0 + }, + 'end': { + 'line': currNode.loc.start.line, + 'column': 0 + } + }; + + context.report({ + 'node': null, + 'message': 'Unexpected empty line between require statements.', + 'loc': loc, + 'fix': fix + }); + + /** + * Fixes the lint error by removing empty lines between requires. + * + * @private + * @param {Object} fixer - ESLint fixer + * @returns {Object} fix + */ + function fix( fixer ) { + var replacement; + var startOfNext; + var startLine; + var endOfPrev; + var nonEmpty; + var endLine; + var range; + var line; + var i; + + // Get the range between the two requires... + endOfPrev = prevNode.range[ 1 ]; + startOfNext = source.getIndexFromLoc({ + 'line': currNode.loc.start.line, + 'column': 0 + }); + + // Collect non-empty lines between the requires... + startLine = prevNode.loc.end.line; + endLine = currNode.loc.start.line; + nonEmpty = []; + for ( i = startLine; i < endLine - 1; i++ ) { + line = lines[ i ]; + if ( trim( line ) !== '' ) { + nonEmpty.push( line ); + } + } + + // Build replacement: newline + non-empty lines (each with newline) + final newline for current require + if ( nonEmpty.length === 0 ) { + replacement = '\n'; + } else { + replacement = '\n' + nonEmpty.join( '\n' ) + '\n'; + } + range = [ endOfPrev, startOfNext ]; + return fixer.replaceTextRange( range, replacement ); + } + } + + /** + * Validates module-level require statements. + * + * @private + * @param {ASTNode} program - program node + */ + function validate( program ) { + var prevRequire; + var body; + var node; + var i; + + body = program.body; + prevRequire = null; + + for ( i = 0; i < body.length; i++ ) { + node = body[ i ]; + if ( isRequireDeclaration( node ) ) { + if ( prevRequire !== null ) { + // Check for empty lines between requires... + if ( + hasEmptyLinesBetween( prevRequire, node ) && + !hasSectionHeaderBetween( prevRequire, node ) + ) { + report( prevRequire, node ); + } + } + prevRequire = node; + } + } + } + + return { + 'Program:exit': validate + }; +} + + +// MAIN // + +rule = { + 'meta': { + 'type': 'layout', + 'docs': { + 'description': 'enforce no empty lines between module-level require statements' + }, + 'fixable': 'whitespace', + 'schema': [] + }, + 'create': main +}; + + +// EXPORTS // + +module.exports = rule; diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/no-empty-lines-between-requires/package.json b/lib/node_modules/@stdlib/_tools/eslint/rules/no-empty-lines-between-requires/package.json new file mode 100644 index 000000000000..18f4ab48ec08 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/no-empty-lines-between-requires/package.json @@ -0,0 +1,66 @@ +{ + "name": "@stdlib/_tools/eslint/rules/no-empty-lines-between-requires", + "version": "0.0.0", + "description": "ESLint rule to enforce no empty lines between module-level require statements.", + "license": "Apache-2.0", + "author": { + "name": "The Stdlib Authors", + "url": "https://github.com/stdlib-js/stdlib/graphs/contributors" + }, + "contributors": [ + { + "name": "The Stdlib Authors", + "url": "https://github.com/stdlib-js/stdlib/graphs/contributors" + } + ], + "main": "./lib", + "directories": { + "example": "./examples", + "lib": "./lib", + "test": "./test" + }, + "scripts": {}, + "homepage": "https://github.com/stdlib-js/stdlib", + "repository": { + "type": "git", + "url": "git://github.com/stdlib-js/stdlib.git" + }, + "bugs": { + "url": "https://github.com/stdlib-js/stdlib/issues" + }, + "dependencies": {}, + "devDependencies": {}, + "engines": { + "node": ">=0.10.0", + "npm": ">2.7.0" + }, + "os": [ + "aix", + "darwin", + "freebsd", + "linux", + "macos", + "openbsd", + "sunos", + "win32", + "windows" + ], + "keywords": [ + "stdlib", + "tools", + "tool", + "eslint", + "lint", + "custom", + "rules", + "rule", + "plugin", + "require", + "import", + "empty", + "line", + "whitespace", + "newline", + "spacing" + ] +} diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/no-empty-lines-between-requires/test/fixtures/invalid.js b/lib/node_modules/@stdlib/_tools/eslint/rules/no-empty-lines-between-requires/test/fixtures/invalid.js new file mode 100644 index 000000000000..74b1d52c3a4b --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/no-empty-lines-between-requires/test/fixtures/invalid.js @@ -0,0 +1,351 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2026 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +var invalid = []; + +// Empty line between consecutive requires: +var test = { + 'code': [ + '\'use strict\';', + '', + '// MODULES //', + '', + 'var tape = require( \'tape\' );', + '', + 'var isnan = require( \'@stdlib/math/base/assert/is-nan\' );' + ].join( '\n' ), + 'errors': [ + { + 'message': 'Unexpected empty line between require statements.', + 'type': null + } + ], + 'output': [ + '\'use strict\';', + '', + '// MODULES //', + '', + 'var tape = require( \'tape\' );', + 'var isnan = require( \'@stdlib/math/base/assert/is-nan\' );' + ].join( '\n' ) +}; +invalid.push( test ); + +// Multiple empty lines between requires: +test = { + 'code': [ + '\'use strict\';', + '', + '// MODULES //', + '', + 'var tape = require( \'tape\' );', + '', + '', + 'var isnan = require( \'@stdlib/math/base/assert/is-nan\' );' + ].join( '\n' ), + 'errors': [ + { + 'message': 'Unexpected empty line between require statements.', + 'type': null + } + ], + 'output': [ + '\'use strict\';', + '', + '// MODULES //', + '', + 'var tape = require( \'tape\' );', + 'var isnan = require( \'@stdlib/math/base/assert/is-nan\' );' + ].join( '\n' ) +}; +invalid.push( test ); + +// Empty line in middle of multiple requires: +test = { + 'code': [ + '\'use strict\';', + '', + '// MODULES //', + '', + 'var tape = require( \'tape\' );', + 'var isnan = require( \'@stdlib/math/base/assert/is-nan\' );', + '', + 'var abs = require( \'./../lib\' );' + ].join( '\n' ), + 'errors': [ + { + 'message': 'Unexpected empty line between require statements.', + 'type': null + } + ], + 'output': [ + '\'use strict\';', + '', + '// MODULES //', + '', + 'var tape = require( \'tape\' );', + 'var isnan = require( \'@stdlib/math/base/assert/is-nan\' );', + 'var abs = require( \'./../lib\' );' + ].join( '\n' ) +}; +invalid.push( test ); + +// Empty lines in FIXTURES section (no section header between): +test = { + 'code': [ + '\'use strict\';', + '', + '// FIXTURES //', + '', + 'var data = require( \'./fixtures/data.json\' );', + '', + 'var expected = require( \'./fixtures/expected.json\' );' + ].join( '\n' ), + 'errors': [ + { + 'message': 'Unexpected empty line between require statements.', + 'type': null + } + ], + 'output': [ + '\'use strict\';', + '', + '// FIXTURES //', + '', + 'var data = require( \'./fixtures/data.json\' );', + 'var expected = require( \'./fixtures/expected.json\' );' + ].join( '\n' ) +}; +invalid.push( test ); + +// Multiple consecutive errors: +test = { + 'code': [ + '\'use strict\';', + '', + '// MODULES //', + '', + 'var a = require( \'a\' );', + '', + 'var b = require( \'b\' );', + '', + 'var c = require( \'c\' );' + ].join( '\n' ), + 'errors': [ + { + 'message': 'Unexpected empty line between require statements.', + 'type': null + }, + { + 'message': 'Unexpected empty line between require statements.', + 'type': null + } + ], + 'output': [ + '\'use strict\';', + '', + '// MODULES //', + '', + 'var a = require( \'a\' );', + 'var b = require( \'b\' );', + 'var c = require( \'c\' );' + ].join( '\n' ) +}; +invalid.push( test ); + +// Empty line before a regular comment (not a section header): +test = { + 'code': [ + '\'use strict\';', + '', + '// MODULES //', + '', + 'var foo = require( \'foo\' );', + '', + '// A regular comment', + 'var bar = require( \'bar\' );' + ].join( '\n' ), + 'errors': [ + { + 'message': 'Unexpected empty line between require statements.', + 'type': null + } + ], + 'output': [ + '\'use strict\';', + '', + '// MODULES //', + '', + 'var foo = require( \'foo\' );', + '// A regular comment', + 'var bar = require( \'bar\' );' + ].join( '\n' ) +}; +invalid.push( test ); + +// Empty line with require using property access: +test = { + 'code': [ + '\'use strict\';', + '', + '// MODULES //', + '', + 'var isString = require( \'@stdlib/assert/is-string\' ).isPrimitive;', + '', + 'var format = require( \'@stdlib/string/format\' );' + ].join( '\n' ), + 'errors': [ + { + 'message': 'Unexpected empty line between require statements.', + 'type': null + } + ], + 'output': [ + '\'use strict\';', + '', + '// MODULES //', + '', + 'var isString = require( \'@stdlib/assert/is-string\' ).isPrimitive;', + 'var format = require( \'@stdlib/string/format\' );' + ].join( '\n' ) +}; +invalid.push( test ); + +// Empty line between requires separated by non-require statement: +test = { + 'code': [ + '\'use strict\';', + '', + 'var foo = require( \'foo\' );', + 'var x = 1;', + '', + 'var bar = require( \'bar\' );' + ].join( '\n' ), + 'errors': [ + { + 'message': 'Unexpected empty line between require statements.', + 'type': null + } + ], + 'output': [ + '\'use strict\';', + '', + 'var foo = require( \'foo\' );', + 'var x = 1;', + 'var bar = require( \'bar\' );' + ].join( '\n' ) +}; +invalid.push( test ); + +// Empty line between multi-line require statements: +test = { + 'code': [ + '\'use strict\';', + '', + 'var foo = require(', + ' \'some/very/long/path/to/module\'', + ');', + '', + 'var bar = require( \'bar\' );' + ].join( '\n' ), + 'errors': [ + { + 'message': 'Unexpected empty line between require statements.', + 'type': null + } + ], + 'output': [ + '\'use strict\';', + '', + 'var foo = require(', + ' \'some/very/long/path/to/module\'', + ');', + 'var bar = require( \'bar\' );' + ].join( '\n' ) +}; +invalid.push( test ); + +// Empty line after multi-line require followed by another multi-line require: +test = { + 'code': [ + '\'use strict\';', + '', + 'var foo = require(', + ' \'path/one\'', + ');', + '', + 'var bar = require(', + ' \'path/two\'', + ');' + ].join( '\n' ), + 'errors': [ + { + 'message': 'Unexpected empty line between require statements.', + 'type': null + } + ], + 'output': [ + '\'use strict\';', + '', + 'var foo = require(', + ' \'path/one\'', + ');', + 'var bar = require(', + ' \'path/two\'', + ');' + ].join( '\n' ) +}; +invalid.push( test ); + +// Multiple non-require statements between requires with empty lines: +test = { + 'code': [ + '\'use strict\';', + '', + 'var foo = require( \'foo\' );', + 'var x = 1;', + '', + 'var y = 2;', + 'var z = x + y;', + '', + 'var bar = require( \'bar\' );' + ].join( '\n' ), + 'errors': [ + { + 'message': 'Unexpected empty line between require statements.', + 'type': null + } + ], + 'output': [ + '\'use strict\';', + '', + 'var foo = require( \'foo\' );', + 'var x = 1;', + 'var y = 2;', + 'var z = x + y;', + 'var bar = require( \'bar\' );' + ].join( '\n' ) +}; +invalid.push( test ); + + +// EXPORTS // + +module.exports = invalid; diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/no-empty-lines-between-requires/test/fixtures/unvalidated.js b/lib/node_modules/@stdlib/_tools/eslint/rules/no-empty-lines-between-requires/test/fixtures/unvalidated.js new file mode 100644 index 000000000000..b00fdc1811d8 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/no-empty-lines-between-requires/test/fixtures/unvalidated.js @@ -0,0 +1,90 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2026 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +var valid = []; + +// Non-require variable declarations (not validated): +var test = { + 'code': [ + '\'use strict\';', + '', + '// VARIABLES //', + '', + 'var x = 1;', + '', + 'var y = 2;' + ].join( '\n' ) +}; +valid.push( test ); + +// Dynamic require (variable path: not a simple require pattern): +test = { + 'code': [ + '\'use strict\';', + '', + 'var path = \'./foo\';', + '', + 'var foo = require( path );' + ].join( '\n' ) +}; +valid.push( test ); + +// Require without assignment (expression statement, not variable declaration): +test = { + 'code': [ + '\'use strict\';', + '', + 'require( \'./setup\' );', + '', + 'require( \'./teardown\' );' + ].join( '\n' ) +}; +valid.push( test ); + +// Require in conditional (not module-level): +test = { + 'code': [ + '\'use strict\';', + '', + 'if ( condition ) {', + ' var foo = require( \'foo\' );', + '', + ' var bar = require( \'bar\' );', + '}' + ].join( '\n' ) +}; +valid.push( test ); + +// Empty file: +test = { + 'code': '' +}; +valid.push( test ); + +// File with only use strict: +test = { + 'code': '\'use strict\';' +}; +valid.push( test ); + + +// EXPORTS // + +module.exports = valid; diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/no-empty-lines-between-requires/test/fixtures/valid.js b/lib/node_modules/@stdlib/_tools/eslint/rules/no-empty-lines-between-requires/test/fixtures/valid.js new file mode 100644 index 000000000000..658b136c16de --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/no-empty-lines-between-requires/test/fixtures/valid.js @@ -0,0 +1,178 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2026 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +var valid = []; + +// Consecutive requires without empty lines: +var test = { + 'code': [ + '\'use strict\';', + '', + '// MODULES //', + '', + 'var tape = require( \'tape\' );', + 'var isnan = require( \'@stdlib/math/base/assert/is-nan\' );', + 'var abs = require( \'./../lib\' );', + '', + '', + '// TESTS //', + '', + 'tape( \'test\', function() {} );' + ].join( '\n' ) +}; +valid.push( test ); + +// Test file with FIXTURES section (empty lines around section header are OK): +test = { + 'code': [ + '\'use strict\';', + '', + '// MODULES //', + '', + 'var tape = require( \'tape\' );', + 'var isnan = require( \'@stdlib/math/base/assert/is-nan\' );', + '', + '', + '// FIXTURES //', + '', + 'var data = require( \'./fixtures/data.json\' );', + 'var expected = require( \'./fixtures/expected.json\' );', + '', + '', + '// TESTS //', + '', + 'tape( \'test\', function() {} );' + ].join( '\n' ) +}; +valid.push( test ); + +// Single require statement (nothing to check): +test = { + 'code': [ + '\'use strict\';', + '', + '// MODULES //', + '', + 'var main = require( \'./main.js\' );', + '', + '', + '// EXPORTS //', + '', + 'module.exports = main;' + ].join( '\n' ) +}; +valid.push( test ); + +// Require with property access: var foo = require( 'bar' ).baz; +test = { + 'code': [ + '\'use strict\';', + '', + '// MODULES //', + '', + 'var isString = require( \'@stdlib/assert/is-string\' ).isPrimitive;', + 'var format = require( \'@stdlib/string/format\' );', + '', + '', + '// MAIN //', + '', + 'function main() {}' + ].join( '\n' ) +}; +valid.push( test ); + +// No require statements: +test = { + 'code': [ + '\'use strict\';', + '', + '// MAIN //', + '', + 'function foo() {', + ' return 1;', + '}' + ].join( '\n' ) +}; +valid.push( test ); + +// Requires inside functions are not checked (only module-level): +test = { + 'code': [ + '\'use strict\';', + '', + 'function helper() {', + ' var a = require( \'a\' );', + '', + ' var b = require( \'b\' );', + '}' + ].join( '\n' ) +}; +valid.push( test ); + +// Comments (non-header) between requires are allowed if no empty lines: +test = { + 'code': [ + '\'use strict\';', + '', + '// MODULES //', + '', + 'var foo = require( \'foo\' );', + '// A regular comment', + 'var bar = require( \'bar\' );' + ].join( '\n' ) +}; +valid.push( test ); + +// Multi-line require statements without empty lines between: +test = { + 'code': [ + '\'use strict\';', + '', + '// MODULES //', + '', + 'var foo = require(', + ' \'some/very/long/path/to/module\'', + ');', + 'var bar = require( \'bar\' );', + 'var baz = require(', + ' \'another/long/path\'', + ');' + ].join( '\n' ) +}; +valid.push( test ); + +// Multiple non-require statements between requires without empty lines: +test = { + 'code': [ + '\'use strict\';', + '', + 'var foo = require( \'foo\' );', + 'var x = 1;', + 'var y = 2;', + 'var z = x + y;', + 'var bar = require( \'bar\' );' + ].join( '\n' ) +}; +valid.push( test ); + + +// EXPORTS // + +module.exports = valid; diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/no-empty-lines-between-requires/test/test.js b/lib/node_modules/@stdlib/_tools/eslint/rules/no-empty-lines-between-requires/test/test.js new file mode 100644 index 000000000000..a36e557a03bf --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/no-empty-lines-between-requires/test/test.js @@ -0,0 +1,86 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2026 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var tape = require( 'tape' ); +var RuleTester = require( 'eslint' ).RuleTester; +var rule = require( './../lib' ); + + +// FIXTURES // + +var valid = require( './fixtures/valid.js' ); +var invalid = require( './fixtures/invalid.js' ); +var unvalidated = require( './fixtures/unvalidated.js' ); + + +// TESTS // + +tape( 'main export is an object', function test( t ) { + t.ok( true, __filename ); + t.strictEqual( typeof rule, 'object', 'main export is an object' ); + t.end(); +}); + +tape( 'the rule positively validates code where module-level require statements have no empty lines between them', function test( t ) { + var tester = new RuleTester(); + + try { + tester.run( 'no-empty-lines-between-requires', rule, { + 'valid': valid, + 'invalid': [] + }); + t.pass( 'passed without errors' ); + } catch ( err ) { + t.fail( 'encountered an error: ' + err.message ); + } + t.end(); +}); + +tape( 'the rule negatively validates code where module-level require statements have empty lines between them', function test( t ) { + var tester = new RuleTester(); + + try { + tester.run( 'no-empty-lines-between-requires', rule, { + 'valid': [], + 'invalid': invalid + }); + t.pass( 'passed without errors' ); + } catch ( err ) { + t.fail( 'encountered an error: ' + err.message ); + } + t.end(); +}); + +tape( 'the rule does not validate non-require declarations or non-module-level requires', function test( t ) { + var tester = new RuleTester(); + + try { + tester.run( 'no-empty-lines-between-requires', rule, { + 'valid': unvalidated, + 'invalid': [] + }); + t.pass( 'passed without errors' ); + } catch ( err ) { + t.fail( 'encountered an error: ' + err.message ); + } + t.end(); +});