module.exports = { rules: { // auto fixable 'no-spaces-in-control-flow-statements': { meta: { docs: { description: 'Disallow spaces in control flow statements', category: 'Z8 Stylistic Issues', recommended: true, }, fixable: 'code', schema: [], }, create: function (context) { return { IfStatement: function (node) { const tokens = context.getSourceCode().getTokens(node); const firstToken = tokens[0]; const secondToken = tokens[1]; if (firstToken.type === 'Keyword' && firstToken.value === 'if' && secondToken.type === 'Punctuator' && secondToken.value === '(' && secondToken.range[0] - firstToken.range[1] > 0 ) { context.report({ node: node, message: 'Do not use spaces between \'if\' and its condition', fix: function(fixer) { return fixer.replaceTextRange([firstToken.range[1], secondToken.range[0]], '('); } }); } }, ForStatement: function (node) { const tokens = context.getSourceCode().getTokens(node); const firstToken = tokens[0]; const secondToken = tokens[1]; if ( firstToken.type === 'Keyword' && firstToken.value === 'for' && secondToken.type === 'Punctuator' && secondToken.value === '(' && secondToken.range[0] - firstToken.range[1] > 0 ) { context.report({ node: node, message: 'Do not use spaces between \'for\' and its condition', fix: function(fixer) { return fixer.replaceTextRange([firstToken.range[1], secondToken.range[0]], '('); } }); } }, WhileStatement: function (node) { const tokens = context.getSourceCode().getTokens(node); const firstToken = tokens[0]; const secondToken = tokens[1]; if ( firstToken.type === 'Keyword' && firstToken.value === 'while' && secondToken.type === 'Punctuator' && secondToken.value === '(' && secondToken.range[0] - firstToken.range[1] > 0 ) { context.report({ node: node, message: 'Do not use spaces between \'while\' and its condition', fix: function(fixer) { return fixer.replaceTextRange([firstToken.range[1], secondToken.range[0]], '('); } }); } }, SwitchStatement: function (node) { const tokens = context.getSourceCode().getTokens(node); const firstToken = tokens[0]; const secondToken = tokens[1]; if ( firstToken.type === 'Keyword' && firstToken.value === 'switch' && secondToken.type === 'Punctuator' && secondToken.value === '(' && secondToken.range[0] - firstToken.range[1] > 0 ) { context.report({ node: node, message: 'Do not use spaces between \'switch\' and its expression', fix: function(fixer) { return fixer.replaceTextRange([firstToken.range[1], secondToken.range[0]], '('); } }); } }, }; }, }, 'no-strict-equality': { meta: { docs: { description: 'Disallow strict equality operator', category: 'Z8 Stylistic Issues', recommended: true, }, fixable: 'code', schema: [], }, create: function (context) { return { BinaryExpression: function (node) { if (node.operator === '===') { context.report({ node: node, message: 'Avoid using strict equality operator \'===\' (use loose equality operator \'==\' instead)', }); } }, }; }, }, // auto fixable 'no-double-quotes': { meta: { docs: { description: 'Disallow double quotes', category: 'Z8 Stylistic Issues', recommended: true, }, fixable: 'code', schema: [], }, create: function (context) { return { Literal: function (node) { if (typeof node.value === 'string' && node.raw.includes('"')) { context.report({ node: node, message: 'Avoid using double quotes (use single quotes instead)', fix: function(fixer) { return fixer.replaceTextRange([node.start+1, node.end-1], "'" + node.value + "'"); } }); } }, }; }, } 'no-arrow-functions': { meta: { docs: { description: 'Disallow arrow functions', category: 'Z8 Stylistic Issues', recommended: true, }, schema: [], }, create: function (context) { return { ArrowFunctionExpression: function (node) { context.report({ node: node, message: 'Avoid using arrow functions', }); }, }; }, }, 'no-function-declaration': { meta: { docs: { description: 'Disallow function declaration', category: 'Z8 Stylistic Issues', recommended: true, }, schema: [], }, create: function (context) { return { FunctionDeclaration: function (node) { context.report({ node: node, message: 'Use function expression instead of function declaration', }); }, VariableDeclarator: function (node) { if ( node.init && node.init.type === 'FunctionExpression' && node.init.id && node.init.id.type === 'Identifier' && node.id && node.id.type === 'Identifier' && node.init.id.name === node.id.name ) { context.report({ node: node, message: 'Use function expression instead of function declaration', }); } }, }; }, }, }, }; /** * Preferable .eslintrc.js: * * module.exports = { * 'plugins': [ * 'z8' * ], * 'rules': { * 'z8/no-spaces-in-control-flow-statements': ['error'], * 'z8/no-strict-equality': ['error'], * 'z8/no-double-quotes': ['error'], * 'z8/no-arrow-functions': ['error'], * 'z8/no-function-declaration': ['error'], * 'object-shorthand': ['error', 'never'], * 'object-curly-spacing': ['error', 'always'], * 'space-before-blocks': ['error', 'always'], * 'func-call-spacing': ['error', 'never'], * 'space-before-function-paren': ['error', 'never'], * 'semi': ['error', 'always'], * 'space-infix-ops': ['error'], * "indent": ['error', 'tab'], * 'no-console': ['warn'], * }, * 'parserOptions': { * 'ecmaVersion': 2022 * } * } * */