Skip to content
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
184 changes: 183 additions & 1 deletion eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,188 @@ module.exports = [
'no-use-before-define': 'off'
}
},
{
// disallow imports from node modules
ignores: ['lib/core/imports/**/*.js'],
rules: {
'no-restricted-imports': [
'error',
{
patterns: [
{
regex: '^[^.]',
message: 'Only core/imports files should import from node modules'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice if this could summarize why we use this pattern (either directly or with a reference to an appropriate readme section/issue); future maintainers are more likely to respect the rule if it's cleary why it exists.

(I think this is more important for this rule and for the "no vNode in utils" thing (see comment below) than the other cases; the other ones are more obviously enforcing a non-circular import structure, but those two rules aren't so obvious about why they're here)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ya, I'm not sure if this restriction is actually needed anymore with how we build things now. I think it was more important before we moved over to es6 imports and esbuild. @WilcoFiers do you think this distinction is needed anymore, or could any file import from node modules?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's probably good we continue to put external dependencies on axe.imports so that we can use them in tests. Can't use imports in our tests yet.

}
]
}
]
}
},
{
// disallow imports in standards
files: ['lib/standards/**/*.js'],
// index file can import other standards and from utils
ignores: ['lib/standards/index.js'],
rules: {
'no-restricted-imports': [
'error',
{
patterns: [
{
group: ['*'],
message:
"Standard files shouldn't use imports as they are just hard coded data objects"
}
]
}
]
}
},
{
// restrict imports to core/utils files to other core/utils, core, core/base, standards, imports, or reporters/helpers
files: ['lib/core/utils/**/*.js'],
rules: {
'no-restricted-imports': [
'error',
{
patterns: [
{
// e.g. "../commons/aria/" or "../public/"
regex:
'.*\\.\\.\\/(commons|public|checks|rules)(\\/|$)|.*\\.\\.\\/reporters\\/.*?\\.js',
message:
'Util files should only import from other utils, core, or standard files'
},
// disallow imports from node modules
// seems only 1 regex pattern is allowed to match as not having this allows node module imports even while having the general rule above for all files)
{
regex: '^[^.]',
message: 'Only core/imports files should import from node modules'
}
]
}
]
}
},
{
// restrict imports to core/public files to other core/public, or imports allowed by core/utils
files: ['lib/core/public/**/*.js'],
rules: {
'no-restricted-imports': [
'error',
{
patterns: [
{
// e.g. "../commons/aria/" or "../checks/"
regex:
'.*\\.\\.\\/(commons|checks|rules)(\\/|$)|.*\\.\\.\\/reporters\\/.*?\\.js',
message:
'Public files should only import from other public, util, core, or standard files'
},
// disallow imports from node modules
{
regex: '^[^.]',
message: 'Only core/imports files should import from node modules'
}
]
}
]
}
},
{
// disallow imports in core/imports files to any non-node module
files: ['lib/core/imports/**/*.js'],
rules: {
'no-restricted-imports': [
'error',
{
patterns: [
{
// relative file paths
regex: '\\\.\\\.\\/',
message: 'Import files should only import from node modules'
}
]
}
]
}
},
{
// disallow imports in core/reporters files to any non-util file
files: ['lib/core/reporters/**/*.js'],
rules: {
'no-restricted-imports': [
'error',
{
patterns: [
{
// e.g. "../commons/aria/" or "../checks/"
regex: '.*\\.\\.\\/(commons|base|public|checks|rules)(\\/|$)',
message: 'Reporter files should only import util functions'
},
// disallow imports from node modules
{
regex: '^[^.]',
message: 'Only core/imports files should import from node modules'
}
]
}
]
}
},
{
// disallow imports in commons files to any check or rule
files: ['lib/commons/**/*.js'],
rules: {
'no-restricted-imports': [
'error',
{
patterns: [
{
// e.g. ../checks/"
regex: '.*\\.\\.\\/(checks|rules)(\\/|$)',
message: 'Commons files cannot import from checks and rules'
},
// disallow imports from node modules
{
regex: '^[^.]',
message: 'Only core/imports files should import from node modules'
}
]
}
]
}
},
{
// Utils should be functions that can be used without setting up the virtual tree, as opposed to commons which require the virtual tree
files: ['lib/core/utils/**/*.js'],
ignores: [
// these are files with known uses of virtual node that are legacy before this rule was enforced
'lib/core/utils/closest.js',
'lib/core/utils/contains.js',
'lib/core/utils/query-selector-all-filter.js',
'lib/core/utils/selector-cache.js',
// this will create a virtual node if one doesn't exist already in order to truncate the html output properly
'lib/core/utils/dq-element.js',
// this sets up the virtual tree so is allowed vNode
'lib/core/utils/get-flattened-tree.js'
],
rules: {
'no-restricted-syntax': [
'error',
{
selector: 'MemberExpression[object.name=vNode]',
message:
"Utils is meant for utility functions that work independently of axe's state; utilities that require the virtual tree to be set up should go in commons, not utils."
},
{
selector: 'MemberExpression[object.name=virtualNode]',
message:
"Utils is meant for utility functions that work independently of axe's state; utilities that require the virtual tree to be set up should go in commons, not utils."
}
]
}
},
{
files: ['doc/examples/chrome-debugging-protocol/axe-cdp.js'],
languageOptions: {
Expand Down Expand Up @@ -189,7 +371,7 @@ module.exports = [
'build/tasks/aria-supported.js',
'doc/api/*',
'doc/examples/jest_react/*.js',
'lib/core/imports/*.js',
'lib/core/imports/polyfills.js',
'lib/core/utils/uuid.js',
'axe.js',
'axe.min.js'
Expand Down
2 changes: 1 addition & 1 deletion lib/commons/text/has-unicode.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
getPunctuationRegExp,
getCategoryFormatRegExp
} from './unicode';
import emojiRegexText from 'emoji-regex';
import { emojiRegexText } from '../../core/imports';

/**
* Determine if a given string contains unicode characters, specified in options
Expand Down
2 changes: 1 addition & 1 deletion lib/commons/text/remove-unicode.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
getPunctuationRegExp,
getCategoryFormatRegExp
} from './unicode.js';
import emojiRegexText from 'emoji-regex';
import { emojiRegexText } from '../../core/imports';

/**
* Remove specified type(s) unicode characters
Expand Down
2 changes: 1 addition & 1 deletion lib/core/base/audit.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
ruleShouldRun,
performanceTimer
} from '../utils';
import doT from '@deque/dot';
import { doT } from '../imports';
import constants from '../constants';

const dotRegex = /\{\{.+?\}\}/g;
Expand Down
2 changes: 1 addition & 1 deletion lib/core/utils/css-parser.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { CssSelectorParser } from 'css-selector-parser';
import { CssSelectorParser } from '../imports';

const parser = new CssSelectorParser();
parser.registerSelectorPseudos('not');
Expand Down
2 changes: 1 addition & 1 deletion lib/core/utils/memoize.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import memoize from 'memoizee';
import { memoize } from '../imports';

// FYI: memoize does not always play nice with esbuild
// and sometimes is built out of order.
Expand Down