@monospaced/set-config 0.20.2 → 0.22.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
@@ -2,26 +2,72 @@
2
2
 
3
3
  Shared developer-tooling config for Set. ESLint, Stylelint, Prettier, browserslist presets plus the `--set-*` token catalog for editor autocomplete and tooling — install once, plug in via subpath imports.
4
4
 
5
+ ## Baseline
6
+
7
+ Set targets [Baseline](https://web.dev/baseline) Widely available: features supported in every core browser for at least 30 months. One constant encodes that target and every preset derives from it, so the browserslist query, the esbuild target, and the ESLint and Stylelint Baseline rules can never disagree.
8
+
9
+ ```ts
10
+ import baseline from "@monospaced/set-config/baseline"; // "widely"
11
+ ```
12
+
13
+ - **ESLint** reports JS builtins and Web APIs outside the target as errors, via [`eslint-plugin-baseline-js`](https://github.com/3ru/eslint-plugin-baseline-js). Unsupported JS throws at runtime, so this is a hard floor.
14
+ - **Stylelint** reports CSS properties, values, functions, at-rules and selectors outside the target as errors, via [`stylelint-plugin-use-baseline`](https://github.com/ryo-manba/stylelint-plugin-use-baseline). Unsupported CSS degrades silently where unsupported JS throws, so the preset ignores a short list of progressive enhancements that degrade gracefully. Anything else needs an `@supports` guard or an inline justification:
15
+
16
+ ```css
17
+ /* stylelint-disable-next-line plugin/use-baseline -- Baseline newly available 2025; physical fallback above */
18
+ overflow-block: auto;
19
+ ```
20
+
5
21
  ## ESLint
6
22
 
7
- Flat-config preset that adds Set's import/export sort convention (`simple-import-sort`) for `.mjs` / `.ts` / `.tsx`. Layer it onto your own ESLint baseline — bring your own TypeScript / JSON / JS recommended.
23
+ Two complete flat configs and one layer. `eslint` and `typescript` are peer dependencies: install them alongside.
24
+
25
+ ### Default
26
+
27
+ A complete config for a web project: `@eslint/js` recommended, `typescript-eslint` recommended, `@eslint/json` recommended (`tsconfig*.json` and `.vscode/*.json` are parsed as JSONC, since TypeScript and VS Code accept comments and trailing commas there), browser globals for source files, Node globals for root-level `*.config.*` files and `scripts/`, Set's import sort, and the Baseline rule (off for the Node-run files, where the `engines` range is the support contract). `dist`, `build` and `coverage` are ignored.
8
28
 
9
29
  ```js
10
30
  // eslint.config.mjs
11
31
  import setEslint from "@monospaced/set-config/eslint";
12
32
 
13
33
  export default [
14
- // your TypeScript / JSON / JS configs here
15
34
  ...setEslint,
16
35
  // your local rules / overrides
17
36
  ];
18
37
  ```
19
38
 
20
- `eslint` itself is a peer dependency — install it alongside.
39
+ ### React
40
+
41
+ The default config plus `eslint-plugin-react-hooks` recommended and the `eslint-plugin-react-refresh` Vite config, both at their own defaults.
42
+
43
+ ```js
44
+ // eslint.config.mjs
45
+ import setEslint from "@monospaced/set-config/eslint/react";
46
+
47
+ export default [...setEslint];
48
+ ```
49
+
50
+ ### Rules
51
+
52
+ Only Set's own conventions — import/export sort (`simple-import-sort`) and the Baseline rule (`baseline-js/use-baseline`, see above) — for layering onto a config you already have. Turn the Baseline rule off for code that runs under Node.
53
+
54
+ ```js
55
+ // eslint.config.mjs
56
+ import setRules from "@monospaced/set-config/eslint/rules";
57
+
58
+ export default [
59
+ // your TypeScript / JSON / JS configs here
60
+ ...setRules,
61
+ {
62
+ files: ["**/scripts/**", "**/*.config.{js,mjs,ts}"],
63
+ rules: { "baseline-js/use-baseline": "off" },
64
+ },
65
+ ];
66
+ ```
21
67
 
22
68
  ## Stylelint
23
69
 
24
- Drop-in shareable config — extends `stylelint-config-standard` and layers on Set's CSS authoring discipline: alphabetical property ordering (`stylelint-order`), token-discipline rules (no raw colors, no absolute lengths, no raw time, no `!important`), and logical-CSS enforcement (`stylelint-plugin-logical-css`) so component CSS stays portable across writing modes.
70
+ Drop-in shareable config — extends `stylelint-config-standard` and layers on Set's CSS authoring discipline: alphabetical property ordering (`stylelint-order`), token-discipline rules (no raw colors, no absolute lengths, no raw time, no `!important`), logical-CSS enforcement (`stylelint-plugin-logical-css`) so component CSS stays portable across writing modes, and the Baseline rule (`plugin/use-baseline`, see above).
25
71
 
26
72
  ```js
27
73
  // .stylelintrc.mjs
@@ -78,9 +124,9 @@ Catalog enforcement for `--set-*` references is preserved; non-`--set-` customs
78
124
  import browserslist from "@monospaced/set-config/browserslist";
79
125
  ```
80
126
 
81
- Use the query directly in tools that accept query arrays (for example Autoprefixer `overrideBrowserslist`).
127
+ Use the query directly in tools that accept query arrays (for example Autoprefixer `overrideBrowserslist`, or Lightning CSS via `browserslistToTargets`).
82
128
 
83
- For plain `package.json` `browserslist` fields, use the equivalent query:
129
+ For plain `package.json` `browserslist` fields, use the equivalent query. Autoprefixer, Lightning CSS and anything else built on the `browserslist` package read this field automatically, so it is the single source of truth for a project:
84
130
 
85
131
  ```json
86
132
  {
@@ -88,8 +134,18 @@ For plain `package.json` `browserslist` fields, use the equivalent query:
88
134
  }
89
135
  ```
90
136
 
91
- ## Vite target
137
+ ## Vite targets
138
+
139
+ The esbuild target string and the Lightning CSS targets object, both derived from the Baseline query. `browserslist` and `lightningcss` are optional peer dependencies, needed only for the Lightning CSS export.
92
140
 
93
141
  ```ts
142
+ // vite.config.ts
94
143
  import target from "@monospaced/set-config/browserslist/esbuild";
144
+ import targets from "@monospaced/set-config/browserslist/lightningcss";
145
+ import { defineConfig } from "vite";
146
+
147
+ export default defineConfig({
148
+ build: { cssMinify: "lightningcss", target },
149
+ css: { lightningcss: { targets }, transformer: "lightningcss" },
150
+ });
95
151
  ```
@@ -0,0 +1,3 @@
1
+ declare const baseline: "widely" | "newly";
2
+
3
+ export default baseline;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Set's Baseline availability target. One constant drives every preset that
3
+ * encodes browser support: the browserslist query, the esbuild target, and
4
+ * the ESLint and Stylelint Baseline rules, so they can never drift apart.
5
+ *
6
+ * "widely" means Baseline Widely available: supported in all core browsers
7
+ * for at least 30 months. Switch to "newly" to adopt features sooner.
8
+ *
9
+ * @type {"widely" | "newly"}
10
+ */
11
+ const baseline = "widely";
12
+
13
+ export default baseline;
@@ -1,3 +1,5 @@
1
- const esbuildTarget = "baseline-widely-available";
1
+ import baseline from "../baseline/index.mjs";
2
+
3
+ const esbuildTarget = `baseline-${baseline}-available`;
2
4
 
3
5
  export default esbuildTarget;
@@ -1,3 +1,5 @@
1
- const browserslist = ["baseline widely available"];
1
+ import baseline from "../baseline/index.mjs";
2
+
3
+ const browserslist = [`baseline ${baseline} available`];
2
4
 
3
5
  export default browserslist;
@@ -0,0 +1,5 @@
1
+ import type { Targets } from "lightningcss";
2
+
3
+ declare const lightningcssTargets: Targets;
4
+
5
+ export default lightningcssTargets;
@@ -0,0 +1,8 @@
1
+ import browserslist from "browserslist";
2
+ import { browserslistToTargets } from "lightningcss";
3
+
4
+ import query from "./index.mjs";
5
+
6
+ const lightningcssTargets = browserslistToTargets(browserslist(query));
7
+
8
+ export default lightningcssTargets;
package/eslint/index.mjs CHANGED
@@ -1,13 +1,55 @@
1
- import simpleImportSort from "eslint-plugin-simple-import-sort";
1
+ import js from "@eslint/js";
2
+ import json from "@eslint/json";
3
+ import globals from "globals";
4
+ import tseslint from "typescript-eslint";
5
+
6
+ import setRules from "./rules.mjs";
7
+
8
+ // Files that run under Node rather than in the browser: root-level tool
9
+ // configs and the scripts directory. Anchored to the root so that shipped
10
+ // code such as src/scripts/ or src/theme.config.ts stays browser code.
11
+ const NODE_FILES = ["*.config.{js,cjs,mjs,ts,cts,mts}", "scripts/**"];
12
+
13
+ const off = (names) => Object.fromEntries(names.map((name) => [name, "off"]));
2
14
 
3
15
  const eslintConfig = [
4
16
  {
5
- files: ["**/*.{js,cjs,mjs,jsx,ts,cts,mts,tsx}"],
6
- plugins: { "simple-import-sort": simpleImportSort },
7
- rules: {
8
- "simple-import-sort/imports": "error",
9
- "simple-import-sort/exports": "error",
17
+ ignores: ["**/build/**", "**/coverage/**", "**/dist/**"],
18
+ },
19
+ ...setRules,
20
+ {
21
+ files: ["**/*.json"],
22
+ ...json.configs.recommended,
23
+ language: "json/json",
24
+ },
25
+ {
26
+ // Editor and TypeScript config files allow comments and trailing commas.
27
+ files: ["**/.vscode/*.json", "**/tsconfig*.json"],
28
+ ...json.configs.recommended,
29
+ language: "json/jsonc",
30
+ languageOptions: { allowTrailingCommas: true },
31
+ },
32
+ {
33
+ files: ["**/*.{js,cjs,mjs,jsx}"],
34
+ ...js.configs.recommended,
35
+ languageOptions: { globals: { ...globals.browser } },
36
+ },
37
+ ...tseslint.configs.recommended.map((config) => ({
38
+ ...config,
39
+ files: ["**/*.{ts,cts,mts,tsx}"],
40
+ languageOptions: {
41
+ ...(config.languageOptions ?? {}),
42
+ globals: { ...globals.browser },
43
+ },
44
+ })),
45
+ {
46
+ files: NODE_FILES,
47
+ languageOptions: {
48
+ globals: { ...off(Object.keys(globals.browser)), ...globals.node },
10
49
  },
50
+ // Enabled for every JS and TS file by rules.mjs; Baseline is a browser
51
+ // support contract, and these files run under Node.
52
+ rules: { "baseline-js/use-baseline": "off" },
11
53
  },
12
54
  ];
13
55
 
@@ -0,0 +1,5 @@
1
+ import type { Linter } from "eslint";
2
+
3
+ declare const reactConfig: Linter.Config[];
4
+
5
+ export default reactConfig;
@@ -0,0 +1,18 @@
1
+ import reactHooks from "eslint-plugin-react-hooks";
2
+ import reactRefresh from "eslint-plugin-react-refresh";
3
+
4
+ import eslintConfig from "./index.mjs";
5
+
6
+ const hooks = reactHooks.configs.flat.recommended;
7
+ const refresh = reactRefresh.configs.vite;
8
+
9
+ const reactConfig = [
10
+ ...eslintConfig,
11
+ {
12
+ files: ["**/*.{js,jsx,ts,tsx}"],
13
+ plugins: { ...hooks.plugins, ...refresh.plugins },
14
+ rules: { ...hooks.rules, ...refresh.rules },
15
+ },
16
+ ];
17
+
18
+ export default reactConfig;
@@ -0,0 +1,5 @@
1
+ import type { Linter } from "eslint";
2
+
3
+ declare const rulesConfig: Linter.Config[];
4
+
5
+ export default rulesConfig;
@@ -0,0 +1,23 @@
1
+ import baselineJs from "eslint-plugin-baseline-js";
2
+ import simpleImportSort from "eslint-plugin-simple-import-sort";
3
+
4
+ import baseline from "../baseline/index.mjs";
5
+
6
+ const rulesConfig = [
7
+ {
8
+ files: ["**/*.{js,cjs,mjs,jsx,ts,cts,mts,tsx}"],
9
+ plugins: {
10
+ "baseline-js": baselineJs,
11
+ "simple-import-sort": simpleImportSort,
12
+ },
13
+ rules: {
14
+ "simple-import-sort/imports": "error",
15
+ "simple-import-sort/exports": "error",
16
+ },
17
+ },
18
+ // Baseline: JS builtins and Web APIs available at Set's Baseline level.
19
+ baselineJs.configs.recommended({ available: baseline }),
20
+ baselineJs.configs["recommended-ts"]({ available: baseline }),
21
+ ];
22
+
23
+ export default rulesConfig;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@monospaced/set-config",
3
- "version": "0.20.2",
3
+ "version": "0.22.0",
4
4
  "description": "Shared developer-tooling config for Set. ESLint, Stylelint, Prettier, browserslist presets plus the --set-* token catalog for editor autocomplete and tooling.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -9,6 +9,7 @@
9
9
  },
10
10
  "type": "module",
11
11
  "files": [
12
+ "baseline",
12
13
  "browserslist",
13
14
  "eslint",
14
15
  "stylelint",
@@ -17,6 +18,10 @@
17
18
  ],
18
19
  "types": "./browserslist/index.d.ts",
19
20
  "exports": {
21
+ "./baseline": {
22
+ "types": "./baseline/index.d.ts",
23
+ "default": "./baseline/index.mjs"
24
+ },
20
25
  "./browserslist": {
21
26
  "types": "./browserslist/index.d.ts",
22
27
  "default": "./browserslist/index.mjs"
@@ -25,10 +30,22 @@
25
30
  "types": "./browserslist/esbuild.d.ts",
26
31
  "default": "./browserslist/esbuild.mjs"
27
32
  },
33
+ "./browserslist/lightningcss": {
34
+ "types": "./browserslist/lightningcss.d.ts",
35
+ "default": "./browserslist/lightningcss.mjs"
36
+ },
28
37
  "./eslint": {
29
38
  "types": "./eslint/index.d.ts",
30
39
  "default": "./eslint/index.mjs"
31
40
  },
41
+ "./eslint/react": {
42
+ "types": "./eslint/react.d.ts",
43
+ "default": "./eslint/react.mjs"
44
+ },
45
+ "./eslint/rules": {
46
+ "types": "./eslint/rules.d.ts",
47
+ "default": "./eslint/rules.mjs"
48
+ },
32
49
  "./stylelint": {
33
50
  "types": "./stylelint/index.d.ts",
34
51
  "default": "./stylelint/index.mjs"
@@ -38,17 +55,47 @@
38
55
  "baseline widely available"
39
56
  ],
40
57
  "dependencies": {
58
+ "@eslint/js": "^10.0.1",
59
+ "@eslint/json": "^2.1.1",
60
+ "eslint-plugin-baseline-js": "^0.7.7",
61
+ "eslint-plugin-react-hooks": "^7.1.1",
62
+ "eslint-plugin-react-refresh": "^0.5.7",
41
63
  "eslint-plugin-simple-import-sort": "^13.0.0",
64
+ "globals": "^17.14.0",
42
65
  "stylelint-config-standard": "^40.0.0",
43
66
  "stylelint-declaration-strict-value": "^1.11.1",
44
67
  "stylelint-order": "^8.1.1",
45
- "stylelint-plugin-logical-css": "^2.1.0"
68
+ "stylelint-plugin-logical-css": "^2.1.0",
69
+ "stylelint-plugin-use-baseline": "^1.4.8",
70
+ "typescript-eslint": "^8.72.1"
46
71
  },
47
72
  "peerDependencies": {
73
+ "browserslist": "^4.26.0",
48
74
  "eslint": "^10.0.0",
49
- "stylelint": "^17.0.0"
75
+ "lightningcss": "^1.0.0",
76
+ "stylelint": "^17.0.0",
77
+ "typescript": "^5.0.0"
78
+ },
79
+ "peerDependenciesMeta": {
80
+ "browserslist": {
81
+ "optional": true
82
+ },
83
+ "lightningcss": {
84
+ "optional": true
85
+ },
86
+ "stylelint": {
87
+ "optional": true
88
+ },
89
+ "typescript": {
90
+ "optional": true
91
+ }
92
+ },
93
+ "devDependencies": {
94
+ "eslint": "^10.2.1",
95
+ "typescript": "^5.9.3"
50
96
  },
51
97
  "scripts": {
98
+ "test": "node --test",
52
99
  "verify": "node scripts/verify.mjs"
53
100
  }
54
101
  }
@@ -1,5 +1,6 @@
1
1
  import { createRequire } from "node:module";
2
2
 
3
+ import baseline from "../baseline/index.mjs";
3
4
  import setTokensPlugin from "./plugin-set-tokens.mjs";
4
5
 
5
6
  // Stylelint resolves `extends`/`plugins` strings from the consumer's config
@@ -34,6 +35,7 @@ const stylelintConfig = {
34
35
  plugins: [
35
36
  require.resolve("stylelint-declaration-strict-value"),
36
37
  require.resolve("stylelint-order"),
38
+ require.resolve("stylelint-plugin-use-baseline"),
37
39
  setTokensPlugin,
38
40
  ],
39
41
  rules: {
@@ -75,6 +77,23 @@ const stylelintConfig = {
75
77
  ],
76
78
  "no-descending-specificity": null,
77
79
  "order/properties-alphabetical-order": true,
80
+ // Baseline: CSS features available at Set's Baseline level. The ignores
81
+ // are progressive enhancements that degrade gracefully; prune each once
82
+ // it reaches Widely available.
83
+ "plugin/use-baseline": [
84
+ true,
85
+ {
86
+ available: baseline,
87
+ ignoreProperties: {
88
+ "accent-color": ["/^.+$/"],
89
+ "forced-color-adjust": ["/^.+$/"],
90
+ "/^overscroll-behavior/": ["/^.+$/"],
91
+ resize: ["/^.+$/"],
92
+ "text-wrap": ["balance", "pretty"],
93
+ },
94
+ ignoreSelectors: ["marker", "selection"],
95
+ },
96
+ ],
78
97
  "scale-unlimited/declaration-strict-value": [
79
98
  [
80
99
  "/^border.*radius$/",