@lvce-editor/eslint-plugin-virtual-dom 16.4.0 → 17.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.
Files changed (2) hide show
  1. package/dist/index.js +175 -30
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -77,7 +77,7 @@ const isStringLiteral = node => {
77
77
  return isLiteralNode(node) && typeof node.value === 'string';
78
78
  };
79
79
 
80
- const meta$a = {
80
+ const meta$c = {
81
81
  docs: {
82
82
  description: 'Require an explicit role on clickable virtual-dom div nodes'
83
83
  },
@@ -86,7 +86,7 @@ const meta$a = {
86
86
  },
87
87
  type: 'problem'
88
88
  };
89
- const create$a = context => {
89
+ const create$c = context => {
90
90
  return {
91
91
  ObjectExpression(node) {
92
92
  if (!isVirtualDomNode(node)) {
@@ -108,11 +108,112 @@ const create$a = context => {
108
108
 
109
109
  const clickableDivNeedsRole = {
110
110
  __proto__: null,
111
- create: create$a,
112
- meta: meta$a
111
+ create: create$c,
112
+ meta: meta$c
113
113
  };
114
114
 
115
- const meta$9 = {
115
+ const meta$b = {
116
+ docs: {
117
+ description: 'Require static virtual-dom nodes created inside functions to be hoisted to module scope'
118
+ },
119
+ messages: {
120
+ hoistStaticNode: 'Hoist this static virtual-dom node to module scope.'
121
+ },
122
+ type: 'suggestion'
123
+ };
124
+ const isFunctionNode$1 = node => {
125
+ return ['ArrowFunctionExpression', 'FunctionDeclaration', 'FunctionExpression'].includes(node.type);
126
+ };
127
+ const findVariable = (sourceCode, identifier) => {
128
+ let scope = sourceCode.getScope(identifier);
129
+ while (scope) {
130
+ const variable = scope.set.get(identifier.name);
131
+ if (variable) {
132
+ return variable;
133
+ }
134
+ scope = scope.upper;
135
+ }
136
+ return undefined;
137
+ };
138
+ const isStaticModuleVariable = variable => {
139
+ if (!['global', 'module'].includes(variable.scope.type)) {
140
+ return false;
141
+ }
142
+ return variable.defs.every(definition => {
143
+ if (['ClassName', 'FunctionName', 'ImportBinding'].includes(definition.type)) {
144
+ return true;
145
+ }
146
+ return definition.type === 'Variable' && definition.parent.kind === 'const';
147
+ });
148
+ };
149
+ const isStaticIdentifier = (sourceCode, node) => {
150
+ const variable = findVariable(sourceCode, node);
151
+ return Boolean(variable && isStaticModuleVariable(variable));
152
+ };
153
+ const isStaticProperty = (sourceCode, node) => {
154
+ if (node.type === 'SpreadElement' || node.kind !== 'init' || node.method) {
155
+ return false;
156
+ }
157
+ if (node.computed && !isStaticExpression(sourceCode, node.key)) {
158
+ return false;
159
+ }
160
+ return isStaticExpression(sourceCode, node.value);
161
+ };
162
+ const isStaticExpression = (sourceCode, node) => {
163
+ if (!node) {
164
+ return true;
165
+ }
166
+ switch (node.type) {
167
+ case 'ArrayExpression':
168
+ return node.elements.every(element => !element || element.type !== 'SpreadElement' && isStaticExpression(sourceCode, element));
169
+ case 'BinaryExpression':
170
+ case 'LogicalExpression':
171
+ return isStaticExpression(sourceCode, node.left) && isStaticExpression(sourceCode, node.right);
172
+ case 'ConditionalExpression':
173
+ return isStaticExpression(sourceCode, node.test) && isStaticExpression(sourceCode, node.consequent) && isStaticExpression(sourceCode, node.alternate);
174
+ case 'Identifier':
175
+ return isStaticIdentifier(sourceCode, node);
176
+ case 'Literal':
177
+ return true;
178
+ case 'MemberExpression':
179
+ return isStaticExpression(sourceCode, node.object) && (!node.computed || node.property.type !== 'PrivateIdentifier' && isStaticExpression(sourceCode, node.property));
180
+ case 'ObjectExpression':
181
+ return node.properties.every(property => isStaticProperty(sourceCode, property));
182
+ case 'TemplateLiteral':
183
+ return node.expressions.every(expression => isStaticExpression(sourceCode, expression));
184
+ case 'UnaryExpression':
185
+ return node.operator !== 'delete' && isStaticExpression(sourceCode, node.argument);
186
+ default:
187
+ return false;
188
+ }
189
+ };
190
+ const create$b = context => {
191
+ return {
192
+ ObjectExpression(node) {
193
+ if (!isVirtualDomNode(node)) {
194
+ return;
195
+ }
196
+ if (!context.sourceCode.getAncestors(node).some(isFunctionNode$1)) {
197
+ return;
198
+ }
199
+ if (!isStaticExpression(context.sourceCode, node)) {
200
+ return;
201
+ }
202
+ context.report({
203
+ messageId: 'hoistStaticNode',
204
+ node
205
+ });
206
+ }
207
+ };
208
+ };
209
+
210
+ const hoistStaticNodes = {
211
+ __proto__: null,
212
+ create: create$b,
213
+ meta: meta$b
214
+ };
215
+
216
+ const meta$a = {
116
217
  docs: {
117
218
  description: 'Disallow empty ARIA values in virtual-dom nodes'
118
219
  },
@@ -124,7 +225,7 @@ const meta$9 = {
124
225
  const isAriaProperty = name => {
125
226
  return /^aria[A-Z]/.test(name);
126
227
  };
127
- const create$9 = context => {
228
+ const create$a = context => {
128
229
  return {
129
230
  ObjectExpression(node) {
130
231
  if (!isVirtualDomNode(node)) {
@@ -149,11 +250,11 @@ const create$9 = context => {
149
250
 
150
251
  const noEmptyAria = {
151
252
  __proto__: null,
152
- create: create$9,
153
- meta: meta$9
253
+ create: create$a,
254
+ meta: meta$a
154
255
  };
155
256
 
156
- const meta$8 = {
257
+ const meta$9 = {
157
258
  docs: {
158
259
  description: 'Disallow empty className values in virtual-dom nodes'
159
260
  },
@@ -162,7 +263,7 @@ const meta$8 = {
162
263
  },
163
264
  type: 'problem'
164
265
  };
165
- const create$8 = context => {
266
+ const create$9 = context => {
166
267
  return {
167
268
  ObjectExpression(node) {
168
269
  if (!isVirtualDomNode(node)) {
@@ -182,11 +283,11 @@ const create$8 = context => {
182
283
 
183
284
  const noEmptyClassName = {
184
285
  __proto__: null,
185
- create: create$8,
186
- meta: meta$8
286
+ create: create$9,
287
+ meta: meta$9
187
288
  };
188
289
 
189
- const meta$7 = {
290
+ const meta$8 = {
190
291
  docs: {
191
292
  description: 'Disallow inline event handlers in virtual-dom nodes'
192
293
  },
@@ -201,7 +302,7 @@ const isEventPropertyName = name => {
201
302
  const isInlineEventHandler = node => {
202
303
  return isStringLiteral(node) || isTemplateLiteralNode(node) || isArrowFunctionExpressionNode(node) || isFunctionExpressionNode(node);
203
304
  };
204
- const create$7 = context => {
305
+ const create$8 = context => {
205
306
  return {
206
307
  ObjectExpression(node) {
207
308
  if (!isVirtualDomNode(node)) {
@@ -226,11 +327,11 @@ const create$7 = context => {
226
327
 
227
328
  const noInlineEventHandlers = {
228
329
  __proto__: null,
229
- create: create$7,
230
- meta: meta$7
330
+ create: create$8,
331
+ meta: meta$8
231
332
  };
232
333
 
233
- const meta$6 = {
334
+ const meta$7 = {
234
335
  docs: {
235
336
  description: 'Disallow inline style attributes in virtual-dom nodes'
236
337
  },
@@ -239,7 +340,7 @@ const meta$6 = {
239
340
  },
240
341
  type: 'problem'
241
342
  };
242
- const create$6 = context => {
343
+ const create$7 = context => {
243
344
  return {
244
345
  ObjectExpression(node) {
245
346
  if (!isVirtualDomNode(node)) {
@@ -259,11 +360,11 @@ const create$6 = context => {
259
360
 
260
361
  const noInlineStyle = {
261
362
  __proto__: null,
262
- create: create$6,
263
- meta: meta$6
363
+ create: create$7,
364
+ meta: meta$7
264
365
  };
265
366
 
266
- const meta$5 = {
367
+ const meta$6 = {
267
368
  docs: {
268
369
  description: 'Disallow object-like attribute values in virtual-dom nodes'
269
370
  },
@@ -276,7 +377,7 @@ const ignoredProperties = new Set(['childCount', 'type']);
276
377
  const isObjectLikeAttributeValue = node => {
277
378
  return isObjectExpressionNode(node) || isArrayExpressionNode(node) || isArrowFunctionExpressionNode(node) || isFunctionExpressionNode(node);
278
379
  };
279
- const create$5 = context => {
380
+ const create$6 = context => {
280
381
  return {
281
382
  ObjectExpression(node) {
282
383
  if (!isVirtualDomNode(node)) {
@@ -301,11 +402,11 @@ const create$5 = context => {
301
402
 
302
403
  const noObjectAttributeValues = {
303
404
  __proto__: null,
304
- create: create$5,
305
- meta: meta$5
405
+ create: create$6,
406
+ meta: meta$6
306
407
  };
307
408
 
308
- const meta$4 = {
409
+ const meta$5 = {
309
410
  docs: {
310
411
  description: 'Disallow raw string children in virtual-dom arrays'
311
412
  },
@@ -317,7 +418,7 @@ const meta$4 = {
317
418
  const isVirtualDomArray = node => {
318
419
  return isArrayExpressionNode(node) && node.elements.some(element => isVirtualDomNode(element) || isTextCall(element));
319
420
  };
320
- const create$4 = context => {
421
+ const create$5 = context => {
321
422
  return {
322
423
  ArrayExpression(node) {
323
424
  if (!isVirtualDomArray(node)) {
@@ -338,11 +439,11 @@ const create$4 = context => {
338
439
 
339
440
  const noRawTextChildren = {
340
441
  __proto__: null,
341
- create: create$4,
342
- meta: meta$4
442
+ create: create$5,
443
+ meta: meta$5
343
444
  };
344
445
 
345
- const meta$3 = {
446
+ const meta$4 = {
346
447
  docs: {
347
448
  description: 'Prefer virtual-dom constants over raw type, role, aria boolean, and tabIndex values'
348
449
  },
@@ -357,7 +458,7 @@ const meta$3 = {
357
458
  const isAriaBooleanProperty = name => {
358
459
  return /^aria[A-Z]/.test(name);
359
460
  };
360
- const create$3 = context => {
461
+ const create$4 = context => {
361
462
  return {
362
463
  ObjectExpression(node) {
363
464
  if (!isVirtualDomNode(node)) {
@@ -404,6 +505,46 @@ const create$3 = context => {
404
505
  };
405
506
 
406
507
  const preferConstants = {
508
+ __proto__: null,
509
+ create: create$4,
510
+ meta: meta$4
511
+ };
512
+
513
+ const meta$3 = {
514
+ docs: {
515
+ description: 'Require Intl.DateTimeFormat instances to be created lazily'
516
+ },
517
+ messages: {
518
+ preferLazyDateTimeFormat: 'Create Intl.DateTimeFormat instances lazily.'
519
+ },
520
+ type: 'suggestion'
521
+ };
522
+ const isFunctionNode = node => {
523
+ return ['ArrowFunctionExpression', 'FunctionDeclaration', 'FunctionExpression'].includes(node.type);
524
+ };
525
+ const isDateTimeFormat = node => {
526
+ return node.type === 'MemberExpression' && !node.computed && node.object.type === 'Identifier' && node.object.name === 'Intl' && node.property.type === 'Identifier' && node.property.name === 'DateTimeFormat';
527
+ };
528
+ const create$3 = context => {
529
+ const isCreatedLazily = node => {
530
+ return context.sourceCode.getAncestors(node).some(isFunctionNode);
531
+ };
532
+ const reportEagerDateTimeFormat = node => {
533
+ if (!isDateTimeFormat(node.callee) || isCreatedLazily(node)) {
534
+ return;
535
+ }
536
+ context.report({
537
+ messageId: 'preferLazyDateTimeFormat',
538
+ node
539
+ });
540
+ };
541
+ return {
542
+ CallExpression: reportEagerDateTimeFormat,
543
+ NewExpression: reportEagerDateTimeFormat
544
+ };
545
+ };
546
+
547
+ const preferLazyDateTimeFormat = {
407
548
  __proto__: null,
408
549
  create: create$3,
409
550
  meta: meta$3
@@ -638,6 +779,7 @@ const plugin = {
638
779
  },
639
780
  rules: {
640
781
  'clickable-div-needs-role': clickableDivNeedsRole,
782
+ 'hoist-static-nodes': hoistStaticNodes,
641
783
  'no-empty-aria': noEmptyAria,
642
784
  'no-empty-class-name': noEmptyClassName,
643
785
  'no-inline-event-handlers': noInlineEventHandlers,
@@ -645,6 +787,7 @@ const plugin = {
645
787
  'no-object-attribute-values': noObjectAttributeValues,
646
788
  'no-raw-text-children': noRawTextChildren,
647
789
  'prefer-constants': preferConstants,
790
+ 'prefer-lazy-date-time-format': preferLazyDateTimeFormat,
648
791
  'prefer-merge-class-names': preferMergeClassNames,
649
792
  'prefer-state-destructuring': preferStateDestructuring,
650
793
  'valid-child-count': validChildCount
@@ -657,6 +800,7 @@ const recommended = [{
657
800
  },
658
801
  rules: {
659
802
  'virtual-dom/clickable-div-needs-role': 'error',
803
+ 'virtual-dom/hoist-static-nodes': 'error',
660
804
  'virtual-dom/no-empty-aria': 'error',
661
805
  'virtual-dom/no-empty-class-name': 'error',
662
806
  'virtual-dom/no-inline-event-handlers': 'error',
@@ -664,6 +808,7 @@ const recommended = [{
664
808
  'virtual-dom/no-object-attribute-values': 'error',
665
809
  'virtual-dom/no-raw-text-children': 'error',
666
810
  'virtual-dom/prefer-constants': 'error',
811
+ 'virtual-dom/prefer-lazy-date-time-format': 'error',
667
812
  'virtual-dom/prefer-merge-class-names': 'error',
668
813
  'virtual-dom/prefer-state-destructuring': 'error',
669
814
  'virtual-dom/valid-child-count': 'error'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/eslint-plugin-virtual-dom",
3
- "version": "16.4.0",
3
+ "version": "17.0.0",
4
4
  "main": "dist/index.js",
5
5
  "repository": {
6
6
  "type": "git",