eslint-plugin-no-jquery 3.0.1 → 3.0.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-no-jquery",
3
- "version": "3.0.1",
3
+ "version": "3.0.2",
4
4
  "description": "Disallow jQuery functions with native equivalents.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -1,7 +1,11 @@
1
1
  'use strict';
2
2
 
3
3
  const utils = require( '../utils.js' );
4
- const methods = [ 'append', 'prepend', 'before', 'after', 'replaceWith', 'add', 'appendTo', 'prependTo' ];
4
+ // htmlStrings or jQuery collections
5
+ const htmlOrCollectionMethods = [ 'append', 'prepend', 'before', 'after', 'replaceWith' ];
6
+ // htmlStrings, selectors or jQuery collections
7
+ const htmlOrSelectorOrCollectionMethods = [ 'add', 'appendTo', 'prependTo', 'insertBefore', 'insertAfter' ];
8
+ const allMethods = htmlOrCollectionMethods.concat( htmlOrSelectorOrCollectionMethods );
5
9
 
6
10
  function alljQueryOrEmpty( context, node ) {
7
11
  if ( node.type === 'ConditionalExpression' ) {
@@ -22,7 +26,7 @@ module.exports = {
22
26
  meta: {
23
27
  type: 'suggestion',
24
28
  docs: {
25
- description: 'Disallows using ' + methods.map( utils.jQueryCollectionLink ).join( '/' ) +
29
+ description: 'Disallows using ' + allMethods.map( utils.jQueryCollectionLink ).join( '/' ) +
26
30
  ' to inject HTML, in order to prevent possible XSS bugs.'
27
31
  },
28
32
  schema: []
@@ -32,13 +36,18 @@ module.exports = {
32
36
  'CallExpression:exit': ( node ) => {
33
37
  if ( !(
34
38
  node.callee.type === 'MemberExpression' &&
35
- methods.includes( node.callee.property.name )
39
+ allMethods.includes( node.callee.property.name )
36
40
  ) ) {
37
41
  return;
38
42
  }
39
43
  if ( node.arguments.every( ( arg ) => alljQueryOrEmpty( context, arg ) ) ) {
40
44
  return;
41
45
  }
46
+ if ( htmlOrSelectorOrCollectionMethods.includes( node.callee.property.name ) ) {
47
+ if ( node.arguments.every( ( arg ) => !utils.isHtmlString( arg ) ) ) {
48
+ return;
49
+ }
50
+ }
42
51
 
43
52
  if ( utils.isjQuery( context, node.callee ) ) {
44
53
  context.report( {
@@ -2,33 +2,11 @@
2
2
 
3
3
  const utils = require( '../utils.js' );
4
4
 
5
- // HTML regex (modified from jQuery)
6
- const rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*)$/;
7
5
  // Single tag regex (from jQuery)
8
6
  const rsingleTag = /^<([a-z][^/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;
9
7
  const rsingleTagMinimal = /^<([a-z][^/\0>:\x20\t\r\n\f]*)>$/i;
10
8
  const rsingleTagSelfClosing = /^<([a-z][^/\0>:\x20\t\r\n\f]*)\/>$/i;
11
9
 
12
- function allLiteral( node ) {
13
- if ( node.type === 'BinaryExpression' ) {
14
- return allLiteral( node.left ) && allLiteral( node.right );
15
- } else {
16
- return node.type === 'Literal';
17
- }
18
- }
19
-
20
- function joinLiterals( node ) {
21
- if ( node.type === 'BinaryExpression' ) {
22
- return joinLiterals( node.left ) + joinLiterals( node.right );
23
- }
24
- /* istanbul ignore else */
25
- if ( node.type === 'Literal' ) {
26
- return node.value;
27
- }
28
- /* istanbul ignore next */
29
- throw new Error( 'Non-literal node passed to joinLiteral' );
30
- }
31
-
32
10
  module.exports = {
33
11
  meta: {
34
12
  type: 'suggestion',
@@ -94,11 +72,10 @@ module.exports = {
94
72
  let expectedTag;
95
73
  const arg = node.arguments[ 0 ];
96
74
  if ( allowSingle ) {
97
- const value = arg && allLiteral( arg ) && joinLiterals( arg );
98
- if ( !( typeof value === 'string' && value ) || !rquickExpr.exec( value ) ) {
99
- // Empty or non-string, or non-HTML
75
+ if ( !utils.isHtmlString( arg ) ) {
100
76
  return;
101
77
  }
78
+ const value = utils.joinLiterals( arg );
102
79
  let match;
103
80
  if ( ( match = rsingleTag.exec( value ) ) ) {
104
81
  // Single tag
@@ -122,7 +99,7 @@ module.exports = {
122
99
  return;
123
100
  }
124
101
  }
125
- } else if ( !( arg && allLiteral( arg ) ) ) {
102
+ } else if ( !( arg && utils.allLiteral( arg ) ) ) {
126
103
  // Non literals passed to $.parseHTML
127
104
  return;
128
105
  }
@@ -2,19 +2,6 @@
2
2
 
3
3
  const utils = require( '../utils.js' );
4
4
 
5
- function collectLiterals( node ) {
6
- if ( node.type === 'BinaryExpression' ) {
7
- return collectLiterals( node.left ) + collectLiterals( node.right );
8
- } else if ( node.type === 'Literal' ) {
9
- return node.value;
10
- } else if ( node.type === 'Identifier' ) {
11
- // Dummy value for regex matching
12
- return 'A0';
13
- } else {
14
- return '';
15
- }
16
- }
17
-
18
5
  module.exports = {
19
6
  meta: {
20
7
  type: 'suggestion',
@@ -79,7 +66,7 @@ module.exports = {
79
66
  context.options[ 0 ].allowPositional;
80
67
  const allowOther = context.options[ 0 ] &&
81
68
  context.options[ 0 ].allowOther;
82
- const value = collectLiterals( node.arguments[ 0 ] );
69
+ const value = utils.joinLiterals( node.arguments[ 0 ] );
83
70
 
84
71
  if ( !allowPositional && forbiddenPositional.test( value ) ) {
85
72
  context.report( {
package/src/utils.js CHANGED
@@ -541,6 +541,35 @@ function eventShorthandFixer( node, context, fixer ) {
541
541
  }
542
542
  }
543
543
 
544
+ function allLiteral( node ) {
545
+ if ( node.type === 'BinaryExpression' ) {
546
+ return allLiteral( node.left ) && allLiteral( node.right );
547
+ } else {
548
+ return node.type === 'Literal';
549
+ }
550
+ }
551
+
552
+ function joinLiterals( node ) {
553
+ if ( node.type === 'BinaryExpression' ) {
554
+ return joinLiterals( node.left ) + joinLiterals( node.right );
555
+ } else if ( node.type === 'Literal' ) {
556
+ return node.value;
557
+ } else if ( node.type === 'Identifier' ) {
558
+ // Dummy value for regex matching
559
+ return 'A0';
560
+ } else {
561
+ return '';
562
+ }
563
+ }
564
+
565
+ // HTML regex (modified from jQuery)
566
+ const rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*)$/;
567
+
568
+ function isHtmlString( arg ) {
569
+ const value = arg && allLiteral( arg ) && joinLiterals( arg );
570
+ return typeof value === 'string' && value && rquickExpr.exec( value );
571
+ }
572
+
544
573
  module.exports = {
545
574
  isjQuery,
546
575
  isjQueryConstructor,
@@ -552,5 +581,8 @@ module.exports = {
552
581
  createCollectionOrUtilMethodRule,
553
582
  eventShorthandFixer,
554
583
  jQueryCollectionLink,
555
- jQueryGlobalLink
584
+ jQueryGlobalLink,
585
+ allLiteral,
586
+ joinLiterals,
587
+ isHtmlString
556
588
  };