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

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.
Files changed (42) hide show
  1. package/dist/create-rule.cjs +2 -1
  2. package/dist/create-rule.d.ts +1 -1
  3. package/dist/create-rule.mjs +2 -1
  4. package/dist/functions/filter-collision-classes.cjs +9 -0
  5. package/dist/functions/filter-collision-classes.d.ts +3 -0
  6. package/dist/functions/filter-collision-classes.mjs +11 -0
  7. package/dist/functions/filter-collision-classes.worker.cjs +35 -0
  8. package/dist/functions/filter-collision-classes.worker.d.ts +1 -0
  9. package/dist/functions/filter-collision-classes.worker.mjs +33 -0
  10. package/dist/functions/get-css.cjs +5 -2
  11. package/dist/functions/get-css.mjs +5 -2
  12. package/dist/functions/reorder-valid-classes.worker.cjs +1 -3
  13. package/dist/functions/reorder-valid-classes.worker.mjs +1 -3
  14. package/dist/index.cjs +26 -4
  15. package/dist/index.d.ts +18 -16
  16. package/dist/index.mjs +26 -4
  17. package/dist/rules/class-collision.cjs +21 -36
  18. package/dist/rules/class-collision.mjs +21 -36
  19. package/dist/utils/parse-node-recursive.cjs +12 -4
  20. package/dist/utils/parse-node-recursive.mjs +12 -4
  21. package/package.json +1 -1
  22. package/dist/configs/config.cjs +0 -16
  23. package/dist/configs/config.d.ts +0 -13
  24. package/dist/configs/config.mjs +0 -14
  25. package/dist/configs/flat.cjs +0 -13
  26. package/dist/configs/flat.d.ts +0 -25
  27. package/dist/configs/flat.mjs +0 -11
  28. package/dist/configs/recommended.cjs +0 -12
  29. package/dist/configs/recommended.d.ts +0 -14
  30. package/dist/configs/recommended.mjs +0 -10
  31. package/dist/functions/valid-rules.cjs +0 -9
  32. package/dist/functions/valid-rules.d.ts +0 -3
  33. package/dist/functions/valid-rules.mjs +0 -11
  34. package/dist/functions/valid-rules.worker.cjs +0 -24
  35. package/dist/functions/valid-rules.worker.d.ts +0 -6
  36. package/dist/functions/valid-rules.worker.mjs +0 -22
  37. package/dist/utils/are-declarations-equal.cjs +0 -21
  38. package/dist/utils/are-declarations-equal.d.ts +0 -1
  39. package/dist/utils/are-declarations-equal.mjs +0 -19
  40. package/dist/utils/are-vendor-prefix-selectors-equal.cjs +0 -14
  41. package/dist/utils/are-vendor-prefix-selectors-equal.d.ts +0 -1
  42. package/dist/utils/are-vendor-prefix-selectors-equal.mjs +0 -12
@@ -1,7 +1,8 @@
1
1
  'use strict';
2
2
 
3
+ var css = require('@master/css');
3
4
  var utils = require('@typescript-eslint/utils');
4
5
 
5
- var createRule = utils.ESLintUtils.RuleCreator((name)=>'https://rc.css.master.co/docs/code-linting#' + name);
6
+ var createRule = utils.ESLintUtils.RuleCreator((name)=>new URL(`/docs/code-linting#${name}`, css.OFFICIAL_URL).href);
6
7
 
7
8
  module.exports = createRule;
@@ -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;
@@ -1,5 +1,6 @@
1
+ import { OFFICIAL_URL } from '@master/css';
1
2
  import { ESLintUtils } from '@typescript-eslint/utils';
2
3
 
3
- var createRule = ESLintUtils.RuleCreator((name)=>'https://rc.css.master.co/docs/code-linting#' + name);
4
+ var createRule = ESLintUtils.RuleCreator((name)=>new URL(`/docs/code-linting#${name}`, OFFICIAL_URL).href);
4
5
 
5
6
  export { createRule as 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,13 +1,16 @@
1
1
  'use strict';
2
2
 
3
3
  var css = require('@master/css');
4
- var exploreConfig = require('explore-config');
4
+ var exploreConfig = require('@master/css-explore-config');
5
5
 
6
6
  let currentCSS;
7
7
  let currentConfig;
8
8
  function getCSS(config) {
9
9
  if (!currentCSS || currentConfig !== config) {
10
- currentCSS = new css.MasterCSS(typeof config === 'object' ? config : exploreConfig(config || ''));
10
+ currentCSS = new css.MasterCSS(typeof config === 'object' ? config : exploreConfig({
11
+ name: config,
12
+ found: undefined
13
+ }));
11
14
  currentConfig = config;
12
15
  }
13
16
  return currentCSS;
@@ -1,11 +1,14 @@
1
1
  import { MasterCSS } from '@master/css';
2
- import exploreConfig from 'explore-config';
2
+ import exploreConfig from '@master/css-explore-config';
3
3
 
4
4
  let currentCSS;
5
5
  let currentConfig;
6
6
  function getCSS(config) {
7
7
  if (!currentCSS || currentConfig !== config) {
8
- currentCSS = new MasterCSS(typeof config === 'object' ? config : exploreConfig(config || ''));
8
+ currentCSS = new MasterCSS(typeof config === 'object' ? config : exploreConfig({
9
+ name: config,
10
+ found: undefined
11
+ }));
9
12
  currentConfig = config;
10
13
  }
11
14
  return currentCSS;
@@ -6,9 +6,7 @@ var getCss = require('./get-css.cjs');
6
6
 
7
7
  function runReorderValidClasses(classNames, config) {
8
8
  const currentCSS = getCss(config);
9
- return css.reorderForReadableClasses(classNames, {
10
- css: currentCSS
11
- }).filter((eachOrderedClassName)=>classNames.includes(eachOrderedClassName));
9
+ return css.reorderForReadableClasses(classNames, currentCSS).filter((eachOrderedClassName)=>classNames.includes(eachOrderedClassName));
12
10
  }
13
11
  synckit.runAsWorker(runReorderValidClasses);
14
12
 
@@ -4,9 +4,7 @@ import getCSS from './get-css.mjs';
4
4
 
5
5
  function runReorderValidClasses(classNames, config) {
6
6
  const currentCSS = getCSS(config);
7
- return reorderForReadableClasses(classNames, {
8
- css: currentCSS
9
- }).filter((eachOrderedClassName)=>classNames.includes(eachOrderedClassName));
7
+ return reorderForReadableClasses(classNames, currentCSS).filter((eachOrderedClassName)=>classNames.includes(eachOrderedClassName));
10
8
  }
11
9
  runAsWorker(runReorderValidClasses);
12
10
 
package/dist/index.cjs CHANGED
@@ -2,14 +2,36 @@
2
2
 
3
3
  var plugin = require('./plugin.cjs');
4
4
  var settings = require('./settings.cjs');
5
- var recommended = require('./configs/recommended.cjs');
6
- var flat = require('./configs/flat.cjs');
7
5
 
6
+ const parserOptions = {
7
+ ecmaFeatures: {
8
+ jsx: true
9
+ }
10
+ };
11
+ const rules = {
12
+ '@master/css/class-order': 'warn',
13
+ '@master/css/class-validation': 'error',
14
+ '@master/css/class-collision': 'warn'
15
+ };
8
16
  /** @type {import('typescript-eslint').Config} */ var index = {
9
17
  ...plugin,
10
18
  configs: {
11
- recommended,
12
- flat
19
+ recommended: {
20
+ plugins: [
21
+ '@master/css'
22
+ ],
23
+ rules,
24
+ parserOptions
25
+ },
26
+ flat: {
27
+ plugins: {
28
+ '@master/css': plugin
29
+ },
30
+ rules,
31
+ languageOptions: {
32
+ parserOptions
33
+ }
34
+ }
13
35
  },
14
36
  settings
15
37
  };
package/dist/index.d.ts CHANGED
@@ -2,29 +2,19 @@
2
2
  declare const _default: {
3
3
  configs: {
4
4
  recommended: {
5
+ plugins: string[];
5
6
  rules: {
6
- readonly '@master/css/class-order': "warn";
7
- readonly '@master/css/class-validation': "error";
8
- readonly '@master/css/class-collision': "warn";
7
+ '@master/css/class-order': string;
8
+ '@master/css/class-validation': string;
9
+ '@master/css/class-collision': string;
9
10
  };
10
11
  parserOptions: {
11
- readonly ecmaFeatures: {
12
- readonly jsx: true;
12
+ ecmaFeatures: {
13
+ jsx: boolean;
13
14
  };
14
15
  };
15
- plugins: string[];
16
16
  };
17
17
  flat: {
18
- rules: {
19
- readonly '@master/css/class-order': "warn";
20
- readonly '@master/css/class-validation': "error";
21
- readonly '@master/css/class-collision': "warn";
22
- };
23
- parserOptions: {
24
- readonly ecmaFeatures: {
25
- readonly jsx: true;
26
- };
27
- };
28
18
  plugins: {
29
19
  '@master/css': {
30
20
  meta: {
@@ -37,6 +27,18 @@ declare const _default: {
37
27
  };
38
28
  };
39
29
  };
30
+ rules: {
31
+ '@master/css/class-order': string;
32
+ '@master/css/class-validation': string;
33
+ '@master/css/class-collision': string;
34
+ };
35
+ languageOptions: {
36
+ parserOptions: {
37
+ ecmaFeatures: {
38
+ jsx: boolean;
39
+ };
40
+ };
41
+ };
40
42
  };
41
43
  };
42
44
  settings: {
package/dist/index.mjs CHANGED
@@ -1,13 +1,35 @@
1
1
  import plugin from './plugin.mjs';
2
2
  import settings from './settings.mjs';
3
- import recommended from './configs/recommended.mjs';
4
- import flat from './configs/flat.mjs';
5
3
 
4
+ const parserOptions = {
5
+ ecmaFeatures: {
6
+ jsx: true
7
+ }
8
+ };
9
+ const rules = {
10
+ '@master/css/class-order': 'warn',
11
+ '@master/css/class-validation': 'error',
12
+ '@master/css/class-collision': 'warn'
13
+ };
6
14
  /** @type {import('typescript-eslint').Config} */ var index = {
7
15
  ...plugin,
8
16
  configs: {
9
- recommended,
10
- flat
17
+ recommended: {
18
+ plugins: [
19
+ '@master/css'
20
+ ],
21
+ rules,
22
+ parserOptions
23
+ },
24
+ flat: {
25
+ plugins: {
26
+ '@master/css': plugin
27
+ },
28
+ rules,
29
+ languageOptions: {
30
+ parserOptions
31
+ }
32
+ }
11
33
  },
12
34
  settings
13
35
  };
@@ -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
  };
@@ -48,15 +48,20 @@ var extractRangeFromNode = require('./extract-range-from-node.cjs');
48
48
  return;
49
49
  } else {
50
50
  const forceIsolation = skipConditional ? true : isolate;
51
+ let expStrings = [];
51
52
  switch(childNode.type){
52
53
  case 'TemplateLiteral':
53
54
  childNode.expressions.forEach((exp)=>{
54
55
  parseNodeRecursive(rootNode, exp, cb, skipConditional, forceIsolation, ignoredKeys);
55
56
  });
56
- childNode.quasis.forEach((quasis)=>{
57
- parseNodeRecursive(rootNode, quasis, cb, skipConditional, isolate, ignoredKeys);
58
- });
59
- return;
57
+ const sourceCode = context.sourceCode;
58
+ originalClassNamesValue = sourceCode.getText(childNode);
59
+ originalClassNamesValue = originalClassNamesValue.substring(1, originalClassNamesValue.length - 1);
60
+ expStrings = originalClassNamesValue.match(/\$\{(?:(?<!\\\\)(['"`]).*?(?<!\\\\)\1|[^}])*?\}/g) ?? [];
61
+ for(let i = 0; i < expStrings.length; i++){
62
+ originalClassNamesValue = originalClassNamesValue.replace(expStrings[i], `EXPRESSION_STRING_NUM_${i}`);
63
+ }
64
+ break;
60
65
  case 'ConditionalExpression':
61
66
  parseNodeRecursive(rootNode, childNode.consequent, cb, skipConditional, forceIsolation, ignoredKeys);
62
67
  parseNodeRecursive(rootNode, childNode.alternate, cb, skipConditional, forceIsolation, ignoredKeys);
@@ -106,6 +111,9 @@ var extractRangeFromNode = require('./extract-range-from-node.cjs');
106
111
  suffix = getTemplateElementSuffix(txt, originalClassNamesValue);
107
112
  break;
108
113
  }
114
+ for(let i = 0; i < expStrings.length; i++){
115
+ originalClassNamesValue = originalClassNamesValue.replace(`EXPRESSION_STRING_NUM_${i}`, expStrings[i]);
116
+ }
109
117
  ({ classNames } = extractClassnamesFromValue(originalClassNamesValue));
110
118
  classNames = [
111
119
  ...new Set(classNames)
@@ -46,15 +46,20 @@ import extractRangeFromNode from './extract-range-from-node.mjs';
46
46
  return;
47
47
  } else {
48
48
  const forceIsolation = skipConditional ? true : isolate;
49
+ let expStrings = [];
49
50
  switch(childNode.type){
50
51
  case 'TemplateLiteral':
51
52
  childNode.expressions.forEach((exp)=>{
52
53
  parseNodeRecursive(rootNode, exp, cb, skipConditional, forceIsolation, ignoredKeys);
53
54
  });
54
- childNode.quasis.forEach((quasis)=>{
55
- parseNodeRecursive(rootNode, quasis, cb, skipConditional, isolate, ignoredKeys);
56
- });
57
- return;
55
+ const sourceCode = context.sourceCode;
56
+ originalClassNamesValue = sourceCode.getText(childNode);
57
+ originalClassNamesValue = originalClassNamesValue.substring(1, originalClassNamesValue.length - 1);
58
+ expStrings = originalClassNamesValue.match(/\$\{(?:(?<!\\\\)(['"`]).*?(?<!\\\\)\1|[^}])*?\}/g) ?? [];
59
+ for(let i = 0; i < expStrings.length; i++){
60
+ originalClassNamesValue = originalClassNamesValue.replace(expStrings[i], `EXPRESSION_STRING_NUM_${i}`);
61
+ }
62
+ break;
58
63
  case 'ConditionalExpression':
59
64
  parseNodeRecursive(rootNode, childNode.consequent, cb, skipConditional, forceIsolation, ignoredKeys);
60
65
  parseNodeRecursive(rootNode, childNode.alternate, cb, skipConditional, forceIsolation, ignoredKeys);
@@ -104,6 +109,9 @@ import extractRangeFromNode from './extract-range-from-node.mjs';
104
109
  suffix = getTemplateElementSuffix(txt, originalClassNamesValue);
105
110
  break;
106
111
  }
112
+ for(let i = 0; i < expStrings.length; i++){
113
+ originalClassNamesValue = originalClassNamesValue.replace(`EXPRESSION_STRING_NUM_${i}`, expStrings[i]);
114
+ }
107
115
  ({ classNames } = extractClassnamesFromValue(originalClassNamesValue));
108
116
  classNames = [
109
117
  ...new Set(classNames)
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.27","@master/css-explore-config":"^2.0.0-rc.27","@master/css-validator":"^2.0.0-rc.27","@typescript-eslint/utils":"^7.7.0","synckit":"^0.9.0","typescript-eslint":"^7.7.0"},"devDependencies":{"@angular-eslint/template-parser":"^17.3.0","@master/css-explore-config":"^2.0.0-rc.27","@master/css-shared":"^2.0.0-rc.27","@types/node":"^20.12.7","@typescript-eslint/rule-tester":"^7.7.0","eslint":"^8.57.0","eslint-plugin-markdown":"^4.0.1","eslint-plugin-mdx":"^3.1.5","svelte-eslint-parser":"^0.34.1","ts-node":"^10.9.2","vue-eslint-parser":"^9.4.2"},"version":"2.0.0-rc.27"}
@@ -1,16 +0,0 @@
1
- 'use strict';
2
-
3
- const config = {
4
- rules: {
5
- '@master/css/class-order': 'warn',
6
- '@master/css/class-validation': 'error',
7
- '@master/css/class-collision': 'warn'
8
- },
9
- parserOptions: {
10
- ecmaFeatures: {
11
- jsx: true
12
- }
13
- }
14
- };
15
-
16
- module.exports = config;
@@ -1,13 +0,0 @@
1
- declare const config: {
2
- readonly rules: {
3
- readonly '@master/css/class-order': "warn";
4
- readonly '@master/css/class-validation': "error";
5
- readonly '@master/css/class-collision': "warn";
6
- };
7
- readonly parserOptions: {
8
- readonly ecmaFeatures: {
9
- readonly jsx: true;
10
- };
11
- };
12
- };
13
- export default config;
@@ -1,14 +0,0 @@
1
- const config = {
2
- rules: {
3
- '@master/css/class-order': 'warn',
4
- '@master/css/class-validation': 'error',
5
- '@master/css/class-collision': 'warn'
6
- },
7
- parserOptions: {
8
- ecmaFeatures: {
9
- jsx: true
10
- }
11
- }
12
- };
13
-
14
- export { config as default };
@@ -1,13 +0,0 @@
1
- 'use strict';
2
-
3
- var plugin = require('../plugin.cjs');
4
- var config = require('./config.cjs');
5
-
6
- var flat = {
7
- plugins: {
8
- '@master/css': plugin
9
- },
10
- ...config
11
- };
12
-
13
- module.exports = flat;
@@ -1,25 +0,0 @@
1
- declare const _default: {
2
- rules: {
3
- readonly '@master/css/class-order': "warn";
4
- readonly '@master/css/class-validation': "error";
5
- readonly '@master/css/class-collision': "warn";
6
- };
7
- parserOptions: {
8
- readonly ecmaFeatures: {
9
- readonly jsx: true;
10
- };
11
- };
12
- plugins: {
13
- '@master/css': {
14
- meta: {
15
- name: string;
16
- };
17
- rules: {
18
- 'class-collision': import("@typescript-eslint/utils/ts-eslint").RuleModule<"collisionClass", [], import("@typescript-eslint/utils/ts-eslint").RuleListener>;
19
- 'class-order': import("@typescript-eslint/utils/ts-eslint").RuleModule<"invalidClassOrder", [], import("@typescript-eslint/utils/ts-eslint").RuleListener>;
20
- 'class-validation': import("@typescript-eslint/utils/ts-eslint").RuleModule<"invalidClass" | "disallowUnknownClass", [], import("@typescript-eslint/utils/ts-eslint").RuleListener>;
21
- };
22
- };
23
- };
24
- };
25
- export default _default;
@@ -1,11 +0,0 @@
1
- import plugin from '../plugin.mjs';
2
- import config from './config.mjs';
3
-
4
- var flat = {
5
- plugins: {
6
- '@master/css': plugin
7
- },
8
- ...config
9
- };
10
-
11
- export { flat as default };
@@ -1,12 +0,0 @@
1
- 'use strict';
2
-
3
- var config = require('./config.cjs');
4
-
5
- var recommended = {
6
- plugins: [
7
- '@master/css'
8
- ],
9
- ...config
10
- };
11
-
12
- module.exports = recommended;
@@ -1,14 +0,0 @@
1
- declare const _default: {
2
- rules: {
3
- readonly '@master/css/class-order': "warn";
4
- readonly '@master/css/class-validation': "error";
5
- readonly '@master/css/class-collision': "warn";
6
- };
7
- parserOptions: {
8
- readonly ecmaFeatures: {
9
- readonly jsx: true;
10
- };
11
- };
12
- plugins: string[];
13
- };
14
- export default _default;
@@ -1,10 +0,0 @@
1
- import config from './config.mjs';
2
-
3
- var recommended = {
4
- plugins: [
5
- '@master/css'
6
- ],
7
- ...config
8
- };
9
-
10
- export { recommended as default };
@@ -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 };