matrix-art

An image gallery for Matrix
git clone git://archive.git.mtrnord.blog/MTRNord/matrix-art.git
Log | Files | Refs | README | LICENSE

commit 243a78a30c8f4e62215cc10a6ae889ae3d0334fe
parent a83e161098980cada061d7a2625f4119d7847c33
Author: MTRNord <mtrnord1@gmail.com>
Date:   Wed,  5 Jan 2022 15:46:18 +0100

Improve code quality

Diffstat:
M.eslintrc.json | 7+++++--
Mcomponents/FrontPageImage.tsx | 18+++++++++---------
Mcomponents/Header.tsx | 6+++---
Mpackage-lock.json | 535++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
Mpackage.json | 3++-
Mpages/Home.tsx | 15++++++++-------
Mpages/api/directory.tsx | 21++++++++++++---------
Mpages/login.tsx | 14+++++++-------
Mpages/post/[id].tsx | 36+++++++++++++++++++-----------------
Mpages/profile/[userid].tsx | 22+++++++++++-----------
10 files changed, 594 insertions(+), 83 deletions(-)

diff --git a/.eslintrc.json b/.eslintrc.json @@ -4,10 +4,13 @@ ], "extends": [ "next/core-web-vitals", - "plugin:jsx-a11y/recommended" + "plugin:jsx-a11y/recommended", + "plugin:unicorn/recommended" ], "rules": { "@next/next/no-img-element": "off", - "jsx-a11y/anchor-is-valid": "off" + "jsx-a11y/anchor-is-valid": "off", + "unicorn/prevent-abbreviations": "off", + "unicorn/filename-case": "off" } } \ No newline at end of file diff --git a/components/FrontPageImage.tsx b/components/FrontPageImage.tsx @@ -41,8 +41,8 @@ export default class FrontPageImage extends Component<Props, State> { this.setState({ displayname: profile.displayname, }); - } catch (ex) { - console.debug(`Failed to fetch profile for user ${this.props.event.sender}:`, ex); + } catch (error) { + console.debug(`Failed to fetch profile for user ${this.props.event.sender}:`, error); } } @@ -55,10 +55,10 @@ export default class FrontPageImage extends Component<Props, State> { if (typeof window !== "undefined") { window.location.reload(); } - } catch (err) { - console.error("Failed to register as guest:", err); + } catch (error) { + console.error("Failed to register as guest:", error); this.setState({ - error: "Failed to register as guest: " + JSON.stringify(err), + error: "Failed to register as guest: " + JSON.stringify(error), }); } } @@ -67,7 +67,7 @@ export default class FrontPageImage extends Component<Props, State> { const event = this.props.event; return ( <> - {isImageGalleryEvent(event) ? this.render_gallery(event) : isImageEvent(event) ? this.render_image(event) : <div key={(event as MatrixEventBase).event_id}></div>} + {isImageGalleryEvent(event) ? this.render_gallery(event) : (isImageEvent(event) ? this.render_image(event) : <div key={(event as MatrixEventBase).event_id}></div>)} </> ); } @@ -79,7 +79,7 @@ export default class FrontPageImage extends Component<Props, State> { return possible_html_caption.body !== undefined && possible_html_caption.mimetype === "text/html"; }); let caption_text = ""; - if (caption.length != 0) { + if (caption.length > 0) { caption_text = (caption[0] as { body: string; mimetype: string; }).body; } return event.content['m.image_gallery'].map(image => { @@ -94,7 +94,7 @@ export default class FrontPageImage extends Component<Props, State> { return possible_html_caption.body !== undefined && possible_html_caption.mimetype === "text/html"; }); let caption_text = ""; - if (caption.length != 0) { + if (caption.length > 0) { caption_text = (caption[0] as { body: string; mimetype: string; }).body; } return this.render_image_box(event.content['m.thumbnail'][0].url, event.event_id, event.event_id, caption_text); @@ -108,7 +108,7 @@ export default class FrontPageImage extends Component<Props, State> { <li style={{ height: this.state.imageHeight }} key={id}> <Link href={direct_link} passHref> <div style={{ height: this.state.imageHeight }} className={`relative cursor-pointer`}> - <img alt={caption} title={caption} style={{ height: this.state.imageHeight }} className={`relative max-w-full object-cover align-bottom z-0`} src={this.context.client?.thumbnailLink(thumbnail_url, "scale", parseInt(this.state.imageHeight?.replace("px", "")!), parseInt(this.state.imageHeight?.replace("px", "")!))}></img> + <img alt={caption} title={caption} style={{ height: this.state.imageHeight }} className={`relative max-w-full object-cover align-bottom z-0`} src={this.context.client?.thumbnailLink(thumbnail_url, "scale", Number.parseInt(this.state.imageHeight?.replace("px", "")!), Number.parseInt(this.state.imageHeight?.replace("px", "")!))}></img> <div style={{ height: this.state.imageHeight }} className={`flex-col max-w-full opacity-0 hover:opacity-100 duration-300 absolute bg-gradient-to-b from-transparent to-black/[.25] inset-0 z-10 flex justify-end items-start text-white p-4`}> <h2 className='truncate max-w-full text-base font-semibold'>{caption}</h2> <p className='truncate max-w-full text-sm'>{this.state.displayname}</p> diff --git a/components/Header.tsx b/components/Header.tsx @@ -22,9 +22,9 @@ export default class Header extends Component { </div> <nav className='flex flex-shrink-0 relative mr-0 h-full'> - {this.context.client.isGuest ? <span className='px-4 h-auto min-w-[1.5rem] flex items-center whitespace-nowrap cursor-pointer text-gray-900 dark:text-gray-200 font-medium'><Link href="/register">Join</Link></span> : null} - {this.context.client.isGuest ? <span className='px-4 h-auto min-w-[1.5rem] flex items-center whitespace-nowrap cursor-pointer text-gray-900 dark:text-gray-200 font-medium'><Link href="/login">Log in</Link></span> : null} - {!this.context.client.isGuest ? <span className='px-4 h-auto min-w-[1.5rem] flex items-center whitespace-nowrap cursor-pointer text-gray-900 dark:text-gray-200 font-medium'><Link href={"/profile/" + encodeURIComponent(this.context.client.userId!)}>Profile</Link></span> : null} + {this.context.client.isGuest ? <span className='px-4 h-auto min-w-[1.5rem] flex items-center whitespace-nowrap cursor-pointer text-gray-900 dark:text-gray-200 font-medium'><Link href="/register">Join</Link></span> : undefined} + {this.context.client.isGuest ? <span className='px-4 h-auto min-w-[1.5rem] flex items-center whitespace-nowrap cursor-pointer text-gray-900 dark:text-gray-200 font-medium'><Link href="/login">Log in</Link></span> : undefined} + {!this.context.client.isGuest ? <span className='px-4 h-auto min-w-[1.5rem] flex items-center whitespace-nowrap cursor-pointer text-gray-900 dark:text-gray-200 font-medium'><Link href={"/profile/" + encodeURIComponent(this.context.client.userId!)}>Profile</Link></span> : undefined} </nav> </div> <span className='lg:opacity-100 opacity-0 inline-block bg-gray-900 dark:bg-gray-200 w-[1px] h-7'></span> diff --git a/package-lock.json b/package-lock.json @@ -27,9 +27,10 @@ "@types/react": "17.0.38", "autoprefixer": "^10.4.0", "cross-env": "^7.0.3", - "eslint": "^8.5.0", + "eslint": "^8.6.0", "eslint-config-next": "12.0.7", "eslint-plugin-jsx-a11y": "^6.5.1", + "eslint-plugin-unicorn": "^40.0.0", "postcss": "^8.4.5", "tailwindcss": "^3.0.7", "typescript": "4.5.4" @@ -1977,6 +1978,12 @@ "@types/events": "*" } }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", + "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", + "dev": true + }, "node_modules/@types/parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", @@ -2985,6 +2992,18 @@ "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" }, + "node_modules/builtin-modules": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.2.0.tgz", + "integrity": "sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/builtin-status-codes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", @@ -3070,6 +3089,12 @@ "fsevents": "~2.3.1" } }, + "node_modules/ci-info": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", + "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", + "dev": true + }, "node_modules/cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", @@ -3084,6 +3109,18 @@ "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz", "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==" }, + "node_modules/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, + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/clone-buffer": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", @@ -3706,9 +3743,9 @@ } }, "node_modules/eslint": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.5.0.tgz", - "integrity": "sha512-tVGSkgNbOfiHyVte8bCM8OmX+xG9PzVG/B4UCF60zx7j61WIVY/AqJECDgpLD4DbbESD0e174gOg3ZlrX15GDg==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.6.0.tgz", + "integrity": "sha512-UvxdOJ7mXFlw7iuHZA4jmzPaUqIw54mZrv+XPYKNbKdLR0et4rf60lIZUU9kiNtnzzMzGWxMV+tQ7uG7JG8DPw==", "dev": true, "dependencies": { "@eslint/eslintrc": "^1.0.5", @@ -3723,7 +3760,7 @@ "eslint-scope": "^7.1.0", "eslint-utils": "^3.0.0", "eslint-visitor-keys": "^3.1.0", - "espree": "^9.2.0", + "espree": "^9.3.0", "esquery": "^1.4.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -4105,6 +4142,52 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/eslint-plugin-unicorn": { + "version": "40.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-40.0.0.tgz", + "integrity": "sha512-5GRXISfBk8jMmYk1eeNDw8zSRnWTxBjWkzx2Prre6E2/yLu2twozZ3EomLWCBu9nWms/ZE361BItyMQwfnG1qA==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.15.7", + "ci-info": "^3.3.0", + "clean-regexp": "^1.0.0", + "eslint-utils": "^3.0.0", + "esquery": "^1.4.0", + "indent-string": "^4.0.0", + "is-builtin-module": "^3.1.0", + "lodash": "^4.17.21", + "pluralize": "^8.0.0", + "read-pkg-up": "^7.0.1", + "regexp-tree": "^0.1.24", + "safe-regex": "^2.1.1", + "semver": "^7.3.5", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/eslint-plugin-unicorn?sponsor=1" + }, + "peerDependencies": { + "eslint": ">=7.32.0" + } + }, + "node_modules/eslint-plugin-unicorn/node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/eslint-scope": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.0.tgz", @@ -4314,12 +4397,12 @@ } }, "node_modules/espree": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.2.0.tgz", - "integrity": "sha512-oP3utRkynpZWF/F2x/HZJ+AGtnIclaR7z1pYPxy7NYM2fSO6LgK/Rkny8anRSPK/VwEA1eqm2squui0T7ZMOBg==", + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.0.tgz", + "integrity": "sha512-d/5nCsb0JcqsSEeQzFZ8DH1RmxPcglRWh24EFTlUEmCKoehXGdpsx0RkHDubqUI8LSAIKMQp4r9SzQ3n+sm4HQ==", "dev": true, "dependencies": { - "acorn": "^8.6.0", + "acorn": "^8.7.0", "acorn-jsx": "^5.3.1", "eslint-visitor-keys": "^3.1.0" }, @@ -4915,6 +4998,12 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, + "node_modules/hosted-git-info": { + "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==", + "dev": true + }, "node_modules/http-errors": { "version": "1.7.3", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", @@ -5086,6 +5175,15 @@ "node": ">=0.8.19" } }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -5178,6 +5276,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-builtin-module": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.1.0.tgz", + "integrity": "sha512-OV7JjAgOTfAFJmHZLvpSTb4qi0nIILDV1gWPYDnDJUTNFM5aGlRAhk4QcT8i7TuAleeEV5Fdkqn3t4mS+Q11fg==", + "dev": true, + "dependencies": { + "builtin-modules": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/is-callable": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", @@ -6035,6 +6145,12 @@ "node": ">=8" } }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -6162,6 +6278,15 @@ "node": ">=4.0.0" } }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", @@ -6376,6 +6501,27 @@ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.77.tgz", "integrity": "sha512-rB1DUFUNAN4Gn9keO2K1efO35IDK7yKHCdCaIMvFO7yUYmmZYeDjnGKle26G4rwj+LKRQpjyUUvMkPglwGCYNQ==" }, + "node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/normalize-package-data/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -6843,6 +6989,15 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "node_modules/pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/pngjs": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz", @@ -7274,6 +7429,56 @@ "react-dom": "^16.0.0 || ^17.0.0" } }, + "node_modules/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, + "dependencies": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/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, + "dependencies": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg/node_modules/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, + "engines": { + "node": ">=8" + } + }, "node_modules/readable-stream": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", @@ -7303,6 +7508,15 @@ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.4.tgz", "integrity": "sha512-plpwicqEzfEyTQohIKktWigcLzmNStMGwbOUbykx51/29Z3JOGYldaaNGK7ngNXV+UcoqvIMmloZ48Sr74sd+g==" }, + "node_modules/regexp-tree": { + "version": "0.1.24", + "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.24.tgz", + "integrity": "sha512-s2aEVuLhvnVJW6s/iPgEGK6R+/xngd2jNQ+xy4bXNDKxZKJH6jpPHY6kVeVv1IeLCHgswRj+Kl3ELaDjG6V1iw==", + "dev": true, + "bin": { + "regexp-tree": "bin/regexp-tree" + } + }, "node_modules/regexp.prototype.flags": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz", @@ -7438,6 +7652,15 @@ } ] }, + "node_modules/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, + "dependencies": { + "regexp-tree": "~0.1.1" + } + }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -7647,6 +7870,38 @@ "resolved": "https://registry.npmjs.org/spark-md5/-/spark-md5-3.0.1.tgz", "integrity": "sha512-0tF3AGSD1ppQeuffsLDIOWlKUd3lS92tFxcsrh5Pe3ZphhnoK+oXIBTzOAThZCiuINZLvpiLH/1VS1/ANEJVig==" }, + "node_modules/spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", + "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==", + "dev": true + }, "node_modules/stack-utils": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", @@ -7791,6 +8046,18 @@ "node": ">=4" } }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -8279,6 +8546,16 @@ "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", "dev": true }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -9922,6 +10199,12 @@ "@types/events": "*" } }, + "@types/normalize-package-data": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", + "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", + "dev": true + }, "@types/parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", @@ -10729,6 +11012,12 @@ "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" }, + "builtin-modules": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.2.0.tgz", + "integrity": "sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA==", + "dev": true + }, "builtin-status-codes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", @@ -10790,6 +11079,12 @@ "readdirp": "~3.5.0" } }, + "ci-info": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", + "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", + "dev": true + }, "cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", @@ -10804,6 +11099,15 @@ "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz", "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==" }, + "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" + } + }, "clone-buffer": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", @@ -11316,9 +11620,9 @@ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, "eslint": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.5.0.tgz", - "integrity": "sha512-tVGSkgNbOfiHyVte8bCM8OmX+xG9PzVG/B4UCF60zx7j61WIVY/AqJECDgpLD4DbbESD0e174gOg3ZlrX15GDg==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.6.0.tgz", + "integrity": "sha512-UvxdOJ7mXFlw7iuHZA4jmzPaUqIw54mZrv+XPYKNbKdLR0et4rf60lIZUU9kiNtnzzMzGWxMV+tQ7uG7JG8DPw==", "dev": true, "requires": { "@eslint/eslintrc": "^1.0.5", @@ -11333,7 +11637,7 @@ "eslint-scope": "^7.1.0", "eslint-utils": "^3.0.0", "eslint-visitor-keys": "^3.1.0", - "espree": "^9.2.0", + "espree": "^9.3.0", "esquery": "^1.4.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -11739,6 +12043,39 @@ "dev": true, "requires": {} }, + "eslint-plugin-unicorn": { + "version": "40.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-40.0.0.tgz", + "integrity": "sha512-5GRXISfBk8jMmYk1eeNDw8zSRnWTxBjWkzx2Prre6E2/yLu2twozZ3EomLWCBu9nWms/ZE361BItyMQwfnG1qA==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.15.7", + "ci-info": "^3.3.0", + "clean-regexp": "^1.0.0", + "eslint-utils": "^3.0.0", + "esquery": "^1.4.0", + "indent-string": "^4.0.0", + "is-builtin-module": "^3.1.0", + "lodash": "^4.17.21", + "pluralize": "^8.0.0", + "read-pkg-up": "^7.0.1", + "regexp-tree": "^0.1.24", + "safe-regex": "^2.1.1", + "semver": "^7.3.5", + "strip-indent": "^3.0.0" + }, + "dependencies": { + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, "eslint-scope": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.0.tgz", @@ -11773,12 +12110,12 @@ "dev": true }, "espree": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.2.0.tgz", - "integrity": "sha512-oP3utRkynpZWF/F2x/HZJ+AGtnIclaR7z1pYPxy7NYM2fSO6LgK/Rkny8anRSPK/VwEA1eqm2squui0T7ZMOBg==", + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.0.tgz", + "integrity": "sha512-d/5nCsb0JcqsSEeQzFZ8DH1RmxPcglRWh24EFTlUEmCKoehXGdpsx0RkHDubqUI8LSAIKMQp4r9SzQ3n+sm4HQ==", "dev": true, "requires": { - "acorn": "^8.6.0", + "acorn": "^8.7.0", "acorn-jsx": "^5.3.1", "eslint-visitor-keys": "^3.1.0" }, @@ -12225,6 +12562,12 @@ } } }, + "hosted-git-info": { + "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==", + "dev": true + }, "http-errors": { "version": "1.7.3", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", @@ -12342,6 +12685,12 @@ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -12413,6 +12762,15 @@ "has-tostringtag": "^1.0.0" } }, + "is-builtin-module": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.1.0.tgz", + "integrity": "sha512-OV7JjAgOTfAFJmHZLvpSTb4qi0nIILDV1gWPYDnDJUTNFM5aGlRAhk4QcT8i7TuAleeEV5Fdkqn3t4mS+Q11fg==", + "dev": true, + "requires": { + "builtin-modules": "^3.0.0" + } + }, "is-callable": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", @@ -13029,6 +13387,12 @@ "p-locate": "^4.1.0" } }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, "lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -13131,6 +13495,12 @@ "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", "dev": true }, + "min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true + }, "minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", @@ -13291,6 +13661,26 @@ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.77.tgz", "integrity": "sha512-rB1DUFUNAN4Gn9keO2K1efO35IDK7yKHCdCaIMvFO7yUYmmZYeDjnGKle26G4rwj+LKRQpjyUUvMkPglwGCYNQ==" }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -13633,6 +14023,12 @@ } } }, + "pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "dev": true + }, "pngjs": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz", @@ -13963,6 +14359,45 @@ "@emotion/react": "^11.1.4" } }, + "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" + }, + "dependencies": { + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + } + } + }, "readable-stream": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", @@ -13986,6 +14421,12 @@ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.4.tgz", "integrity": "sha512-plpwicqEzfEyTQohIKktWigcLzmNStMGwbOUbykx51/29Z3JOGYldaaNGK7ngNXV+UcoqvIMmloZ48Sr74sd+g==" }, + "regexp-tree": { + "version": "0.1.24", + "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.24.tgz", + "integrity": "sha512-s2aEVuLhvnVJW6s/iPgEGK6R+/xngd2jNQ+xy4bXNDKxZKJH6jpPHY6kVeVv1IeLCHgswRj+Kl3ELaDjG6V1iw==", + "dev": true + }, "regexp.prototype.flags": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz", @@ -14062,6 +14503,15 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" }, + "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" + } + }, "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -14226,6 +14676,38 @@ "resolved": "https://registry.npmjs.org/spark-md5/-/spark-md5-3.0.1.tgz", "integrity": "sha512-0tF3AGSD1ppQeuffsLDIOWlKUd3lS92tFxcsrh5Pe3ZphhnoK+oXIBTzOAThZCiuINZLvpiLH/1VS1/ANEJVig==" }, + "spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", + "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==", + "dev": true + }, "stack-utils": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", @@ -14345,6 +14827,15 @@ "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", "dev": true }, + "strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "requires": { + "min-indent": "^1.0.0" + } + }, "strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -14715,6 +15206,16 @@ "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", "dev": true }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", diff --git a/package.json b/package.json @@ -32,9 +32,10 @@ "@types/react": "17.0.38", "autoprefixer": "^10.4.0", "cross-env": "^7.0.3", - "eslint": "^8.5.0", + "eslint": "^8.6.0", "eslint-config-next": "12.0.7", "eslint-plugin-jsx-a11y": "^6.5.1", + "eslint-plugin-unicorn": "^40.0.0", "postcss": "^8.4.5", "tailwindcss": "^3.0.7", "typescript": "4.5.4" diff --git a/pages/Home.tsx b/pages/Home.tsx @@ -53,7 +53,8 @@ export default class Home extends Component<Props, State>{ } else { console.log("Already logged in"); try { - const data = await (await fetch('/api/directory')).json(); + const resp = await fetch('/api/directory'); + const data = await resp.json(); this.setState({ directory_data: data.data, directoryIsLoaded: true }); } catch (error) { this.setState({ @@ -72,10 +73,10 @@ export default class Home extends Component<Props, State>{ if (typeof window !== "undefined") { window.location.reload(); } - } catch (err) { - console.error("Failed to register as guest:", err); + } catch (error) { + console.error("Failed to register as guest:", error); this.setState({ - error: "Failed to register as guest: " + JSON.stringify(err), + error: "Failed to register as guest: " + JSON.stringify(error), }); } } @@ -96,15 +97,15 @@ export default class Home extends Component<Props, State>{ await client?.getTimeline(roomId, 100, (events) => { // Filter events by type const image_events = events.filter((event) => event.type == "m.image_gallery" || event.type == "m.image") as MatrixImageEvents[]; - console.log("Adding ", image_events.length, " items"); + console.log("Adding", image_events.length, "items"); this.setState({ image_events: image_events, }); }); } - } catch (err) { + } catch (error) { this.setState({ - error: JSON.stringify(err), + error: JSON.stringify(error), }); } finally { this.setState({ diff --git a/pages/api/directory.tsx b/pages/api/directory.tsx @@ -2,7 +2,7 @@ import Cors from 'cors'; import initMiddleware from '../../helpers/init-middleware'; import type { NextApiRequest, NextApiResponse } from 'next'; import PouchDB from 'pouchdb'; -import path from 'path'; +import path from 'node:path'; const db = new PouchDB(path.join(process.cwd(), "matrix-art-db")); @@ -26,8 +26,11 @@ export const get_data = async () => { } ]; } - const db_data: { _id: string; user_id: string; user_room: string; _rev?: string; }[] = (await db.allDocs({ include_docs: true })).rows.map(x => x.doc) as unknown as { _id: string; user_id: string; user_room: string; _rev?: string; }[]; - db_data.forEach(x => delete x?._rev); + const db_resp = await db.allDocs({ include_docs: true }); + const db_data: { _id: string; user_id: string; user_room: string; _rev?: string; }[] = db_resp.rows.map(x => x.doc) as unknown as { _id: string; user_id: string; user_room: string; _rev?: string; }[]; + for (const entry of db_data) { + delete entry._rev; + } return db_data; }; @@ -41,9 +44,9 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) try { const db_data = await get_data(); res.status(200).json({ data: db_data }); - } catch (err) { + } catch (error) { res.status(502).json({}); - console.error(err); + console.error(error); } } else if (req.method == "POST") { const data: { @@ -58,9 +61,9 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) try { await db.put(db_data); res.status(200).json({}); - } catch (err) { + } catch (error) { res.status(502).json({}); - console.error(err); + console.error(error); } } else if (req.method == "DELETE") { @@ -72,9 +75,9 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) const db_data = await db.get(data.user_id); await db.remove(db_data); res.status(200).json({}); - } catch (err) { + } catch (error) { res.status(502).json({}); - console.error(err); + console.error(error); } } else { diff --git a/pages/login.tsx b/pages/login.tsx @@ -79,7 +79,7 @@ class Login extends Component<Props, State> { } render(): ReactNode { - const { loading } = this.state; + const { loading, showServerField, serverFieldsOpacity, serverFieldsDisplay, serverUrl, mxid, password } = this.state; if (loading) { return ( <> @@ -126,7 +126,7 @@ class Login extends Component<Props, State> { <div className="mt-2"> <div> <label className="inline-flex items-center"> - <input className="cursor-pointer h-4 w-4" type="checkbox" name="showServerField" checked={this.state.showServerField} onChange={this.handleInputChange} /> + <input className="cursor-pointer h-4 w-4" type="checkbox" name="showServerField" checked={showServerField} onChange={this.handleInputChange} /> <span className="ml-2 text-gray-900 dark:text-gray-200">Use custom Server</span> </label> </div> @@ -135,25 +135,25 @@ class Login extends Component<Props, State> { <label style={{ transition: 'opacity 0.4s ease', - opacity: this.state.serverFieldsOpacity, - display: this.state.serverFieldsDisplay + opacity: serverFieldsOpacity, + display: serverFieldsDisplay }} id="homeserverField"> <span className="text-gray-900 dark:text-gray-200">Homeserver:</span> <div className="mt-1 w-full flex flex-row box-border items-center cursor-text duration-300 rounded-sm border dark:border-slate-400 border-slate-500 py-1.5 px-2 focus-within:border-teal-400"> - <input className="bg-transparent min-w-[1.25rem] focus:outline-none flex-[1] border-none text-gray-900 dark:text-gray-200" type="text" name="serverUrl" value={this.state.serverUrl} onChange={this.handleInputChange} /> + <input className="bg-transparent min-w-[1.25rem] focus:outline-none flex-[1] border-none text-gray-900 dark:text-gray-200" type="text" name="serverUrl" value={serverUrl} onChange={this.handleInputChange} /> </div> </label> <label className="block"> <span className="text-gray-900 dark:text-gray-200">Username:</span> <div className="mt-1 w-full flex flex-row box-border items-center cursor-text duration-300 rounded-sm border dark:border-slate-400 border-slate-500 py-1.5 px-2 focus-within:border-teal-400"> - <input className="bg-transparent min-w-[1.25rem] focus:outline-none flex-[1] border-none text-gray-900 dark:text-gray-200" type="text" name="mxid" value={this.state.mxid} onChange={this.handleInputChange} /> + <input className="bg-transparent min-w-[1.25rem] focus:outline-none flex-[1] border-none text-gray-900 dark:text-gray-200" type="text" name="mxid" value={mxid} onChange={this.handleInputChange} /> </div> </label> <label className="block"> <span className="text-gray-900 dark:text-gray-200">Password:</span> <div className="mt-1 w-full flex flex-row box-border items-center cursor-text duration-300 rounded-sm border dark:border-slate-400 border-slate-500 py-1.5 px-2 focus-within:border-teal-400"> - <input className="bg-transparent min-w-[1.25rem] focus:outline-none flex-[1] border-none text-gray-900 dark:text-gray-200" type="password" name="password" value={this.state.password} onChange={this.handleInputChange} /> + <input className="bg-transparent min-w-[1.25rem] focus:outline-none flex-[1] border-none text-gray-900 dark:text-gray-200" type="password" name="password" value={password} onChange={this.handleInputChange} /> </div> </label> diff --git a/pages/post/[id].tsx b/pages/post/[id].tsx @@ -55,8 +55,8 @@ class Post extends Component<Props, State> { let serverUrl = constMatrixArtServer + "/_matrix/client"; await this.context.client?.registerAsGuest(serverUrl); await this.context.guest_client?.registerAsGuest(serverUrl); - } catch (err) { - console.error("Failed to register as guest:", err); + } catch (error) { + console.error("Failed to register as guest:", error); } } else { console.log("Already logged in"); @@ -81,25 +81,27 @@ class Post extends Component<Props, State> { const roomId = await this.context.client?.followUser(user.user_room); await this.context.client?.getTimeline(roomId, 100, async (events) => { // Filter events by type - const image_event = events.filter((event) => (event.type === "m.image_gallery" || event.type === "m.image") && event.event_id === event_id); + const image_event = events.find((event) => (event.type === "m.image_gallery" || event.type === "m.image") && event.event_id === event_id); try { - const profile = await this.context.client.getProfile(image_event[0].sender); + // TODO this should get handled if null + const profile = await this.context.client.getProfile(image_event!.sender); this.setState({ - image_event: image_event[0] as MatrixImageEvents, + image_event: image_event as MatrixImageEvents, displayname: profile.displayname, }); - } catch (ex) { - console.debug(`Failed to fetch profile for user ${image_event[0].sender}:`, ex); + + } catch (error) { + console.debug(`Failed to fetch profile for user ${image_event?.sender}:`, error); this.setState({ - image_event: image_event[0] as MatrixImageEvents, - displayname: image_event[0].sender, + image_event: image_event as MatrixImageEvents, + displayname: image_event?.sender, }); } }); } - } catch (err) { + } catch (error) { this.setState({ - error: JSON.stringify(err), + error: JSON.stringify(error), }); } finally { this.setState({ @@ -110,7 +112,7 @@ class Post extends Component<Props, State> { } render() { - const { error, hasFullyLoaded, image_event } = this.state; + const { error, hasFullyLoaded, image_event, displayname } = this.state; if (!hasFullyLoaded) { return ( @@ -147,7 +149,7 @@ class Post extends Component<Props, State> { const possible_html_caption = (cap as { body: string; mimetype: string; }); return possible_html_caption.body !== undefined && possible_html_caption.mimetype === "text/html"; }); - if (caption.length != 0) { + if (caption.length > 0) { post_title = (caption[0] as { body: string; mimetype: string; }).body; } return ( @@ -162,12 +164,12 @@ class Post extends Component<Props, State> { <Header></Header> <main className='flex-col h-full flex lg:pt-20 pt-56 z-0'> - {isImageGalleryEvent(image_event) ? this.renderImageGalleryEvent(image_event, post_title) : isImageEvent(image_event) ? this.renderSingleImageEvent(image_event, post_title) : <div key={(image_event as MatrixEventBase).event_id}></div>} + {isImageGalleryEvent(image_event) ? this.renderImageGalleryEvent(image_event, post_title) : (isImageEvent(image_event) ? this.renderSingleImageEvent(image_event, post_title) : <div key={(image_event as MatrixEventBase).event_id}></div>)} <div className="grow bg-[#f8f8f8] dark:bg-[#06070D] min-h-[25rem] flex flex-col items-center"> <div className="flex flex-col items-start lg:min-w-[60rem] lg:w-[60rem]"> <h1 className="my-4 text-6xl text-gray-900 dark:text-gray-200 font-bold">{post_title}</h1> - <h3 className="cursor-pointer mt-0 mb-4 text-l text-gray-900 dark:text-gray-200 font-normal"><Link href={"/profile/" + encodeURIComponent(image_event.sender)}>{this.state.displayname}</Link></h3> - {isImageGalleryEvent(image_event) ? this.renderImageGalleryTags(image_event) : isImageEvent(image_event) ? this.renderSingleImageTags(image_event) : <div key={(image_event as MatrixEventBase).event_id + "tags"}></div>} + <h3 className="cursor-pointer mt-0 mb-4 text-l text-gray-900 dark:text-gray-200 font-normal"><Link href={"/profile/" + encodeURIComponent(image_event.sender)}>{displayname}</Link></h3> + {isImageGalleryEvent(image_event) ? this.renderImageGalleryTags(image_event) : (isImageEvent(image_event) ? this.renderSingleImageTags(image_event) : <div key={(image_event as MatrixEventBase).event_id + "tags"}></div>)} </div> </div> </main> @@ -313,7 +315,7 @@ export const getServerSideProps: GetServerSideProps = async (context) => { directory_data: data, event_id: event_id } }; - } catch (error) { + } catch { return { notFound: true, props: {} }; } } diff --git a/pages/profile/[userid].tsx b/pages/profile/[userid].tsx @@ -50,8 +50,8 @@ class Profile extends Component<Props, State> { displayname: profile.displayname, avatar_url: profile.avatar_url, }); - } catch (ex) { - console.debug(`Failed to fetch profile for user ${this.props.mxid}:`, ex); + } catch (error) { + console.debug(`Failed to fetch profile for user ${this.props.mxid}:`, error); } await this.loadEvents(); } @@ -65,10 +65,10 @@ class Profile extends Component<Props, State> { if (typeof window !== "undefined") { window.location.reload(); } - } catch (err) { - console.error("Failed to register as guest:", err); + } catch (error) { + console.error("Failed to register as guest:", error); this.setState({ - error: "Failed to register as guest: " + JSON.stringify(err), + error: "Failed to register as guest: " + JSON.stringify(error), }); } } @@ -86,14 +86,14 @@ class Profile extends Component<Props, State> { const roomId = await client?.followUser("#" + this.props.mxid); await client?.getTimeline(roomId, 100, (events) => { const filtered_events = events.filter(event => event.type !== "m.room.member" && event.type !== "m.room.topic" && event.type !== "m.room.name" && event.type !== "m.room.power_levels"); - console.log("Adding ", filtered_events.length, " items"); + console.log("Adding", filtered_events.length, "items"); this.setState({ events: filtered_events, }); }); - } catch (err) { + } catch (error) { this.setState({ - error: JSON.stringify(err), + error: JSON.stringify(error), }); } finally { this.setState({ @@ -126,7 +126,7 @@ class Profile extends Component<Props, State> { return this.renderNotFound(); } - const banner_event = this.state.events.filter(event => event.type === "matrixart.profile_banner")[0]; + const banner_event = this.state.events.find(event => event.type === "matrixart.profile_banner"); const avatar_url = this.state.avatar_url; const image_events = this.state.events.filter((event) => event.type == "m.image_gallery" || event.type == "m.image") as MatrixImageEvents[]; // TODO opengraph shows mxid instead of displayname @@ -145,7 +145,7 @@ class Profile extends Component<Props, State> { backgroundImage: `url(${this.context.client.downloadLink((banner_event as BannerEvent).content["m.file"].url)})` }} className="fixed top-14 w-full h-[32.5rem] bg-cover bg-[position:50%]" - ></div> : null} + ></div> : undefined} <div className="relative"> <div className="relative mb-0 min-h-[43.75rem]"> <div id="transparent_gradient" className="absolute left-0 right-0 top-[39rem] bottom-0 bg-[#f8f8f8] dark:bg-[#06070D]"></div> @@ -268,7 +268,7 @@ export const getServerSideProps: GetServerSideProps = async (context) => { mxid: mxid } }; - } catch (error) { + } catch { return { notFound: true, props: {} }; } }