We use the following linting tools in Liferay DXP:
- Underlying linting framework: ESLint.
- Our standard ESLint configuration: eslint-config-liferay.
- Helper for actually applying the above tools: liferay-npm-scripts.
All modules should have a package.json
containing these scripts:
{
"scripts": {
"checkFormat": "liferay-npm-scripts check",
"format": "liferay-npm-scripts fix"
}
}
Additionally, we provide this same configuration in the top-level "modules/" directory so that the scripts can be run globally across all JS files in the repository, even in directories which aren't otherwise covered by a package.json
.
The checkFormat
script runs all lints (in addition to checking source formatting) and will exit with an error if any problems are found.
The format
script not only reports problems but attempts to apply automatic fixes when possible, writing to the files on disk. Note that just like the checkFormat
script, this script deals with both formatting and non-presentational problems with the code (see "Formatting").
eslint-config-liferay provides a base configuration suitable for use in all projects, and liferay-npm-scripts automatically uses it via ESLint's "extends" mechanism. You don't need to set this up manually, but behind the scenes it is effectively doing something like this:
// .eslintrc.js
module.exports = {
extends: ['liferay'],
};
In order to activate React-specific rules in a project, you can create an .eslintrc.js
in the project root that instead extends the "liferay/react" preset:
// .eslintrc.js
module.exports = {
extends: ['liferay/react'],
};
liferay-npm-scripts takes care of extending the base eslint-config-liferay preset, and additionally defines some useful globals (eg. Liferay
etc) that are always present in the Liferay DXP environment.
The base eslint-config-liferay ruleset, however, is general enough that it can be used as-is in our open source projects. Examples include AlloyEditor, Clay, and many others.
In the name of consistency we'd like to avoid using lint suppressions as much as possible and have the same rules apply uniformly everywhere.
However, it is sometimes unavoidable and a lint suppression is required, so this section documents some quirks of the system that may not be obvious if you are coming from the official ESLint configuration documentation.
liferay-npm-scripts enforces the use of standard configuration by creating a temporary configuration file, which it passes to eslint
via the --config
option. Because of the way precedence works in ESLint, these settings will actually override any settings that might be present in a local .eslintrc.js
file.
As such, overrides need be applied using in-file comments of the form:
/* eslint no-unused-vars: "warn" */
/* eslint-disable-next-line no-console */
Key points to note:
- If a suppression is temporary, prefer downgrading it from an error to a warning rather than turning it off completely. In this way, it will continue to be visible but it won't cause CI runs to fail.
- If a suppression is permanent and the code cannot (or should not) be rewritten to avoid it, prefer narrowly scoped suppressions. In other words, prefer more targeted suppressions like
eslint-disable-next-line
overeslint-disable
, and make sure you always provide a specific rule name as opposed to a blanket suppression (eg.eslint-disable-next-line no-console
overeslint-disable-next-line
). Broader suppressions run the risk of masking more problems than the suppression originally intended.
NOTE: Comments written with a leading //
will not work:
// eslint no-undef: "warn"
- Formatting: information on checking and fixing the presentational aspects of our source code.