@master/eslint-plugin-css 2.0.0-rc.69 → 2.0.0-rc.70
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 +136 -7
- package/dist/create-rule.d.ts +3 -1
- package/dist/functions/filter-collision-classes.cjs +4 -4
- package/dist/functions/filter-collision-classes.mjs +1 -1
- package/dist/index.cjs +2 -2
- package/dist/index.d.ts +9 -16
- package/dist/index.mjs +2 -2
- package/dist/plugin.cjs +1 -1
- package/dist/plugin.mjs +3 -3
- package/dist/rules/class-collision.d.ts +3 -1
- package/dist/rules/class-order.cjs +3 -3
- package/dist/rules/class-order.d.ts +3 -1
- package/dist/rules/class-order.mjs +1 -1
- package/dist/rules/class-validation.d.ts +3 -1
- package/dist/settings-schema.cjs +2 -5
- package/dist/settings-schema.mjs +2 -5
- package/dist/settings.cjs +5 -5
- package/dist/settings.d.ts +3 -2
- package/dist/settings.mjs +2 -2
- package/dist/utils/define-visitors.cjs +46 -12
- package/dist/utils/define-visitors.mjs +46 -12
- package/dist/utils/is-same-or-child-path.cjs +10 -0
- package/dist/utils/is-same-or-child-path.d.ts +1 -0
- package/dist/utils/is-same-or-child-path.mjs +8 -0
- package/dist/utils/master-css.cjs +94 -0
- package/dist/utils/master-css.d.ts +21 -0
- package/dist/utils/master-css.mjs +81 -0
- package/dist/utils/resolve-class-node.cjs +1 -1
- package/dist/utils/resolve-class-node.mjs +1 -1
- package/dist/utils/resolve-context.cjs +61 -23
- package/dist/utils/resolve-context.d.ts +2 -2
- package/dist/utils/resolve-context.mjs +58 -20
- package/dist/utils/with-visit-class-node.cjs +2 -1
- package/dist/utils/with-visit-class-node.mjs +2 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -41,19 +41,148 @@
|
|
|
41
41
|
<img alt="Follow @mastercorg" src="https://img.shields.io/static/v1?label=%20&message=twitter&color=f6f7f8&logo=twitter&style=for-the-badge">
|
|
42
42
|
</picture>
|
|
43
43
|
</a>
|
|
44
|
-
<a aria-label="Github Actions" href="https://github.com/master-co/css/actions/workflows/release.yml">
|
|
44
|
+
<a aria-label="Github Actions" href="https://github.com/master-co/css/actions/workflows/ci-release.yml">
|
|
45
45
|
<picture>
|
|
46
|
-
<source media="(prefers-color-scheme: dark)" srcset="https://img.shields.io/github/actions/workflow/status/master-co/css/release.yml?branch=rc&label=%20&message=twitter&color=212022&logo=githubactions&style=for-the-badge">
|
|
47
|
-
<source media="(prefers-color-scheme: light)" srcset="https://img.shields.io/github/actions/workflow/status/master-co/css/release.yml?branch=rc&label=%20&message=twitter&color=f6f7f8&logo=githubactions&style=for-the-badge&logoColor=%23000">
|
|
48
|
-
<img alt="Github release actions" src="https://img.shields.io/github/actions/workflow/status/master-co/css/release.yml?branch=rc&label=%20&message=twitter&color=f6f7f8&logo=githubactions&style=for-the-badge&logoColor=%23000">
|
|
46
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://img.shields.io/github/actions/workflow/status/master-co/css/ci-release.yml?branch=rc&label=%20&message=twitter&color=212022&logo=githubactions&style=for-the-badge">
|
|
47
|
+
<source media="(prefers-color-scheme: light)" srcset="https://img.shields.io/github/actions/workflow/status/master-co/css/ci-release.yml?branch=rc&label=%20&message=twitter&color=f6f7f8&logo=githubactions&style=for-the-badge&logoColor=%23000">
|
|
48
|
+
<img alt="Github release actions" src="https://img.shields.io/github/actions/workflow/status/master-co/css/ci-release.yml?branch=rc&label=%20&message=twitter&color=f6f7f8&logo=githubactions&style=for-the-badge&logoColor=%23000">
|
|
49
49
|
</picture>
|
|
50
50
|
</a>
|
|
51
51
|
</p>
|
|
52
52
|
|
|
53
53
|
</div>
|
|
54
54
|
|
|
55
|
-
##
|
|
56
|
-
|
|
55
|
+
## Installation
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
npm install -D @master/eslint-plugin-css
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
The recommended config is also available through `@master/eslint-config-css`.
|
|
62
|
+
|
|
63
|
+
## Usage
|
|
64
|
+
|
|
65
|
+
Use ESLint flat configuration:
|
|
66
|
+
|
|
67
|
+
```js
|
|
68
|
+
import css from '@master/eslint-config-css'
|
|
69
|
+
import htmlParser from '@angular-eslint/template-parser'
|
|
70
|
+
import tsParser from '@typescript-eslint/parser'
|
|
71
|
+
|
|
72
|
+
/** @type {import('eslint').Linter.Config[]} */
|
|
73
|
+
export default [
|
|
74
|
+
{
|
|
75
|
+
files: ['**/*.html'],
|
|
76
|
+
languageOptions: {
|
|
77
|
+
parser: htmlParser
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
files: ['**/*.{ts,tsx}'],
|
|
82
|
+
languageOptions: {
|
|
83
|
+
parser: tsParser
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
css,
|
|
87
|
+
{
|
|
88
|
+
rules: {
|
|
89
|
+
'@master/css/class-validation': ['error', {
|
|
90
|
+
disallowUnknownClass: true
|
|
91
|
+
}]
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
]
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Rules
|
|
98
|
+
|
|
99
|
+
### `@master/css/class-order`
|
|
100
|
+
|
|
101
|
+
Enforces a consistent and logical order of classes.
|
|
102
|
+
|
|
103
|
+
```js
|
|
104
|
+
export default [
|
|
105
|
+
{
|
|
106
|
+
rules: {
|
|
107
|
+
'@master/css/class-order': 'warn'
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
]
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### `@master/css/class-validation`
|
|
114
|
+
|
|
115
|
+
Detects Master CSS syntax errors.
|
|
116
|
+
|
|
117
|
+
```js
|
|
118
|
+
export default [
|
|
119
|
+
{
|
|
120
|
+
rules: {
|
|
121
|
+
'@master/css/class-validation': 'error'
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
]
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Set `disallowUnknownClass: true` to reject classes that do not match the active manifest:
|
|
128
|
+
|
|
129
|
+
```js
|
|
130
|
+
export default [
|
|
131
|
+
{
|
|
132
|
+
rules: {
|
|
133
|
+
'@master/css/class-validation': ['error', {
|
|
134
|
+
disallowUnknownClass: true
|
|
135
|
+
}]
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
]
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### `@master/css/class-collision`
|
|
142
|
+
|
|
143
|
+
Detects classes that emit the same CSS declaration.
|
|
144
|
+
|
|
145
|
+
```js
|
|
146
|
+
export default [
|
|
147
|
+
{
|
|
148
|
+
rules: {
|
|
149
|
+
'@master/css/class-collision': 'warn'
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
]
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## Settings
|
|
156
|
+
|
|
157
|
+
Settings live under the `@master/css` settings key:
|
|
158
|
+
|
|
159
|
+
```js
|
|
160
|
+
export default [
|
|
161
|
+
{
|
|
162
|
+
settings: {
|
|
163
|
+
'@master/css': {
|
|
164
|
+
classAttributes: ['class', 'className'],
|
|
165
|
+
classFunctions: ['clsx', 'classList.add'],
|
|
166
|
+
classDeclarations: ['classes'],
|
|
167
|
+
ignoredKeys: ['compoundVariants', 'defaultVariants'],
|
|
168
|
+
manifest
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
]
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
| Setting | Type | Description |
|
|
176
|
+
| --- | --- | --- |
|
|
177
|
+
| `classAttributes` | `string[]` | Element attributes containing class strings. |
|
|
178
|
+
| `classFunctions` | `string[]` | Function names whose arguments should be checked. |
|
|
179
|
+
| `classDeclarations` | `string[]` | Variable/member names whose declarations should be checked. |
|
|
180
|
+
| `ignoredKeys` | `string[]` | Object keys ignored during checking. Defaults include variant metadata keys. |
|
|
181
|
+
| `manifest` | `MasterCSSManifest` | Explicit compiled manifest. By default, ESLint loads the project CSS entry discovered from the current working directory. |
|
|
182
|
+
|
|
183
|
+
## Related docs
|
|
184
|
+
|
|
185
|
+
See the [code linting guide](https://rc.css.master.co/guide/code-linting) for setup guides across frameworks and editors.
|
|
57
186
|
|
|
58
187
|
## Credits
|
|
59
|
-
This plugin is heavily inspired by the awesome [eslint-plugin-tailwindcss](https://github.com/francoismassart/eslint-plugin-tailwindcss). We want to thank for their initial work, which served as the foundation for this project. While significant modifications have been made, the core ideas and concepts from A Plugin have been instrumental in developing this plugin.
|
|
188
|
+
This plugin is heavily inspired by the awesome [eslint-plugin-tailwindcss](https://github.com/francoismassart/eslint-plugin-tailwindcss). We want to thank for their initial work, which served as the foundation for this project. While significant modifications have been made, the core ideas and concepts from A Plugin have been instrumental in developing this plugin.
|
package/dist/create-rule.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import { ESLintUtils } from '@typescript-eslint/utils';
|
|
2
|
-
declare const _default: <Options extends readonly unknown[], MessageIds extends string>({ meta, name, ...rule }: Readonly<ESLintUtils.RuleWithMetaAndName<Options, MessageIds, unknown>>) => ESLintUtils.RuleModule<MessageIds, Options, unknown, ESLintUtils.RuleListener
|
|
2
|
+
declare const _default: <Options extends readonly unknown[], MessageIds extends string>({ meta, name, ...rule }: Readonly<ESLintUtils.RuleWithMetaAndName<Options, MessageIds, unknown>>) => ESLintUtils.RuleModule<MessageIds, Options, unknown, ESLintUtils.RuleListener> & {
|
|
3
|
+
name: string;
|
|
4
|
+
};
|
|
3
5
|
export default _default;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var cssValidator = require('@master/css-validator');
|
|
4
|
-
var
|
|
4
|
+
var masterCss = require('../utils/master-css.cjs');
|
|
5
5
|
|
|
6
|
-
function filterCollisionClasses(classNames, css
|
|
7
|
-
const validRules = classNames.map((eachClassName)=>cssValidator.generateValidRules(eachClassName, css
|
|
6
|
+
function filterCollisionClasses(classNames, css) {
|
|
7
|
+
const validRules = classNames.map((eachClassName)=>cssValidator.generateValidRules(eachClassName, css)[0]).filter(Boolean);
|
|
8
8
|
const collisionClassesRecord = {};
|
|
9
9
|
for(let i = 0; i < classNames.length; i++){
|
|
10
10
|
const className = classNames[i];
|
|
@@ -14,7 +14,7 @@ function filterCollisionClasses(classNames, css$1) {
|
|
|
14
14
|
for(let j = 0; j < classNames.length; j++){
|
|
15
15
|
const compareClassName = classNames[j];
|
|
16
16
|
const compareRule = validRules.find((eachValidRule)=>eachValidRule.name === compareClassName);
|
|
17
|
-
if (i !== j && compareRule &&
|
|
17
|
+
if (i !== j && compareRule && masterCss.equalDeclarations(rule.declarations, compareRule.declarations) && masterCss.equalVariants(rule, compareRule)) {
|
|
18
18
|
collisionClasses.push(compareClassName);
|
|
19
19
|
}
|
|
20
20
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { generateValidRules } from '@master/css-validator';
|
|
2
|
-
import { equalDeclarations, equalVariants } from '
|
|
2
|
+
import { equalDeclarations, equalVariants } from '../utils/master-css.mjs';
|
|
3
3
|
|
|
4
4
|
function filterCollisionClasses(classNames, css) {
|
|
5
5
|
const validRules = classNames.map((eachClassName)=>generateValidRules(eachClassName, css)[0]).filter(Boolean);
|
package/dist/index.cjs
CHANGED
|
@@ -6,7 +6,7 @@ var base = require('./configs/base.cjs');
|
|
|
6
6
|
var recommended = require('./configs/recommended.cjs');
|
|
7
7
|
var plugin = require('./plugin.cjs');
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
const masterCSSPlugin = {
|
|
10
10
|
...plugin,
|
|
11
11
|
configs: {
|
|
12
12
|
legacy,
|
|
@@ -16,4 +16,4 @@ var index = {
|
|
|
16
16
|
settings
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
-
module.exports =
|
|
19
|
+
module.exports = masterCSSPlugin;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,19 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
import settings from './settings';
|
|
2
|
+
import type { Linter } from 'eslint';
|
|
3
|
+
import type { TSESLint } from '@typescript-eslint/utils';
|
|
4
|
+
declare const masterCSSPlugin: Omit<TSESLint.Linter.Plugin, 'configs'> & {
|
|
2
5
|
configs: {
|
|
3
|
-
legacy:
|
|
4
|
-
base:
|
|
5
|
-
recommended:
|
|
6
|
+
legacy: unknown;
|
|
7
|
+
base: Linter.Config;
|
|
8
|
+
recommended: Linter.Config;
|
|
6
9
|
};
|
|
7
|
-
settings:
|
|
8
|
-
classAttributes: string[];
|
|
9
|
-
classFunctions: string[];
|
|
10
|
-
classDeclarations: string[];
|
|
11
|
-
ignoredKeys: string[];
|
|
12
|
-
config: string;
|
|
13
|
-
};
|
|
14
|
-
environments?: Record<string, import("@typescript-eslint/utils/ts-eslint").Linter.Environment>;
|
|
15
|
-
meta?: import("@typescript-eslint/utils/ts-eslint").Linter.PluginMeta;
|
|
16
|
-
processors?: Record<string, import("@typescript-eslint/utils/ts-eslint").Processor.ProcessorModule>;
|
|
17
|
-
rules?: import("@typescript-eslint/utils/ts-eslint").Linter.LegacyPluginRules;
|
|
10
|
+
settings: typeof settings;
|
|
18
11
|
};
|
|
19
|
-
export default
|
|
12
|
+
export default masterCSSPlugin;
|
package/dist/index.mjs
CHANGED
|
@@ -4,7 +4,7 @@ import base from './configs/base.mjs';
|
|
|
4
4
|
import recommended from './configs/recommended.mjs';
|
|
5
5
|
import plugin from './plugin.mjs';
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
const masterCSSPlugin = {
|
|
8
8
|
...plugin,
|
|
9
9
|
configs: {
|
|
10
10
|
legacy,
|
|
@@ -14,4 +14,4 @@ var index = {
|
|
|
14
14
|
settings
|
|
15
15
|
};
|
|
16
16
|
|
|
17
|
-
export {
|
|
17
|
+
export { masterCSSPlugin as default };
|
package/dist/plugin.cjs
CHANGED
|
@@ -10,7 +10,7 @@ var path = require('path');
|
|
|
10
10
|
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
11
11
|
const __filename$1 = url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('plugin.cjs', document.baseURI).href)));
|
|
12
12
|
const __dirname$1 = path.dirname(__filename$1);
|
|
13
|
-
const pkg = JSON.parse(fs.readFileSync(path.resolve(__dirname$1, '
|
|
13
|
+
const pkg = JSON.parse(fs.readFileSync(path.resolve(__dirname$1, '..', 'package.json'), 'utf-8'));
|
|
14
14
|
const plugin = {
|
|
15
15
|
meta: {
|
|
16
16
|
name: pkg.name,
|
package/dist/plugin.mjs
CHANGED
|
@@ -5,9 +5,9 @@ import { readFileSync } from 'fs';
|
|
|
5
5
|
import { fileURLToPath } from 'url';
|
|
6
6
|
import { dirname, resolve } from 'path';
|
|
7
7
|
|
|
8
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
-
const __dirname = dirname(__filename);
|
|
10
|
-
const pkg = JSON.parse(readFileSync(resolve(__dirname, '
|
|
8
|
+
const __filename$1 = fileURLToPath(import.meta.url);
|
|
9
|
+
const __dirname$1 = dirname(__filename$1);
|
|
10
|
+
const pkg = JSON.parse(readFileSync(resolve(__dirname$1, '..', 'package.json'), 'utf-8'));
|
|
11
11
|
const plugin = {
|
|
12
12
|
meta: {
|
|
13
13
|
name: pkg.name,
|
|
@@ -1,2 +1,4 @@
|
|
|
1
|
-
declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<"collisionClass", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener
|
|
1
|
+
declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<"collisionClass", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
2
|
+
name: string;
|
|
3
|
+
};
|
|
2
4
|
export default _default;
|
|
@@ -4,7 +4,7 @@ var defineVisitors = require('../utils/define-visitors.cjs');
|
|
|
4
4
|
var resolveContext = require('../utils/resolve-context.cjs');
|
|
5
5
|
var createRule = require('../create-rule.cjs');
|
|
6
6
|
var settingsSchema = require('../settings-schema.cjs');
|
|
7
|
-
var
|
|
7
|
+
var masterCss = require('../utils/master-css.cjs');
|
|
8
8
|
|
|
9
9
|
var classOrder = createRule({
|
|
10
10
|
name: 'consistent-class-order',
|
|
@@ -23,14 +23,14 @@ var classOrder = createRule({
|
|
|
23
23
|
},
|
|
24
24
|
defaultOptions: [],
|
|
25
25
|
create: function(context) {
|
|
26
|
-
const { settings, css
|
|
26
|
+
const { settings, css } = resolveContext(context);
|
|
27
27
|
const { sourceCode } = context;
|
|
28
28
|
return defineVisitors({
|
|
29
29
|
context,
|
|
30
30
|
settings
|
|
31
31
|
}, (node, { raw, start, end, nodes, classValueRawMap, classValues })=>{
|
|
32
32
|
if (nodes.length <= 1) return;
|
|
33
|
-
let orderedClasses =
|
|
33
|
+
let orderedClasses = masterCss.sortReadableClasses(classValues, css);
|
|
34
34
|
let orderedRaw = nodes.map((eachNode, i)=>{
|
|
35
35
|
if (eachNode.type === 'class') {
|
|
36
36
|
const value = orderedClasses.shift();
|
|
@@ -1,2 +1,4 @@
|
|
|
1
|
-
declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<"invalidClassOrder", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener
|
|
1
|
+
declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<"invalidClassOrder", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
2
|
+
name: string;
|
|
3
|
+
};
|
|
2
4
|
export default _default;
|
|
@@ -2,7 +2,7 @@ import defineVisitors from '../utils/define-visitors.mjs';
|
|
|
2
2
|
import resolveContext from '../utils/resolve-context.mjs';
|
|
3
3
|
import createRule from '../create-rule.mjs';
|
|
4
4
|
import settingsSchema from '../settings-schema.mjs';
|
|
5
|
-
import { sortReadableClasses } from '
|
|
5
|
+
import { sortReadableClasses } from '../utils/master-css.mjs';
|
|
6
6
|
|
|
7
7
|
var classOrder = createRule({
|
|
8
8
|
name: 'consistent-class-order',
|
|
@@ -1,2 +1,4 @@
|
|
|
1
|
-
declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<"invalidClass" | "disallowUnknownClass", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener
|
|
1
|
+
declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<"invalidClass" | "disallowUnknownClass", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
2
|
+
name: string;
|
|
3
|
+
};
|
|
2
4
|
export default _default;
|
package/dist/settings-schema.cjs
CHANGED
package/dist/settings-schema.mjs
CHANGED
package/dist/settings.cjs
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var masterCss = require('./utils/master-css.cjs');
|
|
4
4
|
|
|
5
5
|
const settings = {
|
|
6
|
-
classAttributes:
|
|
7
|
-
classFunctions:
|
|
8
|
-
classDeclarations:
|
|
6
|
+
classAttributes: masterCss.CLASS_ATTRIBUTES,
|
|
7
|
+
classFunctions: masterCss.CLASS_FUNCTIONS,
|
|
8
|
+
classDeclarations: masterCss.CLASS_DECLARATIONS,
|
|
9
9
|
ignoredKeys: [
|
|
10
10
|
'compoundVariants',
|
|
11
11
|
'defaultVariants'
|
|
12
12
|
],
|
|
13
|
-
|
|
13
|
+
manifest: undefined
|
|
14
14
|
};
|
|
15
15
|
|
|
16
16
|
module.exports = settings;
|
package/dist/settings.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { type MasterCSSManifest } from './utils/master-css';
|
|
1
2
|
declare const settings: {
|
|
2
3
|
classAttributes: string[];
|
|
3
4
|
classFunctions: string[];
|
|
4
5
|
classDeclarations: string[];
|
|
5
6
|
ignoredKeys: string[];
|
|
6
|
-
|
|
7
|
+
manifest: any;
|
|
7
8
|
};
|
|
8
9
|
export default settings;
|
|
9
10
|
export interface Settings {
|
|
@@ -11,5 +12,5 @@ export interface Settings {
|
|
|
11
12
|
classFunctions?: string[];
|
|
12
13
|
classDeclarations?: string[];
|
|
13
14
|
ignoredKeys: string[];
|
|
14
|
-
|
|
15
|
+
manifest?: MasterCSSManifest;
|
|
15
16
|
}
|
package/dist/settings.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CLASS_DECLARATIONS, CLASS_FUNCTIONS, CLASS_ATTRIBUTES } from '
|
|
1
|
+
import { CLASS_DECLARATIONS, CLASS_FUNCTIONS, CLASS_ATTRIBUTES } from './utils/master-css.mjs';
|
|
2
2
|
|
|
3
3
|
const settings = {
|
|
4
4
|
classAttributes: CLASS_ATTRIBUTES,
|
|
@@ -8,7 +8,7 @@ const settings = {
|
|
|
8
8
|
'compoundVariants',
|
|
9
9
|
'defaultVariants'
|
|
10
10
|
],
|
|
11
|
-
|
|
11
|
+
manifest: undefined
|
|
12
12
|
};
|
|
13
13
|
|
|
14
14
|
export { settings as default };
|
|
@@ -6,18 +6,49 @@ function defineVisitors({ context, settings }, visitNode) {
|
|
|
6
6
|
const classAttributeRegex = new RegExp(`^(?:${settings.classAttributes.join('|')})$`);
|
|
7
7
|
const classFunctionsRegex = new RegExp(`^(?:${settings.classFunctions.join('|')})`);
|
|
8
8
|
const classDeclarationsRegex = new RegExp(`^(?:${settings.classDeclarations.join('|')})$`);
|
|
9
|
-
const
|
|
10
|
-
|
|
9
|
+
const visitClassNode = withVisitClassNode(visitNode, context);
|
|
10
|
+
const getStaticName = (node)=>{
|
|
11
|
+
if (!node) return;
|
|
12
|
+
if (node.type === 'Identifier') return node.name;
|
|
13
|
+
if (node.type === 'Literal' && typeof node.value === 'string') return node.value;
|
|
14
|
+
};
|
|
15
|
+
const getMemberExpressionName = (node)=>{
|
|
16
|
+
if (!node || node.type !== 'MemberExpression') return;
|
|
17
|
+
const objectName = getStaticName(node.object);
|
|
18
|
+
const propertyName = getStaticName(node.property);
|
|
19
|
+
if (!objectName || !propertyName) return;
|
|
20
|
+
return `${objectName}.${propertyName}`;
|
|
21
|
+
};
|
|
22
|
+
const getCalleeName = (node)=>{
|
|
11
23
|
const calleeNode = node.callee || node.tag;
|
|
12
|
-
|
|
13
|
-
|
|
24
|
+
return getStaticName(calleeNode) || getMemberExpressionName(calleeNode);
|
|
25
|
+
};
|
|
26
|
+
const allowCalleeNode = (node)=>{
|
|
27
|
+
const calleeName = getCalleeName(node);
|
|
28
|
+
return calleeName ? classFunctionsRegex.test(calleeName) : false;
|
|
29
|
+
};
|
|
30
|
+
const getPropertyName = (prop)=>getStaticName(prop.key);
|
|
31
|
+
const visitUtilityDefinitions = (node)=>{
|
|
32
|
+
if (!node) return;
|
|
33
|
+
if (node.type === 'ArrayExpression') {
|
|
34
|
+
node.elements.forEach((element)=>{
|
|
35
|
+
if (!element || element.type === 'ObjectExpression') return;
|
|
36
|
+
visitClassNode(element);
|
|
37
|
+
});
|
|
38
|
+
return;
|
|
14
39
|
}
|
|
15
|
-
if (
|
|
16
|
-
|
|
40
|
+
if (node.type !== 'ObjectExpression') {
|
|
41
|
+
visitClassNode(node);
|
|
42
|
+
return;
|
|
17
43
|
}
|
|
18
|
-
return classFunctionsRegex.test(calleeName);
|
|
19
44
|
};
|
|
20
|
-
const
|
|
45
|
+
const visitClassDeclarationNode = (name, node)=>{
|
|
46
|
+
if (name !== 'utilities') {
|
|
47
|
+
visitClassNode(node);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
visitUtilityDefinitions(node);
|
|
51
|
+
};
|
|
21
52
|
const CallExpression = function(node) {
|
|
22
53
|
if (!allowCalleeNode(node)) return;
|
|
23
54
|
node.arguments.forEach((node)=>{
|
|
@@ -51,14 +82,17 @@ function defineVisitors({ context, settings }, visitNode) {
|
|
|
51
82
|
VariableDeclaration: function(node) {
|
|
52
83
|
node.declarations.forEach((decl)=>{
|
|
53
84
|
if (decl.id.type === 'Identifier' && classDeclarationsRegex.test(decl.id.name)) {
|
|
54
|
-
|
|
85
|
+
visitClassDeclarationNode(decl.id.name, decl.init);
|
|
55
86
|
}
|
|
56
87
|
});
|
|
57
88
|
},
|
|
58
89
|
ObjectExpression: function(node) {
|
|
59
90
|
node.properties.forEach((prop)=>{
|
|
60
|
-
if (prop.type === 'Property'
|
|
61
|
-
|
|
91
|
+
if (prop.type === 'Property') {
|
|
92
|
+
const propName = getPropertyName(prop);
|
|
93
|
+
if (typeof propName === 'string' && classDeclarationsRegex.test(propName)) {
|
|
94
|
+
visitClassDeclarationNode(propName, prop.value);
|
|
95
|
+
}
|
|
62
96
|
}
|
|
63
97
|
});
|
|
64
98
|
}
|
|
@@ -66,7 +100,7 @@ function defineVisitors({ context, settings }, visitNode) {
|
|
|
66
100
|
const templateBodyVisitor = {
|
|
67
101
|
CallExpression,
|
|
68
102
|
VAttribute: function(node) {
|
|
69
|
-
const name = node.key
|
|
103
|
+
const name = node.key?.argument?.name || node.key?.name;
|
|
70
104
|
if (!name || !classAttributeRegex.test(name)) return;
|
|
71
105
|
if (node.value && node.value.type === 'VLiteral') {
|
|
72
106
|
visitClassNode(node.value);
|
|
@@ -4,18 +4,49 @@ function defineVisitors({ context, settings }, visitNode) {
|
|
|
4
4
|
const classAttributeRegex = new RegExp(`^(?:${settings.classAttributes.join('|')})$`);
|
|
5
5
|
const classFunctionsRegex = new RegExp(`^(?:${settings.classFunctions.join('|')})`);
|
|
6
6
|
const classDeclarationsRegex = new RegExp(`^(?:${settings.classDeclarations.join('|')})$`);
|
|
7
|
-
const
|
|
8
|
-
|
|
7
|
+
const visitClassNode = withVisitClassNode(visitNode, context);
|
|
8
|
+
const getStaticName = (node)=>{
|
|
9
|
+
if (!node) return;
|
|
10
|
+
if (node.type === 'Identifier') return node.name;
|
|
11
|
+
if (node.type === 'Literal' && typeof node.value === 'string') return node.value;
|
|
12
|
+
};
|
|
13
|
+
const getMemberExpressionName = (node)=>{
|
|
14
|
+
if (!node || node.type !== 'MemberExpression') return;
|
|
15
|
+
const objectName = getStaticName(node.object);
|
|
16
|
+
const propertyName = getStaticName(node.property);
|
|
17
|
+
if (!objectName || !propertyName) return;
|
|
18
|
+
return `${objectName}.${propertyName}`;
|
|
19
|
+
};
|
|
20
|
+
const getCalleeName = (node)=>{
|
|
9
21
|
const calleeNode = node.callee || node.tag;
|
|
10
|
-
|
|
11
|
-
|
|
22
|
+
return getStaticName(calleeNode) || getMemberExpressionName(calleeNode);
|
|
23
|
+
};
|
|
24
|
+
const allowCalleeNode = (node)=>{
|
|
25
|
+
const calleeName = getCalleeName(node);
|
|
26
|
+
return calleeName ? classFunctionsRegex.test(calleeName) : false;
|
|
27
|
+
};
|
|
28
|
+
const getPropertyName = (prop)=>getStaticName(prop.key);
|
|
29
|
+
const visitUtilityDefinitions = (node)=>{
|
|
30
|
+
if (!node) return;
|
|
31
|
+
if (node.type === 'ArrayExpression') {
|
|
32
|
+
node.elements.forEach((element)=>{
|
|
33
|
+
if (!element || element.type === 'ObjectExpression') return;
|
|
34
|
+
visitClassNode(element);
|
|
35
|
+
});
|
|
36
|
+
return;
|
|
12
37
|
}
|
|
13
|
-
if (
|
|
14
|
-
|
|
38
|
+
if (node.type !== 'ObjectExpression') {
|
|
39
|
+
visitClassNode(node);
|
|
40
|
+
return;
|
|
15
41
|
}
|
|
16
|
-
return classFunctionsRegex.test(calleeName);
|
|
17
42
|
};
|
|
18
|
-
const
|
|
43
|
+
const visitClassDeclarationNode = (name, node)=>{
|
|
44
|
+
if (name !== 'utilities') {
|
|
45
|
+
visitClassNode(node);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
visitUtilityDefinitions(node);
|
|
49
|
+
};
|
|
19
50
|
const CallExpression = function(node) {
|
|
20
51
|
if (!allowCalleeNode(node)) return;
|
|
21
52
|
node.arguments.forEach((node)=>{
|
|
@@ -49,14 +80,17 @@ function defineVisitors({ context, settings }, visitNode) {
|
|
|
49
80
|
VariableDeclaration: function(node) {
|
|
50
81
|
node.declarations.forEach((decl)=>{
|
|
51
82
|
if (decl.id.type === 'Identifier' && classDeclarationsRegex.test(decl.id.name)) {
|
|
52
|
-
|
|
83
|
+
visitClassDeclarationNode(decl.id.name, decl.init);
|
|
53
84
|
}
|
|
54
85
|
});
|
|
55
86
|
},
|
|
56
87
|
ObjectExpression: function(node) {
|
|
57
88
|
node.properties.forEach((prop)=>{
|
|
58
|
-
if (prop.type === 'Property'
|
|
59
|
-
|
|
89
|
+
if (prop.type === 'Property') {
|
|
90
|
+
const propName = getPropertyName(prop);
|
|
91
|
+
if (typeof propName === 'string' && classDeclarationsRegex.test(propName)) {
|
|
92
|
+
visitClassDeclarationNode(propName, prop.value);
|
|
93
|
+
}
|
|
60
94
|
}
|
|
61
95
|
});
|
|
62
96
|
}
|
|
@@ -64,7 +98,7 @@ function defineVisitors({ context, settings }, visitNode) {
|
|
|
64
98
|
const templateBodyVisitor = {
|
|
65
99
|
CallExpression,
|
|
66
100
|
VAttribute: function(node) {
|
|
67
|
-
const name = node.key
|
|
101
|
+
const name = node.key?.argument?.name || node.key?.name;
|
|
68
102
|
if (!name || !classAttributeRegex.test(name)) return;
|
|
69
103
|
if (node.value && node.value.type === 'VLiteral') {
|
|
70
104
|
visitClassNode(node.value);
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var path = require('node:path');
|
|
4
|
+
|
|
5
|
+
function isSameOrChildPath(parentPath, childPath) {
|
|
6
|
+
const relativePath = path.relative(parentPath, childPath);
|
|
7
|
+
return relativePath === '' || !!relativePath && relativePath !== '..' && !relativePath.startsWith(`..${path.sep}`) && !path.isAbsolute(relativePath);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
module.exports = isSameOrChildPath;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function isSameOrChildPath(parentPath: string, childPath: string): boolean;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
|
|
3
|
+
function isSameOrChildPath(parentPath, childPath) {
|
|
4
|
+
const relativePath = path.relative(parentPath, childPath);
|
|
5
|
+
return relativePath === '' || !!relativePath && relativePath !== '..' && !relativePath.startsWith(`..${path.sep}`) && !path.isAbsolute(relativePath);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export { isSameOrChildPath as default };
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var css = require('@master/css');
|
|
4
|
+
var cssValidator = require('@master/css-validator');
|
|
5
|
+
var node_module = require('node:module');
|
|
6
|
+
var UtilityType = require('@master/css-schema/utility-type');
|
|
7
|
+
|
|
8
|
+
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
9
|
+
const require$1 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('utils/master-css.cjs', document.baseURI).href)));
|
|
10
|
+
const defaultManifest = require$1('@master/css-preset/default-manifest.json');
|
|
11
|
+
const CLASS_ATTRIBUTES = [
|
|
12
|
+
'class',
|
|
13
|
+
'className'
|
|
14
|
+
];
|
|
15
|
+
const CLASS_DECLARATIONS = [];
|
|
16
|
+
const CLASS_FUNCTIONS = [
|
|
17
|
+
'clsx',
|
|
18
|
+
'cva',
|
|
19
|
+
'ctl',
|
|
20
|
+
'cv',
|
|
21
|
+
'class',
|
|
22
|
+
'classnames',
|
|
23
|
+
'classVariant',
|
|
24
|
+
'styled(?:\\s+)?(?:\\.\\w+)?',
|
|
25
|
+
'classList(?:\\s+)?\\.(?:add|remove|toggle|replace)'
|
|
26
|
+
];
|
|
27
|
+
const LAYER_ORDER = [
|
|
28
|
+
'theme',
|
|
29
|
+
'base',
|
|
30
|
+
'defaults',
|
|
31
|
+
'components',
|
|
32
|
+
'utilities'
|
|
33
|
+
];
|
|
34
|
+
function stable(value) {
|
|
35
|
+
if (!value || typeof value !== 'object') return JSON.stringify(value);
|
|
36
|
+
if (Array.isArray(value)) return `[${value.map(stable).join(',')}]`;
|
|
37
|
+
return `{${Object.entries(value).sort(([a], [b])=>a.localeCompare(b)).map(([key, item])=>`${JSON.stringify(key)}:${stable(item)}`).join(',')}}`;
|
|
38
|
+
}
|
|
39
|
+
function equalDeclarations(a, b) {
|
|
40
|
+
if (!a || !b || typeof a !== 'object' || typeof b !== 'object') return stable(a) === stable(b);
|
|
41
|
+
const aKeys = Object.keys(a).sort();
|
|
42
|
+
const bKeys = Object.keys(b).sort();
|
|
43
|
+
return stable(aKeys) === stable(bKeys);
|
|
44
|
+
}
|
|
45
|
+
function equalVariants(a, b) {
|
|
46
|
+
const branchA = a.variantBranchKey;
|
|
47
|
+
const branchB = b.variantBranchKey;
|
|
48
|
+
return (branchA !== undefined || branchB !== undefined ? branchA === branchB : a.selectorText === b.selectorText) && a.layerName === b.layerName && stable(a.atRules) === stable(b.atRules);
|
|
49
|
+
}
|
|
50
|
+
function getLayerOrder(layerName) {
|
|
51
|
+
const index = LAYER_ORDER.indexOf(layerName || 'utilities');
|
|
52
|
+
return index === -1 ? LAYER_ORDER.length : index;
|
|
53
|
+
}
|
|
54
|
+
function getReadableGroupOrder(rule) {
|
|
55
|
+
if (rule.atRules) return 3;
|
|
56
|
+
if (rule.mode) return 2;
|
|
57
|
+
if (rule.selectorNodes?.length) return 1;
|
|
58
|
+
return 0;
|
|
59
|
+
}
|
|
60
|
+
function getReadableTypeOrder(rule) {
|
|
61
|
+
if (rule.fixedClass) return 0;
|
|
62
|
+
if (rule.type === UtilityType.Semantic) return 1;
|
|
63
|
+
return 2;
|
|
64
|
+
}
|
|
65
|
+
function sortReadableClasses(classNames, css$1) {
|
|
66
|
+
return [
|
|
67
|
+
...new Set(classNames)
|
|
68
|
+
].sort((a, b)=>{
|
|
69
|
+
const ruleA = css$1.generate(a)[0];
|
|
70
|
+
const ruleB = css$1.generate(b)[0];
|
|
71
|
+
if (!ruleA && !ruleB) return a.localeCompare(b);
|
|
72
|
+
if (!ruleA) return 1;
|
|
73
|
+
if (!ruleB) return -1;
|
|
74
|
+
const layerCmp = getLayerOrder(ruleA.layerName) - getLayerOrder(ruleB.layerName);
|
|
75
|
+
if (layerCmp !== 0) return layerCmp;
|
|
76
|
+
const groupCmp = getReadableGroupOrder(ruleA) - getReadableGroupOrder(ruleB);
|
|
77
|
+
if (groupCmp !== 0) return groupCmp;
|
|
78
|
+
const typeCmp = getReadableTypeOrder(ruleA) - getReadableTypeOrder(ruleB);
|
|
79
|
+
if (typeCmp !== 0) return typeCmp;
|
|
80
|
+
return css.compareRulePriority(ruleA, ruleB) || a.localeCompare(b);
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
Object.defineProperty(exports, "createCSSWithNativeDeclarations", {
|
|
85
|
+
enumerable: true,
|
|
86
|
+
get: function () { return cssValidator.createCSSWithNativeDeclarations; }
|
|
87
|
+
});
|
|
88
|
+
exports.CLASS_ATTRIBUTES = CLASS_ATTRIBUTES;
|
|
89
|
+
exports.CLASS_DECLARATIONS = CLASS_DECLARATIONS;
|
|
90
|
+
exports.CLASS_FUNCTIONS = CLASS_FUNCTIONS;
|
|
91
|
+
exports.defaultManifest = defaultManifest;
|
|
92
|
+
exports.equalDeclarations = equalDeclarations;
|
|
93
|
+
exports.equalVariants = equalVariants;
|
|
94
|
+
exports.sortReadableClasses = sortReadableClasses;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type MasterCSS, type MasterCSSManifest } from '@master/css';
|
|
2
|
+
import { createCSSWithNativeDeclarations } from '@master/css-validator';
|
|
3
|
+
export type { MasterCSS, MasterCSSManifest };
|
|
4
|
+
declare const defaultManifest: MasterCSSManifest;
|
|
5
|
+
export { createCSSWithNativeDeclarations, defaultManifest };
|
|
6
|
+
export declare const CLASS_ATTRIBUTES: string[];
|
|
7
|
+
export declare const CLASS_DECLARATIONS: string[];
|
|
8
|
+
export declare const CLASS_FUNCTIONS: string[];
|
|
9
|
+
export declare function equalDeclarations(a: unknown, b: unknown): boolean;
|
|
10
|
+
export declare function equalVariants(a: {
|
|
11
|
+
selectorText?: string;
|
|
12
|
+
atRules?: unknown;
|
|
13
|
+
layerName?: string;
|
|
14
|
+
variantBranchKey?: string;
|
|
15
|
+
}, b: {
|
|
16
|
+
selectorText?: string;
|
|
17
|
+
atRules?: unknown;
|
|
18
|
+
layerName?: string;
|
|
19
|
+
variantBranchKey?: string;
|
|
20
|
+
}): boolean;
|
|
21
|
+
export declare function sortReadableClasses(classNames: string[], css: MasterCSS): string[];
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { compareRulePriority } from '@master/css';
|
|
2
|
+
export { createCSSWithNativeDeclarations } from '@master/css-validator';
|
|
3
|
+
import { createRequire } from 'node:module';
|
|
4
|
+
import UtilityType from '@master/css-schema/utility-type';
|
|
5
|
+
|
|
6
|
+
const require$1 = createRequire(import.meta.url);
|
|
7
|
+
const defaultManifest = require$1('@master/css-preset/default-manifest.json');
|
|
8
|
+
const CLASS_ATTRIBUTES = [
|
|
9
|
+
'class',
|
|
10
|
+
'className'
|
|
11
|
+
];
|
|
12
|
+
const CLASS_DECLARATIONS = [];
|
|
13
|
+
const CLASS_FUNCTIONS = [
|
|
14
|
+
'clsx',
|
|
15
|
+
'cva',
|
|
16
|
+
'ctl',
|
|
17
|
+
'cv',
|
|
18
|
+
'class',
|
|
19
|
+
'classnames',
|
|
20
|
+
'classVariant',
|
|
21
|
+
'styled(?:\\s+)?(?:\\.\\w+)?',
|
|
22
|
+
'classList(?:\\s+)?\\.(?:add|remove|toggle|replace)'
|
|
23
|
+
];
|
|
24
|
+
const LAYER_ORDER = [
|
|
25
|
+
'theme',
|
|
26
|
+
'base',
|
|
27
|
+
'defaults',
|
|
28
|
+
'components',
|
|
29
|
+
'utilities'
|
|
30
|
+
];
|
|
31
|
+
function stable(value) {
|
|
32
|
+
if (!value || typeof value !== 'object') return JSON.stringify(value);
|
|
33
|
+
if (Array.isArray(value)) return `[${value.map(stable).join(',')}]`;
|
|
34
|
+
return `{${Object.entries(value).sort(([a], [b])=>a.localeCompare(b)).map(([key, item])=>`${JSON.stringify(key)}:${stable(item)}`).join(',')}}`;
|
|
35
|
+
}
|
|
36
|
+
function equalDeclarations(a, b) {
|
|
37
|
+
if (!a || !b || typeof a !== 'object' || typeof b !== 'object') return stable(a) === stable(b);
|
|
38
|
+
const aKeys = Object.keys(a).sort();
|
|
39
|
+
const bKeys = Object.keys(b).sort();
|
|
40
|
+
return stable(aKeys) === stable(bKeys);
|
|
41
|
+
}
|
|
42
|
+
function equalVariants(a, b) {
|
|
43
|
+
const branchA = a.variantBranchKey;
|
|
44
|
+
const branchB = b.variantBranchKey;
|
|
45
|
+
return (branchA !== undefined || branchB !== undefined ? branchA === branchB : a.selectorText === b.selectorText) && a.layerName === b.layerName && stable(a.atRules) === stable(b.atRules);
|
|
46
|
+
}
|
|
47
|
+
function getLayerOrder(layerName) {
|
|
48
|
+
const index = LAYER_ORDER.indexOf(layerName || 'utilities');
|
|
49
|
+
return index === -1 ? LAYER_ORDER.length : index;
|
|
50
|
+
}
|
|
51
|
+
function getReadableGroupOrder(rule) {
|
|
52
|
+
if (rule.atRules) return 3;
|
|
53
|
+
if (rule.mode) return 2;
|
|
54
|
+
if (rule.selectorNodes?.length) return 1;
|
|
55
|
+
return 0;
|
|
56
|
+
}
|
|
57
|
+
function getReadableTypeOrder(rule) {
|
|
58
|
+
if (rule.fixedClass) return 0;
|
|
59
|
+
if (rule.type === UtilityType.Semantic) return 1;
|
|
60
|
+
return 2;
|
|
61
|
+
}
|
|
62
|
+
function sortReadableClasses(classNames, css) {
|
|
63
|
+
return [
|
|
64
|
+
...new Set(classNames)
|
|
65
|
+
].sort((a, b)=>{
|
|
66
|
+
const ruleA = css.generate(a)[0];
|
|
67
|
+
const ruleB = css.generate(b)[0];
|
|
68
|
+
if (!ruleA && !ruleB) return a.localeCompare(b);
|
|
69
|
+
if (!ruleA) return 1;
|
|
70
|
+
if (!ruleB) return -1;
|
|
71
|
+
const layerCmp = getLayerOrder(ruleA.layerName) - getLayerOrder(ruleB.layerName);
|
|
72
|
+
if (layerCmp !== 0) return layerCmp;
|
|
73
|
+
const groupCmp = getReadableGroupOrder(ruleA) - getReadableGroupOrder(ruleB);
|
|
74
|
+
if (groupCmp !== 0) return groupCmp;
|
|
75
|
+
const typeCmp = getReadableTypeOrder(ruleA) - getReadableTypeOrder(ruleB);
|
|
76
|
+
if (typeCmp !== 0) return typeCmp;
|
|
77
|
+
return compareRulePriority(ruleA, ruleB) || a.localeCompare(b);
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export { CLASS_ATTRIBUTES, CLASS_DECLARATIONS, CLASS_FUNCTIONS, defaultManifest, equalDeclarations, equalVariants, sortReadableClasses };
|
|
@@ -1,39 +1,77 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var settings = require('../settings.cjs');
|
|
4
|
-
var
|
|
5
|
-
var
|
|
4
|
+
var masterCss = require('./master-css.cjs');
|
|
5
|
+
var entries = require('@master/css-project/entries');
|
|
6
|
+
var manifestSync = require('@master/css-project/manifest-sync');
|
|
7
|
+
var path = require('node:path');
|
|
8
|
+
var node_fs = require('node:fs');
|
|
9
|
+
var isSameOrChildPath = require('./is-same-or-child-path.cjs');
|
|
10
|
+
var cssValidator = require('@master/css-validator');
|
|
6
11
|
|
|
7
12
|
const cssCaches = [];
|
|
13
|
+
const workspaceDirectoriesByCwd = new Map();
|
|
14
|
+
function getContextFilename(context) {
|
|
15
|
+
const filename = context.physicalFilename || context.filename;
|
|
16
|
+
if (!filename || filename.startsWith('<')) return;
|
|
17
|
+
const resolvedFilename = path.isAbsolute(filename) ? filename : path.resolve(context.cwd, filename);
|
|
18
|
+
return node_fs.existsSync(resolvedFilename) ? resolvedFilename : undefined;
|
|
19
|
+
}
|
|
20
|
+
function getWorkspaceDirectories(cwd) {
|
|
21
|
+
let directories = workspaceDirectoriesByCwd.get(cwd);
|
|
22
|
+
if (!directories) {
|
|
23
|
+
directories = entries.findMasterCSSWorkspaceDirectoriesSync(cwd);
|
|
24
|
+
workspaceDirectoriesByCwd.set(cwd, directories);
|
|
25
|
+
}
|
|
26
|
+
return directories;
|
|
27
|
+
}
|
|
28
|
+
function findNearestPackageDirectory(filename) {
|
|
29
|
+
let directory = path.dirname(filename);
|
|
30
|
+
const root = path.parse(directory).root;
|
|
31
|
+
while(directory !== root){
|
|
32
|
+
if (node_fs.existsSync(path.join(directory, 'package.json'))) return directory;
|
|
33
|
+
directory = path.dirname(directory);
|
|
34
|
+
}
|
|
35
|
+
return path.dirname(filename);
|
|
36
|
+
}
|
|
37
|
+
function resolveSearchDirectory(context, filename) {
|
|
38
|
+
const cwd = path.resolve(context.cwd || process.cwd());
|
|
39
|
+
const root = path.parse(cwd).root;
|
|
40
|
+
if (cwd !== root && isSameOrChildPath(cwd, filename)) return cwd;
|
|
41
|
+
return findNearestPackageDirectory(filename);
|
|
42
|
+
}
|
|
43
|
+
function resolveWorkspaceDirectory(context, filename) {
|
|
44
|
+
const cwd = resolveSearchDirectory(context, filename);
|
|
45
|
+
let closestDirectory;
|
|
46
|
+
for (const directory of getWorkspaceDirectories(cwd)){
|
|
47
|
+
if (isSameOrChildPath(directory, filename) && (!closestDirectory || directory.length > closestDirectory.length)) {
|
|
48
|
+
closestDirectory = directory;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return closestDirectory || cwd;
|
|
52
|
+
}
|
|
53
|
+
function resolvePlan(workspaceDir, manifest) {
|
|
54
|
+
const result = manifestSync.loadProjectManifestSync(workspaceDir);
|
|
55
|
+
return result.entries.length ? result.manifest : manifest;
|
|
56
|
+
}
|
|
8
57
|
function resolveContext(context) {
|
|
9
58
|
const resolvedSettings = Object.assign({}, settings, context.settings?.['@master/css']);
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
config = exploreConfig({
|
|
17
|
-
name: resolvedSettings.config,
|
|
18
|
-
cwd: context.cwd,
|
|
19
|
-
found (_, configPath) {
|
|
20
|
-
if (process.env.DEBUG) {
|
|
21
|
-
console.log('Found config:', configPath);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
});
|
|
25
|
-
}
|
|
26
|
-
css$1 = css.createCSS(config);
|
|
59
|
+
const filename = getContextFilename(context);
|
|
60
|
+
const workspaceDir = filename ? resolveWorkspaceDirectory(context, filename) : context.cwd || process.cwd();
|
|
61
|
+
let css = cssCaches.find((cache)=>cache.manifest === resolvedSettings.manifest && cache.cwd === workspaceDir)?.css;
|
|
62
|
+
if (!css) {
|
|
63
|
+
const manifest = filename ? resolvePlan(workspaceDir, resolvedSettings.manifest) : resolvedSettings.manifest;
|
|
64
|
+
css = cssValidator.createCSSWithNativeDeclarations(manifest || masterCss.defaultManifest);
|
|
27
65
|
cssCaches.push({
|
|
28
|
-
cwd:
|
|
29
|
-
|
|
30
|
-
css
|
|
66
|
+
cwd: workspaceDir,
|
|
67
|
+
manifest: resolvedSettings.manifest,
|
|
68
|
+
css
|
|
31
69
|
});
|
|
32
70
|
}
|
|
33
71
|
return {
|
|
34
72
|
settings: resolvedSettings,
|
|
35
73
|
options: context.options[0] || {},
|
|
36
|
-
css
|
|
74
|
+
css
|
|
37
75
|
};
|
|
38
76
|
}
|
|
39
77
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type { RuleContext } from '@typescript-eslint/utils/ts-eslint';
|
|
2
|
-
import { MasterCSS } from '
|
|
2
|
+
import { MasterCSS } from './master-css';
|
|
3
3
|
export default function resolveContext(context: RuleContext<any, any[]>): {
|
|
4
4
|
settings: {
|
|
5
5
|
classAttributes: string[];
|
|
6
6
|
classFunctions: string[];
|
|
7
7
|
classDeclarations: string[];
|
|
8
8
|
ignoredKeys: string[];
|
|
9
|
-
|
|
9
|
+
manifest: any;
|
|
10
10
|
};
|
|
11
11
|
options: any;
|
|
12
12
|
css: MasterCSS;
|
|
@@ -1,30 +1,68 @@
|
|
|
1
1
|
import settings from '../settings.mjs';
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
2
|
+
import { defaultManifest } from './master-css.mjs';
|
|
3
|
+
import { findMasterCSSWorkspaceDirectoriesSync } from '@master/css-project/entries';
|
|
4
|
+
import { loadProjectManifestSync } from '@master/css-project/manifest-sync';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { existsSync } from 'node:fs';
|
|
7
|
+
import isSameOrChildPath from './is-same-or-child-path.mjs';
|
|
8
|
+
import { createCSSWithNativeDeclarations } from '@master/css-validator';
|
|
4
9
|
|
|
5
10
|
const cssCaches = [];
|
|
11
|
+
const workspaceDirectoriesByCwd = new Map();
|
|
12
|
+
function getContextFilename(context) {
|
|
13
|
+
const filename = context.physicalFilename || context.filename;
|
|
14
|
+
if (!filename || filename.startsWith('<')) return;
|
|
15
|
+
const resolvedFilename = path.isAbsolute(filename) ? filename : path.resolve(context.cwd, filename);
|
|
16
|
+
return existsSync(resolvedFilename) ? resolvedFilename : undefined;
|
|
17
|
+
}
|
|
18
|
+
function getWorkspaceDirectories(cwd) {
|
|
19
|
+
let directories = workspaceDirectoriesByCwd.get(cwd);
|
|
20
|
+
if (!directories) {
|
|
21
|
+
directories = findMasterCSSWorkspaceDirectoriesSync(cwd);
|
|
22
|
+
workspaceDirectoriesByCwd.set(cwd, directories);
|
|
23
|
+
}
|
|
24
|
+
return directories;
|
|
25
|
+
}
|
|
26
|
+
function findNearestPackageDirectory(filename) {
|
|
27
|
+
let directory = path.dirname(filename);
|
|
28
|
+
const root = path.parse(directory).root;
|
|
29
|
+
while(directory !== root){
|
|
30
|
+
if (existsSync(path.join(directory, 'package.json'))) return directory;
|
|
31
|
+
directory = path.dirname(directory);
|
|
32
|
+
}
|
|
33
|
+
return path.dirname(filename);
|
|
34
|
+
}
|
|
35
|
+
function resolveSearchDirectory(context, filename) {
|
|
36
|
+
const cwd = path.resolve(context.cwd || process.cwd());
|
|
37
|
+
const root = path.parse(cwd).root;
|
|
38
|
+
if (cwd !== root && isSameOrChildPath(cwd, filename)) return cwd;
|
|
39
|
+
return findNearestPackageDirectory(filename);
|
|
40
|
+
}
|
|
41
|
+
function resolveWorkspaceDirectory(context, filename) {
|
|
42
|
+
const cwd = resolveSearchDirectory(context, filename);
|
|
43
|
+
let closestDirectory;
|
|
44
|
+
for (const directory of getWorkspaceDirectories(cwd)){
|
|
45
|
+
if (isSameOrChildPath(directory, filename) && (!closestDirectory || directory.length > closestDirectory.length)) {
|
|
46
|
+
closestDirectory = directory;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return closestDirectory || cwd;
|
|
50
|
+
}
|
|
51
|
+
function resolvePlan(workspaceDir, manifest) {
|
|
52
|
+
const result = loadProjectManifestSync(workspaceDir);
|
|
53
|
+
return result.entries.length ? result.manifest : manifest;
|
|
54
|
+
}
|
|
6
55
|
function resolveContext(context) {
|
|
7
56
|
const resolvedSettings = Object.assign({}, settings, context.settings?.['@master/css']);
|
|
8
|
-
|
|
57
|
+
const filename = getContextFilename(context);
|
|
58
|
+
const workspaceDir = filename ? resolveWorkspaceDirectory(context, filename) : context.cwd || process.cwd();
|
|
59
|
+
let css = cssCaches.find((cache)=>cache.manifest === resolvedSettings.manifest && cache.cwd === workspaceDir)?.css;
|
|
9
60
|
if (!css) {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
config = resolvedSettings.config;
|
|
13
|
-
} else {
|
|
14
|
-
config = exploreConfig({
|
|
15
|
-
name: resolvedSettings.config,
|
|
16
|
-
cwd: context.cwd,
|
|
17
|
-
found (_, configPath) {
|
|
18
|
-
if (process.env.DEBUG) {
|
|
19
|
-
console.log('Found config:', configPath);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
|
-
css = createCSS(config);
|
|
61
|
+
const manifest = filename ? resolvePlan(workspaceDir, resolvedSettings.manifest) : resolvedSettings.manifest;
|
|
62
|
+
css = createCSSWithNativeDeclarations(manifest || defaultManifest);
|
|
25
63
|
cssCaches.push({
|
|
26
|
-
cwd:
|
|
27
|
-
|
|
64
|
+
cwd: workspaceDir,
|
|
65
|
+
manifest: resolvedSettings.manifest,
|
|
28
66
|
css
|
|
29
67
|
});
|
|
30
68
|
}
|
|
@@ -4,6 +4,7 @@ var resolveClassNode = require('./resolve-class-node.cjs');
|
|
|
4
4
|
|
|
5
5
|
function withVisitClassNode(visit, context) {
|
|
6
6
|
const visitNode = (node)=>{
|
|
7
|
+
if (!node) return;
|
|
7
8
|
switch(node.type){
|
|
8
9
|
case 'BinaryExpression':
|
|
9
10
|
case 'Identifier':
|
|
@@ -45,7 +46,7 @@ function withVisitClassNode(visit, context) {
|
|
|
45
46
|
}
|
|
46
47
|
return;
|
|
47
48
|
default:
|
|
48
|
-
|
|
49
|
+
const resolved = resolveClassNode(node, context);
|
|
49
50
|
if (!resolved) return;
|
|
50
51
|
visit(node, resolved);
|
|
51
52
|
}
|
|
@@ -2,6 +2,7 @@ import resolveClassNode from './resolve-class-node.mjs';
|
|
|
2
2
|
|
|
3
3
|
function withVisitClassNode(visit, context) {
|
|
4
4
|
const visitNode = (node)=>{
|
|
5
|
+
if (!node) return;
|
|
5
6
|
switch(node.type){
|
|
6
7
|
case 'BinaryExpression':
|
|
7
8
|
case 'Identifier':
|
|
@@ -43,7 +44,7 @@ function withVisitClassNode(visit, context) {
|
|
|
43
44
|
}
|
|
44
45
|
return;
|
|
45
46
|
default:
|
|
46
|
-
|
|
47
|
+
const resolved = resolveClassNode(node, context);
|
|
47
48
|
if (!resolved) return;
|
|
48
49
|
visit(node, resolved);
|
|
49
50
|
}
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"@master/eslint-plugin-css","type":"module","scripts":{"build":"techor build \"src/**/*.{js,ts}\"","dev":"pnpm build --watch","test":"vitest","type-check":"tsc --noEmit","lint":"eslint"},"keywords":["mastercss","eslint","eslintplugin"],"license":"MIT","description":"Master CSS ESLint Plugin","author":"Aoyue Design LLC.","funding":"https://rc.css.master.co/sponsor","homepage":"https://css.master.co","bugs":{"url":"https://github.com/master-co/css/issues"},"repository":{"type":"git","url":"https://github.com/master-co/css.git","directory":"packages/eslint-plugin"},"sideEffects":false,"main":"./dist/index.cjs","module":"./dist/index.mjs","jsnext:main":"./dist/index.mjs","esnext":"./dist/index.mjs","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.cjs"},"./configs/*":{"types":"./dist/configs/*.d.ts","import":"./dist/configs/*.mjs","require":"./dist/configs/*.cjs"}},"files":["dist"],"publishConfig":{"access":"public","provenance":true},"dependencies":{"@master/css":"^2.0.0-rc.
|
|
1
|
+
{"name":"@master/eslint-plugin-css","type":"module","scripts":{"build":"techor build \"src/**/*.{js,ts}\"","dev":"pnpm build --watch","test":"vitest","type-check":"tsc --noEmit","lint":"eslint"},"keywords":["mastercss","eslint","eslintplugin"],"license":"MIT","description":"Master CSS ESLint Plugin","author":"Aoyue Design LLC.","funding":"https://rc.css.master.co/sponsor","homepage":"https://css.master.co","bugs":{"url":"https://github.com/master-co/css/issues"},"repository":{"type":"git","url":"https://github.com/master-co/css.git","directory":"packages/eslint-plugin"},"sideEffects":false,"main":"./dist/index.cjs","module":"./dist/index.mjs","jsnext:main":"./dist/index.mjs","esnext":"./dist/index.mjs","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.cjs"},"./configs/*":{"types":"./dist/configs/*.d.ts","import":"./dist/configs/*.mjs","require":"./dist/configs/*.cjs"}},"files":["dist"],"publishConfig":{"access":"public","provenance":true},"dependencies":{"@master/css":"^2.0.0-rc.70","@master/css-project":"^2.0.0-rc.70","@master/css-preset":"^2.0.0-rc.70","@master/css-validator":"^2.0.0-rc.70","@typescript-eslint/utils":"^8.61.1","typescript-eslint":"^8.61.1","@master/css-schema":"^2.0.0-rc.70"},"devDependencies":{"@angular-eslint/template-parser":"^21.4.0","@angular/compiler":"^21.2.17","@typescript-eslint/rule-tester":"^8.61.1","eslint":"^10.5.0","eslint-plugin-markdown":"^5.1.0","eslint-plugin-mdx":"^3.8.1","svelte-eslint-parser":"^1.8.0","ts-node":"^10.9.2","vue-eslint-parser":"^10.4.1"},"version":"2.0.0-rc.70"}
|