diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 4937b8e..0000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "webui"] - path = webui - url = ../deemix-webui diff --git a/webui b/webui deleted file mode 160000 index 2d19ccc..0000000 --- a/webui +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 2d19cccebde7b212202d000e84ff51572b310d24 diff --git a/webui/.eslintrc.yml b/webui/.eslintrc.yml new file mode 100644 index 0000000..914bd5f --- /dev/null +++ b/webui/.eslintrc.yml @@ -0,0 +1,17 @@ +--- +extends: + - "@nuxtjs" + - plugin:prettier/recommended +plugins: + - "@typescript-eslint" +parserOptions: + parser: "@typescript-eslint/parser" +rules: + "@typescript-eslint/no-unused-vars": + - error + - args: all + argsIgnorePattern: ^_ + no-unused-vars: off + no-console: off + camelcase: off + vue/no-v-html: off diff --git a/webui/.gitattributes b/webui/.gitattributes new file mode 100644 index 0000000..ee783f9 --- /dev/null +++ b/webui/.gitattributes @@ -0,0 +1,148 @@ +## Source: https://github.com/ptkdev-boilerplate/node-cli-boilerplate/blob/main/.gitattributes + +## AUTO-DETECT +* text=auto + +## SOURCE CODE +*.bat text eol=crlf +*.css text eol=lf +*.html text diff=html eol=lf +*.ini text eol=crlf +*.js text eol=lf +*.json text eol=lf +*.php text diff=php eol=lf +*.py text diff=python eol=lf +*.rb text diff=ruby +*.sass text eol=lf +*.scss text eol=lf +*.sh text eol=lf +*.sql text eol=lf +*.ts text eol=lf +*.vue text eol=lf +*.svelte text eol=lf +*.xml text eol=lf +*.xhtml text diff=html eol=lf + +## DOCKER +*.dockerignore text eol=lf +Dockerfile text eol=lf + +## DOCUMENTATION +*.md text eol=lf +*.txt text eol=lf +AUTHORS text eol=lf +CHANGELOG text eol=lf +CHANGES text eol=lf +CONTRIBUTING text eol=lf +COPYING text eol=lf +INSTALL text eol=lf +license text eol=lf +LICENSE text eol=lf +NEWS text eol=lf +README text eol=lf +TODO text eol=lf + +## TEMPLATES +*.dot text eol=lf +*.tpl text eol=lf +*.twig text eol=lf + +## LINTERS +.csslintrc text eol=lf +.eslintrc text eol=lf +.htmlhintrc text eol=lf +.jscsrc text eol=lf +.jshintrc text eol=lf +.jshintignore text eol=lf +.stylelintrc text eol=lf +.npmignore text eol=lf + +## CONFIGS +*.bowerrc text eol=lf +*.cnf text eol=lf +*.conf text eol=lf +*.config text eol=lf +.babelrc text eol=lf +.browserslistrc text eol=lf +.editorconfig text eol=lf +.env text eol=lf +.gitattributes text eol=lf +.gitconfig text eol=lf +.htaccess text eol=lf +*.lock text eol=lf +*.npmignore text eol=lf +*.yaml text eol=lf +*.yml text eol=lf +browserslist text eol=lf +Makefile text eol=lf +makefile text eol=lf + +## GRAPHICS +*.ai binary +*.bmp binary +*.eps binary +*.gif binary +*.ico binary +*.jng binary +*.jp2 binary +*.jpg binary +*.jpeg binary +*.jpx binary +*.jxr binary +*.pdf binary +*.png binary +*.psb binary +*.psd binary +*.svg text +*.svgz binary +*.tif binary +*.tiff binary +*.wbmp binary +*.webp binary + +## AUDIO +*.kar binary +*.m4a binary +*.mid binary +*.midi binary +*.mp3 binary +*.ogg binary +*.ra binary + +## VIDEO +*.3gpp binary +*.3gp binary +*.as binary +*.asf binary +*.asx binary +*.fla binary +*.flv binary +*.m4v binary +*.mng binary +*.mov binary +*.mp4 binary +*.mpeg binary +*.mpg binary +*.ogv binary +*.swc binary +*.swf binary +*.webm binary + +## ARCHIVES +*.7z binary +*.gz binary +*.jar binary +*.rar binary +*.tar binary +*.zip binary + +## FONTS +*.ttf binary +*.eot binary +*.otf binary +*.woff binary +*.woff2 binary + +## EXECUTABLES +*.exe binary +*.pyc binary diff --git a/webui/.gitignore b/webui/.gitignore new file mode 100644 index 0000000..e7fbb3b --- /dev/null +++ b/webui/.gitignore @@ -0,0 +1,37 @@ +__pycache__ +*/__pycache__ + +.DS_Store +node_modules + +# pyinstaller build dirs +/dist +/build + +# local env files +/env/ +/venv/ +.env.local +.env.*.local + +# Log files +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Editor directories and files +# .vscode +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +# Private configs +/config.py +tailwind.config.full.js + +# development +*.map +public/js/bundle.js diff --git a/webui/.prettierrc.yml b/webui/.prettierrc.yml new file mode 100644 index 0000000..10839b1 --- /dev/null +++ b/webui/.prettierrc.yml @@ -0,0 +1,10 @@ +--- +useTabs: true +tabWidth: 2 +semi: false +singleQuote: true +bracketSpacing: true +trailingComma: none +printWidth: 120 +arrowParens: avoid +vueIndentScriptAndStyle: false diff --git a/webui/COMPILE-UI.md b/webui/COMPILE-UI.md new file mode 100644 index 0000000..a9e8e02 --- /dev/null +++ b/webui/COMPILE-UI.md @@ -0,0 +1,104 @@ +**NOTE: THIS FILE IS NEEDED JUST FOR DEVELOPERS OF THIS PROJECT, IF YOU AREN'T YOU CAN IGNORE IT** + +This file explains how to compile files for the WebUI. + +# What you need to do just the first time + +1. Download and install Node.js, you can download it [here](https://nodejs.org/en/download/) (also installs npm) + +2. Once you have finished to install Node.js, check if everything is ok by running in a terminal the commands + +```bash +$ node -v +``` +and then +```bash +$ npm -v +``` + +If you see the corresponding versions of node and npm, you can move onto install yarn. + +3. Install the yarn package manager by running in a terminal the command + +```bash +$ npm install -g yarn +``` + +You may want to use `sudo` with that if it gives you permission errors. + +4. Check if yarn has been installed correctly by running in a terminal the command + +```bash +$ yarn --version +``` + +If you see the version number of yarm, you are ready to code! + +5. Go to the root of this project, open your favorite terminal and run + +```bash +$ yarn install +``` + +To work on this webui you will need a working server as well. If you've downloaded this with deemix-gui you can run in a terminal positioned inside the deemix-gui folder the command + +```bash +$ yarn install-all-dev +``` + +To install all dependencies for all the modules (gui, server and webui) + +# Scripts + +## Development + +By simply running + +```bash +$ yarn dev +``` + +you will have 2 tasks running at the same time: +- the server +- the [rollup](https://rollupjs.org/guide/en/) watcher pointing to the configured `.js` file and ready to re-bundle + +Note that in development mode 1 more file (`bundle.js.map`) will be created in the public folder. This file will be deleted when running the build command, so you don't need to worry about it. + +**You can now go to http://127.0.0.1:6595 and see the app running.** + +### Editing files + +You can edit `.scss` and `.js` files and simply refresh the page to see your new code directly in the app. + +However, if you need to edit the `public/index.html` file you'll have to kill the terminal and re-run `npm run dev` to see your edits. + +### Adding files + +If you want to add new `.js` or `.vue` files, just add them. deemix uses ES6 synthax, so you'll probably need to export some functions or variables from your new file. Files that will export and import nothing will be ignored by the bundler (rollup). + +If you want to add new `.scss` (style) files, you need to import them in the main `style.scss` file. The `.scss` files **must** all start with an underscore _, except for the `style.scss` file. + +## Building + +When you want to deploy your application, you **must** run + +```bash +$ yarn build +``` + +This is necessary to get + +- a bundled `.js` file **minified** +- deleted the `.map` file + +in order to drop the final application size (we are talking about MBs, maps are heavy). + +# Other + +If you notice that another team member installed or updated one or more new packages, just run + +```bash +$ yarn install +``` + +and you will be fine. diff --git a/webui/LICENSE.txt b/webui/LICENSE.txt new file mode 100644 index 0000000..810fce6 --- /dev/null +++ b/webui/LICENSE.txt @@ -0,0 +1,621 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS diff --git a/webui/README.md b/webui/README.md new file mode 100644 index 0000000..65e4c4f --- /dev/null +++ b/webui/README.md @@ -0,0 +1,32 @@ +# deemix-webui + +This is just the WebUI for deemix, it should be used with deemix-gui or something like that. +If you are a web developer and want to contribute to this project, please read the [COMPILE-UI](COMPILE-UI.md) file. + +# "Hidden" features + +- `CTRL+SHIFT+Backspace` deletes all the search bar content +- `CTRL+F` focuses the search bar +- `CTRL+B` toggles the download bar +- `ALT+Left` goes back to the previous page, if present (like would happen in the browser) +- `ALT+Right` goes forward to the next page, if present (like would happen in the browser) +- Custom context menu: on certain elements, like download buttons or album covers, when opening the context menu, a custom one with more options will appear instead of the default one + +# Deps + +- `rollup-plugin-vue@4.2.0` is needed because of https://github.com/vuejs/rollup-plugin-vue/issues/238 + +# License + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . diff --git a/webui/babel.config.js b/webui/babel.config.js new file mode 100644 index 0000000..6b68345 --- /dev/null +++ b/webui/babel.config.js @@ -0,0 +1,7 @@ +module.exports = { + env: { + test: { + plugins: ['@babel/plugin-transform-modules-commonjs'] + } + } +} diff --git a/webui/jest.config.js b/webui/jest.config.js new file mode 100644 index 0000000..edbf306 --- /dev/null +++ b/webui/jest.config.js @@ -0,0 +1,13 @@ +module.exports = { + clearMocks: true, + roots: ['/src', '/tests'], + testEnvironment: 'node', + // preset: 'ts-jest', + setupFiles: ['dotenv/config'], + transform: { + '^.+\\.[t|j]sx?$': 'babel-jest' + }, + moduleNameMapper: { + '@/(.*)': ['/src/$1'] + } +} diff --git a/webui/package.json b/webui/package.json new file mode 100644 index 0000000..e805e9f --- /dev/null +++ b/webui/package.json @@ -0,0 +1,61 @@ +{ + "name": "deemix-webui", + "version": "1.9.3", + "scripts": { + "clean": "rimraf public/js/bundle.js public/js/bundle.temp.js public/js/bundle.js.map", + "clean-temp": "rimraf public/js/bundle.temp.js", + "build:js": "rollup -c", + "minify": "esbuild public/js/bundle.temp.js --outfile=public/js/bundle.js --minify", + "build": "npm-run-all --sequential clean build:js minify clean-temp", + "start:gui": "yarn --cwd ../ start", + "watch:server": "yarn --cwd ../server watch", + "watch:js": "rollup -c -w", + "dev": "npm-run-all --parallel watch:server watch:js", + "lint": "eslint src/**/*.{js,vue,mjs} --fix", + "lint-tests": "eslint src/**/*.js --fix", + "test": "jest", + "test-watch": "jest --watch", + "testlang": "node ./tests/testlang.js" + }, + "dependencies": { + "@rollup/plugin-alias": "3.1.5", + "@rollup/plugin-commonjs": "20.0.0", + "@rollup/plugin-node-resolve": "13.0.4", + "@rollup/plugin-replace": "3.0.0", + "@vue/composition-api": "1.0.6", + "esbuild": "0.12.19", + "flag-icon-css": "3.5.0", + "lodash-es": "4.17.21", + "npm-run-all": "4.1.5", + "postcss": "8.3.6", + "rimraf": "3.0.2", + "rollup": "2.56.1", + "rollup-plugin-analyzer": "4.0.0", + "rollup-plugin-postcss": "4.0.0", + "rollup-plugin-svg": "2.0.0", + "rollup-plugin-vue": "4.2.0", + "svg-country-flags": "1.2.10", + "tailwindcss": "1.9.6", + "toastify-js": "1.11.1", + "vue": "2.6.14", + "vue-i18n": "8.25.0", + "vue-router": "3.5.2", + "vuex": "3.6.2" + }, + "devDependencies": { + "@babel/core": "7.15.0", + "@babel/plugin-transform-modules-commonjs": "7.15.0", + "@nuxtjs/eslint-config": "6.0.1", + "@types/jest": "26.0.24", + "@typescript-eslint/eslint-plugin": "4.29.0", + "@typescript-eslint/parser": "4.29.0", + "babel-jest": "27.0.6", + "eslint": "7.32.0", + "eslint-config-prettier": "8.3.0", + "eslint-plugin-prettier": "3.4.0", + "jest": "27.0.6", + "prettier": "2.3.2", + "typescript": "4.3.5", + "vue-template-compiler": "2.6.14" + } +} diff --git a/webui/postcss.config.js b/webui/postcss.config.js new file mode 100644 index 0000000..941cff2 --- /dev/null +++ b/webui/postcss.config.js @@ -0,0 +1,6 @@ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {} + } +} diff --git a/webui/public/favicon.ico b/webui/public/favicon.ico new file mode 100644 index 0000000..7c07bf8 Binary files /dev/null and b/webui/public/favicon.ico differ diff --git a/webui/public/fonts/OpenSans/LICENSE.txt b/webui/public/fonts/OpenSans/LICENSE.txt new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/webui/public/fonts/OpenSans/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN7rgOUehpOqc.woff2 b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN7rgOUehpOqc.woff2 new file mode 100644 index 0000000..eff71c0 Binary files /dev/null and b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN7rgOUehpOqc.woff2 differ diff --git a/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN7rgOUuhp.woff2 b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN7rgOUuhp.woff2 new file mode 100644 index 0000000..3a38286 Binary files /dev/null and b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN7rgOUuhp.woff2 differ diff --git a/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN7rgOVuhpOqc.woff2 b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN7rgOVuhpOqc.woff2 new file mode 100644 index 0000000..43d5a7c Binary files /dev/null and b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN7rgOVuhpOqc.woff2 differ diff --git a/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN7rgOX-hpOqc.woff2 b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN7rgOX-hpOqc.woff2 new file mode 100644 index 0000000..baec66c Binary files /dev/null and b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN7rgOX-hpOqc.woff2 differ diff --git a/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN7rgOXOhpOqc.woff2 b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN7rgOXOhpOqc.woff2 new file mode 100644 index 0000000..c805bc0 Binary files /dev/null and b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN7rgOXOhpOqc.woff2 differ diff --git a/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN7rgOXehpOqc.woff2 b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN7rgOXehpOqc.woff2 new file mode 100644 index 0000000..ea8feb2 Binary files /dev/null and b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN7rgOXehpOqc.woff2 differ diff --git a/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN7rgOXuhpOqc.woff2 b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN7rgOXuhpOqc.woff2 new file mode 100644 index 0000000..1302cd5 Binary files /dev/null and b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN7rgOXuhpOqc.woff2 differ diff --git a/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN8rsOUehpOqc.woff2 b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN8rsOUehpOqc.woff2 new file mode 100644 index 0000000..8a419a1 Binary files /dev/null and b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN8rsOUehpOqc.woff2 differ diff --git a/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN8rsOUuhp.woff2 b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN8rsOUuhp.woff2 new file mode 100644 index 0000000..86a8a87 Binary files /dev/null and b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN8rsOUuhp.woff2 differ diff --git a/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN8rsOVuhpOqc.woff2 b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN8rsOVuhpOqc.woff2 new file mode 100644 index 0000000..9c199fd Binary files /dev/null and b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN8rsOVuhpOqc.woff2 differ diff --git a/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN8rsOX-hpOqc.woff2 b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN8rsOX-hpOqc.woff2 new file mode 100644 index 0000000..b3fa3da Binary files /dev/null and b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN8rsOX-hpOqc.woff2 differ diff --git a/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN8rsOXOhpOqc.woff2 b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN8rsOXOhpOqc.woff2 new file mode 100644 index 0000000..1476f0f Binary files /dev/null and b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN8rsOXOhpOqc.woff2 differ diff --git a/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN8rsOXehpOqc.woff2 b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN8rsOXehpOqc.woff2 new file mode 100644 index 0000000..4feeeab Binary files /dev/null and b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN8rsOXehpOqc.woff2 differ diff --git a/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN8rsOXuhpOqc.woff2 b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN8rsOXuhpOqc.woff2 new file mode 100644 index 0000000..6ec620f Binary files /dev/null and b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN8rsOXuhpOqc.woff2 differ diff --git a/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN_r8OUehpOqc.woff2 b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN_r8OUehpOqc.woff2 new file mode 100644 index 0000000..456c550 Binary files /dev/null and b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN_r8OUehpOqc.woff2 differ diff --git a/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN_r8OUuhp.woff2 b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN_r8OUuhp.woff2 new file mode 100644 index 0000000..7bf901c Binary files /dev/null and b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN_r8OUuhp.woff2 differ diff --git a/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN_r8OVuhpOqc.woff2 b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN_r8OVuhpOqc.woff2 new file mode 100644 index 0000000..d3bbaba Binary files /dev/null and b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN_r8OVuhpOqc.woff2 differ diff --git a/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN_r8OX-hpOqc.woff2 b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN_r8OX-hpOqc.woff2 new file mode 100644 index 0000000..2ea4253 Binary files /dev/null and b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN_r8OX-hpOqc.woff2 differ diff --git a/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN_r8OXOhpOqc.woff2 b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN_r8OXOhpOqc.woff2 new file mode 100644 index 0000000..1ed5f4f Binary files /dev/null and b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN_r8OXOhpOqc.woff2 differ diff --git a/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN_r8OXehpOqc.woff2 b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN_r8OXehpOqc.woff2 new file mode 100644 index 0000000..d36e95d Binary files /dev/null and b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN_r8OXehpOqc.woff2 differ diff --git a/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN_r8OXuhpOqc.woff2 b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN_r8OXuhpOqc.woff2 new file mode 100644 index 0000000..7c251dc Binary files /dev/null and b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UN_r8OXuhpOqc.woff2 differ diff --git a/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UNirkOUehpOqc.woff2 b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UNirkOUehpOqc.woff2 new file mode 100644 index 0000000..59855dc Binary files /dev/null and b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UNirkOUehpOqc.woff2 differ diff --git a/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UNirkOUuhp.woff2 b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UNirkOUuhp.woff2 new file mode 100644 index 0000000..5c5d54e Binary files /dev/null and b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UNirkOUuhp.woff2 differ diff --git a/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UNirkOVuhpOqc.woff2 b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UNirkOVuhpOqc.woff2 new file mode 100644 index 0000000..f8a4ea3 Binary files /dev/null and b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UNirkOVuhpOqc.woff2 differ diff --git a/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UNirkOX-hpOqc.woff2 b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UNirkOX-hpOqc.woff2 new file mode 100644 index 0000000..4587c68 Binary files /dev/null and b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UNirkOX-hpOqc.woff2 differ diff --git a/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UNirkOXOhpOqc.woff2 b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UNirkOXOhpOqc.woff2 new file mode 100644 index 0000000..83b1803 Binary files /dev/null and b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UNirkOXOhpOqc.woff2 differ diff --git a/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UNirkOXehpOqc.woff2 b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UNirkOXehpOqc.woff2 new file mode 100644 index 0000000..9518615 Binary files /dev/null and b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UNirkOXehpOqc.woff2 differ diff --git a/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UNirkOXuhpOqc.woff2 b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UNirkOXuhpOqc.woff2 new file mode 100644 index 0000000..9a9a5c6 Binary files /dev/null and b/webui/public/fonts/OpenSans/mem5YaGs126MiZpBA-UNirkOXuhpOqc.woff2 differ diff --git a/webui/public/fonts/OpenSans/mem6YaGs126MiZpBA-UFUK0Udc1UAw.woff2 b/webui/public/fonts/OpenSans/mem6YaGs126MiZpBA-UFUK0Udc1UAw.woff2 new file mode 100644 index 0000000..b4d9f61 Binary files /dev/null and b/webui/public/fonts/OpenSans/mem6YaGs126MiZpBA-UFUK0Udc1UAw.woff2 differ diff --git a/webui/public/fonts/OpenSans/mem6YaGs126MiZpBA-UFUK0Vdc1UAw.woff2 b/webui/public/fonts/OpenSans/mem6YaGs126MiZpBA-UFUK0Vdc1UAw.woff2 new file mode 100644 index 0000000..3426d9b Binary files /dev/null and b/webui/public/fonts/OpenSans/mem6YaGs126MiZpBA-UFUK0Vdc1UAw.woff2 differ diff --git a/webui/public/fonts/OpenSans/mem6YaGs126MiZpBA-UFUK0Wdc1UAw.woff2 b/webui/public/fonts/OpenSans/mem6YaGs126MiZpBA-UFUK0Wdc1UAw.woff2 new file mode 100644 index 0000000..e4d49fe Binary files /dev/null and b/webui/public/fonts/OpenSans/mem6YaGs126MiZpBA-UFUK0Wdc1UAw.woff2 differ diff --git a/webui/public/fonts/OpenSans/mem6YaGs126MiZpBA-UFUK0Xdc1UAw.woff2 b/webui/public/fonts/OpenSans/mem6YaGs126MiZpBA-UFUK0Xdc1UAw.woff2 new file mode 100644 index 0000000..ca1b2b1 Binary files /dev/null and b/webui/public/fonts/OpenSans/mem6YaGs126MiZpBA-UFUK0Xdc1UAw.woff2 differ diff --git a/webui/public/fonts/OpenSans/mem6YaGs126MiZpBA-UFUK0Zdc0.woff2 b/webui/public/fonts/OpenSans/mem6YaGs126MiZpBA-UFUK0Zdc0.woff2 new file mode 100644 index 0000000..10031c0 Binary files /dev/null and b/webui/public/fonts/OpenSans/mem6YaGs126MiZpBA-UFUK0Zdc0.woff2 differ diff --git a/webui/public/fonts/OpenSans/mem6YaGs126MiZpBA-UFUK0adc1UAw.woff2 b/webui/public/fonts/OpenSans/mem6YaGs126MiZpBA-UFUK0adc1UAw.woff2 new file mode 100644 index 0000000..04139ef Binary files /dev/null and b/webui/public/fonts/OpenSans/mem6YaGs126MiZpBA-UFUK0adc1UAw.woff2 differ diff --git a/webui/public/fonts/OpenSans/mem6YaGs126MiZpBA-UFUK0ddc1UAw.woff2 b/webui/public/fonts/OpenSans/mem6YaGs126MiZpBA-UFUK0ddc1UAw.woff2 new file mode 100644 index 0000000..a7b01fa Binary files /dev/null and b/webui/public/fonts/OpenSans/mem6YaGs126MiZpBA-UFUK0ddc1UAw.woff2 differ diff --git a/webui/public/fonts/OpenSans/mem8YaGs126MiZpBA-UFUZ0bbck.woff2 b/webui/public/fonts/OpenSans/mem8YaGs126MiZpBA-UFUZ0bbck.woff2 new file mode 100644 index 0000000..4c5a6f0 Binary files /dev/null and b/webui/public/fonts/OpenSans/mem8YaGs126MiZpBA-UFUZ0bbck.woff2 differ diff --git a/webui/public/fonts/OpenSans/mem8YaGs126MiZpBA-UFVZ0b.woff2 b/webui/public/fonts/OpenSans/mem8YaGs126MiZpBA-UFVZ0b.woff2 new file mode 100644 index 0000000..e9f58b7 Binary files /dev/null and b/webui/public/fonts/OpenSans/mem8YaGs126MiZpBA-UFVZ0b.woff2 differ diff --git a/webui/public/fonts/OpenSans/mem8YaGs126MiZpBA-UFVp0bbck.woff2 b/webui/public/fonts/OpenSans/mem8YaGs126MiZpBA-UFVp0bbck.woff2 new file mode 100644 index 0000000..3770a39 Binary files /dev/null and b/webui/public/fonts/OpenSans/mem8YaGs126MiZpBA-UFVp0bbck.woff2 differ diff --git a/webui/public/fonts/OpenSans/mem8YaGs126MiZpBA-UFW50bbck.woff2 b/webui/public/fonts/OpenSans/mem8YaGs126MiZpBA-UFW50bbck.woff2 new file mode 100644 index 0000000..4e74089 Binary files /dev/null and b/webui/public/fonts/OpenSans/mem8YaGs126MiZpBA-UFW50bbck.woff2 differ diff --git a/webui/public/fonts/OpenSans/mem8YaGs126MiZpBA-UFWJ0bbck.woff2 b/webui/public/fonts/OpenSans/mem8YaGs126MiZpBA-UFWJ0bbck.woff2 new file mode 100644 index 0000000..1f2f588 Binary files /dev/null and b/webui/public/fonts/OpenSans/mem8YaGs126MiZpBA-UFWJ0bbck.woff2 differ diff --git a/webui/public/fonts/OpenSans/mem8YaGs126MiZpBA-UFWZ0bbck.woff2 b/webui/public/fonts/OpenSans/mem8YaGs126MiZpBA-UFWZ0bbck.woff2 new file mode 100644 index 0000000..1675bab Binary files /dev/null and b/webui/public/fonts/OpenSans/mem8YaGs126MiZpBA-UFWZ0bbck.woff2 differ diff --git a/webui/public/fonts/OpenSans/mem8YaGs126MiZpBA-UFWp0bbck.woff2 b/webui/public/fonts/OpenSans/mem8YaGs126MiZpBA-UFWp0bbck.woff2 new file mode 100644 index 0000000..d72068a Binary files /dev/null and b/webui/public/fonts/OpenSans/mem8YaGs126MiZpBA-UFWp0bbck.woff2 differ diff --git a/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKW-U9hkIqOjjg.woff2 b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKW-U9hkIqOjjg.woff2 new file mode 100644 index 0000000..20c325d Binary files /dev/null and b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKW-U9hkIqOjjg.woff2 differ diff --git a/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKW-U9hlIqOjjg.woff2 b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKW-U9hlIqOjjg.woff2 new file mode 100644 index 0000000..7dbd8fa Binary files /dev/null and b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKW-U9hlIqOjjg.woff2 differ diff --git a/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKW-U9hmIqOjjg.woff2 b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKW-U9hmIqOjjg.woff2 new file mode 100644 index 0000000..ccb1a12 Binary files /dev/null and b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKW-U9hmIqOjjg.woff2 differ diff --git a/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKW-U9hnIqOjjg.woff2 b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKW-U9hnIqOjjg.woff2 new file mode 100644 index 0000000..aaf73e2 Binary files /dev/null and b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKW-U9hnIqOjjg.woff2 differ diff --git a/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKW-U9hoIqOjjg.woff2 b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKW-U9hoIqOjjg.woff2 new file mode 100644 index 0000000..7f0aa70 Binary files /dev/null and b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKW-U9hoIqOjjg.woff2 differ diff --git a/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKW-U9hrIqM.woff2 b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKW-U9hrIqM.woff2 new file mode 100644 index 0000000..82a1f00 Binary files /dev/null and b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKW-U9hrIqM.woff2 differ diff --git a/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKW-U9hvIqOjjg.woff2 b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKW-U9hvIqOjjg.woff2 new file mode 100644 index 0000000..3d996a8 Binary files /dev/null and b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKW-U9hvIqOjjg.woff2 differ diff --git a/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKWiUNhkIqOjjg.woff2 b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKWiUNhkIqOjjg.woff2 new file mode 100644 index 0000000..0c7ef0a Binary files /dev/null and b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKWiUNhkIqOjjg.woff2 differ diff --git a/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKWiUNhlIqOjjg.woff2 b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKWiUNhlIqOjjg.woff2 new file mode 100644 index 0000000..5b3484f Binary files /dev/null and b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKWiUNhlIqOjjg.woff2 differ diff --git a/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKWiUNhmIqOjjg.woff2 b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKWiUNhmIqOjjg.woff2 new file mode 100644 index 0000000..9854e0e Binary files /dev/null and b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKWiUNhmIqOjjg.woff2 differ diff --git a/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKWiUNhnIqOjjg.woff2 b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKWiUNhnIqOjjg.woff2 new file mode 100644 index 0000000..8a4187c Binary files /dev/null and b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKWiUNhnIqOjjg.woff2 differ diff --git a/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKWiUNhoIqOjjg.woff2 b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKWiUNhoIqOjjg.woff2 new file mode 100644 index 0000000..45362f1 Binary files /dev/null and b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKWiUNhoIqOjjg.woff2 differ diff --git a/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKWiUNhrIqM.woff2 b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKWiUNhrIqM.woff2 new file mode 100644 index 0000000..5153813 Binary files /dev/null and b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKWiUNhrIqM.woff2 differ diff --git a/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKWiUNhvIqOjjg.woff2 b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKWiUNhvIqOjjg.woff2 new file mode 100644 index 0000000..0307dec Binary files /dev/null and b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKWiUNhvIqOjjg.woff2 differ diff --git a/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKWyV9hkIqOjjg.woff2 b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKWyV9hkIqOjjg.woff2 new file mode 100644 index 0000000..35801c0 Binary files /dev/null and b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKWyV9hkIqOjjg.woff2 differ diff --git a/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKWyV9hlIqOjjg.woff2 b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKWyV9hlIqOjjg.woff2 new file mode 100644 index 0000000..8f5da52 Binary files /dev/null and b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKWyV9hlIqOjjg.woff2 differ diff --git a/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKWyV9hmIqOjjg.woff2 b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKWyV9hmIqOjjg.woff2 new file mode 100644 index 0000000..be29757 Binary files /dev/null and b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKWyV9hmIqOjjg.woff2 differ diff --git a/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKWyV9hnIqOjjg.woff2 b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKWyV9hnIqOjjg.woff2 new file mode 100644 index 0000000..ccbc460 Binary files /dev/null and b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKWyV9hnIqOjjg.woff2 differ diff --git a/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKWyV9hoIqOjjg.woff2 b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKWyV9hoIqOjjg.woff2 new file mode 100644 index 0000000..e44fa88 Binary files /dev/null and b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKWyV9hoIqOjjg.woff2 differ diff --git a/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKWyV9hrIqM.woff2 b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKWyV9hrIqM.woff2 new file mode 100644 index 0000000..6d4334e Binary files /dev/null and b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKWyV9hrIqM.woff2 differ diff --git a/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKWyV9hvIqOjjg.woff2 b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKWyV9hvIqOjjg.woff2 new file mode 100644 index 0000000..d91cb0b Binary files /dev/null and b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKWyV9hvIqOjjg.woff2 differ diff --git a/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKXGUdhkIqOjjg.woff2 b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKXGUdhkIqOjjg.woff2 new file mode 100644 index 0000000..0f28f12 Binary files /dev/null and b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKXGUdhkIqOjjg.woff2 differ diff --git a/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKXGUdhlIqOjjg.woff2 b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKXGUdhlIqOjjg.woff2 new file mode 100644 index 0000000..ccf4acb Binary files /dev/null and b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKXGUdhlIqOjjg.woff2 differ diff --git a/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKXGUdhmIqOjjg.woff2 b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKXGUdhmIqOjjg.woff2 new file mode 100644 index 0000000..1dd821c Binary files /dev/null and b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKXGUdhmIqOjjg.woff2 differ diff --git a/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKXGUdhnIqOjjg.woff2 b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKXGUdhnIqOjjg.woff2 new file mode 100644 index 0000000..c2f5b87 Binary files /dev/null and b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKXGUdhnIqOjjg.woff2 differ diff --git a/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKXGUdhoIqOjjg.woff2 b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKXGUdhoIqOjjg.woff2 new file mode 100644 index 0000000..6868066 Binary files /dev/null and b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKXGUdhoIqOjjg.woff2 differ diff --git a/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKXGUdhrIqM.woff2 b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKXGUdhrIqM.woff2 new file mode 100644 index 0000000..c2450f3 Binary files /dev/null and b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKXGUdhrIqM.woff2 differ diff --git a/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKXGUdhvIqOjjg.woff2 b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKXGUdhvIqOjjg.woff2 new file mode 100644 index 0000000..1a1fa02 Binary files /dev/null and b/webui/public/fonts/OpenSans/memnYaGs126MiZpBA-UFUKXGUdhvIqOjjg.woff2 differ diff --git a/webui/public/fonts/icons/MaterialIcons-Regular.ttf b/webui/public/fonts/icons/MaterialIcons-Regular.ttf new file mode 100644 index 0000000..be4be29 Binary files /dev/null and b/webui/public/fonts/icons/MaterialIcons-Regular.ttf differ diff --git a/webui/public/index.ejs b/webui/public/index.ejs new file mode 100644 index 0000000..58f19e5 --- /dev/null +++ b/webui/public/index.ejs @@ -0,0 +1,55 @@ + + + + + deemix + + + + + + + + +
+

+ If you're reading this it means that js/bundle.js isn't loading correctly.
+ Make sure the file is present, if not build the webui. +

+ + + + + diff --git a/webui/public/res/InfoSpotifyFeatures/ClientIdSecret.png b/webui/public/res/InfoSpotifyFeatures/ClientIdSecret.png new file mode 100644 index 0000000..82470ee Binary files /dev/null and b/webui/public/res/InfoSpotifyFeatures/ClientIdSecret.png differ diff --git a/webui/public/res/InfoSpotifyFeatures/CreateApp.png b/webui/public/res/InfoSpotifyFeatures/CreateApp.png new file mode 100644 index 0000000..78ae729 Binary files /dev/null and b/webui/public/res/InfoSpotifyFeatures/CreateApp.png differ diff --git a/webui/public/res/InfoSpotifyFeatures/CreateAppForm.png b/webui/public/res/InfoSpotifyFeatures/CreateAppForm.png new file mode 100644 index 0000000..8e749ba Binary files /dev/null and b/webui/public/res/InfoSpotifyFeatures/CreateAppForm.png differ diff --git a/webui/rollup.config.js b/webui/rollup.config.js new file mode 100644 index 0000000..6239b56 --- /dev/null +++ b/webui/rollup.config.js @@ -0,0 +1,56 @@ +import resolve from '@rollup/plugin-node-resolve' +import commonjs from '@rollup/plugin-commonjs' +import replace from '@rollup/plugin-replace' +import alias from '@rollup/plugin-alias' +import analyze from 'rollup-plugin-analyzer' +import vue from 'rollup-plugin-vue' +import svg from 'rollup-plugin-svg' +import postcss from 'rollup-plugin-postcss' + +import { version } from './package.json' + +const isProduction = !process.env.ROLLUP_WATCH +process.env.NODE_ENV = isProduction ? 'production' : 'development' + +export default { + input: 'src/app.js', + output: [ + { + file: isProduction ? 'public/js/bundle.temp.js' : 'public/js/bundle.js', + format: 'module', + sourcemap: !isProduction + } + ], + plugins: [ + alias({ + entries: [ + { + find: 'vue', + replacement: 'vue/dist/vue.esm' + }, + { + find: '@', + replacement: __dirname + '/src' + }, + { + find: '@components', + replacement: __dirname + '/src/components' + } + ] + }), + // Needed for Vue imports + replace({ + preventAssignment: true, + values: { + 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV), + __VER__: JSON.stringify(version) + } + }), + resolve(), // Tells Rollup how to find imported modules in node_modules + commonjs(), // Converts imported modules to ES modules, if necessary + svg(), + vue(), + postcss(), + isProduction && analyze({ summaryOnly: true, limit: 15 }) // Show useful information about bundles, only in production + ] +} diff --git a/webui/src/App.vue b/webui/src/App.vue new file mode 100644 index 0000000..58153fc --- /dev/null +++ b/webui/src/App.vue @@ -0,0 +1,86 @@ + + + + + diff --git a/webui/src/app.js b/webui/src/app.js new file mode 100644 index 0000000..398742d --- /dev/null +++ b/webui/src/app.js @@ -0,0 +1,275 @@ +import Vue from 'vue' + +import '@/plugins/composition-api' + +import '@/styles/vendor/material-icons.css' +import '@/styles/vendor/OpenSans.css' + +import '@/styles/css/tailwind.css' + +import '@/styles/css/normalize.css' +import '@/styles/css/base.css' +import '@/styles/css/components.css' +import '@/styles/css/helpers.css' +import '@/styles/css/icons.css' +import '@/styles/css/tables.css' +import '@/styles/css/typography.css' + +import App from '@/App.vue' +import i18n from '@/plugins/i18n' +import router from '@/router' +import store from '@/store' + +import { socket } from '@/utils/socket' +import { fetchData, postToServer } from '@/utils/api' +import { toast } from '@/utils/toasts' +import { isValidURL } from '@/utils/utils' +import { sendAddToQueue } from '@/utils/downloads' +import { SPOTIFY_STATUS } from '@/constants' + +/* ===== Random utils ===== */ + +/* eslint-disable no-extend-native */ +String.prototype.capitalize = function () { + return this.charAt(0).toUpperCase() + this.slice(1) +} +// Reset if ejs fails +if (location.base == "<%= locationBase %>") location.base = "/" + +/* ===== App initialization ===== */ +async function startApp() { + document.getElementById('missingBundle').remove() + new Vue({ + store, + router, + i18n, + render: h => h(App) + }).$mount('#app') + + const connectResponse = await fetchData('connect') + const spotifyStatus = connectResponse.spotifyEnabled ? SPOTIFY_STATUS.ENABLED : SPOTIFY_STATUS.DISABLED + + if (connectResponse.deezerAvailable === 'no-network') { + document.getElementById('deezer_not_reachable').classList.remove('hide') + } + if (connectResponse.deezerAvailable === 'no') { + document.getElementById('deezer_not_available').classList.remove('hide') + } + + store.dispatch('setAppInfo', connectResponse.update).catch(console.error) + store.dispatch('setSpotifyStatus', spotifyStatus).catch(console.error) + + let arl = localStorage.getItem('arl') + let accessToken = localStorage.getItem('accessToken') + + if (connectResponse.singleUser) { + if (connectResponse.singleUser.arl) arl = connectResponse.singleUser.arl + if (connectResponse.singleUser.accessToken) accessToken = connectResponse.singleUser.accessToken + } + + if (connectResponse.autologin) { + console.info('Autologin') + const accountNum = localStorage.getItem('accountNum') + + async function login(arl, accountNum) { + toast(i18n.t('toasts.loggingIn'), 'loading', false, 'login-toast') + arl = arl.trim() + let result + + if (accountNum !== 0) { + result = await postToServer('loginArl', { arl, force: true, child: accountNum || 0 }) + } else { + result = await postToServer('loginArl', { arl }) + } + + return result + } + + if (arl) { + let result = await login(arl, accountNum) + if (result.status === 0 && accessToken) { + const { arl: newArl } = await postToServer('loginWithCredentials', { accessToken }) + if (newArl && newArl !== arl) { + arl = newArl + store.dispatch('setARL', { arl }) + } + result = await login(newArl, accountNum) + } + loggedIn(result) + } + } else { + loggedIn({ status: 3, user: connectResponse.currentUser, arl }) + } + + if (connectResponse.checkForUpdates) { + toast(i18n.t('toasts.checkingUpdates'), 'loading', false, 'updates-toast') + const updates = await fetchData('checkForUpdates') + store.dispatch('setUpdateInfo', updates).catch(console.error) + if (updates.updateAvailable) { + toast(i18n.t('toasts.updateAvailable'), 'browser_updated', true, 'updates-toast') + } else { + toast(i18n.t('toasts.noUpdateAvailable'), 'done', true, 'updates-toast') + } + } +} + +function initClient() { + store.dispatch('setClientMode', true) + setClientModeKeyBindings() +} + +document.addEventListener('DOMContentLoaded', startApp) +if (window.api) { + initClient() +} + +/* ===== Global shortcuts ===== */ + +document.addEventListener('paste', pasteEvent => { + if (pasteEvent.target.localName === 'input') return + + let pastedText = pasteEvent.clipboardData.getData('Text') + + if (isValidURL(pastedText)) { + if (router.currentRoute.name === 'Link Analyzer') { + socket.emit('analyzeLink', pastedText) + } else { + if (pastedText.includes('\n')) pastedText = pastedText.replace(/\n/g, ';') + sendAddToQueue(pastedText) + } + } else { + const searchbar = document.querySelector('#searchbar') + searchbar.select() + searchbar.setSelectionRange(0, 99999) + } +}) + +/** + * Sets up key bindings that already work in the browser (server mode) + */ +function setClientModeKeyBindings() { + document.addEventListener('keyup', keyEvent => { + // ALT + left + if (keyEvent.altKey && keyEvent.key === 'ArrowLeft') { + router.back() + } + + // ALT + right + if (keyEvent.altKey && keyEvent.key === 'ArrowRight') { + router.forward() + } + }) +} +function loggedIn(data) { + const { status, user } = data + + switch (status) { + case 1: + case 3: + // Login ok + toast(i18n.t('toasts.loggedIn'), 'done', true, 'login-toast') + + store.dispatch('login', data) + break + case 2: + // Already logged in + toast(i18n.t('toasts.alreadyLogged'), 'done', true, 'login-toast') + + store.dispatch('setUser', user) + break + case 0: + // Login failed + toast(i18n.t('toasts.loginFailed'), 'close', true, 'login-toast') + + store.dispatch('removeARL') + break + case -1: + toast(i18n.t('toasts.deezerNotAvailable'), 'close', true, 'login-toast') + + // TODO + // $('#open_login_prompt').show() + // document.getElementById('logged_in_info').classList.add('hide') + // $('#settings_username').text('Not Logged') + // $('#settings_picture').attr('src', `https://e-cdns-images.dzcdn.net/images/user/125x125-000000-80-0-0.jpg`) + // document.getElementById('home_not_logged_in').classList.remove('hide') + } +} + +/* ===== Socketio listeners ===== */ + +// Debug messages for socketio +socket.on('message', function (msg) { + console.log(msg) +}) +socket.on('restoringQueue', function () { + toast(i18n.t('toasts.restoringQueue'), 'loading', false, 'restoring_queue') +}) + +socket.on('cancellingCurrentItem', function (uuid) { + toast(i18n.t('toasts.cancellingCurrentItem'), 'loading', false, 'cancelling_' + uuid) +}) + +socket.on('currentItemCancelled', function (uuid) { + toast(i18n.t('toasts.currentItemCancelled'), 'done', true, 'cancelling_' + uuid) +}) + +socket.on('startAddingArtist', function (data) { + toast(i18n.t('toasts.startAddingArtist', { artist: data.name }), 'loading', false, 'artist_' + data.id) +}) + +socket.on('finishAddingArtist', function (data) { + toast(i18n.t('toasts.finishAddingArtist', { artist: data.name }), 'done', true, 'artist_' + data.id) +}) + +socket.on('startConvertingSpotifyPlaylist', function (id) { + toast(i18n.t('toasts.startConvertingSpotifyPlaylist'), 'loading', false, 'spotifyplaylist_' + id) +}) + +socket.on('finishConvertingSpotifyPlaylist', function (id) { + toast(i18n.t('toasts.finishConvertingSpotifyPlaylist'), 'done', true, 'spotifyplaylist_' + id) +}) + +socket.on('errorMessage', function (error) { + toast(error, 'error') +}) + +socket.on('queueError', function (queueItem) { + if (queueItem.errid) { + toast(queueItem.link + ' - ' + i18n.t(`errors.ids.${queueItem.errid}`), 'error') + } else { + toast(queueItem.link + ' - ' + queueItem.error, 'error') + } +}) + +socket.on('alreadyInQueue', function (data) { + toast(i18n.t('toasts.alreadyInQueue', { item: data.title }), 'playlist_add_check') +}) + +socket.on('queueErrorNotLoggedIn', function () { + toast(i18n.t('toasts.loginNeededToDownload'), 'report') +}) +const bitrateLabels = { + 15: '360 HQ', + 14: '360 MQ', + 13: '360 LQ', + 9: 'FLAC', + 3: '320kbps', + 1: '128kbps', + 8: '128kbps', + 0: 'MP3' +} +socket.on('queueErrorCantStream', function (bitrate) { + toast(i18n.t('toasts.queueErrorCantStream', {bitrate: bitrateLabels[bitrate]}), 'report') +}) + +socket.on('startGeneratingItems', function (data) { + toast(i18n.t('toasts.startGeneratingItems', { n: data.total }), 'loading', false, 'batch_' + data.uuid) +}) + +socket.on('finishGeneratingItems', function (data) { + toast(i18n.t('toasts.finishGeneratingItems', { n: data.total }), 'done', true, 'batch_' + data.uuid) +}) +socket.on('toast', data => { + const { msg, icon, dismiss, id } = data + toast(msg, icon || null, dismiss !== undefined ? dismiss : true, id || null) +}) diff --git a/webui/src/assets/ar.svg b/webui/src/assets/ar.svg new file mode 100644 index 0000000..3767090 --- /dev/null +++ b/webui/src/assets/ar.svg @@ -0,0 +1,914 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/webui/src/assets/deemix-icon.svg b/webui/src/assets/deemix-icon.svg new file mode 100644 index 0000000..d45054e --- /dev/null +++ b/webui/src/assets/deemix-icon.svg @@ -0,0 +1,240 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/webui/src/assets/paypal.svg b/webui/src/assets/paypal.svg new file mode 100644 index 0000000..d698dfa --- /dev/null +++ b/webui/src/assets/paypal.svg @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/webui/src/components/TheContent.vue b/webui/src/components/TheContent.vue new file mode 100644 index 0000000..1d1b406 --- /dev/null +++ b/webui/src/components/TheContent.vue @@ -0,0 +1,107 @@ + + + + + diff --git a/webui/src/components/TheSearchBar.vue b/webui/src/components/TheSearchBar.vue new file mode 100644 index 0000000..13a10b0 --- /dev/null +++ b/webui/src/components/TheSearchBar.vue @@ -0,0 +1,250 @@ + + + + + diff --git a/webui/src/components/TheSidebar.vue b/webui/src/components/TheSidebar.vue new file mode 100644 index 0000000..4bd7534 --- /dev/null +++ b/webui/src/components/TheSidebar.vue @@ -0,0 +1,142 @@ + + + + + diff --git a/webui/src/components/downloads/QueueItem.vue b/webui/src/components/downloads/QueueItem.vue new file mode 100644 index 0000000..fbe67a5 --- /dev/null +++ b/webui/src/components/downloads/QueueItem.vue @@ -0,0 +1,348 @@ + + + + + diff --git a/webui/src/components/downloads/TheDownloadBar.vue b/webui/src/components/downloads/TheDownloadBar.vue new file mode 100644 index 0000000..3fe8ff3 --- /dev/null +++ b/webui/src/components/downloads/TheDownloadBar.vue @@ -0,0 +1,441 @@ + + + + + diff --git a/webui/src/components/globals/BackButton.vue b/webui/src/components/globals/BackButton.vue new file mode 100644 index 0000000..f3dfb9f --- /dev/null +++ b/webui/src/components/globals/BackButton.vue @@ -0,0 +1,14 @@ + + + diff --git a/webui/src/components/globals/BaseAccordion.vue b/webui/src/components/globals/BaseAccordion.vue new file mode 100644 index 0000000..01d2868 --- /dev/null +++ b/webui/src/components/globals/BaseAccordion.vue @@ -0,0 +1,33 @@ + + + + + diff --git a/webui/src/components/globals/BaseLoadingPlaceholder.vue b/webui/src/components/globals/BaseLoadingPlaceholder.vue new file mode 100644 index 0000000..e959789 --- /dev/null +++ b/webui/src/components/globals/BaseLoadingPlaceholder.vue @@ -0,0 +1,56 @@ + + + diff --git a/webui/src/components/globals/BaseTabs.js b/webui/src/components/globals/BaseTabs.js new file mode 100644 index 0000000..981d7c9 --- /dev/null +++ b/webui/src/components/globals/BaseTabs.js @@ -0,0 +1,34 @@ +/* eslint-disable vue/one-component-per-file */ +import { defineComponent } from '@vue/composition-api' + +// https://vuejs.org/v2/guide/render-function.html +// https://vuejs.org/v2/guide/render-function.html#createElement-Arguments +export const BaseTab = defineComponent({ + name: 'BaseTab', + functional: true, + render(h, ctx) { + return h( + 'li', + { + class: [ctx.data.class, 'section-tabs__tab', 'uppercase-first-letter'], + on: ctx.data.on + }, + ctx.slots().default + ) + } +}) + +export const BaseTabs = defineComponent({ + name: 'BaseTabs', + functional: true, + render(h, ctx) { + return h( + 'ul', + { + class: [ctx.data.class, 'my-8', 'section-tabs'], + on: ctx.data.on + }, + ctx.slots().default + ) + } +}) diff --git a/webui/src/components/globals/ConfirmModal.vue b/webui/src/components/globals/ConfirmModal.vue new file mode 100644 index 0000000..fae1151 --- /dev/null +++ b/webui/src/components/globals/ConfirmModal.vue @@ -0,0 +1,86 @@ + + + + + diff --git a/webui/src/components/globals/CoverContainer.vue b/webui/src/components/globals/CoverContainer.vue new file mode 100644 index 0000000..f4a2459 --- /dev/null +++ b/webui/src/components/globals/CoverContainer.vue @@ -0,0 +1,81 @@ + + + + + diff --git a/webui/src/components/globals/DeezerWarning.vue b/webui/src/components/globals/DeezerWarning.vue new file mode 100644 index 0000000..cdcd564 --- /dev/null +++ b/webui/src/components/globals/DeezerWarning.vue @@ -0,0 +1,34 @@ + + + diff --git a/webui/src/components/globals/PreviewControls.vue b/webui/src/components/globals/PreviewControls.vue new file mode 100644 index 0000000..6b7c50f --- /dev/null +++ b/webui/src/components/globals/PreviewControls.vue @@ -0,0 +1,21 @@ + + + diff --git a/webui/src/components/globals/TheContextMenu.vue b/webui/src/components/globals/TheContextMenu.vue new file mode 100644 index 0000000..de6adf0 --- /dev/null +++ b/webui/src/components/globals/TheContextMenu.vue @@ -0,0 +1,308 @@ + + + + + diff --git a/webui/src/components/globals/TheQualityModal.vue b/webui/src/components/globals/TheQualityModal.vue new file mode 100644 index 0000000..c34f3fe --- /dev/null +++ b/webui/src/components/globals/TheQualityModal.vue @@ -0,0 +1,105 @@ + + + + + diff --git a/webui/src/components/globals/TheTrackPreview.vue b/webui/src/components/globals/TheTrackPreview.vue new file mode 100644 index 0000000..c731e99 --- /dev/null +++ b/webui/src/components/globals/TheTrackPreview.vue @@ -0,0 +1,163 @@ + + + diff --git a/webui/src/components/pages/About.vue b/webui/src/components/pages/About.vue new file mode 100644 index 0000000..52b7776 --- /dev/null +++ b/webui/src/components/pages/About.vue @@ -0,0 +1,263 @@ + + + + + diff --git a/webui/src/components/pages/Artist.vue b/webui/src/components/pages/Artist.vue new file mode 100644 index 0000000..b9f37f8 --- /dev/null +++ b/webui/src/components/pages/Artist.vue @@ -0,0 +1,203 @@ + + + diff --git a/webui/src/components/pages/Charts.vue b/webui/src/components/pages/Charts.vue new file mode 100644 index 0000000..62ab262 --- /dev/null +++ b/webui/src/components/pages/Charts.vue @@ -0,0 +1,185 @@ + + + diff --git a/webui/src/components/pages/Errors.vue b/webui/src/components/pages/Errors.vue new file mode 100644 index 0000000..0dd3573 --- /dev/null +++ b/webui/src/components/pages/Errors.vue @@ -0,0 +1,83 @@ + + + + + diff --git a/webui/src/components/pages/Favorites.vue b/webui/src/components/pages/Favorites.vue new file mode 100644 index 0000000..7b1cf09 --- /dev/null +++ b/webui/src/components/pages/Favorites.vue @@ -0,0 +1,316 @@ + + + diff --git a/webui/src/components/pages/Home.vue b/webui/src/components/pages/Home.vue new file mode 100644 index 0000000..18770de --- /dev/null +++ b/webui/src/components/pages/Home.vue @@ -0,0 +1,109 @@ + + + + + diff --git a/webui/src/components/pages/InfoArl.vue b/webui/src/components/pages/InfoArl.vue new file mode 100644 index 0000000..306ab55 --- /dev/null +++ b/webui/src/components/pages/InfoArl.vue @@ -0,0 +1,58 @@ + + + diff --git a/webui/src/components/pages/InfoSpotifyFeatures.vue b/webui/src/components/pages/InfoSpotifyFeatures.vue new file mode 100644 index 0000000..9e5bbdf --- /dev/null +++ b/webui/src/components/pages/InfoSpotifyFeatures.vue @@ -0,0 +1,44 @@ + + + + + diff --git a/webui/src/components/pages/LinkAnalyzer.vue b/webui/src/components/pages/LinkAnalyzer.vue new file mode 100644 index 0000000..774ac36 --- /dev/null +++ b/webui/src/components/pages/LinkAnalyzer.vue @@ -0,0 +1,262 @@ + + + + + diff --git a/webui/src/components/pages/Search.vue b/webui/src/components/pages/Search.vue new file mode 100644 index 0000000..61601bd --- /dev/null +++ b/webui/src/components/pages/Search.vue @@ -0,0 +1,312 @@ + + + + + diff --git a/webui/src/components/pages/Settings.vue b/webui/src/components/pages/Settings.vue new file mode 100644 index 0000000..5c483f2 --- /dev/null +++ b/webui/src/components/pages/Settings.vue @@ -0,0 +1,1175 @@ + + + + + diff --git a/webui/src/components/pages/Tracklist.vue b/webui/src/components/pages/Tracklist.vue new file mode 100644 index 0000000..8893ebf --- /dev/null +++ b/webui/src/components/pages/Tracklist.vue @@ -0,0 +1,310 @@ + + + diff --git a/webui/src/components/search/ResultsAlbums.vue b/webui/src/components/search/ResultsAlbums.vue new file mode 100644 index 0000000..98c4166 --- /dev/null +++ b/webui/src/components/search/ResultsAlbums.vue @@ -0,0 +1,85 @@ + + + diff --git a/webui/src/components/search/ResultsAll.vue b/webui/src/components/search/ResultsAll.vue new file mode 100644 index 0000000..d096f5e --- /dev/null +++ b/webui/src/components/search/ResultsAll.vue @@ -0,0 +1,122 @@ + + + diff --git a/webui/src/components/search/ResultsArtists.vue b/webui/src/components/search/ResultsArtists.vue new file mode 100644 index 0000000..6f48b80 --- /dev/null +++ b/webui/src/components/search/ResultsArtists.vue @@ -0,0 +1,73 @@ + + + diff --git a/webui/src/components/search/ResultsError.vue b/webui/src/components/search/ResultsError.vue new file mode 100644 index 0000000..088f9c8 --- /dev/null +++ b/webui/src/components/search/ResultsError.vue @@ -0,0 +1,17 @@ + + + diff --git a/webui/src/components/search/ResultsPlaylists.vue b/webui/src/components/search/ResultsPlaylists.vue new file mode 100644 index 0000000..2e45859 --- /dev/null +++ b/webui/src/components/search/ResultsPlaylists.vue @@ -0,0 +1,78 @@ + + + diff --git a/webui/src/components/search/ResultsTracks.vue b/webui/src/components/search/ResultsTracks.vue new file mode 100644 index 0000000..807b7f1 --- /dev/null +++ b/webui/src/components/search/ResultsTracks.vue @@ -0,0 +1,142 @@ + + + diff --git a/webui/src/components/search/TopResult.vue b/webui/src/components/search/TopResult.vue new file mode 100644 index 0000000..86a2069 --- /dev/null +++ b/webui/src/components/search/TopResult.vue @@ -0,0 +1,63 @@ + + + diff --git a/webui/src/components/settings/TemplateVariablesList.vue b/webui/src/components/settings/TemplateVariablesList.vue new file mode 100644 index 0000000..1ac81ee --- /dev/null +++ b/webui/src/components/settings/TemplateVariablesList.vue @@ -0,0 +1,32 @@ + + + diff --git a/webui/src/constants.js b/webui/src/constants.js new file mode 100644 index 0000000..c4f6134 --- /dev/null +++ b/webui/src/constants.js @@ -0,0 +1,4 @@ +export const SPOTIFY_STATUS = { + DISABLED: 'DISABLED', + ENABLED: 'ENABLED' +} diff --git a/webui/src/data/artist.js b/webui/src/data/artist.js new file mode 100644 index 0000000..ee3ca1f --- /dev/null +++ b/webui/src/data/artist.js @@ -0,0 +1,43 @@ +import { getPropertyWithFallback } from '@/utils/utils' +import { fetchData } from '@/utils/api' + +export function formatArtistData(artistData) { + return { + artistName: getPropertyWithFallback(artistData, 'name'), + artistPictureXL: getPropertyWithFallback(artistData, 'picture_xl'), + artistReleases: formatArtistReleases(getPropertyWithFallback(artistData, 'releases')) + } +} + +function formatArtistReleases(artistReleases) { + const formattedReleases = {} + + for (const releaseType in artistReleases) { + if (artistReleases.hasOwnProperty(releaseType)) { + const releases = artistReleases[releaseType] + formattedReleases[releaseType] = [] + + for (const release of releases) { + formattedReleases[releaseType].push({ + releaseID: getPropertyWithFallback(release, 'id'), + releaseCover: getPropertyWithFallback(release, 'cover_small'), + releaseTitle: getPropertyWithFallback(release, 'title'), + releaseDate: getPropertyWithFallback(release, 'release_date'), + releaseTracksNumber: getPropertyWithFallback(release, 'nb_tracks'), + releaseLink: getPropertyWithFallback(release, 'link'), + releaseType: getPropertyWithFallback(release, 'record_type'), + isReleaseExplicit: getPropertyWithFallback(release, 'explicit_lyrics') + }) + } + } + } + + return formattedReleases +} + +export function getArtistData(artistID) { + return fetchData('getTracklist', { + type: 'artist', + id: artistID + }) +} diff --git a/webui/src/data/charts.js b/webui/src/data/charts.js new file mode 100644 index 0000000..62ff84b --- /dev/null +++ b/webui/src/data/charts.js @@ -0,0 +1,9 @@ +import { fetchData } from '@/utils/api' + +export function getChartsData() { + return fetchData('getCharts') +} + +export function getChartTracks(chartId) { + return fetchData('getChartTracks', { id: chartId }) +} diff --git a/webui/src/data/file-templates.js b/webui/src/data/file-templates.js new file mode 100644 index 0000000..4a17deb --- /dev/null +++ b/webui/src/data/file-templates.js @@ -0,0 +1,62 @@ +// TODO: Use JSON + +export const trackTemplateVariables = [ + '%title%', + '%artist%', + '%artists%', + '%allartists%', + '%mainartists%', + '%featartists%', + '%album%', + '%albumartist%', + '%tracknumber%', + '%tracktotal%', + '%discnumber%', + '%disctotal%', + '%genre%', + '%year%', + '%date%', + '%bpm%', + '%label%', + '%isrc%', + '%upc%', + '%explicit%', + '%track_id%', + '%album_id%', + '%artist_id%', + '%playlist_id%', + '%position%' +] + +export const albumFolderTemplateVariables = [ + '%album_id%', + '%genre%', + '%album%', + '%artist%', + '%artist_id%', + '%root_artist%', + '%root_artist_id%', + '%tracktotal%', + '%disctotal%', + '%type%', + '%upc%', + '%explicit%', + '%label%', + '%year%', + '%date%', + '%bitrate%' +] + +export const artistFolderTemplateVariables = ['%artist%', '%artist_id%', '%root_artist%', '%root_artist_id%'] + +export const playlistFolderTemplateVariables = [ + '%playlist%', + '%playlist_id%', + '%owner%', + '%owner_id%', + '%year%', + '%date%', + '%explicit%' +] + +export const playlistFilenameTemplateVariables = ['%title%', '%artist%', '%size%', '%type%', '%id%', '%bitrate%'] diff --git a/webui/src/data/home.js b/webui/src/data/home.js new file mode 100644 index 0000000..fe9e33b --- /dev/null +++ b/webui/src/data/home.js @@ -0,0 +1,17 @@ +import { fetchData } from '@/utils/api' + +let homeData = {} +let cached = false + +export async function getHomeData() { + if (cached) { + return homeData + } else { + const data = await fetchData('getHome') + + homeData = data + cached = true + + return data + } +} diff --git a/webui/src/data/qualities.js b/webui/src/data/qualities.js new file mode 100644 index 0000000..322e09d --- /dev/null +++ b/webui/src/data/qualities.js @@ -0,0 +1,32 @@ +export const downloadQualities = [ + { + objName: 'flac', + label: 'FLAC', + value: 9 + }, + { + objName: '320kbps', + label: 'MP3 320kbps', + value: 3 + }, + { + objName: '128kbps', + label: 'MP3 128kbps', + value: 1 + }, + { + objName: 'realityAudioHQ', + label: '360 Reality Audio [HQ]', + value: 15 + }, + { + objName: 'realityAudioMQ', + label: '360 Reality Audio [MQ]', + value: 14 + }, + { + objName: 'realityAudioLQ', + label: '360 Reality Audio [LQ]', + value: 13 + } +] diff --git a/webui/src/data/search.js b/webui/src/data/search.js new file mode 100644 index 0000000..ce8dc9d --- /dev/null +++ b/webui/src/data/search.js @@ -0,0 +1,111 @@ +import { getPropertyWithFallback } from '@/utils/utils' + +/** + * @typedef {object} FormattedSearchResult + * @property {FormattedData} data + * @property {boolean} hasLoaded + */ + +/** + * @typedef {object} FormattedData + */ + +/** + * @typedef {function} Formatter + * @returns {FormattedData} formattedData + */ + +/** + * @param {FormattedData} track + */ +export function formatSingleTrack(track) { + let isTrackExplicit = getPropertyWithFallback(track, 'explicit_lyrics', 'EXPLICIT_LYRICS') + + if (typeof isTrackExplicit === 'string') { + isTrackExplicit = isTrackExplicit !== '0' + } + + return { + /* Track */ + trackTitle: getPropertyWithFallback(track, 'title', 'SNG_TITLE'), + trackTitleVersion: getPropertyWithFallback(track, 'title_version', 'VERSION'), + trackPreview: getPropertyWithFallback(track, 'preview', 'MEDIA.0.HREF'), + trackDuration: getPropertyWithFallback(track, 'duration', 'DURATION'), + trackLink: getPropertyWithFallback(track, 'link') || `https://www.deezer.com/track/${track.SNG_ID}`, + isTrackExplicit, + + /* Artist */ + artistID: getPropertyWithFallback(track, 'artist.id', 'ART_ID'), + artistName: getPropertyWithFallback(track, 'artist.name', 'ART_NAME'), + + /* Album */ + albumID: getPropertyWithFallback(track, 'album.id', 'ALB_ID'), + albumTitle: getPropertyWithFallback(track, 'album.title', 'ALB_TITLE'), + albumPicture: + getPropertyWithFallback(track, 'album.cover_small') || + `https://e-cdns-images.dzcdn.net/images/cover/${track.ALB_PICTURE}/56x56-000000-80-0-0.jpg` + } +} + +export function formatAlbums(album) { + let isAlbumExplicit = getPropertyWithFallback( + album, + 'explicit_lyrics', + 'EXPLICIT_ALBUM_CONTENT.EXPLICIT_LYRICS_STATUS' + ) + + if (typeof isAlbumExplicit === 'number') { + isAlbumExplicit = isAlbumExplicit === 1 + } + + return { + /* Album */ + albumID: getPropertyWithFallback(album, 'id', 'ALB_ID'), + albumTitle: getPropertyWithFallback(album, 'title', 'ALB_TITLE'), + albumCoverMedium: + getPropertyWithFallback(album, 'cover_medium') || + `https://e-cdns-images.dzcdn.net/images/cover/${album.ALB_PICTURE}/156x156-000000-80-0-0.jpg`, + albumLink: getPropertyWithFallback(album, 'link') || `https://deezer.com/album/${album.ALB_ID}`, + albumTracks: getPropertyWithFallback(album, 'nb_tracks', 'NUMBER_TRACK'), + isAlbumExplicit, + + /* Artist */ + artistName: getPropertyWithFallback(album, 'artist.name', 'ART_NAME') + } +} + +export function formatArtist(artist) { + return { + /* Artist */ + artistID: getPropertyWithFallback(artist, 'id', 'ART_ID'), + artistName: getPropertyWithFallback(artist, 'name', 'ART_NAME'), + artistPictureMedium: + getPropertyWithFallback(artist, 'picture_medium') || + `https://e-cdns-images.dzcdn.net/images/artist/${artist.ART_PICTURE}/156x156-000000-80-0-0.jpg`, + artistLink: getPropertyWithFallback(artist, 'link') || `https://deezer.com/artist/${artist.ART_ID}`, + // TODO Fix + artistAlbumsNumber: getPropertyWithFallback(artist, 'nb_album', 'NB_FAN') + } +} + +export function formatPlaylist(playlist) { + return { + /* Playlist */ + playlistID: getPropertyWithFallback(playlist, 'id', 'PLAYLIST_ID'), + playlistTitle: getPropertyWithFallback(playlist, 'title', 'TITLE'), + playlistPictureMedium: + getPropertyWithFallback(playlist, 'picture_medium') || + `https://e-cdns-images.dzcdn.net/images/${playlist.PICTURE_TYPE}/${playlist.PLAYLIST_PICTURE}/156x156-000000-80-0-0.jpg`, + playlistLink: getPropertyWithFallback(playlist, 'link') || `https://deezer.com/playlist/${playlist.PLAYLIST_ID}`, + playlistTracksNumber: getPropertyWithFallback(playlist, 'nb_tracks', 'NB_SONG'), + + /* Artist */ + artistName: getPropertyWithFallback(playlist, 'user.name', 'PARENT_USERNAME') + } +} + +export function formatTitle(track) { + const hasTitleVersion = track.trackTitleVersion && !track.trackTitle.includes(track.trackTitleVersion) + + return `${track.trackTitle}${hasTitleVersion ? ` ${track.trackTitleVersion}` : ''}` +} diff --git a/webui/src/data/settings.js b/webui/src/data/settings.js new file mode 100644 index 0000000..5b33e6a --- /dev/null +++ b/webui/src/data/settings.js @@ -0,0 +1,57 @@ +import { fetchData } from '@/utils/api' + +let settingsData = {} +let defaultSettingsData = {} +let spotifyCredentials = {} + +export async function getSettingsData() { + const data = await fetchData('getSettings') + const { settings, defaultSettings, spotifySettings } = data + settingsData = settings + defaultSettingsData = defaultSettings + spotifyCredentials = spotifySettings || {} + + return { settingsData, defaultSettingsData, spotifyCredentials } +} + +/** + * @returns {number} + */ +export function getInitialPreviewVolume() { + let volume = parseInt(localStorage.getItem('previewVolume')) + + if (isNaN(volume)) { + volume = 80 // Default + localStorage.setItem('previewVolume', volume.toString()) + } + + return volume +} + +/** + * @returns {boolean} + */ +export function checkInitialSlimDownloads() { + return localStorage.getItem('slimDownloads') === 'true' +} + +/** + * @returns {boolean} + */ +export function checkInitialSlimSidebar() { + return localStorage.getItem('slimSidebar') === 'true' +} + +/** + * @returns {boolean} + */ +export function checkInitialShowBitrateTags() { + return localStorage.getItem('showBitrateTags') === 'true' +} + +/** + * @returns {boolean} + */ +export function checkInitialShowSearchButton() { + return localStorage.getItem('showSearchButton') === 'true' +} diff --git a/webui/src/data/sidebar.js b/webui/src/data/sidebar.js new file mode 100644 index 0000000..2dacfbb --- /dev/null +++ b/webui/src/data/sidebar.js @@ -0,0 +1,51 @@ +export const links = [ + { + name: 'home', + ariaLabel: 'home', + routerName: 'Home', + icon: 'home', + label: 'sidebar.home' + }, + { + name: 'search', + ariaLabel: 'search', + routerName: 'Search', + icon: 'search', + label: 'sidebar.search' + }, + { + name: 'charts', + ariaLabel: 'charts', + routerName: 'Charts', + icon: 'show_chart', + label: 'sidebar.charts' + }, + { + name: 'favorites', + ariaLabel: 'favorites', + routerName: 'Favorites', + icon: 'star', + label: 'sidebar.favorites' + }, + { + name: 'analyzer', + ariaLabel: 'link analyzer', + routerName: 'Link Analyzer', + icon: 'link', + label: 'sidebar.linkAnalyzer' + }, + { + name: 'settings', + ariaLabel: 'settings', + routerName: 'Settings', + icon: 'settings', + label: 'sidebar.settings' + }, + { + name: 'about', + ariaLabel: 'info', + routerName: 'About', + icon: 'info', + label: 'sidebar.about' + } +] diff --git a/webui/src/data/standardize.js b/webui/src/data/standardize.js new file mode 100644 index 0000000..b95e03c --- /dev/null +++ b/webui/src/data/standardize.js @@ -0,0 +1,20 @@ +export function standardizeData(rawObj, formatFunc) { + if (!rawObj.hasLoaded) { + return null + } else { + const { data: rawData } = rawObj + const formattedData = [] + + for (const dataElement of rawData) { + const formatted = formatFunc(dataElement) + + formattedData.push(formatted) + } + + return { + data: formattedData, + hasLoaded: rawObj.hasLoaded, + error: rawObj.error + } + } +} diff --git a/webui/src/jsconfig.json b/webui/src/jsconfig.json new file mode 100644 index 0000000..fb488da --- /dev/null +++ b/webui/src/jsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "checkJs": true, + "baseUrl": ".", + "paths": { + "@/*": ["./*"], + "@components/*": ["./components/*"] + } + }, + "exclude": ["assets/**/*", "styles/**/*"] +} diff --git a/webui/src/lang/ar.mjs b/webui/src/lang/ar.mjs new file mode 100644 index 0000000..2b370f3 --- /dev/null +++ b/webui/src/lang/ar.mjs @@ -0,0 +1,337 @@ +const ar = { + globals: { + welcome: 'مرحبأ بك في ديمكس', + back: 'رجوع', + loading: 'جار التحميل', + download: 'تحميل {thing}', + by: 'بواسطة {artist}', + in: 'في {album}', + download_hint: 'تحميل', + play_hint: 'تشغيل', + toggle_download_tab_hint: 'عرض/اخفاء', + clean_queue_hint: 'تم المسح', + cancel_queue_hint: 'الغاء الكل', + listTabs: { + empty: '', + all: 'الكل', + top_result: 'افضل النتائج', + album: 'البوم | البومات', + artist: 'فنان | فنانون', + single: 'اغنية | اغنية', + title: 'عنوان | عناوين', + track: 'مقطع | مقاطع', + trackN: '0 مقاطع | {n} مقطع | {n} مقطع', + releaseN: '0 اصدار | {n} اصدار | {n} اصدار', + playlist: 'قائمة تشغيل | قوائم تشغيل', + compile: 'مجموعة | مجموعات', + ep: 'ep | eps', + spotifyPlaylist: 'قائمة تشغيل سبوتفاي | قوائم تشغيل سبوتفاي', + releaseDate: 'تاريخ الاصدار', + error: 'خطأ' + } + }, + about: { + titles: { + usefulLinks: 'روابط مهمة', + bugReports: 'ابلاغ عن مشكلة', + contributing: 'مساهمة', + donations: 'التبرع', + license: 'الرخصة' + }, + subtitles: { + bugReports: 'هل هناك شيء لا يعمل في ديمكس؟ أخبرنا', + contributing: 'تريد المساهمة في هذا المشروع؟ يمكنك القيام بذلك بعدة طرق', + donations: 'تريد المساهمة مادياً؟ يمكنك التبرع' + }, + usesLibrary: + 'هذا البرنامج يستخدم مكتبة ديمكس والتي يمكنك استخدامها لإنشاء واجهة مستخدم خاصة بك لديمكس.', + thanks: `شكرا لـ rtonno, و uhwot و lollilol لمساعدتي في هذا المشروع و لـ BasCurtiz لصنع الايقونة.`, + officialWebsite: 'الموقع الرسمي', + officialRepo: 'مستودع المكتبة الرسمي', + officialWebuiRepo: 'مستودع واجهة الويب الرسمي', + officialSubreddit: 'السب ريدت الرسمي', + newsChannel: 'قناة الاخبار', + beforeReporting: `قبل ان تبلغ عن خطأ، تأكد من أنك تشغل أحدث إصدار من التطبيق وأن ما تريد الإبلاغ عنه هو في الواقع خطأ وليس مشكلة من جهتك.`, + beSure: `تأكد من أن الخطأ يمكن إعادة إنتاجه على أجهزة أخرى و ايضاً لا تبلغ علة خطأ تم التبليغ عنه سابقاً.`, + duplicateReports: 'سيتم إغلاق تقارير الأخطاء المكررة ، لذلك ترقب ذلك.', + dontOpenIssues: `DO NOT open issues for asking questions, there is a subreddit for that.`, + acceptFeatures: `أقبل اقتراحات الميزات أيضًا ، ولكن لا أشياء معقدة ، فقط اشياء يمكنني تنفيذها مباشرة في التطبيق وليس في المكتبة.`, + otherLanguages: `إذا كنت تجيد لغة برمجة أخرى ، يمكنك محاولة تحويل ديمكس إلى لغات برمجة أخرى!`, + understandingCode: `أنت بحاجة إلى مساعدة في فهم الكود؟ فقط اتصل بـ RemixDev على تيليكرام او ريديت.`, + itsFree: `يجب ان تتذكر ان هذا هو مشروع مجاني و عليك دعم الفنانين المفضلين لك قبل ان تدعم مطورين البرنامج.`, + notObligated: `لا تشعر بالالتزام بالتبرع ، لكني أقدر ذلك على أي حال!` + }, + charts: { + title: 'قائمة الجداول', + changeCountry: 'تغيير الدولة', + download: 'تحميل قائمة الجدول' + }, + errors: { + title: 'خطأ في {name}', + ids: { + invalidURL: 'الرابط غير صحيح', + unsupportedURL: 'الرابط غير متاح حتى الانً', + ISRCnotOnDeezer: 'رمز المقطع غير متوفر في ديزر', + notYourPrivatePlaylist: 'لا يمكنك تحميل قوائم التشغيل الخاصة و المخفية.', + spotifyDisabled: 'لم يتم اعداد ميزات سبوتفاي بالطرقة الصحيحة .', + trackNotOnDeezer: 'المقطع لا يوجد في ديزر!', + albumNotOnDeezer: 'الالبوم لا يوجد في ديزر!', + notOnDeezer: 'المقطع لا يوجد في ديزر!', + notEncoded: 'لم يتم تشفير المقطع حتى الانً!', + notEncodedNoAlternative: 'لم يتم تشفير المقطع حتى الآن ولم يتم العثور على بديل!', + wrongBitrate: 'لم يتم العثور على المقطع في الدقة المطلوبة.', + wrongBitrateNoAlternative: 'لم يتم العثور على المقطع في الدقة المطلوبة و لا توجد دقة بديلة!', + no360RA: 'المقطع غير متوفر في Reality Audio 360.', + notAvailable: 'المقطع غير متوفر في سيرفرات ديزر!', + notAvailableNoAlternative: 'المقطع غير متوفر في سيرفرات ديزر و لا يوجد بديل حتى الان!' + } + }, + favorites: { + title: 'المفضلات', + noPlaylists: 'لا يوجد قوائم تشغيل', + noAlbums: 'لم لا توجد البومات مفضلة', + noArtists: 'لا يوجد فنانين مفضلين', + noTracks: 'لا توجد مقاطع مفضلة' + }, + home: { + needTologin: 'يجب عليك التسجيل في حساب ديزر قبل بدء التحميل.', + openSettings: 'فتح الاعدادات', + sections: { + popularPlaylists: 'قوائم تشغيل مشهورة', + popularAlbums: 'اكثر الالبومات سماعأ' + } + }, + linkAnalyzer: { + info: 'يمكنك استخدام هذا القسم للعثور على مزيد من المعلومات حول الرابط الذي تحاول تنزيله.', + useful: ' كمثال هذا مفيد إذا كنت تحاول تنزيل بعض المقاطع الغير المتاحة في بلدك وتريد معرفة مكان توفرها .', + linkNotSupported: 'هذا الرابط غير معتمد حتى الآن', + linkNotSupportedYet: 'يبدو أن هذا الرابط غير معتمد حتى الآن ، حاول تحليل رابط آخر.', + table: { + id: 'ID', + isrc: 'ISRC', + upc: 'UPC', + duration: 'المدة الزمنية', + diskNumber: 'رقم القرص', + trackNumber: 'رقم المقطع', + releaseDate: 'تاريخ الاصدار', + bpm: 'BPM', + label: 'Label', + recordType: 'نوع التسجيل', + genres: 'النوع الفني', + tracklist: 'قائمة المقاطع' + } + }, + search: { + startSearching: 'ابدأ البحث!', + description: 'يمكنك البحث عن مقطع ، ألبوم كامل ، فنان ، قائمة تشغيل .... كل شيء! يمكنك أيضًا لصق رابط ديزر', + fans: '{n} متابعون', + noResults: 'لا يوجد نتائج', + noResultsTrack: 'لم يتم العثور على مقاطع', + noResultsAlbum: 'لم يتم العثور على البومات', + noResultsArtist: 'لم يتم العثور على فنانين', + noResultsPlaylist: 'لم يتم العثور على قوائم تشغيل' + }, + searchbar: 'ابحث عن أي شيء تريده (أو الصق رابط)', + downloads: 'التحميلات', + toasts: { + addedToQueue: '{item} تمت إلأضافة إلى قائمة الانتظار', + alreadyInQueue: '{item} حالياً في قائمة الانتظار!', + finishDownload: '{item} انتهى تحميل.', + allDownloaded: 'اكتملت جميع التنزيلات!', + refreshFavs: 'اكتمل التحديث!', + loggingIn: 'جار تسجيل الدخول...', + loggedIn: 'تم تسجيل الدخول', + alreadyLogged: 'تم تسجيل الدخول بالفعل', + loginFailed: 'تعذر تسجيل الدخول', + loggedOut: 'تم تسجيل الخروج', + cancellingCurrentItem: 'جار الغاء العنصر الحالي.', + currentItemCancelled: 'تم الغاء العنصر الحالي.', + startAddingArtist: 'جار اضافة {artist} البوم الى قائمة الانتضار', + finishAddingArtist: 'تم اضافة {artist} البوم الى قائمة الانتضار', + startConvertingSpotifyPlaylist: 'جار تحويل مقاطع سبوتفاي الى مقاطع ديزر', + finishConvertingSpotifyPlaylist: 'تم تحويل قائمة تشغيل سبوتفاي', + loginNeededToDownload: 'يجب عليك تسجيل الدخول لتحميل المقاطع!' + }, + settings: { + title: 'الاعدادات', + languages: 'اللغات', + login: { + title: 'تسجيل الدخول', + loggedIn: 'تم تسجيل الدخول كـ {username}', + arl: { + question: 'كيفية الحصول علة ARL', + update: 'ارفع ال ARL' + }, + logout: 'تسجيل الخروج' + }, + appearance: { + title: 'المظهر', + slimDownloadTab: 'لوحة التحميل الرفيعة' + }, + downloadPath: { + title: 'مسار التحميل' + }, + templates: { + title: 'القوالب', + tracknameTemplate: 'قالب اسم المقطع', + albumTracknameTemplate: 'قالب مقطع الالبوم', + playlistTracknameTemplate: 'قالب مقطع قائمة التشغيل' + }, + folders: { + title: 'الملفات', + createPlaylistFolder: 'اصنع ملف لقائمة التشغيل', + playlistNameTemplate: 'قالب ملف قائمة التشغيل', + createArtistFolder: 'اصنع ملف للفنان', + artistNameTemplate: 'قالب ملف الفنان', + createAlbumFolder: 'اصنع ملف للالبوم', + albumNameTemplate: 'قالب ملف الالبوم', + createCDFolder: 'اصنع ملف للاقراص', + createStructurePlaylist: 'اصنع هيكل مجلدات لقوائم التشغيل', + createSingleFolder: 'اصنع هيكل مجلدات لالبومات ذات الاغنية الواحدة' + }, + trackTitles: { + title: 'عنوان المقطع', + padTracks: 'Pad tracks', + paddingSize: 'Overwrite padding size', + illegalCharacterReplacer: 'محول الكتابات الغير مسموح بها' + }, + downloads: { + title: 'التحميلات', + queueConcurrency: 'التنزيلات المتزامنة', + maxBitrate: { + title: 'الدقة المفضلة', + 9: 'FLAC 1411kbps', + 3: 'MP3 320kbps', + 1: 'MP3 128kbps' + }, + overwriteFile: { + title: 'هل يمكنني استبدال الملفات?', + y: 'نعم, استبدال الملفات', + n: 'لا, لا تبدل الملفات', + t: 'استبدل العلامات فقط', + b: 'لا ، احتفظ بالملفين وأضف رقمًا إلى الملف المكرر' + }, + fallbackBitrate: 'تراجع الدقة', + fallbackSearch: 'تراجع البحث', + logErrors: 'إنشاء ملفات سجل للأخطاء', + logSearched: 'إنشاء ملفات سجل للمقاطع التي تم البحث عنها', + createM3U8File: 'انشاء ملف لقوائم التشغيل', + syncedLyrics: 'انشاء ملف لكلمات الاغنية', + playlistFilenameTemplate: 'قالب اسم ملف قائمة التشغيل', + saveDownloadQueue: 'حفظ قائمة انتظار التنزيل عند إغلاق التطبيق' + }, + covers: { + title: 'غلاف الالبوم', + saveArtwork: 'احفظ الغلاف', + coverImageTemplate: 'تغطية قالب الاسم', + saveArtworkArtist: 'احفظ صورة الفنان', + artistImageTemplate: 'قالب صورة الفنان', + localArtworkSize: 'حجم الصورة', + embeddedArtworkSize: 'حجم الصورة المدمجة', + localArtworkFormat: { + title: 'بأي صيغة تريد حفظ الصورة?', + jpg: 'jpeg صورة', + png: 'png صورة', + both: 'الاثنين png و jpeg' + }, + jpegImageQuality: 'JPEG دقة صورة' + }, + tags: { + head: 'العلامات التي يتم حفظها', + title: 'العنوان', + artist: 'الفنان', + album: 'الالبوم', + cover: 'الغلاف', + trackNumber: 'رقم المقطع', + trackTotal: 'مجموع المقاطع', + discNumber: 'رقم القرص', + discTotal: 'مجموع الاقراص', + albumArtist: 'فنان الالبوم', + genre: 'Genre', + year: 'السنة', + date: 'التاريخ', + explicit: 'كلمات اغنية صريحة للكبار', + isrc: 'ISRC', + length: 'طول المقطع', + barcode: 'Album Barcode (UPC)', + bpm: 'BPM', + replayGain: 'Replay Gain', + label: 'Album Label', + lyrics: 'كلمات غير متزامنة', + copyright: 'حقوق النشر', + composer: 'ملحن', + involvedPeople: 'الناس المشتركون' + }, + other: { + title: 'غير', + savePlaylistAsCompilation: 'حفظ قوائم التشغيل كمجموعة', + useNullSeparator: 'استخدم فاصل فارغ', + saveID3v1: 'احفظ ملف ID3v1', + multiArtistSeparator: { + title: 'كيف تريد فصل الفنانين?', + nothing: 'احفظ الفنان الرئيسي فقط', + default: 'استخدام المواصفات القياسية', + andFeat: 'استخدام& و feat.', + using: 'استخدام "{separator}"' + }, + singleAlbumArtist: 'احفظ فقط فنان الألبوم الرئيسي', + albumVariousArtists: 'احتفظ بـ "فنانين متنوعين" في ألبوم الفنانين', + removeAlbumVersion: 'إزالة "إصدار الألبوم" من عنوان المسار', + removeDuplicateArtists: 'إزالة مجموعات الفنانين', + dateFormat: { + title: 'صيغة التاريخ لملفات flac', + year: 'س س س س', + month: 'ش ش', + day: 'ي ي' + }, + featuredToTitle: { + title: 'ماذا علي أن أفعل مع الفنانين الغير رئيسيين ?', + 0: 'لا شيء', + 1: 'حذفه من العنوان', + 3: 'حذفه من عنوان الاغنية و الالبوم', + 2: 'وضعه في العنوان' + }, + titleCasing: 'نوع كتابة العناون', + artistCasing: 'نوع كتابة الفنان', + casing: { + nothing: 'بدون تغيير', + lower: 'احرف صغيرة', + upper: 'احرف كبيرة', + start: 'حرف كبير في بداية كل كلمة', + sentence: 'مثل جملة' + }, + previewVolume: 'معاينة الحجم', + executeCommand: { + title: 'الأمر للتنفيذ بعد التنزيل', + description: 'اتركه فارغًا بدون إجراء' + } + }, + spotify: { + title: 'مميزات سبوتفاي', + clientID: 'معرف عميل سبوتفاي', + clientSecret: 'الكود السري لعميل سبوتفاي', + username: 'اسم مستخدم سبوتفاي' + }, + reset: 'إعادة تعيين إلى الافتراضي', + save: 'حفظ', + toasts: { + init: 'تم تحميل الإعدادات!', + update: 'تم تحديث الاعدادات!', + ARLcopied: 'تم نسخ ARL إلى الحافظة' + } + }, + sidebar: { + home: 'الرئيسية', + search: 'بحث', + charts: 'قائمة الجداول', + favorites: 'المفضلة', + linkAnalyzer: 'محلل الروابط', + settings: 'الاعدادات', + about: 'حول' + }, + tracklist: { + downloadSelection: 'تحميل الاختيار' + } +} + +export default ar diff --git a/webui/src/lang/de.mjs b/webui/src/lang/de.mjs new file mode 100644 index 0000000..8ed3ac6 --- /dev/null +++ b/webui/src/lang/de.mjs @@ -0,0 +1,524 @@ +const de = { + globals: { + welcome: 'Willkommen bei deemix', + back: 'Zurück', + loading: 'Lädt', + download: '{thing} herunterladen', + by: 'von {artist}', + in: 'in {album}', + download_hint: 'Herunterladen', + play_hint: 'Abspielen', + toggle_download_tab_hint: 'Erweitern/Minimieren', + clean_queue_hint: 'Vollständige entfernen', + cancel_queue_hint: 'Alle abbrechen', + open_downloads_folder: 'Download Ordner öffnen', + cut: 'Ausschneiden', + copy: 'Kopieren', + copyLink: 'Link kopieren', + copyImageLink: 'Bildlink kopieren', + copyDeezerLink: 'Deezer Link kopieren', + paste: 'Einfügen', + listTabs: { + empty: '', + all: 'Alle', + discography: 'Diskographie', + top_result: 'Top Ergebnis', + album: 'Album | Alben', + artist: 'Künstler | Künstler', + single: 'Single | Singles', + title: 'Titel | Titel', + track: 'Track | Tracks', + playlist: 'Playlist | Playlists', + compile: 'Sammlung | Sammlungen', + ep: 'EP | EPs', + bundle: 'Bündel | Bündel', + more: 'Weitere Alben', + featured: 'Bekannt in', + spotifyPlaylist: 'Spotify Playlist | Spotify Playlists', + releaseDate: 'Veröffentlichungsdatum', + error: 'Fehler', + trackN: '0 Tracks | {n} Track | {n} Tracks', + albumN: '0 Alben | {n} Album | {n} Alben', + artistN: '0 Künstler | {n} Künstler | {n} Künstler', + releaseN: '0 Veröffentlichungen | {n} Veröffentlichung | {n} Veröffentlichungen', + playlistN: '0 Playlisten | {n} Playlist | {n} Playlisten' + }, + yes: 'Ja', + no: 'Nein', + empty: 'Leer' + }, + about: { + appStatus: { + online: 'App Online', + offline: 'App Offline' + }, + updates: { + currentVersion: 'Aktuelle Version', + currentWebuiVersion: 'Aktuelle WebUI Version', + versionNotAvailable: 'N/A', + updateAvailable: `Du verwendest nicht die neuste Version ({version})`, + deemixVersion: 'Deemix Lib Version' + }, + titles: { + usefulLinks: 'Nützliche Links', + bugReports: 'Fehlermeldung', + contributing: 'Mitwirkende', + donations: 'Spenden', + license: 'Lizenz' + }, + subtitles: { + bugReports: 'Funktioniert etwas in Deemix nicht? Sag uns bescheid!', + contributing: 'Du möchtest bei dem Projekt helfen? Das kannst du auf verschiedene Arten machen!', + donations: 'Du möchtest deemix finanziell unterstützen? Dann lasse eine kleine Spende da!' + }, + usesLibrary: + 'Dieses Programm nutzt die deemix Bibliothek, die du dazu nutzen kannst, deine eigene deemix UI zu erstellen.', + thanks: + 'Ein Dankeschön geht an rtonno, uhwot and lollilol für die Hilfe bei diesem Projekt und an BasCurtiz für die Erstellung des Logos.', + upToDate: { + text: 'Bleib auf dem Laufenden, indem du dem {newsChannel} auf Telegram folgst.', + newsChannel: 'News Channel' + }, + officialWebsite: 'Offizielle Website', + officialRepo: 'Offizielle Bibliotheks Repository', + officialWebuiRepo: 'Offizielle WebUI Repository', + officialSubreddit: 'Offizieller Subreddit', + newsChannel: 'Neuigkeiten Kanal', + devlogChannel: 'Devlog Kanal', + questions: { + text: 'Suche bei Fragen oder Problemen mit der App als erstes nach einer Lösung im {subreddit}. Wenn du dort nichts findest, kannst du einen Beitrag mit deinen Problem auf dem Subreddit verfassen.', + subreddit: 'Subreddit' + }, + beforeReporting: + 'Bevor du einen Fehler meldest, stelle sicher, dass die Version deiner App auf dem neusten Stand ist und dass dies, was du melden möchtest, tatsächlich ein Fehler und nicht nur bei dir falsch ist.', + beSure: + 'Stelle sicher, dass der Fehler auf anderen Computern auch vorhanden ist... MELDE DEN FEHLER NICHT , wenn dieser schon gemeldet worden ist.', + duplicateReports: 'Achte darauf, dass doppelte Fehlerberichte geschlossen, werden.', + dontOpenIssues: + 'ERSTELLE KEINE Fehlermeldungen um Fragen zu stellen, es existiert ein Subreddit dafür.', + newUI: { + text: 'Wenn du Python fließend beherrschst, kannst du versuchen, mithilfe der Basisbibliothek eine neue Benutzeroberfläche für die App zu erstellen oder Fehler in der Bibliothek mit einem Pull-Request in der {repo} zu beheben.', + repo: 'deemix Repo' + }, + acceptFeatures: + 'Ich akzeptiere auch Funktionen, aber keine komplexen Dinge, da sie direkt in der App und nicht in der Bibliothek implementiert werden können.', + otherLanguages: + 'Wenn du eine andere Programmiersprache fließend beherrschst, kannst du versuchen, deemix in andere Programmiersprachen zu portieren!', + understandingCode: 'Du benötigst Hilfe beim verstehen des Codes? Frag einfach RemixDev auf Telegram oder Reddit.', + contributeWebUI: { + text: 'Wenn du Vue.js (JavaScript) oder HTML und CSS kennst, könntest du etwas zum {webui} beitragen.', + webui: 'WebUI' + }, + itsFree: + 'Du solltest im Kopf behalten das dies ein kostenfreies Projekt ist und Du die Künstler unterstützen sollst, die du magst bevor du die Entwickler unterstützt.', + notObligated: 'Fühle dich nicht gezwungen zu spenden, danke, dass du deemix verwendest!', + lincensedUnder: { + text: 'Diese Arbeit ist lizensiert unter der {gpl3}.', + gpl3: 'GNU General Public License 3.0' + } + }, + charts: { + title: 'Charts', + changeCountry: 'Land wechseln', + download: 'Chart herunterladen' + }, + errors: { + title: 'Fehler für {name}', + postTitle: 'Nach dem Herunterladen von Fehlern.', + ids: { + invalidURL: 'URL nicht erkannt', + unsupportedURL: 'URL noch nicht unterstützt', + ISRCnotOnDeezer: 'Track ISRC ist auf Deezer nicht verfügbar', + notYourPrivatePlaylist: 'Du kannst keine privaten Playlisten anderer herunterladen.', + spotifyDisabled: 'Spotify-Funktionen sind nicht richtig eingerichtet', + trackNotOnDeezer: 'Track ist auf Deezer nicht verfügbar!', + albumNotOnDeezer: 'Album auf Deezer nicht gefunden!', + notOnDeezer: 'Track auf Deezer nicht verfügbar!', + notEncoded: 'Track noch nicht codiert!', + notEncodedNoAlternative: 'Track noch nicht codiert und keine Alternative gefunden!', + wrongBitrate: 'Track mit gewünschter Bitrate nicht gefunden.', + wrongBitrateNoAlternative: 'Track mit gewünschter Bitrate nicht gefunden und keine Alternative gefunden!', + no360RA: 'Track ist nicht in Reality Audio 360 verfügbar.', + notAvailable: 'Track ist nicht verfügbar auf den Servern von Deezer!', + notAvailableNoAlternative: 'Track ist nicht auf den Servern von Deezer verfügbar, keine Alternativen gefunden!', + noSpaceLeft: 'Kein Speicherplatz auf dem Gerät!', + albumDoesntExists: 'Das Album des Tracks ist nicht vorhanden, konnte keine Informationen sammeln.', + wrongLicense: 'Dein Account kann die Spur nicht an der gewünschten Bitrate streamen.', + wrongGeolocation: 'Dein Account kann den Track nicht aus Deinem aktuellen Land streamen.', + wrongGeolocationNoAlternative: + 'Dein Account kann den Titel nicht aus Deinem aktuellen Land streamen und es ist keine Alternative verfügbar.' + } + }, + favorites: { + title: 'Favoriten', + noPlaylists: 'Keine Playlist gefunden', + noAlbums: 'Keine favorisierten Alben gefunden', + noArtists: 'Keine favorisierten Künstler gefunden', + noTracks: 'Keine favorisierten Tracks gefunden' + }, + home: { + needTologin: 'Du musst dich in deinem Deezer-Account anmelden bevor du mit dem Download starten kannst.', + openSettings: 'Einstellungen öffnen', + sections: { + popularPlaylists: 'Beliebte Playlists', + popularAlbums: 'Meistgestreamte Alben' + } + }, + linkAnalyzer: { + info: 'Diesen Abschnitt kannst du nutzen, um weitere Informationen über den gewünschten Link zu erhalten, den du herunterladen möchtest.', + useful: + 'Dies ist z.B. nützlich, wenn du versuchst einige Titel herunterzuladen, welche in deinem Land nicht verfügbar sind, und du wissen möchtest, wo sie verfügbar sind.', + linkNotSupported: 'Dieser Link wird noch nicht unterstützt', + linkNotSupportedYet: + 'Es scheint so, als ob dieser Link noch nicht unterstützt wird. Versuche einen anderen Link zu analysieren.', + table: { + id: 'ID', + isrc: 'ISRC', + upc: 'UPC', + duration: 'Dauer', + diskNumber: 'CD Nummer', + trackNumber: 'Track Nummer', + releaseDate: 'Veröffentlichungsdatum', + bpm: 'BPM', + label: 'Label', + recordType: 'Art der Aufnahme', + genres: 'Genres', + tracklist: 'Trackliste', + readable: 'Lesbar', + available: 'Verfügbar' + }, + countries: 'Länder', + noCountries: 'Dieser Track ist in keinem Land verfügbar.' + }, + search: { + startSearching: 'Suche starten!', + description: + 'Du kannst einen Titel, ein ganzes Album, einen Künstler, eine Playlist suchen ... alles! Du kannst auch einen Deezer-Link einfügen', + fans: '{n} Fans', + noResults: 'Keine Ergebnisse', + noResultsTrack: 'Keine Tracks gefunden', + noResultsAlbum: 'Keine Alben gefunden', + noResultsArtist: 'Keinen Künstler gefunden', + noResultsPlaylist: 'Keine Playlist gefunden', + error: 'Ein Fehler ist aufgetreten. Bitte versuche es später erneut.' + }, + searchbar: 'Suche nach allem, was dir gefällt (oder füge einfach einen Link ein)', + downloads: 'Downloads', + toasts: { + restoringQueue: 'Download-Warteschlange wiederherstellen...', + queueRestored: 'Download-Warteschlange wiederhergestellt!', + addedToQueue: '{item} zur Warteschlange hinzugefügt', + addedMoreToQueue: '{n} Einträge zur Warteschlange hinzugefügt', + alreadyInQueue: '{item} ist bereits in der Warteschlange!', + finishDownload: '{item} vollständig heruntergeladen.', + allDownloaded: 'Alle Downloads abgeschlossen!', + refreshFavs: 'Abgeschlossene Downloads neuladen!', + loggingIn: 'Einloggen', + loggedIn: 'Eingeloggt', + alreadyLogged: 'Bereits eingeloggt', + loginFailed: 'Login fehlgeschlagen', + loggedOut: 'Ausgeloggt', + cancellingCurrentItem: 'Aktuelle Auswahl abbrechen.', + currentItemCancelled: 'Aktuelle Auswahl wurde abgebrochen', + startAddingArtist: 'Alben von {artist} werden hinzugefügt', + finishAddingArtist: 'Alben von {artist} wurden hinzugefügt', + startConvertingSpotifyPlaylist: 'Konvertierern von Spotify-Tracks zu Deezer-Tracks', + finishConvertingSpotifyPlaylist: 'Spotify Playlist convertiert', + loginNeededToDownload: 'Du musst eingeloggt sein, um Tracks herunterladen zu können!', + queueErrorCantStream: `Dein Konto kann nicht mit {Bitrate} streamen!`, + deezerNotAvailable: 'Deezer ist in deinem Land nicht verfügbar. Du solltest eine VPN nutzen.', + deezerNotReachable: + 'Die App kann Deezer nicht erreichen. Prüfe deine Internet-Verbindung, deine Firewall oder dein Antivirus.', + startGeneratingItems: 'Verarbeite {n} Einträge....', + finishGeneratingItems: '{n} Einträge generiert.', + noLovedPlaylist: 'Keine Geliebten-Tracks-Wiedergabeliste!', + checkingUpdates: 'Auf Aktualisierungen prüfen...', + noUpdateAvailable: 'Keine Aktualisierungen gefunden', + updateAvailable: 'Eine Aktualisierung ist verfügbar!' + }, + settings: { + title: 'Einstellungen', + languages: 'Sprachen', + login: { + title: 'Einloggen', + loggedIn: 'Du bist eingeloggt als {username}', + arl: { + title: 'Stattdessen ARL verwenden', + question: 'Wie bekomme ich meine eigene ARL?', + howTo: { + prologue: { + p1: 'Deezer verfolgt die Anmeldesitzung mithilfe eines Cookies namens ARL.', + p2: 'Deemix verwendet dieses Cookie, um die Metadaten abzurufen, die es benötigt, um die Tracks von Deezer herunterzuladen.', + p3: 'ARLs sind 3 Monate gültig, danach fordert Deezer Dich auf, sich erneut anzumelden. Die gleiche Methode wird in deemix verwendet.', + p4: 'Wenn Du einer der folgenden Anleitungen folgst, kannst Du deine eigene Account-ARL erhalten.', + warning: 'Verwende diese Methode nur, wenn E-Mail und Passwort nicht funktionieren.' + }, + chromeSteps: { + title: 'Chrome', + step1: 'Öffne Chrome', + easyWay: { + title: 'Chrome (Einfacher Weg)', + step3: 'Klicke auf das kleine "Schloss"-Symbol neben der URL', + step4: 'Klicke auf Cookies > deezer.com > cookies > arl', + step5: 'Wähle die Zeichenfolge neben Inhalt und Kopieren aus' + }, + step4: "Gehe zum Application Tab (if you don't see it click the double arrow)", + videoGuide: { + text: 'Hier ist eine {videoGuide}', + link: 'Video Guide' + } + }, + firefoxSteps: { + title: 'Firefox', + step1: 'Öffne Firefox', + step4: 'Gehe unter die Registerkarte Speicher (wenn Du sie nicht siehst, klicke auf den Doppelpfeil)' + }, + commonSteps: { + step2: 'Gehe zu www.deezer.com und logge dich in deinen Account ein', + step3: 'Drücke nach der Anmeldung F12, um die Entwicklertools zu öffnen', + step5: 'Öffne den Cookie-Dropdown', + step6: 'Wähle www.deezer.com', + step7: 'Finde das `arl` Cookie (It should be 192 chars long)', + step8: 'Stelle sicher, dass Du nur den Wert kopierst und nicht das gesamte Cookie', + lastStep: 'Das ist Deine ARL, jetzt kannst Du sie in der App verwenden' + } + }, + update: 'ARL aktualisieren' + }, + logout: 'Ausloggen', + login: 'Über deezer.com einloggen', + email: 'E-Mail', + password: 'Passwort' + }, + appearance: { + title: 'Design', + slimDownloadTab: 'Schmaler Download-Tab', + slimSidebar: 'Schlanke Seitenleiste', + searchButton: 'Suchschaltfläche anzeigen', + bitrateTags: 'Qualitäts-Tag in Download-Warteschlange anzeigen' + }, + downloadPath: { + title: 'Download Pfad' + }, + templates: { + title: 'Vorlagen', + tracknameTemplate: 'Vorlage für den Tracknamen', + tracknameAvailableVariables: 'Verfügbare Trackname Variablen', + albumTracknameTemplate: 'Album-Track-Vorlage.', + albumTracknameAvailableVariables: 'Verfügbare Album-Track-Variablen', + playlistTracknameTemplate: 'Vorlage für Tracks in einer Playlist', + playlistTracknameAvailableVariables: 'Verfügbare Playlist Trackvariablen' + }, + folders: { + title: 'Ordner', + createPlaylistFolder: 'Ordner für Playlist erstellen', + playlistNameTemplate: 'Vorlage für Playlist-Ordner', + createArtistFolder: 'Ordner für Künstler erstellen', + artistNameTemplate: 'Vorlage für Künstler-Ordner', + createAlbumFolder: 'Ordner für Album erstellen', + albumNameTemplate: 'Vorlage für Album-Ordner', + createCDFolder: 'Ordner für CDs erstellen', + createStructurePlaylist: 'Erstellen von Künstler-, Alben- und CD-Ordnern auch für Playlists', + createSingleFolder: 'Ordner für einzelne Titel erstellen' + }, + trackTitles: { + title: 'Songtitel', + padTracks: 'Einheitliche Länge der Titelnummern (voranstehende Nullen werden ergänzt)', + paddingSize: 'Innenabstand überschreiben', + illegalCharacterReplacer: 'Unzulässige Zeichen ersetzen' + }, + downloads: { + title: 'Downloads', + queueConcurrency: 'Gleichzeitige Downloads', + maxBitrate: { + title: 'Bevorzugte Bitrate', + 9: 'FLAC 1411kbps', + 3: 'MP3 320kbps', + 1: 'MP3 128kbps' + }, + overwriteFile: { + title: 'Soll ich die Dateien überchreiben?', + y: 'Ja überschreibe die Dateien', + n: 'Nein überschreibe die Dateien nicht', + t: 'Überschreibe nur die Tags', + b: 'Nein, behalte beide Dateien und füge der Kopie eine Nummer hinzu', + e: 'Nein, und schau nicht auf die Erweiterungen' + }, + fallbackBitrate: 'Falls gewünschte Bitrate nicht verfügbar, auf niedrigere Bitrate zurückgreifen', + fallbackSearch: 'Zur Suche zurückkehren, wenn der Song nicht verfügbar ist', + fallbackISRC: 'Fallback mit ISRC-Suche', + feelingLucky: 'Spielen mit CDNs und Caches', + logErrors: 'Protokolldatei für Fehler im Download-Ordner erstellen', + logSearched: 'Protokolldatei für gesuchte Titel erstellen', + createM3U8File: 'Erstelle Playlist-Datei (M3U8)', + syncedLyrics: 'Erstelle synchrone Lyrics-Datei (.lrc)', + playlistFilenameTemplate: 'Vorlage für den Namen der Playlist', + clearQueueOnExit: 'Download-Warteschlange beim Schließen der App leeren' + }, + covers: { + title: 'Album Cover', + saveArtwork: 'Cover speichern', + coverImageTemplate: 'Vorlage für den Covernamen', + saveArtworkArtist: 'Speichere das Künstlerbild', + artistImageTemplate: 'Vorlage des Künstlerbildes', + localArtworkSize: 'Lokale Grafikgröße', + embeddedArtworkSize: 'Eingebettete Grafikgröße', + localArtworkFormat: { + title: 'Welches Datei-Format soll das Cover haben?', + jpg: 'Ein jpg Bild', + png: 'Ein png Bild', + both: 'Beides (jpg + png)' + }, + jpegImageQuality: 'JPEG Qualität', + embeddedArtworkPNG: 'Eingebettete Grafiken als PNG speichern', + embeddedPNGWarning: 'PNGs werden von Deezer nicht offiziell unterstützt und können fehlerhaft sein', + imageSizeWarning: 'Alles über x1200 wird nicht offiziell von Deezer verwendet, es können Probleme auftreten', + coverDescriptionUTF8: 'Cover-Beschreibung mit UTF8 speichern (iTunes Cover Fix)' + }, + tags: { + head: 'Welche Tags sollen gespeichert werden?', + title: 'Titel', + artist: 'Künstler', + artists: 'Zusätzlicher ARTISTS Tag', + album: 'Album', + cover: 'Cover', + trackNumber: 'Titelnummer', + trackTotal: 'Titelanzahl', + discNumber: 'CD Nummer', + discTotal: 'CDs insgesamt', + albumArtist: 'Album Künstler', + genre: 'Genre', + year: 'Jahr', + date: 'Datum', + explicit: 'Explizite Lyrics', + isrc: 'ISRC', + length: 'Titel Länge', + barcode: 'Album Barcode (UPC)', + bpm: 'BPM', + replayGain: 'Wiedergabe Lautstärke', + label: 'Album Plattenlabel', + lyrics: 'Nicht synchronisierte Texte', + syncedLyrics: 'Synchronisierte Texte', + copyright: 'Copyright', + composer: 'Komponist', + involvedPeople: 'Mitwirkende Personen', + source: 'Quelle und Song ID', + artistsWarning: + 'Das Deaktivieren des ARTISTS- Tags, während die Standardspezifikation nicht verwendet wird, wird die Multiartist- Unterstützung nicht erhalten' + }, + other: { + title: 'Sonstige', + autoCheckForUpdates: 'Beim Start nach Updates suchen', + savePlaylistAsCompilation: 'Speichere Playlist als Zusammenstellung', + useNullSeparator: 'Verwende Nulltrennzeichen', + saveID3v1: 'Speichere ID3v1 ebenfalls', + multiArtistSeparator: { + title: 'Wie möchtest du die Künstler trennen?', + nothing: 'Speichere nur den Hauptkünstler', + default: 'Verwende Standard Spezifikationen', + andFeat: 'Verwende & und feat.', + using: 'Verwende "{separator}"', + warning: + 'Wenn Du ein anderes Trennzeichen als die Standardspezifikation verwendest, wird ein zusätzliches ARTISTS-Tag hinzugefügt, um die Unterstützung mehrerer Künstler zu erhalten' + }, + singleAlbumArtist: 'Nur den Hauptkünstler speichern', + albumVariousArtists: 'Verschiedene Künstler" im Album Künstler Tag behalten', + removeAlbumVersion: 'Entferne die "Album Version" vom Songtitel', + removeDuplicateArtists: 'Kombinationen von Künstlern entfernen', + dateFormat: { + title: 'Datumsformatierung für FLAC Dateien', + year: 'JJJJ', + month: 'MM', + day: 'TT' + }, + featuredToTitle: { + title: 'Was soll ich mit featured Artists tun?', + 0: 'Nichts', + 1: 'Vom Titel entfernen', + 3: 'Vom Titel und Albumtitel entfernen', + 2: 'Zu dem Titel hinzufügen' + }, + titleCasing: 'Titel-Schreibweise', + artistCasing: 'Künstler-Schreibweise', + casing: { + nothing: 'Unbearbeitet lassen', + lower: 'klein', + upper: 'GROSS', + start: 'Wortanfang Gross', + sentence: 'Satzanfang gross' + }, + previewVolume: 'Vorschau der Lautstärke', + executeCommand: { + title: 'Befehl, der nach dem Download ausgeführt werden soll', + description: 'Leer lassen ohne Aktion' + } + }, + spotify: { + title: 'Spotify Funktionen', + clientID: 'Spotify Client ID', + clientSecret: 'Spotify Client Secret', + username: 'Spotify Benutzername', + question: 'Wie aktiviere ich die Spotify Funktionen?', + howTo: { + prologue: { + p1: '"Spotify Funktionen" ist eine Reihe von Funktionen, mit denen Du Spotify-Tracks und Alben-Links in Deezer-Links konvertieren kannst.', + p2: 'Wenn Du einen Spotify-Playlist-Link bereitstellst, konvertiert die App automatisch alle Links der darin enthaltenen Titel in Deezer-Titel.', + p3: 'Wenn Du diese Funktionen aktivierst, kannst Du Deine öffentlichen Spotify-Wiedergabelisten auch auf der Registerkarte "Favoriten" sehen.' + }, + info: 'Aus Sicherheitsgründen musst Du Deine eigene Client-ID und Dein Client-Secret angeben', + clientSecretQuestion: { + title: 'Wie erhalte ich meine Client-ID und mein Client-Secret?', + step1: { + text: 'Verbinde dich mit {spotifyDevelopersDashboard} und melde dich mit Deinem Spotify-Account an.', + spotifyDevelopersDashboard: 'Spotify Entwickler-Dashboard' + }, + step2: { + text: 'Klicke auf "App erstellen"..', + imageAlt: 'Erstelle eine App-Schaltfläche auf Spotify für das Entwickler-Dashboard' + }, + step3: { + text: 'Fülle die Felder „App-Name“ und „App-Beschreibung“ aus und aktiviere beide Kontrollkästchen. Klicke dann auf die Schaltfläche "Erstellen".', + imageAlt: 'Erstelle ein App-Formular' + }, + step4: { + text: 'Jetzt kannst Du die Client-ID sehen. Wenn Du auf "„"Kundengeheimnis anzeigen"“" klickst, wird das Kundengeheimnis angezeigt.', + imageAlt: 'Screen mit Client-ID und Geheimnis' + }, + step5: + 'Jetzt kannst Du diese Ergebnisse kopieren und in die entsprechenden Felder in den Einstellungen einfügen.' + }, + usernameQuestion: { + title: 'Wie erhalte ich meinen Spotify-Benutzernamen?', + step1: { + text: 'Du kannst Deinen Spotify-Benutzernamen auf der {overviewPage} auf der Spotify-Website abrufen.', + overviewPage: 'Übersichtsseite' + } + } + } + }, + reset: 'Auf Standardwerte zurücksetzen', + resetMessage: 'Bist du sicher, dass du zu den Standarteinstellungen zurückkehren willst?', + save: 'Speichern', + toasts: { + init: 'Einstellungen geladen!', + update: 'Einstellungen aktualisiert!', + reset: 'Einstellungen auf den Standart zurückgesetzt!', + ARLcopied: 'ARL wurde in die Zwischenablage kopiert' + } + }, + sidebar: { + home: 'Startseite', + search: 'Suche', + charts: 'Charts', + favorites: 'Favoriten', + linkAnalyzer: 'Link Analyse', + settings: 'Einstellungen', + logs: 'Protokolle', + about: 'Info' + }, + tracklist: { + downloadSelection: 'Herunterladen' + } +} + +export default de diff --git a/webui/src/lang/el.mjs b/webui/src/lang/el.mjs new file mode 100644 index 0000000..9b9d26e --- /dev/null +++ b/webui/src/lang/el.mjs @@ -0,0 +1,527 @@ +const gr = { + globals: { + welcome: 'Καλωσόρισες στο deemix', + back: 'Πίσω', + loading: 'φόρτωση', + download: 'Λήψη {thing}', + by: 'από {artist}', + in: 'σε {album}', + download_hint: 'Λήψη', + play_hint: 'Αναπαραγωγή', + toggle_download_tab_hint: 'Ανάπτυξη/Σύμπτυξη', + clean_queue_hint: 'Καθαρισμός Ολοκληρωμένων', + cancel_queue_hint: 'Ακύρωση Όλων', + open_downloads_folder: 'Άνοιγμα Φακέλου Λήψεων', + cut: 'αποκοπή', + copy: 'αντιγραφή', + copyLink: 'αντιγραφή συνδέσμου', + copyImageLink: 'αντιγραφή συνδέσμου εικόνας', + copyDeezerLink: 'αντιγραφή συνδέσμου deezer', + paste: 'επικόλληση', + listTabs: { + empty: '', + all: 'όλα', + top_result: 'κορυφαίο αποτέλεσμα', + album: 'άλμπουμ | άλμπουμ', + artist: 'καλλιτέχνης | καλλιτέχνες', + single: 'single | singles', + title: 'τίτλος | τίτλοι', + track: 'κομμάτι | κομμάτια', + releaseN: '0 κυκλοφορίες | {n} κυκλοφορία | {n} κυκλοφορίες', + playlist: 'λίστα αναπαραγωγής | λίστες αναπαραγωγής', + compile: 'συλλογή | συλλογές', + ep: 'ep | eps', + bundle: 'δέσμη | δέσμες', + more: 'Περισσότερα άλμπουμ', + featured: 'Συμμετοχές', + spotifyPlaylist: 'λίστα αναπαραγωγής spotify | λίστες αναπαραγωγής spotify', + releaseDate: 'ημερομηνία κυκλοφορίας', + error: 'σφάλμα', + trackN: '0 κομμάτια | {n} κομμάτι | {n} κομμάτια', + albumN: '0 άλμπουμ | {n} άλμπουμ | {n} άλμπουμ', + artistN: '0 καλλιτέχνες | {n} καλλιτέχνης | {n} καλλιτέχνες', + playlistN: '0 λίστες αναπαραγωγής | {n} λίστα αναπαραγωγής | {n} λίστες αναπαραγωγής' + }, + yes: 'ναι', + no: 'όχι', + empty: 'κενό' + }, + about: { + appStatus: { + online: 'εφαρμογή σε σύνδεση', + offline: 'εφαρμογή εκτός σύνδεσης' + }, + updates: { + currentVersion: 'Τρέχουσα Έκδοση', + currentWebuiVersion: 'Τρέχουσα Έκδοση WebUI', + versionNotAvailable: 'Μη Διαθέσιμη', + updateAvailable: `Δεν εκτελείτε την πιο πρόσφατη διαθέσιμη έκδοση: {version}`, + deemixVersion: 'Έκδοση deemix lib' + }, + titles: { + usefulLinks: 'Χρήσιμοι Σύνδεσμοι', + bugReports: 'Αναφορές Σφαλμάτων', + contributing: 'Συνεισφορά', + donations: 'Δωρεές', + license: 'Άδεια' + }, + subtitles: { + bugReports: 'Υπάρχει κάτι που δεν λειτουργεί στο deemix; Ενημέρωσε μας!', + contributing: 'Θέλετε να συμβάλλετε σε αυτό το πρότζεκτ; Μπορείτε να το κάνετε με διάφορους τρόπους!', + donations: 'Θέλετε να συνεισφέρετε οικονομικά; Θα μπορούσατε να κάνετε μια δωρεά!' + }, + usesLibrary: + 'Αυτή η εφαρμογή χρησιμοποιεί τη βιβλιοθήκη deemix, την οποία μπορείτε να χρησιμοποιήσετε για να δημιουργήσετε το δικό σας περιβάλλον χρήστη για το deemix.', + thanks: `Ευχαριστώ τους rtonno, uhwot και lollilol που με βοήθησαν σε αυτό το έργο και τον BasCurtiz για τη δημιουργία του εικονιδίου του deemix.`, + upToDate: { + text: `Μείνετε ενημερωμένοι ακολουθώντας το {newsChannel} στο Telegram.`, + newsChannel: 'news channel' + }, + officialWebsite: 'Επίσημη Ιστοσελίδα', + officialRepo: 'Επίσημο Αποθετήριο Βιβλιοθήκης', + officialWebuiRepo: 'Επίσημο Αποθετήριο WebUI', + officialSubreddit: 'Επίσημο Subreddit', + newsChannel: 'News Channel', + devlogChannel: 'Devlog Channel', + questions: { + text: `Εάν έχετε ερωτήσεις ή προβλήματα με την εφαρμογή, αναζητήστε αρχικά μια λύση στο {subreddit}. Εάν δεν βρείτε τη λύση εκεί, μπορείτε να κάνετε μια ανάρτηση με το πρόβλημά σας στο subreddit.`, + subreddit: 'subreddit' + }, + beforeReporting: `Πριν αναφέρετε κάποιο σφάλμα, βεβαιωθείτε αρχικά ότι εκτελείτε την τελευταία έκδοση της εφαρμογής και ότι το συγκεκριμένο σφάλμα δεν είναι κάποιο πρόβλημα από πλευράς σας.`, + beSure: `Βεβαιωθείτε ότι το σφάλμα συμβαίνει και σε άλλα μηχανήματα, πχ δοκιμάζοντας σε κάποιον άλλον υπολογιστή και ΜΗΝ αναφέρετε σφάλματα που έχουν ήδη αναφερθεί.`, + duplicateReports: 'Οι διπλές αναφορές σφαλμάτων θα κλείνουν, οπότε έχετε το νου σας σε αυτό.', + dontOpenIssues: `ΜΗΝ ανοίγετε ζητήματα για υποβολή απλών ερωτήσεων, υπάρχει subreddit για αυτό.`, + newUI: { + text: `Εάν χειρίζεστε άριστα την python, μπορείτε να δοκιμάσετε να δημιουργήσετε ένα νέο περιβάλλον χρήστη για την εφαρμογή χρησιμοποιώντας τη βασική βιβλιοθήκη ή να διορθώσετε σφάλματα στη βιβλιοθήκη με ένα pull request στο {repo}.`, + repo: 'repo' + }, + acceptFeatures: `Δέχομαι και επιπλέον λειτουργίες, αλλά όχι περίπλοκα πράγματα, έτσι ώστε να μπορούν να υλοποιηθούν απευθείας στην εφαρμογή και όχι στη βιβλιοθήκη.`, + otherLanguages: `Εάν χειρίζεστε άριστα οποιαδήποτε άλλη γλώσσα προγραμματισμού, μπορείτε να προσπαθήσετε να μεταφέρετε το deemix σε αυτή τη γλώσσα!`, + understandingCode: `Χρειάζεστε βοήθεια για την κατανόηση του κώδικα; Απλώς πατήστε το RemixDev στο Telegram ή το Reddit.`, + contributeWebUI: { + text: `Εάν γνωρίζετε Vue.js (JavaScript), HTML ή CSS, μπορείτε να συνεισφέρετε στο {webui}.`, + webui: 'WebUI' + }, + itsFree: `Πρέπει να έχετε υπόψιν ότι αυτό πρότζεκτ είναι δωρεάν και ότι θα πρέπει αρχικά να υποστηρίξετε τους καλλιτέχνες που αγαπάτε και μετά τους προγραμματιστές.`, + notObligated: `Μην αισθάνεστε υποχρεωμένοι να κάνετε κάποια δωρεά, σας εκτιμώ ούτως ή άλλως!`, + lincensedUnder: { + text: `Αυτή η εργασία είναι αδειοδοτημένη βάσει του {gpl3}.`, + gpl3: 'GNU General Public License 3.0' + } + }, + charts: { + title: 'Διαγράμματα', + changeCountry: 'Αλλαγή Χώρας', + download: 'Λήψη Διαγράμματος' + }, + errors: { + title: 'Σφάλματα για {name}', + postTitle: 'Μετά τη λήψη σφαλμάτων', + ids: { + invalidURL: 'Η διεύθυνση URL δεν αναγνωρίζεται', + unsupportedURL: 'Η διεύθυνση URL δεν υποστηρίζεται ακόμη', + ISRCnotOnDeezer: 'Το κομμάτι ISRC δεν είναι διαθέσιμο στο Deezer', + notYourPrivatePlaylist: 'Δεν μπορείτε να κατεβάσετε ιδιωτικές λίστες αναπαραγωγής άλλων.', + spotifyDisabled: 'Οι δυνατότητες Spotify δεν έχουν ρυθμιστεί σωστά.', + trackNotOnDeezer: 'Αυτό το κομμάτι δεν βρέθηκε στο Deezer!', + albumNotOnDeezer: 'Αυτό το άλμπουμ δεν βρέθηκε στο Deezer!', + notOnDeezer: 'Αυτό το κομμάτι δεν είναι διαθέσιμο στο Deezer!', + notEncoded: 'Αυτό το κομμάτι δεν έχει κωδικοποιηθεί ακόμα!', + notEncodedNoAlternative: 'Αυτό το κομμάτι δεν έχει κωδικοποιηθεί ακόμα και δεν βρέθηκε εναλλακτική λύση!', + wrongBitrate: 'Αυτό το κομμάτι δεν βρέθηκε στο επιθυμητό bitrate.', + wrongBitrateNoAlternative: 'Αυτό το κομμάτι δεν βρέθηκε στον επιθυμητό bitrate και δεν βρέθηκε εναλλακτική λύση!', + no360RA: 'Αυτό το κομμάτι δεν είναι διαθέσιμο στο Reality Audio 360.', + notAvailable: 'Αυτό το κομμάτι δεν είναι διαθέσιμο στους διακομιστές του Deezer!', + notAvailableNoAlternative: + 'Αυτό το κομμάτι δεν είναι διαθέσιμο στους διακομιστές του Deezer και δεν βρέθηκε εναλλακτική λύση!', + noSpaceLeft: 'Δεν υπάρχει διαθέσιμος χώρος στη συσκευή!', + albumDoesntExists: 'Το άλμπουμ αυτού του κομματιού δεν υπάρχει, η συλλογή πληροφοριών απέτυχε.', + wrongLicense: 'Ο λογαριασμός σας δεν μπορεί να κάνει stream αυτό το κομμάτι με το επιθυμητό bitrate.', + wrongGeolocation: 'Ο λογαριασμός σας δεν μπορεί να κάνει stream αυτό το κομμάτι στην χώρα σας.', + wrongGeolocationNoAlternative: + 'Ο λογαριασμός σας δεν μπορεί να μεταδώσει το συγκεκριμένο κομμάτι από την τρέχουσα χώρα και δεν βρέθηκε εναλλακτική πηγή.' + } + }, + favorites: { + title: 'Αγαπημένα', + noPlaylists: 'Δεν Βρέθηκαν Λίστες Αναπαραγωγής', + noAlbums: 'Δεν Βρέθηκαν Αγαπημένα Άλμπουμ', + noArtists: 'Δεν Βρέθηκαν Αγαπημένοι Καλλιτέχνες', + noTracks: 'Δεν Βρέθηκαν Αγαπημένα Κομμάτια' + }, + home: { + needTologin: 'Πρέπει να συνδεθείτε στον λογαριασμό σας Deezer προτού ξεκινήσετε τη λήψη.', + openSettings: 'Άνοιγμα Ρυθμίσεων', + sections: { + popularPlaylists: 'Δημοφιλείς λίστες αναπαραγωγής', + popularAlbums: 'Τα άλμπουμ με τις περισσότερες αναπαραγωγές' + } + }, + linkAnalyzer: { + info: 'Μπορείτε να χρησιμοποιήσετε αυτήν την ενότητα για να βρείτε περισσότερες πληροφορίες σχετικά με τον σύνδεσμο που προσπαθείτε να κατεβάσετε.', + useful: + 'Αυτό για παράδειγμα είναι χρήσιμο εάν προσπαθείτε να κατεβάσετε μερικά κομμάτια που δεν είναι διαθέσιμα στη χώρα σας και θέλετε να μάθετε πού είναι διαθέσιμα.', + linkNotSupported: 'Αυτός ο σύνδεσμος δεν υποστηρίζεται ακόμη', + linkNotSupportedYet: 'Φαίνεται ότι αυτός ο σύνδεσμος δεν υποστηρίζεται ακόμη, δοκιμάστε να αναλύσετε κάποιον άλλο.', + table: { + id: 'ID', + isrc: 'ISRC', + upc: 'UPC', + duration: 'Διάρκεια', + diskNumber: 'Αριθμός Δίσκου', + trackNumber: 'Αριθμός Τραγουδιού', + releaseDate: 'Ημερομηνία Κυκλοφορίας', + bpm: 'BPM', + label: 'Ετικέτα', + recordType: 'Τύπος Εγγραφής', + genres: 'Είδη', + tracklist: 'Λίστα Κομματιών', + readable: 'Αναγνώσιμο', + available: 'Διαθέσιμο' + }, + countries: 'Χώρες', + noCountries: 'Αυτό το κομμάτι δεν είναι διαθέσιμο σε καμία χώρα.' + }, + search: { + startSearching: 'Έναρξη αναζήτησης...', + description: + 'Εδώ μπορείτε να αναζητήσετε κάποιο κομμάτι, κάποιο άλμπουμ, κάποιον καλλιτέχνη, μια λίστα αναπαραγωγής ή οτιδήποτε άλλο επιθυμείτε. Μπορείτε επίσης να επικολλήσετε έναν σύνδεσμο Deezer.', + fans: '{n} θαυμαστές', + noResults: 'Δεν βρέθηκαν αποτελέσματα', + noResultsTrack: 'Δεν βρέθηκαν κομμάτια', + noResultsAlbum: 'Δεν βρέθηκαν άλμπουμ', + noResultsArtist: 'Δεν βρέθηκαν καλλιτέχνες', + noResultsPlaylist: 'Δεν βρέθηκαν λίστες αναπαραγωγής' + }, + searchbar: 'Αναζητήστε οτιδήποτε θέλετε ή απλά επικολλήστε έναν σύνδεσμο', + downloads: 'λήψεις', + toasts: { + restoringQueue: 'Επαναφορά της ουράς λήψης…', + queueRestored: 'Η ουρά λήψης αποκαταστάθηκε!', + addedToQueue: '{item} προστέθηκε στην ουρά', + addedMoreToQueue: '{n} στοιχεία προστέθηκαν στην ουρά', + alreadyInQueue: 'Το {item} είναι ήδη στην ουρά!', + finishDownload: 'Η λήψη του {item} ολοκληρώθηκε.', + allDownloaded: 'Όλες οι λήψεις ολοκληρώθηκαν!', + refreshFavs: 'Η ανανέωση ολοκληρώθηκε!', + loggingIn: 'Σύνδεση...', + loggedIn: 'Συνδεδεμένος', + alreadyLogged: 'Ήδη συνδεδεμένος', + loginFailed: 'Δεν ήταν δυνατή η σύνδεση', + loggedOut: 'Αποσυνδεδεμένος', + cancellingCurrentItem: 'Ακύρωση τρέχοντος στοιχείου.', + currentItemCancelled: 'Το τρέχον στοιχείο ακυρώθηκε.', + startAddingArtist: 'Προσθήκη άλμπουμ του καλλιτέχνη {artist} στην ουρά', + finishAddingArtist: 'Προστέθηκαν άλμπουμ του καλλιτέχνη {artist} στην ουρά', + startConvertingSpotifyPlaylist: 'Μετατροπή κομματιών spotify σε κομμάτια Deezer', + finishConvertingSpotifyPlaylist: 'Η λίστα αναπαραγωγής Spotify μετατράπηκε', + loginNeededToDownload: 'Πρέπει να συνδεθείτε για να κατεβάσετε κομμάτια!', + deezerNotAvailable: 'Το Deezer δεν είναι διαθέσιμο στη χώρα σας. Θα πρέπει να χρησιμοποιήσετε κάποια VPN υπηρεσία.', + deezerNotReachable: + 'Η εφαρμογή δεν μπορεί να συνδεθεί στο Deezer. Ελέγξτε τη σύνδεσή σας στο διαδίκτυο ή το πρόγραμμα προστασίας σας από ιούς.', + startGeneratingItems: 'Επεξεργασία {n} στοιχείων...', + finishGeneratingItems: 'Δημιουργήθηκαν {n} στοιχεία.', + noLovedPlaylist: 'Δεν υπάρχει λίστα αναπαραγωγής αγαπημένων κομματιών!', + checkingUpdates: 'Ελεγχος για ενημερώσεις...', + noUpdateAvailable: 'Δεν βρέθηκαν ενημερώσεις', + updateAvailable: 'Υπάρχει διαθέσιμη ενημέρωση!' + }, + settings: { + title: 'Ρυθμίσεις', + languages: 'Γλώσσες', + login: { + title: 'Σύνδεση', + loggedIn: 'Έχετε συνδεθεί ως {username}', + arl: { + title: 'Χρήση ARL', + question: 'Πώς μπορώ να αποκτήσω το δικό μου ARL;', + howTo: { + prologue: { + p1: 'To "Deezer" παρακολουθεί την περίοδο σύνδεσης σας χρησιμοποιώντας ένα cookie που ονομάζεται "ARL".', + p2: 'Το "Deemix" χρησιμοποιεί αυτό το cookie για να λάβει τα δεδομένα που χρειάζεται για τη λήψη των κομματιών από το "Deezer".', + p3: 'Τα "ARL" διαρκούν τρεις μήνες. Με το πέρας των τριών μηνών το "Deezer" σας ζητά να συνδεθείτε ξανά. Η ίδια μέθοδος χρησιμοποιείται και στο "Deemix".', + p4: 'Ακολουθώντας τα παρακάτω βήματα μπορείτε να αποκτήσετε τον "ARL" κωδικό σας', + warning: 'Χρησιμοποιήστε αυτήν τη μέθοδο μόνο εάν το email και ο κωδικός πρόσβασης δεν λειτουργούν.' + }, + chromeSteps: { + title: 'Chrome', + step1: 'Ανοίξτε τον Chrome', + easyWay: { + title: 'Chrome (Εύκολος Τρόπος)', + step3: + 'Κάντε κλικ στο εικονίδιο με το λουκέτο το οποίο βρίσκεται στα αριστερά του πεδίο διεύθυνσης "URL"', + step4: + 'Επιλέξτε το εικονιδιο "Cookies", πηγαίνετε στην καρτέλα "Allowed" και κάντε κλικ στο "deezer.com" > "cookies" > "arl"', + step5: + 'Κάντε δεξί κλικ μέσα στο πεδίο "Content", αρχικά επιλέξτε "Select All" και στη συνέχεια ξανά δεξί κλικ στο πεδίο "Content" και αντιγραφή.' + }, + step4: 'Πηγαίνετε στην καρτέλα Εφαρμογή (αν δεν τη βλέπετε κάντε κλικ στο διπλό βέλος)', + videoGuide: { + text: 'Εδώ θα βρείτε σχετικό {videoGuide}', + link: 'βίντεο' + } + }, + firefoxSteps: { + title: 'Firefox', + step1: 'Ανοίξτε τον Firefox', + step4: 'Πηγαίνετε στην καρτέλα Αποθήκευση (αν δεν τη βλέπετε κάντε κλικ στο διπλό βέλος)' + }, + commonSteps: { + step2: 'Μεταβείτε στη διεύθυνση "www.deezer.com" και συνδεθείτε στον λογαριασμό σας', + step3: 'Αφού συνδεθείτε, πατήστε F12 για να ανοίξετε τα Εργαλεία προγραμματιστή (Developer Tools)', + step5: 'Ανοίξτε το αναπτυσσόμενο μενού "cookie"', + step6: 'Επιλέξτε το "www.deezer.com"', + step7: 'Βρείτε το cookie "arl" (το οποίο πρέπει να έχει μήκος 192 χαρακτήρες)', + step8: 'Βεβαιωθείτε ότι αντιγράψτε μόνο την τιμή και όχι ολόκληρο το cookie', + lastStep: 'Και αυτό είναι το "ARL" σας. Τώρα μπορείτε να το χρησιμοποιήσετε στην εφαρμογή' + } + }, + update: 'Ενημέρωση ARL' + }, + logout: 'Αποσύνδεση', + login: 'Σύνδεση', + email: 'E-mail', + password: 'Password' + }, + appearance: { + title: 'Εμφάνιση', + slimDownloadTab: 'Λεπτή καρτέλα λήψης', + slimSidebar: 'Λεπτή πλαϊνή μπάρα', + searchButton: 'Εμφάνιση κουμπιού αναζήτησης', + bitrateTags: 'Εμφάνιση ετικέτας ποιότητας στην ουρά λήψης' + }, + downloadPath: { + title: 'Διαδρομή Λήψεων' + }, + templates: { + title: 'Πρότυπα', + tracknameTemplate: 'Πρότυπο ονόματος κομματιού', + tracknameAvailableVariables: 'Διαθέσιμες μεταβλητές ονόματος κομματιού', + albumTracknameTemplate: 'Πρότυπο άλμπουμ κομματιού', + albumTracknameAvailableVariables: 'Διαθέσιμες μεταβλητές άλμπουμ κομματιού', + playlistTracknameTemplate: 'Πρότυπο λίστας αναπαραγωγής κομματιού', + playlistTracknameAvailableVariables: 'Διαθέσιμες μεταβλητές λίστας αναπαραγωγής κομματιών' + }, + folders: { + title: 'Φάκελοι', + createPlaylistFolder: 'Δημιουργία φακέλου για λίστες αναπαραγωγής', + playlistNameTemplate: 'Πρότυπο φακέλου λίστας αναπαραγωγής', + createArtistFolder: 'Δημιουργία φακέλου για καλλιτέχνη', + artistNameTemplate: 'Πρότυπο φακέλου καλλιτέχνη', + createAlbumFolder: 'Δημιουργία φακέλου για άλμπουμ', + albumNameTemplate: 'Πρότυπο φακέλου άλμπουμ', + createCDFolder: 'Δημιουργία φακέλου για CDs', + createStructurePlaylist: 'Δημιουργία δομής φακέλου για λίστες αναπαραγωγής', + createSingleFolder: 'Δημιουργία δομής φακέλου για singles' + }, + trackTitles: { + title: 'Τίτλοι κομματιών', + padTracks: 'Εισαγωγή (0) στην αρίθμηση κομματιών', + paddingSize: 'Πλήθος μηδενικών', + illegalCharacterReplacer: 'Αντικατάσταση μη επιτρεπόμενων χαρακτήρων' + }, + downloads: { + title: 'Λήψεις', + queueConcurrency: 'Παράλληλες λήψεις', + maxBitrate: { + title: 'Προτιμώμενο Bitrate', + 9: 'FLAC 1411kbps', + 3: 'MP3 320kbps', + 1: 'MP3 128kbps' + }, + overwriteFile: { + title: 'Να αντικατασταθούν τα αρχεία;', + y: 'Ναι, να αντικατασταθεί το αρχείο', + n: 'Όχι, να μην αντικατασταθεί το αρχείο', + t: 'Να αντικατασταθούν μόνο τα tags', + b: 'Όχι, να διατηρηθούν και τα δύο αρχεία και να προστεθεί αύξων αριθμός στο διπλότυπο', + e: 'Όχι, και να μην ληφθούν υπόψιν οι επεκτάσεις' + }, + fallbackBitrate: 'Εναλλακτικό bitrate', + fallbackSearch: 'Εναλλακτική αναζήτηση', + fallbackISRC: 'Εναλλακτική αναζήτηση με ISRC', + feelingLucky: 'Παίξτε με τα CDN και τις κρυφές μνήμες', + logErrors: 'Να δημιουργηθούν αρχεία καταγραφής για σφάλματα', + logSearched: 'Δημιουργία αρχείων καταγραφής για κομμάτια που έχουν αναζητηθεί', + createM3U8File: 'Δημιουργία αρχείου λίστας αναπαραγωγής', + syncedLyrics: 'Δημιουργία αρχείων .lrc (Συγχρονισμός στίχων)', + playlistFilenameTemplate: 'Πρότυπο ονόματος αρχείου λίστας αναπαραγωγής', + saveDownloadQueue: 'Αποθήκευση της ουράς λήψης κατά το κλείσιμο της εφαρμογής' + }, + covers: { + title: 'Εξώφυλλα άλμπουμ', + saveArtwork: 'Αποθήκευση εξώφυλλων', + coverImageTemplate: 'Πρότυπο ονόματος εξωφύλλου', + saveArtworkArtist: 'Αποθήκευση εικόνας καλλιτέχνη', + artistImageTemplate: 'Πρότυπο εικόνας καλλιτέχνη', + localArtworkSize: 'Τοπικό μέγεθος εξωφύλλου', + embeddedArtworkSize: 'Ενσωματωμένο μέγεθος εξωφύλλου', + localArtworkFormat: { + title: 'Μορφή τοπικού εξωφύλλου', + jpg: 'Αρχείο εικόνας jpeg', + png: 'Αρχείο εικόνας png', + both: 'Αρχείο jpeg και png' + }, + jpegImageQuality: 'Ποιότητα εικόνας JPEG', + embeddedArtworkPNG: 'Αποθήκευση ενσωματωμένου εξωφύλλου σε PNG αρχείο', + embeddedPNGWarning: + 'Τα αρχεία PNG δεν υποστηρίζονται επίσημα από το Deezer και μπορεί να αντιμετωπίσετε προβλήματα', + imageSizeWarning: + 'Οποιαδήποτε εικόνα πάνω από 1200 pixels δεν υποστηρίζονται επίσημα από το Deezer και μπορεί να αντιμετωπίσετε προβλήματα', + coverDescriptionUTF8: 'Αποθήκευση περιγραφής εξωφύλλου χρησιμοποιώντας UTF8 (iTunes Cover Fix)' + }, + tags: { + head: 'Ποιες ετικέτες να αποθηκευθούν', + title: 'Τίτλος', + artist: 'Καλλιτέχνης', + artists: 'Ετικέτα επιπλέον καλλιτεχνών', + album: 'Άλμπουμ', + cover: 'Εξώφυλλο', + trackNumber: 'Αριθμός Κομματιού', + trackTotal: 'Σύνολο Κομματιών', + discNumber: 'Αριθμός Δίσκου', + discTotal: 'Σύνολο Δίσκων', + albumArtist: 'Καλλιτέχνης του Άλμπουμ', + genre: 'Είδος', + year: 'Χρονιά', + date: 'Ημερομηνία', + explicit: 'Ρητοί Στίχοι', + isrc: 'ISRC', + length: 'Διάρκεια Κομματιού', + barcode: 'Barcode Άλμπουμ (UPC)', + bpm: 'BPM', + replayGain: 'Replay Gain', + label: 'Ετικέτα Άλμπουμ', + lyrics: 'Μη Συγχρονισμένοι Στίχοι', + syncedLyrics: 'Συγχρονισμένοι Στίχοι', + copyright: 'Copyright', + composer: 'Συνθέτης', + involvedPeople: 'Εμπλεκόμενοι', + source: 'Πηγή και Αναγνωριστικό (ID) Κομματιού', + artistsWarning: + 'Η απενεργοποίηση της ετικέτας επιπλέον καλλιτεχνών ενώ δεν χρησιμοποιείτε τυπικές προδιαγραφές δεν θα διατηρήσει την υποστήριξη πολλών καλλιτεχνών' + }, + other: { + title: 'Λοιπά', + autoCheckForUpdates: 'Έλεγχος για ενημερώσεις κατά την εκκίνηση', + savePlaylistAsCompilation: 'Αποθήκευση λιστών αναπαραγωγής ως συλλογή', + useNullSeparator: 'Χρήση μηδενικού διαχωριστικού', + saveID3v1: 'Αποθήκευση του ID3v1', + multiArtistSeparator: { + title: 'Πώς θα θέλατε να χωρίσετε τους αγαπημένους σας καλλιτέχνες;', + nothing: 'Αποθήκευση μόνο του κύριου καλλιτέχνη', + default: 'Χρηση τυπικών προδιαγραφών', + andFeat: 'Χρήση του συμβόλου (&) και της ένδειξης (feat.)', + using: 'Χρήση "{separator}"', + warning: + 'Η χρήση οποιουδήποτε διαχωριστικού εκτός από την τυπική προδιαγραφή θα προσθέσει μια επιπλέον ετικέτα επιπλέον καλλιτεχνών για να διατηρήσει την υποστήριξη πολλών καλλιτεχνών' + }, + singleAlbumArtist: 'Αποθήκευση μόνο του κύριου καλλιτέχνη του άλμπουμ', + albumVariousArtists: 'Αποθήκευση των άλμπουμ διάφορων καλλιτεχνών μέσα στα άλμπουμ καλλιτεχνών', + removeAlbumVersion: 'Κατάργηση της έκδοσης του άλμπουμ από τον τίτλο του κομματιού', + removeDuplicateArtists: 'Κατάργηση των συνδυασμών των καλλιτεχνών', + dateFormat: { + title: 'Μορφή ημερομηνίας για αρχεία FLAC', + year: 'ΕΕΕΕ', + month: 'ΜΜ', + day: 'ΗΗ' + }, + featuredToTitle: { + title: 'Τι να γίνεται με τους συμμετέχοντες καλλιτέχνες (feat.)', + 0: 'Τίποτα', + 1: 'Αφαίρεση από τον τίτλο', + 3: 'Κατάργηση από τον τίτλο του κομματιού και τον τίτλο του άλμπουμ', + 2: 'Μετακίνηση στον τίτλο' + }, + titleCasing: 'Δομή τίτλου', + artistCasing: 'Δομή καλλιτέχνη', + casing: { + nothing: 'Να μείνει αμετάβλητο', + lower: 'Όλα πεζά', + upper: 'Όλα κεφαλαία', + start: 'Κεφαλαίο το πρώτο γράμμα κάθε λέξης', + sentence: 'Σαν μια πρόταση' + }, + previewVolume: 'Ένταση προεπισκόπησης', + executeCommand: { + title: 'Εντολή για εκτέλεση μετά τη λήψη', + description: 'Αφήστε κενό για καμία ενέργεια' + } + }, + spotify: { + title: 'Χαρακτηριστικά Spotify', + clientID: 'Spotify ClientID', + clientSecret: 'Spotify Client Secret', + username: 'Spotify Username', + question: 'Πώς μπορώ να ενεργοποιήσω τις δυνατότητες Spotify;', + howTo: { + prologue: { + p1: 'Το "Spotify Features" είναι ένα σύνολο λειτουργιών που σας επιτρέπει να μετατρέπετε συνδέσμους κομματιών και άλμπουμ "Spotify" σε "Deezer".', + p2: 'Εάν τοποθετήσετε έναν σύνδεσμο "Spotify Playlist", η εφαρμογή θα μετατρέψει αυτόματα όλους τους συνδέσμους των κομματιών μέσα σε αυτό το "playlist" σε κομμάτια "Deezer".', + p3: 'Επίσης η ενεργοποίηση αυτού του συνόλου λειτουργιών θα σας επιτρέψει να δείτε τις δημόσιες λίστες αναπαραγωγής του "Spotify" στην καρτέλα αγαπημένων.' + }, + info: 'Για λόγους ασφαλείας θα χρειαστεί να παρέχετε το δικό σας "Client ID" και "Client Secret"', + clientSecretQuestion: { + title: 'Πώς μπορώ να βρω το δικό μου "Client ID" και το "Client Secret"; ', + step1: { + text: 'Μεταβείτε στο {spotifyDevelopersDashboard} και συνδεθείτε με τον λογαριασμό σας στο "Spotify".', + spotifyDevelopersDashboard: "Spotify for Developers's Dashboard" + }, + step2: { + text: 'Κάντε κλικ στο "Create an App".', + imageAlt: 'Κουμπί "Create an App" στο "Spotify for Developers Dashboard"' + }, + step3: { + text: 'Συμπληρώστε τα πεδία "Όνομα εφαρμογής" και "Περιγραφή εφαρμογής" και επιλέξτε και τα δύο "checkboxes". Στη συνέχεια κάντε κλικ στο κουμπί "Create".\n', + imageAlt: 'Κουμπί δημιουργία φόρμας εφαρμογής' + }, + step4: { + text: 'Τώρα μπορείτε να δείτε το "Client ID". Εάν κάνετε κλικ στο "Show Client Secret" το μυστικό του πελάτη θα αποκαλυφθεί.\n', + imageAlt: 'Προβολή του "Client ID" και του "Client Secret"' + }, + step5: + 'Και τώρα μπορείτε να κάνετε αντιγραφή-επικόλληση αυτών των αποτελεσμάτων στα κατάλληλα πεδία στις ρυθμίσεις.' + }, + usernameQuestion: { + title: 'Πώς μπορώ να βρω το "username" μου στο "Spotify";', + step1: { + text: 'Μπορείτε να βρείτε το "username" σας στο "Spotify" από το {overviewPage} στη σελίδα του "Spotify"', + overviewPage: '"Overview page"' + } + } + } + }, + reset: 'Επαναφορά στις προεπιλεγμένες ρυθμίσεις', + resetMessage: 'Είστε βέβαιοι ότι θέλετε να επιστρέψετε στις προεπιλεγμένες ρυθμίσεις;', + save: 'Αποθήκευση', + toasts: { + init: 'Οι ρυθμίσεις φορτώθηκαν!', + update: 'Οι ρυθμίσεις ενημερώθηκαν!', + reset: 'Οι ρυθμίσεις επαναφέρθηκαν!', + ARLcopied: 'Το ARL αντιγράφηκε' + }, + logs: { + title: 'Αρχεία Καταγραφής', + areLogsActive: 'Ενεργοποιημένα' + } + }, + sidebar: { + home: 'αρχική', + search: 'αναζήτηση', + charts: 'διαγράμματα', + favorites: 'αγαπημένα', + linkAnalyzer: 'αναλυτής συνδέσμου', + settings: 'ρυθμίσεις', + logs: 'αρχεία καταγραφής', + about: 'σχετικά με' + }, + tracklist: { + downloadSelection: 'Λήψη επιλεγμένων' + }, + logs: { + event: 'Συμβάν', + data: 'Δεδομένα' + } +} + +export default gr diff --git a/webui/src/lang/en.mjs b/webui/src/lang/en.mjs new file mode 100644 index 0000000..83e9d12 --- /dev/null +++ b/webui/src/lang/en.mjs @@ -0,0 +1,515 @@ +const en = { + globals: { + welcome: 'Welcome to deemix', + back: 'back', + loading: 'loading', + download: 'Download {thing}', + by: 'by {artist}', + in: 'in {album}', + download_hint: 'Download', + play_hint: 'Play', + toggle_download_tab_hint: 'Expand/Collapse', + clean_queue_hint: 'Clear Finished', + cancel_queue_hint: 'Cancel All', + open_downloads_folder: 'Open Downloads Folder', + cut: 'cut', + copy: 'copy', + copyLink: 'copy link', + copyImageLink: 'copy image link', + copyDeezerLink: 'copy deezer link', + paste: 'paste', + listTabs: { + empty: '', + all: 'all', + discography: 'discography', + top_result: 'top result', + album: 'album | albums', + artist: 'artist | artists', + single: 'single | singles', + title: 'title | titles', + track: 'track | tracks', + playlist: 'playlist | playlists', + compile: 'compilation | compilations', + ep: 'ep | eps', + bundle: 'bundle | bundles', + more: 'More albums', + featured: 'Featured in', + spotifyPlaylist: 'spotify playlist | spotify playlists', + releaseDate: 'release date', + error: 'error', + trackN: '0 tracks | {n} track | {n} tracks', + albumN: '0 albums | {n} album | {n} albums', + artistN: '0 artists | {n} artist | {n} artists', + releaseN: '0 releases | {n} release | {n} releases', + playlistN: '0 playlists | {n} playlist | {n} playlists' + }, + yes: 'yes', + no: 'no', + empty: 'empty' + }, + about: { + appStatus: { + online: 'app online', + offline: 'app offline' + }, + updates: { + currentVersion: 'Current Version', + currentWebuiVersion: 'Current WebUI Version', + versionNotAvailable: 'N/A', + updateAvailable: `You're not running the latest version available: {version}`, + deemixVersion: 'deemix lib version' + }, + titles: { + usefulLinks: 'Useful Links', + bugReports: 'Bug Reports', + contributing: 'Contributing', + donations: 'Donations', + license: 'License' + }, + subtitles: { + bugReports: "Is there something that isn't working in deemix? Tell us!", + contributing: 'You want to contribute to this project? You can do it in different ways!', + donations: 'You want to contribute monetarily? You could make a donation!' + }, + usesLibrary: 'This app uses the deemix library, which you can use to make your own UI for deemix.', + thanks: `Thanks to rtonno, uhwot and lollilol for helping me with this project and to BasCurtiz for making the icon.`, + upToDate: { + text: `Stay up to date with the updates by following the {newsChannel} on Telegram.`, + newsChannel: 'news channel' + }, + officialWebsite: 'Official Website', + officialRepo: 'Official Library Repository', + officialWebuiRepo: 'Official WebUI Repository', + officialSubreddit: 'Official Subreddit', + newsChannel: 'News Channel', + devlogChannel: 'Devlog Channel', + questions: { + text: `If you have questions or problems with the app, search for a solution on the {subreddit} first. Then, if you don't find anything you can make a post with your issue on the subreddit.`, + subreddit: 'subreddit' + }, + beforeReporting: `Before reporting a bug make sure you're running the latest version of the app and that what you want to report is actually a bug and not something that's wrong only on your end.`, + beSure: `Make sure the bug is reproducible on other machines and also DO NOT report a bug if it's already been reported.`, + duplicateReports: 'Duplicate bug reports will be closed, so keep an eye out on that.', + dontOpenIssues: `DO NOT open issues for asking questions, there is a subreddit for that.`, + newUI: { + text: `If you're fluent in python you could try to make a new UI for the app using the base library, or fix bugs in the library with a pull request on the {repo}.`, + repo: 'repo' + }, + acceptFeatures: `I accept features as well, but no complex things, as they can be implementend directly in the app and not the library.`, + otherLanguages: `If you're fluent in another programming language you could try to port deemix into other programming languages!`, + understandingCode: `You need help understanding the code? Just hit RemixDev up on Telegram or Reddit.`, + contributeWebUI: { + text: `If you know Vue.js (JavaScript), HTML or CSS you could contribute to the {webui}.`, + webui: 'WebUI' + }, + itsFree: `You should remember that this is a free project and you should support the artists you love before supporting the developers.`, + notObligated: `Don't feel obligated to donate, I appreciate you anyway!`, + lincensedUnder: { + text: `This work is licensed under the {gpl3}.`, + gpl3: 'GNU General Public License 3.0' + } + }, + charts: { + title: 'Charts', + changeCountry: 'Change Country', + download: 'Download Chart' + }, + errors: { + title: 'Errors for {name}', + postTitle: 'After download errors', + ids: { + invalidURL: 'URL not recognized', + unsupportedURL: 'URL not supported yet', + ISRCnotOnDeezer: 'Track ISRC is not available on Deezer', + notYourPrivatePlaylist: "You can't download others private playlists.", + spotifyDisabled: 'Spotify Features is not setted up correctly.', + trackNotOnDeezer: 'Track not found on Deezer!', + albumNotOnDeezer: 'Album not found on Deezer!', + notOnDeezer: 'Track not available on Deezer!', + notEncoded: 'Track not yet encoded!', + notEncodedNoAlternative: 'Track not yet encoded and no alternative found!', + wrongBitrate: 'Track not found at desired bitrate.', + wrongBitrateNoAlternative: 'Track not found at desired bitrate and no alternative found!', + no360RA: 'Track is not available in Reality Audio 360.', + notAvailable: "Track not available on Deezer's servers!", + notAvailableNoAlternative: "Track not available on Deezer's servers and no alternative found!", + noSpaceLeft: 'No space left on the device!', + albumDoesntExists: "Track's album doesn't exist, failed to gather info.", + wrongLicense: "Your account can't stream tracks in {bitrate}.", + wrongGeolocation: "Your account can't stream the track from your current country.", + wrongGeolocationNoAlternative: + "Your account can't stream the track from your current country and no alternative found." + } + }, + favorites: { + title: 'Favorites', + noPlaylists: 'No Playlists found', + noAlbums: 'No Favorite Albums found', + noArtists: 'No Favorite Artists found', + noTracks: 'No Favorite Tracks found' + }, + home: { + needTologin: 'You need to log into your Deezer account before you can start downloading.', + openSettings: 'Open Settings', + sections: { + popularPlaylists: 'Popular playlists', + popularAlbums: 'Most streamed albums' + } + }, + linkAnalyzer: { + info: 'You can use this section to find more information about the link you are trying to download.', + useful: + "This is useful if you're trying to download some tracks that are not available in your country and want to know where they are available, for instance.", + linkNotSupported: 'This link is not yet supported', + linkNotSupportedYet: 'Seems like this link is not yet supported, try analyzing another one.', + table: { + id: 'ID', + isrc: 'ISRC', + upc: 'UPC', + duration: 'Duration', + diskNumber: 'Disk Number', + trackNumber: 'Track Number', + releaseDate: 'Release Date', + bpm: 'BPM', + label: 'Label', + recordType: 'Record Type', + genres: 'Genres', + tracklist: 'Tracklist', + readable: 'Readable', + available: 'Available' + }, + countries: 'Countries', + noCountries: 'This track is not available in any country.' + }, + search: { + startSearching: 'Start searching!', + description: + 'You can search a track, a whole album, an artist, a playlist.... everything! You can also paste a Deezer link', + fans: '{n} fans', + noResults: 'No results', + noResultsTrack: 'No Tracks found', + noResultsAlbum: 'No Albums found', + noResultsArtist: 'No Artists found', + noResultsPlaylist: 'No Playlists found', + error: 'An error occurred, please try again later.' + }, + searchbar: 'Search anything you want (or just paste a link)', + downloads: 'downloads', + toasts: { + restoringQueue: 'Restoring download queue...', + queueRestored: 'Download queue restored!', + addedToQueue: '{item} added to queue', + addedMoreToQueue: '{n} items added to queue', + alreadyInQueue: '{item} is already in queue!', + finishDownload: '{item} finished downloading.', + allDownloaded: 'All downloads completed!', + refreshFavs: 'Refresh completed!', + loggingIn: 'Logging in...', + loggedIn: 'Logged in', + alreadyLogged: 'Already logged in', + loginFailed: "Couldn't log in", + loggedOut: 'Logged out', + cancellingCurrentItem: 'Cancelling current item.', + currentItemCancelled: 'Current item cancelled.', + startAddingArtist: 'Adding {artist} albums to queue', + finishAddingArtist: 'Added {artist} albums to queue', + startConvertingSpotifyPlaylist: 'Converting spotify tracks to Deezer tracks', + finishConvertingSpotifyPlaylist: 'Spotify playlist converted', + loginNeededToDownload: 'You need to log in to download tracks!', + queueErrorCantStream: `Your account can't stream at {bitrate}!`, + deezerNotAvailable: 'Deezer is not available in your country. You should use a VPN.', + deezerNotReachable: "The app can't reach Deezer. Check your internet connection, your firewall or your antivirus.", + startGeneratingItems: 'Processing {n} items...', + finishGeneratingItems: 'Generated {n} items.', + noLovedPlaylist: 'No loved tracks playlist!', + checkingUpdates: 'Checking for updates...', + noUpdateAvailable: 'No updates found', + updateAvailable: 'An update is available!', + wrongSpotifyUsername: '{username} is not a valid spotify username' + }, + settings: { + title: 'Settings', + languages: 'Languages', + login: { + title: 'Login', + loggedIn: 'You are logged in as {username}', + arl: { + title: 'Use ARL instead', + question: 'How do I get my own ARL?', + howTo: { + prologue: { + p1: 'Deezer keeps track of login session by using a cookie called ARL.', + p2: 'Deemix uses that cookie to get the metadata that it needs to download the tracks from Deezer.', + p3: 'ARLs last for 3 months, after that Deezer asks you to log in again. The same method is used in deemix.', + p4: 'Following one of the guides below you can get your own account ARL.', + warning: "Use this method only if email and password doesn't work." + }, + chromeSteps: { + title: 'Chrome', + step1: 'Open Chrome', + easyWay: { + title: 'Chrome (Easy way)', + step3: 'Click on the little "lock" icon next the URL', + step4: 'Click on Cookies > deezer.com > cookies > arl', + step5: 'Select the string next to Content, and Copy' + }, + step4: "Go under the Application tab (if you don't see it click the double arrow)", + videoGuide: { + text: "Here's a {videoGuide}", + link: 'video guide' + } + }, + firefoxSteps: { + title: 'Firefox', + step1: 'Open Firefox', + step4: "Go under the Storage tab (if you don't see it click the double arrow)" + }, + commonSteps: { + step2: 'Go to www.deezer.com and log into your account', + step3: 'After logging in press F12 to open up Developer Tools', + step5: 'Open the cookie dropdown', + step6: 'Select www.deezer.com', + step7: 'Find the `arl` cookie (It should be 192 chars long)', + step8: 'Make sure only copy the value and not the entire cookie', + lastStep: "That's your ARL, now you can use it in the app" + } + }, + update: 'Force Update ARL' + }, + logout: 'Logout', + login: 'Login', + email: 'E-mail', + password: 'Password' + }, + appearance: { + title: 'Appearance', + slimDownloadTab: 'Slim download tab', + slimSidebar: 'Slim Sidebar', + searchButton: 'Show search button', + bitrateTags: 'Show quality tag in download queue' + }, + downloadPath: { + title: 'Download Path' + }, + templates: { + title: 'Templates', + tracknameTemplate: 'Trackname template', + tracknameAvailableVariables: 'Available trackname variables', + albumTracknameTemplate: 'Album track template', + albumTracknameAvailableVariables: 'Available album track variables', + playlistTracknameTemplate: 'Playlist track template', + playlistTracknameAvailableVariables: 'Available playlist track variables' + }, + folders: { + title: 'Folders', + createPlaylistFolder: 'Create folder for playlists', + playlistNameTemplate: 'Playlist folder template', + createArtistFolder: 'Create folder for artist', + artistNameTemplate: 'Artist folder template', + createAlbumFolder: 'Create folder for album', + albumNameTemplate: 'Album folder template', + createCDFolder: 'Create folder for CDs', + createStructurePlaylist: 'Create folder structure for playlists', + createSingleFolder: 'Create folder structure for singles' + }, + trackTitles: { + title: 'Track titles', + padTracks: 'Pad tracks', + paddingSize: 'Overwrite padding size', + illegalCharacterReplacer: 'Illegal Character replacer' + }, + downloads: { + title: 'Downloads', + queueConcurrency: 'Concurrent Downloads', + maxBitrate: { + title: 'Preferred Bitrate', + 9: 'FLAC 1411kbps', + 3: 'MP3 320kbps', + 1: 'MP3 128kbps' + }, + overwriteFile: { + title: 'Should I overwrite the files?', + y: 'Yes, overwrite the file', + n: "No, don't overwrite the file", + t: 'Overwrite only the tags', + b: 'No, keep both files and add a number to the duplicate', + e: "No, and don't look at the extensions", + l: 'Overwrite only if upgrading bitrate (mp3 only)' + }, + fallbackBitrate: 'Bitrate fallback', + fallbackSearch: 'Search fallback', + fallbackISRC: 'Fallback with ISRC search', + feelingLucky: 'Gamble with CDNs and caches', + logErrors: 'Create log files for errors', + logSearched: 'Create log files for searched tracks', + createM3U8File: 'Create playlist file', + syncedLyrics: 'Create .lrc files (Sync Lyrics)', + playlistFilenameTemplate: 'Playlist filename template', + clearQueueOnExit: 'Clear download queue when closing the app' + }, + covers: { + title: 'Album covers', + saveArtwork: 'Save Covers', + coverImageTemplate: 'Cover name template', + saveArtworkArtist: 'Save artist image', + artistImageTemplate: 'Artist image template', + localArtworkSize: 'Local artwork size', + embeddedArtworkSize: 'Embedded artwork size', + localArtworkFormat: { + title: 'What format do you want the local artwork to be?', + jpg: 'A jpeg image', + png: 'A png image', + both: 'Both a jpeg and a png' + }, + jpegImageQuality: 'JPEG image quality', + embeddedArtworkPNG: 'Save embedded artwork as PNG', + embeddedPNGWarning: 'PNGs are not officialy supported by Deezer and can be buggy', + imageSizeWarning: 'Anything above x1200 is not officialy used by Deezer, you may encounter issues', + coverDescriptionUTF8: 'Save cover description using UTF8 (iTunes Cover Fix)' + }, + tags: { + head: 'Which tags to save', + title: 'Title', + artist: 'Artist', + artists: 'Extra ARTISTS tag', + album: 'Album', + cover: 'Cover', + trackNumber: 'Track Number', + trackTotal: 'Track Total', + discNumber: 'Disc Number', + discTotal: 'Disc Total', + albumArtist: 'Album Artist', + genre: 'Genre', + year: 'Year', + date: 'Date', + explicit: 'Explicit Lyrics', + isrc: 'ISRC', + length: 'Track Length', + barcode: 'Album Barcode (UPC)', + bpm: 'BPM', + replayGain: 'Replay Gain', + label: 'Album Label', + lyrics: 'Unsynchronized Lyrics', + syncedLyrics: 'Synchronized Lyrics', + copyright: 'Copyright', + composer: 'Composer', + involvedPeople: 'Involved People', + source: 'Source and song ID', + artistsWarning: + "Disabling the ARTISTS tag while not using standard specification won't preserve multiartist support" + }, + other: { + title: 'Other', + autoCheckForUpdates: 'Check for updates on startup', + savePlaylistAsCompilation: 'Save playlists as compilation', + useNullSeparator: 'Use null separator', + saveID3v1: 'Save ID3v1 as well', + multiArtistSeparator: { + title: 'How would you like to separate your artists?', + nothing: 'Save only the main artist', + default: 'Using standard specification', + andFeat: 'Using & and feat.', + using: 'Using "{separator}"', + warning: + 'Using any separator other than the standard specification will add a extra ARTISTS tag to preserve multiartist support' + }, + singleAlbumArtist: 'Save only the main album artist', + albumVariousArtists: 'Keep "Various Artists" in the Album Artists', + removeAlbumVersion: 'Remove "Album Version" from track title', + removeDuplicateArtists: 'Remove combinations of artists', + dateFormat: { + title: 'Date format for FLAC files', + year: 'YYYY', + month: 'MM', + day: 'DD' + }, + featuredToTitle: { + title: 'What should I do with featured artists?', + 0: 'Nothing', + 1: 'Remove it from the title', + 3: 'Remove it from the title and the album title', + 2: 'Move it to the title' + }, + titleCasing: 'Title casing', + artistCasing: 'Artist casing', + casing: { + nothing: 'Keep unchanged', + lower: 'lowercase', + upper: 'UPPERCASE', + start: 'Start Of Each Word', + sentence: 'Like a sentence' + }, + previewVolume: 'Preview Volume', + executeCommand: { + title: 'Command to execute after download', + description: 'Leave blank for no action' + } + }, + spotify: { + title: 'Spotify Features', + clientID: 'Spotify ClientID', + clientSecret: 'Spotify Client Secret', + username: 'Spotify Username', + question: 'How do I enable Spotify Features?', + howTo: { + prologue: { + p1: '"Spotify Features" is a set of features that lets you convert Spotify tracks and albums links into Deezer ones.', + p2: 'If you provide a Spotify Playlist link the app will automatically convert all the links of the tracks inside it into deezer tracks.', + p3: 'Enabling this set of features will let you see your public Spotify playlists in the favorites tab as well.' + }, + info: 'For security reasons you will need to provide your own Client ID and Client Secret', + clientSecretQuestion: { + title: 'How do I get my Client ID and Client Secret?', + step1: { + text: 'Connect to {spotifyDevelopersDashboard} and login with your Spotify account.', + spotifyDevelopersDashboard: "Spotify for Developers's Dashboard" + }, + step2: { + text: 'Click on "Create an App".', + imageAlt: "Create an App button on Spotify for Developers's Dashboard" + }, + step3: { + text: 'Fill out the "App name" and "App description" fields and check both checkboxes. Then click on the "Create" button.', + imageAlt: 'Create an app form' + }, + step4: { + text: 'Now you can see the Client ID. If you click on "Show Client Secret" the client secret will be revealed.', + imageAlt: 'Screen of client ID and Secret' + }, + step5: 'Now you can copy-paste those results in the appropriate fields in the settings.' + }, + usernameQuestion: { + title: 'How do I get my Spotify Username?', + step1: { + text: "You can get your Spotify Username from the {overviewPage} on Spotify's Website.", + overviewPage: 'Overview page' + } + } + } + }, + reset: 'Reset to Default', + resetMessage: 'Are you sure you want to go back to default settings?', + save: 'Save', + toasts: { + init: 'Settings loaded!', + update: 'Settings updated!', + reset: 'Settings reset to default!', + ARLcopied: 'ARL copied to clipboard' + } + }, + sidebar: { + home: 'home', + search: 'search', + charts: 'charts', + favorites: 'favorites', + linkAnalyzer: 'link analyzer', + settings: 'settings', + logs: 'logs', + about: 'about' + }, + tracklist: { + downloadSelection: 'Download selection' + } +} + +export default en diff --git a/webui/src/lang/es.mjs b/webui/src/lang/es.mjs new file mode 100644 index 0000000..b63653d --- /dev/null +++ b/webui/src/lang/es.mjs @@ -0,0 +1,394 @@ +const es = { + globals: { + welcome: 'Bienvenido a deemix', + back: 'atrás', + loading: 'cargando', + download: 'Descarga {thing}', + by: 'por {artist}', + in: 'en {album}', + download_hint: 'Descargar', + play_hint: 'Reproducir', + toggle_download_tab_hint: 'Expandir/Colapsar', + clean_queue_hint: 'Limpieza terminada', + cancel_queue_hint: 'Cancelar todo', + open_downloads_folder: 'Abrir la carpeta de descargas', + cut: 'cortar', + copy: 'copiar', + copyLink: 'copiar vinculo', + copyImageLink: 'copiar el vínculo de la imagen', + copyDeezerLink: 'copiar el vínculo de Deezer', + paste: 'pegar', + listTabs: { + empty: '', + all: 'todo', + top_result: 'mejor resultado', + album: 'álbum | álbumes', + artist: 'artista | artistas', + single: 'single | singles', + title: 'título | títulos', + track: 'pista | pistas', + trackN: '0 pistas | {n} pista | {n} pistas', + releaseN: '0 entregas | {n} entrega | {n} entregas', + playlist: 'lista de reproducción | listas de reproducción', + compile: 'compilación | compilaciones', + ep: 'ep | eps', + more: 'Más álbumes', + featured: 'Aparece en', + spotifyPlaylist: 'lista de reproducción spotify | listas de reproducción spotify', + releaseDate: 'fecha de publicación', + error: 'error' + } + }, + about: { + updates: { + currentVersion: 'Versión actual', + versionNotAvailable: 'N/D', + updateAvailable: `No estás ejecutando la última versión disponible: {version}`, + deemixVersion: 'versión de la biblioteca deemix' + }, + titles: { + usefulLinks: 'Enlaces útiles', + bugReports: 'Reportar fallos', + contributing: 'Contribuye', + donations: 'Donaciones', + license: 'Licencia' + }, + subtitles: { + bugReports: '¿Hay algo que no funcione en Deemix? ¡Díganoslo!', + contributing: '¿Quieres contribuir a este proyecto? ¡Puedes hacerlo de diferentes maneras!', + donations: '¿Quiere contribuir monetariamente? ¡Puedes hacer una donación!' + }, + usesLibrary: + 'Esta aplicación usa la biblioteca deemix, que puedes usar para hacer tu propia interfaz de usuario para deemix.', + thanks: `Gracias a rtonno, uhwot y lollilol por ayudarme con este proyecto, a BasCurtiz por hacer el icono.`, + upToDate: { + text: `Mantente al día con las actualizaciones siguiendo el {newsChannel} en Telegram.`, + newsChannel: 'canal de noticias' + }, + officialWebsite: 'Página web oficial', + officialRepo: 'Repositorio de la biblioteca oficial', + officialWebuiRepo: 'Repositorio oficial de WebUI', + officialSubreddit: 'Subreddit oficial', + newsChannel: 'Canal de noticias', + questions: { + text: `Si tienes preguntas o problemas con la aplicación, busca una solución en el {subreddit} primero. Luego, si no encuentras nada puedes hacer un post con tu problema en el subreddit.`, + subreddit: 'subreddit' + }, + beforeReporting: + 'Antes de informar de un error asegúrese de que está ejecutando la última versión de la aplicación y que lo que quiere informar es en realidad un error y no algo que está mal sólo en su extremo.', + beSure: + 'Asegúrate de que el fallo es reproducible en otras máquinas y también NO reporte un fallo si ya ha sido reportado.', + duplicateReports: 'Los informes de errores duplicados se cerrarán, así que manténgase al tanto de eso.', + dontOpenIssues: 'NO abra problemas para hacer preguntas, hay un subreddit para eso.', + newUI: { + text: `Si tienes fluidez en Python podrías intentar hacer una nueva interfaz de usuario para la aplicación usando la biblioteca base, o arreglar los errores de la biblioteca con una petición pull en el {repo}.`, + repo: 'repo' + }, + acceptFeatures: + 'También acepto características, pero no cosas complejas, ya que se pueden implementar directamente en la aplicación y no en la biblioteca.', + otherLanguages: + '¡Si dominas otro lenguaje de programación podrías intentar portar Deemix a otros lenguajes de programación!', + understandingCode: '¿Necesitas ayuda para entender el código? Sólo tienes que poner RemixDev en Telegram o Reddit.', + contributeWebUI: { + text: `Si conoces Vue.js (JavaScript), HTML o CSS podrías contribuir a la {webui}.`, + webui: 'WebUI' + }, + itsFree: + 'Debes recordar que este es un proyecto libre y debes apoyar a los artistas que amas antes de apoyar a los desarrolladores.', + notObligated: 'No te sientas obligado a donar, ¡te aprecio de todas formas!', + lincensedUnder: { + text: `Esta obra está autorizada bajo una {gpl3}.`, + gpl3: 'GNU Licencia Pública General 3.0' + } + }, + charts: { + title: 'Listas', + changeCountry: 'Cambiar país', + download: 'Descargar la lista' + }, + errors: { + title: 'Errores para {name}', + ids: { + invalidURL: 'No se reconoce la URL', + unsupportedURL: 'La URL aún no está soportada', + ISRCnotOnDeezer: 'La pista ISRC no está disponible en Deezer', + notYourPrivatePlaylist: 'No puedes descargar otras listas de reproducción privadas.', + spotifyDisabled: 'Las funciones de Spotify no está configurado correctamente.', + trackNotOnDeezer: '¡No se encontró la pista en Deezer!', + albumNotOnDeezer: '¡El álbum no se encuentra en Deezer!', + notOnDeezer: '¡Pista no disponible en Deezer!', + notEncoded: '¡Pista aún no codificada!', + notEncodedNoAlternative: '¡Pista aún no codificada y no se ha encontrado ninguna alternativa!', + wrongBitrate: 'La pista no se encuentra a la velocidad de bitrate deseada.', + wrongBitrateNoAlternative: + '¡Pista no encontrada a la tasa de bits deseada y no se ha encontrado ninguna alternativa!', + no360RA: 'La pista no está disponible en Reality Audio 360.', + notAvailable: '¡La pista no está disponible en los servidores de Deezer!', + notAvailableNoAlternative: + '¡La pista no está disponible en los servidores de Deezer y no se ha encontrado ninguna alternativa!', + noSpaceLeft: '¡No queda espacio en el dispositivo!' + } + }, + favorites: { + title: 'Favoritos', + noPlaylists: 'No se han encontrado listas de reproducción', + noAlbums: 'No se han encontrado álbumes favoritos', + noArtists: 'No se han encontrado artistas favoritos', + noTracks: 'No se han encontrado pistas favoritas' + }, + home: { + needTologin: 'Necesitas entrar en tu cuenta de Deezer antes de poder empezar a descargar.', + openSettings: 'Abrir la configuración', + sections: { + popularPlaylists: 'Listas de reproducción populares', + popularAlbums: 'Los álbumes más stremeados' + } + }, + linkAnalyzer: { + info: 'Puedes usar esta sección para encontrar más información sobre el enlace que estás tratando de descargar.', + useful: + 'Esto es útil si está tratando de descargar algunas pistas que no están disponibles en su país y quiere saber dónde están disponibles, por ejemplo.', + linkNotSupported: 'Este enlace aún no está soportado', + linkNotSupportedYet: 'Parece que este enlace aún no está soportado, intenta analizar otro.', + table: { + id: 'ID', + isrc: 'ISRC', + upc: 'UPC', + duration: 'Duración', + diskNumber: 'Número del disco', + trackNumber: 'Número de la pista', + releaseDate: 'Fecha de lanzamiento', + bpm: 'BPM', + label: 'Etiqueta', + recordType: 'Tipo de grabación', + genres: 'Géneros', + tracklist: 'Lista de pista' + } + }, + search: { + startSearching: '¡Comienza a buscar!', + description: + 'Puedes buscar un tema, un álbum entero, un artista, una lista de reproducción... ¡todo! También puedes pegar un enlace de Deezer', + fans: '{n} fans', + noResults: 'Ningun resultado', + noResultsTrack: 'No se encontraron pistas', + noResultsAlbum: 'No se encontraron álbumes', + noResultsArtist: 'No se encontraron artistas', + noResultsPlaylist: 'No se encontraron listas de reproducción' + }, + searchbar: 'Busca lo que quieras (o simplemente pega un enlace)', + downloads: 'descargas', + toasts: { + restoringQueue: 'Restaurando la cola de descarga...', + queueRestored: '¡Cola de descarga restaurada!', + addedToQueue: '{item} añadidos a la cola', + addedMoreToQueue: '{n} elementos añadidos a la cola', + alreadyInQueue: '¡{item} ya está en la cola!', + finishDownload: '{item} terminado de descargar.', + allDownloaded: '¡Todas las descargas se han completado!', + refreshFavs: '¡Actualización completada!', + loggingIn: 'Conectando...', + loggedIn: 'Conectado', + alreadyLogged: 'Ya está conectado', + loginFailed: 'No se puede conectar', + loggedOut: 'Desconectado', + cancellingCurrentItem: 'Cancelando el elemento actual.', + currentItemCancelled: 'El elemento actual se ha cancelado.', + startAddingArtist: 'Añadiendo los álbumes de {artist} a la cola', + finishAddingArtist: 'Se ha añadido los álbumes de {artist} a la cola', + startConvertingSpotifyPlaylist: 'Convertir las pistas de Spotify en pistas de Deezer', + finishConvertingSpotifyPlaylist: 'Lista de reproducción de Spotify convertida', + loginNeededToDownload: '¡Necesitas iniciar sesión para descargar títulos!', + deezerNotAvailable: 'Deezer no está disponible en su país. Deberías usar una VPN.' + }, + settings: { + title: 'Configuración', + languages: 'Idiomas', + login: { + title: 'Iniciar Sesión', + loggedIn: 'Usted está conectado como {nombre de usuario}', + arl: { + question: '¿Cómo consigo mi propio ARL?', + update: 'Actualiza la ARL' + }, + logout: 'Cerrar Sesión', + login: 'Inicia sesión a través de deezer.com' + }, + appearance: { + title: 'Apariencia', + slimDownloadTab: 'Pestaña de descargas fina' + }, + downloadPath: { + title: 'Ruta de descarga' + }, + templates: { + title: 'Plantillas', + tracknameTemplate: 'Plantilla de nombres de pista', + albumTracknameTemplate: 'Plantilla de pista del álbum', + playlistTracknameTemplate: 'Plantilla de pista de la lista de reproducción' + }, + folders: { + title: 'Carpetas', + createPlaylistFolder: 'Crear una carpeta para las listas de reproducción', + playlistNameTemplate: 'Plantilla de la carpeta de la lista de reproducción', + createArtistFolder: 'Crear carpeta para el artista', + artistNameTemplate: 'Plantilla de la carpeta del artista', + createAlbumFolder: 'Crear carpeta para el álbum', + albumNameTemplate: 'Plantilla de la carpeta del álbum', + createCDFolder: 'Crear una carpeta para los CDs', + createStructurePlaylist: 'Crear una estructura de carpetas para las listas de reproducción', + createSingleFolder: 'Crear una estructura de carpetas para individuales' + }, + trackTitles: { + title: 'Títulos de las pistas', + padTracks: 'Pad de pistas', + paddingSize: 'Sobrescribir el tamaño del pad', + illegalCharacterReplacer: 'Reemplazo del carácter ilegal' + }, + downloads: { + title: 'Descargas', + queueConcurrency: 'Descargas simultáneas', + maxBitrate: { + title: 'Tasa de bits preferida', + 9: 'FLAC 1411kbps', + 3: 'MP3 320kbps', + 1: 'MP3 128kbps' + }, + overwriteFile: { + title: '¿Desea que se sobreescriban los archivos?', + y: 'Sí, sobrescribir el archivo', + n: 'No, no sobrescribir el archivo', + t: 'Sobrescribir sólo las etiquetas', + b: 'No, mantener los dos archivos y agregar un número al archivo duplicado', + e: 'No, y no mirar las extensiones' + }, + fallbackBitrate: 'La solución alternativa de bitrate', + fallbackSearch: 'Búsqueda de la segunda opción', + logErrors: 'Crear archivos de registro de errores', + logSearched: 'Crear archivos de registro para las pistas buscadas', + createM3U8File: 'Crear archivo de la lista de reproducción', + syncedLyrics: 'Crear archivos .lrc (lyrics sincronizadas)', + playlistFilenameTemplate: 'Plantilla de nombres de archivos de la lista de reproducción', + saveDownloadQueue: 'Guardar la cola de descarga al cerrar la aplicación' + }, + covers: { + title: 'Portadas de álbumes', + saveArtwork: 'Guardar las portadas', + coverImageTemplate: 'Plantilla de nombres de portada', + saveArtworkArtist: 'Guardar imagen de artista', + artistImageTemplate: 'Plantilla de imagen de artista', + localArtworkSize: 'El tamaño de la portada local', + embeddedArtworkSize: 'El tamaño de la portada incorporada', + localArtworkFormat: { + title: '¿Qué formato quieres que tenga la portada local?', + jpg: 'Una imagen jpeg', + png: 'Una imagen png', + both: 'Ambos, jpeg y png' + }, + jpegImageQuality: 'Calidad de la imagen JPEG', + embeddedArtworkPNG: 'Guardar las imágenes incrustadas como PNG', + embeddedPNGWarning: 'Las PNG no están oficialmente soportadas por Deezer y puedes encontrar errores.', + imageSizeWarning: + 'Nada por encima de x1200 no es usado oficialmente por Deezer, puede que encuentres inconvenientes', + coverDescriptionUTF8: 'Guardar la descripción de la portada usando UTF8 (arregla la portada de iTunes)' + }, + tags: { + head: '¿Qué etiquetas guardar?', + title: 'Título', + artist: 'Artista', + album: 'Álbum', + cover: 'Portada', + trackNumber: 'Número de pista', + trackTotal: 'Total de pistas', + discNumber: 'Número del disco', + discTotal: 'Total del disco', + albumArtist: 'Artista del álbum', + genre: 'Género', + year: 'Año', + date: 'Fecha', + explicit: 'Letras explícitas', + isrc: 'ISRC', + length: 'Duración de la pista', + barcode: 'Código de barras del álbum (UPC)', + bpm: 'BPM', + replayGain: 'Ganancia de la reproducción', + label: 'Etiqueta del álbum', + lyrics: 'Lyrics no sincronizadas', + syncedLyrics: 'Lyrics sincronizadas', + copyright: 'Derechos de autor', + composer: 'Compositor', + involvedPeople: 'Personas involucradas' + }, + other: { + title: 'Otro', + savePlaylistAsCompilation: 'Guardar las listas de reproducción como una compilación', + useNullSeparator: 'Usar separador nulo', + saveID3v1: 'Guarda la ID3v1 también', + multiArtistSeparator: { + title: '¿Cómo le gustaría separar a sus artistas?', + nothing: 'Guardar sólo el artista principal', + default: 'Usar la especificación estándar', + andFeat: 'Usar & y feat.', + using: 'Usar "{separator}"' + }, + singleAlbumArtist: 'Guardar sólo el artista principal del álbum', + albumVariousArtists: 'Mantener "Various Artists" en los artistas del álbum', + removeAlbumVersion: 'Eliminar "Album Version" del título de la pista', + removeDuplicateArtists: 'Eliminar las combinaciones de artistas', + dateFormat: { + title: 'Formato de fecha para los archivos FLAC', + year: 'AAAA', + month: 'MM', + day: 'DD' + }, + featuredToTitle: { + title: '¿Qué debo hacer con los artistas destacados?', + 0: 'Nada', + 1: 'Quitarlo del título', + 3: 'Quitarlo del título y del título del álbum', + 2: 'Moverlo al título' + }, + titleCasing: 'Capitalizar título', + artistCasing: 'Capitalizar artista', + casing: { + nothing: 'Manténer sin cambios', + lower: 'minúsculas', + upper: 'MAYÚSCULAS', + start: 'Al Principio De Cada Palabra', + sentence: 'Como una frase' + }, + previewVolume: 'Volumen de previsualización', + executeCommand: { + title: 'Comando a ejecutar después de la descarga', + description: 'Dejar en blanco para no hacer nada' + } + }, + spotify: { + title: 'Funciones de Spotify', + clientID: 'ID del cliente de Spotify', + clientSecret: 'Cliente Secreto Spotify', + username: 'Nombre de usuario de Spotify' + }, + reset: 'Restablecer el valor por defecto', + save: 'Guardar', + toasts: { + init: '¡Configuraciones cargadas!', + update: '¡Ajustes actualizados!', + ARLcopied: 'ARL copiado al portapapeles' + } + }, + sidebar: { + home: 'inicio', + search: 'buscar', + charts: 'charts', + favorites: 'favoritos', + linkAnalyzer: 'analizar enlaces', + settings: 'ajustes', + about: 'acerca de' + }, + tracklist: { + downloadSelection: 'Descargar selección' + } +} + +export default es diff --git a/webui/src/lang/fil.mjs b/webui/src/lang/fil.mjs new file mode 100644 index 0000000..9f74637 --- /dev/null +++ b/webui/src/lang/fil.mjs @@ -0,0 +1,389 @@ +const fil = { + globals: { + welcome: 'Welcome sa deemix', + back: 'bumalik', + loading: 'kumakarga', + download: 'I-download {thing}', + by: 'ayon sa {artist}', + in: 'sa {album}', + download_hint: 'I-download', + play_hint: 'I-play', + toggle_download_tab_hint: 'Palakihin/Paliitan', + clean_queue_hint: 'Natapos na ang Pag-alis', + cancel_queue_hint: 'Ikansel Lahat', + open_downloads_folder: 'Buksan ang Polder ng Download', + cut: 'i-cut', + copy: 'kopyahin', + copyLink: 'kopyahin ang link', + copyImageLink: 'kopyahin ang imahe sa link', + copyDeezerLink: 'kopyahin ang link ng deezer', + paste: 'idikit', + listTabs: { + empty: '', + all: 'lahat', + top_result: 'nangungunang resulta', + album: 'album | mga album', + artist: 'artist | mga artist', + single: 'single | mga single', + title: 'pamagat | mga pamagat', + track: 'track | mga track', + trackN: '0 mga track | {n} track | {n} mga track', + releaseN: '0 mga release | {n} release | {n} mga release', + playlist: 'playlist | mga playlist', + compile: 'pinagsama | mga pinagsama', + ep: 'ep | mga ep', + bundle: 'bundle | mga bundle', + more: 'Iba pang mga album', + featured: 'Ibinida sa', + spotifyPlaylist: 'playlist sa spotify | mga playlist sa spotify', + releaseDate: 'petsa ng paglabas', + error: 'error' + } + }, + about: { + updates: { + currentVersion: 'Kasalukuyang version', + versionNotAvailable: 'H/P', + updateAvailable: `Hindi mo ginagamit ang pinakabagong version: {version}`, + deemixVersion: 'deemix lib version' + }, + titles: { + usefulLinks: 'Nakatutulong na mga Link', + bugReports: 'Report sa Bug', + contributing: 'Pagtulong', + donations: 'Mga donasiyon', + license: 'Lisensiya' + }, + subtitles: { + bugReports: 'Meron bang hindi gumagana sa deemix? Ipaalam mo sa amin!', + contributing: 'Gusto mo bang tumulong sa proyektong ito? Pwede mong gawin iyan sa maraming paraan!', + donations: 'Gusto mo bang tumulong sa pamamagitan ng pera? Pwede kang magbigay ng donasiyon!' + }, + usesLibrary: + 'Ang app na ito ay gumagamit ng library galing sa deemix, na kung saan ay pwede mong gamitin para gumawa ng sarili mong UI ng deemix.', + thanks: `Salamat kay rtonno, uhwot at lollilol sa pagtulong sa akin para sa proyektong ito at kay BasCurtiz sa paggawa ng icon.`, + upToDate: { + text: `Huwag magpapahuli sa mga update patungkol dito sa pamamagitan ng pagsali sa {newsChannel} sa Telegram.`, + newsChannel: 'news channel' + }, + officialWebsite: 'Opisyal na Website', + officialRepo: 'Opisyal na Library Repository', + officialWebuiRepo: 'Opisyal na Repository ng WebUI', + officialSubreddit: 'Opisyal na Subreddit', + newsChannel: 'News Channel', + questions: { + text: `Kung may tanong ka o problema sa app, maghanap ka muna ng solusiyon sa {subreddit}. Ngayon, kung wala ka talagang mahanap ay pwede kang mag-post patungkol sa iyong isyu doon sa subreddit.`, + subreddit: 'subreddit' + }, + beforeReporting: `Bago ka magreport ng bug, siguraduhing pinakabagong version ang ginagamit mo at ang ire-report mo ay talagang bug at hindi dahil sa pagkakamali mo lang ng paggamit.`, + beSure: `Siguraduhing nangyayari rin ang bug sa iba't ibang plataporma at tsaka HUWAG mo nang i-report ang bug kung ito ay naipa-alam na ng iba.`, + duplicateReports: 'Isasara namin ang mga magkaparehong report sa bug, kaya alamin mo muna.', + dontOpenIssues: `HUWAG kayong magbubukas ng isyu kung magtatanong lang kayo, meron tayong subreddit para diyan.`, + newUI: { + text: `Kung ikaw ay maraming alam sa python, subukan mong gumawa ng bagong UI gamit ng base library, o kaya ayusin ang mga bug sa library sa pamamagitan ng pag-pull ng request sa {repo}.`, + repo: 'repo' + }, + acceptFeatures: `Tumatangggap din ako ng mga feature, basta hindi komplikado, dahil diretso ko itong nilalagay sa app at hindi sa library.`, + otherLanguages: `Kung ikaw ay maraming alam sa ibang programming language, maaari mo ring subukan i-port ang deemix sa iba't ibang programming language!`, + understandingCode: `Kailangan mo ba ng tulong para maintindihan ang code? Bisitahin si RemixDev sa Telegram o sa Reddit.`, + contributeWebUI: { + text: `Kung may alam ka sa Vue.js (JavaScript), HTML o kaya CSS, maaari kang sumali at tumulong dito sa {webui}.`, + webui: 'WebUI' + }, + itsFree: `Lagi mong tandaang ang proyektong ito ay libre at suportuhanmuna ang minamahal ninyong mga artist bago ang mga developer.`, + notObligated: `Huwag mong pilitin ang sarili para mag-donate, Naiintindihan ka namin!`, + lincensedUnder: { + text: `Ang aktibidad na ito ay lisensiyado sa {gpl3}.`, + gpl3: 'GNU General Public License 3.0' + } + }, + charts: { + title: 'Mga Chart', + changeCountry: 'Palitan ang Country', + download: 'I-download ang Chart' + }, + errors: { + title: 'Mga error sa {name}', + ids: { + invalidURL: 'Hindi makilala ang URL', + unsupportedURL: 'Hindi pa suportado ang URL', + ISRCnotOnDeezer: 'Ang Track ISRC ay hindi pwede sa Deezer', + notYourPrivatePlaylist: 'Hindi pwedeng i-download ang mga pribadong playlist ng iba.', + spotifyDisabled: 'Hindi mo nai-set nang tama ang Spotify Features.', + trackNotOnDeezer: 'Hindi mahanap ang track sa Deezer!', + albumNotOnDeezer: 'Hindi mahanap ang album sa Deezer!', + notOnDeezer: 'Hindi available ang track sa Deezer!', + notEncoded: 'Hindi pa nae-encode ang track!', + notEncodedNoAlternative: 'Hindi pa nae-encode ang track at walang mahanap na iba!', + wrongBitrate: 'Hindi mahanap ang track sa gusto mong bitrate.', + wrongBitrateNoAlternative: 'Hindi mahanap ang track sa gusto mong bitrate at walang mahanap na iba!', + no360RA: 'Hindi pwede ang track para sa Reality Audio 360.', + notAvailable: 'Walang available na track sa server ng Deezer!', + notAvailableNoAlternative: 'Walang available na track sa server ng Deezer at walang mahanap na iba!', + noSpaceLeft: 'Wala nang natitirang space sa iyong device!' + } + }, + favorites: { + title: 'Mga Paborito', + noPlaylists: 'Walang makitang mga Playlist', + noAlbums: 'Walang makitang mga Paboritong Album', + noArtists: 'Walang makitang mga Paboritong Artist', + noTracks: 'Walang makitang mga Paboritong Track' + }, + home: { + needTologin: 'Kailangan mong mag-log in sa iyong Deezer account bago ka makasimulang magdownload.', + openSettings: 'Buksan ang Mga Setting', + sections: { + popularPlaylists: 'Mga sikat na playlist', + popularAlbums: 'Pinakamaraming pinakikinggang mga album' + } + }, + linkAnalyzer: { + info: 'Pwede gamitin ang section na ito para sa iba pang impormasyon patungkol sa link na gusto mong i-download.', + useful: + 'Makatutulong ito kung meron kang gustong i-download na track na hindi available sa bansa mo at gusto mong malaman kung meron bang ganito kapag sa iba.', + linkNotSupported: 'Hindi pa suportado ang link', + linkNotSupportedYet: 'Mukhang hindi pa suportado itong link, iba na lang ang ilagay mo.', + table: { + id: 'ID', + isrc: 'ISRC', + upc: 'UPC', + duration: 'Haba', + diskNumber: 'Bilang ng Disk', + trackNumber: 'Bilang ng Track', + releaseDate: 'Petsa ng Release', + bpm: 'BPM', + label: 'Label', + recordType: 'Uri ng Rekord', + genres: 'Mga Genre', + tracklist: 'Listahan ng Track' + } + }, + search: { + startSearching: 'Simulang Maghanap!', + description: + 'Pwede kang maghanap ng track, buong album, artist, playlist.... kahit ano! Pwede ka ring mag-paste dito ng link na galing sa Deezer', + fans: '{n} mga fan', + noResults: 'Walang resulta', + noResultsTrack: 'Walang mahanap na mga Track', + noResultsAlbum: 'Walang mahanap na mga Album', + noResultsArtist: 'Walang mahanap na mga Artist', + noResultsPlaylist: 'Walang mahanap na mga Playlist' + }, + searchbar: 'Maghanap ka ng gusto mo (o mag-paste ka ng link)', + downloads: 'mga download', + toasts: { + restoringQueue: 'Binabalik ang download queue...', + queueRestored: 'Naibalik na ang download queue!', + addedToQueue: '{item} ay naidagdag sa queue', + addedMoreToQueue: '{n} naidagdag rin sa queue', + alreadyInQueue: '{item} ay meron na sa queue!', + finishDownload: '{item} ay natapos nang i-download.', + allDownloaded: 'Nadownload na lahat!', + refreshFavs: 'Narefresh na!', + loggingIn: 'Nagla-log in...', + loggedIn: 'Na-login na', + alreadyLogged: 'Nakalogin ka na', + loginFailed: 'Hindi maka-log in', + loggedOut: 'Na-logout na', + cancellingCurrentItem: 'Kinakansel ang item.', + currentItemCancelled: 'Nakansel na ang item.', + startAddingArtist: 'Idinadagdag si {artist} sa queue ng mga album', + finishAddingArtist: 'Naidagdag na si {artist} sa queue ng mga album', + startConvertingSpotifyPlaylist: 'Kino-convert ang mga track sa spotify papuntang Deezer', + finishConvertingSpotifyPlaylist: 'Naconvert na ang playlist sa Spotify', + loginNeededToDownload: 'Kailangan mong mag-login para madownload ang mga track!', + deezerNotAvailable: 'Hindi available ang Deezer sa iyong bansa. Kailangan mong gumamit ng VPN.' + }, + settings: { + title: 'Mga Setting', + languages: 'Mga Wika', + login: { + title: 'Login', + loggedIn: 'Ikaw ay naka-login sa pangalang {username}', + arl: { + question: 'Paano ako makakuha ng sariling ARL?', + update: 'I-update ang ARL' + }, + logout: 'Logout', + login: 'Mag-login gamit ng deezer.com' + }, + appearance: { + title: 'Hitsura', + slimDownloadTab: 'Pinaliit na download tab' + }, + downloadPath: { + title: 'Paglalagyan ng Download' + }, + templates: { + title: 'Mga Template', + tracknameTemplate: 'Template sa pangalan ng Track', + albumTracknameTemplate: 'Template sa track ng Album', + playlistTracknameTemplate: 'Template sa track ng Playlist' + }, + folders: { + title: 'Mga Folder', + createPlaylistFolder: 'Gumawa ng folder para sa mga playlist', + playlistNameTemplate: 'Template sa folder ng Playlist', + createArtistFolder: 'Gumawa ng folder para sa artist', + artistNameTemplate: 'Template sa folder ng Artist', + createAlbumFolder: 'Gumawa ng folder para sa album', + albumNameTemplate: 'Template sa folder ng Album', + createCDFolder: 'Gumawa ng folder para sa mga CD', + createStructurePlaylist: 'Gumawa ng istraktura ng folder para sa mga playlist', + createSingleFolder: 'Gumawa ng istraktura ng folder para sa mga single' + }, + trackTitles: { + title: 'Pamagat sa mga track', + padTracks: 'Mga track ng Pad', + paddingSize: 'Patungan ang laki ng padding', + illegalCharacterReplacer: 'Pamalit sa ilegal na Karakter' + }, + downloads: { + title: 'Mga Download', + queueConcurrency: 'Mga Kasabay na Download', + maxBitrate: { + title: 'Gustong Bitrate', + 9: 'FLAC 1411kbps', + 3: 'MP3 320kbps', + 1: 'MP3 128kbps' + }, + overwriteFile: { + title: 'Papatungan ko ba ang file?', + y: 'Oo, patungan mo ang file', + n: 'Hindi, huwag mong patungan ang file', + t: 'Patungan mo lang ang mga tag', + b: 'Hindi, hayaan mo silang dalawa at lagyan mo lang ng numero sa kapareho niya', + e: 'Hindi, at huwag mong tignan ang mga extension' + }, + fallbackBitrate: 'Binabaang bitrate', + fallbackSearch: 'Maghanap para sa binabaan', + logErrors: 'Gumawa ng log file para sa mga error', + logSearched: 'Gumawa ng log file para sa mga hinanap na track', + createM3U8File: 'Gumawa ng file sa playlist', + syncedLyrics: 'Gumawa ng mga .lrc file (Mga Sync Lyric)', + playlistFilenameTemplate: 'Template sa pangalan ng Playlist file', + saveDownloadQueue: 'I-save ang download queue kapag isasara the app' + }, + covers: { + title: 'Mga cover ng album', + saveArtwork: 'I-save ang mga Cover', + coverImageTemplate: 'Template ng pangalan ng cover', + saveArtworkArtist: 'I-save ang imahe ng artist', + artistImageTemplate: 'Template ng imahe ng artist', + localArtworkSize: 'Laki ng lokal na artwork', + embeddedArtworkSize: 'Laki ng Nakadikit na artwork', + localArtworkFormat: { + title: 'Anong gusto mong format para sa mga lokal na artwork?', + jpg: 'jpeg na imahe', + png: 'png na imahe', + both: 'Parehong jpeg at png' + }, + jpegImageQuality: 'Kalidad ng JPEG na imahe', + embeddedArtworkPNG: 'I-save ang nakadikit na artwork bilang PNG', + embeddedPNGWarning: 'Ang mga PNG ay hindi opisyal na suportado ng Deezer at maaaring magkaroon ng bug', + imageSizeWarning: + 'Lahat ng mas mataas sa x1200 ay hindi opisyal na ginagamit sa Deezer, at posibleng magkaroon ng isyu', + coverDescriptionUTF8: 'I-save ang deskripsyon ng cover gamit ng UTF8 (iTunes Cover Fix)' + }, + tags: { + head: 'Aling tag ang ise-save', + title: 'Pamagat', + artist: 'Artist', + album: 'Album', + cover: 'Cover', + trackNumber: 'Bilang ng Track', + trackTotal: 'Kabuuang Track', + discNumber: 'Bilang ng Disk', + discTotal: 'Kabuuang Disk', + albumArtist: 'Album Artist', + genre: 'Genre', + year: 'Taon', + date: 'Petsa', + explicit: 'Mga Explicit na Lyric', + isrc: 'ISRC', + length: 'Haba ng Track', + barcode: 'Barcode ng Album (UPC)', + bpm: 'BPM', + replayGain: 'Replay Gain', + label: 'Label ng Album', + lyrics: 'Unsynchronized na mga Lyric', + syncedLyrics: 'Synchronized na mga Lyric', + copyright: 'Karapatang Ari', + composer: 'Komposer', + involvedPeople: 'Mga Kasamang Tao' + }, + other: { + title: 'Iba pa', + savePlaylistAsCompilation: 'I-save ang mga playlist bilang compilation', + useNullSeparator: 'Gumamit ng panghiwalay sa null', + saveID3v1: 'I-save rin ang ID3v1', + multiArtistSeparator: { + title: 'Anong gusto mo para maihanay mga artist?', + nothing: 'I-save lang ang pangunahing artist', + default: 'Gamit ng standard na specification', + andFeat: 'Gamit ng & at feat.', + using: 'Gamit ng "{separator}"' + }, + singleAlbumArtist: 'I-save lang ang pangunahing album ng artist', + albumVariousArtists: 'Isama ang "Various Artists" sa mga Album Artist', + removeAlbumVersion: 'Tanggalin ang "Album Version" sa pamagat ng track', + removeDuplicateArtists: 'Tanggalin ang kombinasyon ng mga artist', + dateFormat: { + title: 'Format ng petsa para sa mga FLAC file', + year: 'YYYY', + month: 'MM', + day: 'DD' + }, + featuredToTitle: { + title: 'Anong gagawin ko sa mga itinampok na artist', + 0: 'Wala', + 1: 'Tanggalin mo sila sa Pamagat', + 3: 'Tanggalin mo sila sa Pamagat mismo at Pamagat ng Album', + 2: 'Ilipat mo sila sa pamagat' + }, + titleCasing: 'Pagleletra sa Pamagat', + artistCasing: 'Pagleletra sa Artist', + casing: { + nothing: 'Walang babaguhin', + lower: 'maliliit', + upper: 'MALALAKI', + start: 'Simula Ng Bawata Salita', + sentence: 'Kagaya ng pangungusap' + }, + previewVolume: 'Volume ng Preview', + executeCommand: { + title: 'Mga gagawin pagkatapos ng download', + description: 'Hayaan lang na blangko kung wala' + } + }, + spotify: { + title: 'Spotify Features', + clientID: 'Spotify ClientID', + clientSecret: 'Spotify Client Secret', + username: 'Spotify Username', + question: 'Paano ma-enable ang Spotify Features?' + }, + reset: 'Ibalik sa Dati', + save: 'I-save', + toasts: { + init: 'Ikinarga ang mga Setting!', + update: 'In-update ang mga Setting!', + ARLcopied: 'Kinopya ang ARL sa clipboard' + } + }, + sidebar: { + home: 'tahanan', + search: 'maghanap', + charts: 'mga chart', + favorites: 'mga paborito', + linkAnalyzer: 'tagasuri ng link', + settings: 'mga setting', + about: 'tungkol sa' + }, + tracklist: { + downloadSelection: 'Pagpipili ng download' + } +} + +export default fil diff --git a/webui/src/lang/fr.mjs b/webui/src/lang/fr.mjs new file mode 100644 index 0000000..d7a7576 --- /dev/null +++ b/webui/src/lang/fr.mjs @@ -0,0 +1,529 @@ +const fr = { + globals: { + welcome: 'Bienvenue dans deemix', + back: 'retour', + loading: 'chargement en cours', + download: 'Télécharger {thing}', + by: 'par {artist}', + in: 'dans {album}', + download_hint: 'Télécharger', + play_hint: 'Lire', + toggle_download_tab_hint: 'Développer/Réduire', + clean_queue_hint: 'Retirer Les Tâches Terminées', + cancel_queue_hint: 'Tout Annuler', + open_downloads_folder: 'Ouvrir Le Dossier De Téléchargements', + cut: 'couper', + copy: 'copier', + copyLink: 'copier le lien', + copyImageLink: "copier le lien de l'image", + copyDeezerLink: 'copier le lien deezer', + paste: 'coller', + listTabs: { + empty: '', + all: 'tout', + discography: 'discographie', + top_result: 'meilleur résultat', + album: 'album | albums', + artist: 'artiste | artistes', + single: 'single | singles', + title: 'titre | titres', + track: 'piste | pistes', + playlist: 'playlist | playlists', + compile: 'compilation | compilations', + ep: 'ep | eps', + bundle: 'bundle | bundles', + more: "Plus d'albums", + featured: 'Apparaît dans', + spotifyPlaylist: 'playlist spotify | playlists spotify', + releaseDate: 'date de sortie', + error: 'erreur', + trackN: '0 piste | {n} piste | {n} pistes', + albumN: '0 album | {n} album | {n} albums', + artistN: '0 artiste | {n} artiste | {n} artistes', + releaseN: '0 sortie | {n} sortie | {n} sorties', + playlistN: '0 playlist | {n} playlist | {n} playlists' + }, + yes: 'oui', + no: 'non', + empty: 'vide' + }, + about: { + appStatus: { + online: 'application en ligne', + offline: 'application hors ligne' + }, + updates: { + currentVersion: 'Version Actuelle Du Logiciel', + currentWebuiVersion: 'Version Actuelle De La WebUI', + versionNotAvailable: 'N/A', + updateAvailable: "Vous n'utilisez pas la dernière version disponible : {version}", + deemixVersion: 'Version Actuelle De La Bibliothèque deemix' + }, + titles: { + usefulLinks: 'Liens Utiles', + bugReports: 'Rapports De Bug', + contributing: 'Contribution', + donations: 'Dons', + license: 'Licence' + }, + subtitles: { + bugReports: 'Quelque chose ne fonctionne pas dans deemix ? Contactez-nous !', + contributing: 'Vous souhaitez contribuer à ce projet ? Vous pouvez le faire de différentes manières !', + donations: 'Vous souhaitez contribuer financièrement ? Vous pouvez faire un don !' + }, + usesLibrary: + 'Cette application utilise la bibliothèque deemix, que vous pouvez exploiter afin de créer votre propre interface utilisateur pour deemix.', + thanks: + "Merci à rtonno, uhwot et lollilol de m'avoir aidé dans ce projet ainsi qu'à BasCurtiz pour la création de l'icône.", + upToDate: { + text: `Restez informé des mises à jour en suivant le {newsChannel} sur Telegram.`, + newsChannel: "canal d'informations" + }, + officialWebsite: 'Site Officiel', + officialRepo: 'Répertoire De Dépôt Officiel De La Bibliothèque', + officialWebuiRepo: 'Répertoire De Dépôt Officiel De La WebUI', + officialSubreddit: 'Subreddit Officiel', + newsChannel: "Canal d'Informations", + devlogChannel: 'Canal De Développement', + questions: { + text: `Si vous avez des questions ou des problèmes avec l'application, cherchez d'abord une solution dans le {subreddit}. Ensuite, si la solution ne s'y trouve pas, vous pouvez publier un message dans le subreddit en décrivant votre problème.`, + subreddit: 'subreddit' + }, + beforeReporting: + "Avant de signaler un bug, assurez-vous que vous utilisez la version la plus récente de l'application. Vérifiez que vous souhaitez nous rapporter un bug et non quelque chose qui ne fonctionne pas uniquement de votre côté.", + beSure: + "Assurez-vous que le bug soit reproductible sur d'autres appareils mais aussi de NE PAS signaler un bug si celui-ci a déjà été recensé.", + duplicateReports: "Les rapports de bug répétitifs seront supprimés, merci d'en prendre bonne note.", + dontOpenIssues: + "NE PAS rapporter de problème s'il ne s'agit que de simples questions. Un subreddit existe pour ces questions.", + newUI: { + text: `Si vous maîtrisez python, vous pouvez essayer de créer une nouvelle interface utilisateur pour l'application à l'aide de la bibliothèque de base, ou corriger des bugs dans la bibliothèque à l'aide d'une demande de fusion de branches (pull request) sur le {repo}.`, + repo: 'répertoire de dépôt' + }, + acceptFeatures: + "J'accepte également les nouvelles fonctionnalités, mais pas de choses complexes, dans la mesure où elles peuvent être implémentées directement dans l'application et non dans la bibliothèque.", + otherLanguages: + 'Si vous maîtrisez un autre langage de programmation, vous pouvez essayer de transposer deemix dans ce dernier !', + understandingCode: + "Vous avez besoin d'aide pour comprendre le code ? Il suffit de contacter RemixDev sur Telegram ou Reddit.", + contributeWebUI: { + text: `Si vous vous y connaissez en Vue.js (JavaScript), HTML ou CSS, vous pouvez contribuer à la {webui}.`, + webui: 'WebUI' + }, + itsFree: + "N'oubliez pas que ce projet est libre et qu'il est important de soutenir vos artistes préférés avant de supporter les développeurs.", + notObligated: 'Ne vous sentez pas obligé de faire un don, vous êtes tout de même apprécié !', + lincensedUnder: { + text: `Ce projet s'inscrit dans le cadre de la {gpl3}.`, + gpl3: 'Licence publique générale GNU, version 3' + } + }, + charts: { + title: 'Classements', + changeCountry: 'Changer De Pays', + download: 'Télécharger Le Classement' + }, + errors: { + title: 'Erreurs pour {name}', + postTitle: 'Erreurs survenues après le téléchargement', + ids: { + invalidURL: "Cette URL n'est pas reconnue", + unsupportedURL: "Cette URL n'est actuellement pas supportée", + ISRCnotOnDeezer: "L'ISRC de la piste est indisponible sur Deezer", + notYourPrivatePlaylist: "Vous n'êtes pas autorisé à télécharger les playlists privées de quelqu'un d'autre.", + spotifyDisabled: 'Les Fonctionnalités Spotify ne sont pas configurées correctement.', + trackNotOnDeezer: 'La piste est introuvable sur Deezer !', + albumNotOnDeezer: "L'album est introuvable sur Deezer !", + notOnDeezer: 'La piste est indisponible sur Deezer !', + notEncoded: "La piste n'a pas encore été encodée !", + notEncodedNoAlternative: "La piste n'a pas encore été encodée et aucune alternative n'a été trouvée !", + wrongBitrate: 'La piste est introuvable au débit souhaité.', + wrongBitrateNoAlternative: "La piste est introuvable au débit souhaité et aucune alternative n'a été trouvée !", + no360RA: 'La piste est indisponible au format Reality Audio 360.', + notAvailable: 'La piste est indisponible sur les serveurs de Deezer !', + notAvailableNoAlternative: + "La piste est indisponible sur les serveurs de Deezer et aucune alternative n'a été trouvée !", + noSpaceLeft: "L'espace disponible sur cet appareil est insuffisant !", + albumDoesntExists: "Aucun album n'existe pour cette piste, impossible de collecter les informations nécessaires.", + wrongLicense: 'Votre compte ne prend pas en charge les pistes en {bitrate}.', + wrongGeolocation: 'Votre compte ne prend pas en charge la piste depuis votre pays actuel.', + wrongGeolocationNoAlternative: + "Votre compte ne prend pas en charge la piste depuis votre pays actuel et aucune alternative n'a été trouvée." + } + }, + favorites: { + title: 'Favoris', + noPlaylists: "Aucune Playlist Favorite n'a été trouvée", + noAlbums: "Aucun Album Favori n'a été trouvé", + noArtists: "Aucun Artiste Favori n'a été trouvé", + noTracks: "Aucune Piste Favorite n'a été trouvée" + }, + home: { + needTologin: 'Vous devez vous connecter à votre compte Deezer avant de pouvoir démarrer un téléchargement.', + openSettings: 'Ouvrir Les Paramètres', + sections: { + popularPlaylists: 'Playlists les plus écoutées', + popularAlbums: 'Albums les plus écoutés' + } + }, + linkAnalyzer: { + info: "Vous pouvez utiliser cette section pour obtenir davantage d'informations sur le lien que vous essayez de télécharger.", + useful: + "C'est utile si vous essayez, par exemple, de télécharger des pistes indisponibles dans votre pays et que vous souhaitez savoir où elles sont disponibles.", + linkNotSupported: "Ce lien n'est pas encore pris en charge", + linkNotSupportedYet: "Il semble que ce lien ne soit pas encore pris en charge, essayez d'en analyser un autre.", + table: { + id: 'ID', + isrc: 'ISRC', + upc: 'UPC', + duration: 'Durée', + diskNumber: 'Numéro De Disque', + trackNumber: 'Numéro De Piste', + releaseDate: 'Date De Sortie', + bpm: 'BPM', + label: 'Label', + recordType: "Type d'Enregistrement", + genres: 'Genres', + tracklist: 'Liste Des Pistes', + readable: 'Lisible', + available: 'Disponible' + }, + countries: 'Pays', + noCountries: "Cette piste n'est disponible dans aucun pays." + }, + search: { + startSearching: 'Démarrer une recherche !', + description: + 'Vous pouvez rechercher une piste, un album entier, un artiste, une playlist... tout ce que vous voulez ! Vous pouvez également coller un lien Deezer.', + fans: '{n} fans', + noResults: 'Aucun résultat', + noResultsTrack: "Aucune piste n'a été trouvée", + noResultsAlbum: "Aucun album n'a été trouvé", + noResultsArtist: "Aucun artiste n'a été trouvé", + noResultsPlaylist: "Aucune playlist n'a été trouvée", + error: 'Une erreur est survenue, veuillez réessayer ultérieurement.' + }, + searchbar: 'Saisissez une requête (ou collez simplement un lien)', + downloads: 'téléchargements', + toasts: { + restoringQueue: "Restauration de la file d'attente de téléchargement...", + queueRestored: "La file d'attente de téléchargement a été restaurée !", + addedToQueue: "{item} ajouté à la file d'attente", + addedMoreToQueue: "{n} éléments ajoutés à la file d'attente", + alreadyInQueue: "{item} est déjà dans la file d'attente !", + finishDownload: '{item} a été téléchargé.', + allDownloaded: 'Tous les téléchargements sont terminés !', + refreshFavs: 'Actualisation terminée !', + loggingIn: 'Connexion en cours...', + loggedIn: 'Connecté', + alreadyLogged: 'Déjà connecté', + loginFailed: 'Connexion impossible', + loggedOut: 'Déconnecté', + cancellingCurrentItem: "Annulation de l'élément actuel.", + currentItemCancelled: 'Élément actuel annulé.', + startAddingArtist: "Ajout des albums de {artist} à la file d'attente", + finishAddingArtist: "Les albums de {artist} ont été ajoutés à la file d'attente", + startConvertingSpotifyPlaylist: 'Conversion de pistes Spotify en équivalents Deezer', + finishConvertingSpotifyPlaylist: 'Playlist Spotify convertie', + loginNeededToDownload: 'Vous devez vous connecter pour pouvoir télécharger des pistes !', + queueErrorCantStream: 'Votre compte ne prend pas en charge les téléchargements en {bitrate}.', + deezerNotAvailable: 'Deezer est indisponible dans votre pays. Vous devez utiliser un VPN.', + deezerNotReachable: + "L'application ne semble pas pouvoir communiquer avec Deezer. Vérifiez votre connexion internet, votre pare-feu ou votre antivirus.", + startGeneratingItems: 'Traitement de {n} éléments...', + finishGeneratingItems: '{n} éléments ont été générés.', + noLovedPlaylist: 'Aucune playlist de pistes favorites !', + checkingUpdates: 'Recherche des mises à jour...', + noUpdateAvailable: 'Aucune mise à jour disponible.', + updateAvailable: 'Une mise à jour est disponible !', + wrongSpotifyUsername: "{username} n'est pas un nom d'utilisateur Spotify valide" + }, + settings: { + title: 'Paramètres', + languages: 'Langues', + login: { + title: 'Connexion', + loggedIn: 'Vous êtes connecté en tant que {username}', + arl: { + title: 'Utiliser de préférence la connexion via ARL', + question: 'Comment obtenir mon ARL personnel ?', + howTo: { + prologue: { + p1: 'Deezer conserve une trace de votre connexion en utilisant un cookie appelé ARL.', + p2: 'Deemix utilise ce cookie pour obtenir les métadonnées dont il a besoin pour télécharger les pistes depuis Deezer.', + p3: 'Les ARLs restent valables pendant 3 mois, après quoi Deezer vous demande de vous reconnecter. La même méthode est utilisée dans deemix.', + p4: "En suivant l'un des modes opératoires ci-dessous, vous pouvez obtenir votre ARL personnel.", + warning: "N'utilisez cette méthode que si l'e-mail et le mot de passe ne fonctionnent pas." + }, + chromeSteps: { + title: 'Chrome', + step1: 'Ouvrez Chrome', + easyWay: { + title: 'Chrome (Méthode simple)', + step3: "Cliquez sur la petite icône représentant un cadenas située à côté de l'URL.", + step4: 'Cliquez sur Cookies > deezer.com > cookies > arl', + step5: 'Sélectionnez la chaîne de caractères située à côté de Contenu, et copiez-la' + }, + step4: "Allez sous l'onglet Application (si vous ne le voyez pas, cliquez sur la double flèche).", + videoGuide: { + text: 'Voici un {videoGuide}', + link: 'tutoriel vidéo' + } + }, + firefoxSteps: { + title: 'Firefox', + step1: 'Ouvrez Firefox', + step4: "Allez sous l'onglet Stockage (si vous ne le voyez pas, cliquez sur la double flèche)." + }, + commonSteps: { + step2: 'Allez sur www.deezer.com et connectez-vous à votre compte', + step3: 'Une fois la connexion effectuée, appuyez sur F12 pour ouvrir les outils du développeur.', + step5: 'Ouvrez le menu déroulant Cookies', + step6: 'Sélectionnez www.deezer.com', + step7: 'Recherchez le cookie `arl` (il doit comporter 192 caractères).', + step8: "Assurez-vous de ne copier que la valeur et non l'intégralité du cookie.", + lastStep: "Il s'agit de votre ARL personnel, vous pouvez maintenant l'utiliser dans l'application." + } + }, + update: "Forcer la réactualisation de l'ARL" + }, + logout: 'Déconnexion', + login: 'Connexion', + email: 'E-mail', + password: 'Mot de passe' + }, + appearance: { + title: 'Apparence', + slimDownloadTab: 'Onglet de téléchargement compact', + slimSidebar: 'Barre latérale compacte', + searchButton: 'Afficher le bouton de recherche', + bitrateTags: "Afficher l'indicateur de qualité audio dans la file d'attente de téléchargement" + }, + downloadPath: { + title: 'Emplacement De Téléchargement' + }, + templates: { + title: 'Modèles', + tracknameTemplate: 'Modèle pour le nom de piste', + tracknameAvailableVariables: 'Variables disponibles pour le nom de piste', + albumTracknameTemplate: "Modèle pour le nom de piste de l'album", + albumTracknameAvailableVariables: "Variables disponibles pour le nom de piste de l'album", + playlistTracknameTemplate: 'Modèle pour le nom de piste de la playlist', + playlistTracknameAvailableVariables: 'Variables disponibles pour le nom de piste de la playlist' + }, + folders: { + title: 'Dossiers', + createPlaylistFolder: 'Générer des dossiers par playlist', + playlistNameTemplate: 'Modèle pour le nom du dossier de playlist', + createArtistFolder: 'Générer des dossiers par artiste', + artistNameTemplate: "Modèle pour le nom du dossier d'artiste", + createAlbumFolder: 'Générer des dossiers par album', + albumNameTemplate: "Modèle pour le nom du dossier d'album", + createCDFolder: 'Générer des dossiers par CD', + createStructurePlaylist: 'Générer une structure de dossiers pour les playlists', + createSingleFolder: 'Générer une structure de dossiers pour les singles' + }, + trackTitles: { + title: 'Titres des pistes', + padTracks: + 'Longueur uniforme des numéros de piste (ajoute automatiquement des zéros devant le numéro initial de la piste)', + paddingSize: 'Nombre de zéros à ajouter en permanence devant le numéro initial de la piste', + illegalCharacterReplacer: 'Substitut aux caractères non autorisés (dans les noms de fichiers et de dossiers)' + }, + downloads: { + title: 'Téléchargements', + queueConcurrency: 'Téléchargements Simultanés', + maxBitrate: { + title: 'Débit Préféré', + 9: 'FLAC 1411kbps', + 3: 'MP3 320kbps', + 1: 'MP3 128kbps' + }, + overwriteFile: { + title: 'Les fichiers doivent-ils être écrasés ?', + y: 'Oui, écraser le fichier', + n: 'Non, ne pas écraser le fichier', + t: 'Écraser uniquement les métadonnées', + b: 'Non, conserver les deux fichiers et ajouter un numéro au doublon', + e: "Non, et ne pas tenir compte de l'extension du fichier", + l: 'Écraser uniquement si le débit est plus élevé (mp3 seulement)' + }, + fallbackBitrate: "Recourir à un débit plus faible si le débit préféré n'est pas disponible", + fallbackSearch: "Rechercher la piste ailleurs si le lien original n'est pas disponible", + fallbackISRC: "Rechercher la piste à l'aide de son ISRC si le lien original n'est pas disponible", + feelingLucky: 'Utiliser les CDNs et les caches (ancienne méthode de téléchargement des pistes)', + logErrors: "Créer un fichier journal d'erreurs", + logSearched: 'Créer un fichier journal des pistes recherchées', + createM3U8File: 'Créer un fichier de playlist', + syncedLyrics: 'Créer des fichiers .lrc (Paroles Synchronisées)', + playlistFilenameTemplate: 'Modèle du nom de fichier de la playlist', + clearQueueOnExit: "Effacer la file d'attente de téléchargement lors de la fermeture de l'application" + }, + covers: { + title: "Pochettes d'albums", + saveArtwork: 'Enregistrer Les Pochettes', + coverImageTemplate: 'Modèle pour le nom de la pochette', + saveArtworkArtist: "Enregistrer l'image de l'artiste", + artistImageTemplate: "Modèle pour le nom de l'image de l'artiste", + localArtworkSize: "Taille de l'illustration locale", + embeddedArtworkSize: "Taille de l'illustration incorporée aux fichiers audio", + localArtworkFormat: { + title: "Dans quel format souhaitez-vous l'illustration locale ?", + jpg: 'Une image jpeg', + png: 'Une image png', + both: 'À la fois jpeg et png' + }, + jpegImageQuality: "Qualité de l'image JPEG", + embeddedArtworkPNG: "Enregistrer l'illustration incorporée aux fichiers audio en tant que PNG", + embeddedPNGWarning: + 'Les images PNG ne sont pas officiellement utilisées par Deezer et pourraient causer des problèmes.', + imageSizeWarning: + "Toute valeur supérieure à x1200 n'est pas officiellement supportée par Deezer, vous pourriez donc rencontrer des problèmes.", + coverDescriptionUTF8: 'Enregistrer la description de la pochette au format UTF8 (iTunes Cover Fix)' + }, + tags: { + head: 'Métadonnées à sauvegarder', + title: 'Titre', + artist: 'Artiste', + artists: 'Métadonnée supplémentaire ARTISTS', + album: 'Album', + cover: 'Pochette', + trackNumber: 'Numéro De Piste', + trackTotal: 'Nombre De Pistes', + discNumber: 'Numéro Du Disque', + discTotal: 'Nombre De Disques', + albumArtist: "Artiste De l'Album", + genre: 'Genre', + year: 'Année', + date: 'Date', + explicit: 'Paroles Explicites', + isrc: 'ISRC', + length: 'Longueur De La Piste', + barcode: "Code-Barres De l'Album (UPC)", + bpm: 'BPM', + replayGain: 'Gain En Relecture (Replay Gain)', + label: "Label De l'Album", + lyrics: 'Paroles Non-Synchronisées', + syncedLyrics: 'Paroles Synchronisées', + copyright: "Droits d'Auteur (Copyright)", + composer: 'Compositeur', + involvedPeople: 'Personnes Impliquées', + source: 'ID de la source et de la piste', + artistsWarning: + 'La désactivation de la métadonnée ARTISTS sans utiliser la spécification standard ne préservera pas le support multi-artiste.' + }, + other: { + title: 'Autre', + autoCheckForUpdates: "Vérifier les mises à jour au démarrage de l'application", + savePlaylistAsCompilation: 'Enregistrer les playlists en tant que compilation', + useNullSeparator: 'Utiliser le caractère NULL comme séparateur', + saveID3v1: 'Enregistrer également les métadonnées ID3v1', + multiArtistSeparator: { + title: 'Comment aimeriez-vous séparer les artistes ?', + nothing: "Enregistrer uniquement l'artiste principal", + default: 'En utilisant la spécification standard', + andFeat: 'En utilisant & et feat.', + using: 'En utilisant "{separator}"', + warning: + "L'utilisation d'un séparateur autre que la spécification standard nécessitera l'ajout d'une métadonnée ARTISTS afin de préserver le support multi-artiste." + }, + singleAlbumArtist: "Enregistrer uniquement l'artiste principal de l'album", + albumVariousArtists: `Conserver "Various Artists" dans les Artistes de l'Album`, + removeAlbumVersion: `Supprimer "Album Version" du titre de la piste`, + removeDuplicateArtists: "Supprimer les combinaisons d'artistes", + dateFormat: { + title: 'Format de date pour les fichiers FLAC', + year: 'AAAA', + month: 'MM', + day: 'JJ' + }, + featuredToTitle: { + title: 'Que faire des artistes participants (featuring) ?', + 0: 'Ne rien faire', + 1: 'Les retirer du titre de la piste', + 3: "Les supprimer du titre de la piste et du titre de l'album", + 2: 'Les déplacer vers le titre de la piste' + }, + titleCasing: 'Casse pour le titre', + artistCasing: "Casse pour l'artiste", + casing: { + nothing: 'Conserver inchangé', + lower: 'minuscules', + upper: 'MAJUSCULES', + start: 'Majuscule Au Début De Chaque Mot', + sentence: 'Majuscule seulement au début de la phrase' + }, + previewVolume: 'Volume sonore des aperçus de pistes', + executeCommand: { + title: 'Commande à exécuter après le téléchargement', + description: "Laisser vide pour qu'aucune action n'ait lieu" + } + }, + spotify: { + title: 'Fonctionnalités Spotify', + clientID: 'Client ID Spotify', + clientSecret: 'Client Secret Spotify', + username: "Nom d'utilisateur Spotify", + question: 'Comment activer les Fonctionnalités Spotify ?', + howTo: { + prologue: { + p1: 'Les "Fonctionnalités Spotify" sont un ensemble de fonctionnalités qui vous permet de convertir les liens des pistes et albums Spotify en équivalents Deezer.', + p2: "Si vous introduisez un lien d'une Playlist Spotify, l'application convertira automatiquement tous les liens des pistes qu'elle contient en pistes Deezer correspondantes.", + p3: "En activant ces fonctionnalités, vous pourrez également consulter vos Playlists Spotify publiques dans l'onglet Favoris." + }, + info: 'Pour des raisons de sécurité, vous devrez fournir votre Client ID et votre Client Secret personnels.', + clientSecretQuestion: { + title: 'Comment obtenir mon Client ID ainsi que mon Client Secret personnels ?', + step1: { + text: 'Rendez-vous sur le {spotifyDevelopersDashboard} et connectez-vous avec votre compte Spotify.', + spotifyDevelopersDashboard: 'Tableau de bord Spotify pour les développeurs' + }, + step2: { + text: 'Cliquez sur "Create an App".', + imageAlt: 'Bouton Create an App' + }, + step3: { + text: 'Remplissez les champs "App name" et "App description" et cochez les deux cases. Cliquez ensuite sur le bouton "Create".', + imageAlt: 'Formulaire Create an App' + }, + step4: { + text: 'Vous pouvez maintenant visualiser le Client ID. Si vous cliquez sur "Show Client Secret", le Client Secret vous sera révélé.', + imageAlt: 'Ecran Client ID et Client Secret' + }, + step5: 'Vous pouvez maintenant copier-coller ces données dans les champs appropriés des paramètres.' + }, + usernameQuestion: { + title: "Comment obtenir mon nom d'utilisateur Spotify ?", + step1: { + text: "Vous pouvez obtenir votre nom d'utilisateur Spotify à partir de la page {overviewPage} sur site Web de Spotify.", + overviewPage: "Vue d'ensemble du compte" + } + } + } + }, + reset: 'Rétablir les valeurs par défaut', + resetMessage: 'Souhaitez-vous vraiment rétablir les paramètres par défaut ?', + save: 'Sauvegarder', + toasts: { + init: 'Paramètres chargés !', + update: 'Paramètres mis à jour !', + reset: 'Paramètres réinitialisés à leur valeur par défaut !', + ARLcopied: 'ARL copié dans le presse-papier' + } + }, + sidebar: { + home: 'accueil', + search: 'recherche', + charts: 'classements', + favorites: 'favoris', + linkAnalyzer: 'analyseur de lien', + settings: 'paramètres', + logs: 'journaux (logs)', + about: 'à propos' + }, + tracklist: { + downloadSelection: 'Télécharger la sélection' + } +} + +export default fr diff --git a/webui/src/lang/hr.mjs b/webui/src/lang/hr.mjs new file mode 100644 index 0000000..6f29be4 --- /dev/null +++ b/webui/src/lang/hr.mjs @@ -0,0 +1,359 @@ +const hr = { + globals: { + welcome: 'Dobrodošli u deemix', + back: 'nazad', + loading: 'učitavanje', + download: 'Preuzmi {thing}', + by: 'by {artist}', + in: 'u {album}', + download_hint: 'Preuzmi', + play_hint: 'Play', + toggle_download_tab_hint: 'Proširi/Smanji', + clean_queue_hint: 'Čišćenje završeno', + cancel_queue_hint: 'Zaustavi sve', + listTabs: { + empty: '', + all: 'sve', + top_result: 'Najbolji rezultat', + album: 'album | albumi', + artist: 'izvođač | izvođači', + single: 'singl | singlovi', + title: 'naslov | naslovi', + track: 'pjesma | pjesme', + trackN: '0 pjesmi | {n} pjesma | {n} pjesme', + releaseN: '0 izdanja | {n} izdanje | {n} izdanja', + playlist: 'playlista | playliste', + compile: 'kompilacija | kompilacije', + ep: 'ep | eps', + spotifyPlaylist: 'spotify playlista | spotify playliste', + releaseDate: 'datum izdavanja', + error: 'greška' + } + }, + about: { + titles: { + usefulLinks: 'Korisne poveznice', + bugReports: 'Prijave grešaka', + contributing: 'Doprinosi', + donations: 'Donacije', + license: 'Licenca' + }, + subtitles: { + bugReports: 'Postoji nešto što ne radi u deemixu? Reci nam!', + contributing: 'Želiš doprinijeti ovom projektu? Možeš i to čak u više načina!', + donations: 'Želiš doprijeniti odmah? Možeš donirati!' + }, + usesLibrary: + 'Ova aplikacija koristi deemix biblioteku, koju možeš koristiti i ti kako bi napravio svoj UI za demix.', + thanks: `Hvala rtonno, uhwot i lollilol što su mi pomogli s ovim projektom te BasCurtiz što su napravili ikonu.`, + upToDate: { + text: `Ostani u tijeku s nadogradnjama prateći {newsChannel} na Telegramu.`, + newsChannel: 'kanal s novostima' + }, + officialWebsite: 'Službena web stranica', + officialRepo: 'Službeni repozitorij biblioteke', + officialWebuiRepo: 'Službeni WebUI repozitorij', + officialSubreddit: 'Službeni subreddit', + newsChannel: 'Kanal s novostima', + questions: { + text: `Ukoliko imate pitanja o aplikaciji, prvo potražite riješenje na {subreddit}. Tada, ako ne pronađete ništa, možete objaviti svoj problem na subredditu.`, + subreddit: 'subreddit' + }, + beforeReporting: `Prije prijavljivanja greške provjerite imate li instaliranu zadnju verziju aplikacije i da to što želite prijaviti je ustvari pogreška, a ne nešto što samo vama ne radi.`, + beSure: `Provjerite može li se pogreška reproducirati i na drugim uređajima i također NEMOJTE prijavljivati grešku ako je već prijavljena.`, + duplicateReports: 'Duplicirane prijave o greški bit će zatvorene, tako da pripazite na to.', + dontOpenIssues: `NEMOJTE otvarati issue za postavljanje pitanja, za to postoji subreddit.`, + newUI: { + text: `Ako ste vješti u pythonu možete probati napraviti novi UI za aplikaciju koristeći osnovnu biblioteku ili ispraviti pogrešku u biblioteci sa pull zahtjevom na {repo}.`, + repo: 'repozitoriju' + }, + acceptFeatures: `Prihavaćam i značajke, ali bez kompleksnih stvari, jer one mogu biti implementirane direktno u aplikaciji, a ne u biblioteci.`, + otherLanguages: `Ako ste vješti u drugom programskom jezikumožete probati portati deemix u drugi programski jezik!`, + understandingCode: `Trebate pomoć s razumijevanjem koda? Samo potraži RemixDev na Telegramu ili Redditu.`, + contributeWebUI: { + text: `Ako znaš Vue.js (JavaScript), HTML ili CSS možete doprinijeti za {webui}.`, + webui: 'WebUI' + }, + itsFree: `Trebate zapamtiti da je ovo besplatni projekt i trebali biste podržati autore koje volite prije podržavanja developera.`, + notObligated: `Nemojte se osjećati obveznim darivati, svejedno vas cijenim!`, + lincensedUnder: { + text: `Ovaj rad licenciran je unutar {gpl3}.`, + gpl3: 'GNU General Public License 3.0' + } + }, + charts: { + title: 'Ljestvice', + changeCountry: 'Promijeni državu', + download: 'Preuzmi ljestvicu' + }, + errors: { + title: 'Greške za {name}', + ids: { + invalidURL: 'URL nije prepoznat', + unsupportedURL: 'URL još nije podržan', + ISRCnotOnDeezer: 'Zapis ISRC još nije podržan na Deezeru', + notYourPrivatePlaylist: 'Ne možete preuzeti tuđe privatne playliste.', + spotifyDisabled: 'Spotify značajke nisu podešene ispravno.', + trackNotOnDeezer: 'Pjesma nije pronađena na Deezeru!', + albumNotOnDeezer: 'Album nije pronađen na Deezeru!', + notOnDeezer: 'Pjesma nije dostupna na Deezeru!', + notEncoded: 'Pjesma još nije enkodirana!', + notEncodedNoAlternative: 'Pjesma još nije enkodirana i nije pronađena alternativa!', + wrongBitrate: 'Pjesma nije pronađena u željenom bitrateu.', + wrongBitrateNoAlternative: 'Pjesma nije pronađena u željenom bitrateu i nije pronađena alternativa!', + no360RA: 'Pjesma nije dostupna u Reality Audio 360.', + notAvailable: 'Pjesma nije dostupna na Deezerovim serverima!', + notAvailableNoAlternative: 'Pjesma nije dostupna na Deezerovim serverima i alternativa nije pronađena!' + } + }, + favorites: { + title: 'Favoriti', + noPlaylists: 'Nisu pronađene playliste', + noAlbums: 'Omiljeni albumi nisu pronađeni', + noArtists: 'Omiljeni glazbenici nisu pronađeni', + noTracks: 'Omiljene pjesme nisu pronađene' + }, + home: { + needTologin: 'Trebate se prijaviti sa svojim Deezer računom kako biste mogli početi preuzimati pjesme.', + openSettings: 'Otvori postavke', + sections: { + popularPlaylists: 'Popularne playliste', + popularAlbums: 'Najpreslušaniji album' + } + }, + linkAnalyzer: { + info: 'Ovu sekciju možete koristiti kako biste saznali više informacija o linku koji pokušavate preuzeti.', + useful: + 'Ovo je korisno ako pokušavate preuzeti pjesme koje još nisu dostupne u vašoj zemlji i želite, na primjer, znati gdje su dostupne.', + linkNotSupported: 'Ovaj link još nije podržan', + linkNotSupportedYet: 'Čini se da ovaj link još nije podržan, pokušaj analizirati neki drugi.', + table: { + id: 'ID', + isrc: 'ISRC', + upc: 'UPC', + duration: 'Trajanje', + diskNumber: 'Broj diska', + trackNumber: 'Broj pjesme', + releaseDate: 'Datum izadavanja', + bpm: 'BPM', + label: 'Izdavačka kuća', + recordType: 'Vrsta zapisa', + genres: 'Žanrovi', + tracklist: 'Popis pjesama' + } + }, + search: { + startSearching: 'Počni pretraživati!', + description: + 'Možete pretražiti pjesmu, cijeli album, izvođača, playlistu... sve! Također, možete i zalijepiti Deezer link', + fans: '{n} obožavatelja', + noResults: 'Nema rezultata', + noResultsTrack: 'Pjesme nisu pronađene', + noResultsAlbum: 'Albumi nisu pronađeni', + noResultsArtist: 'Izvođači nisu pronađeni', + noResultsPlaylist: 'Playliste nisu pronađene' + }, + searchbar: 'Pretraži bilo što (ili samo zalijepi link)', + downloads: 'preuzimanja', + toasts: { + addedToQueue: '{item} dodan u red', + alreadyInQueue: '{item} je već u redu!', + finishDownload: '{item} završeno preuzimanje.', + allDownloaded: 'Sva preuzimanja završena!', + refreshFavs: 'Osvježavanje završeno!', + loggingIn: 'Prijavljivanje...', + loggedIn: 'Prijavljeni', + alreadyLogged: 'Već prijavljeni', + loginFailed: 'Prijava nije bila moguća', + loggedOut: 'Odjavljeni', + cancellingCurrentItem: 'Otkazujem trenutnu stavku.', + currentItemCancelled: 'Trenutna stavka otkazana.', + startAddingArtist: 'Dodajem {artist} album u red', + finishAddingArtist: 'Dodan {artist} album u red', + startConvertingSpotifyPlaylist: 'Pretvaram Spotify pjesme u Deezer pjesme', + finishConvertingSpotifyPlaylist: 'Spotify playlista pretvorena', + loginNeededToDownload: 'Trebate se prijaviti kako bi preuzeli pjesme!' + }, + settings: { + title: 'Postavke', + languages: 'Jezici', + login: { + title: 'Prijava', + loggedIn: 'Prijavljeni ste kao {username}', + arl: { + question: 'Kako da dobijem svoj ARL?', + update: 'Ažuriraj ARL' + }, + logout: 'Odjavi se' + }, + appearance: { + title: 'Izgled', + slimDownloadTab: 'Tanka kartica za preuzimanje' + }, + downloadPath: { + title: 'Putanja za preuzimanja' + }, + templates: { + title: 'Predlošci', + tracknameTemplate: 'Naziv pjesme predložak', + albumTracknameTemplate: 'Pjesma albuma predložak', + playlistTracknameTemplate: 'Pjesma playliste predložak' + }, + folders: { + title: 'Mape', + createPlaylistFolder: 'Izradi mapu za playliste', + playlistNameTemplate: 'Mapa za playliste predložak', + createArtistFolder: 'Izradi mapu za izvođača', + artistNameTemplate: 'Izvođač mapa predložak', + createAlbumFolder: 'Izradi mapu za album', + albumNameTemplate: 'Album mapa predložak', + createCDFolder: 'Izradi mapu za CD', + createStructurePlaylist: 'Strkturiraj mape za playliste', + createSingleFolder: 'Strukturiraj mape za singlove' + }, + trackTitles: { + title: 'Naslovi pjesama', + padTracks: 'Pad tracks', + paddingSize: 'Prepiši veličinu paddinga', + illegalCharacterReplacer: 'Zamjena za nedozvoljeni znak' + }, + downloads: { + title: 'Preuzimanja', + queueConcurrency: 'Istovremena preuzimanja', + maxBitrate: { + title: 'Željeni bitrate', + 9: 'FLAC 1411kbps', + 3: 'MP3 320kbps', + 1: 'MP3 128kbps' + }, + overwriteFile: { + title: 'Trebam li prepisati datoteke?', + y: 'Da, prepiši datoteke', + n: 'Ne, nemoj prepisati datoteke', + t: 'Prepiši samo oznake', + b: 'Ne, zadrži obje datoteke i dodaj broj duplikatu' + }, + fallbackBitrate: 'Bitrate fallback', + fallbackSearch: 'Pretraživanje fallback', + logErrors: 'Izradi zapisnik datoteku za greške', + logSearched: 'Izradi zapisnik datoteku za pretražene pjesme', + createM3U8File: 'Izradi playlist datoteku', + syncedLyrics: 'Izradi .lrc datoteke (sinkronizirani lyrics)', + playlistFilenameTemplate: 'Naziv playliste predložak', + saveDownloadQueue: 'Spremi red za preuzimanje prilikom zatvaranja aplikacije' + }, + covers: { + title: 'Omoti albuma', + saveArtwork: 'Spremi omote', + coverImageTemplate: 'Naziv omota predložak', + saveArtworkArtist: 'Spremi sliku izvođača', + artistImageTemplate: 'Slika izvođača predložak', + localArtworkSize: 'Veličina lokalnog omota', + embeddedArtworkSize: 'Veličina ugrađenog omota', + localArtworkFormat: { + title: 'U kojem formatu želite lokalni omot?', + jpg: 'Jpeg slika', + png: 'Png slika', + both: 'I jpeg i png' + }, + jpegImageQuality: 'JPEG kvaliteta slike' + }, + tags: { + head: 'Koja oznake spremam', + title: 'Naslovi', + artist: 'Izvođač', + album: 'Album', + cover: 'Omot', + trackNumber: 'Broj pjesme', + trackTotal: 'Ukupno pjesama', + discNumber: 'Broj diska', + discTotal: 'Ukupno diskova', + albumArtist: 'Izvođač albuma', + genre: 'Žanr', + year: 'Godina', + date: 'Datum', + explicit: 'Eksplicitni lyrics', + isrc: 'ISRC', + length: 'Dužina pjesme', + barcode: 'Album barkod (UPC)', + bpm: 'BPM', + replayGain: 'Replay Gain', + label: 'Izdavačka kuća albuma', + lyrics: 'Nesinkronizirani lyrics', + copyright: 'Autorska prava', + composer: 'Skladatelj', + involvedPeople: 'Uključeni ljudi' + }, + other: { + title: 'Ostalo', + savePlaylistAsCompilation: 'Spremi playliste kao kompilacije', + useNullSeparator: 'Koristi null razdvojnik', + saveID3v1: 'Spremi i ID3v1 također', + multiArtistSeparator: { + title: 'Kako biste željeli razdvojiti izvođače?', + nothing: 'Spremi samo glavnog izvođača', + default: 'Koristeći standardnu specifikaciju', + andFeat: 'Koristeći & i feat.', + using: 'Koristeći "{separator}"' + }, + singleAlbumArtist: 'Spremi samo izvođača glavnog albuma', + albumVariousArtists: 'Zadrži "Various Artists" u Izvođačima albuma', + removeAlbumVersion: 'Izbriši "Album Version" iz naziva pjesme', + removeDuplicateArtists: 'Izbriši kombinacije izvođača', + dateFormat: { + title: 'Format datuma za FLAC datoteke', + year: 'YYYY', + month: 'MM', + day: 'DD' + }, + featuredToTitle: { + title: 'Što trebam napraviti s istaknutim izvođačima? (feat. i ft.)', + 0: 'Ništa', + 1: 'Izbriši ih iz naziva', + 3: 'Izbriši ih iz naziva i iz naziva albuma', + 2: 'Premjesti ih u naziv' + }, + titleCasing: 'Veličina slova naslova', + artistCasing: 'Veličina slova izvođača', + casing: { + nothing: 'Zadrži nepromijenjeno', + lower: 'sve malo', + upper: 'sve VELIKO', + start: 'Početak Svake Riječi', + sentence: 'Kao rečenica' + }, + previewVolume: 'Volumen pregleda', + executeCommand: { + title: 'Naredba za izvršenje nakon preuzimanja', + description: 'Ostavi prazno za bez akcije' + } + }, + spotify: { + title: 'Spotify značajke', + clientID: 'Spotify ClientID', + clientSecret: 'Spotify Client Secret', + username: 'Spotify korisničko ime' + }, + reset: 'Resetiraj na zadano', + save: 'Spremi', + toasts: { + init: 'Postavke učitane!', + update: 'Postavke ažurirane!', + ARLcopied: 'ARL kopiran u međuspremnik' + } + }, + sidebar: { + home: 'početna', + search: 'pretraživanje', + charts: 'ljestvice', + favorites: 'favoriti', + linkAnalyzer: 'analizator linka', + settings: 'postavke', + about: 'o programu' + }, + tracklist: { + downloadSelection: 'Preuzmi selekciju' + } +} + +export default hr diff --git a/webui/src/lang/id.mjs b/webui/src/lang/id.mjs new file mode 100644 index 0000000..3532157 --- /dev/null +++ b/webui/src/lang/id.mjs @@ -0,0 +1,357 @@ +const id = { + globals: { + welcome: 'Selamat datang di deemix', + back: 'kembali', + loading: 'memuat', + download: 'Mengunduh {thing}', + by: 'oleh {artist}', + in: 'di {album}', + download_hint: 'Unduh', + play_hint: 'Putar', + toggle_download_tab_hint: 'Buka/Tutup', + clean_queue_hint: 'Berhasil Mengosongkan', + cancel_queue_hint: 'Batalkan Semua', + listTabs: { + empty: '', + all: 'semua', + top_result: 'hasil teratas', + album: 'album | album', + artist: 'artis | artis', + single: 'singel | singel', + title: 'judul | judul', + track: 'lagu | lagu', + trackN: '0 lagu | {n} lagu | {n} lagu', + releaseN: '0 rilis | {n} rilis | {n} rilis', + playlist: 'daftar putar | daftar putar', + compile: 'kompilasi | kompilasi', + ep: 'ep | ep', + spotifyPlaylist: 'daftar putar spotify | daftar putar spotify', + releaseDate: 'tanggal rilis', + error: 'galat' + } + }, + about: { + titles: { + usefulLinks: 'Tautan Berguna', + bugReports: 'Laporan Kesalahan', + contributing: 'Kontirbutor', + donations: 'Donasi', + license: 'Lisensi' + }, + subtitles: { + bugReports: 'Ada yang tidak bekerja dengan baik di deemix? Beri tahu kami!', + contributing: 'Mau kontribusi dalam proyek ini? Kamu bisa lakukan dengan banyak hal!', + donations: 'Mau kontribusi secara finansial? Kamu bisa beri donasi!' + }, + usesLibrary: + 'Aplikasi ini menggunakan pustaka deemix, yang bisa kamu gunakan untuk membuat UI deemix milikmu sendiri.', + thanks: `Terima kasih kepada rtonno, uhwot dan lollilol yang telah membantuku dalam proyek ini, serta kepada BasCurtiz yang telah membuat ikon.`, + upToDate: { + text: `Ikuti {newsChannel} di Telegram agar tidak ketinggalan berita terbaru.`, + newsChannel: 'kanal berita deemix' + }, + officialWebsite: 'Situs Web Resmi', + officialRepo: 'Repositori Pustaka Resmi', + officialWebuiRepo: 'Repositori WebUI Resmi', + officialSubreddit: 'Subreddit Resmi', + newsChannel: 'Kanal Berita', + questions: { + text: `Kalau kamu punya pertanyaan atau masalah dengan aplikasi ini, tolong cari solusinya di {subreddit} kami terlebih dahulu. Kalau memang tidak ada, silakan buat pos baru berisikan persoalan tersebut.`, + subreddit: 'subreddit' + }, + beforeReporting: `Sebelum melaporkan masalah, pastikan kamu sudah memakai versi aplikasi terbaru dan hal yang akan kamu laporkan memang bukan kesalahan dari pihak kamu sendiri.`, + beSure: `Pastikan masalah tersebut bisa diemulasikan di mesin lain, dan juga JANGAN laporkan masalah yang sudah dilaporkan sebelumnya.`, + duplicateReports: 'Laporan duplikat akan kami tutup, jadi perhatikan baik-baik.', + dontOpenIssues: `JANGAN buka issue baru untuk mengirimkan pertanyaan, silakan lakukan di subreddit.`, + newUI: { + text: `Kalau kamu mahir pada python, kamu bisa coba membuat UI baru untuk aplikasi ini menggunakan pustaka dasar, atau membenarkan masalah di pustaka kami dengan melakukan pull request pada {repo} kami.`, + repo: 'repo' + }, + acceptFeatures: `Kami juga menerima fitur baru, tapi jangan yang terlalu kompleks, karena hal itu lebih baik diimplementasikan langsung di aplikasi daripada di pustaka.`, + otherLanguages: `Kalau kamu mahir dengan bahasa pemrograman lain, kamu bisa coba mentransfer deemix ke bahasa tersebut!`, + understandingCode: `Butuh bantuan untuk memahami kode deemix? Kontak RemixDev di Telegram atau Reddit.`, + contributeWebUI: { + text: `Kalau kamu paham Vue.js (JavaScript), HTML, atau CSS, kamu bisa berkontribusi pada {webui}.`, + webui: 'WebUI' + }, + itsFree: `Perlu diingat bahwa ini adalah proyek gratis dan dukung artis idolamu terlebih dahulu sebelum mendukung kami sebagai pengembang aplikasi.`, + notObligated: `Jangan merasa terpaksa untuk menyumbang, kami tetap menghargai kamu!`, + lincensedUnder: { + text: `Pekerjaan ini ada di bawah lisensi {gpl3}.`, + gpl3: 'GNU General Public License 3.0' + } + }, + charts: { + title: 'Tangga Lagu', + changeCountry: 'Ubah Negara', + download: 'Unduh Tangga Lagu' + }, + errors: { + title: 'Galat untuk {name}', + ids: { + invalidURL: 'URL tidak dikenal', + unsupportedURL: 'URL belum didukung', + ISRCnotOnDeezer: 'Lagu ISRC tidak tersedia di deezer', + notYourPrivatePlaylist: 'Kamu tidak bisa mengunduh daftar putar privat orang lain.', + spotifyDisabled: 'Fitur Spotify tidak diatur dengan benar.', + trackNotOnDeezer: 'Lagu tidak ditemukan di deezer!', + albumNotOnDeezer: 'Album tidak ditemukan di deezer!', + notOnDeezer: 'Lagu tidak ada di Deezer!', + notEncoded: 'Lagu belum di-encode!', + notEncodedNoAlternative: 'Lagu belum di-encode dan tidak ada alternatif lain!', + wrongBitrate: 'Lagu tidak tersedia pada bitrate yang diinginkan.', + wrongBitrateNoAlternative: 'Lagu tidak tersedia pada bitrate yang diinginkan dan tidak ada alternatif lain!', + no360RA: 'Lagu tidak tersedia pada Reality Audio 360.', + notAvailable: 'Lagu tidak tersedia pada server deezer!', + notAvailableNoAlternative: 'Lagu tidak tersedia pada server deezer dan tidak ada alternatif lain!' + } + }, + favorites: { + title: 'Favorit', + noPlaylists: 'Daftar Putar kosong', + noAlbums: 'Album Favorit kosong', + noArtists: 'Artis Favorit kosong', + noTracks: 'Lagu Favorit kosong' + }, + home: { + needTologin: 'Kamu harus masuk ke akun Deezer kamu sebelum bisa memulai pengunduhan.', + openSettings: 'Buka Pengaturan', + sections: { + popularPlaylists: 'Daftar putar populer', + popularAlbums: 'Album paling banyak diputar' + } + }, + linkAnalyzer: { + info: 'Di sini, kamu bisa mencari informasi lebih lanjut tentang tautan yang ingin kamu unduh.', + useful: + 'Contohnya, ini dapat berguna jika kamu ingin mengunduh lagu yang tidak tersedia di negaramu dan ingin tahu di negara mana lagu itu tersedia.', + linkNotSupported: 'Tautan seperti ini belum didukung', + linkNotSupportedYet: 'Sepertinya tautan ini belum didukung, silakan coba analisa tautan lain.', + table: { + id: 'ID', + isrc: 'ISRC', + upc: 'UPC', + duration: 'Durasi', + diskNumber: 'Nomor Disk', + trackNumber: 'Nomor Lagu', + releaseDate: 'Tanggal Rilis', + bpm: 'BPM', + label: 'Label', + recordType: 'Tipe Rekaman', + genres: 'Genre', + tracklist: 'Daftar Lagu' + } + }, + search: { + startSearching: 'Mulai cari!', + description: + 'Kamu bisa mencari lagu, album, artis, daftar putar.... apa pun! Kamu juga bisa memberikan tautan Deezer', + fans: '{n} fan', + noResults: 'Tak ada hasil', + noResultsTrack: 'Lagu tidak ditemukan', + noResultsAlbum: 'Album tidak ditemukan', + noResultsArtist: 'Artis tidak ditemukan', + noResultsPlaylist: 'Daftar putar tidak ditemukan' + }, + searchbar: 'Cari apa pun yang kamu mau (atau berikan tautannya saja)', + downloads: 'unduhan', + toasts: { + addedToQueue: '{item} ditambah ke antrian', + alreadyInQueue: '{item} sudah ada di antrian!', + finishDownload: '{item} selesai diunduh.', + allDownloaded: 'Seluruh unduhan selesai!', + refreshFavs: 'Penyegaran selesai!', + loggingIn: 'Masuk', + loggedIn: 'Telah masuk', + alreadyLogged: 'Telah masuk', + loginFailed: 'Tidak bisa masuk', + loggedOut: 'Belum masuk', + cancellingCurrentItem: 'Membatalkan item.', + currentItemCancelled: 'Item telah dibatalan.', + startAddingArtist: 'Menambahkan {artist} album ke antrian', + finishAddingArtist: '{artist} album telah ditambahkan ke antrian', + startConvertingSpotifyPlaylist: 'Mengonversi lagu spotify ke deezer', + finishConvertingSpotifyPlaylist: 'Daftar putar Spotify selesai dikonversi' + }, + settings: { + title: 'Pengaturan', + languages: 'Bahasa', + login: { + title: 'Masuk', + loggedIn: 'Kamu telah masuk sebagai {username}', + arl: { + question: 'Bagaimana cara mendapat ARL?', + update: 'Perbarui ARL' + }, + logout: 'Keluar' + }, + appearance: { + title: 'Tampilan', + slimDownloadTab: 'Tab unduhan ramping' + }, + downloadPath: { + title: 'Direktori Unduhan' + }, + templates: { + title: 'Templat', + tracknameTemplate: 'Templat judul lagu', + albumTracknameTemplate: 'Templat judul album', + playlistTracknameTemplate: 'Templat judul daftar putar' + }, + folders: { + title: 'Folders', + createPlaylistFolder: 'Buat folder untuk daftar putar', + playlistNameTemplate: 'Templat folder daftar putar', + createArtistFolder: 'Buat folder untuk artis', + artistNameTemplate: 'Templat folder artis', + createAlbumFolder: 'Buat folder untuk album', + albumNameTemplate: 'Templat folder album', + createCDFolder: 'Buat folder untuk CD', + createStructurePlaylist: 'Buat struktur folder untuk daftar putar', + createSingleFolder: 'Buat struktur folder untuk singel' + }, + trackTitles: { + title: 'Judul lagu', + padTracks: 'Judul pad', + paddingSize: 'Timpa ukuran padding', + illegalCharacterReplacer: 'Pengubah Simbol Tak Terdukung' + }, + downloads: { + title: 'Unduhan', + queueConcurrency: 'Unduhan Bersamaan', + maxBitrate: { + title: 'Bitrate Prioritas', + 9: 'FLAC 1411kbps', + 3: 'MP3 320kbps', + 1: 'MP3 128kbps' + }, + overwriteFile: { + title: 'Apakah file mau ditimpa?', + y: 'Ya, silakan', + n: 'Tidak, jangan ditimpa', + t: 'Timpa tag-nya saja' + }, + fallbackBitrate: 'Rendahkan bitrate', + fallbackSearch: 'Cari bitrate lebih rendah', + logErrors: 'Buat file log untuk galat', + logSearched: 'Buat file log untuk lagu yang dicari', + createM3U8File: 'Buat file daftar putar', + syncedLyrics: 'Buat file .lrc (Sinkronisasikan Lirik)', + playlistFilenameTemplate: 'Templat nama file untuk daftar putar', + saveDownloadQueue: 'Simpan antrian pengunduhan saat menutup aplikasi' + }, + covers: { + title: 'Sampul album', + saveArtwork: 'Simpan Sampul', + coverImageTemplate: 'Templat nama sampul', + saveArtworkArtist: 'Simpan gambar artis', + artistImageTemplate: 'Templat gambar artis', + localArtworkSize: 'Ukuran sampul lokal', + embeddedArtworkSize: 'Ukuran sampul tertanam', + localArtworkFormat: { + title: 'Format gambar apa yang kamu mau untuk sampul lokal?', + jpg: 'Gambar JPEG', + png: 'Gambar PNG', + both: 'Keduanya' + }, + jpegImageQuality: 'Kualitas gambar JPEG' + }, + tags: { + head: 'Tag apa saja yang disimpan?', + title: 'Judul', + artist: 'Artis', + album: 'Album', + cover: 'Sampul', + trackNumber: 'Nomor Lagu', + trackTotal: 'Jumlah Lagu', + discNumber: 'Nomor Disk', + discTotal: 'Jumlah Disk', + albumArtist: 'Artis pada Album', + genre: 'Genre', + year: 'Tahun', + date: 'Tanggal', + explicit: 'Lirik Eksplisit', + isrc: 'ISRC', + length: 'Durasi', + barcode: 'Barcode Album (UPC)', + bpm: 'BPM', + replayGain: 'Replay Gain', + label: 'Label Album', + lyrics: 'Lirik Tak Tersinkronisasi', + copyright: 'Hak Cipta', + composer: 'Komposer', + involvedPeople: 'Orang-Orang Terlibat' + }, + other: { + title: 'Lainnya', + savePlaylistAsCompilation: 'Simpan daftar putar sebagai kompilasi', + useNullSeparator: 'Gunakan separator null', + saveID3v1: 'Simpan juga ID3v1', + multiArtistSeparator: { + title: 'Bagaimana kamu mau memisahkan nama artis?', + nothing: 'Simpan artis utamanya saja', + default: 'Gunakan spesifikasi standard', + andFeat: 'Gunakan & dan feat.', + using: 'Gunakan "{separator}"' + }, + singleAlbumArtist: 'Simpan artis utama saja', + albumVariousArtists: 'Simpan "Various Artists" sebagai artis', + removeAlbumVersion: 'Hapus "Versi Album" dari judul lagu', + removeDuplicateArtists: 'Hapus kombinasi artis', + dateFormat: { + title: 'Format tanggal untuk file FLAC', + year: 'YYYY', + month: 'MM', + day: 'DD' + }, + featuredToTitle: { + title: 'Apa yang harus dilakukan jika ada artis kedua?', + 0: 'Biarkan saja', + 1: 'Hapus dari judul lagu', + 3: 'Hapus dari judul lagu dan judul album', + 2: 'Pindahkan ke judul lagu' + }, + titleCasing: 'Kapitalisasi judul', + artistCasing: 'Kapitalisasi album', + casing: { + nothing: 'Biarkan seadanya', + lower: 'huruf kecil', + upper: 'HURUF KAPITAL', + start: 'Setiap Awal Kata', + sentence: 'Huruf pertama saja' + }, + previewVolume: 'Pratinjau volume', + executeCommand: { + title: 'Perintah yang dijalankan setelah pengunduhan', + description: 'Biarkan kosong jika tidak ada' + } + }, + spotify: { + title: 'Fitur Spotify', + clientID: 'clientID Spotify ', + clientSecret: 'Client Secret Spotify ', + username: 'Username Spotify' + }, + reset: 'Kembalikan ke Awal', + save: 'Simpan', + toasts: { + init: 'Pengaturan dimuat!', + update: 'Pengaturan diperbarui!', + ARLcopied: 'ARL tersalin ke papan klip' + } + }, + sidebar: { + home: 'utama', + search: 'cari', + charts: 'tangga lagu', + favorites: 'favorit', + linkAnalyzer: 'penganalisa tautan', + settings: 'pengaturan', + about: 'tentang' + }, + tracklist: { + downloadSelection: 'Seleksi unduhan' + } +} + +export default id diff --git a/webui/src/lang/index.js b/webui/src/lang/index.js new file mode 100644 index 0000000..9a27f8a --- /dev/null +++ b/webui/src/lang/index.js @@ -0,0 +1,44 @@ +// Using ISO 639-1 where possible +import it from '@/lang/it' +import en from '@/lang/en' +import es from '@/lang/es' +import de from '@/lang/de' +import fr from '@/lang/fr' +import id from '@/lang/id' +import pt from '@/lang/pt-pt' +import pt_br from '@/lang/pt-br' +import ru from '@/lang/ru' +import tr from '@/lang/tr' +import vi from '@/lang/vi' +import hr from '@/lang/hr' +import ar from '@/lang/ar' +import ko from '@/lang/ko' +import fil from '@/lang/fil' +import zh_tw from '@/lang/zh-tw' +import pl from '@/lang/pl' +import el from '@/lang/el' +import sr from '@/lang/sr' +import th from '@/lang/th' + +export const locales = { + it, + en, + es, + de, + fr, + id, + pt, + pt_br, + ru, + tr, + vi, + hr, + ar, + ko, + fil, + zh_tw, + pl, + el, + sr, + th +} diff --git a/webui/src/lang/it.mjs b/webui/src/lang/it.mjs new file mode 100644 index 0000000..5672498 --- /dev/null +++ b/webui/src/lang/it.mjs @@ -0,0 +1,517 @@ +const it = { + globals: { + welcome: 'Benvenuto su deemix', + back: 'indietro', + loading: 'caricamento', + download: 'Scarica {thing}', + by: 'di {artist}', + in: 'in {album}', + download_hint: 'Scarica', + play_hint: 'Riproduci', + toggle_download_tab_hint: 'Espandi/Riduci', + clean_queue_hint: 'Pulisci Lista', + cancel_queue_hint: 'Cancella tutti i download', + open_downloads_folder: 'Apri la cartella di download', + cut: 'taglia', + copy: 'copia', + copyLink: 'copia link', + copyImageLink: 'copia link immagine', + copyDeezerLink: 'copia link deezer', + paste: 'incolla', + listTabs: { + all: 'tutto', + discography: 'discografia', + top_result: 'miglior risultato', + album: 'album', + artist: 'artista | artisti', + single: 'singolo | singoli', + title: 'titolo | titoli', + track: 'brano | brani', + releaseN: '0 dischi | {n} disco | {n} dischi', + playlist: 'playlist', + compile: 'compilation', + bundle: 'collezione | collezioni', + ep: 'ep', + more: 'Altri album', + featured: 'Compare in', + spotifyPlaylist: 'playlist spotify', + releaseDate: 'data di uscita', + error: 'errore', + empty: '', + trackN: '0 brani | {n} brano | {n} brani', + albumN: '{n} album', + artistN: '0 artisti | {n} artista | {n} artisti', + playlistN: '{n} playlist' + }, + yes: 'sì', + no: 'no', + empty: 'vuoto' + }, + about: { + appStatus: { + online: 'app online', + offline: 'app offline' + }, + updates: { + currentVersion: 'Versione attuale', + currentWebuiVersion: 'Versione WebUI attuale', + versionNotAvailable: 'N/A', + updateAvailable: `Non stai usando l'ultima versione disponibile: {version}`, + deemixVersion: 'Versione libreria deemix' + }, + titles: { + usefulLinks: 'Link Utili', + bugReports: 'Segnalazione di bug', + contributing: 'Contribuire al progetto', + donations: 'Donazioni', + license: 'Licenza' + }, + subtitles: { + bugReports: "C'è qualcosa di deemix che non funziona? Faccelo sapere!", + contributing: 'Vuoi contribuire a questo progetto? Puoi farlo in più modi!', + donations: 'Vuoi dare una mano economicamente? Puoi fare una donazione!' + }, + usesLibrary: + 'Questa app utilizza la libreria deemix, che puoi utilizzare per creare la tua Interfaccia Utente per deemix.', + thanks: `Un ringraziamento a rtonno, uhwot e lollilol per l'aiuto che mi stanno dando in questo progetto e a BasCurtiz per aver creato l'icona.`, + upToDate: { + text: `Rimani al passo con gli ultimi aggiornamenti seguendo il {newsChannel} su Telegram.`, + newsChannel: 'canale delle news' + }, + officialWebsite: 'Sito Ufficiale', + officialRepo: 'Repository Ufficiale della Libreria', + officialWebuiRepo: `Repository Ufficiale dell'Interfaccia Web`, + officialSubreddit: 'Subreddit Ufficiale', + newsChannel: 'Canale delle news', + devlogChannel: 'Canale Devlog', + questions: { + text: `Se dovessi avere domande o problemi con l'app, cerca prima una soluzione nel {subreddit}. Se non trovi nulla, puoi postare li il tuo problema.`, + subreddit: 'subreddit ufficiale' + }, + beforeReporting: `Prima di segnalare un problema controlla che quella che stai usando sia l'ultima versione dell'app e che ciò che vuoi segnalare sia effettivamente un problema e non qualcosa che non funziona solamente a te.`, + beSure: `Assicurati che il problema sia riproducibile su altri PC e NON segnalare un problema che è già stato segnalato.`, + duplicateReports: 'Le segnalazioni doppie verranno chiuse, tienilo presente.', + dontOpenIssues: `NON aprire issues per porre domande, per quello esiste un subreddit.`, + newUI: { + text: `Se te la cavi in python puoi provare a creare una nuova Interfaccia Utente per l'app usando la libreria base, oppure puoi correggere dei problemi nella libreria con una pull request nella {repo}.`, + repo: 'repo' + }, + acceptFeatures: `Accetto anche funzionalità, ma non cose complesse, dato che possono essere implementate direttamente nell'app invece che nella libreria.`, + otherLanguages: `Se te la cavi in altri linguaggi di programmazione, puoi provare a scrivere deemix in quei linguaggi!`, + understandingCode: `Serve aiuto per capire il codice? Scrivi a RemixDev su Telegram o Reddit`, + contributeWebUI: { + text: `Se te la cavi con Vue.js (JavaScript), HTML o CSS, puoi contribuire alla {webui}.`, + webui: 'WebUI' + }, + itsFree: `Ricordati che questo è un progetto gratuito e che dovresti supportare gli artisti che ami prima di supportare gli sviluppatori.`, + notObligated: `Non sentirti obbligato a donare, mi stai simpatico lo stesso!`, + lincensedUnder: { + text: `Questo progetto è sotto la licenza {gpl3}.`, + gpl3: 'GNU General Public License 3.0' + } + }, + charts: { + title: 'Classifiche', + changeCountry: 'Cambia Paese', + download: 'Scarica Classifica' + }, + errors: { + title: 'Errori riguardanti {name}', + postTitle: 'Errori dopo il download', + ids: { + invalidURL: 'URL non riconosciuto', + unsupportedURL: 'URL non ancora supportato', + ISRCnotOnDeezer: 'Questo ISRC non è disponibile su Deezer', + notYourPrivatePlaylist: 'Non puoi scaricare le playlist private degli altri.', + spotifyDisabled: 'Spotify Features non è impostato correttamente.', + trackNotOnDeezer: 'Brano non trovato su Deezer!', + albumNotOnDeezer: 'Album non trovato su Deezer!', + notOnDeezer: 'Brano non disponibile su Deezer!', + notEncoded: 'Brano non ancora codificato!', + notEncodedNoAlternative: 'Brano non ancora codificato e nessuna alternativa trovata!', + wrongBitrate: 'Brano non trovato con il bitrate specificato.', + wrongBitrateNoAlternative: 'Brano non trovato con il bitrate specificato e nessuna alternativa trovata!', + no360RA: 'Brano non disponibile in Reality Audio 360.', + notAvailable: 'Brano non presente sui server di Deezer!', + notAvailableNoAlternative: 'Brano non presente sui server di Deezer e nessuna alternativa trovata!', + noSpaceLeft: 'Spazio su disco esaurito!', + albumDoesntExists: 'Il brano non ha nessun album, impossibile ottenere informazioni', + wrongLicense: 'Il tuo account non può ascoltare brani in {bitrate}.', + wrongGeolocation: 'Il tuo account non può ascoltare questo brano dal tuo paese.', + wrongGeolocationNoAlternative: 'Il tuo account non può ascoltare questo brano dal e nessuna alternativa trovata.' + } + }, + favorites: { + title: 'Preferiti', + noPlaylists: 'Nessuna Playlist preferita trovata', + noAlbums: 'Nessun Album preferito trovato', + noArtists: 'Nessun Artista preferito trovato', + noTracks: 'Nessun Brano preferito trovato' + }, + home: { + needTologin: 'Devi accedere al tuo account Deezer, fino a quel momento non potrai scaricare nulla.', + openSettings: 'Apri le impostazioni', + sections: { + popularPlaylists: 'Playlist Popolari', + popularAlbums: 'Album più riprodotti' + } + }, + linkAnalyzer: { + info: 'Puoi utilizzare questa sezione per avere più informazioni riguardanti il link che stai cercando di scaricare.', + useful: + 'Ciò può esserti utile se stai cercando di scaricare brani che non sono disponibili nel tuo Paese e vuoi sapere in quale Paese sono invece disponibili, per esempio.', + linkNotSupported: 'Questo link non è ancora supportato', + linkNotSupportedYet: 'Sembra che questo link non sia ancora supportato, prova ad analizzarne un altro.', + table: { + id: 'ID', + isrc: 'ISRC', + upc: 'UPC', + duration: 'Durata', + diskNumber: 'Numero Disco', + trackNumber: 'Numero Traccia', + releaseDate: 'Data di uscita', + bpm: 'BPM', + label: 'Etichetta', + recordType: 'Tipologia di registrazione', + genres: 'Generi', + tracklist: 'Lista tracce', + readable: 'Leggibile', + available: 'Disponibile' + }, + countries: 'Paesi', + noCountries: 'Questo brano non è disponibile in nessun paese.' + }, + search: { + startSearching: 'Inizia a cercare!', + description: + 'Puoi cercare un brano, un intero album, un artista, una playlist.... quello che vuoi! Puoi anche incollare un link di Deezer', + fans: '{n} fan', + noResults: 'Nessun risultato', + noResultsTrack: 'Nessun brano trovato', + noResultsAlbum: 'Nessun album trovato', + noResultsArtist: 'Nessun artista trovato', + noResultsPlaylist: 'Nessuna playlist trovata', + error: 'Si è verificato un errore, riprova più tardi.' + }, + searchbar: 'Cerca qualsiasi cosa (o incolla semplicemente un link)', + downloads: 'download', + toasts: { + restoringQueue: 'Ripristinando la coda di download...', + queueRestored: 'Coda di download ripristinata!', + addedToQueue: '{item} aggiunto alla coda', + addedMoreToQueue: '{n} oggetti aggiunti alla coda', + alreadyInQueue: '{item} è già nella coda!', + finishDownload: '{item} ha finito di scaricarsi.', + allDownloaded: 'Tutti i download completati!', + refreshFavs: 'Preferiti ricaricati!', + loggingIn: 'Effettuando il login...', + loggedIn: 'Login effettuato', + alreadyLogged: 'Sei già loggato', + loginFailed: 'Impossibile loggarsi', + loggedOut: 'Disconnesso', + cancellingCurrentItem: 'Cancellando download corrente.', + currentItemCancelled: 'Download corrente cancellato.', + startAddingArtist: 'Aggiungendo gli album di {artist} alla coda', + finishAddingArtist: 'Aggiunto gli album di {artist} alla coda', + startConvertingSpotifyPlaylist: 'Convertendo i brani da spotify a deezer', + finishConvertingSpotifyPlaylist: 'Playlist di spotify convertita', + loginNeededToDownload: 'Devi accedere prima di poter scaricare brani!', + queueErrorCantStream: `Il tuo account non può ascoltare brani in {bitrate}!`, + deezerNotAvailable: 'Deezer non è disponibile nel tuo paese. Dovresti usare una VPN.', + deezerNotReachable: + "L'applicazione non riesce a contattare Deezer. Controlla la tua connessione internet, il tuo firewall o il tuo antivirus.", + startGeneratingItems: 'Elaborando {n} oggetti...', + finishGeneratingItems: '{n} oggetti generati.', + noLovedPlaylist: 'Nessuna playlist "Canzoni del cuore"!', + checkingUpdates: 'Cercando aggiornamenti...', + noUpdateAvailable: 'Nessun aggiornamento trovato', + updateAvailable: 'È disponibile un aggiornamento!', + wrongSpotifyUsername: '{username} non è un username di Spotify valido' + }, + settings: { + title: 'Impostazioni', + languages: 'Lingue', + login: { + title: 'Login', + loggedIn: 'Sei loggato come {username}', + arl: { + title: "Usa l'ARL", + question: 'Come ottengo il mio ARL?', + howTo: { + prologue: { + p1: 'Deezer tiene traccia delle sessione di login utilizzando un cookie chiamato ARL.', + p2: 'Deemix utilizza lo stesso cookie per ottenere i dati utili per scaricare i brani da Deezer.', + p3: 'Gli ARL durano un massimo di 3 mesi, dopo di che Deezer ti chiede di rifare il login e te ne assegna un altro. Lo stesso metodo è usato da deemix.', + p4: 'Seguendo una delle prossime guide potrai ottenere il tuo ARL personale.', + warning: 'Usa questo metodo solo se il login con email e password non funziona.' + }, + chromeSteps: { + title: 'Chrome', + step1: 'Apri Chrome', + easyWay: { + title: 'Chrome (Semplificato)', + step3: `Clicca sull'icona del "lucchetto" vicino all'URL`, + step4: 'Clicca su Cookies > deezer.com > cookies > arl', + step5: 'Seleziona il testo vicino a Contenuti, e copiala' + }, + step4: 'Vai nella tab Application (se non la vedi clicca la doppia freccia in fondo alla barra)', + videoGuide: { + text: 'Ecco una {videoGuide}', + link: 'videoguida' + } + }, + firefoxSteps: { + title: 'Firefox', + step1: 'Apri Firefox', + step4: 'Vai nella tab Storage (se non la vedi clicca la doppia freccia in fondo alla barra)' + }, + commonSteps: { + step2: 'Vai su www.deezer.com e effettua il login nel tuo account', + step3: 'Dopo il login premi F12 per aprire i Developer Tools', + step5: 'Apri il dropdown "cookies"', + step6: 'Seleziona www.deezer.com', + step7: 'Trova il cookie `arl` (Dovrebbero essere 192 caratteri)', + step8: 'Copia solo il valore e non il cookie intero', + lastStep: "Quello è il tuo ARL, lo puoi utilizzare nell'app!" + } + }, + update: 'Aggiorna ARL' + }, + logout: 'Disconnettiti', + login: 'Login', + email: 'E-mail', + password: 'Password' + }, + appearance: { + title: 'Aspetto', + slimDownloadTab: 'Tab dei download slim', + slimSidebar: 'Sidebar slim', + searchButton: 'Mostra bottone di ricerca', + bitrateTags: 'Mostra targhetta qualità nei download' + }, + downloadPath: { + title: 'Cartella di download' + }, + templates: { + title: 'Template', + tracknameTemplate: 'Template nome brano', + tracknameAvailableVariables: 'Variabili nome brano disponibili', + albumTracknameTemplate: 'Template nome brano negli Album', + albumTracknameAvailableVariables: 'Variabili nome brano negli Album disponibili', + playlistTracknameTemplate: 'Template nome brano nelle Playlist', + playlistTracknameAvailableVariables: 'Variabili nome brano nelle Playlist disponibili' + }, + folders: { + title: 'Cartelle', + createPlaylistFolder: 'Crea cartelle per le Playlist', + playlistNameTemplate: 'Template nome della cartella Playlist', + createArtistFolder: 'Crea cartelle per gli Artisti', + artistNameTemplate: 'Template nome della cartella Artista', + createAlbumFolder: 'Crea cartelle per gli Album', + albumNameTemplate: 'Template nome della cartella Album', + createCDFolder: 'Crea cartelle per i CD', + createStructurePlaylist: 'Crea la struttura di cartelle per le Playlist', + createSingleFolder: 'Crea la struttura di cartelle per i brani singoli' + }, + trackTitles: { + title: 'Titoli brani', + padTracks: 'Aggiungi zeri ai numeri di traccia', + paddingSize: 'Sovrascrivi il numero di zeri da aggiungere', + illegalCharacterReplacer: 'Rimpiazza caratteri illegali con' + }, + downloads: { + title: 'Download', + queueConcurrency: 'Download simultanei', + maxBitrate: { + title: 'Bitrate preferito', + 9: 'FLAC 1411kbps', + 3: 'MP3 320kbps', + 1: 'MP3 128kbps' + }, + overwriteFile: { + title: 'Dovrei sovrascrivere i file già scaricati?', + y: 'Si, sovrascrivi i file', + n: 'No, non sovrascrivere i file', + t: 'Sovrascrivi solo i tag', + b: 'No, mantieni entrambi i file e aggiungi un numero al duplicato', + e: 'No, e non tener conto della estensione del file', + l: 'Sovrascrivi solo se il bitrate migliora (solo per mp3)' + }, + fallbackBitrate: 'Utilizza bitrate più bassi se il bitrate preferito non è disponibile', + fallbackSearch: 'Cerca il brano se il link originale non è disponibile', + fallbackISRC: 'Cerca tramite ISRC se il brano non è disponibile', + feelingLucky: 'Prova e usa il metodo vecchio di generazione degli URL', + logErrors: 'Crea file di log per gli errori', + logSearched: 'Crea file di log per le alternative cercate', + syncedLyrics: 'Crea i file .lrc (Testi Sincronizzati)', + createM3U8File: 'Crea i file playlist', + playlistFilenameTemplate: 'Template nome del file playlist', + clearQueueOnExit: "Pulisci la coda di download quando chiudi l'app" + }, + covers: { + title: 'Copertine', + saveArtwork: 'Salva copertina album', + coverImageTemplate: 'Template nome copertina album', + saveArtworkArtist: 'Salva copertina artista', + artistImageTemplate: 'Template nome copertina artista', + localArtworkSize: 'Dimensioni copertine locali', + embeddedArtworkSize: 'Dimensioni copertine incorporate', + localArtworkFormat: { + title: 'Come vuoi salvare le copertine locali?', + jpg: 'In jpeg', + png: 'In png', + both: 'Sia in jpeg che in png' + }, + jpegImageQuality: 'Qualità immagine JPEG', + embeddedArtworkPNG: 'Salva copertina incorporata come PNG', + embeddedPNGWarning: 'Le immagini PNG non sono usate ufficialmente da Deezer e potrebbero dare problemi', + imageSizeWarning: + 'Dimensioni maggiori di x1200 non sono usate ufficialmente da Deezer, potresti incontrare problemi', + coverDescriptionUTF8: 'Salva la descrizione della copertina in UTF8 (iTunes Cover Fix)' + }, + tags: { + head: 'Quali tag salvare', + title: 'Titolo', + artist: 'Artista', + artists: 'Tag ARTISTS extra', + album: 'Album', + cover: 'Copertina', + trackNumber: 'Numero Traccia', + trackTotal: 'Tracce Totali', + discNumber: 'Numero Disco', + discTotal: 'Dischi Totali', + albumArtist: "Artista dell'album", + genre: 'Genere', + year: 'Anno', + date: 'Data', + explicit: 'Testo Esplicito', + isrc: 'ISRC', + length: 'Durata Traccia', + barcode: "Barcode dell'album (UPC)", + bpm: 'BPM', + replayGain: 'Replay gain', + label: 'Casa Discografica', + lyrics: 'Testo non Sincronizzato', + syncedLyrics: 'Testo Sincronizzato', + copyright: 'Copyright', + composer: 'Compositori', + involvedPeople: 'Persone Coinvolte', + source: 'Sorgente e ID brano', + artistsWarning: + 'Disabilitare il tag ARTSITS mentre non si sta usando la specificazione standard non salverà il multiartist' + }, + other: { + title: 'Altro', + autoCheckForUpdates: "Controlla aggiornamenti all'avvio", + savePlaylistAsCompilation: 'Salva le playlist come Compilation', + useNullSeparator: 'Usa il carattere NULL come separatore', + saveID3v1: "Salva anche l'ID3v1", + multiArtistSeparator: { + title: 'Come vuoi separare gli artisti?', + nothing: "Salva solo l'artista principale", + default: 'Usando la specificazione standard', + andFeat: 'Usando & e feat.', + using: 'Usando "{separator}"', + warning: + 'Usando qualisasi separatore diverso dallo standard aggiugerà il tag ARTISTS per salvare il multiartist' + }, + singleAlbumArtist: "Salva solo l'artista dell'album principale", + albumVariousArtists: 'Lascia "Artisti Vari" negli artisti dell\'album', + removeAlbumVersion: 'Rimuovi "Album Version" dal titolo del brano', + removeDuplicateArtists: 'Rimuovi le combinazioni di artisti', + dateFormat: { + title: 'Formato della data per i file FLAC', + year: 'AAAA', + month: 'MM', + day: 'GG' + }, + featuredToTitle: { + title: 'Cosa dovrei fare con i feat?', + 0: 'Niente', + 1: 'Rimuovili dal titolo', + 3: "Rimuovili dal titolo e dal nome dell'album", + 2: 'Spostali sul titolo' + }, + titleCasing: 'Formato testo dei titoli', + artistCasing: 'Formato testo degli artisti', + casing: { + nothing: 'Non cambiare', + upper: 'TUTTO MAIUSCOLO', + lower: 'tutto minuscolo', + start: 'Prima Lettera Maiuscola', + sentence: 'Come una frase' + }, + previewVolume: 'Volume Anteprime', + executeCommand: { + title: 'Comando da eseguire dopo il download', + description: 'Lascia vuoto per nessuna azione' + } + }, + spotify: { + title: 'Spotify Features', + clientID: 'Spotify clientID', + clientSecret: 'Spotify Client Secret', + username: 'Spotify username', + question: 'Come attivo le Spotify Features?', + howTo: { + prologue: { + p1: 'Le "Spotify Features" sono degli strumenti che ti permettono di convertire i link dei brani e album di Spotify in link di Deezer.', + p2: "Se inserisci un link di una playlist di Spotify l'app convertirà tutti i brani di Spotify in brani di Deezer.", + p3: 'Abilitando questi strumenti potrai vedere le tue playlist pubbliche di Spotify nella tab favoriti.' + }, + info: 'Per ragioni di sicurezza dovrai fornire dei Client ID e Client Secret personali', + clientSecretQuestion: { + title: 'Come ottengo i miei Client ID e Client Secret?', + step1: { + text: 'Visita la {spotifyDevelopersDashboard} e effettua il login con il tuo account Spotify.', + spotifyDevelopersDashboard: 'Dashboard per sviluppatori di Spotify' + }, + step2: { + text: 'Premi su "Create an App".', + imageAlt: "Bottone Create an App button su Spotify for Developers's Dashboard" + }, + step3: { + text: 'Riempi "App name" e "App description" e spunta tutte le caselle. Poi premi il bottone "Create".', + imageAlt: 'Modulo Create an app' + }, + step4: { + text: 'Ora puoi vedere il tuo Client ID. Se premi su "Show Client Secret" potrai vedere il client secret.', + imageAlt: 'Schermata del client ID e Secret' + }, + step5: 'Ora puoi copiare e incollare i codici nei campi adeguati nelle impostazioni.' + }, + usernameQuestion: { + title: 'Dove trovo il mio Username di Spotify?', + step1: { + text: 'Puoi trovare il tuo Username di Spotify nella {overviewPage} sul sito di Spotify.', + overviewPage: 'Overview page' + } + } + } + }, + reset: 'Reimposta Default', + resetMessage: 'Sei sicuro di voler tornare alle impostazioni di default?', + save: 'Salva', + toasts: { + init: 'Impostazioni caricate!', + update: 'Impostazioni aggiornate!', + reset: 'Impostazioni di default ripristinate!', + ARLcopied: 'ARL copiato negli appunti' + } + }, + sidebar: { + home: 'home', + search: 'ricerca', + charts: 'classifiche', + favorites: 'preferiti', + linkAnalyzer: 'analizza link', + settings: 'impostazioni', + logs: 'log', + about: 'info' + }, + tracklist: { + downloadSelection: 'Scarica selezionati' + } +} + +export default it diff --git a/webui/src/lang/ko.mjs b/webui/src/lang/ko.mjs new file mode 100644 index 0000000..5079b7e --- /dev/null +++ b/webui/src/lang/ko.mjs @@ -0,0 +1,406 @@ +const ko = { + globals: { + welcome: 'Deemix에 오신 것을 환영합니다', + back: '뒤로', + loading: '불러오는 중', + download: '{thing} 다운로드', + by: '- {artist}', + in: '{album} 중', + download_hint: '다운로드', + play_hint: '재생', + toggle_download_tab_hint: '펼치기/접기', + clean_queue_hint: '비우기 완료', + cancel_queue_hint: '모두 취소', + open_downloads_folder: '다운로드 폴더 열기', + cut: '잘라내기', + copy: '복사', + copyLink: '링크 복사', + copyImageLink: '이미지 링크 복사', + copyDeezerLink: 'deezer 링크 복사', + paste: '붙여넣기', + listTabs: { + empty: '', + all: '전체', + top_result: '가장 일치하는 결과', + album: '앨범 | 앨범', + artist: '아티스트 | 아티스트', + single: '싱글 | 싱글', + title: '제목 | 제목', + track: '트랙 | 트랙', + releaseN: '0 발매 | {n} 발매 | {n} 발매', + playlist: '재생목록 | 재생목록', + compile: '편찬물 | 편찬물', + ep: 'ep | eps', + bundle: '번들 | 번들', + more: '더 많은 앨범', + featured: '특집', + spotifyPlaylist: '스포티파이 재생목록 | 스포티파이 재생목록', + releaseDate: '발매일자', + error: '오류', + trackN: '0 트랙 | {n} 트랙 | {n} 트랙', + albumN: '0 앨범 | {n} 앨범 | {n} 앨범', + artistN: '0 아티스트 | {n} 아티스트 | {n} 아티스트', + playlistN: '0 재생목록 | {n} 재생목록 | {n} 재생목록' + } + }, + about: { + appStatus: { + online: '프로그램 온라인', + offline: '프로그램 오프라인' + }, + updates: { + currentVersion: '현재 버전', + currentWebuiVersion: '현재 WebUI 버전', + versionNotAvailable: 'N/A', + updateAvailable: `최신 버전 ({version})으로 업데이트 할 수 있습니다`, + deemixVersion: 'deemix lib 버전' + }, + titles: { + usefulLinks: '유용한 링크', + bugReports: '버그 제보', + contributing: '기여자', + donations: '후원', + license: '이용정책' + }, + subtitles: { + bugReports: '무언가 안되는 것이 있다고요? 말해주세요!', + contributing: '이 프로젝트에 기여하고 싶다고요? 어렵지 않아요!', + donations: '금전적으로 지원하고 싶다고요? 후원하세요!' + }, + usesLibrary: + '이 프로그램은 deemix 라이브러리를 사용합니다, 해당 라이브러리로 자신만의 deemix를 만들 수 있습니다.', + thanks: `이 프로젝트를 도와준 rtonno, uhwot 그리고 lollilol님과 아이콘을 만들어준 BasCurtiz 그리고 scarvimane님에게 감사를.`, + upToDate: { + text: `새로운 업데이트 소식을 듣고 싶으면 텔레그램 {newsChannel}을 참고하세요.`, + newsChannel: '새소식 정보통' + }, + officialWebsite: '공식 웹사이트', + officialRepo: '공식 라이브러리 저장소', + officialWebuiRepo: '공식 WebUI 저장소', + officialSubreddit: '공식 서브레딧', + newsChannel: '새 소식 알리미', + questions: { + text: `프로그램에 대한 질문이나 문제에 관한 것은, 먼저 {subreddit}에서 답변을 검색해보세요. 그리고, 서브레딧에서 답변을 찾기 못한 경우에 다음 순서를 이용해주세요.`, + subreddit: '서브레딧' + }, + beforeReporting: `버그 제보를 하기 전에 먼저 최신 버전의 프로그램을 실행하고 있는지, 제보하고자 하는 것이 버그이지 오로지 당신의 목적을 이루기 위한 요구가 아님을 확인해주세요.`, + beSure: `해당 버그가 다른 장치에서도 재현이 가능한지 확인하고 이미 제보된 버그의 경우에는 중복해서 보고하지 마세요.`, + duplicateReports: '중복된 버그 제보의 경우는 해당 요청을 닫을 것이니, 두 눈 뜨고 지켜보세요.', + dontOpenIssues: `질문에 관한 것은 이슈를 열지 마세요, 서브레딧이 있습니다.`, + newUI: { + text: `만약 당신이 파이썬에 능통하고 기본적인 라이브러리를 이용하여 새로운 UI를 만들었거나, 라이브러리의 버그를 수정하였다면 {repo}에 풀 리퀘스트 해주세요.`, + repo: '저장소' + }, + acceptFeatures: `복잡하지 않은 기능 추가도 받습니다, 라이브러리가 아닌 앱에서 직접 구현할 수 있는 것으로요.`, + otherLanguages: `당신이 다른 프로그램 언어에 능통하면, 이 deemix 프로그램을 다른 프로그래밍 언어로 포팅할 수도 있습니다!`, + understandingCode: `코드를 이해하는 데 도움이 필요합니까? 위에 있는 RemixDev, 텔레그램, 서브레딧 링크를 누르세요.`, + contributeWebUI: { + text: `만약 당신이 Vue.js (JavaScript), HTML 또는 CSS 개발자라면 {webui}에 도움을 주세요.`, + webui: 'WebUI' + }, + itsFree: `사용하기 전에 이 프로그램이 무료 프로젝트이고 개발자를 지원하기 전에 예술가들을 먼저 지원해야 함을 기억하세요.`, + notObligated: `기부는 프로젝트를 지속할 수 있는 동력이 됩니다!`, + lincensedUnder: { + text: `이 작업이 요구하고 있는 라이센스는 아래와 같습니다 {gpl3}.`, + gpl3: 'GNU General Public License 3.0' + } + }, + charts: { + title: '차트', + changeCountry: '국가 변경', + download: '차트 다운로드' + }, + errors: { + title: '오류 발생: {name}', + ids: { + unsupportedURL: 'URL 지원 누락', + invalidURL: 'URL 인식 실패', + ISRCnotOnDeezer: '트랙 코드 식별이 불가능합니다', + notYourPrivatePlaylist: '다른 사람의 비공개 재생 목록을 다운로드 할 수 없습니다.', + spotifyDisabled: '스포티파이 기능이 올바르게 설정되지 않았습니다.', + trackNotOnDeezer: 'Deezer에서 트랙을 찾을 수 없습니다!', + albumNotOnDeezer: 'Deezer에서 앨범을 찾을 수 없습니다!', + notOnDeezer: 'Deezer에서 트랙을 찾을 수 없습니다!', + notEncoded: '트랙이 아직 변환(encode)되지 않았습니다!', + notEncodedNoAlternative: '트랙이 아직 변환(encode)되지 않았을 뿐더러 대체할 것을 찾지 못했습니다!', + wrongBitrate: '요구하는 비트레이트의 트랙을 찾을 수 없습니다.', + wrongBitrateNoAlternative: '요구하는 비트레이트를 찾을 수 없을 뿐더러 대체할 것을 찾지 못했습니다!', + no360RA: '해당 트랙은 360 리얼리티 오디오에 존재하지 않습니다.', + notAvailable: '해당 트랙은 Deezer 서버에 존재하지 않습니다!', + notAvailableNoAlternative: '해당 트랙은 Deezer 서버에 존재하지 않을 뿐더러 대체할 것을 찾지 못했습니다!', + noSpaceLeft: '장치에 여유 공간이 없습니다!', + albumDoesntExists: '트랙의 앨범이 존재하지 않습니다, 정보 수집에 실패했습니다.' + } + }, + favorites: { + title: '즐겨듣는 음악', + noPlaylists: '즐겨듣는 재생목록이 없습니다', + noAlbums: '즐겨듣는 앨범이 없습니다', + noArtists: '즐겨듣는 아티스트가 없습니다', + noTracks: '즐겨듣는 트랙이 없습니다' + }, + home: { + needTologin: '다운로드를 시작하기 전에 Deezer 계정에 로그인을 해야합니다.', + openSettings: '설정 열기', + sections: { + popularPlaylists: '인기있는 재생목록', + popularAlbums: '가장 많이 재생된 앨범' + } + }, + linkAnalyzer: { + info: '이 항목에서는 다운로드를 시도할 링크에 대한 더 많은 정보를 찾을 수 있습니다.', + useful: '접속한 국가에서는 재생할 수 없는 특정 트랙을 다운로드 하기 위해서 가능한 국가를 찾는데 유용하게 쓰입니다.', + linkNotSupported: '해당 링크는 아직 지원하지 않습니다', + linkNotSupportedYet: '해당 링크는 아직 지원하지 않습니다, 다른 링크로 시도해보세요.', + + table: { + id: 'ID', + isrc: 'ISRC', + upc: 'UPC', + duration: '길이', + diskNumber: '디스크 번호', + trackNumber: '트랙 번호', + releaseDate: '발매일자', + bpm: 'BPM', + label: '라벨', + recordType: '녹음 종류', + genres: '장르', + tracklist: '트랙목록' + } + }, + search: { + startSearching: '검색하세요!', + description: '트랙, 아티스트, 재생목록, Deezer 링크 등으로 검색할 수 있습니다!', + + fans: '{n}명의 팬들', + noResults: '결과 없음', + noResultsTrack: '발견된 트랙 없음', + noResultsAlbum: '발견된 앨범 없음', + noResultsArtist: '발견된 아티스트 없음', + noResultsPlaylist: '발견된 재생목록 없음' + }, + searchbar: '원하는 것을 검색하세요 (링크를 붙여넣을 수도 있습니다)', + downloads: '다운로드', + toasts: { + restoringQueue: '다운로드 대기 열 복원중...', + queueRestored: '다운로드 대기 열이 복원되었습니다!', + addedToQueue: '대기열에 {item}(이)가 추가되었습니다', + addedMoreToQueue: '대기열에 {n} 항목이 추가되었습니다', + alreadyInQueue: '{item}(이)가 이미 대기열에 존재합니다!', + finishDownload: '{item} 항목이 다운로드 완료되었습니다.', + allDownloaded: '모든 다운로드가 완료되었습니다!', + refreshFavs: '새로고침이 완료되었습니다!', + loggingIn: '로그인 하는 중...', + loggedIn: '로그인 되었습니다', + alreadyLogged: '이미 로그인되어 있습니다', + loginFailed: '로그인 할 수 없습니다', + loggedOut: '로그아웃 하였습니다', + cancellingCurrentItem: '현재 항목을 취소 중입니다.', + currentItemCancelled: '항목이 취소되었습니다.', + startAddingArtist: '{artist} 앨범을 대기열에 추가 중입니다', + finishAddingArtist: '{artist} 앨범이 대기열에 추가되었습니다', + startConvertingSpotifyPlaylist: '스포티파이 트랙을 Deezer 트랙으로 전환 중입니다', + finishConvertingSpotifyPlaylist: '스프토파이 재생 목록이 전환되었습니다', + loginNeededToDownload: '트랙을 다운로드하려면 로그인이 필요합니다!', + deezerNotAvailable: 'Deezer 사이트는 현재 귀하의 국가에서 사용이 불가능합니다. VPN을 사용하세요.', + startGeneratingItems: '{n}개의 항목 진행중...', + finishGeneratingItems: '{n}개의 항목이 생성되었습니다.' + }, + settings: { + title: '설정', + languages: '언어', + login: { + title: '로그인', + loggedIn: '{username}(으)로 로그인되었습니다', + arl: { + question: 'ARL을 어떻게 확인합니까?', + update: 'ARL 업데이트' + }, + logout: '로그아웃', + question: '스포티파이 기능들을 쓰려면 어떻게 해야합니까?' + }, + appearance: { + title: '외관', + slimDownloadTab: '얇은 다운로드 탭', + slimSidebar: '얇은 사이드바' + }, + downloadPath: { + title: '다운로드 경로' + }, + templates: { + title: '템플릿', + tracknameTemplate: '트랙이름 템플릿', + tracknameAvailableVariables: '사용가능한 트랙이름 변수 목록', + albumTracknameTemplate: '앨범 트랙 템플릿', + albumTracknameAvailableVariables: '사용가능한 앨범 트랙 변수 목록', + playlistTracknameTemplate: '재생목록 트랙 템플릿', + playlistTracknameAvailableVariables: '사용가능한 재생 목록 트랙 변수 목록' + }, + folders: { + title: '폴더', + createPlaylistFolder: '재생목록을 위한 폴더 생성', + playlistNameTemplate: '재생목록 폴더 템플릿', + createArtistFolder: '아티스트를 위한 폴더 생성', + artistNameTemplate: '아티스트 폴더 템플릿', + createAlbumFolder: '앨범을 위한 폴더 생성', + albumNameTemplate: '앨범 폴더 템플릿', + createCDFolder: 'CD를 위한 폴더 생성', + createStructurePlaylist: '재생목록을 위한 폴더 구조 생성', + createSingleFolder: '싱글 앨범을 위한 폴더 구조 생성' + }, + trackTitles: { + title: '트랙 제목', + padTracks: '트랙 채워넣기', + paddingSize: '채워넣을 크기', + illegalCharacterReplacer: '지원하지 않는 글자 대체' + }, + downloads: { + title: '다운로드', + queueConcurrency: '동시 다운로드', + maxBitrate: { + title: '선호하는 비트레이트', + 9: 'FLAC 1411kbps', + 3: 'MP3 320kbps', + 1: 'MP3 128kbps' + }, + overwriteFile: { + title: '파일 덮어쓰기 여부', + y: '파일 덮어쓰기', + n: '파일 덮어쓰지 않기', + t: '태그만 덮어쓰기', + b: '모두 유지한 뒤 새 파일에 번호 넣기', + e: '확장자 변경하기' + }, + fallbackBitrate: '비트레이트 대비책', + fallbackSearch: '검색 대비책', + logErrors: '오류 발생시 로그 파일 생성', + logSearched: '검색한 트랙에 대한 로그 파일 생성', + createM3U8File: '재생목록 파일 생성', + syncedLyrics: '.lrc 파일 생성 (가사 동기화)', + playlistFilenameTemplate: '재생목록 파일이름 템플릿', + saveDownloadQueue: '프로그램을 닫을 때 다운로드 대기열 저장' + }, + covers: { + title: '앨범 커버', + saveArtwork: '커버 저장', + coverImageTemplate: '커버 이름 템플릿', + saveArtworkArtist: '아티스트 이미지 저장', + artistImageTemplate: '아티스트 이미지 템플릿', + localArtworkSize: '외부 저장 그림 크기', + embeddedArtworkSize: '내부 저장 그림 크기', + localArtworkFormat: { + title: '별도로 저장할 그림의 형식', + jpg: 'jpeg 이미지', + png: 'png 이미지', + both: 'jpeg와 png 모두' + }, + jpegImageQuality: 'JPEG 이미지 품질', + embeddedArtworkPNG: '포함된 그림의 형식을 PNG로 저장합니다', + embeddedPNGWarning: 'PNG는 Deezer에서 공식적으로 지원하지 않기 때문에 버그가 있을 수 있습니다', + imageSizeWarning: 'x1200 크기를 초과해서는 Deezer에서 공식적으로 사용되지 않기 때문에 문제가 생길 수 있습니다', + coverDescriptionUTF8: '커버 설명을 UTF8 포맷을 이용해 저장합니다 (iTunes 커버 오류 해결)' + }, + tags: { + head: '저장할 태그를 선택하세요', + title: '제목', + artist: '아티스트', + album: '앨범', + cover: '커버', + trackNumber: '트랙 번호', + trackTotal: '전체 트랙 크기', + discNumber: '디스크 번호', + discTotal: '전체 디스크 수', + albumArtist: '앨범 아티스트', + genre: '장르', + year: '연도', + date: '일자', + explicit: '노골적 가사', + isrc: 'ISRC', + length: '트랙 길이', + barcode: '앨범 바코드 (UPC)', + bpm: 'BPM', + replayGain: '리플레이 게인', + label: '앨범 라벨', + lyrics: '비동기 가사', + + copyright: '저작권', + composer: '작곡가', + involvedPeople: '관련있는 사람들', + source: '소스와 음악 ID' + }, + other: { + title: '기타', + savePlaylistAsCompilation: '재생목록을 편찬물로 저장', + useNullSeparator: 'null 구분자 사용', + saveID3v1: 'ID3v1 태그 형식으로 저장', + multiArtistSeparator: { + title: '아티스트를 어떻게 구분하시겠습니까?', + nothing: '주요 아티스트만 저장', + default: '표준 스펙을 사용', + andFeat: '& 기호와 feat 사용.', + using: '"{separator}" 사용' + }, + singleAlbumArtist: '주요 앨범 아티스트만 저장', + albumVariousArtists: '앨범 아티스트에 "Various Artists"(다양한 아티스트들) 유지', + removeAlbumVersion: '트랙 제목에 "Album Version"(앨범 버전) 제거', + removeDuplicateArtists: '아티스트들의 협업 제거', + dateFormat: { + title: 'FLAC 파일의 날짜 형식', + year: 'YYYY', + month: 'MM', + day: 'DD' + }, + featuredToTitle: { + title: '특집에 참여한 아티스트들에 할 수 있는 것이 무엇이 있나요?', + 0: '아무것도 하지 않음', + 1: '제목에서 제거', + 3: '앨범 제목과 트랙에서 제거', + 2: '제목으로 이동' + }, + titleCasing: '제목 케이싱', + artistCasing: '아티스트 케이싱', + casing: { + nothing: '변함없이 유지', + lower: '소문자로', + upper: '대문자로', + start: '각 단어 앞 글자를 대문자로', + sentence: '문장처럼' + }, + previewVolume: '미리듣기 볼륨', + executeCommand: { + title: '다운로드 후 실행할 명령어', + description: '빈칸으로 두면 아무 일도 없습니다' + } + }, + spotify: { + title: '스포티파이 기능', + clientID: 'Spotify ClientID', + clientSecret: 'Spotify Client Secret', + username: 'Spotify 사용자 이름', + question: '스포티파이 기능들을 사용하려면 어떻게 해야 합니까?' + }, + reset: '기본 설정으로 초기화', + resetMessage: '정말 기본 설정으로 돌아가시겠습니까?', + save: '저장', + toasts: { + init: '설정을 불러왔습니다!', + update: '새로운 설정으로 갱신되었습니다!', + reset: '설정이 원래대로 초기화 되었습니다!', + ARLcopied: 'ARL가 클립보드에 복사되었습니다' + } + }, + sidebar: { + home: '홈', + search: '검색', + charts: '차트', + favorites: '즐겨찾기', + linkAnalyzer: '링크 분석기', + settings: '설정', + about: '정보' + }, + tracklist: { + downloadSelection: '선택 다운로드' + } +} + +export default ko diff --git a/webui/src/lang/pl.mjs b/webui/src/lang/pl.mjs new file mode 100644 index 0000000..0971ef0 --- /dev/null +++ b/webui/src/lang/pl.mjs @@ -0,0 +1,384 @@ +const pl = { + globals: { + welcome: 'Witaj w deemix', + back: 'wróć', + loading: 'ładowanie', + download: 'Pobierz {thing}', + by: 'od {artist}', + in: 'w {album}', + download_hint: 'Pobierz', + play_hint: 'Odtwórz', + toggle_download_tab_hint: 'Rozszerz/Zwiń', + clean_queue_hint: 'Wyczyść ukończone', + cancel_queue_hint: 'Anuluj wszystkie', + open_downloads_folder: 'Otwórz pobrane', + cut: 'wytnij', + copy: 'kopiuj', + copyLink: 'kopiuj link', + copyImageLink: 'kopiuj link obrazu', + copyDeezerLink: 'kopiuj link deezera', + paste: 'wklej', + listTabs: { + empty: '', + all: 'wszystkie', + top_result: 'najlepszy wynik', + album: 'album | albumy', + artist: 'artysta | artyści', + single: 'singiel | single', + title: 'tytuł | tytuły', + track: 'utwór | utwory', + trackN: '0 utworów | {n} utwór | {n} utworów', + releaseN: '0 wydań | {n} wydanie | {n} wydań', + playlist: 'playlista | playlisty', + compile: 'kompilacja | kompilacje', + ep: 'ep | ep', + bundle: 'zestaw | zestawy', + more: 'Więcej albumów', + featured: 'Występuje w', + spotifyPlaylist: 'playlista spotify | playlisty spotify', + releaseDate: 'data wydania', + error: 'błąd' + } + }, + about: { + updates: { + currentVersion: 'Obecna wersja', + versionNotAvailable: 'N/A', + updateAvailable: `Nie masz najnowszej dostępnej wersji: {version}`, + deemixVersion: 'Wersja biblioteki deemix' + }, + titles: { + usefulLinks: 'Przydatne linki', + bugReports: 'Zgłoszenia błędów', + contributing: 'Wkład', + donations: 'Dotacje', + license: 'Licencja' + }, + subtitles: { + bugReports: 'Czy deemix działa inaczej niż powinien? Powiedz nam!', + contributing: 'Chcesz pomóc w tym projekcie? Możesz to zrobić na wiele sposobów!', + donations: 'Chcesz pomóc finansowo? Możesz nas wesprzeć!' + }, + usesLibrary: + 'Ten program używa biblioteki deemix, której możesz użyć do stworzenia własnego interfejsu użytkownika', + thanks: `Podziękowania dla rtonno, uhwot i lollilol za pomoc w tym projekcie oraz dla BasCurtiz za stworzenie ikony.`, + upToDate: { + text: `Bądź na bieżąco z aktualizacjami dołączając do {newsChannel} na Telegramie.`, + newsChannel: 'kanału wiadomości' + }, + officialWebsite: 'Oficjalna strona', + officialRepo: 'Oficjalne repozytorium biblioteki', + officialWebuiRepo: 'Oficjalne repozytorium WebUI', + officialSubreddit: 'Oficjalny subreddit', + newsChannel: 'Kanał wiadomości', + questions: { + text: `Jeżeli masz pytania lub problemy związane z aplikacją, szukaj odpowiedzi na {subreddit}. Jeżeli niczego nie znajdziesz, stwórz post na subreddicie.`, + subreddit: 'subreddicie' + }, + beforeReporting: `Przed zgłaszaniem błędu upewnij się, że masz najnowszą wersje aplikacji i to, co chcesz zgłosić jest błędem, a nie usterką z twojej strony.`, + beSure: `Upewnij się, że błąd można odtworzyć na innych urządzeniach i NIE ZGŁASZAJ błędów, które zostały już zgłoszone`, + duplicateReports: 'Identyczne zgłoszenia błędów będą zamykane, więc zwróć na to uwagę.', + dontOpenIssues: `NIE OTWIERAJ zgłoszeń do zadawania pytań, od tego jest subreddit.`, + newUI: { + text: `Jeżeli dobrze znasz Pythona, możesz spróbować stworzyć nowy interfejs dla aplikacji używając bazowej biblioteki lub naprawiać błędy w bibliotece tworząc pull request w {repo}.`, + repo: 'repozytorium' + }, + acceptFeatures: `Przyjmuję nowe funkcje, ale nic złożonego, co mogłoby być zaimplementowane w aplikacji, a nie w bibliotece.`, + otherLanguages: `Jeżeli dobrze znasz inny język programowania, możesz spróbować przeportować deemix do innych języków!`, + understandingCode: `Potrzebujesz pomocy w zrozumieniu kodu? Zapytaj RemixDev na Telegramie lub Reddicie.`, + contributeWebUI: { + text: `Jeżeli znasz Vue.js (JavaScript), HTML lub CSS, możesz pomóc w {webui}.`, + webui: 'WebUI' + }, + itsFree: `Pamiętaj, że ten projekt jest darmowy i powinieneś wspierać artystów przed twórcami aplikacji.`, + notObligated: `Nie czuj potrzeby płacenia, i tak cię doceniam!`, + lincensedUnder: { + text: `Ten projekt jest chroniony licencją {gpl3}.`, + gpl3: 'GNU General Public License 3.0' + } + }, + charts: { + title: 'Wykresy', + changeCountry: 'Zmień kraj', + download: 'Pobierz wykres' + }, + errors: { + title: 'Błędy dla {name}', + ids: { + invalidURL: 'Nierozpoznany URL', + unsupportedURL: 'Niewspierany URL', + ISRCnotOnDeezer: 'ISRC nie jest dostępne na Deezerze', + notYourPrivatePlaylist: 'Nie możesz pobierać czyichś prywatnych playlist.', + spotifyDisabled: 'Funkcje Spotify nie są poprawnie ustawione', + trackNotOnDeezer: 'Nie znaleziono utworu na Deezerze!', + albumNotOnDeezer: 'Nie znaleziono albumu na Deezerze!', + notOnDeezer: 'Utwór nie jest dostępny na Deezerze!', + notEncoded: 'Utwór nie jest jeszcze zakodowany!', + notEncodedNoAlternative: 'Utwór nie jest jeszcze zakodowany i nie można znaleźć alternatywy!', + wrongBitrate: 'Nie znaleziono utworu w wybranym bitrate.', + wrongBitrateNoAlternative: 'Nie znaleziono utworu w wybranym bitrate i nie mozna znaleźć alternatywy!', + no360RA: 'Utwór nie jest dostępny w Reality Audio 360.', + notAvailable: 'Utwór nie jest dostępny na serwerach Deezera!', + notAvailableNoAlternative: 'Utwór nie jest dostępny na serwerach Deezera i nie można znaleźć alternatywy!' + } + }, + favorites: { + title: 'Ulubione', + noPlaylists: 'Nie znaleziono playlist', + noAlbums: 'Nie znaleziono ulubionych albumów', + noArtists: 'Nie znaleziono ulubionych artystów', + noTracks: 'Nie znaleziono ulubonych utworów' + }, + home: { + needTologin: 'Musisz się zalogwać do konta na Deezerze zanim zaczniesz pobierać.', + openSettings: 'Otwórz ustawienia', + sections: { + popularPlaylists: 'Popularne playlisty', + popularAlbums: 'Najpopularniejsze albumy' + } + }, + linkAnalyzer: { + info: 'Możesz użyć tej sekcji, aby znaleźć więcej informacji o linku, który chcesz pobrać.', + useful: + 'Jest to przydatne na przykład gdy chcesz pobrać jakieś utwory, które nie są dostępne w twoim kraju i chcesz wiedzieć gdzie są dostępne.', + linkNotSupported: 'Ten link nie jest jeszcze wspierany', + linkNotSupportedYet: 'Wygląda na to, że ten link nie jest jeszcze wspierany. Spróbuj przeanalizować inny.', + table: { + id: 'ID', + isrc: 'ISRC', + upc: 'UPC', + duration: 'Czas', + diskNumber: 'Numer płyty', + trackNumber: 'Numer utworu', + releaseDate: 'Data wydania', + bpm: 'BPM', + label: 'Wytwórnia', + recordType: 'Rodzaj wydania', + genres: 'Gatunki', + tracklist: 'Lista utworów' + } + }, + search: { + startSearching: 'Zacznij szukać!', + description: 'Możesz wyszukać utwór, album, artystę, playlistę... wszystko! Możesz też wkleić link do Deezera', + fans: '{n} fanów', + noResults: 'Brak wyników', + noResultsTrack: 'Nie znaleziono utworów', + noResultsAlbum: 'Nie znaleziono albumów', + noResultsArtist: 'Nie znaleziono artystów', + noResultsPlaylist: 'Nie znaleziono playlist' + }, + searchbar: 'Szukaj czego chcesz (lub wklej link)', + downloads: 'pobrane', + toasts: { + restoringQueue: 'Przywracanie kolejki pobierania...', + queueRestored: 'Przywrócono kolejkę pobierania!', + addedToQueue: 'Dodano {item} do kolejki', + addedMoreToQueue: 'Dodano {n} przedmiotów do kolejki', + alreadyInQueue: '{item} jest już w kolejce!', + finishDownload: 'Ukończono pobieranie {item}.', + allDownloaded: 'Pobrano wszystkie!', + refreshFavs: 'Ukończono odświeżanie!', + loggingIn: 'Logowanie...', + loggedIn: 'Zalogowano', + alreadyLogged: 'Już zalogowano', + loginFailed: 'Nie można zalogować', + loggedOut: 'Wylogowano', + cancellingCurrentItem: 'Anulowanie przedmiotu.', + currentItemCancelled: 'Anulowano przedmiot.', + startAddingArtist: 'Dodawanie {artist} albumów do kolejki', + finishAddingArtist: 'Dodano {artist} albumów do kolejki', + startConvertingSpotifyPlaylist: 'Konwertowanie utworów Spotify na Deezer', + finishConvertingSpotifyPlaylist: 'Przekonwertowano playlistę Spotify', + loginNeededToDownload: 'Musisz się zalogować, aby pobierać utwory!' + }, + settings: { + title: 'Ustawienia', + languages: 'Języki', + login: { + title: 'Logowanie', + loggedIn: 'Zalogowano jako {username}', + arl: { + question: 'Jak zdobyć swój własny ARL?', + update: 'Zakualizuj ARL' + }, + logout: 'Wyloguj', + login: 'Zaloguj przez deezer.com' + }, + appearance: { + title: 'Wygląd', + slimDownloadTab: 'Cienka karta pobranych' + }, + downloadPath: { + title: 'Ścieżka pobierania' + }, + templates: { + title: 'Szablony', + tracknameTemplate: 'Szablon utworu', + albumTracknameTemplate: 'Szablon utworu z albumu', + playlistTracknameTemplate: 'Szablon utworu z playlisy' + }, + folders: { + title: 'Foldery', + createPlaylistFolder: 'Utwórz foldery dla playlist', + playlistNameTemplate: 'Szablon folderu playlisty', + createArtistFolder: 'Utwórz foldery dla artystów', + artistNameTemplate: 'Szablon folderu artysty', + createAlbumFolder: 'Utwórz foldery dla albumów', + albumNameTemplate: 'Szablon folderu albumu', + createCDFolder: 'Utwórz foldery dla płyt', + createStructurePlaylist: 'Utwórz strukturę folderów dla playlist', + createSingleFolder: 'Utwórz strukturę folderów dla singli' + }, + trackTitles: { + title: 'Tytuły utworow', + padTracks: 'Wypchaj utwory', + paddingSize: 'Rozmiar wypchania', + illegalCharacterReplacer: 'Zamiennik niedozwolonych znaków' + }, + downloads: { + title: 'Pobrane', + queueConcurrency: 'Równoległe pobieranie', + maxBitrate: { + title: 'Bitrate', + 9: 'FLAC 1411kbps', + 3: 'MP3 320kbps', + 1: 'MP3 128kbps' + }, + overwriteFile: { + title: 'Nadpisywać pliki?', + y: 'Tak', + n: 'Nie', + t: 'Tylko tagi', + b: 'Nie, dodaj numer do drugiego pliku', + e: 'Nie, nie patrz na rozszerzenia' + }, + fallbackBitrate: 'Rezerwowy bitrate', + fallbackSearch: 'Rezerwowe wyszukiwanie', + logErrors: 'Utwórz plik dziennika błędów', + logSearched: 'Utwórz plik dziennika wyszukiwanych utworów', + createM3U8File: 'Utwórz plik playlisty', + syncedLyrics: 'Utwórz plik .lrc (synchronizowany tekst)', + playlistFilenameTemplate: 'Szablon pliku playlisty', + saveDownloadQueue: 'Zapisz kolejkę pobierania przy zamykaniu aplikacji' + }, + covers: { + title: 'Okładki albumów', + saveArtwork: 'Zapisz okładki', + coverImageTemplate: 'Szablon nazwy okładki', + saveArtworkArtist: 'Zapisz zdjęcie artysty', + artistImageTemplate: 'Szablon zdjęcia artysty', + localArtworkSize: 'Rozmiar lokalnej okładki', + embeddedArtworkSize: 'Rozmiar osadzonej okładki', + localArtworkFormat: { + title: 'W jakim formacie ma zostać zapisana okładka?', + jpg: 'Plik JPEG', + png: 'Plik PNG', + both: 'Pliki JPEG i PNG' + }, + jpegImageQuality: 'Jakość JPEG', + embeddedArtworkPNG: 'Zapisz osadzoną okładkę jako PNG', + embeddedPNGWarning: 'PNG nie jest oficjalnie wspierane przez Deezer i może powodować błędy', + imageSizeWarning: 'Wszystko powyżej x1200 nie jest oficjalnie używane przez Deezera, więc mogą wystąpić problemy.' + }, + tags: { + head: 'Które tagi zapisać', + title: 'Tytuł', + artist: 'Artysta', + album: 'Album', + cover: 'Okładka', + trackNumber: 'Numer utworu', + trackTotal: 'Liczba utworów', + discNumber: 'Numer płyty', + discTotal: 'Liczba płyt', + albumArtist: 'Album Artist', + genre: 'Gatunek', + year: 'Rok', + date: 'Data', + explicit: 'Wulgarny tekst', + isrc: 'ISRC', + length: 'Długość', + barcode: 'Kod kreskowy albumu (UPC)', + bpm: 'BPM', + replayGain: 'Replay Gain', + label: 'Wytwórnia', + lyrics: 'Niezsynchronizowany tekst', + syncedLyrics: 'Zsynchronizowany tekst', + copyright: 'Prawa autorskie', + composer: 'Kompozytor', + involvedPeople: 'Zaangażowane osoby' + }, + other: { + title: 'Inne', + savePlaylistAsCompilation: 'Zapisz playlisty jako kompilacje', + useNullSeparator: 'Użyj separatora null', + saveID3v1: 'Zapisz ID3v1', + multiArtistSeparator: { + title: 'Jak oddzielić artystów?', + nothing: 'Zapisz tylko głównego artystę', + default: 'Standardowa specyfikacja', + andFeat: '& i feat.', + using: 'Używa "{separator}"' + }, + singleAlbumArtist: 'Zapisz tylko głównego autora albumu', + albumVariousArtists: 'Zostaw "Various Artists" w autorach albumu', + removeAlbumVersion: 'Usuń "Album Version" z tytułu utworu', + removeDuplicateArtists: 'Usuń kombinacje artystów', + dateFormat: { + title: 'Format daty dla plików FLAC', + year: 'YYYY', + month: 'MM', + day: 'DD' + }, + featuredToTitle: { + title: 'Co zrobić z dodatkowymi artystami?', + 0: 'Nic', + 1: 'Usuń z tytułu', + 3: 'Usuń z tytułu i tytułu albumu', + 2: 'Przenieś do tytułu' + }, + titleCasing: 'Rozmiar liter tytułu', + artistCasing: 'Rozmiar liter artysty', + casing: { + nothing: 'Zostaw', + lower: 'małe litery', + upper: 'DUŻE LITERY', + start: 'Na Początku Każdego Słowa', + sentence: 'Jak w zdaniu' + }, + previewVolume: 'Głośność podglądu', + executeCommand: { + title: 'Polecenie do wykonania po pobraniu', + description: 'Zostaw puste, aby nic nie robić' + } + }, + spotify: { + title: 'Funkcje Spotify', + clientID: 'Spotify ClientID', + clientSecret: 'Spotify Client Secret', + username: 'Nazwa użytkownika', + question: 'Jak włączyć funkcje Spotify?' + }, + reset: 'Przywróć domyślne', + save: 'Zapisz', + toasts: { + init: 'Załadowano ustawienia!', + update: 'Zaktualizowano ustawienia!', + ARLcopied: 'Skopiowano ARL do schowka' + } + }, + sidebar: { + home: 'strona główna', + search: 'szukaj', + charts: 'wykresy', + favorites: 'ulubione', + linkAnalyzer: 'analiza linków', + settings: 'ustawienia', + about: 'informacje' + }, + tracklist: { + downloadSelection: 'Pobierz wybrane' + } +} + +export default pl diff --git a/webui/src/lang/pt-br.mjs b/webui/src/lang/pt-br.mjs new file mode 100644 index 0000000..95742a2 --- /dev/null +++ b/webui/src/lang/pt-br.mjs @@ -0,0 +1,517 @@ +const pt_br = { + globals: { + welcome: 'bem-vindo ao deemix', + back: 'voltar', + loading: 'carregando', + download: 'Baixar {thing}', + by: 'por {artist}', + in: 'em {album}', + download_hint: 'Baixar', + play_hint: 'Reproduzir', + toggle_download_tab_hint: 'Expandir/Recolher', + clean_queue_hint: 'Limpar', + cancel_queue_hint: 'Cancelar todos', + open_downloads_folder: 'Abrir pasta de downloads', + cut: 'recortar', + copy: 'copiar', + copyLink: 'copiar link', + copyImageLink: 'copiar link da imagem', + copyDeezerLink: 'copiar link do deezer', + paste: 'colar', + listTabs: { + empty: '', + all: 'todos', + discography: 'discografia', + top_result: 'resultado principal', + album: 'álbum | álbuns', + artist: 'artista | artistas', + single: 'single | singles', + title: 'título | títulos', + track: 'faixa | faixas', + playlist: 'playlist | playlists', + compile: 'compilação | compilações', + ep: 'ep | eps', + bundle: 'pacote | pacotes', + more: 'Mais álbuns', + featured: 'Participação em', + spotifyPlaylist: 'playlist do Spotify | playlists do Spotify', + releaseDate: 'data de lançamento', + error: 'erro', + trackN: '0 faixas | {n} faixa | {n} faixas', + albumN: '0 álbuns | {n} álbum | {n} álbuns', + artistN: '0 artistas | {n} artista | {n} artistas', + releaseN: '0 lançamentos | {n} lançamento | {n} lançamentos', + playlistN: '0 playlists | {n} playlist | {n} playlists' + }, + yes: 'sim', + no: 'não', + empty: 'vazio' + }, + about: { + appStatus: { + online: 'app online', + offline: 'app offline' + }, + updates: { + currentVersion: 'Versão atual', + currentWebuiVersion: 'Versão WebUI atual', + versionNotAvailable: 'N/A', + updateAvailable: `Você está executando a versão mais recente: {version}`, + deemixVersion: 'versão do deemix lib' + }, + titles: { + usefulLinks: 'Links úteis', + bugReports: 'Reportar bugs', + contributing: 'Contribuições', + donations: 'Doações', + license: 'Licença' + }, + subtitles: { + bugReports: 'Algo não funcionando no deemix? Nos diga!', + contributing: 'Você quer contribuir para este projeto? Você pode fazer isso de diferentes maneiras!', + donations: 'Você quer contribuir monetariamente? Você pode fazer uma doação!' + }, + usesLibrary: + 'Esse app usa a biblioteca do deemix, no qual você pode usar para criar sua própria UI para o deemix', + thanks: `Agradecimentos para rtonno, uhwot e lollilol por ajudar neste projeto, e para BasCurtiz por fazer o ícone`, + upToDate: { + text: `Para mais novidades siga o {newsChannel} no Telegram.`, + newsChannel: 'canal de notícias' + }, + officialWebsite: 'Site oficial', + officialRepo: 'Repositório oficial da biblioteca', + officialWebuiRepo: 'Repositório oficial da WebUI', + officialSubreddit: 'Subreddit oficial', + newsChannel: 'Canal de notícias', + devlogChannel: 'Canal Devlog', + questions: { + text: `Se você tiver dúvidas ou problemas com o app, procure uma solução em {subreddit} primeiro. Caso você não encontre, você pode fazer um post explicando seu problema no subreddit.`, + subreddit: 'subreddit' + }, + beforeReporting: `Antes de reportar um bug, tenha certeza que você está rodando a versão mais recente do app, e o que você quer reportar seja realmente um bug e não algo que esteja acontecendo especialmente com você.`, + beSure: `Certifique-se que o bug é reproduzivel em outras máquinas e também NÃO reporte um bug se ele já foi reportado.`, + duplicateReports: 'Reportes de bugs duplicados serão fechados, então fique atento a isso.', + dontOpenIssues: `NÃO abra tópicos para fazer perguntas, há o subreddit para isso.`, + newUI: { + text: `Se você é fluente em Phython, você pode tentar fazer uma nova UI para o app usando a biblioteca base, ou consertar bugs da biblioteca com um pull request em {repo}.`, + repo: 'repo' + }, + acceptFeatures: `Eu aceito funcionalidades extras também, mas nada de coisas complexas, desde que ela possa ser implementada no app, e não na biblioteca.`, + otherLanguages: `Se você for fluente em outra linguagem de programação, você pode tentar portar o deemix para outra linguagem!`, + understandingCode: `Você precisa de ajuda para entender o código? Mande mensagem no RemixDex pelo Telegram ou pelo Reddit.`, + contributeWebUI: { + text: `Se você souber Vue.js (JavaScript), HTML ou CSS você pode contribuir para o {webui}.`, + webui: 'WebUI' + }, + itsFree: `Lembre-se que este projeto é livre e você deve dar suporte aos artistas que você ama antes de dar suporte aos desenvolvedores.`, + notObligated: `Não se sinta na obrigação de doar, eu agradeço de qualquer maneira!`, + lincensedUnder: { + text: `Esse é um projeto licenciado através da {gpl3}.`, + gpl3: 'GNU General Public License 3.0' + } + }, + charts: { + title: 'Mais ouvidas', + changeCountry: 'Mudar país', + download: 'Baixar mais ouvidas' + }, + errors: { + title: 'Erros para {name}', + postTitle: 'Após erros de download', + ids: { + invalidURL: 'URL inválido', + unsupportedURL: 'URL não suportado ainda', + ISRCnotOnDeezer: 'Faixa ISRC não está disponível ainda no Deezer', + notYourPrivatePlaylist: 'Você não pode baixar playlists privadas.', + spotifyDisabled: 'Os Recursos do Spotify não foram configurados corretamente.', + trackNotOnDeezer: 'Faixa não encontrada no Deezer!', + albumNotOnDeezer: 'Álbum não encontrado no Deezer!', + notOnDeezer: 'Faixa indisponível no Deezer!', + notEncoded: 'Faixa ainda não codificada!', + notEncodedNoAlternative: 'Faixa ainda não codificada e sem alternativas encontradas!', + wrongBitrate: 'Faixa não encontrada no bitrate desejado.', + wrongBitrateNoAlternative: 'Faixa não encontrada no bitrate desejado e nenhuma outra alternativa encontrada!', + no360RA: 'Faixa não disponível na qualidade Reality Audio 360.', + notAvailable: 'Faixa não disponível nos servidores do Deezer!', + notAvailableNoAlternative: + 'Faixa não disponível nos servidores do Deezer e nenhuma outra alternativa encontrada!', + noSpaceLeft: 'Espaço insuficiente no dispositivo!', + albumDoesntExists: 'O álbum da faixa não exite, falha ao obter informações.', + wrongLicense: 'A sua conta não permite reproduzir a faixa na qualidade desejada.', + wrongGeolocation: 'A sua conta não permite reproduzir a faixa a partir do país atual.', + wrongGeolocationNoAlternative: + "A sua conta não permite reproduzir a faixa a partir do país atual e nenhuma alternativa foi encontrada." + } + }, + favorites: { + title: 'Favoritos', + noPlaylists: 'Nenhuma playlist encontrada', + noAlbums: 'Nenhum álbum favorito encontrado', + noArtists: 'Nenhum artista favorito encontrado', + noTracks: 'Nenhuma faixa favorita encontrada' + }, + home: { + needTologin: 'Você precisa logar na sua conta do Deezer antes de começar a baixar músicas.', + openSettings: 'Abrir Configurações', + sections: { + popularPlaylists: 'Playlists populares', + popularAlbums: 'Álbuns mais ouvidos' + } + }, + linkAnalyzer: { + info: 'Você pode usar essa seção para encontrar mais informações sobre o link que você quer baixar.', + useful: + 'Isso é útil se você está tentando baixar algumas faixas que não estão disponíveis no seu país, e quer saber onde elas estão disponíveis, por exemplo.', + linkNotSupported: 'Esse link não é suportado ainda', + linkNotSupportedYet: 'Parece que esse link não é suportado ainda, tente analisar outro.', + table: { + id: 'ID', + isrc: 'ISRC', + upc: 'UPC', + duration: 'Duração', + diskNumber: 'Número do disco', + trackNumber: 'Número da faixa', + releaseDate: 'Data de lançamento', + bpm: 'BPM', + label: 'Gravadora', + recordType: 'Tipo de gravação', + genres: 'Gêneros', + tracklist: 'Tracklist', + readable: 'Leitura possível', + available: 'Disponível' + }, + countries: 'Países', + noCountries: 'Esta faixa não está disponível em qualquer país.' + }, + search: { + startSearching: 'Comece pesquisando!', + description: + 'Você pode pesquisar uma música, um álbum, um artista, uma playlist.... tudo! Você também pode colar um link do Deezer', + fans: '{n} fãs', + noResults: 'Nenhum resultado', + noResultsTrack: 'Nenhuma faixa encontrada', + noResultsAlbum: 'Nenhum álbum encontrado', + noResultsArtist: 'Nenhum artista encontrado', + noResultsPlaylist: 'Nenhuma playlist encontrada', + error: 'Ocorreu um erro. Tente novamente mais tarde.' + }, + searchbar: 'Pesquise algo (ou apenas cole um link)', + downloads: 'downloads', + toasts: { + restoringQueue: 'Restaurando fila de downloads...', + queueRestored: 'Fila de downloads restaurada!', + addedToQueue: '{item} adicionado à fila', + addedMoreToQueue: '{n} itens adicionados à fila', + alreadyInQueue: '{item} já está na fila!', + finishDownload: '{item} download concluído.', + allDownloaded: 'Todos os downloads foram concluídos!', + refreshFavs: 'Atualização concluída!', + loggingIn: 'Logando', + loggedIn: 'Logado', + alreadyLogged: 'Você já está logado', + loginFailed: 'Não foi possível entrar', + loggedOut: 'Desconectando', + cancellingCurrentItem: 'Cancelando item atual.', + currentItemCancelled: 'Item atual cancelado.', + startAddingArtist: 'Adicionando álbuns de {artist} à fila', + finishAddingArtist: 'Álbuns de {artist}adicionados a fila', + startConvertingSpotifyPlaylist: 'Convertendo faixas do Spotify para faixas do Deezer', + finishConvertingSpotifyPlaylist: 'Playlists do Spotify convertidas', + loginNeededToDownload: 'Você precisa fazer login para baixar faixas!', + queueErrorCantStream: `Sua conta não pode reproduzir a {bitrate}!`, + deezerNotAvailable: 'Deezer não disponível no seu país. Você precisa usar uma VPN.', + deezerNotReachable: "O aplicativo não consegue conectar-se ao Deezer. Verifique sua conexão com a Internet, firewall ou antivírus.", + startGeneratingItems: 'Processando {n} itens...', + finishGeneratingItems: '{n} itens gerados.', + noLovedPlaylist: 'Nenhuma playlist de músicas curtidas!', + checkingUpdates: 'Verificando por atualizações...', + noUpdateAvailable: 'Nenhuma atualização disponível', + updateAvailable: 'Uma atualização está disponível!', + wrongSpotifyUsername: '{username} não é um nome de usuário válido do Spotify' + }, + settings: { + title: 'Configurações', + languages: 'Idiomas', + login: { + title: 'Login', + loggedIn: 'Você está logado como {username}', + arl: { + title: 'Usar ARL', + question: 'Como eu consigo o meu ARL?', + howTo: { + prologue: { + p1: 'O Deezer mantém o registro de login da sessão usando um cookie chamado ARL.', + p2: 'O Deemix usa este cookie para obter os metadados necessários para fazer o download das faixas do Deezer.', + p3: 'ARLs duram por 3 meses, após isto o Deezer solicita que você faça login novamente. O mesmo método é usado no Deemix.', + p4: 'Seguindo um dos guias abaixo, você pode obter o ARL da sua conta.', + warning: 'Use este método somente se e-mail/senha não funcionar.' + }, + chromeSteps: { + title: 'Chrome', + step1: 'Abra o Chrome', + easyWay: { + title: 'Chrome (Modo fácil)', + step3: 'Clique no pequeno ícone de "cadeado" próximo ao URL', + step4: 'Clique em Cookies > deezer.com > cookies > arl', + step5: 'Selecione a string ao lado de Conteúdo, e Copiar' + }, + step4: 'Acesse a aba Aplicativo (se você não ver, clique na seta dupla)', + videoGuide: { + text: 'Aqui está um {videoGuide}', + link: 'guia em vídeo' + } + }, + firefoxSteps: { + title: 'Firefox', + step1: 'Abra o Firefox', + step4: 'Acesse a aba Armazenamento (se você não ver, clique na seta dupla)' + }, + commonSteps: { + step2: 'Acesse www.deezer.com e faça login na sua conta', + step3: 'Após fazer login, pressione F12 para abrir as Ferramentas de Desenvolvedor', + step5: 'Abra a lista Cookies', + step6: 'Selecione www.deezer.com', + step7: 'Encontre o cookie `arl` (Ele deve ter 192 caracteres de comprimento)', + step8: 'Certifique-se de copiar somente o valor e não o cookie completo', + lastStep: 'Este é o seu ARL, agora você pode usá-lo no aplicativo' + } + }, + update: 'Forçar atualizar ARL' + }, + logout: 'Sair', + login: 'Entrar', + email: 'E-mail', + password: 'Senha' + }, + appearance: { + title: 'Aparência', + slimDownloadTab: 'Aba de downloads pequena', + slimSidebar: 'Barra lateral pequena', + searchButton: 'Mostrar botão de pesquisa', + bitrateTags: 'Mostrar tag de qualidade na fila de downloads' + }, + downloadPath: { + title: 'Pasta de downloads' + }, + templates: { + title: 'Modelos', + tracknameTemplate: 'Modelo do nome da faixa', + tracknameAvailableVariables: 'Variáveis de nomes de faixas disponíveis', + albumTracknameTemplate: 'Modelo da faixa do álbum', + albumTracknameAvailableVariables: 'Variáveis de faixa do álbum disponíveis', + playlistTracknameTemplate: 'Modelo da faixa da playlist', + playlistTracknameAvailableVariables: 'Variáveis de faixa da playlist disponíveis' + }, + folders: { + title: 'Pastas', + createPlaylistFolder: 'Criar pasta para playlists', + playlistNameTemplate: 'Modelo da pasta de playlist', + createArtistFolder: 'Criar pasta para artista', + artistNameTemplate: 'Modelo da pasta de artistas', + createAlbumFolder: 'Criar pasta para álbuns', + albumNameTemplate: 'Modelo da pasta de álbuns', + createCDFolder: 'Criar pasta para CDs', + createStructurePlaylist: 'Criar estrutura de pastas para playlists', + createSingleFolder: 'Criar estrutura de pastas para singles' + }, + trackTitles: { + title: 'Título das faixas', + padTracks: 'Faixas com pad', + paddingSize: 'Sobrescrever tamanho do padding', + illegalCharacterReplacer: 'Substituir caracteres inválidos' + }, + downloads: { + title: 'Downloads', + queueConcurrency: 'Downloads simultâneos', + maxBitrate: { + title: 'Escolher taxa de bits', + 9: 'FLAC 1411kbps', + 3: 'MP3 320kbps', + 1: 'MP3 128kbps' + }, + overwriteFile: { + title: 'Sobrescrever arquivos?', + y: 'Sim, sobrescrever arquivos', + n: 'Não, não sobrescrever arquivos', + t: 'Sobrescrever apenas as tags', + b: 'Não, manter ambos os arquivos e adicionar número ao duplicado', + e: 'Não, e não olhar para as extensões', + l: 'Sobrescrever somente se atualizar o bitrate (somente MP3)' + }, + fallbackBitrate: 'Taxa de bits reserva', + fallbackSearch: 'Procurar reserva', + fallbackISRC: 'Reserva com pesquisa ISRC', + feelingLucky: 'Negociar com CDNs e caches', + logErrors: 'Criar arquivos de log para erros', + logSearched: 'Criar arquivos de log para faixas pesquisadas', + createM3U8File: 'Criar arquivo de playlist', + syncedLyrics: 'Criar arquivos .lrc (Letras sincronizadas)', + playlistFilenameTemplate: 'Modelo do nome do arquivo da playlist', + clearQueueOnExit: 'Limpar a fila de downloads quando fechar o app' + }, + covers: { + title: 'Capa dos álbuns', + saveArtwork: 'Salvar capas', + coverImageTemplate: 'Modelo do nome da capa', + saveArtworkArtist: 'Salvar imagem do artista', + artistImageTemplate: 'Modelo da imagem do artista', + localArtworkSize: 'Tamanho da capa local', + embeddedArtworkSize: 'Tamanho da capa embutida', + localArtworkFormat: { + title: 'Qual o formato da imagem você quer para a capa local?', + jpg: '.jpeg', + png: '.png', + both: 'Ambas, .jpeg e .png' + }, + jpegImageQuality: 'Qualidade da imagem JPEG', + embeddedArtworkPNG: 'Salvar capa embutida como PNG', + embeddedPNGWarning: 'PNGs não são oficialmente suportados pelo Deezer e podem ficar bugados', + imageSizeWarning: 'Tudo acima de x1200 não é oficialmente usado pelo Deezer, você pode encontrar problemas', + coverDescriptionUTF8: 'Salvar descrição da capa usando UTF-8 (correção para capa do iTunes)' + }, + tags: { + head: 'Quais tags salvar', + title: 'Título', + artist: 'Artista', + artists: 'Tag de ARTISTAS extras', + album: 'Álbum', + cover: 'Capa', + trackNumber: 'Número da faixa', + trackTotal: 'Total de faixas', + discNumber: 'Número de discos', + discTotal: 'Total de discos', + albumArtist: 'Artista do álbum', + genre: 'Gênero', + year: 'Ano', + date: 'Data', + explicit: 'Letras explícitas', + isrc: 'ISRC', + length: 'Tamanho da faixa', + barcode: 'Código de barras do álbum (UPC)', + bpm: 'BPM', + replayGain: 'Replay Gain', + label: 'Gravadora', + lyrics: 'Letras não sincronizadas', + syncedLyrics: 'Letras sincronizadas', + copyright: 'Copyright', + composer: 'Compositor', + involvedPeople: 'Pessoas envolvidas', + source: 'Fonte e ID da música', + artistsWarning: + 'Desabilitar a tag ARTISTAS embora não use a especificação padrão, não preservará o suporte para vários artistas' + }, + other: { + title: 'Outros', + autoCheckForUpdates: 'Verificar por atualizações ao iniciar', + savePlaylistAsCompilation: 'Salvar playlists como uma compilação', + useNullSeparator: 'Usar separador nulo', + saveID3v1: 'Salvar ID3v1', + multiArtistSeparator: { + title: 'Como você gostaria de separar os artistas?', + nothing: 'Salvar apenas o artista principal', + default: 'Usar a especificação padrão', + andFeat: 'Usar & e feat.', + using: 'Usar "{separator}"', + warning: + 'Usar qualquer separador diferente do que a especificação padrão irá adicionar uma tag de ARTISTAS extra para preservar o suporte a vários artistas' + }, + singleAlbumArtist: 'Salvar apenas o artista principal', + albumVariousArtists: 'Manter "Various Artists" nos Artistas do Álbum', + removeAlbumVersion: 'Remover "Album Version" do título da faixa', + removeDuplicateArtists: 'Remover combinação de artistas', + dateFormat: { + title: 'Formato da data para arquivos FLAC', + year: 'AAAA', + month: 'MM', + day: 'DD' + }, + featuredToTitle: { + title: 'O que devo fazer com artistas participantes?', + 0: 'Nada', + 1: 'Remover do título da faixa', + 3: 'Remover do título da faixa e do álbum', + 2: 'Mover para o título da faixa' + }, + titleCasing: 'Formatação do título', + artistCasing: 'Formatação do artista', + casing: { + nothing: 'Manter inalterado', + lower: 'minúsculo', + upper: 'MAIÚSCULO', + start: 'Começo De Cada Palavra', + sentence: 'Como uma frase' + }, + previewVolume: 'Volume da prévia', + executeCommand: { + title: 'Comando para executar depois de baixar', + description: 'Deixe em branco para nenhuma ação' + } + }, + spotify: { + title: 'Recursos do Spotify', + clientID: 'Spotify clientID', + clientSecret: 'Spotify Client Secret', + username: 'Usuário do Spotify', + question: 'Como habilitar os Recursos do Spotify?', + howTo: { + prologue: { + p1: '"Recursos do Spotify" é um conjunto de recursos que lhe permite converter links de faixas e álbuns do Spotify para links do Deezer.', + p2: 'Se você fornecer um link para uma playlist do Spotify, o aplicativo vai automaticamente converter todos os links das faixas dentro dela para faixas do Deezer.', + p3: 'Ativar este conjunto de recursos irá permitir que você veja as suas playlists públicas do Spotify também na aba Favoritos.' + }, + info: 'Por motivos de segurança, você vai precisar fornecer o seu próprio Client ID e Client Secret', + clientSecretQuestion: { + title: 'Como obtenho o meu Client ID e Client Secret?', + step1: { + text: 'Acesse o {spotifyDevelopersDashboard} e faça login com a sua conta do Spotify.', + spotifyDevelopersDashboard: "Spotify for Developers's Dashboard" + }, + step2: { + text: 'Clique em "Create an App".', + imageAlt: "Create an App button on Spotify for Developers's Dashboard" + }, + step3: { + text: 'Preencha os campos "App name" e "App description" e marque ambas as caixas de seleção. Então clique em "Create".', + imageAlt: 'Create an app form' + }, + step4: { + text: 'Agora você poderá ver o Client ID. Se você clicar em "Show Client Secret" ele será revelado.', + imageAlt: 'Screen of client ID and Secret' + }, + step5: 'Agora você pode copiar e colar estes resultados nos campos apropriados nas configurações.' + }, + usernameQuestion: { + title: 'Como obtenho meu nome de usuário do Spotify?', + step1: { + text: 'Você pode obter o seu nome de usuário do Spotify na página {overviewPage} no site do Spotify.', + overviewPage: 'Visão geral da conta' + } + } + } + }, + reset: 'Restaurar padrão', + resetMessage: 'Deseja realmente restaurar as configurações padrão?', + save: 'Salvar', + toasts: { + init: 'Configurações carregadas!', + update: 'Configurações atualizadas!', + reset: 'Configurações restauradas para o padrão!', + ARLcopied: 'ARL copiado para a área de transferência' + } + }, + sidebar: { + home: 'início', + search: 'pesquisar', + charts: 'paradas', + favorites: 'favoritos', + linkAnalyzer: 'analisar links', + settings: 'configurações', + logs: 'logs', + about: 'sobre' + }, + tracklist: { + downloadSelection: 'Baixar seleção' + } +} + +export default pt_br diff --git a/webui/src/lang/pt-pt.mjs b/webui/src/lang/pt-pt.mjs new file mode 100644 index 0000000..91ecd87 --- /dev/null +++ b/webui/src/lang/pt-pt.mjs @@ -0,0 +1,509 @@ +const pt = { + globals: { + welcome: 'Bem-vindo ao deemix', + back: 'voltar', + loading: 'A carregar', + download: 'Transferir {thing}', + by: 'por {artist}', + in: 'em {album}', + download_hint: 'Transferir', + play_hint: 'Tocar', + toggle_download_tab_hint: 'Expandir/Recolher', + clean_queue_hint: 'Limpar Finalizados', + cancel_queue_hint: 'Cancelar Tudo', + open_downloads_folder: 'Abrir pasta Transferências', + cut: 'cortar', + copy: 'copiar', + copyLink: 'copiar ligação', + copyImageLink: 'copiar ligação da imagem', + copyDeezerLink: 'copiar ligação do deezer', + paste: 'colar', + listTabs: { + empty: '', + all: 'Tudo', + top_result: 'melhor resultado', + album: 'álbum | álbums', + artist: 'artista | artistas', + single: 'single | singles', + title: 'título | títulos', + track: 'faixa | faixas', + playlist: 'lista de reprodução | listas de reprodução', + compile: 'compilação | compilações', + ep: 'ep | eps', + bundle: 'pacote | pacotes', + more: 'Mais álbuns', + featured: 'Featured in', + spotifyPlaylist: 'lista de reprodução spotify | listas de reprodução spotify', + releaseDate: 'data de lançamento', + error: 'erro', + trackN: '0 faixas | {n} faixa | {n} faixas', + albumN: '0 albuns | {n} album | {n} albuns', + artistN: '0 artistas | {n} artista | {n} artistas', + releaseN: '0 lançamentos | {n} lançamento | {n} lançamento', + playlistN: '0 listas de reprodução | {n} lista de reprodução | {n} listas de reprodução' + }, + yes: 'sim', + no: 'no', + empty: 'vazio' + }, + about: { + appStatus: { + online: 'app online', + offline: 'app offline' + }, + updates: { + currentVersion: 'Versão Atual', + currentWebuiVersion: 'Versão Atual do WebUI', + versionNotAvailable: 'N/D', + updateAvailable: `Não estás a usar a versão mais recente: {version}`, + deemixVersion: 'versão deemix lib' + }, + titles: { + usefulLinks: 'Ligações Úteis', + bugReports: 'Relatório de erros', + contributing: 'Contribuir', + donations: 'Doações', + license: 'Licenças' + }, + subtitles: { + bugReports: 'Existe alguma coisa que não funciona no deemix? Informa-nos!', + contributing: 'Queres contribuir para o projecto? Podes fazê-lo de diferentes formas!', + donations: 'Desejas contribuir monetariamente? Faz uma doação!' + }, + usesLibrary: + 'Esta aplicação usa a biblioteca deemix, que poderás usar para desenvolver o teu proprio UI para o deemix.', + thanks: `Agradeço a rtonno, uhwot and lollilol por me ajudarem neste projeto e a BasCurtiz por elaborarem o ícone.`, + upToDate: { + text: `Mantém-te atualizado seguindo o {newsChannel} no Telegram.`, + newsChannel: 'canal de notícias' + }, + officialWebsite: 'Site Oficial', + officialRepo: 'Repositório Oficial da Biblioteca', + officialWebuiRepo: 'Repositório Oficial WebUI', + officialSubreddit: 'Subreddit Oficial', + newsChannel: 'Canal de Notícias', + questions: { + text: `Caso tenhas alguma duvida ou problema com a app, primeiro procura por uma solução no {subreddit}. Caso não encontres nada podes criar uma publicação com a tua questão.`, + subreddit: 'subreddit' + }, + beforeReporting: `Antes de reportares um bug certifica-te que estás a correr a versão mais recente e que se trata realmentede um bug e não apenas algo que não funciona do teu lado.`, + beSure: `Certifica-te que o erro é reprodutivel noutros dispositivos e NÃO reportes um bug que já tenha sido reportado.`, + duplicateReports: 'Bug reports duplicados serão fechados, mantém-te atento a isso.', + dontOpenIssues: `NÃO abras issues para colocar questões, existe um subreddit para isso.`, + newUI: { + text: `Caso sejas fluente em python podes tentar criar um novo UI para a aplicação recorrendo à biblioteca base ou corrigir erros na biblioteca com um pull request no {repo}.`, + repo: 'repositório' + }, + acceptFeatures: `Também aceito funcionalidades não complexas caso possam ser implementadas directamente na app e não na biblioteca.`, + otherLanguages: `Caso sejas fluente noutra linguagem de programação podes tentar migrar o deemix para outra linguagem de programação!`, + understandingCode: `Precisas de ajuda a compreender o código? Acede a RemixDev no Telegram ou no Reddit.`, + contributeWebUI: { + text: `Caso saibas Vue.js (JavaScript), HTML ou CSS podes contribuir para o {webui}.`, + webui: 'WebUI' + }, + itsFree: `Deves ter em conta que que este projeto é gratuito e deverás apoiar os artistas que aprecias antes de apoiares os programadores.`, + notObligated: `Não te sintas obrigado a doar, agradeço-te na mesma!`, + lincensedUnder: { + text: `Este trabalho esta licenciado sobre a {gpl3}.`, + gpl3: 'GNU Licença publica geral 3.0' + } + }, + charts: { + title: 'Tabelas', + changeCountry: 'Alterar país', + download: 'Transferir tabela' + }, + errors: { + title: 'Erros para {name}', + postTitle: 'Erros após transferência', + ids: { + invalidURL: 'URL não reconhecido', + unsupportedURL: 'URL ainda não suportado', + ISRCnotOnDeezer: 'Faixa ISRC não disponível no deezer', + notYourPrivatePlaylist: 'Nao podes baixar listas de reprodução privadas de outros.', + spotifyDisabled: 'Funcionalidades do Spotify não estão definidas corretamente.', + trackNotOnDeezer: 'Faixa não encontrada no deezer!', + albumNotOnDeezer: 'Álbum não encontrado no deezer!', + notOnDeezer: 'Faixa não encontrada no Deezer!', + notEncoded: 'Faixa ainda não codificada!', + notEncodedNoAlternative: 'Faixa ainda não codificada e não foi encontrada alternativa!', + wrongBitrate: 'Faixa não encontrada no bitrate desejado.', + wrongBitrateNoAlternative: 'Faixa não encontrada no bitrate desejado e não foi encontrada alternativa!', + no360RA: 'Faixa não disponível em Reality Audio 360.', + notAvailable: 'Faixa não disponível nos servidores do deezer!', + notAvailableNoAlternative: 'Faixa não disponível nos servidores do deezer e não foi encontrada alternativa!', + noSpaceLeft: 'O dispositivo não tem armazenamento disponível!', + albumDoesntExists: 'A faixa do álbum não existe, recolha de informação falhou.', + wrongLicense: 'A tua conta não permite fazer streaming da faixa com o bitrate desejado.', + wrongGeolocation: 'A tua conta não permite fazer streaming da faixa a partir do teu país.', + wrongGeolocationNoAlternative: + 'A tua conta não permite fazer streaming da faixa a partir do teu país e não foi encontrada nenhuma alternativa.' + } + }, + favorites: { + title: 'Favoritos', + noPlaylists: 'Listas de reprodução não encontradas', + noAlbums: 'Álbuns favoritos não encontrados', + noArtists: 'Artistas favoritos não encontrados', + noTracks: 'Faixas favoritas não encontradas' + }, + home: { + needTologin: 'Antes de iniciar transferências é necessário efetuar autenticação na conta Deezer.', + openSettings: 'Abrir Definições', + sections: { + popularPlaylists: 'Listas de reprodução populares', + popularAlbums: 'Álbuns mais ouvidos' + } + }, + linkAnalyzer: { + info: 'Podes usar esta secção para obteres mais informação sobre o link que estás a tentar transferir.', + useful: + 'Isto é útil caso estejas a tentar transferir faixas que não estão disponíveis no teu país e queres saber onde estão disponíveis, por exemplo.', + linkNotSupported: 'Este link ainda não é suportado', + linkNotSupportedYet: 'Parece que este link ainda não é suportado, tenta analisar outro.', + table: { + id: 'ID', + isrc: 'ISRC', + upc: 'UPC', + duration: 'Duração', + diskNumber: 'Número do disco', + trackNumber: 'Número da faixa', + releaseDate: 'Data de lançamento', + bpm: 'BPM', + label: 'Editora', + recordType: 'Tipo de Disco', + genres: 'Géneros', + tracklist: 'Lista de faixas', + readable: 'Legível', + available: 'Disponível' + }, + countries: 'Países', + noCountries: 'Esta faixa não está disponível em nenhum país.' + }, + search: { + startSearching: 'Começa a pesquisar!', + description: + 'Podes perquisar uma música, um álbum inteiro, um artista, uma lista de reprodução... tudo! Também podes colar um link do Deezer', + fans: '{n} fãs', + noResults: 'Sem resultados', + noResultsTrack: 'Faixa não encontrada', + noResultsAlbum: 'Álbum não encontrado', + noResultsArtist: 'Artista não encontrado', + noResultsPlaylist: 'Lista de reprodução não encontrada', + error: 'Ocorreu um erro, tenta novamente mais tarde.' + }, + searchbar: 'Procura o que quiseres (ou cola uma ligação)', + downloads: 'transferências', + toasts: { + addedToQueue: '{item} adicionados à fila', + alreadyInQueue: '{item} já está na fila!', + finishDownload: '{item} foi transferido.', + allDownloaded: 'Todas as transferências terminadas!', + refreshFavs: 'Recarregamento terminado!', + loggingIn: 'A autenticar', + loggedIn: 'Autenticado', + alreadyLogged: 'Já estás autenticado', + loginFailed: 'Não foi possível iniciar sessão', + loggedOut: 'Sessão encerrada', + cancellingCurrentItem: 'A cancelar item atual.', + currentItemCancelled: 'Item atual cancelado.', + startAddingArtist: 'A adicionar {artist} álbuns à fila', + finishAddingArtist: 'Adicionados {artist} álbuns à fila', + startConvertingSpotifyPlaylist: 'A converter faixas do spotify em faixas do deezer', + finishConvertingSpotifyPlaylist: 'Lista de reprodução do Spotify convertida.', + loginNeededToDownload: 'É necessário iniciar sessão para transferir faixas!', + deezerNotAvailable: 'O Deezer não está disponível no teu país. Deverás utilizar uma VPN.', + deezerNotReachable: + 'A app não consegue ligar-se ao Deezer. Verifica a tua ligação à internet, a tua firewall ou o teu antivirus.', + startGeneratingItems: 'A processar {n} itens...', + finishGeneratingItems: '{n} itens gerados.', + noLovedPlaylist: 'No loved tracks playlist!', + checkingUpdates: 'A procurar atualizações...', + noUpdateAvailable: 'Não existem novas atualizações', + updateAvailable: 'Existe uma atualização disponível!', + wrongSpotifyUsername: '{username} não é um nome de utilizador válido no spotify' + }, + settings: { + title: 'Definições', + languages: 'Idioma', + login: { + title: 'Inicio de Sessão', + loggedIn: 'Estás autenticado como {username}', + arl: { + question: 'Como obter o meu ARL?', + update: 'Atualizar ARL', + howTo: { + prologue: { + p1: 'O Deezer monitoriza sessões abertas utilizando um cookie chamado ARL.', + p2: 'O Deemix utiliza este cookie para obter metadata necessária para transferir faixas do Deezer.', + p3: 'Os ARL duram 3 meses, após esse período o Deezer solicita novo inicio de sessão. O mesmo método é usado no deemix.', + p4: 'Seguindo um dos guias mais abaixo poderás obter o teu próprio ARL.', + warning: 'Utiliza este método apenas no caso do email e palavra-passe não funcionarem.' + }, + chromeSteps: { + title: 'Chrome', + step1: 'Abrir Chrome', + easyWay: { + title: 'Chrome (Método simples)', + step3: 'Clique no pequeno cadeado ao lado do URL', + step4: 'Clique em Cookies > deezer.com > cookies > arl', + step5: 'Seleciona o texto após Conteúdo, e faz cópia' + }, + step4: 'Vai ao separador Aplicação (caso não o vejas clique na seta dupla)', + videoGuide: { + text: 'Aqui tens um {videoGuide}', + link: 'guia em vídeo' + } + }, + firefoxSteps: { + title: 'Firefox', + step1: 'Abrir Firefox', + step4: 'Ir ao separador Armazenamento (caso não o vejas clique na seta dupla)' + }, + commonSteps: { + step2: 'Acede a www.deezer.com e inicia a sessão na tua conta', + step3: 'Após inicio de sessão carrega no F12 para abrir as Ferramentas de Programador', + step5: 'Expandir cookie', + step6: 'Seleciona www.deezer.com', + step7: 'Procura o cookie `arl` (Deverá ter 192 caracteres)', + step8: 'Certifica-te que apenas copias o valor e não o cookie completo', + lastStep: 'E isso é o teu ARL que agora poderás utilizar na tua app' + } + } + }, + logout: 'Sair', + login: 'Iniciar sessão', + email: 'E-mail', + password: 'Palavra-passe' + }, + appearance: { + title: 'Aspeto', + slimDownloadTab: 'Separador de transferências estreito', + slimSidebar: 'Barra lateral estreita', + searchButton: 'Mostrar botão de pesquisa', + bitrateTags: 'Mostrar etiqueta de qualidade na fila de transferências' + }, + downloadPath: { + title: 'Caminho das transferências' + }, + templates: { + title: 'Formatos', + tracknameTemplate: 'Formato do nome de faixa', + tracknameAvailableVariables: 'Variáveis associadas ao nome das faixas', + albumTracknameTemplate: 'Formato do nome de Álbum', + albumTracknameAvailableVariables: 'Variáveis associadas ao nome dos álbuns', + playlistTracknameTemplate: 'Formato do nome de lista de reprodução', + playlistTracknameAvailableVariables: 'Variáveis associadas ao nome das listas de reprodução' + }, + folders: { + title: 'Pastas', + createPlaylistFolder: 'Criar pasta para lista de reprodução', + playlistNameTemplate: 'Formato da pasta de lista de reprodução', + createArtistFolder: 'Criar pasta para artista', + artistNameTemplate: 'Formato da pasta de artista', + createAlbumFolder: 'Criar pasta para álbum', + albumNameTemplate: 'Formato da pasta de álbum', + createCDFolder: 'Criar pasta para CDs', + createStructurePlaylist: 'Criar estrutura de pastas para listas reprodução', + createSingleFolder: 'Criar estrutura de pastas para singles' + }, + trackTitles: { + title: 'Título', + padTracks: 'Bloco de Faixas', + paddingSize: 'Substituir tamanho do preenchimento', + illegalCharacterReplacer: 'Substituir caractere inválido' + }, + downloads: { + title: 'Transferências', + queueConcurrency: 'Transferências concorrentes', + maxBitrate: { + title: 'Bitrate preferencial', + 9: 'FLAC 1411kbps', + 3: 'MP3 320kbps', + 1: 'MP3 128kbps' + }, + overwriteFile: { + title: 'Ficheiros existentes. Substituir?', + y: 'Sim, substituir o ficheiro', + n: 'Não substituir o ficheiro', + t: 'Substituir apenas as etiquetas', + b: 'Não, manter ambos os ficheiros e numerar o ficheiro duplicado', + e: 'Não e ignorar as extensões' + }, + fallbackBitrate: 'Bitrate fallback', + fallbackSearch: 'Fallback de pesquisa', + fallbackISRC: 'Fallback com pesquisa ISRC', + feelingLucky: 'Arriscar com CDNs e caches', + logErrors: 'Criar histórico para erros', + logSearched: 'Criar histórico para faixas pesquisadas', + createM3U8File: 'Criar ficheiro de lista de reprodução', + syncedLyrics: 'Criar ficheiro .lrc (Letra Sincronizada)', + playlistFilenameTemplate: 'Formato do nome de ficheiro da lista de reprodução', + clearQueueOnExit: 'Limpar fila de transferências ao fechar a aplicação' + }, + covers: { + title: 'Capas do Álbum', + saveArtwork: 'Guardar capas', + coverImageTemplate: 'Modelo do nome da capa', + saveArtworkArtist: 'Salvar imagem do artista', + artistImageTemplate: 'Modelo de imagem do artista', + localArtworkSize: 'Tamanho da arte gráfica local', + embeddedArtworkSize: 'Tamanho da arte gráfica incorporada', + localArtworkFormat: { + title: 'Em que formato desejas guardar localmente a arte gráfica?', + jpg: 'Em jpeg', + png: 'Em png', + both: 'Em jpeg e em png' + }, + jpegImageQuality: 'Qualidade de imagem JPEG', + embeddedArtworkPNG: 'Guardar arte gráfica incorporada como PNG', + embeddedPNGWarning: 'PNGs não são oficialmente suportados pelo Deezer e podem ocorrer erros', + imageSizeWarning: + 'Qualquer resolução acima de x1200 não são oficialmente suportados pelo Deezer e podem ocorrer erros', + coverDescriptionUTF8: 'Guardar descrição da capa como UTF8? (iTunes Cover Fix)' + }, + tags: { + head: 'Etiquetas a guardar', + title: 'Título', + artist: 'Artista', + artists: 'Etiqueta extra ARTISTAS', + album: 'Álbum', + cover: 'Capa', + trackNumber: 'Número de faixa', + trackTotal: 'Total de faixas', + discNumber: 'Número do Disco', + discTotal: 'Total de Discos', + albumArtist: 'Artista do Álbum', + genre: 'Género', + year: 'Ano', + date: 'Data', + explicit: 'Letra Explícita', + isrc: 'ISRC', + length: 'Duração da faixa', + barcode: 'Código de barras do álbum (UPC)', + bpm: 'BPM', + replayGain: 'ReplayGain', + label: 'Editora do álbum', + lyrics: 'Letra da música não sincronizada', + syncedLyrics: 'Letra da música sincronizada', + copyright: 'Direitos de Autor', + composer: 'Compositor', + involvedPeople: 'Pessoas envolvidas', + artistsWarning: + 'Desativar a etiqueta ARTISTAS ao não usar especificações padrão, não preservará o suporte a multi-artistas' + }, + other: { + title: 'Outros', + autoCheckForUpdates: 'Procurar novas atualizações ao iniciar', + savePlaylistAsCompilation: 'Guardar listas de reprodução como compilação', + useNullSeparator: 'Usar separador nulo', + saveID3v1: 'Também guardar ID3v1', + multiArtistSeparator: { + title: 'Como queres separarar os artistas?', + nothing: 'Guardar apenas o artista principal', + default: 'Usar especificação padrão', + andFeat: 'Usar & e feat.', + using: 'Usar "{separator}"', + warning: + 'Utilizar outro separador para além das especificações standard irão adicionar uma etiqueta extra ARTISTAS para perservar o suporte a multi-artistas' + }, + singleAlbumArtist: 'Guardar apenas o artista principal do álbum', + albumVariousArtists: 'Manter "Various Artists" nos Artistas do Álbum', + removeAlbumVersion: 'Remover "Album Version" do título da faixa', + removeDuplicateArtists: 'Remover combinação de artistas', + dateFormat: { + title: 'Formato de data nos ficheiros FLAC', + year: 'AAAA', + month: 'MM', + day: 'DD' + }, + featuredToTitle: { + title: 'O que devo fazer com artistas convidados/participações?', + 0: 'Nada', + 1: 'Remover do título', + 3: 'Remover do título e do título do album', + 2: 'Movê-lo para o título' + }, + titleCasing: 'Caixa do Título', + artistCasing: 'Caixa do Artista', + casing: { + nothing: 'Manter inalterado', + lower: 'minusculas', + upper: 'MAIÚSCULAS', + start: 'Início De Cada Palavra', + sentence: 'Como uma frase' + }, + previewVolume: 'Volume de Pré-visualização', + executeCommand: { + title: 'Comando a executar após transferir', + description: 'Deixar em branco para nenhuma acção' + } + }, + spotify: { + title: 'Funcionalidades Spotify', + clientID: 'Spotify clientID', + clientSecret: 'Spotify Client Secret', + username: 'nome de utilizador Spotify', + question: 'Como ativo as funcionalidades Spotify?', + howTo: { + prologue: { + p1: '"Funcionalidades Spotify" são um conjunto de funcionalidades que permitem converter ligações de faixas e álbuns do Spotify em ligações do Deezer.', + p2: 'Caso forneças uma ligação para uma lista de reprodução Spotify a aplicação converterá automaticamente tosas as ligações de faixas em ligações de faixas Deezer.', + p3: 'Ao ativar estas funcionalidades também permitirá ver as tuas listas de reprodução públicas no separator Favoritos.' + }, + info: 'Por razões de segurança, deverás fornecer o teu próprio Client ID e Client Secret', + clientSecretQuestion: { + title: 'Como obtenho o meu Client ID e Client Secret?', + step1: { + text: 'Ligar a {spotifyDevelopersDashboard} e iniciar sessão com a tua conta Spotify.', + spotifyDevelopersDashboard: "Spotify for Developers's Dashboard" + }, + step2: { + text: 'Clique em "Create an App".', + imageAlt: "Botão 'Create an App' no 'Spotify for Developers's Dashboard'" + }, + step3: { + text: 'Preenche os campos "App name" e "App description" e marca ambas as caixas de seleção. E depois clique no botão "Create".', + imageAlt: 'Formulário "Create an app form"' + }, + step4: { + text: 'O Client ID já está visível. Caso clique em "Show Client Secret" o segredo do cliente será revelado.', + imageAlt: 'Imagem do client ID e Secret' + }, + step5: 'Copia e cola os resultados nos campos correspondentes das definições.' + }, + usernameQuestion: { + title: 'Como obtenho o meu nome de utilizador Spotify?', + step1: { + text: 'Podes obter o teu nome de utilizador na {overviewPage} no site do Spotify.', + overviewPage: 'Overview page' + } + } + } + }, + reset: 'Repor definições padrão', + resetMessage: 'Tens a certeza que queres repor as definições padrão?', + save: 'Guardar', + toasts: { + init: 'Definições carregadas!', + update: 'Definições atualizadas', + reset: 'Definições padrão repostas!', + ARLcopied: 'ARL copiado para area de transferencia' + } + }, + sidebar: { + home: 'início', + search: 'pesquisa', + charts: 'tabelas', + favorites: 'favoritos', + linkAnalyzer: 'analizador de links', + settings: 'definições', + logs: 'logs', + about: 'sobre' + }, + tracklist: { + downloadSelection: 'Transferir selecionados' + } +} + +export default pt diff --git a/webui/src/lang/ru.mjs b/webui/src/lang/ru.mjs new file mode 100644 index 0000000..477e07e --- /dev/null +++ b/webui/src/lang/ru.mjs @@ -0,0 +1,516 @@ +const ru = { + globals: { + welcome: 'Добро пожаловать в deemix', + back: 'назад', + loading: 'загрузка', + download: 'Скачать {thing}', + by: '{artist}', + in: 'из {album}', + download_hint: 'Скачать', + play_hint: 'Прослушать', + toggle_download_tab_hint: 'Показать/Скрыть', + clean_queue_hint: 'Очистить завершённые', + cancel_queue_hint: 'Очистить всё', + open_downloads_folder: 'Открыть папку с загрузками', + cut: 'вырезать', + copy: 'копировать', + copyLink: 'копировать ссылку', + copyImageLink: 'копировать URL картинки', + copyDeezerLink: 'копировать ссылку deezer', + paste: 'вставить', + listTabs: { + empty: '', + all: 'все', + top_result: 'лучший результат', + album: 'альбом | альбомы | альбомы', + artist: 'исполнитель | исполнители | исполнители', + single: 'сингл | синглы | синглы', + title: 'название', + track: 'трек | треки | треки', + trackN: '{n} трек | {n} трека | {n} треков', + releaseN: '{n} релиз | {n} релиза | {n} релизов', + playlist: 'плейлист | плейлисты | плейлисты', + compile: 'сплит | сплиты | сплиты', + ep: 'ep', + bundle: 'бандл | бандлы | бандлы', + more: 'Больше альбомов', + featured: 'Представлено в', + spotifyPlaylist: 'плейлист spotify | плейлисты spotify | плейлисты spotify', + releaseDate: 'Дата выхода', + error: 'ошибка', + albumN: '{n} альбом | {n} альбома | {n} альбомов', + artistN: '{n} исполнитель | {n} исполнителя | {n} исполнителей', + playlistN: '{n} плейлист | {n} плейлиста | {n} плейлистов' + }, + yes: 'да', + no: 'нет', + empty: 'пусто' + }, + about: { + appStatus: { + online: 'приложение онлайн', + offline: 'приложение оффлайн' + }, + updates: { + currentVersion: 'Текущая версия', + currentWebuiVersion: 'Текущая версия WebUI', + versionNotAvailable: 'Н/Д', + updateAvailable: `Вы используете не последнюю доступную версию: {version}`, + deemixVersion: 'Версия библиотеки deemix' + }, + titles: { + usefulLinks: 'Полезные ссылки', + bugReports: 'Отчёты об ошибках', + contributing: 'Помощь проекту', + donations: 'Пожертвования', + license: 'Лицензия' + }, + subtitles: { + bugReports: 'Что-то не работает? Сообщите нам!', + contributing: 'Хотите внести вклад в развитие этого проекта? Это можно сделать разными способами!', + donations: 'Хотите поддержать материально? Можно сделать пожертвование!' + }, + usesLibrary: + 'Приложение использует библиотеку deemix, с помощью которой вы можете разработать собственный UI для deemix.', + thanks: `Спасибо rtonno, uhwot и lollilol за помощь с этим проектом, а также BasCurtiz за иконку.`, + upToDate: { + text: `Следите за последними обновлениями на {newsChannel} в Telegram.`, + newsChannel: 'канале' + }, + officialWebsite: 'Официальный сайт', + officialRepo: 'Официальный репозиторий библиотеки', + officialWebuiRepo: 'Официальный репозиторий WebUI', + officialSubreddit: 'Официальный сабреддит', + newsChannel: 'Канал новостей', + questions: { + text: `Если у вас возникли вопросы или проблемы с приложением, поищите решение на {subreddit}. Если не нашли решение, можете создать новый пост и описать вашу проблему.`, + subreddit: 'сабреддите' + }, + beforeReporting: `Перед тем, как сообщать об ошибках, убедитесь, что вы используете последнюю версию приложения и что проблема не на вашей стороне.`, + beSure: `Убедитесь, что ошибка возникает и на других устройствах. Также НЕ сообщайте об ошибке, если про неё уже известно.`, + duplicateReports: 'Повторные сообщения об ошибках рассматриваться не будут.', + dontOpenIssues: `НЕ используйте репозиторий для вопросов автору, для этого есть сабреддит.`, + newUI: { + text: `Если вы хорошо знаете python, то можете сделать новый UI для приложения с использованием базовой библиотеки или пофиксить в ней баги и сделать pull request в {repo}.`, + repo: 'репозитории' + }, + acceptFeatures: `Можете предложить новые функции, но не слишком сложные, так как они будут добавлены в приложение, а не в саму библиотеку.`, + otherLanguages: `Если вы хорошо знаете другой язык программирования, можете портировать на нём deemix!`, + understandingCode: `Не можете разобраться в коде? Свяжитесь с RemixDev в Telegram или на Reddit.`, + contributeWebUI: { + text: `Если вы знаете Vue.js (JavaScript), HTML или CSS, можете внести вклад в развитие {webui}.`, + webui: 'WebUI' + }, + itsFree: `Помните, что это бесплатное приложение и вам следует поддерживать понравившихся исполнителей прежде, чем поддерживать разработчиков.`, + notObligated: `Вы не обязаны делать пожертвования, я всё равно вас ценю!`, + lincensedUnder: { + text: `Проект распространяется под лицензией {gpl3}.`, + gpl3: 'GNU General Public License 3.0' + } + }, + charts: { + title: 'Чарты', + changeCountry: 'Сменить страну', + download: 'Скачать чарт' + }, + errors: { + title: 'Ошибки {name}', + postTitle: 'Ошибки после скачивания', + ids: { + invalidURL: 'URL не распознан', + unsupportedURL: 'URL не поддерживается', + ISRCnotOnDeezer: 'ISRC данного трека недоступен на Deezer', + notYourPrivatePlaylist: 'Вы не можете скачивать чужие приватные плейлисты.', + spotifyDisabled: 'Неправильно настроены параметры Spotify.', + trackNotOnDeezer: 'Трек не найден на Deezer!', + albumNotOnDeezer: 'Альбом не найден на Deezer!', + notOnDeezer: 'Трек недоступен на Deezer!', + notEncoded: 'Трек ещё не перекодирован!', + notEncodedNoAlternative: 'Трек не перекодирован, альтернатив не найдено!', + wrongBitrate: 'Данного трека нет в нужном битрейте.', + wrongBitrateNoAlternative: 'Данного трека нет в нужном битрейте. Альтернатив не найдено!', + no360RA: 'Трек недоступен в формате Reality Audio 360.', + notAvailable: 'Трек недоступен на серверах Deezer!', + notAvailableNoAlternative: 'Трек недоступен на серверах Deezer. Альтернатив не найдено!', + noSpaceLeft: 'На устройстве не осталось свободного места!', + albumDoesntExists: 'Альбома не существует, информация не получена', + wrongLicense: 'Ваш аккаунт не может играть данный трек с желаемым битрейтом.', + wrongGeolocation: 'Ваш аккаунт не может играть данный трек из вашей текущей страны.', + wrongGeolocationNoAlternative: + 'Ваш аккаунт не может играть данный трек из вашей текущей страны. Альтернатив не найдено.' + } + }, + favorites: { + title: 'Избранное', + noPlaylists: 'Плейлисты не найдены', + noAlbums: 'Избранные альбомы не найдены', + noArtists: 'Избранные исполнители не найдены', + noTracks: 'Избранные треки не найдены' + }, + home: { + needTologin: 'Вам необходимо войти под своей учетной записью Deezer, прежде чем вы сможете скачивать.', + openSettings: 'Открыть настройки', + sections: { + popularPlaylists: 'Популярные плейлисты', + popularAlbums: 'Самые прослушиваемые альбомы' + } + }, + linkAnalyzer: { + info: 'Используйте этот раздел, чтобы узнать информацию о ссылке, которую требуется скачать.', + useful: + 'Этот раздел нужен, если вы хотите загрузить треки, недоступные в вашей стране, а также посмотреть, где они доступны.', + linkNotSupported: 'Ссылка не поддерживается', + linkNotSupportedYet: 'Эта ссылка не поддерживается, попробуйте вставить другую.', + table: { + id: 'ID', + isrc: 'ISRC', + upc: 'UPC', + duration: 'Продолжительность', + diskNumber: 'Номер диска', + trackNumber: 'Номер трека', + releaseDate: 'Дата выхода', + bpm: 'BPM', + label: 'Издатель', + recordType: 'Тип', + genres: 'Жанр', + tracklist: 'Треклист', + readable: 'Читабельный', + available: 'Доступен' + }, + countries: 'Страны, где доступен данный трек', + noCountries: 'Этот трек недоступен ни в одной стране.' + }, + search: { + startSearching: 'Начните искать!', + description: 'Здесь можно найти трек, альбом, исполнителя, плейлист... всё! Можно также вставить ссылку Deezer', + fans: '{n} поклонников', + noResults: 'Нет результатов', + noResultsTrack: 'Треков не найдено', + noResultsAlbum: 'Альбомов не найдено', + noResultsArtist: 'Исполнителей не найдено', + noResultsPlaylist: 'Плейлистов не найдено' + }, + searchbar: 'Ищите, что хотите (или вставьте ссылку)', + downloads: 'загрузки', + toasts: { + restoringQueue: 'Восстановление очереди загрузок...', + queueRestored: 'Очередь восстановлена!', + addedToQueue: '{item} добавлено в очередь', + addedMoreToQueue: '{n} загрузок добавлены в очередь', + alreadyInQueue: '{item} уже присутствует в очереди!', + finishDownload: 'Загрузка {item} завершена.', + allDownloaded: 'Все загрузки завершены!', + refreshFavs: 'Обновление завершено!', + loggingIn: 'Вход...', + loggedIn: 'Вход выполнен', + alreadyLogged: 'Вход уже выполнен', + loginFailed: 'Вход не выполнен', + loggedOut: 'Вы вышли из аккаунта', + cancellingCurrentItem: 'Отмена текущей загрузки.', + currentItemCancelled: 'Отменено.', + startAddingArtist: 'Добавление альбомов {artist} в очередь', + finishAddingArtist: 'Альбомы {artist} добавлены в очередь', + startConvertingSpotifyPlaylist: 'Добавление плейлиста Spotify в очередь', + finishConvertingSpotifyPlaylist: 'Spotify плейлист добавлен в очередь', + loginNeededToDownload: 'Войдите в аккаунт, чтобы скачивать треки!', + deezerNotAvailable: 'Deezer недоступен в вашей стране. Используйте VPN.', + startGeneratingItems: 'Обработка {n} загрузок...', + finishGeneratingItems: 'Обработано {n} загрузок.', + noLovedPlaylist: 'Нет плейлиста с любимыми треками!', + checkingUpdates: 'Проверка обновлений...', + noUpdateAvailable: 'Обновления программы не найдены', + updateAvailable: 'Доступно обновление программы!' + }, + settings: { + title: 'Настройки', + languages: 'Языки', + login: { + title: 'Вход', + loggedIn: 'Вы вошли как {username}', + arl: { + title: 'Либо используйте ARL', + question: 'Как узнать свой ARL?', + howTo: { + prologue: { + p1: 'Deezer отслеживает сеанс входа в систему с помощью файла cookie под названием ARL.', + p2: 'Deemix использует этот файл cookie для получения метаданных, необходимых для загрузки треков с Deezer.', + p3: 'Длительность авторизации через ARL - 3 месяца, после чего Deezer снова просит вас войти в систему. Тот же метод используется в deemix.', + p4: 'Следуя одному из приведенных ниже руководств, вы можете получить ARL для собственной учетной записи.', + warning: 'Используйте этот метод, только если электронная почта и пароль не работают.' + }, + chromeSteps: { + title: 'Chrome', + step1: 'Откройте Chrome', + easyWay: { + title: 'Chrome (простой способ)', + step3: 'Нажмите на маленький значок «замок» рядом с URL-адресом.', + step4: 'Выберите «Файлы cookie» > deezer.com > Файлы cookie > arl', + step5: 'Выберите строку рядом с Контент, выделите ее всю и скопируйте' + }, + step4: 'Перейдите на вкладку «Application» (если вы ее не видите, нажмите двойную стрелку )', + videoGuide: { + text: 'Вот {videoGuide}', + link: 'видео инструкция' + } + }, + firefoxSteps: { + title: 'Firefox', + step1: 'Откройте Firefox', + step4: 'Перейдите на вкладку «Хранилище» (если вы ее не видите, нажмите двойную стрелку)' + }, + commonSteps: { + step2: 'Перейдите на сайт www.deezer.com и войдите в свою учетную запись.', + step3: 'После входа в систему нажмите F12, чтобы открыть инструменты разработчика.', + step5: 'Откройте раскрывающийся список файлов cookie', + step6: 'Выберите www.deezer.com', + step7: 'Найдите файл cookie `arl` (он должен быть длиной 192 символа)', + step8: 'Убедитесь, что скопировано только значение, а не весь файл cookie.', + lastStep: 'Это ваш ARL, теперь вы можете использовать его в приложении' + } + }, + update: 'Обновить ARL' + }, + logout: 'Выйти', + login: 'Авторизоваться', + email: 'Электронная почта', + password: 'Пароль' + }, + appearance: { + title: 'Внешний вид', + slimDownloadTab: 'Компактная вкладка с загрузками', + slimSidebar: 'Компактная левая панель', + searchButton: 'Показывать кнопку поиска', + bitrateTags: 'Показывать битрейт в очереди загрузок' + }, + downloadPath: { + title: 'Путь для сохранения' + }, + templates: { + title: 'Шаблоны', + tracknameTemplate: 'Шаблон названия трека', + tracknameAvailableVariables: 'Доступные переменные для названия трека', + albumTracknameTemplate: 'Шаблон названия трека альбома', + albumTracknameAvailableVariables: 'Доступные переменные для названия трека альбома', + playlistTracknameTemplate: 'Шаблон названия трека плейлиста', + playlistTracknameAvailableVariables: 'Доступные переменные для названия трека плейлиста' + }, + folders: { + title: 'Папки', + createPlaylistFolder: 'Создавать папки для плейлистов', + playlistNameTemplate: 'Название папки плейлиста', + createArtistFolder: 'Создавать папки для исполнителя', + artistNameTemplate: 'Название папки исполнителя', + createAlbumFolder: 'Создавать папки для альбома', + albumNameTemplate: 'Название папки альбома', + createCDFolder: 'Создавать папки для CD', + createStructurePlaylist: 'Создавать структуру папок для плейлистов', + createSingleFolder: 'Создавать структуру папок для синглов' + }, + trackTitles: { + title: 'Названия треков', + padTracks: 'Добавлять ноль к номерам треков (01, 02, ...)', + paddingSize: 'Кол-во цифр в номере', + illegalCharacterReplacer: 'Замена для запрещённых в имени символов' + }, + downloads: { + title: 'Загрузки', + queueConcurrency: 'Количество одновременных загрузок', + maxBitrate: { + title: 'Предпочитаемый битрейт', + 9: 'FLAC 1411kbps', + 3: 'MP3 320kbps', + 1: 'MP3 128kbps' + }, + overwriteFile: { + title: 'Нужно ли перезаписывать файлы?', + y: 'Да, перезаписать файл', + n: 'Нет, не перезаписывать', + t: 'Обновить только теги', + b: 'Нет, оставить оба файла и добавить номер к дубликату', + e: 'Нет, вне зависимости от расширения' + }, + fallbackBitrate: 'Загружать с битрейтом ниже, если текущий недоступен', + fallbackSearch: 'Искать похожий трек, если запрашиваемый недоступен', + fallbackISRC: 'Искать похожий трек, если запрашиваемый по ISRC недоступен', + feelingLucky: 'Скачать при наличии на CDN и в кэше', + logErrors: 'Сохранять логи ошибок', + logSearched: 'Сохранять лог истории поиска', + createM3U8File: 'Создавать файлы плейлистов', + syncedLyrics: 'Создать .lrc файлы (синхронизированная лирика)', + playlistFilenameTemplate: 'Шаблон названия плейлиста', + saveDownloadQueue: 'Сохранять текущую очередь загрузок при закрытии приложения' + }, + covers: { + title: 'Обложки', + saveArtwork: 'Сохранять файл обложки', + coverImageTemplate: 'Шаблон названия обложки', + saveArtworkArtist: 'Сохранять файл изображения исполнителя', + artistImageTemplate: 'Шаблон названия изображения', + localArtworkSize: 'Размер сохраненной обложки', + embeddedArtworkSize: 'Размер встроенной в теги обложки', + localArtworkFormat: { + title: 'В каком формате сохранять обложки?', + jpg: 'jpeg', + png: 'png', + both: 'jpeg и png' + }, + jpegImageQuality: 'Качество JPEG', + embeddedArtworkPNG: 'Сохранять вложенную обложку в PNG', + embeddedPNGWarning: 'PNG официально не поддерживается в Deezer. Могут быть баги', + imageSizeWarning: 'Обложки с разрешением выше x1200 не поддерживаются в Deezer. Могут быть проблемы', + coverDescriptionUTF8: 'Сохранять описание обложки в UTF8 (iTunes Fix)' + }, + tags: { + head: 'Какие теги сохранять', + title: 'Название', + artist: 'Исполнитель', + artists: 'Дополнительный тег ARTISTS', + album: 'Альбом', + cover: 'Обложка', + trackNumber: 'Номер трека', + trackTotal: 'Кол-во треков', + discNumber: 'Номер диска', + discTotal: 'Кол-во дисков', + albumArtist: 'Исполнитель альбома', + genre: 'Жанр', + year: 'Год', + date: 'Дата', + explicit: 'Метка о нецензурной лексике', + isrc: 'Уникальный код трека (ISRC)', + length: 'Продолжительность', + barcode: 'Уникальный код альбома (UPC)', + bpm: 'BPM', + replayGain: 'Replay Gain', + label: 'Издатель', + lyrics: 'Текст песни', + syncedLyrics: 'Синхрон. текст песни', + copyright: 'Права (копирайт)', + composer: 'Композитор', + involvedPeople: 'Вовлечённые люди', + source: 'Источник и ID песни', + artistsWarning: + 'Отключение тега ARTISTS без использования стандартной спецификации не сохранит поддержку нескольких исполнителей.' + }, + other: { + title: 'Разное', + autoCheckForUpdates: 'Проверять наличие обновлений программы при запуске', + savePlaylistAsCompilation: 'Сохранять плейлисты как сборники', + useNullSeparator: 'Использовать null в качестве разделителя', + saveID3v1: 'Сохранить также ID3v1', + multiArtistSeparator: { + title: 'Как разделять несколько исполнителей?', + nothing: 'Сохранить только основного', + default: 'Используя стандартную спецификацию', + andFeat: 'Используя & и feat.', + using: 'Используя "{separator}"', + warning: + 'Использование любого разделителя, отличного от стандартной спецификации, добавит дополнительный тег ARTISTS, чтобы сохранить поддержку нескольких исполнителей.' + }, + singleAlbumArtist: 'Сохранить только основного исполнителя альбома', + albumVariousArtists: 'Оставить "Various Artists" в исполнителях альбома', + removeAlbumVersion: 'Удалить "Album Version" из названия трека', + removeDuplicateArtists: 'Удалить повторяющихся исполнителей', + dateFormat: { + title: 'Формат даты для FLAC файлов', + year: 'ГГГГ', + month: 'ММ', + day: 'ДД' + }, + featuredToTitle: { + title: 'Что делать с приглашёнными исполнителями (feat.)?', + 0: 'Ничего', + 1: 'Удалить из названия трека', + 3: 'Удалить из названия трека и альбома', + 2: 'Добавить в название трека' + }, + titleCasing: 'Регистр названия', + artistCasing: 'Регистр исполнителя', + casing: { + nothing: 'Не менять', + lower: 'в нижнем регистре', + upper: 'В ВЕРХНЕМ РЕГИСТРЕ', + start: 'Каждое Слово С Заглавной Буквы', + sentence: 'Как в предложении' + }, + previewVolume: 'Громкость прослушивания', + executeCommand: { + title: 'Выполнять команды по окончании загрузок', + description: 'Оставьте пустым, если ничего не требуется' + } + }, + spotify: { + title: 'Функции Spotify', + clientID: 'Spotify Client ID', + clientSecret: 'Spotify Client Secret', + username: 'имя пользователя Spotify', + question: 'Как включить «Функции Spotify»?', + howTo: { + prologue: { + p1: '«Функции Spotify» — это набор функций, которые позволяют конвертировать ссылки на треки и альбомы Spotify в ссылки Deezer.', + p2: 'Если вы предоставите ссылку на плейлист Spotify, приложение автоматически преобразует все ссылки на треки внутри него в треки deezer.', + p3: 'Включение этого набора функций позволит вам также видеть общедоступные плейлисты Spotify на вкладке «Избранное».' + }, + info: 'Из соображений безопасности вам нужно будет указать свои Client ID и Client Secret.', + clientSecretQuestion: { + title: 'Как получить Client ID и Client Secret?', + step1: { + text: 'Перейдите на страницу {spotifyDevelopersDashboard} и войдите в свою учетную запись Spotify.', + spotifyDevelopersDashboard: 'информационной панели Spotify для разработчиков' + }, + step2: { + text: 'Нажмите «Создать приложение».', + imageAlt: 'Кнопка «Создать приложение» на информационной панели Spotify для разработчиков' + }, + step3: { + text: 'Заполните поля «Имя приложения» и «Описание приложения» и установите флажок. Затем нажмите на кнопку «Создать».', + imageAlt: 'Создание формы приложения' + }, + step4: { + text: 'Теперь вы можете увидеть Client ID. Если вы нажмете «Показать Client Secret», Client Secret будет раскрыт.', + imageAlt: 'Скриншот с Client ID и Client Secret' + }, + step5: 'Теперь вы можете скопировать и вставить эти результаты в соответствующие поля в настройках.' + }, + usernameQuestion: { + title: 'Как мне получить свое имя пользователя Spotify?', + step1: { + text: 'Вы можете получить свое имя пользователя Spotify на {overviewPage} на веб-сайте Spotify.', + overviewPage: 'странице обзора профиля' + } + } + } + }, + reset: 'По умолчанию', + resetMessage: 'Вы уверены, что хотите вернуться к настройкам по умолчанию?', + save: 'Сохранить', + toasts: { + init: 'Настройки загружены!', + update: 'Настройки обновлены!', + reset: 'Настройки сброшены по умолчанию!', + ARLcopied: 'ARL скопирован в буфер обмена' + }, + logs: { + title: 'Логи', + areLogsActive: 'Активно' + } + }, + sidebar: { + home: 'главная', + search: 'поиск', + charts: 'чарты', + favorites: 'избранное', + linkAnalyzer: 'анализ ссылок', + settings: 'настройки', + logs: 'логи', + about: 'о проекте' + }, + tracklist: { + downloadSelection: 'Скачать выбранные' + }, + logs: { + event: 'Событие', + data: 'Данные' + } +} + +export default ru diff --git a/webui/src/lang/sr.mjs b/webui/src/lang/sr.mjs new file mode 100644 index 0000000..b46f7b1 --- /dev/null +++ b/webui/src/lang/sr.mjs @@ -0,0 +1,421 @@ +const sr = { + globals: { + welcome: 'Добродошли у deemix', + back: 'назад', + loading: 'Учитавам', + download: 'Преузми {thing}', + by: '{artist}', + in: 'на {album}', + download_hint: 'Преузми', + play_hint: 'Репродукуј', + toggle_download_tab_hint: 'Рашири/Скупи', + clean_queue_hint: 'Склони завршено', + cancel_queue_hint: 'Откажи све', + open_downloads_folder: 'Отвори Downloads фолдер', + cut: 'исеци', + copy: 'копирај', + copyLink: 'копирај линк', + copyImageLink: 'копирај линк до слике', + copyDeezerLink: 'копирај deezer линк', + paste: 'налепи', + listTabs: { + empty: '', + all: 'све', + top_result: 'најбољи резултат', + album: 'албум | албуме', + artist: 'извођача | извођаче', + single: 'сингл | синглове', + title: 'наслов | наслове', + track: 'песму | песме', + releaseN: '0 издања | {n} издање | {n} издања', + playlist: 'плејлисту | плејлисте', + compile: 'компилацију | компилације', + ep: 'еп | еп-ови', + bundle: 'bundle | bundle-ови', + more: 'Још албума', + featured: 'Појављује се у', + spotifyPlaylist: 'Spotify плејлисту | Spotify плејлисте', + releaseDate: 'датум издавања', + error: 'грешка', + trackN: '0 песама | {n} песма | {n} песама', + albumN: '0 албума | {n} албум | {n} албума', + artistN: '0 извођача | {n} извођач | {n} извођача', + playlistN: '0 плејлисти | {n} плејлиста | {n} плејлисти' + } + }, + about: { + appStatus: { + online: 'апликација је на мрежи', + offline: 'апликација је ван мреже' + }, + updates: { + currentVersion: 'Тренутна верзија', + currentWebuiVersion: 'Тренутна WebUI верзија', + versionNotAvailable: 'N/A', + updateAvailable: `Немате најновије доступну верзију: {version}`, + deemixVersion: 'Верзија deemix библиотеке' + }, + titles: { + usefulLinks: 'Корисни линкови', + bugReports: 'Пријављивање грешака', + contributing: 'Доприноси', + donations: 'Донације', + license: 'Лиценца' + }, + subtitles: { + bugReports: 'Да ли нешто не ради у deemix-у? Обавестите нас!', + contributing: 'Желите да допринесете овом пројекту? Постоји више начина да то урадите!', + donations: 'Желите да допринесете новчано? Можете да нам донирате!' + }, + usesLibrary: + 'Ова апликација користи deemix библиотеку, коју можете да користите да направите свој кориснички интерфејс за deemix.', + thanks: `Хвала корисницима rtonno, uhwot и lollilol што су ми помогли на овом пројекту и хвала кориснику BasCurtiz што је направио иконицу.`, + upToDate: { + text: `Останите у току са најновијим вестима преко нашег {newsChannel} на апликацији Телеграм.`, + newsChannel: 'канала са новостима' + }, + officialWebsite: 'Званични вебсајт', + officialRepo: 'Званични репозиторијум библиотеке', + officialWebuiRepo: 'Званични репозиторијум WebUI-а', + officialSubreddit: 'Званични подредит', + newsChannel: 'Канал са новостима', + questions: { + text: `Уколико имате питања или проблеме са апликацијом, потражите прво решење на {subreddit}. Након тога, уколико нисте нашли одговор, можете да направите нови пост са описом проблема на подредиту.`, + subreddit: 'подредиту' + }, + beforeReporting: `Пре него што пријавите грешку, проверите да ли имате најновију верзију апликације. Такође, постарајте се да то што желите да пријавите не представља неку грешку која се јавља само код вас.`, + beSure: `Проверите да ли се грешка може репродуковати на другим уређајима. НЕМОЈТЕ да пријављујете грешку уколико је већ пријављена.`, + duplicateReports: 'Дупликати пријављених грешака биће затворени, обратите пажњу на то.', + dontOpenIssues: `НЕМОЈТЕ да отварате issue да бисте поставили питање, постоји подредит за ту намену.`, + newUI: { + text: `Уколико знате Пајтон, можете да пробате да направите нови UI за апликацију користећи основну библиотеку, или да исправите багове у библиотеци слањем pull request-a на {repo}.`, + repo: 'репозиторијум' + }, + acceptFeatures: `Прихватам и нове опције, уколико нису превише сложене, које се могу имплементирати у апликацији а не библиотеци.`, + otherLanguages: `Уколико знате неки други програмски језик, можете да пробате да портујете deemix на други програмски језик!`, + understandingCode: `Треба вам помоћ да разумете код? Потражите RemixDev на Телеграму или Редиту.`, + contributeWebUI: { + text: `Ако знате Vue.js (JavaScript), HTML или CSS, можете да допринесете {webui}-у.`, + webui: 'WebUI' + }, + itsFree: `Имајте на уму да је ово бесплатни пројекат и да би требало да подржите извођаче које волите пре него да подржите програмере.`, + notObligated: `Не осећајте обавезу да донирате, свакако вас ценим!`, + lincensedUnder: { + text: `Ова апликација је објављена под лиценцом {gpl3}.`, + gpl3: 'GNU General Public License 3.0' + } + }, + charts: { + title: 'Топ листе', + changeCountry: 'Промени земљу', + download: 'Преузми топ листу' + }, + errors: { + title: 'Грешке за {name}', + ids: { + invalidURL: 'URL није препознат', + unsupportedURL: 'URL још није подржан', + ISRCnotOnDeezer: 'ISRC наслова није доступан на Deezer-у', + notYourPrivatePlaylist: 'Не можете да преузмете туђе приватне плејлисте', + spotifyDisabled: 'Spotify опције нису исправно подешене.', + trackNotOnDeezer: 'Песма није пронађена на Deezer-у!', + albumNotOnDeezer: 'Албум није пронађен на Deezer-у!', + notOnDeezer: 'Песма није доступна на Deezer-у!', + notEncoded: 'Песма још није енкодирана!', + notEncodedNoAlternative: 'Песма још није енкодирана и нема пронађених алтернатива!', + wrongBitrate: 'Нисам пронашао песму у жељеном битрејту.', + wrongBitrateNoAlternative: 'Нисам пронашао песму у жељеном битрејту и нема пронађених алтернатива!', + no360RA: 'Песма није доступна у Reality Audio 360.', + notAvailable: 'Песна није доступна на Deezer-овим серверима!', + notAvailableNoAlternative: 'Песна није доступна на Deezer-овим серверима и нема пронађених алтернатива!', + noSpaceLeft: 'Нема више слободног простора на уређају!', + albumDoesntExists: 'Албум песме не постоји, нисам успео да прикупим информације.', + wrongLicense: 'Ваш налог не може да стримује песму у жељеном битрејту.', + wrongGeolocation: 'Ваш налог не може да стримује песму из тренутне земље.' + } + }, + favorites: { + title: 'Омиљено', + noPlaylists: 'Нема плејлисти', + noAlbums: 'Нема омиљених албума', + noArtists: 'Нема омиљених извођача', + noTracks: 'Нема омиљених наслова' + }, + home: { + needTologin: 'Морате да се пријавите на свој Deezer налог пре него што кренете са преузимањем.', + openSettings: 'Отвори Подешавања', + sections: { + popularPlaylists: 'Популарне плејлисте', + popularAlbums: 'Најслушанији албуми' + } + }, + linkAnalyzer: { + info: 'Можете да користе ову секцију да сазнате више информација о линку који желите да преузмете.', + useful: + 'Ово можете бити корисно уколико желите да преузмете неке песме које нису доступне у вашој земљи а желите да сазнате са којих локација су доступне.', + linkNotSupported: 'Овај линк још није подржан', + linkNotSupportedYet: 'Изгледа да овај линк још није подржан, пробајте да анализирате неки други.', + table: { + id: 'ID', + isrc: 'ISRC', + upc: 'UPC', + duration: 'Трајање', + diskNumber: 'Број диска', + trackNumber: 'Број песме', + releaseDate: 'Датум објављивања', + bpm: 'BPM', + label: 'Издавачка кућа', + recordType: 'Record Type', + genres: 'Жанрови', + tracklist: 'Tracklist' + } + }, + search: { + startSearching: 'Започните претрагу!', + description: + 'Можете да тражите песму, цео албум, извођача, плејлисту.... било шта! Можете и да налепите Deezer линк', + fans: '{n} фанова', + noResults: 'Нема резултата', + noResultsTrack: 'Нема пронађених песама', + noResultsAlbum: 'Нема пронађених албума', + noResultsArtist: 'Нема пронађених извођача', + noResultsPlaylist: 'Нема пронађених плејлисти' + }, + searchbar: 'Претражите било шта (или налепите линк)', + downloads: 'преузимања', + toasts: { + restoringQueue: 'Обнављам ред за преузимање...', + queueRestored: 'Ред за преузимање је обновљен!', + addedToQueue: '{item} - додато у ред', + addedMoreToQueue: '{n} ставке(и) додате у ред', + alreadyInQueue: '{item} је већ у реду!', + finishDownload: '{item} - завршено преузимање.', + allDownloaded: 'Сва преузимања су завршена!', + refreshFavs: 'Освежавање завршено!', + loggingIn: 'Пријављивање...', + loggedIn: 'Пријављени', + alreadyLogged: 'Већ сте пријављени', + loginFailed: 'Нисам могао да вас пријавим', + loggedOut: 'Одјављени', + cancellingCurrentItem: 'Отказујем тренутну ставку.', + currentItemCancelled: 'Тренутно ставка отказана.', + startAddingArtist: 'Додајем албуме извођача {artist} у ред', + finishAddingArtist: 'Додао албуме извођача {artist} у ред', + startConvertingSpotifyPlaylist: 'Конвертујем Spotify песме у Deezer пезме', + finishConvertingSpotifyPlaylist: 'Spotify плејлиста је конвертована', + loginNeededToDownload: 'Морате да се пријавите да бисте преузели песме!', + deezerNotAvailable: 'Deezer није доступан у вашој земљи. Требало би да користите VPN.', + startGeneratingItems: 'Обрађујем {n} ставки...', + finishGeneratingItems: 'Генерисао {n} ставки.' + }, + settings: { + title: 'Подешавања', + languages: 'Језици', + login: { + title: 'Пријављивање', + loggedIn: 'Пријављени сте као {username}', + arl: { + question: 'Како да набавим свој ARL?', + update: 'Ажурирај ARL' + }, + logout: 'Одјава', + login: 'Пријава преко deezer.com' + }, + loginWithCredentials: { + title: 'Пријава имејлом и шифром', + login: 'Пријава' + }, + appearance: { + title: 'Приказ', + slimDownloadTab: 'Танки таб за преузимање', + slimSidebar: 'Танка бочна трака' + }, + downloadPath: { + title: 'Путања за смештање преузетих фајлова' + }, + templates: { + title: 'Шаблони', + tracknameTemplate: 'Шаблон имена песме', + tracknameAvailableVariables: 'Доступне променљиве за име песме', + albumTracknameTemplate: 'Шаблон имена албума', + albumTracknameAvailableVariables: 'Доступне променљиве за албум', + playlistTracknameTemplate: 'Шаблон имена плејлисте', + playlistTracknameAvailableVariables: 'Доступне променљиве за плејлисту' + }, + folders: { + title: 'Фолдери', + createPlaylistFolder: 'Направи фолдер за плејлисте', + playlistNameTemplate: 'Шаблон фолдера за плејлисте', + createArtistFolder: 'Направи фолдер за извођача', + artistNameTemplate: 'Шаблон фолдера за извођача', + createAlbumFolder: 'Направи фолдер за албум', + albumNameTemplate: 'Шаблон фолдера за албум', + createCDFolder: 'Направи фолдер за CD-ове', + createStructurePlaylist: 'Направи низ фолдера за плејлисте', + createSingleFolder: 'Направи низ фолдера за синглове' + }, + trackTitles: { + title: 'Наслови песама', + padTracks: 'Pad tracks', + paddingSize: 'Overwrite padding size', + illegalCharacterReplacer: 'Замена нелегалних знакова' + }, + downloads: { + title: 'Преузимања', + queueConcurrency: 'Број истовремених преузимања', + maxBitrate: { + title: 'Жељени битрејт', + 9: 'FLAC 1411kbps', + 3: 'MP3 320kbps', + 1: 'MP3 128kbps' + }, + overwriteFile: { + title: 'Да ли да прегазим постојеће фајлове?', + y: 'Да, прегази фајл', + n: 'Не, немој да прегазиш фајл', + t: 'Препиши само тагове', + b: 'Не, задржи оба фајла и додај број дупликату', + e: 'Не, и не гледај екстензије' + }, + fallbackBitrate: 'Bitrate fallback', + fallbackSearch: 'Search fallback', + logErrors: 'Направи фајл са извештајем о грешкама', + logSearched: 'Направи фајл са извештајем о претраживаним песмама', + createM3U8File: 'Направи фајл за плејлисту', + syncedLyrics: 'Направи .lrc фајлове (Sync Lyrics)', + playlistFilenameTemplate: 'Шаблон за фајл за плејлисте', + saveDownloadQueue: 'Сними ред за преузимање приликом затварања апликације' + }, + covers: { + title: 'Омоти албума', + saveArtwork: 'Сними омоте', + coverImageTemplate: 'Шаблон за име омота', + saveArtworkArtist: 'Сачувај слику извођача', + artistImageTemplate: 'Шаблон за слику извођача', + localArtworkSize: 'Величина локалних слика', + embeddedArtworkSize: 'Величина уграђених слика', + localArtworkFormat: { + title: 'У ком формату желите да снимите локалне слике?', + jpg: 'JPEG слика', + png: 'PNG слика', + both: 'И JPEG и PNG' + }, + jpegImageQuality: 'Квалитет JPEG слике', + embeddedArtworkPNG: 'Сними уграђене слике као PNG', + embeddedPNGWarning: 'Deezer нема званичну подршку за PNG формат па може доћи до багова', + imageSizeWarning: 'Deezer не подржава све изнад x1200, може доћи до грешака', + coverDescriptionUTF8: 'Сачувај опис омота као UTF8 (iTunes Cover Fix)' + }, + tags: { + head: 'Које тагове да сачувам', + title: 'Наслов', + artist: 'Извођач', + album: 'Албум', + cover: 'Омот албума', + trackNumber: 'Број песме', + trackTotal: 'Укупно песама', + discNumber: 'Број диска', + discTotal: 'Укупно дискова', + albumArtist: 'Извођач албума', + genre: 'Жанр', + year: 'Година', + date: 'Датум', + explicit: 'Експлицитан текст', + isrc: 'ISRC', + length: 'Дужина песме', + barcode: 'Баркод албума (UPC)', + bpm: 'BPM', + replayGain: 'Replay Gain', + label: 'Издавачка кућа', + lyrics: 'Несинхронизован текст песме', + syncedLyrics: 'Синхронизован текст песме', + copyright: 'Ауторска права', + composer: 'Композитор', + involvedPeople: 'Укључени људи', + source: 'Порекло и ID песме' + }, + other: { + title: 'Остало', + savePlaylistAsCompilation: 'Сачувај плејлисте као компилације', + useNullSeparator: 'Користи null сепаратор', + saveID3v1: 'Сними и ID3v1', + multiArtistSeparator: { + title: 'Како желите да раздвојите више извођача?', + nothing: 'Сними само главног извођача', + default: 'Користећи стандардну спецификацију', + andFeat: 'Користећи & и feat.', + using: "Користећи '{separator}'" + }, + singleAlbumArtist: 'Сними само име главног извођача на албуму', + albumVariousArtists: "Задржи 'Various Artists' као извођаче на албуму", + removeAlbumVersion: "Уклони 'Album Version' из наслова песме", + removeDuplicateArtists: 'Уклони комбинацију извођача', + dateFormat: { + title: 'Формат датума за FLAC фајлове', + year: 'ГГГГ', + month: 'ММ', + day: 'ДД' + }, + featuredToTitle: { + title: 'Шта да урадим са истакнутим извођачима?', + 0: 'Ништа', + 1: 'Уклони их из имена песме', + 3: 'Уклони их из имена песме и албума', + 2: 'Премести их у наслов' + }, + titleCasing: 'Величина слова наслова', + artistCasing: 'Величина слова извођача', + casing: { + nothing: 'Остави непромењено', + lower: 'малим словима', + upper: 'ВЕЛИКИМ СЛОВИМА', + start: 'Почетак Сваке Речи Великим Словима', + sentence: 'Као у реченици' + }, + previewVolume: 'Јачина звука за преслушавање', + executeCommand: { + title: 'Команда коју да извршим након преузимања', + description: 'Оставите празно за неизвршавање акције' + } + }, + spotify: { + title: 'Spotify опције', + clientID: 'Spotify ClientID', + clientSecret: 'Spotify Client Secret', + username: 'Spotify корисничко име', + question: 'Како да омогућим Spotify опције?' + }, + reset: 'Врати на почетне вредности', + resetMessage: 'Да ли сте сигурни да желите да се вратите на почетне вредности?', + save: 'Сними', + toasts: { + init: 'Подешавања учитана!', + update: 'Подешавања ажурирана!', + reset: 'Подешавања враћена на почетне вредности!', + ARLcopied: 'ARL копиран у оставу' + }, + logs: { + title: 'Дневници', + areLogsActive: 'Укључени' + } + }, + sidebar: { + home: 'почетна', + search: 'претрага', + charts: 'топ листе', + favorites: 'омиљено', + linkAnalyzer: 'анализа линкова', + settings: 'подешавања', + logs: 'дневници', + about: 'о програму' + }, + tracklist: { + downloadSelection: 'Преузми одабрано' + }, + logs: { + event: 'Догађај', + data: 'Подаци' + } +} + +export default sr diff --git a/webui/src/lang/th.mjs b/webui/src/lang/th.mjs new file mode 100644 index 0000000..066585b --- /dev/null +++ b/webui/src/lang/th.mjs @@ -0,0 +1,419 @@ +const th = { + globals: { + welcome: 'ยินดีต้อนรับสู่ deemix', + back: 'กลับ', + loading: 'กำลังโหลด', + download: 'ดาวน์โหลด {thing}', + by: 'โดย {artist}', + in: 'ใน {album}', + download_hint: 'ดาวน์โหลด', + play_hint: 'เล่น', + toggle_download_tab_hint: 'ขยาย/ยุบ', + clean_queue_hint: 'เคลียร์ที่ดาวน์โหลดเสร็จแล้ว', + cancel_queue_hint: 'ยกเลิกทั้งหมด', + open_downloads_folder: 'เปิดโฟลเดอร์ดาวน์โหลด', + cut: 'ตัด', + copy: 'คัดลอก', + copyLink: 'คัดลอกลิงก์', + copyImageLink: 'คัดลอกลิงค์รูปภาพ', + copyDeezerLink: 'คัดลอกลิงค์ deezer', + paste: 'วาง', + listTabs: { + empty: '', + all: 'ทั้งหมด', + top_result: 'ผลลัพธ์ที่ดีที่สุด', + album: 'อัลบั้ม | อัลบั้ม', + artist: 'ศิลปิน | ศิลปิน', + single: 'ซิงเกิล | ซิงเกิล', + title: 'ชื่อเพลง | ชื่อเพลง', + track: 'เพลง | เพลง', + releaseN: '0 เผยแพร่ | {n} เผยแพร่ | {n} เผยแพร่', + playlist: 'เพลย์ลิสต์ | เพลย์ลิสต์', + compile: 'อัลบั้มรวมเพลง | อัลบั้มรวมเพลง', + ep: 'อีพี | อีพี ', + bundle: 'ชุดรวม | ชุดรวม', + more: 'อัลบั้มเพิ่มเติม', + featured: 'มีส่วนร่วมใน', + spotifyPlaylist: 'เพลย์ลิสต์ Spotify | เพลย์ลิสต์ Spotify', + releaseDate: 'วันที่เผยแพร่', + error: 'ข้อผิดพลาด', + trackN: '0 เพลง | {n} เพลง | {n} เพลง ', + albumN: '0 อัลบั้ม | {n} อัลบั้ม | {n} อัลบั้ม', + artistN: '0 ศิลปิน | {n} ศิลปิน | {n} ศิลปิน', + playlistN: '0 เพลย์ลิสต์ | {n} เพลย์ลิสต์ | {n} เพลย์ลิสต์' + } + }, + about: { + appStatus: { + online: 'แอปออนไลน์', + offline: 'แอปออฟไลน์' + }, + updates: { + currentVersion: 'รุ่นปัจจุบัน', + currentWebuiVersion: 'รุ่น WebUI ปัจจุบัน', + versionNotAvailable: 'ไม่มี', + updateAvailable: `คุณไม่ได้ใช้แอปรุ่นล่าสุดที่มี: {version}`, + deemixVersion: 'รุ่นไลบรารี deemix' + }, + titles: { + usefulLinks: 'ลิงก์ที่มีประโยชน์', + bugReports: 'รายงานบั๊ก', + contributing: 'การมีส่วนร่วม', + donations: 'การบริจาค', + license: 'สัญญาอนุญาต' + }, + subtitles: { + bugReports: 'มีบางอย่างใน deemix ที่ใช้งานไม่ได้หรือ บอกเราสิ!', + contributing: 'คุณต้องการมีส่วนร่วมในโครงการนี้หรือไม่? คุณสามารถทำได้หลายวิธี!', + donations: 'หากคุณต้องการมีส่วนช่วยเหลือด้านการเงิน? คุณสามารถบริจาคได้!' + }, + usesLibrary: 'แอปนี้ใช้ไลบรารี deemix ซึ่งคุณสามารถใช้เพื่อสร้าง UI ของคุณเองสำหรับ deemix', + thanks: `ขอขอบคุณ rtonno, uhwot และ lolililol ที่ช่วยเหลือผมในโครงการนี้และ BasCurtiz ที่ช่วยทำไอคอนแอป`, + upToDate: { + text: `ติดตามการอัปเดตผ่าน {newsChannel} ใน Telegram.`, + newsChannel: 'แชนแนลข่าวสาร' + }, + officialWebsite: 'เว็บไซต์หลัก', + officialRepo: 'พื้นที่เก็บข้อมูลไลบรารีหลัก', + officialWebuiRepo: 'พื้นที่เก็บข้อมูล WebUI หลัก', + officialSubreddit: 'ซับเรดดิตหลัก', + newsChannel: 'แชนแนลข่าวสาร', + questions: { + text: `หากคุณมีข้อสงสัยหรือพบปัญหาเกี่ยวกับแอป ให้ค้นหาแนวทางแก้ไขใน{subreddit}ก่อน ถ้าไม่พบปัญหาที่เหมือนกันกับกรณีของคุณก็ให้คุณสร้างโพสต์ใหม่`, + subreddit: 'ซับเรดดิต' + }, + beforeReporting: `ก่อนที่จะรายงานจุดบกพร่อง ตรวจสอบให้แน่ใจว่าคุณกำลังใช้งานแอปเวอร์ชันล่าสุดและสิ่งที่คุณต้องการรายงานนั้นเป็นข้อบกพร่องจริง ๆ และไม่ใช่สิ่งผิดปกติที่เกิดขึ้นในเครื่องของคุณเท่านั้น`, + beSure: `ตรวจสอบให้แน่ใจว่าสามารถทำบักซ้ำได้บนเครื่องอื่น และ อย่า รายงานจุดบกพร่องหากมีการรายงานเข้ามาแล้ว`, + duplicateReports: 'การรายงานข้อผิดพลาดที่ซ้ำกันจะถูกปิด ดังนั้นโปรดดูให้ดี', + dontOpenIssues: `ห้ามOpen Issue เพื่อถามคำถาม เรามีซับเรดดิตไว้สำหรับการตอบคำถามแล้ว`, + newUI: { + text: `หากคุณถนัดภาษา python คุณสามารถลองสร้าง UI สำหรับแอปโดยใช้งานไลบราลีนี้ได้ หรือแก้บั๊กด้วยการส่ง pull request มายัง {repo}.`, + repo: 'repo' + }, + acceptFeatures: `เราเปิดรับคุณสมบัติใหม่ด้วย แต่ต้องไม่ใช่สิ่งที่ซับซ้อน เพราะสามารถปรับใช้งานได้โดยตรงในแอป ไม่ใช่ในไลบรารี`, + otherLanguages: `หากคุณถนัดการเขียนโปรแกรมด้วยภาษาอื่น คุณสามารถลองพอร์ต deemix เป็นภาษาโปรแกรมอื่น ๆ ได้!`, + understandingCode: `หากคุณต้องการความช่วยเหลือในการทำความเข้าใจโค้ด สามารถติดต่อ RemixDev ได้ทาง Telegram หรือ Reddit`, + contributeWebUI: { + text: `หากคุณถนัดภาษา Vue.js (JavaScript), HTML หรือ CSS คุณสามารถมีส่วนร่วมในการพัฒนา {webui} ได้`, + webui: 'WebUI' + }, + itsFree: `พึงระลึกเสมอว่า นี่เป็นโปรเจ็กต์ฟรีและคุณควรสนับสนุนศิลปินที่คุณรัก ก่อนที่จะสนับสนุนนักพัฒนาโปรแกรมนี้`, + notObligated: `อย่ารู้สึกว่าโดนบังคับให้บริจาค ยังไงก็เราก็ขอขอบคุณ!`, + lincensedUnder: { + text: `ผลงานนี้ใช้{gpl3}.`, + gpl3: 'สัญญาอนุญาตสาธารณะทั่วไปของกนู 3.0' + } + }, + charts: { + title: 'ชาร์ตเพลง', + changeCountry: 'เปลี่ยนประเทศ', + download: 'ดาวน์โหลดเพลงทั้งชาร์ต' + }, + errors: { + title: 'ข้อผิดพลาด {name}', + ids: { + invalidURL: 'ไม่รู้จัก URL นี้', + unsupportedURL: 'ยังไม่รองรับ URL นี้', + ISRCnotOnDeezer: 'ไม่มีรหัส ISRC ของเพลงนี้บน Deezer', + notYourPrivatePlaylist: 'คุณไม่สามารถดาวน์โหลดเพลย์ลิสต์ส่วนตัวของผู้อื่นได้', + spotifyDisabled: 'คุณสมบัติ Spotify ไม่ได้รับการตั้งค่าอย่างถูกต้อง', + trackNotOnDeezer: 'ไม่พบเพลงนี้ใน Deezer!', + albumNotOnDeezer: 'ไม่พบอัลบั้มนี้ใน Deezer!', + notOnDeezer: 'เพลงนี้ไม่พร้อมใช้งานใน Deezer!', + notEncoded: 'เพลงยังไม่ได้เข้ารหัส!', + notEncodedNoAlternative: 'เพลงยังไม่ได้เข้ารหัสและไม่พบทางเลือกอื่น!', + wrongBitrate: 'ไม่พบเพลงที่ต้องการในอัตราบิตเรตนี้', + wrongBitrateNoAlternative: 'ไม่พบเพลงที่ต้องการในอัตราบิตเรตนี้ และไม่พบตัวเลือกอื่น!', + no360RA: 'เพลงนี้ไม่มีในรูปแบบ Reality Audio 360.', + notAvailable: 'เพลงนี้ไม่พร้อมใช้งานบนเซิร์ฟเวอร์ของ Deezer!', + notAvailableNoAlternative: 'เพลงนี้ไม่พร้อมใช้งานบนเซิร์ฟเวอร์ของ Deezer และไม่พบทางเลือกอื่น!', + noSpaceLeft: 'ไม่มีพื้นที่เหลือบนอุปกรณ์!', + albumDoesntExists: 'ไม่มีอัลบั้มของเพลงนี้ ไม่สามารถรวบรวมข้อมูลได้', + wrongLicense: 'บัญชีของคุณไม่สามารถสตรีมเพลงในบิตเรตที่ต้องการได้', + wrongGeolocation: 'บัญชีของคุณไม่สามารถสตรีมเพลงจากประเทศปัจจุบันของคุณได้' + } + }, + favorites: { + title: 'รายการที่ชื่นชอบ', + noPlaylists: 'ไม่พบเพลย์ลิสต์ที่ชื่นชอบ', + noAlbums: 'ไม่พบอัลบั้มที่ชื่นชอบ', + noArtists: 'ไม่พบศิลปินที่ชื่นชอบ', + noTracks: 'ไม่พบเพลงที่ชื่นชอบ' + }, + home: { + needTologin: 'คุณต้องลงชื่อเข้าใช้บัญชี Deezer ของคุณก่อนจึงจะสามารถเริ่มการดาวน์โหลดได้', + openSettings: 'เปิดการตั้งค่า', + sections: { + popularPlaylists: 'เพลย์ลิสต์ยอดนิยม', + popularAlbums: 'อัลบั้มที่มีการสตรีมมากที่สุด' + } + }, + linkAnalyzer: { + info: 'คุณสามารถใช้ส่วนนี้เพื่อค้นหาข้อมูลเพิ่มเติมเกี่ยวกับลิงก์ที่คุณกำลังพยายามดาวน์โหลด', + useful: + 'หากคุณต้องการดาวน์โหลดเพลงที่ไม่พร้อมงานในประเทศของคุณ และต้องการทราบว่าเพลงเหล่านั้นพร้อมใช้งานในประเทศไหน ตัววิเคราะห์ลิงก์นี้อาจช่วยคุณได้', + linkNotSupported: 'ลิงก์นี้ยังไม่รองรับ', + linkNotSupportedYet: 'ดูเหมือนว่าลิงก์นี้ยังไม่รองรับ ลองวิเคราะห์ลิงก์อื่น', + table: { + id: 'ID', + isrc: 'ISRC', + upc: 'UPC', + duration: 'ระยะเวลา', + diskNumber: 'หมายเลขดิสก์', + trackNumber: 'หมายเลขเพลง', + releaseDate: 'วันที่เผยแพร่', + bpm: 'BPM', + label: 'ค่ายเพลง', + recordType: 'ประเภทการบันทึกเสียง', + genres: 'ประเภท', + tracklist: 'รายชื่อเพลง' + } + }, + search: { + startSearching: 'เริ่มการค้นหา!', + description: 'คุณสามารถค้นหาเพลงทั้งอัลบั้ม ศิลปิน เพลย์ลิสต์.... อะไรได้ทั้งนั้น! หรือจะวางลิงก์ Deezer ก็ได้', + fans: 'แฟนเพลง {n} คน', + noResults: 'ไม่มีผลลัพธ์', + noResultsTrack: 'ไม่พบเพลง', + noResultsAlbum: 'ไม่พบอัลบั้ม', + noResultsArtist: 'ไม่พบศิลปิน', + noResultsPlaylist: 'ไม่พบเพลย์ลิสต์' + }, + searchbar: 'ค้นหาเพลงที่คุณต้องการ (หรือจะวางลิงก์ก็ได้)', + downloads: 'ดาวน์โหลด', + toasts: { + restoringQueue: 'กำลังกู้คืนคิวการดาวน์โหลด...', + queueRestored: 'กู้คืนคิวดาวน์โหลดแล้ว!', + addedToQueue: '{item} ถูกเพิ่มในคิวแล้ว', + addedMoreToQueue: 'เพิ่ม {n} รายการในคิวแล้ว', + alreadyInQueue: '{item} อยู่ในคิวแล้ว!', + finishDownload: 'ดาวน์โหลด {item} เสร็จแล้ว', + allDownloaded: 'การดาวน์โหลดทั้งหมดเสร็จสิ้น!', + refreshFavs: 'รีเฟรชเสร็จแล้ว!', + loggingIn: 'กำลังเข้าสู่ระบบ...', + loggedIn: 'เข้าสู่่ระบบแล้ว', + alreadyLogged: 'เข้าสู่่ระบบอยู่แล้ว', + loginFailed: 'ไม่สามารถเข้าสู่ระบบได้', + loggedOut: 'ออกจากระบบแล้ว', + cancellingCurrentItem: 'กำลังยกเลิกรายการปัจจุบัน', + currentItemCancelled: 'รายการปัจจุบันถูกยกเลิกแล้ว', + startAddingArtist: 'กำลังเพิ่มอัลบั้มของ {artist} ไปยังคิว', + finishAddingArtist: 'เพิ่มอัลบั้มของ {artist} ไปยังคิวแล้ว', + startConvertingSpotifyPlaylist: 'กำลังแปลงเพลงจาก Spotify เป็นเพลง Deezer', + finishConvertingSpotifyPlaylist: 'แปลงเพลย์ลิสต์ Spotify แล้ว', + loginNeededToDownload: 'คุณต้องเข้าสู่ระบบเพื่อดาวน์โหลดแทร็ก!', + deezerNotAvailable: 'Deezer ไม่มีการให้บริการในประเทศของคุณ คุณควรใช้ VPN', + startGeneratingItems: 'กำลังประมวลผล {n} รายการ...', + finishGeneratingItems: 'สร้างแล้ว {n} รายการ' + }, + settings: { + title: 'การตั้งค่า', + languages: 'ภาษา', + login: { + title: 'เข้าสู่ระบบ', + loggedIn: 'คุณเข้าสู่ระบบด้วย {username}', + arl: { + question: 'ฉันจะหารหัส ARL ของตัวเองได้อย่างไร?', + update: 'อัปเดต ARL' + }, + logout: 'ออกจากระบบ', + login: 'เข้าสู่ระบบผ่าน deezer.com' + }, + loginWithCredentials: { + title: 'เข้าสู่ระบบด้วยรหัสรับรองตัวตน', + login: 'เข้าสู่ระบบ' + }, + appearance: { + title: 'หน้าตาแอป', + slimDownloadTab: 'ลดขนาดแถบดาวน์โหลด', + slimSidebar: 'ลดขนาดแถบด้านข้าง' + }, + downloadPath: { + title: 'ตำแหน่งการดาวน์โหลด' + }, + templates: { + title: 'เทมเพลต', + tracknameTemplate: 'เทมเพลตชื่อเพลง', + tracknameAvailableVariables: 'ตัวแปรชื่อเพลงที่ใช้ได้', + albumTracknameTemplate: 'เทมเพลตอัลบั้มเพลง', + albumTracknameAvailableVariables: 'ตัวแปรชื่ออัลบั้มที่สามารถใช้ได้', + playlistTracknameTemplate: 'เทมเพลตชื่อเพลย์ลิสต์', + playlistTracknameAvailableVariables: 'ตัวแปรชื่อเพลย์ลิสต์ที่สามารถใช้ได้' + }, + folders: { + title: 'โฟลเดอร์', + createPlaylistFolder: 'สร้างโฟลเดอร์สำหรับเพลย์ลิสต์', + playlistNameTemplate: 'เทมเพลตชื่อโฟลเดอร์เพลย์ลิสต์', + createArtistFolder: 'สร้างโฟลเดอร์สำหรับศิลปิน', + artistNameTemplate: 'เทมเพลตชื่อโฟลเดอร์ศิลปิน', + createAlbumFolder: 'สร้างโฟลเดอร์สำหรับอัลบั้ม', + albumNameTemplate: 'เทมเพลตชื่อโฟลเดอร์อัลบั้ม', + createCDFolder: 'สร้างโฟลเดอร์สำหรับซีดี', + createStructurePlaylist: 'สร้างโครงสร้างโฟลเดอร์สำหรับเพลย์ลิสต์', + createSingleFolder: 'สร้างโครงสร้างโฟลเดอร์สำหรับซิงเกิล' + }, + trackTitles: { + title: 'ชื่อเพลง', + padTracks: 'เพิ่มช่องว่างในชื่อเพลง', + paddingSize: 'ขนาดช่องว่างบันทึกทับ', + illegalCharacterReplacer: 'การแทนที่อักขระที่ใช้งานไม่ได้' + }, + downloads: { + title: 'ดาวน์โหลด', + queueConcurrency: 'จำนวนการดาวน์โหลดพร้อมกัน', + maxBitrate: { + title: 'บิตเรตที่ต้องการ', + 9: 'FLAC 1411kbps', + 3: 'MP3 320kbps', + 1: 'MP3 128kbps' + }, + overwriteFile: { + title: 'อนุญาตให้บันทึกทับไฟล์เดิมหรือไม่?', + y: 'ใช่ บันทึกทับไฟล์เดิมเลย', + n: 'ไม่ อย่าบันทึกทับไฟล์เดิม', + t: 'บันทึกทับเฉพาะแท็ก', + b: 'ไม่ เก็บทั้งสองไฟล์และเพิ่มหมายเลขลงในสำเนาที่ซ้ำ', + e: 'ไม่ และไม่ต้องสนใจนามสกุลไฟล์' + }, + fallbackBitrate: 'บิตเรตทางเลือกสำรอง', + fallbackSearch: 'การค้นหาทางเลือกสำรอง', + logErrors: 'สร้างไฟล์บันทึกข้อผิดพลาด', + logSearched: 'สร้างไฟล์บันทึกรายการเพลงที่ค้นหา', + createM3U8File: 'สร้างไฟล์เพลย์ลิสต์', + syncedLyrics: 'สร้างไฟล์ .lrc (เนื้อเพลงซิงโครไนซ์)', + playlistFilenameTemplate: 'เทมเพลตชื่อไฟล์เพลย์ลิสต์', + saveDownloadQueue: 'บันทึกคิวดาวน์โหลดเมื่อปิดแอป' + }, + covers: { + title: 'ภาพปกอัลบั้ม', + saveArtwork: 'บันทึกภาพปกอัลบั้ม', + coverImageTemplate: 'เทมเพลตชื่อภาพปก', + saveArtworkArtist: 'บันทึกภาพศิลปิน', + artistImageTemplate: 'เทมเพลตภาพศิลปิน', + localArtworkSize: 'ขนาดภาพปกอัลบั้มในโฟลเดอร์', + embeddedArtworkSize: 'ขนาดภาพปกอัลบั้มที่ฝังในไฟล์', + localArtworkFormat: { + title: 'คุณต้องการบันทึกภาพปกอัลบั้มในโฟลเดอร์เป็นไฟล์ประเภทใด', + jpg: 'ภาพ jpeg', + png: 'ภาพ png', + both: 'บันทึกทั้งภาพ jpeg และ png' + }, + jpegImageQuality: '= คุณภาพของภาพ JPEG', + embeddedArtworkPNG: 'บันทึกภาพปกอัลบั้มที่ฝังในไฟล์เป็นไฟล์ PNG', + embeddedPNGWarning: 'ไฟล์ PNG ไม่ได้รับการสนับสนุนอย่างเป็นทางการจาก Deezer และอาจทำให้มีปัญหาได้', + imageSizeWarning: 'ไฟล์ที่ขนาดมากกว่า x1200 ไม่ได้ถูกใช้อย่างเป็นทางการโดย Deezer คุณอาจพบปัญหาได้', + coverDescriptionUTF8: 'บันทึกคำอธิบายภาพปกโดยใช้ UTF8 (แก้ไขปก iTunes)' + }, + tags: { + head: 'แท็กที่ต้องการบันทึก', + title: 'ชื่อเพลง', + artist: 'ศิลปิน', + album: 'อัลบั้ม', + cover: 'ภาพปกอัลบั้ม', + trackNumber: 'ลำดับเพลง', + trackTotal: 'จำนวนเพลง', + discNumber: 'หมายเลขแผ่น', + discTotal: 'จำนวนแผ่นทั้งหมด', + albumArtist: 'ศิลปินในอัลบั้ม', + genre: 'ประเภท', + year: 'ปี', + date: 'วันที่', + explicit: 'เนื้อเพลงโจ่งแจ้ง', + isrc: 'ISRC', + length: 'ความยาวเพลง', + barcode: 'บาร์โค้ดอัลบั้ม (UPC)', + bpm: 'BPM', + replayGain: 'Replay Gain', + label: 'ค่ายเพลง', + lyrics: 'เนื้อเพลงที่ไม่ซิงโครไนซ์', + syncedLyrics: 'เนื้อเพลงซิงโครไนซ์', + copyright: 'ลิขสิทธิ์', + composer: 'ผู้แต่งเพลง', + involvedPeople: 'ผู้มีส่วนร่วม', + source: 'แหล่งที่มาและรหัสเพลง' + }, + other: { + title: 'การตั้งค่าอื่น ๆ', + savePlaylistAsCompilation: 'บันทึกเพลย์ลิสต์เป็นอัลบั้มรวมเพลง', + useNullSeparator: 'ใช้ตัวคั่นค่า null', + saveID3v1: 'บันทึก ID3v1 ด้วย', + multiArtistSeparator: { + title: 'คุณต้องการแยกชื่อศิลปินอย่างไร?', + nothing: 'บันทึกเฉพาะศิลปินหลักเท่านั้น', + default: 'ใช้การระบุแบบมาตรฐานดั้งเดิม', + andFeat: 'ใช้ & และ feat.', + using: 'ใช้ "{separator}"' + }, + singleAlbumArtist: 'บันทึกเฉพาะศิลปินหลักของอัลบั้ม', + albumVariousArtists: 'เก็บ "หลายศิลปิน" ไว้ในอัลบั้มของศิลปิน', + removeAlbumVersion: 'ลบ "อัลบั้มเวอร์ชัน" ออกจากชื่อเพลง', + removeDuplicateArtists: 'ลบการรวมศิลปิน', + dateFormat: { + title: 'รูปแบบวันที่สำหรับไฟล์ FLAC', + year: 'ปปปป', + month: 'มม', + day: 'ดด' + }, + featuredToTitle: { + title: 'คุณต้องการจัดการชื่อศิลปินร่วมอย่างไร?', + 0: 'ไม่ต้องเปลี่ยนแปลงอะไร', + 1: 'เอาออกจากชื่อไฟล์', + 3: 'ลบออกจากชื่อไฟล์และชื่ออัลบั้ม', + 2: 'ย้ายไปไว้ในชื่อไฟล์' + }, + titleCasing: 'ตัวพิมพ์ใหญ่-พิมพ์เล็ก ชื่อเพลง', + artistCasing: 'ตัวพิมพ์ใหญ่-พิมพ์เล็ก ชื่อศิลปิน', + casing: { + nothing: 'ไม่ต้องเปลี่ยนแปลงอะไร', + lower: 'ตัวพิมพ์เล็ก', + upper: 'ตัวพิมพ์ใหญ่', + start: 'อักษรตัวแรกของทุกคำขึ้นต้นด้วยตัวพิมพ์ใหญ่', + sentence: 'ตัวพิมพ์ใหญ่เฉพาะอักษรตัวแรกเท่านั้นเหมือนในประโยค' + }, + previewVolume: 'ระดับเสียงตัวอย่างเพลง', + executeCommand: { + title: 'รันคำสั่งเมื่อเสร็จสิ้นการดาวน์โหลด', + description: 'เว้นว่างไว้หากไม่ต้องการทำอะไรเพิ่มเติม' + } + }, + spotify: { + title: 'คุณสมบัติ Spotify', + clientID: 'Spotify ClientID', + clientSecret: 'Spotify Client Secret', + username: 'ชื่อผู้ใช้ Spotify', + question: 'ฉันจะเปิดใช้งานคุณสมบัติ Spotify ได้อย่างไร?' + }, + reset: 'รีเซ็ตเป็นค่าเริ่มต้น', + resetMessage: 'คุณแน่ใจหรือไม่ว่าต้องการกลับไปใช้การตั้งค่าเริ่มต้น?', + save: 'บันทึก', + toasts: { + init: 'โหลดการตั้งค่าแล้ว!', + update: 'อัปเดตการตั้งค่าแล้ว!', + reset: 'การตั้งค่าถูกรีเซ็ตเป็นค่าเริ่มต้น!', + ARLcopied: 'คัดลอก ARL ไปยังคลิปบอร์ดแล้ว' + }, + logs: { + title: 'บันทึก', + areLogsActive: 'เปิดใช้งานอยู่' + } + }, + sidebar: { + home: 'หน้าแรก', + search: 'ค้นหา', + charts: 'ชาร์ตเพลง', + favorites: 'รายการที่ชื่นชอบ', + linkAnalyzer: 'ตัววิเคราะห์ลิงก์', + settings: 'การตั้งค่า', + logs: 'บันทึก', + about: 'เกี่ยวกับ' + }, + tracklist: { + downloadSelection: 'ดาวน์โหลดรายการที่เลือก' + }, + logs: { + event: 'เหตุการณ์', + data: 'ข้อมูล' + } +} + +export default th diff --git a/webui/src/lang/tr.mjs b/webui/src/lang/tr.mjs new file mode 100644 index 0000000..747760c --- /dev/null +++ b/webui/src/lang/tr.mjs @@ -0,0 +1,356 @@ +const tr = { + globals: { + welcome: `Deemix'e hoş geldin.`, + back: `geri`, + loading: `yükleniyor`, + download: 'İndir {thing}', + by: '{artist} tarafından', + in: '{album} içinde', + download_hint: 'İndir', + play_hint: 'Oynat', + toggle_download_tab_hint: 'Genişlet/Daralt', + clean_queue_hint: 'Tamamlananları Temizle', + cancel_queue_hint: 'Hepsini ', + listTabs: { + empty: '', + all: 'Tümü', + top_result: 'top result', + album: 'albüm | albümler', + artist: 'sanatçı | sanatçılar', + single: 'single | singlelar', + title: 'başlık | başlıklar', + track: 'Parça | Parçalar', + trackN: '0 parça | {n} parça | {n} parça', + releaseN: '0 yayınlanan | {n} yayınlanan | {n} yayınlanan', + playlist: 'oynatma listesi | oynatma listeleri', + compile: 'derleme | derlemeler', + ep: 'kayıt | kayıtlar', + spotifyPlaylist: 'spotify oynatma listesi | oynatma listeleri', + releaseDate: 'yayınlanma tarihi', + error: 'hata' + } + }, + about: { + titles: { + usefulLinks: 'Yararlı Bağlantılar', + bugReports: 'Hata Raporları', + contributing: 'Katkı Sağlayanlar', + donations: 'Bağışlar', + license: 'Lisans' + }, + subtitles: { + bugReports: "Deemix'te çalışmayan bir şey mi var?, Bize bildirin!", + contributing: 'Projeye katkı sağlamak mı istiyorsun? Farklı yollardan sağlayabilirsin!', + donations: 'Bütçe yardımı mı yapmak istiyorsun? Bağış yapabilirsin!' + }, + usesLibrary: + 'deemix kendi kullanıcı arabiriminizi oluşturabileceğiniz, kendine özgü kütüphanesini kullanıyor.', + thanks: ` rtonno, uhwot ve lollilol'a bu projeye yaptığı katkılardan ve BasCurtiz'e ikonlardan dolayı teşekkür ederim.`, + upToDate: { + text: `{newsChannel} takip ederek güncellemelerden haberdar olun.`, + newsChannel: 'Telegramdaki haber kanalını' + }, + officialWebsite: 'İlgili İnternet Sitemiz', + officialRepo: 'İlgili Kütüphanemiz', + officialWebuiRepo: 'İlgili Web Kullanıcı Arayüzü Kütüphanemiz.', + officialSubreddit: 'İlgili Subreddit adresimiz', + newsChannel: 'Haber Kanalı', + questions: { + text: `Eğer uygulama ile ilgili sorularınız veya bir probleminiz varsa,ilk önce {subreddit} sorununuzu arayın. Eğer bir şey bulamazsanız, sorununuz ile ilgili bir gönderi paylaşabilirsiniz.`, + subreddit: 'subreddit adresinden' + }, + beforeReporting: `Bir hatayı bildirmeden önce, uygulamanın son sürümünde olduğunuza veya sorunun sizden kaynaklı olmayıp bir hata olduğuna emin olduktan sonra emin olun.`, + beSure: `Hatanın başka cihazlarda da olduğunu doğrulayın ve Bildirilen bir hatayı tekrar bildirmeyin.`, + duplicateReports: 'Birbirinin aynısı olan hata bildirileri kapatılacaktır, o yüzden dikkatli olun.', + dontOpenIssues: `Soru sormak için hata bildirisi yollamayın, bunun için bir subreddit adresimiz var.`, + newUI: { + text: `Eğer Phython kullanmakta iyiysen, ana kütüphaneyi kullanan bir kullanıcı arayüzü yapmayı deneyebilir, veya kütüphanedeki hataları düzeltmek için {repo}.`, + repo: 'deposuna değişiklik isteği yollayabilirsin' + }, + acceptFeatures: `Yeni özellikleri de kabul ediyorum, fakat karışık şeyleri kütüphaneye değil uygulamaya eklendiği için kabul edemiyorum.`, + otherLanguages: `Eğer diğer programlama dillerinde kendine güveniyorsan, deemix'i farklı dillere port etmeye çalışabilirsin!`, + understandingCode: `Kodu anlamak için yardım mı lazım? Reddit üzerinden veya Telegramdan RemixDev'e ulaş.`, + contributeWebUI: { + text: `Eğer Vue.js (JavaScript), HTML veya CSS biliyorsan, {webui}.`, + webui: 'Web Kullanıcı Arayüzüne katkıda bulanabilirsin' + }, + itsFree: `Bunun ücretsiz bir proje olduğunu ve geliştiricilerden önce sevdiğiniz sanatçıları desteklemeniz gerektiğini unutmayın.`, + notObligated: `Kendinizi bağış yapmak zorunda hissetmeyin!, Sizi her halinizle seviyorum!`, + lincensedUnder: { + text: `Bu çalışma lisanslıdır: {gpl3}.`, + gpl3: 'GNU General Public License 3.0' + } + }, + charts: { + title: 'Grafikler', + changeCountry: 'Ülke Değiştir', + download: 'Grafiği İndir' + }, + errors: { + title: '{name} Hatalı bulundu', + ids: { + invalidURL: 'URL geçersiz.', + unsupportedURL: 'URL şimdilik desteklenmiyor', + ISRCnotOnDeezer: 'ISRC parça deezerda bulunmuyor', + notYourPrivatePlaylist: 'Başkalarının özel oynatma listelerini indiremezsin.', + spotifyDisabled: 'Spotify Özellikleri doğru şekilde ayarlanmamış.', + trackNotOnDeezer: `Parça Deezer'da bulunamadı!`, + albumNotOnDeezer: `Albüm Deezer'da bulunamadı!`, + notOnDeezer: `Parça Deezer'da yok!`, + notEncoded: `Parça henüz dönüştürülmedi!`, + notEncodedNoAlternative: 'Parça henüz dönüştürülmedi ve alternatifi bulunamadı!', + wrongBitrate: 'Parça, istenen kalitede bulunamadı!', + wrongBitrateNoAlternative: 'Parça veya alternatifler istenen kalitede bulunamadı!', + no360RA: 'Parça 360 Derece gerçekçi ses olarak bulunamadı!', + notAvailable: 'Parça Deezer sunucularında bulunamadı!', + notAvailableNoAlternative: 'Parça veya Alternatifleri Deezer sunucularında bulunamadı.!' + } + }, + favorites: { + title: 'Favoriler', + noPlaylists: 'Oynatma listesi bulunamadı.', + noAlbums: 'Favori albümler bulunamadı.', + noArtists: 'Favori sanatçılar bulunamadı.', + noTracks: 'Favori parçalar bulunamadı.' + }, + home: { + needTologin: 'İndirmeden önce Deezer hesabına giriş yapmalısın.', + openSettings: 'Ayarları Aç', + sections: { + popularPlaylists: 'Popüler Oynatma Listeleri', + popularAlbums: 'En çok dinlenen albümler' + } + }, + linkAnalyzer: { + info: 'İndirmeye çalıştığın link hakkında daha fazla bilgi için burayı kullanabilirsin.', + useful: 'Mesela, ülkende dinlenebilir olmayan parçaların nerelerde var olduğunu bulmak için kullanabilirsin.', + linkNotSupported: 'Bu link şimdilik desteklenmemektedir.', + linkNotSupportedYet: 'Bu link şimdilik desteklenmiyor gibi duruyor, başkasını analiz etmeyi dene.', + table: { + id: 'ID', + isrc: 'ISRC', + upc: 'UPC', + duration: 'Süre', + diskNumber: 'Sıra numarası', + trackNumber: 'Parça numarası', + releaseDate: 'Yayınlanma tarihi', + bpm: 'BPM', + label: 'Etiketi', + recordType: 'Kayıt Şekli', + genres: 'Türü', + tracklist: 'Parça listesi' + } + }, + search: { + startSearching: 'Aramayı Başlat!', + description: + 'Bir parçayı, tüm albümü, bir sanatçıyı, bir oynatma listesini... kısaca her şeyi aratabilirsin! Ayrıca Deezer Linki de yapıştırabilirsin!', + fans: '{n} Hayranlar', + noResults: 'Sonuç Bulunamadı', + noResultsTrack: 'Parça bulunamadı', + noResultsAlbum: 'Albüm bulunamadı', + noResultsArtist: 'Sanatçı bulunamadı', + noResultsPlaylist: 'Oynatma Listesi bulunamadı' + }, + searchbar: 'İstediğin bir şeyi arat (ya da bir link yapıştır.)', + downloads: 'İndirilenler', + toasts: { + addedToQueue: '{item} kuyruğa eklendi', + alreadyInQueue: '{item} çoktan kuyrukta!', + finishDownload: '{item} indirmesi tamamlandı.', + allDownloaded: 'Tüm indirmeler tamamlandı!', + refreshFavs: 'Yenileme tamamlandı.!', + loggingIn: 'Giriş yapılıyor', + loggedIn: 'Giriş yapıldı', + alreadyLogged: 'Çoktan giriş yapıldı', + loginFailed: 'Giriş yapılamadı', + loggedOut: 'Oturum kapatıldı.', + cancellingCurrentItem: 'Geçerli öğe iptal ediliyor.', + currentItemCancelled: 'Geçerli öğe iptal edildi.', + startAddingArtist: '{artist} albüm kuyruğa ekleniyor', + finishAddingArtist: '{artist} albüm kuyruğa eklendi.', + startConvertingSpotifyPlaylist: 'Spotify parçaları deezer parçalarına dönüştürülüyor.', + finishConvertingSpotifyPlaylist: 'Spotify oynatma listesi dönüştürüldü.' + }, + settings: { + title: 'Ayarlar', + languages: 'Diller', + login: { + title: 'Giriş', + loggedIn: '{username} olarak giriş yaptın.', + arl: { + question: `Kendi ARL'mi nasıl alırım?`, + update: 'ARL güncelle.' + }, + logout: 'Çıkış' + }, + appearance: { + title: 'Görünüm', + slimDownloadTab: 'İnce indirme sekmesi' + }, + downloadPath: { + title: 'İndirilen dizin' + }, + templates: { + title: 'Şablonlar', + tracknameTemplate: 'Parça ismi şablonu', + albumTracknameTemplate: 'Albüm parçası şablonu', + playlistTracknameTemplate: 'Oynatma listesi parça şablonu' + }, + folders: { + title: 'Dosyalar', + createPlaylistFolder: 'Oynatma listesi için dosya oluştur', + playlistNameTemplate: 'Oynatma listesi dosyası şablonu', + createArtistFolder: 'Sanatçı için dosya oluştur', + artistNameTemplate: 'Sanatçı dosyası şablonu', + createAlbumFolder: 'Albüm için dosya oluştur', + albumNameTemplate: 'Albüm dosyası şablonu', + createCDFolder: 'CDler için dosya oluştur', + createStructurePlaylist: 'Oynatma listeleri için dosya kökü oluştur', + createSingleFolder: 'Singlelar için dosya kökü oluştur' + }, + trackTitles: { + title: 'Parça başlıkları', + padTracks: 'İz Numaraları', + paddingSize: 'İz Numaralarını değiştir', + illegalCharacterReplacer: 'Illegal Karakter Düzenleyici' + }, + downloads: { + title: 'İndirilenler', + queueConcurrency: 'Devam eden indirmeler', + maxBitrate: { + title: 'Tercih edilmiş Bitrateler (kaliteler)', + 9: 'FLAC 1411kbps', + 3: 'MP3 320kbps', + 1: 'MP3 128kbps' + }, + overwriteFile: { + title: 'Dosyaların üstüne yazmalı mıyım?', + y: 'Evet, üstüne yaz', + n: 'Hayır, üstüne yazma', + t: 'Sadece izleri üstüne yaz' + }, + fallbackBitrate: 'Bitrate düşürme', + fallbackSearch: 'Düşürme ara', + logErrors: 'Hatalar için günlük tut', + logSearched: 'Aranmış parçalar için günlük tut', + createM3U8File: 'Oynatma sıra listesi oluştur', + syncedLyrics: '.lrc dosyaları oluştur (Senkronize şarkı sözleri)', + playlistFilenameTemplate: 'Oynatma listesi şablonu', + saveDownloadQueue: 'Uygulamayı kapatırken indirme kuyruğunu kaydet' + }, + covers: { + title: 'Albüm kapakları', + saveArtwork: 'Kapakları kaydet', + coverImageTemplate: 'Kapak ismi şablonu', + saveArtworkArtist: 'Sanatçı fotoğrafını kaydet', + artistImageTemplate: 'Şarkıcı fotoğraf şablonu', + localArtworkSize: 'Yerel fotoğraf boyutu', + embeddedArtworkSize: 'Gömülü fotoğraf boyutu', + localArtworkFormat: { + title: 'Yerel fotoğrafın hangi formatta olmasını istersin?', + jpg: 'Jpeg dosyası', + png: 'Png dosyası', + both: 'Her ikisi' + }, + jpegImageQuality: 'JPEG görüntü kalitesi' + }, + tags: { + head: 'Hangi izler kayıt edilsin?', + title: 'Başlık', + artist: 'Sanatçı', + album: 'Albüm', + cover: 'Kapak', + trackNumber: 'Parça Numarası', + trackTotal: 'Tüm Parça', + discNumber: 'Plak Sayısı', + discTotal: 'Tüm Plak', + albumArtist: 'Sanatçı Albümü', + genre: 'Tür', + year: 'Yıl', + date: 'Tarih', + explicit: 'Cinsel içerikli şarkı sözleri', + isrc: 'ISRC', + length: 'Parça Uzunluğu', + barcode: 'Albüm Barkodu (UPC)', + bpm: 'BPM', + replayGain: 'Ses Yüksekliği Normalleştirici', + label: 'Albüm Etiketi', + lyrics: 'Senkronize edilmemiş şarkı sözleri', + copyright: 'Telif hakkı', + composer: 'Besteleyen', + involvedPeople: 'Alakalı Kişiler' + }, + other: { + title: 'Diğer', + savePlaylistAsCompilation: 'Oynatma listelerini derleme olarak kaydet', + useNullSeparator: 'Boşluk ayırıcı kullan', + saveID3v1: 'ID3v1 dosyasını da kaydet', + multiArtistSeparator: { + title: 'Sanatçılarınızı nasıl ayırmak istersiniz?', + nothing: 'Sadece ana sanatçıyı kaydet', + default: 'Genel prosedür uygulansın', + andFeat: 'Kullanılanlar & ve Feat.', + using: 'Kullanılan "{separator}"' + }, + singleAlbumArtist: 'Sadece ana albüm sanatçısını kaydet', + albumVariousArtists: '"Çeşitli sanatçılar"ı sanatçı albümlerinde tut', + removeAlbumVersion: '"Albüm Sürümü"nü parça başlığından çıkart', + removeDuplicateArtists: 'Sanatçı topluluğunu çıkart', + dateFormat: { + title: 'FLAC dosyalar için zaman formatı', + year: 'YYYY', + month: 'AA', + day: 'GG' + }, + featuredToTitle: { + title: 'Öne çıkan sanatçıları ne yapmalıyım?', + 0: 'Elleme', + 1: 'Başlıktan çıkart', + 3: 'Başlıktan ve albüm başlığından çıkart', + 2: 'Başlığa taşı' + }, + titleCasing: 'Albüm harfi', + artistCasing: 'Sanatçı harfi', + casing: { + nothing: 'Değiştirmeden bırak', + lower: 'küçük harf', + upper: 'BÜYÜK HARF', + start: 'Kelimenin başı ile başla', + sentence: 'Cümle gibi yap' + }, + previewVolume: 'Ses önizlemesi', + executeCommand: { + title: 'İndirdikten sonra komut uygula', + description: 'Bir şey yapmamak için boş bırak' + } + }, + spotify: { + title: 'Spotify Özelliği', + clientID: 'Spotify clientID', + clientSecret: 'Spotify Client Secret', + username: 'Spotify Kullanıcı Adı' + }, + reset: 'Varsayılana sıfırla', + save: 'Kaydet', + toasts: { + init: 'Ayarlar yüklendi!', + update: 'Ayarlar güncellendi!', + ARLcopied: 'ARL panoya kopyalandı!' + } + }, + sidebar: { + home: 'Ana sayfa', + search: 'Ara', + charts: 'Grafikler', + favorites: 'Favoriler', + linkAnalyzer: 'Link Analizörü', + settings: 'Ayarlar', + about: 'Hakkında' + }, + tracklist: { + downloadSelection: 'İndirme bölümü' + } +} + +export default tr diff --git a/webui/src/lang/vi.mjs b/webui/src/lang/vi.mjs new file mode 100644 index 0000000..2e99d27 --- /dev/null +++ b/webui/src/lang/vi.mjs @@ -0,0 +1,357 @@ +const vi = { + globals: { + welcome: 'Chào mừng đến với deemix', + back: 'trở lại', + loading: 'đang tải', + download: 'Tải xuống {thing}', + by: 'bởi {artist}', + in: 'trong {album}', + download_hint: 'Tải xuống', + play_hint: 'Phát', + toggle_download_tab_hint: 'Mở rộng/Giấu', + clean_queue_hint: 'Xóa những file đã tải xong', + cancel_queue_hint: 'Hủy tất cả', + listTabs: { + empty: '', + all: 'tất cả', + top_result: 'kết quả hàng đầu', + album: 'album | album', + artist: 'Nghệ sĩ | Nghệ sĩ', + single: 'đơn | đơn', + title: 'tiêu đề | tiêu đề', + track: 'Bài hát | Bài hát', + trackN: '0 Bài hát | {n} Bài hát | {n} Bài hát', + releaseN: '0 sản phẩm | {n} sản phẩm | {n} sản phẩm', + playlist: 'playlist | playlist', + compile: 'tổng hợp | tổng hợp', + ep: 'ep | ep', + spotifyPlaylist: 'playlist của spotify | playlist của spotify', + releaseDate: 'ngày phát hành', + error: 'lỗi' + } + }, + about: { + titles: { + usefulLinks: 'Link hữu dụng', + bugReports: 'Báo lỗi', + contributing: 'Đóng góp', + donations: 'Quyên góp', + license: 'Bằng phép' + }, + subtitles: { + bugReports: 'Bạn thấy có gì đó không hoạt động trong deemix? Xin hãy báo với chúng tôi!', + contributing: 'Bạn muốn đóng góp cho dự án này? Bạn có thể làm điều đó với nhiều cách khác nhau!', + donations: 'Bạn muốn ủng hộ kinh phí? Bạn có thể quyên góp tại đây!' + }, + usesLibrary: + 'Ứng dụng này sử dụng thư viện deemix, bạn có thể dùng nó để tạo một UI riêng cho deemix.', + thanks: `Cảm ơn rtonno, uhwotlollilol đã giúp tôi với dự án này và BasCurtiz với việc thiết kế biểu tượng.`, + upToDate: { + text: `Cập nhật app bằng cách theo dõi {newsChannel} trên Telegram.`, + newsChannel: 'kênh tin tức' + }, + officialWebsite: 'Website chính thức', + officialRepo: 'Repo thư viện chính thức', + officialWebuiRepo: 'Repo WebUI chính thức', + officialSubreddit: 'Subreddit chính thức', + newsChannel: 'Kênh tin tức', + questions: { + text: `Nếu bạn có câu hỏi hoặc vấn đề về ứng dụng này, xin hãy tìm giải pháp trên {subreddit} trước. Sau đó, nếu bạn không tìm được gì thì bạn có thể tạo một bài đăng về vấn đề của bạn trên subreddit dó.`, + subreddit: 'subreddit' + }, + beforeReporting: `Trước khi báo lỗi hãy đảm bảo bạn đang sử dụng phiên bản mới nhất của ứng dụng và lỗi bạn đang gặp không phải là do bạn.`, + beSure: `Hãy đảm bảo là lỗi này vẫn có thể xảy ra trên các thiết bị khác và XIN ĐỪNG báo lỗi đã được báo rồi.`, + duplicateReports: 'Những bản báo lỗi trùng nhau sẽ bị đóng, xin bạn hãy để ý điều này.', + dontOpenIssues: `XIN ĐỪNG mở vấn đề để hỏi, bạn có thể dùng subreddit trên cho việc đó.`, + newUI: { + text: `Nếu bạn thành thạo với python bạn có thể tạo một UI mới bằng cách sử dụng thư viện gốc, hoặc sửa lỗi trong thư viện đó với một pull request trên {repo}.`, + repo: 'repo này' + }, + acceptFeatures: `Tôi có chấp nhận yêu cầu về tính năng mới nhưng không quá phức tạp bởi vì chúng có thể được triển khai trực tiếp vào ứng dụng thay vì vào thư viện.`, + otherLanguages: `Nếu bạn thành thạo với một ngôn ngữ khác, bạn có thể port deemix sang ngôn ngữ đó!`, + understandingCode: `Bạn muốn hiểu code của deemix? Xin hãy liên lạc RemixDev trên Telegram hoặc Reddit.`, + contributeWebUI: { + text: `Nếu bạn biết Vue.js (JavaScript), HTML hoặc CSS, bạn có thể góp phần phát triển {webui}.`, + webui: 'WebUI' + }, + itsFree: `Bạn nên nhớ rằng đây là một dự án phi lợi nhuậnbạn nên ủng hộ những Nghệ sĩ yêu thích của bạn trước khi ủng hộ nhà phát triển.`, + notObligated: `Đừng nghĩ rằng bạn phải đóng góp tiền, tôi vẫn sẽ rất biết ơn bạn!`, + lincensedUnder: { + text: `Dự án này được cấp phép bởi {gpl3}.`, + gpl3: 'GNU General Public License 3.0' + } + }, + charts: { + title: 'Bảng xếp hạng', + changeCountry: 'Thay đổi quốc gia', + download: 'Tải xuống bảng xếp hạng này' + }, + errors: { + title: 'Lỗi {name}', + ids: { + invalidURL: 'Không nhận diện được URL', + unsupportedURL: 'URL này chưa được hỗ trợ', + ISRCnotOnDeezer: 'ISRC của bài hát này hiện không có trên Deezer', + notYourPrivatePlaylist: 'Bạn không thể tải xuống playlist riêng của người khác.', + spotifyDisabled: 'Chức năng Spotify chưa được thiết lập đúng cách.', + trackNotOnDeezer: 'Bài hát không có trên Deezer!', + albumNotOnDeezer: 'Album không có trên Deezer!', + notOnDeezer: 'Bài hát chưa có trên Deezer!', + notEncoded: 'Bài hát chưa được encode!', + notEncodedNoAlternative: 'Bài hát chưa được encode và không có bản thay thế nào khác!', + wrongBitrate: 'Bài hát này không có ở bitrate bạn muốn.', + wrongBitrateNoAlternative: 'Bài hát này không có ở bitrate bạn muốn và không có bản thay thế nào khác!', + no360RA: 'Bài hát này không có ở dạng Reality Audio 360.', + notAvailable: 'Bài hát này không có trên server của Deezer!', + notAvailableNoAlternative: 'Bài hát này không có trên server của Deezer và không có bản thay thế nào khác!' + } + }, + favorites: { + title: 'Yêu thích', + noPlaylists: 'Không tìm được Playlist', + noAlbums: 'Không tìm được Album Yêu thích', + noArtists: 'Không tìm được Nghệ sĩ Yêu thích', + noTracks: 'Không tìm được Bài hát Yêu thích' + }, + home: { + needTologin: 'Bạn cần phải đăng nhập vào tài khoản Deezer trước khi bắt đầu tải xuống.', + openSettings: 'Mở Cài đặt', + sections: { + popularPlaylists: 'Playlist Nổi tiếng', + popularAlbums: 'Album được stream nhiều nhất' + } + }, + linkAnalyzer: { + info: 'Bạn có thể sử dụng chức năng này để kiếm thêm thông tin về đường link mà bạn muốn tải xuống.', + useful: + 'Chức năng này rất hữu dụng nếu bạn muốn tải các bài hát hiện không có sẵn ở quốc gia của bạn và muốn biết các quốc gia được hỗ trợ.', + linkNotSupported: 'Đường link này chưa được hỗ trợ', + linkNotSupportedYet: 'Đường link này chưa được hỗ trợ, xin hãy thử lại với một đường link khác.', + table: { + id: 'ID', + isrc: 'ISRC', + upc: 'UPC', + duration: 'Thời lượng', + diskNumber: 'Số đĩa', + trackNumber: 'Số bài hát', + releaseDate: 'Ngày phát hành', + bpm: 'BPM', + label: 'Hãng', + recordType: 'Loại Thu âm', + genres: 'Thể loại', + tracklist: 'Danh sách các bài hát' + } + }, + search: { + startSearching: 'Bắt đầu tìm kiếm!', + description: 'Bạn có thể tìm một bài hát, album, nghệ sĩ, playlist, v.v...! Bạn cũng có thể dùng link của Deezer', + fans: '{n} người hâm mộ', + noResults: 'Không có kết quả', + noResultsTrack: 'Không tìm được bài hát nào', + noResultsAlbum: 'Không tìm được album nào', + noResultsArtist: 'Không tìm được nghệ sĩ nào', + noResultsPlaylist: 'Không tìm được playlist nào' + }, + searchbar: 'Tìm những gì bạn muốn (bạn cũng có thể sữ dụng một đường link)', + downloads: 'Tải xuống', + toasts: { + addedToQueue: '{item} đã được đưa vào hàng chờ', + alreadyInQueue: '{item} đã đang trong hàng chờ!', + finishDownload: '{item} đã tải xong.', + allDownloaded: 'Tất cả các bài hát đã được tải xuống!', + refreshFavs: 'Tải lại hoàn tất!', + loggingIn: 'Đang đăng nhập', + loggedIn: 'Đăng nhập thành công', + alreadyLogged: 'Đã đăng nhập', + loginFailed: 'Không thể đăng nhập', + loggedOut: 'Đăng xuất', + cancellingCurrentItem: 'Đang hủy file hiện tại.', + currentItemCancelled: 'File hiện tại đã bị hủy.', + startAddingArtist: 'Đang đưa {artist} album vào hàng chờ', + finishAddingArtist: 'Đã đưa {artist} album vào hàng chờ', + startConvertingSpotifyPlaylist: 'Đang chuyển đổi các bài hát từ Spotify sang Deezer', + finishConvertingSpotifyPlaylist: 'Playlist của Spotify đã được chuyển đổi', + loginNeededToDownload: 'Bạn cần phải đang nhập để tải nhạc!' + }, + settings: { + title: 'Cài đặt', + languages: 'Ngôn ngữ', + login: { + title: 'Đăng nhập', + loggedIn: 'Bạn đã đăng nhập với tên {username}', + arl: { + question: 'Làm cách nào để có ARL của tôi?', + update: 'Cập nhật ARL' + }, + logout: 'Đăng xuất' + }, + appearance: { + title: 'Giao diện', + slimDownloadTab: 'Thanh tải xuống nhỏ' + }, + downloadPath: { + title: 'Nơi tải xuống' + }, + templates: { + title: 'Bản mẫu', + tracknameTemplate: 'Bài hát mẫu', + albumTracknameTemplate: 'Bài hát trong album mẫu', + playlistTracknameTemplate: 'Bài hát trong playlist mẫu' + }, + folders: { + title: 'Thư mục', + createPlaylistFolder: 'Tạo thư mục cho playlist', + playlistNameTemplate: 'Thư mục playlist mẫu', + createArtistFolder: 'Tạo thư mục cho nghệ sĩ', + artistNameTemplate: 'Thư mục Nghệ sĩ mẫu', + createAlbumFolder: 'Tạo thư mục cho album', + albumNameTemplate: 'Thư mục cho album mẫu', + createCDFolder: 'Tạo thư mục cho đĩa CD', + createStructurePlaylist: 'Tạo thư mục có kết cấu cho playlist', + createSingleFolder: 'Tạo thư mục có kết cấu cho đĩa đơn' + }, + trackTitles: { + title: 'Tên bài hát', + padTracks: 'Đệm tên bài hát', + paddingSize: 'Ghì đè kích cỡ phần đệm', + illegalCharacterReplacer: 'Thay các kí tự không hợp lệ với' + }, + downloads: { + title: 'Tải xuống', + queueConcurrency: 'Số lượng tải xuống cùng lúc', + maxBitrate: { + title: 'Bitrate ưa thích', + 9: 'FLAC 1411kbps', + 3: 'MP3 320kbps', + 1: 'MP3 128kbps' + }, + overwriteFile: { + title: 'Tôi có nên ghi đè file này không?', + y: 'Có, hãy ghi đè file này', + n: 'Không, đừng ghi đè file này', + t: 'Chỉ ghi đè các tag' + }, + fallbackBitrate: 'Bitrate dự phòng', + fallbackSearch: 'Search dự phòng', + logErrors: 'Tạo file log khi có lỗi', + logSearched: 'Tạo file log khi bạn tìm Bài hát', + createM3U8File: 'Tạo file playlist', + syncedLyrics: 'Tạo file .lrc (Lời Bài hát)', + playlistFilenameTemplate: 'Tên playlist mẫu', + saveDownloadQueue: 'Lưu hàng chờ download khi đóng ứng dụng' + }, + covers: { + title: 'Bìa album', + saveArtwork: 'Lưu bìa', + coverImageTemplate: 'Tên bìa mẫu', + saveArtworkArtist: 'Lưu hình Nghệ sĩ', + artistImageTemplate: 'Hình nghệ sĩ mẫu', + localArtworkSize: 'Kích cỡ file bìa', + embeddedArtworkSize: 'Kích cỡ bìa trong file bài hát', + localArtworkFormat: { + title: 'Bạn muốn file bìa ở định dạng nào?', + jpg: 'jpg', + png: 'png', + both: 'Cả jpg và png' + }, + jpegImageQuality: 'Chất lượng file JPEG' + }, + tags: { + head: 'Những tag sẽ được lưu', + title: 'Tiêu đề', + artist: 'Nghệ sĩ', + album: 'Album', + cover: 'Bìa', + trackNumber: 'Số bài hát', + trackTotal: 'Tổng số bài hát', + discNumber: 'Số đĩa', + discTotal: 'Tổng số đĩa', + albumArtist: 'Nghệ sĩ của album', + genre: 'Thể loại', + year: 'Năm', + date: 'Ngày', + explicit: 'Lời explicit', + isrc: 'ISRC', + length: 'Thời lượng', + barcode: 'Mã vạch của album (UPC)', + bpm: 'BPM', + replayGain: 'ReplayGain', + label: 'Nhãn hiệu album', + lyrics: 'Lời', + copyright: 'Bản quyền', + composer: 'Nhà soạn nhạc', + involvedPeople: 'Những người liên quan' + }, + other: { + title: 'Khác', + savePlaylistAsCompilation: 'Lưu playlist dưới dạng tuyển tập', + useNullSeparator: 'Dùng dải phân cách null', + saveID3v1: 'Lưu ID3v1', + multiArtistSeparator: { + title: 'Bạn muốn phân cách các nghệ sĩ như thế nào?', + nothing: 'Chỉ lưu nghệ sĩ chính', + default: 'Dùng quy cách tiêu chuẩn', + andFeat: 'Dùng & và feat.', + using: 'Dùng "{separator}"' + }, + singleAlbumArtist: 'Chỉ lưu Nghệ sĩ Album chính', + albumVariousArtists: 'Giữ nguyên "Nhiều Nghệ sĩ" trong Nghệ sĩ Album', + removeAlbumVersion: 'Bỏ "Phiên bản Album" khỏi tên bài hát', + removeDuplicateArtists: 'Bỏ các tên nghệ sĩ phối hợp', + dateFormat: { + title: 'Định dạng ngày cho file FLAC ', + year: 'YYYY', + month: 'MM', + day: 'DD' + }, + featuredToTitle: { + title: 'Tôi nên làm gì với các nghệ sĩ đóng góp?', + 0: 'Không làm gì cả', + 1: 'Bỏ chúng khỏi tên bài hát', + 3: 'Bỏ chúng khỏi tên bài hát và tên album', + 2: 'Đưa chúng vào tên bài hát' + }, + titleCasing: 'Định dạng tên bài hát', + artistCasing: 'Định dạng tên nghệ sĩ', + casing: { + nothing: 'Không đổi', + lower: 'chữ thường', + upper: 'CHỮ HOA', + start: 'Viết Hoa Ở Chữ Cái Đầu Tiên Của Mỗi Từ', + sentence: 'Như một câu' + }, + previewVolume: 'Âm lượng nghe thử', + executeCommand: { + title: 'Thực hiện những lệnh này khi đã tải xuống xong', + description: 'Để trống nếu bạn không muốn thực hiện lệnh nào' + } + }, + spotify: { + title: 'Chức năng Spotify', + clientID: 'ClientID của Spotify', + clientSecret: 'Client Secret của Spotify', + username: 'Tên tài khoản của Spotify' + }, + reset: 'Quay trở lại cài đặt mặc định', + save: 'Lưu', + toasts: { + init: 'Cài đặt đã được thiết lập!', + update: 'Cài đặt cập nhật thành công!', + ARLcopied: 'ARL đã được sao chép vào clipboard' + } + }, + sidebar: { + home: 'trang chủ', + search: 'tìm kiếm', + charts: 'bảng xếp hạng', + favorites: 'yêu thích', + linkAnalyzer: 'phân tích link', + settings: 'cài đặt', + about: 'thông tin' + }, + tracklist: { + downloadSelection: 'Tải xuống những mục đã chọn' + } +} + +export default vi diff --git a/webui/src/lang/zh-tw.mjs b/webui/src/lang/zh-tw.mjs new file mode 100644 index 0000000..147f446 --- /dev/null +++ b/webui/src/lang/zh-tw.mjs @@ -0,0 +1,400 @@ +const zh_tw = { + globals: { + welcome: '歡迎使用 deemix', + back: '返回', + loading: '載入中', + download: '下載 {thing}', + by: '{artist}', + in: '於 {album}', + download_hint: '下載', + play_hint: '播放', + toggle_download_tab_hint: '展開/折疊', + clean_queue_hint: '清除完成', + cancel_queue_hint: '取消全部', + open_downloads_folder: '開啟下載資料夾', + cut: '剪下', + copy: '複製', + copyLink: '複製連結', + copyImageLink: '複製圖片連結', + copyDeezerLink: '複製 deezer 連結', + paste: '貼上', + listTabs: { + empty: '', + all: '所有', + top_result: '最佳結果', + album: '專輯|專輯', + artist: '藝人|藝人', + single: '單曲', + title: '標題|標題', + track: '歌曲|歌曲', + releaseN: '0 發行| {n} 發行| {n} 發行', + playlist: '播放清單|播放清單', + compile: '合輯|合輯', + ep: '迷你專輯 | 迷你專輯', + bundle: 'bundle | bundles', + more: '更多專輯', + featured: '出現於', + spotifyPlaylist: 'Spotify 播放清單 | Spotify 播放清單', + releaseDate: '發布日期', + error: '錯誤', + trackN: '0 首歌曲| {n} 首歌曲| {n} 首歌曲', + albumN: '0 個專輯 | {n} 個專輯 | {n} 個專輯', + artistN: '0 個藝人 | {n} 個藝人 | {n} 個藝人', + playlistN: '0 個播放清單 | {n} 個播放清單 | {n} 個播放清單' + } + }, + about: { + appStatus: { + online: '上線中', + offline: '離線中' + }, + updates: { + currentVersion: '目前版本', + currentWebuiVersion: '目前前端版本', + versionNotAvailable: 'N/A', + updateAvailable: `您尚未更新至最新版本:{version}`, + deemixVersion: 'deemix 函示庫版本' + }, + titles: { + usefulLinks: '實用連結', + bugReports: '錯誤報告', + contributing: '貢獻', + donations: '贊助', + license: '使用許可' + }, + subtitles: { + bugReports: '使用 deemix 時,遇到了什麼問題嗎?歡迎回報錯誤!', + contributing: '您想替這個專案提出貢獻嗎?您可以透過許多不同的方式來幫忙!', + donations: '您想要捐款嗎?可以贊助我們!' + }, + usesLibrary: '本程式基於 deemix 函示庫。您可以使用該函示庫來製作自己的前端。', + thanks: `感謝 rtonnouhwotlollilol 對於本專案的貢獻,另外也感謝 BasCurtiz 幫忙製作本專案的圖示`, + upToDate: { + text: `您可於 Telegram 上關注{newsChannel}以取得最新動態。`, + newsChannel: '最新消息頻道' + }, + officialWebsite: '官方網站', + officialRepo: '官方函示版本庫', + officialWebuiRepo: '官方 WebUI 版本庫', + officialSubreddit: '官方 Subreddit', + newsChannel: '最新消息頻道', + questions: { + text: `如果您對本程式有疑問或問題,請先在{subreddit}上搜尋解決方案。如果找不到任何解決方法,則可以在我們的 subreddit 上發布與您問題相關的文章。`, + subreddit: ' subreddit ' + }, + beforeReporting: `在報告錯誤之前,請確保您正在運行最新版本的程式,並且要報告的內容真的是一個錯誤,而不僅是您自己遇到的問題。`, + beSure: `請確保您所想回報的錯誤可在其他台裝置上再現的,並且請勿回報已知錯誤。`, + duplicateReports: '請注意,重複的錯誤報告將被移除。', + dontOpenIssues: `請勿透過本版本庫的 Issues 問問題,我們開 subreddit 是有原因的。`, + newUI: { + text: `如果您精通 Python,則可以嘗試使用我們的函示庫來建立新的 UI,或者透過{repo}提出錯誤相關的 PR。`, + repo: '我們的版本庫' + }, + acceptFeatures: `我也歡迎你提交新的功能-但前提是這個功能不能過於複雜-過於複雜的功能,應被新增至程式內而非函示庫內。`, + otherLanguages: `如果您精通其他程式語言,你也可以嘗試將 deemix 移植到其他程式語言中!`, + understandingCode: `你需要幫助了解本專案的程式碼嗎?只需在 Telegram 或 Reddit 上按一下 RemixDev。`, + contributeWebUI: { + text: `如果你熟悉 Vue.js(JavaScript)、HTML 或 CSS,你也可以參與 {webui} 前端的貢獻。`, + webui: 'WebUI' + }, + itsFree: `記得,這是一個免費的專案在支持開發人員之前,應該先支持你喜歡的歌手或藝人。`, + notObligated: `別認為你有義務捐款,無論如何我們都感謝您!`, + lincensedUnder: { + text: `本作品使用 {gpl3} 許可授權。`, + gpl3: 'GNU General Public License 3.0' + } + }, + charts: { + title: '排行榜', + changeCountry: '改變國家', + download: '下載排行榜' + }, + errors: { + title: '{name} 的錯誤', + ids: { + invalidURL: '無法識別網址', + unsupportedURL: '尚不支持此網址', + ISRCnotOnDeezer: '無法在 Deezer 上使用單曲 ISRC', + notYourPrivatePlaylist: '您無法下載他人的私人播放清單。', + spotifyDisabled: 'Spotify 功能未正確設定。', + trackNotOnDeezer: '在 Deezer 上找不到此歌曲!', + albumNotOnDeezer: '在 Deezer 上找不到此專輯!', + notOnDeezer: '無法在 Deezer 上載入此歌曲!', + notEncoded: '本歌曲尚未編碼!', + notEncodedNoAlternative: '本歌曲尚未編碼,且無法找到其他替代歌曲!', + wrongBitrate: '找不到符合所設位元率的歌曲。', + wrongBitrateNoAlternative: '找不到符合所設位元率的歌曲,且無法找到其他替代歌曲!', + no360RA: '本歌曲並不支援 Reality Audio 360。', + notAvailable: '無法在 Deezer 伺服器載入此歌曲!', + notAvailableNoAlternative: '無法在 Deezer 伺服器載入此歌曲,且無法找到其他替代歌曲!', + noSpaceLeft: '本裝置可用空間已用盡!', + albumDoesntExists: '本歌曲的專輯不存在,無法取得資訊' + } + }, + favorites: { + title: '收藏', + noPlaylists: '尚未收藏任何播放清單', + noAlbums: '尚未收藏任何專輯', + noArtists: '尚未收藏任何藝人', + noTracks: '尚未收藏任何歌曲' + }, + home: { + needTologin: '您需要先登入 Deezer 帳戶,然後才能開始下載。', + openSettings: '開啟設定', + sections: { + popularPlaylists: '熱門播放清單', + popularAlbums: '熱門專輯' + } + }, + linkAnalyzer: { + info: '您可以透過此工具取得您所想下載的連結的相關資訊。', + useful: '比如,當您所想下載的歌曲無法在您的國家播放,且您想知道哪些國家可以播放此歌曲時,您可使用此工具。', + linkNotSupported: '尚未支援此連結', + linkNotSupportedYet: '我們似乎尚未支援此連結,請改用其他連結。', + table: { + id: 'ID', + isrc: 'ISRC', + upc: 'UPC', + duration: '長度', + diskNumber: '光碟編號', + trackNumber: '歌曲編號', + releaseDate: '發布日期', + bpm: 'BPM', + label: '標籤', + recordType: '媒體類型', + genres: '類型', + tracklist: '歌曲清單' + } + }, + search: { + startSearching: '開始搜尋!', + description: '您可以搜索歌曲名稱、專輯、藝人、播放清單...等等。您也可以直接貼上 Deezer 網址。', + fans: '{n} 個粉絲', + noResults: '無搜尋結果', + noResultsTrack: '找不到歌曲', + noResultsAlbum: '找不到專輯', + noResultsArtist: '找不到藝人', + noResultsPlaylist: '找不到播放清單' + }, + searchbar: '搜尋任何關鍵字(或貼上連結)', + downloads: '下載', + toasts: { + restoringQueue: '正在恢復下載清單...', + queueRestored: '下載清單已恢復!', + addedToQueue: '已新增 {item} 到下載清單中', + addedMoreToQueue: '已新增 {n} 個項目到下載清單中', + alreadyInQueue: '{item} 已在下載清單中!', + finishDownload: '{item} 已完成下載。', + allDownloaded: '全部下載完成!', + refreshFavs: '刷新完成!', + loggingIn: '登入中...', + loggedIn: '登入', + alreadyLogged: '已登入', + loginFailed: '無法登入', + loggedOut: '登出', + cancellingCurrentItem: '取消當前項目。', + currentItemCancelled: '當前項目已取消。', + startAddingArtist: '已新增 {artist} 個專輯到下載清單中', + finishAddingArtist: '已新增 {artist} 個專輯到下載清單中', + startConvertingSpotifyPlaylist: '將 Spotify 歌曲轉換為 Deezer 歌曲中', + finishConvertingSpotifyPlaylist: '已轉換 Spotify 播放清單', + loginNeededToDownload: '您需要登入才能下載歌曲!', + deezerNotAvailable: 'Deezer 在您所在的國家/地區無法使用。請您使用 VPN。', + startGeneratingItems: '生成 {n} 個項目中...', + finishGeneratingItems: '已生成 {n} 個項目.' + }, + settings: { + title: '設定', + languages: '語言', + login: { + title: '登入', + loggedIn: '目前以 {username} 的身份登入', + arl: { + question: '如何取得自己的 ARL?', + update: '更新 ARL' + }, + logout: '登出', + login: '透過 deezer.com 登入' + }, + appearance: { + title: '外觀', + slimDownloadTab: '薄型下載分頁', + slimSidebar: '薄型測欄' + }, + downloadPath: { + title: '下載目錄' + }, + templates: { + title: '檔案名稱格式', + tracknameTemplate: '單曲名稱格式', + albumTracknameTemplate: '專輯單曲名稱格式', + playlistTracknameTemplate: '播放清單單曲名稱格式' + }, + folders: { + title: '資料夾', + createPlaylistFolder: '替播放清單建立資料夾', + playlistNameTemplate: '播放清單資料夾名稱格式', + createArtistFolder: '替藝人建立資料夾', + artistNameTemplate: '藝人資料夾名稱格式', + createAlbumFolder: '替專輯建立資料夾', + albumNameTemplate: '專輯資料夾名稱格式', + createCDFolder: '替 CD 建立資料夾', + createStructurePlaylist: '建立播放清單資料夾結構', + createSingleFolder: '建立單曲資料夾結構' + }, + trackTitles: { + title: '單曲名稱', + padTracks: '歌曲數目字串填充', + paddingSize: '覆蓋數目字串填充長度', + illegalCharacterReplacer: '替換非法字元' + }, + downloads: { + title: '下載', + queueConcurrency: '並行下載', + maxBitrate: { + title: '偏好位元率', + 9: 'FLAC 1411kbps', + 3: 'MP3 320kbps', + 1: 'MP3 128kbps' + }, + overwriteFile: { + title: '是否要覆蓋檔案?', + y: '是,覆蓋檔案', + n: '否,請勿覆蓋檔案', + t: '僅覆蓋標籤', + b: '否,保留兩個檔案並在重複的檔名中加入一個數字', + e: '否,不顧慮附檔名' + }, + fallbackBitrate: '當偏好位元率無法下載時,下載其他版本', + fallbackSearch: '當搜尋結果無法使用時,使用其他搜尋結果', + logErrors: '記錄錯誤至日誌', + logSearched: '記錄搜尋歌曲至日誌', + createM3U8File: '建立播放清單檔案', + syncedLyrics: '建立 .lrc 檔案(同步歌詞)', + playlistFilenameTemplate: '播放清單檔名格式', + saveDownloadQueue: '關閉應用程式時,保存下載清單' + }, + covers: { + title: '專輯封面', + saveArtwork: '保存封面', + coverImageTemplate: '封面檔名格式', + saveArtworkArtist: '保存藝人照片', + artistImageTemplate: '藝人照片檔名格式', + localArtworkSize: '本地圖片大小', + embeddedArtworkSize: '嵌入圖片大小', + localArtworkFormat: { + title: '您希望本地圖片採用哪種格式?', + jpg: 'JPEG', + png: 'PNG', + both: 'JPEG 及 PNG' + }, + jpegImageQuality: 'JPEG 影像品質', + embeddedArtworkPNG: '將嵌入式圖片存為 PNG', + embeddedPNGWarning: 'Deezer 官方並不支援 PNG,結果可能有誤', + imageSizeWarning: 'Deezer 官方並不使用高於 x1200 的圖片,您可能會遇到問題', + coverDescriptionUTF8: '使用 UTF8 保存封面敘述(修正 iTunes 專輯封面)' + }, + tags: { + head: '要保存哪些標籤', + title: '標題', + artist: '藝人', + album: '專輯', + cover: '專輯封面', + trackNumber: '單曲編號', + trackTotal: '總計歌曲', + discNumber: '光碟編號', + discTotal: '光碟總數', + albumArtist: '專輯藝人', + genre: '類型', + year: '年', + date: '日期', + explicit: '不良歌詞', + isrc: 'ISRC', + length: '單曲長度', + barcode: '專輯條碼(UPC)', + bpm: 'BPM', + replayGain: '重播增益(Replay Gain)', + label: '專輯標籤', + lyrics: '不同步的歌詞', + syncedLyrics: '同步歌詞', + copyright: '版權', + composer: '作曲家', + involvedPeople: '相關藝人', + source: '來源歌曲 ID' + }, + other: { + title: '其他', + savePlaylistAsCompilation: '將播放清單儲存為合輯', + useNullSeparator: '使用空分隔符', + saveID3v1: '保存 ID3v1 標籤', + multiArtistSeparator: { + title: '如何隔開作者名稱?', + nothing: '僅保留主作者', + default: '使用標準規格', + andFeat: '使用 & 及 feat.', + using: '使用 "{separator}"' + }, + singleAlbumArtist: '僅儲存專輯主作者名稱', + albumVariousArtists: '於專輯作者欄位中保留「多位藝人 (Various Artists)」字樣', + removeAlbumVersion: '於單曲名稱中移除「專輯版本 (Album Version)」字樣', + removeDuplicateArtists: '移除重複的作者名稱', + dateFormat: { + title: 'FLAC 檔案日期格式', + year: 'YYYY', + month: 'MM', + day: 'DD' + }, + featuredToTitle: { + title: '如何處理客串藝人名稱 (如 feat. 等字樣) ?', + 0: '什麼都不做', + 1: '從標題中刪除', + 3: '從標題和專輯標題中刪除', + 2: '將其移至標題' + }, + titleCasing: '歌曲名稱大小寫', + artistCasing: '藝人名稱大小寫', + casing: { + nothing: '保持不變', + lower: '小寫', + upper: '大寫', + start: '字詞開頭大寫', + sentence: '句子大寫' + }, + previewVolume: '預覽音量', + executeCommand: { + title: '下載後執行指令', + description: '留空則不執行' + } + }, + spotify: { + title: 'Spotify 功能', + clientID: 'Spotify 客戶端 ID', + clientSecret: 'Spotify 客戶端密碼', + username: 'Spotify 用戶名', + question: '如何啟用 Spotify 功能?' + }, + reset: '重設至預設', + resetMessage: '你確定要重設所有設定嗎?', + save: '儲存', + toasts: { + init: '已載入設定!', + update: '已更新設定!', + reset: '已重設設定!', + ARLcopied: '已複製 ARL 到剪貼簿中' + } + }, + sidebar: { + home: '首頁', + search: '搜尋', + charts: '排行榜', + favorites: '收藏', + linkAnalyzer: '連結分析', + settings: '設定', + about: '關於' + }, + tracklist: { + downloadSelection: '下載所選' + } +} + +export default zh_tw diff --git a/webui/src/plugins/composition-api.js b/webui/src/plugins/composition-api.js new file mode 100644 index 0000000..187f919 --- /dev/null +++ b/webui/src/plugins/composition-api.js @@ -0,0 +1,4 @@ +import Vue from 'vue' +import VueCompositionAPI from '@vue/composition-api' + +Vue.use(VueCompositionAPI) diff --git a/webui/src/plugins/i18n.js b/webui/src/plugins/i18n.js new file mode 100644 index 0000000..c0f482c --- /dev/null +++ b/webui/src/plugins/i18n.js @@ -0,0 +1,44 @@ +import Vue from 'vue' +import VueI18n from 'vue-i18n' + +import { locales } from '@/lang' + +Vue.use(VueI18n) + +const storedLocale = localStorage.getItem('locale') +const DEFAULT_LANG = storedLocale || 'en' + +document.querySelector('html').setAttribute('lang', DEFAULT_LANG) + +const i18n = new VueI18n({ + locale: DEFAULT_LANG, + fallbackLocale: 'en', + messages: locales, + pluralizationRules: { + /** + * @param {number} choice A choice index given by the input to $tc: `$tc('path.to.rule', choiceIndex)` + * @param {number} choicesLength An overall amount of available choices + * @returns A final choice index to select plural word by + */ + ru(choice /*, choicesLength */) { + const n = Math.abs(choice) % 100 + const n1 = n % 10 + + if (n > 10 && n < 20) { + return 2 + } + + if (n1 > 1 && n1 < 5) { + return 1 + } + + if (n1 === 1) { + return 0 + } + + return 2 + } + } +}) + +export default i18n diff --git a/webui/src/router.js b/webui/src/router.js new file mode 100644 index 0000000..8e9ec5a --- /dev/null +++ b/webui/src/router.js @@ -0,0 +1,178 @@ +import Vue from 'vue' +import VueRouter from 'vue-router' + +// Pages +import About from '@components/pages/About.vue' +import InfoArl from '@components/pages/InfoArl.vue' +import InfoSpotifyFeatures from '@components/pages/InfoSpotifyFeatures.vue' +import Artist from '@components/pages/Artist.vue' +import Charts from '@components/pages/Charts.vue' +import Errors from '@components/pages/Errors.vue' +import Favorites from '@components/pages/Favorites.vue' +import Home from '@components/pages/Home.vue' +import LinkAnalyzer from '@components/pages/LinkAnalyzer.vue' +import Search from '@components/pages/Search.vue' +import Settings from '@components/pages/Settings.vue' +import Tracklist from '@components/pages/Tracklist.vue' + +import { fetchData } from '@/utils/api' +import EventBus from '@/utils/EventBus' + +Vue.use(VueRouter) + +const routes = [ + { + path: '/', + name: 'Home', + component: Home, + meta: { + notKeepAlive: true + } + }, + { + path: '/tracklist/:type/:id', + name: 'Tracklist', + component: Tracklist + }, + { + path: '/artist/:id', + name: 'Artist', + component: Artist, + meta: { + notKeepAlive: true + } + }, + { + path: '/album/:id', + name: 'Album', + component: Tracklist + }, + { + path: '/playlist/:id', + name: 'Playlist', + component: Tracklist + }, + { + path: '/spotify-playlist/:id', + name: 'Spotify Playlist', + component: Tracklist + }, + { + path: '/charts', + name: 'Charts', + component: Charts, + meta: { + notKeepAlive: true + } + }, + { + path: '/favorites', + name: 'Favorites', + component: Favorites, + meta: { + notKeepAlive: true + } + }, + { + path: '/errors', + name: 'Errors', + component: Errors + }, + { + path: '/link-analyzer', + name: 'Link Analyzer', + component: LinkAnalyzer + }, + { + path: '/about', + name: 'About', + component: About + }, + { + path: '/info-arl', + name: 'ARL', + component: InfoArl + }, + { + path: '/info-spotify', + name: 'Spotify Features', + component: InfoSpotifyFeatures + }, + { + path: '/settings', + name: 'Settings', + component: Settings + }, + { + path: '/search', + name: 'Search', + component: Search, + meta: { + notKeepAlive: true + } + }, + // 404 client side + { + path: '*', + component: Home + } +] + +const router = new VueRouter({ + mode: 'history', + base: location.base, + routes, + scrollBehavior() { + return { x: 0, y: 0 } + } +}) + +router.beforeEach((to, _, next) => { + switch (to.name) { + case 'Tracklist': { + // const getTracklistParams = { + // type: to.params.type, + // id: to.params.id + // } + console.warn('This should never happen.') + break + } + case 'Album': { + const getTracklistParams = { + type: 'album', + id: to.params.id + } + fetchData('getTracklist', getTracklistParams).then(albumData => { + EventBus.$emit('showAlbum', albumData) + }) + break + } + case 'Playlist': { + const getTracklistParams = { + type: 'playlist', + id: to.params.id + } + fetchData('getTracklist', getTracklistParams).then(playlistData => { + EventBus.$emit('showPlaylist', playlistData) + }) + break + } + case 'Spotify Playlist': { + const getTracklistParams = { + type: 'spotifyplaylist', + id: to.params.id + } + fetchData('getTracklist', getTracklistParams).then(spotifyPlaylistData => { + EventBus.$emit('showSpotifyPlaylist', spotifyPlaylistData) + }) + break + } + + default: + break + } + + next() +}) + +export default router diff --git a/webui/src/store/index.js b/webui/src/store/index.js new file mode 100644 index 0000000..0725a61 --- /dev/null +++ b/webui/src/store/index.js @@ -0,0 +1,17 @@ +import Vuex, { Store } from 'vuex' +import Vue from 'vue' + +import appInfo from '@/store/modules/appInfo' +import login from '@/store/modules/login' +import errors from '@/store/modules/errors' + +Vue.use(Vuex) + +export default new Store({ + modules: { + appInfo, + login, + errors + }, + strict: process.env.NODE_ENV !== 'production' +}) diff --git a/webui/src/store/modules/appInfo.js b/webui/src/store/modules/appInfo.js new file mode 100644 index 0000000..292e1ff --- /dev/null +++ b/webui/src/store/modules/appInfo.js @@ -0,0 +1,199 @@ +/** + * @typedef {object} AppInfo + * @property {string} currentCommit + * @property {string} latestCommit + * @property {boolean} updateAvailable + * @property {string} deemixVersion + * @property {number} previewVolume + * @property {boolean} hasSlimDownloads + * @property {boolean} hasSlimSidebar + */ + +import { + getInitialPreviewVolume, + checkInitialSlimDownloads, + checkInitialSlimSidebar, + checkInitialShowBitrateTags, + checkInitialShowSearchButton +} from '@/data/settings' + +/** + * @returns {AppInfo} + */ +const state = () => ({ + currentCommit: null, + latestCommit: null, + updateAvailable: false, + deemixVersion: null, + previewVolume: getInitialPreviewVolume(), + hasSlimDownloads: checkInitialSlimDownloads(), + hasSlimSidebar: checkInitialSlimSidebar(), + showBitrateTags: checkInitialShowBitrateTags(), + showSearchButton: checkInitialShowSearchButton() +}) + +const actions = { + /** + * @param {any} action + * @param {AppInfo} payload + */ + setAppInfo({ commit }, payload) { + commit('SET_CURRENT_COMMIT', payload.currentCommit) + commit('SET_DEEMIX_VERSION', payload.deemixVersion) + }, + setUpdateInfo({ commit }, payload) { + commit('SET_LATEST_COMMIT', payload.latestCommit) + commit('SET_UPDATE_AVAILABLE', payload.updateAvailable) + }, + /** + * @param {any} action + * @param {AppInfo['previewVolume']} payload + */ + setPreviewVolume({ commit }, payload) { + commit('SET_PREVIEW_VOLUME', payload) + localStorage.setItem('previewVolume', payload.toString()) + }, + /** + * @param {any} action + * @param {AppInfo['hasSlimDownloads']} payload + */ + setSlimDownloads({ commit }, payload) { + commit('SET_SLIM_DOWNLOADS', payload) + localStorage.setItem('slimDownloads', payload.toString()) + }, + /** + * @param {any} action + * @param {AppInfo['hasSlimSidebar']} payload + */ + setSlimSidebar({ commit }, payload) { + commit('SET_SLIM_SIDEBAR', payload) + localStorage.setItem('slimSidebar', payload.toString()) + + // Moves all toast messages when the option changes + Array.from(document.getElementsByClassName('toastify')).forEach(toast => { + toast.style.transform = `translate(${payload ? '3rem' : '14rem'}, 0)` + }) + }, + /** + * @param {any} action + * @param {AppInfo['showBitrateTags']} payload + */ + setShowBitrateTags({ commit }, payload) { + commit('SET_SHOW_BITRATE_TAGS', payload) + localStorage.setItem('showBitrateTags', payload.toString()) + }, + /** + * @param {any} action + * @param {AppInfo['showBitrateTags']} payload + */ + setShowSearchButton({ commit }, payload) { + commit('SET_SHOW_SEARCH_BUTTON', payload) + localStorage.setItem('showSearchButton', payload.toString()) + } +} + +const getters = { + /** + * @param {AppInfo} state + * @returns {AppInfo} + */ + getAppInfo: state => state, + /** + * @param {AppInfo} state + * @returns {AppInfo['previewVolume']} + */ + getPreviewVolume: state => state.previewVolume, + /** + * @param {AppInfo} state + * @returns {AppInfo['hasSlimDownloads']} + */ + getSlimDownloads: state => state.hasSlimDownloads, + /** + * @param {AppInfo} state + * @returns {AppInfo['hasSlimSidebar']} + */ + getSlimSidebar: state => state.hasSlimSidebar, + /** + * @param {AppInfo} state + * @returns {AppInfo['showBitrateTags']} + */ + getShowBitrateTags: state => state.showBitrateTags, + /** + * @param {AppInfo} state + * @returns {AppInfo['showSearchButton']} + */ + getShowSearchButton: state => state.showSearchButton +} + +const mutations = { + /** + * @param {AppInfo} state + * @param {AppInfo['currentCommit']} payload + */ + SET_CURRENT_COMMIT(state, payload) { + state.currentCommit = payload + }, + /** + * @param {AppInfo} state + * @param {AppInfo['latestCommit']} payload + */ + SET_LATEST_COMMIT(state, payload) { + state.latestCommit = payload + }, + /** + * @param {AppInfo} state + * @param {AppInfo['updateAvailable']} payload + */ + SET_UPDATE_AVAILABLE(state, payload) { + state.updateAvailable = payload + }, + /** + * @param {AppInfo} state + * @param {AppInfo['deemixVersion']} payload + */ + SET_DEEMIX_VERSION(state, payload) { + state.deemixVersion = payload + }, + /** + * @param {AppInfo} state + * @param {AppInfo['previewVolume']} payload + */ + SET_PREVIEW_VOLUME(state, payload) { + state.previewVolume = payload + }, + /** + * @param {AppInfo} state + * @param {AppInfo['hasSlimDownloads']} payload + */ + SET_SLIM_DOWNLOADS(state, payload) { + state.hasSlimDownloads = payload + }, + /** + * @param {AppInfo} state + * @param {AppInfo['hasSlimSidebar']} payload + */ + SET_SLIM_SIDEBAR(state, payload) { + state.hasSlimSidebar = payload + }, + /** + * @param {AppInfo} state + * @param {AppInfo['showBitrateTags']} payload + */ + SET_SHOW_BITRATE_TAGS(state, payload) { + state.showBitrateTags = payload + }, + /** + * @param {AppInfo} state + * @param {AppInfo['showSearchButton']} payload + */ + SET_SHOW_SEARCH_BUTTON(state, payload) { + state.showSearchButton = payload + } +} + +export default { + state, + getters, + actions, + mutations +} diff --git a/webui/src/store/modules/errors.js b/webui/src/store/modules/errors.js new file mode 100644 index 0000000..f46f3d5 --- /dev/null +++ b/webui/src/store/modules/errors.js @@ -0,0 +1,44 @@ +const state = () => ({ + artist: '', + bitrate: '', + cover: '', + downloaded: 0, + errors: [], + failed: 0, + id: '', + progress: 0, + silent: true, + size: 0, + title: '', + type: '', + uuid: '' +}) + +const actions = { + setErrors({ commit }, payload) { + commit('SET_ERRORS', payload) + } +} + +const getters = { + getErrors: state => state +} + +const mutations = { + SET_ERRORS(state, payload) { + // The payload has useless data for the GUI, so only the needed data is saved in the store + for (const errorName in state) { + // eslint-disable-next-line no-prototype-builtins + if (state.hasOwnProperty(errorName)) { + state[errorName] = payload[errorName] + } + } + } +} + +export default { + state, + getters, + actions, + mutations +} diff --git a/webui/src/store/modules/login.js b/webui/src/store/modules/login.js new file mode 100644 index 0000000..a17f31f --- /dev/null +++ b/webui/src/store/modules/login.js @@ -0,0 +1,153 @@ +import { SPOTIFY_STATUS } from '@/constants' +import { fetchData } from '@/utils/api' + +const getDefaultState = () => ({ + arl: localStorage.getItem('arl') || '', + accessToken: localStorage.getItem('accessToken') || '', + status: null, + user: { + id: null, + name: '', + picture: '' + }, + spotifyUser: { + id: localStorage.getItem('spotifyUser'), + name: null, + picture: null + }, + // This does not always represent the truth because the status update on the server is async + // and at the moment there's no way to notice the status change. Therefore a fetch of the status + // is needed everytime we need to use it + spotifyStatus: SPOTIFY_STATUS.DISABLED, + clientMode: false +}) + +const state = () => { + return getDefaultState() +} + +const actions = { + login({ commit, dispatch }, payload) { + const { arl, user, status } = payload + + dispatch('setARL', { arl }) + commit('SET_USER', user) + commit('SET_STATUS', status) + }, + logout({ commit }) { + localStorage.removeItem('arl') + localStorage.removeItem('accessToken') + + commit('RESET_LOGIN') + }, + setARL({ commit }, payload) { + let { saveOnLocalStorage } = payload + const { arl } = payload + + saveOnLocalStorage = typeof saveOnLocalStorage === 'undefined' ? true : saveOnLocalStorage + + commit('SET_ARL', arl) + + if (saveOnLocalStorage) { + localStorage.setItem('arl', arl) + } + }, + setAccessToken({ commit }, payload) { + let { saveOnLocalStorage } = payload + const { accessToken } = payload + + saveOnLocalStorage = typeof saveOnLocalStorage === 'undefined' ? true : saveOnLocalStorage + + commit('SET_ACCESS_TOKEN', accessToken) + + if (saveOnLocalStorage) { + localStorage.setItem('accessToken', accessToken) + } + }, + removeARL({ commit }) { + commit('SET_ARL', '') + + localStorage.removeItem('arl') + }, + removeAccessToken({ commit }) { + commit('SET_ACCESS_TOKEN', '') + + localStorage.removeItem('accessToken') + }, + setUser({ commit }, payload) { + commit('SET_USER', payload) + }, + setClientMode({ commit }, payload) { + commit('SET_CLIENT_MODE', payload) + }, + setSpotifyStatus({ commit }, newSpotifyStatus) { + commit('SET_SPOTIFY_STATUS', newSpotifyStatus) + }, + setSpotifyUserId({ commit }, newSpotifyUserId) { + commit('SET_SPOTIFY_USER_ID', newSpotifyUserId) + }, + /** + * Returning a Promise so that who calls this action is sure that + * the fetching is complete after the statement + * + * @example + * await store.dispatch('refreshSpotifyStatus') + * // From here the status is refreshed + */ + refreshSpotifyStatus({ commit }) { + return fetchData('spotifyStatus').then(response => { + commit('SET_SPOTIFY_STATUS', response.spotifyEnabled ? SPOTIFY_STATUS.ENABLED : SPOTIFY_STATUS.DISABLED) + }) + } +} + +const getters = { + getARL: state => state.arl, + getAccessToken: state => state.accessToken, + getUser: state => state.user, + getSpotifyUser: state => state.spotifyUser, + getClientMode: state => state.clientMode, + + isLoggedIn: state => !!state.arl, + isLoggedWithSpotify: state => !!state.spotifyUser.id && state.spotifyStatus === SPOTIFY_STATUS.ENABLED +} + +const mutations = { + SET_ARL(state, payload) { + state.arl = payload + }, + SET_ACCESS_TOKEN(state, payload) { + state.accessToken = payload + }, + SET_STATUS(state, payload) { + state.status = payload + }, + SET_USER(state, payload) { + state.user = payload + }, + SET_CLIENT_MODE(state, payload) { + state.clientMode = payload + }, + RESET_LOGIN(state) { + // Needed for reactivity + const clientMode = state.clientMode + Object.assign(state, getDefaultState()) + state.clientMode = clientMode + }, + SET_SPOTIFY_STATUS(state, newSpotifyStatus) { + state.spotifyStatus = newSpotifyStatus + }, + SET_SPOTIFY_USER_ID(state, newSpotifyUserId) { + state.spotifyUser = { + ...state.spotifyUser, + id: newSpotifyUserId + } + } +} + +export default { + state, + getters, + actions, + mutations +} diff --git a/webui/src/styles/css/base.css b/webui/src/styles/css/base.css new file mode 100644 index 0000000..3a57847 --- /dev/null +++ b/webui/src/styles/css/base.css @@ -0,0 +1,101 @@ +:root { + font-size: 16px; + + --main-scroll: theme('colors.grayscale.300'); + --panels-scroll: hsl(180, 2%, 17%); + --toast-background: hsla(240, 12%, 16%, 0.85); + --toast-secondary: hsla(240, 12%, 16%, 0.15); + --toast-text: hsla(0, 0%, 100%, 0.85); + + --primary-color: hsl(210, 100%, 52%); /* will remove variable */ + --primary-text: theme('colors.grayscale.870'); /* will remove variable */ + --secondary-color: hsl(46, 100%, 57%); /* will remove variable */ +} + +:root[data-theme='light'] { + --main-background: theme('colors.white'); + --secondary-background: theme('colors.grayscale.930'); + --foreground: theme('colors.grayscale.200'); + --panels-background: hsl(216, 4%, 78%); + + --table-bg: theme('colors.white'); + --table-zebra: theme('colors.grayscale.900'); + --table-highlight: theme('colors.grayscale.840'); +} + +:root[data-theme='dark'] { + --main-background: hsl(240, 10%, 8%); + --secondary-background: hsl(240, 12%, 16%); /* e.g. search bar bg */ + --foreground: theme('colors.grayscale.930'); /* primary text + icons in main + search */ + --panels-background: hsl(240, 15%, 12%); /* panel left + right bg */ + + --table-bg: hsl(240, 10%, 8%); /* e.g. results table bg 1st row */ + --table-zebra: hsl(240, 15%, 11%); /* e.g. results table bg 2nd alternate */ + --table-highlight: hsl(240, 10%, 22%); /* e.g. hover bg color on table selection */ +} + +:root[data-theme='purple'] { + --main-background: hsl(261, 74%, 6%); + --secondary-background: hsl(257, 61%, 10%); + --foreground: theme('colors.grayscale.930'); + --panels-background: hsl(257, 70%, 9%); + + --table-bg: hsl(261, 74%, 6%); + --table-zebra: hsl(257, 61%, 10%); + --table-highlight: hsl(257, 66%, 27%); +} + +@layer base { + input[type='text'], + input[type='password'], + input[type='number'], + select { + border-radius: 4px; + background-color: var(--secondary-background); + padding: 0 1rem; + width: 100%; + min-height: 3rem; + line-height: 3rem; + color: var(--foreground); + } + + input[type='text'], + input[type='password'], + input[type='number'] { + padding: 0 16px; + } + + input[type='checkbox'] { + display: inline-block; + position: relative; + opacity: 0.5; + margin: 3px; + border: 2px solid gray; + border-radius: 2px; + background-color: none; + padding: 7px; + } + + input[type='checkbox']:checked { + opacity: 1; + border-width: 0; + background-color: var(--primary-color); + background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' height='18' viewBox='3 3 18 18' width='18'%3E%3Cpath fill='%23ffffff' d='M 10,17 5,12 6.41,10.59 10,14.17 17.59,6.58 19,8 Z'/%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3C/svg%3E"); + background-position: center center; + padding: 9px; + color: var(--primary-text); + } + + select { + background-clip: border-box; + background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' height='24' viewBox='0 0 24 24' width='24'%3E%3Cpath style='fill:gray;fill-opacity:0.5' d='M7 10l5 5 5-5z'/%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3C/svg%3E"); + background-position: calc(100% - 8px) center; + background-repeat: no-repeat; + background-size: 24px; + padding-right: 40px; + } + + a { + color: dodgerblue; + } +} diff --git a/webui/src/styles/css/components.css b/webui/src/styles/css/components.css new file mode 100644 index 0000000..3a9d44d --- /dev/null +++ b/webui/src/styles/css/components.css @@ -0,0 +1,79 @@ +@layer components { + /* Button */ + .btn { + @apply relative h-8 px-2 py-0 text-sm font-semibold uppercase border border-transparent border-solid rounded text-grayscale-900; + + font-family: inherit; + transition: transform 50ms ease-in-out; + } + + .btn:active { + transform: scale(0.98); + } + + .btn[disabled] { + @apply text-gray-300 bg-gray-600 opacity-75 cursor-not-allowed; + } + + .btn-only-icon { + @apply flex items-center justify-center w-12 px-1 py-0; + + min-width: 24px; + } + + .btn-primary { + @apply bg-primary; + } + .btn-flat { + background-color: rgba(0, 0, 0, 0); + color: var(--foreground); + } + + .btn-primary:hover { + @apply bg-blue-600 border-foreground; + } + + /* Section tabs */ + .section-tabs { + @apply flex mt-4 mb-6 list-none cursor-pointer; + } + + .section-tabs__tab { + @apply flex-1 p-3 text-xl text-center capitalize border-t-4 rounded-b border-foreground bg-background-main; + } + + .section-tabs__tab.active { + @apply text-primary border-primary bg-background-main; + } + + .section-tabs__tab:hover { + @apply text-primary border-primary bg-background-secondary; + @apply bg-opacity-25; + } + + /* Image header */ + .image-header header { + @apply px-6 pt-56 pb-2 bg-cover rounded-t-lg; + + background-position: 0% 35%; + } + + /* Fixed footer */ + .fixed-footer footer { + @apply sticky bottom-0 flex flex-row items-center justify-end w-full h-16 mt-6; + } + + /* Release grid */ + .release-grid { + @apply grid gap-4; + + grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr)); + } + + .tag { + padding: 3px; + background-color: var(--primary-color); + font-size: 10px; + border-radius: 3px; + } +} diff --git a/webui/src/styles/css/helpers.css b/webui/src/styles/css/helpers.css new file mode 100644 index 0000000..da52ef4 --- /dev/null +++ b/webui/src/styles/css/helpers.css @@ -0,0 +1,36 @@ +.changing-theme { + /* Applied to ALL elements when changing theme */ + transition: all 200ms ease-in-out; +} + +[v-cloak] { + /* Attribute removed after that a component finished loading */ + display: none; +} + +.clickable { + cursor: pointer !important; +} + +.coverart { + /* ? Why? */ + background-color: var(--secondary-background); +} + +.release { + display: inline-block; + width: 156px; +} + +.spin { + animation: spin 500ms infinite ease-out reverse; +} + +@keyframes spin { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(360deg); + } +} diff --git a/webui/src/styles/css/icons.css b/webui/src/styles/css/icons.css new file mode 100644 index 0000000..b4233d7 --- /dev/null +++ b/webui/src/styles/css/icons.css @@ -0,0 +1,25 @@ +.material-icons.title-icon { + margin-right: 0.3125em; + margin-left: -3px; +} + +.material-icons.title-icon.title-icon--right { + margin-right: 0px; + margin-left: 0.3125em; +} + +.material-icons.title-icon.title-icon--explicit { + color: hsl(240, 5%, 59%); +} + +.material-icons.title-icon.title-icon--new { + color: hsl(27, 100%, 50%); +} + +.material-icons.disabled { + @apply opacity-50 cursor-default; +} + +.material-icons.mirrored { + transform: scaleX(-1); +} diff --git a/webui/src/styles/css/normalize.css b/webui/src/styles/css/normalize.css new file mode 100644 index 0000000..9bb2c1d --- /dev/null +++ b/webui/src/styles/css/normalize.css @@ -0,0 +1,66 @@ +@layer base { + * { + box-sizing: border-box; + margin: 0; + padding: 0; + } + + table, + caption, + tbody, + tfoot, + thead, + tr, + th, + td { + margin: 0; + border: 0; + padding: 0; + vertical-align: baseline; + font: inherit; + font-size: 100%; + } + + table { + border-collapse: collapse; + border-spacing: 0; + } + + /* Taken from Tailwind's Preflight */ + button, + [type='button'], + [type='reset'], + [type='submit'] { + appearance: button; + } + + input[type='text'], + input[type='password'], + input[type='number'], + input[type='search'], + input[type='checkbox'], + select { + appearance: none; + } + + [type='number']::-webkit-inner-spin-button, + [type='number']::-webkit-outer-spin-button { + height: auto; + } + + button, + [role='button'] { + cursor: pointer; + } + + p { + word-break: break-word; + } + + *, + ::before, + ::after { + border-width: 0; + border-style: solid; + } +} diff --git a/webui/src/styles/css/tables.css b/webui/src/styles/css/tables.css new file mode 100644 index 0000000..ef99aec --- /dev/null +++ b/webui/src/styles/css/tables.css @@ -0,0 +1,140 @@ +.table { + width: 100%; + -webkit-border-horizontal-spacing: 0px; + -webkit-border-vertical-spacing: 0px; +} +.table tbody tr:not(.table__row-no-highlight):hover { + background: var(--table-highlight); + cursor: default; +} +.table tr { + transition: background-color 175ms ease-in-out; + background: var(--table-bg); +} +.table tr:nth-child(even) { + transition: background-color 175ms ease-in-out; + background: var(--table-zebra); +} +.table tr:not(:last-child) { + border-bottom: 1px solid var(--table-highlight); +} +.table td, .table th { + vertical-align: middle; +} +.table th .sortable { + user-select: none; +} +.table th .sort-asc::after, .table th .sort-desc::after { + padding-left: 3px; + line-height: 0.7em; + font-size: 0.7em; +} +.table th .sort-asc::after { + content: '\25b2'; +} +.table th .sort-desc::after { + content: '\25bc'; +} +.table td { + padding: 7px 10px; +} +.table td:first-child { + padding: 7px 10px 7px 20px; +} +.table td:last-child { + padding: 7px 20px 7px 10px; +} +.table td img { + vertical-align: middle; +} + +/* === Tracks Table === */ +.table--tracks { + border-collapse: collapse; +} +.table--tracks thead { + border-bottom: 2px solid var(--table-highlight); +} +.table--tracks tr:first-child td:first-child { + border-top-left-radius: 3px; +} +.table--tracks tr:first-child td:last-child { + border-top-right-radius: 3px; +} +.table--tracks tr:last-child td:first-child { + border-bottom-left-radius: 3px; +} +.table--tracks tr:last-child td:last-child { + border-bottom-right-radius: 3px; +} + +/* === Tracklist Table === */ +.table--tracklist thead { + border-bottom: 2px solid var(--table-highlight); + text-transform: capitalize; +} +.table--tracklist th { + padding: 7px 10px; + height: 45px; +} +.table--tracklist th:first-child { + padding: 7px 10px 7px 20px; +} +.table--tracklist th:last-child { + padding: 7px 20px 7px 10px; +} +.table--tracklist td { + height: 35px; +} + +/* === Charts Table === */ +.table--charts td { + height: 35px; +} + +.table .table__icon { + box-sizing: content-box; + width: 32px; +} +.table .table__icon--big { + width: 48px; + text-align: center; +} +.table .table__cell--x-small { + width: 0.32%; +} +.table .table__cell--small { + width: 3.2%; +} +.table .table__cell--medium { + width: 28.7%; +} +.table .table__cell--large { + width: 50%; +} +.table .table__cell--left { + text-align: left; +} +.table .table__cell--center { + text-align: center; +} +.table .table__cell--right { + text-align: right; +} +.table .table__cell-content.table__cell-content--vertical-center { + display: flex; + align-items: center; +} +.track_row > td > img { + width: 32px; + height: 32px; +} +.track_row > td > a > img { + width: 56px; + height: 56px; +} + +.table--tracklist .clickable:hover, +.table--charts .clickable:hover { + text-decoration: underline; +} diff --git a/webui/src/styles/css/tailwind.css b/webui/src/styles/css/tailwind.css new file mode 100644 index 0000000..b5c61c9 --- /dev/null +++ b/webui/src/styles/css/tailwind.css @@ -0,0 +1,3 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; diff --git a/webui/src/styles/css/toasts.css b/webui/src/styles/css/toasts.css new file mode 100644 index 0000000..9b1b580 --- /dev/null +++ b/webui/src/styles/css/toasts.css @@ -0,0 +1,26 @@ +.toast-icon { + @apply flex items-center mr-2; +} + +.circle-loader { + @apply inline-block w-4 h-4; + border: 2px solid var(--primary-color); + border-radius: 50%; + border-bottom: 2px solid var(--secondary-background); + animation: spin 1s linear infinite; +} + +.toastify { + @apply flex items-center; + box-shadow: 0 3px 6px -1px rgba(0, 0, 0, 0.12), 0 10px 36px -4px rgba(0, 0, 0, 0.3); + background: var(--toast-background); + color: var(--toast-text); +} + +.toastify toast { + @apply flex items-center; +} + +.toastify .circle-loader { + border-bottom-color: var(--toast-secondary); +} diff --git a/webui/src/styles/css/typography.css b/webui/src/styles/css/typography.css new file mode 100644 index 0000000..53a4172 --- /dev/null +++ b/webui/src/styles/css/typography.css @@ -0,0 +1,21 @@ +.primary-text { + @apply mb-1 transition-colors duration-200 ease-in-out; +} + +.primary-text:hover { + @apply text-primary; +} + +.secondary-text { + @apply mb-1 text-sm opacity-75; +} + +@layer utilities { + .uppercase-first-letter::first-letter { + @apply uppercase; + } + + .lowercase-first-letter::first-letter { + @apply lowercase; + } +} diff --git a/webui/src/styles/vendor/OpenSans.css b/webui/src/styles/vendor/OpenSans.css new file mode 100644 index 0000000..181ea45 --- /dev/null +++ b/webui/src/styles/vendor/OpenSans.css @@ -0,0 +1,630 @@ +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 300; + font-display: swap; + src: url('fonts/OpenSans/memnYaGs126MiZpBA-UFUKWyV9hmIqOjjg.woff2') format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 300; + font-display: swap; + src: url('fonts/OpenSans/memnYaGs126MiZpBA-UFUKWyV9hvIqOjjg.woff2') format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 300; + font-display: swap; + src: url('fonts/OpenSans/memnYaGs126MiZpBA-UFUKWyV9hnIqOjjg.woff2') format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 300; + font-display: swap; + src: url('fonts/OpenSans/memnYaGs126MiZpBA-UFUKWyV9hoIqOjjg.woff2') format('woff2'); + unicode-range: U+0370-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 300; + font-display: swap; + src: url('fonts/OpenSans/memnYaGs126MiZpBA-UFUKWyV9hkIqOjjg.woff2') format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 300; + font-display: swap; + src: url('fonts/OpenSans/memnYaGs126MiZpBA-UFUKWyV9hlIqOjjg.woff2') format('woff2'); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 300; + font-display: swap; + src: url('fonts/OpenSans/memnYaGs126MiZpBA-UFUKWyV9hrIqM.woff2') format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + font-display: swap; + src: url('fonts/OpenSans/mem6YaGs126MiZpBA-UFUK0Udc1UAw.woff2') format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + font-display: swap; + src: url('fonts/OpenSans/mem6YaGs126MiZpBA-UFUK0ddc1UAw.woff2') format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + font-display: swap; + src: url('fonts/OpenSans/mem6YaGs126MiZpBA-UFUK0Vdc1UAw.woff2') format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + font-display: swap; + src: url('fonts/OpenSans/mem6YaGs126MiZpBA-UFUK0adc1UAw.woff2') format('woff2'); + unicode-range: U+0370-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + font-display: swap; + src: url('fonts/OpenSans/mem6YaGs126MiZpBA-UFUK0Wdc1UAw.woff2') format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + font-display: swap; + src: url('fonts/OpenSans/mem6YaGs126MiZpBA-UFUK0Xdc1UAw.woff2') format('woff2'); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + font-display: swap; + src: url('fonts/OpenSans/mem6YaGs126MiZpBA-UFUK0Zdc0.woff2') format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + font-display: swap; + src: url('fonts/OpenSans/memnYaGs126MiZpBA-UFUKXGUdhmIqOjjg.woff2') format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + font-display: swap; + src: url('fonts/OpenSans/memnYaGs126MiZpBA-UFUKXGUdhvIqOjjg.woff2') format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + font-display: swap; + src: url('fonts/OpenSans/memnYaGs126MiZpBA-UFUKXGUdhnIqOjjg.woff2') format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + font-display: swap; + src: url('fonts/OpenSans/memnYaGs126MiZpBA-UFUKXGUdhoIqOjjg.woff2') format('woff2'); + unicode-range: U+0370-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + font-display: swap; + src: url('fonts/OpenSans/memnYaGs126MiZpBA-UFUKXGUdhkIqOjjg.woff2') format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + font-display: swap; + src: url('fonts/OpenSans/memnYaGs126MiZpBA-UFUKXGUdhlIqOjjg.woff2') format('woff2'); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + font-display: swap; + src: url('fonts/OpenSans/memnYaGs126MiZpBA-UFUKXGUdhrIqM.woff2') format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 700; + font-display: swap; + src: url('fonts/OpenSans/memnYaGs126MiZpBA-UFUKWiUNhmIqOjjg.woff2') format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 700; + font-display: swap; + src: url('fonts/OpenSans/memnYaGs126MiZpBA-UFUKWiUNhvIqOjjg.woff2') format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 700; + font-display: swap; + src: url('fonts/OpenSans/memnYaGs126MiZpBA-UFUKWiUNhnIqOjjg.woff2') format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 700; + font-display: swap; + src: url('fonts/OpenSans/memnYaGs126MiZpBA-UFUKWiUNhoIqOjjg.woff2') format('woff2'); + unicode-range: U+0370-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 700; + font-display: swap; + src: url('fonts/OpenSans/memnYaGs126MiZpBA-UFUKWiUNhkIqOjjg.woff2') format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 700; + font-display: swap; + src: url('fonts/OpenSans/memnYaGs126MiZpBA-UFUKWiUNhlIqOjjg.woff2') format('woff2'); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 700; + font-display: swap; + src: url('fonts/OpenSans/memnYaGs126MiZpBA-UFUKWiUNhrIqM.woff2') format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 800; + font-display: swap; + src: url('fonts/OpenSans/memnYaGs126MiZpBA-UFUKW-U9hmIqOjjg.woff2') format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 800; + font-display: swap; + src: url('fonts/OpenSans/memnYaGs126MiZpBA-UFUKW-U9hvIqOjjg.woff2') format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 800; + font-display: swap; + src: url('fonts/OpenSans/memnYaGs126MiZpBA-UFUKW-U9hnIqOjjg.woff2') format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 800; + font-display: swap; + src: url('fonts/OpenSans/memnYaGs126MiZpBA-UFUKW-U9hoIqOjjg.woff2') format('woff2'); + unicode-range: U+0370-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 800; + font-display: swap; + src: url('fonts/OpenSans/memnYaGs126MiZpBA-UFUKW-U9hkIqOjjg.woff2') format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 800; + font-display: swap; + src: url('fonts/OpenSans/memnYaGs126MiZpBA-UFUKW-U9hlIqOjjg.woff2') format('woff2'); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 800; + font-display: swap; + src: url('fonts/OpenSans/memnYaGs126MiZpBA-UFUKW-U9hrIqM.woff2') format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 300; + font-display: swap; + src: url('fonts/OpenSans/mem5YaGs126MiZpBA-UN_r8OX-hpOqc.woff2') format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 300; + font-display: swap; + src: url('fonts/OpenSans/mem5YaGs126MiZpBA-UN_r8OVuhpOqc.woff2') format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 300; + font-display: swap; + src: url('fonts/OpenSans/mem5YaGs126MiZpBA-UN_r8OXuhpOqc.woff2') format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 300; + font-display: swap; + src: url('fonts/OpenSans/mem5YaGs126MiZpBA-UN_r8OUehpOqc.woff2') format('woff2'); + unicode-range: U+0370-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 300; + font-display: swap; + src: url('fonts/OpenSans/mem5YaGs126MiZpBA-UN_r8OXehpOqc.woff2') format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 300; + font-display: swap; + src: url('fonts/OpenSans/mem5YaGs126MiZpBA-UN_r8OXOhpOqc.woff2') format('woff2'); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 300; + font-display: swap; + src: url('fonts/OpenSans/mem5YaGs126MiZpBA-UN_r8OUuhp.woff2') format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url('fonts/OpenSans/mem8YaGs126MiZpBA-UFWJ0bbck.woff2') format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url('fonts/OpenSans/mem8YaGs126MiZpBA-UFUZ0bbck.woff2') format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url('fonts/OpenSans/mem8YaGs126MiZpBA-UFWZ0bbck.woff2') format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url('fonts/OpenSans/mem8YaGs126MiZpBA-UFVp0bbck.woff2') format('woff2'); + unicode-range: U+0370-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url('fonts/OpenSans/mem8YaGs126MiZpBA-UFWp0bbck.woff2') format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url('fonts/OpenSans/mem8YaGs126MiZpBA-UFW50bbck.woff2') format('woff2'); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url('fonts/OpenSans/mem8YaGs126MiZpBA-UFVZ0b.woff2') format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url('fonts/OpenSans/mem5YaGs126MiZpBA-UNirkOX-hpOqc.woff2') format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url('fonts/OpenSans/mem5YaGs126MiZpBA-UNirkOVuhpOqc.woff2') format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url('fonts/OpenSans/mem5YaGs126MiZpBA-UNirkOXuhpOqc.woff2') format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url('fonts/OpenSans/mem5YaGs126MiZpBA-UNirkOUehpOqc.woff2') format('woff2'); + unicode-range: U+0370-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url('fonts/OpenSans/mem5YaGs126MiZpBA-UNirkOXehpOqc.woff2') format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url('fonts/OpenSans/mem5YaGs126MiZpBA-UNirkOXOhpOqc.woff2') format('woff2'); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url('fonts/OpenSans/mem5YaGs126MiZpBA-UNirkOUuhp.woff2') format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url('fonts/OpenSans/mem5YaGs126MiZpBA-UN7rgOX-hpOqc.woff2') format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url('fonts/OpenSans/mem5YaGs126MiZpBA-UN7rgOVuhpOqc.woff2') format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url('fonts/OpenSans/mem5YaGs126MiZpBA-UN7rgOXuhpOqc.woff2') format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url('fonts/OpenSans/mem5YaGs126MiZpBA-UN7rgOUehpOqc.woff2') format('woff2'); + unicode-range: U+0370-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url('fonts/OpenSans/mem5YaGs126MiZpBA-UN7rgOXehpOqc.woff2') format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url('fonts/OpenSans/mem5YaGs126MiZpBA-UN7rgOXOhpOqc.woff2') format('woff2'); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url('fonts/OpenSans/mem5YaGs126MiZpBA-UN7rgOUuhp.woff2') format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 800; + font-display: swap; + src: url('fonts/OpenSans/mem5YaGs126MiZpBA-UN8rsOX-hpOqc.woff2') format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 800; + font-display: swap; + src: url('fonts/OpenSans/mem5YaGs126MiZpBA-UN8rsOVuhpOqc.woff2') format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 800; + font-display: swap; + src: url('fonts/OpenSans/mem5YaGs126MiZpBA-UN8rsOXuhpOqc.woff2') format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 800; + font-display: swap; + src: url('fonts/OpenSans/mem5YaGs126MiZpBA-UN8rsOUehpOqc.woff2') format('woff2'); + unicode-range: U+0370-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 800; + font-display: swap; + src: url('fonts/OpenSans/mem5YaGs126MiZpBA-UN8rsOXehpOqc.woff2') format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 800; + font-display: swap; + src: url('fonts/OpenSans/mem5YaGs126MiZpBA-UN8rsOXOhpOqc.woff2') format('woff2'); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 800; + font-display: swap; + src: url('fonts/OpenSans/mem5YaGs126MiZpBA-UN8rsOUuhp.woff2') format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} diff --git a/webui/src/styles/vendor/animate.css b/webui/src/styles/vendor/animate.css new file mode 100644 index 0000000..772a60c --- /dev/null +++ b/webui/src/styles/vendor/animate.css @@ -0,0 +1,3625 @@ +@charset "UTF-8"; + +/*! + * animate.css -https://daneden.github.io/animate.css/ + * Version - 3.7.1 + * Licensed under the MIT license - http://opensource.org/licenses/MIT + * + * Copyright (c) 2019 Daniel Eden + */ + +@-webkit-keyframes bounce { + from, + 20%, + 53%, + 80%, + to { + -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + + 40%, + 43% { + -webkit-animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06); + animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06); + -webkit-transform: translate3d(0, -30px, 0); + transform: translate3d(0, -30px, 0); + } + + 70% { + -webkit-animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06); + animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06); + -webkit-transform: translate3d(0, -15px, 0); + transform: translate3d(0, -15px, 0); + } + + 90% { + -webkit-transform: translate3d(0, -4px, 0); + transform: translate3d(0, -4px, 0); + } +} + +@keyframes bounce { + from, + 20%, + 53%, + 80%, + to { + -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + + 40%, + 43% { + -webkit-animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06); + animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06); + -webkit-transform: translate3d(0, -30px, 0); + transform: translate3d(0, -30px, 0); + } + + 70% { + -webkit-animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06); + animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06); + -webkit-transform: translate3d(0, -15px, 0); + transform: translate3d(0, -15px, 0); + } + + 90% { + -webkit-transform: translate3d(0, -4px, 0); + transform: translate3d(0, -4px, 0); + } +} + +.bounce { + -webkit-animation-name: bounce; + animation-name: bounce; + -webkit-transform-origin: center bottom; + transform-origin: center bottom; +} + +@-webkit-keyframes flash { + from, + 50%, + to { + opacity: 1; + } + + 25%, + 75% { + opacity: 0; + } +} + +@keyframes flash { + from, + 50%, + to { + opacity: 1; + } + + 25%, + 75% { + opacity: 0; + } +} + +.flash { + -webkit-animation-name: flash; + animation-name: flash; +} + +/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */ + +@-webkit-keyframes pulse { + from { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } + + 50% { + -webkit-transform: scale3d(1.05, 1.05, 1.05); + transform: scale3d(1.05, 1.05, 1.05); + } + + to { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } +} + +@keyframes pulse { + from { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } + + 50% { + -webkit-transform: scale3d(1.05, 1.05, 1.05); + transform: scale3d(1.05, 1.05, 1.05); + } + + to { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } +} + +.pulse { + -webkit-animation-name: pulse; + animation-name: pulse; +} + +@-webkit-keyframes rubberBand { + from { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } + + 30% { + -webkit-transform: scale3d(1.25, 0.75, 1); + transform: scale3d(1.25, 0.75, 1); + } + + 40% { + -webkit-transform: scale3d(0.75, 1.25, 1); + transform: scale3d(0.75, 1.25, 1); + } + + 50% { + -webkit-transform: scale3d(1.15, 0.85, 1); + transform: scale3d(1.15, 0.85, 1); + } + + 65% { + -webkit-transform: scale3d(0.95, 1.05, 1); + transform: scale3d(0.95, 1.05, 1); + } + + 75% { + -webkit-transform: scale3d(1.05, 0.95, 1); + transform: scale3d(1.05, 0.95, 1); + } + + to { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } +} + +@keyframes rubberBand { + from { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } + + 30% { + -webkit-transform: scale3d(1.25, 0.75, 1); + transform: scale3d(1.25, 0.75, 1); + } + + 40% { + -webkit-transform: scale3d(0.75, 1.25, 1); + transform: scale3d(0.75, 1.25, 1); + } + + 50% { + -webkit-transform: scale3d(1.15, 0.85, 1); + transform: scale3d(1.15, 0.85, 1); + } + + 65% { + -webkit-transform: scale3d(0.95, 1.05, 1); + transform: scale3d(0.95, 1.05, 1); + } + + 75% { + -webkit-transform: scale3d(1.05, 0.95, 1); + transform: scale3d(1.05, 0.95, 1); + } + + to { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } +} + +.rubberBand { + -webkit-animation-name: rubberBand; + animation-name: rubberBand; +} + +@-webkit-keyframes shake { + from, + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + + 10%, + 30%, + 50%, + 70%, + 90% { + -webkit-transform: translate3d(-10px, 0, 0); + transform: translate3d(-10px, 0, 0); + } + + 20%, + 40%, + 60%, + 80% { + -webkit-transform: translate3d(10px, 0, 0); + transform: translate3d(10px, 0, 0); + } +} + +@keyframes shake { + from, + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + + 10%, + 30%, + 50%, + 70%, + 90% { + -webkit-transform: translate3d(-10px, 0, 0); + transform: translate3d(-10px, 0, 0); + } + + 20%, + 40%, + 60%, + 80% { + -webkit-transform: translate3d(10px, 0, 0); + transform: translate3d(10px, 0, 0); + } +} + +.shake { + -webkit-animation-name: shake; + animation-name: shake; +} + +@-webkit-keyframes headShake { + 0% { + -webkit-transform: translateX(0); + transform: translateX(0); + } + + 6.5% { + -webkit-transform: translateX(-6px) rotateY(-9deg); + transform: translateX(-6px) rotateY(-9deg); + } + + 18.5% { + -webkit-transform: translateX(5px) rotateY(7deg); + transform: translateX(5px) rotateY(7deg); + } + + 31.5% { + -webkit-transform: translateX(-3px) rotateY(-5deg); + transform: translateX(-3px) rotateY(-5deg); + } + + 43.5% { + -webkit-transform: translateX(2px) rotateY(3deg); + transform: translateX(2px) rotateY(3deg); + } + + 50% { + -webkit-transform: translateX(0); + transform: translateX(0); + } +} + +@keyframes headShake { + 0% { + -webkit-transform: translateX(0); + transform: translateX(0); + } + + 6.5% { + -webkit-transform: translateX(-6px) rotateY(-9deg); + transform: translateX(-6px) rotateY(-9deg); + } + + 18.5% { + -webkit-transform: translateX(5px) rotateY(7deg); + transform: translateX(5px) rotateY(7deg); + } + + 31.5% { + -webkit-transform: translateX(-3px) rotateY(-5deg); + transform: translateX(-3px) rotateY(-5deg); + } + + 43.5% { + -webkit-transform: translateX(2px) rotateY(3deg); + transform: translateX(2px) rotateY(3deg); + } + + 50% { + -webkit-transform: translateX(0); + transform: translateX(0); + } +} + +.headShake { + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; + -webkit-animation-name: headShake; + animation-name: headShake; +} + +@-webkit-keyframes swing { + 20% { + -webkit-transform: rotate3d(0, 0, 1, 15deg); + transform: rotate3d(0, 0, 1, 15deg); + } + + 40% { + -webkit-transform: rotate3d(0, 0, 1, -10deg); + transform: rotate3d(0, 0, 1, -10deg); + } + + 60% { + -webkit-transform: rotate3d(0, 0, 1, 5deg); + transform: rotate3d(0, 0, 1, 5deg); + } + + 80% { + -webkit-transform: rotate3d(0, 0, 1, -5deg); + transform: rotate3d(0, 0, 1, -5deg); + } + + to { + -webkit-transform: rotate3d(0, 0, 1, 0deg); + transform: rotate3d(0, 0, 1, 0deg); + } +} + +@keyframes swing { + 20% { + -webkit-transform: rotate3d(0, 0, 1, 15deg); + transform: rotate3d(0, 0, 1, 15deg); + } + + 40% { + -webkit-transform: rotate3d(0, 0, 1, -10deg); + transform: rotate3d(0, 0, 1, -10deg); + } + + 60% { + -webkit-transform: rotate3d(0, 0, 1, 5deg); + transform: rotate3d(0, 0, 1, 5deg); + } + + 80% { + -webkit-transform: rotate3d(0, 0, 1, -5deg); + transform: rotate3d(0, 0, 1, -5deg); + } + + to { + -webkit-transform: rotate3d(0, 0, 1, 0deg); + transform: rotate3d(0, 0, 1, 0deg); + } +} + +.swing { + -webkit-transform-origin: top center; + transform-origin: top center; + -webkit-animation-name: swing; + animation-name: swing; +} + +@-webkit-keyframes tada { + from { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } + + 10%, + 20% { + -webkit-transform: scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg); + transform: scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg); + } + + 30%, + 50%, + 70%, + 90% { + -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg); + transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg); + } + + 40%, + 60%, + 80% { + -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg); + transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg); + } + + to { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } +} + +@keyframes tada { + from { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } + + 10%, + 20% { + -webkit-transform: scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg); + transform: scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg); + } + + 30%, + 50%, + 70%, + 90% { + -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg); + transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg); + } + + 40%, + 60%, + 80% { + -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg); + transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg); + } + + to { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } +} + +.tada { + -webkit-animation-name: tada; + animation-name: tada; +} + +/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */ + +@-webkit-keyframes wobble { + from { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + + 15% { + -webkit-transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg); + transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg); + } + + 30% { + -webkit-transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg); + transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg); + } + + 45% { + -webkit-transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg); + transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg); + } + + 60% { + -webkit-transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg); + transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg); + } + + 75% { + -webkit-transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg); + transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg); + } + + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +@keyframes wobble { + from { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + + 15% { + -webkit-transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg); + transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg); + } + + 30% { + -webkit-transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg); + transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg); + } + + 45% { + -webkit-transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg); + transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg); + } + + 60% { + -webkit-transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg); + transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg); + } + + 75% { + -webkit-transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg); + transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg); + } + + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +.wobble { + -webkit-animation-name: wobble; + animation-name: wobble; +} + +@-webkit-keyframes jello { + from, + 11.1%, + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + + 22.2% { + -webkit-transform: skewX(-12.5deg) skewY(-12.5deg); + transform: skewX(-12.5deg) skewY(-12.5deg); + } + + 33.3% { + -webkit-transform: skewX(6.25deg) skewY(6.25deg); + transform: skewX(6.25deg) skewY(6.25deg); + } + + 44.4% { + -webkit-transform: skewX(-3.125deg) skewY(-3.125deg); + transform: skewX(-3.125deg) skewY(-3.125deg); + } + + 55.5% { + -webkit-transform: skewX(1.5625deg) skewY(1.5625deg); + transform: skewX(1.5625deg) skewY(1.5625deg); + } + + 66.6% { + -webkit-transform: skewX(-0.78125deg) skewY(-0.78125deg); + transform: skewX(-0.78125deg) skewY(-0.78125deg); + } + + 77.7% { + -webkit-transform: skewX(0.390625deg) skewY(0.390625deg); + transform: skewX(0.390625deg) skewY(0.390625deg); + } + + 88.8% { + -webkit-transform: skewX(-0.1953125deg) skewY(-0.1953125deg); + transform: skewX(-0.1953125deg) skewY(-0.1953125deg); + } +} + +@keyframes jello { + from, + 11.1%, + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + + 22.2% { + -webkit-transform: skewX(-12.5deg) skewY(-12.5deg); + transform: skewX(-12.5deg) skewY(-12.5deg); + } + + 33.3% { + -webkit-transform: skewX(6.25deg) skewY(6.25deg); + transform: skewX(6.25deg) skewY(6.25deg); + } + + 44.4% { + -webkit-transform: skewX(-3.125deg) skewY(-3.125deg); + transform: skewX(-3.125deg) skewY(-3.125deg); + } + + 55.5% { + -webkit-transform: skewX(1.5625deg) skewY(1.5625deg); + transform: skewX(1.5625deg) skewY(1.5625deg); + } + + 66.6% { + -webkit-transform: skewX(-0.78125deg) skewY(-0.78125deg); + transform: skewX(-0.78125deg) skewY(-0.78125deg); + } + + 77.7% { + -webkit-transform: skewX(0.390625deg) skewY(0.390625deg); + transform: skewX(0.390625deg) skewY(0.390625deg); + } + + 88.8% { + -webkit-transform: skewX(-0.1953125deg) skewY(-0.1953125deg); + transform: skewX(-0.1953125deg) skewY(-0.1953125deg); + } +} + +.jello { + -webkit-animation-name: jello; + animation-name: jello; + -webkit-transform-origin: center; + transform-origin: center; +} + +@-webkit-keyframes heartBeat { + 0% { + -webkit-transform: scale(1); + transform: scale(1); + } + + 14% { + -webkit-transform: scale(1.3); + transform: scale(1.3); + } + + 28% { + -webkit-transform: scale(1); + transform: scale(1); + } + + 42% { + -webkit-transform: scale(1.3); + transform: scale(1.3); + } + + 70% { + -webkit-transform: scale(1); + transform: scale(1); + } +} + +@keyframes heartBeat { + 0% { + -webkit-transform: scale(1); + transform: scale(1); + } + + 14% { + -webkit-transform: scale(1.3); + transform: scale(1.3); + } + + 28% { + -webkit-transform: scale(1); + transform: scale(1); + } + + 42% { + -webkit-transform: scale(1.3); + transform: scale(1.3); + } + + 70% { + -webkit-transform: scale(1); + transform: scale(1); + } +} + +.heartBeat { + -webkit-animation-name: heartBeat; + animation-name: heartBeat; + -webkit-animation-duration: 1.3s; + animation-duration: 1.3s; + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; +} + +@-webkit-keyframes bounceIn { + from, + 20%, + 40%, + 60%, + 80%, + to { + -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + } + + 0% { + opacity: 0; + -webkit-transform: scale3d(0.3, 0.3, 0.3); + transform: scale3d(0.3, 0.3, 0.3); + } + + 20% { + -webkit-transform: scale3d(1.1, 1.1, 1.1); + transform: scale3d(1.1, 1.1, 1.1); + } + + 40% { + -webkit-transform: scale3d(0.9, 0.9, 0.9); + transform: scale3d(0.9, 0.9, 0.9); + } + + 60% { + opacity: 1; + -webkit-transform: scale3d(1.03, 1.03, 1.03); + transform: scale3d(1.03, 1.03, 1.03); + } + + 80% { + -webkit-transform: scale3d(0.97, 0.97, 0.97); + transform: scale3d(0.97, 0.97, 0.97); + } + + to { + opacity: 1; + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } +} + +@keyframes bounceIn { + from, + 20%, + 40%, + 60%, + 80%, + to { + -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + } + + 0% { + opacity: 0; + -webkit-transform: scale3d(0.3, 0.3, 0.3); + transform: scale3d(0.3, 0.3, 0.3); + } + + 20% { + -webkit-transform: scale3d(1.1, 1.1, 1.1); + transform: scale3d(1.1, 1.1, 1.1); + } + + 40% { + -webkit-transform: scale3d(0.9, 0.9, 0.9); + transform: scale3d(0.9, 0.9, 0.9); + } + + 60% { + opacity: 1; + -webkit-transform: scale3d(1.03, 1.03, 1.03); + transform: scale3d(1.03, 1.03, 1.03); + } + + 80% { + -webkit-transform: scale3d(0.97, 0.97, 0.97); + transform: scale3d(0.97, 0.97, 0.97); + } + + to { + opacity: 1; + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } +} + +.bounceIn { + -webkit-animation-duration: 0.75s; + animation-duration: 0.75s; + -webkit-animation-name: bounceIn; + animation-name: bounceIn; +} + +@-webkit-keyframes bounceInDown { + from, + 60%, + 75%, + 90%, + to { + -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + } + + 0% { + opacity: 0; + -webkit-transform: translate3d(0, -3000px, 0); + transform: translate3d(0, -3000px, 0); + } + + 60% { + opacity: 1; + -webkit-transform: translate3d(0, 25px, 0); + transform: translate3d(0, 25px, 0); + } + + 75% { + -webkit-transform: translate3d(0, -10px, 0); + transform: translate3d(0, -10px, 0); + } + + 90% { + -webkit-transform: translate3d(0, 5px, 0); + transform: translate3d(0, 5px, 0); + } + + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +@keyframes bounceInDown { + from, + 60%, + 75%, + 90%, + to { + -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + } + + 0% { + opacity: 0; + -webkit-transform: translate3d(0, -3000px, 0); + transform: translate3d(0, -3000px, 0); + } + + 60% { + opacity: 1; + -webkit-transform: translate3d(0, 25px, 0); + transform: translate3d(0, 25px, 0); + } + + 75% { + -webkit-transform: translate3d(0, -10px, 0); + transform: translate3d(0, -10px, 0); + } + + 90% { + -webkit-transform: translate3d(0, 5px, 0); + transform: translate3d(0, 5px, 0); + } + + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +.bounceInDown { + -webkit-animation-name: bounceInDown; + animation-name: bounceInDown; +} + +@-webkit-keyframes bounceInLeft { + from, + 60%, + 75%, + 90%, + to { + -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + } + + 0% { + opacity: 0; + -webkit-transform: translate3d(-3000px, 0, 0); + transform: translate3d(-3000px, 0, 0); + } + + 60% { + opacity: 1; + -webkit-transform: translate3d(25px, 0, 0); + transform: translate3d(25px, 0, 0); + } + + 75% { + -webkit-transform: translate3d(-10px, 0, 0); + transform: translate3d(-10px, 0, 0); + } + + 90% { + -webkit-transform: translate3d(5px, 0, 0); + transform: translate3d(5px, 0, 0); + } + + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +@keyframes bounceInLeft { + from, + 60%, + 75%, + 90%, + to { + -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + } + + 0% { + opacity: 0; + -webkit-transform: translate3d(-3000px, 0, 0); + transform: translate3d(-3000px, 0, 0); + } + + 60% { + opacity: 1; + -webkit-transform: translate3d(25px, 0, 0); + transform: translate3d(25px, 0, 0); + } + + 75% { + -webkit-transform: translate3d(-10px, 0, 0); + transform: translate3d(-10px, 0, 0); + } + + 90% { + -webkit-transform: translate3d(5px, 0, 0); + transform: translate3d(5px, 0, 0); + } + + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +.bounceInLeft { + -webkit-animation-name: bounceInLeft; + animation-name: bounceInLeft; +} + +@-webkit-keyframes bounceInRight { + from, + 60%, + 75%, + 90%, + to { + -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + } + + from { + opacity: 0; + -webkit-transform: translate3d(3000px, 0, 0); + transform: translate3d(3000px, 0, 0); + } + + 60% { + opacity: 1; + -webkit-transform: translate3d(-25px, 0, 0); + transform: translate3d(-25px, 0, 0); + } + + 75% { + -webkit-transform: translate3d(10px, 0, 0); + transform: translate3d(10px, 0, 0); + } + + 90% { + -webkit-transform: translate3d(-5px, 0, 0); + transform: translate3d(-5px, 0, 0); + } + + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +@keyframes bounceInRight { + from, + 60%, + 75%, + 90%, + to { + -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + } + + from { + opacity: 0; + -webkit-transform: translate3d(3000px, 0, 0); + transform: translate3d(3000px, 0, 0); + } + + 60% { + opacity: 1; + -webkit-transform: translate3d(-25px, 0, 0); + transform: translate3d(-25px, 0, 0); + } + + 75% { + -webkit-transform: translate3d(10px, 0, 0); + transform: translate3d(10px, 0, 0); + } + + 90% { + -webkit-transform: translate3d(-5px, 0, 0); + transform: translate3d(-5px, 0, 0); + } + + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +.bounceInRight { + -webkit-animation-name: bounceInRight; + animation-name: bounceInRight; +} + +@-webkit-keyframes bounceInUp { + from, + 60%, + 75%, + 90%, + to { + -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + } + + from { + opacity: 0; + -webkit-transform: translate3d(0, 3000px, 0); + transform: translate3d(0, 3000px, 0); + } + + 60% { + opacity: 1; + -webkit-transform: translate3d(0, -20px, 0); + transform: translate3d(0, -20px, 0); + } + + 75% { + -webkit-transform: translate3d(0, 10px, 0); + transform: translate3d(0, 10px, 0); + } + + 90% { + -webkit-transform: translate3d(0, -5px, 0); + transform: translate3d(0, -5px, 0); + } + + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +@keyframes bounceInUp { + from, + 60%, + 75%, + 90%, + to { + -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + } + + from { + opacity: 0; + -webkit-transform: translate3d(0, 3000px, 0); + transform: translate3d(0, 3000px, 0); + } + + 60% { + opacity: 1; + -webkit-transform: translate3d(0, -20px, 0); + transform: translate3d(0, -20px, 0); + } + + 75% { + -webkit-transform: translate3d(0, 10px, 0); + transform: translate3d(0, 10px, 0); + } + + 90% { + -webkit-transform: translate3d(0, -5px, 0); + transform: translate3d(0, -5px, 0); + } + + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +.bounceInUp { + -webkit-animation-name: bounceInUp; + animation-name: bounceInUp; +} + +@-webkit-keyframes bounceOut { + 20% { + -webkit-transform: scale3d(0.9, 0.9, 0.9); + transform: scale3d(0.9, 0.9, 0.9); + } + + 50%, + 55% { + opacity: 1; + -webkit-transform: scale3d(1.1, 1.1, 1.1); + transform: scale3d(1.1, 1.1, 1.1); + } + + to { + opacity: 0; + -webkit-transform: scale3d(0.3, 0.3, 0.3); + transform: scale3d(0.3, 0.3, 0.3); + } +} + +@keyframes bounceOut { + 20% { + -webkit-transform: scale3d(0.9, 0.9, 0.9); + transform: scale3d(0.9, 0.9, 0.9); + } + + 50%, + 55% { + opacity: 1; + -webkit-transform: scale3d(1.1, 1.1, 1.1); + transform: scale3d(1.1, 1.1, 1.1); + } + + to { + opacity: 0; + -webkit-transform: scale3d(0.3, 0.3, 0.3); + transform: scale3d(0.3, 0.3, 0.3); + } +} + +.bounceOut { + -webkit-animation-duration: 0.75s; + animation-duration: 0.75s; + -webkit-animation-name: bounceOut; + animation-name: bounceOut; +} + +@-webkit-keyframes bounceOutDown { + 20% { + -webkit-transform: translate3d(0, 10px, 0); + transform: translate3d(0, 10px, 0); + } + + 40%, + 45% { + opacity: 1; + -webkit-transform: translate3d(0, -20px, 0); + transform: translate3d(0, -20px, 0); + } + + to { + opacity: 0; + -webkit-transform: translate3d(0, 2000px, 0); + transform: translate3d(0, 2000px, 0); + } +} + +@keyframes bounceOutDown { + 20% { + -webkit-transform: translate3d(0, 10px, 0); + transform: translate3d(0, 10px, 0); + } + + 40%, + 45% { + opacity: 1; + -webkit-transform: translate3d(0, -20px, 0); + transform: translate3d(0, -20px, 0); + } + + to { + opacity: 0; + -webkit-transform: translate3d(0, 2000px, 0); + transform: translate3d(0, 2000px, 0); + } +} + +.bounceOutDown { + -webkit-animation-name: bounceOutDown; + animation-name: bounceOutDown; +} + +@-webkit-keyframes bounceOutLeft { + 20% { + opacity: 1; + -webkit-transform: translate3d(20px, 0, 0); + transform: translate3d(20px, 0, 0); + } + + to { + opacity: 0; + -webkit-transform: translate3d(-2000px, 0, 0); + transform: translate3d(-2000px, 0, 0); + } +} + +@keyframes bounceOutLeft { + 20% { + opacity: 1; + -webkit-transform: translate3d(20px, 0, 0); + transform: translate3d(20px, 0, 0); + } + + to { + opacity: 0; + -webkit-transform: translate3d(-2000px, 0, 0); + transform: translate3d(-2000px, 0, 0); + } +} + +.bounceOutLeft { + -webkit-animation-name: bounceOutLeft; + animation-name: bounceOutLeft; +} + +@-webkit-keyframes bounceOutRight { + 20% { + opacity: 1; + -webkit-transform: translate3d(-20px, 0, 0); + transform: translate3d(-20px, 0, 0); + } + + to { + opacity: 0; + -webkit-transform: translate3d(2000px, 0, 0); + transform: translate3d(2000px, 0, 0); + } +} + +@keyframes bounceOutRight { + 20% { + opacity: 1; + -webkit-transform: translate3d(-20px, 0, 0); + transform: translate3d(-20px, 0, 0); + } + + to { + opacity: 0; + -webkit-transform: translate3d(2000px, 0, 0); + transform: translate3d(2000px, 0, 0); + } +} + +.bounceOutRight { + -webkit-animation-name: bounceOutRight; + animation-name: bounceOutRight; +} + +@-webkit-keyframes bounceOutUp { + 20% { + -webkit-transform: translate3d(0, -10px, 0); + transform: translate3d(0, -10px, 0); + } + + 40%, + 45% { + opacity: 1; + -webkit-transform: translate3d(0, 20px, 0); + transform: translate3d(0, 20px, 0); + } + + to { + opacity: 0; + -webkit-transform: translate3d(0, -2000px, 0); + transform: translate3d(0, -2000px, 0); + } +} + +@keyframes bounceOutUp { + 20% { + -webkit-transform: translate3d(0, -10px, 0); + transform: translate3d(0, -10px, 0); + } + + 40%, + 45% { + opacity: 1; + -webkit-transform: translate3d(0, 20px, 0); + transform: translate3d(0, 20px, 0); + } + + to { + opacity: 0; + -webkit-transform: translate3d(0, -2000px, 0); + transform: translate3d(0, -2000px, 0); + } +} + +.bounceOutUp { + -webkit-animation-name: bounceOutUp; + animation-name: bounceOutUp; +} + +@-webkit-keyframes fadeIn { + from { + opacity: 0; + } + + to { + opacity: 1; + } +} + +@keyframes fadeIn { + from { + opacity: 0; + } + + to { + opacity: 1; + } +} + +.fadeIn { + -webkit-animation-name: fadeIn; + animation-name: fadeIn; +} + +@-webkit-keyframes fadeInDown { + from { + opacity: 0; + -webkit-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + } + + to { + opacity: 1; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +@keyframes fadeInDown { + from { + opacity: 0; + -webkit-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + } + + to { + opacity: 1; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +.fadeInDown { + -webkit-animation-name: fadeInDown; + animation-name: fadeInDown; +} + +@-webkit-keyframes fadeInDownBig { + from { + opacity: 0; + -webkit-transform: translate3d(0, -2000px, 0); + transform: translate3d(0, -2000px, 0); + } + + to { + opacity: 1; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +@keyframes fadeInDownBig { + from { + opacity: 0; + -webkit-transform: translate3d(0, -2000px, 0); + transform: translate3d(0, -2000px, 0); + } + + to { + opacity: 1; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +.fadeInDownBig { + -webkit-animation-name: fadeInDownBig; + animation-name: fadeInDownBig; +} + +@-webkit-keyframes fadeInLeft { + from { + opacity: 0; + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + } + + to { + opacity: 1; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +@keyframes fadeInLeft { + from { + opacity: 0; + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + } + + to { + opacity: 1; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +.fadeInLeft { + -webkit-animation-name: fadeInLeft; + animation-name: fadeInLeft; +} + +@-webkit-keyframes fadeInLeftBig { + from { + opacity: 0; + -webkit-transform: translate3d(-2000px, 0, 0); + transform: translate3d(-2000px, 0, 0); + } + + to { + opacity: 1; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +@keyframes fadeInLeftBig { + from { + opacity: 0; + -webkit-transform: translate3d(-2000px, 0, 0); + transform: translate3d(-2000px, 0, 0); + } + + to { + opacity: 1; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +.fadeInLeftBig { + -webkit-animation-name: fadeInLeftBig; + animation-name: fadeInLeftBig; +} + +@-webkit-keyframes fadeInRight { + from { + opacity: 0; + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + } + + to { + opacity: 1; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +@keyframes fadeInRight { + from { + opacity: 0; + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + } + + to { + opacity: 1; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +.fadeInRight { + -webkit-animation-name: fadeInRight; + animation-name: fadeInRight; +} + +@-webkit-keyframes fadeInRightBig { + from { + opacity: 0; + -webkit-transform: translate3d(2000px, 0, 0); + transform: translate3d(2000px, 0, 0); + } + + to { + opacity: 1; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +@keyframes fadeInRightBig { + from { + opacity: 0; + -webkit-transform: translate3d(2000px, 0, 0); + transform: translate3d(2000px, 0, 0); + } + + to { + opacity: 1; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +.fadeInRightBig { + -webkit-animation-name: fadeInRightBig; + animation-name: fadeInRightBig; +} + +@-webkit-keyframes fadeInUp { + from { + opacity: 0; + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + } + + to { + opacity: 1; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +@keyframes fadeInUp { + from { + opacity: 0; + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + } + + to { + opacity: 1; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +.fadeInUp { + -webkit-animation-name: fadeInUp; + animation-name: fadeInUp; +} + +@-webkit-keyframes fadeInUpBig { + from { + opacity: 0; + -webkit-transform: translate3d(0, 2000px, 0); + transform: translate3d(0, 2000px, 0); + } + + to { + opacity: 1; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +@keyframes fadeInUpBig { + from { + opacity: 0; + -webkit-transform: translate3d(0, 2000px, 0); + transform: translate3d(0, 2000px, 0); + } + + to { + opacity: 1; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +.fadeInUpBig { + -webkit-animation-name: fadeInUpBig; + animation-name: fadeInUpBig; +} + +@-webkit-keyframes fadeOut { + from { + opacity: 1; + } + + to { + opacity: 0; + } +} + +@keyframes fadeOut { + from { + opacity: 1; + } + + to { + opacity: 0; + } +} + +.fadeOut { + -webkit-animation-name: fadeOut; + animation-name: fadeOut; +} + +@-webkit-keyframes fadeOutDown { + from { + opacity: 1; + } + + to { + opacity: 0; + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + } +} + +@keyframes fadeOutDown { + from { + opacity: 1; + } + + to { + opacity: 0; + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + } +} + +.fadeOutDown { + -webkit-animation-name: fadeOutDown; + animation-name: fadeOutDown; +} + +@-webkit-keyframes fadeOutDownBig { + from { + opacity: 1; + } + + to { + opacity: 0; + -webkit-transform: translate3d(0, 2000px, 0); + transform: translate3d(0, 2000px, 0); + } +} + +@keyframes fadeOutDownBig { + from { + opacity: 1; + } + + to { + opacity: 0; + -webkit-transform: translate3d(0, 2000px, 0); + transform: translate3d(0, 2000px, 0); + } +} + +.fadeOutDownBig { + -webkit-animation-name: fadeOutDownBig; + animation-name: fadeOutDownBig; +} + +@-webkit-keyframes fadeOutLeft { + from { + opacity: 1; + } + + to { + opacity: 0; + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + } +} + +@keyframes fadeOutLeft { + from { + opacity: 1; + } + + to { + opacity: 0; + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + } +} + +.fadeOutLeft { + -webkit-animation-name: fadeOutLeft; + animation-name: fadeOutLeft; +} + +@-webkit-keyframes fadeOutLeftBig { + from { + opacity: 1; + } + + to { + opacity: 0; + -webkit-transform: translate3d(-2000px, 0, 0); + transform: translate3d(-2000px, 0, 0); + } +} + +@keyframes fadeOutLeftBig { + from { + opacity: 1; + } + + to { + opacity: 0; + -webkit-transform: translate3d(-2000px, 0, 0); + transform: translate3d(-2000px, 0, 0); + } +} + +.fadeOutLeftBig { + -webkit-animation-name: fadeOutLeftBig; + animation-name: fadeOutLeftBig; +} + +@-webkit-keyframes fadeOutRight { + from { + opacity: 1; + } + + to { + opacity: 0; + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + } +} + +@keyframes fadeOutRight { + from { + opacity: 1; + } + + to { + opacity: 0; + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + } +} + +.fadeOutRight { + -webkit-animation-name: fadeOutRight; + animation-name: fadeOutRight; +} + +@-webkit-keyframes fadeOutRightBig { + from { + opacity: 1; + } + + to { + opacity: 0; + -webkit-transform: translate3d(2000px, 0, 0); + transform: translate3d(2000px, 0, 0); + } +} + +@keyframes fadeOutRightBig { + from { + opacity: 1; + } + + to { + opacity: 0; + -webkit-transform: translate3d(2000px, 0, 0); + transform: translate3d(2000px, 0, 0); + } +} + +.fadeOutRightBig { + -webkit-animation-name: fadeOutRightBig; + animation-name: fadeOutRightBig; +} + +@-webkit-keyframes fadeOutUp { + from { + opacity: 1; + } + + to { + opacity: 0; + -webkit-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + } +} + +@keyframes fadeOutUp { + from { + opacity: 1; + } + + to { + opacity: 0; + -webkit-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + } +} + +.fadeOutUp { + -webkit-animation-name: fadeOutUp; + animation-name: fadeOutUp; +} + +@-webkit-keyframes fadeOutUpBig { + from { + opacity: 1; + } + + to { + opacity: 0; + -webkit-transform: translate3d(0, -2000px, 0); + transform: translate3d(0, -2000px, 0); + } +} + +@keyframes fadeOutUpBig { + from { + opacity: 1; + } + + to { + opacity: 0; + -webkit-transform: translate3d(0, -2000px, 0); + transform: translate3d(0, -2000px, 0); + } +} + +.fadeOutUpBig { + -webkit-animation-name: fadeOutUpBig; + animation-name: fadeOutUpBig; +} + +@-webkit-keyframes flip { + from { + -webkit-transform: perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 0) + rotate3d(0, 1, 0, -360deg); + transform: perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 0) rotate3d(0, 1, 0, -360deg); + -webkit-animation-timing-function: ease-out; + animation-timing-function: ease-out; + } + + 40% { + -webkit-transform: perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 150px) + rotate3d(0, 1, 0, -190deg); + transform: perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 150px) + rotate3d(0, 1, 0, -190deg); + -webkit-animation-timing-function: ease-out; + animation-timing-function: ease-out; + } + + 50% { + -webkit-transform: perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 150px) + rotate3d(0, 1, 0, -170deg); + transform: perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 150px) + rotate3d(0, 1, 0, -170deg); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } + + 80% { + -webkit-transform: perspective(400px) scale3d(0.95, 0.95, 0.95) translate3d(0, 0, 0) + rotate3d(0, 1, 0, 0deg); + transform: perspective(400px) scale3d(0.95, 0.95, 0.95) translate3d(0, 0, 0) + rotate3d(0, 1, 0, 0deg); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } + + to { + -webkit-transform: perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 0) + rotate3d(0, 1, 0, 0deg); + transform: perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 0) rotate3d(0, 1, 0, 0deg); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } +} + +@keyframes flip { + from { + -webkit-transform: perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 0) + rotate3d(0, 1, 0, -360deg); + transform: perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 0) rotate3d(0, 1, 0, -360deg); + -webkit-animation-timing-function: ease-out; + animation-timing-function: ease-out; + } + + 40% { + -webkit-transform: perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 150px) + rotate3d(0, 1, 0, -190deg); + transform: perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 150px) + rotate3d(0, 1, 0, -190deg); + -webkit-animation-timing-function: ease-out; + animation-timing-function: ease-out; + } + + 50% { + -webkit-transform: perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 150px) + rotate3d(0, 1, 0, -170deg); + transform: perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 150px) + rotate3d(0, 1, 0, -170deg); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } + + 80% { + -webkit-transform: perspective(400px) scale3d(0.95, 0.95, 0.95) translate3d(0, 0, 0) + rotate3d(0, 1, 0, 0deg); + transform: perspective(400px) scale3d(0.95, 0.95, 0.95) translate3d(0, 0, 0) + rotate3d(0, 1, 0, 0deg); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } + + to { + -webkit-transform: perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 0) + rotate3d(0, 1, 0, 0deg); + transform: perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 0) rotate3d(0, 1, 0, 0deg); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } +} + +.animated.flip { + -webkit-backface-visibility: visible; + backface-visibility: visible; + -webkit-animation-name: flip; + animation-name: flip; +} + +@-webkit-keyframes flipInX { + from { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + opacity: 0; + } + + 40% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } + + 60% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg); + transform: perspective(400px) rotate3d(1, 0, 0, 10deg); + opacity: 1; + } + + 80% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg); + transform: perspective(400px) rotate3d(1, 0, 0, -5deg); + } + + to { + -webkit-transform: perspective(400px); + transform: perspective(400px); + } +} + +@keyframes flipInX { + from { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + opacity: 0; + } + + 40% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } + + 60% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg); + transform: perspective(400px) rotate3d(1, 0, 0, 10deg); + opacity: 1; + } + + 80% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg); + transform: perspective(400px) rotate3d(1, 0, 0, -5deg); + } + + to { + -webkit-transform: perspective(400px); + transform: perspective(400px); + } +} + +.flipInX { + -webkit-backface-visibility: visible !important; + backface-visibility: visible !important; + -webkit-animation-name: flipInX; + animation-name: flipInX; +} + +@-webkit-keyframes flipInY { + from { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg); + transform: perspective(400px) rotate3d(0, 1, 0, 90deg); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + opacity: 0; + } + + 40% { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -20deg); + transform: perspective(400px) rotate3d(0, 1, 0, -20deg); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } + + 60% { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 10deg); + transform: perspective(400px) rotate3d(0, 1, 0, 10deg); + opacity: 1; + } + + 80% { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -5deg); + transform: perspective(400px) rotate3d(0, 1, 0, -5deg); + } + + to { + -webkit-transform: perspective(400px); + transform: perspective(400px); + } +} + +@keyframes flipInY { + from { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg); + transform: perspective(400px) rotate3d(0, 1, 0, 90deg); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + opacity: 0; + } + + 40% { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -20deg); + transform: perspective(400px) rotate3d(0, 1, 0, -20deg); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } + + 60% { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 10deg); + transform: perspective(400px) rotate3d(0, 1, 0, 10deg); + opacity: 1; + } + + 80% { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -5deg); + transform: perspective(400px) rotate3d(0, 1, 0, -5deg); + } + + to { + -webkit-transform: perspective(400px); + transform: perspective(400px); + } +} + +.flipInY { + -webkit-backface-visibility: visible !important; + backface-visibility: visible !important; + -webkit-animation-name: flipInY; + animation-name: flipInY; +} + +@-webkit-keyframes flipOutX { + from { + -webkit-transform: perspective(400px); + transform: perspective(400px); + } + + 30% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + opacity: 1; + } + + to { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + opacity: 0; + } +} + +@keyframes flipOutX { + from { + -webkit-transform: perspective(400px); + transform: perspective(400px); + } + + 30% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + opacity: 1; + } + + to { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + opacity: 0; + } +} + +.flipOutX { + -webkit-animation-duration: 0.75s; + animation-duration: 0.75s; + -webkit-animation-name: flipOutX; + animation-name: flipOutX; + -webkit-backface-visibility: visible !important; + backface-visibility: visible !important; +} + +@-webkit-keyframes flipOutY { + from { + -webkit-transform: perspective(400px); + transform: perspective(400px); + } + + 30% { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -15deg); + transform: perspective(400px) rotate3d(0, 1, 0, -15deg); + opacity: 1; + } + + to { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg); + transform: perspective(400px) rotate3d(0, 1, 0, 90deg); + opacity: 0; + } +} + +@keyframes flipOutY { + from { + -webkit-transform: perspective(400px); + transform: perspective(400px); + } + + 30% { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -15deg); + transform: perspective(400px) rotate3d(0, 1, 0, -15deg); + opacity: 1; + } + + to { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg); + transform: perspective(400px) rotate3d(0, 1, 0, 90deg); + opacity: 0; + } +} + +.flipOutY { + -webkit-animation-duration: 0.75s; + animation-duration: 0.75s; + -webkit-backface-visibility: visible !important; + backface-visibility: visible !important; + -webkit-animation-name: flipOutY; + animation-name: flipOutY; +} + +@-webkit-keyframes lightSpeedIn { + from { + -webkit-transform: translate3d(100%, 0, 0) skewX(-30deg); + transform: translate3d(100%, 0, 0) skewX(-30deg); + opacity: 0; + } + + 60% { + -webkit-transform: skewX(20deg); + transform: skewX(20deg); + opacity: 1; + } + + 80% { + -webkit-transform: skewX(-5deg); + transform: skewX(-5deg); + } + + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +@keyframes lightSpeedIn { + from { + -webkit-transform: translate3d(100%, 0, 0) skewX(-30deg); + transform: translate3d(100%, 0, 0) skewX(-30deg); + opacity: 0; + } + + 60% { + -webkit-transform: skewX(20deg); + transform: skewX(20deg); + opacity: 1; + } + + 80% { + -webkit-transform: skewX(-5deg); + transform: skewX(-5deg); + } + + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +.lightSpeedIn { + -webkit-animation-name: lightSpeedIn; + animation-name: lightSpeedIn; + -webkit-animation-timing-function: ease-out; + animation-timing-function: ease-out; +} + +@-webkit-keyframes lightSpeedOut { + from { + opacity: 1; + } + + to { + -webkit-transform: translate3d(100%, 0, 0) skewX(30deg); + transform: translate3d(100%, 0, 0) skewX(30deg); + opacity: 0; + } +} + +@keyframes lightSpeedOut { + from { + opacity: 1; + } + + to { + -webkit-transform: translate3d(100%, 0, 0) skewX(30deg); + transform: translate3d(100%, 0, 0) skewX(30deg); + opacity: 0; + } +} + +.lightSpeedOut { + -webkit-animation-name: lightSpeedOut; + animation-name: lightSpeedOut; + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; +} + +@-webkit-keyframes rotateIn { + from { + -webkit-transform-origin: center; + transform-origin: center; + -webkit-transform: rotate3d(0, 0, 1, -200deg); + transform: rotate3d(0, 0, 1, -200deg); + opacity: 0; + } + + to { + -webkit-transform-origin: center; + transform-origin: center; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + opacity: 1; + } +} + +@keyframes rotateIn { + from { + -webkit-transform-origin: center; + transform-origin: center; + -webkit-transform: rotate3d(0, 0, 1, -200deg); + transform: rotate3d(0, 0, 1, -200deg); + opacity: 0; + } + + to { + -webkit-transform-origin: center; + transform-origin: center; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + opacity: 1; + } +} + +.rotateIn { + -webkit-animation-name: rotateIn; + animation-name: rotateIn; +} + +@-webkit-keyframes rotateInDownLeft { + from { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate3d(0, 0, 1, -45deg); + transform: rotate3d(0, 0, 1, -45deg); + opacity: 0; + } + + to { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + opacity: 1; + } +} + +@keyframes rotateInDownLeft { + from { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate3d(0, 0, 1, -45deg); + transform: rotate3d(0, 0, 1, -45deg); + opacity: 0; + } + + to { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + opacity: 1; + } +} + +.rotateInDownLeft { + -webkit-animation-name: rotateInDownLeft; + animation-name: rotateInDownLeft; +} + +@-webkit-keyframes rotateInDownRight { + from { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate3d(0, 0, 1, 45deg); + transform: rotate3d(0, 0, 1, 45deg); + opacity: 0; + } + + to { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + opacity: 1; + } +} + +@keyframes rotateInDownRight { + from { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate3d(0, 0, 1, 45deg); + transform: rotate3d(0, 0, 1, 45deg); + opacity: 0; + } + + to { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + opacity: 1; + } +} + +.rotateInDownRight { + -webkit-animation-name: rotateInDownRight; + animation-name: rotateInDownRight; +} + +@-webkit-keyframes rotateInUpLeft { + from { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate3d(0, 0, 1, 45deg); + transform: rotate3d(0, 0, 1, 45deg); + opacity: 0; + } + + to { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + opacity: 1; + } +} + +@keyframes rotateInUpLeft { + from { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate3d(0, 0, 1, 45deg); + transform: rotate3d(0, 0, 1, 45deg); + opacity: 0; + } + + to { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + opacity: 1; + } +} + +.rotateInUpLeft { + -webkit-animation-name: rotateInUpLeft; + animation-name: rotateInUpLeft; +} + +@-webkit-keyframes rotateInUpRight { + from { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate3d(0, 0, 1, -90deg); + transform: rotate3d(0, 0, 1, -90deg); + opacity: 0; + } + + to { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + opacity: 1; + } +} + +@keyframes rotateInUpRight { + from { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate3d(0, 0, 1, -90deg); + transform: rotate3d(0, 0, 1, -90deg); + opacity: 0; + } + + to { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + opacity: 1; + } +} + +.rotateInUpRight { + -webkit-animation-name: rotateInUpRight; + animation-name: rotateInUpRight; +} + +@-webkit-keyframes rotateOut { + from { + -webkit-transform-origin: center; + transform-origin: center; + opacity: 1; + } + + to { + -webkit-transform-origin: center; + transform-origin: center; + -webkit-transform: rotate3d(0, 0, 1, 200deg); + transform: rotate3d(0, 0, 1, 200deg); + opacity: 0; + } +} + +@keyframes rotateOut { + from { + -webkit-transform-origin: center; + transform-origin: center; + opacity: 1; + } + + to { + -webkit-transform-origin: center; + transform-origin: center; + -webkit-transform: rotate3d(0, 0, 1, 200deg); + transform: rotate3d(0, 0, 1, 200deg); + opacity: 0; + } +} + +.rotateOut { + -webkit-animation-name: rotateOut; + animation-name: rotateOut; +} + +@-webkit-keyframes rotateOutDownLeft { + from { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + opacity: 1; + } + + to { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate3d(0, 0, 1, 45deg); + transform: rotate3d(0, 0, 1, 45deg); + opacity: 0; + } +} + +@keyframes rotateOutDownLeft { + from { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + opacity: 1; + } + + to { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate3d(0, 0, 1, 45deg); + transform: rotate3d(0, 0, 1, 45deg); + opacity: 0; + } +} + +.rotateOutDownLeft { + -webkit-animation-name: rotateOutDownLeft; + animation-name: rotateOutDownLeft; +} + +@-webkit-keyframes rotateOutDownRight { + from { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + opacity: 1; + } + + to { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate3d(0, 0, 1, -45deg); + transform: rotate3d(0, 0, 1, -45deg); + opacity: 0; + } +} + +@keyframes rotateOutDownRight { + from { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + opacity: 1; + } + + to { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate3d(0, 0, 1, -45deg); + transform: rotate3d(0, 0, 1, -45deg); + opacity: 0; + } +} + +.rotateOutDownRight { + -webkit-animation-name: rotateOutDownRight; + animation-name: rotateOutDownRight; +} + +@-webkit-keyframes rotateOutUpLeft { + from { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + opacity: 1; + } + + to { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate3d(0, 0, 1, -45deg); + transform: rotate3d(0, 0, 1, -45deg); + opacity: 0; + } +} + +@keyframes rotateOutUpLeft { + from { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + opacity: 1; + } + + to { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate3d(0, 0, 1, -45deg); + transform: rotate3d(0, 0, 1, -45deg); + opacity: 0; + } +} + +.rotateOutUpLeft { + -webkit-animation-name: rotateOutUpLeft; + animation-name: rotateOutUpLeft; +} + +@-webkit-keyframes rotateOutUpRight { + from { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + opacity: 1; + } + + to { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate3d(0, 0, 1, 90deg); + transform: rotate3d(0, 0, 1, 90deg); + opacity: 0; + } +} + +@keyframes rotateOutUpRight { + from { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + opacity: 1; + } + + to { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate3d(0, 0, 1, 90deg); + transform: rotate3d(0, 0, 1, 90deg); + opacity: 0; + } +} + +.rotateOutUpRight { + -webkit-animation-name: rotateOutUpRight; + animation-name: rotateOutUpRight; +} + +@-webkit-keyframes hinge { + 0% { + -webkit-transform-origin: top left; + transform-origin: top left; + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; + } + + 20%, + 60% { + -webkit-transform: rotate3d(0, 0, 1, 80deg); + transform: rotate3d(0, 0, 1, 80deg); + -webkit-transform-origin: top left; + transform-origin: top left; + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; + } + + 40%, + 80% { + -webkit-transform: rotate3d(0, 0, 1, 60deg); + transform: rotate3d(0, 0, 1, 60deg); + -webkit-transform-origin: top left; + transform-origin: top left; + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; + opacity: 1; + } + + to { + -webkit-transform: translate3d(0, 700px, 0); + transform: translate3d(0, 700px, 0); + opacity: 0; + } +} + +@keyframes hinge { + 0% { + -webkit-transform-origin: top left; + transform-origin: top left; + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; + } + + 20%, + 60% { + -webkit-transform: rotate3d(0, 0, 1, 80deg); + transform: rotate3d(0, 0, 1, 80deg); + -webkit-transform-origin: top left; + transform-origin: top left; + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; + } + + 40%, + 80% { + -webkit-transform: rotate3d(0, 0, 1, 60deg); + transform: rotate3d(0, 0, 1, 60deg); + -webkit-transform-origin: top left; + transform-origin: top left; + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; + opacity: 1; + } + + to { + -webkit-transform: translate3d(0, 700px, 0); + transform: translate3d(0, 700px, 0); + opacity: 0; + } +} + +.hinge { + -webkit-animation-duration: 2s; + animation-duration: 2s; + -webkit-animation-name: hinge; + animation-name: hinge; +} + +@-webkit-keyframes jackInTheBox { + from { + opacity: 0; + -webkit-transform: scale(0.1) rotate(30deg); + transform: scale(0.1) rotate(30deg); + -webkit-transform-origin: center bottom; + transform-origin: center bottom; + } + + 50% { + -webkit-transform: rotate(-10deg); + transform: rotate(-10deg); + } + + 70% { + -webkit-transform: rotate(3deg); + transform: rotate(3deg); + } + + to { + opacity: 1; + -webkit-transform: scale(1); + transform: scale(1); + } +} + +@keyframes jackInTheBox { + from { + opacity: 0; + -webkit-transform: scale(0.1) rotate(30deg); + transform: scale(0.1) rotate(30deg); + -webkit-transform-origin: center bottom; + transform-origin: center bottom; + } + + 50% { + -webkit-transform: rotate(-10deg); + transform: rotate(-10deg); + } + + 70% { + -webkit-transform: rotate(3deg); + transform: rotate(3deg); + } + + to { + opacity: 1; + -webkit-transform: scale(1); + transform: scale(1); + } +} + +.jackInTheBox { + -webkit-animation-name: jackInTheBox; + animation-name: jackInTheBox; +} + +/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */ + +@-webkit-keyframes rollIn { + from { + opacity: 0; + -webkit-transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg); + transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg); + } + + to { + opacity: 1; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +@keyframes rollIn { + from { + opacity: 0; + -webkit-transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg); + transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg); + } + + to { + opacity: 1; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +.rollIn { + -webkit-animation-name: rollIn; + animation-name: rollIn; +} + +/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */ + +@-webkit-keyframes rollOut { + from { + opacity: 1; + } + + to { + opacity: 0; + -webkit-transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg); + transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg); + } +} + +@keyframes rollOut { + from { + opacity: 1; + } + + to { + opacity: 0; + -webkit-transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg); + transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg); + } +} + +.rollOut { + -webkit-animation-name: rollOut; + animation-name: rollOut; +} + +@-webkit-keyframes zoomIn { + from { + opacity: 0; + -webkit-transform: scale3d(0.3, 0.3, 0.3); + transform: scale3d(0.3, 0.3, 0.3); + } + + 50% { + opacity: 1; + } +} + +@keyframes zoomIn { + from { + opacity: 0; + -webkit-transform: scale3d(0.3, 0.3, 0.3); + transform: scale3d(0.3, 0.3, 0.3); + } + + 50% { + opacity: 1; + } +} + +.zoomIn { + -webkit-animation-name: zoomIn; + animation-name: zoomIn; +} + +@-webkit-keyframes zoomInDown { + from { + opacity: 0; + -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -1000px, 0); + transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -1000px, 0); + -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + } + + 60% { + opacity: 1; + -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0); + transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0); + -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + } +} + +@keyframes zoomInDown { + from { + opacity: 0; + -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -1000px, 0); + transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -1000px, 0); + -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + } + + 60% { + opacity: 1; + -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0); + transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0); + -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + } +} + +.zoomInDown { + -webkit-animation-name: zoomInDown; + animation-name: zoomInDown; +} + +@-webkit-keyframes zoomInLeft { + from { + opacity: 0; + -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(-1000px, 0, 0); + transform: scale3d(0.1, 0.1, 0.1) translate3d(-1000px, 0, 0); + -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + } + + 60% { + opacity: 1; + -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(10px, 0, 0); + transform: scale3d(0.475, 0.475, 0.475) translate3d(10px, 0, 0); + -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + } +} + +@keyframes zoomInLeft { + from { + opacity: 0; + -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(-1000px, 0, 0); + transform: scale3d(0.1, 0.1, 0.1) translate3d(-1000px, 0, 0); + -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + } + + 60% { + opacity: 1; + -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(10px, 0, 0); + transform: scale3d(0.475, 0.475, 0.475) translate3d(10px, 0, 0); + -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + } +} + +.zoomInLeft { + -webkit-animation-name: zoomInLeft; + animation-name: zoomInLeft; +} + +@-webkit-keyframes zoomInRight { + from { + opacity: 0; + -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(1000px, 0, 0); + transform: scale3d(0.1, 0.1, 0.1) translate3d(1000px, 0, 0); + -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + } + + 60% { + opacity: 1; + -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(-10px, 0, 0); + transform: scale3d(0.475, 0.475, 0.475) translate3d(-10px, 0, 0); + -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + } +} + +@keyframes zoomInRight { + from { + opacity: 0; + -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(1000px, 0, 0); + transform: scale3d(0.1, 0.1, 0.1) translate3d(1000px, 0, 0); + -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + } + + 60% { + opacity: 1; + -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(-10px, 0, 0); + transform: scale3d(0.475, 0.475, 0.475) translate3d(-10px, 0, 0); + -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + } +} + +.zoomInRight { + -webkit-animation-name: zoomInRight; + animation-name: zoomInRight; +} + +@-webkit-keyframes zoomInUp { + from { + opacity: 0; + -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 1000px, 0); + transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 1000px, 0); + -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + } + + 60% { + opacity: 1; + -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0); + transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0); + -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + } +} + +@keyframes zoomInUp { + from { + opacity: 0; + -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 1000px, 0); + transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 1000px, 0); + -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + } + + 60% { + opacity: 1; + -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0); + transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0); + -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + } +} + +.zoomInUp { + -webkit-animation-name: zoomInUp; + animation-name: zoomInUp; +} + +@-webkit-keyframes zoomOut { + from { + opacity: 1; + } + + 50% { + opacity: 0; + -webkit-transform: scale3d(0.3, 0.3, 0.3); + transform: scale3d(0.3, 0.3, 0.3); + } + + to { + opacity: 0; + } +} + +@keyframes zoomOut { + from { + opacity: 1; + } + + 50% { + opacity: 0; + -webkit-transform: scale3d(0.3, 0.3, 0.3); + transform: scale3d(0.3, 0.3, 0.3); + } + + to { + opacity: 0; + } +} + +.zoomOut { + -webkit-animation-name: zoomOut; + animation-name: zoomOut; +} + +@-webkit-keyframes zoomOutDown { + 40% { + opacity: 1; + -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0); + transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0); + -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + } + + to { + opacity: 0; + -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 2000px, 0); + transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 2000px, 0); + -webkit-transform-origin: center bottom; + transform-origin: center bottom; + -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + } +} + +@keyframes zoomOutDown { + 40% { + opacity: 1; + -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0); + transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0); + -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + } + + to { + opacity: 0; + -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 2000px, 0); + transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 2000px, 0); + -webkit-transform-origin: center bottom; + transform-origin: center bottom; + -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + } +} + +.zoomOutDown { + -webkit-animation-name: zoomOutDown; + animation-name: zoomOutDown; +} + +@-webkit-keyframes zoomOutLeft { + 40% { + opacity: 1; + -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(42px, 0, 0); + transform: scale3d(0.475, 0.475, 0.475) translate3d(42px, 0, 0); + } + + to { + opacity: 0; + -webkit-transform: scale(0.1) translate3d(-2000px, 0, 0); + transform: scale(0.1) translate3d(-2000px, 0, 0); + -webkit-transform-origin: left center; + transform-origin: left center; + } +} + +@keyframes zoomOutLeft { + 40% { + opacity: 1; + -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(42px, 0, 0); + transform: scale3d(0.475, 0.475, 0.475) translate3d(42px, 0, 0); + } + + to { + opacity: 0; + -webkit-transform: scale(0.1) translate3d(-2000px, 0, 0); + transform: scale(0.1) translate3d(-2000px, 0, 0); + -webkit-transform-origin: left center; + transform-origin: left center; + } +} + +.zoomOutLeft { + -webkit-animation-name: zoomOutLeft; + animation-name: zoomOutLeft; +} + +@-webkit-keyframes zoomOutRight { + 40% { + opacity: 1; + -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(-42px, 0, 0); + transform: scale3d(0.475, 0.475, 0.475) translate3d(-42px, 0, 0); + } + + to { + opacity: 0; + -webkit-transform: scale(0.1) translate3d(2000px, 0, 0); + transform: scale(0.1) translate3d(2000px, 0, 0); + -webkit-transform-origin: right center; + transform-origin: right center; + } +} + +@keyframes zoomOutRight { + 40% { + opacity: 1; + -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(-42px, 0, 0); + transform: scale3d(0.475, 0.475, 0.475) translate3d(-42px, 0, 0); + } + + to { + opacity: 0; + -webkit-transform: scale(0.1) translate3d(2000px, 0, 0); + transform: scale(0.1) translate3d(2000px, 0, 0); + -webkit-transform-origin: right center; + transform-origin: right center; + } +} + +.zoomOutRight { + -webkit-animation-name: zoomOutRight; + animation-name: zoomOutRight; +} + +@-webkit-keyframes zoomOutUp { + 40% { + opacity: 1; + -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0); + transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0); + -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + } + + to { + opacity: 0; + -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -2000px, 0); + transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -2000px, 0); + -webkit-transform-origin: center bottom; + transform-origin: center bottom; + -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + } +} + +@keyframes zoomOutUp { + 40% { + opacity: 1; + -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0); + transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0); + -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + } + + to { + opacity: 0; + -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -2000px, 0); + transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -2000px, 0); + -webkit-transform-origin: center bottom; + transform-origin: center bottom; + -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + } +} + +.zoomOutUp { + -webkit-animation-name: zoomOutUp; + animation-name: zoomOutUp; +} + +@-webkit-keyframes slideInDown { + from { + -webkit-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + visibility: visible; + } + + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +@keyframes slideInDown { + from { + -webkit-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + visibility: visible; + } + + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +.slideInDown { + -webkit-animation-name: slideInDown; + animation-name: slideInDown; +} + +@-webkit-keyframes slideInLeft { + from { + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + visibility: visible; + } + + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +@keyframes slideInLeft { + from { + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + visibility: visible; + } + + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +.slideInLeft { + -webkit-animation-name: slideInLeft; + animation-name: slideInLeft; +} + +@-webkit-keyframes slideInRight { + from { + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + visibility: visible; + } + + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +@keyframes slideInRight { + from { + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + visibility: visible; + } + + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +.slideInRight { + -webkit-animation-name: slideInRight; + animation-name: slideInRight; +} + +@-webkit-keyframes slideInUp { + from { + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + visibility: visible; + } + + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +@keyframes slideInUp { + from { + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + visibility: visible; + } + + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +.slideInUp { + -webkit-animation-name: slideInUp; + animation-name: slideInUp; +} + +@-webkit-keyframes slideOutDown { + from { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + + to { + visibility: hidden; + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + } +} + +@keyframes slideOutDown { + from { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + + to { + visibility: hidden; + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + } +} + +.slideOutDown { + -webkit-animation-name: slideOutDown; + animation-name: slideOutDown; +} + +@-webkit-keyframes slideOutLeft { + from { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + + to { + visibility: hidden; + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + } +} + +@keyframes slideOutLeft { + from { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + + to { + visibility: hidden; + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + } +} + +.slideOutLeft { + -webkit-animation-name: slideOutLeft; + animation-name: slideOutLeft; +} + +@-webkit-keyframes slideOutRight { + from { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + + to { + visibility: hidden; + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + } +} + +@keyframes slideOutRight { + from { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + + to { + visibility: hidden; + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + } +} + +.slideOutRight { + -webkit-animation-name: slideOutRight; + animation-name: slideOutRight; +} + +@-webkit-keyframes slideOutUp { + from { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + + to { + visibility: hidden; + -webkit-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + } +} + +@keyframes slideOutUp { + from { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + + to { + visibility: hidden; + -webkit-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + } +} + +.slideOutUp { + -webkit-animation-name: slideOutUp; + animation-name: slideOutUp; +} + +.animated { + -webkit-animation-duration: 1s; + animation-duration: 1s; + -webkit-animation-fill-mode: both; + animation-fill-mode: both; +} + +.animated.infinite { + -webkit-animation-iteration-count: infinite; + animation-iteration-count: infinite; +} + +.animated.delay-1s { + -webkit-animation-delay: 1s; + animation-delay: 1s; +} + +.animated.delay-2s { + -webkit-animation-delay: 2s; + animation-delay: 2s; +} + +.animated.delay-3s { + -webkit-animation-delay: 3s; + animation-delay: 3s; +} + +.animated.delay-4s { + -webkit-animation-delay: 4s; + animation-delay: 4s; +} + +.animated.delay-5s { + -webkit-animation-delay: 5s; + animation-delay: 5s; +} + +.animated.fast { + -webkit-animation-duration: 800ms; + animation-duration: 800ms; +} + +.animated.faster { + -webkit-animation-duration: 500ms; + animation-duration: 500ms; +} + +.animated.slow { + -webkit-animation-duration: 2s; + animation-duration: 2s; +} + +.animated.slower { + -webkit-animation-duration: 3s; + animation-duration: 3s; +} + +@media (print), (prefers-reduced-motion: reduce) { + .animated { + -webkit-animation-duration: 1ms !important; + animation-duration: 1ms !important; + -webkit-transition-duration: 1ms !important; + transition-duration: 1ms !important; + -webkit-animation-iteration-count: 1 !important; + animation-iteration-count: 1 !important; + } +} diff --git a/webui/src/styles/vendor/material-icons.css b/webui/src/styles/vendor/material-icons.css new file mode 100644 index 0000000..c0335a5 --- /dev/null +++ b/webui/src/styles/vendor/material-icons.css @@ -0,0 +1,24 @@ +/* fallback */ +@font-face { + font-family: 'Material Icons'; + font-style: normal; + font-weight: 400; + src: url('fonts/icons/MaterialIcons-Regular.ttf') format('truetype'); +} + +.material-icons { + font-family: 'Material Icons'; + font-weight: normal; + font-style: normal; + font-size: 24px; + line-height: 1; + letter-spacing: normal; + text-transform: none; + display: inline-block; + white-space: nowrap; + word-wrap: normal; + direction: ltr; + -webkit-font-feature-settings: 'liga'; + font-feature-settings: 'liga'; + -webkit-font-smoothing: antialiased; +} diff --git a/webui/src/use/favorites.js b/webui/src/use/favorites.js new file mode 100644 index 0000000..60926cb --- /dev/null +++ b/webui/src/use/favorites.js @@ -0,0 +1,77 @@ +import { ref, computed } from '@vue/composition-api' + +import store from '@/store' +import { fetchData } from '@/utils/api' +import { toast } from '@/utils/toasts' +import i18n from '@/plugins/i18n' +import { SPOTIFY_STATUS } from '@/constants' + +const favoriteArtists = ref([]) +const favoriteAlbums = ref([]) +const favoriteSpotifyPlaylists = ref([]) +const favoritePlaylists = ref([]) +const favoriteTracks = ref([]) +const lovedTracksPlaylist = ref('') +const isLoggedWithSpotify = computed(() => store.getters.isLoggedWithSpotify) + +const isRefreshingFavorites = ref(false) + +const setAllFavorites = data => { + const { tracks, albums, artists, playlists, lovedTracks } = data + + isRefreshingFavorites.value = false + + favoriteArtists.value = artists || [] + favoriteAlbums.value = albums || [] + favoritePlaylists.value = playlists || [] + favoriteTracks.value = tracks || [] + lovedTracksPlaylist.value = lovedTracks || [] +} + +const setSpotifyPlaylists = response => { + if (response.error) { + favoriteSpotifyPlaylists.value = [] + switch (response.error) { + case 'spotifyNotEnabled': + store.dispatch('setSpotifyStatus', SPOTIFY_STATUS.DISABLED).catch(console.error) + break + case 'wrongSpotifyUsername': + toast(i18n.t('toasts.wrongSpotifyUsername', { username: response.username }), 'person_off') + break + default: + break + } + return + } + + favoriteSpotifyPlaylists.value = response || [] +} + +const refreshFavorites = async ({ isInitial = false }) => { + if (!isInitial) { + isRefreshingFavorites.value = true + } + + await store.dispatch('refreshSpotifyStatus') + + fetchData('getUserFavorites').then(setAllFavorites).catch(console.error) + + if (isLoggedWithSpotify.value) { + const spotifyUser = store.getters.getSpotifyUser.id + + fetchData('getUserSpotifyPlaylists', { spotifyUser }).then(setSpotifyPlaylists).catch(console.error) + } else { + favoriteSpotifyPlaylists.value = [] + } +} + +export const useFavorites = () => ({ + favoriteArtists, + favoriteAlbums, + favoriteSpotifyPlaylists, + favoritePlaylists, + favoriteTracks, + lovedTracksPlaylist, + isRefreshingFavorites, + refreshFavorites +}) diff --git a/webui/src/use/main-search.js b/webui/src/use/main-search.js new file mode 100644 index 0000000..de18035 --- /dev/null +++ b/webui/src/use/main-search.js @@ -0,0 +1,17 @@ +import { ref } from '@vue/composition-api' +import { fetchData } from '@/utils/api' + +const searchResult = ref({}) + +function performMainSearch(searchTerm) { + fetchData('mainSearch', { term: searchTerm }).then(data => { + searchResult.value = data + }) +} + +export function useMainSearch() { + return { + searchResult, + performMainSearch + } +} diff --git a/webui/src/use/online.js b/webui/src/use/online.js new file mode 100644 index 0000000..6eea25d --- /dev/null +++ b/webui/src/use/online.js @@ -0,0 +1,13 @@ +import { ref } from '@vue/composition-api' + +const isOnline = ref(navigator.onLine) + +window.addEventListener('online', () => { + isOnline.value = true +}) + +window.addEventListener('offline', () => { + isOnline.value = false +}) + +export const useOnline = () => ({ isOnline }) diff --git a/webui/src/use/search.js b/webui/src/use/search.js new file mode 100644 index 0000000..9546988 --- /dev/null +++ b/webui/src/use/search.js @@ -0,0 +1,22 @@ +import { ref } from '@vue/composition-api' +import { fetchData } from '@/utils/api' + +const result = ref({}) + +function performSearch({ term, type, start = 0, nb = 30 }) { + fetchData('search', { + term, + type, + start, + nb + }).then(data => { + result.value = data + }) +} + +export function useSearch() { + return { + result, + performSearch + } +} diff --git a/webui/src/use/theme.js b/webui/src/use/theme.js new file mode 100644 index 0000000..b6da7b7 --- /dev/null +++ b/webui/src/use/theme.js @@ -0,0 +1,46 @@ +import { ref, watch } from '@vue/composition-api' + +/** + * @typedef {string} Theme + */ + +const THEMES = { + dark: 'dark', + light: 'light', + purple: 'purple' +} + +const initialTheme = localStorage.getItem('selectedTheme') || document.documentElement.dataset.theme || THEMES.dark +const currentTheme = ref(initialTheme) + +watch(currentTheme, (newTheme, oldTheme) => { + // No operation needed + if (oldTheme === newTheme) return + + localStorage.setItem('selectedTheme', newTheme) + document.documentElement.dataset.theme = newTheme + + animateAllElements() +}) + +function animateAllElements() { + // Animating everything to have a smoother theme switch + const allElements = document.querySelectorAll('*') + + allElements.forEach(el => { + el.classList.add('changing-theme') + }) + + document.documentElement.addEventListener('transitionend', function transitionHandler() { + allElements.forEach(el => { + el.classList.remove('changing-theme') + }) + + document.documentElement.removeEventListener('transitionend', transitionHandler) + }) +} + +export const useTheme = () => ({ + THEMES, + currentTheme +}) diff --git a/webui/src/utils/EventBus.js b/webui/src/utils/EventBus.js new file mode 100644 index 0000000..68b11ec --- /dev/null +++ b/webui/src/utils/EventBus.js @@ -0,0 +1,4 @@ +// https://alligator.io/vuejs/global-event-bus/ +import Vue from 'vue' + +export default new Vue() diff --git a/webui/src/utils/adjust-volume.js b/webui/src/utils/adjust-volume.js new file mode 100644 index 0000000..25ce2ae --- /dev/null +++ b/webui/src/utils/adjust-volume.js @@ -0,0 +1,27 @@ +// https://stackoverflow.com/questions/7451508/html5-audio-playback-with-fade-in-and-fade-out#answer-13149848 +export function adjustVolume(element, newVolume, { duration = 1000, easing = swing, interval = 13 } = {}) { + const originalVolume = element.volume + const delta = newVolume - originalVolume + + if (!delta || !duration || !easing || !interval) { + element.volume = newVolume + return Promise.resolve() + } + + const ticks = Math.floor(duration / interval) + let tick = 1 + + return new Promise(resolve => { + const timer = setInterval(() => { + element.volume = originalVolume + easing(tick / ticks) * delta + if (++tick === ticks) { + clearInterval(timer) + resolve() + } + }, interval) + }) +} + +export function swing(p) { + return 0.5 - Math.cos(p * Math.PI) / 2 +} diff --git a/webui/src/utils/api.js b/webui/src/utils/api.js new file mode 100644 index 0000000..0efcec4 --- /dev/null +++ b/webui/src/utils/api.js @@ -0,0 +1,47 @@ +export function fetchData(key, data = {}, method = 'GET') { + const url = new URL(`${window.location.origin}${location.base}api/${key}`) + + Object.keys(data).forEach(key => { + url.searchParams.append(key, data[key]) + }) + + return fetch(url.href, { method }) + .then(response => response.json()) + .catch(error => { + console.error('There has been a problem with your fetch operation:', error) + return Promise.reject(error) + }) +} + +export function sendToServer(key, data) { + const url = new URL(`${window.location.origin}${location.base}api/${key}`) + + Object.keys(data).forEach(key => { + url.searchParams.append(key, data[key]) + }) + + fetch(url.href).catch(error => { + console.error('There has been a problem with your fetch operation:', error) + }) +} + +export function postToServer(endpoint, data) { + const url = new URL(`${window.location.origin}${location.base}api/${endpoint}`) + + return fetch(url, { + body: JSON.stringify(data), + headers: { + 'Content-Type': 'application/json' + }, + method: 'POST' + }) + .then(response => { + if (!response.ok) { + throw new Error('Network response was not ok') + } + return response.json() + }) + .catch(error => { + console.error('There has been a problem with your fetch operation:', error) + }) +} diff --git a/webui/src/utils/countries.js b/webui/src/utils/countries.js new file mode 100644 index 0000000..cc11a85 --- /dev/null +++ b/webui/src/utils/countries.js @@ -0,0 +1,251 @@ +export const COUNTRIES = { + AF: 'Afghanistan', + AX: '\u00C5land Islands', + AL: 'Albania', + DZ: 'Algeria', + AS: 'American Samoa', + AD: 'Andorra', + AO: 'Angola', + AI: 'Anguilla', + AQ: 'Antarctica', + AG: 'Antigua and Barbuda', + AR: 'Argentina', + AM: 'Armenia', + AW: 'Aruba', + AU: 'Australia', + AT: 'Austria', + AZ: 'Azerbaijan', + BS: 'Bahamas', + BH: 'Bahrain', + BD: 'Bangladesh', + BB: 'Barbados', + BY: 'Belarus', + BE: 'Belgium', + BZ: 'Belize', + BJ: 'Benin', + BM: 'Bermuda', + BT: 'Bhutan', + BO: 'Bolivia, Plurinational State of', + BQ: 'Bonaire, Sint Eustatius and Saba', + BA: 'Bosnia and Herzegovina', + BW: 'Botswana', + BV: 'Bouvet Island', + BR: 'Brazil', + IO: 'British Indian Ocean Territory', + BN: 'Brunei Darussalam', + BG: 'Bulgaria', + BF: 'Burkina Faso', + BI: 'Burundi', + KH: 'Cambodia', + CM: 'Cameroon', + CA: 'Canada', + CV: 'Cape Verde', + KY: 'Cayman Islands', + CF: 'Central African Republic', + TD: 'Chad', + CL: 'Chile', + CN: 'China', + CX: 'Christmas Island', + CC: 'Cocos (Keeling) Islands', + CO: 'Colombia', + KM: 'Comoros', + CG: 'Congo', + CD: 'Congo, the Democratic Republic of the', + CK: 'Cook Islands', + CR: 'Costa Rica', + CI: "C\u00F4te d'Ivoire", + HR: 'Croatia', + CU: 'Cuba', + CW: 'Cura\u00E7ao', + CY: 'Cyprus', + CZ: 'Czech Republic', + DK: 'Denmark', + DJ: 'Djibouti', + DM: 'Dominica', + DO: 'Dominican Republic', + EC: 'Ecuador', + EG: 'Egypt', + SV: 'El Salvador', + GQ: 'Equatorial Guinea', + ER: 'Eritrea', + EE: 'Estonia', + ET: 'Ethiopia', + FK: 'Falkland Islands (Malvinas)', + FO: 'Faroe Islands', + FJ: 'Fiji', + FI: 'Finland', + FR: 'France', + GF: 'French Guiana', + PF: 'French Polynesia', + TF: 'French Southern Territories', + GA: 'Gabon', + GM: 'Gambia', + GE: 'Georgia', + DE: 'Germany', + GH: 'Ghana', + GI: 'Gibraltar', + GR: 'Greece', + GL: 'Greenland', + GD: 'Grenada', + GP: 'Guadeloupe', + GU: 'Guam', + GT: 'Guatemala', + GG: 'Guernsey', + GN: 'Guinea', + GW: 'Guinea-Bissau', + GY: 'Guyana', + HT: 'Haiti', + HM: 'Heard Island and McDonald Islands', + VA: 'Holy See (Vatican City State)', + HN: 'Honduras', + HK: 'Hong Kong', + HU: 'Hungary', + IS: 'Iceland', + IN: 'India', + ID: 'Indonesia', + IR: 'Iran, Islamic Republic of', + IQ: 'Iraq', + IE: 'Ireland', + IM: 'Isle of Man', + IL: 'Israel', + IT: 'Italy', + JM: 'Jamaica', + JP: 'Japan', + JE: 'Jersey', + JO: 'Jordan', + KZ: 'Kazakhstan', + KE: 'Kenya', + KI: 'Kiribati', + KP: "Korea, Democratic People's Republic of", + KR: 'Korea, Republic of', + KW: 'Kuwait', + KG: 'Kyrgyzstan', + LA: "Lao People's Democratic Republic", + LV: 'Latvia', + LB: 'Lebanon', + LS: 'Lesotho', + LR: 'Liberia', + LY: 'Libya', + LI: 'Liechtenstein', + LT: 'Lithuania', + LU: 'Luxembourg', + MO: 'Macao', + MK: 'Macedonia, the Former Yugoslav Republic of', + MG: 'Madagascar', + MW: 'Malawi', + MY: 'Malaysia', + MV: 'Maldives', + ML: 'Mali', + MT: 'Malta', + MH: 'Marshall Islands', + MQ: 'Martinique', + MR: 'Mauritania', + MU: 'Mauritius', + YT: 'Mayotte', + MX: 'Mexico', + FM: 'Micronesia, Federated States of', + MD: 'Moldova, Republic of', + MC: 'Monaco', + MN: 'Mongolia', + ME: 'Montenegro', + MS: 'Montserrat', + MA: 'Morocco', + MZ: 'Mozambique', + MM: 'Myanmar', + NA: 'Namibia', + NR: 'Nauru', + NP: 'Nepal', + NL: 'Netherlands', + NC: 'New Caledonia', + NZ: 'New Zealand', + NI: 'Nicaragua', + NE: 'Niger', + NG: 'Nigeria', + NU: 'Niue', + NF: 'Norfolk Island', + MP: 'Northern Mariana Islands', + NO: 'Norway', + OM: 'Oman', + PK: 'Pakistan', + PW: 'Palau', + PS: 'Palestine, State of', + PA: 'Panama', + PG: 'Papua New Guinea', + PY: 'Paraguay', + PE: 'Peru', + PH: 'Philippines', + PN: 'Pitcairn', + PL: 'Poland', + PT: 'Portugal', + PR: 'Puerto Rico', + QA: 'Qatar', + RE: 'R\u00E9union', + RO: 'Romania', + RU: 'Russian Federation', + RW: 'Rwanda', + BL: 'Saint Barth\u00E9lemy', + SH: 'Saint Helena, Ascension and Tristan da Cunha', + KN: 'Saint Kitts and Nevis', + LC: 'Saint Lucia', + MF: 'Saint Martin (French part)', + PM: 'Saint Pierre and Miquelon', + VC: 'Saint Vincent and the Grenadines', + WS: 'Samoa', + SM: 'San Marino', + ST: 'Sao Tome and Principe', + SA: 'Saudi Arabia', + SN: 'Senegal', + RS: 'Serbia', + SC: 'Seychelles', + SL: 'Sierra Leone', + SG: 'Singapore', + SX: 'Sint Maarten (Dutch part)', + SK: 'Slovakia', + SI: 'Slovenia', + SB: 'Solomon Islands', + SO: 'Somalia', + ZA: 'South Africa', + GS: 'South Georgia and the South Sandwich Islands', + SS: 'South Sudan', + ES: 'Spain', + LK: 'Sri Lanka', + SD: 'Sudan', + SR: 'Suriname', + SJ: 'Svalbard and Jan Mayen', + SZ: 'Swaziland', + SE: 'Sweden', + CH: 'Switzerland', + SY: 'Syrian Arab Republic', + TW: 'Taiwan, Province of China', + TJ: 'Tajikistan', + TZ: 'Tanzania, United Republic of', + TH: 'Thailand', + TL: 'Timor-Leste', + TG: 'Togo', + TK: 'Tokelau', + TO: 'Tonga', + TT: 'Trinidad and Tobago', + TN: 'Tunisia', + TR: 'Turkey', + TM: 'Turkmenistan', + TC: 'Turks and Caicos Islands', + TV: 'Tuvalu', + UG: 'Uganda', + UA: 'Ukraine', + AE: 'United Arab Emirates', + GB: 'United Kingdom', + US: 'United States', + UM: 'United States Minor Outlying Islands', + UY: 'Uruguay', + UZ: 'Uzbekistan', + VU: 'Vanuatu', + VE: 'Venezuela, Bolivarian Republic of', + VN: 'Viet Nam', + VG: 'Virgin Islands, British', + VI: 'Virgin Islands, U.S.', + WF: 'Wallis and Futuna', + EH: 'Western Sahara', + YE: 'Yemen', + ZM: 'Zambia', + ZW: 'Zimbabwe' +} diff --git a/webui/src/utils/dates.js b/webui/src/utils/dates.js new file mode 100644 index 0000000..e9a60a5 --- /dev/null +++ b/webui/src/utils/dates.js @@ -0,0 +1,14 @@ +/** + * @param {Date} dateToCheck + * @returns {boolean} The passed date is less than 3 days distant from today, + * therefore it's considered a new release, if referring to a track or album + */ +export function checkNewRelease(dateToCheck) { + const now = new Date() + now.setHours(0, 0, 0, 0) + + dateToCheck = new Date(dateToCheck) + dateToCheck.setDate(dateToCheck.getDate() + 3) + + return now.getTime() <= dateToCheck.getTime() +} diff --git a/webui/src/utils/downloads.js b/webui/src/utils/downloads.js new file mode 100644 index 0000000..129a575 --- /dev/null +++ b/webui/src/utils/downloads.js @@ -0,0 +1,21 @@ +import { postToServer } from '@/utils/api' + +/** + * @param {string} url + * @param {number|null} bitrate + */ +export function sendAddToQueue(url, bitrate = null) { + if (!url) throw new Error('No URL given to sendAddToQueue function!') + + postToServer('addToQueue', { url, bitrate }) +} + +/** + * @param {{ link: string }[]} releases + * @returns {string} + */ +export function aggregateDownloadLinks(releases) { + const links = releases.map(release => release.link) + + return links.join(';') +} diff --git a/webui/src/utils/flags.js b/webui/src/utils/flags.js new file mode 100644 index 0000000..203844f --- /dev/null +++ b/webui/src/utils/flags.js @@ -0,0 +1,43 @@ +import it from 'flag-icon-css/flags/4x3/it.svg' +import gb from 'flag-icon-css/flags/4x3/gb.svg' +import es from 'flag-icon-css/flags/4x3/es.svg' +import de from 'flag-icon-css/flags/4x3/de.svg' +import fr from 'flag-icon-css/flags/4x3/fr.svg' +import id from 'flag-icon-css/flags/4x3/id.svg' +import pt from 'flag-icon-css/flags/4x3/pt.svg' +import br from 'flag-icon-css/flags/4x3/br.svg' +import ru from 'flag-icon-css/flags/4x3/ru.svg' +import tr from 'flag-icon-css/flags/4x3/tr.svg' +import vn from 'flag-icon-css/flags/4x3/vn.svg' +import hr from 'flag-icon-css/flags/4x3/hr.svg' +import ko from 'flag-icon-css/flags/4x3/kr.svg' +import ph from 'flag-icon-css/flags/4x3/ph.svg' +import tw from 'flag-icon-css/flags/4x3/tw.svg' +import pl from 'flag-icon-css/flags/4x3/pl.svg' +import rs from 'flag-icon-css/flags/4x3/rs.svg' +import gr from 'flag-icon-css/flags/4x3/gr.svg' +import th from 'flag-icon-css/flags/4x3/th.svg' +import ar from '@/assets/ar.svg' + +export const flags = { + it: { name: 'Italiano', eng: 'Italian', flag: it }, + en: { name: 'English', eng: 'English', flag: gb }, + es: { name: 'Español', eng: 'Spanish', flag: es }, + de: { name: 'Deutsch', eng: 'German', flag: de }, + fr: { name: 'Français', eng: 'French', flag: fr }, + id: { name: 'Bahasa Indonesia', eng: 'Indonesian', flag: id }, + pt: { name: 'Português', eng: 'Portuguese', flag: pt }, + pt_br: { name: 'Português Brasileiro', eng: 'Portuguese of Brasil', flag: br }, + ru: { name: 'Русский', eng: 'Russian', flag: ru }, + tr: { name: 'Türkçe', eng: 'Turkish', flag: tr }, + vi: { name: 'Tiếng Việt', eng: 'Vietnamese', flag: vn }, + hr: { name: 'Hrvatski Jezik', eng: 'Croatian', flag: hr }, + ar: { name: 'العربية', eng: 'Arabic', flag: ar }, + ko: { name: '한국어', eng: 'Korean', flag: ko }, + fil: { name: 'Wikang Filipino', eng: 'Filipino', flag: ph }, + zh_tw: { name: '漢語', eng: 'Chinese', flag: tw }, + pl: { name: 'Polszczyzna', eng: 'Polish', flag: pl }, + el: { name: 'ελληνικά', eng: 'Greek', flag: gr }, + sr: { name: 'српски језик', eng: 'Serbian', flag: rs }, + th: { name: 'ไทย', eng: 'Thai', flag: th } +} diff --git a/webui/src/utils/forms.js b/webui/src/utils/forms.js new file mode 100644 index 0000000..c045ee7 --- /dev/null +++ b/webui/src/utils/forms.js @@ -0,0 +1,12 @@ +/** + * @param {HTMLFormElement} formEl + * @returns {function(item: string): {}} + * @since 1.6.1 + */ +export const getFormItem = formEl => item => { + const element = formEl.elements.namedItem(item) + + return { + [item]: element.value + } +} diff --git a/webui/src/utils/socket.js b/webui/src/utils/socket.js new file mode 100644 index 0000000..4e245c4 --- /dev/null +++ b/webui/src/utils/socket.js @@ -0,0 +1,37 @@ +class CustomSocket extends WebSocket { + constructor(args) { + super(args) + this.listeners = {} + } + + emit(key, data) { + if (this.readyState !== WebSocket.OPEN) return false + + this.send(JSON.stringify({ key, data })) + } + + on(key, cb) { + if (!Object.keys(this.listeners).includes(key)) { + // console.log('on:', key) + this.listeners[key] = cb + + this.addEventListener('message', event => { + const messageData = JSON.parse(event.data) + + if (messageData.key === key) { + cb(messageData.data) + } + }) + } + } + + off(key) { + if (Object.keys(this.listeners).includes(key)) { + // console.log('off:', key) + this.removeEventListener('message', this.listeners[key]) + delete this.listeners[key] + } + } +} + +export const socket = new CustomSocket((location.protocol === 'https:' ? 'wss://' : 'ws://') + location.host + location.base) diff --git a/webui/src/utils/texts.js b/webui/src/utils/texts.js new file mode 100644 index 0000000..338a1da --- /dev/null +++ b/webui/src/utils/texts.js @@ -0,0 +1,4 @@ +/** + * @param {string} text + */ +export const upperCaseFirstLowerCaseRest = text => text.charAt(0).toUpperCase() + text.slice(1).toLowerCase() diff --git a/webui/src/utils/toasts.js b/webui/src/utils/toasts.js new file mode 100644 index 0000000..7eacf13 --- /dev/null +++ b/webui/src/utils/toasts.js @@ -0,0 +1,118 @@ +import Toastify from 'toastify-js' +import 'toastify-js/src/toastify.css' +import '@/styles/css/toasts.css' + +const sharedOptions = { + gravity: 'bottom', + position: 'left' +} + +const toastsWithId = {} + +export const toast = function (msg, icon = null, dismiss = true, id = null) { + if (toastsWithId[id]) { + const toastObj = toastsWithId[id] + + const toastElement = document.querySelectorAll(`div.toastify[toast_id=${id}]`) + + if (msg) { + toastElement.forEach(toast => { + const messages = toast.querySelectorAll('.toast-message') + + messages.forEach(message => { + message.innerText = msg + }) + }) + } + + if (icon) { + const iconNode = document.createElement('span') + iconNode.classList.add('toast-icon') + + if (icon === 'loading') { + const loader = document.createElement('div') + loader.classList.add('circle-loader') + iconNode.appendChild(loader) + } else { + const materialIcon = document.createElement('i') + materialIcon.classList.add('material-icons') + materialIcon.appendChild(document.createTextNode(icon)) + iconNode.appendChild(materialIcon) + } + + toastElement.forEach(toast => { + const icons = toast.querySelectorAll('.toast-icon') + + icons.forEach(toastIcon => { + toastIcon.parentNode.replaceChild(iconNode, toastIcon) + }) + }) + } + if (dismiss !== null && dismiss) { + toastElement.forEach(toast => { + toast.classList.add('dismissable') + }) + + setTimeout(() => { + toastObj.hideToast() + + delete toastsWithId[id] + }, 3000) + } + } else { + const iconNode = document.createElement('span') + iconNode.classList.add('toast-icon') + if (icon == null) { + iconNode.appendChild(document.createTextNode('')) + } else if (icon === 'loading') { + const loader = document.createElement('div') + loader.classList.add('circle-loader') + iconNode.appendChild(loader) + } else { + const materialIcon = document.createElement('i') + materialIcon.classList.add('material-icons') + materialIcon.appendChild(document.createTextNode(icon)) + iconNode.appendChild(materialIcon) + } + const messageNode = document.createElement('span') + messageNode.classList.add('toast-message') + messageNode.appendChild(document.createTextNode(msg)) + + const toastNode = document.createElement('toast') + toastNode.appendChild(iconNode) + toastNode.appendChild(messageNode) + + const toastObj = Toastify({ + ...sharedOptions, + node: toastNode, + duration: dismiss ? 3000 : 0, + className: dismiss ? 'dismissable' : '', + onClick() { + let dismissable = true + + if (id) { + const toastClasses = document.querySelector(`div.toastify[toast_id=${id}]`).classList + + if (toastClasses) { + dismissable = Array.prototype.slice.call(toastClasses).includes('dismissable') + } + } + if (toastObj && dismissable) { + toastObj.hideToast() + + if (id) { + delete toastsWithId[id] + } + } + }, + offset: { + x: localStorage.getItem('slimSidebar') === 'true' ? '3rem' : '14rem' + } + }).showToast() + if (id) { + toastsWithId[id] = toastObj + + toastObj.toastElement.setAttribute('toast_id', id) + } + } +} diff --git a/webui/src/utils/utils.js b/webui/src/utils/utils.js new file mode 100644 index 0000000..9059b00 --- /dev/null +++ b/webui/src/utils/utils.js @@ -0,0 +1,157 @@ +/** + * Climbs the DOM until the root is reached, storing every node passed. + * @param {HTMLElement} el + * @return {Array} Contains all the nodes between el and the root + * @since 0.0.0 + */ +export function generatePath(el) { + if (!el) { + throw new Error('No element passed to the generatePath function!') + } + + const path = [el] + + while ((el = el.parentNode) && el !== document) { + path.push(el) + } + + return path +} + +/** + * @param {string} text + * @returns {boolean} + * @since 0.0.0 + */ +export function isValidURL(text) { + const lowerCaseText = text.toLowerCase() + + if (lowerCaseText.startsWith('http')) { + if ( + lowerCaseText.includes('deezer.com') || + lowerCaseText.includes('deezer.page.link') || + lowerCaseText.includes('open.spotify.com') || + lowerCaseText.includes('link.tospotify.com') + ) { + return true + } + } else if (lowerCaseText.startsWith('spotify:')) { + return true + } + return false +} + +/** + * @param {number} duration + * @returns {string} + * @since 0.0.0 + */ +export function convertDuration(duration) { + const mm = Math.floor(duration / 60) + + // Convert from seconds only to mm:ss format + let ss = duration - mm * 60 // Add leading zero if ss < 0 + + if (ss < 10) { + ss = '0' + ss + } + + return mm + ':' + ss +} + +/** + * @param {number} duration + * @returns {[number, number, number]} + * @since 0.0.0 + */ +export function convertDurationSeparated(duration) { + let mm = Math.floor(duration / 60) + + const hh = Math.floor(mm / 60) + const ss = duration - mm * 60 + + mm -= hh * 60 + + return [hh, mm, ss] +} + +/** + * @param {number} x + * @returns {string} + * @since 0.0.0 + * @deprecated + */ +export const numberWithDots = x => x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, '.') + +// On scroll event, returns currentTarget = null +// Probably on other events too +export function debounce(func, wait, immediate) { + let timeout + return function () { + const context = this + const args = arguments + const later = function () { + timeout = null + if (!immediate) func.apply(context, args) + } + const callNow = immediate && !timeout + clearTimeout(timeout) + timeout = setTimeout(later, wait) + if (callNow) func.apply(context, args) + } +} + +/** + * Workaround to copy to the clipboard cross-OS by generating a + * ghost input and copying the passed String + * + * @param {string} text Text to copy + * @returns void + * @since 0.0.0 + */ +export function copyToClipboard(text) { + const ghostInput = document.createElement('input') + + document.body.appendChild(ghostInput) + ghostInput.setAttribute('type', 'text') + ghostInput.setAttribute('value', text) + ghostInput.select() + ghostInput.setSelectionRange(0, 99999) + document.execCommand('copy') + ghostInput.remove() +} + +/** + * @param {object|array} obj + * @param {...any} props + * @returns {any|null} property requested + * @since 0.0.0 + */ +export function getPropertyWithFallback(obj, ...props) { + for (const prop of props) { + // Example: this.is.an.example + const hasDotNotation = /\./.test(prop) + + // Searching the properties in the object + const valueToTest = hasDotNotation + ? prop.split('.').reduce((o, i) => { + if (o) return o[i] + return undefined + }, obj) + : obj[prop] + + if (typeof valueToTest !== 'undefined') { + return valueToTest + } + } + + return null +} + +export default { + isValidURL, + convertDuration, + convertDurationSeparated, + numberWithDots, + debounce +} diff --git a/webui/tailwind.config.js b/webui/tailwind.config.js new file mode 100644 index 0000000..1a9a1a9 --- /dev/null +++ b/webui/tailwind.config.js @@ -0,0 +1,64 @@ +const defaultTheme = require('tailwindcss/defaultTheme') + +module.exports = { + future: { + removeDeprecatedGapUtilities: true, + purgeLayersByDefault: true + }, + purge: { + // https://medium.com/@kyis/vue-tailwind-purgecss-the-right-way-c70d04461475 + content: [`./public/**/*.html`, `./public/**/*.ejs`, `./src/**/*.vue`, `./src/**/*.js`], + defaultExtractor(content) { + const contentWithoutStyleBlocks = content.replace(//gi, '') + return contentWithoutStyleBlocks.match(/[A-Za-z0-9-_/:]*[A-Za-z0-9-_/]+/g) || [] + }, + whitelist: [], + whitelistPatterns: [ + /-(leave|enter|appear)(|-(to|from|active))$/, + /^(?!(|.*?:)cursor-move).+-move$/, + /^router-link(|-exact)-active$/ + ] + }, + theme: { + extend: { + colors: { + grayscale: { + 100: 'hsl(0, 0%, 10%)', + 200: 'hsl(0, 0%, 20%)', + 300: 'hsl(0, 0%, 30%)', + 400: 'hsl(0, 0%, 40%)', + 500: 'hsl(0, 0%, 50%)', + 600: 'hsl(0, 0%, 60%)', + 700: 'hsl(0, 0%, 70%)', + 800: 'hsl(0, 0%, 80%)', + 840: 'hsl(0, 0%, 84%)', // Remove maybe + 870: 'hsl(0, 0%, 87%)', // Remove maybe + 900: 'hsl(0, 0%, 90%)', + 930: 'hsl(0, 0%, 93%)' // Remove maybe + }, + primary: 'hsl(210, 100%, 52%)', + background: { + main: 'var(--main-background)', + secondary: 'var(--secondary-background)' + }, + foreground: 'var(--foreground)', + panels: { + bg: 'var(--panels-background)' + } + }, + fontFamily: { + sans: ['Open Sans', ...defaultTheme.fontFamily.sans] + } + } + }, + variants: { + textColor: ({ after }) => after(['group-hover']), + margin: ({ before }) => before(['first']), + borderWidth: ['responsive', 'first', 'hover', 'focus'], + cursor: ['responsive', 'hover'] + }, + corePlugins: { + preflight: false + }, + plugins: [] +} diff --git a/webui/tests/testlang.js b/webui/tests/testlang.js new file mode 100644 index 0000000..85b6fbc --- /dev/null +++ b/webui/tests/testlang.js @@ -0,0 +1,52 @@ +async function loadLang(lang_id) { + let language_module + const result = [] + try { + language_module = await import(`../src/lang/${lang_id}.mjs`) + language_module = language_module.default + } catch (e) { + language_module = {} + } + function parseObject(obj, root = '') { + for (const [key, value] of Object.entries(obj)) { + if (typeof value === 'string') { + result.push(root + key) + } else { + parseObject(value, root + key + '.') + } + } + } + parseObject(language_module) + return result +} + +async function testLang(lang_id) { + const baseLangFile = await loadLang('en') + const comparedLangFile = await loadLang(lang_id) + + if (comparedLangFile.length === 0) { + console.log(`Language file ${lang_id} doesn't exist!`) + return + } + + console.log('\nMissing Keys:') + baseLangFile.forEach(key => { + if (!comparedLangFile.includes(key)) console.log(key) + }) + + console.log('\nExtra Keys:') + comparedLangFile.forEach(key => { + if (!baseLangFile.includes(key)) console.log(key) + }) +} + +;(async () => { + const args = process.argv.slice(2) + if (args.length !== 1) { + console.log('Usage:\nyarn testlang [COUNTRY_ID]\n') + return + } + console.log(`Testing language file ${args[0]}`) + await testLang(args[0]) + console.log('') +})() diff --git a/webui/tests/unit/utils/dates.spec.js b/webui/tests/unit/utils/dates.spec.js new file mode 100644 index 0000000..56ea726 --- /dev/null +++ b/webui/tests/unit/utils/dates.spec.js @@ -0,0 +1,16 @@ +import { checkNewRelease } from '../../../src/utils/dates.js' + +describe('date utils', () => { + describe('checkNewRelease', () => { + it("returns a positive result checking today's date", () => { + expect(checkNewRelease(new Date())).toBe(true) + }) + + it("returns a negative result checking a week ago's date", () => { + const dateToCheck = new Date() + dateToCheck.setDate(dateToCheck.getDate() - 7) + + expect(checkNewRelease(dateToCheck)).toBe(false) + }) + }) +}) diff --git a/webui/tests/unit/utils/downloads.spec.js b/webui/tests/unit/utils/downloads.spec.js new file mode 100644 index 0000000..f6395d7 --- /dev/null +++ b/webui/tests/unit/utils/downloads.spec.js @@ -0,0 +1,12 @@ +import { aggregateDownloadLinks } from '../../../src/utils/downloads' + +describe('download utils', () => { + describe('aggregateDownloadLinks', () => { + it('merges links into a single string', () => { + const release = { link: 'abcde' } + const aggregated = aggregateDownloadLinks([release, release]) + + expect(aggregated).toBe('abcde;abcde') + }) + }) +}) diff --git a/webui/tests/unit/utils/texts.spec.js b/webui/tests/unit/utils/texts.spec.js new file mode 100644 index 0000000..eefafff --- /dev/null +++ b/webui/tests/unit/utils/texts.spec.js @@ -0,0 +1,17 @@ +import { upperCaseFirstLowerCaseRest } from '../../../src/utils/texts' + +describe('texts utils', () => { + describe('upperCaseFirstLowerCaseRest', () => { + it('converts a full uppercase string', () => { + expect(upperCaseFirstLowerCaseRest('TEST STRING')).toBe('Test string') + }) + + it('converts a full lowercase string', () => { + expect(upperCaseFirstLowerCaseRest('test string')).toBe('Test string') + }) + + it('converts a mixed string', () => { + expect(upperCaseFirstLowerCaseRest("i wOn'T woRK")).toBe("I won't work") + }) + }) +}) diff --git a/webui/tests/unit/utils/utils.spec.js b/webui/tests/unit/utils/utils.spec.js new file mode 100644 index 0000000..0e64e59 --- /dev/null +++ b/webui/tests/unit/utils/utils.spec.js @@ -0,0 +1,33 @@ +import { isValidURL, convertDuration, convertDurationSeparated } from '../../../src/utils/utils' + +describe('utils utils (needs refactor)', () => { + describe('isValidURL', () => { + it('returns a positive result with all supported URLs', () => { + expect(isValidURL('https://www.deezer.com')).toBe(true) + expect(isValidURL('https://deezer.page.link')).toBe(true) + expect(isValidURL('https://open.spotify.com')).toBe(true) + expect(isValidURL('https://link.tospotify.com')).toBe(true) + expect(isValidURL('spotify:something')).toBe(true) + }) + + it('returns a negative result with a not supported URL', () => { + expect(isValidURL('https://www.google.com')).toBe(false) + }) + }) + + describe('convertDuration', () => { + it('converts seconds in the correct format', () => { + expect(convertDuration(120)).toBe('2:00') + expect(convertDuration(60)).toBe('1:00') + expect(convertDuration(30)).toBe('0:30') + }) + }) + + describe('convertDurationSeparated', () => { + it('converts seconds in the correct format', () => { + expect(convertDurationSeparated(120)).toStrictEqual([0, 2, 0]) + expect(convertDurationSeparated(60)).toStrictEqual([0, 1, 0]) + expect(convertDurationSeparated(30)).toStrictEqual([0, 0, 30]) + }) + }) +}) diff --git a/webui/yarn.lock b/webui/yarn.lock new file mode 100644 index 0000000..33d08b4 --- /dev/null +++ b/webui/yarn.lock @@ -0,0 +1,5852 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@ampproject/remapping@^2.1.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d" + integrity sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w== + dependencies: + "@jridgewell/gen-mapping" "^0.1.0" + "@jridgewell/trace-mapping" "^0.3.9" + +"@babel/code-frame@7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f" + integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw== + dependencies: + "@babel/highlight" "^7.10.4" + +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.14.5", "@babel/code-frame@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a" + integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q== + dependencies: + "@babel/highlight" "^7.18.6" + +"@babel/compat-data@^7.20.0": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.20.5.tgz#86f172690b093373a933223b4745deeb6049e733" + integrity sha512-KZXo2t10+/jxmkhNXc7pZTqRvSOIvVv/+lJwHS+B2rErwOyjuVRh60yVpb7liQ1U5t7lLJ1bz+t8tSypUZdm0g== + +"@babel/core@7.15.0": + version "7.15.0" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.15.0.tgz#749e57c68778b73ad8082775561f67f5196aafa8" + integrity sha512-tXtmTminrze5HEUPn/a0JtOzzfp0nk+UEXQ/tqIJo3WDGypl/2OFQEMll/zSFU8f/lfmfLXvTaORHF3cfXIQMw== + dependencies: + "@babel/code-frame" "^7.14.5" + "@babel/generator" "^7.15.0" + "@babel/helper-compilation-targets" "^7.15.0" + "@babel/helper-module-transforms" "^7.15.0" + "@babel/helpers" "^7.14.8" + "@babel/parser" "^7.15.0" + "@babel/template" "^7.14.5" + "@babel/traverse" "^7.15.0" + "@babel/types" "^7.15.0" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.1.2" + semver "^6.3.0" + source-map "^0.5.0" + +"@babel/core@^7.1.0", "@babel/core@^7.12.16", "@babel/core@^7.12.3", "@babel/core@^7.7.2", "@babel/core@^7.8.0": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.20.5.tgz#45e2114dc6cd4ab167f81daf7820e8fa1250d113" + integrity sha512-UdOWmk4pNWTm/4DlPUl/Pt4Gz4rcEMb7CY0Y3eJl5Yz1vI8ZJGmHWaVE55LoxRjdpx0z259GE9U5STA9atUinQ== + dependencies: + "@ampproject/remapping" "^2.1.0" + "@babel/code-frame" "^7.18.6" + "@babel/generator" "^7.20.5" + "@babel/helper-compilation-targets" "^7.20.0" + "@babel/helper-module-transforms" "^7.20.2" + "@babel/helpers" "^7.20.5" + "@babel/parser" "^7.20.5" + "@babel/template" "^7.18.10" + "@babel/traverse" "^7.20.5" + "@babel/types" "^7.20.5" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.1" + semver "^6.3.0" + +"@babel/eslint-parser@^7.12.16": + version "7.19.1" + resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.19.1.tgz#4f68f6b0825489e00a24b41b6a1ae35414ecd2f4" + integrity sha512-AqNf2QWt1rtu2/1rLswy6CDP7H9Oh3mMhk177Y67Rg8d7RD9WfOLLv8CGn6tisFvS2htm86yIe1yLF6I1UDaGQ== + dependencies: + "@nicolo-ribaudo/eslint-scope-5-internals" "5.1.1-v1" + eslint-visitor-keys "^2.1.0" + semver "^6.3.0" + +"@babel/generator@^7.15.0", "@babel/generator@^7.20.5", "@babel/generator@^7.7.2": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.20.5.tgz#cb25abee3178adf58d6814b68517c62bdbfdda95" + integrity sha512-jl7JY2Ykn9S0yj4DQP82sYvPU+T3g0HFcWTqDLqiuA9tGRNIj9VfbtXGAYTTkyNEnQk1jkMGOdYka8aG/lulCA== + dependencies: + "@babel/types" "^7.20.5" + "@jridgewell/gen-mapping" "^0.3.2" + jsesc "^2.5.1" + +"@babel/helper-compilation-targets@^7.15.0", "@babel/helper-compilation-targets@^7.20.0": + version "7.20.0" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.0.tgz#6bf5374d424e1b3922822f1d9bdaa43b1a139d0a" + integrity sha512-0jp//vDGp9e8hZzBc6N/KwA5ZK3Wsm/pfm4CrY7vzegkVxc65SgSn6wYOnwHe9Js9HRQ1YTCKLGPzDtaS3RoLQ== + dependencies: + "@babel/compat-data" "^7.20.0" + "@babel/helper-validator-option" "^7.18.6" + browserslist "^4.21.3" + semver "^6.3.0" + +"@babel/helper-environment-visitor@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz#0c0cee9b35d2ca190478756865bb3528422f51be" + integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg== + +"@babel/helper-function-name@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz#941574ed5390682e872e52d3f38ce9d1bef4648c" + integrity sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w== + dependencies: + "@babel/template" "^7.18.10" + "@babel/types" "^7.19.0" + +"@babel/helper-hoist-variables@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678" + integrity sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-module-imports@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz#1e3ebdbbd08aad1437b428c50204db13c5a3ca6e" + integrity sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-module-transforms@^7.15.0", "@babel/helper-module-transforms@^7.20.2": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.20.2.tgz#ac53da669501edd37e658602a21ba14c08748712" + integrity sha512-zvBKyJXRbmK07XhMuujYoJ48B5yvvmM6+wcpv6Ivj4Yg6qO7NOZOSnvZN9CRl1zz1Z4cKf8YejmCMh8clOoOeA== + dependencies: + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-module-imports" "^7.18.6" + "@babel/helper-simple-access" "^7.20.2" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/helper-validator-identifier" "^7.19.1" + "@babel/template" "^7.18.10" + "@babel/traverse" "^7.20.1" + "@babel/types" "^7.20.2" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.19.0", "@babel/helper-plugin-utils@^7.8.0": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz#d1b9000752b18d0877cff85a5c376ce5c3121629" + integrity sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ== + +"@babel/helper-simple-access@^7.14.8", "@babel/helper-simple-access@^7.20.2": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz#0ab452687fe0c2cfb1e2b9e0015de07fc2d62dd9" + integrity sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA== + dependencies: + "@babel/types" "^7.20.2" + +"@babel/helper-split-export-declaration@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz#7367949bc75b20c6d5a5d4a97bba2824ae8ef075" + integrity sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-string-parser@^7.19.4": + version "7.19.4" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz#38d3acb654b4701a9b77fb0615a96f775c3a9e63" + integrity sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw== + +"@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.19.1": + version "7.19.1" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" + integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== + +"@babel/helper-validator-option@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8" + integrity sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw== + +"@babel/helpers@^7.14.8", "@babel/helpers@^7.20.5": + version "7.20.6" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.20.6.tgz#e64778046b70e04779dfbdf924e7ebb45992c763" + integrity sha512-Pf/OjgfgFRW5bApskEz5pvidpim7tEDPlFtKcNRXWmfHGn9IEI2W2flqRQXTFb7gIPTyK++N6rVHuwKut4XK6w== + dependencies: + "@babel/template" "^7.18.10" + "@babel/traverse" "^7.20.5" + "@babel/types" "^7.20.5" + +"@babel/highlight@^7.10.4", "@babel/highlight@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf" + integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g== + dependencies: + "@babel/helper-validator-identifier" "^7.18.6" + chalk "^2.0.0" + js-tokens "^4.0.0" + +"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.15.0", "@babel/parser@^7.18.10", "@babel/parser@^7.20.5": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.20.5.tgz#7f3c7335fe417665d929f34ae5dceae4c04015e8" + integrity sha512-r27t/cy/m9uKLXQNWWebeCUHgnAZq0CpG1OwKRxzJMP1vpSU4bSIK2hq+/cp0bQxetkXx38n09rNu8jVkcK/zA== + +"@babel/plugin-syntax-async-generators@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" + integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-bigint@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea" + integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-class-properties@^7.8.3": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" + integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== + dependencies: + "@babel/helper-plugin-utils" "^7.12.13" + +"@babel/plugin-syntax-import-meta@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" + integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-json-strings@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" + integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-logical-assignment-operators@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" + integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" + integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-numeric-separator@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" + integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-object-rest-spread@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-catch-binding@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" + integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-chaining@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" + integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-top-level-await@^7.8.3": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" + integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-typescript@^7.7.2": + version "7.20.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.20.0.tgz#4e9a0cfc769c85689b77a2e642d24e9f697fc8c7" + integrity sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.19.0" + +"@babel/plugin-transform-modules-commonjs@7.15.0": + version "7.15.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.15.0.tgz#3305896e5835f953b5cdb363acd9e8c2219a5281" + integrity sha512-3H/R9s8cXcOGE8kgMlmjYYC9nqr5ELiPkJn4q0mypBrjhYQoc+5/Maq69vV4xRPWnkzZuwJPf5rArxpB/35Cig== + dependencies: + "@babel/helper-module-transforms" "^7.15.0" + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-simple-access" "^7.14.8" + babel-plugin-dynamic-import-node "^2.3.3" + +"@babel/runtime@^7.0.0-beta.46": + version "7.20.6" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.20.6.tgz#facf4879bfed9b5326326273a64220f099b0fce3" + integrity sha512-Q+8MqP7TiHMWzSfwiJwXCjyf4GYA4Dgw3emg/7xmwsdLJOZUp+nMqcOwOzzYheuM1rhDu8FSj2l0aoMygEuXuA== + dependencies: + regenerator-runtime "^0.13.11" + +"@babel/template@^7.14.5", "@babel/template@^7.18.10", "@babel/template@^7.3.3": + version "7.18.10" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.18.10.tgz#6f9134835970d1dbf0835c0d100c9f38de0c5e71" + integrity sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA== + dependencies: + "@babel/code-frame" "^7.18.6" + "@babel/parser" "^7.18.10" + "@babel/types" "^7.18.10" + +"@babel/traverse@^7.15.0", "@babel/traverse@^7.20.1", "@babel/traverse@^7.20.5", "@babel/traverse@^7.7.2": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.20.5.tgz#78eb244bea8270fdda1ef9af22a5d5e5b7e57133" + integrity sha512-WM5ZNN3JITQIq9tFZaw1ojLU3WgWdtkxnhM1AegMS+PvHjkM5IXjmYEGY7yukz5XS4sJyEf2VzWjI8uAavhxBQ== + dependencies: + "@babel/code-frame" "^7.18.6" + "@babel/generator" "^7.20.5" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-function-name" "^7.19.0" + "@babel/helper-hoist-variables" "^7.18.6" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/parser" "^7.20.5" + "@babel/types" "^7.20.5" + debug "^4.1.0" + globals "^11.1.0" + +"@babel/types@^7.0.0", "@babel/types@^7.15.0", "@babel/types@^7.18.10", "@babel/types@^7.18.6", "@babel/types@^7.19.0", "@babel/types@^7.20.2", "@babel/types@^7.20.5", "@babel/types@^7.3.0", "@babel/types@^7.3.3": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.20.5.tgz#e206ae370b5393d94dfd1d04cd687cace53efa84" + integrity sha512-c9fst/h2/dcF7H+MJKZ2T0KjEQ8hY/BNnDk/H3XY8C4Aw/eWQXWn/lWntHF9ooUBnGmEvbfGrTgLWc+um0YDUg== + dependencies: + "@babel/helper-string-parser" "^7.19.4" + "@babel/helper-validator-identifier" "^7.19.1" + to-fast-properties "^2.0.0" + +"@bcoe/v8-coverage@^0.2.3": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" + integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== + +"@eslint/eslintrc@^0.4.3": + version "0.4.3" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz#9e42981ef035beb3dd49add17acb96e8ff6f394c" + integrity sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw== + dependencies: + ajv "^6.12.4" + debug "^4.1.1" + espree "^7.3.0" + globals "^13.9.0" + ignore "^4.0.6" + import-fresh "^3.2.1" + js-yaml "^3.13.1" + minimatch "^3.0.4" + strip-json-comments "^3.1.1" + +"@fullhuman/postcss-purgecss@^2.1.2": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@fullhuman/postcss-purgecss/-/postcss-purgecss-2.3.0.tgz#50a954757ec78696615d3e118e3fee2d9291882e" + integrity sha512-qnKm5dIOyPGJ70kPZ5jiz0I9foVOic0j+cOzNDoo8KoCf6HjicIZ99UfO2OmE7vCYSKAAepEwJtNzpiiZAh9xw== + dependencies: + postcss "7.0.32" + purgecss "^2.3.0" + +"@humanwhocodes/config-array@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.5.0.tgz#1407967d4c6eecd7388f83acf1eaf4d0c6e58ef9" + integrity sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg== + dependencies: + "@humanwhocodes/object-schema" "^1.2.0" + debug "^4.1.1" + minimatch "^3.0.4" + +"@humanwhocodes/object-schema@^1.2.0": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" + integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== + +"@istanbuljs/load-nyc-config@^1.0.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" + integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== + dependencies: + camelcase "^5.3.1" + find-up "^4.1.0" + get-package-type "^0.1.0" + js-yaml "^3.13.1" + resolve-from "^5.0.0" + +"@istanbuljs/schema@^0.1.2": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" + integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== + +"@jest/console@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-27.5.1.tgz#260fe7239602fe5130a94f1aa386eff54b014bba" + integrity sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg== + dependencies: + "@jest/types" "^27.5.1" + "@types/node" "*" + chalk "^4.0.0" + jest-message-util "^27.5.1" + jest-util "^27.5.1" + slash "^3.0.0" + +"@jest/core@^27.0.6", "@jest/core@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-27.5.1.tgz#267ac5f704e09dc52de2922cbf3af9edcd64b626" + integrity sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ== + dependencies: + "@jest/console" "^27.5.1" + "@jest/reporters" "^27.5.1" + "@jest/test-result" "^27.5.1" + "@jest/transform" "^27.5.1" + "@jest/types" "^27.5.1" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + emittery "^0.8.1" + exit "^0.1.2" + graceful-fs "^4.2.9" + jest-changed-files "^27.5.1" + jest-config "^27.5.1" + jest-haste-map "^27.5.1" + jest-message-util "^27.5.1" + jest-regex-util "^27.5.1" + jest-resolve "^27.5.1" + jest-resolve-dependencies "^27.5.1" + jest-runner "^27.5.1" + jest-runtime "^27.5.1" + jest-snapshot "^27.5.1" + jest-util "^27.5.1" + jest-validate "^27.5.1" + jest-watcher "^27.5.1" + micromatch "^4.0.4" + rimraf "^3.0.0" + slash "^3.0.0" + strip-ansi "^6.0.0" + +"@jest/environment@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-27.5.1.tgz#d7425820511fe7158abbecc010140c3fd3be9c74" + integrity sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA== + dependencies: + "@jest/fake-timers" "^27.5.1" + "@jest/types" "^27.5.1" + "@types/node" "*" + jest-mock "^27.5.1" + +"@jest/fake-timers@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-27.5.1.tgz#76979745ce0579c8a94a4678af7a748eda8ada74" + integrity sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ== + dependencies: + "@jest/types" "^27.5.1" + "@sinonjs/fake-timers" "^8.0.1" + "@types/node" "*" + jest-message-util "^27.5.1" + jest-mock "^27.5.1" + jest-util "^27.5.1" + +"@jest/globals@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-27.5.1.tgz#7ac06ce57ab966566c7963431cef458434601b2b" + integrity sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q== + dependencies: + "@jest/environment" "^27.5.1" + "@jest/types" "^27.5.1" + expect "^27.5.1" + +"@jest/reporters@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-27.5.1.tgz#ceda7be96170b03c923c37987b64015812ffec04" + integrity sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw== + dependencies: + "@bcoe/v8-coverage" "^0.2.3" + "@jest/console" "^27.5.1" + "@jest/test-result" "^27.5.1" + "@jest/transform" "^27.5.1" + "@jest/types" "^27.5.1" + "@types/node" "*" + chalk "^4.0.0" + collect-v8-coverage "^1.0.0" + exit "^0.1.2" + glob "^7.1.2" + graceful-fs "^4.2.9" + istanbul-lib-coverage "^3.0.0" + istanbul-lib-instrument "^5.1.0" + istanbul-lib-report "^3.0.0" + istanbul-lib-source-maps "^4.0.0" + istanbul-reports "^3.1.3" + jest-haste-map "^27.5.1" + jest-resolve "^27.5.1" + jest-util "^27.5.1" + jest-worker "^27.5.1" + slash "^3.0.0" + source-map "^0.6.0" + string-length "^4.0.1" + terminal-link "^2.0.0" + v8-to-istanbul "^8.1.0" + +"@jest/source-map@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-27.5.1.tgz#6608391e465add4205eae073b55e7f279e04e8cf" + integrity sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg== + dependencies: + callsites "^3.0.0" + graceful-fs "^4.2.9" + source-map "^0.6.0" + +"@jest/test-result@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-27.5.1.tgz#56a6585fa80f7cdab72b8c5fc2e871d03832f5bb" + integrity sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag== + dependencies: + "@jest/console" "^27.5.1" + "@jest/types" "^27.5.1" + "@types/istanbul-lib-coverage" "^2.0.0" + collect-v8-coverage "^1.0.0" + +"@jest/test-sequencer@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-27.5.1.tgz#4057e0e9cea4439e544c6353c6affe58d095745b" + integrity sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ== + dependencies: + "@jest/test-result" "^27.5.1" + graceful-fs "^4.2.9" + jest-haste-map "^27.5.1" + jest-runtime "^27.5.1" + +"@jest/transform@^27.0.6", "@jest/transform@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-27.5.1.tgz#6c3501dcc00c4c08915f292a600ece5ecfe1f409" + integrity sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw== + dependencies: + "@babel/core" "^7.1.0" + "@jest/types" "^27.5.1" + babel-plugin-istanbul "^6.1.1" + chalk "^4.0.0" + convert-source-map "^1.4.0" + fast-json-stable-stringify "^2.0.0" + graceful-fs "^4.2.9" + jest-haste-map "^27.5.1" + jest-regex-util "^27.5.1" + jest-util "^27.5.1" + micromatch "^4.0.4" + pirates "^4.0.4" + slash "^3.0.0" + source-map "^0.6.1" + write-file-atomic "^3.0.0" + +"@jest/types@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.6.2.tgz#bef5a532030e1d88a2f5a6d933f84e97226ed48e" + integrity sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^15.0.0" + chalk "^4.0.0" + +"@jest/types@^27.0.6", "@jest/types@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-27.5.1.tgz#3c79ec4a8ba61c170bf937bcf9e98a9df175ec80" + integrity sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^16.0.0" + chalk "^4.0.0" + +"@jridgewell/gen-mapping@^0.1.0": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz#e5d2e450306a9491e3bd77e323e38d7aff315996" + integrity sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w== + dependencies: + "@jridgewell/set-array" "^1.0.0" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@jridgewell/gen-mapping@^0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" + integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== + dependencies: + "@jridgewell/set-array" "^1.0.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/resolve-uri@3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" + integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== + +"@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" + integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== + +"@jridgewell/sourcemap-codec@1.4.14", "@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.14" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" + integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== + +"@jridgewell/trace-mapping@^0.3.9": + version "0.3.17" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985" + integrity sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g== + dependencies: + "@jridgewell/resolve-uri" "3.1.0" + "@jridgewell/sourcemap-codec" "1.4.14" + +"@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1": + version "5.1.1-v1" + resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz#dbf733a965ca47b1973177dc0bb6c889edcfb129" + integrity sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg== + dependencies: + eslint-scope "5.1.1" + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@nuxtjs/eslint-config@6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/@nuxtjs/eslint-config/-/eslint-config-6.0.1.tgz#305450a71e362c26f99b3a7130be960015a96c9b" + integrity sha512-NISrmMx4J2usVDVLG7WFwTdfQaznHf/b2aKTb1o0TCxxXdY30UHLqEH+3MqpjY+0+UPM06YswFmOBjOg5y2BXQ== + dependencies: + eslint-config-standard "^16.0.3" + eslint-plugin-import "^2.23.3" + eslint-plugin-jest "^24.3.6" + eslint-plugin-node "^11.1.0" + eslint-plugin-promise "^5.1.0" + eslint-plugin-standard "^4.1.0" + eslint-plugin-unicorn "^28.0.2" + eslint-plugin-vue "^7.9.0" + +"@rollup/plugin-alias@3.1.5": + version "3.1.5" + resolved "https://registry.yarnpkg.com/@rollup/plugin-alias/-/plugin-alias-3.1.5.tgz#73356a3a1eab2e1e2fd952f9f53cd89fc740d952" + integrity sha512-yzUaSvCC/LJPbl9rnzX3HN7vy0tq7EzHoEiQl1ofh4n5r2Rd5bj/+zcJgaGA76xbw95/JjWQyvHg9rOJp2y0oQ== + dependencies: + slash "^3.0.0" + +"@rollup/plugin-commonjs@20.0.0": + version "20.0.0" + resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-20.0.0.tgz#3246872dcbcb18a54aaa6277a8c7d7f1b155b745" + integrity sha512-5K0g5W2Ol8hAcTHqcTBHiA7M58tfmYi1o9KxeJuuRNpGaTa5iLjcyemBitCBcKXaHamOBBEH2dGom6v6Unmqjg== + dependencies: + "@rollup/pluginutils" "^3.1.0" + commondir "^1.0.1" + estree-walker "^2.0.1" + glob "^7.1.6" + is-reference "^1.2.1" + magic-string "^0.25.7" + resolve "^1.17.0" + +"@rollup/plugin-node-resolve@13.0.4": + version "13.0.4" + resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-13.0.4.tgz#b10222f4145a019740acb7738402130d848660c0" + integrity sha512-eYq4TFy40O8hjeDs+sIxEH/jc9lyuI2k9DM557WN6rO5OpnC2qXMBNj4IKH1oHrnAazL49C5p0tgP0/VpqJ+/w== + dependencies: + "@rollup/pluginutils" "^3.1.0" + "@types/resolve" "1.17.1" + builtin-modules "^3.1.0" + deepmerge "^4.2.2" + is-module "^1.0.0" + resolve "^1.19.0" + +"@rollup/plugin-replace@3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@rollup/plugin-replace/-/plugin-replace-3.0.0.tgz#3a4c9665d4e7a4ce2c360cf021232784892f3fac" + integrity sha512-3c7JCbMuYXM4PbPWT4+m/4Y6U60SgsnDT/cCyAyUKwFHg7pTSfsSQzIpETha3a3ig6OdOKzZz87D9ZXIK3qsDg== + dependencies: + "@rollup/pluginutils" "^3.1.0" + magic-string "^0.25.7" + +"@rollup/pluginutils@^3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-3.1.0.tgz#706b4524ee6dc8b103b3c995533e5ad680c02b9b" + integrity sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg== + dependencies: + "@types/estree" "0.0.39" + estree-walker "^1.0.1" + picomatch "^2.2.2" + +"@sinonjs/commons@^1.7.0": + version "1.8.6" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.6.tgz#80c516a4dc264c2a69115e7578d62581ff455ed9" + integrity sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ== + dependencies: + type-detect "4.0.8" + +"@sinonjs/fake-timers@^8.0.1": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz#3fdc2b6cb58935b21bfb8d1625eb1300484316e7" + integrity sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg== + dependencies: + "@sinonjs/commons" "^1.7.0" + +"@tootallnate/once@1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" + integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw== + +"@types/babel__core@^7.0.0", "@types/babel__core@^7.1.14": + version "7.1.20" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.20.tgz#e168cdd612c92a2d335029ed62ac94c95b362359" + integrity sha512-PVb6Bg2QuscZ30FvOU7z4guG6c926D9YRvOxEaelzndpMsvP+YM74Q/dAFASpg2l6+XLalxSGxcq/lrgYWZtyQ== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + "@types/babel__generator" "*" + "@types/babel__template" "*" + "@types/babel__traverse" "*" + +"@types/babel__generator@*": + version "7.6.4" + resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.4.tgz#1f20ce4c5b1990b37900b63f050182d28c2439b7" + integrity sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg== + dependencies: + "@babel/types" "^7.0.0" + +"@types/babel__template@*": + version "7.4.1" + resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.1.tgz#3d1a48fd9d6c0edfd56f2ff578daed48f36c8969" + integrity sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + +"@types/babel__traverse@*", "@types/babel__traverse@^7.0.4", "@types/babel__traverse@^7.0.6": + version "7.18.3" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.18.3.tgz#dfc508a85781e5698d5b33443416b6268c4b3e8d" + integrity sha512-1kbcJ40lLB7MHsj39U4Sh1uTd2E7rLEa79kmDpI6cy+XiXsteB3POdQomoq4FxszMrO3ZYchkhYJw7A2862b3w== + dependencies: + "@babel/types" "^7.3.0" + +"@types/estree@*": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.0.tgz#5fb2e536c1ae9bf35366eed879e827fa59ca41c2" + integrity sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ== + +"@types/estree@0.0.39": + version "0.0.39" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" + integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== + +"@types/graceful-fs@^4.1.2": + version "4.1.5" + resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.5.tgz#21ffba0d98da4350db64891f92a9e5db3cdb4e15" + integrity sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw== + dependencies: + "@types/node" "*" + +"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44" + integrity sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g== + +"@types/istanbul-lib-report@*": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#c14c24f18ea8190c118ee7562b7ff99a36552686" + integrity sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg== + dependencies: + "@types/istanbul-lib-coverage" "*" + +"@types/istanbul-reports@^3.0.0": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz#9153fe98bba2bd565a63add9436d6f0d7f8468ff" + integrity sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw== + dependencies: + "@types/istanbul-lib-report" "*" + +"@types/jest@26.0.24": + version "26.0.24" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-26.0.24.tgz#943d11976b16739185913a1936e0de0c4a7d595a" + integrity sha512-E/X5Vib8BWqZNRlDxj9vYXhsDwPYbPINqKF9BsnSoon4RQ0D9moEuLD8txgyypFLH7J4+Lho9Nr/c8H0Fi+17w== + dependencies: + jest-diff "^26.0.0" + pretty-format "^26.0.0" + +"@types/json-schema@^7.0.7": + version "7.0.11" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" + integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== + +"@types/json5@^0.0.29": + version "0.0.29" + resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" + integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== + +"@types/node@*": + version "18.11.15" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.15.tgz#de0e1fbd2b22b962d45971431e2ae696643d3f5d" + integrity sha512-VkhBbVo2+2oozlkdHXLrb3zjsRkpdnaU2bXmX8Wgle3PUi569eLRaHGlgETQHR7lLL1w7GiG3h9SnePhxNDecw== + +"@types/normalize-package-data@^2.4.0": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz#d3357479a0fdfdd5907fe67e17e0a85c906e1301" + integrity sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw== + +"@types/prettier@^2.1.5": + version "2.7.1" + resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.1.tgz#dfd20e2dc35f027cdd6c1908e80a5ddc7499670e" + integrity sha512-ri0UmynRRvZiiUJdiz38MmIblKK+oH30MztdBVR95dv/Ubw6neWSb8u1XpRb72L4qsZOhz+L+z9JD40SJmfWow== + +"@types/q@^1.5.1": + version "1.5.5" + resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.5.tgz#75a2a8e7d8ab4b230414505d92335d1dcb53a6df" + integrity sha512-L28j2FcJfSZOnL1WBjDYp2vUHCeIFlyYI/53EwD/rKUBQ7MtUUfbQWiyKJGpcnv4/WgrhWsFKrcPstcAt/J0tQ== + +"@types/resolve@1.17.1": + version "1.17.1" + resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.17.1.tgz#3afd6ad8967c77e4376c598a82ddd58f46ec45d6" + integrity sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw== + dependencies: + "@types/node" "*" + +"@types/stack-utils@^2.0.0": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c" + integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw== + +"@types/yargs-parser@*": + version "21.0.0" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b" + integrity sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA== + +"@types/yargs@^15.0.0": + version "15.0.14" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.14.tgz#26d821ddb89e70492160b66d10a0eb6df8f6fb06" + integrity sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ== + dependencies: + "@types/yargs-parser" "*" + +"@types/yargs@^16.0.0": + version "16.0.4" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-16.0.4.tgz#26aad98dd2c2a38e421086ea9ad42b9e51642977" + integrity sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw== + dependencies: + "@types/yargs-parser" "*" + +"@typescript-eslint/eslint-plugin@4.29.0": + version "4.29.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.29.0.tgz#b866c9cd193bfaba5e89bade0015629ebeb27996" + integrity sha512-eiREtqWRZ8aVJcNru7cT/AMVnYd9a2UHsfZT8MR1dW3UUEg6jDv9EQ9Cq4CUPZesyQ58YUpoAADGv71jY8RwgA== + dependencies: + "@typescript-eslint/experimental-utils" "4.29.0" + "@typescript-eslint/scope-manager" "4.29.0" + debug "^4.3.1" + functional-red-black-tree "^1.0.1" + regexpp "^3.1.0" + semver "^7.3.5" + tsutils "^3.21.0" + +"@typescript-eslint/experimental-utils@4.29.0": + version "4.29.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.29.0.tgz#19b1417602d0e1ef325b3312ee95f61220542df5" + integrity sha512-FpNVKykfeaIxlArLUP/yQfv/5/3rhl1ov6RWgud4OgbqWLkEq7lqgQU9iiavZRzpzCRQV4XddyFz3wFXdkiX9w== + dependencies: + "@types/json-schema" "^7.0.7" + "@typescript-eslint/scope-manager" "4.29.0" + "@typescript-eslint/types" "4.29.0" + "@typescript-eslint/typescript-estree" "4.29.0" + eslint-scope "^5.1.1" + eslint-utils "^3.0.0" + +"@typescript-eslint/experimental-utils@^4.0.1": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.33.0.tgz#6f2a786a4209fa2222989e9380b5331b2810f7fd" + integrity sha512-zeQjOoES5JFjTnAhI5QY7ZviczMzDptls15GFsI6jyUOq0kOf9+WonkhtlIhh0RgHRnqj5gdNxW5j1EvAyYg6Q== + dependencies: + "@types/json-schema" "^7.0.7" + "@typescript-eslint/scope-manager" "4.33.0" + "@typescript-eslint/types" "4.33.0" + "@typescript-eslint/typescript-estree" "4.33.0" + eslint-scope "^5.1.1" + eslint-utils "^3.0.0" + +"@typescript-eslint/parser@4.29.0": + version "4.29.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.29.0.tgz#e5367ca3c63636bb5d8e0748fcbab7a4f4a04289" + integrity sha512-+92YRNHFdXgq+GhWQPT2bmjX09X7EH36JfgN2/4wmhtwV/HPxozpCNst8jrWcngLtEVd/4zAwA6BKojAlf+YqA== + dependencies: + "@typescript-eslint/scope-manager" "4.29.0" + "@typescript-eslint/types" "4.29.0" + "@typescript-eslint/typescript-estree" "4.29.0" + debug "^4.3.1" + +"@typescript-eslint/scope-manager@4.29.0": + version "4.29.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.29.0.tgz#cf5474f87321bedf416ef65839b693bddd838599" + integrity sha512-HPq7XAaDMM3DpmuijxLV9Io8/6pQnliiXMQUcAdjpJJSR+fdmbD/zHCd7hMkjJn04UQtCQBtshgxClzg6NIS2w== + dependencies: + "@typescript-eslint/types" "4.29.0" + "@typescript-eslint/visitor-keys" "4.29.0" + +"@typescript-eslint/scope-manager@4.33.0": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.33.0.tgz#d38e49280d983e8772e29121cf8c6e9221f280a3" + integrity sha512-5IfJHpgTsTZuONKbODctL4kKuQje/bzBRkwHE8UOZ4f89Zeddg+EGZs8PD8NcN4LdM3ygHWYB3ukPAYjvl/qbQ== + dependencies: + "@typescript-eslint/types" "4.33.0" + "@typescript-eslint/visitor-keys" "4.33.0" + +"@typescript-eslint/types@4.29.0": + version "4.29.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.29.0.tgz#c8f1a1e4441ea4aca9b3109241adbc145f7f8a4e" + integrity sha512-2YJM6XfWfi8pgU2HRhTp7WgRw78TCRO3dOmSpAvIQ8MOv4B46JD2chnhpNT7Jq8j0APlIbzO1Bach734xxUl4A== + +"@typescript-eslint/types@4.33.0": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.33.0.tgz#a1e59036a3b53ae8430ceebf2a919dc7f9af6d72" + integrity sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ== + +"@typescript-eslint/typescript-estree@4.29.0": + version "4.29.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.29.0.tgz#af7ab547757b86c91bfdbc54ff86845410856256" + integrity sha512-8ZpNHDIOyqzzgZrQW9+xQ4k5hM62Xy2R4RPO3DQxMc5Rq5QkCdSpk/drka+DL9w6sXNzV5nrdlBmf8+x495QXQ== + dependencies: + "@typescript-eslint/types" "4.29.0" + "@typescript-eslint/visitor-keys" "4.29.0" + debug "^4.3.1" + globby "^11.0.3" + is-glob "^4.0.1" + semver "^7.3.5" + tsutils "^3.21.0" + +"@typescript-eslint/typescript-estree@4.33.0": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.33.0.tgz#0dfb51c2908f68c5c08d82aefeaf166a17c24609" + integrity sha512-rkWRY1MPFzjwnEVHsxGemDzqqddw2QbTJlICPD9p9I9LfsO8fdmfQPOX3uKfUaGRDFJbfrtm/sXhVXN4E+bzCA== + dependencies: + "@typescript-eslint/types" "4.33.0" + "@typescript-eslint/visitor-keys" "4.33.0" + debug "^4.3.1" + globby "^11.0.3" + is-glob "^4.0.1" + semver "^7.3.5" + tsutils "^3.21.0" + +"@typescript-eslint/visitor-keys@4.29.0": + version "4.29.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.29.0.tgz#1ff60f240def4d85ea68d4fd2e4e9759b7850c04" + integrity sha512-LoaofO1C/jAJYs0uEpYMXfHboGXzOJeV118X4OsZu9f7rG7Pr9B3+4HTU8+err81rADa4xfQmAxnRnPAI2jp+Q== + dependencies: + "@typescript-eslint/types" "4.29.0" + eslint-visitor-keys "^2.0.0" + +"@typescript-eslint/visitor-keys@4.33.0": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.33.0.tgz#2a22f77a41604289b7a186586e9ec48ca92ef1dd" + integrity sha512-uqi/2aSz9g2ftcHWf8uLPJA70rUv6yuMW5Bohw+bwcuzaxQIHaKFZCKGoGXIrc9vkTJ3+0txM73K0Hq3d5wgIg== + dependencies: + "@typescript-eslint/types" "4.33.0" + eslint-visitor-keys "^2.0.0" + +"@vue/component-compiler-utils@^1.2.1": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@vue/component-compiler-utils/-/component-compiler-utils-1.3.1.tgz#686f0b913d59590ae327b2a1cb4b6d9b931bbe0e" + integrity sha512-IyjJW6ToMitgAhp3xh22QiEW8JvHfLyzlyY/J+GjJ71miod9tNsy6xT2ckm/VirlhPMfeM43kgYZe34jhmmzpw== + dependencies: + consolidate "^0.15.1" + hash-sum "^1.0.2" + lru-cache "^4.1.2" + merge-source-map "^1.1.0" + postcss "^6.0.20" + postcss-selector-parser "^3.1.1" + prettier "^1.13.0" + source-map "^0.5.6" + vue-template-es2015-compiler "^1.6.0" + +"@vue/component-compiler-utils@^2.1.0": + version "2.6.0" + resolved "https://registry.yarnpkg.com/@vue/component-compiler-utils/-/component-compiler-utils-2.6.0.tgz#aa46d2a6f7647440b0b8932434d22f12371e543b" + integrity sha512-IHjxt7LsOFYc0DkTncB7OXJL7UzwOLPPQCfEUNyxL2qt+tF12THV+EO33O1G2Uk4feMSWua3iD39Itszx0f0bw== + dependencies: + consolidate "^0.15.1" + hash-sum "^1.0.2" + lru-cache "^4.1.2" + merge-source-map "^1.1.0" + postcss "^7.0.14" + postcss-selector-parser "^5.0.0" + prettier "1.16.3" + source-map "~0.6.1" + vue-template-es2015-compiler "^1.9.0" + +"@vue/component-compiler@^3.3.2": + version "3.6.0" + resolved "https://registry.yarnpkg.com/@vue/component-compiler/-/component-compiler-3.6.0.tgz#8db313e50eaa2903cef5aac68c37a09364dba79d" + integrity sha512-NIA0vmOI4zbtJAn69iZls8IJ8VxmguswAuiUdu8TcR+YYTYzntfw290HUCSFjzAdRg+FUWZv8r+wc3TzJ/IjwA== + dependencies: + "@vue/component-compiler-utils" "^2.1.0" + clean-css "^4.1.11" + hash-sum "^1.0.2" + postcss-modules-sync "^1.0.0" + source-map "0.6.*" + +"@vue/composition-api@1.0.6": + version "1.0.6" + resolved "https://registry.yarnpkg.com/@vue/composition-api/-/composition-api-1.0.6.tgz#a28e73b6a0939d446badfbde1b532bfdf3bb7c1d" + integrity sha512-P4abcx92znWAG6HaB4p5zCwGVDptfiOaV3kDSwA9Zwc0Nb4urDh5RvCQYEE8uE2SDQxqcR4r2ijWW5gzfVIUwQ== + dependencies: + tslib "^2.3.0" + +abab@^2.0.3, abab@^2.0.5: + version "2.0.6" + resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291" + integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA== + +acorn-globals@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-6.0.0.tgz#46cdd39f0f8ff08a876619b55f5ac8a6dc770b45" + integrity sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg== + dependencies: + acorn "^7.1.1" + acorn-walk "^7.1.1" + +acorn-jsx@^5.2.0, acorn-jsx@^5.3.1: + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + +acorn-node@^1.8.2: + version "1.8.2" + resolved "https://registry.yarnpkg.com/acorn-node/-/acorn-node-1.8.2.tgz#114c95d64539e53dede23de8b9d96df7c7ae2af8" + integrity sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A== + dependencies: + acorn "^7.0.0" + acorn-walk "^7.0.0" + xtend "^4.0.2" + +acorn-walk@^7.0.0, acorn-walk@^7.1.1: + version "7.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" + integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== + +acorn@^7.0.0, acorn@^7.1.1, acorn@^7.4.0: + version "7.4.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" + integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== + +acorn@^8.2.4: + version "8.8.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.1.tgz#0a3f9cbecc4ec3bea6f0a80b66ae8dd2da250b73" + integrity sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA== + +agent-base@6: + version "6.0.2" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== + dependencies: + debug "4" + +ajv@^6.10.0, ajv@^6.12.4: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ajv@^8.0.1: + version "8.11.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.11.2.tgz#aecb20b50607acf2569b6382167b65a96008bb78" + integrity sha512-E4bfmKAhGiSTvMfL1Myyycaub+cUEU2/IvpylXkUu7CHBkBj1f/ikdzbD7YQ6FKUbixDxeYvB/xY4fvyroDlQg== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + +alphanum-sort@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" + integrity sha512-0FcBfdcmaumGPQ0qPn7Q5qTgz/ooXgIyp1rf8ik5bGX8mpE2YHjC0P/eyQvxu1GURYQgq9ozf2mteQ5ZD9YiyQ== + +ansi-colors@^4.1.1: + version "4.1.3" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" + integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== + +ansi-escapes@^4.2.1: + version "4.3.2" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + dependencies: + type-fest "^0.21.3" + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA== + +ansi-regex@^5.0.0, ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + integrity sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA== + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +ansi-styles@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" + integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== + +anymatch@^3.0.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +array-includes@^3.1.4: + version "3.1.6" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.6.tgz#9e9e720e194f198266ba9e18c29e6a9b0e4b225f" + integrity sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + get-intrinsic "^1.1.3" + is-string "^1.0.7" + +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + +array.prototype.flat@^1.2.5: + version "1.3.1" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz#ffc6576a7ca3efc2f46a143b9d1dda9b4b3cf5e2" + integrity sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + es-shim-unscopables "^1.0.0" + +array.prototype.reduce@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/array.prototype.reduce/-/array.prototype.reduce-1.0.5.tgz#6b20b0daa9d9734dd6bc7ea66b5bbce395471eac" + integrity sha512-kDdugMl7id9COE8R7MHF5jWk7Dqt/fs4Pv+JXoICnYwqpjjjbUurz6w5fT5IG6brLdJhv6/VoHB0H7oyIBXd+Q== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + es-array-method-boxes-properly "^1.0.0" + is-string "^1.0.7" + +astral-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" + integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + +autoprefixer@^9.4.5: + version "9.8.8" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.8.8.tgz#fd4bd4595385fa6f06599de749a4d5f7a474957a" + integrity sha512-eM9d/swFopRt5gdJ7jrpCwgvEMIayITpojhkkSMRsFHYuH5bkSQ4p/9qTEHtmNudUZh22Tehu7I6CxAW0IXTKA== + dependencies: + browserslist "^4.12.0" + caniuse-lite "^1.0.30001109" + normalize-range "^0.1.2" + num2fraction "^1.2.2" + picocolors "^0.2.1" + postcss "^7.0.32" + postcss-value-parser "^4.1.0" + +babel-jest@27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-27.0.6.tgz#e99c6e0577da2655118e3608b68761a5a69bd0d8" + integrity sha512-iTJyYLNc4wRofASmofpOc5NK9QunwMk+TLFgGXsTFS8uEqmd8wdI7sga0FPe2oVH3b5Agt/EAK1QjPEuKL8VfA== + dependencies: + "@jest/transform" "^27.0.6" + "@jest/types" "^27.0.6" + "@types/babel__core" "^7.1.14" + babel-plugin-istanbul "^6.0.0" + babel-preset-jest "^27.0.6" + chalk "^4.0.0" + graceful-fs "^4.2.4" + slash "^3.0.0" + +babel-jest@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-27.5.1.tgz#a1bf8d61928edfefd21da27eb86a695bfd691444" + integrity sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg== + dependencies: + "@jest/transform" "^27.5.1" + "@jest/types" "^27.5.1" + "@types/babel__core" "^7.1.14" + babel-plugin-istanbul "^6.1.1" + babel-preset-jest "^27.5.1" + chalk "^4.0.0" + graceful-fs "^4.2.9" + slash "^3.0.0" + +babel-plugin-dynamic-import-node@^2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3" + integrity sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ== + dependencies: + object.assign "^4.1.0" + +babel-plugin-istanbul@^6.0.0, babel-plugin-istanbul@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" + integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@istanbuljs/load-nyc-config" "^1.0.0" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-instrument "^5.0.4" + test-exclude "^6.0.0" + +babel-plugin-jest-hoist@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz#9be98ecf28c331eb9f5df9c72d6f89deb8181c2e" + integrity sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ== + dependencies: + "@babel/template" "^7.3.3" + "@babel/types" "^7.3.3" + "@types/babel__core" "^7.0.0" + "@types/babel__traverse" "^7.0.6" + +babel-preset-current-node-syntax@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" + integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ== + dependencies: + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-syntax-bigint" "^7.8.3" + "@babel/plugin-syntax-class-properties" "^7.8.3" + "@babel/plugin-syntax-import-meta" "^7.8.3" + "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.8.3" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.8.3" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-syntax-top-level-await" "^7.8.3" + +babel-preset-jest@^27.0.6, babel-preset-jest@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz#91f10f58034cb7989cb4f962b69fa6eef6a6bc81" + integrity sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag== + dependencies: + babel-plugin-jest-hoist "^27.5.1" + babel-preset-current-node-syntax "^1.0.0" + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +big.js@^3.1.3: + version "3.2.0" + resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e" + integrity sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q== + +bluebird@^3.1.1: + version "3.7.2" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" + integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== + +boolbase@^1.0.0, boolbase@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" + integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +browser-process-hrtime@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" + integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow== + +browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.21.3: + version "4.21.4" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.4.tgz#e7496bbc67b9e39dd0f98565feccdcb0d4ff6987" + integrity sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw== + dependencies: + caniuse-lite "^1.0.30001400" + electron-to-chromium "^1.4.251" + node-releases "^2.0.6" + update-browserslist-db "^1.0.9" + +bser@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" + integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== + dependencies: + node-int64 "^0.4.0" + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +builtin-modules@^3.1.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.3.0.tgz#cae62812b89801e9656336e46223e030386be7b6" + integrity sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw== + +bytes@^3.0.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== + +call-bind@^1.0.0, call-bind@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + +caller-callsite@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" + integrity sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ== + dependencies: + callsites "^2.0.0" + +caller-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" + integrity sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A== + dependencies: + caller-callsite "^2.0.0" + +callsites@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" + integrity sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ== + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +camelcase-css@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5" + integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA== + +camelcase@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +camelcase@^6.2.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + +caniuse-api@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0" + integrity sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw== + dependencies: + browserslist "^4.0.0" + caniuse-lite "^1.0.0" + lodash.memoize "^4.1.2" + lodash.uniq "^4.5.0" + +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001400: + version "1.0.30001439" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001439.tgz#ab7371faeb4adff4b74dad1718a6fd122e45d9cb" + integrity sha512-1MgUzEkoMO6gKfXflStpYgZDlFM7M/ck/bgfVCACO5vnAf0fXoNVHdWtqGU+MYca+4bL9Z5bpOVmR33cWW9G2A== + +chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + integrity sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A== + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +chalk@^2.0.0, chalk@^2.4.1, chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +"chalk@^3.0.0 || ^4.0.0", chalk@^4.0.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" + +char-regex@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" + integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== + +ci-info@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" + integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== + +ci-info@^3.2.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.7.0.tgz#6d01b3696c59915b6ce057e4aa4adfc2fa25f5ef" + integrity sha512-2CpRNYmImPx+RXKLq6jko/L07phmS9I02TyqkcNU20GCF/GgaWvc58hPtjxDX8lPpkdwc9sNh72V9k00S7ezog== + +cjs-module-lexer@^1.0.0: + version "1.2.2" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz#9f84ba3244a512f3a54e5277e8eef4c489864e40" + integrity sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA== + +clean-css@^4.1.11: + version "4.2.4" + resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.4.tgz#733bf46eba4e607c6891ea57c24a989356831178" + integrity sha512-EJUDT7nDVFDvaQgAo2G/PJvxmp1o/c6iXLbswsBbUFXi1Nr+AjA2cKmfbKDMjMvzEe75g3P6JkaDDAKk96A85A== + dependencies: + source-map "~0.6.0" + +clean-regexp@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/clean-regexp/-/clean-regexp-1.0.0.tgz#8df7c7aae51fd36874e8f8d05b9180bc11a3fed7" + integrity sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw== + dependencies: + escape-string-regexp "^1.0.5" + +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== + +coa@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/coa/-/coa-2.0.2.tgz#43f6c21151b4ef2bf57187db0d73de229e3e7ec3" + integrity sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA== + dependencies: + "@types/q" "^1.5.1" + chalk "^2.4.1" + q "^1.1.2" + +collect-v8-coverage@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59" + integrity sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg== + +color-convert@^1.9.0, color-convert@^1.9.3: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== + +color-name@^1.0.0, color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +color-string@^1.6.0: + version "1.9.1" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.9.1.tgz#4467f9146f036f855b764dfb5bf8582bf342c7a4" + integrity sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg== + dependencies: + color-name "^1.0.0" + simple-swizzle "^0.2.2" + +color@^3.0.0, color@^3.1.2: + version "3.2.1" + resolved "https://registry.yarnpkg.com/color/-/color-3.2.1.tgz#3544dc198caf4490c3ecc9a790b54fe9ff45e164" + integrity sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA== + dependencies: + color-convert "^1.9.3" + color-string "^1.6.0" + +colorette@^1.2.2: + version "1.4.0" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.4.0.tgz#5190fbb87276259a86ad700bff2c6d6faa3fca40" + integrity sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g== + +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +commander@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae" + integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg== + +commondir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" + integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +concat-with-sourcemaps@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz#d4ea93f05ae25790951b99e7b3b09e3908a4082e" + integrity sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg== + dependencies: + source-map "^0.6.1" + +consolidate@^0.15.1: + version "0.15.1" + resolved "https://registry.yarnpkg.com/consolidate/-/consolidate-0.15.1.tgz#21ab043235c71a07d45d9aad98593b0dba56bab7" + integrity sha512-DW46nrsMJgy9kqAbPt5rKaCr7uFtpo4mSUvLHIUbJEjm0vo+aY5QLwBUq3FK4tRnJr/X0Psc0C4jf/h+HtXSMw== + dependencies: + bluebird "^3.1.1" + +convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" + integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== + +cosmiconfig@^5.0.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" + integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA== + dependencies: + import-fresh "^2.0.0" + is-directory "^0.3.1" + js-yaml "^3.13.1" + parse-json "^4.0.0" + +cross-spawn@^6.0.5: + version "6.0.5" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" + integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== + dependencies: + nice-try "^1.0.4" + path-key "^2.0.1" + semver "^5.5.0" + shebang-command "^1.2.0" + which "^1.2.9" + +cross-spawn@^7.0.2, 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" + +css-color-names@0.0.4, css-color-names@^0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0" + integrity sha512-zj5D7X1U2h2zsXOAM8EyUREBnnts6H+Jm+d1M2DbiQQcUtnqgQsMrdo8JW9R80YFUmIdBZeMu5wvYM7hcgWP/Q== + +css-declaration-sorter@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz#c198940f63a76d7e36c1e71018b001721054cb22" + integrity sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA== + dependencies: + postcss "^7.0.1" + timsort "^0.3.0" + +css-select-base-adapter@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz#3b2ff4972cc362ab88561507a95408a1432135d7" + integrity sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w== + +css-select@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-2.1.0.tgz#6a34653356635934a81baca68d0255432105dbef" + integrity sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ== + dependencies: + boolbase "^1.0.0" + css-what "^3.2.1" + domutils "^1.7.0" + nth-check "^1.0.2" + +css-selector-tokenizer@^0.7.0: + version "0.7.3" + resolved "https://registry.yarnpkg.com/css-selector-tokenizer/-/css-selector-tokenizer-0.7.3.tgz#735f26186e67c749aaf275783405cf0661fae8f1" + integrity sha512-jWQv3oCEL5kMErj4wRnK/OPoBi0D+P1FR2cDCKYPaMeD2eW3/mttav8HT4hT1CKopiJI/psEULjkClhvJo4Lvg== + dependencies: + cssesc "^3.0.0" + fastparse "^1.1.2" + +css-tree@1.0.0-alpha.37: + version "1.0.0-alpha.37" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.37.tgz#98bebd62c4c1d9f960ec340cf9f7522e30709a22" + integrity sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg== + dependencies: + mdn-data "2.0.4" + source-map "^0.6.1" + +css-tree@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.1.3.tgz#eb4870fb6fd7707327ec95c2ff2ab09b5e8db91d" + integrity sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q== + dependencies: + mdn-data "2.0.14" + source-map "^0.6.1" + +css-unit-converter@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/css-unit-converter/-/css-unit-converter-1.1.2.tgz#4c77f5a1954e6dbff60695ecb214e3270436ab21" + integrity sha512-IiJwMC8rdZE0+xiEZHeru6YoONC4rfPMqGm2W85jMIbkFvv5nFTwJVFHam2eFrN6txmoUYFAFXiv8ICVeTO0MA== + +css-what@^3.2.1: + version "3.4.2" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-3.4.2.tgz#ea7026fcb01777edbde52124e21f327e7ae950e4" + integrity sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ== + +cssesc@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-2.0.0.tgz#3b13bd1bb1cb36e1bcb5a4dcd27f54c5dcb35703" + integrity sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg== + +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== + +cssnano-preset-default@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-4.0.8.tgz#920622b1fc1e95a34e8838203f1397a504f2d3ff" + integrity sha512-LdAyHuq+VRyeVREFmuxUZR1TXjQm8QQU/ktoo/x7bz+SdOge1YKc5eMN6pRW7YWBmyq59CqYba1dJ5cUukEjLQ== + dependencies: + css-declaration-sorter "^4.0.1" + cssnano-util-raw-cache "^4.0.1" + postcss "^7.0.0" + postcss-calc "^7.0.1" + postcss-colormin "^4.0.3" + postcss-convert-values "^4.0.1" + postcss-discard-comments "^4.0.2" + postcss-discard-duplicates "^4.0.2" + postcss-discard-empty "^4.0.1" + postcss-discard-overridden "^4.0.1" + postcss-merge-longhand "^4.0.11" + postcss-merge-rules "^4.0.3" + postcss-minify-font-values "^4.0.2" + postcss-minify-gradients "^4.0.2" + postcss-minify-params "^4.0.2" + postcss-minify-selectors "^4.0.2" + postcss-normalize-charset "^4.0.1" + postcss-normalize-display-values "^4.0.2" + postcss-normalize-positions "^4.0.2" + postcss-normalize-repeat-style "^4.0.2" + postcss-normalize-string "^4.0.2" + postcss-normalize-timing-functions "^4.0.2" + postcss-normalize-unicode "^4.0.1" + postcss-normalize-url "^4.0.1" + postcss-normalize-whitespace "^4.0.2" + postcss-ordered-values "^4.1.2" + postcss-reduce-initial "^4.0.3" + postcss-reduce-transforms "^4.0.2" + postcss-svgo "^4.0.3" + postcss-unique-selectors "^4.0.1" + +cssnano-util-get-arguments@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz#ed3a08299f21d75741b20f3b81f194ed49cc150f" + integrity sha512-6RIcwmV3/cBMG8Aj5gucQRsJb4vv4I4rn6YjPbVWd5+Pn/fuG+YseGvXGk00XLkoZkaj31QOD7vMUpNPC4FIuw== + +cssnano-util-get-match@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz#c0e4ca07f5386bb17ec5e52250b4f5961365156d" + integrity sha512-JPMZ1TSMRUPVIqEalIBNoBtAYbi8okvcFns4O0YIhcdGebeYZK7dMyHJiQ6GqNBA9kE0Hym4Aqym5rPdsV/4Cw== + +cssnano-util-raw-cache@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz#b26d5fd5f72a11dfe7a7846fb4c67260f96bf282" + integrity sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA== + dependencies: + postcss "^7.0.0" + +cssnano-util-same-parent@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz#574082fb2859d2db433855835d9a8456ea18bbf3" + integrity sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q== + +cssnano@^4.1.10: + version "4.1.11" + resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-4.1.11.tgz#c7b5f5b81da269cb1fd982cb960c1200910c9a99" + integrity sha512-6gZm2htn7xIPJOHY824ERgj8cNPgPxyCSnkXc4v7YvNW+TdVfzgngHcEhy/8D11kUWRUMbke+tC+AUcUsnMz2g== + dependencies: + cosmiconfig "^5.0.0" + cssnano-preset-default "^4.0.8" + is-resolvable "^1.0.0" + postcss "^7.0.0" + +csso@^4.0.2: + version "4.2.0" + resolved "https://registry.yarnpkg.com/csso/-/csso-4.2.0.tgz#ea3a561346e8dc9f546d6febedd50187cf389529" + integrity sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA== + dependencies: + css-tree "^1.1.2" + +cssom@^0.4.4: + version "0.4.4" + resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.4.4.tgz#5a66cf93d2d0b661d80bf6a44fb65f5c2e4e0a10" + integrity sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw== + +cssom@~0.3.6: + version "0.3.8" + resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a" + integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg== + +cssstyle@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-2.3.0.tgz#ff665a0ddbdc31864b09647f34163443d90b0852" + integrity sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A== + dependencies: + cssom "~0.3.6" + +data-urls@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-2.0.0.tgz#156485a72963a970f5d5821aaf642bef2bf2db9b" + integrity sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ== + dependencies: + abab "^2.0.3" + whatwg-mimetype "^2.3.0" + whatwg-url "^8.0.0" + +de-indent@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d" + integrity sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg== + +debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +debug@^2.6.0, debug@^2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@^3.2.7: + version "3.2.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== + dependencies: + ms "^2.1.1" + +decimal.js@^10.2.1: + version "10.4.3" + resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.4.3.tgz#1044092884d245d1b7f65725fa4ad4c6f781cc23" + integrity sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA== + +dedent@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" + integrity sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA== + +deep-is@^0.1.3, deep-is@~0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + +deepmerge@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" + integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== + +define-properties@^1.1.3, define-properties@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1" + integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA== + dependencies: + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" + +defined@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.1.tgz#c0b9db27bfaffd95d6f61399419b893df0f91ebf" + integrity sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q== + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + +detect-newline@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" + integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== + +detective@^5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/detective/-/detective-5.2.1.tgz#6af01eeda11015acb0e73f933242b70f24f91034" + integrity sha512-v9XE1zRnz1wRtgurGu0Bs8uHKFSTdteYZNbIPFVhUZ39L/S79ppMpdmVOZAnoz1jfEFodc48n6MX483Xo3t1yw== + dependencies: + acorn-node "^1.8.2" + defined "^1.0.0" + minimist "^1.2.6" + +diff-sequences@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-26.6.2.tgz#48ba99157de1923412eed41db6b6d4aa9ca7c0b1" + integrity sha512-Mv/TDa3nZ9sbc5soK+OoA74BsS3mL37yixCvUAQkiuA4Wz6YtwP/K47n2rv2ovzHZvoiQeA5FTQOschKkEwB0Q== + +diff-sequences@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.5.1.tgz#eaecc0d327fd68c8d9672a1e64ab8dccb2ef5327" + integrity sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ== + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +doctrine@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" + integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== + dependencies: + esutils "^2.0.2" + +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + +dom-serializer@0: + version "0.2.2" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51" + integrity sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g== + dependencies: + domelementtype "^2.0.1" + entities "^2.0.0" + +domelementtype@1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" + integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== + +domelementtype@^2.0.1: + version "2.3.0" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" + integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== + +domexception@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/domexception/-/domexception-2.0.1.tgz#fb44aefba793e1574b0af6aed2801d057529f304" + integrity sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg== + dependencies: + webidl-conversions "^5.0.0" + +domutils@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" + integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg== + dependencies: + dom-serializer "0" + domelementtype "1" + +dot-prop@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88" + integrity sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q== + dependencies: + is-obj "^2.0.0" + +electron-to-chromium@^1.4.251: + version "1.4.284" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz#61046d1e4cab3a25238f6bf7413795270f125592" + integrity sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA== + +emittery@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.8.1.tgz#bb23cc86d03b30aa75a7f734819dee2e1ba70860" + integrity sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +emojis-list@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" + integrity sha512-knHEZMgs8BB+MInokmNTg/OyPlAddghe1YBgNwJBc5zsJi/uyIcXoSDsL/W9ymOsBoBGdPIHXYJ9+qKFwRwDng== + +enquirer@^2.3.5: + version "2.3.6" + resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" + integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== + dependencies: + ansi-colors "^4.1.1" + +entities@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" + integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== + +error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + +es-abstract@^1.17.2, es-abstract@^1.19.0, es-abstract@^1.20.4: + version "1.20.5" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.20.5.tgz#e6dc99177be37cacda5988e692c3fa8b218e95d2" + integrity sha512-7h8MM2EQhsCA7pU/Nv78qOXFpD8Rhqd12gYiSJVkrH9+e8VuA8JlPJK/hQjjlLv6pJvx/z1iRFKzYb0XT/RuAQ== + dependencies: + call-bind "^1.0.2" + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + function.prototype.name "^1.1.5" + get-intrinsic "^1.1.3" + get-symbol-description "^1.0.0" + gopd "^1.0.1" + has "^1.0.3" + has-property-descriptors "^1.0.0" + has-symbols "^1.0.3" + internal-slot "^1.0.3" + is-callable "^1.2.7" + is-negative-zero "^2.0.2" + is-regex "^1.1.4" + is-shared-array-buffer "^1.0.2" + is-string "^1.0.7" + is-weakref "^1.0.2" + object-inspect "^1.12.2" + object-keys "^1.1.1" + object.assign "^4.1.4" + regexp.prototype.flags "^1.4.3" + safe-regex-test "^1.0.0" + string.prototype.trimend "^1.0.6" + string.prototype.trimstart "^1.0.6" + unbox-primitive "^1.0.2" + +es-array-method-boxes-properly@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e" + integrity sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA== + +es-shim-unscopables@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz#702e632193201e3edf8713635d083d378e510241" + integrity sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w== + dependencies: + has "^1.0.3" + +es-to-primitive@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" + integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + +esbuild@0.12.19: + version "0.12.19" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.12.19.tgz#ab849766705a5093df5acd8ec2f6ba2159a38a6c" + integrity sha512-5NuT1G6THW7l3fsSCDkcPepn24R0XtyPjKoqKHD8LfhqMXzCdz0mrS9HgO6hIhzVT7zt0T+JGbzCqF5AH8hS9w== + +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + +escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + +escape-string-regexp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" + integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +escodegen@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.0.0.tgz#5e32b12833e8aa8fa35e1bf0befa89380484c7dd" + integrity sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw== + dependencies: + esprima "^4.0.1" + estraverse "^5.2.0" + esutils "^2.0.2" + optionator "^0.8.1" + optionalDependencies: + source-map "~0.6.1" + +eslint-config-prettier@8.3.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz#f7471b20b6fe8a9a9254cc684454202886a2dd7a" + integrity sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew== + +eslint-config-standard@^16.0.3: + version "16.0.3" + resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-16.0.3.tgz#6c8761e544e96c531ff92642eeb87842b8488516" + integrity sha512-x4fmJL5hGqNJKGHSjnLdgA6U6h1YW/G2dW9fA+cyVur4SK6lyue8+UgNKWlZtUDTXvgKDD/Oa3GQjmB5kjtVvg== + +eslint-import-resolver-node@^0.3.6: + version "0.3.6" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz#4048b958395da89668252001dbd9eca6b83bacbd" + integrity sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw== + dependencies: + debug "^3.2.7" + resolve "^1.20.0" + +eslint-module-utils@^2.7.3: + version "2.7.4" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz#4f3e41116aaf13a20792261e61d3a2e7e0583974" + integrity sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA== + dependencies: + debug "^3.2.7" + +eslint-plugin-es@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz#75a7cdfdccddc0589934aeeb384175f221c57893" + integrity sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ== + dependencies: + eslint-utils "^2.0.0" + regexpp "^3.0.0" + +eslint-plugin-import@^2.23.3: + version "2.26.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz#f812dc47be4f2b72b478a021605a59fc6fe8b88b" + integrity sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA== + dependencies: + array-includes "^3.1.4" + array.prototype.flat "^1.2.5" + debug "^2.6.9" + doctrine "^2.1.0" + eslint-import-resolver-node "^0.3.6" + eslint-module-utils "^2.7.3" + has "^1.0.3" + is-core-module "^2.8.1" + is-glob "^4.0.3" + minimatch "^3.1.2" + object.values "^1.1.5" + resolve "^1.22.0" + tsconfig-paths "^3.14.1" + +eslint-plugin-jest@^24.3.6: + version "24.7.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-24.7.0.tgz#206ac0833841e59e375170b15f8d0955219c4889" + integrity sha512-wUxdF2bAZiYSKBclsUMrYHH6WxiBreNjyDxbRv345TIvPeoCEgPNEn3Sa+ZrSqsf1Dl9SqqSREXMHExlMMu1DA== + dependencies: + "@typescript-eslint/experimental-utils" "^4.0.1" + +eslint-plugin-node@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz#c95544416ee4ada26740a30474eefc5402dc671d" + integrity sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g== + dependencies: + eslint-plugin-es "^3.0.0" + eslint-utils "^2.0.0" + ignore "^5.1.1" + minimatch "^3.0.4" + resolve "^1.10.1" + semver "^6.1.0" + +eslint-plugin-prettier@3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.0.tgz#cdbad3bf1dbd2b177e9825737fe63b476a08f0c7" + integrity sha512-UDK6rJT6INSfcOo545jiaOwB701uAIt2/dR7WnFQoGCVl1/EMqdANBmwUaqqQ45aXprsTGzSa39LI1PyuRBxxw== + dependencies: + prettier-linter-helpers "^1.0.0" + +eslint-plugin-promise@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-5.2.0.tgz#a596acc32981627eb36d9d75f9666ac1a4564971" + integrity sha512-SftLb1pUG01QYq2A/hGAWfDRXqYD82zE7j7TopDOyNdU+7SvvoXREls/+PRTY17vUXzXnZA/zfnyKgRH6x4JJw== + +eslint-plugin-standard@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-4.1.0.tgz#0c3bf3a67e853f8bbbc580fb4945fbf16f41b7c5" + integrity sha512-ZL7+QRixjTR6/528YNGyDotyffm5OQst/sGxKDwGb9Uqs4In5Egi4+jbobhqJoyoCM6/7v/1A5fhQ7ScMtDjaQ== + +eslint-plugin-unicorn@^28.0.2: + version "28.0.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-unicorn/-/eslint-plugin-unicorn-28.0.2.tgz#ab9884ebae04590ecd9c1c294330d889a74b7c37" + integrity sha512-k4AoFP7n8/oq6lBXkdc9Flid6vw2B8j7aXFCxgzJCyKvmaKrCUFb1TFPhG9eSJQFZowqmymMPRtl8oo9NKLUbw== + dependencies: + ci-info "^2.0.0" + clean-regexp "^1.0.0" + eslint-template-visitor "^2.2.2" + eslint-utils "^2.1.0" + eslint-visitor-keys "^2.0.0" + import-modules "^2.1.0" + lodash "^4.17.20" + pluralize "^8.0.0" + read-pkg-up "^7.0.1" + regexp-tree "^0.1.22" + reserved-words "^0.1.2" + safe-regex "^2.1.1" + semver "^7.3.4" + +eslint-plugin-vue@^7.9.0: + version "7.20.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-vue/-/eslint-plugin-vue-7.20.0.tgz#98c21885a6bfdf0713c3a92957a5afeaaeed9253" + integrity sha512-oVNDqzBC9h3GO+NTgWeLMhhGigy6/bQaQbHS+0z7C4YEu/qK/yxHvca/2PTZtGNPsCrHwOTgKMrwu02A9iPBmw== + dependencies: + eslint-utils "^2.1.0" + natural-compare "^1.4.0" + semver "^6.3.0" + vue-eslint-parser "^7.10.0" + +eslint-scope@5.1.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" + +eslint-template-visitor@^2.2.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/eslint-template-visitor/-/eslint-template-visitor-2.3.2.tgz#b52f96ff311e773a345d79053ccc78275bbc463d" + integrity sha512-3ydhqFpuV7x1M9EK52BPNj6V0Kwu0KKkcIAfpUhwHbR8ocRln/oUHgfxQupY8O1h4Qv/POHDumb/BwwNfxbtnA== + dependencies: + "@babel/core" "^7.12.16" + "@babel/eslint-parser" "^7.12.16" + eslint-visitor-keys "^2.0.0" + esquery "^1.3.1" + multimap "^1.1.0" + +eslint-utils@^2.0.0, eslint-utils@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" + integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== + dependencies: + eslint-visitor-keys "^1.1.0" + +eslint-utils@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" + integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== + dependencies: + eslint-visitor-keys "^2.0.0" + +eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" + integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== + +eslint-visitor-keys@^2.0.0, eslint-visitor-keys@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" + integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== + +eslint@7.32.0: + version "7.32.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.32.0.tgz#c6d328a14be3fb08c8d1d21e12c02fdb7a2a812d" + integrity sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA== + dependencies: + "@babel/code-frame" "7.12.11" + "@eslint/eslintrc" "^0.4.3" + "@humanwhocodes/config-array" "^0.5.0" + ajv "^6.10.0" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.0.1" + doctrine "^3.0.0" + enquirer "^2.3.5" + escape-string-regexp "^4.0.0" + eslint-scope "^5.1.1" + eslint-utils "^2.1.0" + eslint-visitor-keys "^2.0.0" + espree "^7.3.1" + esquery "^1.4.0" + esutils "^2.0.2" + fast-deep-equal "^3.1.3" + file-entry-cache "^6.0.1" + functional-red-black-tree "^1.0.1" + glob-parent "^5.1.2" + globals "^13.6.0" + ignore "^4.0.6" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + js-yaml "^3.13.1" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.4.1" + lodash.merge "^4.6.2" + minimatch "^3.0.4" + natural-compare "^1.4.0" + optionator "^0.9.1" + progress "^2.0.0" + regexpp "^3.1.0" + semver "^7.2.1" + strip-ansi "^6.0.0" + strip-json-comments "^3.1.0" + table "^6.0.9" + text-table "^0.2.0" + v8-compile-cache "^2.0.3" + +espree@^6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-6.2.1.tgz#77fc72e1fd744a2052c20f38a5b575832e82734a" + integrity sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw== + dependencies: + acorn "^7.1.1" + acorn-jsx "^5.2.0" + eslint-visitor-keys "^1.1.0" + +espree@^7.3.0, espree@^7.3.1: + version "7.3.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.1.tgz#f2df330b752c6f55019f8bd89b7660039c1bbbb6" + integrity sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g== + dependencies: + acorn "^7.4.0" + acorn-jsx "^5.3.1" + eslint-visitor-keys "^1.3.0" + +esprima@^4.0.0, esprima@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +esquery@^1.3.1, esquery@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" + integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== + dependencies: + estraverse "^5.1.0" + +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.1.0, estraverse@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +estree-walker@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.2.1.tgz#bdafe8095383d8414d5dc2ecf4c9173b6db9412e" + integrity sha512-6/I1dwNKk0N9iGOU3ydzAAurz4NPo/ttxZNCqgIVbWFvWyzWBSNonRrJ5CpjDuyBfmM7ENN7WCzUi9aT/UPXXQ== + +estree-walker@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.6.1.tgz#53049143f40c6eb918b23671d1fe3219f3a1b362" + integrity sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w== + +estree-walker@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-1.0.1.tgz#31bc5d612c96b704106b477e6dd5d8aa138cb700" + integrity sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg== + +estree-walker@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" + integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +eventemitter3@^4.0.4: + version "4.0.7" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" + integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== + +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" + +exit@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" + integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== + +expect@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/expect/-/expect-27.5.1.tgz#83ce59f1e5bdf5f9d2b94b61d2050db48f3fef74" + integrity sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw== + dependencies: + "@jest/types" "^27.5.1" + jest-get-type "^27.5.1" + jest-matcher-utils "^27.5.1" + jest-message-util "^27.5.1" + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-diff@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" + integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== + +fast-glob@^3.2.9: + version "3.2.12" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" + integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== + +fastparse@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.2.tgz#91728c5a5942eced8531283c79441ee4122c35a9" + integrity sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ== + +fastq@^1.6.0: + version "1.14.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.14.0.tgz#107f69d7295b11e0fccc264e1fc6389f623731ce" + integrity sha512-eR2D+V9/ExcbF9ls441yIuN6TI2ED1Y2ZcA5BmMtJsOkWOFRJQ0Jt0g1UwqXJJVAb+V+umH5Dfr8oh4EVP7VVg== + dependencies: + reusify "^1.0.4" + +fb-watchman@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.2.tgz#e9524ee6b5c77e9e5001af0f85f3adbb8623255c" + integrity sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA== + dependencies: + bser "2.1.1" + +file-entry-cache@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" + integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== + dependencies: + flat-cache "^3.0.4" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +find-up@^4.0.0, find-up@^4.1.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" + +flag-icon-css@3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/flag-icon-css/-/flag-icon-css-3.5.0.tgz#430747d5cb91e60babf85494de99173c16dc7cf2" + integrity sha512-pgJnJLrtb0tcDgU1fzGaQXmR8h++nXvILJ+r5SmOXaaL/2pocunQo2a8TAXhjQnBpRLPtZ1KCz/TYpqeNuE2ew== + +flat-cache@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" + integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== + dependencies: + flatted "^3.1.0" + rimraf "^3.0.2" + +flatted@^3.1.0: + version "3.2.7" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787" + integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ== + +form-data@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" + integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + +fs-extra@^8.0.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" + integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@^2.3.2, fsevents@~2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +function.prototype.name@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621" + integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.0" + functions-have-names "^1.2.2" + +functional-red-black-tree@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g== + +functions-have-names@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" + integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== + +generic-names@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/generic-names/-/generic-names-1.0.3.tgz#2d786a121aee508876796939e8e3bff836c20917" + integrity sha512-b6OHfQuKasIKM9b6YPkX+KUj/TLBTx3B/1aT1T5F12FEuEqyFMdr59OMS53aoaSw8eVtapdqieX6lbg5opaOhA== + dependencies: + loader-utils "^0.2.16" + +generic-names@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/generic-names/-/generic-names-4.0.0.tgz#0bd8a2fd23fe8ea16cbd0a279acd69c06933d9a3" + integrity sha512-ySFolZQfw9FoDb3ed9d80Cm9f0+r7qj+HJkWjeD9RBfpxEVTlVhol+gvaQB/78WbwYfbnNh8nWHHBSlg072y6A== + dependencies: + loader-utils "^3.2.0" + +gensync@^1.0.0-beta.2: + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.3.tgz#063c84329ad93e83893c7f4f243ef63ffa351385" + integrity sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.3" + +get-package-type@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" + integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== + +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-symbol-description@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" + integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.1" + +glob-parent@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob@^7.0.0, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + +globals@^13.6.0, globals@^13.9.0: + version "13.19.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.19.0.tgz#7a42de8e6ad4f7242fbcca27ea5b23aca367b5c8" + integrity sha512-dkQ957uSRWHw7CFXLUtUHQI3g3aWApYhfNR2O6jn/907riyTYKVBmxYVROkBcY614FSSeSJh7Xm7SrUWCxvJMQ== + dependencies: + type-fest "^0.20.2" + +globby@^11.0.3: + version "11.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.2.9" + ignore "^5.2.0" + merge2 "^1.4.1" + slash "^3.0.0" + +gopd@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" + integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== + dependencies: + get-intrinsic "^1.1.3" + +graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.9: + version "4.2.10" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" + integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== + +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + integrity sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg== + dependencies: + ansi-regex "^2.0.0" + +has-bigints@^1.0.1, has-bigints@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" + integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== + +has-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" + integrity sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA== + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-property-descriptors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" + integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== + dependencies: + get-intrinsic "^1.1.1" + +has-symbols@^1.0.1, has-symbols@^1.0.2, has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== + +has-tostringtag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" + integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== + dependencies: + has-symbols "^1.0.2" + +has@^1.0.0, has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +hash-sum@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/hash-sum/-/hash-sum-1.0.2.tgz#33b40777754c6432573c120cc3808bbd10d47f04" + integrity sha512-fUs4B4L+mlt8/XAtSOGMUO1TXmAelItBPtJG7CyHJfYTdDjwisntGO2JQz7oUsatOY9o68+57eziUVNw/mRHmA== + +he@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +hex-color-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e" + integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ== + +hosted-git-info@^2.1.4: + version "2.8.9" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" + integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== + +hsl-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/hsl-regex/-/hsl-regex-1.0.0.tgz#d49330c789ed819e276a4c0d272dffa30b18fe6e" + integrity sha512-M5ezZw4LzXbBKMruP+BNANf0k+19hDQMgpzBIYnya//Al+fjNct9Wf3b1WedLqdEs2hKBvxq/jh+DsHJLj0F9A== + +hsla-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/hsla-regex/-/hsla-regex-1.0.0.tgz#c1ce7a3168c8c6614033a4b5f7877f3b225f9c38" + integrity sha512-7Wn5GMLuHBjZCb2bTmnDOycho0p/7UVaAeqXZGbHrBCl6Yd/xDhQJAXe6Ga9AXJH2I5zY1dEdYw2u1UptnSBJA== + +html-encoding-sniffer@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz#42a6dc4fd33f00281176e8b23759ca4e4fa185f3" + integrity sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ== + dependencies: + whatwg-encoding "^1.0.5" + +html-escaper@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" + integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== + +html-tags@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.2.0.tgz#dbb3518d20b726524e4dd43de397eb0a95726961" + integrity sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg== + +http-proxy-agent@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a" + integrity sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg== + dependencies: + "@tootallnate/once" "1" + agent-base "6" + debug "4" + +https-proxy-agent@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" + integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== + dependencies: + agent-base "6" + debug "4" + +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.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +icss-replace-symbols@^1.0.2, icss-replace-symbols@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz#06ea6f83679a7749e386cfe1fe812ae5db223ded" + integrity sha512-chIaY3Vh2mh2Q3RGXttaDIzeiPvaVXJ+C4DAh/w3c37SKZ/U6PGMmuicR2EQQp9bKG8zLMCl7I+PtIoOOPp8Gg== + +icss-utils@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" + integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== + +ignore@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" + integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== + +ignore@^5.1.1, ignore@^5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.1.tgz#c2b1f76cb999ede1502f3a226a9310fdfe88d46c" + integrity sha512-d2qQLzTJ9WxQftPAuEQpSPmKqzxePjzVbpAVv62AQ64NTL+wR4JkrVqR/LqFsFEUsHDAiId52mJteHDFuDkElA== + +import-cwd@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/import-cwd/-/import-cwd-3.0.0.tgz#20845547718015126ea9b3676b7592fb8bd4cf92" + integrity sha512-4pnzH16plW+hgvRECbDWpQl3cqtvSofHWh44met7ESfZ8UZOWWddm8hEyDTqREJ9RbYHY8gi8DqmaelApoOGMg== + dependencies: + import-from "^3.0.0" + +import-fresh@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" + integrity sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg== + dependencies: + caller-path "^2.0.0" + resolve-from "^3.0.0" + +import-fresh@^3.0.0, import-fresh@^3.2.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +import-from@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/import-from/-/import-from-3.0.0.tgz#055cfec38cd5a27d8057ca51376d7d3bf0891966" + integrity sha512-CiuXOFFSzkU5x/CR0+z7T91Iht4CXgfCxVOFRhh2Zyhg5wOpWvvDLQUsWl+gcN+QscYBjez8hDCt85O7RLDttQ== + dependencies: + resolve-from "^5.0.0" + +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" + +import-modules@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/import-modules/-/import-modules-2.1.0.tgz#abe7df297cb6c1f19b57246eb8b8bd9664b6d8c2" + integrity sha512-8HEWcnkbGpovH9yInoisxaSoIg9Brbul+Ju3Kqe2UsYDUBJD/iQjSgEj0zPcTDPKfPp2fs5xlv1i+JSye/m1/A== + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + +indexes-of@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" + integrity sha512-bup+4tap3Hympa+JBJUG7XuOsdNQ6fxt0MHyXMKuLBKn0OqsTfvUxkUrroEX1+B2VsSHvCjiIcZVxRtYa4nllA== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +internal-slot@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.4.tgz#8551e7baf74a7a6ba5f749cfb16aa60722f0d6f3" + integrity sha512-tA8URYccNzMo94s5MQZgH8NB/XTa6HsOo0MLfXTKKEnHVVdegzaQoFZ7Jp44bdvLvY2waT5dc+j5ICEswhi7UQ== + dependencies: + get-intrinsic "^1.1.3" + has "^1.0.3" + side-channel "^1.0.4" + +is-absolute-url@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6" + integrity sha512-vOx7VprsKyllwjSkLV79NIhpyLfr3jAp7VaTCMXOJHu4m0Ew1CZ2fcjASwmV1jI3BWuWHB013M48eyeldk9gYg== + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== + +is-arrayish@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" + integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== + +is-bigint@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" + integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== + dependencies: + has-bigints "^1.0.1" + +is-boolean-object@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" + integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-callable@^1.1.4, is-callable@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" + integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== + +is-color-stop@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-color-stop/-/is-color-stop-1.1.0.tgz#cfff471aee4dd5c9e158598fbe12967b5cdad345" + integrity sha512-H1U8Vz0cfXNujrJzEcvvwMDW9Ra+biSYA3ThdQvAnMLJkEHQXn6bWzLkxHtVYJ+Sdbx0b6finn3jZiaVe7MAHA== + dependencies: + css-color-names "^0.0.4" + hex-color-regex "^1.1.0" + hsl-regex "^1.0.0" + hsla-regex "^1.0.0" + rgb-regex "^1.0.1" + rgba-regex "^1.0.0" + +is-core-module@^2.8.1, is-core-module@^2.9.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144" + integrity sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw== + dependencies: + has "^1.0.3" + +is-date-object@^1.0.1: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" + integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== + dependencies: + has-tostringtag "^1.0.0" + +is-directory@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" + integrity sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw== + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-generator-fn@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" + integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== + +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" + integrity sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g== + +is-negative-zero@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" + integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== + +is-number-object@^1.0.4: + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" + integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ== + dependencies: + has-tostringtag "^1.0.0" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-obj@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" + integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== + +is-potential-custom-element-name@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" + integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ== + +is-reference@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/is-reference/-/is-reference-1.2.1.tgz#8b2dac0b371f4bc994fdeaba9eb542d03002d0b7" + integrity sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ== + dependencies: + "@types/estree" "*" + +is-regex@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" + integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-resolvable@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" + integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg== + +is-shared-array-buffer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79" + integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA== + dependencies: + call-bind "^1.0.2" + +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + +is-string@^1.0.5, is-string@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" + integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== + dependencies: + has-tostringtag "^1.0.0" + +is-symbol@^1.0.2, is-symbol@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" + integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== + dependencies: + has-symbols "^1.0.2" + +is-typedarray@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== + +is-weakref@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" + integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== + dependencies: + call-bind "^1.0.2" + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz#189e7909d0a39fa5a3dfad5b03f71947770191d3" + integrity sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw== + +istanbul-lib-instrument@^5.0.4, istanbul-lib-instrument@^5.1.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz#d10c8885c2125574e1c231cacadf955675e1ce3d" + integrity sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg== + dependencies: + "@babel/core" "^7.12.3" + "@babel/parser" "^7.14.7" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-coverage "^3.2.0" + semver "^6.3.0" + +istanbul-lib-report@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6" + integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw== + dependencies: + istanbul-lib-coverage "^3.0.0" + make-dir "^3.0.0" + supports-color "^7.1.0" + +istanbul-lib-source-maps@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551" + integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== + dependencies: + debug "^4.1.1" + istanbul-lib-coverage "^3.0.0" + source-map "^0.6.1" + +istanbul-reports@^3.1.3: + version "3.1.5" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.5.tgz#cc9a6ab25cb25659810e4785ed9d9fb742578bae" + integrity sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w== + dependencies: + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" + +jest-changed-files@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-27.5.1.tgz#a348aed00ec9bf671cc58a66fcbe7c3dfd6a68f5" + integrity sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw== + dependencies: + "@jest/types" "^27.5.1" + execa "^5.0.0" + throat "^6.0.1" + +jest-circus@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-27.5.1.tgz#37a5a4459b7bf4406e53d637b49d22c65d125ecc" + integrity sha512-D95R7x5UtlMA5iBYsOHFFbMD/GVA4R/Kdq15f7xYWUfWHBto9NYRsOvnSauTgdF+ogCpJ4tyKOXhUifxS65gdw== + dependencies: + "@jest/environment" "^27.5.1" + "@jest/test-result" "^27.5.1" + "@jest/types" "^27.5.1" + "@types/node" "*" + chalk "^4.0.0" + co "^4.6.0" + dedent "^0.7.0" + expect "^27.5.1" + is-generator-fn "^2.0.0" + jest-each "^27.5.1" + jest-matcher-utils "^27.5.1" + jest-message-util "^27.5.1" + jest-runtime "^27.5.1" + jest-snapshot "^27.5.1" + jest-util "^27.5.1" + pretty-format "^27.5.1" + slash "^3.0.0" + stack-utils "^2.0.3" + throat "^6.0.1" + +jest-cli@^27.0.6: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-27.5.1.tgz#278794a6e6458ea8029547e6c6cbf673bd30b145" + integrity sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw== + dependencies: + "@jest/core" "^27.5.1" + "@jest/test-result" "^27.5.1" + "@jest/types" "^27.5.1" + chalk "^4.0.0" + exit "^0.1.2" + graceful-fs "^4.2.9" + import-local "^3.0.2" + jest-config "^27.5.1" + jest-util "^27.5.1" + jest-validate "^27.5.1" + prompts "^2.0.1" + yargs "^16.2.0" + +jest-config@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-27.5.1.tgz#5c387de33dca3f99ad6357ddeccd91bf3a0e4a41" + integrity sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA== + dependencies: + "@babel/core" "^7.8.0" + "@jest/test-sequencer" "^27.5.1" + "@jest/types" "^27.5.1" + babel-jest "^27.5.1" + chalk "^4.0.0" + ci-info "^3.2.0" + deepmerge "^4.2.2" + glob "^7.1.1" + graceful-fs "^4.2.9" + jest-circus "^27.5.1" + jest-environment-jsdom "^27.5.1" + jest-environment-node "^27.5.1" + jest-get-type "^27.5.1" + jest-jasmine2 "^27.5.1" + jest-regex-util "^27.5.1" + jest-resolve "^27.5.1" + jest-runner "^27.5.1" + jest-util "^27.5.1" + jest-validate "^27.5.1" + micromatch "^4.0.4" + parse-json "^5.2.0" + pretty-format "^27.5.1" + slash "^3.0.0" + strip-json-comments "^3.1.1" + +jest-diff@^26.0.0: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-26.6.2.tgz#1aa7468b52c3a68d7d5c5fdcdfcd5e49bd164394" + integrity sha512-6m+9Z3Gv9wN0WFVasqjCL/06+EFCMTqDEUl/b87HYK2rAPTyfz4ZIuSlPhY51PIQRWx5TaxeF1qmXKe9gfN3sA== + dependencies: + chalk "^4.0.0" + diff-sequences "^26.6.2" + jest-get-type "^26.3.0" + pretty-format "^26.6.2" + +jest-diff@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-27.5.1.tgz#a07f5011ac9e6643cf8a95a462b7b1ecf6680def" + integrity sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw== + dependencies: + chalk "^4.0.0" + diff-sequences "^27.5.1" + jest-get-type "^27.5.1" + pretty-format "^27.5.1" + +jest-docblock@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-27.5.1.tgz#14092f364a42c6108d42c33c8cf30e058e25f6c0" + integrity sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ== + dependencies: + detect-newline "^3.0.0" + +jest-each@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-27.5.1.tgz#5bc87016f45ed9507fed6e4702a5b468a5b2c44e" + integrity sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ== + dependencies: + "@jest/types" "^27.5.1" + chalk "^4.0.0" + jest-get-type "^27.5.1" + jest-util "^27.5.1" + pretty-format "^27.5.1" + +jest-environment-jsdom@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz#ea9ccd1fc610209655a77898f86b2b559516a546" + integrity sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw== + dependencies: + "@jest/environment" "^27.5.1" + "@jest/fake-timers" "^27.5.1" + "@jest/types" "^27.5.1" + "@types/node" "*" + jest-mock "^27.5.1" + jest-util "^27.5.1" + jsdom "^16.6.0" + +jest-environment-node@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-27.5.1.tgz#dedc2cfe52fab6b8f5714b4808aefa85357a365e" + integrity sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw== + dependencies: + "@jest/environment" "^27.5.1" + "@jest/fake-timers" "^27.5.1" + "@jest/types" "^27.5.1" + "@types/node" "*" + jest-mock "^27.5.1" + jest-util "^27.5.1" + +jest-get-type@^26.3.0: + version "26.3.0" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-26.3.0.tgz#e97dc3c3f53c2b406ca7afaed4493b1d099199e0" + integrity sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig== + +jest-get-type@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.5.1.tgz#3cd613c507b0f7ace013df407a1c1cd578bcb4f1" + integrity sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw== + +jest-haste-map@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-27.5.1.tgz#9fd8bd7e7b4fa502d9c6164c5640512b4e811e7f" + integrity sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng== + dependencies: + "@jest/types" "^27.5.1" + "@types/graceful-fs" "^4.1.2" + "@types/node" "*" + anymatch "^3.0.3" + fb-watchman "^2.0.0" + graceful-fs "^4.2.9" + jest-regex-util "^27.5.1" + jest-serializer "^27.5.1" + jest-util "^27.5.1" + jest-worker "^27.5.1" + micromatch "^4.0.4" + walker "^1.0.7" + optionalDependencies: + fsevents "^2.3.2" + +jest-jasmine2@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz#a037b0034ef49a9f3d71c4375a796f3b230d1ac4" + integrity sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ== + dependencies: + "@jest/environment" "^27.5.1" + "@jest/source-map" "^27.5.1" + "@jest/test-result" "^27.5.1" + "@jest/types" "^27.5.1" + "@types/node" "*" + chalk "^4.0.0" + co "^4.6.0" + expect "^27.5.1" + is-generator-fn "^2.0.0" + jest-each "^27.5.1" + jest-matcher-utils "^27.5.1" + jest-message-util "^27.5.1" + jest-runtime "^27.5.1" + jest-snapshot "^27.5.1" + jest-util "^27.5.1" + pretty-format "^27.5.1" + throat "^6.0.1" + +jest-leak-detector@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz#6ec9d54c3579dd6e3e66d70e3498adf80fde3fb8" + integrity sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ== + dependencies: + jest-get-type "^27.5.1" + pretty-format "^27.5.1" + +jest-matcher-utils@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz#9c0cdbda8245bc22d2331729d1091308b40cf8ab" + integrity sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw== + dependencies: + chalk "^4.0.0" + jest-diff "^27.5.1" + jest-get-type "^27.5.1" + pretty-format "^27.5.1" + +jest-message-util@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-27.5.1.tgz#bdda72806da10d9ed6425e12afff38cd1458b6cf" + integrity sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g== + dependencies: + "@babel/code-frame" "^7.12.13" + "@jest/types" "^27.5.1" + "@types/stack-utils" "^2.0.0" + chalk "^4.0.0" + graceful-fs "^4.2.9" + micromatch "^4.0.4" + pretty-format "^27.5.1" + slash "^3.0.0" + stack-utils "^2.0.3" + +jest-mock@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-27.5.1.tgz#19948336d49ef4d9c52021d34ac7b5f36ff967d6" + integrity sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og== + dependencies: + "@jest/types" "^27.5.1" + "@types/node" "*" + +jest-pnp-resolver@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz#930b1546164d4ad5937d5540e711d4d38d4cad2e" + integrity sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w== + +jest-regex-util@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-27.5.1.tgz#4da143f7e9fd1e542d4aa69617b38e4a78365b95" + integrity sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg== + +jest-resolve-dependencies@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz#d811ecc8305e731cc86dd79741ee98fed06f1da8" + integrity sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg== + dependencies: + "@jest/types" "^27.5.1" + jest-regex-util "^27.5.1" + jest-snapshot "^27.5.1" + +jest-resolve@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-27.5.1.tgz#a2f1c5a0796ec18fe9eb1536ac3814c23617b384" + integrity sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw== + dependencies: + "@jest/types" "^27.5.1" + chalk "^4.0.0" + graceful-fs "^4.2.9" + jest-haste-map "^27.5.1" + jest-pnp-resolver "^1.2.2" + jest-util "^27.5.1" + jest-validate "^27.5.1" + resolve "^1.20.0" + resolve.exports "^1.1.0" + slash "^3.0.0" + +jest-runner@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-27.5.1.tgz#071b27c1fa30d90540805c5645a0ec167c7b62e5" + integrity sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ== + dependencies: + "@jest/console" "^27.5.1" + "@jest/environment" "^27.5.1" + "@jest/test-result" "^27.5.1" + "@jest/transform" "^27.5.1" + "@jest/types" "^27.5.1" + "@types/node" "*" + chalk "^4.0.0" + emittery "^0.8.1" + graceful-fs "^4.2.9" + jest-docblock "^27.5.1" + jest-environment-jsdom "^27.5.1" + jest-environment-node "^27.5.1" + jest-haste-map "^27.5.1" + jest-leak-detector "^27.5.1" + jest-message-util "^27.5.1" + jest-resolve "^27.5.1" + jest-runtime "^27.5.1" + jest-util "^27.5.1" + jest-worker "^27.5.1" + source-map-support "^0.5.6" + throat "^6.0.1" + +jest-runtime@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-27.5.1.tgz#4896003d7a334f7e8e4a53ba93fb9bcd3db0a1af" + integrity sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A== + dependencies: + "@jest/environment" "^27.5.1" + "@jest/fake-timers" "^27.5.1" + "@jest/globals" "^27.5.1" + "@jest/source-map" "^27.5.1" + "@jest/test-result" "^27.5.1" + "@jest/transform" "^27.5.1" + "@jest/types" "^27.5.1" + chalk "^4.0.0" + cjs-module-lexer "^1.0.0" + collect-v8-coverage "^1.0.0" + execa "^5.0.0" + glob "^7.1.3" + graceful-fs "^4.2.9" + jest-haste-map "^27.5.1" + jest-message-util "^27.5.1" + jest-mock "^27.5.1" + jest-regex-util "^27.5.1" + jest-resolve "^27.5.1" + jest-snapshot "^27.5.1" + jest-util "^27.5.1" + slash "^3.0.0" + strip-bom "^4.0.0" + +jest-serializer@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-27.5.1.tgz#81438410a30ea66fd57ff730835123dea1fb1f64" + integrity sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w== + dependencies: + "@types/node" "*" + graceful-fs "^4.2.9" + +jest-snapshot@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-27.5.1.tgz#b668d50d23d38054a51b42c4039cab59ae6eb6a1" + integrity sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA== + dependencies: + "@babel/core" "^7.7.2" + "@babel/generator" "^7.7.2" + "@babel/plugin-syntax-typescript" "^7.7.2" + "@babel/traverse" "^7.7.2" + "@babel/types" "^7.0.0" + "@jest/transform" "^27.5.1" + "@jest/types" "^27.5.1" + "@types/babel__traverse" "^7.0.4" + "@types/prettier" "^2.1.5" + babel-preset-current-node-syntax "^1.0.0" + chalk "^4.0.0" + expect "^27.5.1" + graceful-fs "^4.2.9" + jest-diff "^27.5.1" + jest-get-type "^27.5.1" + jest-haste-map "^27.5.1" + jest-matcher-utils "^27.5.1" + jest-message-util "^27.5.1" + jest-util "^27.5.1" + natural-compare "^1.4.0" + pretty-format "^27.5.1" + semver "^7.3.2" + +jest-util@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-27.5.1.tgz#3ba9771e8e31a0b85da48fe0b0891fb86c01c2f9" + integrity sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw== + dependencies: + "@jest/types" "^27.5.1" + "@types/node" "*" + chalk "^4.0.0" + ci-info "^3.2.0" + graceful-fs "^4.2.9" + picomatch "^2.2.3" + +jest-validate@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-27.5.1.tgz#9197d54dc0bdb52260b8db40b46ae668e04df067" + integrity sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ== + dependencies: + "@jest/types" "^27.5.1" + camelcase "^6.2.0" + chalk "^4.0.0" + jest-get-type "^27.5.1" + leven "^3.1.0" + pretty-format "^27.5.1" + +jest-watcher@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-27.5.1.tgz#71bd85fb9bde3a2c2ec4dc353437971c43c642a2" + integrity sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw== + dependencies: + "@jest/test-result" "^27.5.1" + "@jest/types" "^27.5.1" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + jest-util "^27.5.1" + string-length "^4.0.1" + +jest-worker@^27.5.1: + 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" + +jest@27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest/-/jest-27.0.6.tgz#10517b2a628f0409087fbf473db44777d7a04505" + integrity sha512-EjV8aETrsD0wHl7CKMibKwQNQc3gIRBXlTikBmmHUeVMKaPFxdcUIBfoDqTSXDoGJIivAYGqCWVlzCSaVjPQsA== + dependencies: + "@jest/core" "^27.0.6" + import-local "^3.0.2" + jest-cli "^27.0.6" + +js-base64@^2.1.9: + version "2.6.4" + resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.6.4.tgz#f4e686c5de1ea1f867dbcad3d46d969428df98c4" + integrity sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ== + +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^3.13.1: + version "3.14.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +jsdom@^16.6.0: + version "16.7.0" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.7.0.tgz#918ae71965424b197c819f8183a754e18977b710" + integrity sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw== + dependencies: + abab "^2.0.5" + acorn "^8.2.4" + acorn-globals "^6.0.0" + cssom "^0.4.4" + cssstyle "^2.3.0" + data-urls "^2.0.0" + decimal.js "^10.2.1" + domexception "^2.0.1" + escodegen "^2.0.0" + form-data "^3.0.0" + html-encoding-sniffer "^2.0.1" + http-proxy-agent "^4.0.1" + https-proxy-agent "^5.0.0" + is-potential-custom-element-name "^1.0.1" + nwsapi "^2.2.0" + parse5 "6.0.1" + saxes "^5.0.1" + symbol-tree "^3.2.4" + tough-cookie "^4.0.0" + w3c-hr-time "^1.0.2" + w3c-xmlserializer "^2.0.0" + webidl-conversions "^6.1.0" + whatwg-encoding "^1.0.5" + whatwg-mimetype "^2.3.0" + whatwg-url "^8.5.0" + ws "^7.4.6" + xml-name-validator "^3.0.0" + +jsesc@^2.5.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== + +json-parse-better-errors@^1.0.1: + 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-parse-even-better-errors@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== + +json5@^0.5.0: + version "0.5.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" + integrity sha512-4xrs1aW+6N5DalkqSVA8fxh458CXvR99WU8WLKmq4v8eWAL86Xo3BVqyd3SkA9wEVjCMqyvvRRkshAdOnBp5rw== + +json5@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" + integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== + dependencies: + minimist "^1.2.0" + +json5@^2.1.2, json5@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c" + integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA== + +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg== + optionalDependencies: + graceful-fs "^4.1.6" + +kleur@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" + integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== + +leven@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" + integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== + +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +levn@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + integrity sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA== + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + +lilconfig@^2.0.5: + version "2.0.6" + resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.6.tgz#32a384558bd58af3d4c6e077dd1ad1d397bc69d4" + integrity sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg== + +lines-and-columns@^1.1.6: + version "1.2.4" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" + integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== + +load-json-file@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" + integrity sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw== + dependencies: + graceful-fs "^4.1.2" + parse-json "^4.0.0" + pify "^3.0.0" + strip-bom "^3.0.0" + +loader-utils@^0.2.16: + version "0.2.17" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.17.tgz#f86e6374d43205a6e6c60e9196f17c0299bfb348" + integrity sha512-tiv66G0SmiOx+pLWMtGEkfSEejxvb6N6uRrQjfWJIT79W9GMpgKeCAmm9aVBKtd4WEgntciI8CsGqjpDoCWJug== + dependencies: + big.js "^3.1.3" + emojis-list "^2.0.0" + json5 "^0.5.0" + object-assign "^4.0.1" + +loader-utils@^3.2.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-3.2.1.tgz#4fb104b599daafd82ef3e1a41fb9265f87e1f576" + integrity sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw== + +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-es@4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee" + integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw== + +lodash.camelcase@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" + integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA== + +lodash.memoize@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" + integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== + +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +lodash.truncate@^4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193" + integrity sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw== + +lodash.uniq@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" + integrity sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ== + +lodash@^4.17.20, lodash@^4.17.21, lodash@^4.7.0: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +lru-cache@^4.1.2: + version "4.1.5" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" + integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== + dependencies: + pseudomap "^1.0.2" + yallist "^2.1.2" + +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" + +magic-string@^0.25.7: + version "0.25.9" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.9.tgz#de7f9faf91ef8a1c91d02c2e5314c8277dbcdd1c" + integrity sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ== + dependencies: + sourcemap-codec "^1.4.8" + +make-dir@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + dependencies: + semver "^6.0.0" + +makeerror@1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a" + integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg== + dependencies: + tmpl "1.0.5" + +mdn-data@2.0.14: + version "2.0.14" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" + integrity sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow== + +mdn-data@2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b" + integrity sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA== + +memorystream@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" + integrity sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw== + +merge-source-map@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/merge-source-map/-/merge-source-map-1.1.0.tgz#2fdde7e6020939f70906a68f2d7ae685e4c8c646" + integrity sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw== + dependencies: + source-map "^0.6.1" + +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.3.0, merge2@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +micromatch@^4.0.4: + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + dependencies: + braces "^3.0.2" + picomatch "^2.3.1" + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +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== + +minimatch@^3.0.2, minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimist@^1.2.0, minimist@^1.2.6: + version "1.2.7" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18" + integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g== + +mkdirp@~0.5.1: + version "0.5.6" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" + integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== + dependencies: + minimist "^1.2.6" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@^2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +multimap@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/multimap/-/multimap-1.1.0.tgz#5263febc085a1791c33b59bb3afc6a76a2a10ca8" + integrity sha512-0ZIR9PasPxGXmRsEF8jsDzndzHDj7tIav+JUmvIFB/WHswliFnquxECT/De7GR4yg99ky/NlRKJT82G1y271bw== + +nanoid@^3.1.23: + version "3.3.4" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab" + integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw== + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== + +nice-try@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" + integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== + +node-emoji@^1.8.1: + version "1.11.0" + resolved "https://registry.yarnpkg.com/node-emoji/-/node-emoji-1.11.0.tgz#69a0150e6946e2f115e9d7ea4df7971e2628301c" + integrity sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A== + dependencies: + lodash "^4.17.21" + +node-int64@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" + integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== + +node-releases@^2.0.6: + version "2.0.7" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.7.tgz#593edbc7c22860ee4d32d3933cfebdfab0c0e0e5" + integrity sha512-EJ3rzxL9pTWPjk5arA0s0dgXpnyiAbJDE6wHT62g7VsgrgQgmmZ+Ru++M1BFofncWja+Pnn3rEr3fieRySAdKQ== + +normalize-package-data@^2.3.2, normalize-package-data@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" + integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== + dependencies: + hosted-git-info "^2.1.4" + resolve "^1.10.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +normalize-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +normalize-range@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" + integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA== + +normalize-url@^3.0.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559" + integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg== + +normalize.css@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/normalize.css/-/normalize.css-8.0.1.tgz#9b98a208738b9cc2634caacbc42d131c97487bf3" + integrity sha512-qizSNPO93t1YUuUhP22btGOo3chcvDFqFaj2TRybP0DMxkHOCTYwp3n34fel4a31ORXy4m1Xq0Gyqpb5m33qIg== + +npm-run-all@4.1.5: + version "4.1.5" + resolved "https://registry.yarnpkg.com/npm-run-all/-/npm-run-all-4.1.5.tgz#04476202a15ee0e2e214080861bff12a51d98fba" + integrity sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ== + dependencies: + ansi-styles "^3.2.1" + chalk "^2.4.1" + cross-spawn "^6.0.5" + memorystream "^0.3.1" + minimatch "^3.0.4" + pidtree "^0.3.0" + read-pkg "^3.0.0" + shell-quote "^1.6.1" + string.prototype.padend "^3.0.0" + +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" + +nth-check@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" + integrity sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg== + dependencies: + boolbase "~1.0.0" + +num2fraction@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede" + integrity sha512-Y1wZESM7VUThYY+4W+X4ySH2maqcA+p7UR+w8VWNWVAd6lwuXXWz/w/Cz43J/dI2I+PS6wD5N+bJUF+gjWvIqg== + +nwsapi@^2.2.0: + version "2.2.2" + resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.2.tgz#e5418863e7905df67d51ec95938d67bf801f0bb0" + integrity sha512-90yv+6538zuvUMnN+zCr8LuV6bPFdq50304114vJYJ8RDyK8D5O9Phpbd6SZWgI7PwzmmfN1upeOJlvybDSgCw== + +object-assign@^4.0.1, object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== + +object-hash@^2.0.3: + version "2.2.0" + resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-2.2.0.tgz#5ad518581eefc443bd763472b8ff2e9c2c0d54a5" + integrity sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw== + +object-inspect@^1.12.2, object-inspect@^1.9.0: + version "1.12.2" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" + integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== + +object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object.assign@^4.1.0, object.assign@^4.1.4: + version "4.1.4" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f" + integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + has-symbols "^1.0.3" + object-keys "^1.1.1" + +object.getownpropertydescriptors@^2.1.0: + version "2.1.5" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.5.tgz#db5a9002489b64eef903df81d6623c07e5b4b4d3" + integrity sha512-yDNzckpM6ntyQiGTik1fKV1DcVDRS+w8bvpWNCBanvH5LfRX9O8WTHqQzG4RZwRAM4I0oU7TV11Lj5v0g20ibw== + dependencies: + array.prototype.reduce "^1.0.5" + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + +object.values@^1.1.0, object.values@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.6.tgz#4abbaa71eba47d63589d402856f908243eea9b1d" + integrity sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + 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" + +optionator@^0.8.1: + version "0.8.3" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" + integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.6" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + word-wrap "~1.2.3" + +optionator@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" + integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== + dependencies: + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.3" + +p-finally@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + integrity sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow== + +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^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-queue@^6.6.2: + version "6.6.2" + resolved "https://registry.yarnpkg.com/p-queue/-/p-queue-6.6.2.tgz#2068a9dcf8e67dd0ec3e7a2bcb76810faa85e426" + integrity sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ== + dependencies: + eventemitter3 "^4.0.4" + p-timeout "^3.2.0" + +p-timeout@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-3.2.0.tgz#c7e17abc971d2a7962ef83626b35d635acf23dfe" + integrity sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg== + dependencies: + p-finally "^1.0.0" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +parse-json@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" + integrity sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw== + dependencies: + error-ex "^1.3.1" + json-parse-better-errors "^1.0.1" + +parse-json@^5.0.0, parse-json@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" + integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-even-better-errors "^2.3.0" + lines-and-columns "^1.1.6" + +parse5@6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" + integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== + +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.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-key@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + integrity sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw== + +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.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-type@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" + integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg== + dependencies: + pify "^3.0.0" + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +picocolors@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-0.2.1.tgz#570670f793646851d1ba135996962abad587859f" + integrity sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA== + +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.2, picomatch@^2.2.3, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +pidtree@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.3.1.tgz#ef09ac2cc0533df1f3250ccf2c4d366b0d12114a" + integrity sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA== + +pify@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" + integrity sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg== + +pify@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-5.0.0.tgz#1f5eca3f5e87ebec28cc6d54a0e4aaf00acc127f" + integrity sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA== + +pirates@^4.0.4: + version "4.0.5" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.5.tgz#feec352ea5c3268fb23a37c702ab1699f35a5f3b" + integrity sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ== + +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" + +pluralize@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1" + integrity sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA== + +postcss-calc@^7.0.1: + version "7.0.5" + resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.5.tgz#f8a6e99f12e619c2ebc23cf6c486fdc15860933e" + integrity sha512-1tKHutbGtLtEZF6PT4JSihCHfIVldU72mZ8SdZHIYriIZ9fh9k9aWSppaT8rHsyI3dX+KSR+W+Ix9BMY3AODrg== + dependencies: + postcss "^7.0.27" + postcss-selector-parser "^6.0.2" + postcss-value-parser "^4.0.2" + +postcss-colormin@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-4.0.3.tgz#ae060bce93ed794ac71264f08132d550956bd381" + integrity sha512-WyQFAdDZpExQh32j0U0feWisZ0dmOtPl44qYmJKkq9xFWY3p+4qnRzCHeNrkeRhwPHz9bQ3mo0/yVkaply0MNw== + dependencies: + browserslist "^4.0.0" + color "^3.0.0" + has "^1.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-convert-values@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz#ca3813ed4da0f812f9d43703584e449ebe189a7f" + integrity sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ== + dependencies: + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-discard-comments@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-4.0.2.tgz#1fbabd2c246bff6aaad7997b2b0918f4d7af4033" + integrity sha512-RJutN259iuRf3IW7GZyLM5Sw4GLTOH8FmsXBnv8Ab/Tc2k4SR4qbV4DNbyyY4+Sjo362SyDmW2DQ7lBSChrpkg== + dependencies: + postcss "^7.0.0" + +postcss-discard-duplicates@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz#3fe133cd3c82282e550fc9b239176a9207b784eb" + integrity sha512-ZNQfR1gPNAiXZhgENFfEglF93pciw0WxMkJeVmw8eF+JZBbMD7jp6C67GqJAXVZP2BWbOztKfbsdmMp/k8c6oQ== + dependencies: + postcss "^7.0.0" + +postcss-discard-empty@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz#c8c951e9f73ed9428019458444a02ad90bb9f765" + integrity sha512-B9miTzbznhDjTfjvipfHoqbWKwd0Mj+/fL5s1QOz06wufguil+Xheo4XpOnc4NqKYBCNqqEzgPv2aPBIJLox0w== + dependencies: + postcss "^7.0.0" + +postcss-discard-overridden@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz#652aef8a96726f029f5e3e00146ee7a4e755ff57" + integrity sha512-IYY2bEDD7g1XM1IDEsUT4//iEYCxAmP5oDSFMVU/JVvT7gh+l4fmjciLqGgwjdWpQIdb0Che2VX00QObS5+cTg== + dependencies: + postcss "^7.0.0" + +postcss-functions@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postcss-functions/-/postcss-functions-3.0.0.tgz#0e94d01444700a481de20de4d55fb2640564250e" + integrity sha512-N5yWXWKA+uhpLQ9ZhBRl2bIAdM6oVJYpDojuI1nF2SzXBimJcdjFwiAouBVbO5VuOF3qA6BSFWFc3wXbbj72XQ== + dependencies: + glob "^7.1.2" + object-assign "^4.1.1" + postcss "^6.0.9" + postcss-value-parser "^3.3.0" + +postcss-js@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/postcss-js/-/postcss-js-2.0.3.tgz#a96f0f23ff3d08cec7dc5b11bf11c5f8077cdab9" + integrity sha512-zS59pAk3deu6dVHyrGqmC3oDXBdNdajk4k1RyxeVXCrcEDBUBHoIhE4QTsmhxgzXxsaqFDAkUZfmMa5f/N/79w== + dependencies: + camelcase-css "^2.0.1" + postcss "^7.0.18" + +postcss-load-config@^3.0.0: + version "3.1.4" + resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-3.1.4.tgz#1ab2571faf84bb078877e1d07905eabe9ebda855" + integrity sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg== + dependencies: + lilconfig "^2.0.5" + yaml "^1.10.2" + +postcss-merge-longhand@^4.0.11: + version "4.0.11" + resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz#62f49a13e4a0ee04e7b98f42bb16062ca2549e24" + integrity sha512-alx/zmoeXvJjp7L4mxEMjh8lxVlDFX1gqWHzaaQewwMZiVhLo42TEClKaeHbRf6J7j82ZOdTJ808RtN0ZOZwvw== + dependencies: + css-color-names "0.0.4" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + stylehacks "^4.0.0" + +postcss-merge-rules@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-4.0.3.tgz#362bea4ff5a1f98e4075a713c6cb25aefef9a650" + integrity sha512-U7e3r1SbvYzO0Jr3UT/zKBVgYYyhAz0aitvGIYOYK5CPmkNih+WDSsS5tvPrJ8YMQYlEMvsZIiqmn7HdFUaeEQ== + dependencies: + browserslist "^4.0.0" + caniuse-api "^3.0.0" + cssnano-util-same-parent "^4.0.0" + postcss "^7.0.0" + postcss-selector-parser "^3.0.0" + vendors "^1.0.0" + +postcss-minify-font-values@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz#cd4c344cce474343fac5d82206ab2cbcb8afd5a6" + integrity sha512-j85oO6OnRU9zPf04+PZv1LYIYOprWm6IA6zkXkrJXyRveDEuQggG6tvoy8ir8ZwjLxLuGfNkCZEQG7zan+Hbtg== + dependencies: + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-minify-gradients@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-4.0.2.tgz#93b29c2ff5099c535eecda56c4aa6e665a663471" + integrity sha512-qKPfwlONdcf/AndP1U8SJ/uzIJtowHlMaSioKzebAXSG4iJthlWC9iSWznQcX4f66gIWX44RSA841HTHj3wK+Q== + dependencies: + cssnano-util-get-arguments "^4.0.0" + is-color-stop "^1.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-minify-params@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-4.0.2.tgz#6b9cef030c11e35261f95f618c90036d680db874" + integrity sha512-G7eWyzEx0xL4/wiBBJxJOz48zAKV2WG3iZOqVhPet/9geefm/Px5uo1fzlHu+DOjT+m0Mmiz3jkQzVHe6wxAWg== + dependencies: + alphanum-sort "^1.0.0" + browserslist "^4.0.0" + cssnano-util-get-arguments "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + uniqs "^2.0.0" + +postcss-minify-selectors@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-4.0.2.tgz#e2e5eb40bfee500d0cd9243500f5f8ea4262fbd8" + integrity sha512-D5S1iViljXBj9kflQo4YutWnJmwm8VvIsU1GeXJGiG9j8CIg9zs4voPMdQDUmIxetUOh60VilsNzCiAFTOqu3g== + dependencies: + alphanum-sort "^1.0.0" + has "^1.0.0" + postcss "^7.0.0" + postcss-selector-parser "^3.0.0" + +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@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz#f7d80c398c5a393fa7964466bd19500a7d61c069" + integrity sha512-X4cquUPIaAd86raVrBwO8fwRfkIdbwFu7CTfEOjiZQHVQwlHRSkTgH5NLDmMm5+1hQO8u6dZ+TOOJDbay1hYpA== + dependencies: + css-selector-tokenizer "^0.7.0" + postcss "^6.0.1" + +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@^1.0.2: + version "1.1.0" + resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz#d6ea64994c79f97b62a72b426fbe6056a194bb90" + integrity sha512-LTYwnA4C1He1BKZXIx1CYiHixdSe9LWYVKadq9lK5aCCMkoOkFyZ7aigt+srfjlRplJY3gIol6KUNefdMQJdlw== + dependencies: + css-selector-tokenizer "^0.7.0" + postcss "^6.0.1" + +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-sync@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-sync/-/postcss-modules-sync-1.0.0.tgz#619a719cf78dd16a4834135140b324cf77334be1" + integrity sha512-kIDk2NYmxHshqUbjtFf1WdBij08IsvRdgDT0nOGWhvwkr8/z1piLSzxVrPt56J4DU6ON986h2H+5xcBnFhT8UQ== + dependencies: + generic-names "^1.0.2" + icss-replace-symbols "^1.0.2" + postcss "^5.2.5" + postcss-modules-local-by-default "^1.1.1" + postcss-modules-scope "^1.0.2" + string-hash "^1.1.0" + +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-modules@^4.0.0: + version "4.3.1" + resolved "https://registry.yarnpkg.com/postcss-modules/-/postcss-modules-4.3.1.tgz#517c06c09eab07d133ae0effca2c510abba18048" + integrity sha512-ItUhSUxBBdNamkT3KzIZwYNNRFKmkJrofvC2nWab3CPKhYBQ1f27XXh1PAPE27Psx58jeelPsxWB/+og+KEH0Q== + dependencies: + generic-names "^4.0.0" + icss-replace-symbols "^1.1.0" + lodash.camelcase "^4.3.0" + 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" + string-hash "^1.1.1" + +postcss-nested@^4.1.1: + version "4.2.3" + resolved "https://registry.yarnpkg.com/postcss-nested/-/postcss-nested-4.2.3.tgz#c6f255b0a720549776d220d00c4b70cd244136f6" + integrity sha512-rOv0W1HquRCamWy2kFl3QazJMMe1ku6rCFoAAH+9AcxdbpDeBr6k968MLWuLjvjMcGEip01ak09hKOEgpK9hvw== + dependencies: + postcss "^7.0.32" + postcss-selector-parser "^6.0.2" + +postcss-normalize-charset@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz#8b35add3aee83a136b0471e0d59be58a50285dd4" + integrity sha512-gMXCrrlWh6G27U0hF3vNvR3w8I1s2wOBILvA87iNXaPvSNo5uZAMYsZG7XjCUf1eVxuPfyL4TJ7++SGZLc9A3g== + dependencies: + postcss "^7.0.0" + +postcss-normalize-display-values@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.2.tgz#0dbe04a4ce9063d4667ed2be476bb830c825935a" + integrity sha512-3F2jcsaMW7+VtRMAqf/3m4cPFhPD3EFRgNs18u+k3lTJJlVe7d0YPO+bnwqo2xg8YiRpDXJI2u8A0wqJxMsQuQ== + dependencies: + cssnano-util-get-match "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-positions@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-4.0.2.tgz#05f757f84f260437378368a91f8932d4b102917f" + integrity sha512-Dlf3/9AxpxE+NF1fJxYDeggi5WwV35MXGFnnoccP/9qDtFrTArZ0D0R+iKcg5WsUd8nUYMIl8yXDCtcrT8JrdA== + dependencies: + cssnano-util-get-arguments "^4.0.0" + has "^1.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-repeat-style@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.2.tgz#c4ebbc289f3991a028d44751cbdd11918b17910c" + integrity sha512-qvigdYYMpSuoFs3Is/f5nHdRLJN/ITA7huIoCyqqENJe9PvPmLhNLMu7QTjPdtnVf6OcYYO5SHonx4+fbJE1+Q== + dependencies: + cssnano-util-get-arguments "^4.0.0" + cssnano-util-get-match "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-string@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-4.0.2.tgz#cd44c40ab07a0c7a36dc5e99aace1eca4ec2690c" + integrity sha512-RrERod97Dnwqq49WNz8qo66ps0swYZDSb6rM57kN2J+aoyEAJfZ6bMx0sx/F9TIEX0xthPGCmeyiam/jXif0eA== + dependencies: + has "^1.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-timing-functions@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.2.tgz#8e009ca2a3949cdaf8ad23e6b6ab99cb5e7d28d9" + integrity sha512-acwJY95edP762e++00Ehq9L4sZCEcOPyaHwoaFOhIwWCDfik6YvqsYNxckee65JHLKzuNSSmAdxwD2Cud1Z54A== + dependencies: + cssnano-util-get-match "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-unicode@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz#841bd48fdcf3019ad4baa7493a3d363b52ae1cfb" + integrity sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg== + dependencies: + browserslist "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-url@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz#10e437f86bc7c7e58f7b9652ed878daaa95faae1" + integrity sha512-p5oVaF4+IHwu7VpMan/SSpmpYxcJMtkGppYf0VbdH5B6hN8YNmVyJLuY9FmLQTzY3fag5ESUUHDqM+heid0UVA== + dependencies: + is-absolute-url "^2.0.0" + normalize-url "^3.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-whitespace@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.2.tgz#bf1d4070fe4fcea87d1348e825d8cc0c5faa7d82" + integrity sha512-tO8QIgrsI3p95r8fyqKV+ufKlSHh9hMJqACqbv2XknufqEDhDvbguXGBBqxw9nsQoXWf0qOqppziKJKHMD4GtA== + dependencies: + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-ordered-values@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-4.1.2.tgz#0cf75c820ec7d5c4d280189559e0b571ebac0eee" + integrity sha512-2fCObh5UanxvSxeXrtLtlwVThBvHn6MQcu4ksNT2tsaV2Fg76R2CV98W7wNSlX+5/pFwEyaDwKLLoEV7uRybAw== + dependencies: + cssnano-util-get-arguments "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-reduce-initial@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz#7fd42ebea5e9c814609639e2c2e84ae270ba48df" + integrity sha512-gKWmR5aUulSjbzOfD9AlJiHCGH6AEVLaM0AV+aSioxUDd16qXP1PCh8d1/BGVvpdWn8k/HiK7n6TjeoXN1F7DA== + dependencies: + browserslist "^4.0.0" + caniuse-api "^3.0.0" + has "^1.0.0" + postcss "^7.0.0" + +postcss-reduce-transforms@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.2.tgz#17efa405eacc6e07be3414a5ca2d1074681d4e29" + integrity sha512-EEVig1Q2QJ4ELpJXMZR8Vt5DQx8/mo+dGWSR7vWXqcob2gQLyQGsionYcGKATXvQzMPn6DSN1vTN7yFximdIAg== + dependencies: + cssnano-util-get-match "^4.0.0" + has "^1.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-selector-parser@^3.0.0, postcss-selector-parser@^3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz#b310f5c4c0fdaf76f94902bbaa30db6aa84f5270" + integrity sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA== + dependencies: + dot-prop "^5.2.0" + indexes-of "^1.0.1" + uniq "^1.0.1" + +postcss-selector-parser@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz#249044356697b33b64f1a8f7c80922dddee7195c" + integrity sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ== + dependencies: + cssesc "^2.0.0" + indexes-of "^1.0.1" + uniq "^1.0.1" + +postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4: + version "6.0.11" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.11.tgz#2e41dc39b7ad74046e1615185185cd0b17d0c8dc" + integrity sha512-zbARubNdogI9j7WY4nQJBiNqQf3sLS3wCP4WfOidu+p28LofJqDH1tcXypGrcmMHhDk2t9wGhCsYe/+szLTy1g== + dependencies: + cssesc "^3.0.0" + util-deprecate "^1.0.2" + +postcss-svgo@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-4.0.3.tgz#343a2cdbac9505d416243d496f724f38894c941e" + integrity sha512-NoRbrcMWTtUghzuKSoIm6XV+sJdvZ7GZSc3wdBN0W19FTtp2ko8NqLsgoh/m9CzNhU3KLPvQmjIwtaNFkaFTvw== + dependencies: + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + svgo "^1.0.0" + +postcss-unique-selectors@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz#9446911f3289bfd64c6d680f073c03b1f9ee4bac" + integrity sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg== + dependencies: + alphanum-sort "^1.0.0" + postcss "^7.0.0" + uniqs "^2.0.0" + +postcss-value-parser@^3.0.0, postcss-value-parser@^3.3.0: + version "3.3.1" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" + integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ== + +postcss-value-parser@^4.0.2, postcss-value-parser@^4.1.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@7.0.32: + version "7.0.32" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.32.tgz#4310d6ee347053da3433db2be492883d62cec59d" + integrity sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw== + dependencies: + chalk "^2.4.2" + source-map "^0.6.1" + supports-color "^6.1.0" + +postcss@8.3.6: + version "8.3.6" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.3.6.tgz#2730dd76a97969f37f53b9a6096197be311cc4ea" + integrity sha512-wG1cc/JhRgdqB6WHEuyLTedf3KIRuD0hG6ldkFEZNCjRxiC+3i6kkWUUbiJQayP28iwG35cEmAbe98585BYV0A== + dependencies: + colorette "^1.2.2" + nanoid "^3.1.23" + source-map-js "^0.6.2" + +postcss@^5.2.5: + version "5.2.18" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-5.2.18.tgz#badfa1497d46244f6390f58b319830d9107853c5" + integrity sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg== + dependencies: + chalk "^1.1.3" + js-base64 "^2.1.9" + source-map "^0.5.6" + supports-color "^3.2.3" + +postcss@^6.0.1, postcss@^6.0.20, postcss@^6.0.22, postcss@^6.0.9: + version "6.0.23" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.23.tgz#61c82cc328ac60e677645f979054eb98bc0e3324" + integrity sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag== + dependencies: + chalk "^2.4.1" + source-map "^0.6.1" + supports-color "^5.4.0" + +postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.11, postcss@^7.0.14, postcss@^7.0.18, postcss@^7.0.27, postcss@^7.0.32: + version "7.0.39" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.39.tgz#9624375d965630e2e1f2c02a935c82a59cb48309" + integrity sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA== + dependencies: + picocolors "^0.2.1" + source-map "^0.6.1" + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + integrity sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w== + +prettier-linter-helpers@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" + integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== + dependencies: + fast-diff "^1.1.2" + +prettier@1.16.3: + version "1.16.3" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.16.3.tgz#8c62168453badef702f34b45b6ee899574a6a65d" + integrity sha512-kn/GU6SMRYPxUakNXhpP0EedT/KmaPzr0H5lIsDogrykbaxOpOfAFfk5XA7DZrJyMAv1wlMV3CPcZruGXVVUZw== + +prettier@2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.3.2.tgz#ef280a05ec253712e486233db5c6f23441e7342d" + integrity sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ== + +prettier@^1.13.0: + version "1.19.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb" + integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew== + +pretty-format@^26.0.0, pretty-format@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.6.2.tgz#e35c2705f14cb7fe2fe94fa078345b444120fc93" + integrity sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg== + dependencies: + "@jest/types" "^26.6.2" + ansi-regex "^5.0.0" + ansi-styles "^4.0.0" + react-is "^17.0.1" + +pretty-format@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e" + integrity sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ== + dependencies: + ansi-regex "^5.0.1" + ansi-styles "^5.0.0" + react-is "^17.0.1" + +pretty-hrtime@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1" + integrity sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A== + +progress@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" + integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== + +promise.series@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/promise.series/-/promise.series-0.2.0.tgz#2cc7ebe959fc3a6619c04ab4dbdc9e452d864bbd" + integrity sha512-VWQJyU2bcDTgZw8kpfBpB/ejZASlCrzwz5f2hjb/zlujOEB4oeiAhHygAWq8ubsX2GVkD4kCU5V2dwOTaCY5EQ== + +prompts@^2.0.1: + version "2.4.2" + resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" + integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== + dependencies: + kleur "^3.0.3" + sisteransi "^1.0.5" + +pseudomap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + integrity sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ== + +psl@^1.1.33: + version "1.9.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" + integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== + +punycode@^2.1.0, punycode@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + +purgecss@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/purgecss/-/purgecss-2.3.0.tgz#5327587abf5795e6541517af8b190a6fb5488bb3" + integrity sha512-BE5CROfVGsx2XIhxGuZAT7rTH9lLeQx/6M0P7DTXQH4IUc3BBzs9JUzt4yzGf3JrH9enkeq6YJBe9CTtkm1WmQ== + dependencies: + commander "^5.0.0" + glob "^7.0.0" + postcss "7.0.32" + postcss-selector-parser "^6.0.2" + +q@^1.1.2: + version "1.5.1" + resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" + integrity sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw== + +querystring@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.1.tgz#40d77615bb09d16902a85c3e38aa8b5ed761c2dd" + integrity sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg== + +querystringify@^2.1.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" + integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +react-is@^17.0.1: + version "17.0.2" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" + integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== + +read-pkg-up@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507" + integrity sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg== + dependencies: + find-up "^4.1.0" + read-pkg "^5.2.0" + type-fest "^0.8.1" + +read-pkg@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" + integrity sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA== + dependencies: + load-json-file "^4.0.0" + normalize-package-data "^2.3.2" + path-type "^3.0.0" + +read-pkg@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" + integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg== + dependencies: + "@types/normalize-package-data" "^2.4.0" + normalize-package-data "^2.5.0" + parse-json "^5.0.0" + type-fest "^0.6.0" + +reduce-css-calc@^2.1.6: + version "2.1.8" + resolved "https://registry.yarnpkg.com/reduce-css-calc/-/reduce-css-calc-2.1.8.tgz#7ef8761a28d614980dc0c982f772c93f7a99de03" + integrity sha512-8liAVezDmUcH+tdzoEGrhfbGcP7nOV4NkGE3a74+qqvE7nt9i4sKLGBuZNOnpI4WiGksiNPklZxva80061QiPg== + dependencies: + css-unit-converter "^1.1.1" + postcss-value-parser "^3.3.0" + +regenerator-runtime@^0.13.11: + version "0.13.11" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" + integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== + +regexp-tree@^0.1.22, regexp-tree@~0.1.1: + version "0.1.24" + resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.24.tgz#3d6fa238450a4d66e5bc9c4c14bb720e2196829d" + integrity sha512-s2aEVuLhvnVJW6s/iPgEGK6R+/xngd2jNQ+xy4bXNDKxZKJH6jpPHY6kVeVv1IeLCHgswRj+Kl3ELaDjG6V1iw== + +regexp.prototype.flags@^1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac" + integrity sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + functions-have-names "^1.2.2" + +regexpp@^3.0.0, regexpp@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" + integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + +requires-port@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== + +reserved-words@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/reserved-words/-/reserved-words-0.1.2.tgz#00a0940f98cd501aeaaac316411d9adc52b31ab1" + integrity sha512-0S5SrIUJ9LfpbVl4Yzij6VipUdafHrOTzvmfazSw/jeZrZtQK303OPZW+obtkaw7jQlTQppy0UvZWm9872PbRw== + +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@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" + integrity sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw== + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +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.exports@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-1.1.0.tgz#5ce842b94b05146c0e03076985d1d0e7e48c90c9" + integrity sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ== + +resolve@^1.10.0, resolve@^1.10.1, resolve@^1.14.2, resolve@^1.17.0, resolve@^1.19.0, resolve@^1.20.0, resolve@^1.22.0: + version "1.22.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" + integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== + dependencies: + is-core-module "^2.9.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +rgb-regex@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/rgb-regex/-/rgb-regex-1.0.1.tgz#c0e0d6882df0e23be254a475e8edd41915feaeb1" + integrity sha512-gDK5mkALDFER2YLqH6imYvK6g02gpNGM4ILDZ472EwWfXZnC2ZEpoB2ECXTyOVUKuk/bPJZMzwQPBYICzP+D3w== + +rgba-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3" + integrity sha512-zgn5OjNQXLUTdq8m17KdaicF6w89TZs8ZU8y0AYENIU6wG8GG6LLm0yLSiPY8DmaYmHdgRW8rnApjoT0fQRfMg== + +rimraf@3.0.2, rimraf@^3.0.0, rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +rollup-plugin-analyzer@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/rollup-plugin-analyzer/-/rollup-plugin-analyzer-4.0.0.tgz#96b757ed64a098b59d72f085319e68cdd86d5798" + integrity sha512-LL9GEt3bkXp6Wa19SNR5MWcvHNMvuTFYg+eYBZN2OIFhSWN+pEJUQXEKu5BsOeABob3x9PDaLKW7w5iOJnsESQ== + +rollup-plugin-postcss@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/rollup-plugin-postcss/-/rollup-plugin-postcss-4.0.0.tgz#2131fb6db0d5dce01a37235e4f6ad4523c681cea" + integrity sha512-OQzT+YspV01/6dxfyEw8lBO2px3hyL8Xn+k2QGctL7V/Yx2Z1QaMKdYVslP1mqv7RsKt6DROIlnbpmgJ3yxf6g== + dependencies: + chalk "^4.1.0" + concat-with-sourcemaps "^1.1.0" + cssnano "^4.1.10" + import-cwd "^3.0.0" + p-queue "^6.6.2" + pify "^5.0.0" + postcss-load-config "^3.0.0" + postcss-modules "^4.0.0" + promise.series "^0.2.0" + resolve "^1.19.0" + rollup-pluginutils "^2.8.2" + safe-identifier "^0.4.2" + style-inject "^0.3.0" + +rollup-plugin-svg@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/rollup-plugin-svg/-/rollup-plugin-svg-2.0.0.tgz#ce11b55e915d5b2190328c4e6632bd6b4fe12ee9" + integrity sha512-DmE7dSQHo1SC5L2uH2qul3Mjyd5oV6U1aVVkyvTLX/mUsRink7f1b1zaIm+32GEBA6EHu8H/JJi3DdWqM53ySQ== + dependencies: + rollup-pluginutils "^1.3.1" + +rollup-plugin-vue@4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/rollup-plugin-vue/-/rollup-plugin-vue-4.2.0.tgz#83cf392c5e929c34d5f4992e75c2ed32aa600c09" + integrity sha512-n8NDvhYtA9HC3hRyLNAV+0Ei4FHlaOB8LoiXxVwYclgHxOR4aku57zIw8EPf+ETSf45w49UP4VUXgpX6XNwdOA== + dependencies: + "@babel/runtime" "^7.0.0-beta.46" + "@vue/component-compiler" "^3.3.2" + "@vue/component-compiler-utils" "^1.2.1" + debug "^2.6.0" + hash-sum "^1.0.2" + postcss "^6.0.22" + querystring "^0.2.0" + rollup-pluginutils "^2.0.1" + +rollup-pluginutils@^1.3.1: + version "1.5.2" + resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-1.5.2.tgz#1e156e778f94b7255bfa1b3d0178be8f5c552408" + integrity sha512-SjdWWWO/CUoMpDy8RUbZ/pSpG68YHmhk5ROKNIoi2En9bJ8bTt3IhYi254RWiTclQmL7Awmrq+rZFOhZkJAHmQ== + dependencies: + estree-walker "^0.2.1" + minimatch "^3.0.2" + +rollup-pluginutils@^2.0.1, rollup-pluginutils@^2.8.2: + version "2.8.2" + resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz#72f2af0748b592364dbd3389e600e5a9444a351e" + integrity sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ== + dependencies: + estree-walker "^0.6.1" + +rollup@2.56.1: + version "2.56.1" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.56.1.tgz#f29dbc04a5d532dfa904f76b62395f359506211e" + integrity sha512-KkrsNjeiTfGJMUFBi/PNfj3fnt70akqdoNXOjlzwo98uA1qrlkmgt6SGaK5OwhyDYCVnJb6jb2Xa2wbI47P4Nw== + optionalDependencies: + fsevents "~2.3.2" + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +safe-identifier@^0.4.2: + version "0.4.2" + resolved "https://registry.yarnpkg.com/safe-identifier/-/safe-identifier-0.4.2.tgz#cf6bfca31c2897c588092d1750d30ef501d59fcb" + integrity sha512-6pNbSMW6OhAi9j+N8V+U715yBQsaWJ7eyEUaOrawX+isg5ZxhUlV1NipNtgaKHmFGiABwt+ZF04Ii+3Xjkg+8w== + +safe-regex-test@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz#793b874d524eb3640d1873aad03596db2d4f2295" + integrity sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.3" + is-regex "^1.1.4" + +safe-regex@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-2.1.1.tgz#f7128f00d056e2fe5c11e81a1324dd974aadced2" + integrity sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A== + dependencies: + regexp-tree "~0.1.1" + +"safer-buffer@>= 2.1.2 < 3": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +sax@~1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" + integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== + +saxes@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/saxes/-/saxes-5.0.1.tgz#eebab953fa3b7608dbe94e5dadb15c888fa6696d" + integrity sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw== + dependencies: + xmlchars "^2.2.0" + +"semver@2 || 3 || 4 || 5", semver@^5.5.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + +semver@^6.0.0, semver@^6.1.0, semver@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + +semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5: + version "7.3.8" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798" + integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A== + dependencies: + lru-cache "^6.0.0" + +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + integrity sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg== + dependencies: + shebang-regex "^1.0.0" + +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@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + integrity sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ== + +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== + +shell-quote@^1.6.1: + version "1.7.4" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.4.tgz#33fe15dee71ab2a81fcbd3a52106c5cfb9fb75d8" + integrity sha512-8o/QEhSSRb1a5i7TFR0iM4G16Z0vYB2OQVs4G3aAFXjn3T6yEx8AZxy1PgDF7I00LZHYA3WxaSYIf5e5sAX8Rw== + +side-channel@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.0" + +signal-exit@^3.0.2, 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== + +simple-swizzle@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" + integrity sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg== + dependencies: + is-arrayish "^0.3.1" + +sisteransi@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" + integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +slice-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" + integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + +source-map-js@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-0.6.2.tgz#0bb5de631b41cfbda6cfba8bd05a80efdfd2385e" + integrity sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug== + +source-map-support@^0.5.6: + 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@0.6.*, source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +source-map@^0.5.0, source-map@^0.5.6: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== + +source-map@^0.7.3: + version "0.7.4" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.4.tgz#a9bbe705c9d8846f4e08ff6765acf0f1b0898656" + integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA== + +sourcemap-codec@^1.4.8: + version "1.4.8" + resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" + integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== + +spdx-correct@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" + integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w== + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" + integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== + +spdx-expression-parse@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" + integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.12" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz#69077835abe2710b65f03969898b6637b505a779" + integrity sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA== + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== + +stable@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" + integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== + +stack-utils@^2.0.3: + version "2.0.6" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f" + integrity sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ== + dependencies: + escape-string-regexp "^2.0.0" + +string-hash@^1.1.0, string-hash@^1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/string-hash/-/string-hash-1.1.3.tgz#e8aafc0ac1855b4666929ed7dd1275df5d6c811b" + integrity sha512-kJUvRUFK49aub+a7T1nNE66EJbZBMnBgoC1UbCZ5n6bsZKBRga4KgBRTMn/pFkeCZSYtNeSyMxPDM0AXWELk2A== + +string-length@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" + integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ== + dependencies: + char-regex "^1.0.2" + strip-ansi "^6.0.0" + +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string.prototype.padend@^3.0.0: + version "3.1.4" + resolved "https://registry.yarnpkg.com/string.prototype.padend/-/string.prototype.padend-3.1.4.tgz#2c43bb3a89eb54b6750de5942c123d6c98dd65b6" + integrity sha512-67otBXoksdjsnXXRUq+KMVTdlVRZ2af422Y0aTyTjVaoQkGr3mxl2Bc5emi7dOQ3OGVVQQskmLEWwFXwommpNw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + +string.prototype.trimend@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz#c4a27fa026d979d79c04f17397f250a462944533" + integrity sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + +string.prototype.trimstart@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz#e90ab66aa8e4007d92ef591bbf3cd422c56bdcf4" + integrity sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + +strip-ansi@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg== + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== + +strip-bom@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" + integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== + +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@^3.1.0, strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +style-inject@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/style-inject/-/style-inject-0.3.0.tgz#d21c477affec91811cc82355832a700d22bf8dd3" + integrity sha512-IezA2qp+vcdlhJaVm5SOdPPTUu0FCEqfNSli2vRuSIBbu5Nq5UvygTk/VzeCqfLz2Atj3dVII5QBKGZRZ0edzw== + +stylehacks@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-4.0.3.tgz#6718fcaf4d1e07d8a1318690881e8d96726a71d5" + integrity sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g== + dependencies: + browserslist "^4.0.0" + postcss "^7.0.0" + postcss-selector-parser "^3.0.0" + +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + integrity sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g== + +supports-color@^3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" + integrity sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A== + dependencies: + has-flag "^1.0.0" + +supports-color@^5.3.0, supports-color@^5.4.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" + integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.0.0, supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + 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-hyperlinks@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz#3943544347c1ff90b15effb03fc14ae45ec10624" + integrity sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA== + dependencies: + has-flag "^4.0.0" + supports-color "^7.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== + +svg-country-flags@1.2.10: + version "1.2.10" + resolved "https://registry.yarnpkg.com/svg-country-flags/-/svg-country-flags-1.2.10.tgz#b1b94e9f08f065d7b3d0ff9ab359898edd4dd3b0" + integrity sha512-xrqwo0TYf/h2cfPvGpjdSuSguUbri4vNNizBnwzoZnX0xGo3O5nGJMlbYEp7NOYcnPGBm6LE2axqDWSB847bLw== + +svgo@^1.0.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.3.2.tgz#b6dc511c063346c9e415b81e43401145b96d4167" + integrity sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw== + dependencies: + chalk "^2.4.1" + coa "^2.0.2" + css-select "^2.0.0" + css-select-base-adapter "^0.1.1" + css-tree "1.0.0-alpha.37" + csso "^4.0.2" + js-yaml "^3.13.1" + mkdirp "~0.5.1" + object.values "^1.1.0" + sax "~1.2.4" + stable "^0.1.8" + unquote "~1.1.1" + util.promisify "~1.0.0" + +symbol-tree@^3.2.4: + version "3.2.4" + resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" + integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== + +table@^6.0.9: + version "6.8.1" + resolved "https://registry.yarnpkg.com/table/-/table-6.8.1.tgz#ea2b71359fe03b017a5fbc296204471158080bdf" + integrity sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA== + dependencies: + ajv "^8.0.1" + lodash.truncate "^4.4.2" + slice-ansi "^4.0.0" + string-width "^4.2.3" + strip-ansi "^6.0.1" + +tailwindcss@1.9.6: + version "1.9.6" + resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-1.9.6.tgz#0c5089911d24e1e98e592a31bfdb3d8f34ecf1a0" + integrity sha512-nY8WYM/RLPqGsPEGEV2z63riyQPcHYZUJpAwdyBzVpxQHOHqHE+F/fvbCeXhdF1+TA5l72vSkZrtYCB9hRcwkQ== + dependencies: + "@fullhuman/postcss-purgecss" "^2.1.2" + autoprefixer "^9.4.5" + browserslist "^4.12.0" + bytes "^3.0.0" + chalk "^3.0.0 || ^4.0.0" + color "^3.1.2" + detective "^5.2.0" + fs-extra "^8.0.0" + html-tags "^3.1.0" + lodash "^4.17.20" + node-emoji "^1.8.1" + normalize.css "^8.0.1" + object-hash "^2.0.3" + postcss "^7.0.11" + postcss-functions "^3.0.0" + postcss-js "^2.0.0" + postcss-nested "^4.1.1" + postcss-selector-parser "^6.0.0" + postcss-value-parser "^4.1.0" + pretty-hrtime "^1.0.3" + reduce-css-calc "^2.1.6" + resolve "^1.14.2" + +terminal-link@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/terminal-link/-/terminal-link-2.1.1.tgz#14a64a27ab3c0df933ea546fba55f2d078edc994" + integrity sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ== + dependencies: + ansi-escapes "^4.2.1" + supports-hyperlinks "^2.0.0" + +test-exclude@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" + integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== + dependencies: + "@istanbuljs/schema" "^0.1.2" + glob "^7.1.4" + minimatch "^3.0.4" + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== + +throat@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/throat/-/throat-6.0.1.tgz#d514fedad95740c12c2d7fc70ea863eb51ade375" + integrity sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w== + +timsort@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" + integrity sha512-qsdtZH+vMoCARQtyod4imc2nIJwg9Cc7lPRrw9CzF8ZKR0khdr8+2nX80PBhET3tcyTtJDxAffGh2rXH4tyU8A== + +tmpl@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" + integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== + +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +toastify-js@1.11.1: + version "1.11.1" + resolved "https://registry.yarnpkg.com/toastify-js/-/toastify-js-1.11.1.tgz#023a4ce64ecdead1d6d170072b62bd345088c427" + integrity sha512-O1UR06KEhFY9Vu2iKltgOE62+Vq/5iU7AOktouFkEegEisrqtNhEri9RpSd6u6wyPsd4Ae9RT1io3uwkMAlLVQ== + +tough-cookie@^4.0.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.2.tgz#e53e84b85f24e0b65dd526f46628db6c85f6b874" + integrity sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ== + dependencies: + psl "^1.1.33" + punycode "^2.1.1" + universalify "^0.2.0" + url-parse "^1.5.3" + +tr46@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-2.1.0.tgz#fa87aa81ca5d5941da8cbf1f9b749dc969a4e240" + integrity sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw== + dependencies: + punycode "^2.1.1" + +tsconfig-paths@^3.14.1: + version "3.14.1" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz#ba0734599e8ea36c862798e920bcf163277b137a" + integrity sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ== + dependencies: + "@types/json5" "^0.0.29" + json5 "^1.0.1" + minimist "^1.2.6" + strip-bom "^3.0.0" + +tslib@^1.8.1: + version "1.14.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + +tslib@^2.3.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.1.tgz#0d0bfbaac2880b91e22df0768e55be9753a5b17e" + integrity sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA== + +tsutils@^3.21.0: + version "3.21.0" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" + integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== + dependencies: + tslib "^1.8.1" + +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + +type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + integrity sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg== + dependencies: + prelude-ls "~1.1.2" + +type-detect@4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + +type-fest@^0.20.2: + version "0.20.2" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== + +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + +type-fest@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" + integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg== + +type-fest@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" + integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== + +typedarray-to-buffer@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== + dependencies: + is-typedarray "^1.0.0" + +typescript@4.3.5: + version "4.3.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.3.5.tgz#4d1c37cc16e893973c45a06886b7113234f119f4" + integrity sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA== + +unbox-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" + integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== + dependencies: + call-bind "^1.0.2" + has-bigints "^1.0.2" + has-symbols "^1.0.3" + which-boxed-primitive "^1.0.2" + +uniq@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" + integrity sha512-Gw+zz50YNKPDKXs+9d+aKAjVwpjNwqzvNpLigIruT4HA9lMZNdMqs9x07kKHB/L9WRzqp4+DlTU5s4wG2esdoA== + +uniqs@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/uniqs/-/uniqs-2.0.0.tgz#ffede4b36b25290696e6e165d4a59edb998e6b02" + integrity sha512-mZdDpf3vBV5Efh29kMw5tXoup/buMgxLzOt/XKFKcVmi+15ManNQWr6HfZ2aiZTYlYixbdNJ0KFmIZIv52tHSQ== + +universalify@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== + +universalify@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0" + integrity sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg== + +unquote@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/unquote/-/unquote-1.1.1.tgz#8fded7324ec6e88a0ff8b905e7c098cdc086d544" + integrity sha512-vRCqFv6UhXpWxZPyGDh/F3ZpNv8/qo7w6iufLpQg9aKnQ71qM4B5KiI7Mia9COcjEhrO9LueHpMYjYzsWH3OIg== + +update-browserslist-db@^1.0.9: + version "1.0.10" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz#0f54b876545726f17d00cd9a2561e6dade943ff3" + integrity sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ== + dependencies: + escalade "^3.1.1" + picocolors "^1.0.0" + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +url-parse@^1.5.3: + version "1.5.10" + resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" + integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== + dependencies: + querystringify "^2.1.1" + requires-port "^1.0.0" + +util-deprecate@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +util.promisify@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.1.tgz#6baf7774b80eeb0f7520d8b81d07982a59abbaee" + integrity sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.2" + has-symbols "^1.0.1" + object.getownpropertydescriptors "^2.1.0" + +v8-compile-cache@^2.0.3: + version "2.3.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" + integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== + +v8-to-istanbul@^8.1.0: + version "8.1.1" + resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz#77b752fd3975e31bbcef938f85e9bd1c7a8d60ed" + integrity sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.1" + convert-source-map "^1.6.0" + source-map "^0.7.3" + +validate-npm-package-license@^3.0.1: + version "3.0.4" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" + integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + +vendors@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.4.tgz#e2b800a53e7a29b93506c3cf41100d16c4c4ad8e" + integrity sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w== + +vue-eslint-parser@^7.10.0: + version "7.11.0" + resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-7.11.0.tgz#214b5dea961007fcffb2ee65b8912307628d0daf" + integrity sha512-qh3VhDLeh773wjgNTl7ss0VejY9bMMa0GoDG2fQVyDzRFdiU3L7fw74tWZDHNQXdZqxO3EveQroa9ct39D2nqg== + dependencies: + debug "^4.1.1" + eslint-scope "^5.1.1" + eslint-visitor-keys "^1.1.0" + espree "^6.2.1" + esquery "^1.4.0" + lodash "^4.17.21" + semver "^6.3.0" + +vue-i18n@8.25.0: + version "8.25.0" + resolved "https://registry.yarnpkg.com/vue-i18n/-/vue-i18n-8.25.0.tgz#1037d9295fa2845a230b771de473481edb2cfc4c" + integrity sha512-ynhcL+PmTxuuSE1T10htiSXzjBozxYIE3ffbM1RfgAkVbr/v1SP+9Mi/7/uv8ZVV1yGuKjFAYp9BXq+X7op6MQ== + +vue-router@3.5.2: + version "3.5.2" + resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-3.5.2.tgz#5f55e3f251970e36c3e8d88a7cd2d67a350ade5c" + integrity sha512-807gn82hTnjCYGrnF3eNmIw/dk7/GE4B5h69BlyCK9KHASwSloD1Sjcn06zg9fVG4fYH2DrsNBZkpLtb25WtaQ== + +vue-template-compiler@2.6.14: + version "2.6.14" + resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.6.14.tgz#a2f0e7d985670d42c9c9ee0d044fed7690f4f763" + integrity sha512-ODQS1SyMbjKoO1JBJZojSw6FE4qnh9rIpUZn2EUT86FKizx9uH5z6uXiIrm4/Nb/gwxTi/o17ZDEGWAXHvtC7g== + dependencies: + de-indent "^1.0.2" + he "^1.1.0" + +vue-template-es2015-compiler@^1.6.0, vue-template-es2015-compiler@^1.9.0: + version "1.9.1" + resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz#1ee3bc9a16ecbf5118be334bb15f9c46f82f5825" + integrity sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw== + +vue@2.6.14: + version "2.6.14" + resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.14.tgz#e51aa5250250d569a3fbad3a8a5a687d6036e235" + integrity sha512-x2284lgYvjOMj3Za7kqzRcUSxBboHqtgRE2zlos1qWaOye5yUmHn42LB1250NJBLRwEcdrB0JRwyPTEPhfQjiQ== + +vuex@3.6.2: + version "3.6.2" + resolved "https://registry.yarnpkg.com/vuex/-/vuex-3.6.2.tgz#236bc086a870c3ae79946f107f16de59d5895e71" + integrity sha512-ETW44IqCgBpVomy520DT5jf8n0zoCac+sxWnn+hMe/CzaSejb/eVw2YToiXYX+Ex/AuHHia28vWTq4goAexFbw== + +w3c-hr-time@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd" + integrity sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ== + dependencies: + browser-process-hrtime "^1.0.0" + +w3c-xmlserializer@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz#3e7104a05b75146cc60f564380b7f683acf1020a" + integrity sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA== + dependencies: + xml-name-validator "^3.0.0" + +walker@^1.0.7: + version "1.0.8" + resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" + integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== + dependencies: + makeerror "1.0.12" + +webidl-conversions@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff" + integrity sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA== + +webidl-conversions@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514" + integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w== + +whatwg-encoding@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0" + integrity sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw== + dependencies: + iconv-lite "0.4.24" + +whatwg-mimetype@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf" + integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g== + +whatwg-url@^8.0.0, whatwg-url@^8.5.0: + version "8.7.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.7.0.tgz#656a78e510ff8f3937bc0bcbe9f5c0ac35941b77" + integrity sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg== + dependencies: + lodash "^4.7.0" + tr46 "^2.1.0" + webidl-conversions "^6.1.0" + +which-boxed-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" + integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== + dependencies: + is-bigint "^1.0.1" + is-boolean-object "^1.1.0" + is-number-object "^1.0.4" + is-string "^1.0.5" + is-symbol "^1.0.3" + +which@^1.2.9: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + +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" + +word-wrap@^1.2.3, word-wrap@~1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" + integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +write-file-atomic@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" + integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== + dependencies: + imurmurhash "^0.1.4" + is-typedarray "^1.0.0" + signal-exit "^3.0.2" + typedarray-to-buffer "^3.1.5" + +ws@^7.4.6: + version "7.5.9" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" + integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== + +xml-name-validator@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" + integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw== + +xmlchars@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" + integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== + +xtend@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yallist@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" + integrity sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A== + +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== + +yaml@^1.10.2: + version "1.10.2" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" + integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== + +yargs-parser@^20.2.2: + version "20.2.9" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== + +yargs@^16.2.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2"