Skip to content

Commit

Permalink
Merge pull request #578 from github/filenames-fix
Browse files Browse the repository at this point in the history
Update filenames
  • Loading branch information
gracepark authored Nov 25, 2024
2 parents 491ca33 + b5369f3 commit 97908fc
Show file tree
Hide file tree
Showing 18 changed files with 164 additions and 17 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ This config will be interpreted in the following way:
| [async-currenttarget](docs/rules/async-currenttarget.md) | disallow `event.currentTarget` calls inside of async functions | 🔍 | | |
| [async-preventdefault](docs/rules/async-preventdefault.md) | disallow `event.preventDefault` calls inside of async functions | 🔍 | | |
| [authenticity-token](docs/rules/authenticity-token.md) | disallow usage of CSRF tokens in JavaScript | 🔐 | | |
| [filenames-match-regex](docs/rules/filenames-match-regex.md) | ensure filenames match a regex naming convention || | |
| [get-attribute](docs/rules/get-attribute.md) | disallow wrong usage of attribute names | 🔍 | 🔧 | |
| [js-class-name](docs/rules/js-class-name.md) | enforce a naming convention for js- prefixed classes | 🔐 | | |
| [no-blur](docs/rules/no-blur.md) | disallow usage of `Element.prototype.blur()` | 🔍 | | |
Expand Down
35 changes: 35 additions & 0 deletions docs/rules/filenames-match-regex.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Ensure filenames match a regex naming convention (`github/filenames-match-regex`)

💼 This rule is enabled in the ✅ `recommended` config.

<!-- end auto-generated rule header -->

## Rule Details

Rule to ensure that filenames match a convention, with a default of camelCase.

👎 Examples of **incorrect** filename for this default rule:

`file-name.js`

👍 Examples of **correct** code for this rule:

`fileName.js`

## Options

regex - Regex to match the filename structure. Defaults to camelCase.


```json
{
"filenames-match-regex": [
"error",
"^[a-z0-9-]+(.[a-z0-9-]+)?$"
]
}
```

## Version

4.3.2
4 changes: 1 addition & 3 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
const globals = require('globals')
const eslintPlugin = require('eslint-plugin-eslint-plugin')
const importPlugin = require('eslint-plugin-import')
const filenames = require('eslint-plugin-filenames')
const i18nTextPlugin = require('eslint-plugin-i18n-text')
const recommendedGitHub = require('./lib/configs/flat/recommended')
const {fixupPluginRules} = require('@eslint/compat')
Expand All @@ -23,13 +22,12 @@ module.exports = [
plugins: {
eslintPlugin,
importPlugin,
filenames,
'i18n-text': fixupPluginRules(i18nTextPlugin),
},
rules: {
'importPlugin/extensions': 'off',
'importPlugin/no-commonjs': 'off',
'filenamesPlugin/match-regex': 'off',
'github/filenames-match-regex': 'off',
'i18n-text/no-en': 'off',
'eslint-plugin/prefer-placeholders': 'off',
'eslint-plugin/test-case-shorthand-strings': 'off',
Expand Down
3 changes: 2 additions & 1 deletion lib/configs/flat/browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const globals = require('globals')
const github = require('../../plugin')
const importPlugin = require('eslint-plugin-import')
const escompatPlugin = require('eslint-plugin-escompat')
const {fixupPluginRules} = require('@eslint/compat')

module.exports = {
...escompatPlugin.configs['flat/recommended'],
Expand All @@ -10,7 +11,7 @@ module.exports = {
...globals.browser,
},
},
plugins: {importPlugin, escompatPlugin, github},
plugins: {importPlugin, escompatPlugin, github: fixupPluginRules(github)},
rules: {
'escompatPlugin/no-dynamic-imports': 'off',
'github/async-currenttarget': 'error',
Expand Down
3 changes: 2 additions & 1 deletion lib/configs/flat/internal.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
const github = require('../../plugin')
const {fixupPluginRules} = require('@eslint/compat')

module.exports = {
plugins: {github},
plugins: {github: fixupPluginRules(github)},
rules: {
'github/authenticity-token': 'error',
'github/js-class-name': 'error',
Expand Down
3 changes: 2 additions & 1 deletion lib/configs/flat/react.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const github = require('../../plugin')
const jsxA11yPlugin = require('eslint-plugin-jsx-a11y')
const {fixupPluginRules} = require('@eslint/compat')

module.exports = {
...jsxA11yPlugin.flatConfigs.recommended,
Expand All @@ -11,7 +12,7 @@ module.exports = {
},
},
},
plugins: {github, jsxA11yPlugin},
plugins: {github: fixupPluginRules(github), jsxA11yPlugin},
rules: {
'jsxA11yPlugin/role-supports-aria-props': 'off', // Override with github/a11y-role-supports-aria-props until https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/issues/910 is resolved
'github/a11y-aria-label-is-well-formatted': 'error',
Expand Down
6 changes: 2 additions & 4 deletions lib/configs/flat/recommended.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ const github = require('../../plugin')
const prettierPlugin = require('eslint-plugin-prettier')
const eslintComments = require('eslint-plugin-eslint-comments')
const importPlugin = require('eslint-plugin-import')
const filenames = require('eslint-plugin-filenames')
const i18nTextPlugin = require('eslint-plugin-i18n-text')
const noOnlyTestsPlugin = require('eslint-plugin-no-only-tests')
const {fixupPluginRules} = require('@eslint/compat')
Expand All @@ -17,13 +16,12 @@ module.exports = {
},
},
plugins: {
filenamesPlugin: fixupPluginRules(filenames),
prettierPlugin,
eslintComments,
importPlugin,
'i18n-text': fixupPluginRules(i18nTextPlugin),
noOnlyTestsPlugin,
github,
github: fixupPluginRules(github),
},
rules: {
'constructor-super': 'error',
Expand All @@ -34,7 +32,7 @@ module.exports = {
'eslintComments/no-unused-disable': 'error',
'eslintComments/no-unused-enable': 'error',
'eslintComments/no-use': ['error', {allow: ['eslint', 'eslint-disable-next-line', 'eslint-env', 'globals']}],
'filenamesPlugin/match-regex': ['error', '^[a-z0-9-]+(.[a-z0-9-]+)?$'],
'github/filenames-match-regex': ['error', '^[a-z0-9-]+(.[a-z0-9-]+)?$'],
'func-style': ['error', 'declaration', {allowArrowFunctions: true}],
'github/array-foreach': 'error',
'github/no-implicit-buggy-globals': 'error',
Expand Down
3 changes: 2 additions & 1 deletion lib/configs/flat/typescript.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ const eslint = require('@eslint/js')
const tseslint = require('typescript-eslint')
const escompatPlugin = require('eslint-plugin-escompat')
const github = require('../../plugin')
const {fixupPluginRules} = require('@eslint/compat')

module.exports = tseslint.config(eslint.configs.recommended, ...tseslint.configs.recommended, {
languageOptions: {
parser: tseslint.parser,
},
plugins: {'@typescript-eslint': tseslint.plugin, escompatPlugin, github},
plugins: {'@typescript-eslint': tseslint.plugin, escompatPlugin, github: fixupPluginRules(github)},
rules: {
camelcase: 'off',
'no-unused-vars': 'off',
Expand Down
4 changes: 2 additions & 2 deletions lib/configs/recommended.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ module.exports = {
env: {
es6: true,
},
plugins: ['github', 'prettier', 'eslint-comments', 'import', 'filenames', 'i18n-text', 'no-only-tests'],
plugins: ['github', 'prettier', 'eslint-comments', 'import', 'i18n-text', 'no-only-tests'],
rules: {
'constructor-super': 'error',
'eslint-comments/disable-enable-pair': 'off',
Expand All @@ -18,7 +18,7 @@ module.exports = {
'eslint-comments/no-unused-disable': 'error',
'eslint-comments/no-unused-enable': 'error',
'eslint-comments/no-use': ['error', {allow: ['eslint', 'eslint-disable-next-line', 'eslint-env', 'globals']}],
'filenames/match-regex': ['error', '^[a-z0-9-]+(.[a-z0-9-]+)?$'],
'github/filenames-match-regex': ['error', '^[a-z0-9-]+(.[a-z0-9-]+)?$'],
'func-style': ['error', 'declaration', {allowArrowFunctions: true}],
'github/array-foreach': 'error',
'github/no-implicit-buggy-globals': 'error',
Expand Down
1 change: 1 addition & 0 deletions lib/plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ module.exports = {
'async-currenttarget': require('./rules/async-currenttarget'),
'async-preventdefault': require('./rules/async-preventdefault'),
'authenticity-token': require('./rules/authenticity-token'),
'filenames-match-regex': require('./rules/filenames-match-regex'),
'get-attribute': require('./rules/get-attribute'),
'js-class-name': require('./rules/js-class-name'),
'no-blur': require('./rules/no-blur'),
Expand Down
51 changes: 51 additions & 0 deletions lib/rules/filenames-match-regex.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// This is adapted from https://github.com/selaux/eslint-plugin-filenames since it's no longer actively maintained
// and needed a fix for eslint v9
const path = require('path')
const parseFilename = require('../utils/parse-filename')
const getExportedName = require('../utils/get-exported-name')
const isIgnoredFilename = require('../utils/is-ignored-filename')

module.exports = {
meta: {
type: 'problem',
docs: {
description: 'ensure filenames match a regex naming convention',
url: require('../url')(module),
},
schema: {
type: 'array',
minItems: 0,
maxItems: 1,
items: [
{
type: 'string',
},
],
},
},

create(context) {
const defaultRegexp = /^([a-z0-9]+)([A-Z][a-z0-9]+)*$/g
const conventionRegexp = context.options[0] ? new RegExp(context.options[0]) : defaultRegexp
const ignoreExporting = context.options[1] ? context.options[1] : false

return {
Program(node) {
const filename = context.getFilename()
const absoluteFilename = path.resolve(filename)
const parsed = parseFilename(absoluteFilename)
const shouldIgnore = isIgnoredFilename(filename)
const isExporting = Boolean(getExportedName(node))
const matchesRegex = conventionRegexp.test(parsed.name)

if (shouldIgnore) return
if (ignoreExporting && isExporting) return
if (!matchesRegex) {
context.report(node, "Filename '{{name}}' does not match the regex naming convention.", {
name: parsed.base,
})
}
},
}
},
}
37 changes: 37 additions & 0 deletions lib/utils/get-exported-name.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
function getNodeName(node, options) {
const op = options || []

if (node.type === 'Identifier') {
return node.name
}

if (node.id && node.id.type === 'Identifier') {
return node.id.name
}

if (op[2] && node.type === 'CallExpression' && node.callee.type === 'Identifier') {
return node.callee.name
}
}

module.exports = function getExportedName(programNode, options) {
for (let i = 0; i < programNode.body.length; i += 1) {
const node = programNode.body[i]

if (node.type === 'ExportDefaultDeclaration') {
return getNodeName(node.declaration, options)
}

if (
node.type === 'ExpressionStatement' &&
node.expression.type === 'AssignmentExpression' &&
node.expression.left.type === 'MemberExpression' &&
node.expression.left.object.type === 'Identifier' &&
node.expression.left.object.name === 'module' &&
node.expression.left.property.type === 'Identifier' &&
node.expression.left.property.name === 'exports'
) {
return getNodeName(node.expression.right, options)
}
}
}
5 changes: 5 additions & 0 deletions lib/utils/is-ignored-filename.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const ignoredFilenames = ['<text>', '<input>']

module.exports = function isIgnoredFilename(filename) {
return ignoredFilenames.indexOf(filename) !== -1
}
12 changes: 12 additions & 0 deletions lib/utils/parse-filename.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
const path = require('path')

module.exports = function parseFilename(filename) {
const ext = path.extname(filename)

return {
dir: path.dirname(filename),
base: path.basename(filename),
ext,
name: path.basename(filename, ext),
}
}
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@
"eslint-config-prettier": ">=8.0.0",
"eslint-plugin-escompat": "^3.11.3",
"eslint-plugin-eslint-comments": "^3.2.0",
"eslint-plugin-filenames": "^1.3.2",
"eslint-plugin-i18n-text": "^1.0.1",
"eslint-plugin-import": "^2.25.2",
"eslint-plugin-jsx-a11y": "^6.7.1",
Expand Down
4 changes: 2 additions & 2 deletions test-examples/flat/eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import github from 'eslint-plugin-github'

export default [
github.getFlatConfigs().browser,
github.getFlatConfigs().recommended,
github.getFlatConfigs().browser,
github.getFlatConfigs().react,
...github.getFlatConfigs().typescript,
{
files: ['**/*.{js,mjs,cjs,jsx,mjsx,ts,tsx,mtsx}'],
ignores: ['eslint.config.mjs'],
rules: {
'github/array-foreach': 'error',
'github/async-preventdefault': 'warn',
'github/no-then': 'error',
'github/no-blur': 'error',
'github/async-preventdefault': 'error',
},
},
]
2 changes: 1 addition & 1 deletion test-examples/flat/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"@eslint/js": "^9.5.0",
"@types/node": "^20.14.5",
"cross-env": "^7.0.3",
"eslint": "^8.57.0",
"eslint": "^9.14.0",
"eslint-plugin-github": "file:../..",
"typescript": "^5.6.3",
"typescript-eslint": "^8.12.2"
Expand Down
6 changes: 6 additions & 0 deletions test-examples/flat/src/getAttribute.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,9 @@ const title = document.createElement('h1')
title.textContent = `${title}!`

foobar(title)

document.addEventListener('click', async function (event) {
const data = await fetch()

event.preventDefault()
})

0 comments on commit 97908fc

Please sign in to comment.