diff --git a/eslint.flat.config.js b/eslint.flat.config.js new file mode 100644 index 000000000000..7e87d1f7a498 --- /dev/null +++ b/eslint.flat.config.js @@ -0,0 +1,131 @@ +/** +* @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. +*/ + +/* eslint-disable n/no-unpublished-require */ + +'use strict'; + +// MODULES // + +var globals = require( 'globals' ); +var pluginN = require( 'eslint-plugin-n' ); +var pluginCspell = require( '@cspell/eslint-plugin' ); +var pluginJsdoc = require( 'eslint-plugin-jsdoc' ); +var assign = require( './lib/node_modules/@stdlib/object/assign' ); +var stdlibPlugin = require( './lib/node_modules/@stdlib/_tools/eslint/rules/scripts/plugin.js' ); +var restrictedSyntaxConfig = require( './etc/eslint/overrides/restricted_syntax.js' ); +var rules = require( './etc/eslint/rules' ); + + +// VARIABLES // + +var globalVars; +var config; + + +// MAIN // + +globalVars = assign( {}, globals.browser, globals.node ); +globalVars = assign( globalVars, globals.commonjs, globals.worker ); + +config = [ + // Global ignores: + { + 'ignores': [ + '**/build/', + '**/reports/', + 'dist/', + '.git*' + ] + }, + + // Base JavaScript config: + { + 'files': [ '**/*.js' ], + 'languageOptions': { + 'ecmaVersion': 6, + 'sourceType': 'script', + 'globals': globalVars + }, + 'plugins': { + 'n': pluginN, + 'jsdoc': pluginJsdoc, + '@cspell': pluginCspell, + 'stdlib': stdlibPlugin + }, + 'rules': rules + }, + + // REPL namespace files: + { + 'files': [ '**/lib/node_modules/@stdlib/**/lib/[a-z].js' ], + 'rules': { + 'stdlib/repl-namespace-order': 'error' + } + }, + + // Benchmarks: + { + 'files': [ '**/benchmark/**/*.js' ], + 'rules': { + 'no-new-wrappers': 'warn', + 'max-lines': [ 'warn', { + 'max': 1000, + 'skipBlankLines': true, + 'skipComments': true + }], + 'jsdoc/require-jsdoc': 'off', + 'no-restricted-syntax': restrictedSyntaxConfig + } + }, + + // Examples: + { + 'files': [ '**/examples/**/*.js' ], + 'rules': { + 'no-console': 'off', + 'vars-on-top': 'off', + 'jsdoc/require-jsdoc': 'off', + 'stdlib/jsdoc-private-annotation': 'off', + 'stdlib/require-order': 'off', + 'stdlib/require-file-extensions': 'off', + 'no-restricted-syntax': restrictedSyntaxConfig + } + }, + + // Tests: + { + 'files': [ '**/test/**/*.js' ], + 'rules': { + 'no-empty-function': 'off', + 'jsdoc/require-jsdoc': 'off', + 'no-undefined': 'off', + 'max-lines': [ 'warn', { + 'max': 1000, + 'skipBlankLines': true, + 'skipComments': true + }], + 'no-restricted-syntax': restrictedSyntaxConfig + } + } +]; + + +// EXPORTS // + +module.exports = config; diff --git a/etc/eslint/overrides/index.js b/etc/eslint/overrides/index.js index 8133780619d1..6b45d71d8051 100644 --- a/etc/eslint/overrides/index.js +++ b/etc/eslint/overrides/index.js @@ -21,48 +21,7 @@ // MODULES // var resolve = require( 'path' ).resolve; - - -// VARIABLES // - -var restrictedSyntaxConfig = [ 'error', - 'ArrowFunctionExpression', - 'ClassBody', - 'ClassDeclaration', - 'ClassExpression', - 'DebuggerStatement', - 'ExperimentalRestProperty', - 'ExperimentalSpreadProperty', - - // 'FunctionExpression', - 'LabeledStatement', - 'RestElement', - 'SpreadElement', - 'TaggedTemplateExpression', - 'TemplateElement', - 'TemplateLiteral', - 'WithStatement', - 'YieldExpression', - 'JSXIdentifier', - 'JSXNamespacedName', - 'JSXMemberExpression', - 'JSXEmptyExpression', - 'JSXExpressionContainer', - 'JSXElement', - 'JSXClosingElement', - 'JSXOpeningElement', - 'JSXAttribute', - 'JSXSpreadAttribute', - 'JSXText', - 'ExportDefaultDeclaration', - 'ExportNamedDeclaration', - 'ExportAllDeclaration', - 'ExportSpecifier', - 'ImportDeclaration', - 'ImportSpecifier', - 'ImportDefaultSpecifier', - 'ImportNamespaceSpecifier' -]; +var restrictedSyntaxConfig = require( './restricted_syntax.js' ); // MAIN // diff --git a/etc/eslint/overrides/restricted_syntax.js b/etc/eslint/overrides/restricted_syntax.js new file mode 100644 index 000000000000..d33a9d190bb7 --- /dev/null +++ b/etc/eslint/overrides/restricted_syntax.js @@ -0,0 +1,65 @@ +/** +* @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'; + +// MAIN // + +var rule = [ 'error', + 'ArrowFunctionExpression', + 'ClassBody', + 'ClassDeclaration', + 'ClassExpression', + 'DebuggerStatement', + 'ExperimentalRestProperty', + 'ExperimentalSpreadProperty', + + // 'FunctionExpression', + 'LabeledStatement', + 'RestElement', + 'SpreadElement', + 'TaggedTemplateExpression', + 'TemplateElement', + 'TemplateLiteral', + 'WithStatement', + 'YieldExpression', + 'JSXIdentifier', + 'JSXNamespacedName', + 'JSXMemberExpression', + 'JSXEmptyExpression', + 'JSXExpressionContainer', + 'JSXElement', + 'JSXClosingElement', + 'JSXOpeningElement', + 'JSXAttribute', + 'JSXSpreadAttribute', + 'JSXText', + 'ExportDefaultDeclaration', + 'ExportNamedDeclaration', + 'ExportAllDeclaration', + 'ExportSpecifier', + 'ImportDeclaration', + 'ImportSpecifier', + 'ImportDefaultSpecifier', + 'ImportNamespaceSpecifier' +]; + + +// EXPORTS // + +module.exports = rule; diff --git a/etc/eslint/rules/stdlib.js b/etc/eslint/rules/stdlib.js index 1c84b79de46c..806287f8f0cc 100644 --- a/etc/eslint/rules/stdlib.js +++ b/etc/eslint/rules/stdlib.js @@ -1,4 +1,4 @@ -/* eslint-disable stdlib/jsdoc-doctest-marker, stdlib/jsdoc-doctest, stdlib/jsdoc-example-require-spacing, stdlib/jsdoc-no-tabs */ +/* eslint-disable stdlib/jsdoc-doctest-marker, stdlib/jsdoc-example-require-spacing, stdlib/jsdoc-no-tabs */ /** * @license Apache-2.0 @@ -1720,7 +1720,7 @@ rules[ 'stdlib/jsdoc-list-item-spacing' ] = 'error'; */ rules[ 'stdlib/jsdoc-markdown-remark' ] = [ 'error', { - 'config': require( './../../remark/.remarkrc.jsdoc.js' ) + 'configPath': require.resolve( './../../remark/.remarkrc.jsdoc.js' ) } ]; diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/jsdoc-markdown-remark/README.md b/lib/node_modules/@stdlib/_tools/eslint/rules/jsdoc-markdown-remark/README.md index 43dea465621b..d764a819c5ff 100644 --- a/lib/node_modules/@stdlib/_tools/eslint/rules/jsdoc-markdown-remark/README.md +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/jsdoc-markdown-remark/README.md @@ -84,6 +84,16 @@ function beep() { +
+ +## Notes + +- To keep rule options serializable (e.g., when using an ESLint flat config), set the `configPath` option to an absolute path for a CommonJS module which exports a remark configuration. + +
+ + +
## Examples @@ -97,12 +107,9 @@ var noDuplicateHeadings = require( 'remark-lint-no-duplicate-headings' ); var rule = require( '@stdlib/_tools/eslint/rules/jsdoc-markdown-remark' ); var linter = new Linter(); -var config; -var result; -var code; // Generate our source code containing a single lint error (a duplicate heading): -code = [ +var code = [ '/**', '* Beep boop.', '*', @@ -150,7 +157,7 @@ code = [ ].join( '\n' ); // Create a remark configuration: -config = { +var config = { 'plugins': [ [ remarkLint ], [ noDuplicateHeadings, [ 'error' ] ] @@ -161,7 +168,7 @@ config = { linter.defineRule( 'jsdoc-markdown-remark', rule ); // Lint the code: -result = linter.verify( code, { +var result = linter.verify( code, { 'rules': { 'jsdoc-markdown-remark': [ 'error', { 'config': config diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/jsdoc-markdown-remark/lib/main.js b/lib/node_modules/@stdlib/_tools/eslint/rules/jsdoc-markdown-remark/lib/main.js index 2081e110d0dd..88bba2133419 100644 --- a/lib/node_modules/@stdlib/_tools/eslint/rules/jsdoc-markdown-remark/lib/main.js +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/jsdoc-markdown-remark/lib/main.js @@ -46,18 +46,19 @@ var rule; */ function main( context ) { var options; + var config; var source; var lint; - var opts; options = context.options[ 0 ]; - opts = {}; - if ( hasOwnProp( options, 'config' ) ) { - opts.config = options.config; + if ( hasOwnProp( options, 'configPath' ) ) { + config = require( options.configPath ); // eslint-disable-line stdlib/no-dynamic-require + } else if ( hasOwnProp( options, 'config' ) ) { + config = options.config; } else { - opts.config = {}; + config = {}; } - lint = remark().use( opts.config ).processSync; + lint = remark().use( config ).processSync; source = context.sourceCode; return { @@ -151,6 +152,9 @@ rule = { 'properties': { 'config': { 'type': 'object' + }, + 'configPath': { + 'type': 'string' } }, 'additionalProperties': false diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/jsdoc-markdown-remark/test/fixtures/invalid.js b/lib/node_modules/@stdlib/_tools/eslint/rules/jsdoc-markdown-remark/test/fixtures/invalid.js index 639ad6f1c220..bafee125621c 100644 --- a/lib/node_modules/@stdlib/_tools/eslint/rules/jsdoc-markdown-remark/test/fixtures/invalid.js +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/jsdoc-markdown-remark/test/fixtures/invalid.js @@ -23,41 +23,49 @@ var config = require( './config.js' ); -// VARIABLES // - -var invalid; -var test; - - // MAIN // // Create our test cases: -invalid = []; +var invalid = []; -test = { - 'code': [ - '/**', - '* Beep boop.', - '*', - '* ## Beep', - '*', - '* ## Beep', - '*/', - 'function beep() {', - ' console.log( "boop" );', - '}' - ].join( '\n' ), +var code = [ + '/**', + '* Beep boop.', + '*', + '* ## Beep', + '*', + '* ## Beep', + '*/', + 'function beep() {', + ' console.log( "boop" );', + '}' +].join( '\n' ); +var errors = [ + { + 'message': '5:1-5:8 error Do not use headings with similar content (3:1) no-duplicate-headings remark-lint', + 'type': null + } +]; + +var test = { + 'code': code, 'options': [ { 'config': config } ], - 'errors': [ + 'errors': errors +}; +invalid.push( test ); + +test = { + 'code': code, + 'options': [ { - 'message': '5:1-5:8 error Do not use headings with similar content (3:1) no-duplicate-headings remark-lint', - 'type': null + 'configPath': require.resolve( './config.js' ) } - ] + ], + 'errors': errors }; invalid.push( test ); diff --git a/package.json b/package.json index aab0d6a5bace..d6672b72b383 100644 --- a/package.json +++ b/package.json @@ -148,6 +148,7 @@ "eslint-plugin-import": "^2.29.0", "eslint-plugin-jsdoc": "^46.8.2", "eslint-plugin-stdlib": "file:./etc/eslint/plugin", + "globals": "^16.1.0", "exorcist": "^2.0.0", "factor-bundle": "^2.5.0", "gh-pages": "git+https://github.com/Planeshifter/gh-pages.git#main",