@plumeria/eslint-plugin 19.15.0 → 21.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -125,7 +125,7 @@ Disallow calling APIs inside functions.
125
125
 
126
126
  ### no-invalid-selector
127
127
 
128
- Disallow invalid selector inside `css.create()` and `css.keyframes()` and `css.viewTransition()`.
128
+ Disallow invalid selector inside `css.create()` and `css.keyframes()` and `css.viewTransitionClass()`.
129
129
  `create()` example: (Pseudo -> Query, Query -> Query)
130
130
  Also reports a functional pseudo-class nested inside one of the same name, such as `:where(:where(.a), .b)`, and flattens it with a fix when the nested call is a whole argument. `:not()` may nest inside `:not()`. Reports a key nested deeper than 16 levels or holding a stray quote.
131
131
 
@@ -162,7 +162,7 @@ Accepts `{ styleProp }`; see [Configuring the styling prop](#configuring-the-sty
162
162
 
163
163
  ### no-unknown-css-properties
164
164
 
165
- Disallow unknown CSS properties in camelCase within `css.create`, `css.keyframes`, and `css.viewTransition`.
165
+ Disallow unknown CSS properties in camelCase within `css.create`, `css.keyframes`, `css.viewTransitionClass`, and `css.positionTry`. Inside `css.positionTry`, it also reports properties that `@position-try` does not accept.
166
166
 
167
167
  In `css.create`, a key that holds an object is reported with a hint that nested selectors start with `:`, `[` or `@`.
168
168
 
@@ -197,7 +197,7 @@ Validates CSS pseudo-classes and pseudo-elements inside `css.create()`. It check
197
197
 
198
198
  ### validate-at-rules
199
199
 
200
- Validates at-rules inside `css.create()`. It accepts `@media`, `@container`, `@supports`, `@layer`, and `@scope`, each with a prelude, whether or not a space separates it from the keyword, and supports validation of computed keys when TypeScript is available.
200
+ Validates at-rules inside `css.create()`. It accepts `@media`, `@container`, and `@supports`, each with a prelude, whether or not a space separates it from the keyword, and `@starting-style` on its own, and supports validation of computed keys when TypeScript is available.
201
201
 
202
202
  ## Optional rules
203
203
 
@@ -41,6 +41,7 @@ exports.expandBorderShorthands = {
41
41
  },
42
42
  CallExpression(node) {
43
43
  let isCssProperties = false;
44
+ let isPositionTry = false;
44
45
  if (node.callee.type === 'MemberExpression') {
45
46
  if (node.callee.object.type === 'Identifier' &&
46
47
  plumeriaAliases[node.callee.object.name] === 'NAMESPACE') {
@@ -49,8 +50,10 @@ exports.expandBorderShorthands = {
49
50
  : null;
50
51
  if (propertyName === 'create' ||
51
52
  propertyName === 'keyframes' ||
52
- propertyName === 'viewTransition') {
53
+ propertyName === 'viewTransitionClass' ||
54
+ propertyName === 'positionTry') {
53
55
  isCssProperties = true;
56
+ isPositionTry = propertyName === 'positionTry';
54
57
  }
55
58
  }
56
59
  }
@@ -58,13 +61,19 @@ exports.expandBorderShorthands = {
58
61
  const aliasName = plumeriaAliases[node.callee.name];
59
62
  if (aliasName === 'create' ||
60
63
  aliasName === 'keyframes' ||
61
- aliasName === 'viewTransition') {
64
+ aliasName === 'viewTransitionClass' ||
65
+ aliasName === 'positionTry') {
62
66
  isCssProperties = true;
67
+ isPositionTry = aliasName === 'positionTry';
63
68
  }
64
69
  }
65
70
  if (isCssProperties) {
66
71
  node.arguments.forEach((arg) => {
67
72
  if (arg.type === 'ObjectExpression') {
73
+ if (isPositionTry) {
74
+ checkStyleObject(arg);
75
+ return;
76
+ }
68
77
  arg.properties.forEach((prop) => {
69
78
  if (prop.type !== 'Property')
70
79
  return;
@@ -140,6 +140,7 @@ exports.formatProperties = {
140
140
  },
141
141
  CallExpression(node) {
142
142
  let isCssProperties = false;
143
+ let isPositionTry = false;
143
144
  if (node.callee.type === 'MemberExpression') {
144
145
  if (node.callee.object.type === 'Identifier' &&
145
146
  plumeriaAliases[node.callee.object.name] === 'NAMESPACE') {
@@ -148,8 +149,10 @@ exports.formatProperties = {
148
149
  : null;
149
150
  if (propertyName === 'create' ||
150
151
  propertyName === 'keyframes' ||
151
- propertyName === 'viewTransition') {
152
+ propertyName === 'viewTransitionClass' ||
153
+ propertyName === 'positionTry') {
152
154
  isCssProperties = true;
155
+ isPositionTry = propertyName === 'positionTry';
153
156
  }
154
157
  }
155
158
  }
@@ -157,13 +160,19 @@ exports.formatProperties = {
157
160
  const alias = plumeriaAliases[node.callee.name];
158
161
  if (alias === 'create' ||
159
162
  alias === 'keyframes' ||
160
- alias === 'viewTransition') {
163
+ alias === 'viewTransitionClass' ||
164
+ alias === 'positionTry') {
161
165
  isCssProperties = true;
166
+ isPositionTry = alias === 'positionTry';
162
167
  }
163
168
  }
164
169
  if (isCssProperties) {
165
170
  node.arguments.forEach((arg) => {
166
171
  if (arg.type === 'ObjectExpression') {
172
+ if (isPositionTry) {
173
+ checkStyleObject(arg);
174
+ return;
175
+ }
167
176
  arg.properties.forEach((prop) => {
168
177
  if (prop.type !== 'Property')
169
178
  return;
@@ -48,7 +48,8 @@ exports.noDestructure = {
48
48
  keyName === 'createStatic' ||
49
49
  keyName === 'createTheme' ||
50
50
  keyName === 'keyframes' ||
51
- keyName === 'viewTransition' ||
51
+ keyName === 'viewTransitionClass' ||
52
+ keyName === 'positionTry' ||
52
53
  keyName === 'varType' ||
53
54
  keyName === 'use') {
54
55
  context.report({
@@ -80,7 +80,8 @@ exports.noInnerCall = {
80
80
  propertyName === 'createStatic' ||
81
81
  propertyName === 'createTheme' ||
82
82
  propertyName === 'keyframes' ||
83
- propertyName === 'viewTransition' ||
83
+ propertyName === 'viewTransitionClass' ||
84
+ propertyName === 'positionTry' ||
84
85
  propertyName === 'varType') {
85
86
  context.report({
86
87
  node,
@@ -425,7 +425,7 @@ exports.noInvalidSelector = {
425
425
  isCssCreate = true;
426
426
  if (propertyName === 'keyframes')
427
427
  isCssKeyframes = true;
428
- if (propertyName === 'viewTransition')
428
+ if (propertyName === 'viewTransitionClass')
429
429
  isCssViewTransition = true;
430
430
  }
431
431
  }
@@ -435,7 +435,7 @@ exports.noInvalidSelector = {
435
435
  isCssCreate = true;
436
436
  if (alias === 'keyframes')
437
437
  isCssKeyframes = true;
438
- if (alias === 'viewTransition')
438
+ if (alias === 'viewTransitionClass')
439
439
  isCssViewTransition = true;
440
440
  }
441
441
  if (isCssCreate && node.arguments[0]?.type === 'ObjectExpression') {
@@ -6,7 +6,8 @@ const STYLE_APIS = new Set([
6
6
  'createStatic',
7
7
  'createTheme',
8
8
  'keyframes',
9
- 'viewTransition',
9
+ 'viewTransitionClass',
10
+ 'positionTry',
10
11
  'varType',
11
12
  ]);
12
13
  const isReference = (node, parent) => {
@@ -115,6 +115,7 @@ exports.noOrderDependentOverlap = {
115
115
  },
116
116
  CallExpression(node) {
117
117
  let isCssProperties = false;
118
+ let isPositionTry = false;
118
119
  if (node.callee.type === 'MemberExpression') {
119
120
  if (node.callee.object.type === 'Identifier' &&
120
121
  plumeriaAliases[node.callee.object.name] === 'NAMESPACE') {
@@ -123,8 +124,10 @@ exports.noOrderDependentOverlap = {
123
124
  : null;
124
125
  if (propertyName === 'create' ||
125
126
  propertyName === 'keyframes' ||
126
- propertyName === 'viewTransition') {
127
+ propertyName === 'viewTransitionClass' ||
128
+ propertyName === 'positionTry') {
127
129
  isCssProperties = true;
130
+ isPositionTry = propertyName === 'positionTry';
128
131
  }
129
132
  }
130
133
  }
@@ -132,13 +135,19 @@ exports.noOrderDependentOverlap = {
132
135
  const aliasName = plumeriaAliases[node.callee.name];
133
136
  if (aliasName === 'create' ||
134
137
  aliasName === 'keyframes' ||
135
- aliasName === 'viewTransition') {
138
+ aliasName === 'viewTransitionClass' ||
139
+ aliasName === 'positionTry') {
136
140
  isCssProperties = true;
141
+ isPositionTry = aliasName === 'positionTry';
137
142
  }
138
143
  }
139
144
  if (isCssProperties) {
140
145
  node.arguments.forEach((arg) => {
141
146
  if (arg.type === 'ObjectExpression') {
147
+ if (isPositionTry) {
148
+ checkStyleObject(arg);
149
+ return;
150
+ }
142
151
  arg.properties.forEach((prop) => {
143
152
  if (prop.type !== 'Property')
144
153
  return;
@@ -5,15 +5,57 @@ const zss_engine_1 = require("zss-engine");
5
5
  const styleObject_1 = require("../util/styleObject");
6
6
  const cssPropertyData_1 = require("../util/cssPropertyData");
7
7
  const knownProperties = new Set(cssPropertyData_1.cssPropertyData);
8
+ const positionTryProperties = new Set([
9
+ 'position-anchor',
10
+ 'position-area',
11
+ 'inset',
12
+ 'inset-block',
13
+ 'inset-block-start',
14
+ 'inset-block-end',
15
+ 'inset-inline',
16
+ 'inset-inline-start',
17
+ 'inset-inline-end',
18
+ 'top',
19
+ 'right',
20
+ 'bottom',
21
+ 'left',
22
+ 'place-self',
23
+ 'align-self',
24
+ 'justify-self',
25
+ 'inline-size',
26
+ 'min-inline-size',
27
+ 'max-inline-size',
28
+ 'width',
29
+ 'min-width',
30
+ 'max-width',
31
+ 'block-size',
32
+ 'min-block-size',
33
+ 'max-block-size',
34
+ 'height',
35
+ 'min-height',
36
+ 'max-height',
37
+ 'margin',
38
+ 'margin-block',
39
+ 'margin-block-start',
40
+ 'margin-block-end',
41
+ 'margin-inline',
42
+ 'margin-inline-start',
43
+ 'margin-inline-end',
44
+ 'margin-top',
45
+ 'margin-right',
46
+ 'margin-bottom',
47
+ 'margin-left',
48
+ ]);
8
49
  exports.noUnknownCssProperties = {
9
50
  meta: {
10
51
  type: 'problem',
11
52
  docs: {
12
- description: 'Disallow unknown CSS properties in camelCase within css.create, css.keyframes, and css.viewTransition',
53
+ description: 'Disallow unknown CSS properties in camelCase within css.create, css.keyframes, css.viewTransitionClass, and css.positionTry',
13
54
  },
14
55
  messages: {
15
56
  unknownProperty: "Unknown CSS property '{{ name }}'.",
16
57
  unknownNestedProperty: "Unknown CSS property '{{ name }}'. Nested selectors start with ':', '[' or '@'.",
58
+ positionTryProperty: "'{{ name }}' cannot be used in css.positionTry. @position-try only accepts inset, margin, sizing and self-alignment properties, positionAnchor and positionArea.",
17
59
  },
18
60
  schema: [],
19
61
  },
@@ -39,6 +81,7 @@ exports.noUnknownCssProperties = {
39
81
  },
40
82
  CallExpression(node) {
41
83
  let isCssProperties = false;
84
+ let isPositionTry = false;
42
85
  let isCreate = false;
43
86
  if (node.callee.type === 'MemberExpression') {
44
87
  if (node.callee.object.type === 'Identifier' &&
@@ -48,8 +91,10 @@ exports.noUnknownCssProperties = {
48
91
  : null;
49
92
  if (propertyName === 'create' ||
50
93
  propertyName === 'keyframes' ||
51
- propertyName === 'viewTransition') {
94
+ propertyName === 'viewTransitionClass' ||
95
+ propertyName === 'positionTry') {
52
96
  isCssProperties = true;
97
+ isPositionTry = propertyName === 'positionTry';
53
98
  isCreate = propertyName === 'create';
54
99
  }
55
100
  }
@@ -58,14 +103,20 @@ exports.noUnknownCssProperties = {
58
103
  const alias = plumeriaAliases[node.callee.name];
59
104
  if (alias === 'create' ||
60
105
  alias === 'keyframes' ||
61
- alias === 'viewTransition') {
106
+ alias === 'viewTransitionClass' ||
107
+ alias === 'positionTry') {
62
108
  isCssProperties = true;
109
+ isPositionTry = alias === 'positionTry';
63
110
  isCreate = alias === 'create';
64
111
  }
65
112
  }
66
113
  if (isCssProperties) {
67
114
  node.arguments.forEach((arg) => {
68
115
  if (arg.type === 'ObjectExpression') {
116
+ if (isPositionTry) {
117
+ checkPositionTry(arg);
118
+ return;
119
+ }
69
120
  arg.properties.forEach((prop) => {
70
121
  if (prop.type !== 'Property')
71
122
  return;
@@ -78,6 +129,38 @@ exports.noUnknownCssProperties = {
78
129
  }
79
130
  },
80
131
  };
132
+ function checkPositionTry(node) {
133
+ node.properties.forEach((prop) => {
134
+ if (prop.type !== 'Property')
135
+ return;
136
+ let keyName;
137
+ if (!prop.computed) {
138
+ keyName =
139
+ prop.key.type === 'Identifier'
140
+ ? prop.key.name
141
+ : String(prop.key.value);
142
+ }
143
+ else if (prop.key.type === 'Literal' &&
144
+ typeof prop.key.value === 'string') {
145
+ keyName = prop.key.value;
146
+ }
147
+ else {
148
+ return;
149
+ }
150
+ const kebabName = (0, zss_engine_1.camelToKebabCase)(keyName);
151
+ if (positionTryProperties.has(kebabName))
152
+ return;
153
+ context.report({
154
+ node: prop.key,
155
+ messageId: /^[:[@]|^--/.test(keyName) || knownProperties.has(kebabName)
156
+ ? 'positionTryProperty'
157
+ : 'unknownProperty',
158
+ data: {
159
+ name: keyName,
160
+ },
161
+ });
162
+ });
163
+ }
81
164
  function checkStyleObject(node, isCreate) {
82
165
  node.properties.forEach((prop) => {
83
166
  if (prop.type === 'Property') {
@@ -188,6 +188,7 @@ exports.sortProperties = {
188
188
  },
189
189
  CallExpression(node) {
190
190
  let isCssProperties = false;
191
+ let isPositionTry = false;
191
192
  if (node.callee.type === 'MemberExpression') {
192
193
  if (node.callee.object.type === 'Identifier' &&
193
194
  plumeriaAliases[node.callee.object.name] === 'NAMESPACE') {
@@ -196,8 +197,10 @@ exports.sortProperties = {
196
197
  : null;
197
198
  if (propertyName === 'create' ||
198
199
  propertyName === 'keyframes' ||
199
- propertyName === 'viewTransition') {
200
+ propertyName === 'viewTransitionClass' ||
201
+ propertyName === 'positionTry') {
200
202
  isCssProperties = true;
203
+ isPositionTry = propertyName === 'positionTry';
201
204
  }
202
205
  }
203
206
  }
@@ -205,13 +208,19 @@ exports.sortProperties = {
205
208
  const alias = plumeriaAliases[node.callee.name];
206
209
  if (alias === 'create' ||
207
210
  alias === 'keyframes' ||
208
- alias === 'viewTransition') {
211
+ alias === 'viewTransitionClass' ||
212
+ alias === 'positionTry') {
209
213
  isCssProperties = true;
214
+ isPositionTry = alias === 'positionTry';
210
215
  }
211
216
  }
212
217
  if (isCssProperties) {
213
218
  node.arguments.forEach((arg) => {
214
219
  if (arg.type === 'ObjectExpression') {
220
+ if (isPositionTry) {
221
+ checkStyleObject(arg);
222
+ return;
223
+ }
215
224
  arg.properties.forEach((prop) => {
216
225
  if (prop.type !== 'Property')
217
226
  return;
@@ -4,14 +4,10 @@ exports.validateAtRules = void 0;
4
4
  exports.isValidAtRule = isValidAtRule;
5
5
  const styleObject_1 = require("../util/styleObject");
6
6
  const staticValue_1 = require("../util/staticValue");
7
- const VALID_AT_RULES = [
8
- '@media',
9
- '@container',
10
- '@supports',
11
- '@layer',
12
- '@scope',
13
- ];
7
+ const VALID_AT_RULES = ['@media', '@container', '@supports'];
14
8
  function isValidAtRule(rule) {
9
+ if (rule === '@starting-style')
10
+ return true;
15
11
  return VALID_AT_RULES.some((keyword) => {
16
12
  if (!rule.startsWith(keyword))
17
13
  return false;
@@ -2123,6 +2123,7 @@ exports.validateValues = {
2123
2123
  return;
2124
2124
  }
2125
2125
  let isCssProperties = false;
2126
+ let isPositionTry = false;
2126
2127
  if (node.callee.type === 'MemberExpression') {
2127
2128
  if (node.callee.object.type === 'Identifier' &&
2128
2129
  plumeriaAliases[node.callee.object.name] === 'NAMESPACE') {
@@ -2131,8 +2132,10 @@ exports.validateValues = {
2131
2132
  : null;
2132
2133
  if (propertyName === 'create' ||
2133
2134
  propertyName === 'keyframes' ||
2134
- propertyName === 'viewTransition') {
2135
+ propertyName === 'viewTransitionClass' ||
2136
+ propertyName === 'positionTry') {
2135
2137
  isCssProperties = true;
2138
+ isPositionTry = propertyName === 'positionTry';
2136
2139
  }
2137
2140
  }
2138
2141
  }
@@ -2140,14 +2143,20 @@ exports.validateValues = {
2140
2143
  const alias = plumeriaAliases[node.callee.name];
2141
2144
  if (alias === 'create' ||
2142
2145
  alias === 'keyframes' ||
2143
- alias === 'viewTransition') {
2146
+ alias === 'viewTransitionClass' ||
2147
+ alias === 'positionTry') {
2144
2148
  isCssProperties = true;
2149
+ isPositionTry = alias === 'positionTry';
2145
2150
  }
2146
2151
  }
2147
2152
  if (!isCssProperties)
2148
2153
  return;
2149
2154
  node.arguments.forEach((arg) => {
2150
2155
  if (arg.type === 'ObjectExpression') {
2156
+ if (isPositionTry) {
2157
+ checkStyleObject(arg);
2158
+ return;
2159
+ }
2151
2160
  arg.properties.forEach((prop) => {
2152
2161
  if (prop.type !== 'Property')
2153
2162
  return;
@@ -11,6 +11,14 @@ exports.propertyGroups = [
11
11
  {
12
12
  properties: [
13
13
  'position',
14
+ 'positionAnchor',
15
+ 'positionArea',
16
+ 'positionTry',
17
+ 'positionTryOrder',
18
+ 'positionTryFallbacks',
19
+ 'positionVisibility',
20
+ 'anchorName',
21
+ 'anchorScope',
14
22
  'inset',
15
23
  'insetBlock',
16
24
  'insetBlockStart',
@@ -53,6 +53,7 @@ const createSpellingRule = (reject) => ({
53
53
  },
54
54
  CallExpression(node) {
55
55
  let isCssProperties = false;
56
+ let isPositionTry = false;
56
57
  if (node.callee.type === 'MemberExpression') {
57
58
  if (node.callee.object.type === 'Identifier' &&
58
59
  plumeriaAliases[node.callee.object.name] === 'NAMESPACE') {
@@ -61,8 +62,10 @@ const createSpellingRule = (reject) => ({
61
62
  : null;
62
63
  if (propertyName === 'create' ||
63
64
  propertyName === 'keyframes' ||
64
- propertyName === 'viewTransition') {
65
+ propertyName === 'viewTransitionClass' ||
66
+ propertyName === 'positionTry') {
65
67
  isCssProperties = true;
68
+ isPositionTry = propertyName === 'positionTry';
66
69
  }
67
70
  }
68
71
  }
@@ -70,13 +73,19 @@ const createSpellingRule = (reject) => ({
70
73
  const aliasName = plumeriaAliases[node.callee.name];
71
74
  if (aliasName === 'create' ||
72
75
  aliasName === 'keyframes' ||
73
- aliasName === 'viewTransition') {
76
+ aliasName === 'viewTransitionClass' ||
77
+ aliasName === 'positionTry') {
74
78
  isCssProperties = true;
79
+ isPositionTry = aliasName === 'positionTry';
75
80
  }
76
81
  }
77
82
  if (isCssProperties) {
78
83
  node.arguments.forEach((arg) => {
79
84
  if (arg.type === 'ObjectExpression') {
85
+ if (isPositionTry) {
86
+ checkStyleObject(arg);
87
+ return;
88
+ }
80
89
  arg.properties.forEach((prop) => {
81
90
  if (prop.type !== 'Property')
82
91
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plumeria/eslint-plugin",
3
- "version": "19.15.0",
3
+ "version": "21.0.0",
4
4
  "description": "Plumeria ESLint plugin",
5
5
  "author": "Refirst 11",
6
6
  "license": "MIT",
@@ -58,8 +58,8 @@
58
58
  },
59
59
  "dependencies": {
60
60
  "oxlint": "1.87.0",
61
- "zss-engine": "2.10.0",
62
- "@plumeria/compiler": "19.15.0"
61
+ "zss-engine": "3.0.1",
62
+ "@plumeria/compiler": "21.0.0"
63
63
  },
64
64
  "scripts": {
65
65
  "build": "rimraf dist && pnpm cjs",