This package is part of the @dhis2/cli commandline interface.
This tool is part of the dhis2/cli suite, but can also be used standalone which is useful for project level integration.
As a terminal user check out the full CLI. 🚀
This tool includes the following tools as runtime dependencies, so they are not necessary to explicitly install:
yarn add @dhis2/cli-style --dev
# or
npm install @dhis2/cli-style --save-dev
npx d2-style --help
npx d2-style validate --help
npx d2-style setup --help
npx d2-style js --help
npx d2-style js check --help
npx d2-style js apply --help
d2-style
can automatically generate the configuration files into the
repository for you. For a list of valid groups run:
npx d2-style setup
The setup
command works with the notion of groups. To install the
"base/all" group, which contains the bare essentials you need:
npx d2-style setup base/all
If a config file already exists, the tool skips overwriting it, in case there are local modifications.
To regenerate and overwrite, pass the --force
flag:
npx d2-style setup base/all --force
For a JavaScript project you will very likely want to use the
project/js
group.
npx d2-style setup project/js
Which includes a formatter, linter, git hook manager, etc.
-
When
d2-style
is installed, Husky installs itself as a Git hook, since it is a runtime dependency ofd2-style
. -
d2-style setup project/js
installs the necessary configuration files in the repo. -
Now, when a hook is triggered (e.g.
pre-commit
), the.huskyrc.js
configuration is read for that specific hook, and the command is executed. -
In the case of
pre-commit
, the command isd2-style validate
, which resolves the relevantlint-staged
configuration. -
lint-staged
is executed and passes all the staged files matching a glob in the lint-staged configuration to the designated command, e.g.d2-style js apply --stage
which will delint JS files and automatically apply the fixes, and stage the result. -
If all goes well,
d2-style js apply --stage
exits with a exit code of0
, which will let lint-staged to continue with matching more globs and running additional linters. When everything is good,lint-staged
exits with code0
. -
With the default Husky config, the commit message itself will be checked using
d2-style commit check
which usescommitlint
internally. If the commit message is valid, it exits with0
. -
The commit is created. If at any point a tool exits with a non-zero exit code, then the process halts.
-
Husky runs
d2-style validate
. -
validate
runs lint-staged. -
lint-staged runs linters.
-
Husky runs commit message check:
d2-style commit check
.
There are opportunities to extend and change the behaviour of
d2-style
, and because of how the different tools themselves work, the
process varies slightly. Remember how the command chain work, and it is
easier to reason about why.
The base
group installs .huskyrc.js
in the repository, which looks
like:
module.exports = {
hooks: {
'commit-msg': 'd2-style commit check',
'pre-commit': 'd2-style validate',
},
}
It can also be installed with:
npx d2-style setup git/husky
From here, the commands for each hook and be customized and/or extended.
By default, d2-style
uses the bundled lint-staged
configuration, so
it is possible to just run d2-style validate
without having a
configuration file for it in the repository. To override the config, we
must first generate one in the repository:
npx d2-style setup git/lint-staged
Now, in .lint-stagedrc.js
you can modify the linters to be run and on
which globs. Let's add CSS linting:
const fix = process.env.CLI_STYLE_FIX === 'true'
const stage = process.env.CLI_STYLE_STAGE === 'true'
module.exports = {
'*.{js,jsx,ts,tsx}': [
`d2-style js ${fix ? 'apply' : 'check'} ${
fix && stage ? '--stage' : ''
}`,
],
'*.css': [
'stylelint',
'git add',
]
}
The environment variables CLI_STYLE_*
are set by the validate
command, so they can be safely read in .lint-stagedrc.js
. Note that
you should always run d2-style validate
, and not lint-staged
directly.
Now we have to tell Husky to tell d2-style validate
to use our custom
lint-staged
configuration, so in .huskyrc.js
we can update the
pre-commit
hook:
'pre-commit': 'd2-style validate --lint-staged-config .lint-stagedrc.js',
We do not automatically look for a configuration file in the current
working directory as that can lead to unexpected results when using the
d2-style
command globally.
d2-style
's ESLint configuration is barebones for a reason. JavaScript
is used in many different environments and tool chains for the front-end
and back-end which all require different linters.
The scope of the base ESLint config is to include general JavaScript rules, which we have decided on, most often as a result of the decision process.
It doesn't make sense to include d2-style
and ESlint in the same
project, which can lead to strange dependency resolution issues, and
differences in the configuration format.
As the other tools, d2-style
by default uses the bundled ESLint
configuration as its
baseConfig
,
and allows a user to extend the configuration in two different ways.
Let's start with the most common one, and install the local
.eslintrc.js
config file into our repo.
npx d2-style setup linter/eslint
This gives us a very basic configuration file, which doesn't do much.
module.exports = {
extends: [],
}
From here, if you are using Babel to transpile your modern JavaScript,
you will probably need to use babel-eslint
with ESLint to parse and
lint your code, so let's set that up.
The errors I got looked like:
src/Tabs/ScrollBar.js
Line 10: Parsing error: Unexpected token =
# assuming you already use babel we only need babel-eslint
yarn add --dev babel-eslint
Now update the .eslintrc.js
file to use the new parser:
module.exports = {
parser: 'babel-eslint',
}
And run d2-style
again:
npx d2-style js check --all
119 javascript file(s) checked.
You can install plugins, extend presets, etc. and d2-style
will do its
best to resolve them to the repository's node_modules/
directory. If
it fails to parse your custom .eslintrc.js
file, it will fall back to
its internal configuration files.
If that happens, run the command with the --verbose
flag and you will
see something like:
[DEBUG] Could not init ESLint with local configuration, falling back to
built-in. Error from local cfg:
See configuring ESLint for more information on how to configure ESLint.
Also, please note that if you already have a .eslintrc.*
file,
d2-style
will pick that up according to the priority defined in
ESLint, which might give you surprising results, so make sure you only
have one.
There should be little reason to modify the Prettier configuration, though there is an escape hatch if need be:
npx d2-style setup formatter/prettier
This generates a .prettierrc.js
file for you with the contents:
module.exports = {
...require('@dhis2/cli-style/config/js/prettier.config.js'),
}
From here, you can add your overrides under the base configuration:
module.exports = {
...require('@dhis2/cli-style/config/js/prettier.config.js'),
// overrides go below here
semi: true,
}
Now you can update your .huskyrc.js
line where you call d2-style validate
to:
'pre-commit': 'd2-style validate --prettier-config .prettierrc.js',
Your custom Prettier config will be used to format code when validate
runs.