diff --git a/.eslintrc.js b/.eslintrc.js index 3480d73..24a6fc7 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -50,6 +50,7 @@ module.exports = { }, ], rules: { + // "prettier/prettier": ["error", { endOfLine: "auto", },], "react/jsx-filename-extension": "off", "import/prefer-default-export": "off", "prefer-destructuring": "off", @@ -59,5 +60,6 @@ module.exports = { "no-underscore-dangle": "off", "react/forbid-prop-types": "off", "react/prop-types": "off", + "no-console":"off", }, }; diff --git a/package-lock.json b/package-lock.json index 993b456..4466f39 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2097,6 +2097,15 @@ "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=" }, + "@types/mdast": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.3.tgz", + "integrity": "sha512-SXPBMnFVQg1s00dlMCc/jCdvPqdE4mXaMMCeRlxLDmTAEoegHT53xKtkDnzDTOcmMHUfcjyf36/YYZ6SxRdnsw==", + "dev": true, + "requires": { + "@types/unist": "*" + } + }, "@types/minimatch": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", @@ -2166,6 +2175,12 @@ "source-map": "^0.6.1" } }, + "@types/unist": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.3.tgz", + "integrity": "sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==", + "dev": true + }, "@types/webpack": { "version": "4.41.26", "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.26.tgz", @@ -3292,12 +3307,6 @@ "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==" }, - "bail": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz", - "integrity": "sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ==", - "dev": true - }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -3578,15 +3587,27 @@ } }, "browserslist": { - "version": "4.16.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.3.tgz", - "integrity": "sha512-vIyhWmIkULaq04Gt93txdh+j02yX/JzlyhLYbV3YQCn/zvES3JnY7TifHHvvr1w5hTDluNKMkV05cs4vy8Q7sw==", + "version": "4.16.6", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz", + "integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==", "requires": { - "caniuse-lite": "^1.0.30001181", - "colorette": "^1.2.1", - "electron-to-chromium": "^1.3.649", + "caniuse-lite": "^1.0.30001219", + "colorette": "^1.2.2", + "electron-to-chromium": "^1.3.723", "escalade": "^3.1.1", - "node-releases": "^1.1.70" + "node-releases": "^1.1.71" + }, + "dependencies": { + "caniuse-lite": { + "version": "1.0.30001230", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001230.tgz", + "integrity": "sha512-5yBd5nWCBS+jWKTcHOzXwo5xzcj4ePE/yjtkZyUV1BTUmrBaA9MRGC+e7mxnqXSA90CmCA8L3eKLaSUkt099IQ==" + }, + "electron-to-chromium": { + "version": "1.3.739", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.739.tgz", + "integrity": "sha512-+LPJVRsN7hGZ9EIUUiWCpO7l4E3qBYHNadazlucBfsXBbccDFNKUBAgzE68FnkWGJPwD/AfKhSzL+G+Iqb8A4A==" + } } }, "bser": { @@ -3970,12 +3991,6 @@ } } }, - "collapse-white-space": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.6.tgz", - "integrity": "sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ==", - "dev": true - }, "collect-v8-coverage": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", @@ -5880,13 +5895,12 @@ } }, "eslint-plugin-markdown": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-markdown/-/eslint-plugin-markdown-2.0.0.tgz", - "integrity": "sha512-zt10JoexHeJFMTE5egDcetAJ34bn5k/92s0wAuRZfhDAyI0ryEj+O91JL2CbBExajie6BE5L63y47dN1Sbp6mQ==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-markdown/-/eslint-plugin-markdown-2.2.0.tgz", + "integrity": "sha512-Ctuc7aP1tU92qnFwVO1wDLEzf1jqMxwRkcSTw7gjbvnEqfh5CKUcTXM0sxg8CB2KDXrqpTuMZPgJ1XE9Olr7KA==", "dev": true, "requires": { - "remark-parse": "^5.0.0", - "unified": "^6.1.2" + "mdast-util-from-markdown": "^0.8.5" } }, "eslint-plugin-node": { @@ -7222,9 +7236,9 @@ "integrity": "sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ==" }, "hosted-git-info": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", - "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==" + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==" }, "hpack.js": { "version": "2.1.6", @@ -8029,23 +8043,11 @@ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" }, - "is-whitespace-character": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz", - "integrity": "sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w==", - "dev": true - }, "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" }, - "is-word-character": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.4.tgz", - "integrity": "sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA==", - "dev": true - }, "is-wsl": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", @@ -9415,12 +9417,6 @@ "object-visit": "^1.0.0" } }, - "markdown-escapes": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.4.tgz", - "integrity": "sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg==", - "dev": true - }, "md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -9431,6 +9427,25 @@ "safe-buffer": "^5.1.2" } }, + "mdast-util-from-markdown": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-0.8.5.tgz", + "integrity": "sha512-2hkTXtYYnr+NubD/g6KGBS/0mFmBcifAsI0yIWRiRo0PjVs6SSOSOdtzbp6kSGnShDN6G5aWZpKQ2lWRy27mWQ==", + "dev": true, + "requires": { + "@types/mdast": "^3.0.0", + "mdast-util-to-string": "^2.0.0", + "micromark": "~2.11.0", + "parse-entities": "^2.0.0", + "unist-util-stringify-position": "^2.0.0" + } + }, + "mdast-util-to-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz", + "integrity": "sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==", + "dev": true + }, "mdn-data": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", @@ -9499,6 +9514,16 @@ "resolved": "https://registry.npmjs.org/microevent.ts/-/microevent.ts-0.1.1.tgz", "integrity": "sha512-jo1OfR4TaEwd5HOrt5+tAZ9mqT4jmpNAusXtyfNzqVm9uiSYFZlKM1wYL4oU7azZW/PxQW53wM0S6OR1JHNa2g==" }, + "micromark": { + "version": "2.11.4", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-2.11.4.tgz", + "integrity": "sha512-+WoovN/ppKolQOFIAajxi7Lu9kInbPxFuTBVEavFcL8eAfVstoc5MocPmqBeAdBOJV00uaVjegzH4+MA0DN/uA==", + "dev": true, + "requires": { + "debug": "^4.0.0", + "parse-entities": "^2.0.0" + } + }, "micromatch": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", @@ -9758,11 +9783,6 @@ "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==", "optional": true }, - "nanoid": { - "version": "3.1.20", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz", - "integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==" - }, "nanomatch": { "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", @@ -10344,9 +10364,9 @@ } }, "parse-entities": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.2.2.tgz", - "integrity": "sha512-NzfpbxW/NPrzZ/yYSoQxyqUZMZXIdCfE0OIN4ESsnptHJECoUk3FZktxNuzQf4tjt5UEopnxpYJbvYuxIFDdsg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz", + "integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==", "dev": true, "requires": { "character-entities": "^1.0.0", @@ -11555,13 +11575,20 @@ }, "dependencies": { "postcss": { - "version": "8.2.8", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.2.8.tgz", - "integrity": "sha512-1F0Xb2T21xET7oQV9eKuctbM9S7BC0fetoHCc4H13z0PT6haiRLP4T0ZY4XWh7iLP0usgqykT6p9B2RtOf4FPw==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.3.0.tgz", + "integrity": "sha512-+ogXpdAjWGa+fdYY5BQ96V/6tAo+TdSSIMP5huJBIygdWwKtVoB5JWZ7yUd4xZ8r+8Kvvx4nyg/PQ071H4UtcQ==", "requires": { "colorette": "^1.2.2", - "nanoid": "^3.1.20", - "source-map": "^0.6.1" + "nanoid": "^3.1.23", + "source-map-js": "^0.6.2" + }, + "dependencies": { + "nanoid": { + "version": "3.1.23", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz", + "integrity": "sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==" + } } } } @@ -12458,29 +12485,6 @@ "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=" }, - "remark-parse": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-5.0.0.tgz", - "integrity": "sha512-b3iXszZLH1TLoyUzrATcTQUZrwNl1rE70rVdSruJFlDaJ9z5aMkhrG43Pp68OgfHndL/ADz6V69Zow8cTQu+JA==", - "dev": true, - "requires": { - "collapse-white-space": "^1.0.2", - "is-alphabetical": "^1.0.0", - "is-decimal": "^1.0.0", - "is-whitespace-character": "^1.0.0", - "is-word-character": "^1.0.0", - "markdown-escapes": "^1.0.0", - "parse-entities": "^1.1.0", - "repeat-string": "^1.5.4", - "state-toggle": "^1.0.0", - "trim": "0.0.1", - "trim-trailing-lines": "^1.0.0", - "unherit": "^1.0.4", - "unist-util-remove-position": "^1.0.0", - "vfile-location": "^2.0.0", - "xtend": "^4.0.1" - } - }, "remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", @@ -12523,12 +12527,6 @@ "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" }, - "replace-ext": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", - "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", - "dev": true - }, "request": { "version": "2.88.2", "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", @@ -13606,6 +13604,11 @@ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, + "source-map-js": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-0.6.2.tgz", + "integrity": "sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug==" + }, "source-map-resolve": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.6.0.tgz", @@ -13749,12 +13752,6 @@ "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.2.0.tgz", "integrity": "sha512-GrdeshiRmS1YLMYgzF16olf2jJ/IzxXY9lhKOskuVziubpTYcYqyOwYeJKzQkwy7uN0fYSsbsC4RQaXf9LCrYA==" }, - "state-toggle": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.3.tgz", - "integrity": "sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ==", - "dev": true - }, "static-extend": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", @@ -14483,24 +14480,6 @@ "punycode": "^2.1.1" } }, - "trim": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", - "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=", - "dev": true - }, - "trim-trailing-lines": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.4.tgz", - "integrity": "sha512-rjUWSqnfTNrjbB9NQWfPMH/xRK1deHeGsHoVfpxJ++XeYXE0d6B1En37AHfw3jtfTU7dzMzZL2jjpe8Qb5gLIQ==", - "dev": true - }, - "trough": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz", - "integrity": "sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==", - "dev": true - }, "tryer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz", @@ -14625,16 +14604,6 @@ "which-boxed-primitive": "^1.0.1" } }, - "unherit": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.3.tgz", - "integrity": "sha512-Ft16BJcnapDKp0+J/rqFC3Rrk6Y/Ng4nzsC028k2jdDII/rdZ7Wd3pPT/6+vIIxRagwRc9K0IUX0Ra4fKvw+WQ==", - "dev": true, - "requires": { - "inherits": "^2.0.0", - "xtend": "^4.0.0" - } - }, "unicode-canonical-property-names-ecmascript": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", @@ -14659,20 +14628,6 @@ "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz", "integrity": "sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg==" }, - "unified": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/unified/-/unified-6.2.0.tgz", - "integrity": "sha512-1k+KPhlVtqmG99RaTbAv/usu85fcSRu3wY8X+vnsEhIxNP5VbVIDiXnLqyKIG+UMdyTg0ZX9EI6k2AfjJkHPtA==", - "dev": true, - "requires": { - "bail": "^1.0.0", - "extend": "^3.0.0", - "is-plain-obj": "^1.1.0", - "trough": "^1.0.0", - "vfile": "^2.0.0", - "x-is-string": "^0.1.0" - } - }, "union-value": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", @@ -14718,43 +14673,13 @@ "crypto-random-string": "^1.0.0" } }, - "unist-util-is": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-3.0.0.tgz", - "integrity": "sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A==", - "dev": true - }, - "unist-util-remove-position": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-1.1.4.tgz", - "integrity": "sha512-tLqd653ArxJIPnKII6LMZwH+mb5q+n/GtXQZo6S6csPRs5zB0u79Yw8ouR3wTw8wxvdJFhpP6Y7jorWdCgLO0A==", - "dev": true, - "requires": { - "unist-util-visit": "^1.1.0" - } - }, "unist-util-stringify-position": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-1.1.2.tgz", - "integrity": "sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ==", - "dev": true - }, - "unist-util-visit": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.4.1.tgz", - "integrity": "sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw==", - "dev": true, - "requires": { - "unist-util-visit-parents": "^2.0.0" - } - }, - "unist-util-visit-parents": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz", - "integrity": "sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz", + "integrity": "sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==", "dev": true, "requires": { - "unist-util-is": "^3.0.0" + "@types/unist": "^2.0.2" } }, "universalify": { @@ -14986,33 +14911,6 @@ "extsprintf": "^1.2.0" } }, - "vfile": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-2.3.0.tgz", - "integrity": "sha512-ASt4mBUHcTpMKD/l5Q+WJXNtshlWxOogYyGYYrg4lt/vuRjC1EFQtlAofL5VmtVNIZJzWYFJjzGWZ0Gw8pzW1w==", - "dev": true, - "requires": { - "is-buffer": "^1.1.4", - "replace-ext": "1.0.0", - "unist-util-stringify-position": "^1.0.0", - "vfile-message": "^1.0.0" - } - }, - "vfile-location": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-2.0.6.tgz", - "integrity": "sha512-sSFdyCP3G6Ka0CEmN83A2YCMKIieHx0EDaj5IDP4g1pa5ZJ4FJDvpO0WODLxo4LUX4oe52gmSCK7Jw4SBghqxA==", - "dev": true - }, - "vfile-message": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-1.1.1.tgz", - "integrity": "sha512-1WmsopSGhWt5laNir+633LszXvZ+Z/lxveBf6yhGsqnQIhlhzooZae7zV6YVM1Sdkw68dtAW3ow0pOdPANugvA==", - "dev": true, - "requires": { - "unist-util-stringify-position": "^1.1.1" - } - }, "vm-browserify": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", @@ -15523,8 +15421,7 @@ }, "ssri": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", - "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", + "resolved": "", "requires": { "figgy-pudding": "^3.5.1" } @@ -16455,12 +16352,6 @@ "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.4.tgz", "integrity": "sha512-Qm8k8ojNQIMx7S+Zp8u/uHOx7Qazv3Yv4q68MiWWWOJhiwG5W3x7iqmRtJo8xxrciZUY4vRxUTJCKuRnF28ZZw==" }, - "x-is-string": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/x-is-string/-/x-is-string-0.1.0.tgz", - "integrity": "sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI=", - "dev": true - }, "xml-name-validator": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", diff --git a/package.json b/package.json index a154f9e..5569635 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "eslint-plugin-import": "^2.22.1", "eslint-plugin-jest": "^24.2.1", "eslint-plugin-jsx-a11y": "^6.4.1", - "eslint-plugin-markdown": "^2.0.0", + "eslint-plugin-markdown": "^2.2.0", "eslint-plugin-node": "^11.1.0", "eslint-plugin-react": "^7.22.0", "eslint-plugin-react-hooks": "^4.2.0", diff --git a/src/App.js b/src/App.js index 3a49c0e..d3f7545 100644 --- a/src/App.js +++ b/src/App.js @@ -1,9 +1,38 @@ import React from "react"; +import { Switch, Route } from "react-router-dom"; + +import { + CHARACTER, + EPISODE, + // EPISODES, + HOME, + LOCATION, +} from "./constants/routes"; + import Home from "./pages/Home"; +import Episode from "./pages/Episode"; +import CharacterPage from "./pages/Character"; +import LocationPage from "./pages/LocationPage"; function App() { - return ; + return ( + + } + /> + } + /> + } + /> + } /> + + ); } export default App; diff --git a/src/api/api.js b/src/api/api.js new file mode 100644 index 0000000..b5e5dd2 --- /dev/null +++ b/src/api/api.js @@ -0,0 +1,26 @@ +import axios from "axios"; + +export function makeApi() { + return axios.create({ + baseURL: "https://rickandmortyapi.com/api", + timeout: 1000, + }); +} + +export function getEpisodes(page = 1, api = makeApi()) { + return api.get(`/episode?page=${page}`); +} + +export function getEpisode(episodeId, api = makeApi()) { + return api.get(`/episode/${episodeId}`); +} +export function getCharacters(characterId, api = makeApi()) { + return api.get(`/character/${characterId}`); +} +export function getLocation(locationId, api = makeApi()) { + return api.get(`/location/${locationId}`); +} + +export function getUrl(url, api = makeApi()) { + return api.get(url); +} diff --git a/src/api/index.js b/src/api/index.js new file mode 100644 index 0000000..d158c57 --- /dev/null +++ b/src/api/index.js @@ -0,0 +1 @@ +export * from "./api"; diff --git a/src/components/EpisodeCard/EpisodeCard.js b/src/components/EpisodeCard/EpisodeCard.js index 13cb5cf..6b2235a 100644 --- a/src/components/EpisodeCard/EpisodeCard.js +++ b/src/components/EpisodeCard/EpisodeCard.js @@ -1,6 +1,10 @@ import React from "react"; import { Link } from "react-router-dom"; +// import { axios } from "axios"; + +// import { getCharacters } from "../../api"; + import "./EpisodeCard.scss"; import * as routes from "../../constants/routes"; diff --git a/src/pages/Character/characterPage.js b/src/pages/Character/characterPage.js new file mode 100644 index 0000000..612baf1 --- /dev/null +++ b/src/pages/Character/characterPage.js @@ -0,0 +1,159 @@ +import React, { Component } from "react"; + +import Layout from "../../components/Layout"; + +import { getCharacters, getUrl } from "../../api"; + +import "../../components/CharacterCard/CharacterCard.scss"; + +import EpisodeCard from "../../components/EpisodeCard"; + +import * as routes from "../../constants/routes"; + +function makePromises(urls = []) { + const myArray = urls.map((url) => getUrl(url)); + // console.log(myArray); + return myArray; +} + +class CharacterPage extends Component { + constructor(props) { + super(props); + + this.state = { + episodes: [], + name: "", + image: "", + species: "", + status: "", + origin: "", + location: "", + hasLoaded: false, + hasError: false, + errorMessage: null, + }; + this.loadCharacters = this.loadCharacters.bind(this); + } + + componentDidMount() { + // console.log(this); + + const { match } = this.props; + const { characterId } = match.params; + + // console.log(characterId); + this.loadCharacters(characterId); + } + + async loadCharacters(characterId) { + // console.log(this); + try { + const { data } = await getCharacters(characterId); + + // eslint-disable-next-line compat/compat + const characterEpisodes = await Promise.all( + makePromises(data.episode), + ); + + const episodesFromCharacter = characterEpisodes.map((character) => character.data); + + console.log(episodesFromCharacter); + + this.setState({ + episodes: episodesFromCharacter, + name: data.name, + image: data.image, + species: data.species, + status: data.status, + origin: data.origin.name, + location: data.location.name, + hasLoaded: true, + hasError: false, + errorMessage: null, + + }); + + console.log(data); + } catch (error) { + this.setState({ + hasLoaded: true, + hasError: true, + errorMessage: error.message, + }); + } + } + + render() { + const { + episodes, + name, + image, + species, + status, + origin, + location, + hasLoaded, + hasError, + errorMessage, + } = this.state; + + return ( + +
+ {!hasLoaded && ( +
+
+

Loading data...

+
+
+ )} + {hasError && ( +
+
+

Something went wrong...

+

{errorMessage}

+
+
+ )} +
+
+ +
+
+

{name}

+
+
+
CHARACTER
+

{species} | {status}

+
+
+
+
ORIGIN
+

{origin}

+
+
+
LOCATION
+

{location}

+
+
+
+
+
+
+ {episodes.length > 0 && + episodes.map((episode) => ( + + ))} +
+
+
+ ); + } +} +export default CharacterPage; diff --git a/src/pages/Character/index.js b/src/pages/Character/index.js new file mode 100644 index 0000000..34d5b02 --- /dev/null +++ b/src/pages/Character/index.js @@ -0,0 +1 @@ +export { default } from "./characterPage"; \ No newline at end of file diff --git a/src/pages/Episode/Episode.js b/src/pages/Episode/Episode.js index 8255df5..dd4a6a2 100644 --- a/src/pages/Episode/Episode.js +++ b/src/pages/Episode/Episode.js @@ -1,38 +1,137 @@ import React, { Component } from "react"; +// import { axios } from "axios"; + +import { getEpisode, getUrl } from "../../api"; + + import Layout from "../../components/Layout"; -// import CharacterCard from "../../components/CharacterCard"; +import CharacterCard from "../../components/CharacterCard"; + +function makePromises(urls = []) { + const myArray = urls.map((url) => getUrl(url)); + // onsole.log(myArray); + return myArray; +} class Episode extends Component { constructor(props) { super(props); - this.state = {}; - // episode: null, - // characters: [], - // hasLoaded: false, - // hasError: false, - // errorMessage: null, + this.state = { + episode: null, + characters: [], + hasLoaded: false, + hasError: false, + errorMessage: null, + }; + this.loadEpisode = this.loadEpisode.bind(this); + } + + componentDidMount() { + // console.log(this.props); + + const { match } = this.props; + const { episodeId } = match.params; + // console.log(episodeId); + + /* + * La siguiente funcion se ejecuta al cargarse este mismo componente + * y ademas le asignamos como parametro el episodeId que llevará el mismo numero + * de episodio que hemos clickado. + */ + this.loadEpisode(episodeId); + } + + async loadEpisode(episodeId) { + // console.log(this); + /* + * Aquí lo que hacemos es encapsular dentro de DATA, toda la informacion + * del episodio que nos traemos del API + */ + + try { + const { data } = await getEpisode(episodeId); + /* + * Esta funcion nos llama a otra funcion que dentro nos devuelve un Array mediante un map + * en la siguiente variante, haremos lo mismo pero de forma manual (NO RECOMENDABLE) + */ + // eslint-disable-next-line compat/compat + const characterResponse = await Promise.all( + makePromises(data.characters), + ); + + // const promises = data.characters.map((character) => axios.get(character)); + + /* + * Ademas, axios, siempre nos devuelve las propiedades que necesitamos dentro de un objeto y dentro del objeto en DATA. + * para solucionarlo, debemos recorrer cada objeto, sacando ese DATA y guardandolo + * en un nuevo array con ese contenido. + */ + const characters = characterResponse.map((character) => character.data); + + this.setState({ + hasLoaded: true, + episode: data, + characters: characters, + }); + + // console.log(data); + // console.log(characterResponse); + // console.log(promises); + // console.log(characters); + } catch (error) { + this.setState({ + hasLoaded: true, + hasError: true, + errorMessage: error.message, + }); + } } render() { + const { + episode, + characters, + hasLoaded, + hasError, + errorMessage, + } = this.state; return (
-
- {/* {characters.map((character) => ( - - ))} */} -
+ {!hasLoaded && ( +
+

Episode not loaded...

+
+ )} + {hasError && ( +
+

Something went wrong

+

{errorMessage}

+
+ )} + {/*
+ {episode && JSON.stringify(episode, null, 2)} +
*/} + {/*
*/} +
+ {characters.length > 0 && + characters.map((character) => ( + + )) + } + {/*
*/} +
); diff --git a/src/pages/Home/Home.js b/src/pages/Home/Home.js index f86e93c..687c3da 100644 --- a/src/pages/Home/Home.js +++ b/src/pages/Home/Home.js @@ -1,42 +1,128 @@ import React, { Component } from "react"; +import { getEpisodes } from "../../api"; + import Layout from "../../components/Layout"; -// import EpisodeCard from "../../components/EpisodeCard"; +import EpisodeCard from "../../components/EpisodeCard"; class Home extends Component { constructor(props) { super(props); - this.state = {}; - // page: 1, - // paginationInfo: null, - // episodes: [], - // hasLoaded: false, - // hasError: false, - // errorMessage: null, + this.state = { + page: 1, + paginationInfo: null, + episodes: [], + hasLoaded: false, + hasError: false, + errorMessage: null, + }; + this.loadEpisodes = this.loadEpisodes.bind(this); + this.loadNextPage = this.loadNextPage.bind(this); + } + + /* + * Esta funcion viene predefinida por react y se ejecutará al inicio de la APP por defecto + */ + componentDidMount() { + const { page } = this.state; + this.loadEpisodes(page); + } + + componentDidUpdate(_prevProps, prevState){ + const { page } = this.state; + const { page: prevPage } = prevState; + + // console.log({page}); + // console.log({prevPage}); + // console.log("----"); + + if( prevPage !== page ){ + this.loadEpisodes(page); + } } - async componentDidMount() { - // this.loadEpisodes(); + /* + * funcion inicial para cargar los episodios + */ + async loadEpisodes(page) { + // console.log(this); + try { + // console.log(data); + /* + * la constante data la creamos mediante destructuring, para obtener la funcion creada en Api.js + */ + const { data } = await getEpisodes(page); + /* + * El siguiente State, te recoge desde el API los episodios + * Pero solo te muestra una "version" de los episodios por pagina + */ + // this.setState({ + // paginationInfo: data.info, + // episodes: data.results, + // hasLoaded: true, + // }); + /* + * En cambio el siguiente State, te va copiando los anteriores episodios y no los sustituye, si no que + * Los añade a continuación ya que "copiamos" los capitulos en el prevState + */ + this.setState((prevState)=>({ + paginationInfo: data.info, + episodes: [ ...prevState.episodes, ...data.results ], + hasLoaded: true, + })); + } catch (error) { + this.setState({ + hasLoaded: true, + hasError: true, + errorMessage: error.message, + }); + } } - async loadEpisodes() { - console.log(this); + loadNextPage() { + this.setState((prevState) => ({ + page: prevState.page + 1, + })); + // console.log(this); } render() { + const { + paginationInfo, + episodes, + hasLoaded, + hasError, + errorMessage, + } = this.state; + return (
- {/* {hasLoaded && !hasError && ( + {hasLoaded && !hasError && (

Episodes loaded!

- )} */} + )} + {hasError && ( +
+

Something went wrong!

+

{errorMessage}

+
+ )} + {!hasLoaded && ( +
+

Loading Episodes...

+
+ )}

- {/* {episodes.map((episode) => ( + {/*
+ {JSON.stringify(episodes, null, 2)} +
*/} + {episodes.length > 0 && + episodes.map((episode) => ( - ))} */} + ))}

+
+ +
); diff --git a/src/pages/LocationPage/LocationPage.js b/src/pages/LocationPage/LocationPage.js new file mode 100644 index 0000000..d452194 --- /dev/null +++ b/src/pages/LocationPage/LocationPage.js @@ -0,0 +1,89 @@ +import React, { Component } from "react"; + +import { getLocation } from "../../api"; + +import Layout from "../../components/Layout"; + +function makePromises(urls = []) { + const myArray = urls.map((url) => getLocation(url)); + // console.log(myArray); + return myArray; +} + +class LocationPage extends Component { + constructor(props){ + super(props); + this.state = { + location: "", + name: "", + hasLoaded: false, + hasError: false, + errorMessage: null, + }; + this.loadLocation = this.loadLocation.bind(this); + } + + componentDidMount() { + // console.log(this); + + const { match } = this.props; + const { locationId } = match.params; + + console.log(locationId); + this.loadLocation(locationId); + } + + async loadLocation(locationId) { + // console.log(this); + try{ + + const { data } = await getLocation(locationId); + console.log(data); + + this.setState({ + location: data, + name: data.name, + }); + + } catch (error){ + this.setState({ + hasLoaded: false, + hasError: true, + errorMessage: error.message, + }); + } + } + + render(){ + const {errorMessage, hasError, hasLoaded, location, name} = this.state; + + return ( + + {hasLoaded && ( +
+
+

Loading data...

+
+
+ )} + {hasError && ( +
+
+

Something went wrong...

+

{errorMessage}

+
+
+ )} +
+

LOCATION: {name}

+
+
+
+ {JSON.stringify(location, null, 1)} +
+
+ ) + } +} + +export default LocationPage; \ No newline at end of file diff --git a/src/pages/LocationPage/index.js b/src/pages/LocationPage/index.js new file mode 100644 index 0000000..cb54906 --- /dev/null +++ b/src/pages/LocationPage/index.js @@ -0,0 +1 @@ +export { default } from "./LocationPage"; \ No newline at end of file