An opinionated, yet universally applicable JavaScript code style guide
MIT License
Bot releases are visible (Hide)
→ Updated to tmpl
version 0.11.0
, including the versions in between starting from 0.10.0:
This also includes changes required for any linter matches.
→ With the retirement of the Arctic Ice Studio personal & Nord project brand this project also moved to the real-in-person identity “Sven Greb“ both in the context of the repository to the svengreb
GitHub account and the @svengreb
npm package scope.
During this migration the current npm packages @arcticicestudio/eslint-config-base
, @arcticicestudio/eslint-config
and @arcticicestudio/eslint-config-typescript
have been deprecated in favor of the new and upcoming @svengreb/eslint-config-base
, @svengreb/eslint-config
and @svengreb/eslint-config-typescript
packages that will be published afterwards.
Also the visual representation of this style guide through the way too outdated and deprecated GitBook major version 2
has been unpublished and removed. The documentations and references have been updated to use the GitHub repository with the Markdown rendering instead for now until a custom website has been implemented using a modern TechStack like Next.js.
→ Before the used @arcticicestudio/remark-preset-lint
package has been deprecated during the svengreb
GitHub account and @svengreb
npm package scope migration and replaced by the new @svengreb/remark-preset-lint
package.
→ Before the supported ESLint major version for all npm packages of this styleguide was still 7
which has been updated to 8
, released on 2021-10-09.
To update all packages, the official ESLint 8 migration guide has been used to adapt the breaking changes for users, but none of them affected this project so there were no further steps required other than updating the corresponding package (dev
/peer
)dependencies
.
The following plugins have been updated to their latest major & minor versions to match the supported ESLint version:
eslint
— ^7.32.0
→ major version 8
· currently latest version is ^8.39.0
which will be used as minimal requirement.eslint-plugin-prettier
— ^3.4.1
→ major version 4
· currently latest version is 4.2.1
which will be used as minimal requirement.
>=7.28.0 <8.0.0
, Prettier >=2.0.0 <3.0.0
and Node >=12.0.0
.eslint-find-rules
— 3.6.1
→ major version 4
· currently latest version is 4.1.0
which will be used as minimal requirement.
@typescript-eslint/eslint-plugin
— ^4.33.0
→ major version 5
· currently latest version is 5.59.1
which will be used as minimal requirement.
<=10
.<=5
.@typescript-eslint/parser
— ^4.33.0
→ major version 5
· currently latest version is 5.59.1
which will be used as minimal requirement.
<=10
.<=5
.typescript
— ^4.9.5
→ major version 5
· currently latest version is 5.0.4
which will be used as minimal requirement.
<=12
.The full changelog is available in the repository
Published by arcticicestudio over 3 years ago
↠ To run async
code in a React useEffect
Hook the official React Hook FAQ section about how to fetch data recommends and shows in a demo how to define a scoped fat arrow function and run it immediately. Unfortunately this collided with the @typescript/no-floating-promises
rule because the returned Promise
of the called function must not be handled anymore.
useEffect(() => {
const init = async () => {
try {
const data = await fetchData();
setInitialized(isInit);
if (data) initStores(data);
} catch (err) {
handleError(err);
}
};
// This will trigger the "@typescript/no-floating-promises" rule because the returned "Promise" is not handled.
init();
}, [fetchData, handleError, initStores, setInitialized]);
Explicitly disabling the rule for these specific code lines would have been an option, but it is recommended to use the void
operator instead.
// ...
// This will trigger the "no-void" rule because the "void" operator is currently not allowed as a statement.
void init();
// ...
However, the no-void
rule did not allow the void
operator to be used as statement which resulted in this rule to also throw an error.
To resolve both problems, the allowAsStatement
option of the no-void
rule has been enabled.
Also see typescript-eslint/typescript-eslint#1184 where this solution is also recommended by one of the @typescript-eslint
package maintainers.
The full changelog is available in the repository
Published by arcticicestudio over 3 years ago
↠ The remark-preset-lint-arcticicestudio
package has been deprecated during the migration into a monorepo and replaced by the new @arcticicestudio/remark-preset-lint
package. This package also introduced support for remark 13.0.0
which comes with some new features and great improvements.
To migrate to the new package the remark-preset-lint-arcticicestudio
preset has been replaced by the new @arcticicestudio/remark-preset-lint
preset in the .remarkrc.js
file.
↠ As of eslint-config-prettier
version 8.0.0
all configurations have been merged into the prettier
configuration that now includes not just ESLint core rules, but also rules from all plugins.
In #32 the eslint-config-prettier
version was bumped from version v6.0.0 to v8.1.0, but the @arcticicestudio/eslint-config-typescript
package still explicitly extends the prettier/@typescript-eslint
configuration which results in an error when consuming the package.
To fix this problem, the prettier/@typescript-eslint
has been removed entirely from the extend
field, leaving only the all-in-one prettier
configuration.
↠ In #32 the @arcticicestudio/eslint-config-typescript
package migrated to the latest plugin versions and added the override
field to its index to simplify the usage for consumers by removing the need to explicitly define it per project. Unfortunately this resulted in a crash loop when doing so and also blocked users from overriding single rules based on the project needs.
To fix this problem, the override
field has been removed again, leaving it up to the user to define and customize the ESLint configuration for TypeScript to fit the project needs.
↠ TypeScript uses triple-slash directives (single-line comments containing a single XML tag) to define compiler directives. The @arcticicestudio/eslint-config-base
configures the ESLint core rule spaced-comment
and already defines exceptions and comment markers for special use cases, but did not support triple-slash directives. When running eslint --fix
these comments in *.d.ts
files were malformed (///
→ // /
) which resulted in invalid TypeScript syntax.
To support triple-slash directives, the /
marker has been added to the line
field.
Published by arcticicestudio over 3 years ago
↠ ESLint and most of the used plugins released new major versions so trying to use later versions of these plugins as well as ESLint itself caused errors when using npm v7 because peer dependencies are installed automatically now, which is a fantastic change, but also breaks and blocks the usage of the configuration packages due to outdated peerDependencies
like eslint@^6
.
The latest version 7 comes with great features and improvements.
See the official v7 migration guide for all details.
v6.2.0
to v7.23.0
.overrides[].files
are now linted by default which allows to add extensions like *.ts
and *.tsx
to the @arcticicestudio/eslint-config-typescript
without the need to specify this override over and over again in each project.eslint-plugin-node
like documented in #30.
callback-return
→ node/callback-return
global-require
→ node/global-require
handle-callback-err
→ node/handle-callback-err
no-mixed-requires
→ node/no-mixed-requires
no-new-require
→ node/no-new-require
no-path-concat
→ node/no-path-concat
no-process-env
→ node/no-process-env
no-process-exit
→ node/no-process-exit
no-restricted-modules
→ node/no-restricted-modules
no-sync
→ node/no-sync
eslint:recommended
rule set and have ben added to @arcticicestudio/eslint-config-base
with error
level:
@arcticicestudio/eslint-config
v6.0.0
to v8.1.0
. As of version 8.0.0
all rule sets have been merged into the main prettier
set. Therefore the additional prettier/react
set has been removed from the extends
array of the Prettier specific rules.v3.4.0
to v3.6.1
.v2.18.2
to v2.22.1
.v6.2.3
to v6.4.1
.v3.1.0
to v3.3.1
.v7.14.3
to v7.23.1
. This includes new rules and improvements to existing ones:
react/jsx-no-useless-fragment
rule with error
level (introduced in v7.15.0
) that disallows unnecessary fragments.static-variables
option to the react/sort-comp
rule (introduced in v7.15.0
).react/jsx-newline
rule (introduced in v7.22.0
) and disable by default.react/jsx-no-constructed-context-values
rule (introduced in v7.22.0
) and enabled it by default to prevent react contexts from taking non-stable values.
React Context, and all its child nodes and Consumers are rerendered whenever the value prop changes. Because each Javascript object carries its own identity, things like object expressions (
{foo: "bar"}
) or function expressions get a new identity on every run through the component. This makes the context think it has gotten a new object and can cause needless rerenders and unintended consequences.
This can be a pretty large performance hit because not only will it cause the context providers and consumers to rerender with all the elements in its subtree, the processing for the tree scan react does to render the provider and find consumers is also wasted.
enforceDynamicLinks
option with value always
for react/jsx-no-target-blank
rule (introduced in v7.9.0
)react/no-unstable-nested-components
rule and enabled it by default to prevent creating unstable components inside components.
Creating components inside components without memoization leads to unstable components. The nested component and all its children are recreated during each re-render. Given stateful children of the nested component will lose their state on each re-render.
React reconcilation performs element type comparison with reference equality. The reference to the same element changes on each re-render when defining components inside the render block. This leads to complete recreation of the current node and all its children. As a result the virtual DOM has to do extra unnecessary work and possible bugs are introduced.
forbidDefaultForRequired
option with value true
for react/require-default-props
rule (introduced in v7.5.0
)v2.0.0
to v4.2.0
.@arcticicestudio/eslint-config-base
v1.0.8
to v1.0.10
.v3.4.0
to v3.6.1
.v2.18.2
to v2.22.1
.@arcticicestudio/eslint-config-typescript
v2.0.0
to v4.20.0
.v2.0.0
to v4.20.0
.v3.5.3
to v4.2.3
.↠ Migrated the project setup, structure and development workflow from version 0.9.0 of the “tmpl“ template repository.
Additionally specific assets like the repository hero image have been replaced and documentations like the README and GitHub issue/PR templates have been adjusted.
↠ Before eslint-plugin-prettier and its corresponding eslint-config-prettier package were supported by the @arcticicestudio/eslint-config rule preset package. This worked fine for most projects, but also pulled in React specific dependencies like eslint-plugin-react and eslint-plugin-jsx-a11y.
To allow to use Prettier without @arcticicestudio/eslint-config
, the support has been moved into the @arcticicestudio/eslint-config-base
package, including the optional entry point.
↠ Bumped outdated Node.js package dependencies and GitHub actions to their latest versions:
acorn
from 7.0.0 to 7.1.1
eslint-plugin-react-hooks
from 1.7.0
to 2.0.0
.v6.2.0
to v7.23.0
. See #32 and the official v7 migration guide for more details.--ext
option for ESLint tasks — as of ESLint v7, files matched by overrides[].files
are now linted by default which makes it obsolete to explicitly define file extensions like *.js
.v2.0.0
to v3.0.1
.v6.1.0
to v8.1.0
.v3.1.0
to v3.3.1
.v2.18.2
to v2.22.1
.v3.0.4
to v6.0.0
. This also includes some breaking changes that require migrations. Run the official migration CLI to automatically migrate from v4 to v6: npx husky-init && npm exec -- github:typicode/husky-4-to-6 --remove-v4-config
v9.2.3
to v10.5.4
.v1.18.2
to v2.2.1
.v7.0.0
to v9.0.0
.Subtask of arcticicestudio/styleguide-git#9
↠ Adapted to GitHub Flow like documented in detail in the main task issue arcticicestudio/styleguide-git#9.
Subtask of arcticicestudio/styleguide-git#11
↠ Adapted to the default branch renaming from master
to main
like documented in detail in the main task issue arcticicestudio/styleguide-git#11.
The full changelog is available in the repository
Published by arcticicestudio about 5 years ago
@arcticicestudio/eslint-config
React Hooks support and entry point — #17 ⇄ #18 (⊶ 833cc51d)
↠ All React based Arctic Ice Studio projects using at least React version 16.8 that introduced the awesome Hooks. Since this comes with a entire new API that follows new design/usage pattern, the React team created an official „Hooks“ ESLint plugin to help to adhere to the „Rules of Hooks“.
Since the @arcticicestudio/eslint-config
package already includes support for React and „JSX A11Y“, support for Hooks has also been added through a new shareable configuration entry point that
react-hooks
plugin.react-hooks/rules-of-hooks
and react-hooks/exhaustive-deps
rule to error
level.Because Hooks make more use of arrow functions the react/jsx-no-bind
has been adjusted to prevent compatibility problems by allowing setting the ignoreDOMComponents
and allowArrowFunctions
options to true
.
The react/display-name
rule has also been disabled in order to prevent problems due to missing display names for functional components that make use of Hooks instead of being created through a class component.
The new entry point is available as @arcticicestudio/eslint-config/react-hooks
and can be composed with all other available entry points to inherit their rules.
This feature adds the eslint-plugin-react-hooks
package as new peer dependency for @arcticicestudio/eslint-config
.
ESLint TypeScript Configuration Package — #19 ⇄ #20 (⊶ 484c981d)
↠ To support projects build with TypeScript, a new @arcticicestudio/eslint-config-typescript
package has been implemented using the awesome @typescript-eslint project. It mainly extends @typescript-eslint/eslint-plugin
's already provided and recommended configurations in order to adapt best practices:
plugin:@typescript-eslint/eslint-recommended
plugin:@typescript-eslint/recommended
plugin:@typescript-eslint/recommended-requiring-type-checking
The @typescript-eslint/parser
is set as ESLint parser. As of @typescript-eslint/parser
version 2.0.0
(also see typescript-eslint/typescript-eslint#890), the parser will panic when parsing files that are not included within the provided tsconfig(s).
The documentation of the new package contains instructions and a quick setup and usage guide to inform about the required tsconfig
configurations and the corresponding eslintrc
changes.
Next to the support for TypeScript, the package also modifies some React and import related rules in order to prevent conflicts, like the adaption of the .ts
and .tsx
extensions for all JS and JSX files as well as removing .jsx
to force the usage of .tsx
. There are other rules that have been disabled like the check for valid React prop-types
since these and not necessary anymore when working with TypeScript.
The new package provides two entry points, available as @arcticicestudio/eslint-config-typescript
(main) and @arcticicestudio/eslint-config-typescript/prettier
that can both be composed with all other available entry points to inherit their rules.
This package mainly depends on the @typescript-eslint/eslint-plugin@^2.0.0
and @typescript-eslint/parser@^2.0.0
packages as peer dependencies.
From CircleCI to GitHub Actions — #21 ⇄ #22 (⊶ c7d663eb)
↠ The project migrated from CircleCI as CI/CD service to the awesome new GitHub Actions that is smoothly integrated into the GitHub platform and page for a „single-source-of-truth“ developer experience: OPS configurations as code right next to the source code in the repository.
The previous project setup used CircleCI with API version 2.x as CI/CD service. This worked great, but also comes with the disadvantage of being decoupled from the repository.
During GitHub Universe 2018, the awesome new GitHub Actions feature was introduced and launched as closed beta. Luckily Arctic Ice Studio was given access in order to test all the great possibilities. During the GitHub Actions stream „Now with built-in CI/CD!“ (live from GitHub HQ) the Actions update was announced and previewed showing the expansion to use GitHub Actions as CI/CD service described as „fast CI/CD for any OS, any language, and any cloud“.
See the official GitHub Actions documentation for details about setups, features, the configuration API and many more!
The switch from CircleCI to GitHub Actions brought many advantages like a „close-to-the-source“ development pipeline. Having the code and automated pipelines/workflows in one place is worth a lot. This also comes along with the perfect and smooth integrations into the GitHub platform and page itself like status reports on PRs and many more possibilities like the customization and triggering of workflows through webhooks for almost every event that can occur in a repository/issue/PR etc.
To integrate GitHub Actions the previous CircleCI build configuration has been adapted and adjusted. The official starter-workflows were used as inspiration as well as showcase projects like Yarn Berry (Yarn v2) also presented during the announcement livestream.
Next to the starter-workflows
repository the official GitHub Actions documentation was the main source of information to set up the project workflows.
Since GitHub Actions are still in closed/limited public beta, there is no support for SVG badges through shields.io. Anyway, there are (currently undocumented) official badges provided by the GitHub API that are used until Actions goes GA and shields.io implements support for it: https://github.com/{owner}/{repo}/workflows/{workflow_name}/badge.svg
The full changelog is available in the repository
Published by arcticicestudio about 5 years ago
Monorepo with ESLint packages — #8 ⇄ #16 (⊶ ac611f7e)
↠ Resolved the epic by converting the repository into a monorepo and migrating the @arcticicestudio/eslint-config
(previously eslint-config-arcticicestudio
) + @arcticicestudio/eslint-config-base
(previously eslint-config-arcticicestudio-base
) packages!
Previously this repository only contained the actual styleguide documentation while specific projects that implement the guidelines for linters and code style analyzer lived in separate repositories. This was the best approach for modularity and a small and clear code base, but it increased the maintenance overhead by 1(n) since changes to the development workflow or toolbox, general project documentations as well as dependency management required changes in every repository with dedicated tickets/issues and PRs. In particular, Node packages require frequent dependency management due to their fast development cycles to keep up-to-date with the latest package changes like (security) bug fixes.
This styleguide is currently implemented by the @arcticicestudio/eslint-config
(previously eslint-config-arcticicestudio
) and @arcticicestudio/eslint-config-base
(previously eslint-config-arcticicestudio-base
) Node packages that lived in their own repositories. The development workflow was clean using most of GitHub's awesome features like project boards, codeowner assignments, issue & PR automation and so on, but changes to one of them often required actions for the other package too since they are based on each other and they are using the same development tooling and documentation standards.
Actually I'm not a supporter when it comes to monorepos and next to the advantages a monorepo also comes with disadvantages:
packages
) with other modules, commits can now contain changes to multiple code scopes spread over the entire code base.master
branch as well as “empty” changelogs and release notes with placeholder logs that only refer to changes of other modules.Even though there are disadvantages (see above), a monorepo makes sense only for specific project modules thar are slightly coupled and where using dedicated repositories only increases the maintenance overhead when changes must be reflected in multiple modules anyway.
In order to reduce the maintenance overhead both Node packages, @arcticicestudio/eslint-config
(previously eslint-config-arcticicestudio
) and @arcticicestudio/eslint-config-base
(previously eslint-config-arcticicestudio-base
), have been migrated into this repository by adapting to Yarn workspaces since they are slightly dependent on each other anyway. This simplifies the development tooling setup and allows to use a unified documentation base as well as a smoother development and testing workflow.
This change also implies that the root of the repository is now the main package for the entire project setup including shared development dependencies, tools and documentations while the packages only contains specific configurations and (dev)dependencies.
The previous eslint-config-arcticicestudio
and eslint-config-arcticicestudio-base
packages were no scoped packages but suffixed with -arcticicestudio*
. To simplify the naming and improving the usage of user/organization specific packages both packages are now scoped to @arcticicestudio
resulting in the new names @arcticicestudio/eslint-config-base
and @arcticicestudio/eslint-config
. They can be used through ESLint's support for shared configuration with scoped packages.
The previously released public versions have been deprecated using the npm deprecate
command where the provided message points out to migrate to the new scoped packages.
The style guide itself and all packages using a shared/fixed/locked version. This helps all packages to keep in sync and ensure the compatibility with the latest style guide version.
In order to keep up-to-date with the latest project setup for all Arctic Ice Studio projects, the tools and documentations have been integrated and updated through the following tickets:
GitHub issue and pull request templates — #15 (⊶ c25d1efe)
↠ Integrated GitHub's feature to define multiple issue templates while the initial template file is used as a fallback/generic template to link to the specific ones.
Read the GitHub Help article for more details about issue and pull request templates. Also check out how to manually create issue templates, a pull request template. and the guide on how to create the (deprecated) fallback/generic issue template.
General repository and package documentations and metadata — #14 (⊶ be122b12)
↠ The previous project repository documentations were not designed for a monorepo layout and have been be updated including various badges provided by the great shields.io project.
Further documentations about the project architecture and technologies as well as guides for contributions to develop, run and maintain the project stayed within the packages itself.
There are also various places that contained outdated documentations and metadata that have been updated too.
See #14 for more details about what exactly has been updated.
Introducing remark-lint — #5 ⇄ #6 (⊶ fa9af093)
↠ Integrated remark-lint, a linter built on remark, the powerful Markdown processor powered by plugins such as remark-lint.
It is used through remark-cli with remark-preset-lint-arcticicestudio, the custom preset that implements the Arctic ice Studio Markdown Style Guide.
To lint all Markdown sources within the project the lint:md
NPM script has been added that will be picked up by the main lint
script.
Documentation for official ESLint extensible shared configurations — #7 (⊶ 57b8ce03)
↠ Added information about the official @arcticicestudio/eslint-config
and @arcticicestudio/eslint-config-base
extensible shared configurations for ESLint to the documentation.
Git ignore and attribute pattern — #9 (⊶ 8e992407)
↠ Added the .gitattributes
and .gitignore
configuration files to define the pattern.
Git mail mapping — #10 (⊶ db2a43bc)
↠ Added a Git mailmap file to link to in documentations and allow contributors to send mails regarding security issues. This prevents unnecessary overhead of updating all documents when new core team and members and contributors are added and additionally adds the main functionality of the file: Mapping commits when someone uses a different email address.
Introducing Prettier — #11 (⊶ 10253246)
↠ Integrated Prettier, the opinionated code formatter with support for many languages and integrations with most editors. It ensures that all outputted code conforms to a consistent style and provides the best and recommended style configurations of-out-the-box™.
Read #11 for more details about the configuration and setup as well as included plugins.
To format all compatible sources within the project the format:pretty
NPM script has been added that will be picked up by the main format
script.
Introducing lint-staged — #12 (⊶ c21a58a9)
↠ Integrated lint-staged to run linters against staged Git files and prevent adding code that violates any style guide into the code base.
Read #12 for more details about the configuration and setup.
Introducing Husky — #13 (⊶ b4cac34f)
↠ Integrated Husky, the tool that make Git hooks easy and can prevent bad Git commits, pushes and more woof!
Read #13 for more details about the configuration and setup.
The full changelog is available in the repository
Published by arcticicestudio over 6 years ago
Detailed information can be found in the project documentation.
❯ Added the initial style guide with chapters to learn about the comprehensive base rules. (#1 in PR #2, dee0441a)
❯ Added the initial style guide for React specific rules like e.g. Higher-Order Components, the component methods & properties ordering and props. (#3 in PR #4, cee71142)
The full changelog is available in the repository