Переглянути джерело

Add ESLint support.

Used the Bootstrap master branch config and adapted it.

Also, remove the `babel-eslint` package since we don't use it.
XhmikosR 4 роки тому
батько
коміт
5ba59f1454
10 змінених файлів з 567 додано та 365 видалено
  1. 3 4
      .eslintignore
  2. 0 300
      .eslintrc
  3. 63 0
      .eslintrc.json
  4. 1 0
      .gitignore
  5. 14 0
      build/config/.eslintrc.json
  6. 0 44
      build/js/.jscsrc
  7. 14 0
      build/npm/.eslintrc.json
  8. 46 0
      dist/js/.eslintrc.json
  9. 420 14
      package-lock.json
  10. 6 3
      package.json

+ 3 - 4
.eslintignore

@@ -1,5 +1,4 @@
 **/*.min.js
-**/plugins/*
-**/dist/*
-**/build/npm
-ad.js
+**/plugins/
+/dist/js/adminlte.js
+/docs/

+ 0 - 300
.eslintrc

@@ -1,300 +0,0 @@
-{
-  "root": true,
-  "parser": "babel-eslint",
-  "env": {
-    "browser": true,
-    "es6": true,
-    "amd": true
-  },
-  "extends": "eslint:recommended",
-  "plugins": [
-    "compat"
-  ],
-  "globals": {
-    "jQuery": true
-  },
-  "rules": {
-    // Possible Errors
-    "no-await-in-loop": "error",
-    "no-extra-parens": "error",
-    "no-prototype-builtins": "error",
-    "no-template-curly-in-string": "error",
-    "compat/compat": "error",
-    "valid-jsdoc": "error",
-    // Best Practices
-    "accessor-pairs": "error",
-    "array-callback-return": "error",
-    "block-scoped-var": "error",
-    "class-methods-use-this": "off",
-    "complexity": "error",
-    "consistent-return": "error",
-    "curly": "error",
-    "default-case": "error",
-    "dot-location": [
-      "error",
-      "property"
-    ],
-    "dot-notation": "error",
-    "eqeqeq": "error",
-    "guard-for-in": "error",
-    "no-alert": "error",
-    "no-caller": "error",
-    "no-div-regex": "error",
-    "no-else-return": "error",
-    "no-empty-function": "error",
-    "no-eq-null": "error",
-    "no-eval": "error",
-    "no-extend-native": "error",
-    "no-extra-bind": "error",
-    "no-extra-label": "error",
-    "no-floating-decimal": "error",
-    "no-implicit-coercion": "error",
-    "no-implicit-globals": "error",
-    "no-implied-eval": "error",
-    "no-invalid-this": "off",
-    "no-iterator": "error",
-    "no-labels": "error",
-    "no-lone-blocks": "error",
-    "no-loop-func": "error",
-    "no-magic-numbers": [
-      "error",
-      {
-        "ignore": [
-          -1,
-          0,
-          1
-        ],
-        "ignoreArrayIndexes": true
-      }
-    ],
-    "no-multi-spaces": [
-      "error",
-      {
-        "ignoreEOLComments": true,
-        "exceptions": {
-          "AssignmentExpression": true,
-          "ArrowFunctionExpression": true,
-          "CallExpression": true,
-          "VariableDeclarator": true
-        }
-      }
-    ],
-    "no-multi-str": "error",
-    "no-new": "error",
-    "no-new-func": "error",
-    "no-new-wrappers": "error",
-    "no-octal-escape": "error",
-    "no-param-reassign": "off",
-    "no-proto": "error",
-    "no-restricted-properties": "error",
-    "no-return-assign": "error",
-    "no-return-await": "error",
-    "no-script-url": "error",
-    "no-self-compare": "error",
-    "no-sequences": "error",
-    "no-throw-literal": "error",
-    "no-unmodified-loop-condition": "error",
-    "no-unused-expressions": "error",
-    "no-useless-call": "error",
-    "no-useless-concat": "error",
-    "no-useless-return": "error",
-    "no-void": "error",
-    "no-warning-comments": "off",
-    "no-with": "error",
-    "prefer-promise-reject-errors": "error",
-    "radix": "error",
-    "require-await": "error",
-    "vars-on-top": "error",
-    "wrap-iife": "error",
-    "yoda": "error",
-    // Strict Mode
-    "strict": "error",
-    // Variables
-    "init-declarations": "off",
-    "no-catch-shadow": "error",
-    "no-label-var": "error",
-    "no-restricted-globals": "error",
-    "no-shadow": "off",
-    "no-shadow-restricted-names": "error",
-    "no-undef-init": "error",
-    "no-undefined": "error",
-    "no-use-before-define": "off",
-    // Node.js and CommonJS
-    "callback-return": "off",
-    "global-require": "error",
-    "handle-callback-err": "error",
-    "no-mixed-requires": "error",
-    "no-new-require": "error",
-    "no-path-concat": "error",
-    "no-process-env": "error",
-    "no-process-exit": "error",
-    "no-restricted-modules": "error",
-    "no-sync": "error",
-    // Stylistic Issues
-    "array-bracket-spacing": "error",
-    "block-spacing": "error",
-    "brace-style": "error",
-    "camelcase": "error",
-    "capitalized-comments": "off",
-    "comma-dangle": "error",
-    "comma-spacing": "error",
-    "comma-style": "error",
-    "computed-property-spacing": "error",
-    "consistent-this": "error",
-    "eol-last": "error",
-    "func-call-spacing": "error",
-    "func-name-matching": "error",
-    "func-names": "off",
-    "func-style": [
-      "error",
-      "declaration"
-    ],
-    "id-blacklist": "error",
-    "id-length": "off",
-    "id-match": "error",
-    "indent": [
-      "error",
-      2,
-      {
-        "SwitchCase": 1
-      }
-    ],
-    "jsx-quotes": "error",
-    "key-spacing": "off",
-    "keyword-spacing": "error",
-    "linebreak-style": [
-      "error",
-      "unix"
-    ],
-    "line-comment-position": "off",
-    "lines-around-comment": "off",
-    "lines-around-directive": "error",
-    "max-depth": [
-      "error",
-      10
-    ],
-    "max-len": "off",
-    "max-lines": "off",
-    "max-nested-callbacks": "error",
-    "max-params": "off",
-    "max-statements": "off",
-    "max-statements-per-line": "error",
-    "multiline-ternary": "off",
-    "new-cap": [
-      "error",
-      {
-        "capIsNewExceptionPattern": "$.*"
-      }
-    ],
-    "newline-after-var": "off",
-    "newline-per-chained-call": [
-      "error",
-      {
-        "ignoreChainWithDepth": 5
-      }
-    ],
-    "new-parens": "error",
-    "no-array-constructor": "error",
-    "no-bitwise": "error",
-    "no-continue": "off",
-    "no-inline-comments": "off",
-    "no-lonely-if": "error",
-    "no-mixed-operators": "off",
-    "no-multi-assign": "error",
-    "no-multiple-empty-lines": "error",
-    "nonblock-statement-body-position": "error",
-    "no-negated-condition": "off",
-    "no-nested-ternary": "error",
-    "no-new-object": "error",
-    "no-plusplus": "off",
-    "no-restricted-syntax": "error",
-    "no-tabs": "error",
-    "no-ternary": "off",
-    "no-trailing-spaces": "error",
-    "no-underscore-dangle": "off",
-    "no-unneeded-ternary": "error",
-    "no-whitespace-before-property": "error",
-    "object-curly-newline": [
-      "error",
-      {
-        "minProperties": 1
-      }
-    ],
-    "object-curly-spacing": [
-      "error",
-      "always"
-    ],
-    "object-property-newline": "error",
-    "one-var": [
-      "error",
-      "never"
-    ],
-    "one-var-declaration-per-line": "error",
-    "operator-assignment": "error",
-    "operator-linebreak": "error",
-    "padded-blocks": [
-      "error",
-      "never"
-    ],
-    "padding-line-between-statements": "off",
-    "quote-props": [
-      "error",
-      "as-needed"
-    ],
-    "quotes": [
-      "error",
-      "single"
-    ],
-    "require-jsdoc": "off",
-    "semi": [
-      "error",
-      "never"
-    ],
-    "semi-spacing": "error",
-    "sort-keys": "off",
-    "sort-vars": "error",
-    "space-before-blocks": "error",
-    "space-before-function-paren": [
-      "error",
-      {
-        "anonymous": "always",
-        "named": "never"
-      }
-    ],
-    "space-in-parens": "error",
-    "space-infix-ops": "error",
-    "space-unary-ops": "error",
-    "spaced-comment": "error",
-    "template-tag-spacing": "error",
-    "unicode-bom": "error",
-    "wrap-regex": "off",
-    // ECMAScript 6
-    "arrow-body-style": [
-      "error",
-      "as-needed"
-    ],
-    "arrow-parens": "error",
-    "arrow-spacing": "error",
-    "generator-star-spacing": "error",
-    "no-confusing-arrow": "error",
-    "no-duplicate-imports": "error",
-    "no-restricted-imports": "error",
-    "no-useless-computed-key": "error",
-    "no-useless-constructor": "error",
-    "no-useless-rename": "error",
-    "no-var": "error",
-    "object-shorthand": "error",
-    "prefer-arrow-callback": "error",
-    "prefer-const": "error",
-    "prefer-destructuring": "off",
-    "prefer-numeric-literals": "error",
-    "prefer-rest-params": "error",
-    "prefer-spread": "error",
-    "prefer-template": "error",
-    "rest-spread-spacing": "error",
-    "sort-imports": "error",
-    "symbol-description": "error",
-    "template-curly-spacing": "error",
-    "yield-star-spacing": "error"
-  }
-}

+ 63 - 0
.eslintrc.json

@@ -0,0 +1,63 @@
+{
+  "root": true,
+  "extends": [
+    "plugin:compat/recommended",
+    "plugin:import/errors",
+    "plugin:import/warnings",
+    "plugin:unicorn/recommended",
+    "xo/esnext",
+    "xo/browser"
+  ],
+  "env": {
+    "jquery": true
+  },
+  "rules": {
+    "capitalized-comments": "off",
+    "eqeqeq": "off",
+    "indent": [
+      "error",
+      2,
+      {
+        "MemberExpression": "off",
+        "SwitchCase": 1
+      }
+    ],
+    "multiline-ternary": [
+      "error",
+      "always-multiline"
+    ],
+    "new-cap": [
+      "error",
+      {
+        "properties": false
+      }
+    ],
+    "no-eq-null": "off",
+    "no-negated-condition": "off",
+    "no-console": "error",
+    "object-curly-spacing": [
+      "error",
+      "always"
+    ],
+    "prefer-named-capture-group": "off",
+    "semi": [
+      "error",
+      "never"
+    ],
+    "unicorn/filename-case": "off",
+    "unicorn/import-index": "off",
+    "unicorn/no-fn-reference-in-iterator": "off",
+    "unicorn/no-for-loop": "off",
+    "unicorn/no-null": "off",
+    "unicorn/no-unused-properties": "error",
+    "unicorn/prefer-dataset": "off",
+    "unicorn/prefer-includes": "off",
+    "unicorn/prefer-node-append": "off",
+    "unicorn/prefer-node-remove": "off",
+    "unicorn/prefer-number-properties": "off",
+    "unicorn/prefer-optional-catch-binding": "off",
+    "unicorn/prefer-query-selector": "off",
+    "unicorn/prefer-set-has": "off",
+    "unicorn/prevent-abbreviations": "off"
+  }
+}

+ 1 - 0
.gitignore

@@ -36,3 +36,4 @@ TODO
 test.html
 ad.js
 /.cache/
+/docs/assets/js/.eslintrc.json

+ 14 - 0
build/config/.eslintrc.json

@@ -0,0 +1,14 @@
+{
+  "env": {
+    "browser": false,
+    "node": true
+  },
+  "parserOptions": {
+    "sourceType": "script"
+  },
+  "extends": "../../.eslintrc.json",
+  "rules": {
+    "no-console": "off",
+    "strict": "error"
+  }
+}

+ 0 - 44
build/js/.jscsrc

@@ -1,44 +0,0 @@
-{
-  "esnext": true,
-  "verbose": true,
-  "disallowEmptyBlocks": true,
-  "disallowKeywords": ["with"],
-  "disallowMixedSpacesAndTabs": true,
-  "disallowMultipleLineStrings": true,
-  "disallowMultipleVarDecl": true,
-  "disallowQuotedKeysInObjects": "allButReserved",
-  "disallowSpaceAfterPrefixUnaryOperators": ["++", "--", "+", "-", "~", "!"],
-  "disallowSpaceBeforeBinaryOperators": [","],
-  "disallowSpaceBeforePostfixUnaryOperators": ["++", "--"],
-  "disallowSpacesInFunctionDeclaration": { "beforeOpeningRoundBrace": true },
-  "disallowSpacesInNamedFunctionExpression": { "beforeOpeningRoundBrace": true },
-  "disallowSpacesInsideArrayBrackets": true,
-  "disallowSpacesInsideParentheses": true,
-  "disallowTrailingComma": true,
-  "disallowTrailingWhitespace": true,
-  "requireCamelCaseOrUpperCaseIdentifiers": true,
-  "requireCapitalizedConstructors": true,
-  "requireCommaBeforeLineBreak": true,
-  "requireDollarBeforejQueryAssignment": true,
-  "requireDotNotation": true,
-  "requireLineFeedAtFileEnd": true,
-  "requirePaddingNewLinesAfterUseStrict": true,
-  "requirePaddingNewLinesBeforeExport": true,
-  "requireSpaceAfterBinaryOperators": ["+", "-", "/", "*", "=", "==", "===", "!=", "!==", ">", "<", ">=", "<="],
-  "requireSpaceAfterKeywords": ["if", "else", "for", "while", "do", "switch", "return", "try", "catch"],
-  "requireSpaceAfterLineComment": true,
-  "requireSpaceBeforeBinaryOperators": ["+", "-", "/", "*", "=", "==", "===", "!=", "!==", ">", "<", ">=", "<="],
-  "requireSpaceBetweenArguments": true,
-  "requireSpacesInAnonymousFunctionExpression": { "beforeOpeningCurlyBrace": true, "beforeOpeningRoundBrace": true, "allExcept": ["shorthand"] },
-  "requireSpacesInConditionalExpression": true,
-  "requireSpacesInForStatement": true,
-  "requireSpacesInFunctionDeclaration": { "beforeOpeningCurlyBrace": true },
-  "requireSpacesInFunctionExpression": { "beforeOpeningCurlyBrace": true },
-  "requireSpacesInNamedFunctionExpression": { "beforeOpeningCurlyBrace": true },
-  "requireSpacesInsideObjectBrackets": "allButNested",
-  "validateAlignedFunctionParameters": true,
-  "validateIndentation": 2,
-  "validateLineBreaks": "LF",
-  "validateNewlineAfterArrayElements": true,
-  "validateQuoteMarks": "'"
-}

+ 14 - 0
build/npm/.eslintrc.json

@@ -0,0 +1,14 @@
+{
+  "env": {
+    "browser": false,
+    "node": true
+  },
+  "parserOptions": {
+    "sourceType": "script"
+  },
+  "extends": "../../.eslintrc.json",
+  "rules": {
+    "no-console": "off",
+    "strict": "error"
+  }
+}

+ 46 - 0
dist/js/.eslintrc.json

@@ -0,0 +1,46 @@
+{
+  "root": true,
+  "parserOptions": {
+    "ecmaVersion": 5,
+    "sourceType": "script"
+  },
+  "env": {
+    "jquery": true
+  },
+  "extends": [
+    "plugin:unicorn/recommended",
+    "xo",
+    "xo/browser"
+  ],
+  "rules": {
+    "capitalized-comments": "off",
+    "indent": [
+      "error",
+      2,
+      {
+        "MemberExpression": "off",
+        "SwitchCase": 1
+      }
+    ],
+    "multiline-ternary": [
+      "error",
+      "always-multiline"
+    ],
+    "object-curly-spacing": [
+      "error",
+      "always"
+    ],
+    "semi": [
+      "error",
+      "never"
+    ],
+    "strict": "error",
+    "unicorn/no-for-loop": "off",
+    "unicorn/no-null": "off",
+    "unicorn/prefer-dataset": "off",
+    "unicorn/prefer-includes": "off",
+    "unicorn/prefer-node-append": "off",
+    "unicorn/prefer-query-selector": "off",
+    "unicorn/prevent-abbreviations": "off"
+  }
+}

+ 420 - 14
package-lock.json

@@ -1374,6 +1374,17 @@
       "resolved": "https://registry.npmjs.org/array-from/-/array-from-2.1.1.tgz",
       "integrity": "sha1-z+nYwmYoudxa7MYqn12PHzUsEZU="
     },
+    "array-includes": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.1.tgz",
+      "integrity": "sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ==",
+      "dev": true,
+      "requires": {
+        "define-properties": "^1.1.3",
+        "es-abstract": "^1.17.0",
+        "is-string": "^1.0.5"
+      }
+    },
     "array-union": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
@@ -1386,6 +1397,16 @@
       "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
       "dev": true
     },
+    "array.prototype.flat": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz",
+      "integrity": "sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ==",
+      "dev": true,
+      "requires": {
+        "define-properties": "^1.1.3",
+        "es-abstract": "^1.17.0-next.1"
+      }
+    },
     "arraybuffer.slice": {
       "version": "0.0.7",
       "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz",
@@ -1575,20 +1596,6 @@
         }
       }
     },
-    "babel-eslint": {
-      "version": "10.1.0",
-      "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz",
-      "integrity": "sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==",
-      "dev": true,
-      "requires": {
-        "@babel/code-frame": "^7.0.0",
-        "@babel/parser": "^7.7.0",
-        "@babel/traverse": "^7.7.0",
-        "@babel/types": "^7.7.0",
-        "eslint-visitor-keys": "^1.0.0",
-        "resolve": "^1.12.0"
-      }
-    },
     "babel-plugin-dynamic-import-node": {
       "version": "2.3.3",
       "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz",
@@ -2416,6 +2423,15 @@
         "glob": "7.x"
       }
     },
+    "clean-regexp": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/clean-regexp/-/clean-regexp-1.0.0.tgz",
+      "integrity": "sha1-jffHquUf02h06PjQW5GAvBGj/tc=",
+      "dev": true,
+      "requires": {
+        "escape-string-regexp": "^1.0.5"
+      }
+    },
     "cli-boxes": {
       "version": "2.2.0",
       "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.0.tgz",
@@ -2577,6 +2593,12 @@
         "xdg-basedir": "^4.0.0"
       }
     },
+    "confusing-browser-globals": {
+      "version": "1.0.9",
+      "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.9.tgz",
+      "integrity": "sha512-KbS1Y0jMtyPgIxjO7ZzMAuUpAKMt1SzCL9fsrKsX6b0zJPTaT0SiSPmewwVZg9UAO83HVIlEhZF84LIjZ0lmAw==",
+      "dev": true
+    },
     "connect": {
       "version": "3.6.6",
       "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.6.tgz",
@@ -2628,6 +2650,12 @@
         "upper-case": "^1.1.1"
       }
     },
+    "contains-path": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz",
+      "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=",
+      "dev": true
+    },
     "convert-source-map": {
       "version": "1.7.0",
       "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz",
@@ -3796,6 +3824,79 @@
         }
       }
     },
+    "eslint-ast-utils": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/eslint-ast-utils/-/eslint-ast-utils-1.1.0.tgz",
+      "integrity": "sha512-otzzTim2/1+lVrlH19EfQQJEhVJSu0zOb9ygb3iapN6UlyaDtyRq4b5U1FuW0v1lRa9Fp/GJyHkSwm6NqABgCA==",
+      "dev": true,
+      "requires": {
+        "lodash.get": "^4.4.2",
+        "lodash.zip": "^4.2.0"
+      }
+    },
+    "eslint-config-xo": {
+      "version": "0.29.1",
+      "resolved": "https://registry.npmjs.org/eslint-config-xo/-/eslint-config-xo-0.29.1.tgz",
+      "integrity": "sha512-RDjeKh8CV0/EH4utW/6uOkwJJOOU+rX3uE5eUBOamcLNe4lNjyo8kSt3B6DzAm1L/1tWGikI7LFNVY9gG7PDQw==",
+      "dev": true,
+      "requires": {
+        "confusing-browser-globals": "1.0.9"
+      }
+    },
+    "eslint-import-resolver-node": {
+      "version": "0.3.3",
+      "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.3.tgz",
+      "integrity": "sha512-b8crLDo0M5RSe5YG8Pu2DYBj71tSB6OvXkfzwbJU2w7y8P4/yo0MyF8jU26IEuEuHF2K5/gcAJE3LhQGqBBbVg==",
+      "dev": true,
+      "requires": {
+        "debug": "^2.6.9",
+        "resolve": "^1.13.1"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "2.6.9",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+          "dev": true,
+          "requires": {
+            "ms": "2.0.0"
+          }
+        },
+        "ms": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+          "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+          "dev": true
+        }
+      }
+    },
+    "eslint-module-utils": {
+      "version": "2.6.0",
+      "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz",
+      "integrity": "sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA==",
+      "dev": true,
+      "requires": {
+        "debug": "^2.6.9",
+        "pkg-dir": "^2.0.0"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "2.6.9",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+          "dev": true,
+          "requires": {
+            "ms": "2.0.0"
+          }
+        },
+        "ms": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+          "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+          "dev": true
+        }
+      }
+    },
     "eslint-plugin-compat": {
       "version": "3.7.0",
       "resolved": "https://registry.npmjs.org/eslint-plugin-compat/-/eslint-plugin-compat-3.7.0.tgz",
@@ -3825,6 +3926,231 @@
         }
       }
     },
+    "eslint-plugin-import": {
+      "version": "2.20.2",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.20.2.tgz",
+      "integrity": "sha512-FObidqpXrR8OnCh4iNsxy+WACztJLXAHBO5hK79T1Hc77PgQZkyDGA5Ag9xAvRpglvLNxhH/zSmZ70/pZ31dHg==",
+      "dev": true,
+      "requires": {
+        "array-includes": "^3.0.3",
+        "array.prototype.flat": "^1.2.1",
+        "contains-path": "^0.1.0",
+        "debug": "^2.6.9",
+        "doctrine": "1.5.0",
+        "eslint-import-resolver-node": "^0.3.2",
+        "eslint-module-utils": "^2.4.1",
+        "has": "^1.0.3",
+        "minimatch": "^3.0.4",
+        "object.values": "^1.1.0",
+        "read-pkg-up": "^2.0.0",
+        "resolve": "^1.12.0"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "2.6.9",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+          "dev": true,
+          "requires": {
+            "ms": "2.0.0"
+          }
+        },
+        "doctrine": {
+          "version": "1.5.0",
+          "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz",
+          "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=",
+          "dev": true,
+          "requires": {
+            "esutils": "^2.0.2",
+            "isarray": "^1.0.0"
+          }
+        },
+        "load-json-file": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
+          "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=",
+          "dev": true,
+          "requires": {
+            "graceful-fs": "^4.1.2",
+            "parse-json": "^2.2.0",
+            "pify": "^2.0.0",
+            "strip-bom": "^3.0.0"
+          }
+        },
+        "ms": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+          "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+          "dev": true
+        },
+        "path-type": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz",
+          "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=",
+          "dev": true,
+          "requires": {
+            "pify": "^2.0.0"
+          }
+        },
+        "read-pkg": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz",
+          "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=",
+          "dev": true,
+          "requires": {
+            "load-json-file": "^2.0.0",
+            "normalize-package-data": "^2.3.2",
+            "path-type": "^2.0.0"
+          }
+        },
+        "read-pkg-up": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz",
+          "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=",
+          "dev": true,
+          "requires": {
+            "find-up": "^2.0.0",
+            "read-pkg": "^2.0.0"
+          }
+        },
+        "strip-bom": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+          "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
+          "dev": true
+        }
+      }
+    },
+    "eslint-plugin-unicorn": {
+      "version": "20.1.0",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-20.1.0.tgz",
+      "integrity": "sha512-XQxLBJT/gnwyRR6cfYsIK1AdekQchAt5tmcsnldevGjgR2xoZsRUa5/i6e0seNHy2RoT57CkTnbVHwHF8No8LA==",
+      "dev": true,
+      "requires": {
+        "ci-info": "^2.0.0",
+        "clean-regexp": "^1.0.0",
+        "eslint-ast-utils": "^1.1.0",
+        "eslint-template-visitor": "^2.0.0",
+        "eslint-utils": "^2.0.0",
+        "import-modules": "^2.0.0",
+        "lodash": "^4.17.15",
+        "pluralize": "^8.0.0",
+        "read-pkg-up": "^7.0.1",
+        "regexp-tree": "^0.1.21",
+        "reserved-words": "^0.1.2",
+        "safe-regex": "^2.1.1",
+        "semver": "^7.3.2"
+      },
+      "dependencies": {
+        "find-up": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+          "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+          "dev": true,
+          "requires": {
+            "locate-path": "^5.0.0",
+            "path-exists": "^4.0.0"
+          }
+        },
+        "locate-path": {
+          "version": "5.0.0",
+          "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+          "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+          "dev": true,
+          "requires": {
+            "p-locate": "^4.1.0"
+          }
+        },
+        "p-limit": {
+          "version": "2.3.0",
+          "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+          "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+          "dev": true,
+          "requires": {
+            "p-try": "^2.0.0"
+          }
+        },
+        "p-locate": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+          "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+          "dev": true,
+          "requires": {
+            "p-limit": "^2.2.0"
+          }
+        },
+        "p-try": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+          "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+          "dev": true
+        },
+        "parse-json": {
+          "version": "5.0.0",
+          "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.0.0.tgz",
+          "integrity": "sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw==",
+          "dev": true,
+          "requires": {
+            "@babel/code-frame": "^7.0.0",
+            "error-ex": "^1.3.1",
+            "json-parse-better-errors": "^1.0.1",
+            "lines-and-columns": "^1.1.6"
+          }
+        },
+        "path-exists": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+          "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+          "dev": true
+        },
+        "read-pkg": {
+          "version": "5.2.0",
+          "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz",
+          "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==",
+          "dev": true,
+          "requires": {
+            "@types/normalize-package-data": "^2.4.0",
+            "normalize-package-data": "^2.5.0",
+            "parse-json": "^5.0.0",
+            "type-fest": "^0.6.0"
+          },
+          "dependencies": {
+            "type-fest": {
+              "version": "0.6.0",
+              "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz",
+              "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==",
+              "dev": true
+            }
+          }
+        },
+        "read-pkg-up": {
+          "version": "7.0.1",
+          "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz",
+          "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==",
+          "dev": true,
+          "requires": {
+            "find-up": "^4.1.0",
+            "read-pkg": "^5.2.0",
+            "type-fest": "^0.8.1"
+          }
+        },
+        "safe-regex": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-2.1.1.tgz",
+          "integrity": "sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A==",
+          "dev": true,
+          "requires": {
+            "regexp-tree": "~0.1.1"
+          }
+        },
+        "semver": {
+          "version": "7.3.2",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz",
+          "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==",
+          "dev": true
+        }
+      }
+    },
     "eslint-scope": {
       "version": "5.0.0",
       "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz",
@@ -3835,6 +4161,17 @@
         "estraverse": "^4.1.1"
       }
     },
+    "eslint-template-visitor": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/eslint-template-visitor/-/eslint-template-visitor-2.0.0.tgz",
+      "integrity": "sha512-WijrLXWk/TiiG9FBTeEeb2pj/nD8H4eKIYx1DhTv/c7QoFmelE5P+3gzKUcXWZz88AI2+Wjse9DTV8lXrhcUsw==",
+      "dev": true,
+      "requires": {
+        "eslint-visitor-keys": "^1.1.0",
+        "espree": "^7.0.0",
+        "multimap": "^1.1.0"
+      }
+    },
     "eslint-utils": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.0.0.tgz",
@@ -5075,6 +5412,12 @@
       "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=",
       "dev": true
     },
+    "import-modules": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/import-modules/-/import-modules-2.0.0.tgz",
+      "integrity": "sha512-iczM/v9drffdNnABOKwj0f9G3cFDon99VcG1mxeBsdqnbd+vnQ5c2uAiCHNQITqFTOPaEvwg3VjoWCur0uHLEw==",
+      "dev": true
+    },
     "imurmurhash": {
       "version": "0.1.4",
       "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
@@ -5537,6 +5880,12 @@
       "integrity": "sha512-OZ4IlER3zmRIoB9AqNhEggVxqIH4ofDns5nRrPS6yQxXE1TPCUpFznBfRQmQa8uC+pXqjMnukiJBxCisIxiLGA==",
       "dev": true
     },
+    "is-string": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz",
+      "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==",
+      "dev": true
+    },
     "is-symbol": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz",
@@ -5935,6 +6284,12 @@
       "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
       "dev": true
     },
+    "lodash.get": {
+      "version": "4.4.2",
+      "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
+      "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=",
+      "dev": true
+    },
     "lodash.isfinite": {
       "version": "3.3.2",
       "resolved": "https://registry.npmjs.org/lodash.isfinite/-/lodash.isfinite-3.3.2.tgz",
@@ -5947,6 +6302,12 @@
       "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=",
       "dev": true
     },
+    "lodash.zip": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/lodash.zip/-/lodash.zip-4.2.0.tgz",
+      "integrity": "sha1-7GZi5IlkCO1KtsVCo5kLcswIACA=",
+      "dev": true
+    },
     "log-symbols": {
       "version": "2.2.0",
       "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz",
@@ -6296,6 +6657,12 @@
       "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
       "dev": true
     },
+    "multimap": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/multimap/-/multimap-1.1.0.tgz",
+      "integrity": "sha512-0ZIR9PasPxGXmRsEF8jsDzndzHDj7tIav+JUmvIFB/WHswliFnquxECT/De7GR4yg99ky/NlRKJT82G1y271bw==",
+      "dev": true
+    },
     "mute-stream": {
       "version": "0.0.8",
       "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
@@ -6919,6 +7286,18 @@
         "isobject": "^3.0.1"
       }
     },
+    "object.values": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz",
+      "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==",
+      "dev": true,
+      "requires": {
+        "define-properties": "^1.1.3",
+        "es-abstract": "^1.17.0-next.1",
+        "function-bind": "^1.1.1",
+        "has": "^1.0.3"
+      }
+    },
     "on-finished": {
       "version": "2.3.0",
       "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
@@ -7262,6 +7641,15 @@
         "pinkie": "^2.0.0"
       }
     },
+    "pkg-dir": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz",
+      "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=",
+      "dev": true,
+      "requires": {
+        "find-up": "^2.1.0"
+      }
+    },
     "pkg-up": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-2.0.0.tgz",
@@ -7271,6 +7659,12 @@
         "find-up": "^2.1.0"
       }
     },
+    "pluralize": {
+      "version": "8.0.0",
+      "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz",
+      "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==",
+      "dev": true
+    },
     "png-js": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/png-js/-/png-js-1.0.0.tgz",
@@ -8047,6 +8441,12 @@
         "safe-regex": "^1.1.0"
       }
     },
+    "regexp-tree": {
+      "version": "0.1.21",
+      "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.21.tgz",
+      "integrity": "sha512-kUUXjX4AnqnR8KRTCrayAo9PzYMRKmVoGgaz2tBuz0MF3g1ZbGebmtW0yFHfFK9CmBjQKeYIgoL22pFLBJY7sw==",
+      "dev": true
+    },
     "regexp.prototype.flags": {
       "version": "1.3.0",
       "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz",
@@ -8261,6 +8661,12 @@
       "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
       "dev": true
     },
+    "reserved-words": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/reserved-words/-/reserved-words-0.1.2.tgz",
+      "integrity": "sha1-AKCUD5jNUBrqqsMWQR2a3FKzGrE=",
+      "dev": true
+    },
     "resolve": {
       "version": "1.17.0",
       "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz",

+ 6 - 3
package.json

@@ -37,7 +37,8 @@
     "js": "npm-run-all --sequential js-compile js-minify",
     "js-compile": "rollup --config build/config/rollup.config.js --sourcemap",
     "js-minify": "terser --compress typeofs=false --mangle --comments \"/^!/\" --source-map \"content=dist/js/adminlte.js.map,includeSources,url=adminlte.min.js.map\" --output dist/js/adminlte.min.js dist/js/adminlte.js",
-    "lint": "npm run css-lint",
+    "js-lint": "eslint --cache --cache-location .cache/.eslintcache --report-unused-disable-directives .",
+    "lint": "npm-run-all --continue-on-error --parallel css-lint js-lint",
     "production": "npm-run-all --sequential compile plugins",
     "prepare-release": "npm-run-all --sequential production docs",
     "test": "npm-run-all lint production",
@@ -45,7 +46,7 @@
     "sync": "browser-sync start --server --files *.html pages/ dist/",
     "watch": "npm-run-all --parallel watch-css watch-js",
     "watch-css": "nodemon --watch build/scss -e scss -x \"npm-run-all css-lint css\"",
-    "watch-js": "nodemon --watch build/js -e js -x \"npm run js\""
+    "watch-js": "nodemon --watch build/js -e js -x \"npm-run-all js-lint js\""
   },
   "keywords": [
     "css",
@@ -134,11 +135,13 @@
     "@babel/preset-env": "^7.10.2",
     "@rollup/plugin-babel": "^5.0.2",
     "autoprefixer": "^9.8.0",
-    "babel-eslint": "^10.1.0",
     "browser-sync": "^2.26.7",
     "clean-css-cli": "^4.3.0",
     "eslint": "^7.1.0",
+    "eslint-config-xo": "^0.29.1",
     "eslint-plugin-compat": "^3.7.0",
+    "eslint-plugin-import": "^2.20.2",
+    "eslint-plugin-unicorn": "^20.1.0",
     "node-sass": "^4.14.1",
     "node-sass-package-importer": "^5.3.2",
     "nodemon": "^2.0.4",