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

[WIP] aksel stylelint #1973

Merged
merged 78 commits into from
May 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
1018811
rebased
JulianNymark May 10, 2023
0f34404
rebase
JulianNymark May 25, 2023
0c958d6
working stylelint config + test rule
JulianNymark May 11, 2023
3ec4624
merge ideas (sortof)
JulianNymark May 11, 2023
63d77c7
wip commit
JulianNymark May 15, 2023
7637d2f
wip commit
JulianNymark May 15, 2023
4f2c706
wip commit
JulianNymark May 16, 2023
e46d1f1
delete test-rule + add URL to readme section
JulianNymark May 16, 2023
8f76170
flatten json object
JulianNymark May 16, 2023
0c536b9
bundle token files at build time
JulianNymark May 16, 2023
ceb04be
update lock file deps
JulianNymark May 16, 2023
0adc7c4
package distribution & version in error message
JulianNymark May 16, 2023
1c730ea
rule for internal tokens
HalvorHaugan May 22, 2023
92e6edb
rule for class name override
HalvorHaugan May 22, 2023
2de8926
remove config props
HalvorHaugan May 22, 2023
1bef442
fix: emit multiple errors for nodes in postcss-value-parser
JulianNymark May 22, 2023
0c642df
adjust error messages
HalvorHaugan May 22, 2023
ab4a463
some tests
HalvorHaugan May 23, 2023
3020779
final tests
HalvorHaugan May 23, 2023
a693f22
refactor
JulianNymark May 23, 2023
6974711
no more regex
HalvorHaugan May 23, 2023
4ebdd1f
update README.md
JulianNymark May 23, 2023
547278e
update README.md (again)
JulianNymark May 23, 2023
4cf44c8
readme
HalvorHaugan May 23, 2023
9bf5866
readme and usage example for aksel-design-token-exists
JulianNymark May 23, 2023
a0bbde7
move README of rule into top-level README
JulianNymark May 23, 2023
62f41a1
update README
JulianNymark May 23, 2023
42e8ba9
update README
JulianNymark May 23, 2023
132827c
move sources into /src, bookkeeping
JulianNymark May 23, 2023
9da8d0f
add aksel-stylelint to changeset.fixed
JulianNymark May 23, 2023
33f296b
set exports correctly (exposes ./recommended)
JulianNymark May 23, 2023
1d158e9
bookkeeping, cleanup, refactor, remove test files
JulianNymark May 24, 2023
bd18ff6
Update README.md
JulianNymark May 24, 2023
7c1da73
Update README.md
JulianNymark May 24, 2023
9d0c90e
changeset
JulianNymark May 24, 2023
146b916
fix urls
HalvorHaugan May 24, 2023
76f13b3
update test for aksel-design-token-exists to cover all token files
HalvorHaugan May 24, 2023
f9281a9
add more granular error catching
JulianNymark May 24, 2023
cad0c45
cleanup, improve error message
JulianNymark May 25, 2023
7db7144
update tests + fix code that broke tests
JulianNymark May 25, 2023
5897505
add rule: deprecate classes
JulianNymark May 25, 2023
fa4bc69
adjust aksel-design-token-exists
HalvorHaugan May 25, 2023
764e8aa
adjust test for no-deprecated-classes
HalvorHaugan May 25, 2023
c70db3e
refactor design-token-exists
HalvorHaugan May 25, 2023
4fbc220
update README
JulianNymark May 25, 2023
8e35264
:memo: update README
JulianNymark May 26, 2023
14c3ea6
update readme
JulianNymark May 26, 2023
803554b
Merge branch 'main' into aksel-linting
KenAJoh May 26, 2023
143b17d
refactor: split rules into smaller rules
JulianNymark May 26, 2023
6173f2e
Merge branch 'aksel-linting' of github.com:navikt/aksel into aksel-li…
JulianNymark May 26, 2023
a596ad8
Merge branch 'main' into aksel-linting
KenAJoh May 30, 2023
8570890
fix tests (deduplicate from refactor), fix plugin too
JulianNymark May 30, 2023
50d1b55
Merge branch 'aksel-linting' of github.com:navikt/aksel into aksel-li…
JulianNymark May 30, 2023
45b3c05
fix meta name / ruleName -> ruleNamePackage refactor
JulianNymark May 30, 2023
2332a44
set internal dependencies (build time)
JulianNymark May 30, 2023
d2edb66
set internal dependencies (build time)
JulianNymark May 30, 2023
30c61a3
when building stylelint, always pull latest css & token files
JulianNymark May 30, 2023
3660fe5
new lock
JulianNymark May 31, 2023
1a639b4
test cache-busting
JulianNymark May 31, 2023
5aa6a25
ignore some lint rules
JulianNymark May 31, 2023
4c55f95
deduplicate rulename
JulianNymark May 31, 2023
9a7a743
bring back caching in ci.yml
JulianNymark May 31, 2023
6acb8c9
:memo: Oppdatert Package.json docs
KenAJoh May 31, 2023
386ae12
Merge branch 'aksel-linting' of https://github.com/navikt/aksel into …
KenAJoh May 31, 2023
daaeaec
more helpful error messages
JulianNymark May 31, 2023
61ac6d0
Merge branch 'main' into aksel-linting
KenAJoh May 31, 2023
331e7d9
:memo: Updated readme
KenAJoh May 31, 2023
482fa62
:memo: Updated prefixes for rules in readme
KenAJoh May 31, 2023
b41c9b7
Merge branch 'aksel-linting' of github.com:navikt/aksel into aksel-li…
JulianNymark May 31, 2023
d50f570
:memo: Formateringsfeil i readme
KenAJoh May 31, 2023
bd068e6
Merge branch 'aksel-linting' of https://github.com/navikt/aksel into …
KenAJoh May 31, 2023
fcd30ff
refactor ruleNames (shorter and better!)
JulianNymark May 31, 2023
7d40a04
Merge branch 'aksel-linting' of github.com:navikt/aksel into aksel-li…
JulianNymark May 31, 2023
1f43c11
update one more rule name (I forgor)
JulianNymark May 31, 2023
7bb8aa5
refactor names again (must have namespace)
JulianNymark May 31, 2023
e0533b2
:bug: Fikset intern bruk av lint-regler
KenAJoh May 31, 2023
1c8d70f
Merge branch 'main' into aksel-linting
KenAJoh May 31, 2023
b2a0971
:arrow_up: yarn lock sync
KenAJoh May 31, 2023
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
3 changes: 2 additions & 1 deletion .changeset/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
"@navikt/ds-codemod",
"@navikt/aksel-icons",
"@navikt/aksel",
"@navikt/ds-icons"
"@navikt/ds-icons",
"@navikt/aksel-stylelint"
]
],
"linked": [],
Expand Down
5 changes: 5 additions & 0 deletions .changeset/shy-days-walk.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@navikt/aksel-stylelint": minor
---

add stylelint plugin
1 change: 1 addition & 0 deletions @navikt/aksel-stylelint/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/dist
173 changes: 173 additions & 0 deletions @navikt/aksel-stylelint/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
# Aksel stylelint rules & plugins

This stylelint plugin is useful when working with the [Aksel design system](https://aksel.nav.no/).

It is designed to be useful for both _internal_ and _external_ developers, so _everyone_ should install this 🙌.

> **Warning**
> The version of this plugin **_MUST MATCH_** the version of the other design system packages used in your project for the linting to make sense!
> Otherwise you are very likely to get _incorrect_ errors that tell you to use the wrong token names.

# Install

```bash
yarn add -D @navikt/aksel-stylelint
npm install -D @navikt/aksel-stylelint
```

### How to configure

It should be sufficient for most cases to extend the recommended defaults.

```js
"stylelint": {
"extends": [
...
"@navikt/aksel-stylelint/recommended"
],
...
}
```

## aksel/design-token-exists

Makes sure all referenced CSS-variables with prefix `--a-` or `--ac-` exists in Aksels token-collection. As a side-effect Aksel reserves these prefixes for its design-tokens.

❌ Incorrect:

```css
html {
--a-my-own-color-bg-hover: #f2f2f2;
^^^^^^^^^^^^^^^^^^^^^^^^^
background-color: var(--a-my-own-color-bg-hover);
^^^^^^^^^^^^^^^^^^^^^^^^^
}
```

✅ Correct:

```css
html {
background-color: var(--custom-tag-surface-default);
}
```

## aksel/design-token-no-global-override

Makes sure you don't override global level tokens with `--a-`-prefix. Global/Semantic tokens are supposed to be used as is, and not overridden. That is unless you are theming your solution to match a different sub-brands or brands. In those cases we encourage to make all the changes in a single 'config'-file, then disable the rule for that file only.

❌ Incorrect:

```css
div {
--a-surface-default: #f2f2f2;
^^^^^^^^^^^^^^^^^^^
}
```

✅ Correct:

```css
div {
background-color: var(--a-surface-default);
}
```

## aksel/design-token-no-component-reference

Makes sure you don't reference component level tokens with `--ac-`-prefix. Component level tokens are only supposed to be overridden, not referenced.
This is since they are by default not defined, leading to unknown side-effects when referenced incorrectly.

❌ Incorrect:

```css
html {
stroke: var(--ac-button-loader-stroke);
^^^^^^^^^^^^^^^^^^^^^^^^^
}
```

✅ Correct:

```css
html {
--ac-button-loader-stroke: lawngreen;
}
```

## aksel/no-internal-tokens

Disallows use or override of internal Aksel design tokens. Internal tokens are not supposed to be used outside the design system, and may be changed or removed without warning. Be aware that the rule simply checks the prefix of the token, and not if it actually exists in the design system. Even if it doesn't exist, using design system prefixes should be avoided.

❌ Incorrect:

```css
a {
--__ac-some-property: pink;
} ^^^^^^^^^^^^^^^^^^^^
```

```css
a {
color: var(--__ac-some-property);
} ^^^^^^^^^^^^^^^^^^^^
```

✅ Correct:

```css
a {
--some-property: pink;
}
```

```css
a {
color: var(--some-property);
}
```

## aksel/no-class-override

Warns when trying to override design system styling by using class selectors that starts with "navds-" or "navdsi-". Overriding styles in the design system is discouraged. We want to have consistent look and feel across applications. Even if it seems to work fine now, it might break on subsequent updates in the design system.

❌ Incorrect:

```css
.navds-button {
^^^^^^^^^^^^^
}
```

```css
.some-class .navdsi-header {
} ^^^^^^^^^^^^^^
```

✅ Correct:

```css
.some-class {
}
```

## aksel/no-deprecated-classes

Warns when you try to use deprecated class names.

❌ Incorrect:

```css
.navdsi-deprecated-example {
^^^^^^^^^^^^^^^^^^^^^^^^^^
}
```

✅ Correct:

```css
.guaranteed-not-deprecated {
}
```

🐛 Found a bug? https://github.com/navikt/aksel/issues
58 changes: 58 additions & 0 deletions @navikt/aksel-stylelint/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
{
"name": "@navikt/aksel-stylelint",
"version": "3.3.1",
"author": "Aksel | NAV",
"homepage": "https://aksel.nav.no/grunnleggende/kode/stylelint",
"repository": {
"type": "git",
"url": "git+https://github.com/navikt/aksel.git",
"directory": "@navikt/aksel-stylelint"
},
"keywords": [
"aksel",
"stylelint",
"config",
"linting"
],
"publishConfig": {
"access": "public"
},
"license": "MIT",
"main": "./dist/index.js",
KenAJoh marked this conversation as resolved.
Show resolved Hide resolved
"exports": {
"./recommended": "./dist/recommended.js"
},
"files": [
"./dist"
],
"scripts": {
"test": "jest",
"copy-internal-tokens": "node -e \"require('fs').copyFileSync('../internal/css/tokens.json','dist/internal-tokens.json')\"",
"copy-css": "node -e \"require('fs').copyFileSync('../core/css/dist/index.css','dist/index.css')\"",
"copy-tokens": "node -e \"require('fs').copyFileSync('../core/css/tokens.json','dist/tokens.json')\"",
"copy": "yarn copy-internal-tokens && yarn copy-css && yarn copy-tokens",
"build": "tsc -p . && concurrently \"yarn:copy-*\"",
"watch:lint": "tsc --watch -p .",
"dev": "yarn watch:lint"
},
"devDependencies": {
"@navikt/ds-css": "^3.3.1",
"@navikt/ds-tokens": "^3.3.1",
"@types/jest": "^29.0.0",
"concurrently": "7.2.1",
"copyfiles": "2.4.1",
"jest": "^29.0.0",
"jest-preset-stylelint": "^6.1.0",
"stylelint": "^14.8.5",
"typescript": "^4.8.0"
},
"jest": {
"preset": "jest-preset-stylelint",
"testMatch": [
"**/*.test.ts"
],
"transform": {
"^.+\\.ts?$": "ts-jest"
}
}
}
8 changes: 8 additions & 0 deletions @navikt/aksel-stylelint/src/deprecations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
type DeprecatedList = { classes: string[]; message: string }[];

export const deprecations: DeprecatedList = [
{
classes: ["navdsi-deprecated-example", "navdsi-other-deprecated-example"],
message: "Removed in vX.X.X, see documentation [link] for more information",
},
];
8 changes: 8 additions & 0 deletions @navikt/aksel-stylelint/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { createPlugin } from "stylelint";
import { rules } from "./rules";

const rulesPlugins = Object.keys(rules).map((ruleName) => {
return createPlugin(`${ruleName}`, rules[ruleName]);
});

export default rulesPlugins;
11 changes: 11 additions & 0 deletions @navikt/aksel-stylelint/src/recommended.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module.exports = {
plugins: ["."],
rules: {
"aksel/design-token-exists": true,
"aksel/no-internal-tokens": true,
"aksel/no-class-override": [true, { severity: "warning" }],
"aksel/no-deprecated-classes": true,
"aksel/design-token-no-global-override": true,
"aksel/design-token-no-component-reference": true,
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import { getTestRule } from "jest-preset-stylelint";
import rule, { messages } from ".";

getTestRule()({
plugins: ["./dist/index.js"],
ruleName: rule.ruleName,
config: true,

accept: [
{
code: ".foo { --ac-accordion-header-bg-hover: 1px; --ac-header-bg: red; }",
description: "existing '--ac-' tokens overridden",
},
{
code: ".foo { --my-custom-color: var(--a-orange-800); }",
description: "existing '--a-' token referenced",
},
],

reject: [
{
code: ".foo { --a-does-not-exist: 1px }",
description: "attempt to override nonexistent '--a-' token",
warnings: [
{
message: messages.propNotExist({ prop: "--a-does-not-exist" }),
line: 1,
endLine: 1,
column: 8,
endColumn: 26,
},
],
},
{
code: ".foo \n { \n --ac-does-not-exist: 1px; \n }",
description: "attempt to override nonexistent '--ac-' token",
message: messages.propNotExist({ prop: "--ac-does-not-exist" }),
line: 3,
endLine: 3,
column: 2,
endColumn: 21,
},

{
code: ".foo { color: var(--a-bar) }",
description: "attempt to use nonexistent token",
message: messages.valueNotExist({ prop: "color" }, "--a-bar"),
line: 1,
endLine: 1,
column: 19,
endColumn: 26,
},
{
code: ".foo { width: var(--ac-bar, --a-baz) }",
description: "attempt to use two nonexistent tokens in one var()",
warnings: [
{
message: messages.valueNotExist({ prop: "width" }, "--ac-bar"),
line: 1,
endLine: 1,
column: 19,
endColumn: 27,
},
{
message: messages.valueNotExist({ prop: "width" }, "--a-baz"),
line: 1,
endLine: 1,
column: 29,
endColumn: 36,
},
],
},
{
code: ".foo { padding: var(--a-bar) var(--a-baz); }",
description: "attempt to use two nonexistent tokens as separate vars",
warnings: [
{
message: messages.valueNotExist({ prop: "padding" }, "--a-bar"),
line: 1,
endLine: 1,
column: 21,
endColumn: 28,
},
{
message: messages.valueNotExist({ prop: "padding" }, "--a-baz"),
line: 1,
endLine: 1,
column: 34,
endColumn: 41,
},
],
},
],
});
Loading