Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: migrate to ESM only #622

Merged
merged 2 commits into from
Mar 19, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .eslint-doc-generatorrc.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/** @type {import('eslint-doc-generator').GenerateOptions} */
module.exports = {
export default {
configEmoji: [
['browser', '🔍'],
['internal', '🔐'],
Expand Down
19 changes: 11 additions & 8 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
const globals = require('globals')
const eslintPlugin = require('eslint-plugin-eslint-plugin')
const importPlugin = require('eslint-plugin-import')
const i18nTextPlugin = require('eslint-plugin-i18n-text')
const recommendedGitHub = require('./lib/configs/flat/recommended')
const {fixupPluginRules} = require('@eslint/compat')
import globals from 'globals'
import eslintPlugin from 'eslint-plugin-eslint-plugin'
import importPlugin from 'eslint-plugin-import'
import i18nTextPlugin from 'eslint-plugin-i18n-text'
import recommendedGitHub from './lib/configs/flat/recommended.js'
import {fixupPluginRules} from '@eslint/compat'

module.exports = [
export default [
recommendedGitHub,
eslintPlugin.configs['flat/all'],
{
files: ['lib/rules/**/*.js'],
...eslintPlugin.configs['flat/all'],
},
{
ignores: ['test-examples/**'],
},
Expand Down
2 changes: 1 addition & 1 deletion lib/configs/browser.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module.exports = {
export default {
env: {
browser: true,
},
Expand Down
12 changes: 6 additions & 6 deletions lib/configs/flat/browser.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
const globals = require('globals')
const github = require('../../plugin')
const importPlugin = require('eslint-plugin-import')
const escompat = require('eslint-plugin-escompat')
const {fixupPluginRules} = require('@eslint/compat')
import globals from 'globals'
import github from '../../plugin.js'
import importPlugin from 'eslint-plugin-import'
import escompat from 'eslint-plugin-escompat'
import {fixupPluginRules} from '@eslint/compat'

module.exports = {
export default {
...escompat.configs['flat/recommended'],
languageOptions: {
globals: {
Expand Down
6 changes: 3 additions & 3 deletions lib/configs/flat/internal.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const github = require('../../plugin')
const {fixupPluginRules} = require('@eslint/compat')
import github from '../../plugin.js'
import {fixupPluginRules} from '@eslint/compat'

module.exports = {
export default {
plugins: {github: fixupPluginRules(github)},
rules: {
'github/authenticity-token': 'error',
Expand Down
8 changes: 4 additions & 4 deletions lib/configs/flat/react.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
const github = require('../../plugin')
const jsxA11yPlugin = require('eslint-plugin-jsx-a11y')
const {fixupPluginRules} = require('@eslint/compat')
import github from '../../plugin.js'
import jsxA11yPlugin from 'eslint-plugin-jsx-a11y'
import {fixupPluginRules} from '@eslint/compat'

module.exports = {
export default {
...jsxA11yPlugin.flatConfigs.recommended,
languageOptions: {
sourceType: 'module',
Expand Down
18 changes: 9 additions & 9 deletions lib/configs/flat/recommended.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
const globals = require('globals')
const github = require('../../plugin')
const prettierPlugin = require('eslint-plugin-prettier')
const eslintComments = require('eslint-plugin-eslint-comments')
const importPlugin = require('eslint-plugin-import')
const i18nTextPlugin = require('eslint-plugin-i18n-text')
const noOnlyTestsPlugin = require('eslint-plugin-no-only-tests')
const {fixupPluginRules} = require('@eslint/compat')
import globals from 'globals'
import github from '../../plugin.js'
import prettierPlugin from 'eslint-plugin-prettier'
import eslintComments from 'eslint-plugin-eslint-comments'
import importPlugin from 'eslint-plugin-import'
import i18nTextPlugin from 'eslint-plugin-i18n-text'
import noOnlyTestsPlugin from 'eslint-plugin-no-only-tests'
import {fixupPluginRules} from '@eslint/compat'

module.exports = {
export default {
languageOptions: {
ecmaVersion: 6,
sourceType: 'module',
Expand Down
7 changes: 4 additions & 3 deletions lib/configs/flat/typescript.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
const tseslint = require('typescript-eslint')
const escompat = require('eslint-plugin-escompat')
// eslint-disable-next-line import/no-unresolved
import tseslint from 'typescript-eslint'
import escompat from 'eslint-plugin-escompat'

module.exports = tseslint.config(...tseslint.configs.recommended, ...escompat.configs['flat/typescript-2020'], {
export default tseslint.config(...tseslint.configs.recommended, ...escompat.configs['flat/typescript-2020'], {
languageOptions: {
parser: tseslint.parser,
},
Expand Down
2 changes: 1 addition & 1 deletion lib/configs/internal.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module.exports = {
export default {
plugins: ['github'],
rules: {
'github/authenticity-token': 'error',
Expand Down
2 changes: 1 addition & 1 deletion lib/configs/react.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module.exports = {
export default {
parserOptions: {
sourceType: 'module',
ecmaFeatures: {
Expand Down
2 changes: 1 addition & 1 deletion lib/configs/recommended.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module.exports = {
export default {
parserOptions: {
ecmaFeatures: {
ecmaVersion: 6,
Expand Down
2 changes: 1 addition & 1 deletion lib/configs/typescript.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module.exports = {
export default {
extends: ['plugin:@typescript-eslint/recommended', 'prettier', 'plugin:escompat/typescript-2020'],
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint', 'escompat', 'github'],
Expand Down
21 changes: 7 additions & 14 deletions lib/formatters/stylish-fixes.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,11 @@
'use strict'
import childProcess from 'node:child_process'
import fs from 'node:fs'
import os from 'node:os'
import path from 'node:path'
import SourceCodeFixer from 'eslint/lib/linter/source-code-fixer.js'
import getRuleURI from 'eslint-rule-documentation'

const childProcess = require('child_process')
const fs = require('fs')
const os = require('os')
const path = require('path')
let SourceCodeFixer = null
try {
SourceCodeFixer = require('eslint/lib/linter/source-code-fixer')
} catch {
SourceCodeFixer = require('eslint/lib/util/source-code-fixer')
}
const getRuleURI = require('eslint-rule-documentation')

module.exports = function (results) {
export default function stylishFixes(results) {
let output = '\n'
let errors = 0
let warnings = 0
Expand Down
34 changes: 22 additions & 12 deletions lib/index.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,31 @@
const github = require('./plugin')
import github from './plugin.js'
import flatBrowserConfig from './configs/flat/browser.js'
import flatInternalConfig from './configs/flat/internal.js'
import flatRecommendedConfig from './configs/flat/recommended.js'
import flatTypescriptConfig from './configs/flat/typescript.js'
import flatReactConfig from './configs/flat/react.js'
import browserConfig from './configs/browser.js'
import internalConfig from './configs/internal.js'
import recommendedConfig from './configs/recommended.js'
import typescriptConfig from './configs/typescript.js'
import reactConfig from './configs/react.js'

const getFlatConfig = () => ({
browser: require('./configs/flat/browser'),
internal: require('./configs/flat/internal'),
recommended: require('./configs/flat/recommended'),
typescript: require('./configs/flat/typescript'),
react: require('./configs/flat/react'),
browser: flatBrowserConfig,
internal: flatInternalConfig,
recommended: flatRecommendedConfig,
typescript: flatTypescriptConfig,
react: flatReactConfig,
})

module.exports = {
export default {
rules: github.rules,
configs: {
browser: require('./configs/browser'),
internal: require('./configs/internal'),
recommended: require('./configs/recommended'),
typescript: require('./configs/typescript'),
react: require('./configs/react'),
browser: browserConfig,
internal: internalConfig,
recommended: recommendedConfig,
typescript: typescriptConfig,
react: reactConfig,
},
getFlatConfigs: getFlatConfig,
}
81 changes: 54 additions & 27 deletions lib/plugin.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,59 @@
const {name, version} = require('../package.json')
import {packageJson} from './utils/commonjs-json-wrappers.cjs'
import a11yNoVisuallyHiddenInteractiveElement from './rules/a11y-no-visually-hidden-interactive-element.js'
import a11yNoGenericLinkText from './rules/a11y-no-generic-link-text.js'
import a11yNoTitleAttribute from './rules/a11y-no-title-attribute.js'
import a11yAriaLabelIsWellFormatted from './rules/a11y-aria-label-is-well-formatted.js'
import a11yRoleSupportsAriaProps from './rules/a11y-role-supports-aria-props.js'
import a11ySvgHasAccessibleName from './rules/a11y-svg-has-accessible-name.js'
import arrayForeach from './rules/array-foreach.js'
import asyncCurrenttarget from './rules/async-currenttarget.js'
import asyncPreventdefault from './rules/async-preventdefault.js'
import authenticityToken from './rules/authenticity-token.js'
import filenamesMatchRegex from './rules/filenames-match-regex.js'
import getAttribute from './rules/get-attribute.js'
import jsClassName from './rules/js-class-name.js'
import noBlur from './rules/no-blur.js'
import noDNone from './rules/no-d-none.js'
import noDataset from './rules/no-dataset.js'
import noImplicitBuggyGlobals from './rules/no-implicit-buggy-globals.js'
import noInnerHTML from './rules/no-inner-html.js'
import noInnerText from './rules/no-innerText.js'
import noDynamicScriptTag from './rules/no-dynamic-script-tag.js'
import noThen from './rules/no-then.js'
import noUselessPassive from './rules/no-useless-passive.js'
import preferObservers from './rules/prefer-observers.js'
import requirePassiveEvents from './rules/require-passive-events.js'
import unescapedHtmlLiteral from './rules/unescaped-html-literal.js'

module.exports = {
const {name, version} = packageJson

export default {
meta: {name, version},
rules: {
'a11y-no-visually-hidden-interactive-element': require('./rules/a11y-no-visually-hidden-interactive-element'),
'a11y-no-generic-link-text': require('./rules/a11y-no-generic-link-text'),
'a11y-no-title-attribute': require('./rules/a11y-no-title-attribute'),
'a11y-aria-label-is-well-formatted': require('./rules/a11y-aria-label-is-well-formatted'),
'a11y-role-supports-aria-props': require('./rules/a11y-role-supports-aria-props'),
'a11y-svg-has-accessible-name': require('./rules/a11y-svg-has-accessible-name'),
'array-foreach': require('./rules/array-foreach'),
'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'),
'no-d-none': require('./rules/no-d-none'),
'no-dataset': require('./rules/no-dataset'),
'no-implicit-buggy-globals': require('./rules/no-implicit-buggy-globals'),
'no-inner-html': require('./rules/no-inner-html'),
'no-innerText': require('./rules/no-innerText'),
'no-dynamic-script-tag': require('./rules/no-dynamic-script-tag'),
'no-then': require('./rules/no-then'),
'no-useless-passive': require('./rules/no-useless-passive'),
'prefer-observers': require('./rules/prefer-observers'),
'require-passive-events': require('./rules/require-passive-events'),
'unescaped-html-literal': require('./rules/unescaped-html-literal'),
'a11y-no-visually-hidden-interactive-element': a11yNoVisuallyHiddenInteractiveElement,
'a11y-no-generic-link-text': a11yNoGenericLinkText,
'a11y-no-title-attribute': a11yNoTitleAttribute,
'a11y-aria-label-is-well-formatted': a11yAriaLabelIsWellFormatted,
'a11y-role-supports-aria-props': a11yRoleSupportsAriaProps,
'a11y-svg-has-accessible-name': a11ySvgHasAccessibleName,
'array-foreach': arrayForeach,
'async-currenttarget': asyncCurrenttarget,
'async-preventdefault': asyncPreventdefault,
'authenticity-token': authenticityToken,
'filenames-match-regex': filenamesMatchRegex,
'get-attribute': getAttribute,
'js-class-name': jsClassName,
'no-blur': noBlur,
'no-d-none': noDNone,
'no-dataset': noDataset,
'no-implicit-buggy-globals': noImplicitBuggyGlobals,
'no-inner-html': noInnerHTML,
'no-innerText': noInnerText,
'no-dynamic-script-tag': noDynamicScriptTag,
'no-then': noThen,
'no-useless-passive': noUselessPassive,
'prefer-observers': preferObservers,
'require-passive-events': requirePassiveEvents,
'unescaped-html-literal': unescapedHtmlLiteral,
},
}
9 changes: 6 additions & 3 deletions lib/rules/a11y-aria-label-is-well-formatted.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
const {getProp} = require('jsx-ast-utils')
import jsxAstUtils from 'jsx-ast-utils'
import url from '../url.js'

module.exports = {
const {getProp} = jsxAstUtils

export default {
meta: {
type: 'problem',
docs: {
description: 'enforce [aria-label] text to be formatted as you would visual text.',
url: require('../url')(module),
url: url(import.meta.url),
recommended: false,
},
schema: [],
Expand Down
10 changes: 6 additions & 4 deletions lib/rules/a11y-no-generic-link-text.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
const {getProp, getPropValue} = require('jsx-ast-utils')
const {getElementType} = require('../utils/get-element-type')
import jsxAstUtils from 'jsx-ast-utils'
import {getElementType} from '../utils/get-element-type.js'
import url from '../url.js'

const {getProp, getPropValue} = jsxAstUtils
const bannedLinkText = ['read more', 'here', 'click here', 'learn more', 'more']

/* Downcase and strip extra whitespaces and punctuation */
Expand All @@ -12,12 +14,12 @@ const stripAndDowncaseText = text => {
.trim()
}

module.exports = {
export default {
meta: {
type: 'problem',
docs: {
description: 'disallow generic link text',
url: require('../url')(module),
url: url(import.meta.url),
recommended: false,
},
deprecated: true,
Expand Down
10 changes: 6 additions & 4 deletions lib/rules/a11y-no-title-attribute.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
const {getProp, getPropValue} = require('jsx-ast-utils')
const {getElementType} = require('../utils/get-element-type')
import jsxAstUtils from 'jsx-ast-utils'
import {getElementType} from '../utils/get-element-type.js'
import url from '../url.js'

const {getProp, getPropValue} = jsxAstUtils
const SEMANTIC_ELEMENTS = [
'a',
'button',
Expand Down Expand Up @@ -38,12 +40,12 @@ const ifSemanticElement = (context, node) => {
return false
}

module.exports = {
export default {
meta: {
type: 'problem',
docs: {
description: 'disallow using the title attribute',
url: require('../url')(module),
url: url(import.meta.url),
recommended: false,
},
schema: [],
Expand Down
12 changes: 7 additions & 5 deletions lib/rules/a11y-no-visually-hidden-interactive-element.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
const {getProp, getLiteralPropValue} = require('jsx-ast-utils')
const {getElementType} = require('../utils/get-element-type')
const {generateObjSchema} = require('eslint-plugin-jsx-a11y/lib/util/schemas')
import jsxAstUtils from 'jsx-ast-utils'
import {getElementType} from '../utils/get-element-type.js'
import {generateObjSchema} from 'eslint-plugin-jsx-a11y/lib/util/schemas.js'
import url from '../url.js'

const {getProp, getLiteralPropValue} = jsxAstUtils
const defaultClassName = 'sr-only'
const defaultcomponentName = 'VisuallyHidden'

Expand Down Expand Up @@ -55,12 +57,12 @@ const checkIfVisuallyHiddenAndInteractive = (context, options, node, isParentVis
return false
}

module.exports = {
export default {
meta: {
type: 'problem',
docs: {
description: 'enforce that interactive elements are not visually hidden',
url: require('../url')(module),
url: url(import.meta.url),
recommended: false,
},
schema: [schema],
Expand Down
Loading