stylelint-root-colors 1.0.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,39 +1,39 @@
1
1
  # stylelint-root-colors
2
2
 
3
3
  [![npm version](https://badge.fury.io/js/stylelint-root-colors.svg)](https://www.npmjs.com/package/stylelint-root-colors)
4
- [![Workflow status](https://github.com/SaekiTominaga/stylelint-plugin/actions/workflows/root-colors.yml/badge.svg)](https://github.com/SaekiTominaga/stylelint-plugin/actions/workflows/root-colors.yml)
4
+ [![Workflow status](https://github.com/SaekiTominaga/stylelint-plugin/actions/workflows/package-root-colors.yml/badge.svg)](https://github.com/SaekiTominaga/stylelint-plugin/actions/workflows/package-root-colors.yml)
5
5
 
6
6
  ## Summary
7
7
 
8
- `color` and `background-color` must be specified as a set in the root element.
8
+ It is recommended to use `color` and `background-color` together on the root element.
9
9
 
10
- The root element is `:root { }` or `html { }`.
10
+ Typically, the term <dfn>[root element](https://drafts.csswg.org/css-display-4/#root-element)</dfn> refers to the `<html>` element. However, the [CSS specification](https://www.w3.org/TR/css-backgrounds-3/#body-background) states that <q>It is recommended that authors of HTML documents specify the canvas background using the `BODY` element rather than the `HTML` element</q>. Therefore, this plugin performs linting on the `<body>` element by default.
11
11
 
12
12
  ```css
13
13
  /* 🆖 Do not specify only either `color` or `background-color` in the root element */
14
- :root {
14
+ body {
15
15
  color: #000;
16
16
  }
17
17
 
18
- html,
18
+ body,
19
19
  .foo {
20
20
  background-color: #fff;
21
21
  }
22
22
 
23
23
  /* 🆗 It is good to specify both `color` and `background-color` */
24
- :root {
24
+ body {
25
25
  background-color: #fff;
26
26
  color: #000;
27
27
  }
28
28
 
29
29
  /* 🆗 You may use the `background` short hand */
30
- :root {
30
+ body {
31
31
  background: #fff;
32
32
  color: #000;
33
33
  }
34
34
 
35
- /* 🆗 The `color` and `background-color` are not required */
36
- :root {
35
+ /* 🆗 The `color` and `background-color` are not required, but can be overridden with the `required` option */
36
+ body {
37
37
  }
38
38
 
39
39
  /* 🆗 Except in the root element, only either `color` or `background-color` may be specified */
@@ -44,13 +44,31 @@ html,
44
44
 
45
45
  ## Why?
46
46
 
47
- Browser text and background colors can be changed at the user's discretion.
47
+ The text and background colors in browsers have long been customizable by users.
48
+
49
+ The following screenshot shows a user-defined dark mode configuration in Firefox's “Manage Colors” settings, where the text color is set to white and the background color is set to black.
50
+
51
+ ▼ Internet Explorer 3 (1996) <q>General</q> Settings
52
+
53
+ <img src="assets/setting_ie3.png" alt="Dialog with color selection palettes for Text, Background, Visited Links, and Unvisited Links" width="404" height="448">
54
+
55
+ ▼ Firefox 130 (2024) <q>Colors</q> Settings
56
+
57
+ <img src="assets/setting_firefox130.png" alt="Dialog with color selection palettes for Text, Background, Unvisited Links, and Visited Links" width="1780" height="1386">
58
+
59
+ And around 2024, browsers began implementing forced dark mode.
60
+
61
+ ▼ iOS Vivaldi 7.7 (2025) <q>Appearance & Theme</q> Settings
62
+
63
+ <img src="assets/setting_ios-vivaldi7.7.png" alt="Dialog with a switch control for “Force a dark theme on all websites”" width="2360" height="1575">
48
64
 
49
65
  In this case, if only either `color` or `background-color` is specified in the root element through producer stylesheets, the text will be unreadable in some cases.
50
66
 
51
- In Firefox, you can set text and background colors arbitrarily in the <q>Manage Colors</q>. The screenshot below shows the text in white and the background in black (i.e., dark mode).
67
+ The following screenshot shows a web page with `body { color: black }` displayed after setting iOS's system appearance to <q>Dark</q> and enabling Vivaldi's <q>Force a dark theme on all websites</q>.
52
68
 
53
- ![Dialog with color selection palettes for Text, Background, Unvisited Links, and Visited Links](https://github.com/SaekiTominaga/stylelint-plugin/assets/4138486/da4e43c0-4f33-4bd9-a2a1-709db8295b81)
69
+ iOS Vivaldi 7.7 (2025) Rendering
70
+
71
+ <img src="assets/rendaring_ios-vivaldi7.7.png" alt="The background color is light gray, and the text color is white" width="1640" height="1025">
54
72
 
55
73
  See also [F24 in Techniques for WCAG 2.2](https://www.w3.org/WAI/WCAG22/Techniques/failures/F24).
56
74
 
@@ -64,7 +82,8 @@ export default {
64
82
  'plugin/root-colors': [
65
83
  true,
66
84
  {
67
- root: ['.root'],
85
+ root: ['#root'],
86
+ required: true,
68
87
  },
69
88
  ],
70
89
  },
@@ -73,6 +92,23 @@ export default {
73
92
 
74
93
  ### Rule options
75
94
 
76
- | name | type | description |
77
- | ------ | -------------------- | --------------------------------------------------------------------------------------- |
78
- | `root` | `string \| string[]` | Specifies the selector of the root element. If omitted, it will be `[':root', 'html']`. |
95
+ | name | type | default | description |
96
+ | ---------- | -------------------- | ---------- | ------------------------------------------------- |
97
+ | `root` | `string \| string[]` | `['body']` | Specifies the selector of the root element |
98
+ | `required` | `boolean` | `false` | Make both `color` and `background-color` required |
99
+
100
+ \* Note that setting `required: true` will considered problem when the code is divided into multiple declaration blocks as shown below.
101
+
102
+ ```css
103
+ body {
104
+ background-color: #fff;
105
+ color: #000;
106
+ }
107
+
108
+ .any-selector {
109
+ }
110
+
111
+ body /* considered problem */ {
112
+ line-height: 1.8;
113
+ }
114
+ ```
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import stylelint from 'stylelint';
2
- export declare const ruleName = "plugin/root-colors";
2
+ export declare const ruleName: "plugin/root-colors";
3
3
  export declare const messages: {
4
4
  rejected: (selector: string) => string;
5
5
  };
package/dist/index.js CHANGED
@@ -7,7 +7,7 @@ export const messages = utils.ruleMessages(ruleName, {
7
7
  const meta = {
8
8
  url: 'https://github.com/SaekiTominaga/stylelint-plugin/blob/main/packages/root-colors/README.md',
9
9
  };
10
- const DEFAULT_ROOT_SELECTORS = [':root', 'html'];
10
+ const DEFAULT_ROOT_SELECTORS = ['body'];
11
11
  const ruleFunction = (primary, secondaryOptions) => (root, result) => {
12
12
  const validOptions = utils.validateOptions(result, ruleName, {
13
13
  actual: primary,
@@ -16,21 +16,23 @@ const ruleFunction = (primary, secondaryOptions) => (root, result) => {
16
16
  actual: secondaryOptions,
17
17
  possible: {
18
18
  root: [(value) => typeof value === 'string'],
19
+ required: [(value) => typeof value === 'boolean'],
19
20
  },
20
21
  optional: true,
21
22
  });
22
23
  if (!validOptions) {
23
24
  return;
24
25
  }
25
- let rootSelectors = DEFAULT_ROOT_SELECTORS;
26
- if (secondaryOptions !== undefined) {
27
- if (Array.isArray(secondaryOptions.root)) {
28
- rootSelectors = secondaryOptions.root;
29
- }
30
- else {
31
- rootSelectors = [secondaryOptions.root];
26
+ const rootSelectors = (() => {
27
+ if (secondaryOptions?.root !== undefined) {
28
+ if (Array.isArray(secondaryOptions.root)) {
29
+ return secondaryOptions.root;
30
+ }
31
+ return [secondaryOptions.root];
32
32
  }
33
- }
33
+ return DEFAULT_ROOT_SELECTORS;
34
+ })();
35
+ const required = secondaryOptions?.required ?? false;
34
36
  root.walkRules((ruleNode) => {
35
37
  const { selector, selectors } = ruleNode;
36
38
  if (!selectors.some((selectorPart) => rootSelectors.includes(selectorPart))) {
@@ -55,7 +57,10 @@ const ruleFunction = (primary, secondaryOptions) => (root, result) => {
55
57
  default:
56
58
  }
57
59
  });
58
- if ((colorValue === undefined && backgroundColorValue === undefined) || (colorValue !== undefined && backgroundColorValue !== undefined)) {
60
+ if (required && colorValue !== undefined && backgroundColorValue !== undefined) {
61
+ return;
62
+ }
63
+ if (!required && ((colorValue === undefined && backgroundColorValue === undefined) || (colorValue !== undefined && backgroundColorValue !== undefined))) {
59
64
  return;
60
65
  }
61
66
  utils.report({
package/package.json CHANGED
@@ -1,43 +1,41 @@
1
- {
2
- "name": "stylelint-root-colors",
3
- "version": "1.0.1",
4
- "description": "`color` and `background-color` must be specified as a set in the root element",
5
- "keywords": [
6
- "stylelint-plugin",
7
- "accessibility",
8
- "a11y"
9
- ],
10
- "homepage": "https://github.com/SaekiTominaga/stylelint-plugin#readme",
11
- "bugs": {
12
- "url": "https://github.com/SaekiTominaga/stylelint-plugin/issues"
13
- },
14
- "license": "MIT",
15
- "author": "Saeki Tominaga",
16
- "files": [
17
- "dist/**/*.d.ts",
18
- "!dist/**/*.test.d.ts",
19
- "dist/**/*.js",
20
- "!dist/**/*.test.js"
21
- ],
22
- "type": "module",
23
- "main": "dist/index.js",
24
- "module": "dist/index.js",
25
- "types": "dist/index.d.ts",
26
- "repository": {
27
- "type": "git",
28
- "url": "git+https://github.com/SaekiTominaga/stylelint-plugin.git"
29
- },
30
- "scripts": {
31
- "build": "tsc",
32
- "watch": "tsc -w",
33
- "lint": "eslint src/*.ts",
34
- "pretest": "npm run build",
35
- "test": "node dist/index.test.js"
36
- },
37
- "peerDependencies": {
38
- "stylelint": "^16.0.0"
39
- },
40
- "publishConfig": {
41
- "access": "public"
42
- }
43
- }
1
+ {
2
+ "name": "stylelint-root-colors",
3
+ "version": "2.0.0",
4
+ "description": "It is recommended to use `color` and `background-color` together on the root element",
5
+ "keywords": [
6
+ "stylelint-plugin",
7
+ "accessibility",
8
+ "a11y"
9
+ ],
10
+ "homepage": "https://github.com/SaekiTominaga/stylelint-plugin#readme",
11
+ "bugs": {
12
+ "url": "https://github.com/SaekiTominaga/stylelint-plugin/issues"
13
+ },
14
+ "license": "MIT",
15
+ "author": "Saeki Tominaga",
16
+ "files": [
17
+ "dist/**/*.d.ts",
18
+ "dist/**/*.js"
19
+ ],
20
+ "type": "module",
21
+ "main": "dist/index.js",
22
+ "module": "dist/index.js",
23
+ "types": "dist/index.d.ts",
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "git+https://github.com/SaekiTominaga/stylelint-plugin.git"
27
+ },
28
+ "scripts": {
29
+ "prebuild": "rimraf dist/* -g",
30
+ "build": "tsc",
31
+ "lint": "eslint src/**/*.ts",
32
+ "pretest": "tsc --noEmit",
33
+ "test": "node src/index.test.ts"
34
+ },
35
+ "peerDependencies": {
36
+ "stylelint": "^16.0.0"
37
+ },
38
+ "publishConfig": {
39
+ "access": "public"
40
+ }
41
+ }