diff --git a/Dockerfile b/Dockerfile index bccdbb2..e357410 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,12 @@ FROM node:14-alpine + WORKDIR /app + COPY . . + RUN yarn --production --pure-lockfile +RUN yarn run build:static + EXPOSE 3000 + CMD yarn start \ No newline at end of file diff --git a/package.json b/package.json index 7158bb1..3d136cb 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "dotenv": "^8.2.0", "express": "^4.17.1", "express-validator": "^6.13.0", + "fork-awesome": "^1.2.0", "got": "^11.8.2", "jstransformer-markdown-it": "^2.1.0", "libravatar": "^3.0.0", @@ -21,12 +22,21 @@ "string-replace-middleware": "^1.0.2" }, "devDependencies": { + "css-loader": "^6.6.0", "license-check-and-add": "^4.0.3", - "nodemon": "^2.0.7" + "mini-css-extract-plugin": "^2.5.3", + "nodemon": "^2.0.7", + "style-loader": "^3.3.1", + "webpack": "^5.69.1", + "webpack-bundle-analyzer": "^4.5.0", + "webpack-cli": "^4.9.2" }, "scripts": { "start": "node ./", - "dev": "NODE_ENV=development ./node_modules/.bin/nodemon --config nodemon.json ./", + "dev": "yarn run watch & yarn run build:static:dev", + "watch": "./node_modules/.bin/nodemon --config nodemon.json ./", + "build:static": "webpack --config webpack.config.js --env static=true --env mode=production", + "build:static:dev": "webpack --config webpack.config.js --env static=true --env mode=development", "license:check": "./node_modules/.bin/license-check-and-add check", "license:add": "./node_modules/.bin/license-check-and-add add", "license:remove": "./node_modules/.bin/license-check-and-add remove" diff --git a/routes/static.js b/routes/static.js index 23eb1df..2a7782f 100644 --- a/routes/static.js +++ b/routes/static.js @@ -30,34 +30,6 @@ more information on this, and how to apply and follow the GNU AGPL, see . + +Also add information on how to contact you by electronic and paper mail. + +If your software can interact with users remotely through a computer network, +you should also make sure that it provides a way for users to get its source. +For example, if your program is a web application, its interface could display +a "Source" link that leads users to an archive of the code. There are many +ways you could offer source, and different solutions will be better for different +programs; see section 13 for the specific requirements. + +You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. For +more information on this, and how to apply and follow the GNU AGPL, see . +*/ +// Import JS libraries +import * as kx from'./keyoxide' +import * as kxKey from'./kx-key' +import * as kxClaim from'./kx-claim' +import * as ui from'./ui' +import * as utils from'./utils' + +// Import CSS files +import './styles.css' +import './kx-styles.css' + +// Add functions to window +window.showQR = utils.showQR + +// Register custom elements +customElements.define('kx-key', kxKey.Key) +customElements.define('kx-claim', kxClaim.Claim) + +// Run scripts +ui.init() +kx.init() \ No newline at end of file diff --git a/static-src/keyoxide.js b/static-src/keyoxide.js new file mode 100644 index 0000000..62c3c3f --- /dev/null +++ b/static-src/keyoxide.js @@ -0,0 +1,39 @@ +/* +Copyright (C) 2021 Yarmo Mackenbach + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU Affero General Public License as published by the Free +Software Foundation, either version 3 of the License, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more +details. + +You should have received a copy of the GNU Affero General Public License along +with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + +If your software can interact with users remotely through a computer network, +you should also make sure that it provides a way for users to get its source. +For example, if your program is a web application, its interface could display +a "Source" link that leads users to an archive of the code. There are many +ways you could offer source, and different solutions will be better for different +programs; see section 13 for the specific requirements. + +You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. For +more information on this, and how to apply and follow the GNU AGPL, see . +*/ +export function init() { + // Verify all claims + const claims = document.querySelectorAll('kx-claim'); + claims.forEach(function(claim) { + if (claim.hasAttribute('data-skip') && claim.getAttribute('data-skip')) { + return; + } + claim.verify(); + }); +} \ No newline at end of file diff --git a/static-src/kx-claim.js b/static-src/kx-claim.js new file mode 100644 index 0000000..6549e18 --- /dev/null +++ b/static-src/kx-claim.js @@ -0,0 +1,220 @@ +/* +Copyright (C) 2021 Yarmo Mackenbach + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU Affero General Public License as published by the Free +Software Foundation, either version 3 of the License, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more +details. + +You should have received a copy of the GNU Affero General Public License along +with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + +If your software can interact with users remotely through a computer network, +you should also make sure that it provides a way for users to get its source. +For example, if your program is a web application, its interface could display +a "Source" link that leads users to an archive of the code. There are many +ways you could offer source, and different solutions will be better for different +programs; see section 13 for the specific requirements. + +You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. For +more information on this, and how to apply and follow the GNU AGPL, see . +*/ +import * as doip from "doipjs" + +export class Claim extends HTMLElement { + // Specify the attributes to observe + static get observedAttributes() { + return ['data-claim']; + } + + constructor() { + // Call super + super(); + } + + attributeChangedCallback(name, oldValue, newValue) { + this.updateContent(newValue); + } + + async verify() { + const claim = new doip.Claim(JSON.parse(this.getAttribute('data-claim'))); + await claim.verify({ + proxy: { + policy: 'adaptive', + hostname: 'PLACEHOLDER__PROXY_HOSTNAME' + } + }); + this.setAttribute('data-claim', JSON.stringify(claim)); + } + + updateContent(value) { + const root = this; + const claim = new doip.Claim(JSON.parse(value)); + + switch (claim.matches[0].serviceprovider.name) { + case 'dns': + case 'xmpp': + case 'irc': + root.querySelector('.info .subtitle').innerText = claim.matches[0].serviceprovider.name.toUpperCase(); + break; + + default: + root.querySelector('.info .subtitle').innerText = claim.matches[0].serviceprovider.name; + break; + } + root.querySelector('.info .title').innerText = claim.matches[0].profile.display; + + try { + if (claim.status === 'verified') { + root.querySelector('.icons .verificationStatus').setAttribute('data-value', claim.verification.result ? 'success' : 'failed'); + } else { + root.querySelector('.icons .verificationStatus').setAttribute('data-value', 'running'); + } + } catch (error) { + root.querySelector('.icons .verificationStatus').setAttribute('data-value', 'failed'); + } + + const elContent = root.querySelector('.content'); + elContent.innerHTML = ``; + + // Handle failed ambiguous claim + if (claim.status === 'verified' && !claim.verification.result && claim.isAmbiguous()) { + root.querySelector('.info .subtitle').innerText = '---'; + + const subsection_alert = elContent.appendChild(document.createElement('div')); + subsection_alert.setAttribute('class', 'subsection'); + const subsection_alert_icon = subsection_alert.appendChild(document.createElement('img')); + subsection_alert_icon.setAttribute('src', '/static/img/alert-decagram.png'); + subsection_alert_icon.setAttribute('alt', ''); + subsection_alert_icon.setAttribute('aria-hidden', 'true'); + const subsection_alert_text = subsection_alert.appendChild(document.createElement('div')); + + const message = subsection_alert_text.appendChild(document.createElement('p')); + message.innerHTML = `None of the matched service providers could be verified. Keyoxide was not able to determine which was the correct service provider or why the verification process failed.`; + return; + } + + // Links to profile and proof + const subsection_links = elContent.appendChild(document.createElement('div')); + subsection_links.setAttribute('class', 'subsection'); + const subsection_links_icon = subsection_links.appendChild(document.createElement('img')); + subsection_links_icon.setAttribute('src', '/static/img/link.png'); + subsection_links_icon.setAttribute('alt', ''); + subsection_links_icon.setAttribute('aria-hidden', 'true'); + const subsection_links_text = subsection_links.appendChild(document.createElement('div')); + + const profile_link = subsection_links_text.appendChild(document.createElement('p')); + if (claim.matches[0].profile.uri) { + profile_link.innerHTML = `Profile link: ${claim.matches[0].profile.uri}`; + } else { + profile_link.innerHTML = `Profile link: not accessible from browser`; + } + + const proof_link = subsection_links_text.appendChild(document.createElement('p')); + if (claim.matches[0].proof.uri) { + proof_link.innerHTML = `Proof link: ${claim.matches[0].proof.uri}`; + } else { + proof_link.innerHTML = `Proof link: not accessible from browser`; + } + + // QR Code + if (claim.matches[0].profile.qr) { + elContent.appendChild(document.createElement('hr')); + + const subsection_qr = elContent.appendChild(document.createElement('div')); + subsection_qr.setAttribute('class', 'subsection'); + const subsection_qr_icon = subsection_qr.appendChild(document.createElement('img')); + subsection_qr_icon.setAttribute('src', '/static/img/qrcode.png'); + subsection_qr_icon.setAttribute('alt', ''); + subsection_qr_icon.setAttribute('aria-hidden', 'true'); + const subsection_qr_text = subsection_qr.appendChild(document.createElement('div')); + + const button_profileQR = subsection_qr_text.appendChild(document.createElement('button')); + button_profileQR.innerText = `Show profile QR`; + button_profileQR.setAttribute('onClick', `window.showQR('${claim.matches[0].profile.qr}', 'url')`); + button_profileQR.setAttribute('aria-label', `Show QR code linking to profile`); + } + + elContent.appendChild(document.createElement('hr')); + + // Claim verification status + const subsection_status = elContent.appendChild(document.createElement('div')); + subsection_status.setAttribute('class', 'subsection'); + const subsection_status_icon = subsection_status.appendChild(document.createElement('img')); + subsection_status_icon.setAttribute('src', '/static/img/decagram.png'); + subsection_status_icon.setAttribute('alt', ''); + subsection_status_icon.setAttribute('aria-hidden', 'true'); + const subsection_status_text = subsection_status.appendChild(document.createElement('div')); + + const verification = subsection_status_text.appendChild(document.createElement('p')); + if (claim.status === 'verified') { + verification.innerHTML = `Claim verification has completed.`; + subsection_status_icon.setAttribute('src', '/static/img/check-decagram.png'); + subsection_status_icon.setAttribute('alt', ''); + subsection_status_icon.setAttribute('aria-hidden', 'true'); + } else { + verification.innerHTML = `Claim verification is in progress…`; + return; + } + + elContent.appendChild(document.createElement('hr')); + + // Result of claim verification + const subsection_result = elContent.appendChild(document.createElement('div')); + subsection_result.setAttribute('class', 'subsection'); + const subsection_result_icon = subsection_result.appendChild(document.createElement('img')); + subsection_result_icon.setAttribute('src', '/static/img/shield-search.png'); + subsection_result_icon.setAttribute('alt', ''); + subsection_result_icon.setAttribute('aria-hidden', 'true'); + const subsection_result_text = subsection_result.appendChild(document.createElement('div')); + + const result = subsection_result_text.appendChild(document.createElement('p')); + result.innerHTML = `The claim ${claim.verification.result ? 'HAS BEEN' : 'COULD NOT BE'} verified by the proof.`; + + // Additional info + if (claim.verification.proof.viaProxy) { + elContent.appendChild(document.createElement('hr')); + + const subsection_info = elContent.appendChild(document.createElement('div')); + subsection_info.setAttribute('class', 'subsection'); + const subsection_info_icon = subsection_info.appendChild(document.createElement('img')); + subsection_info_icon.setAttribute('src', '/static/img/information.png'); + subsection_info_icon.setAttribute('alt', ''); + subsection_info_icon.setAttribute('aria-hidden', 'true'); + const subsection_info_text = subsection_info.appendChild(document.createElement('div')); + + const result_proxyUsed = subsection_info_text.appendChild(document.createElement('p')); + result_proxyUsed.innerHTML = `A proxy was used to fetch the proof: PLACEHOLDER__PROXY_HOSTNAME`; + } + + // TODO Display errors + // if (claim.verification.errors.length > 0) { + // console.log(claim.verification); + // elContent.appendChild(document.createElement('hr')); + + // const subsection_errors = elContent.appendChild(document.createElement('div')); + // subsection_errors.setAttribute('class', 'subsection'); + // const subsection_errors_icon = subsection_errors.appendChild(document.createElement('img')); + // subsection_errors_icon.setAttribute('src', '/static/img/alert-circle.png'); + // const subsection_errors_text = subsection_errors.appendChild(document.createElement('div')); + + // claim.verification.errors.forEach(message => { + // const error = subsection_errors_text.appendChild(document.createElement('p')); + + // if (message instanceof Error) { + // error.innerText = message.message; + // } else { + // error.innerText = message; + // } + // }); + // } + } +} \ No newline at end of file diff --git a/static-src/kx-key.js b/static-src/kx-key.js new file mode 100644 index 0000000..9774b50 --- /dev/null +++ b/static-src/kx-key.js @@ -0,0 +1,83 @@ +/* +Copyright (C) 2021 Yarmo Mackenbach + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU Affero General Public License as published by the Free +Software Foundation, either version 3 of the License, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more +details. + +You should have received a copy of the GNU Affero General Public License along +with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + +If your software can interact with users remotely through a computer network, +you should also make sure that it provides a way for users to get its source. +For example, if your program is a web application, its interface could display +a "Source" link that leads users to an archive of the code. There are many +ways you could offer source, and different solutions will be better for different +programs; see section 13 for the specific requirements. + +You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. For +more information on this, and how to apply and follow the GNU AGPL, see . +*/ +export class Key extends HTMLElement { + // Specify the attributes to observe + static get observedAttributes() { + return ['data-keydata']; + } + + constructor() { + // Call super + super(); + } + + attributeChangedCallback(name, oldValue, newValue) { + this.updateContent(newValue); + } + + updateContent(value) { + const root = this; + const data = JSON.parse(value); + + root.querySelector('.info .subtitle').innerText = data.key.fetchMethod; + root.querySelector('.info .title').innerText = data.fingerprint; + + const elContent = root.querySelector('.content'); + elContent.innerHTML = ``; + + // Link to key + const subsection_links = elContent.appendChild(document.createElement('div')); + subsection_links.setAttribute('class', 'subsection'); + const subsection_links_icon = subsection_links.appendChild(document.createElement('img')); + subsection_links_icon.setAttribute('src', '/static/img/link.png'); + subsection_links_icon.setAttribute('alt', ''); + subsection_links_icon.setAttribute('aria-hidden', 'true'); + const subsection_links_text = subsection_links.appendChild(document.createElement('div')); + + const profile_link = subsection_links_text.appendChild(document.createElement('p')); + profile_link.innerHTML = `Key link: ${data.key.uri}`; + + elContent.appendChild(document.createElement('hr')); + + // QR Code + const subsection_qr = elContent.appendChild(document.createElement('div')); + subsection_qr.setAttribute('class', 'subsection'); + const subsection_qr_icon = subsection_qr.appendChild(document.createElement('img')); + subsection_qr_icon.setAttribute('src', '/static/img/qrcode.png'); + subsection_qr_icon.setAttribute('alt', ''); + subsection_qr_icon.setAttribute('aria-hidden', 'true'); + const subsection_qr_text = subsection_qr.appendChild(document.createElement('div')); + + const button_fingerprintQR = subsection_qr_text.appendChild(document.createElement('button')); + button_fingerprintQR.innerText = `Show OpenPGP fingerprint QR`; + button_fingerprintQR.setAttribute('onClick', `window.showQR('${data.fingerprint}', 'fingerprint')`); + button_fingerprintQR.setAttribute('aria-label', `Show QR code for cryptographic fingerprint`); + } +} \ No newline at end of file diff --git a/static-src/kx-styles.css b/static-src/kx-styles.css new file mode 100644 index 0000000..0210c52 --- /dev/null +++ b/static-src/kx-styles.css @@ -0,0 +1,254 @@ +/* +Copyright (C) 2021 Yarmo Mackenbach + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU Affero General Public License as published by the Free +Software Foundation, either version 3 of the License, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more +details. + +You should have received a copy of the GNU Affero General Public License along +with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + +If your software can interact with users remotely through a computer network, +you should also make sure that it provides a way for users to get its source. +For example, if your program is a web application, its interface could display +a "Source" link that leads users to an archive of the code. There are many +ways you could offer source, and different solutions will be better for different +programs; see section 13 for the specific requirements. + +You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. For +more information on this, and how to apply and follow the GNU AGPL, see . +*/ +* { + box-sizing: border-box; +} +details.kx-item { + width: 100%; + border-radius: 8px; +} +details.kx-item p { + margin: 0; + word-break: break-word; +} +details.kx-item a { + color: var(--blue-700); +} +details.kx-item hr { + border: none; + border-top: 2px solid var(--purple-100); +} +details.kx-item .content { + padding: 12px; + border: solid 3px var(--purple-100); + border-top: 0px; + border-radius: 0px 0px 8px 8px; +} +details.kx-item summary { + display: flex; + align-items: center; + padding: 8px 12px; + background-color: var(--purple-100); + border: solid 3px var(--purple-100); + border-radius: 8px; + list-style: none; + cursor: pointer; +} +details.kx-item summary::-webkit-details-marker { + display: none; +} +details.kx-item summary:hover, summary:focus { + border-color: var(--purple-400); +} +details[open] summary { + border-radius: 8px 8px 0px 0px; +} +details.kx-item summary .info { + flex: 1; +} +details.kx-item summary .info .title { + font-size: 1.1em; +} +details.kx-item summary .claim__description p { + font-size: 1.4rem; + line-height: 2rem; +} +details.kx-item summary .claim__links p, p.subtle-links { + display: flex; + align-items: center; + flex-wrap: wrap; + font-size: 1rem; + color: var(--grey-700); +} +details.kx-item summary .claim__links a, summary .claim__links span, p.subtle-links a { + font-size: 1rem; + margin: 0 10px 0 0; + color: var(--grey-700); +} +details.kx-item summary .subtitle { + color: var(--purple-700); +} +details.kx-item summary .verificationStatus { + position: relative; + display: flex; + align-items: center; + justify-content: center; + width: 48px; + height: 48px; + border-radius: 100%; + color: #fff; + font-size: 2rem; + user-select: none; +} +details.kx-item summary .verificationStatus::after { + position: absolute; + display: flex; + top: 0; + left: 0; + right: 0; + bottom: 0; + align-items: center; + justify-content: center; +} +details.kx-item summary .verificationStatus .inProgress { + opacity: 0; + transition: opacity 0.4s ease; + pointer-events: none; +} +details.kx-item summary .verificationStatus[data-value="success"] { + content: "v"; + background-color: var(--green-600); +} +details.kx-item summary .verificationStatus[data-value="success"]::after { + content: "✔"; +} +details.kx-item summary .verificationStatus[data-value="failed"] { + background-color: var(--red-400); +} +details.kx-item summary .verificationStatus[data-value="failed"]::after { + content: "✕"; +} +details.kx-item summary .verificationStatus[data-value="running"] .inProgress { + opacity: 1; +} + +details.kx-item .subsection { + display: flex; + align-items: center; + gap: 16px; +} +details.kx-item .subsection > img { + width: 24px; + height: 24px; + opacity: 0.4; +} + +details.kx-item .inProgress { + font-size: 10px; + margin: 50px auto; + text-indent: -9999em; + width: 48px; + height: 48px; + border-radius: 50%; + background: var(--purple-400); + background: -moz-linear-gradient(left, var(--purple-400) 10%, rgba(255, 255, 255, 0) 42%); + background: -webkit-linear-gradient(left, var(--purple-400) 10%, rgba(255, 255, 255, 0) 42%); + background: -o-linear-gradient(left, var(--purple-400) 10%, rgba(255, 255, 255, 0) 42%); + background: -ms-linear-gradient(left, var(--purple-400) 10%, rgba(255, 255, 255, 0) 42%); + background: linear-gradient(to right, var(--purple-400) 10%, rgba(255, 255, 255, 0) 42%); + position: relative; + -webkit-animation: load3 1.4s infinite linear; + animation: load3 1.4s infinite linear; + -webkit-transform: translateZ(0); + -ms-transform: translateZ(0); + transform: translateZ(0); +} +details.kx-item .inProgress:before { + width: 50%; + height: 50%; + background: var(--purple-400); + border-radius: 100% 0 0 0; + position: absolute; + top: 0; + left: 0; + content: ''; +} +details.kx-item .inProgress:after { + background: var(--purple-100); + width: 65%; + height: 65%; + border-radius: 50%; + content: ''; + margin: auto; + position: absolute; + top: 0; + left: 0; + bottom: 0; + right: 0; +} +details.kx-item button { + padding: 0.4rem 0.8rem; + margin-right: 8px; + text-decoration: none; + text-transform: uppercase; + background-color: #fff; + border: solid 2px var(--purple-400); + border-radius: 4px; + cursor: pointer; +} +details.kx-item button:hover { + background-color: var(--purple-500); + border-color: var(--purple-500); + color: #fff; +} + +@media screen and (max-width: 640px) { + details.kx-item summary .claim__description p { + font-size: 1.2rem; + } + details.kx-item summary .claim__links a, p.subtle-links a { + font-size: 0.9rem; + } +} +@media screen and (max-width: 480px) { + summary .claim__description p { + font-size: 1rem; + } + details.kx-item summary .verificationStatus { + width: 36px; + height: 36px; + font-size: 1.6rem; + } + details.kx-item .inProgress { + width: 36px; + height: 36px; + } +} + +@-webkit-keyframes load3 { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} +@keyframes load3 { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} diff --git a/static-src/styles.css b/static-src/styles.css new file mode 100644 index 0000000..657265d --- /dev/null +++ b/static-src/styles.css @@ -0,0 +1,744 @@ +/* +Copyright (C) 2021 Yarmo Mackenbach + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU Affero General Public License as published by the Free +Software Foundation, either version 3 of the License, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more +details. + +You should have received a copy of the GNU Affero General Public License along +with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + +If your software can interact with users remotely through a computer network, +you should also make sure that it provides a way for users to get its source. +For example, if your program is a web application, its interface could display +a "Source" link that leads users to an archive of the code. There are many +ways you could offer source, and different solutions will be better for different +programs; see section 13 for the specific requirements. + +You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. For +more information on this, and how to apply and follow the GNU AGPL, see . +*/ +@import '../node_modules/fork-awesome/css/fork-awesome.css'; +@import '../node_modules/dialog-polyfill/dist/dialog-polyfill.css'; + +:root { + --grey-500: hsl(0, 0%, 50%); + --grey-600: hsl(0, 0%, 40%); + --grey-700: hsl(0, 0%, 30%); + --grey-900: hsl(0, 0%, 10%); + --green-300: hsl(110, 45%, 70%); + --green-400: hsl(110, 45%, 60%); + --green-600: hsl(110, 45%, 40%); + --red-400: hsl(10, 60%, 60%); + --blue-500: hsl(201, 80%, 59%); + --blue-700: hsl(201, 90%, 30%); + --purple-50: hsl(250, 30%, 98%); + --purple-100: hsl(250, 48%, 95%); + --purple-200: hsl(250, 48%, 90%); + --purple-300: hsl(250, 48%, 85%); + --purple-400: hsl(250, 48%, 70%); + --purple-500: hsl(250, 48%, 65%); + --purple-600: hsl(250, 48%, 60%); + --purple-700: hsl(250, 48%, 55%); + --purple-900: hsl(250, 38%, 45%); + --yellow-100: hsl(56, 100%, 95%); + --yellow-200: hsl(56, 100%, 90%); + --yellow-500: hsl(56, 100%, 65%); +} + +* { + box-sizing: border-box; +} +:focus { + outline: none; + box-shadow: 0 0 0 3px lightskyblue; +} +input:focus, textarea:focus { + background: azure; +} +input[type="radio"]:focus + label { + box-shadow: 0 0 0 3px lightskyblue; + background: azure !important; + color: var(--grey-900) !important; +} +body { + display: flex; + flex-direction: column; + min-height: 100vh; + margin: 0; + padding: 1.6rem 0 0; + line-height: 1.4rem; + font-family: sans-serif; + color: var(--grey-900); +} + +/* HELPERS */ +.spacer { + flex: 1; +} +.no-margin { + margin: 0 !important; +} +.full-width { + display: block; + width: 100% !important; +} + +/* LAYOUT */ +header { + margin: 0 1.6rem 1.6rem; +} +header nav { + flex: 1; + display: flex; + flex-wrap: wrap; + align-items: center; + justify-content: center; + gap: 8px; +} +header nav a.logo { + width: 64px; + height: 64px; + font-size: 1.6rem; + text-transform: uppercase; + text-decoration: none; + color: var(--purple-700); +} +header nav a.logo img { + width: 100%; +} +nav a.text { + /* font-size: 0.9em; */ + margin: 0; + padding: 0.5em 1em; + text-transform: uppercase; + text-decoration: none; + color: var(--purple-700); + border-radius: 4px; +} +nav a.text:hover, nav a.text:active { + color: #fff; + background-color: var(--purple-500); +} +main { + flex: 1; + margin: 0 1.6rem; +} +footer { + margin: 4.8rem 0 0; + padding: 0 1.6rem 1.6rem; + background-color: var(--purple-900); + color: var(--purple-200); +} + +.container { + width: 100%; + max-width: 720px; + margin: 0 auto; +} +section.profile p, .demo p { + font-size: 1.2rem; +} +.demo { + margin: 4.8rem auto; +} + +.card { + margin: 0 0 1.6rem; + padding: 0 1.2rem; + background-color: #fff; + background-color: var(--purple-50); + border: 2px solid var(--purple-200); + border-radius: 4px; +} +.card.card--transparent { + padding-left: 0; + padding-right: 0; + background-color: transparent; + border: 0; +} +.card--profileHeader { + display: flex; + flex-direction: column; + flex-wrap: wrap; + align-items: center; + gap: 24px; +} +.card--profileHeader p, .card--profileHeader small { + margin: 0; +} +.card--small-profile { + display: flex; + flex-direction: column; + text-align: center; +} +.card--small-profile-dummy { + opacity: 0.5; + border: 0; +} +.card--small-profile .name { + font-size: 1.4em; +} +.card--small-profile p { + margin-top: 0; +} +.card--small-profile p span.fingerprint { + display: inline-block; + width: 100%; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + font-size: 0.8rem; +} +#profileName { + font-size: 1.6rem; + color: var(--grey-700); +} +#profileURLFingerprint { + font-size: 1rem; + margin: 0 0 1.2rem; +} + +.hcards { + display: grid; + grid-gap: 1.2rem; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + margin-bottom: 1.6rem; +} +.hcards .card { + margin: 0; +} +.hcards--col-1-2, .hcards--col-2-1 { + grid-template-columns: repeat(auto-fit, minmax(256px, 1fr)); +} +.hcards--col-1-2 .card, .hcards--col-2-1 .card { + grid-column: 1 / 2; +} +@media screen and (min-width: 1024px) { + .hcards--max-3 { + grid-template-columns: 1fr 1fr 1fr; + } + .hcards--col-1-2, .hcards--col-2-1 { + grid-template-columns: repeat(3, 1fr); + } +} +@media screen and (min-width: 720px) { + .hcards--col-2-1 .card:nth-of-type(1) { + grid-column: 1 / -2; + } + .hcards--col-2-1 .card:nth-of-type(2) { + grid-column: -2 / -1; + } + .hcards--col-1-2 .card:nth-of-type(1) { + grid-column: 1 / 2; + } + .hcards--col-1-2 .card:nth-of-type(2) { + grid-column: 2 / -1; + } +} + +.warning { + padding: calc(0.8rem - 2px) 0.8rem; + background-color: var(--yellow-200); + border: solid 2px var(--yellow-500); +} +.warning p:first-of-type { + margin-top: 0; +} +.warning p:last-of-type { + margin-bottom: 0; +} + +kx-claim { + display: block; + margin: 12px 0; +} + +#profileAvatar { + display: inline-block; + min-width: 96px; + max-width: 128px; + line-height: 0; + text-align: center; + border-radius: 50%; +} + +/* TYPOGRAPHY */ +h1 { + font-size: 1.6em; + margin: 3.2rem 0 1.6rem; + font-weight: normal; + color: var(--purple-700); + cursor: default; +} +h2 { + font-size: 1.4em; + margin: 3.2rem 0 1.6rem; + font-weight: normal; + color: var(--purple-700); + cursor: default; +} +h2 small { + margin-left: 0.8rem; + padding: 3px 6px; + background-color: var(--purple-600); + color: #fff; + border-radius: 4px; +} +h3 { + margin: 1.6rem 0; + font-size: 1.3em; + line-height: 1.6rem; + color: var(--grey-700); + font-weight: normal; + /* text-align: center; */ + cursor: default; +} +h3 small { + margin-left: 0.8rem; + padding: 3px 6px; + background-color: var(--purple-400); + color: #fff; + border-radius: 4px; +} +h4 { + margin: 1.6rem 0; + font-size: 1em; + line-height: 1.6rem; + color: var(--grey-600); + /* color: var(--purple-700); */ + font-weight: bold; + cursor: default; +} +h4 small { + margin-left: 0.8rem; + padding: 3px 6px; + background-color: var(--purple-400); + color: #fff; + border-radius: 4px; +} +p { + margin: 1.6rem 0; +} +p.warning { + padding: 8px; + background-color: #fffadc; + border: solid 1px #ffeea8; +} +a { + color: var(--blue-700); +} +ul { + padding-left: 1em; + list-style: '- '; +} +main h1:first-of-type { + margin-top: 1.6rem; +} +footer h1 { + margin-bottom: 0.8rem; + color: var(--purple-200); + font-size: 1.2rem; + font-weight: bold; +} +footer a { + display: inline-block; + color: var(--purple-100); + height: 32px; +} + +code { + padding: 2px 4px; + background-color: var(--purple-100); + border: 1px solid var(--purple-500); +} +pre { + padding: 8px 12px; + background-color: var(--purple-100); + border: 1px solid var(--purple-500); + overflow-x: auto; + line-height: 1.2rem; + font-size: 1rem; +} +pre code { + padding: 0; + background-color: 0px; + border: 0px; +} + +#qr { + display: block; + width: 100% !important; + max-width: 256px !important; + height: auto !important; + margin: 0 auto 16px; +} + +/* FORM ELEMENTS */ +.form-wrapper { + align-items: center; + padding-top: 1.4rem; + padding-bottom: 1.6rem; + margin-bottom: 48px; +} +.form-wrapper form { + display: flex; + flex-direction: column; + margin: 0; +} +.form-wrapper h2 { + margin-top: 0; +} +form input[type="text"], form input[type="search"] { + margin: 8px 0; + padding: 4px; + border: 1px solid #444; + font-size: 0.9rem; +} +form textarea { + width: 100%; + height: 128px; + margin: 8px 0; + resize: vertical; + font-size: 0.9rem; + border: 1px solid #444; +} +.button-wrapper { + display: flex; + flex-wrap: wrap; + gap: 8px; + margin: 8px 0; +} +.radio-wrapper { + display: flex; + flex-wrap: wrap; + margin: 8px 0; +} +.radio-wrapper input[type="radio"] { + position: absolute; + opacity: 0; + z-index: -1; +} +.radio-wrapper input[type="radio"] + label { + margin: 0; + padding: 2px 8px; + background-color: #fff; + border: solid var(--purple-400); + border-width: 2px 1px; + cursor: pointer; +} +.radio-wrapper input[type="radio"]:first-of-type + label { + border-radius: 4px 0 0 4px; + border-left-width: 2px; +} +.radio-wrapper input[type="radio"]:last-of-type + label { + border-radius: 0 4px 4px 0; + border-right-width: 2px; +} +.radio-wrapper input[type="radio"]:focus + label { + z-index: 1; +} +.radio-wrapper input[type="radio"] + label:hover { + background-color: var(--purple-100); + border-color: var(--purple-500); +} +.radio-wrapper input[type="radio"]:checked + label { + color: #fff; + background-color: var(--purple-600); + border-color: var(--purple-600); +} + +input[type="button"], input[type="submit"], button, a.button { + display: inline-block; + min-height: 36px; + margin: 8px 0; + padding: 4px 8px; + font-family: sans-serif; + font-size: 0.9rem; + text-decoration: none; + text-transform: uppercase; + color: #333; + background-color: #fff; + border: solid 2px var(--purple-400); + border-radius: 4px; + cursor: pointer; +} +input[type="button"]:focus, input[type="submit"]:focus, button:focus, a.button:focus { + background-color: azure; +} +input[type="button"]:hover, input[type="submit"]:hover, button:hover, a.button:hover { + background-color: var(--purple-500); + border-color: var(--purple-500); + color: #fff; +} +a.button i { + font-size: 1.4em; +} +a.button.button--liberapay { + padding: 8px 16px; + font-size: 0.95rem; + color: #333; + background-color: #ffee16; + border: 0; +} +a.button.button--liberapay:hover { + background-color: #fff463; +} + +/* DIALOGS */ +dialog { + width: 100% !important; + max-width: 800px !important; + padding: 0 !important; + word-wrap: anywhere; +} +dialog > div { + padding: 1em; +} +dialog form[method="Dialog"] { + margin: 1em 0 0 !important; +} +dialog form[method="Dialog"] input { + width: auto; +} +dialog p { + font-size: 1rem !important; + margin: 1rem 0; +} +dialog p:first-of-type { + margin-top: 0; +} + +/* KX-ITEM */ +.kx-item details { + width: 100%; + border-radius: 8px; +} +.kx-item details p { + margin: 0; + word-break: break-word; + font-size: 1rem; +} +.kx-item details a { + color: var(--blue-700); +} +.kx-item details hr { + border: none; + border-top: 2px solid var(--purple-100); +} +.kx-item details .content { + padding: 12px; + border: solid 3px var(--purple-100); + border-top: 0px; + border-radius: 0px 0px 8px 8px; +} +.kx-item details summary { + display: flex; + align-items: center; + padding: 8px 12px; + background-color: var(--purple-100); + border: solid 3px var(--purple-100); + border-radius: 8px; + list-style: none; + cursor: pointer; +} +.kx-item details summary::-webkit-details-marker { + display: none; +} +.kx-item details summary:hover, summary:focus { + border-color: var(--purple-400); +} +details[open] summary { + border-radius: 8px 8px 0px 0px; +} +.kx-item details summary .info { + flex: 1; +} +.kx-item details summary .info .title { + font-size: 1.1em; +} +.kx-item details summary .claim__description p { + font-size: 1.4rem; + line-height: 2rem; +} +.kx-item details summary .claim__links p, p.subtle-links { + display: flex; + align-items: center; + flex-wrap: wrap; + font-size: 1rem; + color: var(--grey-700); +} +.kx-item details summary .claim__links a, summary .claim__links span, p.subtle-links a { + font-size: 1rem; + margin: 0 10px 0 0; + color: var(--grey-700); +} +.kx-item details summary .subtitle { + color: var(--purple-700); +} +.kx-item details summary .verificationStatus { + position: relative; + display: flex; + align-items: center; + justify-content: center; + width: 48px; + height: 48px; + border-radius: 100%; + color: #fff; + font-size: 2rem; + user-select: none; +} +.kx-item details summary .verificationStatus::after { + position: absolute; + display: flex; + top: 0; + left: 0; + right: 0; + bottom: 0; + align-items: center; + justify-content: center; +} +.kx-item details summary .verificationStatus .inProgress { + opacity: 0; + transition: opacity 0.4s ease; + pointer-events: none; +} +.kx-item details summary .verificationStatus[data-value="success"] { + content: "v"; + background-color: var(--green-600); +} +.kx-item details summary .verificationStatus[data-value="success"]::after { + content: "✔"; +} +.kx-item details summary .verificationStatus[data-value="failed"] { + background-color: var(--red-400); +} +.kx-item details summary .verificationStatus[data-value="failed"]::after { + content: "✕"; +} +.kx-item details summary .verificationStatus[data-value="running"] .inProgress { + opacity: 1; +} + +.kx-item details .subsection { + display: flex; + align-items: center; + gap: 16px; +} +.kx-item details .subsection > img { + width: 24px; + height: 24px; + opacity: 0.4; +} + +.kx-item details .inProgress { + font-size: 10px; + margin: 50px auto; + text-indent: -9999em; + width: 48px; + height: 48px; + border-radius: 50%; + background: var(--purple-400); + background: -moz-linear-gradient(left, var(--purple-400) 10%, rgba(255, 255, 255, 0) 42%); + background: -webkit-linear-gradient(left, var(--purple-400) 10%, rgba(255, 255, 255, 0) 42%); + background: -o-linear-gradient(left, var(--purple-400) 10%, rgba(255, 255, 255, 0) 42%); + background: -ms-linear-gradient(left, var(--purple-400) 10%, rgba(255, 255, 255, 0) 42%); + background: linear-gradient(to right, var(--purple-400) 10%, rgba(255, 255, 255, 0) 42%); + position: relative; + -webkit-animation: load3 1.4s infinite linear; + animation: load3 1.4s infinite linear; + -webkit-transform: translateZ(0); + -ms-transform: translateZ(0); + transform: translateZ(0); +} +.kx-item details .inProgress:before { + width: 50%; + height: 50%; + background: var(--purple-400); + border-radius: 100% 0 0 0; + position: absolute; + top: 0; + left: 0; + content: ''; +} +.kx-item details .inProgress:after { + background: var(--purple-100); + width: 65%; + height: 65%; + border-radius: 50%; + content: ''; + margin: auto; + position: absolute; + top: 0; + left: 0; + bottom: 0; + right: 0; +} +.kx-item details button { + padding: 0.4rem 0.8rem; + margin-right: 8px; + text-decoration: none; + text-transform: uppercase; + background-color: #fff; + border: solid 2px var(--purple-400); + border-radius: 4px; + cursor: pointer; +} +.kx-item details button:hover { + background-color: var(--purple-500); + border-color: var(--purple-500); + color: #fff; +} + +@media screen and (max-width: 640px) { + .kx-item details summary .claim__description p { + font-size: 1.2rem; + } + .kx-item details summary .claim__links a, p.subtle-links a { + font-size: 0.9rem; + } +} +@media screen and (max-width: 480px) { + summary .claim__description p { + font-size: 1rem; + } + .kx-item details summary .verificationStatus { + width: 36px; + height: 36px; + font-size: 1.6rem; + } + .kx-item details .inProgress { + width: 36px; + height: 36px; + } +} + +@-webkit-keyframes load3 { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} +@keyframes load3 { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} diff --git a/static-src/ui.js b/static-src/ui.js new file mode 100644 index 0000000..a07b8c7 --- /dev/null +++ b/static-src/ui.js @@ -0,0 +1,400 @@ +/* +Copyright (C) 2021 Yarmo Mackenbach + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU Affero General Public License as published by the Free +Software Foundation, either version 3 of the License, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more +details. + +You should have received a copy of the GNU Affero General Public License along +with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + +If your software can interact with users remotely through a computer network, +you should also make sure that it provides a way for users to get its source. +For example, if your program is a web application, its interface could display +a "Source" link that leads users to an archive of the code. There are many +ways you could offer source, and different solutions will be better for different +programs; see section 13 for the specific requirements. + +You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. For +more information on this, and how to apply and follow the GNU AGPL, see . +*/ +import dialogPolyfill from 'dialog-polyfill' +import QRCode from 'qrcode' +import * as openpgp from 'openpgp' +import * as utils from './utils' + +// Prepare element selectors +const elFormSignatureProfile = document.body.querySelector("#formGenerateSignatureProfile") +const elFormEncrypt = document.body.querySelector("#dialog--encryptMessage form") +const elFormVerify = document.body.querySelector("#dialog--verifySignature form") +const elFormSearch = document.body.querySelector("#search") + +const elProfileUid = document.body.querySelector("#profileUid") +const elProfileMode = document.body.querySelector("#profileMode") +const elProfileServer = document.body.querySelector("#profileServer") + +const elModeSelect = document.body.querySelector("#modeSelect") + +const elUtilWKD = document.body.querySelector("#form-util-wkd") +const elUtilQRFP = document.body.querySelector("#form-util-qrfp") +const elUtilQR = document.body.querySelector("#form-util-qr") +const elUtilProfileURL = document.body.querySelector("#form-util-profile-url") + +// Initialize UI elements and event listeners +export function init() { + // Register modals + document.querySelectorAll('dialog').forEach(function(d) { + dialogPolyfill.registerDialog(d); + d.addEventListener('click', function(ev) { + if (ev && ev.target != d) { + return; + } + d.close(); + }); + }); + + // Run context-dependent scripts + if (elFormEncrypt) { + runEncryptionForm() + } + + if (elFormVerify) { + runVerificationForm() + } + + if (elFormSearch) { + runSearchForm() + } + if (elModeSelect) { + runModeSelector() + } + + if (elProfileUid) { + runProfileGenerator() + } + + if (elUtilWKD) { + runWKDUtility() + } + + if (elUtilQRFP) { + runQRFPUtility() + } + + if (elUtilQR) { + runQRUtility + } + + if (elUtilProfileURL) { + runProfileURLUtility + } +} + +const runEncryptionForm = () => { + elFormEncrypt.onsubmit = async function (evt) { + evt.preventDefault(); + + try { + // Fetch a key if needed + await utils.fetchProfileKey(); + + // Encrypt the message + let config = openpgp.config; + config.show_comment = false; + config.show_version = false; + + let encrypted = await openpgp.encrypt({ + message: openpgp.message.fromText(elFormEncrypt.querySelector('.input').value), + publicKeys: window.kx.key.object, + config: config + }); + elFormEncrypt.querySelector('.output').value = encrypted.data; + } catch (e) { + console.error(e); + elFormEncrypt.querySelector('.output').value = `Could not encrypt message!\n==========================\n${e.message ? e.message : e}`; + } + } +} + +const runVerificationForm = () => { + elFormVerify.onsubmit = async function (evt) { + evt.preventDefault(); + + try { + // Fetch a key if needed + await utils.fetchProfileKey(); + + // Try two different methods of signature reading + let signature = null, verified = null, readError = null; + try { + signature = await openpgp.message.readArmored(elFormVerify.querySelector('.input').value); + } catch(e) { + readError = e; + } + try { + signature = await openpgp.cleartext.readArmored(elFormVerify.querySelector('.input').value); + } catch(e) { + readError = e; + } + if (signature == null) { throw(readError) }; + + // Verify the signature + verified = await openpgp.verify({ + message: signature, + publicKeys: window.kx.key.object + }); + + if (verified.signatures[0].valid) { + elFormVerify.querySelector('.output').value = `The message was signed by the profile's key.`; + } else { + elFormVerify.querySelector('.output').value = `The message was NOT signed by the profile's key.`; + } + } catch (e) { + console.error(e); + elFormVerify.querySelector('.output').value = `Could not verify signature!\n===========================\n${e.message ? e.message : e}`; + } + } +} + +const runSearchForm = () => { + elFormSearch.onsubmit = function (evt) { + evt.preventDefault(); + + const protocol = elFormSearch.querySelector("input[type='radio']:checked").value; + const identifier = elFormSearch.querySelector("input[type='search']").value; + + if (protocol == 'sig') { + window.location.href = `/${protocol}`; + } else { + window.location.href = `/${protocol}/${encodeURIComponent(identifier)}`; + } + } + + elFormSearch.querySelectorAll("input[type='radio']").forEach(function (el) { + el.oninput = function (evt) { + evt.preventDefault(); + + if (evt.target.getAttribute('id') === 'protocol-sig') { + elFormSearch.querySelector("input[type='search']").setAttribute('disabled', true); + } else { + elFormSearch.querySelector("input[type='search']").removeAttribute('disabled'); + } + } + }); + + elFormSearch.querySelector("input[type='radio']:checked").dispatchEvent(new Event('input')); +} + +const runModeSelector = () => { + elModeSelect.onchange = function (evt) { + let elAllModes = document.body.querySelectorAll('.modes'); + elAllModes.forEach(function(el) { + el.classList.remove('modes--visible'); + }); + document.body.querySelector(`.modes--${elModeSelect.value}`).classList.add('modes--visible'); + } + elModeSelect.dispatchEvent(new Event("change")); +} + +const runProfileGenerator = () => { + let opts, profileUid = elProfileUid.innerHTML; + switch (elProfileMode.innerHTML) { + default: + case "sig": + elFormSignatureProfile.onsubmit = function (evt) { + evt.preventDefault(); + + opts = { + input: document.body.querySelector("#plaintext_input").value, + mode: elProfileMode.innerHTML + } + + displayProfile(opts) + } + break; + + case "auto": + if (/.*@.*/.test(profileUid)) { + // Match email for wkd + opts = { + input: profileUid, + mode: "wkd" + } + } else { + // Match fingerprint for hkp + opts = { + input: profileUid, + mode: "hkp" + } + } + break; + + case "hkp": + opts = { + input: profileUid, + server: elProfileServer.innerHTML, + mode: elProfileMode.innerHTML + } + break; + + case "wkd": + opts = { + input: profileUid, + mode: elProfileMode.innerHTML + } + break; + + case "keybase": + let match = profileUid.match(/(.*)\/(.*)/); + opts = { + username: match[1], + fingerprint: match[2], + mode: elProfileMode.innerHTML + } + break; + } + + if (elProfileMode.innerHTML !== 'sig') { + keyoxide.displayProfile(opts); + } +} + +const runWKDUtility = () => { + elUtilWKD.onsubmit = function (evt) { + evt.preventDefault(); + } + + const elInput = document.body.querySelector("#input"); + const elOutput = document.body.querySelector("#output"); + const elOutputDirect = document.body.querySelector("#output_url_direct"); + const elOutputAdvanced = document.body.querySelector("#output_url_advanced"); + let match; + + elInput.addEventListener("input", async function(evt) { + if (evt.target.value) { + if (/(.*)@(.{1,}\..{1,})/.test(evt.target.value)) { + match = evt.target.value.match(/(.*)@(.*)/); + elOutput.innerText = await utils.computeWKDLocalPart(match[1]); + elOutputDirect.innerText = `https://${match[2]}/.well-known/openpgpkey/hu/${elOutput.innerText}?l=${match[1]}`; + elOutputAdvanced.innerText = `https://openpgpkey.${match[2]}/.well-known/openpgpkey/${match[2]}/hu/${elOutput.innerText}?l=${match[1]}`; + } else { + elOutput.innerText = await utils.computeWKDLocalPart(evt.target.value); + elOutputDirect.innerText = "Waiting for input"; + elOutputAdvanced.innerText = "Waiting for input"; + } + } else { + elOutput.innerText = "Waiting for input"; + elOutputDirect.innerText = "Waiting for input"; + elOutputAdvanced.innerText = "Waiting for input"; + } + }); + + elInput.dispatchEvent(new Event("input")); +} + +const runQRFPUtility = () => { + elUtilQRFP.onsubmit = function (evt) { + evt.preventDefault(); + } + + const qrTarget = document.getElementById('qrcode'); + const qrContext = qrTarget.getContext('2d'); + const qrOpts = { + errorCorrectionLevel: 'H', + margin: 1, + width: 256, + height: 256 + }; + + const elInput = document.body.querySelector("#input"); + + elInput.addEventListener("input", async function(evt) { + if (evt.target.value) { + QRCode.toCanvas(qrTarget, evt.target.value, qrOpts, function (error) { + if (error) { + qrContext.clearRect(0, 0, qrTarget.width, qrTarget.height); + console.error(error); + } + }); + } else { + qrContext.clearRect(0, 0, qrTarget.width, qrTarget.height); + } + }); + + elInput.dispatchEvent(new Event("input")); +} + +const runQRUtility = () => { + elUtilQR.onsubmit = function (evt) { + evt.preventDefault(); + } + + const qrTarget = document.getElementById('qrcode'); + const qrContext = qrTarget.getContext('2d'); + const qrOpts = { + errorCorrectionLevel: 'L', + margin: 1, + width: 256, + height: 256 + }; + + const elInput = document.body.querySelector("#input"); + + if (elInput.innerText) { + elInput.innerText = decodeURIComponent(elInput.innerText); + + QRCode.toCanvas(qrTarget, elInput.innerText, qrOpts, function (error) { + if (error) { + document.body.querySelector("#qrcode--altLink").href = "#"; + qrContext.clearRect(0, 0, qrTarget.width, qrTarget.height); + console.error(error); + } else { + document.body.querySelector("#qrcode--altLink").href = elInput.innerText; + } + }); + } else { + qrContext.clearRect(0, 0, qrTarget.width, qrTarget.height); + } +} + +const runProfileURLUtility = () => { + elUtilProfileURL.onsubmit = function (evt) { + evt.preventDefault(); + } + + const elInput = document.body.querySelector("#input"), + elSource = document.body.querySelector("#source"), + elOutput = document.body.querySelector("#output"); + + let data = { + input: elInput.value, + source: elSource.value + }; + + elInput.addEventListener("input", async function(evt) { + data = { + input: elInput.value, + source: elSource.value + }; + elOutput.innerText = await utils.generateProfileURL(data); + }); + + elSource.addEventListener("input", async function(evt) { + data = { + input: elInput.value, + source: elSource.value + }; + elOutput.innerText = await utils.generateProfileURL(data); + }); + + elInput.dispatchEvent(new Event("input")); +} \ No newline at end of file diff --git a/static-src/utils.js b/static-src/utils.js new file mode 100644 index 0000000..270f133 --- /dev/null +++ b/static-src/utils.js @@ -0,0 +1,134 @@ +/* +Copyright (C) 2021 Yarmo Mackenbach + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU Affero General Public License as published by the Free +Software Foundation, either version 3 of the License, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more +details. + +You should have received a copy of the GNU Affero General Public License along +with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + +If your software can interact with users remotely through a computer network, +you should also make sure that it provides a way for users to get its source. +For example, if your program is a web application, its interface could display +a "Source" link that leads users to an archive of the code. There are many +ways you could offer source, and different solutions will be better for different +programs; see section 13 for the specific requirements. + +You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. For +more information on this, and how to apply and follow the GNU AGPL, see . +*/ +import * as openpgp from 'openpgp' +import QRCode from 'qrcode' + +// Compute local part of Web Key Directory URL +export async function computeWKDLocalPart(message) { + const data = openpgp.util.str_to_Uint8Array(message.toLowerCase()); + const hash = await openpgp.crypto.hash.sha1(data); + return openpgp.util.encodeZBase32(hash); +} + +// Generate Keyoxide profile URL +export async function generateProfileURL(data) { + let hostname = window.location.hostname; + + if (data.input == "") { + return "Waiting for input..."; + } + switch (data.source) { + case "wkd": + return `https://${hostname}/${data.input}`; + break; + case "hkp": + if (/.*@.*\..*/.test(data.input)) { + return `https://${hostname}/hkp/${data.input}`; + } else { + return `https://${hostname}/${data.input}`; + } + break; + case "keybase": + const re = /https\:\/\/keybase.io\/(.*)\/pgp_keys\.asc\?fingerprint\=(.*)/; + if (!re.test(data.input)) { + return "Incorrect Keybase public key URL."; + } + const match = data.input.match(re); + return `https://${hostname}/keybase/${match[1]}/${match[2]}`; + break; + } +} + +// Fetch OpenPGP key based on information stored in window +export async function fetchProfileKey() { + if (window.kx.key.object && window.kx.key.object instanceof openpgp.key.Key) { + return; + } + + const rawKeyData = await fetch(window.kx.key.url) + let key, errorMsg + + try { + key = (await openpgp.key.read(new Uint8Array(await rawKeyData.clone().arrayBuffer()))).keys[0] + } catch(error) { + errorMsg = error.message + } + + if (!key) { + try { + key = (await openpgp.key.readArmored(await rawKeyData.clone().text())).keys[0] + } catch (error) { + errorMsg = error.message + } + } + + if (key) { + window.kx.key.object = key + return + } else { + throw new Error(`Public key could not be fetched (${errorMsg})`) + } +} + +// Show QR modal +export function showQR(input, type) { + const qrTarget = document.getElementById('qr'); + const qrContext = qrTarget.getContext('2d'); + const qrOpts = { + errorCorrectionLevel: 'L', + margin: 1, + width: 256, + height: 256 + }; + + if (input) { + if (type === 'url') { + input = decodeURIComponent(input); + } + if (type === 'fingerprint') { + input = `OPENPGP4FPR:${input.toUpperCase()}` + } + + QRCode.toCanvas(qrTarget, input, qrOpts, function(error) { + if (error) { + document.querySelector("#qr--altLink").innerText = ""; + document.querySelector("#qr--altLink").href = "#"; + qrContext.clearRect(0, 0, qrTarget.width, qrTarget.height); + console.error(error); + } else { + document.querySelector("#qr--altLink").innerText = input; + document.querySelector("#qr--altLink").href = input; + document.querySelector('#dialog--qr').showModal(); + } + }); + } else { + qrContext.clearRect(0, 0, qrTarget.width, qrTarget.height); + } +} diff --git a/views/index.pug b/views/index.pug index 6878992..4b98fc9 100644 --- a/views/index.pug +++ b/views/index.pug @@ -1,11 +1,5 @@ extends templates/base.pug -block js - script(type='application/javascript' defer src='/static/openpgp.min.js' charset='utf-8') - script(type='application/javascript' defer src='/static/doip.min.js' charset='utf-8') - script(type='application/javascript' defer src='/static/kx-claim.js' charset='utf-8') - script(type='application/javascript' defer src='/static/scripts.js' charset='utf-8') - block content .demo kx-claim.kx-item(data-claim= demoData data-skip="true") diff --git a/views/profile.pug b/views/profile.pug index 21a63ec..eb16296 100644 --- a/views/profile.pug +++ b/views/profile.pug @@ -30,18 +30,6 @@ mixin generateUser(user, isPrimary) a(rel='me' href=claim.matches[0].proof.uri aria-label="Link to proof")= claim.matches[0].proof.uri else p Proof link: not accessible from browser - -block js - script(type='application/javascript' src='/static/qrcode.min.js' charset='utf-8') - script(type='application/javascript' src='/static/dialog-polyfill.js' charset='utf-8') - script(type='application/javascript' src='/static/openpgp.min.js' charset='utf-8') - script(type='application/javascript' src='/static/doip.min.js' charset='utf-8') - script(type='application/javascript' src='/static/kx-claim.js' charset='utf-8') - script(type='application/javascript' src='/static/kx-key.js' charset='utf-8') - script(type='application/javascript' src='/static/scripts.js' charset='utf-8') - -block css - link(rel='stylesheet' href='/static/dialog-polyfill.css') block content script. diff --git a/views/templates/base.pug b/views/templates/base.pug index 486ef7a..3088428 100644 --- a/views/templates/base.pug +++ b/views/templates/base.pug @@ -16,8 +16,6 @@ html(lang='en') include ../partials/footer.pug - link(rel='stylesheet' href='/static/styles.css') - link(rel='stylesheet' href='https://cdn.jsdelivr.net/npm/fork-awesome@1.1.7/css/fork-awesome.min.css' integrity='sha256-gsmEoJAws/Kd3CjuOQzLie5Q3yshhvmo7YNtBG7aaEY=' crossorigin='anonymous') - block css - - block js + link(rel='stylesheet' href='/static/main.css') + script(type='application/javascript' defer src='/static/openpgp.js' charset='utf-8') + script(type='application/javascript' defer src='/static/main.js' charset='utf-8') \ No newline at end of file diff --git a/views/util/profile-url.pug b/views/util/profile-url.pug index dd54d9d..1167c7d 100644 --- a/views/util/profile-url.pug +++ b/views/util/profile-url.pug @@ -1,9 +1,5 @@ extends ../templates/base.pug -block js - script(type='application/javascript' src='/static/scripts.js' charset='utf-8') - script(type='application/javascript' src='/static/scripts.util.js' charset='utf-8') - block content section.narrow h1 Profile URL diff --git a/views/util/qr.pug b/views/util/qr.pug index bf6b60e..1a28df4 100644 --- a/views/util/qr.pug +++ b/views/util/qr.pug @@ -1,10 +1,5 @@ extends ../templates/base.pug -block js - script(type='application/javascript' src='/static/qrcode.min.js' charset='utf-8') - script(type='application/javascript' src='/static/scripts.js' charset='utf-8') - script(type='application/javascript' src='/static/scripts.util.js' charset='utf-8') - block content section.narrow h1 QR Code diff --git a/views/util/qrfp.pug b/views/util/qrfp.pug index 4047bad..98eee11 100644 --- a/views/util/qrfp.pug +++ b/views/util/qrfp.pug @@ -1,10 +1,5 @@ extends ../templates/base.pug -block js - script(type='application/javascript' src='/static/qrcode.min.js' charset='utf-8') - script(type='application/javascript' src='/static/scripts.js' charset='utf-8') - script(type='application/javascript' src='/static/scripts.util.js' charset='utf-8') - block content section.narrow h1 QR Code diff --git a/views/util/wkd.pug b/views/util/wkd.pug index 3a89ce2..dbaebcb 100644 --- a/views/util/wkd.pug +++ b/views/util/wkd.pug @@ -1,10 +1,5 @@ extends ../templates/base.pug -block js - script(type='application/javascript' src='/static/openpgp.min.js' charset='utf-8') - script(type='application/javascript' src='/static/scripts.js' charset='utf-8') - script(type='application/javascript' src='/static/scripts.util.js' charset='utf-8') - block content section.narrow h1 Web Key Directory generator diff --git a/webpack.config.js b/webpack.config.js new file mode 100644 index 0000000..2e92849 --- /dev/null +++ b/webpack.config.js @@ -0,0 +1,48 @@ +const path = require('path') +const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin +const MiniCssExtractPlugin = require("mini-css-extract-plugin") + +module.exports = (env) => { + let config + if (env.static) { + config = { + mode: env.mode, + entry: { + main: { + import: './static-src/index.js', + dependOn: 'openpgp', + }, + openpgp: './node_modules/openpgp/dist/openpgp.js', + }, + output: { + filename: '[name].js', + path: path.resolve(__dirname, 'static'), + }, + watch: env.mode == "development", + module: { + rules: [ + { + test: /\.css$/, + use: [ + MiniCssExtractPlugin.loader, + 'css-loader' + ] + } + ] + }, + plugins: [ + new MiniCssExtractPlugin(), + ], + } + } else { + return {} + } + + if (env.mode == 'development') { + config.plugins.push(new BundleAnalyzerPlugin({ + openAnalyzer: false + })) + } + + return config +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 2962109..a7a02ef 100644 --- a/yarn.lock +++ b/yarn.lock @@ -262,6 +262,11 @@ "@babel/helper-validator-identifier" "^7.14.0" to-fast-properties "^2.0.0" +"@discoveryjs/json-ext@^0.5.0": + version "0.5.6" + resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.6.tgz#d5e0706cf8c6acd8c6032f8d54070af261bbbb2f" + integrity sha512-ws57AidsDvREKrZKYffXddNkyaF14iHNHm8VQnZH6t99E8gczjNN0GpvcGny0imC80yQ0tHz1xVUKk/KFQSUyA== + "@nicolo-ribaudo/chokidar-2@2.1.8-no-fsevents": version "2.1.8-no-fsevents" resolved "https://registry.npmjs.org/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.tgz" @@ -300,6 +305,11 @@ "@nodelib/fs.scandir" "2.1.4" fastq "^1.6.0" +"@polka/url@^1.0.0-next.20": + version "1.0.0-next.21" + resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.21.tgz#5de5a2385a35309427f6011992b544514d559aa1" + integrity sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g== + "@sindresorhus/is@^0.14.0": version "0.14.0" resolved "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz" @@ -334,6 +344,27 @@ "@types/node" "*" "@types/responselike" "*" +"@types/eslint-scope@^3.7.3": + version "3.7.3" + resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.3.tgz#125b88504b61e3c8bc6f870882003253005c3224" + integrity sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g== + dependencies: + "@types/eslint" "*" + "@types/estree" "*" + +"@types/eslint@*": + version "8.4.1" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.4.1.tgz#c48251553e8759db9e656de3efc846954ac32304" + integrity sha512-GE44+DNEyxxh2Kc6ro/VkIj+9ma0pO0bwv9+uHSyBrikYOHr8zYcdPvnBOp1aw8s+CjRvuSx7CyWqRrNFQ59mA== + dependencies: + "@types/estree" "*" + "@types/json-schema" "*" + +"@types/estree@*", "@types/estree@^0.0.51": + version "0.0.51" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.51.tgz#cfd70924a25a3fd32b218e5e420e6897e1ac4f40" + integrity sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ== + "@types/glob@^7.1.1": version "7.1.3" resolved "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz" @@ -347,6 +378,11 @@ resolved "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.0.tgz" integrity sha512-c3Xy026kOF7QOTn00hbIllV1dLR9hG9NkSrLQgCVs8NF6sBU+VGWjD3wLPhmh1TYAc7ugCFsvHYMN4VcBN1U1A== +"@types/json-schema@*", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": + version "7.0.9" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" + integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ== + "@types/keyv@*": version "3.1.1" resolved "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.1.tgz" @@ -371,6 +407,144 @@ dependencies: "@types/node" "*" +"@webassemblyjs/ast@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7" + integrity sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw== + dependencies: + "@webassemblyjs/helper-numbers" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + +"@webassemblyjs/floating-point-hex-parser@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz#f6c61a705f0fd7a6aecaa4e8198f23d9dc179e4f" + integrity sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ== + +"@webassemblyjs/helper-api-error@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz#1a63192d8788e5c012800ba6a7a46c705288fd16" + integrity sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg== + +"@webassemblyjs/helper-buffer@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz#832a900eb444884cde9a7cad467f81500f5e5ab5" + integrity sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA== + +"@webassemblyjs/helper-numbers@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz#64d81da219fbbba1e3bd1bfc74f6e8c4e10a62ae" + integrity sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ== + dependencies: + "@webassemblyjs/floating-point-hex-parser" "1.11.1" + "@webassemblyjs/helper-api-error" "1.11.1" + "@xtuc/long" "4.2.2" + +"@webassemblyjs/helper-wasm-bytecode@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz#f328241e41e7b199d0b20c18e88429c4433295e1" + integrity sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q== + +"@webassemblyjs/helper-wasm-section@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz#21ee065a7b635f319e738f0dd73bfbda281c097a" + integrity sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-buffer" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/wasm-gen" "1.11.1" + +"@webassemblyjs/ieee754@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz#963929e9bbd05709e7e12243a099180812992614" + integrity sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ== + dependencies: + "@xtuc/ieee754" "^1.2.0" + +"@webassemblyjs/leb128@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.1.tgz#ce814b45574e93d76bae1fb2644ab9cdd9527aa5" + integrity sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw== + dependencies: + "@xtuc/long" "4.2.2" + +"@webassemblyjs/utf8@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.1.tgz#d1f8b764369e7c6e6bae350e854dec9a59f0a3ff" + integrity sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ== + +"@webassemblyjs/wasm-edit@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz#ad206ebf4bf95a058ce9880a8c092c5dec8193d6" + integrity sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-buffer" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/helper-wasm-section" "1.11.1" + "@webassemblyjs/wasm-gen" "1.11.1" + "@webassemblyjs/wasm-opt" "1.11.1" + "@webassemblyjs/wasm-parser" "1.11.1" + "@webassemblyjs/wast-printer" "1.11.1" + +"@webassemblyjs/wasm-gen@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz#86c5ea304849759b7d88c47a32f4f039ae3c8f76" + integrity sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/ieee754" "1.11.1" + "@webassemblyjs/leb128" "1.11.1" + "@webassemblyjs/utf8" "1.11.1" + +"@webassemblyjs/wasm-opt@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz#657b4c2202f4cf3b345f8a4c6461c8c2418985f2" + integrity sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-buffer" "1.11.1" + "@webassemblyjs/wasm-gen" "1.11.1" + "@webassemblyjs/wasm-parser" "1.11.1" + +"@webassemblyjs/wasm-parser@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz#86ca734534f417e9bd3c67c7a1c75d8be41fb199" + integrity sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-api-error" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/ieee754" "1.11.1" + "@webassemblyjs/leb128" "1.11.1" + "@webassemblyjs/utf8" "1.11.1" + +"@webassemblyjs/wast-printer@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz#d0c73beda8eec5426f10ae8ef55cee5e7084c2f0" + integrity sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@xtuc/long" "4.2.2" + +"@webpack-cli/configtest@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-1.1.1.tgz#9f53b1b7946a6efc2a749095a4f450e2932e8356" + integrity sha512-1FBc1f9G4P/AxMqIgfZgeOTuRnwZMten8E7zap5zgpPInnCrP8D4Q81+4CWIch8i/Nf7nXjP0v6CjjbHOrXhKg== + +"@webpack-cli/info@^1.4.1": + version "1.4.1" + resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-1.4.1.tgz#2360ea1710cbbb97ff156a3f0f24556e0fc1ebea" + integrity sha512-PKVGmazEq3oAo46Q63tpMr4HipI3OPfP7LiNOEJg963RMgT0rqheag28NCML0o3GIzA3DmxP1ZIAv9oTX1CUIA== + dependencies: + envinfo "^7.7.3" + +"@webpack-cli/serve@^1.6.1": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-1.6.1.tgz#0de2875ac31b46b6c5bb1ae0a7d7f0ba5678dffe" + integrity sha512-gNGTiTrjEVQ0OcVnzsRSqTxaBSr+dmTfm+qJsCDluky8uhdLWep7Gcr62QsAKHTMxjCS/8nEITsmFAhfIx+QSw== + "@xmpp/base64@^0.12.0": version "0.12.0" resolved "https://registry.npmjs.org/@xmpp/base64/-/base64-0.12.0.tgz" @@ -594,6 +768,16 @@ dependencies: ltx "^2.10.0" +"@xtuc/ieee754@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" + integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== + +"@xtuc/long@4.2.2": + version "4.2.2" + resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" + integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== + abab@^2.0.3, abab@^2.0.5: version "2.0.5" resolved "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz" @@ -620,22 +804,56 @@ acorn-globals@^6.0.0: acorn "^7.1.1" acorn-walk "^7.1.1" +acorn-import-assertions@^1.7.6: + version "1.8.0" + resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz#ba2b5939ce62c238db6d93d81c9b111b29b855e9" + integrity sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw== + acorn-walk@^7.1.1: version "7.2.0" resolved "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz" integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== +acorn-walk@^8.0.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" + integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== + acorn@^7.1.1: version "7.4.1" resolved "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== +acorn@^8.0.4, acorn@^8.4.1, acorn@^8.5.0: + version "8.7.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf" + integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ== + acorn@^8.1.0: version "8.2.2" resolved "https://registry.npmjs.org/acorn/-/acorn-8.2.2.tgz" integrity sha512-VrMS8kxT0e7J1EX0p6rI/E0FbfOVcvBpbIqHThFv+f8YrZIlMfVotYcXKVPmTvPW8sW5miJzfUFrrvthUZg8VQ== -ajv@^6.12.3: +ajv-formats@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" + integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA== + dependencies: + ajv "^8.0.0" + +ajv-keywords@^3.5.2: + version "3.5.2" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" + integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== + +ajv-keywords@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz#69d4d385a4733cdbeab44964a1170a88f87f0e16" + integrity sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw== + dependencies: + fast-deep-equal "^3.1.3" + +ajv@^6.12.3, ajv@^6.12.5: version "6.12.6" resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -645,6 +863,16 @@ ajv@^6.12.3: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +ajv@^8.0.0, ajv@^8.8.0: + version "8.10.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.10.0.tgz#e573f719bd3af069017e3b66538ab968d040e54d" + integrity sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + ajv@^8.6.3: version "8.6.3" resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.6.3.tgz#11a66527761dc3e9a3845ea775d2d3c0414e8764" @@ -1093,6 +1321,14 @@ chalk@^3.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" +chalk@^4.1.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + character-parser@^2.2.0: version "2.2.0" resolved "https://registry.npmjs.org/character-parser/-/character-parser-2.2.0.tgz" @@ -1120,6 +1356,11 @@ chokidar@^3.2.2, chokidar@^3.4.0: optionalDependencies: fsevents "~2.3.1" +chrome-trace-event@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" + integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== + ci-info@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz" @@ -1210,6 +1451,11 @@ colorette@^1.2.2: resolved "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz" integrity sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w== +colorette@^2.0.14: + version "2.0.16" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.16.tgz#713b9af84fdb000139f04546bd4a93f62a5085da" + integrity sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g== + combined-stream@^1.0.6, combined-stream@~1.0.6: version "1.0.8" resolved "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz" @@ -1217,11 +1463,21 @@ combined-stream@^1.0.6, combined-stream@~1.0.6: dependencies: delayed-stream "~1.0.0" +commander@^2.20.0: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + commander@^4.0.1: version "4.1.1" resolved "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz" integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== +commander@^7.0.0, commander@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" + integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== + commondir@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz" @@ -1332,11 +1588,39 @@ create-hmac@^1.1.3: safe-buffer "^5.0.1" sha.js "^2.4.8" +cross-spawn@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + crypto-random-string@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz" integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== +css-loader@^6.6.0: + version "6.6.0" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.6.0.tgz#c792ad5510bd1712618b49381bd0310574fafbd3" + integrity sha512-FK7H2lisOixPT406s5gZM1S3l8GrfhEBT3ZiL2UX1Ng1XWs0y2GPllz/OTyvbaHe12VgQrIXIzuEGVlbUhodqg== + dependencies: + icss-utils "^5.1.0" + postcss "^8.4.5" + postcss-modules-extract-imports "^3.0.0" + postcss-modules-local-by-default "^4.0.0" + postcss-modules-scope "^3.0.0" + postcss-modules-values "^4.0.0" + postcss-value-parser "^4.2.0" + semver "^7.3.5" + +cssesc@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" + integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== + cssom@^0.4.4: version "0.4.4" resolved "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz" @@ -1551,6 +1835,11 @@ duplexer3@^0.1.4: resolved "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz" integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= +duplexer@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" + integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== + ecc-jsbn@~0.1.1: version "0.1.2" resolved "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz" @@ -1591,11 +1880,24 @@ end-of-stream@^1.1.0: dependencies: once "^1.4.0" +enhanced-resolve@^5.8.3: + version "5.9.1" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.9.1.tgz#e898cea44d9199fd92137496cff5691b910fb43e" + integrity sha512-jdyZMwCQ5Oj4c5+BTnkxPgDZO/BJzh/ADDmKebayyzNwjVX1AFCeGkOfxNx0mHi2+8BKC5VxUYiw3TIvoT7vhw== + dependencies: + graceful-fs "^4.2.4" + tapable "^2.2.0" + entities@~1.1.1: version "1.1.2" resolved "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz" integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== +envinfo@^7.7.3: + version "7.8.1" + resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.8.1.tgz#06377e3e5f4d379fea7ac592d5ad8927e0c4d475" + integrity sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw== + es-abstract@^1.18.0-next.2: version "1.18.0" resolved "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0.tgz" @@ -1618,6 +1920,11 @@ es-abstract@^1.18.0-next.2: string.prototype.trimstart "^1.0.4" unbox-primitive "^1.0.0" +es-module-lexer@^0.9.0: + version "0.9.3" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19" + integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ== + es-to-primitive@^1.2.1: version "1.2.1" resolved "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz" @@ -1664,11 +1971,31 @@ escodegen@^2.0.0: optionalDependencies: source-map "~0.6.1" +eslint-scope@5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + esprima@^4.0.1: version "4.0.1" resolved "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + estraverse@^5.2.0: version "5.2.0" resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz" @@ -1689,6 +2016,21 @@ events@^3.2.0: resolved "https://registry.npmjs.org/events/-/events-3.3.0.tgz" integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== +execa@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" + integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.0" + human-signals "^2.1.0" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.1" + onetime "^5.1.2" + signal-exit "^3.0.3" + strip-final-newline "^2.0.0" + expand-brackets@^2.1.4: version "2.1.4" resolved "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz" @@ -1798,7 +2140,7 @@ extsprintf@^1.2.0: resolved "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.0.tgz" integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= -fast-deep-equal@^3.1.1: +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== @@ -1825,6 +2167,11 @@ fast-levenshtein@~2.0.6: resolved "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= +fastest-levenshtein@^1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz#9990f7d3a88cc5a9ffd1f1745745251700d497e2" + integrity sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow== + fastq@^1.6.0: version "1.11.0" resolved "https://registry.npmjs.org/fastq/-/fastq-1.11.0.tgz" @@ -1883,6 +2230,14 @@ find-up@^3.0.0: dependencies: locate-path "^3.0.0" +find-up@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + for-in@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz" @@ -1893,6 +2248,11 @@ forever-agent@~0.6.1: resolved "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz" integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= +fork-awesome@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/fork-awesome/-/fork-awesome-1.2.0.tgz#acd43f1e1f54510fa45209c31385b4fde3a95003" + integrity sha512-MNwTBnnudMIweHfDtTY8TeR5fxIAZ2w9o8ITn5XDySqdxa4k5AH8IuAMa89RVxDxgPNlosZxqkFKN5UmHXuYSw== + form-data@~2.3.2: version "2.3.3" resolved "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz" @@ -1981,6 +2341,11 @@ get-stream@^5.1.0: dependencies: pump "^3.0.0" +get-stream@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== + get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz" @@ -2013,6 +2378,11 @@ glob-parent@^5.1.0, glob-parent@~5.1.0: dependencies: is-glob "^4.0.1" +glob-to-regexp@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" + integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== + glob@^7.0.0, glob@^7.1.3: version "7.1.6" resolved "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz" @@ -2090,6 +2460,18 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0: resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz" integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ== +graceful-fs@^4.2.4, graceful-fs@^4.2.9: + version "4.2.9" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96" + integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== + +gzip-size@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-6.0.0.tgz#065367fd50c239c0671cbcbad5be3e2eeb10e462" + integrity sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q== + dependencies: + duplexer "^0.1.2" + har-schema@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz" @@ -2238,6 +2620,11 @@ http2-wrapper@^1.0.0-beta.5.2: quick-lru "^5.1.1" resolve-alpn "^1.0.0" +human-signals@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" + integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== + iconv-lite@0.4.24: version "0.4.24" resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz" @@ -2252,6 +2639,11 @@ iconv-lite@^0.6.2: dependencies: safer-buffer ">= 2.1.2 < 3.0.0" +icss-utils@^5.0.0, icss-utils@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" + integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== + ieee754@^1.1.13: version "1.2.1" resolved "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz" @@ -2272,6 +2664,14 @@ import-lazy@^2.1.0: resolved "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz" integrity sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM= +import-local@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" + integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== + dependencies: + pkg-dir "^4.2.0" + resolve-cwd "^3.0.0" + imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz" @@ -2305,6 +2705,11 @@ ini@~1.3.0: resolved "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz" integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== +interpret@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9" + integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw== + ipaddr.js@1.9.1: version "1.9.1" resolved "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz" @@ -2389,6 +2794,13 @@ is-core-module@^2.2.0: dependencies: has "^1.0.3" +is-core-module@^2.8.1: + version "2.8.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211" + integrity sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA== + dependencies: + has "^1.0.3" + is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz" @@ -2592,6 +3004,11 @@ isarray@^2.0.1: resolved "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz" integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + isobject@^2.0.0: version "2.1.0" resolved "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz" @@ -2609,6 +3026,15 @@ isstream@~0.1.2: resolved "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz" integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= +jest-worker@^27.4.5: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" + integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== + dependencies: + "@types/node" "*" + merge-stream "^2.0.0" + supports-color "^8.0.0" + js-stringify@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/js-stringify/-/js-stringify-1.0.2.tgz" @@ -2671,6 +3097,11 @@ json-buffer@3.0.1: resolved "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz" integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== +json-parse-better-errors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" + integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== + json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz" @@ -2811,6 +3242,11 @@ linkify-it@^2.0.0: dependencies: uc.micro "^1.0.1" +loader-runner@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.2.0.tgz#d7022380d66d14c5fb1d496b89864ebcfd478384" + integrity sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw== + locate-path@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz" @@ -2819,7 +3255,14 @@ locate-path@^3.0.0: p-locate "^3.0.0" path-exists "^3.0.0" -lodash@^4.17.19, lodash@^4.17.21, lodash@^4.7.0: +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.7.0: version "4.17.21" resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -2834,6 +3277,13 @@ lowercase-keys@^2.0.0: resolved "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz" integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + ltx@^2.10.0: version "2.10.0" resolved "https://registry.npmjs.org/ltx/-/ltx-2.10.0.tgz" @@ -2910,6 +3360,11 @@ merge-options@^3.0.3: dependencies: is-plain-obj "^2.1.0" +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + merge2@^1.2.3, merge2@^1.3.0: version "1.4.1" resolved "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz" @@ -2952,6 +3407,11 @@ mime-db@1.47.0: resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.47.0.tgz" integrity sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw== +mime-db@1.51.0: + version "1.51.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.51.0.tgz#d9ff62451859b18342d960850dc3cfb77e63fb0c" + integrity sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g== + mime-types@^2.1.12, mime-types@~2.1.19, mime-types@~2.1.24: version "2.1.30" resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.30.tgz" @@ -2959,11 +3419,23 @@ mime-types@^2.1.12, mime-types@~2.1.19, mime-types@~2.1.24: dependencies: mime-db "1.47.0" +mime-types@^2.1.27: + version "2.1.34" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.34.tgz#5a712f9ec1503511a945803640fafe09d3793c24" + integrity sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A== + dependencies: + mime-db "1.51.0" + mime@1.6.0: version "1.6.0" resolved "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + mimic-response@^1.0.0, mimic-response@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz" @@ -2974,6 +3446,13 @@ mimic-response@^3.1.0: resolved "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz" integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== +mini-css-extract-plugin@^2.5.3: + version "2.5.3" + resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.5.3.tgz#c5c79f9b22ce9b4f164e9492267358dbe35376d9" + integrity sha512-YseMB8cs8U/KCaAGQoqYmfUuhhGW0a9p9XvWXrxVOkE3/IiISTLw4ALNt7JR5B2eYauFM+PQGSbXMDmVbR7Tfw== + dependencies: + schema-utils "^4.0.0" + minimalistic-assert@^1.0.0: version "1.0.1" resolved "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz" @@ -2999,6 +3478,11 @@ mixin-deep@^1.2.0: for-in "^1.0.2" is-extendable "^1.0.1" +mrmime@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/mrmime/-/mrmime-1.0.0.tgz#14d387f0585a5233d291baba339b063752a2398b" + integrity sha512-a70zx7zFfVO7XpnQ2IX1Myh9yY4UYvfld/dikWRnsXxbyvMcfz+u6UfgNAtH+k2QqtJuzVpv6eLTx1G2+WKZbQ== + ms@2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" @@ -3019,6 +3503,11 @@ ms@^2.1.1: resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== +nanoid@^3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.1.tgz#6347a18cac88af88f58af0b3594b723d5e99bb35" + integrity sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw== + nanomatch@^1.2.9: version "1.2.13" resolved "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz" @@ -3041,6 +3530,11 @@ negotiator@0.6.2: resolved "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz" integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== +neo-async@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== + node-environment-flags@^1.0.5: version "1.0.6" resolved "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.6.tgz" @@ -3111,6 +3605,13 @@ normalize-url@^4.1.0: resolved "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz" integrity sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ== +npm-run-path@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== + dependencies: + path-key "^3.0.0" + nwsapi@^2.2.0: version "2.2.0" resolved "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz" @@ -3192,6 +3693,18 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0: dependencies: wrappy "1" +onetime@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + +opener@^1.5.2: + version "1.5.2" + resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598" + integrity sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A== + openpgp@^4.10.9: version "4.10.10" resolved "https://registry.npmjs.org/openpgp/-/openpgp-4.10.10.tgz" @@ -3223,7 +3736,7 @@ p-cancelable@^2.0.0: resolved "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.0.tgz" integrity sha512-HAZyB3ZodPo+BDpb4/Iu7Jv4P6cSazBz9ZM0ChhEXp70scx834aWCEjQRwgt41UzzejUAPdbqqONfRWTPYrPAQ== -p-limit@^2.0.0: +p-limit@^2.0.0, p-limit@^2.2.0: version "2.3.0" resolved "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz" integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== @@ -3237,6 +3750,13 @@ p-locate@^3.0.0: dependencies: p-limit "^2.0.0" +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + p-try@^2.0.0: version "2.2.0" resolved "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz" @@ -3282,16 +3802,31 @@ path-exists@^3.0.0: resolved "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz" integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= +path-key@^3.0.0, path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + path-parse@^1.0.6: version "1.0.6" resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz" integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + path-to-regexp@0.1.7: version "0.1.7" resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz" @@ -3307,6 +3842,11 @@ performance-now@^2.1.0: resolved "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz" integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= +picocolors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3: version "2.2.3" resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.2.3.tgz" @@ -3331,6 +3871,13 @@ pkg-dir@^3.0.0: dependencies: find-up "^3.0.0" +pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + pngjs@^3.3.0: version "3.4.0" resolved "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz" @@ -3341,6 +3888,56 @@ posix-character-classes@^0.1.0: resolved "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz" integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= +postcss-modules-extract-imports@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz#cda1f047c0ae80c97dbe28c3e76a43b88025741d" + integrity sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw== + +postcss-modules-local-by-default@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz#ebbb54fae1598eecfdf691a02b3ff3b390a5a51c" + integrity sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ== + dependencies: + icss-utils "^5.0.0" + postcss-selector-parser "^6.0.2" + postcss-value-parser "^4.1.0" + +postcss-modules-scope@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz#9ef3151456d3bbfa120ca44898dfca6f2fa01f06" + integrity sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg== + dependencies: + postcss-selector-parser "^6.0.4" + +postcss-modules-values@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz#d7c5e7e68c3bb3c9b27cbf48ca0bb3ffb4602c9c" + integrity sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ== + dependencies: + icss-utils "^5.0.0" + +postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4: + version "6.0.9" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz#ee71c3b9ff63d9cd130838876c13a2ec1a992b2f" + integrity sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ== + dependencies: + cssesc "^3.0.0" + util-deprecate "^1.0.2" + +postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" + integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== + +postcss@^8.4.5: + version "8.4.7" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.7.tgz#f99862069ec4541de386bf57f5660a6c7a0875a8" + integrity sha512-L9Ye3r6hkkCeOETQX6iOaWZgjp3LL6Lpqm6EtgbKrgqGGteRMNb9vzBfRL96YOSu8o7x3MfIH9Mo5cPJFGrW6A== + dependencies: + nanoid "^3.3.1" + picocolors "^1.0.0" + source-map-js "^1.0.2" + prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz" @@ -3547,7 +4144,7 @@ quick-lru@^5.1.1: resolved "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz" integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== -randombytes@^2.0.1: +randombytes@^2.0.1, randombytes@^2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz" integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== @@ -3617,6 +4214,13 @@ readdirp@~3.5.0: dependencies: picomatch "^2.2.1" +rechoir@^0.7.0: + version "0.7.1" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.7.1.tgz#9478a96a1ca135b5e88fc027f03ee92d6c645686" + integrity sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg== + dependencies: + resolve "^1.9.0" + regenerator-runtime@^0.13.4: version "0.13.7" resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz" @@ -3721,6 +4325,18 @@ resolve-alpn@^1.0.0: resolved "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.1.2.tgz" integrity sha512-8OyfzhAtA32LVUsJSke3auIyINcwdh5l3cvYKdKO0nvsYSKuiLfTM5i78PJswFPT8y6cPW+L1v6/hE95chcpDA== +resolve-cwd@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" + integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== + dependencies: + resolve-from "^5.0.0" + +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + resolve-url@^0.2.1: version "0.2.1" resolved "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz" @@ -3734,6 +4350,15 @@ resolve@^1.15.1: is-core-module "^2.2.0" path-parse "^1.0.6" +resolve@^1.9.0: + version "1.22.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198" + integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw== + dependencies: + is-core-module "^2.8.1" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + responselike@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz" @@ -3827,6 +4452,25 @@ saxes@^5.0.1: dependencies: xmlchars "^2.2.0" +schema-utils@^3.1.0, schema-utils@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281" + integrity sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw== + dependencies: + "@types/json-schema" "^7.0.8" + ajv "^6.12.5" + ajv-keywords "^3.5.2" + +schema-utils@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.0.0.tgz#60331e9e3ae78ec5d16353c467c34b3a0a1d3df7" + integrity sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg== + dependencies: + "@types/json-schema" "^7.0.9" + ajv "^8.8.0" + ajv-formats "^2.1.1" + ajv-keywords "^5.0.0" + semver-diff@^3.1.1: version "3.1.1" resolved "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz" @@ -3844,6 +4488,13 @@ semver@^6.0.0, semver@^6.2.0, semver@^6.3.0: resolved "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== +semver@^7.3.5: + version "7.3.5" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" + integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== + dependencies: + lru-cache "^6.0.0" + send@0.17.1: version "0.17.1" resolved "https://registry.npmjs.org/send/-/send-0.17.1.tgz" @@ -3863,6 +4514,13 @@ send@0.17.1: range-parser "~1.2.1" statuses "~1.5.0" +serialize-javascript@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" + integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== + dependencies: + randombytes "^2.1.0" + serve-static@1.14.1: version "1.14.1" resolved "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz" @@ -3908,11 +4566,37 @@ shallow-clone@^3.0.0: dependencies: kind-of "^6.0.2" +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + signal-exit@^3.0.2: version "3.0.3" resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz" integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== +signal-exit@^3.0.3: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +sirv@^1.0.7: + version "1.0.19" + resolved "https://registry.yarnpkg.com/sirv/-/sirv-1.0.19.tgz#1d73979b38c7fe91fcba49c85280daa9c2363b49" + integrity sha512-JuLThK3TnZG1TAKDwNIqNq6QA2afLOCcm+iE8D1Kj3GA40pSPsxQjjJl0J8X3tsR7T+CP1GavpzLwYkgVLWrZQ== + dependencies: + "@polka/url" "^1.0.0-next.20" + mrmime "^1.0.0" + totalist "^1.0.0" + slash@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz" @@ -3958,6 +4642,11 @@ snapdragon@^0.8.1: source-map-resolve "^0.5.0" use "^3.1.0" +source-map-js@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" + integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== + source-map-resolve@^0.5.0: version "0.5.3" resolved "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz" @@ -3977,6 +4666,14 @@ source-map-support@^0.5.16: buffer-from "^1.0.0" source-map "^0.6.0" +source-map-support@~0.5.20: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + source-map-url@^0.4.0: version "0.4.1" resolved "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz" @@ -3987,11 +4684,16 @@ source-map@^0.5.0, source-map@^0.5.6: resolved "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz" integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= -source-map@^0.6.0, source-map@~0.6.1: +source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: version "0.6.1" resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== +source-map@~0.7.2: + version "0.7.3" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" + integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== + split-on-first@^1.0.0: version "1.1.0" resolved "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz" @@ -4117,11 +4819,21 @@ strip-ansi@^6.0.0: dependencies: ansi-regex "^5.0.0" +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz" integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= +style-loader@^3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-3.3.1.tgz#057dfa6b3d4d7c7064462830f9113ed417d38575" + integrity sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ== + supports-color@^5.3.0, supports-color@^5.5.0: version "5.5.0" resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" @@ -4136,16 +4848,54 @@ supports-color@^7.1.0: dependencies: has-flag "^4.0.0" +supports-color@^8.0.0: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + symbol-tree@^3.2.4: version "3.2.4" resolved "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz" integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== +tapable@^2.1.1, tapable@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" + integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== + term-size@^2.1.0: version "2.2.1" resolved "https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz" integrity sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg== +terser-webpack-plugin@^5.1.3: + version "5.3.1" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.1.tgz#0320dcc270ad5372c1e8993fabbd927929773e54" + integrity sha512-GvlZdT6wPQKbDNW/GDQzZFg/j4vKU96yl2q6mcUkzKOgW4gwf1Z8cZToUCrz31XHlPWH8MVb1r2tFtdDtTGJ7g== + dependencies: + jest-worker "^27.4.5" + schema-utils "^3.1.1" + serialize-javascript "^6.0.0" + source-map "^0.6.1" + terser "^5.7.2" + +terser@^5.7.2: + version "5.11.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.11.0.tgz#2da5506c02e12cd8799947f30ce9c5b760be000f" + integrity sha512-uCA9DLanzzWSsN1UirKwylhhRz3aKPInlfmpGfw8VN6jHsAtu8HJtIpeeHHK23rxnE/cDc+yvmq5wqkIC6Kn0A== + dependencies: + acorn "^8.5.0" + commander "^2.20.0" + source-map "~0.7.2" + source-map-support "~0.5.20" + to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz" @@ -4198,6 +4948,11 @@ token-stream@1.0.0: resolved "https://registry.npmjs.org/token-stream/-/token-stream-1.0.0.tgz" integrity sha1-zCAOqyYT9BZtJ/+a/HylbUnfbrQ= +totalist@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/totalist/-/totalist-1.1.0.tgz#a4d65a3e546517701e3e5c37a47a70ac97fe56df" + integrity sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g== + touch@^3.1.0: version "3.1.0" resolved "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz" @@ -4373,7 +5128,7 @@ use@^3.1.0: resolved "https://registry.npmjs.org/use/-/use-3.1.1.tgz" integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== -util-deprecate@^1.0.1, util-deprecate@~1.0.1: +util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= @@ -4438,6 +5193,14 @@ w3c-xmlserializer@^2.0.0: dependencies: xml-name-validator "^3.0.0" +watchpack@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.3.1.tgz#4200d9447b401156eeca7767ee610f8809bc9d25" + integrity sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA== + dependencies: + glob-to-regexp "^0.4.1" + graceful-fs "^4.1.2" + webidl-conversions@^5.0.0: version "5.0.0" resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz" @@ -4448,6 +5211,82 @@ webidl-conversions@^6.1.0: resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz" integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w== +webpack-bundle-analyzer@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.5.0.tgz#1b0eea2947e73528754a6f9af3e91b2b6e0f79d5" + integrity sha512-GUMZlM3SKwS8Z+CKeIFx7CVoHn3dXFcUAjT/dcZQQmfSZGvitPfMob2ipjai7ovFFqPvTqkEZ/leL4O0YOdAYQ== + dependencies: + acorn "^8.0.4" + acorn-walk "^8.0.0" + chalk "^4.1.0" + commander "^7.2.0" + gzip-size "^6.0.0" + lodash "^4.17.20" + opener "^1.5.2" + sirv "^1.0.7" + ws "^7.3.1" + +webpack-cli@^4.9.2: + version "4.9.2" + resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-4.9.2.tgz#77c1adaea020c3f9e2db8aad8ea78d235c83659d" + integrity sha512-m3/AACnBBzK/kMTcxWHcZFPrw/eQuY4Df1TxvIWfWM2x7mRqBQCqKEd96oCUa9jkapLBaFfRce33eGDb4Pr7YQ== + dependencies: + "@discoveryjs/json-ext" "^0.5.0" + "@webpack-cli/configtest" "^1.1.1" + "@webpack-cli/info" "^1.4.1" + "@webpack-cli/serve" "^1.6.1" + colorette "^2.0.14" + commander "^7.0.0" + execa "^5.0.0" + fastest-levenshtein "^1.0.12" + import-local "^3.0.2" + interpret "^2.2.0" + rechoir "^0.7.0" + webpack-merge "^5.7.3" + +webpack-merge@^5.7.3: + version "5.8.0" + resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.8.0.tgz#2b39dbf22af87776ad744c390223731d30a68f61" + integrity sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q== + dependencies: + clone-deep "^4.0.1" + wildcard "^2.0.0" + +webpack-sources@^3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" + integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== + +webpack@^5.69.1: + version "5.69.1" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.69.1.tgz#8cfd92c192c6a52c99ab00529b5a0d33aa848dc5" + integrity sha512-+VyvOSJXZMT2V5vLzOnDuMz5GxEqLk7hKWQ56YxPW/PQRUuKimPqmEIJOx8jHYeyo65pKbapbW464mvsKbaj4A== + dependencies: + "@types/eslint-scope" "^3.7.3" + "@types/estree" "^0.0.51" + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/wasm-edit" "1.11.1" + "@webassemblyjs/wasm-parser" "1.11.1" + acorn "^8.4.1" + acorn-import-assertions "^1.7.6" + browserslist "^4.14.5" + chrome-trace-event "^1.0.2" + enhanced-resolve "^5.8.3" + es-module-lexer "^0.9.0" + eslint-scope "5.1.1" + events "^3.2.0" + glob-to-regexp "^0.4.1" + graceful-fs "^4.2.9" + json-parse-better-errors "^1.0.2" + loader-runner "^4.2.0" + mime-types "^2.1.27" + neo-async "^2.6.2" + schema-utils "^3.1.0" + tapable "^2.1.1" + terser-webpack-plugin "^5.1.3" + watchpack "^2.3.1" + webpack-sources "^3.2.3" + whatwg-encoding@^1.0.5: version "1.0.5" resolved "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz" @@ -4485,6 +5324,13 @@ which-module@^2.0.0: resolved "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz" integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + widest-line@^3.1.0: version "3.1.0" resolved "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz" @@ -4492,6 +5338,11 @@ widest-line@^3.1.0: dependencies: string-width "^4.0.0" +wildcard@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.0.tgz#a77d20e5200c6faaac979e4b3aadc7b3dd7f8fec" + integrity sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw== + with@^7.0.0: version "7.0.2" resolved "https://registry.npmjs.org/with/-/with-7.0.2.tgz" @@ -4540,6 +5391,11 @@ write-file-atomic@^3.0.0: signal-exit "^3.0.2" typedarray-to-buffer "^3.1.5" +ws@^7.3.1: + version "7.5.7" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.7.tgz#9e0ac77ee50af70d58326ecff7e85eb3fa375e67" + integrity sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A== + ws@^7.4.0, ws@^7.4.4: version "7.4.5" resolved "https://registry.npmjs.org/ws/-/ws-7.4.5.tgz" @@ -4565,6 +5421,11 @@ y18n@^4.0.0: resolved "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz" integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + yargs-parser@^13.1.2: version "13.1.2" resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz"