@master/eslint-plugin-css 2.0.0-rc.61 → 2.0.0-rc.63

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 (52) hide show
  1. package/dist/common.cjs +7 -0
  2. package/dist/common.d.ts +2 -0
  3. package/dist/common.mjs +4 -0
  4. package/dist/create-rule.cjs +1 -1
  5. package/dist/create-rule.mjs +1 -1
  6. package/dist/functions/filter-collision-classes.cjs +1 -1
  7. package/dist/functions/filter-collision-classes.mjs +2 -2
  8. package/dist/rules/class-collision.cjs +44 -38
  9. package/dist/rules/class-collision.mjs +44 -38
  10. package/dist/rules/class-order.cjs +23 -134
  11. package/dist/rules/class-order.mjs +24 -135
  12. package/dist/rules/class-validation.cjs +26 -37
  13. package/dist/rules/class-validation.mjs +26 -37
  14. package/dist/utils/define-visitors.cjs +24 -25
  15. package/dist/utils/define-visitors.d.ts +2 -1
  16. package/dist/utils/define-visitors.mjs +24 -25
  17. package/dist/utils/resolve-class-node.cjs +144 -0
  18. package/dist/utils/resolve-class-node.d.ts +12 -0
  19. package/dist/utils/resolve-class-node.mjs +142 -0
  20. package/dist/utils/resolve-context.cjs +6 -2
  21. package/dist/utils/resolve-context.mjs +6 -2
  22. package/dist/utils/with-visit-class-node.cjs +56 -0
  23. package/dist/utils/with-visit-class-node.d.ts +4 -0
  24. package/dist/utils/with-visit-class-node.mjs +54 -0
  25. package/package.json +1 -1
  26. package/dist/utils/extract-classnames-from-value.cjs +0 -34
  27. package/dist/utils/extract-classnames-from-value.d.ts +0 -6
  28. package/dist/utils/extract-classnames-from-value.mjs +0 -32
  29. package/dist/utils/extract-range-from-node.cjs +0 -18
  30. package/dist/utils/extract-range-from-node.d.ts +0 -1
  31. package/dist/utils/extract-range-from-node.mjs +0 -16
  32. package/dist/utils/extract-value-from-node.cjs +0 -23
  33. package/dist/utils/extract-value-from-node.d.ts +0 -1
  34. package/dist/utils/extract-value-from-node.mjs +0 -21
  35. package/dist/utils/find-loc.cjs +0 -51
  36. package/dist/utils/find-loc.d.ts +0 -7
  37. package/dist/utils/find-loc.mjs +0 -49
  38. package/dist/utils/get-template-element-body.cjs +0 -12
  39. package/dist/utils/get-template-element-body.d.ts +0 -1
  40. package/dist/utils/get-template-element-body.mjs +0 -10
  41. package/dist/utils/get-template-element-prefix.cjs +0 -11
  42. package/dist/utils/get-template-element-prefix.d.ts +0 -1
  43. package/dist/utils/get-template-element-prefix.mjs +0 -9
  44. package/dist/utils/get-template-element-suffix.cjs +0 -10
  45. package/dist/utils/get-template-element-suffix.d.ts +0 -1
  46. package/dist/utils/get-template-element-suffix.mjs +0 -8
  47. package/dist/utils/index-of-all.cjs +0 -12
  48. package/dist/utils/index-of-all.d.ts +0 -1
  49. package/dist/utils/index-of-all.mjs +0 -10
  50. package/dist/utils/parse-node-recursive.cjs +0 -129
  51. package/dist/utils/parse-node-recursive.d.ts +0 -13
  52. package/dist/utils/parse-node-recursive.mjs +0 -127
@@ -2,8 +2,6 @@
2
2
 
3
3
  var defineVisitors = require('../utils/define-visitors.cjs');
4
4
  var resolveContext = require('../utils/resolve-context.cjs');
5
- var findLoc = require('../utils/find-loc.cjs');
6
- var parseNodeRecursive = require('../utils/parse-node-recursive.cjs');
7
5
  var createRule = require('../create-rule.cjs');
8
6
  var settingsSchema = require('../settings-schema.cjs');
9
7
  var cssValidator = require('@master/css-validator');
@@ -27,44 +25,35 @@ var classValidation = createRule({
27
25
  defaultOptions: [],
28
26
  create: function(context) {
29
27
  const { options, settings, css } = resolveContext(context);
30
- const visitNode = (node, arg = null)=>{
31
- parseNodeRecursive.parseNodeRecursive(node, arg, (classNames, node)=>{
32
- const sourceCode = context.sourceCode;
33
- const sourceCodeLines = sourceCode.lines;
34
- const nodeStartLine = node.loc.start.line;
35
- const nodeStartColumn = node.loc.start.column;
36
- const nodeEndLine = node.loc.end.line;
37
- const nodeEndColumn = node.loc.end.column;
38
- for (const className of classNames){
39
- const { matched, errors } = cssValidator.validate(className, css);
40
- if (errors.length > 0) {
41
- for (const error of errors){
42
- if (matched) {
43
- context.report({
44
- loc: findLoc(className, sourceCodeLines, nodeStartLine, nodeStartColumn, nodeEndLine, nodeEndColumn),
45
- messageId: 'invalidClass',
46
- data: {
47
- message: error.message + '.'
48
- }
49
- });
50
- } else if (options.disallowUnknownClass) {
51
- context.report({
52
- loc: findLoc(className, sourceCodeLines, nodeStartLine, nodeStartColumn, nodeEndLine, nodeEndColumn),
53
- messageId: 'disallowUnknownClass',
54
- data: {
55
- message: `"${className}" is not a valid or known class.`
56
- }
57
- });
58
- }
59
- }
60
- }
61
- }
62
- }, false, false, settings.ignoredKeys, context);
63
- };
64
28
  return defineVisitors({
65
29
  context,
66
30
  settings
67
- }, visitNode);
31
+ }, (_, { classNodes })=>{
32
+ for (const node of classNodes){
33
+ const { matched, errors } = cssValidator.validate(node.value, css);
34
+ if (errors.length > 0) {
35
+ for (const error of errors){
36
+ if (matched) {
37
+ context.report({
38
+ node,
39
+ messageId: 'invalidClass',
40
+ data: {
41
+ message: error.message + '.'
42
+ }
43
+ });
44
+ } else if (options.disallowUnknownClass) {
45
+ context.report({
46
+ node,
47
+ messageId: 'disallowUnknownClass',
48
+ data: {
49
+ message: `"${node.raw}" is not a valid or known class.`
50
+ }
51
+ });
52
+ }
53
+ }
54
+ }
55
+ }
56
+ });
68
57
  }
69
58
  });
70
59
 
@@ -1,7 +1,5 @@
1
1
  import defineVisitors from '../utils/define-visitors.mjs';
2
2
  import resolveContext from '../utils/resolve-context.mjs';
3
- import findLoc from '../utils/find-loc.mjs';
4
- import { parseNodeRecursive } from '../utils/parse-node-recursive.mjs';
5
3
  import createRule from '../create-rule.mjs';
6
4
  import settingsSchema from '../settings-schema.mjs';
7
5
  import { validate } from '@master/css-validator';
@@ -25,44 +23,35 @@ var classValidation = createRule({
25
23
  defaultOptions: [],
26
24
  create: function(context) {
27
25
  const { options, settings, css } = resolveContext(context);
28
- const visitNode = (node, arg = null)=>{
29
- parseNodeRecursive(node, arg, (classNames, node)=>{
30
- const sourceCode = context.sourceCode;
31
- const sourceCodeLines = sourceCode.lines;
32
- const nodeStartLine = node.loc.start.line;
33
- const nodeStartColumn = node.loc.start.column;
34
- const nodeEndLine = node.loc.end.line;
35
- const nodeEndColumn = node.loc.end.column;
36
- for (const className of classNames){
37
- const { matched, errors } = validate(className, css);
38
- if (errors.length > 0) {
39
- for (const error of errors){
40
- if (matched) {
41
- context.report({
42
- loc: findLoc(className, sourceCodeLines, nodeStartLine, nodeStartColumn, nodeEndLine, nodeEndColumn),
43
- messageId: 'invalidClass',
44
- data: {
45
- message: error.message + '.'
46
- }
47
- });
48
- } else if (options.disallowUnknownClass) {
49
- context.report({
50
- loc: findLoc(className, sourceCodeLines, nodeStartLine, nodeStartColumn, nodeEndLine, nodeEndColumn),
51
- messageId: 'disallowUnknownClass',
52
- data: {
53
- message: `"${className}" is not a valid or known class.`
54
- }
55
- });
56
- }
57
- }
58
- }
59
- }
60
- }, false, false, settings.ignoredKeys, context);
61
- };
62
26
  return defineVisitors({
63
27
  context,
64
28
  settings
65
- }, visitNode);
29
+ }, (_, { classNodes })=>{
30
+ for (const node of classNodes){
31
+ const { matched, errors } = validate(node.value, css);
32
+ if (errors.length > 0) {
33
+ for (const error of errors){
34
+ if (matched) {
35
+ context.report({
36
+ node,
37
+ messageId: 'invalidClass',
38
+ data: {
39
+ message: error.message + '.'
40
+ }
41
+ });
42
+ } else if (options.disallowUnknownClass) {
43
+ context.report({
44
+ node,
45
+ messageId: 'disallowUnknownClass',
46
+ data: {
47
+ message: `"${node.raw}" is not a valid or known class.`
48
+ }
49
+ });
50
+ }
51
+ }
52
+ }
53
+ }
54
+ });
66
55
  }
67
56
  });
68
57
 
@@ -1,10 +1,12 @@
1
1
  'use strict';
2
2
 
3
+ var withVisitClassNode = require('./with-visit-class-node.cjs');
4
+
3
5
  function defineVisitors({ context, settings }, visitNode) {
4
6
  const classAttributeRegex = new RegExp(`^(?:${settings.classAttributes.join('|')})$`);
5
7
  const classFunctionsRegex = new RegExp(`^(?:${settings.classFunctions.join('|')})`);
6
8
  const classDeclarationsRegex = new RegExp(`^(?:${settings.classDeclarations.join('|')})$`);
7
- const isFnNode = (node)=>{
9
+ const allowCalleeNode = (node)=>{
8
10
  let calleeName = '';
9
11
  const calleeNode = node.callee || node.tag;
10
12
  if (calleeNode.type === 'Identifier') {
@@ -15,51 +17,48 @@ function defineVisitors({ context, settings }, visitNode) {
15
17
  }
16
18
  return classFunctionsRegex.test(calleeName);
17
19
  };
20
+ const visitClassNode = withVisitClassNode(visitNode, context);
18
21
  const CallExpression = function(node) {
19
- if (!isFnNode(node)) {
20
- return;
21
- }
22
- node.arguments.forEach((arg)=>{
23
- visitNode(node, arg);
22
+ if (!allowCalleeNode(node)) return;
23
+ node.arguments.forEach((node)=>{
24
+ visitClassNode(node);
24
25
  });
25
26
  };
26
27
  const scriptVisitor = {
27
28
  CallExpression,
28
29
  JSXAttribute: function(node) {
29
30
  if (!node.name || !classAttributeRegex.test(node.name.name)) return;
30
- if (node.value && node.value.type === 'Literal') {
31
- visitNode(node);
32
- } else if (node.value && node.value.type === 'JSXExpressionContainer') {
33
- visitNode(node, node.value.expression);
31
+ if (node.value) {
32
+ visitClassNode(node.value);
34
33
  }
35
34
  },
36
35
  SvelteAttribute: function(node) {
37
36
  if (!node.key?.name || !classAttributeRegex.test(node.key.name)) return;
38
37
  for (const eachValue of node.value){
39
- visitNode(node, eachValue);
38
+ visitClassNode(eachValue);
40
39
  }
41
40
  },
42
41
  TextAttribute: function(node) {
43
42
  if (!node.name || !classAttributeRegex.test(node.name)) return;
44
- visitNode(node);
43
+ visitClassNode(node);
45
44
  },
46
45
  TaggedTemplateExpression: function(node) {
47
- if (isFnNode(node)) {
48
- visitNode(node, node.quasi);
46
+ if (allowCalleeNode(node)) {
47
+ visitClassNode(node.quasi);
49
48
  return;
50
49
  }
51
50
  },
52
51
  VariableDeclaration: function(node) {
53
52
  node.declarations.forEach((decl)=>{
54
53
  if (decl.id.type === 'Identifier' && classDeclarationsRegex.test(decl.id.name)) {
55
- visitNode(node, decl.init);
54
+ visitClassNode(decl.init);
56
55
  }
57
56
  });
58
57
  },
59
58
  ObjectExpression: function(node) {
60
59
  node.properties.forEach((prop)=>{
61
60
  if (prop.type === 'Property' && prop.key.type === 'Identifier' && classDeclarationsRegex.test(prop.key.name)) {
62
- visitNode(node, prop.value);
61
+ visitClassNode(prop.value);
63
62
  }
64
63
  });
65
64
  }
@@ -67,16 +66,16 @@ function defineVisitors({ context, settings }, visitNode) {
67
66
  const templateBodyVisitor = {
68
67
  CallExpression,
69
68
  VAttribute: function(node) {
69
+ const name = node.key.argument?.name || node.key.name;
70
+ if (!name || !classAttributeRegex.test(name)) return;
70
71
  if (node.value && node.value.type === 'VLiteral') {
71
- visitNode(node);
72
- } else if (node.value && node.value.type === 'VExpressionContainer' && node.value.expression?.type === 'ArrayExpression') {
73
- node.value.expression.elements.forEach((arg)=>{
74
- visitNode(node, arg);
75
- });
76
- } else if (node.value && node.value.type === 'VExpressionContainer' && node.value.expression?.type === 'ObjectExpression') {
77
- node.value.expression.properties.forEach((prop)=>{
78
- visitNode(node, prop);
79
- });
72
+ visitClassNode(node.value);
73
+ } else if (node.value) {
74
+ if (node.value.type === 'VExpressionContainer') {
75
+ if (node.value.expression?.type === 'ArrayExpression' || node.value.expression?.type === 'ObjectExpression') {
76
+ visitClassNode(node.value.expression);
77
+ }
78
+ }
80
79
  }
81
80
  }
82
81
  };
@@ -1,7 +1,8 @@
1
1
  import { TSESTree } from '@typescript-eslint/utils';
2
2
  import type { RuleContext, RuleListener } from '@typescript-eslint/utils/ts-eslint';
3
3
  import { Settings } from '../settings';
4
+ import resolveClassNode from './resolve-class-node';
4
5
  export default function defineVisitors({ context, settings }: {
5
6
  context: RuleContext<any, any[]>;
6
7
  settings: Settings;
7
- }, visitNode: (node: TSESTree.Node, args?: any) => void): RuleListener;
8
+ }, visitNode: (node: TSESTree.Node, resolved: ReturnType<typeof resolveClassNode>) => void): RuleListener;
@@ -1,8 +1,10 @@
1
+ import withVisitClassNode from './with-visit-class-node.mjs';
2
+
1
3
  function defineVisitors({ context, settings }, visitNode) {
2
4
  const classAttributeRegex = new RegExp(`^(?:${settings.classAttributes.join('|')})$`);
3
5
  const classFunctionsRegex = new RegExp(`^(?:${settings.classFunctions.join('|')})`);
4
6
  const classDeclarationsRegex = new RegExp(`^(?:${settings.classDeclarations.join('|')})$`);
5
- const isFnNode = (node)=>{
7
+ const allowCalleeNode = (node)=>{
6
8
  let calleeName = '';
7
9
  const calleeNode = node.callee || node.tag;
8
10
  if (calleeNode.type === 'Identifier') {
@@ -13,51 +15,48 @@ function defineVisitors({ context, settings }, visitNode) {
13
15
  }
14
16
  return classFunctionsRegex.test(calleeName);
15
17
  };
18
+ const visitClassNode = withVisitClassNode(visitNode, context);
16
19
  const CallExpression = function(node) {
17
- if (!isFnNode(node)) {
18
- return;
19
- }
20
- node.arguments.forEach((arg)=>{
21
- visitNode(node, arg);
20
+ if (!allowCalleeNode(node)) return;
21
+ node.arguments.forEach((node)=>{
22
+ visitClassNode(node);
22
23
  });
23
24
  };
24
25
  const scriptVisitor = {
25
26
  CallExpression,
26
27
  JSXAttribute: function(node) {
27
28
  if (!node.name || !classAttributeRegex.test(node.name.name)) return;
28
- if (node.value && node.value.type === 'Literal') {
29
- visitNode(node);
30
- } else if (node.value && node.value.type === 'JSXExpressionContainer') {
31
- visitNode(node, node.value.expression);
29
+ if (node.value) {
30
+ visitClassNode(node.value);
32
31
  }
33
32
  },
34
33
  SvelteAttribute: function(node) {
35
34
  if (!node.key?.name || !classAttributeRegex.test(node.key.name)) return;
36
35
  for (const eachValue of node.value){
37
- visitNode(node, eachValue);
36
+ visitClassNode(eachValue);
38
37
  }
39
38
  },
40
39
  TextAttribute: function(node) {
41
40
  if (!node.name || !classAttributeRegex.test(node.name)) return;
42
- visitNode(node);
41
+ visitClassNode(node);
43
42
  },
44
43
  TaggedTemplateExpression: function(node) {
45
- if (isFnNode(node)) {
46
- visitNode(node, node.quasi);
44
+ if (allowCalleeNode(node)) {
45
+ visitClassNode(node.quasi);
47
46
  return;
48
47
  }
49
48
  },
50
49
  VariableDeclaration: function(node) {
51
50
  node.declarations.forEach((decl)=>{
52
51
  if (decl.id.type === 'Identifier' && classDeclarationsRegex.test(decl.id.name)) {
53
- visitNode(node, decl.init);
52
+ visitClassNode(decl.init);
54
53
  }
55
54
  });
56
55
  },
57
56
  ObjectExpression: function(node) {
58
57
  node.properties.forEach((prop)=>{
59
58
  if (prop.type === 'Property' && prop.key.type === 'Identifier' && classDeclarationsRegex.test(prop.key.name)) {
60
- visitNode(node, prop.value);
59
+ visitClassNode(prop.value);
61
60
  }
62
61
  });
63
62
  }
@@ -65,16 +64,16 @@ function defineVisitors({ context, settings }, visitNode) {
65
64
  const templateBodyVisitor = {
66
65
  CallExpression,
67
66
  VAttribute: function(node) {
67
+ const name = node.key.argument?.name || node.key.name;
68
+ if (!name || !classAttributeRegex.test(name)) return;
68
69
  if (node.value && node.value.type === 'VLiteral') {
69
- visitNode(node);
70
- } else if (node.value && node.value.type === 'VExpressionContainer' && node.value.expression?.type === 'ArrayExpression') {
71
- node.value.expression.elements.forEach((arg)=>{
72
- visitNode(node, arg);
73
- });
74
- } else if (node.value && node.value.type === 'VExpressionContainer' && node.value.expression?.type === 'ObjectExpression') {
75
- node.value.expression.properties.forEach((prop)=>{
76
- visitNode(node, prop);
77
- });
70
+ visitClassNode(node.value);
71
+ } else if (node.value) {
72
+ if (node.value.type === 'VExpressionContainer') {
73
+ if (node.value.expression?.type === 'ArrayExpression' || node.value.expression?.type === 'ObjectExpression') {
74
+ visitClassNode(node.value.expression);
75
+ }
76
+ }
78
77
  }
79
78
  }
80
79
  };
@@ -0,0 +1,144 @@
1
+ 'use strict';
2
+
3
+ var common = require('../common.cjs');
4
+
5
+ function resolveClassNode(node, context) {
6
+ const { sourceCode } = context;
7
+ let value = null;
8
+ let raw = null;
9
+ let start = null;
10
+ let end = null;
11
+ switch(node.type){
12
+ case 'Literal':
13
+ value = node.value;
14
+ raw = node.raw;
15
+ start = node.range[0];
16
+ end = node.range[1];
17
+ break;
18
+ case 'VLiteral':
19
+ value = node.value;
20
+ raw = sourceCode.getText(node);
21
+ start = node.range[0];
22
+ end = node.range[1];
23
+ break;
24
+ case 'TextAttribute':
25
+ value = node.value;
26
+ start = node.valueSpan.fullStart.offset;
27
+ end = node.valueSpan.end.offset;
28
+ raw = sourceCode.getText({
29
+ ...node,
30
+ range: [
31
+ start,
32
+ end
33
+ ]
34
+ });
35
+ break;
36
+ case 'SvelteLiteral':
37
+ value = node.value;
38
+ raw = sourceCode.getText(node);
39
+ start = node.range[0];
40
+ end = node.range[1];
41
+ break;
42
+ case 'TemplateElement':
43
+ if (node.parent.expressions.length) {
44
+ return;
45
+ }
46
+ value = node.value.cooked;
47
+ raw = node.value.raw;
48
+ start = node.range[0] + 1;
49
+ end = node.range[1] - 1;
50
+ break;
51
+ default:
52
+ return;
53
+ }
54
+ if (/^(['"`])(.*)\1$/.test(raw)) {
55
+ raw = raw.slice(1, -1);
56
+ start = start + 1;
57
+ end = end - 1;
58
+ }
59
+ const nodes = [];
60
+ const classValues = value.split(common.HALF_WIDTH_WHITESPACE_REGEX);
61
+ const classRaws = raw.split(common.HALF_WIDTH_WHITESPACE_REGEX);
62
+ const classValueRawMap = new Map();
63
+ const classRawValueMap = new Map();
64
+ for(let i = 0; i < classRaws.length; i++){
65
+ classValueRawMap.set(classValues[i], classRaws[i]);
66
+ classRawValueMap.set(classRaws[i], classValues[i]);
67
+ }
68
+ let lastIndex = 0;
69
+ let match;
70
+ while((match = common.HALF_WIDTH_WHITESPACE_GLOBAL_REGEX.exec(raw)) !== null){
71
+ const spaceRaw = match[0];
72
+ const spaceStart = match.index;
73
+ const spaceEnd = spaceStart + spaceRaw.length;
74
+ if (spaceStart > lastIndex) {
75
+ const classRaw = raw.slice(lastIndex, spaceStart);
76
+ const classValue = classRawValueMap.get(classRaw);
77
+ if (!classValue) return;
78
+ const startOffset = start + lastIndex;
79
+ const endOffset = start + spaceStart;
80
+ nodes.push({
81
+ type: 'class',
82
+ value: classValue,
83
+ raw: classRaw,
84
+ range: [
85
+ startOffset,
86
+ endOffset
87
+ ],
88
+ loc: {
89
+ start: sourceCode.getLocFromIndex(startOffset),
90
+ end: sourceCode.getLocFromIndex(endOffset)
91
+ }
92
+ });
93
+ }
94
+ const spaceStartOffset = start + spaceStart;
95
+ const spaceEndOffset = start + spaceEnd;
96
+ nodes.push({
97
+ type: 'space',
98
+ raw: spaceRaw,
99
+ range: [
100
+ spaceStartOffset,
101
+ spaceEndOffset
102
+ ],
103
+ loc: {
104
+ start: sourceCode.getLocFromIndex(spaceStartOffset),
105
+ end: sourceCode.getLocFromIndex(spaceEndOffset)
106
+ }
107
+ });
108
+ lastIndex = spaceEnd;
109
+ }
110
+ if (lastIndex < raw.length) {
111
+ const classRaw = raw.slice(lastIndex);
112
+ const classValue = classRawValueMap.get(classRaw);
113
+ if (!classValue) return;
114
+ const startOffset = start + lastIndex;
115
+ const endOffset = start + raw.length;
116
+ nodes.push({
117
+ type: 'class',
118
+ value: classValue,
119
+ raw: classRaw,
120
+ range: [
121
+ start,
122
+ endOffset
123
+ ],
124
+ loc: {
125
+ start: sourceCode.getLocFromIndex(startOffset),
126
+ end: sourceCode.getLocFromIndex(endOffset)
127
+ }
128
+ });
129
+ }
130
+ const classNodes = nodes.filter((node)=>node.type === 'class');
131
+ return {
132
+ nodes,
133
+ start,
134
+ end,
135
+ raw,
136
+ value,
137
+ classRawValueMap,
138
+ classValueRawMap,
139
+ classNodes,
140
+ classValues: classNodes.map((node)=>node.value)
141
+ };
142
+ }
143
+
144
+ module.exports = resolveClassNode;
@@ -0,0 +1,12 @@
1
+ import { RuleContext } from '@typescript-eslint/utils/ts-eslint';
2
+ export default function resolveClassNode(node: any, context: RuleContext<any, any[]>): {
3
+ nodes: any[];
4
+ start: number;
5
+ end: number;
6
+ raw: string;
7
+ value: string;
8
+ classRawValueMap: Map<any, any>;
9
+ classValueRawMap: Map<any, any>;
10
+ classNodes: any[];
11
+ classValues: any[];
12
+ };
@@ -0,0 +1,142 @@
1
+ import { HALF_WIDTH_WHITESPACE_REGEX, HALF_WIDTH_WHITESPACE_GLOBAL_REGEX } from '../common.mjs';
2
+
3
+ function resolveClassNode(node, context) {
4
+ const { sourceCode } = context;
5
+ let value = null;
6
+ let raw = null;
7
+ let start = null;
8
+ let end = null;
9
+ switch(node.type){
10
+ case 'Literal':
11
+ value = node.value;
12
+ raw = node.raw;
13
+ start = node.range[0];
14
+ end = node.range[1];
15
+ break;
16
+ case 'VLiteral':
17
+ value = node.value;
18
+ raw = sourceCode.getText(node);
19
+ start = node.range[0];
20
+ end = node.range[1];
21
+ break;
22
+ case 'TextAttribute':
23
+ value = node.value;
24
+ start = node.valueSpan.fullStart.offset;
25
+ end = node.valueSpan.end.offset;
26
+ raw = sourceCode.getText({
27
+ ...node,
28
+ range: [
29
+ start,
30
+ end
31
+ ]
32
+ });
33
+ break;
34
+ case 'SvelteLiteral':
35
+ value = node.value;
36
+ raw = sourceCode.getText(node);
37
+ start = node.range[0];
38
+ end = node.range[1];
39
+ break;
40
+ case 'TemplateElement':
41
+ if (node.parent.expressions.length) {
42
+ return;
43
+ }
44
+ value = node.value.cooked;
45
+ raw = node.value.raw;
46
+ start = node.range[0] + 1;
47
+ end = node.range[1] - 1;
48
+ break;
49
+ default:
50
+ return;
51
+ }
52
+ if (/^(['"`])(.*)\1$/.test(raw)) {
53
+ raw = raw.slice(1, -1);
54
+ start = start + 1;
55
+ end = end - 1;
56
+ }
57
+ const nodes = [];
58
+ const classValues = value.split(HALF_WIDTH_WHITESPACE_REGEX);
59
+ const classRaws = raw.split(HALF_WIDTH_WHITESPACE_REGEX);
60
+ const classValueRawMap = new Map();
61
+ const classRawValueMap = new Map();
62
+ for(let i = 0; i < classRaws.length; i++){
63
+ classValueRawMap.set(classValues[i], classRaws[i]);
64
+ classRawValueMap.set(classRaws[i], classValues[i]);
65
+ }
66
+ let lastIndex = 0;
67
+ let match;
68
+ while((match = HALF_WIDTH_WHITESPACE_GLOBAL_REGEX.exec(raw)) !== null){
69
+ const spaceRaw = match[0];
70
+ const spaceStart = match.index;
71
+ const spaceEnd = spaceStart + spaceRaw.length;
72
+ if (spaceStart > lastIndex) {
73
+ const classRaw = raw.slice(lastIndex, spaceStart);
74
+ const classValue = classRawValueMap.get(classRaw);
75
+ if (!classValue) return;
76
+ const startOffset = start + lastIndex;
77
+ const endOffset = start + spaceStart;
78
+ nodes.push({
79
+ type: 'class',
80
+ value: classValue,
81
+ raw: classRaw,
82
+ range: [
83
+ startOffset,
84
+ endOffset
85
+ ],
86
+ loc: {
87
+ start: sourceCode.getLocFromIndex(startOffset),
88
+ end: sourceCode.getLocFromIndex(endOffset)
89
+ }
90
+ });
91
+ }
92
+ const spaceStartOffset = start + spaceStart;
93
+ const spaceEndOffset = start + spaceEnd;
94
+ nodes.push({
95
+ type: 'space',
96
+ raw: spaceRaw,
97
+ range: [
98
+ spaceStartOffset,
99
+ spaceEndOffset
100
+ ],
101
+ loc: {
102
+ start: sourceCode.getLocFromIndex(spaceStartOffset),
103
+ end: sourceCode.getLocFromIndex(spaceEndOffset)
104
+ }
105
+ });
106
+ lastIndex = spaceEnd;
107
+ }
108
+ if (lastIndex < raw.length) {
109
+ const classRaw = raw.slice(lastIndex);
110
+ const classValue = classRawValueMap.get(classRaw);
111
+ if (!classValue) return;
112
+ const startOffset = start + lastIndex;
113
+ const endOffset = start + raw.length;
114
+ nodes.push({
115
+ type: 'class',
116
+ value: classValue,
117
+ raw: classRaw,
118
+ range: [
119
+ start,
120
+ endOffset
121
+ ],
122
+ loc: {
123
+ start: sourceCode.getLocFromIndex(startOffset),
124
+ end: sourceCode.getLocFromIndex(endOffset)
125
+ }
126
+ });
127
+ }
128
+ const classNodes = nodes.filter((node)=>node.type === 'class');
129
+ return {
130
+ nodes,
131
+ start,
132
+ end,
133
+ raw,
134
+ value,
135
+ classRawValueMap,
136
+ classValueRawMap,
137
+ classNodes,
138
+ classValues: classNodes.map((node)=>node.value)
139
+ };
140
+ }
141
+
142
+ export { resolveClassNode as default };