From e46a591c1a16f6c1cb6c21548faf2bf6599cc923 Mon Sep 17 00:00:00 2001
From: eug-vs <eug-vs@keemail.me>
Date: Sat, 18 Apr 2020 19:57:17 +0300
Subject: feat: update linting config

---
 .eslintrc.json    |   5 +-
 package-lock.json | 420 +++++++++++++++++++++++++++++++++++++++++++++++-------
 package.json      |   8 +-
 3 files changed, 381 insertions(+), 52 deletions(-)

diff --git a/.eslintrc.json b/.eslintrc.json
index ac05a7f..0d36de5 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -1,9 +1,12 @@
 {
   "parser": "@typescript-eslint/parser",
   "extends": [
-    "react-app",
+    "airbnb-typescript",
     "plugin:@typescript-eslint/recommended"
   ],
+  "parserOptions": {
+    "project": "./tsconfig.json"
+  },
   "ignorePatterns": "dist/",
   "rules": {
     "jsx-quotes": ["error", "prefer-double"],
diff --git a/package-lock.json b/package-lock.json
index c7282df..86d3071 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1082,13 +1082,21 @@
       }
     },
     "@babel/runtime-corejs3": {
-      "version": "7.8.4",
-      "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.8.4.tgz",
-      "integrity": "sha512-+wpLqy5+fbQhvbllvlJEVRIpYj+COUWnnsm+I4jZlA8Lo7/MJmBhGTCHyk1/RWfOqBRJ2MbadddG6QltTKTlrg==",
+      "version": "7.9.2",
+      "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.9.2.tgz",
+      "integrity": "sha512-HHxmgxbIzOfFlZ+tdeRKtaxWOMUoCG5Mu3wKeUmOxjYrwb3AAHgnmtCUbPPK11/raIWLIBK250t8E2BPO0p7jA==",
       "dev": true,
       "requires": {
         "core-js-pure": "^3.0.0",
-        "regenerator-runtime": "^0.13.2"
+        "regenerator-runtime": "^0.13.4"
+      },
+      "dependencies": {
+        "regenerator-runtime": {
+          "version": "0.13.5",
+          "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz",
+          "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==",
+          "dev": true
+        }
       }
     },
     "@babel/template": {
@@ -1806,33 +1814,33 @@
       "dev": true
     },
     "@typescript-eslint/eslint-plugin": {
-      "version": "2.19.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.19.0.tgz",
-      "integrity": "sha512-u7IcQ9qwsB6U806LupZmINRnQjC+RJyv36sV/ugaFWMHTbFm/hlLTRx3gGYJgHisxcGSTnf+I/fPDieRMhPSQQ==",
+      "version": "2.28.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.28.0.tgz",
+      "integrity": "sha512-w0Ugcq2iatloEabQP56BRWJowliXUP5Wv6f9fKzjJmDW81hOTBxRoJ4LoEOxRpz9gcY51Libytd2ba3yLmSOfg==",
       "dev": true,
       "requires": {
-        "@typescript-eslint/experimental-utils": "2.19.0",
-        "eslint-utils": "^1.4.3",
+        "@typescript-eslint/experimental-utils": "2.28.0",
         "functional-red-black-tree": "^1.0.1",
         "regexpp": "^3.0.0",
         "tsutils": "^3.17.1"
       },
       "dependencies": {
         "@typescript-eslint/experimental-utils": {
-          "version": "2.19.0",
-          "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.19.0.tgz",
-          "integrity": "sha512-zwpg6zEOPbhB3+GaQfufzlMUOO6GXCNZq6skk+b2ZkZAIoBhVoanWK255BS1g5x9bMwHpLhX0Rpn5Fc3NdCZdg==",
+          "version": "2.28.0",
+          "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.28.0.tgz",
+          "integrity": "sha512-4SL9OWjvFbHumM/Zh/ZeEjUFxrYKtdCi7At4GyKTbQlrj1HcphIDXlje4Uu4cY+qzszR5NdVin4CCm6AXCjd6w==",
           "dev": true,
           "requires": {
             "@types/json-schema": "^7.0.3",
-            "@typescript-eslint/typescript-estree": "2.19.0",
-            "eslint-scope": "^5.0.0"
+            "@typescript-eslint/typescript-estree": "2.28.0",
+            "eslint-scope": "^5.0.0",
+            "eslint-utils": "^2.0.0"
           }
         },
         "@typescript-eslint/typescript-estree": {
-          "version": "2.19.0",
-          "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.19.0.tgz",
-          "integrity": "sha512-n6/Xa37k0jQdwpUszffi19AlNbVCR0sdvCs3DmSKMD7wBttKY31lhD2fug5kMD91B2qW4mQldaTEc1PEzvGu8w==",
+          "version": "2.28.0",
+          "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.28.0.tgz",
+          "integrity": "sha512-HDr8MP9wfwkiuqzRVkuM3BeDrOC4cKbO5a6BymZBHUt5y/2pL0BXD6I/C/ceq2IZoHWhcASk+5/zo+dwgu9V8Q==",
           "dev": true,
           "requires": {
             "debug": "^4.1.1",
@@ -1843,6 +1851,15 @@
             "semver": "^6.3.0",
             "tsutils": "^3.17.1"
           }
+        },
+        "eslint-utils": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.0.0.tgz",
+          "integrity": "sha512-0HCPuJv+7Wv1bACm8y5/ECVfYdfsAm9xmVb7saeFlxjPYALefjhbYoCkBjPdPzGH8wWyTpAez82Fh3VKYEZ8OA==",
+          "dev": true,
+          "requires": {
+            "eslint-visitor-keys": "^1.1.0"
+          }
         }
       }
     },
@@ -2497,14 +2514,10 @@
       }
     },
     "axobject-query": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.1.1.tgz",
-      "integrity": "sha512-lF98xa/yvy6j3fBHAgQXIYl+J4eZadOSqsPojemUqClzNbBV38wWGpUbQbVEyf4eUF5yF7eHmGgGA2JiHyjeqw==",
-      "dev": true,
-      "requires": {
-        "@babel/runtime": "^7.7.4",
-        "@babel/runtime-corejs3": "^7.7.4"
-      }
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.1.2.tgz",
+      "integrity": "sha512-ICt34ZmrVt8UQnvPl6TVyDTkmhXmAyAT4Jh5ugfGUX4MOrZ+U/ZY6/sdylRw3qGNr9Ub5AJsaHeDMzNLehRdOQ==",
+      "dev": true
     },
     "babel-code-frame": {
       "version": "6.26.0",
@@ -3882,9 +3895,9 @@
       }
     },
     "core-js-pure": {
-      "version": "3.6.4",
-      "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.6.4.tgz",
-      "integrity": "sha512-epIhRLkXdgv32xIUFaaAry2wdxZYBi6bgM7cB136dzzXXa+dFyRLTZeLUJxnd8ShrmyVXBub63n2NHo2JAt8Cw==",
+      "version": "3.6.5",
+      "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.6.5.tgz",
+      "integrity": "sha512-lacdXOimsiD0QyNf9BC/mxivNJ/ybBGJXQFKzRekp1WTHoVUWsUHEn+2T8GJAzzIhyOuXA+gOxCVN3l+5PLPUA==",
       "dev": true
     },
     "core-util-is": {
@@ -5069,13 +5082,87 @@
         }
       }
     },
-    "eslint-config-react-app": {
-      "version": "5.1.0",
-      "resolved": "https://registry.npmjs.org/eslint-config-react-app/-/eslint-config-react-app-5.1.0.tgz",
-      "integrity": "sha512-hBaxisHC6HXRVvxX+/t1n8mOdmCVIKgkXsf2WoUkJi7upHJTwYTsdCmx01QPOjKNT34QMQQ9sL0tVBlbiMFjxA==",
+    "eslint-config-airbnb": {
+      "version": "18.1.0",
+      "resolved": "https://registry.npmjs.org/eslint-config-airbnb/-/eslint-config-airbnb-18.1.0.tgz",
+      "integrity": "sha512-kZFuQC/MPnH7KJp6v95xsLBf63G/w7YqdPfQ0MUanxQ7zcKUNG8j+sSY860g3NwCBOa62apw16J6pRN+AOgXzw==",
+      "dev": true,
+      "requires": {
+        "eslint-config-airbnb-base": "^14.1.0",
+        "object.assign": "^4.1.0",
+        "object.entries": "^1.1.1"
+      }
+    },
+    "eslint-config-airbnb-base": {
+      "version": "14.1.0",
+      "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-14.1.0.tgz",
+      "integrity": "sha512-+XCcfGyCnbzOnktDVhwsCAx+9DmrzEmuwxyHUJpw+kqBVT744OUBrB09khgFKlK1lshVww6qXGsYPZpavoNjJw==",
+      "dev": true,
+      "requires": {
+        "confusing-browser-globals": "^1.0.9",
+        "object.assign": "^4.1.0",
+        "object.entries": "^1.1.1"
+      }
+    },
+    "eslint-config-airbnb-typescript": {
+      "version": "7.2.1",
+      "resolved": "https://registry.npmjs.org/eslint-config-airbnb-typescript/-/eslint-config-airbnb-typescript-7.2.1.tgz",
+      "integrity": "sha512-D3elVKUbdsCfkOVstSyWuiu+KGCVTrYxJPoenPIqZtL6Li/R4xBeVTXjZIui8B8D17bDN3Pz5dSr7jRLY5HqIg==",
       "dev": true,
       "requires": {
-        "confusing-browser-globals": "^1.0.9"
+        "@typescript-eslint/parser": "^2.24.0",
+        "eslint-config-airbnb": "^18.1.0",
+        "eslint-config-airbnb-base": "^14.1.0"
+      },
+      "dependencies": {
+        "@typescript-eslint/experimental-utils": {
+          "version": "2.28.0",
+          "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.28.0.tgz",
+          "integrity": "sha512-4SL9OWjvFbHumM/Zh/ZeEjUFxrYKtdCi7At4GyKTbQlrj1HcphIDXlje4Uu4cY+qzszR5NdVin4CCm6AXCjd6w==",
+          "dev": true,
+          "requires": {
+            "@types/json-schema": "^7.0.3",
+            "@typescript-eslint/typescript-estree": "2.28.0",
+            "eslint-scope": "^5.0.0",
+            "eslint-utils": "^2.0.0"
+          }
+        },
+        "@typescript-eslint/parser": {
+          "version": "2.28.0",
+          "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-2.28.0.tgz",
+          "integrity": "sha512-RqPybRDquui9d+K86lL7iPqH6Dfp9461oyqvlXMNtap+PyqYbkY5dB7LawQjDzot99fqzvS0ZLZdfe+1Bt3Jgw==",
+          "dev": true,
+          "requires": {
+            "@types/eslint-visitor-keys": "^1.0.0",
+            "@typescript-eslint/experimental-utils": "2.28.0",
+            "@typescript-eslint/typescript-estree": "2.28.0",
+            "eslint-visitor-keys": "^1.1.0"
+          }
+        },
+        "@typescript-eslint/typescript-estree": {
+          "version": "2.28.0",
+          "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.28.0.tgz",
+          "integrity": "sha512-HDr8MP9wfwkiuqzRVkuM3BeDrOC4cKbO5a6BymZBHUt5y/2pL0BXD6I/C/ceq2IZoHWhcASk+5/zo+dwgu9V8Q==",
+          "dev": true,
+          "requires": {
+            "debug": "^4.1.1",
+            "eslint-visitor-keys": "^1.1.0",
+            "glob": "^7.1.6",
+            "is-glob": "^4.0.1",
+            "lodash": "^4.17.15",
+            "semver": "^6.3.0",
+            "tsutils": "^3.17.1"
+          }
+        },
+        "eslint-utils": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.0.0.tgz",
+          "integrity": "sha512-0HCPuJv+7Wv1bACm8y5/ECVfYdfsAm9xmVb7saeFlxjPYALefjhbYoCkBjPdPzGH8wWyTpAez82Fh3VKYEZ8OA==",
+          "dev": true,
+          "requires": {
+            "eslint-visitor-keys": "^1.1.0"
+          }
+        }
       }
     },
     "eslint-import-resolver-node": {
@@ -5119,9 +5206,9 @@
       }
     },
     "eslint-module-utils": {
-      "version": "2.5.2",
-      "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.5.2.tgz",
-      "integrity": "sha512-LGScZ/JSlqGKiT8OC+cYRxseMjyqt6QO54nl281CK93unD89ijSeRV6An8Ci/2nvWVKe8K/Tqdm75RQoIOCr+Q==",
+      "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",
@@ -5207,9 +5294,9 @@
       }
     },
     "eslint-plugin-import": {
-      "version": "2.20.0",
-      "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.20.0.tgz",
-      "integrity": "sha512-NK42oA0mUc8Ngn4kONOPsPB1XhbUvNHqF+g307dPV28aknPoiNnKLFd9em4nkswwepdF5ouieqv5Th/63U7YJQ==",
+      "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",
@@ -5379,9 +5466,9 @@
       }
     },
     "eslint-plugin-react": {
-      "version": "7.18.0",
-      "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.18.0.tgz",
-      "integrity": "sha512-p+PGoGeV4SaZRDsXqdj9OWcOrOpZn8gXoGPcIQTzo2IDMbAKhNDnME9myZWqO3Ic4R3YmwAZ1lDjWl2R2hMUVQ==",
+      "version": "7.19.0",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.19.0.tgz",
+      "integrity": "sha512-SPT8j72CGuAP+JFbT0sJHOB80TX/pu44gQ4vXH/cq+hQTiY2PuZ6IHkqXJV6x1b28GDdo1lbInjKUrrdUf0LOQ==",
       "dev": true,
       "requires": {
         "array-includes": "^3.1.1",
@@ -5392,7 +5479,10 @@
         "object.fromentries": "^2.0.2",
         "object.values": "^1.1.1",
         "prop-types": "^15.7.2",
-        "resolve": "^1.14.2"
+        "resolve": "^1.15.1",
+        "semver": "^6.3.0",
+        "string.prototype.matchall": "^4.0.2",
+        "xregexp": "^4.3.0"
       },
       "dependencies": {
         "doctrine": {
@@ -5403,13 +5493,22 @@
           "requires": {
             "esutils": "^2.0.2"
           }
+        },
+        "resolve": {
+          "version": "1.16.1",
+          "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.16.1.tgz",
+          "integrity": "sha512-rmAglCSqWWMrrBv/XM6sW0NuRFiKViw/W4d9EbC4pt+49H8JwHy+mcGmALTEg504AUDcLTvb1T2q3E9AnmY+ig==",
+          "dev": true,
+          "requires": {
+            "path-parse": "^1.0.6"
+          }
         }
       }
     },
     "eslint-plugin-react-hooks": {
-      "version": "1.7.0",
-      "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-1.7.0.tgz",
-      "integrity": "sha512-iXTCFcOmlWvw4+TOE8CLWj6yX1GwzT0Y6cUfHHZqWnSk144VmVIRcVGtUAzrLES7C798lmvnt02C7rxaOX1HNA==",
+      "version": "2.5.1",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-2.5.1.tgz",
+      "integrity": "sha512-Y2c4b55R+6ZzwtTppKwSmK/Kar8AdLiC2f9NADCuxbcTgPPg41Gyqa6b9GppgXSvCtkRw43ZE86CT5sejKC6/g==",
       "dev": true
     },
     "eslint-scope": {
@@ -7064,6 +7163,17 @@
         "ipaddr.js": "^1.9.0"
       }
     },
+    "internal-slot": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.2.tgz",
+      "integrity": "sha512-2cQNfwhAfJIkU4KZPkDI+Gj5yNNnbqi40W9Gge6dfnk4TocEVm00B3bdiL+JINrbGJil2TeHvM4rETGzk/f/0g==",
+      "dev": true,
+      "requires": {
+        "es-abstract": "^1.17.0-next.1",
+        "has": "^1.0.3",
+        "side-channel": "^1.0.2"
+      }
+    },
     "invariant": {
       "version": "2.2.4",
       "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
@@ -12064,6 +12174,25 @@
         "workbox-webpack-plugin": "4.3.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"
+          }
+        },
+        "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"
+          }
+        },
         "eslint-config-react-app": {
           "version": "5.2.0",
           "resolved": "https://registry.npmjs.org/eslint-config-react-app/-/eslint-config-react-app-5.2.0.tgz",
@@ -12072,6 +12201,166 @@
           "requires": {
             "confusing-browser-globals": "^1.0.9"
           }
+        },
+        "eslint-plugin-import": {
+          "version": "2.20.0",
+          "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.20.0.tgz",
+          "integrity": "sha512-NK42oA0mUc8Ngn4kONOPsPB1XhbUvNHqF+g307dPV28aknPoiNnKLFd9em4nkswwepdF5ouieqv5Th/63U7YJQ==",
+          "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"
+          }
+        },
+        "eslint-plugin-react": {
+          "version": "7.18.0",
+          "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.18.0.tgz",
+          "integrity": "sha512-p+PGoGeV4SaZRDsXqdj9OWcOrOpZn8gXoGPcIQTzo2IDMbAKhNDnME9myZWqO3Ic4R3YmwAZ1lDjWl2R2hMUVQ==",
+          "dev": true,
+          "requires": {
+            "array-includes": "^3.1.1",
+            "doctrine": "^2.1.0",
+            "has": "^1.0.3",
+            "jsx-ast-utils": "^2.2.3",
+            "object.entries": "^1.1.1",
+            "object.fromentries": "^2.0.2",
+            "object.values": "^1.1.1",
+            "prop-types": "^15.7.2",
+            "resolve": "^1.14.2"
+          },
+          "dependencies": {
+            "doctrine": {
+              "version": "2.1.0",
+              "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+              "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+              "dev": true,
+              "requires": {
+                "esutils": "^2.0.2"
+              }
+            }
+          }
+        },
+        "eslint-plugin-react-hooks": {
+          "version": "1.7.0",
+          "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-1.7.0.tgz",
+          "integrity": "sha512-iXTCFcOmlWvw4+TOE8CLWj6yX1GwzT0Y6cUfHHZqWnSk144VmVIRcVGtUAzrLES7C798lmvnt02C7rxaOX1HNA==",
+          "dev": true
+        },
+        "find-up": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
+          "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
+          "dev": true,
+          "requires": {
+            "locate-path": "^2.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"
+          }
+        },
+        "locate-path": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
+          "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
+          "dev": true,
+          "requires": {
+            "p-locate": "^2.0.0",
+            "path-exists": "^3.0.0"
+          }
+        },
+        "ms": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+          "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+          "dev": true
+        },
+        "p-limit": {
+          "version": "1.3.0",
+          "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
+          "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
+          "dev": true,
+          "requires": {
+            "p-try": "^1.0.0"
+          }
+        },
+        "p-locate": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
+          "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
+          "dev": true,
+          "requires": {
+            "p-limit": "^1.1.0"
+          }
+        },
+        "p-try": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
+          "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=",
+          "dev": true
+        },
+        "parse-json": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
+          "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
+          "dev": true,
+          "requires": {
+            "error-ex": "^1.2.0"
+          }
+        },
+        "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"
+          }
+        },
+        "pify": {
+          "version": "2.3.0",
+          "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+          "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+          "dev": true
+        },
+        "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"
+          }
         }
       }
     },
@@ -12215,9 +12504,9 @@
       }
     },
     "regexpp": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.0.0.tgz",
-      "integrity": "sha512-Z+hNr7RAVWxznLPuA7DIh8UNX1j9CDrUQxskw9IrBE1Dxue2lyXT+shqEIeLUjrokxIP8CMy1WkjgG3rTsd5/g==",
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz",
+      "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==",
       "dev": true
     },
     "regexpu-core": {
@@ -12982,6 +13271,16 @@
       "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==",
       "dev": true
     },
+    "side-channel": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.2.tgz",
+      "integrity": "sha512-7rL9YlPHg7Ancea1S96Pa8/QWb4BtXL/TZvS6B8XFetGBeuhAsfmUspK6DokBeZ64+Kj9TCNRD/30pVz1BvQNA==",
+      "dev": true,
+      "requires": {
+        "es-abstract": "^1.17.0-next.1",
+        "object-inspect": "^1.7.0"
+      }
+    },
     "signal-exit": {
       "version": "3.0.2",
       "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
@@ -13547,6 +13846,20 @@
         }
       }
     },
+    "string.prototype.matchall": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.2.tgz",
+      "integrity": "sha512-N/jp6O5fMf9os0JU3E72Qhf590RSRZU/ungsL/qJUYVTNv7hTG0P/dbPjxINVN9jpscu3nzYwKESU3P3RY5tOg==",
+      "dev": true,
+      "requires": {
+        "define-properties": "^1.1.3",
+        "es-abstract": "^1.17.0",
+        "has-symbols": "^1.0.1",
+        "internal-slot": "^1.0.2",
+        "regexp.prototype.flags": "^1.3.0",
+        "side-channel": "^1.0.2"
+      }
+    },
     "string.prototype.trimleft": {
       "version": "2.1.1",
       "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz",
@@ -16603,6 +16916,15 @@
       "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==",
       "dev": true
     },
+    "xregexp": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-4.3.0.tgz",
+      "integrity": "sha512-7jXDIFXh5yJ/orPn4SXjuVrWWoi4Cr8jfV1eHv9CixKSbU+jY4mxfrBwAuDvupPNKpMUY+FeIqsVw/JLT9+B8g==",
+      "dev": true,
+      "requires": {
+        "@babel/runtime-corejs3": "^7.8.3"
+      }
+    },
     "xtend": {
       "version": "4.0.2",
       "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
diff --git a/package.json b/package.json
index f5e6d22..b423aae 100644
--- a/package.json
+++ b/package.json
@@ -34,10 +34,14 @@
     "@types/react-dom": "^16.9.5",
     "@types/react-virtualized-auto-sizer": "^1.0.0",
     "@types/react-window": "^1.8.1",
-    "@typescript-eslint/eslint-plugin": "^2.19.0",
+    "@typescript-eslint/eslint-plugin": "^2.28.0",
     "@typescript-eslint/parser": "^2.19.0",
     "eslint": "^6.8.0",
-    "eslint-config-react-app": "^5.1.0",
+    "eslint-config-airbnb-typescript": "^7.2.1",
+    "eslint-plugin-import": "^2.20.2",
+    "eslint-plugin-jsx-a11y": "^6.2.3",
+    "eslint-plugin-react": "^7.19.0",
+    "eslint-plugin-react-hooks": "^2.5.1",
     "gh-pages": "^2.2.0",
     "react-scripts": "^3.3.1",
     "typescript": "^3.7.5"
-- 
cgit v1.2.3


From 9941754be106accd5ea8ce4b6f8229dd6f4afc9b Mon Sep 17 00:00:00 2001
From: eug-vs <eug-vs@keemail.me>
Date: Sat, 18 Apr 2020 20:23:32 +0300
Subject: feat: update linting rules

---
 .eslintrc.json | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/.eslintrc.json b/.eslintrc.json
index 0d36de5..c5c45a7 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -10,6 +10,10 @@
   "ignorePatterns": "dist/",
   "rules": {
     "jsx-quotes": ["error", "prefer-double"],
-    "quotes": ["error", "single"]
+    "quotes": ["error", "single"],
+    "react/prop-types": 0,
+    "arrow-body-style": 0,
+    "arrow-parens": [2, "as-needed"],
+    "no-multiple-empty-lines": [2, { "max": 2, "maxEOF": 1 } ]
   }
 }
-- 
cgit v1.2.3


From 2c5fa193541eb8b74974731d01312f73951bca17 Mon Sep 17 00:00:00 2001
From: eug-vs <eug-vs@keemail.me>
Date: Sat, 18 Apr 2020 20:26:32 +0300
Subject: style: correct some errors with eslint --fix

---
 src/index.tsx                             | 73 +++++++++++++++----------------
 src/lib/Benzin/Benzin.tsx                 |  8 ++--
 src/lib/ContentSection/ContentSection.tsx |  7 ++-
 src/lib/Header/Header.tsx                 | 48 ++++++++++----------
 src/lib/Markdown/CodeBlock.tsx            |  6 +--
 src/lib/Markdown/Content.tsx              | 27 ++++++------
 src/lib/Markdown/Markdown.tsx             |  6 +--
 src/lib/Markdown/Section.tsx              | 28 ++++++------
 src/lib/Markdown/SyntacticSpan.tsx        | 18 ++++----
 src/lib/Markdown/Text.tsx                 |  2 +-
 src/lib/SmartList/SmartList.tsx           |  3 +-
 src/lib/Window/Window.tsx                 |  5 ++-
 src/lib/Window/WindowSurface.tsx          |  6 +--
 src/react-app-env.d.ts                    |  2 +-
 14 files changed, 121 insertions(+), 118 deletions(-)

diff --git a/src/index.tsx b/src/index.tsx
index a9a7012..ac7bfc2 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -27,23 +27,23 @@ const useStyles = makeStyles(theme => ({
     display: 'flex',
     justifyContent: 'center',
     marginTop: theme.spacing(4),
-  }
+  },
 }));
 
 
-const Icon = <img src={icon} width="32px" height="37px" alt="logo"/>
+const Icon = <img src={icon} width="32px" height="37px" alt="logo" />;
 
 const headerContents = {
   home: null,
-  'spacevim': null,
+  spacevim: null,
   'material-ui': null,
-  'custom': null,
+  custom: null,
   'live preview': null,
 };
 
 const pageMap: Record<string, string> = {
   home: 'https://raw.githubusercontent.com/eug-vs/react-benzin/develop/README.md',
-  'spacevim': 'https://raw.githubusercontent.com/spacevim/spacevim/master/README.md',
+  spacevim: 'https://raw.githubusercontent.com/spacevim/spacevim/master/README.md',
   'material-ui': 'https://raw.githubusercontent.com/mui-org/material-ui/master/README.md',
 };
 
@@ -54,11 +54,11 @@ const CustomPage: React.FC = () => {
 
   const handleParseUrl = (): void => {
     setUrl(inputEl.current?.value || '');
-  }
+  };
 
   return (
     <>
-      <ContentSection sectionName="Render custom markdown document" level={2} >
+      <ContentSection sectionName="Render custom markdown document" level={2}>
         <p>
           This should be a link to a valid markdown file. Response should give the file contents.
           If you copy README file from GitHub, make sure you provide link to raw view.
@@ -72,14 +72,14 @@ const CustomPage: React.FC = () => {
             label="Markdown url"
           />
         </p>
-        <Button variant="contained" color="secondary" onClick={handleParseUrl} >
+        <Button variant="contained" color="secondary" onClick={handleParseUrl}>
           Render!
         </Button>
       </ContentSection>
       <Markdown url={url} />
     </>
   );
-}
+};
 
 interface LivePropTypes {
   setLivePreviewData: (livePreviewData: string) => void;
@@ -90,11 +90,11 @@ const LivePreviewPage: React.FC<LivePropTypes> = ({ setLivePreviewData }) => {
 
   const handleRender = (): void => {
     setLivePreviewData(inputEl.current?.value || '');
-  }
+  };
 
   return (
     <>
-      <ContentSection sectionName="Markdown live preview" level={2} >
+      <ContentSection sectionName="Markdown live preview" level={2}>
         <p>
           Start typing and see your text rendered on the left window! We recommend starting with # Header.
         </p>
@@ -111,8 +111,8 @@ const LivePreviewPage: React.FC<LivePropTypes> = ({ setLivePreviewData }) => {
         </p>
       </ContentSection>
     </>
-  )
-}
+  );
+};
 
 
 const App: React.FC = () => {
@@ -122,7 +122,7 @@ const App: React.FC = () => {
 
   const handleGoLivePreview = (): void => {
     setPage('live preview');
-  }
+  };
 
   const url = pageMap[page];
   const fileName = url?.slice(url.lastIndexOf('/') + 1);
@@ -153,35 +153,34 @@ const App: React.FC = () => {
       <Window type="primary">
         <div className={classes.window}>
           {
-            (page === 'custom') ?
-            <CustomPage />
-            :
-            (page === 'live preview') ?
-            <Markdown data={livePreviewData || '# Start typing in the right window!'} />
-            :
-            <Markdown url={url} />
+            (page === 'custom')
+              ? <CustomPage />
+              : (page === 'live preview')
+                ? <Markdown data={livePreviewData || '# Start typing in the right window!'} />
+                : <Markdown url={url} />
           }
         </div>
       </Window>
       <Window type="secondary" name="Feature preview">
         <div className={classes.window}>
           {
-            (page === 'live preview') ?
-            <LivePreviewPage setLivePreviewData={setLivePreviewData} />
-            :
-            <>
-              <Markdown data={info} />
-              <p className={classes.promoButton}>
-                <Button
-                  variant="contained"
-                  color="primary"
-                  size="large"
-                  onClick={handleGoLivePreview}
-                >
-                  Try it yourself!
-                </Button>
-              </p>
-            </>
+            (page === 'live preview')
+              ? <LivePreviewPage setLivePreviewData={setLivePreviewData} />
+              : (
+                <>
+                  <Markdown data={info} />
+                  <p className={classes.promoButton}>
+                    <Button
+                      variant="contained"
+                      color="primary"
+                      size="large"
+                      onClick={handleGoLivePreview}
+                    >
+                      Try it yourself!
+                    </Button>
+                  </p>
+                </>
+              )
           }
         </div>
       </Window>
diff --git a/src/lib/Benzin/Benzin.tsx b/src/lib/Benzin/Benzin.tsx
index 83ed0b0..bc436f7 100644
--- a/src/lib/Benzin/Benzin.tsx
+++ b/src/lib/Benzin/Benzin.tsx
@@ -8,9 +8,9 @@ import 'typeface-roboto';
 
 declare module '@material-ui/core/styles/createPalette' {
   interface TypeBackground {
-      elevation1: string;
-      elevation2: string;
-      elevation3: string;
+    elevation1: string;
+    elevation2: string;
+    elevation3: string;
   }
 }
 
@@ -34,7 +34,7 @@ const benzinTheme = createMuiTheme({
     text: {
       primary: '#f4f4f4',
       secondary: 'rgba(255, 255, 255, 0.6)',
-    }
+    },
   },
 });
 
diff --git a/src/lib/ContentSection/ContentSection.tsx b/src/lib/ContentSection/ContentSection.tsx
index ba8b882..6b27bba 100644
--- a/src/lib/ContentSection/ContentSection.tsx
+++ b/src/lib/ContentSection/ContentSection.tsx
@@ -3,7 +3,7 @@ import React from 'react';
 import {
   Typography,
   Divider,
-  makeStyles
+  makeStyles,
 } from '@material-ui/core';
 
 
@@ -30,18 +30,17 @@ const ContentSection: React.FC<PropTypes> = ({ sectionName, children, level = 0
   if (level > 6) level = 6;
 
   type Variant = 'h3' | 'h4' | 'h5' | 'h6';
-  const variant: Variant = 'h' + level as Variant;
+  const variant: Variant = `h${level}` as Variant;
 
   return (
     <>
       <Typography variant={variant}>{sectionName}</Typography>
-      <Divider variant="middle"/>
+      <Divider variant="middle" />
       <Typography component="div" className={classes.content}>
         {children}
       </Typography>
     </>
   );
-
 };
 
 
diff --git a/src/lib/Header/Header.tsx b/src/lib/Header/Header.tsx
index 233eacb..58be989 100644
--- a/src/lib/Header/Header.tsx
+++ b/src/lib/Header/Header.tsx
@@ -40,13 +40,15 @@ const useStyles = makeStyles(theme => ({
       '& svg': {
         marginRight: theme.spacing(1),
         marginBottom: '0 !important',
-      }
-    }
-  }
+      },
+    },
+  },
 }));
 
 
-const Header: React.FC<PropTypes> = ({ logo, contents, page, setPage }) => {
+const Header: React.FC<PropTypes> = ({
+  logo, contents, page, setPage,
+}) => {
   const classes = useStyles();
 
   const handleChange = (event: React.ChangeEvent<{}>, newPage: string): void => {
@@ -54,25 +56,25 @@ const Header: React.FC<PropTypes> = ({ logo, contents, page, setPage }) => {
   };
 
   return (
-  <AppBar position="sticky" className={classes.root}>
-    <Toolbar>
-      {logo.icon}
-      <Typography variant="h5" className={classes.logo} color="primary">
-        {logo.title}
-      </Typography>
-      <Tabs onChange={handleChange} value={page}>
-        {contents && Object.keys(contents).map((item: string) => (
-          <Tab
-            label={item}
-            icon={contents[item] as JSX.Element}
-            value={item}
-            className={classes.tab}
-            key={item}
-          />
-        ))}
-      </Tabs>
-    </Toolbar>
-  </AppBar>
+    <AppBar position="sticky" className={classes.root}>
+      <Toolbar>
+        {logo.icon}
+        <Typography variant="h5" className={classes.logo} color="primary">
+          {logo.title}
+        </Typography>
+        <Tabs onChange={handleChange} value={page}>
+          {contents && Object.keys(contents).map((item: string) => (
+            <Tab
+              label={item}
+              icon={contents[item] as JSX.Element}
+              value={item}
+              className={classes.tab}
+              key={item}
+            />
+          ))}
+        </Tabs>
+      </Toolbar>
+    </AppBar>
   );
 };
 
diff --git a/src/lib/Markdown/CodeBlock.tsx b/src/lib/Markdown/CodeBlock.tsx
index 5b8edec..394458e 100644
--- a/src/lib/Markdown/CodeBlock.tsx
+++ b/src/lib/Markdown/CodeBlock.tsx
@@ -1,8 +1,8 @@
 import React from 'react';
-import { ParserPropTypes } from './types';
 import { Paper } from '@material-ui/core';
 
 import { makeStyles } from '@material-ui/core/styles';
+import { ParserPropTypes } from './types';
 
 const useStyles = makeStyles(theme => ({
   root: {
@@ -10,7 +10,7 @@ const useStyles = makeStyles(theme => ({
     padding: theme.spacing(1),
     overflowX: 'auto',
     fontFamily: 'Monospace',
-    scrollbarColor: 'auto'
+    scrollbarColor: 'auto',
   },
 }));
 
@@ -21,7 +21,7 @@ const CodeBlock: React.FC<ParserPropTypes> = ({ rawLines }) => {
       {rawLines.map(line => <pre>{line}</pre>)}
     </Paper>
   );
-}
+};
 
 export default CodeBlock;
 
diff --git a/src/lib/Markdown/Content.tsx b/src/lib/Markdown/Content.tsx
index 5816214..d64720b 100644
--- a/src/lib/Markdown/Content.tsx
+++ b/src/lib/Markdown/Content.tsx
@@ -6,31 +6,32 @@ import { ParserPropTypes } from './types';
 
 
 const denotesCodeBlock = (line: string): boolean => {
-  return line.match(/^\s*```.*$/) !== null; }
+  return line.match(/^\s*```.*$/) !== null;
+};
 
 const denotesDottedList = (line: string): boolean => {
   return line.match(/^ ?[-*] .*$/) !== null;
-}
+};
 
-const denotesOpenHtml= (line: string): string => {
+const denotesOpenHtml = (line: string): string => {
   const regex = /<([^/\s]*)[^<]*[^/]>/g;
   const match = regex.exec(line);
   return match ? match[1] : '';
-}
+};
 
-const denotesClosingHtml= (line: string, tag: string): boolean => {
+const denotesClosingHtml = (line: string, tag: string): boolean => {
   const regex = new RegExp(`</${tag}[^<]*>`);
   return line.match(regex) !== null;
-}
+};
 
 const denotesSelfClosingHtml = (line: string): string[] | null => {
   const regex = /(<[^/\s]*[^<]*\/>)/g;
   return line.match(regex);
-}
+};
 
 const declaresNoLineBreak = (line: string): boolean => {
   return line.match(/\\\|$/) !== null;
-}
+};
 
 const Content: React.FC<ParserPropTypes> = ({ rawLines }) => {
   if (!rawLines.length) return null;
@@ -41,7 +42,7 @@ const Content: React.FC<ParserPropTypes> = ({ rawLines }) => {
   if (denotesCodeBlock(line)) {
     const closeIndex = rawLines.findIndex(line => denotesCodeBlock(line));
     const codeBlockLines = rawLines.splice(0, closeIndex + 1).slice(0, closeIndex);
-    buffer = <CodeBlock rawLines={codeBlockLines} />
+    buffer = <CodeBlock rawLines={codeBlockLines} />;
   } else if (denotesDottedList(line)) {
     const closeIndex = rawLines.findIndex(line => !denotesDottedList(line));
     const dottedListLines = rawLines.splice(0, closeIndex).slice(0, closeIndex);
@@ -52,14 +53,14 @@ const Content: React.FC<ParserPropTypes> = ({ rawLines }) => {
     const closeIndex = denotesClosingHtml(line, tag) ? -1 : rawLines.findIndex(line => denotesClosingHtml(line, tag));
     const htmlLines = rawLines.splice(0, closeIndex + 1);
     htmlLines.unshift(line);
-    buffer = <div dangerouslySetInnerHTML={{ __html: htmlLines.join('\n') }}></div>;
+    buffer = <div dangerouslySetInnerHTML={{ __html: htmlLines.join('\n') }} />;
   } else if ((buffer = denotesSelfClosingHtml(line)) !== null) {
     const match = buffer[0];
     const [before, after] = line.split(match);
     buffer = (
       <>
         <Text line={before} />
-        <div dangerouslySetInnerHTML={{ __html: match }}></div>
+        <div dangerouslySetInnerHTML={{ __html: match }} />
         <Text line={after} />
       </>
     );
@@ -72,7 +73,7 @@ const Content: React.FC<ParserPropTypes> = ({ rawLines }) => {
   } else if (denotesClosingHtml(line, '')) {
     buffer = null;
   } else {
-    buffer = <p><Text line={line} /></p>
+    buffer = <p><Text line={line} /></p>;
   }
 
   return (
@@ -81,7 +82,7 @@ const Content: React.FC<ParserPropTypes> = ({ rawLines }) => {
       <Content rawLines={rawLines} />
     </>
   );
-}
+};
 
 export default Content;
 
diff --git a/src/lib/Markdown/Markdown.tsx b/src/lib/Markdown/Markdown.tsx
index 82e889c..68967c5 100644
--- a/src/lib/Markdown/Markdown.tsx
+++ b/src/lib/Markdown/Markdown.tsx
@@ -10,8 +10,8 @@ interface PropTypes {
 
 const resolveUrls = (line: string, baseUrl: string): string => {
   return line.replace(/src="(?!http)(.*)"[\s>]/, (match, url, offset, string) => `src="${baseUrl}/${url}?sanitize=true"`)
-             .replace(/\[(.*\]?.*)\]\((?!http)(.+?)\)/, (match, text, url, offset, string) => `[${text}](${baseUrl}/${url})`);
-}
+    .replace(/\[(.*\]?.*)\]\((?!http)(.+?)\)/, (match, text, url, offset, string) => `[${text}](${baseUrl}/${url})`);
+};
 
 const Markdown: React.FC<PropTypes> = ({ data, url }) => {
   const [markdown, setMarkdown] = useState<string>(data || '');
@@ -24,7 +24,7 @@ const Markdown: React.FC<PropTypes> = ({ data, url }) => {
 
   const baseUrl = url?.slice(0, url.lastIndexOf('/')) || '';
   const lines = markdown.split(/\r?\n/).map(line => resolveUrls(line, baseUrl));
-  return <Section rawLines={lines} />
+  return <Section rawLines={lines} />;
 };
 
 
diff --git a/src/lib/Markdown/Section.tsx b/src/lib/Markdown/Section.tsx
index 1fcc46f..f554062 100644
--- a/src/lib/Markdown/Section.tsx
+++ b/src/lib/Markdown/Section.tsx
@@ -1,6 +1,6 @@
 import React from 'react';
-import ContentSection from '../ContentSection/ContentSection';
 import { Typography } from '@material-ui/core';
+import ContentSection from '../ContentSection/ContentSection';
 import Content from './Content';
 import { ParserPropTypes } from './types';
 
@@ -11,9 +11,9 @@ interface PropTypes extends ParserPropTypes {
 const getHeaderLevel = (header: string): number => {
   if (!header) return 0;
   let level = 0;
-  while(header[level] === '#') level++;
+  while (header[level] === '#') level++;
   return level;
-}
+};
 
 const ChildrenSections: React.FC<PropTypes> = ({ rawLines, level = 0 }) => {
   const childrenSectionLines = rawLines.reduce((sections: string[][], line: string) => {
@@ -23,20 +23,22 @@ const ChildrenSections: React.FC<PropTypes> = ({ rawLines, level = 0 }) => {
     }
     return sections;
   }, []);
-  const children = childrenSectionLines.map(sectionLines => <Section rawLines={sectionLines} level={level}/>);
-  return <> {children} </>;
-}
+  const children = childrenSectionLines.map(sectionLines => <Section rawLines={sectionLines} level={level} />);
+  return <>{children}</>;
+};
 
 const Section: React.FC<PropTypes> = ({ rawLines, level = 0 }) => {
   const deeperLevelIndex = rawLines.findIndex(line => line.match(`^#{${level + 1},} .*$`));
   const rawContent = rawLines.splice(0, (deeperLevelIndex < 0) ? rawLines.length : deeperLevelIndex);
 
-  if (!level) return (
-    <>
-      <Typography> <Content rawLines={rawContent} /> </Typography>
-      <ChildrenSections rawLines={rawLines} level={getHeaderLevel(rawLines[0])}/>
-    </>
-  )
+  if (!level) {
+    return (
+      <>
+        <Typography><Content rawLines={rawContent} /></Typography>
+        <ChildrenSections rawLines={rawLines} level={getHeaderLevel(rawLines[0])} />
+      </>
+    );
+  }
 
   const sectionName = rawContent.splice(0, 1)[0].slice(level).trim();
   const deeperLevel = getHeaderLevel(rawLines[0]);
@@ -46,7 +48,7 @@ const Section: React.FC<PropTypes> = ({ rawLines, level = 0 }) => {
       <ChildrenSections rawLines={rawLines} level={deeperLevel} />
     </ContentSection>
   );
-}
+};
 
 export default Section;
 
diff --git a/src/lib/Markdown/SyntacticSpan.tsx b/src/lib/Markdown/SyntacticSpan.tsx
index f3c2125..bdce3f7 100644
--- a/src/lib/Markdown/SyntacticSpan.tsx
+++ b/src/lib/Markdown/SyntacticSpan.tsx
@@ -19,24 +19,24 @@ interface Emoji {
 
 const enclosureRegex = (e: string): RegexPair => ({
   local: new RegExp(`${e}([^${e}]+)${e}`),
-  global: new RegExp(`(${e}[^${e}]+${e})`)
+  global: new RegExp(`(${e}[^${e}]+${e})`),
 });
 
 const regex: Record<string, RegexPair> = {
   conceal: {
     global: /(!?\[.+?\]\(.+?\))(?!])/g,
-    local: /!?\[(.*\]?.*)\]\((.+?)\)/
+    local: /!?\[(.*\]?.*)\]\((.+?)\)/,
   },
   rawLink: {
     global: /((?:(?:[A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=+$,\w]+@)?[A-Za-z0-9.-]+|(?:www\.|[-;:&=+$,\w]+@)[A-Za-z0-9.-]+)(?:(?:\/[+~%/.\w-_]*)?\??(?:[-+=&;%@.\w_]*)#?(?:[.!/\\\w]*))?)/,
-    local: /&^/
+    local: /&^/,
   },
   emoji: enclosureRegex(':'),
   bold: enclosureRegex('\\*\\*'),
   italic: enclosureRegex('\\*'),
   code: enclosureRegex('`'),
   strikeThrough: enclosureRegex('~~'),
-}
+};
 
 const splitter = new RegExp(Object.values(regex).map(pair => pair.global.source).join('|'));
 
@@ -46,13 +46,13 @@ Object.keys(emojiLib).forEach(name => emojiList.push({ name, char: emojiLib[name
 const useStyles = makeStyles(theme => ({
   code: {
     background: theme.palette.background.default,
-    borderRadius: theme.spacing(.5),
-    padding: theme.spacing(.5),
+    borderRadius: theme.spacing(0.5),
+    padding: theme.spacing(0.5),
     fontFamily: 'Monospace',
   },
   image: {
     maxWidth: '100%',
-    maxHeight: '100%'
+    maxHeight: '100%',
   },
 }));
 
@@ -82,12 +82,12 @@ const SyntacticSpan: React.FC<PropTypes> = ({ span }) => {
   if (matchItalic) return <i>{matchItalic[1]}</i>;
 
   const matchStrikeThrough = span.match(regex.strikeThrough.local);
-  if (matchStrikeThrough) return <span style={{textDecoration: 'line-through' }}>{matchStrikeThrough[1]}</span>;
+  if (matchStrikeThrough) return <span style={{ textDecoration: 'line-through' }}>{matchStrikeThrough[1]}</span>;
 
   if (span.match(regex.rawLink.global)) return <Link href={span}>{span}</Link>;
 
   return <>{span}</>;
-}
+};
 
 
 export { splitter };
diff --git a/src/lib/Markdown/Text.tsx b/src/lib/Markdown/Text.tsx
index e287dee..be715fd 100644
--- a/src/lib/Markdown/Text.tsx
+++ b/src/lib/Markdown/Text.tsx
@@ -7,7 +7,7 @@ interface PropTypes {
 
 const Text: React.FC<PropTypes> = ({ line }) => {
   return <>{line.split(splitter).map(span => <SyntacticSpan span={span} />)}</>;
-}
+};
 
 export default Text;
 
diff --git a/src/lib/SmartList/SmartList.tsx b/src/lib/SmartList/SmartList.tsx
index 22cd3b2..c86c127 100644
--- a/src/lib/SmartList/SmartList.tsx
+++ b/src/lib/SmartList/SmartList.tsx
@@ -21,8 +21,7 @@ interface Size {
 
 
 const SmartList: React.FC<PropTypes> = ({ itemSize, itemCount, renderItem }) => {
-
-  const ResizedList: React.FC<Size> = ({ width, height}) => (
+  const ResizedList: React.FC<Size> = ({ width, height }) => (
     <FixedSizeList
       height={height}
       width={width}
diff --git a/src/lib/Window/Window.tsx b/src/lib/Window/Window.tsx
index 6821593..beaa672 100644
--- a/src/lib/Window/Window.tsx
+++ b/src/lib/Window/Window.tsx
@@ -47,12 +47,13 @@ const Window: React.FC<PropTypes> = ({ type, name, children }) => {
       size={size}
       position={position}
     >
-      {name &&
+      {name
+      && (
       <div>
         <Typography variant="h5" className={classes.header}>{name}</Typography>
         <Divider />
       </div>
-      }
+      )}
       {children}
     </WindowSurface>
   );
diff --git a/src/lib/Window/WindowSurface.tsx b/src/lib/Window/WindowSurface.tsx
index a65e398..1900901 100644
--- a/src/lib/Window/WindowSurface.tsx
+++ b/src/lib/Window/WindowSurface.tsx
@@ -22,7 +22,7 @@ const useStyles = makeStyles(theme => ({
     '& a.MuiTypography-root': {
       color: theme.palette.primary.light,
     },
-  }
+  },
 }));
 
 
@@ -32,12 +32,12 @@ const WindowSurface: React.FC<PropTypes> = ({ size, position, children }) => {
   return (
     <Paper
       variant="outlined"
-      style={{...size, ...position}}
+      style={{ ...size, ...position }}
       className={classes.surface}
     >
       {children}
     </Paper>
-  )
+  );
 };
 
 
diff --git a/src/react-app-env.d.ts b/src/react-app-env.d.ts
index 6431bc5..30da896 100644
--- a/src/react-app-env.d.ts
+++ b/src/react-app-env.d.ts
@@ -1 +1 @@
-/// <reference types="react-scripts" />
+// / <reference types="react-scripts" />
-- 
cgit v1.2.3


From 9272b0af3d7b2fba4738a341a1f2776243e0e515 Mon Sep 17 00:00:00 2001
From: eug-vs <eug-vs@keemail.me>
Date: Sat, 18 Apr 2020 20:44:55 +0300
Subject: style: manually fix some errors

---
 .eslintrc.json                            |  2 ++
 src/lib/ContentSection/ContentSection.tsx |  6 +++---
 src/lib/Markdown/Content.tsx              | 12 +++++++-----
 src/lib/Markdown/Markdown.tsx             | 11 +++++++----
 4 files changed, 19 insertions(+), 12 deletions(-)

diff --git a/.eslintrc.json b/.eslintrc.json
index c5c45a7..a755820 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -12,7 +12,9 @@
     "jsx-quotes": ["error", "prefer-double"],
     "quotes": ["error", "single"],
     "react/prop-types": 0,
+    "react/no-children-prop": 0,
     "arrow-body-style": 0,
+    "no-cond-assign": 0,
     "arrow-parens": [2, "as-needed"],
     "no-multiple-empty-lines": [2, { "max": 2, "maxEOF": 1 } ]
   }
diff --git a/src/lib/ContentSection/ContentSection.tsx b/src/lib/ContentSection/ContentSection.tsx
index 6b27bba..28b1ad5 100644
--- a/src/lib/ContentSection/ContentSection.tsx
+++ b/src/lib/ContentSection/ContentSection.tsx
@@ -26,11 +26,11 @@ const useStyles = makeStyles(theme => ({
 const ContentSection: React.FC<PropTypes> = ({ sectionName, children, level = 0 }) => {
   const classes = useStyles();
 
-  level += 2; // Make everything smaller
-  if (level > 6) level = 6;
+  let adjustedLevel = level + 2; // Make everything smaller
+  if (adjustedLevel > 6) adjustedLevel = 6;
 
   type Variant = 'h3' | 'h4' | 'h5' | 'h6';
-  const variant: Variant = `h${level}` as Variant;
+  const variant: Variant = `h${adjustedLevel}` as Variant;
 
   return (
     <>
diff --git a/src/lib/Markdown/Content.tsx b/src/lib/Markdown/Content.tsx
index d64720b..88409fa 100644
--- a/src/lib/Markdown/Content.tsx
+++ b/src/lib/Markdown/Content.tsx
@@ -40,17 +40,19 @@ const Content: React.FC<ParserPropTypes> = ({ rawLines }) => {
 
   let buffer;
   if (denotesCodeBlock(line)) {
-    const closeIndex = rawLines.findIndex(line => denotesCodeBlock(line));
+    const closeIndex = rawLines.findIndex(rawLine => denotesCodeBlock(rawLine));
     const codeBlockLines = rawLines.splice(0, closeIndex + 1).slice(0, closeIndex);
     buffer = <CodeBlock rawLines={codeBlockLines} />;
   } else if (denotesDottedList(line)) {
-    const closeIndex = rawLines.findIndex(line => !denotesDottedList(line));
+    const closeIndex = rawLines.findIndex(rawLine => !denotesDottedList(rawLine));
     const dottedListLines = rawLines.splice(0, closeIndex).slice(0, closeIndex);
     dottedListLines.unshift(line);
     buffer = <ul>{dottedListLines.map(li => <li><Text line={li.slice(2)} /></li>)}</ul>;
   } else if ((buffer = denotesOpenHtml(line))) {
     const tag = buffer;
-    const closeIndex = denotesClosingHtml(line, tag) ? -1 : rawLines.findIndex(line => denotesClosingHtml(line, tag));
+    const closeIndex = denotesClosingHtml(line, tag) ? -1 : rawLines.findIndex(
+      rawLine => denotesClosingHtml(rawLine, tag),
+    );
     const htmlLines = rawLines.splice(0, closeIndex + 1);
     htmlLines.unshift(line);
     buffer = <div dangerouslySetInnerHTML={{ __html: htmlLines.join('\n') }} />;
@@ -65,8 +67,8 @@ const Content: React.FC<ParserPropTypes> = ({ rawLines }) => {
       </>
     );
   } else if (declaresNoLineBreak(line)) {
-    const closeIndex = rawLines.findIndex(line => !declaresNoLineBreak(line));
-    const lineBreakLines = rawLines.splice(0, closeIndex).map(line => line.slice(0, -2));
+    const closeIndex = rawLines.findIndex(rawLine => !declaresNoLineBreak(rawLine));
+    const lineBreakLines = rawLines.splice(0, closeIndex).map(rawLine => rawLine.slice(0, -2));
     lineBreakLines.unshift(line.slice(0, -2));
     lineBreakLines.push(rawLines.splice(0, 1)[0]);
     buffer = <p>{lineBreakLines.map(lineBreakLine => <Text line={lineBreakLine} />)}</p>;
diff --git a/src/lib/Markdown/Markdown.tsx b/src/lib/Markdown/Markdown.tsx
index 68967c5..cfcf117 100644
--- a/src/lib/Markdown/Markdown.tsx
+++ b/src/lib/Markdown/Markdown.tsx
@@ -8,10 +8,13 @@ interface PropTypes {
   url?: string;
 }
 
-const resolveUrls = (line: string, baseUrl: string): string => {
-  return line.replace(/src="(?!http)(.*)"[\s>]/, (match, url, offset, string) => `src="${baseUrl}/${url}?sanitize=true"`)
-    .replace(/\[(.*\]?.*)\]\((?!http)(.+?)\)/, (match, text, url, offset, string) => `[${text}](${baseUrl}/${url})`);
-};
+const resolveUrls = (line: string, baseUrl: string): string => line.replace(
+  /src="(?!http)(.*)"[\s>]/,
+  (match, url) => `src="${baseUrl}/${url}?sanitize=true"`,
+).replace(
+  /\[(.*\]?.*)\]\((?!http)(.+?)\)/,
+  (match, text, url) => `[${text}](${baseUrl}/${url})`,
+);
 
 const Markdown: React.FC<PropTypes> = ({ data, url }) => {
   const [markdown, setMarkdown] = useState<string>(data || '');
-- 
cgit v1.2.3


From 8e4a483fb7d1ebdfc950c1cc456ae2d4bd558147 Mon Sep 17 00:00:00 2001
From: eug-vs <eug-vs@keemail.me>
Date: Sat, 18 Apr 2020 20:52:31 +0300
Subject: style: fix remaining errors

---
 .eslintrc.json                     | 4 +++-
 src/lib/Markdown/Section.tsx       | 2 +-
 src/lib/Markdown/SyntacticSpan.tsx | 3 ++-
 3 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/.eslintrc.json b/.eslintrc.json
index a755820..5e44a20 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -13,9 +13,11 @@
     "quotes": ["error", "single"],
     "react/prop-types": 0,
     "react/no-children-prop": 0,
+    "react/no-danger": 0,
     "arrow-body-style": 0,
     "no-cond-assign": 0,
     "arrow-parens": [2, "as-needed"],
-    "no-multiple-empty-lines": [2, { "max": 2, "maxEOF": 1 } ]
+    "no-multiple-empty-lines": [2, { "max": 2, "maxEOF": 1 } ],
+    "max-len": ["error", { "code": 120 }]
   }
 }
diff --git a/src/lib/Markdown/Section.tsx b/src/lib/Markdown/Section.tsx
index f554062..fc208b1 100644
--- a/src/lib/Markdown/Section.tsx
+++ b/src/lib/Markdown/Section.tsx
@@ -11,7 +11,7 @@ interface PropTypes extends ParserPropTypes {
 const getHeaderLevel = (header: string): number => {
   if (!header) return 0;
   let level = 0;
-  while (header[level] === '#') level++;
+  while (header[level] === '#') level += 1;
   return level;
 };
 
diff --git a/src/lib/Markdown/SyntacticSpan.tsx b/src/lib/Markdown/SyntacticSpan.tsx
index bdce3f7..11cc024 100644
--- a/src/lib/Markdown/SyntacticSpan.tsx
+++ b/src/lib/Markdown/SyntacticSpan.tsx
@@ -28,6 +28,7 @@ const regex: Record<string, RegexPair> = {
     local: /!?\[(.*\]?.*)\]\((.+?)\)/,
   },
   rawLink: {
+    // eslint-disable-next-line max-len
     global: /((?:(?:[A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=+$,\w]+@)?[A-Za-z0-9.-]+|(?:www\.|[-;:&=+$,\w]+@)[A-Za-z0-9.-]+)(?:(?:\/[+~%/.\w-_]*)?\??(?:[-+=&;%@.\w_]*)#?(?:[.!/\\\w]*))?)/,
     local: /&^/,
   },
@@ -68,7 +69,7 @@ const SyntacticSpan: React.FC<PropTypes> = ({ span }) => {
 
   const matchEmoji = span.match(regex.emoji.local);
   if (matchEmoji) {
-    const emoji = emojiList.find(emoji => emoji.name === matchEmoji[1]);
+    const emoji = emojiList.find(e => e.name === matchEmoji[1]);
     return <span>{emoji ? emoji.char : span}</span>;
   }
 
-- 
cgit v1.2.3


From f4f8689631d247f0be93c2f32791c9ba02ecb64e Mon Sep 17 00:00:00 2001
From: eug-vs <eug-vs@keemail.me>
Date: Sat, 18 Apr 2020 21:01:34 +0300
Subject: style: fix index.tsx

---
 .eslintrc.json | 12 ++++++------
 src/index.tsx  | 21 +++++++++++----------
 2 files changed, 17 insertions(+), 16 deletions(-)

diff --git a/.eslintrc.json b/.eslintrc.json
index 5e44a20..c86a906 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -11,13 +11,13 @@
   "rules": {
     "jsx-quotes": ["error", "prefer-double"],
     "quotes": ["error", "single"],
-    "react/prop-types": 0,
-    "react/no-children-prop": 0,
-    "react/no-danger": 0,
+    "no-multiple-empty-lines": [2, { "max": 2, "maxEOF": 1 } ],
+    "max-len": ["error", { "code": 120 }],
+    "arrow-parens": [2, "as-needed"],
     "arrow-body-style": 0,
     "no-cond-assign": 0,
-    "arrow-parens": [2, "as-needed"],
-    "no-multiple-empty-lines": [2, { "max": 2, "maxEOF": 1 } ],
-    "max-len": ["error", { "code": 120 }]
+    "react/prop-types": 0,
+    "react/no-children-prop": 0,
+    "react/no-danger": 0
   }
 }
diff --git a/src/index.tsx b/src/index.tsx
index ac7bfc2..c5e1989 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -96,7 +96,8 @@ const LivePreviewPage: React.FC<LivePropTypes> = ({ setLivePreviewData }) => {
     <>
       <ContentSection sectionName="Markdown live preview" level={2}>
         <p>
-          Start typing and see your text rendered on the left window! We recommend starting with # Header.
+          Start typing and see your text rendered on the left window!
+          We recommend starting with # Header.
         </p>
         <p>
           <TextField
@@ -127,6 +128,7 @@ const App: React.FC = () => {
   const url = pageMap[page];
   const fileName = url?.slice(url.lastIndexOf('/') + 1);
   const info = [
+    /* eslint-disable max-len */
     `## Markdown\n [Markdown file](${url}) *(...${fileName})* that you can see on the left was parsed and rendered by **BENZIN**! :rocket:`,
     'Switch between tabs on the header to explore other markdown templates. :recycle: ',
     'Currently **only core features** of markdown function.',
@@ -137,8 +139,15 @@ const App: React.FC = () => {
     'const data = \'# Header\\nHello, *world!*\';',
     'ReactDOM.render(<Markdown data={data}/>, document.getElementById(\'root\'));',
     '```',
+    /* eslint-enable max-len */
   ].join('\n');
 
+  let primaryWindowContent = <Markdown url={url} />;
+  if (page === 'custom') primaryWindowContent = <CustomPage />;
+  else if (page === 'live preview') {
+    primaryWindowContent = <Markdown data={livePreviewData || '# Start typing in the right window!'} />;
+  }
+
   return (
     <Benzin>
       <Header
@@ -151,15 +160,7 @@ const App: React.FC = () => {
         setPage={setPage}
       />
       <Window type="primary">
-        <div className={classes.window}>
-          {
-            (page === 'custom')
-              ? <CustomPage />
-              : (page === 'live preview')
-                ? <Markdown data={livePreviewData || '# Start typing in the right window!'} />
-                : <Markdown url={url} />
-          }
-        </div>
+        <div className={classes.window}>{primaryWindowContent}</div>
       </Window>
       <Window type="secondary" name="Feature preview">
         <div className={classes.window}>
-- 
cgit v1.2.3


From a31244374f5609e89d8ff22e4111ab04d94886a2 Mon Sep 17 00:00:00 2001
From: eug-vs <eug-vs@keemail.me>
Date: Sat, 18 Apr 2020 21:11:52 +0300
Subject: fix: disable linting for env.d.ts

---
 src/react-app-env.d.ts | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/react-app-env.d.ts b/src/react-app-env.d.ts
index 30da896..c7466ce 100644
--- a/src/react-app-env.d.ts
+++ b/src/react-app-env.d.ts
@@ -1 +1,2 @@
-// / <reference types="react-scripts" />
+// eslint-disable-next-line
+/// <reference types="react-scripts" />
-- 
cgit v1.2.3