@master/eslint-plugin-css 2.0.0-rc.25 → 2.0.0-rc.26

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.
@@ -1,3 +1,3 @@
1
1
  import { ESLintUtils } from '@typescript-eslint/utils';
2
- declare const _default: <TOptions extends readonly unknown[], TMessageIds extends string>({ name, meta, ...rule }: Readonly<ESLintUtils.RuleWithMetaAndName<TOptions, TMessageIds>>) => ESLintUtils.RuleModule<TMessageIds, TOptions, ESLintUtils.RuleListener>;
2
+ declare const _default: <Options extends readonly unknown[], MessageIds extends string>({ name, meta, ...rule }: Readonly<ESLintUtils.RuleWithMetaAndName<Options, MessageIds>>) => ESLintUtils.RuleModule<MessageIds, Options, ESLintUtils.RuleListener>;
3
3
  export default _default;
@@ -0,0 +1,9 @@
1
+ 'use strict';
2
+
3
+ var synckit = require('synckit');
4
+ var filterCollisionClasses_worker = require('./filter-collision-classes.worker.cjs');
5
+ var path = require('path');
6
+
7
+ var filterCollisionClasses = process.env.NODE_ENV === 'test' ? filterCollisionClasses_worker : synckit.createSyncFn(path.join(__dirname, 'filter-collision-classes.worker.cjs'));
8
+
9
+ module.exports = filterCollisionClasses;
@@ -0,0 +1,3 @@
1
+ import runFilterCollisionClasses from './filter-collision-classes.worker';
2
+ declare const _default: typeof runFilterCollisionClasses;
3
+ export default _default;
@@ -0,0 +1,11 @@
1
+ import __url_for_shim from 'url';
2
+ import __path_for_shim from 'path';
3
+ const __filename = __url_for_shim.fileURLToPath(import.meta.url);
4
+ const __dirname = __path_for_shim.dirname(__filename);
5
+ import { createSyncFn } from 'synckit';
6
+ import runFilterCollisionClasses from './filter-collision-classes.worker.mjs';
7
+ import { join } from 'path';
8
+ var filterCollisionClasses = process.env.NODE_ENV === 'test' ? runFilterCollisionClasses : createSyncFn(join(__dirname, 'filter-collision-classes.worker.cjs'));
9
+ export {
10
+ filterCollisionClasses as default
11
+ };
@@ -0,0 +1,35 @@
1
+ 'use strict';
2
+
3
+ var synckit = require('synckit');
4
+ var getCss = require('./get-css.cjs');
5
+ var cssValidator = require('@master/css-validator');
6
+ var css = require('@master/css');
7
+
8
+ function runFilterCollisionClasses(classNames, config) {
9
+ const currentCSS = getCss(config);
10
+ const validRules = classNames.map((eachClassName)=>cssValidator.generateValidRules(eachClassName, {
11
+ css: currentCSS
12
+ })[0]).filter(Boolean);
13
+ const collisionClassesRecord = {};
14
+ for(let i = 0; i < classNames.length; i++){
15
+ const className = classNames[i];
16
+ const rule = validRules.find((eachValidRule)=>eachValidRule.className === className);
17
+ const collisionClasses = [];
18
+ if (rule) {
19
+ for(let j = 0; j < classNames.length; j++){
20
+ const compareClassName = classNames[j];
21
+ const compareRule = validRules.find((eachValidRule)=>eachValidRule.className === compareClassName);
22
+ if (i !== j && compareRule && css.areRulesDuplicated(rule, compareRule) && css.areRuleStatesEqual(rule, compareRule)) {
23
+ collisionClasses.push(compareClassName);
24
+ }
25
+ }
26
+ if (collisionClasses.length > 0) {
27
+ collisionClassesRecord[className] = collisionClasses;
28
+ }
29
+ }
30
+ }
31
+ return collisionClassesRecord;
32
+ }
33
+ synckit.runAsWorker(runFilterCollisionClasses);
34
+
35
+ module.exports = runFilterCollisionClasses;
@@ -0,0 +1 @@
1
+ export default function runFilterCollisionClasses(classNames: string[], config: string | object): Record<string, string[]>;
@@ -0,0 +1,33 @@
1
+ import { runAsWorker } from 'synckit';
2
+ import getCSS from './get-css.mjs';
3
+ import { generateValidRules } from '@master/css-validator';
4
+ import { areRulesDuplicated, areRuleStatesEqual } from '@master/css';
5
+
6
+ function runFilterCollisionClasses(classNames, config) {
7
+ const currentCSS = getCSS(config);
8
+ const validRules = classNames.map((eachClassName)=>generateValidRules(eachClassName, {
9
+ css: currentCSS
10
+ })[0]).filter(Boolean);
11
+ const collisionClassesRecord = {};
12
+ for(let i = 0; i < classNames.length; i++){
13
+ const className = classNames[i];
14
+ const rule = validRules.find((eachValidRule)=>eachValidRule.className === className);
15
+ const collisionClasses = [];
16
+ if (rule) {
17
+ for(let j = 0; j < classNames.length; j++){
18
+ const compareClassName = classNames[j];
19
+ const compareRule = validRules.find((eachValidRule)=>eachValidRule.className === compareClassName);
20
+ if (i !== j && compareRule && areRulesDuplicated(rule, compareRule) && areRuleStatesEqual(rule, compareRule)) {
21
+ collisionClasses.push(compareClassName);
22
+ }
23
+ }
24
+ if (collisionClasses.length > 0) {
25
+ collisionClassesRecord[className] = collisionClasses;
26
+ }
27
+ }
28
+ }
29
+ return collisionClassesRecord;
30
+ }
31
+ runAsWorker(runFilterCollisionClasses);
32
+
33
+ export { runFilterCollisionClasses as default };
@@ -1,12 +1,10 @@
1
1
  'use strict';
2
2
 
3
- var areDeclarationsEqual = require('../utils/are-declarations-equal.cjs');
4
- var areVendorPrefixSelectorsEqual = require('../utils/are-vendor-prefix-selectors-equal.cjs');
5
3
  var defineVisitors = require('../utils/define-visitors.cjs');
6
4
  var resolveContext = require('../utils/resolve-context.cjs');
7
5
  var findLoc = require('../utils/find-loc.cjs');
8
6
  var parseNodeRecursive = require('../utils/parse-node-recursive.cjs');
9
- var validRules = require('../functions/valid-rules.cjs');
7
+ var filterCollisionClasses = require('../functions/filter-collision-classes.cjs');
10
8
  var createRule = require('../create-rule.cjs');
11
9
 
12
10
  var classCollision = createRule({
@@ -58,41 +56,28 @@ var classCollision = createRule({
58
56
  const sourceCodeLines = sourceCode.lines;
59
57
  const nodeStartLine = node.loc.start.line;
60
58
  const nodeEndLine = node.loc.end.line;
61
- const ruleOfClass = validRules(classNames, settings.config);
62
- for(let i = 0; i < classNames.length; i++){
63
- const className = classNames[i];
64
- const rule = ruleOfClass[className];
65
- const conflicts = [];
66
- if (rule) {
67
- for(let j = 0; j < classNames.length; j++){
68
- const compareClassName = classNames[j];
69
- const compareRule = ruleOfClass[compareClassName];
70
- if (i !== j && compareRule && areDeclarationsEqual(rule.declarations, compareRule.declarations) && areVendorPrefixSelectorsEqual(rule.vendorPrefixSelectors, compareRule.vendorPrefixSelectors) && rule.stateToken === compareRule.stateToken) {
71
- conflicts.push(compareClassName);
72
- }
73
- }
59
+ const collisionClassesRecord = filterCollisionClasses(classNames, settings.config);
60
+ for(const className in collisionClassesRecord){
61
+ const collisionClasses = collisionClassesRecord[className];
62
+ const collisionClassNamesMsg = collisionClasses.map((x)=>`"${x}"`).join(' and ');
63
+ let fixClassNames = originalClassNamesValue;
64
+ for (const collisionClassName of collisionClasses){
65
+ const regexSafe = collisionClassName.replace(/(\\|\.|\(|\)|\[|\]|\{|\}|\+|\*|\?|\^|\$|\||\/)/g, '\\$1');
66
+ fixClassNames = fixClassNames.replace(new RegExp(`\\s+${regexSafe}|${regexSafe}\\s+`), '');
74
67
  }
75
- if (conflicts.length > 0) {
76
- const conflictClassNamesMsg = conflicts.map((x)=>`"${x}"`).join(' and ');
77
- let fixClassNames = originalClassNamesValue;
78
- for (const conflictClassName of conflicts){
79
- const regexSafe = conflictClassName.replace(/(\\|\.|\(|\)|\[|\]|\{|\}|\+|\*|\?|\^|\$|\||\/)/g, '\\$1');
80
- fixClassNames = fixClassNames.replace(new RegExp(`\\s+${regexSafe}|${regexSafe}\\s+`), '');
68
+ context.report({
69
+ loc: findLoc(className, sourceCodeLines, nodeStartLine, nodeEndLine),
70
+ messageId: 'collisionClass',
71
+ data: {
72
+ message: `"${className}" applies the same CSS declarations as ${collisionClassNamesMsg}.`
73
+ },
74
+ fix: function(fixer) {
75
+ return fixer.replaceTextRange([
76
+ start,
77
+ end
78
+ ], fixClassNames);
81
79
  }
82
- context.report({
83
- loc: findLoc(className, sourceCodeLines, nodeStartLine, nodeEndLine),
84
- messageId: 'collisionClass',
85
- data: {
86
- message: `"${className}" applies the same CSS declarations as ${conflictClassNamesMsg}.`
87
- },
88
- fix: function(fixer) {
89
- return fixer.replaceTextRange([
90
- start,
91
- end
92
- ], fixClassNames);
93
- }
94
- });
95
- }
80
+ });
96
81
  }
97
82
  }, false, false, settings.ignoredKeys, context);
98
83
  };
@@ -1,10 +1,8 @@
1
- import areDeclarationsEqual from '../utils/are-declarations-equal.mjs';
2
- import areVendorPrefixSelectorsEqual from '../utils/are-vendor-prefix-selectors-equal.mjs';
3
1
  import defineVisitors from '../utils/define-visitors.mjs';
4
2
  import resolveContext from '../utils/resolve-context.mjs';
5
3
  import findLoc from '../utils/find-loc.mjs';
6
4
  import { parseNodeRecursive } from '../utils/parse-node-recursive.mjs';
7
- import validRules from '../functions/valid-rules.mjs';
5
+ import filterCollisionClasses from '../functions/filter-collision-classes.mjs';
8
6
  import createRule from '../create-rule.mjs';
9
7
 
10
8
  var classCollision = createRule({
@@ -56,41 +54,28 @@ var classCollision = createRule({
56
54
  const sourceCodeLines = sourceCode.lines;
57
55
  const nodeStartLine = node.loc.start.line;
58
56
  const nodeEndLine = node.loc.end.line;
59
- const ruleOfClass = validRules(classNames, settings.config);
60
- for(let i = 0; i < classNames.length; i++){
61
- const className = classNames[i];
62
- const rule = ruleOfClass[className];
63
- const conflicts = [];
64
- if (rule) {
65
- for(let j = 0; j < classNames.length; j++){
66
- const compareClassName = classNames[j];
67
- const compareRule = ruleOfClass[compareClassName];
68
- if (i !== j && compareRule && areDeclarationsEqual(rule.declarations, compareRule.declarations) && areVendorPrefixSelectorsEqual(rule.vendorPrefixSelectors, compareRule.vendorPrefixSelectors) && rule.stateToken === compareRule.stateToken) {
69
- conflicts.push(compareClassName);
70
- }
71
- }
57
+ const collisionClassesRecord = filterCollisionClasses(classNames, settings.config);
58
+ for(const className in collisionClassesRecord){
59
+ const collisionClasses = collisionClassesRecord[className];
60
+ const collisionClassNamesMsg = collisionClasses.map((x)=>`"${x}"`).join(' and ');
61
+ let fixClassNames = originalClassNamesValue;
62
+ for (const collisionClassName of collisionClasses){
63
+ const regexSafe = collisionClassName.replace(/(\\|\.|\(|\)|\[|\]|\{|\}|\+|\*|\?|\^|\$|\||\/)/g, '\\$1');
64
+ fixClassNames = fixClassNames.replace(new RegExp(`\\s+${regexSafe}|${regexSafe}\\s+`), '');
72
65
  }
73
- if (conflicts.length > 0) {
74
- const conflictClassNamesMsg = conflicts.map((x)=>`"${x}"`).join(' and ');
75
- let fixClassNames = originalClassNamesValue;
76
- for (const conflictClassName of conflicts){
77
- const regexSafe = conflictClassName.replace(/(\\|\.|\(|\)|\[|\]|\{|\}|\+|\*|\?|\^|\$|\||\/)/g, '\\$1');
78
- fixClassNames = fixClassNames.replace(new RegExp(`\\s+${regexSafe}|${regexSafe}\\s+`), '');
66
+ context.report({
67
+ loc: findLoc(className, sourceCodeLines, nodeStartLine, nodeEndLine),
68
+ messageId: 'collisionClass',
69
+ data: {
70
+ message: `"${className}" applies the same CSS declarations as ${collisionClassNamesMsg}.`
71
+ },
72
+ fix: function(fixer) {
73
+ return fixer.replaceTextRange([
74
+ start,
75
+ end
76
+ ], fixClassNames);
79
77
  }
80
- context.report({
81
- loc: findLoc(className, sourceCodeLines, nodeStartLine, nodeEndLine),
82
- messageId: 'collisionClass',
83
- data: {
84
- message: `"${className}" applies the same CSS declarations as ${conflictClassNamesMsg}.`
85
- },
86
- fix: function(fixer) {
87
- return fixer.replaceTextRange([
88
- start,
89
- end
90
- ], fixClassNames);
91
- }
92
- });
93
- }
78
+ });
94
79
  }
95
80
  }, false, false, settings.ignoredKeys, context);
96
81
  };
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":"jest","type-check":"tsc --noEmit","lint":"eslint src"},"keywords":["mastercss","eslint","eslintplugin"],"license":"MIT","description":"Master CSS ESLint Plugin","author":"Aoyue Design LLC.","funding":"https://css.master.co/docs/donate","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":{".":{"import":"./dist/index.mjs","require":"./dist/index.cjs","types":"./dist/index.d.ts"}},"files":["dist"],"publishConfig":{"access":"public","provenance":true},"dependencies":{"@master/css":"^2.0.0-rc.25","@master/css-validator":"^2.0.0-rc.25","@typescript-eslint/utils":"^7.0.2","explore-config":"^3.0.15","synckit":"^0.9.0","typescript-eslint":"^7.0.2"},"devDependencies":{"@angular-eslint/template-parser":"^16.3.1","@types/node":"^20.11.20","@typescript-eslint/rule-tester":"^7.0.2","eslint":"^8.57.0","eslint-plugin-markdown":"^3.0.1","eslint-plugin-mdx":"^2.3.4","svelte-eslint-parser":"^0.33.1","ts-node":"^10.9.2","vue-eslint-parser":"^9.4.2"},"version":"2.0.0-rc.25"}
1
+ {"name":"@master/eslint-plugin-css","type":"module","scripts":{"build":"techor build \"src/**/*.{js,ts}\"","dev":"pnpm build --watch","test":"jest","type-check":"tsc --noEmit","lint":"eslint src"},"keywords":["mastercss","eslint","eslintplugin"],"license":"MIT","description":"Master CSS ESLint Plugin","author":"Aoyue Design LLC.","funding":"https://css.master.co/docs/donate","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":{".":{"import":"./dist/index.mjs","require":"./dist/index.cjs","types":"./dist/index.d.ts"}},"files":["dist"],"publishConfig":{"access":"public","provenance":true},"dependencies":{"@master/css":"^2.0.0-rc.26","@master/css-validator":"^2.0.0-rc.26","@typescript-eslint/utils":"^7.0.2","explore-config":"^3.0.15","synckit":"^0.9.0","typescript-eslint":"^7.0.2"},"devDependencies":{"@angular-eslint/template-parser":"^16.3.1","@types/node":"^20.11.20","@typescript-eslint/rule-tester":"^7.0.2","eslint":"^8.57.0","eslint-plugin-markdown":"^3.0.1","eslint-plugin-mdx":"^2.3.4","svelte-eslint-parser":"^0.33.1","ts-node":"^10.9.2","vue-eslint-parser":"^9.4.2"},"version":"2.0.0-rc.26"}
@@ -1,9 +0,0 @@
1
- 'use strict';
2
-
3
- var synckit = require('synckit');
4
- var validRules_worker = require('./valid-rules.worker.cjs');
5
- var path = require('path');
6
-
7
- var validRules = process.env.NODE_ENV === 'test' ? validRules_worker : synckit.createSyncFn(path.join(__dirname, 'valid-rules.worker.cjs'));
8
-
9
- module.exports = validRules;
@@ -1,3 +0,0 @@
1
- import runValidRules from './valid-rules.worker';
2
- declare const _default: typeof runValidRules;
3
- export default _default;
@@ -1,11 +0,0 @@
1
- import __url_for_shim from 'url';
2
- import __path_for_shim from 'path';
3
- const __filename = __url_for_shim.fileURLToPath(import.meta.url);
4
- const __dirname = __path_for_shim.dirname(__filename);
5
- import { createSyncFn } from 'synckit';
6
- import runValidRules from './valid-rules.worker.mjs';
7
- import { join } from 'path';
8
- var validRules = process.env.NODE_ENV === 'test' ? runValidRules : createSyncFn(join(__dirname, 'valid-rules.worker.cjs'));
9
- export {
10
- validRules as default
11
- };
@@ -1,24 +0,0 @@
1
- 'use strict';
2
-
3
- var synckit = require('synckit');
4
- var getCss = require('./get-css.cjs');
5
- var cssValidator = require('@master/css-validator');
6
-
7
- function runValidRules(classNames, config) {
8
- const currentCSS = getCss(config);
9
- const ruleOfClass = {};
10
- classNames.forEach((eachClassName)=>{
11
- const validRule = cssValidator.generateValidRules(eachClassName, {
12
- css: currentCSS
13
- })[0];
14
- if (validRule) ruleOfClass[eachClassName] = {
15
- vendorPrefixSelectors: validRule?.vendorPrefixSelectors,
16
- declarations: validRule?.declarations,
17
- stateToken: validRule?.stateToken
18
- };
19
- });
20
- return ruleOfClass;
21
- }
22
- synckit.runAsWorker(runValidRules);
23
-
24
- module.exports = runValidRules;
@@ -1,6 +0,0 @@
1
- import { Rule } from '@master/css';
2
- export default function runValidRules(classNames: string[], config: string | object): Record<string, {
3
- declarations: Rule['declarations'];
4
- stateToken: Rule['stateToken'];
5
- vendorPrefixSelectors: Rule['vendorPrefixSelectors'];
6
- }>;
@@ -1,22 +0,0 @@
1
- import { runAsWorker } from 'synckit';
2
- import getCSS from './get-css.mjs';
3
- import { generateValidRules } from '@master/css-validator';
4
-
5
- function runValidRules(classNames, config) {
6
- const currentCSS = getCSS(config);
7
- const ruleOfClass = {};
8
- classNames.forEach((eachClassName)=>{
9
- const validRule = generateValidRules(eachClassName, {
10
- css: currentCSS
11
- })[0];
12
- if (validRule) ruleOfClass[eachClassName] = {
13
- vendorPrefixSelectors: validRule?.vendorPrefixSelectors,
14
- declarations: validRule?.declarations,
15
- stateToken: validRule?.stateToken
16
- };
17
- });
18
- return ruleOfClass;
19
- }
20
- runAsWorker(runValidRules);
21
-
22
- export { runValidRules as default };
@@ -1,21 +0,0 @@
1
- 'use strict';
2
-
3
- function areDeclarationsEqual(aDeclarations, bDeclarations) {
4
- // 获取对象A和B的所有属性名
5
- const aKeys = Object.keys(aDeclarations);
6
- const bKeys = Object.keys(bDeclarations);
7
- // 如果属性数量不相等,返回false
8
- if (aKeys.length !== bKeys.length) {
9
- return false;
10
- }
11
- // 检查对象A的属性是否都存在于对象B中
12
- for (const key of aKeys){
13
- if (!Object.prototype.hasOwnProperty.call(bDeclarations, key)) {
14
- return false;
15
- }
16
- }
17
- // 如果所有属性都匹配,返回true
18
- return true;
19
- }
20
-
21
- module.exports = areDeclarationsEqual;
@@ -1 +0,0 @@
1
- export default function areDeclarationsEqual(aDeclarations: any, bDeclarations: any): boolean;
@@ -1,19 +0,0 @@
1
- function areDeclarationsEqual(aDeclarations, bDeclarations) {
2
- // 获取对象A和B的所有属性名
3
- const aKeys = Object.keys(aDeclarations);
4
- const bKeys = Object.keys(bDeclarations);
5
- // 如果属性数量不相等,返回false
6
- if (aKeys.length !== bKeys.length) {
7
- return false;
8
- }
9
- // 检查对象A的属性是否都存在于对象B中
10
- for (const key of aKeys){
11
- if (!Object.prototype.hasOwnProperty.call(bDeclarations, key)) {
12
- return false;
13
- }
14
- }
15
- // 如果所有属性都匹配,返回true
16
- return true;
17
- }
18
-
19
- export { areDeclarationsEqual as default };
@@ -1,14 +0,0 @@
1
- 'use strict';
2
-
3
- function areVendorPrefixSelectorsEqual(aVendorPrefixSelectors, bVendorPrefixSelectors) {
4
- const aKeys = Object.keys(aVendorPrefixSelectors);
5
- if (aKeys.length !== Object.keys(bVendorPrefixSelectors).length) return false;
6
- return aKeys.every((eachAKey)=>{
7
- if (!Object.prototype.hasOwnProperty.call(bVendorPrefixSelectors, eachAKey)) return false;
8
- const aValues = aVendorPrefixSelectors[eachAKey];
9
- const bValues = bVendorPrefixSelectors[eachAKey];
10
- return aValues.length === bValues.length && aValues.every((eachAValue)=>bValues.includes(eachAValue));
11
- });
12
- }
13
-
14
- module.exports = areVendorPrefixSelectorsEqual;
@@ -1 +0,0 @@
1
- export default function areVendorPrefixSelectorsEqual(aVendorPrefixSelectors: any, bVendorPrefixSelectors: any): boolean;
@@ -1,12 +0,0 @@
1
- function areVendorPrefixSelectorsEqual(aVendorPrefixSelectors, bVendorPrefixSelectors) {
2
- const aKeys = Object.keys(aVendorPrefixSelectors);
3
- if (aKeys.length !== Object.keys(bVendorPrefixSelectors).length) return false;
4
- return aKeys.every((eachAKey)=>{
5
- if (!Object.prototype.hasOwnProperty.call(bVendorPrefixSelectors, eachAKey)) return false;
6
- const aValues = aVendorPrefixSelectors[eachAKey];
7
- const bValues = bVendorPrefixSelectors[eachAKey];
8
- return aValues.length === bValues.length && aValues.every((eachAValue)=>bValues.includes(eachAValue));
9
- });
10
- }
11
-
12
- export { areVendorPrefixSelectorsEqual as default };