diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
index 5a28406a..a4621025 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -11,7 +11,7 @@ assignees: ''
After 6 years of more or less intensive programming on Calibre-Web, I need a break.
The last few months, maintaining Calibre-Web has felt more like work than a hobby. I felt pressured and teased by people to solve "their" problems and merge PRs for "their" Calibre-Web.
-I have turned off all notifications from Github/Discord and will now concentrate undisturbed on the development of “my” Calibre-Web over the next few weeks/months.
+I have turned off all notifications from GitHub/Discord and will now concentrate undisturbed on the development of “my” Calibre-Web over the next few weeks/months.
I will look into the issues and maybe also the PRs from time to time, but don't expect a quick response from me.
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
index dec77d51..3e5c7b9f 100644
--- a/.github/ISSUE_TEMPLATE/feature_request.md
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -11,7 +11,7 @@ assignees: ''
After 6 years of more or less intensive programming on Calibre-Web, I need a break.
The last few months, maintaining Calibre-Web has felt more like work than a hobby. I felt pressured and teased by people to solve "their" problems and merge PRs for "their" Calibre-Web.
-I have turned off all notifications from Github/Discord and will now concentrate undisturbed on the development of “my” Calibre-Web over the next few weeks/months.
+I have turned off all notifications from GitHub/Discord and will now concentrate undisturbed on the development of “my” Calibre-Web over the next few weeks/months.
I will look into the issues and maybe also the PRs from time to time, but don't expect a quick response from me.
Please have a look at our [Contributing Guidelines](https://github.com/janeczku/calibre-web/blob/master/CONTRIBUTING.md)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 2ab32cf9..5f538dfa 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -20,7 +20,7 @@ Some of the user languages in Calibre-Web having missing translations. We are ha
### **Documentation**
-The Calibre-Web documentation is hosted in the Github [Wiki](https://github.com/janeczku/calibre-web/wiki). The Wiki is open to everybody, if you find a problem, feel free to correct it. If information is missing, you are welcome to add it. The content will be reviewed time by time. Please try to be consistent with the form with the other Wiki pages (e.g. the project name is Calibre-Web with 2 capital letters and a dash in between).
+The Calibre-Web documentation is hosted in the GitHub [Wiki](https://github.com/janeczku/calibre-web/wiki). The Wiki is open to everybody, if you find a problem, feel free to correct it. If information is missing, you are welcome to add it. The content will be reviewed time by time. Please try to be consistent with the form with the other Wiki pages (e.g. the project name is Calibre-Web with 2 capital letters and a dash in between).
### **Reporting a bug**
@@ -28,12 +28,12 @@ Do not open up a GitHub issue if the bug is a **security vulnerability** in Cali
Ensure the **bug was not already reported** by searching on GitHub under [Issues](https://github.com/janeczku/calibre-web/issues). Please also check if a solution for your problem can be found in the [wiki](https://github.com/janeczku/calibre-web/wiki).
-If you're unable to find an **open issue** addressing the problem, open a [new one](https://github.com/janeczku/calibre-web/issues/new/choose). Be sure to include a **title** and **clear description**, as much relevant information as possible, the **issue form** helps you providing the right information. Deleting the form and just pasting the stack trace doesn't speed up fixing the problem. If your issue could be resolved, consider closing the issue.
+If you're unable to find an **open issue** addressing the problem, open a [new one](https://github.com/janeczku/calibre-web/issues/new/choose). Be sure to include a **title** and **clear description**, as much relevant information as possible, the **issue form** helps you provide the right information. Deleting the form and just pasting the stack trace doesn't speed up fixing the problem. If your issue could be resolved, consider closing the issue.
### **Feature Request**
If there is a feature missing in Calibre-Web and you can't find a feature request in the [Issues](https://github.com/janeczku/calibre-web/issues) section, you could create a [feature request](https://github.com/janeczku/calibre-web/issues/new?assignees=&labels=&template=feature_request.md&title=).
-We will not extend Calibre-Web with any more login abilities or add further files storages, or file syncing ability. Furthermore Calibre-Web is made for home usage for company in-house usage, so requests regarding any sorts of social interaction capability, payment routines, search engine or web site analytics integration will not be implemented.
+We will not extend Calibre-Web with any more login abilities or add further files storages, or file syncing ability. Calibre-Web is made for home usage for company in-house usage, so requests regarding any sorts of social interaction capability, payment routines, search engine or website analytics integration will not be implemented.
### **Contributing code to Calibre-Web**
@@ -42,5 +42,5 @@ Open a new GitHub pull request with the patch. Ensure the PR description clearly
In case your code enhances features of Calibre-Web: Create your pull request for the development branch if your enhancement consists of more than some lines of code in a local section of Calibre-Webs code. This makes it easier to test it and check all implication before it's made public.
Please check if your code runs with python 3, python 2 is no longer supported. If possible and the feature is related to operating system functions, try to check it on Windows and Linux.
-Calibre-Web is automatically tested on Linux in combination with python 3.8. The code for testing is in a [separate repo](https://github.com/OzzieIsaacs/calibre-web-test) on Github. It uses unit tests and performs real system tests with selenium; it would be great if you could consider also writing some tests.
+Calibre-Web is automatically tested on Linux in combination with python 3.8. The code for testing is in a [separate repo](https://github.com/OzzieIsaacs/calibre-web-test) on GitHub. It uses unit tests and performs real system tests with selenium; it would be great if you could consider also writing some tests.
A static code analysis is done by Codacy, but it's partly broken and doesn't run automatically. You could check your code with ESLint before contributing, a configuration file can be found in the projects root folder.
diff --git a/MANIFEST.in b/MANIFEST.in
index b667159c..f07c4d83 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1 +1,3 @@
graft src/calibreweb
+global-exclude __pycache__
+global-exclude *.pyc
diff --git a/README.md b/README.md
index a400b3b2..2d9c7d18 100755
--- a/README.md
+++ b/README.md
@@ -1,10 +1,3 @@
-# Short Notice from the maintainer
-
-After 6 years of more or less intensive programming on Calibre-Web, I need a break.
-The last few months, maintaining Calibre-Web has felt more like work than a hobby. I felt pressured and teased by people to solve "their" problems and merge PRs for "their" Calibre-Web.
-I have turned off all notifications from Github/Discord and will now concentrate undisturbed on the development of “my” Calibre-Web over the next few weeks/months.
-I will look into the issues and maybe also the PRs from time to time, but don't expect a quick response from me.
-
# Calibre-Web
Calibre-Web is a web app that offers a clean and intuitive interface for browsing, reading, and downloading eBooks using a valid [Calibre](https://calibre-ebook.com) database.
@@ -26,13 +19,13 @@ Calibre-Web is a web app that offers a clean and intuitive interface for browsin
- [Quick start](#quick-start)
- [Requirements](#requirements)
4. [Docker Images](#docker-images)
-5. [Contributor Recognition](#contributor-recognition)
-6. [Contact](#contact)
-7. [Contributing to Calibre-Web](#contributing-to-calibre-web)
+5. [Troubleshooting](#troubleshooting)
+6. [Contributor Recognition](#contributor-recognition)
+7. [Contact](#contact)
+8. [Contributing to Calibre-Web](#contributing-to-calibre-web)
-
*This software is a fork of [library](https://github.com/mutschler/calibreserver) and licensed under the GPL v3 License.*

@@ -64,52 +57,102 @@ Calibre-Web is a web app that offers a clean and intuitive interface for browsin
## Installation
-#### Installation via pip (recommended)
-1. Create a virtual environment for Calibre-Web to avoid conflicts with existing Python dependencies
-2. Install Calibre-Web via pip: `pip install calibreweb` (or `pip3` depending on your OS/distro)
-3. Install optional features via pip as needed, see [this page](https://github.com/janeczku/calibre-web/wiki/Dependencies-in-Calibre-Web-Linux-and-Windows) for details
-4. Start Calibre-Web by typing `cps`
+### Installation via pip (recommended)
-*Note: Raspberry Pi OS users may encounter issues during installation. If so, please update pip (`./venv/bin/python3 -m pip install --upgrade pip`) and/or install cargo (`sudo apt install cargo`) before retrying the installation.*
+1. **Create a virtual environment**: It’s essential to isolate your Calibre-Web installation to avoid dependency conflicts. You can create a virtual environment by running:
+ ```
+ python3 -m venv calibre-web-env
+ ```
+2. **Activate the virtual environment**:
+ ```
+ source calibre-web-env/bin/activate
+ ```
+3. **Install Calibre-Web**: Use pip to install the application:
+ ```
+ pip install calibreweb
+ ```
+4. **Install optional features**: For additional functionality, you may need to install optional features. Refer to [this page](https://github.com/janeczku/calibre-web/wiki/Dependencies-in-Calibre-Web-Linux-and-Windows) for details on what can be installed.
+5. **Start Calibre-Web**: After installation, you can start the application with:
+ ```
+ cps
+ ```
-Refer to the Wiki for additional installation examples: [manual installation](https://github.com/janeczku/calibre-web/wiki/Manual-installation), [Linux Mint](https://github.com/janeczku/calibre-web/wiki/How-To:-Install-Calibre-Web-in-Linux-Mint-19-or-20), [Cloud Provider](https://github.com/janeczku/calibre-web/wiki/How-To:-Install-Calibre-Web-on-a-Cloud-Provider).
+*Note: Users of Raspberry Pi OS may encounter installation issues. If you do, try upgrading pip and/or installing cargo as follows:*
+ ```
+ ./venv/bin/python3 -m pip install --upgrade pip
+ sudo apt install cargo
+ ```
+
+### Important Links
+- For additional installation examples, check the following:
+ - [Manual installation](https://github.com/janeczku/calibre-web/wiki/Manual-installation)
+ - [Linux Mint installation](https://github.com/janeczku/calibre-web/wiki/How-To:-Install-Calibre-Web-in-Linux-Mint-19-or-20)
+ - [Cloud Provider setup](https://github.com/janeczku/calibre-web/wiki/How-To:-Install-Calibre-Web-on-a-Cloud-Provider)
## Quick Start
-1. Open your browser and navigate to `http://localhost:8083` or `http://localhost:8083/opds` for the OPDS catalog
-2. Log in with the default admin credentials
-3. If you don't have a Calibre database, you can use [this database](https://github.com/janeczku/calibre-web/raw/master/library/metadata.db) (move it out of the Calibre-Web folder to prevent overwriting during updates)
-4. Set `Location of Calibre database` to the path of the folder containing your Calibre library (metadata.db) and click "Save"
-5. Optionally, use Google Drive to host your Calibre library by following the [Google Drive integration guide](https://github.com/janeczku/calibre-web/wiki/G-Drive-Setup#using-google-drive-integration)
-6. Configure your Calibre-Web instance via the admin page, referring to the [Basic Configuration](https://github.com/janeczku/calibre-web/wiki/Configuration#basic-configuration) and [UI Configuration](https://github.com/janeczku/calibre-web/wiki/Configuration#ui-configuration) guides
-
-#### Default Admin Login:
-- **Username:** admin
-- **Password:** admin123
+1. **Access Calibre-Web**: Open your browser and navigate to:
+ ```
+ http://localhost:8083
+ ```
+ or for the OPDS catalog:
+ ```
+ http://localhost:8083/opds
+ ```
+2. **Log in**: Use the default admin credentials:
+ - **Username:** admin
+ - **Password:** admin123
+3. **Database Setup**: If you do not have a Calibre database, download a sample from:
+ ```
+ https://github.com/janeczku/calibre-web/raw/master/library/metadata.db
+ ```
+ Move it out of the Calibre-Web folder to avoid overwriting during updates.
+4. **Configure Calibre Database**: In the admin interface, set the `Location of Calibre database` to the path of the folder containing your Calibre library (where `metadata.db` is located) and click "Save".
+5. **Google Drive Integration**: For hosting your Calibre library on Google Drive, refer to the [Google Drive integration guide](https://github.com/janeczku/calibre-web/wiki/G-Drive-Setup#using-google-drive-integration).
+6. **Admin Configuration**: Configure your instance via the admin page, referring to the [Basic Configuration](https://github.com/janeczku/calibre-web/wiki/Configuration#basic-configuration) and [UI Configuration](https://github.com/janeczku/calibre-web/wiki/Configuration#ui-configuration) guides.
## Requirements
-- Python 3.7+
-- [Imagemagick](https://imagemagick.org/script/download.php) for cover extraction from EPUBs (Windows users may need to install [Ghostscript](https://ghostscript.com/releases/gsdnld.html) for PDF cover extraction)
-- Windows users need to install [libmagic for 32bit python](https://gnuwin32.sourceforge.net/downlinks/file.php) or [libmagic for 64bit python](https://github.com/nscaife/file-windows/releases/tag/20170108), depending on the python version; The files need to be installed in path (e.g. script folder of your Calibre-Web venv, or in the root folder of Calibre-Web
-- Optional: [Calibre desktop program](https://calibre-ebook.com/download) for on-the-fly conversion and metadata editing (set "calibre's converter tool" path on the setup page)
-- Optional: [Kepubify tool](https://github.com/pgaskin/kepubify/releases/latest) for Kobo device support (place the binary in `/opt/kepubify` on Linux or `C:\Program Files\kepubify` on Windows)
+- **Python Version**: Ensure you have Python 3.7 or newer.
+- **Imagemagick**: Required for cover extraction from EPUBs. Windows users may also need to install [Ghostscript](https://ghostscript.com/releases/gsdnld.html) for PDF cover extraction.
+- **Optional Tools**:
+ - **Calibre desktop program**: Recommended for on-the-fly conversion and metadata editing. Set the path to Calibre’s converter tool on the setup page.
+ - **Kepubify tool**: Needed for Kobo device support. Download the tool and place the binary in `/opt/kepubify` on Linux or `C:\Program Files\kepubify` on Windows.
## Docker Images
-Pre-built Docker images are available in the following Docker Hub repositories (maintained by the LinuxServer team):
+Pre-built Docker images are available:
-#### **LinuxServer - x64, aarch64**
-- [Docker Hub](https://hub.docker.com/r/linuxserver/calibre-web)
-- [GitHub](https://github.com/linuxserver/docker-calibre-web)
-- [GitHub - Optional Calibre layer](https://github.com/linuxserver/docker-mods/tree/universal-calibre)
+### **LinuxServer - x64, aarch64**
+- **Docker Hub**: [linuxserver/calibre-web](https://hub.docker.com/r/linuxserver/calibre-web)
+- **GitHub**: [linuxserver/docker-calibre-web](https://github.com/linuxserver/docker-calibre-web)
+- **Optional Calibre layer**: [linuxserver/docker-mods](https://github.com/linuxserver/docker-mods/tree/universal-calibre)
- Include the environment variable `DOCKER_MODS=linuxserver/mods:universal-calibre` in your Docker run/compose file to add the Calibre `ebook-convert` binary (x64 only). Omit this variable for a lightweight image.
+To include the Calibre `ebook-convert` binary (x64 only), add the environment variable:
+```
+DOCKER_MODS=linuxserver/mods:universal-calibre
+```
+in your Docker run/compose file. Omit this variable for a lightweight image.
- Both the Calibre-Web and Calibre-Mod images are automatically rebuilt on new releases and updates.
+- **Paths Configuration**:
+ - Set **Path to Calibre Binaries** to `/usr/bin`.
+ - Set **Path to Unrar** to `/usr/bin/unrar`.
- - Set "Path to Calibre Binaries" to `/usr/bin`
- - Set "Path to Unrar" to `/usr/bin/unrar`
+## Troubleshooting
+
+- **Common Issues**:
+ - If you experience issues starting the application, check the log files located in the `logs` directory for error messages.
+ - If eBooks fail to load, verify that the `Location of Calibre database` is correctly set and that the database file is accessible.
+
+- **Configuration Errors**: Ensure that your Calibre database is compatible and properly formatted. Refer to the Calibre documentation for guidance on maintaining the database.
+
+- **Performance Problems**:
+ - If the application is slow, consider increasing the allocated resources (CPU/RAM) to your server or optimizing the Calibre database by removing duplicates and unnecessary entries.
+ - Regularly clear the cache in your web browser to improve loading times.
+
+- **User Management Issues**: If users are unable to log in or register, check the user permission settings in the admin interface. Ensure that registration is enabled and that users are being assigned appropriate roles.
+
+- **Support Resources**: For additional help, consider visiting the [FAQ section](https://github.com/janeczku/calibre-web/wiki/FAQ) of the wiki or posting your questions in the [Discord community](https://discord.gg/h2VsJ2NEfB).
## Contributor Recognition
@@ -123,4 +166,21 @@ For more information, How To's, and FAQs, please visit the [Wiki](https://github
## Contributing to Calibre-Web
-Check out our [Contributing Guidelines](https://github.com/janeczku/calibre-web/blob/master/CONTRIBUTING.md)
+To contribute, please check our [Contributing Guidelines](https://github.com/janeczku/calibre-web/blob/master/CONTRIBUTING.md). We welcome issues, feature requests, and pull requests from the community.
+
+### Reporting Bugs
+
+If you encounter bugs or issues, please report them in the [issues section](https://github.com/janeczku/calibre-web/issues) of the repository. Be sure to include detailed information about your setup and the problem encountered.
+
+### Feature Requests
+
+We welcome suggestions for new features. Please create a new issue in the repository to discuss your ideas.
+
+## Additional Resources
+
+- **Documentation**: Comprehensive documentation is available on the [Calibre-Web wiki](https://github.com/janeczku/calibre-web/wiki).
+- **Community Contributions**: Explore the [community contributions](https://github.com/janeczku/calibre-web/pulls) to see ongoing work and how you can get involved.
+
+---
+
+Thank you for using Calibre-Web! We hope you enjoy managing your eBook library with our tool.
diff --git a/SECURITY.md b/SECURITY.md
index e4ab1a8d..c0861a18 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -10,41 +10,46 @@ To receive fixes for security vulnerabilities it is required to always upgrade t
## History
-| Fixed in | Description |CVE number |
-|---------------|--------------------------------------------------------------------------------------------------------------------|---------|
-| 3rd July 2018 | Guest access acts as a backdoor ||
-| V 0.6.7 | Hardcoded secret key for sessions |CVE-2020-12627 |
-| V 0.6.13 | Calibre-Web Metadata cross site scripting |CVE-2021-25964|
-| V 0.6.13 | Name of Shelves are only visible to users who can access the corresponding shelf Thanks to @ibarrionuevo ||
-| V 0.6.13 | JavaScript could get executed in the description field. Thanks to @ranjit-git and Hagai Wechsler (WhiteSource) ||
-| V 0.6.13 | JavaScript could get executed in a custom column of type "comment" field ||
-| V 0.6.13 | JavaScript could get executed after converting a book to another format with a title containing javascript code ||
-| V 0.6.13 | JavaScript could get executed after converting a book to another format with a username containing javascript code ||
-| V 0.6.13 | JavaScript could get executed in the description series, categories or publishers title ||
-| V 0.6.13 | JavaScript could get executed in the shelf title ||
-| V 0.6.13 | Login with the old session cookie after logout. Thanks to @ibarrionuevo ||
-| V 0.6.14 | CSRF was possible. Thanks to @mik317 and Hagai Wechsler (WhiteSource) |CVE-2021-25965|
-| V 0.6.14 | Migrated some routes to POST-requests (CSRF protection). Thanks to @scara31 |CVE-2021-4164|
-| V 0.6.15 | Fix for "javascript:" script links in identifier. Thanks to @scara31 |CVE-2021-4170|
-| V 0.6.15 | Cross-Site Scripting vulnerability on uploaded cover file names. Thanks to @ibarrionuevo ||
-| V 0.6.15 | Creating public shelfs is now denied if user is missing the edit public shelf right. Thanks to @ibarrionuevo ||
-| V 0.6.15 | Changed error message in case of trying to delete a shelf unauthorized. Thanks to @ibarrionuevo ||
-| V 0.6.16 | JavaScript could get executed on authors page. Thanks to @alicaz |CVE-2022-0352|
-| V 0.6.16 | Localhost can no longer be used to upload covers. Thanks to @scara31 |CVE-2022-0339|
-| V 0.6.16 | Another case where public shelfs could be created without permission is prevented. Thanks to @nhiephon |CVE-2022-0273|
-| V 0.6.16 | It's prevented to get the name of a private shelfs. Thanks to @nhiephon |CVE-2022-0405|
-| V 0.6.17 | The SSRF Protection can no longer be bypassed via an HTTP redirect. Thanks to @416e6e61 |CVE-2022-0767|
-| V 0.6.17 | The SSRF Protection can no longer be bypassed via 0.0.0.0 and it's ipv6 equivalent. Thanks to @r0hanSH |CVE-2022-0766|
-| V 0.6.18 | Possible SQL Injection is prevented in user table Thanks to Iman Sharafaldin (Forward Security) |CVE-2022-30765|
-| V 0.6.18 | The SSRF protection no longer can be bypassed by IPV6/IPV4 embedding. Thanks to @416e6e61 |CVE-2022-0939|
-| V 0.6.18 | The SSRF protection no longer can be bypassed to connect to other servers in the local network. Thanks to @michaellrowley |CVE-2022-0990|
-| V 0.6.20 | Credentials for emails are now stored encrypted ||
-| V 0.6.20 | Login is rate limited ||
-| V 0.6.20 | Passwordstrength can be forced ||
-| V 0.6.21 | SMTP server credentials are no longer returned to client ||
-| V 0.6.21 | Cross-site scripting (XSS) stored in href bypasses filter using data wrapper no longer possible ||
-| V 0.6.21 | Cross-site scripting (XSS) is no longer possible via pathchooser ||
-| V 0.6.21 | Error Handling at non existent rating, language, and user downloaded books was fixed ||
+| Fixed in | Description | CVE number |
+|---------------|----------------------------------------------------------------------------------------------------------------------------------|----------------|
+| 3rd July 2018 | Guest access acts as a backdoor | |
+| V 0.6.7 | Hardcoded secret key for sessions | CVE-2020-12627 |
+| V 0.6.13 | Calibre-Web Metadata cross site scripting | CVE-2021-25964 |
+| V 0.6.13 | Name of Shelves are only visible to users who can access the corresponding shelf Thanks to @ibarrionuevo | |
+| V 0.6.13 | JavaScript could get executed in the description field. Thanks to @ranjit-git and Hagai Wechsler (WhiteSource) | |
+| V 0.6.13 | JavaScript could get executed in a custom column of type "comment" field | |
+| V 0.6.13 | JavaScript could get executed after converting a book to another format with a title containing javascript code | |
+| V 0.6.13 | JavaScript could get executed after converting a book to another format with a username containing javascript code | |
+| V 0.6.13 | JavaScript could get executed in the description series, categories or publishers title | |
+| V 0.6.13 | JavaScript could get executed in the shelf title | |
+| V 0.6.13 | Login with the old session cookie after logout. Thanks to @ibarrionuevo | |
+| V 0.6.14 | CSRF was possible. Thanks to @mik317 and Hagai Wechsler (WhiteSource) | CVE-2021-25965 |
+| V 0.6.14 | Migrated some routes to POST-requests (CSRF protection). Thanks to @scara31 | CVE-2021-4164 |
+| V 0.6.15 | Fix for "javascript:" script links in identifier. Thanks to @scara31 | CVE-2021-4170 |
+| V 0.6.15 | Cross-Site Scripting vulnerability on uploaded cover file names. Thanks to @ibarrionuevo | |
+| V 0.6.15 | Creating public shelfs is now denied if user is missing the edit public shelf right. Thanks to @ibarrionuevo | |
+| V 0.6.15 | Changed error message in case of trying to delete a shelf unauthorized. Thanks to @ibarrionuevo | |
+| V 0.6.16 | JavaScript could get executed on authors page. Thanks to @alicaz | CVE-2022-0352 |
+| V 0.6.16 | Localhost can no longer be used to upload covers. Thanks to @scara31 | CVE-2022-0339 |
+| V 0.6.16 | Another case where public shelfs could be created without permission is prevented. Thanks to @nhiephon | CVE-2022-0273 |
+| V 0.6.16 | It's prevented to get the name of a private shelfs. Thanks to @nhiephon | CVE-2022-0405 |
+| V 0.6.17 | The SSRF Protection can no longer be bypassed via an HTTP redirect. Thanks to @416e6e61 | CVE-2022-0767 |
+| V 0.6.17 | The SSRF Protection can no longer be bypassed via 0.0.0.0 and it's ipv6 equivalent. Thanks to @r0hanSH | CVE-2022-0766 |
+| V 0.6.18 | Possible SQL Injection is prevented in user table Thanks to Iman Sharafaldin (Forward Security) | CVE-2022-30765 |
+| V 0.6.18 | The SSRF protection no longer can be bypassed by IPV6/IPV4 embedding. Thanks to @416e6e61 | CVE-2022-0939 |
+| V 0.6.18 | The SSRF protection no longer can be bypassed to connect to other servers in the local network. Thanks to @michaellrowley | CVE-2022-0990 |
+| V 0.6.20 | Credentials for emails are now stored encrypted | |
+| V 0.6.20 | Login is rate limited | |
+| V 0.6.20 | Passwordstrength can be forced | |
+| V 0.6.21 | SMTP server credentials are no longer returned to client | |
+| V 0.6.21 | Cross-site scripting (XSS) stored in href bypasses filter using data wrapper no longer possible | |
+| V 0.6.21 | Cross-site scripting (XSS) is no longer possible via pathchooser | |
+| V 0.6.21 | Error Handling at non existent rating, language, and user downloaded books was fixed | |
+| V 0.6.22 | Upload mimetype is checked to prevent malicious file content in the books library | |
+| V 0.6.22 | Cross-site scripting (XSS) stored in comments section is prevented better (switching from lxml to bleach for sanitizing strings) | |
+| V 0.6.23 | Cookies are no longer stored for opds basic authentication and proxy authentication | |
+
+
## Statement regarding Log4j (CVE-2021-44228 and related)
diff --git a/cps/__init__.py b/cps/__init__.py
index d003ed5a..c4150942 100644
--- a/cps/__init__.py
+++ b/cps/__init__.py
@@ -35,7 +35,6 @@ from .reverseproxy import ReverseProxied
from .server import WebServer
from .dep_check import dependency_check
from .updater import Updater
-from .babel import babel, get_locale
from . import config_sql
from . import cache_buster
from . import ub, db
@@ -56,35 +55,41 @@ mimetypes.init()
mimetypes.add_type('application/xhtml+xml', '.xhtml')
mimetypes.add_type('application/epub+zip', '.epub')
mimetypes.add_type('application/epub+zip', '.kepub')
-mimetypes.add_type('text/xml', '.fb2')
-mimetypes.add_type('application/octet-stream', '.mobi')
+mimetypes.add_type('application/fb2+zip', '.fb2')
+mimetypes.add_type('application/x-mobipocket-ebook', '.mobi')
mimetypes.add_type('application/octet-stream', '.prc')
-mimetypes.add_type('application/vnd.amazon.ebook', '.azw')
-mimetypes.add_type('application/x-mobi8-ebook', '.azw3')
-mimetypes.add_type('application/x-rar', '.cbr')
-mimetypes.add_type('application/zip', '.cbz')
+mimetypes.add_type('application/x-mobipocket-ebook', '.azw')
+mimetypes.add_type('application/x-mobipocket-ebook', '.azw3')
+mimetypes.add_type('application/x-cbr', '.cbr')
+mimetypes.add_type('application/x-cbz', '.cbz')
mimetypes.add_type('application/x-tar', '.cbt')
mimetypes.add_type('application/x-7z-compressed', '.cb7')
-mimetypes.add_type('image/vnd.djv', '.djv')
-mimetypes.add_type('image/vnd.djv', '.djvu')
+mimetypes.add_type('image/vnd.djvu', '.djv')
+mimetypes.add_type('image/vnd.djvu', '.djvu')
mimetypes.add_type('application/mpeg', '.mpeg')
mimetypes.add_type('audio/mpeg', '.mp3')
mimetypes.add_type('audio/x-m4a', '.m4a')
mimetypes.add_type('audio/x-m4a', '.m4b')
+mimetypes.add_type('audio/x-hx-aac-adts', '.aac')
+mimetypes.add_type('audio/vnd.dolby.dd-raw', '.ac3')
+mimetypes.add_type('video/x-ms-asf', '.asf')
mimetypes.add_type('audio/ogg', '.ogg')
mimetypes.add_type('application/ogg', '.oga')
mimetypes.add_type('text/css', '.css')
mimetypes.add_type('application/x-ms-reader', '.lit')
-mimetypes.add_type('text/javascript; charset=UTF-8', '.js')
+mimetypes.add_type('text/javascript', '.js')
+mimetypes.add_type('text/rtf', '.rtf')
log = logger.create()
app = Flask(__name__)
app.config.update(
SESSION_COOKIE_HTTPONLY=True,
- SESSION_COOKIE_SAMESITE='Strict',
- REMEMBER_COOKIE_SAMESITE='Strict', # will be available in flask-login 0.5.1 earliest
- WTF_CSRF_SSL_STRICT=False
+ SESSION_COOKIE_SAMESITE='Lax',
+ REMEMBER_COOKIE_SAMESITE='Strict',
+ WTF_CSRF_SSL_STRICT=False,
+ SESSION_COOKIE_NAME=os.environ.get('COOKIE_PREFIX', "") + "session",
+ REMEMBER_COOKIE_NAME=os.environ.get('COOKIE_PREFIX', "") + "remember_token"
)
lm = MyLoginManager()
@@ -98,7 +103,7 @@ if wtf_present:
else:
csrf = None
-calibre_db = db.CalibreDB()
+calibre_db = db.CalibreDB(app)
web_server = WebServer()
@@ -142,9 +147,7 @@ def create_app():
lm.anonymous_user = ub.Anonymous
lm.session_protection = 'strong' if config.config_session == 1 else "basic"
- db.CalibreDB.update_config(config)
- db.CalibreDB.setup_db(config.config_calibre_dir, cli_param.settings_path)
- calibre_db.init_db()
+ db.CalibreDB.update_config(config, config.config_calibre_dir, cli_param.settings_path)
updater_thread.init_updater(config, web_server)
# Perform dry run of updater and exit afterward
@@ -177,6 +180,7 @@ def create_app():
app.secret_key = os.getenv('SECRET_KEY', config_sql.get_flask_session_key(ub.session))
web_server.init_app(app, config)
+ from .cw_babel import babel, get_locale
if hasattr(babel, "localeselector"):
babel.init_app(app)
babel.localeselector(get_locale)
diff --git a/cps/about.py b/cps/about.py
index 355978c3..d76fc510 100644
--- a/cps/about.py
+++ b/cps/about.py
@@ -23,10 +23,10 @@
import sys
import platform
import sqlite3
+from importlib.metadata import metadata
from collections import OrderedDict
import flask
-import jinja2
from flask_babel import gettext as _
from . import db, calibre_db, converter, uploader, constants, dep_check
@@ -41,17 +41,18 @@ req = dep_check.load_dependencies(False)
opt = dep_check.load_dependencies(True)
for i in (req + opt):
modules[i[1]] = i[0]
-modules['Jinja2'] = jinja2.__version__
-modules['pySqlite'] = sqlite3.version
+modules['Jinja2'] = metadata("jinja2")["Version"]
+if sys.version_info < (3, 12):
+ modules['pySqlite'] = sqlite3.version
modules['SQLite'] = sqlite3.sqlite_version
sorted_modules = OrderedDict((sorted(modules.items(), key=lambda x: x[0].casefold())))
def collect_stats():
if constants.NIGHTLY_VERSION[0] == "$Format:%H$":
- calibre_web_version = constants.STABLE_VERSION['version'].replace("b", " Beta")
+ calibre_web_version = constants.STABLE_VERSION.replace("b", " Beta")
else:
- calibre_web_version = (constants.STABLE_VERSION['version'].replace("b", " Beta") + ' - '
+ calibre_web_version = (constants.STABLE_VERSION.replace("b", " Beta") + ' - '
+ constants.NIGHTLY_VERSION[0].replace('%', '%%') + ' - '
+ constants.NIGHTLY_VERSION[1].replace('%', '%%'))
diff --git a/cps/admin.py b/cps/admin.py
index 5f481fa1..5451080a 100644
--- a/cps/admin.py
+++ b/cps/admin.py
@@ -32,7 +32,8 @@ from datetime import time as datetime_time
from functools import wraps
from urllib.parse import urlparse
-from flask import Blueprint, flash, redirect, url_for, abort, request, make_response, send_from_directory, g, Response
+from flask import Blueprint, flash, redirect, url_for, abort, request, make_response, \
+ send_from_directory, g, jsonify
from markupsafe import Markup
from .cw_login import current_user
from flask_babel import gettext as _
@@ -52,8 +53,9 @@ from .gdriveutils import is_gdrive_ready, gdrive_support
from .render_template import render_title_template, get_sidebar_config
from .services.worker import WorkerThread
from .usermanagement import user_login_required
-from .babel import get_available_translations, get_available_locale, get_user_locale_language
+from .cw_babel import get_available_translations, get_available_locale, get_user_locale_language
from . import debug_info
+from .string_helper import strip_whitespaces
log = logger.create()
@@ -117,7 +119,7 @@ def before_request():
g.allow_upload = config.config_uploading
g.current_theme = config.config_theme
g.config_authors_max = config.config_authors_max
- if '/static/' not in request.path and not config.db_configured and \
+ if ('/static/' not in request.path and not config.db_configured and
request.endpoint not in ('admin.ajax_db_config',
'admin.simulatedbchange',
'admin.db_configuration',
@@ -125,7 +127,7 @@ def before_request():
'web.login_post',
'web.logout',
'admin.load_dialogtexts',
- 'admin.ajax_pathchooser'):
+ 'admin.ajax_pathchooser')):
return redirect(url_for('admin.db_configuration'))
@@ -143,7 +145,6 @@ def shutdown():
show_text = {}
if task in (0, 1): # valid commandos received
# close all database connections
- calibre_db.dispose()
ub.dispose()
if task == 0:
@@ -305,7 +306,15 @@ def edit_user_table():
.group_by(text('books_tags_link.tag')) \
.order_by(db.Tags.name).all()
if config.config_restricted_column:
- custom_values = calibre_db.session.query(db.cc_classes[config.config_restricted_column]).all()
+ try:
+ custom_values = calibre_db.session.query(db.cc_classes[config.config_restricted_column]).all()
+ except (KeyError, AttributeError, IndexError):
+ custom_values = []
+ log.error("Custom Column No.{} does not exist in calibre database".format(
+ config.config_restricted_column))
+ flash(_("Custom Column No.%(column)d does not exist in calibre database",
+ column=config.config_restricted_column),
+ category="error")
else:
custom_values = []
if not config.config_anonbrowse:
@@ -370,10 +379,7 @@ def list_users():
user.default = get_user_locale_language(user.default_language)
table_entries = {'totalNotFiltered': total_count, 'total': filtered_count, "rows": users}
- js_list = json.dumps(table_entries, cls=db.AlchemyEncoder)
- response = make_response(js_list)
- response.headers["Content-Type"] = "application/json; charset=utf-8"
- return response
+ return make_response(json.dumps(table_entries, cls=db.AlchemyEncoder))
@admi.route("/ajax/deleteuser", methods=['POST'])
@@ -392,7 +398,7 @@ def delete_user():
success = list()
if not users:
log.error("User not found")
- return Response(json.dumps({'type': "danger", 'message': _("User not found")}), mimetype='application/json')
+ return make_response(jsonify(type="danger", message=_("User not found")))
for user in users:
try:
message = _delete_user(user)
@@ -408,7 +414,7 @@ def delete_user():
log.info("Users {} deleted".format(user_ids))
success = [{'type': "success", 'message': _("{} users deleted successfully").format(count)}]
success.extend(errors)
- return Response(json.dumps(success), mimetype='application/json')
+ return make_response(jsonify(success))
@admi.route("/ajax/getlocale")
@@ -420,7 +426,7 @@ def table_get_locale():
current_locale = get_locale()
for loc in locale:
ret.append({'value': str(loc), 'text': loc.get_language_name(current_locale)})
- return json.dumps(ret)
+ return json.dumps(sorted(ret, key=lambda x: x['text']))
@admi.route("/ajax/getdefaultlanguage")
@@ -432,7 +438,7 @@ def table_get_default_lang():
ret.append({'value': 'all', 'text': _('Show All')})
for lang in languages:
ret.append({'value': lang.lang_code, 'text': lang.name})
- return json.dumps(ret)
+ return json.dumps(sorted(ret, key=lambda x: x['text']))
@admi.route("/ajax/editlistusers/", methods=['POST'])
@@ -463,9 +469,9 @@ def edit_list_user(param):
if 'value[]' in vals:
setattr(user, param, prepare_tags(user, vals['action'][0], param, vals['value[]']))
else:
- setattr(user, param, vals['value'].strip())
+ setattr(user, param, strip_whitespaces(vals['value']))
else:
- vals['value'] = vals['value'].strip()
+ vals['value'] = strip_whitespaces(vals['value'])
if param == 'name':
if user.name == "Guest":
raise Exception(_("Guest Name can't be changed"))
@@ -490,10 +496,10 @@ def edit_list_user(param):
if not ub.session.query(ub.User). \
filter(ub.User.role.op('&')(constants.ROLE_ADMIN) == constants.ROLE_ADMIN,
ub.User.id != user.id).count():
- return Response(
- json.dumps([{'type': "danger",
+ return make_response(
+ jsonify([{'type': "danger",
'message': _("No admin user remaining, can't remove admin role",
- nick=user.name)}]), mimetype='application/json')
+ nick=user.name)}]))
user.role &= ~value
else:
raise Exception(_("Value has to be true or false"))
@@ -566,7 +572,7 @@ def update_view_configuration():
_config_string(to_save, "config_calibre_web_title")
_config_string(to_save, "config_columns_to_ignore")
if _config_string(to_save, "config_title_regex"):
- calibre_db.update_title_sort(config)
+ calibre_db.create_functions(config)
if not check_valid_read_column(to_save.get("config_read_column", "0")):
flash(_("Invalid Read Column"), category="error")
@@ -690,7 +696,7 @@ def delete_domain():
def list_domain(allow):
answer = ub.session.query(ub.Registration).filter(ub.Registration.allow == allow).all()
json_dumps = json.dumps([{"domain": r.domain.replace('%', '*').replace('_', '?'), "id": r.id} for r in answer])
- js = json.dumps(json_dumps.replace('"', "'")).lstrip('"').strip('"')
+ js = json.dumps(json_dumps.replace('"', "'")).strip('"')
response = make_response(js.replace("'", '"'))
response.headers["Content-Type"] = "application/json; charset=utf-8"
return response
@@ -939,7 +945,7 @@ def do_full_kobo_sync(userid):
count = ub.session.query(ub.KoboSyncedBooks).filter(userid == ub.KoboSyncedBooks.user_id).delete()
message = _("{} sync entries deleted").format(count)
ub.session_commit(message)
- return Response(json.dumps([{"type": "success", "message": message}]), mimetype='application/json')
+ return make_response(jsonify(type="success", message=message))
def check_valid_read_column(column):
@@ -981,8 +987,14 @@ def prepare_tags(user, action, tags_name, id_list):
raise Exception(_("Tag not found"))
new_tags_list = [x.name for x in tags]
else:
- tags = calibre_db.session.query(db.cc_classes[config.config_restricted_column]) \
- .filter(db.cc_classes[config.config_restricted_column].id.in_(id_list)).all()
+ try:
+ tags = calibre_db.session.query(db.cc_classes[config.config_restricted_column]) \
+ .filter(db.cc_classes[config.config_restricted_column].id.in_(id_list)).all()
+ except (KeyError, AttributeError, IndexError):
+ log.error("Custom Column No.{} does not exist in calibre database".format(
+ config.config_restricted_column))
+ raise Exception(_("Custom Column No.%(column)d does not exist in calibre database",
+ column=config.config_restricted_column))
new_tags_list = [x.value for x in tags]
saved_tags_list = user.__dict__[tags_name].split(",") if len(user.__dict__[tags_name]) else []
if action == "remove":
@@ -1100,7 +1112,7 @@ def _config_checkbox_int(to_save, x):
def _config_string(to_save, x):
- return config.set_from_dictionary(to_save, x, lambda y: y.strip().strip(u'\u200B\u200C\u200D\ufeff') if y else y)
+ return config.set_from_dictionary(to_save, x, lambda y: strip_whitespaces(y) if y else y)
def _configuration_gdrive_helper(to_save):
@@ -1250,7 +1262,7 @@ def _configuration_ldap_helper(to_save):
@admin_required
def simulatedbchange():
db_change, db_valid = _db_simulate_change()
- return Response(json.dumps({"change": db_change, "valid": db_valid}), mimetype='application/json')
+ return make_response(jsonify(change=db_change, valid=db_valid))
@admi.route("/admin/user/new", methods=["GET", "POST"])
@@ -1311,9 +1323,9 @@ def update_mailsettings():
if to_save.get("mail_password_e", ""):
_config_string(to_save, "mail_password_e")
_config_int(to_save, "mail_size", lambda y: int(y) * 1024 * 1024)
- config.mail_server = to_save.get('mail_server', "").strip()
- config.mail_from = to_save.get('mail_from', "").strip()
- config.mail_login = to_save.get('mail_login', "").strip()
+ config.mail_server = strip_whitespaces(to_save.get('mail_server', ""))
+ config.mail_from = strip_whitespaces(to_save.get('mail_from', ""))
+ config.mail_login = strip_whitespaces(to_save.get('mail_login', ""))
try:
config.save()
except (OperationalError, InvalidRequestError) as e:
@@ -1678,10 +1690,10 @@ def cancel_task():
def _db_simulate_change():
param = request.form.to_dict()
to_save = dict()
- to_save['config_calibre_dir'] = re.sub(r'[\\/]metadata\.db$',
+ to_save['config_calibre_dir'] = strip_whitespaces(re.sub(r'[\\/]metadata\.db$',
'',
param['config_calibre_dir'],
- flags=re.IGNORECASE).strip()
+ flags=re.IGNORECASE))
db_valid, db_change = calibre_db.check_valid_db(to_save["config_calibre_dir"],
ub.app_DB_path,
config.config_calibre_uuid)
@@ -1715,14 +1727,19 @@ def _db_configuration_update_helper():
db_change = True
except Exception as ex:
return _db_configuration_result('{}'.format(ex), gdrive_error)
-
- if db_change or not db_valid or not config.db_configured \
- or config.config_calibre_dir != to_save["config_calibre_dir"]:
+ config.config_calibre_split = to_save.get('config_calibre_split', 0) == "on"
+ if config.config_calibre_split:
+ split_dir = to_save.get("config_calibre_split_dir")
+ if not os.path.exists(split_dir):
+ return _db_configuration_result(_("Books path not valid"), gdrive_error)
+ else:
+ _config_string(to_save, "config_calibre_split_dir")
+ if (db_change or not db_valid or not config.db_configured
+ or config.config_calibre_dir != to_save["config_calibre_dir"]):
if not os.path.exists(metadata_db) or not to_save['config_calibre_dir']:
return _db_configuration_result(_('DB Location is not Valid, Please Enter Correct Path'), gdrive_error)
else:
calibre_db.setup_db(to_save['config_calibre_dir'], ub.app_DB_path)
- config.store_calibre_uuid(calibre_db, db.Library_Id)
# if db changed -> delete shelfs, delete download books, delete read books, kobo sync...
if db_change:
log.info("Calibre Database changed, all Calibre-Web info related to old Database gets deleted")
@@ -1736,13 +1753,20 @@ def _db_configuration_update_helper():
ub.session.query(ub.KoboSyncedBooks).delete()
helper.delete_thumbnail_cache()
ub.session_commit()
+ # deleted visibilities based on custom column and tags
+ config.config_restricted_column = 0
+ config.config_denied_tags = ""
+ config.config_allowed_tags = ""
+ config.config_columns_to_ignore = ""
+ config.config_denied_column_value = ""
+ config.config_allowed_column_value = ""
+ config.config_read_column = 0
_config_string(to_save, "config_calibre_dir")
- calibre_db.update_config(config)
+ calibre_db.update_config(config, config.config_calibre_dir, ub.app_DB_path)
+ config.store_calibre_uuid(calibre_db, db.Library_Id)
if not os.access(os.path.join(config.config_calibre_dir, "metadata.db"), os.W_OK):
flash(_("DB is not Writeable"), category="warning")
- _config_string(to_save, "config_calibre_split_dir")
- config.config_calibre_split = to_save.get('config_calibre_split', 0) == "on"
- calibre_db.update_config(config)
+ calibre_db.update_config(config, config.config_calibre_dir, ub.app_DB_path)
config.save()
return _db_configuration_result(None, gdrive_error)
@@ -1775,9 +1799,8 @@ def _configuration_update_helper():
if "config_upload_formats" in to_save:
to_save["config_upload_formats"] = ','.join(
- helper.uniq([x.lstrip().rstrip().lower() for x in to_save["config_upload_formats"].split(',')]))
+ helper.uniq([x.strip().lower() for x in to_save["config_upload_formats"].split(',')]))
_config_string(to_save, "config_upload_formats")
- # constants.EXTENSIONS_UPLOAD = config.config_upload_formats.split(',')
_config_string(to_save, "config_calibre")
_config_string(to_save, "config_binariesdir")
@@ -1871,7 +1894,7 @@ def _configuration_result(error_flash=None, reboot=False):
resp['result'] = [{'type': "success", 'message': _("Calibre-Web configuration updated")}]
resp['reboot'] = reboot
resp['config_upload'] = config.config_upload_formats
- return Response(json.dumps(resp), mimetype='application/json')
+ return make_response(jsonify(resp))
def _db_configuration_result(error_flash=None, gdrive_error=None):
@@ -2076,7 +2099,7 @@ def _handle_edit_user(to_save, content, languages, translations, kobo_support):
def extract_user_data_from_field(user, field):
- match = re.search(field + r"=([@\.\d\s\w-]+)", user, re.IGNORECASE | re.UNICODE)
+ match = re.search(field + r"=(.*?)($|(?.
+
+import mutagen
+import base64
+from . import cover, logger
+
+from cps.constants import BookMeta
+
+log = logger.create()
+
+def get_audio_file_info(tmp_file_path, original_file_extension, original_file_name, no_cover_processing):
+ tmp_cover_name = None
+ audio_file = mutagen.File(tmp_file_path)
+ comments = None
+ if original_file_extension in [".mp3", ".wav", ".aiff"]:
+ cover_data = list()
+ for key, val in audio_file.tags.items():
+ if key.startswith("APIC:"):
+ cover_data.append(val)
+ if key.startswith("COMM:"):
+ comments = val.text[0]
+ title = audio_file.tags.get('TIT2').text[0] if "TIT2" in audio_file.tags else None
+ author = audio_file.tags.get('TPE1').text[0] if "TPE1" in audio_file.tags else None
+ if author is None:
+ author = audio_file.tags.get('TPE2').text[0] if "TPE2" in audio_file.tags else None
+ tags = audio_file.tags.get('TCON').text[0] if "TCON" in audio_file.tags else None # Genre
+ series = audio_file.tags.get('TALB').text[0] if "TALB" in audio_file.tags else None# Album
+ series_id = audio_file.tags.get('TRCK').text[0] if "TRCK" in audio_file.tags else None # track no.
+ publisher = audio_file.tags.get('TPUB').text[0] if "TPUB" in audio_file.tags else None
+ pubdate = str(audio_file.tags.get('TDRL').text[0]) if "TDRL" in audio_file.tags else None
+ if not pubdate:
+ pubdate = str(audio_file.tags.get('TDRC').text[0]) if "TDRC" in audio_file.tags else None
+ if not pubdate:
+ pubdate = str(audio_file.tags.get('TDOR').text[0]) if "TDOR" in audio_file.tags else None
+ if cover_data and not no_cover_processing:
+ cover_info = cover_data[0]
+ for dat in cover_data:
+ if dat.type == mutagen.id3.PictureType.COVER_FRONT:
+ cover_info = dat
+ break
+ tmp_cover_name = cover.cover_processing(tmp_file_path, cover_info.data, "." + cover_info.mime[-3:])
+ elif original_file_extension in [".ogg", ".flac", ".opus", ".ogv"]:
+ title = audio_file.tags.get('TITLE')[0] if "TITLE" in audio_file else None
+ author = audio_file.tags.get('ARTIST')[0] if "ARTIST" in audio_file else None
+ comments = audio_file.tags.get('COMMENTS')[0] if "COMMENTS" in audio_file else None
+ tags = audio_file.tags.get('GENRE')[0] if "GENRE" in audio_file else None # Genre
+ series = audio_file.tags.get('ALBUM')[0] if "ALBUM" in audio_file else None
+ series_id = audio_file.tags.get('TRACKNUMBER')[0] if "TRACKNUMBER" in audio_file else None
+ publisher = audio_file.tags.get('LABEL')[0] if "LABEL" in audio_file else None
+ pubdate = audio_file.tags.get('DATE')[0] if "DATE" in audio_file else None
+ cover_data = audio_file.tags.get('METADATA_BLOCK_PICTURE')
+ if not no_cover_processing:
+ if cover_data:
+ cover_info = mutagen.flac.Picture(base64.b64decode(cover_data[0]))
+ tmp_cover_name = cover.cover_processing(tmp_file_path, cover_info.data, "." + cover_info.mime[-3:])
+ if hasattr(audio_file, "pictures"):
+ cover_info = audio_file.pictures[0]
+ for dat in audio_file.pictures:
+ if dat.type == mutagen.id3.PictureType.COVER_FRONT:
+ cover_info = dat
+ break
+ tmp_cover_name = cover.cover_processing(tmp_file_path, cover_info.data, "." + cover_info.mime[-3:])
+ elif original_file_extension in [".aac"]:
+ title = audio_file.tags.get('Title').value if "Title" in audio_file else None
+ author = audio_file.tags.get('Artist').value if "Artist" in audio_file else None
+ comments = audio_file.tags.get('Comment').value if "Comment" in audio_file else None
+ tags = audio_file.tags.get('Genre').value if "Genre" in audio_file else None
+ series = audio_file.tags.get('Album').value if "Album" in audio_file else None
+ series_id = audio_file.tags.get('Track').value if "Track" in audio_file else None
+ publisher = audio_file.tags.get('Label').value if "Label" in audio_file else None
+ pubdate = audio_file.tags.get('Year').value if "Year" in audio_file else None
+ cover_data = audio_file.tags['Cover Art (Front)']
+ if cover_data and not no_cover_processing:
+ tmp_cover_name = tmp_file_path + '.jpg'
+ with open(tmp_cover_name, "wb") as cover_file:
+ cover_file.write(cover_data.value.split(b"\x00",1)[1])
+ elif original_file_extension in [".asf"]:
+ title = audio_file.tags.get('Title')[0].value if "Title" in audio_file else None
+ author = audio_file.tags.get('Artist')[0].value if "Artist" in audio_file else None
+ comments = audio_file.tags.get('Comments')[0].value if "Comments" in audio_file else None
+ tags = audio_file.tags.get('Genre')[0].value if "Genre" in audio_file else None
+ series = audio_file.tags.get('Album')[0].value if "Album" in audio_file else None
+ series_id = audio_file.tags.get('Track')[0].value if "Track" in audio_file else None
+ publisher = audio_file.tags.get('Label')[0].value if "Label" in audio_file else None
+ pubdate = audio_file.tags.get('Year')[0].value if "Year" in audio_file else None
+ cover_data = audio_file.tags.get('WM/Picture', None)
+ if cover_data and not no_cover_processing:
+ tmp_cover_name = tmp_file_path + '.jpg'
+ with open(tmp_cover_name, "wb") as cover_file:
+ cover_file.write(cover_data[0].value)
+ elif original_file_extension in [".mp4", ".m4a", ".m4b"]:
+ title = audio_file.tags.get('©nam')[0] if "©nam" in audio_file.tags else None
+ author = audio_file.tags.get('©ART')[0] if "©ART" in audio_file.tags else None
+ comments = audio_file.tags.get('©cmt')[0] if "©cmt" in audio_file.tags else None
+ tags = audio_file.tags.get('©gen')[0] if "©gen" in audio_file.tags else None
+ series = audio_file.tags.get('©alb')[0] if "©alb" in audio_file.tags else None
+ series_id = str(audio_file.tags.get('trkn')[0][0]) if "trkn" in audio_file.tags else None
+ publisher = ""
+ pubdate = audio_file.tags.get('©day')[0] if "©day" in audio_file.tags else None
+ cover_data = audio_file.tags.get('covr', None)
+ if cover_data and not no_cover_processing:
+ cover_type = None
+ for c in cover_data:
+ if c.imageformat == mutagen.mp4.AtomDataType.JPEG:
+ cover_type =".jpg"
+ cover_bin = c
+ break
+ elif c.imageformat == mutagen.mp4.AtomDataType.PNG:
+ cover_type = ".png"
+ cover_bin = c
+ break
+ if cover_type:
+ tmp_cover_name = cover.cover_processing(tmp_file_path, cover_bin, cover_type)
+ else:
+ logger.error("Unknown covertype in file {} ".format(original_file_name))
+
+ return BookMeta(
+ file_path=tmp_file_path,
+ extension=original_file_extension,
+ title=title or original_file_name ,
+ author="Unknown" if author is None else author,
+ cover=tmp_cover_name,
+ description="" if comments is None else comments,
+ tags="" if tags is None else tags,
+ series="" if series is None else series,
+ series_id="1" if series_id is None else series_id.split("/")[0],
+ languages="",
+ publisher= "" if publisher is None else publisher,
+ pubdate="" if pubdate is None else pubdate,
+ identifiers=[],
+ )
diff --git a/cps/basic.py b/cps/basic.py
new file mode 100644
index 00000000..b0121010
--- /dev/null
+++ b/cps/basic.py
@@ -0,0 +1,90 @@
+# This file is part of the Calibre-Web (https://github.com/janeczku/calibre-web)
+# Copyright (C) 2018-2019 OzzieIsaacs, cervinko, jkrehm, bodybybuddha, ok11,
+# andy29485, idalin, Kyosfonica, wuqi, Kennyl, lemmsh,
+# falgh1, grunjol, csitko, ytils, xybydy, trasba, vrabe,
+# ruben-herold, marblepebble, JackED42, SiphonSquirrel,
+# apetresc, nanu-c, mutschler, carderne
+#
+# 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 .
+
+
+from cps.pagination import Pagination
+from flask import Blueprint
+from flask_babel import gettext as _
+from flask_babel import get_locale
+from flask import request, redirect, url_for
+
+from . import logger, isoLanguages
+from . import db, config
+from . import calibre_db
+from .usermanagement import login_required_if_no_ano
+from .render_template import render_title_template
+from .web import get_sort_function
+
+try:
+ from natsort import natsorted as sort
+except ImportError:
+ sort = sorted # Just use regular sort then, may cause issues with badly named pages in cbz/cbr files
+
+basic = Blueprint('basic', __name__)
+
+log = logger.create()
+
+
+@basic.route("/basic", methods=["GET"])
+@login_required_if_no_ano
+def index():
+ term = request.args.get("query", "") # default to showing all books
+ limit = 15
+ page = int(request.args.get("page") or 1)
+ off = (page - 1) * limit
+ order = get_sort_function("stored", "search")
+ join = db.books_series_link, db.Books.id == db.books_series_link.c.book, db.Series
+ entries, result_count, pagination = calibre_db.get_search_results(term,
+ config,
+ off,
+ order,
+ limit,
+ *join)
+ return render_title_template('basic_index.html',
+ searchterm=term,
+ pagination=pagination,
+ query=term,
+ adv_searchterm=term,
+ entries=entries,
+ result_count=result_count,
+ title=_("Search"),
+ page="search",
+ order=order[1])
+
+
+@basic.route("/basic_book/")
+@login_required_if_no_ano
+def show_book(book_id):
+ entries = calibre_db.get_book_read_archived(book_id, config.config_read_column, allow_show_archived=True)
+ if entries:
+ entry = entries[0]
+ for lang_index in range(0, len(entry.languages)):
+ entry.languages[lang_index].language_name = isoLanguages.get_language_name(get_locale(), entry.languages[
+ lang_index].lang_code)
+ entry.ordered_authors = calibre_db.order_authors([entry])
+
+ return render_title_template('basic_detail.html',
+ entry=entry,
+ is_xhr=request.headers.get('X-Requested-With') == 'XMLHttpRequest',
+ title=entry.title,
+ page="book")
+ else:
+ log.debug("Selected book is unavailable. File does not exist or is not accessible")
+ return redirect(url_for("basic.index"))
diff --git a/cps/cli.py b/cps/cli.py
index 5bf289b8..3f21a17e 100644
--- a/cps/cli.py
+++ b/cps/cli.py
@@ -29,8 +29,8 @@ from .constants import DEFAULT_SETTINGS_FILE, DEFAULT_GDRIVE_FILE
def version_info():
if _NIGHTLY_VERSION[1].startswith('$Format'):
- return "Calibre-Web version: %s - unknown git-clone" % _STABLE_VERSION['version'].replace("b", " Beta")
- return "Calibre-Web version: %s -%s" % (_STABLE_VERSION['version'].replace("b", " Beta"), _NIGHTLY_VERSION[1])
+ return "Calibre-Web version: %s - unknown git-clone" % _STABLE_VERSION.replace("b", " Beta")
+ return "Calibre-Web version: %s -%s" % (_STABLE_VERSION.replace("b", " Beta"), _NIGHTLY_VERSION[1])
class CliParameter(object):
diff --git a/cps/comic.py b/cps/comic.py
index 27c86c9a..271b1b45 100644
--- a/cps/comic.py
+++ b/cps/comic.py
@@ -90,7 +90,7 @@ def _extract_cover_from_archive(original_file_extension, tmp_file_name, rar_exec
if len(ext) > 1:
extension = ext[1].lower()
if extension in cover.COVER_EXTENSIONS:
- cover_data = cf.read([name])
+ cover_data = cf.read(name)
break
except Exception as ex:
log.error('Rarfile failed with error: {}'.format(ex))
@@ -109,13 +109,13 @@ def _extract_cover_from_archive(original_file_extension, tmp_file_name, rar_exec
return cover_data, extension
-def _extract_cover(tmp_file_name, original_file_extension, rar_executable):
+def _extract_cover(tmp_file_path, original_file_extension, rar_executable):
cover_data = extension = None
if use_comic_meta:
try:
- archive = ComicArchive(tmp_file_name, rar_exe_path=rar_executable)
+ archive = ComicArchive(tmp_file_path, rar_exe_path=rar_executable)
except TypeError:
- archive = ComicArchive(tmp_file_name)
+ archive = ComicArchive(tmp_file_path)
name_list = archive.getPageNameList if hasattr(archive, "getPageNameList") else archive.get_page_name_list
for index, name in enumerate(name_list()):
ext = os.path.splitext(name)
@@ -126,11 +126,11 @@ def _extract_cover(tmp_file_name, original_file_extension, rar_executable):
cover_data = get_page(index)
break
else:
- cover_data, extension = _extract_cover_from_archive(original_file_extension, tmp_file_name, rar_executable)
- return cover.cover_processing(tmp_file_name, cover_data, extension)
+ cover_data, extension = _extract_cover_from_archive(original_file_extension, tmp_file_path, rar_executable)
+ return cover.cover_processing(tmp_file_path, cover_data, extension)
-def get_comic_info(tmp_file_path, original_file_name, original_file_extension, rar_executable):
+def get_comic_info(tmp_file_path, original_file_name, original_file_extension, rar_executable, no_cover_processing):
if use_comic_meta:
try:
archive = ComicArchive(tmp_file_path, rar_exe_path=rar_executable)
@@ -155,14 +155,17 @@ def get_comic_info(tmp_file_path, original_file_name, original_file_extension, r
lang = loaded_metadata.language or ""
loaded_metadata.language = isoLanguages.get_lang3(lang)
-
+ if not no_cover_processing:
+ cover_file = _extract_cover(tmp_file_path, original_file_extension, rar_executable)
+ else:
+ cover_file = None
return BookMeta(
file_path=tmp_file_path,
extension=original_file_extension,
title=loaded_metadata.title or original_file_name,
author=" & ".join([credit["person"]
for credit in loaded_metadata.credits if credit["role"] == "Writer"]) or 'Unknown',
- cover=_extract_cover(tmp_file_path, original_file_extension, rar_executable),
+ cover=cover_file,
description=loaded_metadata.comments or "",
tags="",
series=loaded_metadata.series or "",
@@ -171,13 +174,17 @@ def get_comic_info(tmp_file_path, original_file_name, original_file_extension, r
publisher="",
pubdate="",
identifiers=[])
+ if not no_cover_processing:
+ cover_file = _extract_cover(tmp_file_path, original_file_extension, rar_executable)
+ else:
+ cover_file = None
return BookMeta(
file_path=tmp_file_path,
extension=original_file_extension,
title=original_file_name,
author='Unknown',
- cover=_extract_cover(tmp_file_path, original_file_extension, rar_executable),
+ cover=cover_file,
description="",
tags="",
series="",
diff --git a/cps/config_sql.py b/cps/config_sql.py
index 044c12b5..7e7d033d 100644
--- a/cps/config_sql.py
+++ b/cps/config_sql.py
@@ -35,7 +35,7 @@ except ImportError:
from . import constants, logger
from .subproc_wrapper import process_wait
-
+from .string_helper import strip_whitespaces
log = logger.create()
_Base = declarative_base()
@@ -182,26 +182,6 @@ class _Settings(_Base):
class ConfigSQL(object):
# pylint: disable=no-member
def __init__(self):
- '''self.config_calibre_uuid = None
- self.config_calibre_split_dir = None
- self.dirty = None
- self.config_logfile = None
- self.config_upload_formats = None
- self.mail_gmail_token = None
- self.mail_server_type = None
- self.mail_server = None
- self.config_log_level = None
- self.config_allowed_column_value = None
- self.config_denied_column_value = None
- self.config_allowed_tags = None
- self.config_denied_tags = None
- self.config_default_show = None
- self.config_default_role = None
- self.config_keyfile = None
- self.config_certfile = None
- self.config_rarfile_location = None
- self.config_kepubifypath = None
- self.config_binariesdir = None'''
self.__dict__["dirty"] = list()
def init_config(self, session, secret_key, cli):
@@ -288,19 +268,19 @@ class ConfigSQL(object):
def list_denied_tags(self):
mct = self.config_denied_tags or ""
- return [t.strip() for t in mct.split(",")]
+ return [strip_whitespaces(t) for t in mct.split(",")]
def list_allowed_tags(self):
mct = self.config_allowed_tags or ""
- return [t.strip() for t in mct.split(",")]
+ return [strip_whitespaces(t) for t in mct.split(",")]
def list_denied_column_values(self):
mct = self.config_denied_column_value or ""
- return [t.strip() for t in mct.split(",")]
+ return [strip_whitespaces(t) for t in mct.split(",")]
def list_allowed_column_values(self):
mct = self.config_allowed_column_value or ""
- return [t.strip() for t in mct.split(",")]
+ return [strip_whitespaces(t) for t in mct.split(",")]
def get_log_level(self):
return logger.get_level_name(self.config_log_level)
@@ -372,7 +352,7 @@ class ConfigSQL(object):
db_file = os.path.join(self.config_calibre_dir, 'metadata.db')
have_metadata_db = os.path.isfile(db_file)
self.db_configured = have_metadata_db
- # constants.EXTENSIONS_UPLOAD = [x.lstrip().rstrip().lower() for x in self.config_upload_formats.split(',')]
+
from . import cli_param
if os.environ.get('FLASK_DEBUG'):
logfile = logger.setup(logger.LOG_TO_STDOUT, logger.logging.DEBUG)
@@ -425,11 +405,13 @@ class ConfigSQL(object):
return self.config_calibre_split_dir if self.config_calibre_split_dir else self.config_calibre_dir
def store_calibre_uuid(self, calibre_db, Library_table):
+ from . import app
try:
- calibre_uuid = calibre_db.session.query(Library_table).one_or_none()
- if self.config_calibre_uuid != calibre_uuid.uuid:
- self.config_calibre_uuid = calibre_uuid.uuid
- self.save()
+ with app.app_context():
+ calibre_uuid = calibre_db.session.query(Library_table).one_or_none()
+ if self.config_calibre_uuid != calibre_uuid.uuid:
+ self.config_calibre_uuid = calibre_uuid.uuid
+ self.save()
except AttributeError:
pass
@@ -503,6 +485,8 @@ def autodetect_calibre_binaries():
"C:\\program files(x86)\\calibre\\",
"C:\\program files(x86)\\calibre2\\",
"C:\\program files\\calibre2\\"]
+ elif sys.platform.startswith("freebsd"):
+ calibre_path = ["/usr/local/bin/"]
else:
calibre_path = ["/opt/calibre/"]
for element in calibre_path:
@@ -533,6 +517,8 @@ def autodetect_unrar_binary():
if sys.platform == "win32":
calibre_path = ["C:\\program files\\WinRar\\unRAR.exe",
"C:\\program files(x86)\\WinRar\\unRAR.exe"]
+ elif sys.platform.startswith("freebsd"):
+ calibre_path = ["/usr/local/bin/unrar"]
else:
calibre_path = ["/usr/bin/unrar"]
for element in calibre_path:
@@ -545,6 +531,8 @@ def autodetect_kepubify_binary():
if sys.platform == "win32":
calibre_path = ["C:\\program files\\kepubify\\kepubify-windows-64Bit.exe",
"C:\\program files(x86)\\kepubify\\kepubify-windows-64Bit.exe"]
+ elif sys.platform.startswith("freebsd"):
+ calibre_path = ["/usr/local/bin/kepubify"]
else:
calibre_path = ["/opt/kepubify/kepubify-linux-64bit", "/opt/kepubify/kepubify-linux-32bit"]
for element in calibre_path:
diff --git a/cps/constants.py b/cps/constants.py
index 13146845..48b5a106 100644
--- a/cps/constants.py
+++ b/cps/constants.py
@@ -19,9 +19,6 @@
import sys
import os
from collections import namedtuple
-from sqlalchemy import __version__ as sql_version
-
-sqlalchemy_version2 = ([int(x) for x in sql_version.split('.')] >= [2, 0, 0])
# APP_MODE - production, development, or test
APP_MODE = os.environ.get('APP_MODE', 'production')
@@ -175,7 +172,7 @@ BookMeta = namedtuple('BookMeta', 'file_path, extension, title, author, cover, d
'series_id, languages, publisher, pubdate, identifiers')
# python build process likes to have x.y.zbw -> b for beta and w a counting number
-STABLE_VERSION = {'version': '0.6.23b'}
+STABLE_VERSION = '0.6.25b'
NIGHTLY_VERSION = dict()
NIGHTLY_VERSION[0] = '$Format:%H$'
@@ -193,7 +190,7 @@ THUMBNAIL_TYPE_AUTHOR = 3
COVER_THUMBNAIL_ORIGINAL = 0
COVER_THUMBNAIL_SMALL = 1
COVER_THUMBNAIL_MEDIUM = 2
-COVER_THUMBNAIL_LARGE = 3
+COVER_THUMBNAIL_LARGE = 4
# clean-up the module namespace
del sys, os, namedtuple
diff --git a/cps/cover.py b/cps/cover.py
index 5dd29534..6c42d73e 100644
--- a/cps/cover.py
+++ b/cps/cover.py
@@ -29,13 +29,14 @@ NO_JPEG_EXTENSIONS = ['.png', '.webp', '.bmp']
COVER_EXTENSIONS = ['.png', '.webp', '.bmp', '.jpg', '.jpeg']
-def cover_processing(tmp_file_name, img, extension):
- tmp_cover_name = os.path.join(os.path.dirname(tmp_file_name), 'cover.jpg')
+def cover_processing(tmp_file_path, img, extension):
+ # tmp_cover_name = os.path.join(os.path.dirname(tmp_file_name), 'cover.jpg')
+ tmp_cover_name = tmp_file_path + '.jpg'
if extension in NO_JPEG_EXTENSIONS:
if use_IM:
with Image(blob=img) as imgc:
imgc.format = 'jpeg'
- imgc.transform_colorspace('rgb')
+ imgc.transform_colorspace('srgb')
imgc.save(filename=tmp_cover_name)
return tmp_cover_name
else:
diff --git a/cps/cw_advocate/__init__.py b/cps/cw_advocate/__init__.py
new file mode 100644
index 00000000..58407b7b
--- /dev/null
+++ b/cps/cw_advocate/__init__.py
@@ -0,0 +1,22 @@
+#
+# Copyright 2015 Jordan Milne
+#
+# 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.
+#
+# Source: https://github.com/JordanMilne/Advocate
+
+
+from .adapters import ValidatingHTTPAdapter
+from .api import *
+from .addrvalidator import AddrValidator
+from .exceptions import UnacceptableAddressException
diff --git a/cps/cw_advocate/adapters.py b/cps/cw_advocate/adapters.py
new file mode 100644
index 00000000..b15a141d
--- /dev/null
+++ b/cps/cw_advocate/adapters.py
@@ -0,0 +1,48 @@
+#
+# Copyright 2015 Jordan Milne
+#
+# 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.
+#
+# Source: https://github.com/JordanMilne/Advocate
+
+from requests.adapters import HTTPAdapter, DEFAULT_POOLBLOCK
+
+from .addrvalidator import AddrValidator
+from .exceptions import ProxyDisabledException
+from .poolmanager import ValidatingPoolManager
+
+
+class ValidatingHTTPAdapter(HTTPAdapter):
+ __attrs__ = HTTPAdapter.__attrs__ + ['_validator']
+
+ def __init__(self, *args, **kwargs):
+ self._validator = kwargs.pop('validator', None)
+ if not self._validator:
+ self._validator = AddrValidator()
+ super().__init__(*args, **kwargs)
+
+ def init_poolmanager(self, connections, maxsize, block=DEFAULT_POOLBLOCK,
+ **pool_kwargs):
+ self._pool_connections = connections
+ self._pool_maxsize = maxsize
+ self._pool_block = block
+ self.poolmanager = ValidatingPoolManager(
+ num_pools=connections,
+ maxsize=maxsize,
+ block=block,
+ validator=self._validator,
+ **pool_kwargs
+ )
+
+ def proxy_manager_for(self, proxy, **proxy_kwargs):
+ raise ProxyDisabledException("Proxies cannot be used with Advocate")
diff --git a/cps/cw_advocate/addrvalidator.py b/cps/cw_advocate/addrvalidator.py
new file mode 100644
index 00000000..0f14ce85
--- /dev/null
+++ b/cps/cw_advocate/addrvalidator.py
@@ -0,0 +1,281 @@
+#
+# Copyright 2015 Jordan Milne
+#
+# 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.
+#
+# Source: https://github.com/JordanMilne/Advocate
+
+import functools
+import fnmatch
+import ipaddress
+import re
+
+try:
+ import netifaces
+ HAVE_NETIFACES = True
+except ImportError:
+ netifaces = None
+ HAVE_NETIFACES = False
+
+from .exceptions import NameserverException, ConfigException
+
+
+def canonicalize_hostname(hostname):
+ """Lowercase and punycodify a hostname"""
+ # We do the lowercasing after IDNA encoding because we only want to
+ # lowercase the *ASCII* chars.
+ # TODO: The differences between IDNA2003 and IDNA2008 might be relevant
+ # to us, but both specs are damn confusing.
+ return str(hostname.encode("idna").lower(), 'utf-8')
+
+
+def determine_local_addresses():
+ """Get all IPs that refer to this machine according to netifaces"""
+ if not HAVE_NETIFACES:
+ raise ConfigException("Tried to determine local addresses, "
+ "but netifaces module was not importable")
+ ips = []
+ for interface in netifaces.interfaces():
+ if_families = netifaces.ifaddresses(interface)
+ for family_kind in {netifaces.AF_INET, netifaces.AF_INET6}:
+ addrs = if_families.get(family_kind, [])
+ for addr in (x.get("addr", "") for x in addrs):
+ if family_kind == netifaces.AF_INET6:
+ # We can't do anything sensible with the scope here
+ addr = addr.split("%")[0]
+ ips.append(ipaddress.ip_network(addr))
+ return ips
+
+
+def add_local_address_arg(func):
+ """Add the "_local_addresses" kwarg if it's missing
+
+ IMO this information shouldn't be cached between calls (what if one of the
+ adapters got a new IP at runtime?,) and we don't want each function to
+ recalculate it. Just recalculate it if the caller didn't provide it for us.
+ """
+ @functools.wraps(func)
+ def wrapper(self, *args, **kwargs):
+ if "_local_addresses" not in kwargs:
+ if self.autodetect_local_addresses:
+ kwargs["_local_addresses"] = determine_local_addresses()
+ else:
+ kwargs["_local_addresses"] = []
+ return func(self, *args, **kwargs)
+ return wrapper
+
+
+class AddrValidator:
+ _6TO4_RELAY_NET = ipaddress.ip_network("192.88.99.0/24")
+ # Just the well known prefix, DNS64 servers can set their own
+ # prefix, but in practice most probably don't.
+ _DNS64_WK_PREFIX = ipaddress.ip_network("64:ff9b::/96")
+ DEFAULT_PORT_WHITELIST = {80, 8080, 443, 8443, 8000}
+
+ def __init__(
+ self,
+ ip_blacklist=None,
+ ip_whitelist=None,
+ port_whitelist=None,
+ port_blacklist=None,
+ hostname_blacklist=None,
+ allow_ipv6=False,
+ allow_teredo=False,
+ allow_6to4=False,
+ allow_dns64=False,
+ # Must be explicitly set to "False" if you don't want to try
+ # detecting local interface addresses with netifaces.
+ autodetect_local_addresses=True,
+ ):
+ if not port_blacklist and not port_whitelist:
+ # An assortment of common HTTPS? ports.
+ port_whitelist = self.DEFAULT_PORT_WHITELIST.copy()
+ self.ip_blacklist = ip_blacklist or set()
+ self.ip_whitelist = ip_whitelist or set()
+ self.port_blacklist = port_blacklist or set()
+ self.port_whitelist = port_whitelist or set()
+ # TODO: ATM this can contain either regexes or globs that are converted
+ # to regexes upon every check. Create a collection that automagically
+ # converts them to regexes on insert?
+ self.hostname_blacklist = hostname_blacklist or set()
+ self.allow_ipv6 = allow_ipv6
+ self.allow_teredo = allow_teredo
+ self.allow_6to4 = allow_6to4
+ self.allow_dns64 = allow_dns64
+ self.autodetect_local_addresses = autodetect_local_addresses
+
+ @add_local_address_arg
+ def is_ip_allowed(self, addr_ip, _local_addresses=None):
+ if not isinstance(addr_ip,
+ (ipaddress.IPv4Address, ipaddress.IPv6Address)):
+ addr_ip = ipaddress.ip_address(addr_ip)
+
+ # The whitelist should take precedence over the blacklist so we can
+ # punch holes in blacklisted ranges
+ if any(addr_ip in net for net in self.ip_whitelist):
+ return True
+
+ if any(addr_ip in net for net in self.ip_blacklist):
+ return False
+
+ if any(addr_ip in net for net in _local_addresses):
+ return False
+
+ if addr_ip.version == 4:
+ if not addr_ip.is_private:
+ # IPs for carrier-grade NAT. Seems weird that it doesn't set
+ # `is_private`, but we need to check `not is_global`
+ if not ipaddress.ip_network(addr_ip).is_global:
+ return False
+ elif addr_ip.version == 6:
+ # You'd better have a good reason for enabling IPv6
+ # because Advocate's techniques don't work well without NAT.
+ if not self.allow_ipv6:
+ return False
+
+ # v6 addresses can also map to IPv4 addresses! Tricky!
+ v4_nested = []
+ if addr_ip.ipv4_mapped:
+ v4_nested.append(addr_ip.ipv4_mapped)
+ # WTF IPv6? Why you gotta have a billion tunneling mechanisms?
+ # XXX: Do we even really care about these? If we're tunneling
+ # through public servers we shouldn't be able to access
+ # addresses on our private network, right?
+ if addr_ip.sixtofour:
+ if not self.allow_6to4:
+ return False
+ v4_nested.append(addr_ip.sixtofour)
+ if addr_ip.teredo:
+ if not self.allow_teredo:
+ return False
+ # Check both the client *and* server IPs
+ v4_nested.extend(addr_ip.teredo)
+ if addr_ip in self._DNS64_WK_PREFIX:
+ if not self.allow_dns64:
+ return False
+ # When using the well-known prefix the last 4 bytes
+ # are the IPv4 addr
+ v4_nested.append(ipaddress.ip_address(addr_ip.packed[-4:]))
+
+ if not all(self.is_ip_allowed(addr_v4) for addr_v4 in v4_nested):
+ return False
+
+ # fec0::*, apparently deprecated?
+ if addr_ip.is_site_local:
+ return False
+ else:
+ raise ValueError("Unsupported IP version(?): %r" % addr_ip)
+
+ # 169.254.XXX.XXX, AWS uses these for autoconfiguration
+ if addr_ip.is_link_local:
+ return False
+ # 127.0.0.1, ::1, etc.
+ if addr_ip.is_loopback:
+ return False
+ if addr_ip.is_multicast:
+ return False
+ # 192.168.XXX.XXX, 10.XXX.XXX.XXX
+ if addr_ip.is_private:
+ return False
+ # 255.255.255.255, ::ffff:XXXX:XXXX (v6->v4) mapping
+ if addr_ip.is_reserved:
+ return False
+ # There's no reason to connect directly to a 6to4 relay
+ if addr_ip in self._6TO4_RELAY_NET:
+ return False
+ # 0.0.0.0
+ if addr_ip.is_unspecified:
+ return False
+
+ # It doesn't look bad, so... it's must be ok!
+ return True
+
+ def _hostname_matches_pattern(self, hostname, pattern):
+ # If they specified a string, just assume they only want basic globbing.
+ # This stops people from not realizing they're dealing in REs and
+ # not escaping their periods unless they specifically pass in an RE.
+ # This has the added benefit of letting us sanely handle globbed
+ # IDNs by default.
+ if isinstance(pattern, str):
+ # convert the glob to a punycode glob, then a regex
+ pattern = fnmatch.translate(canonicalize_hostname(pattern))
+
+ hostname = canonicalize_hostname(hostname)
+ # Down the line the hostname may get treated as a null-terminated string
+ # (as with `socket.getaddrinfo`.) Try to account for that.
+ #
+ # >>> socket.getaddrinfo("example.com\x00aaaa", 80)
+ # [(2, 1, 6, '', ('93.184.216.34', 80)), [...]
+ no_null_hostname = hostname.split("\x00")[0]
+
+ return any(re.match(pattern, x.strip(".")) for x
+ in (no_null_hostname, hostname))
+
+ def is_hostname_allowed(self, hostname):
+ # Sometimes (like with "external" services that your IP has privileged
+ # access to) you might not always know the IP range to blacklist access
+ # to, or the `A` record might change without you noticing.
+ # For e.x.: `foocorp.external.org`.
+ #
+ # Another option is doing something like:
+ #
+ # for addrinfo in socket.getaddrinfo("foocorp.external.org", 80):
+ # global_validator.ip_blacklist.add(ip_address(addrinfo[4][0]))
+ #
+ # but that's not always a good idea if they're behind a third-party lb.
+ for pattern in self.hostname_blacklist:
+ if self._hostname_matches_pattern(hostname, pattern):
+ return False
+ return True
+
+ @add_local_address_arg
+ def is_addrinfo_allowed(self, addrinfo, _local_addresses=None):
+ assert(len(addrinfo) == 5)
+ # XXX: Do we care about any of the other elements? Guessing not.
+ family, socktype, proto, canonname, sockaddr = addrinfo
+
+ # The 4th elem inaddrinfo may either be a touple of two or four items,
+ # depending on whether we're dealing with IPv4 or v6
+ if len(sockaddr) == 2:
+ # v4
+ ip, port = sockaddr
+ elif len(sockaddr) == 4:
+ # v6
+ # XXX: what *are* `flow_info` and `scope_id`? Anything useful?
+ # Seems like we can figure out all we need about the scope from
+ # the `is_` properties.
+ ip, port, flow_info, scope_id = sockaddr
+ else:
+ raise ValueError("Unexpected addrinfo format %r" % sockaddr)
+
+ # Probably won't help protect against SSRF, but might prevent our being
+ # used to attack others' non-HTTP services. See
+ # http://www.remote.org/jochen/sec/hfpa/
+ if self.port_whitelist and port not in self.port_whitelist:
+ return False
+ if port in self.port_blacklist:
+ return False
+
+ if self.hostname_blacklist:
+ if not canonname:
+ raise NameserverException(
+ "addrinfo must contain the canon name to do blacklisting "
+ "based on hostname. Make sure you use the "
+ "`socket.AI_CANONNAME` flag, and that each record contains "
+ "the canon name. Your DNS server might also be garbage."
+ )
+
+ if not self.is_hostname_allowed(canonname):
+ return False
+
+ return self.is_ip_allowed(ip, _local_addresses=_local_addresses)
diff --git a/cps/cw_advocate/api.py b/cps/cw_advocate/api.py
new file mode 100644
index 00000000..5a5ac203
--- /dev/null
+++ b/cps/cw_advocate/api.py
@@ -0,0 +1,202 @@
+#
+# Copyright 2015 Jordan Milne
+#
+# 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.
+#
+# Source: https://github.com/JordanMilne/Advocate
+
+"""
+advocate.api
+~~~~~~~~~~~~
+
+This module implements the Requests API, largely a copy/paste from `requests`
+itself.
+
+:copyright: (c) 2015 by Jordan Milne.
+:license: Apache2, see LICENSE for more details.
+
+"""
+from collections import OrderedDict
+import hashlib
+import pickle
+
+from requests import Session as RequestsSession
+
+# import cw_advocate
+from .adapters import ValidatingHTTPAdapter
+from .exceptions import MountDisabledException
+
+
+class Session(RequestsSession):
+ """Convenience wrapper around `requests.Session` set up for `advocate`ing"""
+
+ __attrs__ = RequestsSession.__attrs__ + ["validator"]
+ DEFAULT_VALIDATOR = None
+ """
+ User-replaceable default validator to use for all Advocate sessions,
+ includes sessions created by advocate.get()
+ """
+
+ def __init__(self, *args, **kwargs):
+ self.validator = kwargs.pop("validator", None) or self.DEFAULT_VALIDATOR
+ adapter_kwargs = kwargs.pop("_adapter_kwargs", {})
+
+ # `Session.__init__()` calls `mount()` internally, so we need to allow
+ # it temporarily
+ self.__mount_allowed = True
+ RequestsSession.__init__(self, *args, **kwargs)
+
+ # Drop any existing adapters
+ self.adapters = OrderedDict()
+
+ self.mount("http://", ValidatingHTTPAdapter(validator=self.validator, **adapter_kwargs))
+ self.mount("https://", ValidatingHTTPAdapter(validator=self.validator, **adapter_kwargs))
+ self.__mount_allowed = False
+
+ def mount(self, *args, **kwargs):
+ """Wrapper around `mount()` to prevent a protection bypass"""
+ if self.__mount_allowed:
+ super().mount(*args, **kwargs)
+ else:
+ raise MountDisabledException(
+ "mount() is disabled to prevent protection bypasses"
+ )
+
+
+def session(*args, **kwargs):
+ return Session(*args, **kwargs)
+
+
+def request(method, url, **kwargs):
+ """Constructs and sends a :class:`Request `.
+
+ :param method: method for the new :class:`Request` object.
+ :param url: URL for the new :class:`Request` object.
+ :param params: (optional) Dictionary or bytes to be sent in the query string for the :class:`Request`.
+ :param data: (optional) Dictionary, bytes, or file-like object to send in the body of the :class:`Request`.
+ :param json: (optional) json data to send in the body of the :class:`Request`.
+ :param headers: (optional) Dictionary of HTTP Headers to send with the :class:`Request`.
+ :param cookies: (optional) Dict or CookieJar object to send with the :class:`Request`.
+ :param files: (optional) Dictionary of ``'name': file-like-objects`` (or ``{'name': ('filename', fileobj)}``) for multipart encoding upload.
+ :param auth: (optional) Auth tuple to enable Basic/Digest/Custom HTTP Auth.
+ :param timeout: (optional) How long to wait for the server to send data
+ before giving up, as a float, or a (`connect timeout, read timeout
+ `_) tuple.
+ :type timeout: float or tuple
+ :param allow_redirects: (optional) Boolean. Set to True if POST/PUT/DELETE redirect following is allowed.
+ :type allow_redirects: bool
+ :param proxies: (optional) Dictionary mapping protocol to the URL of the proxy.
+ :param verify: (optional) if ``True``, the SSL cert will be verified. A CA_BUNDLE path can also be provided.
+ :param stream: (optional) if ``False``, the response content will be immediately downloaded.
+ :param cert: (optional) if String, path to ssl client cert file (.pem). If Tuple, ('cert', 'key') pair.
+ :return: :class:`Response ` object
+ :rtype: requests.Response
+ """
+
+ validator = kwargs.pop("validator", None)
+ with Session(validator=validator) as sess:
+ response = sess.request(method=method, url=url, **kwargs)
+ return response
+
+
+def get(url, **kwargs):
+ """Sends a GET request.
+
+ :param url: URL for the new :class:`Request` object.
+ :param **kwargs: Optional arguments that ``request`` takes.
+ :return: :class:`Response ` object
+ :rtype: requests.Response
+ """
+
+ kwargs.setdefault('allow_redirects', True)
+ return request('get', url, **kwargs)
+
+
+class RequestsAPIWrapper:
+ """Provides a `requests.api`-like interface with a specific validator"""
+
+ # Due to how the classes are dynamically constructed pickling may not work
+ # correctly unless loaded within the same interpreter instance.
+ # Enable at your peril.
+ SUPPORT_WRAPPER_PICKLING = False
+
+ def __init__(self, validator):
+ # Do this here to avoid circular import issues
+ try:
+ from .futures import FuturesSession
+ have_requests_futures = True
+ except ImportError as e:
+ have_requests_futures = False
+
+ self.validator = validator
+ outer_self = self
+
+ class _WrappedSession(Session):
+ """An `advocate.Session` that uses the wrapper's blacklist
+
+ the wrapper is meant to be a transparent replacement for `requests`,
+ so people should be able to subclass `wrapper.Session` and still
+ get the desired validation behaviour
+ """
+ DEFAULT_VALIDATOR = outer_self.validator
+
+ self._make_wrapper_cls_global(_WrappedSession)
+
+ if have_requests_futures:
+
+ class _WrappedFuturesSession(FuturesSession):
+ """Like _WrappedSession, but for `FuturesSession`s"""
+ DEFAULT_VALIDATOR = outer_self.validator
+ self._make_wrapper_cls_global(_WrappedFuturesSession)
+
+ self.FuturesSession = _WrappedFuturesSession
+
+ self.request = self._default_arg_wrapper(request)
+ self.get = self._default_arg_wrapper(get)
+ self.Session = _WrappedSession
+
+ def __getattr__(self, item):
+ # This class is meant to mimic the requests base module, so if we don't
+ # have this attribute, it might be on the base module (like the Request
+ # class, etc.)
+ try:
+ return object.__getattribute__(self, item)
+ except AttributeError:
+ from . import cw_advocate
+ return getattr(cw_advocate, item)
+
+ def _default_arg_wrapper(self, fun):
+ def wrapped_func(*args, **kwargs):
+ kwargs.setdefault("validator", self.validator)
+ return fun(*args, **kwargs)
+ return wrapped_func
+
+ def _make_wrapper_cls_global(self, cls):
+ if not self.SUPPORT_WRAPPER_PICKLING:
+ return
+ # Gnarly, but necessary to give pickle a consistent module-level
+ # reference for each wrapper.
+ wrapper_hash = hashlib.sha256(pickle.dumps(self)).hexdigest()
+ cls.__name__ = "_".join((cls.__name__, wrapper_hash))
+ cls.__qualname__ = ".".join((__name__, cls.__name__))
+ if not globals().get(cls.__name__):
+ globals()[cls.__name__] = cls
+
+
+__all__ = (
+ "get",
+ "request",
+ "session",
+ "Session",
+ "RequestsAPIWrapper",
+)
diff --git a/cps/cw_advocate/connection.py b/cps/cw_advocate/connection.py
new file mode 100644
index 00000000..ce790ada
--- /dev/null
+++ b/cps/cw_advocate/connection.py
@@ -0,0 +1,201 @@
+#
+# Copyright 2015 Jordan Milne
+#
+# 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.
+#
+# Source: https://github.com/JordanMilne/Advocate
+
+import ipaddress
+import socket
+from socket import timeout as SocketTimeout
+
+from urllib3.connection import HTTPSConnection, HTTPConnection
+from urllib3.exceptions import ConnectTimeoutError
+from urllib3.util.connection import _set_socket_options
+from urllib3.util.connection import create_connection as old_create_connection
+
+from . import addrvalidator
+from .exceptions import UnacceptableAddressException
+
+
+def advocate_getaddrinfo(host, port, get_canonname=False):
+ addrinfo = socket.getaddrinfo(
+ host,
+ port,
+ 0,
+ socket.SOCK_STREAM,
+ 0,
+ # We need what the DNS client sees the hostname as, correctly handles
+ # IDNs and tricky things like `private.foocorp.org\x00.google.com`.
+ # All IDNs will be converted to punycode.
+ socket.AI_CANONNAME if get_canonname else 0,
+ )
+ return fix_addrinfo(addrinfo)
+
+
+def fix_addrinfo(records):
+ """
+ Propagate the canonname across records and parse IPs
+
+ I'm not sure if this is just the behaviour of `getaddrinfo` on Linux, but
+ it seems like only the first record in the set has the canonname field
+ populated.
+ """
+ def fix_record(record, canonname):
+ sa = record[4]
+ sa = (ipaddress.ip_address(sa[0]),) + sa[1:]
+ return record[0], record[1], record[2], canonname, sa
+
+ canonname = None
+ if records:
+ # Apparently the canonical name is only included in the first record?
+ # Add it to all of them.
+ assert(len(records[0]) == 5)
+ canonname = records[0][3]
+ return tuple(fix_record(x, canonname) for x in records)
+
+
+# Lifted from requests' urllib3, which in turn lifted it from `socket.py`. Oy!
+def validating_create_connection(address,
+ timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
+ source_address=None, socket_options=None,
+ validator=None):
+ """Connect to *address* and return the socket object.
+
+ Convenience function. Connect to *address* (a 2-tuple ``(host,
+ port)``) and return the socket object. Passing the optional
+ *timeout* parameter will set the timeout on the socket instance
+ before attempting to connect. If no *timeout* is supplied, the
+ global default timeout setting returned by :func:`getdefaulttimeout`
+ is used. If *source_address* is set it must be a tuple of (host, port)
+ for the socket to bind as a source address before making the connection.
+ An host of '' or port 0 tells the OS to use the default.
+ """
+
+ host, port = address
+ # We can skip asking for the canon name if we're not doing hostname-based
+ # blacklisting.
+ need_canonname = False
+ if validator.hostname_blacklist:
+ need_canonname = True
+ # We check both the non-canonical and canonical hostnames so we can
+ # catch both of these:
+ # CNAME from nonblacklisted.com -> blacklisted.com
+ # CNAME from blacklisted.com -> nonblacklisted.com
+ if not validator.is_hostname_allowed(host):
+ raise UnacceptableAddressException(host)
+
+ err = None
+ addrinfo = advocate_getaddrinfo(host, port, get_canonname=need_canonname)
+ if addrinfo:
+ if validator.autodetect_local_addresses:
+ local_addresses = addrvalidator.determine_local_addresses()
+ else:
+ local_addresses = []
+ for res in addrinfo:
+ # Are we allowed to connect with this result?
+ if not validator.is_addrinfo_allowed(
+ res,
+ _local_addresses=local_addresses,
+ ):
+ continue
+ af, socktype, proto, canonname, sa = res
+ # Unparse the validated IP
+ sa = (sa[0].exploded,) + sa[1:]
+ sock = None
+ try:
+ sock = socket.socket(af, socktype, proto)
+
+ # If provided, set socket level options before connecting.
+ # This is the only addition urllib3 makes to this function.
+ _set_socket_options(sock, socket_options)
+
+ if timeout is not socket._GLOBAL_DEFAULT_TIMEOUT:
+ sock.settimeout(timeout)
+ if source_address:
+ sock.bind(source_address)
+ sock.connect(sa)
+ return sock
+
+ except socket.error as _:
+ err = _
+ if sock is not None:
+ sock.close()
+ sock = None
+
+ if err is None:
+ # If we got here, none of the results were acceptable
+ err = UnacceptableAddressException(address)
+ if err is not None:
+ raise err
+ else:
+ raise socket.error("getaddrinfo returns an empty list")
+
+
+# TODO: Is there a better way to add this to multiple classes with different
+# base classes? I tried a mixin, but it used the base method instead.
+def _validating_new_conn(self):
+ """ Establish a socket connection and set nodelay settings on it.
+
+ :return: New socket connection.
+ """
+ extra_kw = {}
+ if self.source_address:
+ extra_kw['source_address'] = self.source_address
+
+ if self.socket_options:
+ extra_kw['socket_options'] = self.socket_options
+
+ try:
+ # Hack around HTTPretty's patched sockets
+ # TODO: some better method of hacking around it that checks if we
+ # _would have_ connected to a private addr?
+ conn_func = validating_create_connection
+ if socket.getaddrinfo.__module__.startswith("httpretty"):
+ conn_func = old_create_connection
+ else:
+ extra_kw["validator"] = self._validator
+
+ conn = conn_func(
+ (self.host, self.port),
+ self.timeout,
+ **extra_kw
+ )
+
+ except SocketTimeout:
+ raise ConnectTimeoutError(
+ self, "Connection to %s timed out. (connect timeout=%s)" %
+ (self.host, self.timeout))
+
+ return conn
+
+
+# Don't silently break if the private API changes across urllib3 versions
+assert(hasattr(HTTPConnection, '_new_conn'))
+assert(hasattr(HTTPSConnection, '_new_conn'))
+
+
+class ValidatingHTTPConnection(HTTPConnection):
+ _new_conn = _validating_new_conn
+
+ def __init__(self, *args, **kwargs):
+ self._validator = kwargs.pop("validator")
+ HTTPConnection.__init__(self, *args, **kwargs)
+
+
+class ValidatingHTTPSConnection(HTTPSConnection):
+ _new_conn = _validating_new_conn
+
+ def __init__(self, *args, **kwargs):
+ self._validator = kwargs.pop("validator")
+ HTTPSConnection.__init__(self, *args, **kwargs)
diff --git a/cps/cw_advocate/connectionpool.py b/cps/cw_advocate/connectionpool.py
new file mode 100644
index 00000000..3bbbfac7
--- /dev/null
+++ b/cps/cw_advocate/connectionpool.py
@@ -0,0 +1,39 @@
+#
+# Copyright 2015 Jordan Milne
+#
+# 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.
+#
+# Source: https://github.com/JordanMilne/Advocate
+
+from urllib3 import HTTPConnectionPool, HTTPSConnectionPool
+
+from .connection import (
+ ValidatingHTTPConnection,
+ ValidatingHTTPSConnection,
+)
+
+# Don't silently break if the private API changes across urllib3 versions
+assert(hasattr(HTTPConnectionPool, 'ConnectionCls'))
+assert(hasattr(HTTPSConnectionPool, 'ConnectionCls'))
+assert(hasattr(HTTPConnectionPool, 'scheme'))
+assert(hasattr(HTTPSConnectionPool, 'scheme'))
+
+
+class ValidatingHTTPConnectionPool(HTTPConnectionPool):
+ scheme = 'http'
+ ConnectionCls = ValidatingHTTPConnection
+
+
+class ValidatingHTTPSConnectionPool(HTTPSConnectionPool):
+ scheme = 'https'
+ ConnectionCls = ValidatingHTTPSConnection
diff --git a/cps/cw_advocate/exceptions.py b/cps/cw_advocate/exceptions.py
new file mode 100644
index 00000000..5ff9852b
--- /dev/null
+++ b/cps/cw_advocate/exceptions.py
@@ -0,0 +1,39 @@
+#
+# Copyright 2015 Jordan Milne
+#
+# 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.
+#
+# Source: https://github.com/JordanMilne/Advocate
+
+class AdvocateException(Exception):
+ pass
+
+
+class UnacceptableAddressException(AdvocateException):
+ pass
+
+
+class NameserverException(AdvocateException):
+ pass
+
+
+class MountDisabledException(AdvocateException):
+ pass
+
+
+class ProxyDisabledException(NotImplementedError, AdvocateException):
+ pass
+
+
+class ConfigException(AdvocateException):
+ pass
diff --git a/cps/cw_advocate/poolmanager.py b/cps/cw_advocate/poolmanager.py
new file mode 100644
index 00000000..d912d65d
--- /dev/null
+++ b/cps/cw_advocate/poolmanager.py
@@ -0,0 +1,61 @@
+#
+# Copyright 2015 Jordan Milne
+#
+# 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.
+#
+# Source: https://github.com/JordanMilne/Advocate
+
+import collections
+import functools
+
+from urllib3 import PoolManager
+from urllib3.poolmanager import _default_key_normalizer, PoolKey
+
+from .connectionpool import (
+ ValidatingHTTPSConnectionPool,
+ ValidatingHTTPConnectionPool,
+)
+
+pool_classes_by_scheme = {
+ "http": ValidatingHTTPConnectionPool,
+ "https": ValidatingHTTPSConnectionPool,
+}
+
+AdvocatePoolKey = collections.namedtuple('AdvocatePoolKey',
+ PoolKey._fields + ('key_validator',))
+
+
+def key_normalizer(key_class, request_context):
+ request_context = request_context.copy()
+ # TODO: add ability to serialize validator rules to dict,
+ # allowing pool to be shared between sessions with the same
+ # rules.
+ request_context["validator"] = id(request_context["validator"])
+ return _default_key_normalizer(key_class, request_context)
+
+
+key_fn_by_scheme = {
+ 'http': functools.partial(key_normalizer, AdvocatePoolKey),
+ 'https': functools.partial(key_normalizer, AdvocatePoolKey),
+}
+
+
+class ValidatingPoolManager(PoolManager):
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+
+ # Make sure the API hasn't changed
+ assert (hasattr(self, 'pool_classes_by_scheme'))
+
+ self.pool_classes_by_scheme = pool_classes_by_scheme
+ self.key_fn_by_scheme = key_fn_by_scheme.copy()
diff --git a/cps/babel.py b/cps/cw_babel.py
similarity index 93%
rename from cps/babel.py
rename to cps/cw_babel.py
index cf043d52..878984f6 100644
--- a/cps/babel.py
+++ b/cps/cw_babel.py
@@ -34,7 +34,7 @@ def get_user_locale_language(user_language):
def get_available_locale():
- return [Locale('en')] + babel.list_translations()
+ return sorted(babel.list_translations(), key=lambda x: x.display_name.lower())
def get_available_translations():
diff --git a/cps/cw_login/login_manager.py b/cps/cw_login/login_manager.py
index 21dc803d..a3714af6 100644
--- a/cps/cw_login/login_manager.py
+++ b/cps/cw_login/login_manager.py
@@ -1,4 +1,5 @@
from datetime import datetime
+from datetime import timezone
from datetime import timedelta
import hashlib
@@ -496,7 +497,7 @@ class LoginManager:
duration = timedelta(seconds=duration)
try:
- expires = datetime.utcnow() + duration
+ expires = datetime.now(timezone.utc) + duration
except TypeError as e:
raise Exception(
"REMEMBER_COOKIE_DURATION must be a datetime.timedelta,"
diff --git a/cps/db.py b/cps/db.py
index 62b68b47..15921d7a 100644
--- a/cps/db.py
+++ b/cps/db.py
@@ -20,10 +20,11 @@
import os
import re
import json
-from datetime import datetime
+from datetime import datetime, timezone
from urllib.parse import quote
import unidecode
-from weakref import WeakSet
+# from weakref import WeakSet
+from uuid import uuid4
from sqlite3 import OperationalError as sqliteOperationalError
from sqlalchemy import create_engine
@@ -44,11 +45,11 @@ from sqlalchemy.ext.associationproxy import association_proxy
from .cw_login import current_user
from flask_babel import gettext as _
from flask_babel import get_locale
-from flask import flash
+from flask import flash, g, Flask
from . import logger, ub, isoLanguages
from .pagination import Pagination
-
+from .string_helper import strip_whitespaces
log = logger.create()
@@ -101,6 +102,16 @@ class Identifiers(Base):
type = Column(String(collation='NOCASE'), nullable=False, default="isbn")
val = Column(String(collation='NOCASE'), nullable=False)
book = Column(Integer, ForeignKey('books.id'), nullable=False)
+ amazon = {
+ "jp": "co.jp",
+ "uk": "co.uk",
+ "us": "com",
+ "au": "com.au",
+ "be": "com.be",
+ "br": "com.br",
+ "tr": "com.tr",
+ "mx": "com.mx",
+ }
def __init__(self, val, id_type, book):
super().__init__()
@@ -113,7 +124,11 @@ class Identifiers(Base):
if format_type == 'amazon':
return "Amazon"
elif format_type.startswith("amazon_"):
- return "Amazon.{0}".format(format_type[7:])
+ label_amazon = "Amazon.{0}"
+ country_code = format_type[7:].lower()
+ if country_code not in self.amazon:
+ return label_amazon.format(country_code)
+ return label_amazon.format(self.amazon[country_code])
elif format_type == "isbn":
return "ISBN"
elif format_type == "doi":
@@ -136,6 +151,8 @@ class Identifiers(Base):
return "ISSN"
elif format_type == "isfdb":
return "ISFDB"
+ elif format_type == "storygraph":
+ return "StoryGraph"
if format_type == "lubimyczytac":
return "Lubimyczytac"
if format_type == "databazeknih":
@@ -148,7 +165,11 @@ class Identifiers(Base):
if format_type == "amazon" or format_type == "asin":
return "https://amazon.com/dp/{0}".format(self.val)
elif format_type.startswith('amazon_'):
- return "https://amazon.{0}/dp/{1}".format(format_type[7:], self.val)
+ link_amazon = "https://amazon.{0}/dp/{1}"
+ country_code = format_type[7:].lower()
+ if country_code not in self.amazon:
+ return link_amazon.format(country_code, self.val)
+ return link_amazon.format(self.amazon[country_code], self.val)
elif format_type == "isbn":
return "https://www.worldcat.org/isbn/{0}".format(self.val)
elif format_type == "doi":
@@ -172,9 +193,11 @@ class Identifiers(Base):
elif format_type == "issn":
return "https://portal.issn.org/resource/ISSN/{0}".format(self.val)
elif format_type == "isfdb":
- return "http://www.isfdb.org/cgi-bin/pl.cgi?{0}".format(self.val)
+ return "https://www.isfdb.org/cgi-bin/pl.cgi?{0}".format(self.val)
elif format_type == "databazeknih":
return "https://www.databazeknih.cz/knihy/{0}".format(self.val)
+ elif format_type == "storygraph":
+ return "https://app.thestorygraph.com/books/{0}".format(self.val)
elif self.val.lower().startswith("javascript:"):
return quote(self.val)
elif self.val.lower().startswith("data:"):
@@ -378,10 +401,10 @@ class Books(Base):
title = Column(String(collation='NOCASE'), nullable=False, default='Unknown')
sort = Column(String(collation='NOCASE'))
author_sort = Column(String(collation='NOCASE'))
- timestamp = Column(TIMESTAMP, default=datetime.utcnow)
+ timestamp = Column(TIMESTAMP, default=lambda: datetime.now(timezone.utc))
pubdate = Column(TIMESTAMP, default=DEFAULT_PUBDATE)
series_index = Column(String, nullable=False, default="1.0")
- last_modified = Column(TIMESTAMP, default=datetime.utcnow)
+ last_modified = Column(TIMESTAMP, default=lambda: datetime.now(timezone.utc))
path = Column(String, default="", nullable=False)
has_cover = Column(Integer, default=0)
uuid = Column(String)
@@ -509,34 +532,25 @@ class AlchemyEncoder(json.JSONEncoder):
class CalibreDB:
- _init = False
- engine = None
config = None
- session_factory = None
- # This is a WeakSet so that references here don't keep other CalibreDB
- # instances alive once they reach the end of their respective scopes
- instances = WeakSet()
+ config_calibre_dir = None
+ app_db_path = None
- def __init__(self, expire_on_commit=True, init=False):
+ def __init__(self, _app: Flask=None): # , expire_on_commit=True, init=False):
""" Initialize a new CalibreDB session
"""
- self.session = None
- if init:
- self.init_db(expire_on_commit)
+ self.Session = None
+ #if init:
+ # self.init_db(expire_on_commit)
+ if _app is not None and not _app._got_first_request:
+ self.init_app(_app)
- def init_db(self, expire_on_commit=True):
- if self._init:
- self.init_session(expire_on_commit)
-
- self.instances.add(self)
-
- def init_session(self, expire_on_commit=True):
- self.session = self.session_factory()
- self.session.expire_on_commit = expire_on_commit
- self.update_title_sort(self.config)
+ def init_app(self, _app):
+ _app.teardown_appcontext(self.teardown)
@classmethod
def setup_db_cc_classes(cls, cc):
+ global cc_classes
cc_ids = []
books_custom_column_links = {}
for row in cc:
@@ -604,8 +618,6 @@ class CalibreDB:
secondary=books_custom_column_links[cc_id[0]],
backref='books'))
- return cc_classes
-
@classmethod
def check_valid_db(cls, config_calibre_dir, app_db_path, config_calibre_uuid):
if not config_calibre_dir:
@@ -625,7 +637,6 @@ class CalibreDB:
local_session = scoped_session(sessionmaker())
local_session.configure(bind=connection)
database_uuid = local_session().query(Library_Id).one_or_none()
- # local_session.dispose()
check_engine.connect()
db_change = config_calibre_uuid != database_uuid.uuid
@@ -633,13 +644,30 @@ class CalibreDB:
return False, False
return True, db_change
+ def teardown(self, exception):
+ ctx = g.get("lib_sql")
+ if ctx:
+ ctx.close()
+
+ @property
+ def session(self):
+ # connect or get active connection
+ if not g.get("lib_sql"):
+ g.lib_sql = self.connect()
+ return g.lib_sql
+
@classmethod
- def update_config(cls, config):
+ def update_config(cls, config, config_calibre_dir, app_db_path):
cls.config = config
+ cls.config_calibre_dir = config_calibre_dir
+ cls.app_db_path = app_db_path
+
+
+ def connect(self):
+ return self.setup_db(self.config_calibre_dir, self.app_db_path)
@classmethod
def setup_db(cls, config_calibre_dir, app_db_path):
- cls.dispose()
if not config_calibre_dir:
cls.config.invalidate()
@@ -651,16 +679,17 @@ class CalibreDB:
return None
try:
- cls.engine = create_engine('sqlite://',
+ engine = create_engine('sqlite://',
echo=False,
isolation_level="SERIALIZABLE",
connect_args={'check_same_thread': False},
poolclass=StaticPool)
- with cls.engine.begin() as connection:
+ with engine.begin() as connection:
+ connection.execute(text('PRAGMA cache_size = 10000;'))
connection.execute(text("attach database '{}' as calibre;".format(dbpath)))
connection.execute(text("attach database '{}' as app_settings;".format(app_db_path)))
- conn = cls.engine.connect()
+ conn = engine.connect()
# conn.text_factory = lambda b: b.decode(errors = 'ignore') possible fix for #1302
except Exception as ex:
cls.config.invalidate(ex)
@@ -676,13 +705,10 @@ class CalibreDB:
log.error_or_exception(e)
return None
- cls.session_factory = scoped_session(sessionmaker(autocommit=False,
- autoflush=True,
- bind=cls.engine, future=True))
- for inst in cls.instances:
- inst.init_session()
+ return scoped_session(sessionmaker(autocommit=False,
+ autoflush=False,
+ bind=engine, future=True))
- cls._init = True
def get_book(self, book_id):
return self.session.query(Books).filter(Books.id == book_id).first()
@@ -875,10 +901,12 @@ class CalibreDB:
authors_ordered = list()
# error = False
for auth in sort_authors:
- results = self.session.query(Authors).filter(Authors.sort == auth.lstrip().strip()).all()
+ auth = strip_whitespaces(auth)
+ results = self.session.query(Authors).filter(Authors.sort == auth).all()
# ToDo: How to handle not found author name
if not len(results):
- log.error("Author {} not found to display name in right order".format(auth.strip()))
+ book_id = entry.id if isinstance(entry, Books) else entry[0].id
+ log.error("Author '{}' of book {} not found to display name in right order".format(auth, book_id))
# error = True
break
for r in results:
@@ -900,7 +928,8 @@ class CalibreDB:
def get_typeahead(self, database, query, replace=('', ''), tag_filter=true()):
query = query or ''
- self.session.connection().connection.connection.create_function("lower", 1, lcase)
+ self.create_functions()
+ # self.session.connection().connection.connection.create_function("lower", 1, lcase)
entries = self.session.query(database).filter(tag_filter). \
filter(func.lower(database.name).ilike("%" + query + "%")).all()
# json_dumps = json.dumps([dict(name=escape(r.name.replace(*replace))) for r in entries])
@@ -908,7 +937,8 @@ class CalibreDB:
return json_dumps
def check_exists_book(self, authr, title):
- self.session.connection().connection.connection.create_function("lower", 1, lcase)
+ self.create_functions()
+ # self.session.connection().connection.connection.create_function("lower", 1, lcase)
q = list()
author_terms = re.split(r'\s*&\s*', authr)
for author_term in author_terms:
@@ -918,8 +948,9 @@ class CalibreDB:
.filter(and_(Books.authors.any(and_(*q)), func.lower(Books.title).ilike("%" + title + "%"))).first()
def search_query(self, term, config, *join):
- term.strip().lower()
- self.session.connection().connection.connection.create_function("lower", 1, lcase)
+ strip_whitespaces(term).lower()
+ self.create_functions()
+ # self.session.connection().connection.connection.create_function("lower", 1, lcase)
q = list()
author_terms = re.split("[, ]+", term)
for author_term in author_terms:
@@ -1017,7 +1048,7 @@ class CalibreDB:
lang.name = isoLanguages.get_language_name(get_locale(), lang.lang_code)
return sorted(languages, key=lambda x: x.name, reverse=reverse_order)
- def update_title_sort(self, config, conn=None):
+ def create_functions(self, config=None):
# user defined sort function for calibre databases (Series, etc.)
def _title_sort(title):
# calibre sort stuff
@@ -1026,56 +1057,27 @@ class CalibreDB:
if match:
prep = match.group(1)
title = title[len(prep):] + ', ' + prep
- return title.strip()
+ return strip_whitespaces(title)
try:
- # sqlalchemy <1.4.24
- conn = conn or self.session.connection().connection.driver_connection
+ # sqlalchemy <1.4.24 and sqlalchemy 2.0
+ conn = self.session.connection().connection.driver_connection
except AttributeError:
- # sqlalchemy >1.4.24 and sqlalchemy 2.0
- conn = conn or self.session.connection().connection.connection
+ # sqlalchemy >1.4.24
+ conn = self.session.connection().connection.connection
try:
- conn.create_function("title_sort", 1, _title_sort)
+ if config:
+ conn.create_function("title_sort", 1, _title_sort)
+ conn.create_function('uuid4', 0, lambda: str(uuid4()))
+ conn.create_function("lower", 1, lcase)
except sqliteOperationalError:
pass
- @classmethod
- def dispose(cls):
- # global session
-
- for inst in cls.instances:
- old_session = inst.session
- inst.session = None
- if old_session:
- try:
- old_session.close()
- except Exception:
- pass
- if old_session.bind:
- try:
- old_session.bind.dispose()
- except Exception:
- pass
-
- for attr in list(Books.__dict__.keys()):
- if attr.startswith("custom_column_"):
- setattr(Books, attr, None)
-
- for db_class in cc_classes.values():
- Base.metadata.remove(db_class.__table__)
- cc_classes.clear()
-
- for table in reversed(Base.metadata.sorted_tables):
- name = table.key
- if name.startswith("custom_column_") or name.startswith("books_custom_column_"):
- if table is not None:
- Base.metadata.remove(table)
-
def reconnect_db(self, config, app_db_path):
- self.dispose()
- self.engine.dispose()
+ # self.dispose()
+ # self.engine.dispose()
self.setup_db(config.config_calibre_dir, app_db_path)
- self.update_config(config)
+ self.update_config(config, config.config_calibre_dir, app_db_path)
def lcase(s):
diff --git a/cps/debug_info.py b/cps/debug_info.py
index 879846ab..66762e1c 100644
--- a/cps/debug_info.py
+++ b/cps/debug_info.py
@@ -23,10 +23,10 @@ import zipfile
import json
from io import BytesIO
from flask_babel.speaklater import LazyString
-
+from importlib.metadata import metadata
import os
-from flask import send_file, __version__
+from flask import send_file
from . import logger, config
from .about import collect_stats
@@ -49,7 +49,8 @@ def assemble_logfiles(file_name):
with open(f, 'rb') as fd:
shutil.copyfileobj(fd, wfd)
wfd.seek(0)
- if int(__version__.split('.')[0]) < 2:
+ version = metadata("flask")["Version"]
+ if int(version.split('.')[0]) < 2:
return send_file(wfd,
as_attachment=True,
attachment_filename=os.path.basename(file_name))
@@ -72,7 +73,8 @@ def send_debug():
for fp in file_list:
zf.write(fp, os.path.basename(fp))
memory_zip.seek(0)
- if int(__version__.split('.')[0]) < 2:
+ version = metadata("flask")["Version"]
+ if int(version.split('.')[0]) < 2:
return send_file(memory_zip,
as_attachment=True,
attachment_filename="Calibre-Web-debug-pack.zip")
diff --git a/cps/dep_check.py b/cps/dep_check.py
index b1917f7a..f1c290ad 100644
--- a/cps/dep_check.py
+++ b/cps/dep_check.py
@@ -39,8 +39,24 @@ def load_dependencies(optional=False):
with open(req_path, 'r') as f:
for line in f:
if not line.startswith('#') and not line == '\n' and not line.startswith('git'):
- res = re.match(r'(.*?)([<=>\s]+)([\d\.]+),?\s?([<=>\s]+)?([\d\.]+)?', line.strip())
+ res = re.match(r'(.*?)([<=>\s]+)([\d\.]+),?\s?([<=>\s]+)?([\d\.]+)?(?:\s?;\s?'
+ r'(?:(python_version)\s?([<=>]+)\s?\'([\d\.]+)\'|'
+ r'(sys_platform)\s?([\!=]+)\s?\'([\w]+)\'))?', line.strip())
try:
+ if res.group(7) and res.group(8):
+ val = res.group(8).split(".")
+ if not eval(str(sys.version_info[0]) + "." + "{:02d}".format(sys.version_info[1]) +
+ res.group(7) + val[0] + "." + "{:02d}".format(int(val[1]))):
+ continue
+ elif res.group(10) and res.group(11):
+ # only installed if platform is eqal, don't check if platform is not equal
+ if res.group(10) == "==":
+ if sys.platform != res.group(11):
+ continue
+ # installed if platform is not eqal, don't check if platform is equal
+ elif res.group(10) == "!=":
+ if sys.platform == res.group(11):
+ continue
if getattr(sys, 'frozen', False):
dep_version = exe_deps[res.group(1).lower().replace('_', '-')]
else:
@@ -63,7 +79,7 @@ def dependency_check(optional=False):
deps = load_dependencies(optional)
for dep in deps:
try:
- dep_version_int = [int(x) if x.isnumeric() else 0 for x in dep[0].split('.')]
+ dep_version_int = [int(x) if x.isnumeric() else 0 for x in dep[0].split('.')[:3]]
low_check = [int(x) for x in dep[3].split('.')]
high_check = [int(x) for x in dep[5].split('.')]
except AttributeError:
diff --git a/cps/editbooks.py b/cps/editbooks.py
index 5f58cf81..948ad1ab 100644
--- a/cps/editbooks.py
+++ b/cps/editbooks.py
@@ -21,18 +21,18 @@
# along with this program. If not, see .
import os
-from datetime import datetime
+from datetime import datetime, timezone
import json
from shutil import copyfile
-from uuid import uuid4
+
from markupsafe import escape, Markup # dependency of flask
from functools import wraps
-from flask import Blueprint, request, flash, redirect, url_for, abort, Response
+from flask import Blueprint, request, flash, redirect, url_for, abort, jsonify, make_response, Response
from flask_babel import gettext as _
from flask_babel import lazy_gettext as N_
from flask_babel import get_locale
-from .cw_login import current_user, login_required
+from .cw_login import current_user
from sqlalchemy.exc import OperationalError, IntegrityError, InterfaceError
from sqlalchemy.orm.exc import StaleDataError
from sqlalchemy.sql.expression import func
@@ -47,7 +47,7 @@ from .kobo_sync_status import change_archived_books
from .redirect import get_redirect_location
from .file_helper import validate_mime_type
from .usermanagement import user_login_required, login_required_if_no_ano
-
+from .string_helper import strip_whitespaces
editbook = Blueprint('edit-book', __name__)
log = logger.create()
@@ -76,7 +76,7 @@ def edit_required(f):
@editbook.route("/ajax/delete/", methods=["POST"])
@user_login_required
def delete_book_from_details(book_id):
- return Response(delete_book_from_table(book_id, "", True), mimetype='application/json')
+ return delete_book_from_table(book_id, "", True)
@editbook.route("/delete/", defaults={'book_format': ""}, methods=["POST"])
@@ -97,157 +97,22 @@ def show_edit_book(book_id):
@login_required_if_no_ano
@edit_required
def edit_book(book_id):
- modify_date = False
- edit_error = False
-
- # create the function for sorting...
- calibre_db.update_title_sort(config)
-
- book = calibre_db.get_filtered_book(book_id, allow_show_archived=True)
- # Book not found
- if not book:
- flash(_("Oops! Selected book is unavailable. File does not exist or is not accessible"),
- category="error")
- return redirect(url_for("web.index"))
-
- to_save = request.form.to_dict()
-
- try:
- # Update folder of book on local disk
- edited_books_id = None
- title_author_error = None
- # handle book title change
- title_change = handle_title_on_edit(book, to_save["book_title"])
- # handle book author change
- input_authors, author_change = handle_author_on_edit(book, to_save["author_name"])
- if author_change or title_change:
- edited_books_id = book.id
- modify_date = True
- title_author_error = helper.update_dir_structure(edited_books_id,
- config.get_book_path(),
- input_authors[0])
- if title_author_error:
- flash(title_author_error, category="error")
- calibre_db.session.rollback()
- book = calibre_db.get_filtered_book(book_id, allow_show_archived=True)
-
- # handle upload other formats from local disk
- meta = upload_single_file(request, book, book_id)
- # only merge metadata if file was uploaded and no error occurred (meta equals not false or none)
- upload_format = False
- if meta:
- upload_format = merge_metadata(to_save, meta)
- # handle upload covers from local disk
- cover_upload_success = upload_cover(request, book)
- if cover_upload_success:
- book.has_cover = 1
- modify_date = True
-
- # upload new covers or new file formats to google drive
- if config.config_use_google_drive:
- gdriveutils.updateGdriveCalibreFromLocal()
-
- if to_save.get("cover_url", None):
- if not current_user.role_upload():
- edit_error = True
- flash(_("User has no rights to upload cover"), category="error")
- if to_save["cover_url"].endswith('/static/generic_cover.jpg'):
- book.has_cover = 0
- else:
- result, error = helper.save_cover_from_url(to_save["cover_url"].strip(), book.path)
- if result is True:
- book.has_cover = 1
- modify_date = True
- helper.replace_cover_thumbnail_cache(book.id)
- else:
- flash(error, category="error")
-
- # Add default series_index to book
- modify_date |= edit_book_series_index(to_save["series_index"], book)
- # Handle book comments/description
- modify_date |= edit_book_comments(Markup(to_save['description']).unescape(), book)
- # Handle identifiers
- input_identifiers = identifier_list(to_save, book)
- modification, warning = modify_identifiers(input_identifiers, book.identifiers, calibre_db.session)
- if warning:
- flash(_("Identifiers are not Case Sensitive, Overwriting Old Identifier"), category="warning")
- modify_date |= modification
- # Handle book tags
- modify_date |= edit_book_tags(to_save['tags'], book)
- # Handle book series
- modify_date |= edit_book_series(to_save["series"], book)
- # handle book publisher
- modify_date |= edit_book_publisher(to_save['publisher'], book)
- # handle book languages
- try:
- modify_date |= edit_book_languages(to_save['languages'], book, upload_format)
- except ValueError as e:
- flash(str(e), category="error")
- edit_error = True
- # handle book ratings
- modify_date |= edit_book_ratings(to_save, book)
- # handle cc data
- modify_date |= edit_all_cc_data(book_id, book, to_save)
-
- if to_save.get("pubdate", None):
- try:
- book.pubdate = datetime.strptime(to_save["pubdate"], "%Y-%m-%d")
- except ValueError as e:
- book.pubdate = db.Books.DEFAULT_PUBDATE
- flash(str(e), category="error")
- edit_error = True
- else:
- book.pubdate = db.Books.DEFAULT_PUBDATE
-
- if modify_date:
- book.last_modified = datetime.utcnow()
- kobo_sync_status.remove_synced_book(edited_books_id, all=True)
- calibre_db.set_metadata_dirty(book.id)
-
- calibre_db.session.merge(book)
- calibre_db.session.commit()
- if config.config_use_google_drive:
- gdriveutils.updateGdriveCalibreFromLocal()
- if meta is not False \
- and edit_error is not True \
- and title_author_error is not True \
- and cover_upload_success is not False:
- flash(_("Metadata successfully updated"), category="success")
- if "detail_view" in to_save:
- return redirect(url_for('web.show_book', book_id=book.id))
- else:
- return render_edit_book(book_id)
- except ValueError as e:
- log.error_or_exception("Error: {}".format(e))
- calibre_db.session.rollback()
- flash(str(e), category="error")
- return redirect(url_for('web.show_book', book_id=book.id))
- except (OperationalError, IntegrityError, StaleDataError, InterfaceError) as e:
- log.error_or_exception("Database error: {}".format(e))
- calibre_db.session.rollback()
- flash(_("Oops! Database Error: %(error)s.", error=e.orig if hasattr(e, "orig") else e), category="error")
- return redirect(url_for('web.show_book', book_id=book.id))
- except Exception as ex:
- log.error_or_exception(ex)
- calibre_db.session.rollback()
- flash(_("Error editing book: {}".format(ex)), category="error")
- return redirect(url_for('web.show_book', book_id=book.id))
+ return do_edit_book(book_id)
@editbook.route("/upload", methods=["POST"])
@login_required_if_no_ano
@upload_required
def upload():
- if not config.config_uploading:
- abort(404)
- if request.method == 'POST' and 'btn-upload' in request.files:
+ if len(request.files.getlist("btn-upload-format")):
+ book_id = request.form.get('book_id', -1)
+ return do_edit_book(book_id, request.files.getlist("btn-upload-format"))
+ elif len(request.files.getlist("btn-upload")):
for requested_file in request.files.getlist("btn-upload"):
try:
modify_date = False
# create the function for sorting...
- calibre_db.update_title_sort(config)
- calibre_db.session.connection().connection.connection.create_function('uuid4', 0, lambda: str(uuid4()))
-
+ calibre_db.create_functions(config)
meta, error = file_handling_on_upload(requested_file)
if error:
return error
@@ -275,9 +140,7 @@ def upload():
input_authors[0],
meta.file_path,
title_dir + meta.extension.lower())
-
move_coverfile(meta, db_book)
-
if modify_date:
calibre_db.set_metadata_dirty(book_id)
# save data to database, reread data
@@ -295,16 +158,17 @@ def upload():
if len(request.files.getlist("btn-upload")) < 2:
if current_user.role_edit() or current_user.role_admin():
resp = {"location": url_for('edit-book.show_edit_book', book_id=book_id)}
- return Response(json.dumps(resp), mimetype='application/json')
+ return make_response(jsonify(resp))
else:
resp = {"location": url_for('web.show_book', book_id=book_id)}
- return Response(json.dumps(resp), mimetype='application/json')
+ return make_response(jsonify(resp))
except (OperationalError, IntegrityError, StaleDataError) as e:
calibre_db.session.rollback()
log.error_or_exception("Database error: {}".format(e))
flash(_("Oops! Database Error: %(error)s.", error=e.orig if hasattr(e, "orig") else e),
category="error")
- return Response(json.dumps({"location": url_for("web.index")}), mimetype='application/json')
+ return make_response(jsonify(location=url_for("web.index")))
+ abort(404)
@editbook.route("/admin/book/convert/", methods=['POST'])
@@ -342,7 +206,7 @@ def table_get_custom_enum(c_id):
ret.append({'value': "", 'text': ""})
for idx, en in enumerate(cc.get_display_dict()['enum_values']):
ret.append({'value': en, 'text': en})
- return json.dumps(ret)
+ return make_response(jsonify(ret))
@editbook.route("/ajax/editbooks/", methods=['POST'])
@@ -351,73 +215,60 @@ def table_get_custom_enum(c_id):
def edit_list_book(param):
vals = request.form.to_dict()
book = calibre_db.get_book(vals['pk'])
+ calibre_db.create_functions(config)
sort_param = ""
ret = ""
try:
if param == 'series_index':
edit_book_series_index(vals['value'], book)
- ret = Response(json.dumps({'success': True, 'newValue': book.series_index}), mimetype='application/json')
+ ret = make_response(jsonify(success=True, newValue=book.series_index))
elif param == 'tags':
edit_book_tags(vals['value'], book)
- ret = Response(json.dumps({'success': True, 'newValue': ', '.join([tag.name for tag in book.tags])}),
- mimetype='application/json')
+ ret = make_response(jsonify(success=True, newValue=', '.join([tag.name for tag in book.tags])))
elif param == 'series':
edit_book_series(vals['value'], book)
- ret = Response(json.dumps({'success': True, 'newValue': ', '.join([serie.name for serie in book.series])}),
- mimetype='application/json')
+ ret = make_response(jsonify(success=True, newValue=', '.join([serie.name for serie in book.series])))
elif param == 'publishers':
edit_book_publisher(vals['value'], book)
- ret = Response(json.dumps({'success': True,
- 'newValue': ', '.join([publisher.name for publisher in book.publishers])}),
- mimetype='application/json')
+ ret = make_response(jsonify(success=True,
+ newValue=', '.join([publisher.name for publisher in book.publishers])))
elif param == 'languages':
invalid = list()
edit_book_languages(vals['value'], book, invalid=invalid)
if invalid:
- ret = Response(json.dumps({'success': False,
- 'msg': 'Invalid languages in request: {}'.format(','.join(invalid))}),
- mimetype='application/json')
+ ret = make_response(jsonify(success=False,
+ msg='Invalid languages in request: {}'.format(','.join(invalid))))
else:
lang_names = list()
for lang in book.languages:
lang_names.append(isoLanguages.get_language_name(get_locale(), lang.lang_code))
- ret = Response(json.dumps({'success': True, 'newValue': ', '.join(lang_names)}),
- mimetype='application/json')
+ ret = make_response(jsonify(success=True, newValue=', '.join(lang_names)))
elif param == 'author_sort':
book.author_sort = vals['value']
- ret = Response(json.dumps({'success': True, 'newValue': book.author_sort}),
- mimetype='application/json')
+ ret = make_response(jsonify(success=True, newValue=book.author_sort))
elif param == 'title':
sort_param = book.sort
if handle_title_on_edit(book, vals.get('value', "")):
rename_error = helper.update_dir_structure(book.id, config.get_book_path())
if not rename_error:
- ret = Response(json.dumps({'success': True, 'newValue': book.title}),
- mimetype='application/json')
+ ret = make_response(jsonify(success=True, newValue=book.title))
else:
- ret = Response(json.dumps({'success': False,
- 'msg': rename_error}),
- mimetype='application/json')
+ ret = make_response(jsonify(success=False, msg=rename_error))
elif param == 'sort':
book.sort = vals['value']
- ret = Response(json.dumps({'success': True, 'newValue': book.sort}),
- mimetype='application/json')
+ ret = make_response(jsonify(success=True,newValue=book.sort))
elif param == 'comments':
edit_book_comments(vals['value'], book)
- ret = Response(json.dumps({'success': True, 'newValue': book.comments[0].text}),
- mimetype='application/json')
+ ret = make_response(jsonify(success=True, newValue=book.comments[0].text))
elif param == 'authors':
input_authors, __ = handle_author_on_edit(book, vals['value'], vals.get('checkA', None) == "true")
rename_error = helper.update_dir_structure(book.id, config.get_book_path(), input_authors[0])
if not rename_error:
- ret = Response(json.dumps({
- 'success': True,
- 'newValue': ' & '.join([author.replace('|', ',') for author in input_authors])}),
- mimetype='application/json')
+ ret = make_response(jsonify(
+ success=True,
+ newValue=' & '.join([author.replace('|', ',') for author in input_authors])))
else:
- ret = Response(json.dumps({'success': False,
- 'msg': rename_error}),
- mimetype='application/json')
+ ret = make_response(jsonify(success=False, msg=rename_error))
elif param == 'is_archived':
is_archived = change_archived_books(book.id, vals['value'] == "True",
message="Book {} archive bit set to: {}".format(book.id, vals['value']))
@@ -436,11 +287,10 @@ def edit_list_book(param):
if vals['value'] in ["True", "False"]:
ret = ""
else:
- ret = Response(json.dumps({'success': True, 'newValue': vals['value']}),
- mimetype='application/json')
+ ret = make_response(jsonify(success=True, newValue=vals['value']))
else:
return _("Parameter not found"), 400
- book.last_modified = datetime.utcnow()
+ book.last_modified = datetime.now(timezone.utc)
calibre_db.session.commit()
# revert change for sort if automatic fields link is deactivated
@@ -450,9 +300,8 @@ def edit_list_book(param):
except (OperationalError, IntegrityError, StaleDataError) as e:
calibre_db.session.rollback()
log.error_or_exception("Database error: {}".format(e))
- ret = Response(json.dumps({'success': False,
- 'msg': 'Database error: {}'.format(e.orig if hasattr(e, "orig") else e)}),
- mimetype='application/json')
+ ret = make_response(jsonify(success=False,
+ msg='Database error: {}'.format(e.orig if hasattr(e, "orig") else e)))
return ret
@@ -463,13 +312,13 @@ def get_sorted_entry(field, bookid):
book = calibre_db.get_filtered_book(bookid)
if book:
if field == 'title':
- return json.dumps({'sort': book.sort})
+ return make_response(jsonify(sort=book.sort))
elif field == 'authors':
- return json.dumps({'author_sort': book.author_sort})
+ return make_response(jsonify(author_sort=book.author_sort))
if field == 'sort':
- return json.dumps({'sort': book.title})
+ return make_response(jsonify(sort=book.title))
if field == 'author_sort':
- return json.dumps({'authors': " & ".join([a.name for a in calibre_db.order_authors([book])])})
+ return make_response(jsonify(authors=" & ".join([a.name for a in calibre_db.order_authors([book])])))
return ""
@@ -485,7 +334,7 @@ def simulate_merge_list_book():
from_book = []
for book_id in vals:
from_book.append(calibre_db.get_book(book_id).title)
- return json.dumps({'to': to_book, 'from': from_book})
+ return make_response(jsonify({'to': to_book, 'from': from_book}))
return ""
@@ -523,7 +372,7 @@ def merge_list_book():
element.uncompressed_size,
to_name))
delete_book_from_table(from_book.id, "", True)
- return json.dumps({'success': True})
+ return make_response(jsonify(success=True))
return ""
@@ -556,38 +405,182 @@ def table_xchange_author_title():
# toDo: Handle error
edit_error = helper.update_dir_structure(edited_books_id, config.get_book_path(), input_authors[0])
if modify_date:
- book.last_modified = datetime.utcnow()
+ book.last_modified = datetime.now(timezone.utc)
calibre_db.set_metadata_dirty(book.id)
try:
calibre_db.session.commit()
except (OperationalError, IntegrityError, StaleDataError) as e:
calibre_db.session.rollback()
log.error_or_exception("Database error: {}".format(e))
- return json.dumps({'success': False})
+ return make_response(jsonify(success=False))
if config.config_use_google_drive:
gdriveutils.updateGdriveCalibreFromLocal()
- return json.dumps({'success': True})
+ return make_response(jsonify(success=True))
return ""
-def merge_metadata(to_save, meta):
- if to_save.get('author_name', "") == _('Unknown'):
- to_save['author_name'] = ''
- if to_save.get('book_title', "") == _('Unknown'):
- to_save['book_title'] = ''
- if not to_save["languages"] and meta.languages:
- upload_language = True
- else:
- upload_language = False
+def do_edit_book(book_id, upload_formats=None):
+ modify_date = False
+ edit_error = False
+
+ # create the function for sorting...
+ calibre_db.create_functions(config)
+
+ book = calibre_db.get_filtered_book(book_id, allow_show_archived=True)
+ # Book not found
+ if not book:
+ flash(_("Oops! Selected book is unavailable. File does not exist or is not accessible"),
+ category="error")
+ return redirect(url_for("web.index"))
+
+ to_save = request.form.to_dict()
+
+ try:
+ # Update folder of book on local disk
+ edited_books_id = None
+ title_author_error = None
+ # upload_mode = False
+ # handle book title change
+ if "title" in to_save:
+ title_change = handle_title_on_edit(book, to_save["title"])
+ # handle book author change
+ if not upload_formats:
+ input_authors, author_change = handle_author_on_edit(book, to_save["authors"])
+ if author_change or title_change:
+ edited_books_id = book.id
+ modify_date = True
+ title_author_error = helper.update_dir_structure(edited_books_id,
+ config.get_book_path(),
+ input_authors[0])
+ if title_author_error:
+ flash(title_author_error, category="error")
+ calibre_db.session.rollback()
+ book = calibre_db.get_filtered_book(book_id, allow_show_archived=True)
+
+ # handle book ratings
+ modify_date |= edit_book_ratings(to_save, book)
+ else:
+ # handle upload other formats from local disk
+ to_save, edit_error = upload_book_formats(upload_formats, book, book_id, book.has_cover)
+ # handle upload covers from local disk
+ cover_upload_success = upload_cover(request, book)
+ if cover_upload_success or to_save.get("format_cover"):
+ book.has_cover = 1
+ modify_date = True
+
+ # upload new covers or new file formats to google drive
+ if config.config_use_google_drive:
+ gdriveutils.updateGdriveCalibreFromLocal()
+
+ if to_save.get("cover_url",):
+ if not current_user.role_upload():
+ edit_error = True
+ flash(_("User has no rights to upload cover"), category="error")
+ if to_save["cover_url"].endswith('/static/generic_cover.jpg'):
+ book.has_cover = 0
+ else:
+ result, error = helper.save_cover_from_url(to_save["cover_url"].strip(), book.path)
+ if result is True:
+ book.has_cover = 1
+ modify_date = True
+ helper.replace_cover_thumbnail_cache(book.id)
+ else:
+ edit_error = True
+ flash(error, category="error")
+
+ # Add default series_index to book
+ modify_date |= edit_book_series_index(to_save.get("series_index"), book)
+ # Handle book comments/description
+ modify_date |= edit_book_comments(Markup(to_save.get('comments')).unescape(), book)
+ # Handle identifiers
+ input_identifiers = identifier_list(to_save, book)
+ modification, warning = modify_identifiers(input_identifiers, book.identifiers, calibre_db.session)
+ if warning:
+ flash(_("Identifiers are not Case Sensitive, Overwriting Old Identifier"), category="warning")
+ modify_date |= modification
+ # Handle book tags
+ modify_date |= edit_book_tags(to_save.get('tags'), book)
+ # Handle book series
+ modify_date |= edit_book_series(to_save.get("series"), book)
+ # handle book publisher
+ modify_date |= edit_book_publisher(to_save.get('publisher'), book)
+ # handle book languages
+ try:
+ invalid = []
+ modify_date |= edit_book_languages(to_save.get('languages'), book, upload_mode=upload_formats,
+ invalid=invalid)
+ if invalid:
+ for lang in invalid:
+ flash(_("'%(langname)s' is not a valid language", langname=lang), category="warning")
+ except ValueError as e:
+ flash(str(e), category="error")
+ edit_error = True
+ # handle cc data
+ modify_date |= edit_all_cc_data(book_id, book, to_save)
+
+ if to_save.get("pubdate") is not None:
+ if to_save.get("pubdate"):
+ try:
+ book.pubdate = datetime.strptime(to_save["pubdate"], "%Y-%m-%d")
+ except ValueError as e:
+ book.pubdate = db.Books.DEFAULT_PUBDATE
+ flash(str(e), category="error")
+ edit_error = True
+ else:
+ book.pubdate = db.Books.DEFAULT_PUBDATE
+
+ if modify_date:
+ book.last_modified = datetime.now(timezone.utc)
+ kobo_sync_status.remove_synced_book(edited_books_id, all=True)
+ calibre_db.set_metadata_dirty(book.id)
+
+ calibre_db.session.merge(book)
+ calibre_db.session.commit()
+ if config.config_use_google_drive:
+ gdriveutils.updateGdriveCalibreFromLocal()
+ if edit_error is not True and title_author_error is not True and cover_upload_success is not False:
+ flash(_("Metadata successfully updated"), category="success")
+
+ if upload_formats:
+ resp = {"location": url_for('edit-book.show_edit_book', book_id=book_id)}
+ return make_response(jsonify(resp))
+
+ if "detail_view" in to_save:
+ return redirect(url_for('web.show_book', book_id=book.id))
+ else:
+ return render_edit_book(book_id)
+ except ValueError as e:
+ log.error_or_exception("Error: {}".format(e))
+ calibre_db.session.rollback()
+ flash(str(e), category="error")
+ return redirect(url_for('web.show_book', book_id=book.id))
+ except (OperationalError, IntegrityError, StaleDataError, InterfaceError) as e:
+ log.error_or_exception("Database error: {}".format(e))
+ calibre_db.session.rollback()
+ flash(_("Oops! Database Error: %(error)s.", error=e.orig if hasattr(e, "orig") else e), category="error")
+ return redirect(url_for('web.show_book', book_id=book.id))
+ except Exception as ex:
+ log.error_or_exception(ex)
+ calibre_db.session.rollback()
+ flash(_("Error editing book: {}".format(ex)), category="error")
+ return redirect(url_for('web.show_book', book_id=book.id))
+
+
+def merge_metadata(book, meta, to_save):
+ if meta.cover:
+ to_save['cover_format'] = meta.cover
for s_field, m_field in [
- ('tags', 'tags'), ('author_name', 'author'), ('series', 'series'),
+ ('tags', 'tags'), ('authors', 'author'), ('series', 'series'),
('series_index', 'series_id'), ('languages', 'languages'),
- ('book_title', 'title')]:
- to_save[s_field] = to_save[s_field] or getattr(meta, m_field, '')
- to_save["description"] = to_save["description"] or Markup(
- getattr(meta, 'description', '')).unescape()
- return upload_language
+ ('title', 'title'), ('comments', 'description')]:
+ try:
+ val = None if len(getattr(book, s_field)) else getattr(meta, m_field, '')
+ except TypeError:
+ val = None if len(str(getattr(book, s_field))) else getattr(meta, m_field, '')
+ if val:
+ to_save[s_field] = val
+
def identifier_list(to_save, book):
"""Generate a list of Identifiers from form information"""
@@ -707,8 +700,8 @@ def create_book_on_upload(modify_date, meta):
pubdate = datetime(101, 1, 1)
# Calibre adds books with utc as timezone
- db_book = db.Books(title, "", sort_authors, datetime.utcnow(), pubdate,
- '1', datetime.utcnow(), path, meta.cover, db_author, [], "")
+ db_book = db.Books(title, "", sort_authors, datetime.now(timezone.utc), pubdate,
+ '1', datetime.now(timezone.utc), path, meta.cover, db_author, [], "")
modify_date |= modify_database_object(input_authors, db_book.authors, db.Authors, calibre_db.session,
'author')
@@ -760,17 +753,17 @@ def file_handling_on_upload(requested_file):
if config.config_check_extensions and allowed_extensions != ['']:
if not validate_mime_type(requested_file, allowed_extensions):
flash(_("File type isn't allowed to be uploaded to this server"), category="error")
- return None, Response(json.dumps({"location": url_for("web.index")}), mimetype='application/json')
+ return None, make_response(jsonify(location=url_for("web.index")))
if '.' in requested_file.filename:
file_ext = requested_file.filename.rsplit('.', 1)[-1].lower()
if file_ext not in allowed_extensions and '' not in allowed_extensions:
flash(
_("File extension '%(ext)s' is not allowed to be uploaded to this server",
ext=file_ext), category="error")
- return None, Response(json.dumps({"location": url_for("web.index")}), mimetype='application/json')
+ return None, make_response(jsonify(location=url_for("web.index")))
else:
flash(_('File to be uploaded must have an extension'), category="error")
- return None, Response(json.dumps({"location": url_for("web.index")}), mimetype='application/json')
+ return None, make_response(jsonify(location=url_for("web.index")))
# extract metadata from file
try:
@@ -779,7 +772,7 @@ def file_handling_on_upload(requested_file):
log.error("File %s could not saved to temp dir", requested_file.filename)
flash(_("File %(filename)s could not saved to temp dir",
filename=requested_file.filename), category="error")
- return None, Response(json.dumps({"location": url_for("web.index")}), mimetype='application/json')
+ return None, make_response(jsonify(location=url_for("web.index")))
return meta, None
@@ -851,7 +844,7 @@ def delete_whole_book(book_id, book):
def render_delete_book_result(book_format, json_response, warning, book_id, location=""):
if book_format:
if json_response:
- return json.dumps([warning, {"location": url_for("edit-book.show_edit_book", book_id=book_id),
+ return jsonify([warning, {"location": url_for("edit-book.show_edit_book", book_id=book_id),
"type": "success",
"format": book_format,
"message": _('Book Format Successfully Deleted')}])
@@ -860,7 +853,7 @@ def render_delete_book_result(book_format, json_response, warning, book_id, loca
return redirect(url_for('edit-book.show_edit_book', book_id=book_id))
else:
if json_response:
- return json.dumps([warning, {"location": get_redirect_location(location, "web.index"),
+ return jsonify([warning, {"location": get_redirect_location(location, "web.index"),
"type": "success",
"format": book_format,
"message": _('Book Successfully Deleted')}])
@@ -878,7 +871,7 @@ def delete_book_from_table(book_id, book_format, json_response, location=""):
result, error = helper.delete_book(book, config.get_book_path(), book_format=book_format.upper())
if not result:
if json_response:
- return json.dumps([{"location": url_for("edit-book.show_edit_book", book_id=book_id),
+ return jsonify([{"location": url_for("edit-book.show_edit_book", book_id=book_id),
"type": "danger",
"format": "",
"message": error}])
@@ -905,7 +898,7 @@ def delete_book_from_table(book_id, book_format, json_response, location=""):
log.error_or_exception(ex)
calibre_db.session.rollback()
if json_response:
- return json.dumps([{"location": url_for("edit-book.show_edit_book", book_id=book_id),
+ return jsonify([{"location": url_for("edit-book.show_edit_book", book_id=book_id),
"type": "danger",
"format": "",
"message": ex}])
@@ -919,7 +912,7 @@ def delete_book_from_table(book_id, book_format, json_response, location=""):
return render_delete_book_result(book_format, json_response, warning, book_id, location)
message = _("You are missing permissions to delete books")
if json_response:
- return json.dumps({"location": url_for("edit-book.show_edit_book", book_id=book_id),
+ return jsonify({"location": url_for("edit-book.show_edit_book", book_id=book_id),
"type": "danger",
"format": "",
"message": message})
@@ -975,7 +968,7 @@ def render_edit_book(book_id):
def edit_book_ratings(to_save, book):
changed = False
- if to_save.get("rating", "").strip():
+ if strip_whitespaces(to_save.get("rating", "")):
old_rating = False
if len(book.ratings) > 0:
old_rating = book.ratings[0].rating
@@ -998,84 +991,93 @@ def edit_book_ratings(to_save, book):
def edit_book_tags(tags, book):
- input_tags = tags.split(',')
- input_tags = list(map(lambda it: it.strip(), input_tags))
- # Remove duplicates
- input_tags = helper.uniq(input_tags)
- return modify_database_object(input_tags, book.tags, db.Tags, calibre_db.session, 'tags')
-
+ if tags is not None:
+ input_tags = tags.split(',')
+ input_tags = list(map(lambda it: strip_whitespaces(it), input_tags))
+ # Remove duplicates
+ input_tags = helper.uniq(input_tags)
+ return modify_database_object(input_tags, book.tags, db.Tags, calibre_db.session, 'tags')
+ return False
def edit_book_series(series, book):
- input_series = [series.strip()]
- input_series = [x for x in input_series if x != '']
- return modify_database_object(input_series, book.series, db.Series, calibre_db.session, 'series')
+ if series is not None:
+ input_series = [strip_whitespaces(series)]
+ input_series = [x for x in input_series if x != '']
+ return modify_database_object(input_series, book.series, db.Series, calibre_db.session, 'series')
+ return False
def edit_book_series_index(series_index, book):
- # Add default series_index to book
- modify_date = False
- series_index = series_index or '1'
- if not series_index.replace('.', '', 1).isdigit():
- flash(_("%(seriesindex)s is not a valid number, skipping", seriesindex=series_index), category="warning")
- return False
- if str(book.series_index) != series_index:
- book.series_index = series_index
- modify_date = True
- return modify_date
+ if series_index:
+ # Add default series_index to book
+ modify_date = False
+ series_index = series_index or '1'
+ if not series_index.replace('.', '', 1).isdigit():
+ flash(_("Seriesindex: %(seriesindex)s is not a valid number, skipping", seriesindex=series_index), category="warning")
+ return False
+ if str(book.series_index) != series_index:
+ book.series_index = series_index
+ modify_date = True
+ return modify_date
+ return False
# Handle book comments/description
def edit_book_comments(comments, book):
- modify_date = False
- if comments:
- comments = clean_string(comments, book.id)
- if len(book.comments):
- if book.comments[0].text != comments:
- book.comments[0].text = comments
- modify_date = True
- else:
+ if comments is not None:
+ modify_date = False
if comments:
- book.comments.append(db.Comments(comment=comments, book=book.id))
- modify_date = True
- return modify_date
+ comments = clean_string(comments, book.id)
+ if len(book.comments):
+ if book.comments[0].text != comments:
+ book.comments[0].text = comments
+ modify_date = True
+ else:
+ if comments:
+ book.comments.append(db.Comments(comment=comments, book=book.id))
+ modify_date = True
+ return modify_date
def edit_book_languages(languages, book, upload_mode=False, invalid=None):
- input_languages = languages.split(',')
- unknown_languages = []
- if not upload_mode:
- input_l = isoLanguages.get_language_codes(get_locale(), input_languages, unknown_languages)
- else:
- input_l = isoLanguages.get_valid_language_codes(get_locale(), input_languages, unknown_languages)
- for lang in unknown_languages:
- log.error("'%s' is not a valid language", lang)
- if isinstance(invalid, list):
- invalid.append(lang)
+ if languages is not None:
+ input_languages = languages.split(',')
+ unknown_languages = []
+ if not upload_mode:
+ input_l = isoLanguages.get_language_code_from_name(get_locale(), input_languages, unknown_languages)
else:
- raise ValueError(_("'%(langname)s' is not a valid language", langname=lang))
- # ToDo: Not working correct
- if upload_mode and len(input_l) == 1:
- # If the language of the file is excluded from the users view, it's not imported, to allow the user to view
- # the book it's language is set to the filter language
- if input_l[0] != current_user.filter_language() and current_user.filter_language() != "all":
- input_l[0] = calibre_db.session.query(db.Languages). \
- filter(db.Languages.lang_code == current_user.filter_language()).first().lang_code
- # Remove duplicates
- input_l = helper.uniq(input_l)
- return modify_database_object(input_l, book.languages, db.Languages, calibre_db.session, 'languages')
+ input_l = isoLanguages.get_valid_language_codes_from_code(get_locale(), input_languages, unknown_languages)
+ for lang in unknown_languages:
+ log.error("'%s' is not a valid language", lang)
+ if isinstance(invalid, list):
+ invalid.append(lang)
+ else:
+ raise ValueError(_("'%(langname)s' is not a valid language", langname=lang))
+ # ToDo: Not working correct
+ if upload_mode and len(input_l) == 1:
+ # If the language of the file is excluded from the users view, it's not imported, to allow the user to view
+ # the book it's language is set to the filter language
+ if input_l[0] != current_user.filter_language() and current_user.filter_language() != "all":
+ input_l[0] = calibre_db.session.query(db.Languages). \
+ filter(db.Languages.lang_code == current_user.filter_language()).first().lang_code
+ # Remove duplicates from normalized langcodes
+ input_l = helper.uniq(input_l)
+ return modify_database_object(input_l, book.languages, db.Languages, calibre_db.session, 'languages')
+ return False
def edit_book_publisher(publishers, book):
- changed = False
- if publishers:
- publisher = publishers.rstrip().strip()
- if len(book.publishers) == 0 or (len(book.publishers) > 0 and publisher != book.publishers[0].name):
- changed |= modify_database_object([publisher], book.publishers, db.Publishers, calibre_db.session,
- 'publisher')
- elif len(book.publishers):
- changed |= modify_database_object([], book.publishers, db.Publishers, calibre_db.session, 'publisher')
- return changed
-
+ if publishers is not None:
+ changed = False
+ if publishers:
+ publisher = strip_whitespaces(publishers)
+ if len(book.publishers) == 0 or (len(book.publishers) > 0 and publisher != book.publishers[0].name):
+ changed |= modify_database_object([publisher], book.publishers, db.Publishers, calibre_db.session,
+ 'publisher')
+ elif len(book.publishers):
+ changed |= modify_database_object([], book.publishers, db.Publishers, calibre_db.session, 'publisher')
+ return changed
+ return False
def edit_cc_data_value(book_id, book, c, to_save, cc_db_value, cc_string):
changed = False
@@ -1115,7 +1117,7 @@ def edit_cc_data_string(book, c, to_save, cc_db_value, cc_string):
changed = False
if c.datatype == 'rating':
to_save[cc_string] = str(int(float(to_save[cc_string]) * 2))
- if to_save[cc_string].strip() != cc_db_value:
+ if strip_whitespaces(to_save[cc_string]) != cc_db_value:
if cc_db_value is not None:
# remove old cc_val
del_cc = getattr(book, cc_string)[0]
@@ -1125,15 +1127,15 @@ def edit_cc_data_string(book, c, to_save, cc_db_value, cc_string):
changed = True
cc_class = db.cc_classes[c.id]
new_cc = calibre_db.session.query(cc_class).filter(
- cc_class.value == to_save[cc_string].strip()).first()
+ cc_class.value == strip_whitespaces(to_save[cc_string])).first()
# if no cc val is found add it
if new_cc is None:
- new_cc = cc_class(value=to_save[cc_string].strip())
+ new_cc = cc_class(value=strip_whitespaces(to_save[cc_string]))
calibre_db.session.add(new_cc)
changed = True
calibre_db.session.flush()
new_cc = calibre_db.session.query(cc_class).filter(
- cc_class.value == to_save[cc_string].strip()).first()
+ cc_class.value == strip_whitespaces(to_save[cc_string])).first()
# add cc value to book
getattr(book, cc_string).append(new_cc)
return changed, to_save
@@ -1156,61 +1158,66 @@ def edit_cc_data(book_id, book, to_save, cc):
changed = False
for c in cc:
cc_string = "custom_column_" + str(c.id)
- if not c.is_multiple:
- if len(getattr(book, cc_string)) > 0:
- cc_db_value = getattr(book, cc_string)[0].value
- else:
- cc_db_value = None
- if to_save[cc_string].strip():
- if c.datatype in ['int', 'bool', 'float', "datetime", "comments"]:
- change, to_save = edit_cc_data_value(book_id, book, c, to_save, cc_db_value, cc_string)
+ if to_save.get(cc_string) is not None:
+ if not c.is_multiple:
+ if len(getattr(book, cc_string)) > 0:
+ cc_db_value = getattr(book, cc_string)[0].value
else:
- change, to_save = edit_cc_data_string(book, c, to_save, cc_db_value, cc_string)
- changed |= change
+ cc_db_value = None
+ if strip_whitespaces(to_save[cc_string]):
+ if c.datatype in ['int', 'bool', 'float', "datetime", "comments"]:
+ change, to_save = edit_cc_data_value(book_id, book, c, to_save, cc_db_value, cc_string)
+ else:
+ change, to_save = edit_cc_data_string(book, c, to_save, cc_db_value, cc_string)
+ changed |= change
+ else:
+ if cc_db_value is not None:
+ # remove old cc_val
+ del_cc = getattr(book, cc_string)[0]
+ getattr(book, cc_string).remove(del_cc)
+ if not del_cc.books or len(del_cc.books) == 0:
+ calibre_db.session.delete(del_cc)
+ changed = True
else:
- if cc_db_value is not None:
- # remove old cc_val
- del_cc = getattr(book, cc_string)[0]
- getattr(book, cc_string).remove(del_cc)
- if not del_cc.books or len(del_cc.books) == 0:
- calibre_db.session.delete(del_cc)
- changed = True
- else:
- input_tags = to_save[cc_string].split(',')
- input_tags = list(map(lambda it: it.strip(), input_tags))
- changed |= modify_database_object(input_tags,
- getattr(book, cc_string),
- db.cc_classes[c.id],
- calibre_db.session,
- 'custom')
+ input_tags = to_save[cc_string].split(',')
+ input_tags = list(map(lambda it: strip_whitespaces(it), input_tags))
+ changed |= modify_database_object(input_tags,
+ getattr(book, cc_string),
+ db.cc_classes[c.id],
+ calibre_db.session,
+ 'custom')
return changed
-# returns None if no file is uploaded
-# returns False if an error occurs, in all other cases the ebook metadata is returned
-def upload_single_file(file_request, book, book_id):
+# returns False if an error occurs or no book is uploaded, in all other cases the ebook metadata to change is returned
+def upload_book_formats(requested_files, book, book_id, no_cover=True):
# Check and handle Uploaded file
- requested_file = file_request.files.get('btn-upload-format', None)
+ to_save = dict()
+ error = False
allowed_extensions = config.config_upload_formats.split(',')
- if requested_file:
+ for requested_file in requested_files:
+ current_filename = requested_file.filename
if config.config_check_extensions and allowed_extensions != ['']:
if not validate_mime_type(requested_file, allowed_extensions):
flash(_("File type isn't allowed to be uploaded to this server"), category="error")
- return False
- # check for empty request
- if requested_file.filename != '':
+ error = True
+ continue
+ if current_filename != '':
if not current_user.role_upload():
flash(_("User has no rights to upload additional file formats"), category="error")
- return False
- if '.' in requested_file.filename:
- file_ext = requested_file.filename.rsplit('.', 1)[-1].lower()
+ error = True
+ continue
+ if '.' in current_filename:
+ file_ext = current_filename.rsplit('.', 1)[-1].lower()
if file_ext not in allowed_extensions and '' not in allowed_extensions:
flash(_("File extension '%(ext)s' is not allowed to be uploaded to this server", ext=file_ext),
category="error")
- return False
+ error = True
+ continue
else:
flash(_('File to be uploaded must have an extension'), category="error")
- return False
+ error = True
+ continue
file_name = book.path.rsplit('/', 1)[-1]
filepath = os.path.normpath(os.path.join(config.get_book_path(), book.path))
@@ -1223,41 +1230,50 @@ def upload_single_file(file_request, book, book_id):
except OSError:
flash(_("Failed to create path %(path)s (Permission denied).", path=filepath),
category="error")
- return False
+ error = True
+ continue
try:
requested_file.save(saved_filename)
except OSError:
flash(_("Failed to store file %(file)s.", file=saved_filename), category="error")
- return False
+ error = True
+ continue
file_size = os.path.getsize(saved_filename)
- is_format = calibre_db.get_book_format(book_id, file_ext.upper())
# Format entry already exists, no need to update the database
- if is_format:
+ if calibre_db.get_book_format(book_id, file_ext.upper()):
log.warning('Book format %s already existing', file_ext.upper())
else:
try:
db_format = db.Data(book_id, file_ext.upper(), file_size, file_name)
calibre_db.session.add(db_format)
calibre_db.session.commit()
- calibre_db.update_title_sort(config)
+ calibre_db.create_functions(config)
except (OperationalError, IntegrityError, StaleDataError) as e:
calibre_db.session.rollback()
log.error_or_exception("Database error: {}".format(e))
flash(_("Oops! Database Error: %(error)s.", error=e.orig if hasattr(e, "orig") else e),
category="error")
- return False # return redirect(url_for('web.show_book', book_id=book.id))
+ error = True
+ continue
# Queue uploader info
link = '{}'.format(url_for('web.show_book', book_id=book.id), escape(book.title))
upload_text = N_("File format %(ext)s added to %(book)s", ext=file_ext.upper(), book=link)
WorkerThread.add(current_user.name, TaskUpload(upload_text, escape(book.title)))
-
- return uploader.process(
- saved_filename, *os.path.splitext(requested_file.filename),
- rar_executable=config.config_rarfile_location)
- return None
+ meta = uploader.process(
+ saved_filename,
+ *os.path.splitext(current_filename),
+ rar_executable=config.config_rarfile_location,
+ no_cover=no_cover)
+ merge_metadata(book, meta, to_save)
+ #if to_save.get('languages'):
+ # langs = []
+ # for lang_code in to_save['languages'].split(','):
+ # langs.append(isoLanguages.get_language_name(get_locale(), lang_code))
+ # to_save['languages'] = ",".join(langs)
+ return to_save, error
def upload_cover(cover_request, book):
@@ -1280,7 +1296,7 @@ def upload_cover(cover_request, book):
def handle_title_on_edit(book, book_title):
# handle book title
- book_title = book_title.rstrip().strip()
+ book_title = strip_whitespaces(book_title)
if book.title != book_title:
if book_title == '':
book_title = _(u'Unknown')
@@ -1291,7 +1307,6 @@ def handle_title_on_edit(book, book_title):
def handle_author_on_edit(book, author_name, update_stored=True):
change = False
- # handle author(s)
input_authors = prepare_authors(author_name, config.get_book_path(), config.config_use_google_drive)
# Search for each author if author is in database, if not, author name and sorted author name is generated new
@@ -1321,7 +1336,6 @@ def search_objects_remove(db_book_object, db_type, input_elements):
if db_type == 'custom':
type_elements = c_elements.value
else:
- # type_elements = c_elements.name
type_elements = c_elements
for inp_element in input_elements:
if type_elements == inp_element:
diff --git a/cps/embed_helper.py b/cps/embed_helper.py
index 54db47ef..f222bcd0 100644
--- a/cps/embed_helper.py
+++ b/cps/embed_helper.py
@@ -35,9 +35,7 @@ def do_calibre_export(book_id, book_format):
my_env = os.environ.copy()
if config.config_calibre_split:
my_env['CALIBRE_OVERRIDE_DATABASE_PATH'] = os.path.join(config.config_calibre_dir, "metadata.db")
- library_path = config.config_calibre_split_dir
- else:
- library_path = config.config_calibre_dir
+ library_path = config.get_book_path()
opf_command = [calibredb_binarypath, 'export', '--dont-write-opf', '--with-library', library_path,
'--to-dir', tmp_dir, '--formats', book_format, "--template", "{}".format(temp_file_name),
str(book_id)]
diff --git a/cps/epub.py b/cps/epub.py
index c802f61d..3947cee6 100644
--- a/cps/epub.py
+++ b/cps/epub.py
@@ -25,6 +25,7 @@ from . import config, logger
from .helper import split_authors
from .epub_helper import get_content_opf, default_ns
from .constants import BookMeta
+from .string_helper import strip_whitespaces
log = logger.create()
@@ -55,7 +56,7 @@ def get_epub_layout(book, book_data):
p = tree.xpath('/pkg:package/pkg:metadata', namespaces=default_ns)[0]
layout = p.xpath('pkg:meta[@property="rendition:layout"]/text()', namespaces=default_ns)
- except (etree.XMLSyntaxError, KeyError, IndexError, OSError) as e:
+ except (etree.XMLSyntaxError, KeyError, IndexError, OSError, UnicodeDecodeError) as e:
log.error("Could not parse epub metadata of book {} during kobo sync: {}".format(book.id, e))
layout = []
@@ -65,7 +66,7 @@ def get_epub_layout(book, book_data):
return layout[0]
-def get_epub_info(tmp_file_path, original_file_name, original_file_extension):
+def get_epub_info(tmp_file_path, original_file_name, original_file_extension, no_cover_processing):
ns = {
'n': 'urn:oasis:names:tc:opendocument:xmlns:container',
'pkg': 'http://www.idpf.org/2007/opf',
@@ -90,7 +91,7 @@ def get_epub_info(tmp_file_path, original_file_name, original_file_extension):
elif s == 'date':
epub_metadata[s] = tmp[0][:10]
else:
- epub_metadata[s] = tmp[0].strip()
+ epub_metadata[s] = strip_whitespaces(tmp[0])
else:
epub_metadata[s] = 'Unknown'
@@ -116,7 +117,10 @@ def get_epub_info(tmp_file_path, original_file_name, original_file_extension):
epub_metadata = parse_epub_series(ns, tree, epub_metadata)
epub_zip = zipfile.ZipFile(tmp_file_path)
- cover_file = parse_epub_cover(ns, tree, epub_zip, cover_path, tmp_file_path)
+ if not no_cover_processing:
+ cover_file = parse_epub_cover(ns, tree, epub_zip, cover_path, tmp_file_path)
+ else:
+ cover_file = None
identifiers = []
for node in p.xpath('dc:identifier', namespaces=ns):
diff --git a/cps/error_handler.py b/cps/error_handler.py
index 92d3e876..0df98332 100644
--- a/cps/error_handler.py
+++ b/cps/error_handler.py
@@ -37,17 +37,31 @@ def error_http(error):
error_code="Error {0}".format(error.code),
error_name=error.name,
issue=False,
+ goto_admin=False,
unconfigured=not config.db_configured,
instance=config.config_calibre_web_title
), error.code
def internal_error(error):
+ if (isinstance(error.original_exception, AttributeError) and
+ error.original_exception.args[0] == "'NoneType' object has no attribute 'query'"
+ and error.original_exception.name == "query"):
+ return render_template('http_error.html',
+ error_code="Database Error",
+ error_name='The library used is invalid or has permission errors',
+ issue=False,
+ goto_admin=True,
+ unconfigured=False,
+ error_stack="",
+ instance=config.config_calibre_web_title
+ ), 500
return render_template('http_error.html',
error_code="500 Internal Server Error",
error_name='The server encountered an internal error and was unable to complete your '
'request. There is an error in the application.',
issue=True,
+ goto_admin=False,
unconfigured=False,
error_stack=traceback.format_exc().split("\n"),
instance=config.config_calibre_web_title
diff --git a/cps/file_helper.py b/cps/file_helper.py
index 9d5406d3..361709f8 100644
--- a/cps/file_helper.py
+++ b/cps/file_helper.py
@@ -34,6 +34,15 @@ except ImportError as e:
error = "Cannot import python-magic, checking uploaded file metadata will not work: {}".format(e)
+def get_mimetype(ext):
+ # overwrite some mimetypes for proper file detection
+ mimes = {".fb2": "text/xml",
+ ".cbz": "application/zip",
+ ".cbr": "application/x-rar"
+ }
+ return mimes.get(ext, mimetypes.types_map[ext])
+
+
def get_temp_dir():
tmp_dir = os.path.join(gettempdir(), 'calibre_web')
if not os.path.isdir(tmp_dir):
@@ -54,7 +63,7 @@ def validate_mime_type(file_buffer, allowed_extensions):
allowed_mimetypes = list()
for x in allowed_extensions:
try:
- allowed_mimetypes.append(mimetypes.types_map["." + x])
+ allowed_mimetypes.append(get_mimetype("." + x))
except KeyError:
log.error("Unkown mimetype for Extension: {}".format(x))
tmp_mime_type = mime.from_buffer(file_buffer.read())
diff --git a/cps/helper.py b/cps/helper.py
index 004e1b0e..8fa9bbac 100644
--- a/cps/helper.py
+++ b/cps/helper.py
@@ -25,12 +25,12 @@ import re
import regex
import shutil
import socket
-from datetime import datetime, timedelta
+from datetime import datetime, timedelta, timezone
import requests
import unidecode
from uuid import uuid4
-from flask import send_from_directory, make_response, abort, url_for, Response
+from flask import send_from_directory, make_response, abort, url_for, Response, request
from flask_babel import gettext as _
from flask_babel import lazy_gettext as N_
from flask_babel import get_locale
@@ -43,15 +43,16 @@ from markupsafe import escape
from urllib.parse import quote
try:
- import advocate
- from advocate.exceptions import UnacceptableAddressException
+ from . import cw_advocate
+ from .cw_advocate.exceptions import UnacceptableAddressException
use_advocate = True
-except ImportError:
+except ImportError as e:
use_advocate = False
advocate = requests
UnacceptableAddressException = MissingSchema = BaseException
from . import calibre_db, cli_param
+from .string_helper import strip_whitespaces
from .tasks.convert import TaskConvert
from . import logger, config, db, ub, fs
from . import gdriveutils as gd
@@ -118,7 +119,7 @@ def convert_book_format(book_id, calibre_path, old_book_format, new_book_format,
# Texts are not lazy translated as they are supposed to get send out as is
def send_test_mail(ereader_mail, user_name):
for email in ereader_mail.split(','):
- email = email.strip()
+ email = strip_whitespaces(email)
WorkerThread.add(user_name, TaskEmail(_('Calibre-Web Test Email'), None, None,
config.get_mail_settings(), email, N_("Test Email"),
_('This Email has been sent via Calibre-Web.')))
@@ -198,7 +199,7 @@ def check_send_to_ereader(entry):
# Check if a reader is existing for any of the book formats, if not, return empty list, otherwise return
# list with supported formats
def check_read_formats(entry):
- extensions_reader = {'TXT', 'PDF', 'EPUB', 'CBZ', 'CBT', 'CBR', 'DJVU', 'DJV'}
+ extensions_reader = {'TXT', 'PDF', 'EPUB', 'KEPUB', 'CBZ', 'CBT', 'CBR', 'DJVU', 'DJV'}
book_formats = list()
if len(entry.data):
for ele in iter(entry.data):
@@ -228,7 +229,7 @@ def send_mail(book_id, book_format, convert, ereader_mail, calibrepath, user_id)
link = '{}'.format(url_for('web.show_book', book_id=book_id), escape(book.title))
email_text = N_("%(book)s send to eReader", book=link)
for email in ereader_mail.split(','):
- email = email.strip()
+ email = strip_whitespaces(email)
WorkerThread.add(user_id, TaskEmail(_("Send to eReader"), book.path, converted_file_name,
config.get_mail_settings(), email,
email_text, _('This Email has been sent via Calibre-Web.'), book.id))
@@ -236,7 +237,7 @@ def send_mail(book_id, book_format, convert, ereader_mail, calibrepath, user_id)
return _("The requested file could not be read. Maybe wrong permissions?")
-def get_valid_filename(value, replace_whitespace=True, chars=128):
+def get_valid_filename(value, replace_whitespace=True, chars=128, force_unidecode=False):
"""
Returns the given string converted to a string that can be used for a clean
filename. Limits num characters to 128 max.
@@ -244,7 +245,7 @@ def get_valid_filename(value, replace_whitespace=True, chars=128):
if value[-1:] == '.':
value = value[:-1]+'_'
value = value.replace("/", "_").replace(":", "_").strip('\0')
- if config.config_unicode_filename:
+ if config.config_unicode_filename or force_unidecode:
value = (unidecode.unidecode(value))
if replace_whitespace:
# *+:\"/<>? are replaced by _
@@ -252,7 +253,7 @@ def get_valid_filename(value, replace_whitespace=True, chars=128):
# pipe has to be replaced with comma
value = re.sub(r'[|]+', ',', value, flags=re.U)
- value = value.encode('utf-8')[:chars].decode('utf-8', errors='ignore').strip()
+ value = strip_whitespaces(value.encode('utf-8')[:chars].decode('utf-8', errors='ignore'))
if not value:
raise ValueError("Filename cannot be empty")
@@ -267,11 +268,11 @@ def split_authors(values):
commas = author.count(',')
if commas == 1:
author_split = author.split(',')
- authors_list.append(author_split[1].strip() + ' ' + author_split[0].strip())
+ authors_list.append(strip_whitespaces(author_split[1]) + ' ' + strip_whitespaces(author_split[0]))
elif commas > 1:
- authors_list.extend([x.strip() for x in author.split(',')])
+ authors_list.extend([strip_whitespaces(x) for x in author.split(',')])
else:
- authors_list.append(author.strip())
+ authors_list.append(strip_whitespaces(author))
return authors_list
@@ -327,7 +328,7 @@ def edit_book_read_status(book_id, read_status=None):
ub.session_commit("Book {} readbit toggled".format(book_id))
else:
try:
- calibre_db.update_title_sort(config)
+ calibre_db.create_functions(config)
book = calibre_db.get_filtered_book(book_id)
book_read_status = getattr(book, 'custom_column_' + str(config.config_read_column))
if len(book_read_status):
@@ -417,8 +418,6 @@ def rename_author_path(first_author, old_author_dir, renamed_author, calibre_pat
# Create new_author_dir from parameter or from database
# Create new title_dir from database and add id
new_authordir = get_valid_filename(first_author, chars=96)
- # new_author = calibre_db.session.query(db.Authors).filter(db.Authors.name == renamed_author).first()
- # old_author_dir = get_valid_filename(old_author_name, chars=96)
new_author_rename_dir = get_valid_filename(renamed_author, chars=96)
if gdrive:
g_file = gd.getFileFromEbooksFolder(None, old_author_dir)
@@ -467,7 +466,6 @@ def update_dir_structure_file(book_id, calibre_path, original_filepath, new_auth
db_filename,
original_filepath,
path)
- # old_path = os.path.join(calibre_path, author_dir, new_title_dir).replace('\\', '/')
new_path = os.path.join(calibre_path, new_author_dir, new_title_dir).replace('\\', '/')
all_new_name = get_valid_filename(local_book.title, chars=42) + ' - ' \
+ get_valid_filename(new_author, chars=42)
@@ -476,8 +474,6 @@ def update_dir_structure_file(book_id, calibre_path, original_filepath, new_auth
if error:
return error
-
- # Rename all files from old names to new names
return False
@@ -489,7 +485,7 @@ def upload_new_file_gdrive(book_id, first_author, title, title_dir, original_fil
title_dir + " (" + str(book_id) + ")")
book.path = gdrive_path.replace("\\", "/")
gd.uploadFileToEbooksFolder(os.path.join(gdrive_path, file_name).replace("\\", "/"), original_filepath)
- return False # rename_files_on_change(first_author, renamed_author, local_book=book, gdrive=True)
+ return False
def update_dir_structure_gdrive(book_id, first_author):
@@ -517,24 +513,26 @@ def update_dir_structure_gdrive(book_id, first_author):
book.path = new_authordir + '/' + book.path.split('/')[1]
gd.updateDatabaseOnEdit(g_file['id'], book.path)
else:
- return _('File %(file)s not found on Google Drive', file=authordir) # file not found'''
+ return _('File %(file)s not found on Google Drive', file=authordir) # file not found
if titledir != new_titledir or authordir != new_authordir :
all_new_name = get_valid_filename(book.title, chars=42) + ' - ' \
+ get_valid_filename(new_authordir, chars=42)
rename_all_files_on_change(book, book.path, book.path, all_new_name, gdrive=True) # todo: Move filenames on gdrive
- # change location in database to new author/title path
- # book.path = os.path.join(authordir, new_titledir).replace('\\', '/')
return False
def move_files_on_change(calibre_path, new_author_dir, new_titledir, localbook, db_filename, original_filepath, path):
new_path = os.path.join(calibre_path, new_author_dir, new_titledir)
- # new_name = get_valid_filename(localbook.title, chars=96) + ' - ' + new_author_dir
try:
if original_filepath:
if not os.path.isdir(new_path):
os.makedirs(new_path)
- shutil.move(original_filepath, os.path.join(new_path, db_filename))
+ try:
+ shutil.move(original_filepath, os.path.join(new_path, db_filename))
+ except OSError:
+ log.error("Rename title from {} to {} failed with error, trying to "
+ "move without metadata".format(path, new_path))
+ shutil.move(original_filepath, os.path.join(new_path, db_filename), copy_function=shutil.copy)
log.debug("Moving title: %s to %s", original_filepath, new_path)
else:
# Check new path is not valid path
@@ -661,7 +659,7 @@ def check_email(email):
def check_username(username):
- username = username.strip()
+ username = strip_whitespaces(username)
if ub.session.query(ub.User).filter(func.lower(ub.User.name) == username.lower()).scalar():
log.error("This username is already taken")
raise Exception(_("This username is already taken"))
@@ -669,16 +667,18 @@ def check_username(username):
def valid_email(emails):
+ valid_emails = []
for email in emails.split(','):
- email = email.strip()
- # if email is not deleted
- if email:
- # Regex according to https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/email#validation
- if not re.search(r"^[\w.!#$%&'*+\\/=?^_`{|}~-]+@[\w](?:[\w-]{0,61}[\w])?(?:\.[\w](?:[\w-]{0,61}[\w])?)*$",
- email):
- log.error("Invalid Email address format")
- raise Exception(_("Invalid Email address format"))
- return email
+ email = strip_whitespaces(email)
+ # if email is not deleted
+ if email:
+ # Regex according to https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/email#validation
+ if not re.search(r"^[\w.!#$%&'*+\\/=?^_`{|}~-]+@[\w](?:[\w-]{0,61}[\w])?(?:\.[\w](?:[\w-]{0,61}[\w])?)*$",
+ email):
+ log.error("Invalid Email address format for {}".format(email))
+ raise Exception(_("Invalid Email address format"))
+ valid_emails.append(email)
+ return ",".join(valid_emails)
def valid_password(check_password):
@@ -788,24 +788,23 @@ def get_book_cover_internal(book, resolution=None):
def get_book_cover_thumbnail(book, resolution):
if book and book.has_cover:
- return ub.session \
- .query(ub.Thumbnail) \
- .filter(ub.Thumbnail.type == THUMBNAIL_TYPE_COVER) \
- .filter(ub.Thumbnail.entity_id == book.id) \
- .filter(ub.Thumbnail.resolution == resolution) \
- .filter(or_(ub.Thumbnail.expiration.is_(None), ub.Thumbnail.expiration > datetime.utcnow())) \
- .first()
+ return (ub.session
+ .query(ub.Thumbnail)
+ .filter(ub.Thumbnail.type == THUMBNAIL_TYPE_COVER)
+ .filter(ub.Thumbnail.entity_id == book.id)
+ .filter(ub.Thumbnail.resolution == resolution)
+ .filter(or_(ub.Thumbnail.expiration.is_(None), ub.Thumbnail.expiration > datetime.now(timezone.utc)))
+ .first())
def get_series_thumbnail_on_failure(series_id, resolution):
- book = calibre_db.session \
- .query(db.Books) \
- .join(db.books_series_link) \
- .join(db.Series) \
- .filter(db.Series.id == series_id) \
- .filter(db.Books.has_cover == 1) \
- .first()
-
+ book = (calibre_db.session
+ .query(db.Books)
+ .join(db.books_series_link)
+ .join(db.Series)
+ .filter(db.Series.id == series_id)
+ .filter(db.Books.has_cover == 1)
+ .first())
return get_book_cover_internal(book, resolution=resolution)
@@ -827,13 +826,13 @@ def get_series_cover_internal(series_id, resolution=None):
def get_series_thumbnail(series_id, resolution):
- return ub.session \
- .query(ub.Thumbnail) \
- .filter(ub.Thumbnail.type == THUMBNAIL_TYPE_SERIES) \
- .filter(ub.Thumbnail.entity_id == series_id) \
- .filter(ub.Thumbnail.resolution == resolution) \
- .filter(or_(ub.Thumbnail.expiration.is_(None), ub.Thumbnail.expiration > datetime.utcnow())) \
- .first()
+ return (ub.session
+ .query(ub.Thumbnail)
+ .filter(ub.Thumbnail.type == THUMBNAIL_TYPE_SERIES)
+ .filter(ub.Thumbnail.entity_id == series_id)
+ .filter(ub.Thumbnail.resolution == resolution)
+ .filter(or_(ub.Thumbnail.expiration.is_(None), ub.Thumbnail.expiration > datetime.now(timezone.utc)))
+ .first())
# saves book cover from url
@@ -842,7 +841,7 @@ def save_cover_from_url(url, book_path):
if cli_param.allow_localhost:
img = requests.get(url, timeout=(10, 200), allow_redirects=False) # ToDo: Error Handling
elif use_advocate:
- img = advocate.get(url, timeout=(10, 200), allow_redirects=False) # ToDo: Error Handling
+ img = cw_advocate.get(url, timeout=(10, 200), allow_redirects=False) # ToDo: Error Handling
else:
log.error("python module advocate is not installed but is needed")
return False, _("Python module 'advocate' is not installed but is needed for cover uploads")
@@ -906,7 +905,7 @@ def save_cover(img, book_path):
else:
imgc = Image(blob=io.BytesIO(img.content))
imgc.format = 'jpeg'
- imgc.transform_colorspace("rgb")
+ imgc.transform_colorspace("srgb")
img = imgc
except (BlobError, MissingDelegateError):
log.error("Invalid cover file content")
@@ -975,7 +974,8 @@ def do_download_file(book, book_format, client, data, headers):
# ToDo Check headers parameter
for element in headers:
response.headers[element[0]] = element[1]
- log.info('Downloading file: {}'.format(os.path.join(filename, book_name + "." + book_format)))
+ log.info('Downloading file: \'%s\' by %s - %s', format(os.path.join(filename, book_name + "." + book_format)),
+ current_user.name, request.headers.get('X-Forwarded-For', request.remote_addr))
return response
@@ -1105,11 +1105,14 @@ def get_download_link(book_id, book_format, client):
file_name = book.title
if len(book.authors) > 0:
file_name = file_name + ' - ' + book.authors[0].name
- file_name = get_valid_filename(file_name, replace_whitespace=False)
+ if client == "kindle":
+ file_name = get_valid_filename(file_name, replace_whitespace=False, force_unidecode=True)
+ else:
+ file_name = quote(get_valid_filename(file_name, replace_whitespace=False))
headers = Headers()
headers["Content-Type"] = mimetypes.types_map.get('.' + book_format, "application/octet-stream")
- headers["Content-Disposition"] = "attachment; filename=%s.%s; filename*=UTF-8''%s.%s" % (
- quote(file_name), book_format, quote(file_name), book_format)
+ headers["Content-Disposition"] = ('attachment; filename="{}.{}"; filename*=UTF-8\'\'{}.{}').format(
+ file_name, book_format, file_name, book_format)
return do_download_file(book, book_format, client, data1, headers)
else:
log.error("Book id {} not found for downloading".format(book_id))
diff --git a/cps/isoLanguages.py b/cps/isoLanguages.py
index 57473658..a34cd34a 100644
--- a/cps/isoLanguages.py
+++ b/cps/isoLanguages.py
@@ -15,24 +15,17 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
+import sys
from .iso_language_names import LANGUAGE_NAMES as _LANGUAGE_NAMES
from . import logger
+from .string_helper import strip_whitespaces
log = logger.create()
try:
- from iso639 import languages, __version__
- get = languages.get
-except ImportError:
from pycountry import languages as pyc_languages
- try:
- import pkg_resources
- __version__ = pkg_resources.get_distribution('pycountry').version + ' (PyCountry)'
- del pkg_resources
- except (ImportError, Exception):
- __version__ = "? (PyCountry)"
def _copy_fields(l):
l.part1 = getattr(l, 'alpha_2', None)
@@ -46,6 +39,11 @@ except ImportError:
return _copy_fields(pyc_languages.get(alpha_2=part1))
if name is not None:
return _copy_fields(pyc_languages.get(name=name))
+except ImportError as ex:
+ if sys.version_info >= (3, 12):
+ print("Python 3.12 isn't compatible with iso-639. Please install pycountry.")
+ from iso639 import languages
+ get = languages.get
def get_language_names(locale):
@@ -69,20 +67,20 @@ def get_language_name(locale, lang_code):
return name
-def get_language_codes(locale, language_names, remainder=None):
- language_names = set(x.strip().lower() for x in language_names if x)
+def get_language_code_from_name(locale, language_names, remainder=None):
+ language_names = set(strip_whitespaces(x).lower() for x in language_names if x)
lang = list()
- for k, v in get_language_names(locale).items():
- v = v.lower()
- if v in language_names:
- lang.append(k)
- language_names.remove(v)
+ for key, val in get_language_names(locale).items():
+ val = val.lower()
+ if val in language_names:
+ lang.append(key)
+ language_names.remove(val)
if remainder is not None and language_names:
remainder.extend(language_names)
return lang
-def get_valid_language_codes(locale, language_names, remainder=None):
+def get_valid_language_codes_from_code(locale, language_names, remainder=None):
lang = list()
if "" in language_names:
language_names.remove("")
@@ -103,6 +101,6 @@ def get_lang3(lang):
ret_value = lang
else:
ret_value = ""
- except KeyError:
+ except (KeyError, AttributeError):
ret_value = lang
return ret_value
diff --git a/cps/iso_language_names.py b/cps/iso_language_names.py
index 4b9a8ef9..9248443e 100644
--- a/cps/iso_language_names.py
+++ b/cps/iso_language_names.py
@@ -8138,6 +8138,384 @@ LANGUAGE_NAMES = {
"zul": "Zulu",
"zun": "Zuni"
},
+ "sl": {
+ "abk": "abhazijski",
+ "ace": "achinese",
+ "ach": "Acoli",
+ "ada": "Adangme",
+ "ady": "Adyghe",
+ "aar": "afarski",
+ "afh": "Afrihili",
+ "afr": "afrikanski",
+ "ain": "Ainu (Japan)",
+ "aka": "Akan",
+ "akk": "akadski",
+ "sqi": "albanščina",
+ "ale": "aleutski",
+ "amh": "amharski",
+ "anp": "Angika",
+ "ara": "arabski",
+ "arg": "aragonski",
+ "arp": "Arapaho",
+ "arw": "araukanski",
+ "hye": "armenščina",
+ "asm": "asamski",
+ "ast": "Asturian",
+ "ava": "avarski",
+ "ave": "avestijski jeziki",
+ "awa": "Awadhi",
+ "aym": "Aymara",
+ "aze": "azerbajdžanski",
+ "ban": "balijščina",
+ "bal": "belučijski",
+ "bam": "bambarski",
+ "bas": "Basa (Cameroon)",
+ "bak": "baškirski",
+ "eus": "baskovščina",
+ "bej": "Beja",
+ "bel": "beloruščina",
+ "bem": "Bemba (Zambia)",
+ "ben": "bengalščina",
+ "bit": "Berinomo",
+ "bho": "Bhojpuri",
+ "bik": "bikolščina",
+ "byn": "Bilin",
+ "bin": "Bini",
+ "bis": "bislama",
+ "zbl": "Blissymbols",
+ "bos": "bošnjaščina",
+ "bra": "Braj",
+ "bre": "bretonščina",
+ "bug": "buginščina",
+ "bul": "bolgarščina",
+ "bua": "burjatščina",
+ "mya": "burmanščina",
+ "cad": "kadajščina?",
+ "cat": "katalonščina",
+ "ceb": "cebuanščina",
+ "chg": "Chagatai",
+ "cha": "čamorščina",
+ "che": "čečenščina",
+ "chr": "čerokeščina",
+ "chy": "čejenščina",
+ "chb": "čibčevščina",
+ "zho": "kitajščina",
+ "chn": "Chinook jargon",
+ "chp": "čipevščina",
+ "cho": "Choctaw",
+ "cht": "Cholón",
+ "chk": "Chuukese",
+ "chv": "čuvaščina",
+ "cop": "koptščina",
+ "cor": "kornijščina",
+ "cos": "korzijščina",
+ "cre": "krijščina",
+ "mus": "Creek",
+ "hrv": "hrvaščina",
+ "ces": "češčina",
+ "dak": "Dakota",
+ "dan": "danski",
+ "dar": "Dargwa",
+ "del": "Delaware",
+ "div": "Dhivehi",
+ "din": "Dinka",
+ "doi": "Dogri (macrolanguage)",
+ "dgr": "Dogrib",
+ "dua": "Duala",
+ "nld": "nizozemščina",
+ "dse": "Dutch Sign Language",
+ "dyu": "Dyula",
+ "dzo": "dzongkha",
+ "efi": "Efik",
+ "egy": "egipčanski",
+ "eka": "Ekajuk",
+ "elx": "elamščina",
+ "eng": "angleščina",
+ "enu": "Enu",
+ "myv": "Erzya",
+ "epo": "esperanto",
+ "est": "estonščina",
+ "ewe": "evenščina",
+ "ewo": "Ewondo",
+ "fan": "Fang (Equatorial Guinea)",
+ "fat": "Fanti",
+ "fao": "ferščina",
+ "fij": "fidžijščina",
+ "fil": "Filipino",
+ "fin": "finščina",
+ "fon": "Fon",
+ "fra": "francoščina",
+ "fur": "furlanščina",
+ "ful": "fulščina",
+ "gaa": "Ga",
+ "glg": "Galician",
+ "lug": "Ganda",
+ "gay": "gajščina?",
+ "gba": "Gbaya (Central African Republic)",
+ "hmj": "Ge",
+ "gez": "etiopščina?",
+ "kat": "gruzinščina",
+ "deu": "nemški",
+ "gil": "gilbertščina",
+ "gon": "Gondi",
+ "gor": "Gorontalo",
+ "got": "gotščina",
+ "grb": "Grebo",
+ "grn": "gvaranijščina",
+ "guj": "gudžaratščina",
+ "gwi": "Gwichʼin",
+ "hai": "haidščina",
+ "hau": "havščina",
+ "haw": "havajščina",
+ "heb": "hebrejščina",
+ "her": "Herero",
+ "hil": "hilingajnonščina",
+ "hin": "hindijščina",
+ "hmo": "hiri motu",
+ "hit": "hetitščina",
+ "hmn": "hmonščina; miaojščina",
+ "hun": "madžarščina",
+ "hup": "hupščina",
+ "iba": "ibanščina",
+ "isl": "islandščina",
+ "ido": "Ido",
+ "ibo": "Igbo",
+ "ilo": "Iloko",
+ "ind": "indonezijščina",
+ "inh": "inguščina",
+ "ina": "interlingva",
+ "ile": "Interlingue",
+ "iku": "inuktituščina",
+ "ipk": "Inupiaq",
+ "gle": "irščina",
+ "ita": "italijanščina",
+ "jpn": "japonščina",
+ "jav": "javanščina",
+ "jrb": "Judeo-Arabic",
+ "jpr": "Judeo-Persian",
+ "kbd": "kabardinščina",
+ "kab": "Kabyle",
+ "kac": "Kachin",
+ "kal": "Kalaallisut",
+ "xal": "Kalmyk",
+ "kam": "Kamba (Kenya)",
+ "kan": "kanareščina",
+ "kau": "Kanuri",
+ "kaa": "Kara-Kalpak",
+ "krc": "Karachay-Balkar",
+ "krl": "Karelian",
+ "kas": "kašmirščina",
+ "csb": "Kashubian",
+ "kaw": "kavi",
+ "kaz": "kazaščina",
+ "kha": "Khasi",
+ "kho": "Khotanese",
+ "kik": "kikujščina",
+ "kmb": "Kimbundu",
+ "kin": "Kinyarwanda",
+ "kir": "kirgiščina",
+ "tlh": "Klingon",
+ "kom": "komijščina",
+ "kon": "Kongo",
+ "kok": "Konkani (macrolanguage)",
+ "kor": "korejščina",
+ "kos": "Kosraean",
+ "kpe": "Kpelle",
+ "kua": "Kuanyama",
+ "kum": "kumiščina",
+ "kur": "kurdščina",
+ "kru": "Kurukh",
+ "kut": "kutenajščina",
+ "lad": "ladinščina",
+ "lah": "Lahnda",
+ "lam": "Lamba",
+ "lao": "laoščina",
+ "lat": "latinščina",
+ "lav": "latvijščina",
+ "lez": "lezginščina",
+ "lim": "Limburgan",
+ "lin": "lingala",
+ "lit": "litvanščina",
+ "jbo": "Lojban",
+ "loz": "Lozi",
+ "lub": "Luba-Katanga",
+ "lua": "lubalulujščina",
+ "lui": "Luiseno",
+ "smj": "Lule Sami",
+ "lun": "Lunda",
+ "luo": "Luo (Kenya and Tanzania)",
+ "lus": "Lushai",
+ "ltz": "Luxembourgish",
+ "mkd": "makedonščina",
+ "mad": "madurščina",
+ "mag": "Magahi",
+ "mai": "Maithili",
+ "mak": "makasarščina",
+ "mlg": "malgaščina",
+ "msa": "Malay (macrolanguage)",
+ "mal": "malajalščina",
+ "mlt": "malteščina",
+ "mnc": "Manchu",
+ "mdr": "Mandar",
+ "man": "Mandingo",
+ "mni": "manipurščina",
+ "glv": "manska gelščina",
+ "mri": "maorščina",
+ "arn": "Mapudungun",
+ "mar": "maratščina",
+ "chm": "Mari (Russia)",
+ "mah": "Marshallese",
+ "mwr": "Marwari",
+ "mas": "masajščina",
+ "men": "Mende (Sierra Leone)",
+ "mic": "Mi'kmaq",
+ "min": "Minangkabau",
+ "mwl": "Mirandese",
+ "moh": "mohoščina",
+ "mdf": "Moksha",
+ "lol": "Mongo",
+ "mon": "mongolščina",
+ "mos": "mosanščina",
+ "mul": "Več jezikov",
+ "nqo": "N'Ko",
+ "nau": "Nauru",
+ "nav": "navaščina",
+ "ndo": "Ndonga",
+ "nap": "napolitanščina",
+ "nia": "niaščina",
+ "niu": "niuejščina",
+ "zxx": "No linguistic content",
+ "nog": "Nogai",
+ "nor": "norveščina",
+ "nob": "Norwegian Bokmål",
+ "nno": "norveščina; nynorsk",
+ "nym": "Nyamwezi",
+ "nya": "Nyanja",
+ "nyn": "Nyankole",
+ "nyo": "Nyoro",
+ "nzi": "Nzima",
+ "oci": "Occitan (post 1500)",
+ "oji": "Ojibwa",
+ "orm": "Oromo",
+ "osa": "Osage",
+ "oss": "Ossetian",
+ "pal": "Pahlavi",
+ "pau": "palavanščina",
+ "pli": "Pali",
+ "pam": "Pampanga",
+ "pag": "pangasinanščina",
+ "pan": "Panjabi",
+ "pap": "papiamentu",
+ "fas": "perzijščina",
+ "phn": "feničanščina",
+ "pon": "Pohnpeian",
+ "pol": "poljščina",
+ "por": "portugalđščina",
+ "pus": "paštu",
+ "que": "Quechua",
+ "raj": "radžastanščina",
+ "rap": "rapanujščina",
+ "ron": "romunščina",
+ "roh": "Romansh",
+ "rom": "romščina",
+ "run": "rundščina",
+ "rus": "ruščina",
+ "smo": "samoanščina",
+ "sad": "Sandawe",
+ "sag": "Sango",
+ "san": "sanskrt",
+ "sat": "santalščina",
+ "srd": "sardinščina",
+ "sas": "Sasak",
+ "sco": "škotščina",
+ "sel": "selkupščina",
+ "srp": "srbščina",
+ "srr": "Serer",
+ "shn": "šanščina",
+ "sna": "šonščina",
+ "scn": "sicilijanščina",
+ "sid": "Sidamo",
+ "bla": "Siksika",
+ "snd": "sindščina",
+ "sin": "Sinhala",
+ "den": "Slave (Athapascan)",
+ "slk": "slovaščina",
+ "slv": "slovenščina",
+ "sog": "Sogdian",
+ "som": "Somali",
+ "snk": "Soninke",
+ "spa": "španščina",
+ "srn": "Sranan Tongo",
+ "suk": "Sukuma",
+ "sux": "sumerščina",
+ "sun": "sundščina",
+ "sus": "susuamijščina?",
+ "swa": "Swahili (macrolanguage)",
+ "ssw": "svazijščina?",
+ "swe": "švedščina",
+ "syr": "sirščina",
+ "tgl": "tagaloščina",
+ "tah": "tahitijščina",
+ "tgk": "tadžiščina",
+ "tmh": "Tamashek",
+ "tam": "tamilščina",
+ "tat": "tatarščina",
+ "tel": "Telugu",
+ "ter": "Tereno",
+ "tet": "Tetum",
+ "tha": "tajščina",
+ "bod": "tibetanščina",
+ "tig": "Tigre",
+ "tir": "Tigrinya",
+ "tem": "Timne",
+ "tiv": "Tiv",
+ "tli": "Tlingit",
+ "tpi": "tok pisin",
+ "tkl": "Tokelau",
+ "tog": "Tonga (Nyasa)",
+ "ton": "tonganščina",
+ "tsi": "tsimšijščina",
+ "tso": "Tsonga",
+ "tsn": "Tswana",
+ "tum": "Tumbuka",
+ "tur": "turščina",
+ "tuk": "turkmenščina",
+ "tvl": "tuvalujščina",
+ "tyv": "Tuvinian",
+ "twi": "Twi",
+ "udm": "Udmurt",
+ "uga": "ugaritščina",
+ "uig": "ujgurščina",
+ "ukr": "ukrajinščina",
+ "umb": "Umbundu",
+ "mis": "Uncoded languages",
+ "und": "nedoločen",
+ "urd": "urdujščina",
+ "uzb": "uzbeščina",
+ "vai": "vajščina",
+ "ven": "Venda",
+ "vie": "vietnamščina",
+ "vol": "Volapük",
+ "vot": "votjaščina",
+ "wln": "valonščina",
+ "war": "Waray (Philippines)",
+ "was": "Washo",
+ "cym": "valižanščina",
+ "wal": "Wolaytta",
+ "wol": "Wolof",
+ "xho": "koščina",
+ "sah": "jakutščina",
+ "yao": "jaojščina",
+ "yap": "Yapese",
+ "yid": "jidiš",
+ "yor": "jorubščina",
+ "zap": "Zapotec",
+ "zza": "Zaza",
+ "zen": "Zenaga",
+ "zha": "Zhuang",
+ "zul": "zulujščina",
+ "zun": "Zuni"
+ },
"sv": {
"aar": "Afar",
"abk": "Abchaziska",
diff --git a/cps/jinjia.py b/cps/jinjia.py
index f0b3489d..cb51b2bc 100644
--- a/cps/jinjia.py
+++ b/cps/jinjia.py
@@ -27,7 +27,7 @@ import datetime
import mimetypes
from uuid import uuid4
-from flask import Blueprint, request, url_for
+from flask import Blueprint, request, url_for, g
from flask_babel import format_date
from .cw_login import current_user
@@ -43,6 +43,8 @@ def url_for_other_page(page):
args = request.view_args.copy()
args['page'] = page
for get, val in request.args.items():
+ if get == "page":
+ continue
args[get] = val
return url_for(request.endpoint, **args)
@@ -111,21 +113,12 @@ def yesno(value, yes, no):
@jinjia.app_template_filter('formatfloat')
def formatfloat(value, decimals=1):
- value = 0 if not value else value
- return ('{0:.' + str(decimals) + 'f}').format(value).rstrip('0').rstrip('.')
-
-
-@jinjia.app_template_filter('formatseriesindex')
-def formatseriesindex_filter(series_index):
- if series_index:
- try:
- if int(series_index) - series_index == 0:
- return int(series_index)
- else:
- return series_index
- except (ValueError, TypeError):
- return series_index
- return 0
+ if not value or (isinstance(value, str) and not value.is_numeric()):
+ return value
+ formated_value = ('{0:.' + str(decimals) + 'f}').format(value)
+ if formated_value.endswith('.' + "0" * decimals):
+ formated_value = formated_value.rstrip('0').rstrip('.')
+ return formated_value
@jinjia.app_template_filter('escapedlink')
@@ -179,3 +172,12 @@ def get_cover_srcset(series):
url = url_for('web.get_series_cover', series_id=series.id, resolution=shortname, c=cache_timestamp())
srcset.append(f'{url} {resolution}x')
return ', '.join(srcset)
+
+
+@jinjia.app_template_filter('music')
+def contains_music(book_formats):
+ result = False
+ for format in book_formats:
+ if format.format.lower() in g.constants.EXTENSIONS_AUDIO:
+ result = True
+ return result
diff --git a/cps/kobo.py b/cps/kobo.py
index 3e01f410..cfdc60c9 100644
--- a/cps/kobo.py
+++ b/cps/kobo.py
@@ -18,7 +18,7 @@
# along with this program. If not, see .
import base64
-import datetime
+from datetime import datetime, timezone
import os
import uuid
import zipfile
@@ -47,7 +47,7 @@ import requests
from . import config, logger, kobo_auth, db, calibre_db, helper, shelf as shelf_lib, ub, csrf, kobo_sync_status
from . import isoLanguages
from .epub import get_epub_layout
-from .constants import COVER_THUMBNAIL_SMALL
+from .constants import COVER_THUMBNAIL_SMALL, COVER_THUMBNAIL_MEDIUM, COVER_THUMBNAIL_LARGE
from .helper import get_download_link
from .services import SyncToken as SyncToken
from .web import download_required
@@ -106,24 +106,29 @@ def make_request_to_kobo_store(sync_token=None):
return store_response
-def redirect_or_proxy_request():
+def redirect_or_proxy_request(auth=False):
if config.config_kobo_proxy:
- if request.method == "GET":
- return redirect(get_store_url_for_current_request(), 307)
- else:
- # The Kobo device turns other request types into GET requests on redirects,
- # so we instead proxy to the Kobo store ourselves.
- store_response = make_request_to_kobo_store()
+ try:
+ if request.method == "GET":
+ alfa = redirect(get_store_url_for_current_request(), 307)
+ return alfa
+ else:
+ # The Kobo device turns other request types into GET requests on redirects,
+ # so we instead proxy to the Kobo store ourselves.
+ store_response = make_request_to_kobo_store()
- response_headers = store_response.headers
- for header_key in CONNECTION_SPECIFIC_HEADERS:
- response_headers.pop(header_key, default=None)
+ response_headers = store_response.headers
+ for header_key in CONNECTION_SPECIFIC_HEADERS:
+ response_headers.pop(header_key, default=None)
- return make_response(
- store_response.content, store_response.status_code, response_headers.items()
- )
- else:
- return make_response(jsonify({}))
+ return make_response(
+ store_response.content, store_response.status_code, response_headers.items()
+ )
+ except Exception as e:
+ log.error("Failed to receive or parse response from Kobo's endpoint: {}".format(e))
+ if auth:
+ return make_calibre_web_auth_response()
+ return make_response(jsonify({}))
def convert_to_kobo_timestamp_string(timestamp):
@@ -131,7 +136,7 @@ def convert_to_kobo_timestamp_string(timestamp):
return timestamp.strftime("%Y-%m-%dT%H:%M:%SZ")
except AttributeError as exc:
log.debug("Timestamp not valid: {}".format(exc))
- return datetime.datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ")
+ return datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
@kobo.route("/v1/library/sync")
@@ -150,15 +155,15 @@ def HandleSyncRequest():
# if no books synced don't respect sync_token
if not ub.session.query(ub.KoboSyncedBooks).filter(ub.KoboSyncedBooks.user_id == current_user.id).count():
- sync_token.books_last_modified = datetime.datetime.min
- sync_token.books_last_created = datetime.datetime.min
- sync_token.reading_state_last_modified = datetime.datetime.min
+ sync_token.books_last_modified = datetime.min
+ sync_token.books_last_created = datetime.min
+ sync_token.reading_state_last_modified = datetime.min
new_books_last_modified = sync_token.books_last_modified # needed for sync selected shelfs only
new_books_last_created = sync_token.books_last_created # needed to distinguish between new and changed entitlement
new_reading_state_last_modified = sync_token.reading_state_last_modified
- new_archived_last_modified = datetime.datetime.min
+ new_archived_last_modified = datetime.min
sync_results = []
# We reload the book database so that the user gets a fresh view of the library
@@ -323,7 +328,7 @@ def generate_sync_response(sync_token, sync_results, set_cont=False):
sync_token.to_headers(extra_headers)
# log.debug("Kobo Sync Content: {}".format(sync_results))
- # jsonify decodes the unicode string different to what kobo expects
+ # jsonify decodes the Unicode string different to what kobo expects
response = make_response(json.dumps(sync_results), extra_headers)
response.headers["Content-Type"] = "application/json; charset=utf-8"
return response
@@ -375,7 +380,7 @@ def create_book_entitlement(book, archived):
book_uuid = str(book.uuid)
return {
"Accessibility": "Full",
- "ActivePeriod": {"From": convert_to_kobo_timestamp_string(datetime.datetime.utcnow())},
+ "ActivePeriod": {"From": convert_to_kobo_timestamp_string(datetime.now(timezone.utc))},
"Created": convert_to_kobo_timestamp_string(book.timestamp),
"CrossRevisionId": book_uuid,
"Id": book_uuid,
@@ -423,7 +428,7 @@ def get_series(book):
def get_seriesindex(book):
- return book.series_index or 1
+ return book.series_index if isinstance(book.series_index, float) else 1
def get_language(book):
@@ -486,14 +491,16 @@ def get_metadata(book):
if get_series(book):
name = get_series(book)
- metadata["Series"] = {
- "Name": get_series(book),
- "Number": get_seriesindex(book), # ToDo Check int() ?
- "NumberFloat": float(get_seriesindex(book)),
- # Get a deterministic id based on the series name.
- "Id": str(uuid.uuid3(uuid.NAMESPACE_DNS, name)),
- }
-
+ try:
+ metadata["Series"] = {
+ "Name": get_series(book),
+ "Number": get_seriesindex(book), # ToDo Check int() ?
+ "NumberFloat": float(get_seriesindex(book)),
+ # Get a deterministic id based on the series name.
+ "Id": str(uuid.uuid3(uuid.NAMESPACE_DNS, name)),
+ }
+ except Exception as e:
+ print(e)
return metadata
@@ -725,7 +732,7 @@ def sync_shelves(sync_token, sync_results, only_kobo_shelves=False):
ub.session_commit()
-# Creates a Kobo "Tag" object from a ub.Shelf object
+# Creates a Kobo "Tag" object from an ub.Shelf object
def create_kobo_tag(shelf):
tag = {
"Created": convert_to_kobo_timestamp_string(shelf.created),
@@ -795,7 +802,7 @@ def HandleStateRequest(book_uuid):
if new_book_read_status == ub.ReadBook.STATUS_IN_PROGRESS \
and new_book_read_status != book_read.read_status:
book_read.times_started_reading += 1
- book_read.last_time_started_reading = datetime.datetime.utcnow()
+ book_read.last_time_started_reading = datetime.now(timezone.utc)
book_read.read_status = new_book_read_status
update_results_response["StatusInfoResult"] = {"Result": "Success"}
except (KeyError, TypeError, ValueError, StatementError):
@@ -903,7 +910,12 @@ def get_current_bookmark_response(current_bookmark):
@requires_kobo_auth
def HandleCoverImageRequest(book_uuid, width, height, Quality, isGreyscale):
try:
- resolution = None if int(height) > 1000 else COVER_THUMBNAIL_SMALL
+ if int(height) > 1000:
+ resolution = COVER_THUMBNAIL_LARGE
+ elif int(height) > 500:
+ resolution = COVER_THUMBNAIL_MEDIUM
+ else:
+ resolution = COVER_THUMBNAIL_SMALL
except ValueError:
log.error("Requested height %s of book %s is invalid" % (book_uuid, height))
resolution = COVER_THUMBNAIL_SMALL
@@ -948,7 +960,7 @@ def HandleBookDeletionRequest(book_uuid):
# TODO: Implement the following routes
@csrf.exempt
-@kobo.route("/v1/library/", methods=["DELETE", "GET"])
+@kobo.route("/v1/library/", methods=["DELETE", "GET", "POST"])
def HandleUnimplementedRequest(dummy=None):
log.debug("Unimplemented Library Request received: %s (request is forwarded to kobo if configured)",
request.base_url)
@@ -1035,7 +1047,7 @@ def HandleAuthRequest():
log.debug('Kobo Auth request')
if config.config_kobo_proxy:
try:
- return redirect_or_proxy_request()
+ return redirect_or_proxy_request(auth=True)
except Exception:
log.error("Failed to receive or parse response from Kobo's auth endpoint. Falling back to un-proxied mode.")
return make_calibre_web_auth_response()
@@ -1119,25 +1131,37 @@ def download_book(book_id, book_format):
def NATIVE_KOBO_RESOURCES():
return {
- "account_page": "https://secure.kobobooks.com/profile",
+ "account_page": "https://www.kobo.com/account/settings",
"account_page_rakuten": "https://my.rakuten.co.jp/",
+ "add_device": "https://storeapi.kobo.com/v1/user/add-device",
"add_entitlement": "https://storeapi.kobo.com/v1/library/{RevisionIds}",
"affiliaterequest": "https://storeapi.kobo.com/v1/affiliate",
+ "assets": "https://storeapi.kobo.com/v1/assets",
+ "audiobook": "https://storeapi.kobo.com/v1/products/audiobooks/{ProductId}",
+ "audiobook_detail_page": "https://www.kobo.com/{region}/{language}/audiobook/{slug}",
+ "audiobook_landing_page": "https://www.kobo.com/{region}/{language}/audiobooks",
+ "audiobook_preview": "https://storeapi.kobo.com/v1/products/audiobooks/{Id}/preview",
+ "audiobook_purchase_withcredit": "https://storeapi.kobo.com/v1/store/audiobook/{Id}",
"audiobook_subscription_orange_deal_inclusion_url": "https://authorize.kobo.com/inclusion",
"authorproduct_recommendations": "https://storeapi.kobo.com/v1/products/books/authors/recommendations",
"autocomplete": "https://storeapi.kobo.com/v1/products/autocomplete",
- "blackstone_header": {"key": "x-amz-request-payer", "value": "requester"},
+ "blackstone_header": {
+ "key": "x-amz-request-payer",
+ "value": "requester"
+ },
"book": "https://storeapi.kobo.com/v1/products/books/{ProductId}",
- "book_detail_page": "https://store.kobobooks.com/{culture}/ebook/{slug}",
- "book_detail_page_rakuten": "https://books.rakuten.co.jp/rk/{crossrevisionid}",
- "book_landing_page": "https://store.kobobooks.com/ebooks",
+ "book_detail_page": "https://www.kobo.com/{region}/{language}/ebook/{slug}",
+ "book_detail_page_rakuten": "http://books.rakuten.co.jp/rk/{crossrevisionid}",
+ "book_landing_page": "https://www.kobo.com/ebooks",
"book_subscription": "https://storeapi.kobo.com/v1/products/books/subscriptions",
+ "browse_history": "https://storeapi.kobo.com/v1/user/browsehistory",
"categories": "https://storeapi.kobo.com/v1/categories",
- "categories_page": "https://store.kobobooks.com/ebooks/categories",
+ "categories_page": "https://www.kobo.com/ebooks/categories",
"category": "https://storeapi.kobo.com/v1/categories/{CategoryId}",
"category_featured_lists": "https://storeapi.kobo.com/v1/categories/{CategoryId}/featured",
"category_products": "https://storeapi.kobo.com/v1/categories/{CategoryId}/products",
"checkout_borrowed_book": "https://storeapi.kobo.com/v1/library/borrow",
+ "client_authd_referral": "https://authorize.kobo.com/api/AuthenticatedReferral/client/v1/getLink",
"configuration_data": "https://storeapi.kobo.com/v1/configuration",
"content_access_book": "https://storeapi.kobo.com/v1/products/books/{ProductId}/access",
"customer_care_live_chat": "https://v2.zopim.com/widget/livechat.html?key=Y6gwUmnu4OATxN3Tli4Av9bYN319BTdO",
@@ -1148,92 +1172,109 @@ def NATIVE_KOBO_RESOURCES():
"delete_tag_items": "https://storeapi.kobo.com/v1/library/tags/{TagId}/items/delete",
"device_auth": "https://storeapi.kobo.com/v1/auth/device",
"device_refresh": "https://storeapi.kobo.com/v1/auth/refresh",
- "dictionary_host": "https://kbdownload1-a.akamaihd.net",
+ "dictionary_host": "https://ereaderfiles.kobo.com",
"discovery_host": "https://discovery.kobobooks.com",
+ "ereaderdevices": "https://storeapi.kobo.com/v2/products/EReaderDeviceFeeds",
"eula_page": "https://www.kobo.com/termsofuse?style=onestore",
"exchange_auth": "https://storeapi.kobo.com/v1/auth/exchange",
"external_book": "https://storeapi.kobo.com/v1/products/books/external/{Ids}",
- "facebook_sso_page":
- "https://authorize.kobo.com/signin/provider/Facebook/login?returnUrl=http://store.kobobooks.com/",
+ "facebook_sso_page": "https://authorize.kobo.com/signin/provider/Facebook/login?returnUrl=http://kobo.com/",
"featured_list": "https://storeapi.kobo.com/v1/products/featured/{FeaturedListId}",
"featured_lists": "https://storeapi.kobo.com/v1/products/featured",
"free_books_page": {
"EN": "https://www.kobo.com/{region}/{language}/p/free-ebooks",
"FR": "https://www.kobo.com/{region}/{language}/p/livres-gratuits",
"IT": "https://www.kobo.com/{region}/{language}/p/libri-gratuiti",
- "NL": "https://www.kobo.com/{region}/{language}/"
- "List/bekijk-het-overzicht-van-gratis-ebooks/QpkkVWnUw8sxmgjSlCbJRg",
- "PT": "https://www.kobo.com/{region}/{language}/p/livros-gratis",
+ "NL": "https://www.kobo.com/{region}/{language}/List/bekijk-het-overzicht-van-gratis-ebooks/QpkkVWnUw8sxmgjSlCbJRg",
+ "PT": "https://www.kobo.com/{region}/{language}/p/livros-gratis"
},
"fte_feedback": "https://storeapi.kobo.com/v1/products/ftefeedback",
+ "funnel_metrics": "https://storeapi.kobo.com/v1/funnelmetrics",
+ "get_download_keys": "https://storeapi.kobo.com/v1/library/downloadkeys",
+ "get_download_link": "https://storeapi.kobo.com/v1/library/downloadlink",
"get_tests_request": "https://storeapi.kobo.com/v1/analytics/gettests",
"giftcard_epd_redeem_url": "https://www.kobo.com/{storefront}/{language}/redeem-ereader",
"giftcard_redeem_url": "https://www.kobo.com/{storefront}/{language}/redeem",
- "help_page": "https://www.kobo.com/help",
- "kobo_audiobooks_enabled": "False",
+ "gpb_flow_enabled": "False",
+ "help_page": "http://www.kobo.com/help",
+ "image_host": "//cdn.kobo.com/book-images/",
+ "image_url_quality_template": "https://cdn.kobo.com/book-images/{ImageId}/{Width}/{Height}/{Quality}/{IsGreyscale}/image.jpg",
+ "image_url_template": "https://cdn.kobo.com/book-images/{ImageId}/{Width}/{Height}/false/image.jpg",
+ "kobo_audiobooks_credit_redemption": "False",
+ "kobo_audiobooks_enabled": "True",
"kobo_audiobooks_orange_deal_enabled": "False",
"kobo_audiobooks_subscriptions_enabled": "False",
- "kobo_nativeborrow_enabled": "True",
+ "kobo_display_price": "True",
+ "kobo_dropbox_link_account_enabled": "False",
+ "kobo_google_tax": "False",
+ "kobo_googledrive_link_account_enabled": "False",
+ "kobo_nativeborrow_enabled": "False",
+ "kobo_onedrive_link_account_enabled": "False",
"kobo_onestorelibrary_enabled": "False",
+ "kobo_privacyCentre_url": "https://www.kobo.com/privacy",
"kobo_redeem_enabled": "True",
"kobo_shelfie_enabled": "False",
- "kobo_subscriptions_enabled": "False",
- "kobo_superpoints_enabled": "False",
+ "kobo_subscriptions_enabled": "True",
+ "kobo_superpoints_enabled": "True",
"kobo_wishlist_enabled": "True",
"library_book": "https://storeapi.kobo.com/v1/user/library/books/{LibraryItemId}",
"library_items": "https://storeapi.kobo.com/v1/user/library",
"library_metadata": "https://storeapi.kobo.com/v1/library/{Ids}/metadata",
"library_prices": "https://storeapi.kobo.com/v1/user/library/previews/prices",
- "library_stack": "https://storeapi.kobo.com/v1/user/library/stacks/{LibraryItemId}",
+ "library_search": "https://storeapi.kobo.com/v1/library/search",
"library_sync": "https://storeapi.kobo.com/v1/library/sync",
- "love_dashboard_page": "https://store.kobobooks.com/{culture}/kobosuperpoints",
- "love_points_redemption_page":
- "https://store.kobobooks.com/{culture}/KoboSuperPointsRedemption?productId={ProductId}",
- "magazine_landing_page": "https://store.kobobooks.com/emagazines",
+ "love_dashboard_page": "https://www.kobo.com/{region}/{language}/kobosuperpoints",
+ "love_points_redemption_page": "https://www.kobo.com/{region}/{language}/KoboSuperPointsRedemption?productId={ProductId}",
+ "magazine_landing_page": "https://www.kobo.com/emagazines",
+ "more_sign_in_options": "https://authorize.kobo.com/signin?returnUrl=http://kobo.com/#allProviders",
+ "notebooks": "https://storeapi.kobo.com/api/internal/notebooks",
"notifications_registration_issue": "https://storeapi.kobo.com/v1/notifications/registration",
"oauth_host": "https://oauth.kobo.com",
- "overdrive_account": "https://auth.overdrive.com/account",
- "overdrive_library": "https://{libraryKey}.auth.overdrive.com/library",
- "overdrive_library_finder_host": "https://libraryfinder.api.overdrive.com",
- "overdrive_thunder_host": "https://thunder.api.overdrive.com",
- "password_retrieval_page": "https://www.kobobooks.com/passwordretrieval.html",
+ "password_retrieval_page": "https://www.kobo.com/passwordretrieval.html",
+ "personalizedrecommendations": "https://storeapi.kobo.com/v2/users/personalizedrecommendations",
+ "pocket_link_account_start": "https://authorize.kobo.com/{region}/{language}/linkpocket",
"post_analytics_event": "https://storeapi.kobo.com/v1/analytics/event",
+ "ppx_purchasing_url": "https://purchasing.kobo.com",
"privacy_page": "https://www.kobo.com/privacypolicy?style=onestore",
"product_nextread": "https://storeapi.kobo.com/v1/products/{ProductIds}/nextread",
"product_prices": "https://storeapi.kobo.com/v1/products/{ProductIds}/prices",
"product_recommendations": "https://storeapi.kobo.com/v1/products/{ProductId}/recommendations",
"product_reviews": "https://storeapi.kobo.com/v1/products/{ProductIds}/reviews",
"products": "https://storeapi.kobo.com/v1/products",
- "provider_external_sign_in_page":
- "https://authorize.kobo.com/ExternalSignIn/{providerName}?returnUrl=http://store.kobobooks.com/",
- "purchase_buy": "https://www.kobo.com/checkout/createpurchase/",
- "purchase_buy_templated": "https://www.kobo.com/{culture}/checkout/createpurchase/{ProductId}",
+ "productsv2": "https://storeapi.kobo.com/v2/products",
+ "provider_external_sign_in_page": "https://authorize.kobo.com/ExternalSignIn/{providerName}?returnUrl=http://kobo.com/",
"quickbuy_checkout": "https://storeapi.kobo.com/v1/store/quickbuy/{PurchaseId}/checkout",
"quickbuy_create": "https://storeapi.kobo.com/v1/store/quickbuy/purchase",
+ "rakuten_token_exchange": "https://storeapi.kobo.com/v1/auth/rakuten_token_exchange",
"rating": "https://storeapi.kobo.com/v1/products/{ProductId}/rating/{Rating}",
+ "reading_services_host": "https://readingservices.kobo.com",
"reading_state": "https://storeapi.kobo.com/v1/library/{Ids}/state",
- "redeem_interstitial_page": "https://store.kobobooks.com",
- "registration_page": "https://authorize.kobo.com/signup?returnUrl=http://store.kobobooks.com/",
+ "redeem_interstitial_page": "https://www.kobo.com",
+ "registration_page": "https://authorize.kobo.com/signup?returnUrl=http://kobo.com/",
"related_items": "https://storeapi.kobo.com/v1/products/{Id}/related",
"remaining_book_series": "https://storeapi.kobo.com/v1/products/books/series/{SeriesId}",
"rename_tag": "https://storeapi.kobo.com/v1/library/tags/{TagId}",
"review": "https://storeapi.kobo.com/v1/products/reviews/{ReviewId}",
"review_sentiment": "https://storeapi.kobo.com/v1/products/reviews/{ReviewId}/sentiment/{Sentiment}",
"shelfie_recommendations": "https://storeapi.kobo.com/v1/user/recommendations/shelfie",
- "sign_in_page": "https://authorize.kobo.com/signin?returnUrl=http://store.kobobooks.com/",
+ "sign_in_page": "https://authorize.kobo.com/signin?returnUrl=http://kobo.com/",
"social_authorization_host": "https://social.kobobooks.com:8443",
"social_host": "https://social.kobobooks.com",
- "stacks_host_productId": "https://store.kobobooks.com/collections/byproductid/",
"store_home": "www.kobo.com/{region}/{language}",
- "store_host": "store.kobobooks.com",
- "store_newreleases": "https://store.kobobooks.com/{culture}/List/new-releases/961XUjtsU0qxkFItWOutGA",
- "store_search": "https://store.kobobooks.com/{culture}/Search?Query={query}",
- "store_top50": "https://store.kobobooks.com/{culture}/ebooks/Top",
+ "store_host": "www.kobo.com",
+ "store_newreleases": "https://www.kobo.com/{region}/{language}/List/new-releases/961XUjtsU0qxkFItWOutGA",
+ "store_search": "https://www.kobo.com/{region}/{language}/Search?Query={query}",
+ "store_top50": "https://www.kobo.com/{region}/{language}/ebooks/Top",
+ "subs_landing_page": "https://www.kobo.com/{region}/{language}/plus",
+ "subs_management_page": "https://www.kobo.com/{region}/{language}/account/subscriptions",
+ "subs_plans_page": "https://www.kobo.com/{region}/{language}/plus/plans",
+ "subs_purchase_buy_templated": "https://www.kobo.com/{region}/{language}/Checkoutoption/{ProductId}/{TierId}",
"tag_items": "https://storeapi.kobo.com/v1/library/tags/{TagId}/Items",
"tags": "https://storeapi.kobo.com/v1/library/tags",
"taste_profile": "https://storeapi.kobo.com/v1/products/tasteprofile",
+ "terms_of_sale_page": "https://authorize.kobo.com/{region}/{language}/terms/termsofsale",
"update_accessibility_to_preview": "https://storeapi.kobo.com/v1/library/{EntitlementIds}/preview",
- "use_one_store": "False",
+ "use_one_store": "True",
"user_loyalty_benefits": "https://storeapi.kobo.com/v1/user/loyalty/benefits",
"user_platform": "https://storeapi.kobo.com/v1/user/platform",
"user_profile": "https://storeapi.kobo.com/v1/user/profile",
@@ -1241,6 +1282,6 @@ def NATIVE_KOBO_RESOURCES():
"user_recommendations": "https://storeapi.kobo.com/v1/user/recommendations",
"user_reviews": "https://storeapi.kobo.com/v1/user/reviews",
"user_wishlist": "https://storeapi.kobo.com/v1/user/wishlist",
- "userguide_host": "https://kbdownload1-a.akamaihd.net",
- "wishlist_page": "https://store.kobobooks.com/{region}/{language}/account/wishlist",
+ "userguide_host": "https://ereaderfiles.kobo.com",
+ "wishlist_page": "https://www.kobo.com/{region}/{language}/account/wishlist"
}
diff --git a/cps/kobo_auth.py b/cps/kobo_auth.py
index f99bf77c..53f35dcc 100644
--- a/cps/kobo_auth.py
+++ b/cps/kobo_auth.py
@@ -22,7 +22,7 @@
This module also includes research notes into the auth protocol used by Kobo devices.
Log-in:
-When first booting a Kobo device the user must sign into a Kobo (or affiliate) account.
+When first booting a Kobo device the user must log in to a Kobo (or affiliate) account.
Upon successful sign-in, the user is redirected to
https://auth.kobobooks.com/CrossDomainSignIn?id=
which serves the following response:
@@ -41,7 +41,7 @@ issue for a few years now https://www.mobileread.com/forums/showpost.php?p=34768
will still grant access given the userkey.)
Official Kobo Store Api authorization:
-* For most of the endpoints we care about (sync, metadata, tags, etc), the userKey is
+* For most of the endpoints we care about (sync, metadata, tags, etc.), the userKey is
passed in the x-kobo-userkey header, and is sufficient to authorize the API call.
* Some endpoints (e.g: AnnotationService) instead make use of Bearer tokens pass through
an authorization header. To get a BearerToken, the device makes a POST request to the
diff --git a/cps/kobo_sync_status.py b/cps/kobo_sync_status.py
index ef732aaa..357b84ef 100644
--- a/cps/kobo_sync_status.py
+++ b/cps/kobo_sync_status.py
@@ -19,7 +19,7 @@
from .cw_login import current_user
from . import ub
-import datetime
+from datetime import datetime, timezone
from sqlalchemy.sql.expression import or_, and_, true
# from sqlalchemy import exc
@@ -58,7 +58,7 @@ def change_archived_books(book_id, state=None, message=None):
archived_book = ub.ArchivedBook(user_id=current_user.id, book_id=book_id)
archived_book.is_archived = state if state else not archived_book.is_archived
- archived_book.last_modified = datetime.datetime.utcnow() # toDo. Check utc timestamp
+ archived_book.last_modified = datetime.now(timezone.utc) # toDo. Check utc timestamp
ub.session.merge(archived_book)
ub.session_commit(message)
diff --git a/cps/logger.py b/cps/logger.py
index 9aa076d4..7ce2dbc2 100644
--- a/cps/logger.py
+++ b/cps/logger.py
@@ -29,7 +29,7 @@ from .constants import CONFIG_DIR as _CONFIG_DIR
ACCESS_FORMATTER_GEVENT = Formatter("%(message)s")
ACCESS_FORMATTER_TORNADO = Formatter("[%(asctime)s] %(message)s")
-FORMATTER = Formatter("[%(asctime)s] %(levelname)5s {%(name)s:%(lineno)d} %(message)s")
+FORMATTER = Formatter("[%(asctime)s] %(levelname)5s {%(filename)s:%(lineno)d} %(message)s")
DEFAULT_LOG_LEVEL = logging.INFO
DEFAULT_LOG_FILE = os.path.join(_CONFIG_DIR, "calibre-web.log")
DEFAULT_ACCESS_LOG = os.path.join(_CONFIG_DIR, "access.log")
@@ -42,18 +42,12 @@ logging.addLevelName(logging.CRITICAL, "CRIT")
class _Logger(logging.Logger):
- def error_or_exception(self, message, stacklevel=2, *args, **kwargs):
+ def error_or_exception(self, message, stacklevel=1, *args, **kwargs):
is_debug = self.getEffectiveLevel() <= logging.DEBUG
- if sys.version_info > (3, 7):
- if is_debug:
- self.exception(message, stacklevel=stacklevel, *args, **kwargs)
- else:
- self.error(message, stacklevel=stacklevel, *args, **kwargs)
+ if not is_debug:
+ self.exception(message, stacklevel=stacklevel, *args, **kwargs)
else:
- if is_debug:
- self.exception(message, stack_info=True, *args, **kwargs)
- else:
- self.error(message, *args, **kwargs)
+ self.error(message, stacklevel=stacklevel, *args, **kwargs)
def debug_no_auth(self, message, *args, **kwargs):
message = message.strip("\r\n")
diff --git a/cps/main.py b/cps/main.py
index 1b3b40b4..44e563f9 100644
--- a/cps/main.py
+++ b/cps/main.py
@@ -31,6 +31,7 @@ def main():
app = create_app()
from .web import web
+ from .basic import basic
from .opds import opds
from .admin import admi
from .gdrive import gdrive
@@ -64,6 +65,7 @@ def main():
app.register_blueprint(search)
app.register_blueprint(tasks)
app.register_blueprint(web)
+ app.register_blueprint(basic)
app.register_blueprint(opds)
limiter.limit("3/minute", key_func=request_username)(opds)
app.register_blueprint(jinjia)
diff --git a/cps/metadata_provider/amazon.py b/cps/metadata_provider/amazon.py
index 843a9d76..5b07819c 100644
--- a/cps/metadata_provider/amazon.py
+++ b/cps/metadata_provider/amazon.py
@@ -38,14 +38,16 @@ class Amazon(Metadata):
__name__ = "Amazon"
__id__ = "amazon"
headers = {'upgrade-insecure-requests': '1',
- 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36',
- 'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
- 'sec-gpc': '1',
- 'sec-fetch-site': 'none',
- 'sec-fetch-mode': 'navigate',
- 'sec-fetch-user': '?1',
- 'sec-fetch-dest': 'document',
- 'accept-encoding': 'gzip, deflate, br',
+ 'user-agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:130.0) Gecko/20100101 Firefox/130.0',
+ 'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8',
+ 'Sec-Fetch-Site': 'same-origin',
+ 'Sec-Fetch-Mode': 'navigate',
+ 'Sec-Fetch-User': '?1',
+ 'Sec-Fetch-Dest': 'document',
+ 'Upgrade-Insecure-Requests': '1',
+ 'Alt-Used' : 'www.amazon.com',
+ 'Priority' : 'u=0, i',
+ 'accept-encoding': 'gzip, deflate, br, zstd',
'accept-language': 'en-US,en;q=0.9'}
session = requests.Session()
session.headers=headers
@@ -53,7 +55,6 @@ class Amazon(Metadata):
def search(
self, query: str, generic_cover: str = "", locale: str = "en"
) -> Optional[List[MetaRecord]]:
- #timer=time()
def inner(link, index) -> [dict, int]:
with self.session as session:
try:
@@ -61,11 +62,11 @@ class Amazon(Metadata):
r.raise_for_status()
except Exception as ex:
log.warning(ex)
- return None
+ return []
long_soup = BS(r.text, "lxml") #~4sec :/
- soup2 = long_soup.find("div", attrs={"cel_widget_id": "dpx-books-ppd_csm_instrumentation_wrapper"})
+ soup2 = long_soup.find("div", attrs={"cel_widget_id": "dpx-ppd_csm_instrumentation_wrapper"})
if soup2 is None:
- return None
+ return []
try:
match = MetaRecord(
title = "",
@@ -88,7 +89,7 @@ class Amazon(Metadata):
soup2.find("div", attrs={"data-feature-name": "bookDescription"}).stripped_strings)\
.replace("\xa0"," ")[:-9].strip().strip("\n")
except (AttributeError, TypeError):
- return None # if there is no description it is not a book and therefore should be ignored
+ return [] # if there is no description it is not a book and therefore should be ignored
try:
match.title = soup2.find("span", attrs={"id": "productTitle"}).text
except (AttributeError, TypeError):
@@ -107,13 +108,13 @@ class Amazon(Metadata):
except (AttributeError, ValueError):
match.rating = 0
try:
- match.cover = soup2.find("img", attrs={"class": "a-dynamic-image frontImage"})["src"]
+ match.cover = soup2.find("img", attrs={"class": "a-dynamic-image"})["src"]
except (AttributeError, TypeError):
match.cover = ""
return match, index
except Exception as e:
log.error_or_exception(e)
- return None
+ return []
val = list()
if self.active:
@@ -133,7 +134,7 @@ class Amazon(Metadata):
links_list = [next(filter(lambda i: "digital-text" in i["href"], x.findAll("a")))["href"] for x in
soup.findAll("div", attrs={"data-component-type": "s-search-result"})]
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
- fut = {executor.submit(inner, link, index) for index, link in enumerate(links_list[:5])}
- val = list(map(lambda x : x.result() ,concurrent.futures.as_completed(fut)))
+ fut = {executor.submit(inner, link, index) for index, link in enumerate(links_list[:3])}
+ val = list(map(lambda x : x.result(), concurrent.futures.as_completed(fut)))
result = list(filter(lambda x: x, val))
return [x[0] for x in sorted(result, key=itemgetter(1))] #sort by amazons listing order for best relevance
diff --git a/cps/metadata_provider/google.py b/cps/metadata_provider/google.py
index ba7e10af..df9c0dc2 100644
--- a/cps/metadata_provider/google.py
+++ b/cps/metadata_provider/google.py
@@ -54,7 +54,7 @@ class Google(Metadata):
results.raise_for_status()
except Exception as e:
log.warning(e)
- return None
+ return []
for result in results.json().get("items", []):
val.append(
self._parse_search_result(
diff --git a/cps/oauth.py b/cps/oauth.py
index 0caa61ec..22e92733 100644
--- a/cps/oauth.py
+++ b/cps/oauth.py
@@ -32,7 +32,7 @@ class OAuthBackend(SQLAlchemyBackend):
Stores and retrieves OAuth tokens using a relational database through
the `SQLAlchemy`_ ORM.
- .. _SQLAlchemy: https://www.sqlalchemy.org/
+ _SQLAlchemy: https://www.sqlalchemy.org/
"""
def __init__(self, model, session, provider_id,
user=None, user_id=None, user_required=None, anon_user=None,
diff --git a/cps/opds.py b/cps/opds.py
index 3d8c78b9..6dea544a 100644
--- a/cps/opds.py
+++ b/cps/opds.py
@@ -21,10 +21,10 @@
# along with this program. If not, see .
import datetime
-import json
+# import json
from urllib.parse import unquote_plus
-from flask import Blueprint, request, render_template, make_response, abort, Response, g
+from flask import Blueprint, request, render_template, make_response, abort, g, jsonify
from flask_babel import get_locale
from flask_babel import gettext as _
@@ -424,11 +424,8 @@ def feed_shelf(book_id):
@requires_basic_auth_if_no_ano
def opds_download_link(book_id, book_format):
if not auth.current_user().role_download():
- return abort(403)
- if "Kobo" in request.headers.get('User-Agent'):
- client = "kobo"
- else:
- client = ""
+ return abort(401)
+ client = "kobo" if "Kobo" in request.headers.get('User-Agent') else ""
return get_download_link(book_id, book_format.lower(), client)
@@ -454,7 +451,7 @@ def get_database_stats():
stat['authors'] = calibre_db.session.query(db.Authors).count()
stat['categories'] = calibre_db.session.query(db.Tags).count()
stat['series'] = calibre_db.session.query(db.Series).count()
- return Response(json.dumps(stat), mimetype="application/json")
+ return make_response(jsonify(stat))
@opds.route("/opds/thumb_240_240/")
diff --git a/cps/reverseproxy.py b/cps/reverseproxy.py
index 4acb8e45..887590bf 100644
--- a/cps/reverseproxy.py
+++ b/cps/reverseproxy.py
@@ -41,9 +41,9 @@ class ReverseProxied(object):
"""Wrap the application in this middleware and configure the
front-end server to add these headers, to let you quietly bind
this to a URL other than / and to an HTTP scheme that is
- different than what is used locally.
+ different from what is used locally.
- Code courtesy of: http://flask.pocoo.org/snippets/35/
+ Code courtesy of: https://flask.pocoo.org/snippets/35/
In nginx:
location /myprefix {
diff --git a/cps/search.py b/cps/search.py
index 6054ec9e..29dda16d 100644
--- a/cps/search.py
+++ b/cps/search.py
@@ -24,9 +24,9 @@ from flask_babel import format_date
from flask_babel import gettext as _
from sqlalchemy.sql.expression import func, not_, and_, or_, text, true
from sqlalchemy.sql.functions import coalesce
-from sqlalchemy import exists
from . import logger, db, calibre_db, config, ub
+from .string_helper import strip_whitespaces
from .usermanagement import login_required_if_no_ano
from .render_template import render_title_template
from .pagination import Pagination
@@ -244,7 +244,8 @@ def render_adv_search_results(term, offset=None, order=None, limit=None):
pagination = None
cc = calibre_db.get_cc_columns(config, filter_config_custom_read=True)
- calibre_db.session.connection().connection.connection.create_function("lower", 1, db.lcase)
+ calibre_db.create_functions()
+ # calibre_db.session.connection().connection.connection.create_function("lower", 1, db.lcase)
query = calibre_db.generate_linked_query(config.config_read_column, db.Books)
q = query.outerjoin(db.books_series_link, db.Books.id == db.books_series_link.c.book)\
.outerjoin(db.Series)\
@@ -257,21 +258,21 @@ def render_adv_search_results(term, offset=None, order=None, limit=None):
tags['include_' + element] = term.get('include_' + element)
tags['exclude_' + element] = term.get('exclude_' + element)
- author_name = term.get("author_name")
- book_title = term.get("book_title")
+ author_name = term.get("authors")
+ book_title = term.get("title")
publisher = term.get("publisher")
pub_start = term.get("publishstart")
pub_end = term.get("publishend")
rating_low = term.get("ratinghigh")
rating_high = term.get("ratinglow")
- description = term.get("comment")
+ description = term.get("comments")
read_status = term.get("read_status")
if author_name:
- author_name = author_name.strip().lower().replace(',', '|')
+ author_name = strip_whitespaces(author_name).lower().replace(',', '|')
if book_title:
- book_title = book_title.strip().lower()
+ book_title = strip_whitespaces(book_title).lower()
if publisher:
- publisher = publisher.strip().lower()
+ publisher = strip_whitespaces(publisher).lower()
search_term = []
cc_present = False
diff --git a/cps/search_metadata.py b/cps/search_metadata.py
index b818a87c..ae3c9faf 100644
--- a/cps/search_metadata.py
+++ b/cps/search_metadata.py
@@ -23,7 +23,7 @@ import json
import os
import sys
-from flask import Blueprint, Response, request, url_for
+from flask import Blueprint, request, url_for, make_response, jsonify
from .cw_login import current_user
from flask_babel import get_locale
from sqlalchemy.exc import InvalidRequestError, OperationalError
@@ -33,7 +33,6 @@ from cps.services.Metadata import Metadata
from . import constants, logger, ub, web_server
from .usermanagement import user_login_required
-# current_milli_time = lambda: int(round(time() * 1000))
meta = Blueprint("metadata", __name__)
@@ -90,7 +89,7 @@ def metadata_provider():
provider.append(
{"name": c.__name__, "active": ac, "initial": ac, "id": c.__id__}
)
- return Response(json.dumps(provider), mimetype="application/json")
+ return make_response(jsonify(provider))
@meta.route("/metadata/provider", methods=["POST"])
@@ -115,9 +114,7 @@ def metadata_change_active_provider(prov_name):
provider = next((c for c in cl if c.__id__ == prov_name), None)
if provider is not None:
data = provider.search(new_state.get("query", ""))
- return Response(
- json.dumps([asdict(x) for x in data]), mimetype="application/json"
- )
+ return make_response(jsonify([asdict(x) for x in data]))
return ""
@@ -130,7 +127,7 @@ def metadata_search():
locale = get_locale()
if query:
static_cover = url_for("static", filename="generic_cover.jpg")
- # start = current_milli_time()
+ # ret = cl[0].search(query, static_cover, locale)
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
meta = {
executor.submit(c.search, query, static_cover, locale): c
@@ -139,5 +136,4 @@ def metadata_search():
}
for future in concurrent.futures.as_completed(meta):
data.extend([asdict(x) for x in future.result() if x])
- # log.info({'Time elapsed {}'.format(current_milli_time()-start)})
- return Response(json.dumps(data), mimetype="application/json")
+ return make_response(jsonify(data))
diff --git a/cps/services/background_scheduler.py b/cps/services/background_scheduler.py
index 72991559..55b12df3 100644
--- a/cps/services/background_scheduler.py
+++ b/cps/services/background_scheduler.py
@@ -42,6 +42,7 @@ class BackgroundScheduler:
if cls._instance is None:
cls._instance = super(BackgroundScheduler, cls).__new__(cls)
cls.log = logger.create()
+ logger.logging.getLogger('tzlocal').setLevel(logger.logging.WARNING)
cls.scheduler = BScheduler()
cls.scheduler.start()
diff --git a/cps/services/gmail.py b/cps/services/gmail.py
index 5b0cdbe5..67b346a8 100644
--- a/cps/services/gmail.py
+++ b/cps/services/gmail.py
@@ -92,7 +92,7 @@ def send_messsage(token, msg):
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
service = build('gmail', 'v1', credentials=creds)
- message_as_bytes = msg.as_bytes() # the message should converted from string to bytes.
+ message_as_bytes = msg.as_bytes() # the message should be converted from string to bytes.
message_as_base64 = base64.urlsafe_b64encode(message_as_bytes) # encode in base64 (printable letters coding)
raw = message_as_base64.decode() # convert to something JSON serializable
body = {'raw': raw}
diff --git a/cps/services/goodreads_support.py b/cps/services/goodreads_support.py
index b3b7bdef..c3bdbacb 100644
--- a/cps/services/goodreads_support.py
+++ b/cps/services/goodreads_support.py
@@ -117,7 +117,7 @@ def get_author_info(author_name):
def get_other_books(author_info, library_books=None):
- # Get all identifiers (ISBN, Goodreads, etc) and filter author's books by that list so we show fewer duplicates
+ # Get all identifiers (ISBN, Goodreads, etc.) and filter author's books by that list so we show fewer duplicates
# Note: Not all images will be shown, even though they're available on Goodreads.com.
# See https://www.goodreads.com/topic/show/18213769-goodreads-book-images
diff --git a/cps/services/worker.py b/cps/services/worker.py
index dce3da79..a804f633 100644
--- a/cps/services/worker.py
+++ b/cps/services/worker.py
@@ -199,7 +199,7 @@ class CalibreTask:
self.run(*args)
except Exception as ex:
self._handleError(str(ex))
- log.error_or_exception(ex)
+ log.exception(ex)
self.end_time = datetime.now()
@@ -235,7 +235,7 @@ class CalibreTask:
@property
def dead(self):
- """Determines whether or not this task can be garbage collected
+ """Determines whether this task can be garbage collected
We have a separate dictating this because there may be certain tasks that want to override this
"""
diff --git a/cps/shelf.py b/cps/shelf.py
index c8f43446..e4f93909 100644
--- a/cps/shelf.py
+++ b/cps/shelf.py
@@ -21,7 +21,7 @@
# along with this program. If not, see .
import sys
-from datetime import datetime
+from datetime import datetime, timezone
from flask import Blueprint, flash, redirect, request, url_for, abort
from flask_babel import gettext as _
@@ -80,7 +80,7 @@ def add_to_shelf(shelf_id, book_id):
return "%s is a invalid Book Id. Could not be added to Shelf" % book_id, 400
shelf.books.append(ub.BookShelf(shelf=shelf.id, book_id=book_id, order=maxOrder + 1))
- shelf.last_modified = datetime.utcnow()
+ shelf.last_modified = datetime.now(timezone.utc)
try:
ub.session.merge(shelf)
ub.session.commit()
@@ -139,7 +139,7 @@ def search_to_shelf(shelf_id):
for book in books_for_shelf:
maxOrder += 1
shelf.books.append(ub.BookShelf(shelf=shelf.id, book_id=book, order=maxOrder))
- shelf.last_modified = datetime.utcnow()
+ shelf.last_modified = datetime.now(timezone.utc)
try:
ub.session.merge(shelf)
ub.session.commit()
@@ -185,7 +185,7 @@ def remove_from_shelf(shelf_id, book_id):
try:
ub.session.delete(book_shelf)
- shelf.last_modified = datetime.utcnow()
+ shelf.last_modified = datetime.now(timezone.utc)
ub.session.commit()
except (OperationalError, InvalidRequestError) as e:
ub.session.rollback()
@@ -250,7 +250,7 @@ def show_simpleshelf(shelf_id):
return render_show_shelf(2, shelf_id, 1, None)
-@shelf.route("/shelf/", defaults={"sort_param": "order", 'page': 1})
+@shelf.route("/shelf/", defaults={"sort_param": "stored", 'page': 1})
@shelf.route("/shelf//", defaults={'page': 1})
@shelf.route("/shelf///")
@login_required_if_no_ano
@@ -271,7 +271,7 @@ def order_shelf(shelf_id):
for book in books_in_shelf:
setattr(book, 'order', to_save[str(book.book_id)])
counter += 1
- # if order different from before -> shelf.last_modified = datetime.utcnow()
+ # if order different from before -> shelf.last_modified = datetime.now(timezone.utc)
try:
ub.session.commit()
except (OperationalError, InvalidRequestError) as e:
@@ -418,29 +418,37 @@ def change_shelf_order(shelf_id, order):
def render_show_shelf(shelf_type, shelf_id, page_no, sort_param):
shelf = ub.session.query(ub.Shelf).filter(ub.Shelf.id == shelf_id).first()
-
+ status = current_user.get_view_property("shelf", 'man')
# check user is allowed to access shelf
if shelf and check_shelf_view_permissions(shelf):
if shelf_type == 1:
- # order = [ub.BookShelf.order.asc()]
- if sort_param == 'pubnew':
- change_shelf_order(shelf_id, [db.Books.pubdate.desc()])
- if sort_param == 'pubold':
- change_shelf_order(shelf_id, [db.Books.pubdate])
- if sort_param == 'abc':
- change_shelf_order(shelf_id, [db.Books.sort])
- if sort_param == 'zyx':
- change_shelf_order(shelf_id, [db.Books.sort.desc()])
- if sort_param == 'new':
- change_shelf_order(shelf_id, [db.Books.timestamp.desc()])
- if sort_param == 'old':
- change_shelf_order(shelf_id, [db.Books.timestamp])
- if sort_param == 'authaz':
- change_shelf_order(shelf_id, [db.Books.author_sort.asc(), db.Series.name, db.Books.series_index])
- if sort_param == 'authza':
- change_shelf_order(shelf_id, [db.Books.author_sort.desc(),
- db.Series.name.desc(),
- db.Books.series_index.desc()])
+ if status != 'on':
+ if sort_param == 'stored':
+ sort_param = current_user.get_view_property("shelf", 'stored')
+ else:
+ current_user.set_view_property("shelf", 'stored', sort_param)
+ if sort_param == 'pubnew':
+ change_shelf_order(shelf_id, [db.Books.pubdate.desc()])
+ if sort_param == 'pubold':
+ change_shelf_order(shelf_id, [db.Books.pubdate])
+ if sort_param == 'shelfnew':
+ change_shelf_order(shelf_id, [ub.BookShelf.date_added.desc()])
+ if sort_param == 'shelfold':
+ change_shelf_order(shelf_id, [ub.BookShelf.date_added])
+ if sort_param == 'abc':
+ change_shelf_order(shelf_id, [db.Books.sort])
+ if sort_param == 'zyx':
+ change_shelf_order(shelf_id, [db.Books.sort.desc()])
+ if sort_param == 'new':
+ change_shelf_order(shelf_id, [db.Books.timestamp.desc()])
+ if sort_param == 'old':
+ change_shelf_order(shelf_id, [db.Books.timestamp])
+ if sort_param == 'authaz':
+ change_shelf_order(shelf_id, [db.Books.author_sort.asc(), db.Series.name, db.Books.series_index])
+ if sort_param == 'authza':
+ change_shelf_order(shelf_id, [db.Books.author_sort.desc(),
+ db.Series.name.desc(),
+ db.Books.series_index.desc()])
page = "shelf.html"
pagesize = 0
else:
@@ -453,7 +461,7 @@ def render_show_shelf(shelf_type, shelf_id, page_no, sort_param):
[ub.BookShelf.order.asc()],
True, config.config_read_column,
ub.BookShelf, ub.BookShelf.book_id == db.Books.id)
- # delete chelf entries where book is not existent anymore, can happen if book is deleted outside calibre-web
+ # delete shelf entries where book is not existent anymore, can happen if book is deleted outside calibre-web
wrong_entries = calibre_db.session.query(ub.BookShelf) \
.join(db.Books, ub.BookShelf.book_id == db.Books.id, isouter=True) \
.filter(db.Books.id == None).all()
@@ -472,7 +480,9 @@ def render_show_shelf(shelf_type, shelf_id, page_no, sort_param):
pagination=pagination,
title=_("Shelf: '%(name)s'", name=shelf.name),
shelf=shelf,
- page="shelf")
+ page="shelf",
+ status=status,
+ order=sort_param)
else:
flash(_("Error opening shelf. Shelf does not exist or is not accessible"), category="error")
return redirect(url_for("web.index"))
diff --git a/cps/static/css/basic.css b/cps/static/css/basic.css
new file mode 100644
index 00000000..7fe9e5b8
--- /dev/null
+++ b/cps/static/css/basic.css
@@ -0,0 +1,108 @@
+body {
+ margin: 0;
+}
+
+nav {
+ height: 75px;
+ padding: 5px 20px;
+ width: 100%;
+ display: table;
+ box-sizing: border-box;
+ border-bottom: 1px solid black;
+}
+
+nav > * {
+ display: inline-block;
+ display: table-cell;
+ vertical-align: middle;
+ float: none;
+ text-align: center;
+ width: auto;
+}
+
+nav > *:first-child {
+ text-align: left;
+ width: 1%;
+}
+
+.theme{
+ text-align: center;
+ margin: 10px;
+}
+nav > *:last-child {
+ text-align: right;
+ width: 1%;
+}
+
+nav > a {
+ color: black;
+ margin: 0 20px;
+}
+
+.search {
+ margin: auto auto;
+}
+
+form > input {
+ width: 18ch;
+ padding-left: 4px;
+}
+
+form > * {
+ height: 50px;
+ background-color: white;
+ border-radius: 0;
+ border: 1px solid #ccc;
+ padding: 0;
+ margin: 0;
+ display: inline-block;
+ vertical-align: top;
+}
+
+form > span {
+ margin-left: -5px;
+}
+
+button {
+ border: none;
+ padding: 0 10px;
+ margin: 0;
+ width: 160px;
+ height: 100%;
+ background-color: white;
+}
+
+.body {
+ padding: 5px 20px;
+}
+
+a {
+ color: black;
+}
+
+img {
+ width: 150px;
+ height: 250px;
+ object-fit: cover;
+}
+
+.listing {
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ margin-right: 20px;
+}
+
+.pagination {
+ padding: 10px 0;
+ height: 20px;
+ font-weight: 700;
+}
+
+.pagination > div {
+ float: left;
+}
+
+.pagination > div:last-child {
+ float: right;
+}
diff --git a/cps/static/css/caliBlur.css b/cps/static/css/caliBlur.css
index 3647b871..c5e96bf4 100644
--- a/cps/static/css/caliBlur.css
+++ b/cps/static/css/caliBlur.css
@@ -3268,6 +3268,10 @@ div.btn-group[role=group][aria-label="Download, send to Kindle, reading"] > div.
left: auto !important
}
+ul.dropdown-menu.offscreen {
+ margin: 2px -160px 0
+}
+
div.btn-group[role=group][aria-label="Download, send to Kindle, reading"] .dropdown-menu.offscreen {
position: fixed;
top: 120px;
@@ -4333,6 +4337,7 @@ body.advanced_search > div.container-fluid > div.row-fluid > div.col-sm-10 > div
.navbar-right > li > ul.dropdown-menu.offscreen {
right: -10px
+
}
.login .plexBack, body.login > div.container-fluid > div.row-fluid > div.col-sm-2, body.login > div.navbar.navbar-default.navbar-static-top > div > form {
@@ -7148,12 +7153,11 @@ body.edituser.admin > div.container-fluid > div.row-fluid > div.col-sm-10 > div.
}
body.editbook > div.container-fluid > div.row-fluid > div.col-sm-10 > div.col-sm-3, body.upload > div.container-fluid > div.row-fluid > div.col-sm-10 > div.col-sm-3 {
- max-width: 130px;
- width: 130px;
- height: 180px;
- margin: 0;
+ position: relative;
+ max-width: unset;
+ width: 100%;
+ height: unset;
padding: 15px;
- position: absolute
}
body.editbook > div.container-fluid > div.row-fluid > div.col-sm-10 > form > div.col-sm-9, body.upload > div.container-fluid > div.row-fluid > div.col-sm-10 > form > div.col-sm-9 {
@@ -7162,10 +7166,6 @@ body.edituser.admin > div.container-fluid > div.row-fluid > div.col-sm-10 > div.
width: 100%
}
- body.editbook > div.container-fluid > div.row-fluid > div.col-sm-10 > form > div.col-sm-9 > .form-group:nth-child(1), body.editbook > div.container-fluid > div.row-fluid > div.col-sm-10 > form > div.col-sm-9 > .form-group:nth-child(2), body.upload > div.container-fluid > div.row-fluid > div.col-sm-10 > form > div.col-sm-9 > .form-group:nth-child(1), body.upload > div.container-fluid > div.row-fluid > div.col-sm-10 > form > div.col-sm-9 > .form-group:nth-child(2) {
- padding-left: 120px
- }
-
#deleteButton, body.editbook > div.container-fluid > div.row-fluid > div.col-sm-10 > div.col-sm-3 > div.text-center > #delete, body.upload > div.container-fluid > div.row-fluid > div.col-sm-10 > div.col-sm-3 > div.text-center > #delete {
top: 48px;
height: 42px
@@ -7951,3 +7951,5 @@ div.comments[data-readmore] {
transition: height 300ms;
overflow: hidden
}
+
+.dropdown-menu > .offscreen
diff --git a/cps/static/css/epub_themes.css b/cps/static/css/epub_themes.css
index 16c27805..b9cbcedb 100644
--- a/cps/static/css/epub_themes.css
+++ b/cps/static/css/epub_themes.css
@@ -15,5 +15,5 @@
.blackTheme {
background: #000;
- color: #fff
+ color: #fff;
}
\ No newline at end of file
diff --git a/cps/static/css/libs/typeahead.css b/cps/static/css/libs/typeahead.css
index fcc17a5b..b00303fe 100644
--- a/cps/static/css/libs/typeahead.css
+++ b/cps/static/css/libs/typeahead.css
@@ -157,7 +157,6 @@ fieldset[disabled] .twitter-typeahead .tt-input {
list-style: none;
font-size: 14px;
background-color: #ffffff;
- border: 1px solid #cccccc;
border: 1px solid rgba(0, 0, 0, 0.15);
border-radius: 4px;
-webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
diff --git a/cps/static/css/main.css b/cps/static/css/main.css
index 0dc0532c..571f546c 100644
--- a/cps/static/css/main.css
+++ b/cps/static/css/main.css
@@ -77,7 +77,6 @@ body {
}
#panels a {
- visibility: hidden;
width: 18px;
height: 20px;
overflow: hidden;
@@ -512,12 +511,12 @@ input:-moz-placeholder { color: #454545; }
position: fixed;
top: 50%;
left: 50%;
- width: 630px;
+ transform: translate(-50%, -50%);
+ width: 100vw;
height: auto;
+ max-width: 630px;
z-index: 2000;
visibility: hidden;
- margin-left: -320px;
- margin-top: -160px;
}
.overlay {
diff --git a/cps/static/js/caliBlur.js b/cps/static/js/caliBlur.js
old mode 100755
new mode 100644
diff --git a/cps/static/js/edit_books.js b/cps/static/js/edit_books.js
index c1eb319d..54f615fb 100644
--- a/cps/static/js/edit_books.js
+++ b/cps/static/js/edit_books.js
@@ -3,9 +3,9 @@
*/
/* global Bloodhound, language, Modernizr, tinymce, getPath */
-if ($("#description").length) {
+if ($("#comments").length && typeof tinymce !== "undefined") {
tinymce.init({
- selector: "#description",
+ selector: "#comments",
plugins: 'code',
branding: false,
menubar: "edit view format",
@@ -93,7 +93,7 @@ var authors = new Bloodhound({
},
});
-$(".form-group #bookAuthor").typeahead(
+$(".form-group #authors").typeahead(
{
highlight: true,
minLength: 1,
@@ -243,13 +243,13 @@ $("#search").on("change input.typeahead:selected", function(event) {
});
});
-$("#btn-upload-format").on("change", function () {
+/*$("#btn-upload-format").on("change", function () {
var filename = $(this).val();
if (filename.substring(3, 11) === "fakepath") {
filename = filename.substring(12);
} // Remove c:\fake at beginning from localhost chrome
$("#upload-format").text(filename);
-});
+});*/
$("#btn-upload-cover").on("change", function () {
var filename = $(this).val();
@@ -261,8 +261,8 @@ $("#btn-upload-cover").on("change", function () {
$("#xchange").click(function () {
this.blur();
- var title = $("#book_title").val();
- $("#book_title").val($("#bookAuthor").val());
- $("#bookAuthor").val(title);
+ var title = $("#title").val();
+ $("#title").val($("#authors").val());
+ $("#authors").val(title);
});
diff --git a/cps/static/js/get_meta.js b/cps/static/js/get_meta.js
index 43a40fa6..df4119dc 100644
--- a/cps/static/js/get_meta.js
+++ b/cps/static/js/get_meta.js
@@ -38,12 +38,12 @@ $(function () {
}
function populateForm (book) {
- tinymce.get("description").setContent(book.description);
+ tinymce.get("comments").setContent(book.description);
var uniqueTags = getUniqueValues('tags', book)
var uniqueLanguages = getUniqueValues('languages', book)
var ampSeparatedAuthors = (book.authors || []).join(" & ");
- $("#bookAuthor").val(ampSeparatedAuthors);
- $("#book_title").val(book.title);
+ $("#authors").val(ampSeparatedAuthors);
+ $("#title").val(book.title);
$("#tags").val(uniqueTags.join(", "));
$("#languages").val(uniqueLanguages.join(", "));
$("#rating").data("rating").setValue(Math.round(book.rating));
@@ -172,7 +172,7 @@ $(function () {
$("#get_meta").click(function () {
populate_provider();
- var bookTitle = $("#book_title").val();
+ var bookTitle = $("#title").val();
$("#keyword").val(bookTitle);
keyword = bookTitle;
doSearch(bookTitle);
diff --git a/cps/static/js/libs/bootstrap-datepicker/locales/bootstrap-datepicker.sl.min.js b/cps/static/js/libs/bootstrap-datepicker/locales/bootstrap-datepicker.sl.min.js
new file mode 100644
index 00000000..831cf739
--- /dev/null
+++ b/cps/static/js/libs/bootstrap-datepicker/locales/bootstrap-datepicker.sl.min.js
@@ -0,0 +1 @@
+!function(a){a.fn.datepicker.dates.sl={days:["Nedelja","Ponedeljek","Torek","Sreda","Četrtek","Petek","Sobota"],daysShort:["Ned","Pon","Tor","Sre","Čet","Pet","Sob"],daysMin:["Ne","Po","To","Sr","Če","Pe","So"],months:["Januar","Februar","Marec","April","Maj","Junij","Julij","Avgust","September","Oktober","November","December"],monthsShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Avg","Sep","Okt","Nov","Dec"],today:"Danes",weekStart:1}}(jQuery);
\ No newline at end of file
diff --git a/cps/static/js/libs/pdf.mjs b/cps/static/js/libs/pdf.js
similarity index 80%
rename from cps/static/js/libs/pdf.mjs
rename to cps/static/js/libs/pdf.js
index 7906d1a9..13face72 100644
--- a/cps/static/js/libs/pdf.mjs
+++ b/cps/static/js/libs/pdf.js
@@ -2,7 +2,7 @@
* @licstart The following is the entire license notice for the
* JavaScript code in this page
*
- * Copyright 2023 Mozilla Foundation
+ * Copyright 2024 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,8 +20,4712 @@
* JavaScript code in this page
*/
-/******/ // The require scope
-/******/ var __webpack_require__ = {};
+/******/ var __webpack_modules__ = ({
+
+/***/ 9306:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var isCallable = __webpack_require__(4901);
+var tryToString = __webpack_require__(6823);
+
+var $TypeError = TypeError;
+
+// `Assert: IsCallable(argument) is true`
+module.exports = function (argument) {
+ if (isCallable(argument)) return argument;
+ throw new $TypeError(tryToString(argument) + ' is not a function');
+};
+
+
+/***/ }),
+
+/***/ 3506:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var isPossiblePrototype = __webpack_require__(3925);
+
+var $String = String;
+var $TypeError = TypeError;
+
+module.exports = function (argument) {
+ if (isPossiblePrototype(argument)) return argument;
+ throw new $TypeError("Can't set " + $String(argument) + ' as a prototype');
+};
+
+
+/***/ }),
+
+/***/ 7080:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var has = (__webpack_require__(4402).has);
+
+// Perform ? RequireInternalSlot(M, [[SetData]])
+module.exports = function (it) {
+ has(it);
+ return it;
+};
+
+
+/***/ }),
+
+/***/ 679:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var isPrototypeOf = __webpack_require__(1625);
+
+var $TypeError = TypeError;
+
+module.exports = function (it, Prototype) {
+ if (isPrototypeOf(Prototype, it)) return it;
+ throw new $TypeError('Incorrect invocation');
+};
+
+
+/***/ }),
+
+/***/ 8551:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var isObject = __webpack_require__(34);
+
+var $String = String;
+var $TypeError = TypeError;
+
+// `Assert: Type(argument) is Object`
+module.exports = function (argument) {
+ if (isObject(argument)) return argument;
+ throw new $TypeError($String(argument) + ' is not an object');
+};
+
+
+/***/ }),
+
+/***/ 7811:
+/***/ ((module) => {
+
+
+// eslint-disable-next-line es/no-typed-arrays -- safe
+module.exports = typeof ArrayBuffer != 'undefined' && typeof DataView != 'undefined';
+
+
+/***/ }),
+
+/***/ 7394:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var uncurryThisAccessor = __webpack_require__(6706);
+var classof = __webpack_require__(4576);
+
+var $TypeError = TypeError;
+
+// Includes
+// - Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
+// - If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
+module.exports = uncurryThisAccessor(ArrayBuffer.prototype, 'byteLength', 'get') || function (O) {
+ if (classof(O) !== 'ArrayBuffer') throw new $TypeError('ArrayBuffer expected');
+ return O.byteLength;
+};
+
+
+/***/ }),
+
+/***/ 3238:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var uncurryThis = __webpack_require__(9504);
+var arrayBufferByteLength = __webpack_require__(7394);
+
+var slice = uncurryThis(ArrayBuffer.prototype.slice);
+
+module.exports = function (O) {
+ if (arrayBufferByteLength(O) !== 0) return false;
+ try {
+ slice(O, 0, 0);
+ return false;
+ } catch (error) {
+ return true;
+ }
+};
+
+
+/***/ }),
+
+/***/ 5636:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var global = __webpack_require__(4475);
+var uncurryThis = __webpack_require__(9504);
+var uncurryThisAccessor = __webpack_require__(6706);
+var toIndex = __webpack_require__(7696);
+var isDetached = __webpack_require__(3238);
+var arrayBufferByteLength = __webpack_require__(7394);
+var detachTransferable = __webpack_require__(4483);
+var PROPER_STRUCTURED_CLONE_TRANSFER = __webpack_require__(1548);
+
+var structuredClone = global.structuredClone;
+var ArrayBuffer = global.ArrayBuffer;
+var DataView = global.DataView;
+var TypeError = global.TypeError;
+var min = Math.min;
+var ArrayBufferPrototype = ArrayBuffer.prototype;
+var DataViewPrototype = DataView.prototype;
+var slice = uncurryThis(ArrayBufferPrototype.slice);
+var isResizable = uncurryThisAccessor(ArrayBufferPrototype, 'resizable', 'get');
+var maxByteLength = uncurryThisAccessor(ArrayBufferPrototype, 'maxByteLength', 'get');
+var getInt8 = uncurryThis(DataViewPrototype.getInt8);
+var setInt8 = uncurryThis(DataViewPrototype.setInt8);
+
+module.exports = (PROPER_STRUCTURED_CLONE_TRANSFER || detachTransferable) && function (arrayBuffer, newLength, preserveResizability) {
+ var byteLength = arrayBufferByteLength(arrayBuffer);
+ var newByteLength = newLength === undefined ? byteLength : toIndex(newLength);
+ var fixedLength = !isResizable || !isResizable(arrayBuffer);
+ var newBuffer;
+ if (isDetached(arrayBuffer)) throw new TypeError('ArrayBuffer is detached');
+ if (PROPER_STRUCTURED_CLONE_TRANSFER) {
+ arrayBuffer = structuredClone(arrayBuffer, { transfer: [arrayBuffer] });
+ if (byteLength === newByteLength && (preserveResizability || fixedLength)) return arrayBuffer;
+ }
+ if (byteLength >= newByteLength && (!preserveResizability || fixedLength)) {
+ newBuffer = slice(arrayBuffer, 0, newByteLength);
+ } else {
+ var options = preserveResizability && !fixedLength && maxByteLength ? { maxByteLength: maxByteLength(arrayBuffer) } : undefined;
+ newBuffer = new ArrayBuffer(newByteLength, options);
+ var a = new DataView(arrayBuffer);
+ var b = new DataView(newBuffer);
+ var copyLength = min(newByteLength, byteLength);
+ for (var i = 0; i < copyLength; i++) setInt8(b, i, getInt8(a, i));
+ }
+ if (!PROPER_STRUCTURED_CLONE_TRANSFER) detachTransferable(arrayBuffer);
+ return newBuffer;
+};
+
+
+/***/ }),
+
+/***/ 4644:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var NATIVE_ARRAY_BUFFER = __webpack_require__(7811);
+var DESCRIPTORS = __webpack_require__(3724);
+var global = __webpack_require__(4475);
+var isCallable = __webpack_require__(4901);
+var isObject = __webpack_require__(34);
+var hasOwn = __webpack_require__(9297);
+var classof = __webpack_require__(6955);
+var tryToString = __webpack_require__(6823);
+var createNonEnumerableProperty = __webpack_require__(6699);
+var defineBuiltIn = __webpack_require__(6840);
+var defineBuiltInAccessor = __webpack_require__(2106);
+var isPrototypeOf = __webpack_require__(1625);
+var getPrototypeOf = __webpack_require__(2787);
+var setPrototypeOf = __webpack_require__(2967);
+var wellKnownSymbol = __webpack_require__(8227);
+var uid = __webpack_require__(3392);
+var InternalStateModule = __webpack_require__(1181);
+
+var enforceInternalState = InternalStateModule.enforce;
+var getInternalState = InternalStateModule.get;
+var Int8Array = global.Int8Array;
+var Int8ArrayPrototype = Int8Array && Int8Array.prototype;
+var Uint8ClampedArray = global.Uint8ClampedArray;
+var Uint8ClampedArrayPrototype = Uint8ClampedArray && Uint8ClampedArray.prototype;
+var TypedArray = Int8Array && getPrototypeOf(Int8Array);
+var TypedArrayPrototype = Int8ArrayPrototype && getPrototypeOf(Int8ArrayPrototype);
+var ObjectPrototype = Object.prototype;
+var TypeError = global.TypeError;
+
+var TO_STRING_TAG = wellKnownSymbol('toStringTag');
+var TYPED_ARRAY_TAG = uid('TYPED_ARRAY_TAG');
+var TYPED_ARRAY_CONSTRUCTOR = 'TypedArrayConstructor';
+// Fixing native typed arrays in Opera Presto crashes the browser, see #595
+var NATIVE_ARRAY_BUFFER_VIEWS = NATIVE_ARRAY_BUFFER && !!setPrototypeOf && classof(global.opera) !== 'Opera';
+var TYPED_ARRAY_TAG_REQUIRED = false;
+var NAME, Constructor, Prototype;
+
+var TypedArrayConstructorsList = {
+ Int8Array: 1,
+ Uint8Array: 1,
+ Uint8ClampedArray: 1,
+ Int16Array: 2,
+ Uint16Array: 2,
+ Int32Array: 4,
+ Uint32Array: 4,
+ Float32Array: 4,
+ Float64Array: 8
+};
+
+var BigIntArrayConstructorsList = {
+ BigInt64Array: 8,
+ BigUint64Array: 8
+};
+
+var isView = function isView(it) {
+ if (!isObject(it)) return false;
+ var klass = classof(it);
+ return klass === 'DataView'
+ || hasOwn(TypedArrayConstructorsList, klass)
+ || hasOwn(BigIntArrayConstructorsList, klass);
+};
+
+var getTypedArrayConstructor = function (it) {
+ var proto = getPrototypeOf(it);
+ if (!isObject(proto)) return;
+ var state = getInternalState(proto);
+ return (state && hasOwn(state, TYPED_ARRAY_CONSTRUCTOR)) ? state[TYPED_ARRAY_CONSTRUCTOR] : getTypedArrayConstructor(proto);
+};
+
+var isTypedArray = function (it) {
+ if (!isObject(it)) return false;
+ var klass = classof(it);
+ return hasOwn(TypedArrayConstructorsList, klass)
+ || hasOwn(BigIntArrayConstructorsList, klass);
+};
+
+var aTypedArray = function (it) {
+ if (isTypedArray(it)) return it;
+ throw new TypeError('Target is not a typed array');
+};
+
+var aTypedArrayConstructor = function (C) {
+ if (isCallable(C) && (!setPrototypeOf || isPrototypeOf(TypedArray, C))) return C;
+ throw new TypeError(tryToString(C) + ' is not a typed array constructor');
+};
+
+var exportTypedArrayMethod = function (KEY, property, forced, options) {
+ if (!DESCRIPTORS) return;
+ if (forced) for (var ARRAY in TypedArrayConstructorsList) {
+ var TypedArrayConstructor = global[ARRAY];
+ if (TypedArrayConstructor && hasOwn(TypedArrayConstructor.prototype, KEY)) try {
+ delete TypedArrayConstructor.prototype[KEY];
+ } catch (error) {
+ // old WebKit bug - some methods are non-configurable
+ try {
+ TypedArrayConstructor.prototype[KEY] = property;
+ } catch (error2) { /* empty */ }
+ }
+ }
+ if (!TypedArrayPrototype[KEY] || forced) {
+ defineBuiltIn(TypedArrayPrototype, KEY, forced ? property
+ : NATIVE_ARRAY_BUFFER_VIEWS && Int8ArrayPrototype[KEY] || property, options);
+ }
+};
+
+var exportTypedArrayStaticMethod = function (KEY, property, forced) {
+ var ARRAY, TypedArrayConstructor;
+ if (!DESCRIPTORS) return;
+ if (setPrototypeOf) {
+ if (forced) for (ARRAY in TypedArrayConstructorsList) {
+ TypedArrayConstructor = global[ARRAY];
+ if (TypedArrayConstructor && hasOwn(TypedArrayConstructor, KEY)) try {
+ delete TypedArrayConstructor[KEY];
+ } catch (error) { /* empty */ }
+ }
+ if (!TypedArray[KEY] || forced) {
+ // V8 ~ Chrome 49-50 `%TypedArray%` methods are non-writable non-configurable
+ try {
+ return defineBuiltIn(TypedArray, KEY, forced ? property : NATIVE_ARRAY_BUFFER_VIEWS && TypedArray[KEY] || property);
+ } catch (error) { /* empty */ }
+ } else return;
+ }
+ for (ARRAY in TypedArrayConstructorsList) {
+ TypedArrayConstructor = global[ARRAY];
+ if (TypedArrayConstructor && (!TypedArrayConstructor[KEY] || forced)) {
+ defineBuiltIn(TypedArrayConstructor, KEY, property);
+ }
+ }
+};
+
+for (NAME in TypedArrayConstructorsList) {
+ Constructor = global[NAME];
+ Prototype = Constructor && Constructor.prototype;
+ if (Prototype) enforceInternalState(Prototype)[TYPED_ARRAY_CONSTRUCTOR] = Constructor;
+ else NATIVE_ARRAY_BUFFER_VIEWS = false;
+}
+
+for (NAME in BigIntArrayConstructorsList) {
+ Constructor = global[NAME];
+ Prototype = Constructor && Constructor.prototype;
+ if (Prototype) enforceInternalState(Prototype)[TYPED_ARRAY_CONSTRUCTOR] = Constructor;
+}
+
+// WebKit bug - typed arrays constructors prototype is Object.prototype
+if (!NATIVE_ARRAY_BUFFER_VIEWS || !isCallable(TypedArray) || TypedArray === Function.prototype) {
+ // eslint-disable-next-line no-shadow -- safe
+ TypedArray = function TypedArray() {
+ throw new TypeError('Incorrect invocation');
+ };
+ if (NATIVE_ARRAY_BUFFER_VIEWS) for (NAME in TypedArrayConstructorsList) {
+ if (global[NAME]) setPrototypeOf(global[NAME], TypedArray);
+ }
+}
+
+if (!NATIVE_ARRAY_BUFFER_VIEWS || !TypedArrayPrototype || TypedArrayPrototype === ObjectPrototype) {
+ TypedArrayPrototype = TypedArray.prototype;
+ if (NATIVE_ARRAY_BUFFER_VIEWS) for (NAME in TypedArrayConstructorsList) {
+ if (global[NAME]) setPrototypeOf(global[NAME].prototype, TypedArrayPrototype);
+ }
+}
+
+// WebKit bug - one more object in Uint8ClampedArray prototype chain
+if (NATIVE_ARRAY_BUFFER_VIEWS && getPrototypeOf(Uint8ClampedArrayPrototype) !== TypedArrayPrototype) {
+ setPrototypeOf(Uint8ClampedArrayPrototype, TypedArrayPrototype);
+}
+
+if (DESCRIPTORS && !hasOwn(TypedArrayPrototype, TO_STRING_TAG)) {
+ TYPED_ARRAY_TAG_REQUIRED = true;
+ defineBuiltInAccessor(TypedArrayPrototype, TO_STRING_TAG, {
+ configurable: true,
+ get: function () {
+ return isObject(this) ? this[TYPED_ARRAY_TAG] : undefined;
+ }
+ });
+ for (NAME in TypedArrayConstructorsList) if (global[NAME]) {
+ createNonEnumerableProperty(global[NAME], TYPED_ARRAY_TAG, NAME);
+ }
+}
+
+module.exports = {
+ NATIVE_ARRAY_BUFFER_VIEWS: NATIVE_ARRAY_BUFFER_VIEWS,
+ TYPED_ARRAY_TAG: TYPED_ARRAY_TAG_REQUIRED && TYPED_ARRAY_TAG,
+ aTypedArray: aTypedArray,
+ aTypedArrayConstructor: aTypedArrayConstructor,
+ exportTypedArrayMethod: exportTypedArrayMethod,
+ exportTypedArrayStaticMethod: exportTypedArrayStaticMethod,
+ getTypedArrayConstructor: getTypedArrayConstructor,
+ isView: isView,
+ isTypedArray: isTypedArray,
+ TypedArray: TypedArray,
+ TypedArrayPrototype: TypedArrayPrototype
+};
+
+
+/***/ }),
+
+/***/ 5370:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var lengthOfArrayLike = __webpack_require__(6198);
+
+module.exports = function (Constructor, list, $length) {
+ var index = 0;
+ var length = arguments.length > 2 ? $length : lengthOfArrayLike(list);
+ var result = new Constructor(length);
+ while (length > index) result[index] = list[index++];
+ return result;
+};
+
+
+/***/ }),
+
+/***/ 9617:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var toIndexedObject = __webpack_require__(5397);
+var toAbsoluteIndex = __webpack_require__(5610);
+var lengthOfArrayLike = __webpack_require__(6198);
+
+// `Array.prototype.{ indexOf, includes }` methods implementation
+var createMethod = function (IS_INCLUDES) {
+ return function ($this, el, fromIndex) {
+ var O = toIndexedObject($this);
+ var length = lengthOfArrayLike(O);
+ if (length === 0) return !IS_INCLUDES && -1;
+ var index = toAbsoluteIndex(fromIndex, length);
+ var value;
+ // Array#includes uses SameValueZero equality algorithm
+ // eslint-disable-next-line no-self-compare -- NaN check
+ if (IS_INCLUDES && el !== el) while (length > index) {
+ value = O[index++];
+ // eslint-disable-next-line no-self-compare -- NaN check
+ if (value !== value) return true;
+ // Array#indexOf ignores holes, Array#includes - not
+ } else for (;length > index; index++) {
+ if ((IS_INCLUDES || index in O) && O[index] === el) return IS_INCLUDES || index || 0;
+ } return !IS_INCLUDES && -1;
+ };
+};
+
+module.exports = {
+ // `Array.prototype.includes` method
+ // https://tc39.es/ecma262/#sec-array.prototype.includes
+ includes: createMethod(true),
+ // `Array.prototype.indexOf` method
+ // https://tc39.es/ecma262/#sec-array.prototype.indexof
+ indexOf: createMethod(false)
+};
+
+
+/***/ }),
+
+/***/ 4527:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var DESCRIPTORS = __webpack_require__(3724);
+var isArray = __webpack_require__(4376);
+
+var $TypeError = TypeError;
+// eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
+var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
+
+// Safari < 13 does not throw an error in this case
+var SILENT_ON_NON_WRITABLE_LENGTH_SET = DESCRIPTORS && !function () {
+ // makes no sense without proper strict mode support
+ if (this !== undefined) return true;
+ try {
+ // eslint-disable-next-line es/no-object-defineproperty -- safe
+ Object.defineProperty([], 'length', { writable: false }).length = 1;
+ } catch (error) {
+ return error instanceof TypeError;
+ }
+}();
+
+module.exports = SILENT_ON_NON_WRITABLE_LENGTH_SET ? function (O, length) {
+ if (isArray(O) && !getOwnPropertyDescriptor(O, 'length').writable) {
+ throw new $TypeError('Cannot set read only .length');
+ } return O.length = length;
+} : function (O, length) {
+ return O.length = length;
+};
+
+
+/***/ }),
+
+/***/ 7628:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var lengthOfArrayLike = __webpack_require__(6198);
+
+// https://tc39.es/proposal-change-array-by-copy/#sec-array.prototype.toReversed
+// https://tc39.es/proposal-change-array-by-copy/#sec-%typedarray%.prototype.toReversed
+module.exports = function (O, C) {
+ var len = lengthOfArrayLike(O);
+ var A = new C(len);
+ var k = 0;
+ for (; k < len; k++) A[k] = O[len - k - 1];
+ return A;
+};
+
+
+/***/ }),
+
+/***/ 9928:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var lengthOfArrayLike = __webpack_require__(6198);
+var toIntegerOrInfinity = __webpack_require__(1291);
+
+var $RangeError = RangeError;
+
+// https://tc39.es/proposal-change-array-by-copy/#sec-array.prototype.with
+// https://tc39.es/proposal-change-array-by-copy/#sec-%typedarray%.prototype.with
+module.exports = function (O, C, index, value) {
+ var len = lengthOfArrayLike(O);
+ var relativeIndex = toIntegerOrInfinity(index);
+ var actualIndex = relativeIndex < 0 ? len + relativeIndex : relativeIndex;
+ if (actualIndex >= len || actualIndex < 0) throw new $RangeError('Incorrect index');
+ var A = new C(len);
+ var k = 0;
+ for (; k < len; k++) A[k] = k === actualIndex ? value : O[k];
+ return A;
+};
+
+
+/***/ }),
+
+/***/ 6319:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var anObject = __webpack_require__(8551);
+var iteratorClose = __webpack_require__(9539);
+
+// call something on iterator step with safe closing on error
+module.exports = function (iterator, fn, value, ENTRIES) {
+ try {
+ return ENTRIES ? fn(anObject(value)[0], value[1]) : fn(value);
+ } catch (error) {
+ iteratorClose(iterator, 'throw', error);
+ }
+};
+
+
+/***/ }),
+
+/***/ 4576:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var uncurryThis = __webpack_require__(9504);
+
+var toString = uncurryThis({}.toString);
+var stringSlice = uncurryThis(''.slice);
+
+module.exports = function (it) {
+ return stringSlice(toString(it), 8, -1);
+};
+
+
+/***/ }),
+
+/***/ 6955:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var TO_STRING_TAG_SUPPORT = __webpack_require__(2140);
+var isCallable = __webpack_require__(4901);
+var classofRaw = __webpack_require__(4576);
+var wellKnownSymbol = __webpack_require__(8227);
+
+var TO_STRING_TAG = wellKnownSymbol('toStringTag');
+var $Object = Object;
+
+// ES3 wrong here
+var CORRECT_ARGUMENTS = classofRaw(function () { return arguments; }()) === 'Arguments';
+
+// fallback for IE11 Script Access Denied error
+var tryGet = function (it, key) {
+ try {
+ return it[key];
+ } catch (error) { /* empty */ }
+};
+
+// getting tag from ES6+ `Object.prototype.toString`
+module.exports = TO_STRING_TAG_SUPPORT ? classofRaw : function (it) {
+ var O, tag, result;
+ return it === undefined ? 'Undefined' : it === null ? 'Null'
+ // @@toStringTag case
+ : typeof (tag = tryGet(O = $Object(it), TO_STRING_TAG)) == 'string' ? tag
+ // builtinTag case
+ : CORRECT_ARGUMENTS ? classofRaw(O)
+ // ES3 arguments fallback
+ : (result = classofRaw(O)) === 'Object' && isCallable(O.callee) ? 'Arguments' : result;
+};
+
+
+/***/ }),
+
+/***/ 7740:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var hasOwn = __webpack_require__(9297);
+var ownKeys = __webpack_require__(5031);
+var getOwnPropertyDescriptorModule = __webpack_require__(7347);
+var definePropertyModule = __webpack_require__(4913);
+
+module.exports = function (target, source, exceptions) {
+ var keys = ownKeys(source);
+ var defineProperty = definePropertyModule.f;
+ var getOwnPropertyDescriptor = getOwnPropertyDescriptorModule.f;
+ for (var i = 0; i < keys.length; i++) {
+ var key = keys[i];
+ if (!hasOwn(target, key) && !(exceptions && hasOwn(exceptions, key))) {
+ defineProperty(target, key, getOwnPropertyDescriptor(source, key));
+ }
+ }
+};
+
+
+/***/ }),
+
+/***/ 2211:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var fails = __webpack_require__(9039);
+
+module.exports = !fails(function () {
+ function F() { /* empty */ }
+ F.prototype.constructor = null;
+ // eslint-disable-next-line es/no-object-getprototypeof -- required for testing
+ return Object.getPrototypeOf(new F()) !== F.prototype;
+});
+
+
+/***/ }),
+
+/***/ 2529:
+/***/ ((module) => {
+
+
+// `CreateIterResultObject` abstract operation
+// https://tc39.es/ecma262/#sec-createiterresultobject
+module.exports = function (value, done) {
+ return { value: value, done: done };
+};
+
+
+/***/ }),
+
+/***/ 6699:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var DESCRIPTORS = __webpack_require__(3724);
+var definePropertyModule = __webpack_require__(4913);
+var createPropertyDescriptor = __webpack_require__(6980);
+
+module.exports = DESCRIPTORS ? function (object, key, value) {
+ return definePropertyModule.f(object, key, createPropertyDescriptor(1, value));
+} : function (object, key, value) {
+ object[key] = value;
+ return object;
+};
+
+
+/***/ }),
+
+/***/ 6980:
+/***/ ((module) => {
+
+
+module.exports = function (bitmap, value) {
+ return {
+ enumerable: !(bitmap & 1),
+ configurable: !(bitmap & 2),
+ writable: !(bitmap & 4),
+ value: value
+ };
+};
+
+
+/***/ }),
+
+/***/ 4659:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var DESCRIPTORS = __webpack_require__(3724);
+var definePropertyModule = __webpack_require__(4913);
+var createPropertyDescriptor = __webpack_require__(6980);
+
+module.exports = function (object, key, value) {
+ if (DESCRIPTORS) definePropertyModule.f(object, key, createPropertyDescriptor(0, value));
+ else object[key] = value;
+};
+
+
+/***/ }),
+
+/***/ 2106:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var makeBuiltIn = __webpack_require__(283);
+var defineProperty = __webpack_require__(4913);
+
+module.exports = function (target, name, descriptor) {
+ if (descriptor.get) makeBuiltIn(descriptor.get, name, { getter: true });
+ if (descriptor.set) makeBuiltIn(descriptor.set, name, { setter: true });
+ return defineProperty.f(target, name, descriptor);
+};
+
+
+/***/ }),
+
+/***/ 6840:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var isCallable = __webpack_require__(4901);
+var definePropertyModule = __webpack_require__(4913);
+var makeBuiltIn = __webpack_require__(283);
+var defineGlobalProperty = __webpack_require__(9433);
+
+module.exports = function (O, key, value, options) {
+ if (!options) options = {};
+ var simple = options.enumerable;
+ var name = options.name !== undefined ? options.name : key;
+ if (isCallable(value)) makeBuiltIn(value, name, options);
+ if (options.global) {
+ if (simple) O[key] = value;
+ else defineGlobalProperty(key, value);
+ } else {
+ try {
+ if (!options.unsafe) delete O[key];
+ else if (O[key]) simple = true;
+ } catch (error) { /* empty */ }
+ if (simple) O[key] = value;
+ else definePropertyModule.f(O, key, {
+ value: value,
+ enumerable: false,
+ configurable: !options.nonConfigurable,
+ writable: !options.nonWritable
+ });
+ } return O;
+};
+
+
+/***/ }),
+
+/***/ 6279:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var defineBuiltIn = __webpack_require__(6840);
+
+module.exports = function (target, src, options) {
+ for (var key in src) defineBuiltIn(target, key, src[key], options);
+ return target;
+};
+
+
+/***/ }),
+
+/***/ 9433:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var global = __webpack_require__(4475);
+
+// eslint-disable-next-line es/no-object-defineproperty -- safe
+var defineProperty = Object.defineProperty;
+
+module.exports = function (key, value) {
+ try {
+ defineProperty(global, key, { value: value, configurable: true, writable: true });
+ } catch (error) {
+ global[key] = value;
+ } return value;
+};
+
+
+/***/ }),
+
+/***/ 3724:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var fails = __webpack_require__(9039);
+
+// Detect IE8's incomplete defineProperty implementation
+module.exports = !fails(function () {
+ // eslint-disable-next-line es/no-object-defineproperty -- required for testing
+ return Object.defineProperty({}, 1, { get: function () { return 7; } })[1] !== 7;
+});
+
+
+/***/ }),
+
+/***/ 4483:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var global = __webpack_require__(4475);
+var tryNodeRequire = __webpack_require__(9714);
+var PROPER_STRUCTURED_CLONE_TRANSFER = __webpack_require__(1548);
+
+var structuredClone = global.structuredClone;
+var $ArrayBuffer = global.ArrayBuffer;
+var $MessageChannel = global.MessageChannel;
+var detach = false;
+var WorkerThreads, channel, buffer, $detach;
+
+if (PROPER_STRUCTURED_CLONE_TRANSFER) {
+ detach = function (transferable) {
+ structuredClone(transferable, { transfer: [transferable] });
+ };
+} else if ($ArrayBuffer) try {
+ if (!$MessageChannel) {
+ WorkerThreads = tryNodeRequire('worker_threads');
+ if (WorkerThreads) $MessageChannel = WorkerThreads.MessageChannel;
+ }
+
+ if ($MessageChannel) {
+ channel = new $MessageChannel();
+ buffer = new $ArrayBuffer(2);
+
+ $detach = function (transferable) {
+ channel.port1.postMessage(null, [transferable]);
+ };
+
+ if (buffer.byteLength === 2) {
+ $detach(buffer);
+ if (buffer.byteLength === 0) detach = $detach;
+ }
+ }
+} catch (error) { /* empty */ }
+
+module.exports = detach;
+
+
+/***/ }),
+
+/***/ 4055:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var global = __webpack_require__(4475);
+var isObject = __webpack_require__(34);
+
+var document = global.document;
+// typeof document.createElement is 'object' in old IE
+var EXISTS = isObject(document) && isObject(document.createElement);
+
+module.exports = function (it) {
+ return EXISTS ? document.createElement(it) : {};
+};
+
+
+/***/ }),
+
+/***/ 6837:
+/***/ ((module) => {
+
+
+var $TypeError = TypeError;
+var MAX_SAFE_INTEGER = 0x1FFFFFFFFFFFFF; // 2 ** 53 - 1 == 9007199254740991
+
+module.exports = function (it) {
+ if (it > MAX_SAFE_INTEGER) throw $TypeError('Maximum allowed index exceeded');
+ return it;
+};
+
+
+/***/ }),
+
+/***/ 5002:
+/***/ ((module) => {
+
+
+module.exports = {
+ IndexSizeError: { s: 'INDEX_SIZE_ERR', c: 1, m: 1 },
+ DOMStringSizeError: { s: 'DOMSTRING_SIZE_ERR', c: 2, m: 0 },
+ HierarchyRequestError: { s: 'HIERARCHY_REQUEST_ERR', c: 3, m: 1 },
+ WrongDocumentError: { s: 'WRONG_DOCUMENT_ERR', c: 4, m: 1 },
+ InvalidCharacterError: { s: 'INVALID_CHARACTER_ERR', c: 5, m: 1 },
+ NoDataAllowedError: { s: 'NO_DATA_ALLOWED_ERR', c: 6, m: 0 },
+ NoModificationAllowedError: { s: 'NO_MODIFICATION_ALLOWED_ERR', c: 7, m: 1 },
+ NotFoundError: { s: 'NOT_FOUND_ERR', c: 8, m: 1 },
+ NotSupportedError: { s: 'NOT_SUPPORTED_ERR', c: 9, m: 1 },
+ InUseAttributeError: { s: 'INUSE_ATTRIBUTE_ERR', c: 10, m: 1 },
+ InvalidStateError: { s: 'INVALID_STATE_ERR', c: 11, m: 1 },
+ SyntaxError: { s: 'SYNTAX_ERR', c: 12, m: 1 },
+ InvalidModificationError: { s: 'INVALID_MODIFICATION_ERR', c: 13, m: 1 },
+ NamespaceError: { s: 'NAMESPACE_ERR', c: 14, m: 1 },
+ InvalidAccessError: { s: 'INVALID_ACCESS_ERR', c: 15, m: 1 },
+ ValidationError: { s: 'VALIDATION_ERR', c: 16, m: 0 },
+ TypeMismatchError: { s: 'TYPE_MISMATCH_ERR', c: 17, m: 1 },
+ SecurityError: { s: 'SECURITY_ERR', c: 18, m: 1 },
+ NetworkError: { s: 'NETWORK_ERR', c: 19, m: 1 },
+ AbortError: { s: 'ABORT_ERR', c: 20, m: 1 },
+ URLMismatchError: { s: 'URL_MISMATCH_ERR', c: 21, m: 1 },
+ QuotaExceededError: { s: 'QUOTA_EXCEEDED_ERR', c: 22, m: 1 },
+ TimeoutError: { s: 'TIMEOUT_ERR', c: 23, m: 1 },
+ InvalidNodeTypeError: { s: 'INVALID_NODE_TYPE_ERR', c: 24, m: 1 },
+ DataCloneError: { s: 'DATA_CLONE_ERR', c: 25, m: 1 }
+};
+
+
+/***/ }),
+
+/***/ 7290:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var IS_DENO = __webpack_require__(516);
+var IS_NODE = __webpack_require__(9088);
+
+module.exports = !IS_DENO && !IS_NODE
+ && typeof window == 'object'
+ && typeof document == 'object';
+
+
+/***/ }),
+
+/***/ 516:
+/***/ ((module) => {
+
+
+/* global Deno -- Deno case */
+module.exports = typeof Deno == 'object' && Deno && typeof Deno.version == 'object';
+
+
+/***/ }),
+
+/***/ 9088:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var global = __webpack_require__(4475);
+var classof = __webpack_require__(4576);
+
+module.exports = classof(global.process) === 'process';
+
+
+/***/ }),
+
+/***/ 9392:
+/***/ ((module) => {
+
+
+module.exports = typeof navigator != 'undefined' && String(navigator.userAgent) || '';
+
+
+/***/ }),
+
+/***/ 7388:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var global = __webpack_require__(4475);
+var userAgent = __webpack_require__(9392);
+
+var process = global.process;
+var Deno = global.Deno;
+var versions = process && process.versions || Deno && Deno.version;
+var v8 = versions && versions.v8;
+var match, version;
+
+if (v8) {
+ match = v8.split('.');
+ // in old Chrome, versions of V8 isn't V8 = Chrome / 10
+ // but their correct versions are not interesting for us
+ version = match[0] > 0 && match[0] < 4 ? 1 : +(match[0] + match[1]);
+}
+
+// BrowserFS NodeJS `process` polyfill incorrectly set `.v8` to `0.0`
+// so check `userAgent` even if `.v8` exists, but 0
+if (!version && userAgent) {
+ match = userAgent.match(/Edge\/(\d+)/);
+ if (!match || match[1] >= 74) {
+ match = userAgent.match(/Chrome\/(\d+)/);
+ if (match) version = +match[1];
+ }
+}
+
+module.exports = version;
+
+
+/***/ }),
+
+/***/ 8727:
+/***/ ((module) => {
+
+
+// IE8- don't enum bug keys
+module.exports = [
+ 'constructor',
+ 'hasOwnProperty',
+ 'isPrototypeOf',
+ 'propertyIsEnumerable',
+ 'toLocaleString',
+ 'toString',
+ 'valueOf'
+];
+
+
+/***/ }),
+
+/***/ 6193:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var uncurryThis = __webpack_require__(9504);
+
+var $Error = Error;
+var replace = uncurryThis(''.replace);
+
+var TEST = (function (arg) { return String(new $Error(arg).stack); })('zxcasd');
+// eslint-disable-next-line redos/no-vulnerable -- safe
+var V8_OR_CHAKRA_STACK_ENTRY = /\n\s*at [^:]*:[^\n]*/;
+var IS_V8_OR_CHAKRA_STACK = V8_OR_CHAKRA_STACK_ENTRY.test(TEST);
+
+module.exports = function (stack, dropEntries) {
+ if (IS_V8_OR_CHAKRA_STACK && typeof stack == 'string' && !$Error.prepareStackTrace) {
+ while (dropEntries--) stack = replace(stack, V8_OR_CHAKRA_STACK_ENTRY, '');
+ } return stack;
+};
+
+
+/***/ }),
+
+/***/ 6518:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var global = __webpack_require__(4475);
+var getOwnPropertyDescriptor = (__webpack_require__(7347).f);
+var createNonEnumerableProperty = __webpack_require__(6699);
+var defineBuiltIn = __webpack_require__(6840);
+var defineGlobalProperty = __webpack_require__(9433);
+var copyConstructorProperties = __webpack_require__(7740);
+var isForced = __webpack_require__(2796);
+
+/*
+ options.target - name of the target object
+ options.global - target is the global object
+ options.stat - export as static methods of target
+ options.proto - export as prototype methods of target
+ options.real - real prototype method for the `pure` version
+ options.forced - export even if the native feature is available
+ options.bind - bind methods to the target, required for the `pure` version
+ options.wrap - wrap constructors to preventing global pollution, required for the `pure` version
+ options.unsafe - use the simple assignment of property instead of delete + defineProperty
+ options.sham - add a flag to not completely full polyfills
+ options.enumerable - export as enumerable property
+ options.dontCallGetSet - prevent calling a getter on target
+ options.name - the .name of the function if it does not match the key
+*/
+module.exports = function (options, source) {
+ var TARGET = options.target;
+ var GLOBAL = options.global;
+ var STATIC = options.stat;
+ var FORCED, target, key, targetProperty, sourceProperty, descriptor;
+ if (GLOBAL) {
+ target = global;
+ } else if (STATIC) {
+ target = global[TARGET] || defineGlobalProperty(TARGET, {});
+ } else {
+ target = global[TARGET] && global[TARGET].prototype;
+ }
+ if (target) for (key in source) {
+ sourceProperty = source[key];
+ if (options.dontCallGetSet) {
+ descriptor = getOwnPropertyDescriptor(target, key);
+ targetProperty = descriptor && descriptor.value;
+ } else targetProperty = target[key];
+ FORCED = isForced(GLOBAL ? key : TARGET + (STATIC ? '.' : '#') + key, options.forced);
+ // contained in target
+ if (!FORCED && targetProperty !== undefined) {
+ if (typeof sourceProperty == typeof targetProperty) continue;
+ copyConstructorProperties(sourceProperty, targetProperty);
+ }
+ // add a flag to not completely full polyfills
+ if (options.sham || (targetProperty && targetProperty.sham)) {
+ createNonEnumerableProperty(sourceProperty, 'sham', true);
+ }
+ defineBuiltIn(target, key, sourceProperty, options);
+ }
+};
+
+
+/***/ }),
+
+/***/ 9039:
+/***/ ((module) => {
+
+
+module.exports = function (exec) {
+ try {
+ return !!exec();
+ } catch (error) {
+ return true;
+ }
+};
+
+
+/***/ }),
+
+/***/ 6080:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var uncurryThis = __webpack_require__(7476);
+var aCallable = __webpack_require__(9306);
+var NATIVE_BIND = __webpack_require__(616);
+
+var bind = uncurryThis(uncurryThis.bind);
+
+// optional / simple context binding
+module.exports = function (fn, that) {
+ aCallable(fn);
+ return that === undefined ? fn : NATIVE_BIND ? bind(fn, that) : function (/* ...args */) {
+ return fn.apply(that, arguments);
+ };
+};
+
+
+/***/ }),
+
+/***/ 616:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var fails = __webpack_require__(9039);
+
+module.exports = !fails(function () {
+ // eslint-disable-next-line es/no-function-prototype-bind -- safe
+ var test = (function () { /* empty */ }).bind();
+ // eslint-disable-next-line no-prototype-builtins -- safe
+ return typeof test != 'function' || test.hasOwnProperty('prototype');
+});
+
+
+/***/ }),
+
+/***/ 9565:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var NATIVE_BIND = __webpack_require__(616);
+
+var call = Function.prototype.call;
+
+module.exports = NATIVE_BIND ? call.bind(call) : function () {
+ return call.apply(call, arguments);
+};
+
+
+/***/ }),
+
+/***/ 350:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var DESCRIPTORS = __webpack_require__(3724);
+var hasOwn = __webpack_require__(9297);
+
+var FunctionPrototype = Function.prototype;
+// eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
+var getDescriptor = DESCRIPTORS && Object.getOwnPropertyDescriptor;
+
+var EXISTS = hasOwn(FunctionPrototype, 'name');
+// additional protection from minified / mangled / dropped function names
+var PROPER = EXISTS && (function something() { /* empty */ }).name === 'something';
+var CONFIGURABLE = EXISTS && (!DESCRIPTORS || (DESCRIPTORS && getDescriptor(FunctionPrototype, 'name').configurable));
+
+module.exports = {
+ EXISTS: EXISTS,
+ PROPER: PROPER,
+ CONFIGURABLE: CONFIGURABLE
+};
+
+
+/***/ }),
+
+/***/ 6706:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var uncurryThis = __webpack_require__(9504);
+var aCallable = __webpack_require__(9306);
+
+module.exports = function (object, key, method) {
+ try {
+ // eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
+ return uncurryThis(aCallable(Object.getOwnPropertyDescriptor(object, key)[method]));
+ } catch (error) { /* empty */ }
+};
+
+
+/***/ }),
+
+/***/ 7476:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var classofRaw = __webpack_require__(4576);
+var uncurryThis = __webpack_require__(9504);
+
+module.exports = function (fn) {
+ // Nashorn bug:
+ // https://github.com/zloirock/core-js/issues/1128
+ // https://github.com/zloirock/core-js/issues/1130
+ if (classofRaw(fn) === 'Function') return uncurryThis(fn);
+};
+
+
+/***/ }),
+
+/***/ 9504:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var NATIVE_BIND = __webpack_require__(616);
+
+var FunctionPrototype = Function.prototype;
+var call = FunctionPrototype.call;
+var uncurryThisWithBind = NATIVE_BIND && FunctionPrototype.bind.bind(call, call);
+
+module.exports = NATIVE_BIND ? uncurryThisWithBind : function (fn) {
+ return function () {
+ return call.apply(fn, arguments);
+ };
+};
+
+
+/***/ }),
+
+/***/ 7751:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var global = __webpack_require__(4475);
+var isCallable = __webpack_require__(4901);
+
+var aFunction = function (argument) {
+ return isCallable(argument) ? argument : undefined;
+};
+
+module.exports = function (namespace, method) {
+ return arguments.length < 2 ? aFunction(global[namespace]) : global[namespace] && global[namespace][method];
+};
+
+
+/***/ }),
+
+/***/ 1767:
+/***/ ((module) => {
+
+
+// `GetIteratorDirect(obj)` abstract operation
+// https://tc39.es/proposal-iterator-helpers/#sec-getiteratordirect
+module.exports = function (obj) {
+ return {
+ iterator: obj,
+ next: obj.next,
+ done: false
+ };
+};
+
+
+/***/ }),
+
+/***/ 8646:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var call = __webpack_require__(9565);
+var anObject = __webpack_require__(8551);
+var getIteratorDirect = __webpack_require__(1767);
+var getIteratorMethod = __webpack_require__(851);
+
+module.exports = function (obj, stringHandling) {
+ if (!stringHandling || typeof obj !== 'string') anObject(obj);
+ var method = getIteratorMethod(obj);
+ return getIteratorDirect(anObject(method !== undefined ? call(method, obj) : obj));
+};
+
+
+/***/ }),
+
+/***/ 851:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var classof = __webpack_require__(6955);
+var getMethod = __webpack_require__(5966);
+var isNullOrUndefined = __webpack_require__(4117);
+var Iterators = __webpack_require__(6269);
+var wellKnownSymbol = __webpack_require__(8227);
+
+var ITERATOR = wellKnownSymbol('iterator');
+
+module.exports = function (it) {
+ if (!isNullOrUndefined(it)) return getMethod(it, ITERATOR)
+ || getMethod(it, '@@iterator')
+ || Iterators[classof(it)];
+};
+
+
+/***/ }),
+
+/***/ 81:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var call = __webpack_require__(9565);
+var aCallable = __webpack_require__(9306);
+var anObject = __webpack_require__(8551);
+var tryToString = __webpack_require__(6823);
+var getIteratorMethod = __webpack_require__(851);
+
+var $TypeError = TypeError;
+
+module.exports = function (argument, usingIterator) {
+ var iteratorMethod = arguments.length < 2 ? getIteratorMethod(argument) : usingIterator;
+ if (aCallable(iteratorMethod)) return anObject(call(iteratorMethod, argument));
+ throw new $TypeError(tryToString(argument) + ' is not iterable');
+};
+
+
+/***/ }),
+
+/***/ 5966:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var aCallable = __webpack_require__(9306);
+var isNullOrUndefined = __webpack_require__(4117);
+
+// `GetMethod` abstract operation
+// https://tc39.es/ecma262/#sec-getmethod
+module.exports = function (V, P) {
+ var func = V[P];
+ return isNullOrUndefined(func) ? undefined : aCallable(func);
+};
+
+
+/***/ }),
+
+/***/ 3789:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var aCallable = __webpack_require__(9306);
+var anObject = __webpack_require__(8551);
+var call = __webpack_require__(9565);
+var toIntegerOrInfinity = __webpack_require__(1291);
+var getIteratorDirect = __webpack_require__(1767);
+
+var INVALID_SIZE = 'Invalid size';
+var $RangeError = RangeError;
+var $TypeError = TypeError;
+var max = Math.max;
+
+var SetRecord = function (set, intSize) {
+ this.set = set;
+ this.size = max(intSize, 0);
+ this.has = aCallable(set.has);
+ this.keys = aCallable(set.keys);
+};
+
+SetRecord.prototype = {
+ getIterator: function () {
+ return getIteratorDirect(anObject(call(this.keys, this.set)));
+ },
+ includes: function (it) {
+ return call(this.has, this.set, it);
+ }
+};
+
+// `GetSetRecord` abstract operation
+// https://tc39.es/proposal-set-methods/#sec-getsetrecord
+module.exports = function (obj) {
+ anObject(obj);
+ var numSize = +obj.size;
+ // NOTE: If size is undefined, then numSize will be NaN
+ // eslint-disable-next-line no-self-compare -- NaN check
+ if (numSize !== numSize) throw new $TypeError(INVALID_SIZE);
+ var intSize = toIntegerOrInfinity(numSize);
+ if (intSize < 0) throw new $RangeError(INVALID_SIZE);
+ return new SetRecord(obj, intSize);
+};
+
+
+/***/ }),
+
+/***/ 4475:
+/***/ (function(module) {
+
+
+var check = function (it) {
+ return it && it.Math === Math && it;
+};
+
+// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028
+module.exports =
+ // eslint-disable-next-line es/no-global-this -- safe
+ check(typeof globalThis == 'object' && globalThis) ||
+ check(typeof window == 'object' && window) ||
+ // eslint-disable-next-line no-restricted-globals -- safe
+ check(typeof self == 'object' && self) ||
+ check(typeof global == 'object' && global) ||
+ check(typeof this == 'object' && this) ||
+ // eslint-disable-next-line no-new-func -- fallback
+ (function () { return this; })() || Function('return this')();
+
+
+/***/ }),
+
+/***/ 9297:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var uncurryThis = __webpack_require__(9504);
+var toObject = __webpack_require__(8981);
+
+var hasOwnProperty = uncurryThis({}.hasOwnProperty);
+
+// `HasOwnProperty` abstract operation
+// https://tc39.es/ecma262/#sec-hasownproperty
+// eslint-disable-next-line es/no-object-hasown -- safe
+module.exports = Object.hasOwn || function hasOwn(it, key) {
+ return hasOwnProperty(toObject(it), key);
+};
+
+
+/***/ }),
+
+/***/ 421:
+/***/ ((module) => {
+
+
+module.exports = {};
+
+
+/***/ }),
+
+/***/ 397:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var getBuiltIn = __webpack_require__(7751);
+
+module.exports = getBuiltIn('document', 'documentElement');
+
+
+/***/ }),
+
+/***/ 5917:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var DESCRIPTORS = __webpack_require__(3724);
+var fails = __webpack_require__(9039);
+var createElement = __webpack_require__(4055);
+
+// Thanks to IE8 for its funny defineProperty
+module.exports = !DESCRIPTORS && !fails(function () {
+ // eslint-disable-next-line es/no-object-defineproperty -- required for testing
+ return Object.defineProperty(createElement('div'), 'a', {
+ get: function () { return 7; }
+ }).a !== 7;
+});
+
+
+/***/ }),
+
+/***/ 7055:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var uncurryThis = __webpack_require__(9504);
+var fails = __webpack_require__(9039);
+var classof = __webpack_require__(4576);
+
+var $Object = Object;
+var split = uncurryThis(''.split);
+
+// fallback for non-array-like ES3 and non-enumerable old V8 strings
+module.exports = fails(function () {
+ // throws an error in rhino, see https://github.com/mozilla/rhino/issues/346
+ // eslint-disable-next-line no-prototype-builtins -- safe
+ return !$Object('z').propertyIsEnumerable(0);
+}) ? function (it) {
+ return classof(it) === 'String' ? split(it, '') : $Object(it);
+} : $Object;
+
+
+/***/ }),
+
+/***/ 3167:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var isCallable = __webpack_require__(4901);
+var isObject = __webpack_require__(34);
+var setPrototypeOf = __webpack_require__(2967);
+
+// makes subclassing work correct for wrapped built-ins
+module.exports = function ($this, dummy, Wrapper) {
+ var NewTarget, NewTargetPrototype;
+ if (
+ // it can work only with native `setPrototypeOf`
+ setPrototypeOf &&
+ // we haven't completely correct pre-ES6 way for getting `new.target`, so use this
+ isCallable(NewTarget = dummy.constructor) &&
+ NewTarget !== Wrapper &&
+ isObject(NewTargetPrototype = NewTarget.prototype) &&
+ NewTargetPrototype !== Wrapper.prototype
+ ) setPrototypeOf($this, NewTargetPrototype);
+ return $this;
+};
+
+
+/***/ }),
+
+/***/ 3706:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var uncurryThis = __webpack_require__(9504);
+var isCallable = __webpack_require__(4901);
+var store = __webpack_require__(7629);
+
+var functionToString = uncurryThis(Function.toString);
+
+// this helper broken in `core-js@3.4.1-3.4.4`, so we can't use `shared` helper
+if (!isCallable(store.inspectSource)) {
+ store.inspectSource = function (it) {
+ return functionToString(it);
+ };
+}
+
+module.exports = store.inspectSource;
+
+
+/***/ }),
+
+/***/ 1181:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var NATIVE_WEAK_MAP = __webpack_require__(8622);
+var global = __webpack_require__(4475);
+var isObject = __webpack_require__(34);
+var createNonEnumerableProperty = __webpack_require__(6699);
+var hasOwn = __webpack_require__(9297);
+var shared = __webpack_require__(7629);
+var sharedKey = __webpack_require__(6119);
+var hiddenKeys = __webpack_require__(421);
+
+var OBJECT_ALREADY_INITIALIZED = 'Object already initialized';
+var TypeError = global.TypeError;
+var WeakMap = global.WeakMap;
+var set, get, has;
+
+var enforce = function (it) {
+ return has(it) ? get(it) : set(it, {});
+};
+
+var getterFor = function (TYPE) {
+ return function (it) {
+ var state;
+ if (!isObject(it) || (state = get(it)).type !== TYPE) {
+ throw new TypeError('Incompatible receiver, ' + TYPE + ' required');
+ } return state;
+ };
+};
+
+if (NATIVE_WEAK_MAP || shared.state) {
+ var store = shared.state || (shared.state = new WeakMap());
+ /* eslint-disable no-self-assign -- prototype methods protection */
+ store.get = store.get;
+ store.has = store.has;
+ store.set = store.set;
+ /* eslint-enable no-self-assign -- prototype methods protection */
+ set = function (it, metadata) {
+ if (store.has(it)) throw new TypeError(OBJECT_ALREADY_INITIALIZED);
+ metadata.facade = it;
+ store.set(it, metadata);
+ return metadata;
+ };
+ get = function (it) {
+ return store.get(it) || {};
+ };
+ has = function (it) {
+ return store.has(it);
+ };
+} else {
+ var STATE = sharedKey('state');
+ hiddenKeys[STATE] = true;
+ set = function (it, metadata) {
+ if (hasOwn(it, STATE)) throw new TypeError(OBJECT_ALREADY_INITIALIZED);
+ metadata.facade = it;
+ createNonEnumerableProperty(it, STATE, metadata);
+ return metadata;
+ };
+ get = function (it) {
+ return hasOwn(it, STATE) ? it[STATE] : {};
+ };
+ has = function (it) {
+ return hasOwn(it, STATE);
+ };
+}
+
+module.exports = {
+ set: set,
+ get: get,
+ has: has,
+ enforce: enforce,
+ getterFor: getterFor
+};
+
+
+/***/ }),
+
+/***/ 4209:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var wellKnownSymbol = __webpack_require__(8227);
+var Iterators = __webpack_require__(6269);
+
+var ITERATOR = wellKnownSymbol('iterator');
+var ArrayPrototype = Array.prototype;
+
+// check on default Array iterator
+module.exports = function (it) {
+ return it !== undefined && (Iterators.Array === it || ArrayPrototype[ITERATOR] === it);
+};
+
+
+/***/ }),
+
+/***/ 4376:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var classof = __webpack_require__(4576);
+
+// `IsArray` abstract operation
+// https://tc39.es/ecma262/#sec-isarray
+// eslint-disable-next-line es/no-array-isarray -- safe
+module.exports = Array.isArray || function isArray(argument) {
+ return classof(argument) === 'Array';
+};
+
+
+/***/ }),
+
+/***/ 1108:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var classof = __webpack_require__(6955);
+
+module.exports = function (it) {
+ var klass = classof(it);
+ return klass === 'BigInt64Array' || klass === 'BigUint64Array';
+};
+
+
+/***/ }),
+
+/***/ 4901:
+/***/ ((module) => {
+
+
+// https://tc39.es/ecma262/#sec-IsHTMLDDA-internal-slot
+var documentAll = typeof document == 'object' && document.all;
+
+// `IsCallable` abstract operation
+// https://tc39.es/ecma262/#sec-iscallable
+// eslint-disable-next-line unicorn/no-typeof-undefined -- required for testing
+module.exports = typeof documentAll == 'undefined' && documentAll !== undefined ? function (argument) {
+ return typeof argument == 'function' || argument === documentAll;
+} : function (argument) {
+ return typeof argument == 'function';
+};
+
+
+/***/ }),
+
+/***/ 2796:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var fails = __webpack_require__(9039);
+var isCallable = __webpack_require__(4901);
+
+var replacement = /#|\.prototype\./;
+
+var isForced = function (feature, detection) {
+ var value = data[normalize(feature)];
+ return value === POLYFILL ? true
+ : value === NATIVE ? false
+ : isCallable(detection) ? fails(detection)
+ : !!detection;
+};
+
+var normalize = isForced.normalize = function (string) {
+ return String(string).replace(replacement, '.').toLowerCase();
+};
+
+var data = isForced.data = {};
+var NATIVE = isForced.NATIVE = 'N';
+var POLYFILL = isForced.POLYFILL = 'P';
+
+module.exports = isForced;
+
+
+/***/ }),
+
+/***/ 4117:
+/***/ ((module) => {
+
+
+// we can't use just `it == null` since of `document.all` special case
+// https://tc39.es/ecma262/#sec-IsHTMLDDA-internal-slot-aec
+module.exports = function (it) {
+ return it === null || it === undefined;
+};
+
+
+/***/ }),
+
+/***/ 34:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var isCallable = __webpack_require__(4901);
+
+module.exports = function (it) {
+ return typeof it == 'object' ? it !== null : isCallable(it);
+};
+
+
+/***/ }),
+
+/***/ 3925:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var isObject = __webpack_require__(34);
+
+module.exports = function (argument) {
+ return isObject(argument) || argument === null;
+};
+
+
+/***/ }),
+
+/***/ 6395:
+/***/ ((module) => {
+
+
+module.exports = false;
+
+
+/***/ }),
+
+/***/ 757:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var getBuiltIn = __webpack_require__(7751);
+var isCallable = __webpack_require__(4901);
+var isPrototypeOf = __webpack_require__(1625);
+var USE_SYMBOL_AS_UID = __webpack_require__(7040);
+
+var $Object = Object;
+
+module.exports = USE_SYMBOL_AS_UID ? function (it) {
+ return typeof it == 'symbol';
+} : function (it) {
+ var $Symbol = getBuiltIn('Symbol');
+ return isCallable($Symbol) && isPrototypeOf($Symbol.prototype, $Object(it));
+};
+
+
+/***/ }),
+
+/***/ 507:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var call = __webpack_require__(9565);
+
+module.exports = function (record, fn, ITERATOR_INSTEAD_OF_RECORD) {
+ var iterator = ITERATOR_INSTEAD_OF_RECORD ? record : record.iterator;
+ var next = record.next;
+ var step, result;
+ while (!(step = call(next, iterator)).done) {
+ result = fn(step.value);
+ if (result !== undefined) return result;
+ }
+};
+
+
+/***/ }),
+
+/***/ 2652:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var bind = __webpack_require__(6080);
+var call = __webpack_require__(9565);
+var anObject = __webpack_require__(8551);
+var tryToString = __webpack_require__(6823);
+var isArrayIteratorMethod = __webpack_require__(4209);
+var lengthOfArrayLike = __webpack_require__(6198);
+var isPrototypeOf = __webpack_require__(1625);
+var getIterator = __webpack_require__(81);
+var getIteratorMethod = __webpack_require__(851);
+var iteratorClose = __webpack_require__(9539);
+
+var $TypeError = TypeError;
+
+var Result = function (stopped, result) {
+ this.stopped = stopped;
+ this.result = result;
+};
+
+var ResultPrototype = Result.prototype;
+
+module.exports = function (iterable, unboundFunction, options) {
+ var that = options && options.that;
+ var AS_ENTRIES = !!(options && options.AS_ENTRIES);
+ var IS_RECORD = !!(options && options.IS_RECORD);
+ var IS_ITERATOR = !!(options && options.IS_ITERATOR);
+ var INTERRUPTED = !!(options && options.INTERRUPTED);
+ var fn = bind(unboundFunction, that);
+ var iterator, iterFn, index, length, result, next, step;
+
+ var stop = function (condition) {
+ if (iterator) iteratorClose(iterator, 'normal', condition);
+ return new Result(true, condition);
+ };
+
+ var callFn = function (value) {
+ if (AS_ENTRIES) {
+ anObject(value);
+ return INTERRUPTED ? fn(value[0], value[1], stop) : fn(value[0], value[1]);
+ } return INTERRUPTED ? fn(value, stop) : fn(value);
+ };
+
+ if (IS_RECORD) {
+ iterator = iterable.iterator;
+ } else if (IS_ITERATOR) {
+ iterator = iterable;
+ } else {
+ iterFn = getIteratorMethod(iterable);
+ if (!iterFn) throw new $TypeError(tryToString(iterable) + ' is not iterable');
+ // optimisation for array iterators
+ if (isArrayIteratorMethod(iterFn)) {
+ for (index = 0, length = lengthOfArrayLike(iterable); length > index; index++) {
+ result = callFn(iterable[index]);
+ if (result && isPrototypeOf(ResultPrototype, result)) return result;
+ } return new Result(false);
+ }
+ iterator = getIterator(iterable, iterFn);
+ }
+
+ next = IS_RECORD ? iterable.next : iterator.next;
+ while (!(step = call(next, iterator)).done) {
+ try {
+ result = callFn(step.value);
+ } catch (error) {
+ iteratorClose(iterator, 'throw', error);
+ }
+ if (typeof result == 'object' && result && isPrototypeOf(ResultPrototype, result)) return result;
+ } return new Result(false);
+};
+
+
+/***/ }),
+
+/***/ 9539:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var call = __webpack_require__(9565);
+var anObject = __webpack_require__(8551);
+var getMethod = __webpack_require__(5966);
+
+module.exports = function (iterator, kind, value) {
+ var innerResult, innerError;
+ anObject(iterator);
+ try {
+ innerResult = getMethod(iterator, 'return');
+ if (!innerResult) {
+ if (kind === 'throw') throw value;
+ return value;
+ }
+ innerResult = call(innerResult, iterator);
+ } catch (error) {
+ innerError = true;
+ innerResult = error;
+ }
+ if (kind === 'throw') throw value;
+ if (innerError) throw innerResult;
+ anObject(innerResult);
+ return value;
+};
+
+
+/***/ }),
+
+/***/ 9462:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var call = __webpack_require__(9565);
+var create = __webpack_require__(2360);
+var createNonEnumerableProperty = __webpack_require__(6699);
+var defineBuiltIns = __webpack_require__(6279);
+var wellKnownSymbol = __webpack_require__(8227);
+var InternalStateModule = __webpack_require__(1181);
+var getMethod = __webpack_require__(5966);
+var IteratorPrototype = (__webpack_require__(7657).IteratorPrototype);
+var createIterResultObject = __webpack_require__(2529);
+var iteratorClose = __webpack_require__(9539);
+
+var TO_STRING_TAG = wellKnownSymbol('toStringTag');
+var ITERATOR_HELPER = 'IteratorHelper';
+var WRAP_FOR_VALID_ITERATOR = 'WrapForValidIterator';
+var setInternalState = InternalStateModule.set;
+
+var createIteratorProxyPrototype = function (IS_ITERATOR) {
+ var getInternalState = InternalStateModule.getterFor(IS_ITERATOR ? WRAP_FOR_VALID_ITERATOR : ITERATOR_HELPER);
+
+ return defineBuiltIns(create(IteratorPrototype), {
+ next: function next() {
+ var state = getInternalState(this);
+ // for simplification:
+ // for `%WrapForValidIteratorPrototype%.next` our `nextHandler` returns `IterResultObject`
+ // for `%IteratorHelperPrototype%.next` - just a value
+ if (IS_ITERATOR) return state.nextHandler();
+ try {
+ var result = state.done ? undefined : state.nextHandler();
+ return createIterResultObject(result, state.done);
+ } catch (error) {
+ state.done = true;
+ throw error;
+ }
+ },
+ 'return': function () {
+ var state = getInternalState(this);
+ var iterator = state.iterator;
+ state.done = true;
+ if (IS_ITERATOR) {
+ var returnMethod = getMethod(iterator, 'return');
+ return returnMethod ? call(returnMethod, iterator) : createIterResultObject(undefined, true);
+ }
+ if (state.inner) try {
+ iteratorClose(state.inner.iterator, 'normal');
+ } catch (error) {
+ return iteratorClose(iterator, 'throw', error);
+ }
+ iteratorClose(iterator, 'normal');
+ return createIterResultObject(undefined, true);
+ }
+ });
+};
+
+var WrapForValidIteratorPrototype = createIteratorProxyPrototype(true);
+var IteratorHelperPrototype = createIteratorProxyPrototype(false);
+
+createNonEnumerableProperty(IteratorHelperPrototype, TO_STRING_TAG, 'Iterator Helper');
+
+module.exports = function (nextHandler, IS_ITERATOR) {
+ var IteratorProxy = function Iterator(record, state) {
+ if (state) {
+ state.iterator = record.iterator;
+ state.next = record.next;
+ } else state = record;
+ state.type = IS_ITERATOR ? WRAP_FOR_VALID_ITERATOR : ITERATOR_HELPER;
+ state.nextHandler = nextHandler;
+ state.counter = 0;
+ state.done = false;
+ setInternalState(this, state);
+ };
+
+ IteratorProxy.prototype = IS_ITERATOR ? WrapForValidIteratorPrototype : IteratorHelperPrototype;
+
+ return IteratorProxy;
+};
+
+
+/***/ }),
+
+/***/ 713:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var call = __webpack_require__(9565);
+var aCallable = __webpack_require__(9306);
+var anObject = __webpack_require__(8551);
+var getIteratorDirect = __webpack_require__(1767);
+var createIteratorProxy = __webpack_require__(9462);
+var callWithSafeIterationClosing = __webpack_require__(6319);
+
+var IteratorProxy = createIteratorProxy(function () {
+ var iterator = this.iterator;
+ var result = anObject(call(this.next, iterator));
+ var done = this.done = !!result.done;
+ if (!done) return callWithSafeIterationClosing(iterator, this.mapper, [result.value, this.counter++], true);
+});
+
+// `Iterator.prototype.map` method
+// https://github.com/tc39/proposal-iterator-helpers
+module.exports = function map(mapper) {
+ anObject(this);
+ aCallable(mapper);
+ return new IteratorProxy(getIteratorDirect(this), {
+ mapper: mapper
+ });
+};
+
+
+/***/ }),
+
+/***/ 7657:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var fails = __webpack_require__(9039);
+var isCallable = __webpack_require__(4901);
+var isObject = __webpack_require__(34);
+var create = __webpack_require__(2360);
+var getPrototypeOf = __webpack_require__(2787);
+var defineBuiltIn = __webpack_require__(6840);
+var wellKnownSymbol = __webpack_require__(8227);
+var IS_PURE = __webpack_require__(6395);
+
+var ITERATOR = wellKnownSymbol('iterator');
+var BUGGY_SAFARI_ITERATORS = false;
+
+// `%IteratorPrototype%` object
+// https://tc39.es/ecma262/#sec-%iteratorprototype%-object
+var IteratorPrototype, PrototypeOfArrayIteratorPrototype, arrayIterator;
+
+/* eslint-disable es/no-array-prototype-keys -- safe */
+if ([].keys) {
+ arrayIterator = [].keys();
+ // Safari 8 has buggy iterators w/o `next`
+ if (!('next' in arrayIterator)) BUGGY_SAFARI_ITERATORS = true;
+ else {
+ PrototypeOfArrayIteratorPrototype = getPrototypeOf(getPrototypeOf(arrayIterator));
+ if (PrototypeOfArrayIteratorPrototype !== Object.prototype) IteratorPrototype = PrototypeOfArrayIteratorPrototype;
+ }
+}
+
+var NEW_ITERATOR_PROTOTYPE = !isObject(IteratorPrototype) || fails(function () {
+ var test = {};
+ // FF44- legacy iterators case
+ return IteratorPrototype[ITERATOR].call(test) !== test;
+});
+
+if (NEW_ITERATOR_PROTOTYPE) IteratorPrototype = {};
+else if (IS_PURE) IteratorPrototype = create(IteratorPrototype);
+
+// `%IteratorPrototype%[@@iterator]()` method
+// https://tc39.es/ecma262/#sec-%iteratorprototype%-@@iterator
+if (!isCallable(IteratorPrototype[ITERATOR])) {
+ defineBuiltIn(IteratorPrototype, ITERATOR, function () {
+ return this;
+ });
+}
+
+module.exports = {
+ IteratorPrototype: IteratorPrototype,
+ BUGGY_SAFARI_ITERATORS: BUGGY_SAFARI_ITERATORS
+};
+
+
+/***/ }),
+
+/***/ 6269:
+/***/ ((module) => {
+
+
+module.exports = {};
+
+
+/***/ }),
+
+/***/ 6198:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var toLength = __webpack_require__(8014);
+
+// `LengthOfArrayLike` abstract operation
+// https://tc39.es/ecma262/#sec-lengthofarraylike
+module.exports = function (obj) {
+ return toLength(obj.length);
+};
+
+
+/***/ }),
+
+/***/ 283:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var uncurryThis = __webpack_require__(9504);
+var fails = __webpack_require__(9039);
+var isCallable = __webpack_require__(4901);
+var hasOwn = __webpack_require__(9297);
+var DESCRIPTORS = __webpack_require__(3724);
+var CONFIGURABLE_FUNCTION_NAME = (__webpack_require__(350).CONFIGURABLE);
+var inspectSource = __webpack_require__(3706);
+var InternalStateModule = __webpack_require__(1181);
+
+var enforceInternalState = InternalStateModule.enforce;
+var getInternalState = InternalStateModule.get;
+var $String = String;
+// eslint-disable-next-line es/no-object-defineproperty -- safe
+var defineProperty = Object.defineProperty;
+var stringSlice = uncurryThis(''.slice);
+var replace = uncurryThis(''.replace);
+var join = uncurryThis([].join);
+
+var CONFIGURABLE_LENGTH = DESCRIPTORS && !fails(function () {
+ return defineProperty(function () { /* empty */ }, 'length', { value: 8 }).length !== 8;
+});
+
+var TEMPLATE = String(String).split('String');
+
+var makeBuiltIn = module.exports = function (value, name, options) {
+ if (stringSlice($String(name), 0, 7) === 'Symbol(') {
+ name = '[' + replace($String(name), /^Symbol\(([^)]*)\).*$/, '$1') + ']';
+ }
+ if (options && options.getter) name = 'get ' + name;
+ if (options && options.setter) name = 'set ' + name;
+ if (!hasOwn(value, 'name') || (CONFIGURABLE_FUNCTION_NAME && value.name !== name)) {
+ if (DESCRIPTORS) defineProperty(value, 'name', { value: name, configurable: true });
+ else value.name = name;
+ }
+ if (CONFIGURABLE_LENGTH && options && hasOwn(options, 'arity') && value.length !== options.arity) {
+ defineProperty(value, 'length', { value: options.arity });
+ }
+ try {
+ if (options && hasOwn(options, 'constructor') && options.constructor) {
+ if (DESCRIPTORS) defineProperty(value, 'prototype', { writable: false });
+ // in V8 ~ Chrome 53, prototypes of some methods, like `Array.prototype.values`, are non-writable
+ } else if (value.prototype) value.prototype = undefined;
+ } catch (error) { /* empty */ }
+ var state = enforceInternalState(value);
+ if (!hasOwn(state, 'source')) {
+ state.source = join(TEMPLATE, typeof name == 'string' ? name : '');
+ } return value;
+};
+
+// add fake Function#toString for correct work wrapped methods / constructors with methods like LoDash isNative
+// eslint-disable-next-line no-extend-native -- required
+Function.prototype.toString = makeBuiltIn(function toString() {
+ return isCallable(this) && getInternalState(this).source || inspectSource(this);
+}, 'toString');
+
+
+/***/ }),
+
+/***/ 741:
+/***/ ((module) => {
+
+
+var ceil = Math.ceil;
+var floor = Math.floor;
+
+// `Math.trunc` method
+// https://tc39.es/ecma262/#sec-math.trunc
+// eslint-disable-next-line es/no-math-trunc -- safe
+module.exports = Math.trunc || function trunc(x) {
+ var n = +x;
+ return (n > 0 ? floor : ceil)(n);
+};
+
+
+/***/ }),
+
+/***/ 6043:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var aCallable = __webpack_require__(9306);
+
+var $TypeError = TypeError;
+
+var PromiseCapability = function (C) {
+ var resolve, reject;
+ this.promise = new C(function ($$resolve, $$reject) {
+ if (resolve !== undefined || reject !== undefined) throw new $TypeError('Bad Promise constructor');
+ resolve = $$resolve;
+ reject = $$reject;
+ });
+ this.resolve = aCallable(resolve);
+ this.reject = aCallable(reject);
+};
+
+// `NewPromiseCapability` abstract operation
+// https://tc39.es/ecma262/#sec-newpromisecapability
+module.exports.f = function (C) {
+ return new PromiseCapability(C);
+};
+
+
+/***/ }),
+
+/***/ 2603:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var toString = __webpack_require__(655);
+
+module.exports = function (argument, $default) {
+ return argument === undefined ? arguments.length < 2 ? '' : $default : toString(argument);
+};
+
+
+/***/ }),
+
+/***/ 4149:
+/***/ ((module) => {
+
+
+var $RangeError = RangeError;
+
+module.exports = function (it) {
+ // eslint-disable-next-line no-self-compare -- NaN check
+ if (it === it) return it;
+ throw new $RangeError('NaN is not allowed');
+};
+
+
+/***/ }),
+
+/***/ 2360:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+/* global ActiveXObject -- old IE, WSH */
+var anObject = __webpack_require__(8551);
+var definePropertiesModule = __webpack_require__(6801);
+var enumBugKeys = __webpack_require__(8727);
+var hiddenKeys = __webpack_require__(421);
+var html = __webpack_require__(397);
+var documentCreateElement = __webpack_require__(4055);
+var sharedKey = __webpack_require__(6119);
+
+var GT = '>';
+var LT = '<';
+var PROTOTYPE = 'prototype';
+var SCRIPT = 'script';
+var IE_PROTO = sharedKey('IE_PROTO');
+
+var EmptyConstructor = function () { /* empty */ };
+
+var scriptTag = function (content) {
+ return LT + SCRIPT + GT + content + LT + '/' + SCRIPT + GT;
+};
+
+// Create object with fake `null` prototype: use ActiveX Object with cleared prototype
+var NullProtoObjectViaActiveX = function (activeXDocument) {
+ activeXDocument.write(scriptTag(''));
+ activeXDocument.close();
+ var temp = activeXDocument.parentWindow.Object;
+ activeXDocument = null; // avoid memory leak
+ return temp;
+};
+
+// Create object with fake `null` prototype: use iframe Object with cleared prototype
+var NullProtoObjectViaIFrame = function () {
+ // Thrash, waste and sodomy: IE GC bug
+ var iframe = documentCreateElement('iframe');
+ var JS = 'java' + SCRIPT + ':';
+ var iframeDocument;
+ iframe.style.display = 'none';
+ html.appendChild(iframe);
+ // https://github.com/zloirock/core-js/issues/475
+ iframe.src = String(JS);
+ iframeDocument = iframe.contentWindow.document;
+ iframeDocument.open();
+ iframeDocument.write(scriptTag('document.F=Object'));
+ iframeDocument.close();
+ return iframeDocument.F;
+};
+
+// Check for document.domain and active x support
+// No need to use active x approach when document.domain is not set
+// see https://github.com/es-shims/es5-shim/issues/150
+// variation of https://github.com/kitcambridge/es5-shim/commit/4f738ac066346
+// avoid IE GC bug
+var activeXDocument;
+var NullProtoObject = function () {
+ try {
+ activeXDocument = new ActiveXObject('htmlfile');
+ } catch (error) { /* ignore */ }
+ NullProtoObject = typeof document != 'undefined'
+ ? document.domain && activeXDocument
+ ? NullProtoObjectViaActiveX(activeXDocument) // old IE
+ : NullProtoObjectViaIFrame()
+ : NullProtoObjectViaActiveX(activeXDocument); // WSH
+ var length = enumBugKeys.length;
+ while (length--) delete NullProtoObject[PROTOTYPE][enumBugKeys[length]];
+ return NullProtoObject();
+};
+
+hiddenKeys[IE_PROTO] = true;
+
+// `Object.create` method
+// https://tc39.es/ecma262/#sec-object.create
+// eslint-disable-next-line es/no-object-create -- safe
+module.exports = Object.create || function create(O, Properties) {
+ var result;
+ if (O !== null) {
+ EmptyConstructor[PROTOTYPE] = anObject(O);
+ result = new EmptyConstructor();
+ EmptyConstructor[PROTOTYPE] = null;
+ // add "__proto__" for Object.getPrototypeOf polyfill
+ result[IE_PROTO] = O;
+ } else result = NullProtoObject();
+ return Properties === undefined ? result : definePropertiesModule.f(result, Properties);
+};
+
+
+/***/ }),
+
+/***/ 6801:
+/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
+
+
+var DESCRIPTORS = __webpack_require__(3724);
+var V8_PROTOTYPE_DEFINE_BUG = __webpack_require__(8686);
+var definePropertyModule = __webpack_require__(4913);
+var anObject = __webpack_require__(8551);
+var toIndexedObject = __webpack_require__(5397);
+var objectKeys = __webpack_require__(1072);
+
+// `Object.defineProperties` method
+// https://tc39.es/ecma262/#sec-object.defineproperties
+// eslint-disable-next-line es/no-object-defineproperties -- safe
+exports.f = DESCRIPTORS && !V8_PROTOTYPE_DEFINE_BUG ? Object.defineProperties : function defineProperties(O, Properties) {
+ anObject(O);
+ var props = toIndexedObject(Properties);
+ var keys = objectKeys(Properties);
+ var length = keys.length;
+ var index = 0;
+ var key;
+ while (length > index) definePropertyModule.f(O, key = keys[index++], props[key]);
+ return O;
+};
+
+
+/***/ }),
+
+/***/ 4913:
+/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
+
+
+var DESCRIPTORS = __webpack_require__(3724);
+var IE8_DOM_DEFINE = __webpack_require__(5917);
+var V8_PROTOTYPE_DEFINE_BUG = __webpack_require__(8686);
+var anObject = __webpack_require__(8551);
+var toPropertyKey = __webpack_require__(6969);
+
+var $TypeError = TypeError;
+// eslint-disable-next-line es/no-object-defineproperty -- safe
+var $defineProperty = Object.defineProperty;
+// eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
+var $getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
+var ENUMERABLE = 'enumerable';
+var CONFIGURABLE = 'configurable';
+var WRITABLE = 'writable';
+
+// `Object.defineProperty` method
+// https://tc39.es/ecma262/#sec-object.defineproperty
+exports.f = DESCRIPTORS ? V8_PROTOTYPE_DEFINE_BUG ? function defineProperty(O, P, Attributes) {
+ anObject(O);
+ P = toPropertyKey(P);
+ anObject(Attributes);
+ if (typeof O === 'function' && P === 'prototype' && 'value' in Attributes && WRITABLE in Attributes && !Attributes[WRITABLE]) {
+ var current = $getOwnPropertyDescriptor(O, P);
+ if (current && current[WRITABLE]) {
+ O[P] = Attributes.value;
+ Attributes = {
+ configurable: CONFIGURABLE in Attributes ? Attributes[CONFIGURABLE] : current[CONFIGURABLE],
+ enumerable: ENUMERABLE in Attributes ? Attributes[ENUMERABLE] : current[ENUMERABLE],
+ writable: false
+ };
+ }
+ } return $defineProperty(O, P, Attributes);
+} : $defineProperty : function defineProperty(O, P, Attributes) {
+ anObject(O);
+ P = toPropertyKey(P);
+ anObject(Attributes);
+ if (IE8_DOM_DEFINE) try {
+ return $defineProperty(O, P, Attributes);
+ } catch (error) { /* empty */ }
+ if ('get' in Attributes || 'set' in Attributes) throw new $TypeError('Accessors not supported');
+ if ('value' in Attributes) O[P] = Attributes.value;
+ return O;
+};
+
+
+/***/ }),
+
+/***/ 7347:
+/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
+
+
+var DESCRIPTORS = __webpack_require__(3724);
+var call = __webpack_require__(9565);
+var propertyIsEnumerableModule = __webpack_require__(8773);
+var createPropertyDescriptor = __webpack_require__(6980);
+var toIndexedObject = __webpack_require__(5397);
+var toPropertyKey = __webpack_require__(6969);
+var hasOwn = __webpack_require__(9297);
+var IE8_DOM_DEFINE = __webpack_require__(5917);
+
+// eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
+var $getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
+
+// `Object.getOwnPropertyDescriptor` method
+// https://tc39.es/ecma262/#sec-object.getownpropertydescriptor
+exports.f = DESCRIPTORS ? $getOwnPropertyDescriptor : function getOwnPropertyDescriptor(O, P) {
+ O = toIndexedObject(O);
+ P = toPropertyKey(P);
+ if (IE8_DOM_DEFINE) try {
+ return $getOwnPropertyDescriptor(O, P);
+ } catch (error) { /* empty */ }
+ if (hasOwn(O, P)) return createPropertyDescriptor(!call(propertyIsEnumerableModule.f, O, P), O[P]);
+};
+
+
+/***/ }),
+
+/***/ 8480:
+/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
+
+
+var internalObjectKeys = __webpack_require__(1828);
+var enumBugKeys = __webpack_require__(8727);
+
+var hiddenKeys = enumBugKeys.concat('length', 'prototype');
+
+// `Object.getOwnPropertyNames` method
+// https://tc39.es/ecma262/#sec-object.getownpropertynames
+// eslint-disable-next-line es/no-object-getownpropertynames -- safe
+exports.f = Object.getOwnPropertyNames || function getOwnPropertyNames(O) {
+ return internalObjectKeys(O, hiddenKeys);
+};
+
+
+/***/ }),
+
+/***/ 3717:
+/***/ ((__unused_webpack_module, exports) => {
+
+
+// eslint-disable-next-line es/no-object-getownpropertysymbols -- safe
+exports.f = Object.getOwnPropertySymbols;
+
+
+/***/ }),
+
+/***/ 2787:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var hasOwn = __webpack_require__(9297);
+var isCallable = __webpack_require__(4901);
+var toObject = __webpack_require__(8981);
+var sharedKey = __webpack_require__(6119);
+var CORRECT_PROTOTYPE_GETTER = __webpack_require__(2211);
+
+var IE_PROTO = sharedKey('IE_PROTO');
+var $Object = Object;
+var ObjectPrototype = $Object.prototype;
+
+// `Object.getPrototypeOf` method
+// https://tc39.es/ecma262/#sec-object.getprototypeof
+// eslint-disable-next-line es/no-object-getprototypeof -- safe
+module.exports = CORRECT_PROTOTYPE_GETTER ? $Object.getPrototypeOf : function (O) {
+ var object = toObject(O);
+ if (hasOwn(object, IE_PROTO)) return object[IE_PROTO];
+ var constructor = object.constructor;
+ if (isCallable(constructor) && object instanceof constructor) {
+ return constructor.prototype;
+ } return object instanceof $Object ? ObjectPrototype : null;
+};
+
+
+/***/ }),
+
+/***/ 1625:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var uncurryThis = __webpack_require__(9504);
+
+module.exports = uncurryThis({}.isPrototypeOf);
+
+
+/***/ }),
+
+/***/ 1828:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var uncurryThis = __webpack_require__(9504);
+var hasOwn = __webpack_require__(9297);
+var toIndexedObject = __webpack_require__(5397);
+var indexOf = (__webpack_require__(9617).indexOf);
+var hiddenKeys = __webpack_require__(421);
+
+var push = uncurryThis([].push);
+
+module.exports = function (object, names) {
+ var O = toIndexedObject(object);
+ var i = 0;
+ var result = [];
+ var key;
+ for (key in O) !hasOwn(hiddenKeys, key) && hasOwn(O, key) && push(result, key);
+ // Don't enum bug & hidden keys
+ while (names.length > i) if (hasOwn(O, key = names[i++])) {
+ ~indexOf(result, key) || push(result, key);
+ }
+ return result;
+};
+
+
+/***/ }),
+
+/***/ 1072:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var internalObjectKeys = __webpack_require__(1828);
+var enumBugKeys = __webpack_require__(8727);
+
+// `Object.keys` method
+// https://tc39.es/ecma262/#sec-object.keys
+// eslint-disable-next-line es/no-object-keys -- safe
+module.exports = Object.keys || function keys(O) {
+ return internalObjectKeys(O, enumBugKeys);
+};
+
+
+/***/ }),
+
+/***/ 8773:
+/***/ ((__unused_webpack_module, exports) => {
+
+
+var $propertyIsEnumerable = {}.propertyIsEnumerable;
+// eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
+var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
+
+// Nashorn ~ JDK8 bug
+var NASHORN_BUG = getOwnPropertyDescriptor && !$propertyIsEnumerable.call({ 1: 2 }, 1);
+
+// `Object.prototype.propertyIsEnumerable` method implementation
+// https://tc39.es/ecma262/#sec-object.prototype.propertyisenumerable
+exports.f = NASHORN_BUG ? function propertyIsEnumerable(V) {
+ var descriptor = getOwnPropertyDescriptor(this, V);
+ return !!descriptor && descriptor.enumerable;
+} : $propertyIsEnumerable;
+
+
+/***/ }),
+
+/***/ 2967:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+/* eslint-disable no-proto -- safe */
+var uncurryThisAccessor = __webpack_require__(6706);
+var isObject = __webpack_require__(34);
+var requireObjectCoercible = __webpack_require__(7750);
+var aPossiblePrototype = __webpack_require__(3506);
+
+// `Object.setPrototypeOf` method
+// https://tc39.es/ecma262/#sec-object.setprototypeof
+// Works with __proto__ only. Old v8 can't work with null proto objects.
+// eslint-disable-next-line es/no-object-setprototypeof -- safe
+module.exports = Object.setPrototypeOf || ('__proto__' in {} ? function () {
+ var CORRECT_SETTER = false;
+ var test = {};
+ var setter;
+ try {
+ setter = uncurryThisAccessor(Object.prototype, '__proto__', 'set');
+ setter(test, []);
+ CORRECT_SETTER = test instanceof Array;
+ } catch (error) { /* empty */ }
+ return function setPrototypeOf(O, proto) {
+ requireObjectCoercible(O);
+ aPossiblePrototype(proto);
+ if (!isObject(O)) return O;
+ if (CORRECT_SETTER) setter(O, proto);
+ else O.__proto__ = proto;
+ return O;
+ };
+}() : undefined);
+
+
+/***/ }),
+
+/***/ 4270:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var call = __webpack_require__(9565);
+var isCallable = __webpack_require__(4901);
+var isObject = __webpack_require__(34);
+
+var $TypeError = TypeError;
+
+// `OrdinaryToPrimitive` abstract operation
+// https://tc39.es/ecma262/#sec-ordinarytoprimitive
+module.exports = function (input, pref) {
+ var fn, val;
+ if (pref === 'string' && isCallable(fn = input.toString) && !isObject(val = call(fn, input))) return val;
+ if (isCallable(fn = input.valueOf) && !isObject(val = call(fn, input))) return val;
+ if (pref !== 'string' && isCallable(fn = input.toString) && !isObject(val = call(fn, input))) return val;
+ throw new $TypeError("Can't convert object to primitive value");
+};
+
+
+/***/ }),
+
+/***/ 5031:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var getBuiltIn = __webpack_require__(7751);
+var uncurryThis = __webpack_require__(9504);
+var getOwnPropertyNamesModule = __webpack_require__(8480);
+var getOwnPropertySymbolsModule = __webpack_require__(3717);
+var anObject = __webpack_require__(8551);
+
+var concat = uncurryThis([].concat);
+
+// all object keys, includes non-enumerable and symbols
+module.exports = getBuiltIn('Reflect', 'ownKeys') || function ownKeys(it) {
+ var keys = getOwnPropertyNamesModule.f(anObject(it));
+ var getOwnPropertySymbols = getOwnPropertySymbolsModule.f;
+ return getOwnPropertySymbols ? concat(keys, getOwnPropertySymbols(it)) : keys;
+};
+
+
+/***/ }),
+
+/***/ 8235:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var uncurryThis = __webpack_require__(9504);
+var hasOwn = __webpack_require__(9297);
+
+var $SyntaxError = SyntaxError;
+var $parseInt = parseInt;
+var fromCharCode = String.fromCharCode;
+var at = uncurryThis(''.charAt);
+var slice = uncurryThis(''.slice);
+var exec = uncurryThis(/./.exec);
+
+var codePoints = {
+ '\\"': '"',
+ '\\\\': '\\',
+ '\\/': '/',
+ '\\b': '\b',
+ '\\f': '\f',
+ '\\n': '\n',
+ '\\r': '\r',
+ '\\t': '\t'
+};
+
+var IS_4_HEX_DIGITS = /^[\da-f]{4}$/i;
+// eslint-disable-next-line regexp/no-control-character -- safe
+var IS_C0_CONTROL_CODE = /^[\u0000-\u001F]$/;
+
+module.exports = function (source, i) {
+ var unterminated = true;
+ var value = '';
+ while (i < source.length) {
+ var chr = at(source, i);
+ if (chr === '\\') {
+ var twoChars = slice(source, i, i + 2);
+ if (hasOwn(codePoints, twoChars)) {
+ value += codePoints[twoChars];
+ i += 2;
+ } else if (twoChars === '\\u') {
+ i += 2;
+ var fourHexDigits = slice(source, i, i + 4);
+ if (!exec(IS_4_HEX_DIGITS, fourHexDigits)) throw new $SyntaxError('Bad Unicode escape at: ' + i);
+ value += fromCharCode($parseInt(fourHexDigits, 16));
+ i += 4;
+ } else throw new $SyntaxError('Unknown escape sequence: "' + twoChars + '"');
+ } else if (chr === '"') {
+ unterminated = false;
+ i++;
+ break;
+ } else {
+ if (exec(IS_C0_CONTROL_CODE, chr)) throw new $SyntaxError('Bad control character in string literal at: ' + i);
+ value += chr;
+ i++;
+ }
+ }
+ if (unterminated) throw new $SyntaxError('Unterminated string at: ' + i);
+ return { value: value, end: i };
+};
+
+
+/***/ }),
+
+/***/ 7750:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var isNullOrUndefined = __webpack_require__(4117);
+
+var $TypeError = TypeError;
+
+// `RequireObjectCoercible` abstract operation
+// https://tc39.es/ecma262/#sec-requireobjectcoercible
+module.exports = function (it) {
+ if (isNullOrUndefined(it)) throw new $TypeError("Can't call method on " + it);
+ return it;
+};
+
+
+/***/ }),
+
+/***/ 9286:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var SetHelpers = __webpack_require__(4402);
+var iterate = __webpack_require__(8469);
+
+var Set = SetHelpers.Set;
+var add = SetHelpers.add;
+
+module.exports = function (set) {
+ var result = new Set();
+ iterate(set, function (it) {
+ add(result, it);
+ });
+ return result;
+};
+
+
+/***/ }),
+
+/***/ 3440:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var aSet = __webpack_require__(7080);
+var SetHelpers = __webpack_require__(4402);
+var clone = __webpack_require__(9286);
+var size = __webpack_require__(5170);
+var getSetRecord = __webpack_require__(3789);
+var iterateSet = __webpack_require__(8469);
+var iterateSimple = __webpack_require__(507);
+
+var has = SetHelpers.has;
+var remove = SetHelpers.remove;
+
+// `Set.prototype.difference` method
+// https://github.com/tc39/proposal-set-methods
+module.exports = function difference(other) {
+ var O = aSet(this);
+ var otherRec = getSetRecord(other);
+ var result = clone(O);
+ if (size(O) <= otherRec.size) iterateSet(O, function (e) {
+ if (otherRec.includes(e)) remove(result, e);
+ });
+ else iterateSimple(otherRec.getIterator(), function (e) {
+ if (has(O, e)) remove(result, e);
+ });
+ return result;
+};
+
+
+/***/ }),
+
+/***/ 4402:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var uncurryThis = __webpack_require__(9504);
+
+// eslint-disable-next-line es/no-set -- safe
+var SetPrototype = Set.prototype;
+
+module.exports = {
+ // eslint-disable-next-line es/no-set -- safe
+ Set: Set,
+ add: uncurryThis(SetPrototype.add),
+ has: uncurryThis(SetPrototype.has),
+ remove: uncurryThis(SetPrototype['delete']),
+ proto: SetPrototype
+};
+
+
+/***/ }),
+
+/***/ 8750:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var aSet = __webpack_require__(7080);
+var SetHelpers = __webpack_require__(4402);
+var size = __webpack_require__(5170);
+var getSetRecord = __webpack_require__(3789);
+var iterateSet = __webpack_require__(8469);
+var iterateSimple = __webpack_require__(507);
+
+var Set = SetHelpers.Set;
+var add = SetHelpers.add;
+var has = SetHelpers.has;
+
+// `Set.prototype.intersection` method
+// https://github.com/tc39/proposal-set-methods
+module.exports = function intersection(other) {
+ var O = aSet(this);
+ var otherRec = getSetRecord(other);
+ var result = new Set();
+
+ if (size(O) > otherRec.size) {
+ iterateSimple(otherRec.getIterator(), function (e) {
+ if (has(O, e)) add(result, e);
+ });
+ } else {
+ iterateSet(O, function (e) {
+ if (otherRec.includes(e)) add(result, e);
+ });
+ }
+
+ return result;
+};
+
+
+/***/ }),
+
+/***/ 4449:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var aSet = __webpack_require__(7080);
+var has = (__webpack_require__(4402).has);
+var size = __webpack_require__(5170);
+var getSetRecord = __webpack_require__(3789);
+var iterateSet = __webpack_require__(8469);
+var iterateSimple = __webpack_require__(507);
+var iteratorClose = __webpack_require__(9539);
+
+// `Set.prototype.isDisjointFrom` method
+// https://tc39.github.io/proposal-set-methods/#Set.prototype.isDisjointFrom
+module.exports = function isDisjointFrom(other) {
+ var O = aSet(this);
+ var otherRec = getSetRecord(other);
+ if (size(O) <= otherRec.size) return iterateSet(O, function (e) {
+ if (otherRec.includes(e)) return false;
+ }, true) !== false;
+ var iterator = otherRec.getIterator();
+ return iterateSimple(iterator, function (e) {
+ if (has(O, e)) return iteratorClose(iterator, 'normal', false);
+ }) !== false;
+};
+
+
+/***/ }),
+
+/***/ 3838:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var aSet = __webpack_require__(7080);
+var size = __webpack_require__(5170);
+var iterate = __webpack_require__(8469);
+var getSetRecord = __webpack_require__(3789);
+
+// `Set.prototype.isSubsetOf` method
+// https://tc39.github.io/proposal-set-methods/#Set.prototype.isSubsetOf
+module.exports = function isSubsetOf(other) {
+ var O = aSet(this);
+ var otherRec = getSetRecord(other);
+ if (size(O) > otherRec.size) return false;
+ return iterate(O, function (e) {
+ if (!otherRec.includes(e)) return false;
+ }, true) !== false;
+};
+
+
+/***/ }),
+
+/***/ 8527:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var aSet = __webpack_require__(7080);
+var has = (__webpack_require__(4402).has);
+var size = __webpack_require__(5170);
+var getSetRecord = __webpack_require__(3789);
+var iterateSimple = __webpack_require__(507);
+var iteratorClose = __webpack_require__(9539);
+
+// `Set.prototype.isSupersetOf` method
+// https://tc39.github.io/proposal-set-methods/#Set.prototype.isSupersetOf
+module.exports = function isSupersetOf(other) {
+ var O = aSet(this);
+ var otherRec = getSetRecord(other);
+ if (size(O) < otherRec.size) return false;
+ var iterator = otherRec.getIterator();
+ return iterateSimple(iterator, function (e) {
+ if (!has(O, e)) return iteratorClose(iterator, 'normal', false);
+ }) !== false;
+};
+
+
+/***/ }),
+
+/***/ 8469:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var uncurryThis = __webpack_require__(9504);
+var iterateSimple = __webpack_require__(507);
+var SetHelpers = __webpack_require__(4402);
+
+var Set = SetHelpers.Set;
+var SetPrototype = SetHelpers.proto;
+var forEach = uncurryThis(SetPrototype.forEach);
+var keys = uncurryThis(SetPrototype.keys);
+var next = keys(new Set()).next;
+
+module.exports = function (set, fn, interruptible) {
+ return interruptible ? iterateSimple({ iterator: keys(set), next: next }, fn) : forEach(set, fn);
+};
+
+
+/***/ }),
+
+/***/ 4916:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var getBuiltIn = __webpack_require__(7751);
+
+var createSetLike = function (size) {
+ return {
+ size: size,
+ has: function () {
+ return false;
+ },
+ keys: function () {
+ return {
+ next: function () {
+ return { done: true };
+ }
+ };
+ }
+ };
+};
+
+module.exports = function (name) {
+ var Set = getBuiltIn('Set');
+ try {
+ new Set()[name](createSetLike(0));
+ try {
+ // late spec change, early WebKit ~ Safari 17.0 beta implementation does not pass it
+ // https://github.com/tc39/proposal-set-methods/pull/88
+ new Set()[name](createSetLike(-1));
+ return false;
+ } catch (error2) {
+ return true;
+ }
+ } catch (error) {
+ return false;
+ }
+};
+
+
+/***/ }),
+
+/***/ 5170:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var uncurryThisAccessor = __webpack_require__(6706);
+var SetHelpers = __webpack_require__(4402);
+
+module.exports = uncurryThisAccessor(SetHelpers.proto, 'size', 'get') || function (set) {
+ return set.size;
+};
+
+
+/***/ }),
+
+/***/ 3650:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var aSet = __webpack_require__(7080);
+var SetHelpers = __webpack_require__(4402);
+var clone = __webpack_require__(9286);
+var getSetRecord = __webpack_require__(3789);
+var iterateSimple = __webpack_require__(507);
+
+var add = SetHelpers.add;
+var has = SetHelpers.has;
+var remove = SetHelpers.remove;
+
+// `Set.prototype.symmetricDifference` method
+// https://github.com/tc39/proposal-set-methods
+module.exports = function symmetricDifference(other) {
+ var O = aSet(this);
+ var keysIter = getSetRecord(other).getIterator();
+ var result = clone(O);
+ iterateSimple(keysIter, function (e) {
+ if (has(O, e)) remove(result, e);
+ else add(result, e);
+ });
+ return result;
+};
+
+
+/***/ }),
+
+/***/ 4204:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var aSet = __webpack_require__(7080);
+var add = (__webpack_require__(4402).add);
+var clone = __webpack_require__(9286);
+var getSetRecord = __webpack_require__(3789);
+var iterateSimple = __webpack_require__(507);
+
+// `Set.prototype.union` method
+// https://github.com/tc39/proposal-set-methods
+module.exports = function union(other) {
+ var O = aSet(this);
+ var keysIter = getSetRecord(other).getIterator();
+ var result = clone(O);
+ iterateSimple(keysIter, function (it) {
+ add(result, it);
+ });
+ return result;
+};
+
+
+/***/ }),
+
+/***/ 6119:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var shared = __webpack_require__(5745);
+var uid = __webpack_require__(3392);
+
+var keys = shared('keys');
+
+module.exports = function (key) {
+ return keys[key] || (keys[key] = uid(key));
+};
+
+
+/***/ }),
+
+/***/ 7629:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var IS_PURE = __webpack_require__(6395);
+var globalThis = __webpack_require__(4475);
+var defineGlobalProperty = __webpack_require__(9433);
+
+var SHARED = '__core-js_shared__';
+var store = module.exports = globalThis[SHARED] || defineGlobalProperty(SHARED, {});
+
+(store.versions || (store.versions = [])).push({
+ version: '3.37.1',
+ mode: IS_PURE ? 'pure' : 'global',
+ copyright: '© 2014-2024 Denis Pushkarev (zloirock.ru)',
+ license: 'https://github.com/zloirock/core-js/blob/v3.37.1/LICENSE',
+ source: 'https://github.com/zloirock/core-js'
+});
+
+
+/***/ }),
+
+/***/ 5745:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var store = __webpack_require__(7629);
+
+module.exports = function (key, value) {
+ return store[key] || (store[key] = value || {});
+};
+
+
+/***/ }),
+
+/***/ 1548:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var global = __webpack_require__(4475);
+var fails = __webpack_require__(9039);
+var V8 = __webpack_require__(7388);
+var IS_BROWSER = __webpack_require__(7290);
+var IS_DENO = __webpack_require__(516);
+var IS_NODE = __webpack_require__(9088);
+
+var structuredClone = global.structuredClone;
+
+module.exports = !!structuredClone && !fails(function () {
+ // prevent V8 ArrayBufferDetaching protector cell invalidation and performance degradation
+ // https://github.com/zloirock/core-js/issues/679
+ if ((IS_DENO && V8 > 92) || (IS_NODE && V8 > 94) || (IS_BROWSER && V8 > 97)) return false;
+ var buffer = new ArrayBuffer(8);
+ var clone = structuredClone(buffer, { transfer: [buffer] });
+ return buffer.byteLength !== 0 || clone.byteLength !== 8;
+});
+
+
+/***/ }),
+
+/***/ 4495:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+/* eslint-disable es/no-symbol -- required for testing */
+var V8_VERSION = __webpack_require__(7388);
+var fails = __webpack_require__(9039);
+var global = __webpack_require__(4475);
+
+var $String = global.String;
+
+// eslint-disable-next-line es/no-object-getownpropertysymbols -- required for testing
+module.exports = !!Object.getOwnPropertySymbols && !fails(function () {
+ var symbol = Symbol('symbol detection');
+ // Chrome 38 Symbol has incorrect toString conversion
+ // `get-own-property-symbols` polyfill symbols converted to object are not Symbol instances
+ // nb: Do not call `String` directly to avoid this being optimized out to `symbol+''` which will,
+ // of course, fail.
+ return !$String(symbol) || !(Object(symbol) instanceof Symbol) ||
+ // Chrome 38-40 symbols are not inherited from DOM collections prototypes to instances
+ !Symbol.sham && V8_VERSION && V8_VERSION < 41;
+});
+
+
+/***/ }),
+
+/***/ 5610:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var toIntegerOrInfinity = __webpack_require__(1291);
+
+var max = Math.max;
+var min = Math.min;
+
+// Helper for a popular repeating case of the spec:
+// Let integer be ? ToInteger(index).
+// If integer < 0, let result be max((length + integer), 0); else let result be min(integer, length).
+module.exports = function (index, length) {
+ var integer = toIntegerOrInfinity(index);
+ return integer < 0 ? max(integer + length, 0) : min(integer, length);
+};
+
+
+/***/ }),
+
+/***/ 5854:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var toPrimitive = __webpack_require__(2777);
+
+var $TypeError = TypeError;
+
+// `ToBigInt` abstract operation
+// https://tc39.es/ecma262/#sec-tobigint
+module.exports = function (argument) {
+ var prim = toPrimitive(argument, 'number');
+ if (typeof prim == 'number') throw new $TypeError("Can't convert number to bigint");
+ // eslint-disable-next-line es/no-bigint -- safe
+ return BigInt(prim);
+};
+
+
+/***/ }),
+
+/***/ 7696:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var toIntegerOrInfinity = __webpack_require__(1291);
+var toLength = __webpack_require__(8014);
+
+var $RangeError = RangeError;
+
+// `ToIndex` abstract operation
+// https://tc39.es/ecma262/#sec-toindex
+module.exports = function (it) {
+ if (it === undefined) return 0;
+ var number = toIntegerOrInfinity(it);
+ var length = toLength(number);
+ if (number !== length) throw new $RangeError('Wrong length or index');
+ return length;
+};
+
+
+/***/ }),
+
+/***/ 5397:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+// toObject with fallback for non-array-like ES3 strings
+var IndexedObject = __webpack_require__(7055);
+var requireObjectCoercible = __webpack_require__(7750);
+
+module.exports = function (it) {
+ return IndexedObject(requireObjectCoercible(it));
+};
+
+
+/***/ }),
+
+/***/ 1291:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var trunc = __webpack_require__(741);
+
+// `ToIntegerOrInfinity` abstract operation
+// https://tc39.es/ecma262/#sec-tointegerorinfinity
+module.exports = function (argument) {
+ var number = +argument;
+ // eslint-disable-next-line no-self-compare -- NaN check
+ return number !== number || number === 0 ? 0 : trunc(number);
+};
+
+
+/***/ }),
+
+/***/ 8014:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var toIntegerOrInfinity = __webpack_require__(1291);
+
+var min = Math.min;
+
+// `ToLength` abstract operation
+// https://tc39.es/ecma262/#sec-tolength
+module.exports = function (argument) {
+ var len = toIntegerOrInfinity(argument);
+ return len > 0 ? min(len, 0x1FFFFFFFFFFFFF) : 0; // 2 ** 53 - 1 == 9007199254740991
+};
+
+
+/***/ }),
+
+/***/ 8981:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var requireObjectCoercible = __webpack_require__(7750);
+
+var $Object = Object;
+
+// `ToObject` abstract operation
+// https://tc39.es/ecma262/#sec-toobject
+module.exports = function (argument) {
+ return $Object(requireObjectCoercible(argument));
+};
+
+
+/***/ }),
+
+/***/ 9590:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var toIntegerOrInfinity = __webpack_require__(1291);
+
+var $RangeError = RangeError;
+
+module.exports = function (it) {
+ var result = toIntegerOrInfinity(it);
+ if (result < 0) throw new $RangeError("The argument can't be less than 0");
+ return result;
+};
+
+
+/***/ }),
+
+/***/ 2777:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var call = __webpack_require__(9565);
+var isObject = __webpack_require__(34);
+var isSymbol = __webpack_require__(757);
+var getMethod = __webpack_require__(5966);
+var ordinaryToPrimitive = __webpack_require__(4270);
+var wellKnownSymbol = __webpack_require__(8227);
+
+var $TypeError = TypeError;
+var TO_PRIMITIVE = wellKnownSymbol('toPrimitive');
+
+// `ToPrimitive` abstract operation
+// https://tc39.es/ecma262/#sec-toprimitive
+module.exports = function (input, pref) {
+ if (!isObject(input) || isSymbol(input)) return input;
+ var exoticToPrim = getMethod(input, TO_PRIMITIVE);
+ var result;
+ if (exoticToPrim) {
+ if (pref === undefined) pref = 'default';
+ result = call(exoticToPrim, input, pref);
+ if (!isObject(result) || isSymbol(result)) return result;
+ throw new $TypeError("Can't convert object to primitive value");
+ }
+ if (pref === undefined) pref = 'number';
+ return ordinaryToPrimitive(input, pref);
+};
+
+
+/***/ }),
+
+/***/ 6969:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var toPrimitive = __webpack_require__(2777);
+var isSymbol = __webpack_require__(757);
+
+// `ToPropertyKey` abstract operation
+// https://tc39.es/ecma262/#sec-topropertykey
+module.exports = function (argument) {
+ var key = toPrimitive(argument, 'string');
+ return isSymbol(key) ? key : key + '';
+};
+
+
+/***/ }),
+
+/***/ 2140:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var wellKnownSymbol = __webpack_require__(8227);
+
+var TO_STRING_TAG = wellKnownSymbol('toStringTag');
+var test = {};
+
+test[TO_STRING_TAG] = 'z';
+
+module.exports = String(test) === '[object z]';
+
+
+/***/ }),
+
+/***/ 655:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var classof = __webpack_require__(6955);
+
+var $String = String;
+
+module.exports = function (argument) {
+ if (classof(argument) === 'Symbol') throw new TypeError('Cannot convert a Symbol value to a string');
+ return $String(argument);
+};
+
+
+/***/ }),
+
+/***/ 9714:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var IS_NODE = __webpack_require__(9088);
+
+module.exports = function (name) {
+ try {
+ // eslint-disable-next-line no-new-func -- safe
+ if (IS_NODE) return Function('return require("' + name + '")')();
+ } catch (error) { /* empty */ }
+};
+
+
+/***/ }),
+
+/***/ 6823:
+/***/ ((module) => {
+
+
+var $String = String;
+
+module.exports = function (argument) {
+ try {
+ return $String(argument);
+ } catch (error) {
+ return 'Object';
+ }
+};
+
+
+/***/ }),
+
+/***/ 3392:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var uncurryThis = __webpack_require__(9504);
+
+var id = 0;
+var postfix = Math.random();
+var toString = uncurryThis(1.0.toString);
+
+module.exports = function (key) {
+ return 'Symbol(' + (key === undefined ? '' : key) + ')_' + toString(++id + postfix, 36);
+};
+
+
+/***/ }),
+
+/***/ 7040:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+/* eslint-disable es/no-symbol -- required for testing */
+var NATIVE_SYMBOL = __webpack_require__(4495);
+
+module.exports = NATIVE_SYMBOL
+ && !Symbol.sham
+ && typeof Symbol.iterator == 'symbol';
+
+
+/***/ }),
+
+/***/ 8686:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var DESCRIPTORS = __webpack_require__(3724);
+var fails = __webpack_require__(9039);
+
+// V8 ~ Chrome 36-
+// https://bugs.chromium.org/p/v8/issues/detail?id=3334
+module.exports = DESCRIPTORS && fails(function () {
+ // eslint-disable-next-line es/no-object-defineproperty -- required for testing
+ return Object.defineProperty(function () { /* empty */ }, 'prototype', {
+ value: 42,
+ writable: false
+ }).prototype !== 42;
+});
+
+
+/***/ }),
+
+/***/ 2812:
+/***/ ((module) => {
+
+
+var $TypeError = TypeError;
+
+module.exports = function (passed, required) {
+ if (passed < required) throw new $TypeError('Not enough arguments');
+ return passed;
+};
+
+
+/***/ }),
+
+/***/ 8622:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var global = __webpack_require__(4475);
+var isCallable = __webpack_require__(4901);
+
+var WeakMap = global.WeakMap;
+
+module.exports = isCallable(WeakMap) && /native code/.test(String(WeakMap));
+
+
+/***/ }),
+
+/***/ 8227:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var global = __webpack_require__(4475);
+var shared = __webpack_require__(5745);
+var hasOwn = __webpack_require__(9297);
+var uid = __webpack_require__(3392);
+var NATIVE_SYMBOL = __webpack_require__(4495);
+var USE_SYMBOL_AS_UID = __webpack_require__(7040);
+
+var Symbol = global.Symbol;
+var WellKnownSymbolsStore = shared('wks');
+var createWellKnownSymbol = USE_SYMBOL_AS_UID ? Symbol['for'] || Symbol : Symbol && Symbol.withoutSetter || uid;
+
+module.exports = function (name) {
+ if (!hasOwn(WellKnownSymbolsStore, name)) {
+ WellKnownSymbolsStore[name] = NATIVE_SYMBOL && hasOwn(Symbol, name)
+ ? Symbol[name]
+ : createWellKnownSymbol('Symbol.' + name);
+ } return WellKnownSymbolsStore[name];
+};
+
+
+/***/ }),
+
+/***/ 6573:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var DESCRIPTORS = __webpack_require__(3724);
+var defineBuiltInAccessor = __webpack_require__(2106);
+var isDetached = __webpack_require__(3238);
+
+var ArrayBufferPrototype = ArrayBuffer.prototype;
+
+if (DESCRIPTORS && !('detached' in ArrayBufferPrototype)) {
+ defineBuiltInAccessor(ArrayBufferPrototype, 'detached', {
+ configurable: true,
+ get: function detached() {
+ return isDetached(this);
+ }
+ });
+}
+
+
+/***/ }),
+
+/***/ 7936:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var $ = __webpack_require__(6518);
+var $transfer = __webpack_require__(5636);
+
+// `ArrayBuffer.prototype.transferToFixedLength` method
+// https://tc39.es/proposal-arraybuffer-transfer/#sec-arraybuffer.prototype.transfertofixedlength
+if ($transfer) $({ target: 'ArrayBuffer', proto: true }, {
+ transferToFixedLength: function transferToFixedLength() {
+ return $transfer(this, arguments.length ? arguments[0] : undefined, false);
+ }
+});
+
+
+/***/ }),
+
+/***/ 8100:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var $ = __webpack_require__(6518);
+var $transfer = __webpack_require__(5636);
+
+// `ArrayBuffer.prototype.transfer` method
+// https://tc39.es/proposal-arraybuffer-transfer/#sec-arraybuffer.prototype.transfer
+if ($transfer) $({ target: 'ArrayBuffer', proto: true }, {
+ transfer: function transfer() {
+ return $transfer(this, arguments.length ? arguments[0] : undefined, true);
+ }
+});
+
+
+/***/ }),
+
+/***/ 4114:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var $ = __webpack_require__(6518);
+var toObject = __webpack_require__(8981);
+var lengthOfArrayLike = __webpack_require__(6198);
+var setArrayLength = __webpack_require__(4527);
+var doesNotExceedSafeInteger = __webpack_require__(6837);
+var fails = __webpack_require__(9039);
+
+var INCORRECT_TO_LENGTH = fails(function () {
+ return [].push.call({ length: 0x100000000 }, 1) !== 4294967297;
+});
+
+// V8 <= 121 and Safari <= 15.4; FF < 23 throws InternalError
+// https://bugs.chromium.org/p/v8/issues/detail?id=12681
+var properErrorOnNonWritableLength = function () {
+ try {
+ // eslint-disable-next-line es/no-object-defineproperty -- safe
+ Object.defineProperty([], 'length', { writable: false }).push();
+ } catch (error) {
+ return error instanceof TypeError;
+ }
+};
+
+var FORCED = INCORRECT_TO_LENGTH || !properErrorOnNonWritableLength();
+
+// `Array.prototype.push` method
+// https://tc39.es/ecma262/#sec-array.prototype.push
+$({ target: 'Array', proto: true, arity: 1, forced: FORCED }, {
+ // eslint-disable-next-line no-unused-vars -- required for `.length`
+ push: function push(item) {
+ var O = toObject(this);
+ var len = lengthOfArrayLike(O);
+ var argCount = arguments.length;
+ doesNotExceedSafeInteger(len + argCount);
+ for (var i = 0; i < argCount; i++) {
+ O[len] = arguments[i];
+ len++;
+ }
+ setArrayLength(O, len);
+ return len;
+ }
+});
+
+
+/***/ }),
+
+/***/ 4628:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var $ = __webpack_require__(6518);
+var newPromiseCapabilityModule = __webpack_require__(6043);
+
+// `Promise.withResolvers` method
+// https://github.com/tc39/proposal-promise-with-resolvers
+$({ target: 'Promise', stat: true }, {
+ withResolvers: function withResolvers() {
+ var promiseCapability = newPromiseCapabilityModule.f(this);
+ return {
+ promise: promiseCapability.promise,
+ resolve: promiseCapability.resolve,
+ reject: promiseCapability.reject
+ };
+ }
+});
+
+
+/***/ }),
+
+/***/ 7642:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var $ = __webpack_require__(6518);
+var difference = __webpack_require__(3440);
+var setMethodAcceptSetLike = __webpack_require__(4916);
+
+// `Set.prototype.difference` method
+// https://github.com/tc39/proposal-set-methods
+$({ target: 'Set', proto: true, real: true, forced: !setMethodAcceptSetLike('difference') }, {
+ difference: difference
+});
+
+
+/***/ }),
+
+/***/ 8004:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var $ = __webpack_require__(6518);
+var fails = __webpack_require__(9039);
+var intersection = __webpack_require__(8750);
+var setMethodAcceptSetLike = __webpack_require__(4916);
+
+var INCORRECT = !setMethodAcceptSetLike('intersection') || fails(function () {
+ // eslint-disable-next-line es/no-array-from, es/no-set -- testing
+ return String(Array.from(new Set([1, 2, 3]).intersection(new Set([3, 2])))) !== '3,2';
+});
+
+// `Set.prototype.intersection` method
+// https://github.com/tc39/proposal-set-methods
+$({ target: 'Set', proto: true, real: true, forced: INCORRECT }, {
+ intersection: intersection
+});
+
+
+/***/ }),
+
+/***/ 3853:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var $ = __webpack_require__(6518);
+var isDisjointFrom = __webpack_require__(4449);
+var setMethodAcceptSetLike = __webpack_require__(4916);
+
+// `Set.prototype.isDisjointFrom` method
+// https://github.com/tc39/proposal-set-methods
+$({ target: 'Set', proto: true, real: true, forced: !setMethodAcceptSetLike('isDisjointFrom') }, {
+ isDisjointFrom: isDisjointFrom
+});
+
+
+/***/ }),
+
+/***/ 5876:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var $ = __webpack_require__(6518);
+var isSubsetOf = __webpack_require__(3838);
+var setMethodAcceptSetLike = __webpack_require__(4916);
+
+// `Set.prototype.isSubsetOf` method
+// https://github.com/tc39/proposal-set-methods
+$({ target: 'Set', proto: true, real: true, forced: !setMethodAcceptSetLike('isSubsetOf') }, {
+ isSubsetOf: isSubsetOf
+});
+
+
+/***/ }),
+
+/***/ 2475:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var $ = __webpack_require__(6518);
+var isSupersetOf = __webpack_require__(8527);
+var setMethodAcceptSetLike = __webpack_require__(4916);
+
+// `Set.prototype.isSupersetOf` method
+// https://github.com/tc39/proposal-set-methods
+$({ target: 'Set', proto: true, real: true, forced: !setMethodAcceptSetLike('isSupersetOf') }, {
+ isSupersetOf: isSupersetOf
+});
+
+
+/***/ }),
+
+/***/ 5024:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var $ = __webpack_require__(6518);
+var symmetricDifference = __webpack_require__(3650);
+var setMethodAcceptSetLike = __webpack_require__(4916);
+
+// `Set.prototype.symmetricDifference` method
+// https://github.com/tc39/proposal-set-methods
+$({ target: 'Set', proto: true, real: true, forced: !setMethodAcceptSetLike('symmetricDifference') }, {
+ symmetricDifference: symmetricDifference
+});
+
+
+/***/ }),
+
+/***/ 1698:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var $ = __webpack_require__(6518);
+var union = __webpack_require__(4204);
+var setMethodAcceptSetLike = __webpack_require__(4916);
+
+// `Set.prototype.union` method
+// https://github.com/tc39/proposal-set-methods
+$({ target: 'Set', proto: true, real: true, forced: !setMethodAcceptSetLike('union') }, {
+ union: union
+});
+
+
+/***/ }),
+
+/***/ 7467:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var arrayToReversed = __webpack_require__(7628);
+var ArrayBufferViewCore = __webpack_require__(4644);
+
+var aTypedArray = ArrayBufferViewCore.aTypedArray;
+var exportTypedArrayMethod = ArrayBufferViewCore.exportTypedArrayMethod;
+var getTypedArrayConstructor = ArrayBufferViewCore.getTypedArrayConstructor;
+
+// `%TypedArray%.prototype.toReversed` method
+// https://tc39.es/ecma262/#sec-%typedarray%.prototype.toreversed
+exportTypedArrayMethod('toReversed', function toReversed() {
+ return arrayToReversed(aTypedArray(this), getTypedArrayConstructor(this));
+});
+
+
+/***/ }),
+
+/***/ 4732:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var ArrayBufferViewCore = __webpack_require__(4644);
+var uncurryThis = __webpack_require__(9504);
+var aCallable = __webpack_require__(9306);
+var arrayFromConstructorAndList = __webpack_require__(5370);
+
+var aTypedArray = ArrayBufferViewCore.aTypedArray;
+var getTypedArrayConstructor = ArrayBufferViewCore.getTypedArrayConstructor;
+var exportTypedArrayMethod = ArrayBufferViewCore.exportTypedArrayMethod;
+var sort = uncurryThis(ArrayBufferViewCore.TypedArrayPrototype.sort);
+
+// `%TypedArray%.prototype.toSorted` method
+// https://tc39.es/ecma262/#sec-%typedarray%.prototype.tosorted
+exportTypedArrayMethod('toSorted', function toSorted(compareFn) {
+ if (compareFn !== undefined) aCallable(compareFn);
+ var O = aTypedArray(this);
+ var A = arrayFromConstructorAndList(getTypedArrayConstructor(O), O);
+ return sort(A, compareFn);
+});
+
+
+/***/ }),
+
+/***/ 9577:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var arrayWith = __webpack_require__(9928);
+var ArrayBufferViewCore = __webpack_require__(4644);
+var isBigIntArray = __webpack_require__(1108);
+var toIntegerOrInfinity = __webpack_require__(1291);
+var toBigInt = __webpack_require__(5854);
+
+var aTypedArray = ArrayBufferViewCore.aTypedArray;
+var getTypedArrayConstructor = ArrayBufferViewCore.getTypedArrayConstructor;
+var exportTypedArrayMethod = ArrayBufferViewCore.exportTypedArrayMethod;
+
+var PROPER_ORDER = !!function () {
+ try {
+ // eslint-disable-next-line no-throw-literal, es/no-typed-arrays, es/no-array-prototype-with -- required for testing
+ new Int8Array(1)['with'](2, { valueOf: function () { throw 8; } });
+ } catch (error) {
+ // some early implementations, like WebKit, does not follow the final semantic
+ // https://github.com/tc39/proposal-change-array-by-copy/pull/86
+ return error === 8;
+ }
+}();
+
+// `%TypedArray%.prototype.with` method
+// https://tc39.es/ecma262/#sec-%typedarray%.prototype.with
+exportTypedArrayMethod('with', { 'with': function (index, value) {
+ var O = aTypedArray(this);
+ var relativeIndex = toIntegerOrInfinity(index);
+ var actualValue = isBigIntArray(O) ? toBigInt(value) : +value;
+ return arrayWith(O, getTypedArrayConstructor(O), relativeIndex, actualValue);
+} }['with'], !PROPER_ORDER);
+
+
+/***/ }),
+
+/***/ 8992:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var $ = __webpack_require__(6518);
+var global = __webpack_require__(4475);
+var anInstance = __webpack_require__(679);
+var anObject = __webpack_require__(8551);
+var isCallable = __webpack_require__(4901);
+var getPrototypeOf = __webpack_require__(2787);
+var defineBuiltInAccessor = __webpack_require__(2106);
+var createProperty = __webpack_require__(4659);
+var fails = __webpack_require__(9039);
+var hasOwn = __webpack_require__(9297);
+var wellKnownSymbol = __webpack_require__(8227);
+var IteratorPrototype = (__webpack_require__(7657).IteratorPrototype);
+var DESCRIPTORS = __webpack_require__(3724);
+var IS_PURE = __webpack_require__(6395);
+
+var CONSTRUCTOR = 'constructor';
+var ITERATOR = 'Iterator';
+var TO_STRING_TAG = wellKnownSymbol('toStringTag');
+
+var $TypeError = TypeError;
+var NativeIterator = global[ITERATOR];
+
+// FF56- have non-standard global helper `Iterator`
+var FORCED = IS_PURE
+ || !isCallable(NativeIterator)
+ || NativeIterator.prototype !== IteratorPrototype
+ // FF44- non-standard `Iterator` passes previous tests
+ || !fails(function () { NativeIterator({}); });
+
+var IteratorConstructor = function Iterator() {
+ anInstance(this, IteratorPrototype);
+ if (getPrototypeOf(this) === IteratorPrototype) throw new $TypeError('Abstract class Iterator not directly constructable');
+};
+
+var defineIteratorPrototypeAccessor = function (key, value) {
+ if (DESCRIPTORS) {
+ defineBuiltInAccessor(IteratorPrototype, key, {
+ configurable: true,
+ get: function () {
+ return value;
+ },
+ set: function (replacement) {
+ anObject(this);
+ if (this === IteratorPrototype) throw new $TypeError("You can't redefine this property");
+ if (hasOwn(this, key)) this[key] = replacement;
+ else createProperty(this, key, replacement);
+ }
+ });
+ } else IteratorPrototype[key] = value;
+};
+
+if (!hasOwn(IteratorPrototype, TO_STRING_TAG)) defineIteratorPrototypeAccessor(TO_STRING_TAG, ITERATOR);
+
+if (FORCED || !hasOwn(IteratorPrototype, CONSTRUCTOR) || IteratorPrototype[CONSTRUCTOR] === Object) {
+ defineIteratorPrototypeAccessor(CONSTRUCTOR, IteratorConstructor);
+}
+
+IteratorConstructor.prototype = IteratorPrototype;
+
+// `Iterator` constructor
+// https://github.com/tc39/proposal-iterator-helpers
+$({ global: true, constructor: true, forced: FORCED }, {
+ Iterator: IteratorConstructor
+});
+
+
+/***/ }),
+
+/***/ 4743:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var $ = __webpack_require__(6518);
+var call = __webpack_require__(9565);
+var anObject = __webpack_require__(8551);
+var getIteratorDirect = __webpack_require__(1767);
+var notANaN = __webpack_require__(4149);
+var toPositiveInteger = __webpack_require__(9590);
+var createIteratorProxy = __webpack_require__(9462);
+var IS_PURE = __webpack_require__(6395);
+
+var IteratorProxy = createIteratorProxy(function () {
+ var iterator = this.iterator;
+ var next = this.next;
+ var result, done;
+ while (this.remaining) {
+ this.remaining--;
+ result = anObject(call(next, iterator));
+ done = this.done = !!result.done;
+ if (done) return;
+ }
+ result = anObject(call(next, iterator));
+ done = this.done = !!result.done;
+ if (!done) return result.value;
+});
+
+// `Iterator.prototype.drop` method
+// https://github.com/tc39/proposal-iterator-helpers
+$({ target: 'Iterator', proto: true, real: true, forced: IS_PURE }, {
+ drop: function drop(limit) {
+ anObject(this);
+ var remaining = toPositiveInteger(notANaN(+limit));
+ return new IteratorProxy(getIteratorDirect(this), {
+ remaining: remaining
+ });
+ }
+});
+
+
+/***/ }),
+
+/***/ 3215:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var $ = __webpack_require__(6518);
+var iterate = __webpack_require__(2652);
+var aCallable = __webpack_require__(9306);
+var anObject = __webpack_require__(8551);
+var getIteratorDirect = __webpack_require__(1767);
+
+// `Iterator.prototype.every` method
+// https://github.com/tc39/proposal-iterator-helpers
+$({ target: 'Iterator', proto: true, real: true }, {
+ every: function every(predicate) {
+ anObject(this);
+ aCallable(predicate);
+ var record = getIteratorDirect(this);
+ var counter = 0;
+ return !iterate(record, function (value, stop) {
+ if (!predicate(value, counter++)) return stop();
+ }, { IS_RECORD: true, INTERRUPTED: true }).stopped;
+ }
+});
+
+
+/***/ }),
+
+/***/ 4520:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var $ = __webpack_require__(6518);
+var call = __webpack_require__(9565);
+var aCallable = __webpack_require__(9306);
+var anObject = __webpack_require__(8551);
+var getIteratorDirect = __webpack_require__(1767);
+var createIteratorProxy = __webpack_require__(9462);
+var callWithSafeIterationClosing = __webpack_require__(6319);
+var IS_PURE = __webpack_require__(6395);
+
+var IteratorProxy = createIteratorProxy(function () {
+ var iterator = this.iterator;
+ var predicate = this.predicate;
+ var next = this.next;
+ var result, done, value;
+ while (true) {
+ result = anObject(call(next, iterator));
+ done = this.done = !!result.done;
+ if (done) return;
+ value = result.value;
+ if (callWithSafeIterationClosing(iterator, predicate, [value, this.counter++], true)) return value;
+ }
+});
+
+// `Iterator.prototype.filter` method
+// https://github.com/tc39/proposal-iterator-helpers
+$({ target: 'Iterator', proto: true, real: true, forced: IS_PURE }, {
+ filter: function filter(predicate) {
+ anObject(this);
+ aCallable(predicate);
+ return new IteratorProxy(getIteratorDirect(this), {
+ predicate: predicate
+ });
+ }
+});
+
+
+/***/ }),
+
+/***/ 670:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var $ = __webpack_require__(6518);
+var call = __webpack_require__(9565);
+var aCallable = __webpack_require__(9306);
+var anObject = __webpack_require__(8551);
+var getIteratorDirect = __webpack_require__(1767);
+var getIteratorFlattenable = __webpack_require__(8646);
+var createIteratorProxy = __webpack_require__(9462);
+var iteratorClose = __webpack_require__(9539);
+var IS_PURE = __webpack_require__(6395);
+
+var IteratorProxy = createIteratorProxy(function () {
+ var iterator = this.iterator;
+ var mapper = this.mapper;
+ var result, inner;
+
+ while (true) {
+ if (inner = this.inner) try {
+ result = anObject(call(inner.next, inner.iterator));
+ if (!result.done) return result.value;
+ this.inner = null;
+ } catch (error) { iteratorClose(iterator, 'throw', error); }
+
+ result = anObject(call(this.next, iterator));
+
+ if (this.done = !!result.done) return;
+
+ try {
+ this.inner = getIteratorFlattenable(mapper(result.value, this.counter++), false);
+ } catch (error) { iteratorClose(iterator, 'throw', error); }
+ }
+});
+
+// `Iterator.prototype.flatMap` method
+// https://github.com/tc39/proposal-iterator-helpers
+$({ target: 'Iterator', proto: true, real: true, forced: IS_PURE }, {
+ flatMap: function flatMap(mapper) {
+ anObject(this);
+ aCallable(mapper);
+ return new IteratorProxy(getIteratorDirect(this), {
+ mapper: mapper,
+ inner: null
+ });
+ }
+});
+
+
+/***/ }),
+
+/***/ 1454:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var $ = __webpack_require__(6518);
+var map = __webpack_require__(713);
+var IS_PURE = __webpack_require__(6395);
+
+// `Iterator.prototype.map` method
+// https://github.com/tc39/proposal-iterator-helpers
+$({ target: 'Iterator', proto: true, real: true, forced: IS_PURE }, {
+ map: map
+});
+
+
+/***/ }),
+
+/***/ 7550:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var $ = __webpack_require__(6518);
+var iterate = __webpack_require__(2652);
+var aCallable = __webpack_require__(9306);
+var anObject = __webpack_require__(8551);
+var getIteratorDirect = __webpack_require__(1767);
+
+// `Iterator.prototype.some` method
+// https://github.com/tc39/proposal-iterator-helpers
+$({ target: 'Iterator', proto: true, real: true }, {
+ some: function some(predicate) {
+ anObject(this);
+ aCallable(predicate);
+ var record = getIteratorDirect(this);
+ var counter = 0;
+ return iterate(record, function (value, stop) {
+ if (predicate(value, counter++)) return stop();
+ }, { IS_RECORD: true, INTERRUPTED: true }).stopped;
+ }
+});
+
+
+/***/ }),
+
+/***/ 8335:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var $ = __webpack_require__(6518);
+var DESCRIPTORS = __webpack_require__(3724);
+var global = __webpack_require__(4475);
+var getBuiltIn = __webpack_require__(7751);
+var uncurryThis = __webpack_require__(9504);
+var call = __webpack_require__(9565);
+var isCallable = __webpack_require__(4901);
+var isObject = __webpack_require__(34);
+var isArray = __webpack_require__(4376);
+var hasOwn = __webpack_require__(9297);
+var toString = __webpack_require__(655);
+var lengthOfArrayLike = __webpack_require__(6198);
+var createProperty = __webpack_require__(4659);
+var fails = __webpack_require__(9039);
+var parseJSONString = __webpack_require__(8235);
+var NATIVE_SYMBOL = __webpack_require__(4495);
+
+var JSON = global.JSON;
+var Number = global.Number;
+var SyntaxError = global.SyntaxError;
+var nativeParse = JSON && JSON.parse;
+var enumerableOwnProperties = getBuiltIn('Object', 'keys');
+// eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
+var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
+var at = uncurryThis(''.charAt);
+var slice = uncurryThis(''.slice);
+var exec = uncurryThis(/./.exec);
+var push = uncurryThis([].push);
+
+var IS_DIGIT = /^\d$/;
+var IS_NON_ZERO_DIGIT = /^[1-9]$/;
+var IS_NUMBER_START = /^(?:-|\d)$/;
+var IS_WHITESPACE = /^[\t\n\r ]$/;
+
+var PRIMITIVE = 0;
+var OBJECT = 1;
+
+var $parse = function (source, reviver) {
+ source = toString(source);
+ var context = new Context(source, 0, '');
+ var root = context.parse();
+ var value = root.value;
+ var endIndex = context.skip(IS_WHITESPACE, root.end);
+ if (endIndex < source.length) {
+ throw new SyntaxError('Unexpected extra character: "' + at(source, endIndex) + '" after the parsed data at: ' + endIndex);
+ }
+ return isCallable(reviver) ? internalize({ '': value }, '', reviver, root) : value;
+};
+
+var internalize = function (holder, name, reviver, node) {
+ var val = holder[name];
+ var unmodified = node && val === node.value;
+ var context = unmodified && typeof node.source == 'string' ? { source: node.source } : {};
+ var elementRecordsLen, keys, len, i, P;
+ if (isObject(val)) {
+ var nodeIsArray = isArray(val);
+ var nodes = unmodified ? node.nodes : nodeIsArray ? [] : {};
+ if (nodeIsArray) {
+ elementRecordsLen = nodes.length;
+ len = lengthOfArrayLike(val);
+ for (i = 0; i < len; i++) {
+ internalizeProperty(val, i, internalize(val, '' + i, reviver, i < elementRecordsLen ? nodes[i] : undefined));
+ }
+ } else {
+ keys = enumerableOwnProperties(val);
+ len = lengthOfArrayLike(keys);
+ for (i = 0; i < len; i++) {
+ P = keys[i];
+ internalizeProperty(val, P, internalize(val, P, reviver, hasOwn(nodes, P) ? nodes[P] : undefined));
+ }
+ }
+ }
+ return call(reviver, holder, name, val, context);
+};
+
+var internalizeProperty = function (object, key, value) {
+ if (DESCRIPTORS) {
+ var descriptor = getOwnPropertyDescriptor(object, key);
+ if (descriptor && !descriptor.configurable) return;
+ }
+ if (value === undefined) delete object[key];
+ else createProperty(object, key, value);
+};
+
+var Node = function (value, end, source, nodes) {
+ this.value = value;
+ this.end = end;
+ this.source = source;
+ this.nodes = nodes;
+};
+
+var Context = function (source, index) {
+ this.source = source;
+ this.index = index;
+};
+
+// https://www.json.org/json-en.html
+Context.prototype = {
+ fork: function (nextIndex) {
+ return new Context(this.source, nextIndex);
+ },
+ parse: function () {
+ var source = this.source;
+ var i = this.skip(IS_WHITESPACE, this.index);
+ var fork = this.fork(i);
+ var chr = at(source, i);
+ if (exec(IS_NUMBER_START, chr)) return fork.number();
+ switch (chr) {
+ case '{':
+ return fork.object();
+ case '[':
+ return fork.array();
+ case '"':
+ return fork.string();
+ case 't':
+ return fork.keyword(true);
+ case 'f':
+ return fork.keyword(false);
+ case 'n':
+ return fork.keyword(null);
+ } throw new SyntaxError('Unexpected character: "' + chr + '" at: ' + i);
+ },
+ node: function (type, value, start, end, nodes) {
+ return new Node(value, end, type ? null : slice(this.source, start, end), nodes);
+ },
+ object: function () {
+ var source = this.source;
+ var i = this.index + 1;
+ var expectKeypair = false;
+ var object = {};
+ var nodes = {};
+ while (i < source.length) {
+ i = this.until(['"', '}'], i);
+ if (at(source, i) === '}' && !expectKeypair) {
+ i++;
+ break;
+ }
+ // Parsing the key
+ var result = this.fork(i).string();
+ var key = result.value;
+ i = result.end;
+ i = this.until([':'], i) + 1;
+ // Parsing value
+ i = this.skip(IS_WHITESPACE, i);
+ result = this.fork(i).parse();
+ createProperty(nodes, key, result);
+ createProperty(object, key, result.value);
+ i = this.until([',', '}'], result.end);
+ var chr = at(source, i);
+ if (chr === ',') {
+ expectKeypair = true;
+ i++;
+ } else if (chr === '}') {
+ i++;
+ break;
+ }
+ }
+ return this.node(OBJECT, object, this.index, i, nodes);
+ },
+ array: function () {
+ var source = this.source;
+ var i = this.index + 1;
+ var expectElement = false;
+ var array = [];
+ var nodes = [];
+ while (i < source.length) {
+ i = this.skip(IS_WHITESPACE, i);
+ if (at(source, i) === ']' && !expectElement) {
+ i++;
+ break;
+ }
+ var result = this.fork(i).parse();
+ push(nodes, result);
+ push(array, result.value);
+ i = this.until([',', ']'], result.end);
+ if (at(source, i) === ',') {
+ expectElement = true;
+ i++;
+ } else if (at(source, i) === ']') {
+ i++;
+ break;
+ }
+ }
+ return this.node(OBJECT, array, this.index, i, nodes);
+ },
+ string: function () {
+ var index = this.index;
+ var parsed = parseJSONString(this.source, this.index + 1);
+ return this.node(PRIMITIVE, parsed.value, index, parsed.end);
+ },
+ number: function () {
+ var source = this.source;
+ var startIndex = this.index;
+ var i = startIndex;
+ if (at(source, i) === '-') i++;
+ if (at(source, i) === '0') i++;
+ else if (exec(IS_NON_ZERO_DIGIT, at(source, i))) i = this.skip(IS_DIGIT, ++i);
+ else throw new SyntaxError('Failed to parse number at: ' + i);
+ if (at(source, i) === '.') i = this.skip(IS_DIGIT, ++i);
+ if (at(source, i) === 'e' || at(source, i) === 'E') {
+ i++;
+ if (at(source, i) === '+' || at(source, i) === '-') i++;
+ var exponentStartIndex = i;
+ i = this.skip(IS_DIGIT, i);
+ if (exponentStartIndex === i) throw new SyntaxError("Failed to parse number's exponent value at: " + i);
+ }
+ return this.node(PRIMITIVE, Number(slice(source, startIndex, i)), startIndex, i);
+ },
+ keyword: function (value) {
+ var keyword = '' + value;
+ var index = this.index;
+ var endIndex = index + keyword.length;
+ if (slice(this.source, index, endIndex) !== keyword) throw new SyntaxError('Failed to parse value at: ' + index);
+ return this.node(PRIMITIVE, value, index, endIndex);
+ },
+ skip: function (regex, i) {
+ var source = this.source;
+ for (; i < source.length; i++) if (!exec(regex, at(source, i))) break;
+ return i;
+ },
+ until: function (array, i) {
+ i = this.skip(IS_WHITESPACE, i);
+ var chr = at(this.source, i);
+ for (var j = 0; j < array.length; j++) if (array[j] === chr) return i;
+ throw new SyntaxError('Unexpected character: "' + chr + '" at: ' + i);
+ }
+};
+
+var NO_SOURCE_SUPPORT = fails(function () {
+ var unsafeInt = '9007199254740993';
+ var source;
+ nativeParse(unsafeInt, function (key, value, context) {
+ source = context.source;
+ });
+ return source !== unsafeInt;
+});
+
+var PROPER_BASE_PARSE = NATIVE_SYMBOL && !fails(function () {
+ // Safari 9 bug
+ return 1 / nativeParse('-0 \t') !== -Infinity;
+});
+
+// `JSON.parse` method
+// https://tc39.es/ecma262/#sec-json.parse
+// https://github.com/tc39/proposal-json-parse-with-source
+$({ target: 'JSON', stat: true, forced: NO_SOURCE_SUPPORT }, {
+ parse: function parse(text, reviver) {
+ return PROPER_BASE_PARSE && !isCallable(reviver) ? nativeParse(text) : $parse(text, reviver);
+ }
+});
+
+
+/***/ }),
+
+/***/ 3375:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+// TODO: Remove from `core-js@4`
+__webpack_require__(7642);
+
+
+/***/ }),
+
+/***/ 9225:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+// TODO: Remove from `core-js@4`
+__webpack_require__(8004);
+
+
+/***/ }),
+
+/***/ 3972:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+// TODO: Remove from `core-js@4`
+__webpack_require__(3853);
+
+
+/***/ }),
+
+/***/ 9209:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+// TODO: Remove from `core-js@4`
+__webpack_require__(5876);
+
+
+/***/ }),
+
+/***/ 5714:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+// TODO: Remove from `core-js@4`
+__webpack_require__(2475);
+
+
+/***/ }),
+
+/***/ 7561:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+// TODO: Remove from `core-js@4`
+__webpack_require__(5024);
+
+
+/***/ }),
+
+/***/ 6197:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+// TODO: Remove from `core-js@4`
+__webpack_require__(1698);
+
+
+/***/ }),
+
+/***/ 4979:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var $ = __webpack_require__(6518);
+var global = __webpack_require__(4475);
+var getBuiltIn = __webpack_require__(7751);
+var createPropertyDescriptor = __webpack_require__(6980);
+var defineProperty = (__webpack_require__(4913).f);
+var hasOwn = __webpack_require__(9297);
+var anInstance = __webpack_require__(679);
+var inheritIfRequired = __webpack_require__(3167);
+var normalizeStringArgument = __webpack_require__(2603);
+var DOMExceptionConstants = __webpack_require__(5002);
+var clearErrorStack = __webpack_require__(6193);
+var DESCRIPTORS = __webpack_require__(3724);
+var IS_PURE = __webpack_require__(6395);
+
+var DOM_EXCEPTION = 'DOMException';
+var Error = getBuiltIn('Error');
+var NativeDOMException = getBuiltIn(DOM_EXCEPTION);
+
+var $DOMException = function DOMException() {
+ anInstance(this, DOMExceptionPrototype);
+ var argumentsLength = arguments.length;
+ var message = normalizeStringArgument(argumentsLength < 1 ? undefined : arguments[0]);
+ var name = normalizeStringArgument(argumentsLength < 2 ? undefined : arguments[1], 'Error');
+ var that = new NativeDOMException(message, name);
+ var error = new Error(message);
+ error.name = DOM_EXCEPTION;
+ defineProperty(that, 'stack', createPropertyDescriptor(1, clearErrorStack(error.stack, 1)));
+ inheritIfRequired(that, this, $DOMException);
+ return that;
+};
+
+var DOMExceptionPrototype = $DOMException.prototype = NativeDOMException.prototype;
+
+var ERROR_HAS_STACK = 'stack' in new Error(DOM_EXCEPTION);
+var DOM_EXCEPTION_HAS_STACK = 'stack' in new NativeDOMException(1, 2);
+
+// eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
+var descriptor = NativeDOMException && DESCRIPTORS && Object.getOwnPropertyDescriptor(global, DOM_EXCEPTION);
+
+// Bun ~ 0.1.1 DOMException have incorrect descriptor and we can't redefine it
+// https://github.com/Jarred-Sumner/bun/issues/399
+var BUGGY_DESCRIPTOR = !!descriptor && !(descriptor.writable && descriptor.configurable);
+
+var FORCED_CONSTRUCTOR = ERROR_HAS_STACK && !BUGGY_DESCRIPTOR && !DOM_EXCEPTION_HAS_STACK;
+
+// `DOMException` constructor patch for `.stack` where it's required
+// https://webidl.spec.whatwg.org/#es-DOMException-specialness
+$({ global: true, constructor: true, forced: IS_PURE || FORCED_CONSTRUCTOR }, { // TODO: fix export logic
+ DOMException: FORCED_CONSTRUCTOR ? $DOMException : NativeDOMException
+});
+
+var PolyfilledDOMException = getBuiltIn(DOM_EXCEPTION);
+var PolyfilledDOMExceptionPrototype = PolyfilledDOMException.prototype;
+
+if (PolyfilledDOMExceptionPrototype.constructor !== PolyfilledDOMException) {
+ if (!IS_PURE) {
+ defineProperty(PolyfilledDOMExceptionPrototype, 'constructor', createPropertyDescriptor(1, PolyfilledDOMException));
+ }
+
+ for (var key in DOMExceptionConstants) if (hasOwn(DOMExceptionConstants, key)) {
+ var constant = DOMExceptionConstants[key];
+ var constantName = constant.s;
+ if (!hasOwn(PolyfilledDOMException, constantName)) {
+ defineProperty(PolyfilledDOMException, constantName, createPropertyDescriptor(6, constant.c));
+ }
+ }
+}
+
+
+/***/ }),
+
+/***/ 4603:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var defineBuiltIn = __webpack_require__(6840);
+var uncurryThis = __webpack_require__(9504);
+var toString = __webpack_require__(655);
+var validateArgumentsLength = __webpack_require__(2812);
+
+var $URLSearchParams = URLSearchParams;
+var URLSearchParamsPrototype = $URLSearchParams.prototype;
+var append = uncurryThis(URLSearchParamsPrototype.append);
+var $delete = uncurryThis(URLSearchParamsPrototype['delete']);
+var forEach = uncurryThis(URLSearchParamsPrototype.forEach);
+var push = uncurryThis([].push);
+var params = new $URLSearchParams('a=1&a=2&b=3');
+
+params['delete']('a', 1);
+// `undefined` case is a Chromium 117 bug
+// https://bugs.chromium.org/p/v8/issues/detail?id=14222
+params['delete']('b', undefined);
+
+if (params + '' !== 'a=2') {
+ defineBuiltIn(URLSearchParamsPrototype, 'delete', function (name /* , value */) {
+ var length = arguments.length;
+ var $value = length < 2 ? undefined : arguments[1];
+ if (length && $value === undefined) return $delete(this, name);
+ var entries = [];
+ forEach(this, function (v, k) { // also validates `this`
+ push(entries, { key: k, value: v });
+ });
+ validateArgumentsLength(length, 1);
+ var key = toString(name);
+ var value = toString($value);
+ var index = 0;
+ var dindex = 0;
+ var found = false;
+ var entriesLength = entries.length;
+ var entry;
+ while (index < entriesLength) {
+ entry = entries[index++];
+ if (found || entry.key === key) {
+ found = true;
+ $delete(this, entry.key);
+ } else dindex++;
+ }
+ while (dindex < entriesLength) {
+ entry = entries[dindex++];
+ if (!(entry.key === key && entry.value === value)) append(this, entry.key, entry.value);
+ }
+ }, { enumerable: true, unsafe: true });
+}
+
+
+/***/ }),
+
+/***/ 7566:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var defineBuiltIn = __webpack_require__(6840);
+var uncurryThis = __webpack_require__(9504);
+var toString = __webpack_require__(655);
+var validateArgumentsLength = __webpack_require__(2812);
+
+var $URLSearchParams = URLSearchParams;
+var URLSearchParamsPrototype = $URLSearchParams.prototype;
+var getAll = uncurryThis(URLSearchParamsPrototype.getAll);
+var $has = uncurryThis(URLSearchParamsPrototype.has);
+var params = new $URLSearchParams('a=1');
+
+// `undefined` case is a Chromium 117 bug
+// https://bugs.chromium.org/p/v8/issues/detail?id=14222
+if (params.has('a', 2) || !params.has('a', undefined)) {
+ defineBuiltIn(URLSearchParamsPrototype, 'has', function has(name /* , value */) {
+ var length = arguments.length;
+ var $value = length < 2 ? undefined : arguments[1];
+ if (length && $value === undefined) return $has(this, name);
+ var values = getAll(this, name); // also validates `this`
+ validateArgumentsLength(length, 1);
+ var value = toString($value);
+ var index = 0;
+ while (index < values.length) {
+ if (values[index++] === value) return true;
+ } return false;
+ }, { enumerable: true, unsafe: true });
+}
+
+
+/***/ }),
+
+/***/ 8721:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var DESCRIPTORS = __webpack_require__(3724);
+var uncurryThis = __webpack_require__(9504);
+var defineBuiltInAccessor = __webpack_require__(2106);
+
+var URLSearchParamsPrototype = URLSearchParams.prototype;
+var forEach = uncurryThis(URLSearchParamsPrototype.forEach);
+
+// `URLSearchParams.prototype.size` getter
+// https://github.com/whatwg/url/pull/734
+if (DESCRIPTORS && !('size' in URLSearchParamsPrototype)) {
+ defineBuiltInAccessor(URLSearchParamsPrototype, 'size', {
+ get: function size() {
+ var count = 0;
+ forEach(this, function () { count++; });
+ return count;
+ },
+ configurable: true,
+ enumerable: true
+ });
+}
+
+
+/***/ })
+
+/******/ });
+/************************************************************************/
+/******/ // The module cache
+/******/ var __webpack_module_cache__ = {};
+/******/
+/******/ // The require function
+/******/ function __webpack_require__(moduleId) {
+/******/ // Check if module is in cache
+/******/ var cachedModule = __webpack_module_cache__[moduleId];
+/******/ if (cachedModule !== undefined) {
+/******/ return cachedModule.exports;
+/******/ }
+/******/ // Create a new module (and put it into the cache)
+/******/ var module = __webpack_module_cache__[moduleId] = {
+/******/ // no module.id needed
+/******/ // no module.loaded needed
+/******/ exports: {}
+/******/ };
+/******/
+/******/ // Execute the module function
+/******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/ // Return the exports of the module
+/******/ return module.exports;
+/******/ }
/******/
/************************************************************************/
/******/ /* webpack/runtime/define property getters */
@@ -63,7 +4767,6 @@ __webpack_require__.d(__webpack_exports__, {
InvalidPDFException: () => (/* reexport */ InvalidPDFException),
MissingPDFException: () => (/* reexport */ MissingPDFException),
OPS: () => (/* reexport */ OPS),
- Outliner: () => (/* reexport */ Outliner),
PDFDataRangeTransport: () => (/* reexport */ PDFDataRangeTransport),
PDFDateString: () => (/* reexport */ PDFDateString),
PDFWorker: () => (/* reexport */ PDFWorker),
@@ -87,14 +4790,42 @@ __webpack_require__.d(__webpack_exports__, {
isPdfFile: () => (/* reexport */ isPdfFile),
noContextMenu: () => (/* reexport */ noContextMenu),
normalizeUnicode: () => (/* reexport */ normalizeUnicode),
- renderTextLayer: () => (/* reexport */ renderTextLayer),
setLayerDimensions: () => (/* reexport */ setLayerDimensions),
shadow: () => (/* reexport */ shadow),
- updateTextLayer: () => (/* reexport */ updateTextLayer),
version: () => (/* reexport */ version)
});
+// EXTERNAL MODULE: ./node_modules/core-js/modules/es.array.push.js
+var es_array_push = __webpack_require__(4114);
+// EXTERNAL MODULE: ./node_modules/core-js/modules/es.array-buffer.detached.js
+var es_array_buffer_detached = __webpack_require__(6573);
+// EXTERNAL MODULE: ./node_modules/core-js/modules/es.array-buffer.transfer.js
+var es_array_buffer_transfer = __webpack_require__(8100);
+// EXTERNAL MODULE: ./node_modules/core-js/modules/es.array-buffer.transfer-to-fixed-length.js
+var es_array_buffer_transfer_to_fixed_length = __webpack_require__(7936);
+// EXTERNAL MODULE: ./node_modules/core-js/modules/es.typed-array.to-reversed.js
+var es_typed_array_to_reversed = __webpack_require__(7467);
+// EXTERNAL MODULE: ./node_modules/core-js/modules/es.typed-array.to-sorted.js
+var es_typed_array_to_sorted = __webpack_require__(4732);
+// EXTERNAL MODULE: ./node_modules/core-js/modules/es.typed-array.with.js
+var es_typed_array_with = __webpack_require__(9577);
+// EXTERNAL MODULE: ./node_modules/core-js/modules/web.url-search-params.delete.js
+var web_url_search_params_delete = __webpack_require__(4603);
+// EXTERNAL MODULE: ./node_modules/core-js/modules/web.url-search-params.has.js
+var web_url_search_params_has = __webpack_require__(7566);
+// EXTERNAL MODULE: ./node_modules/core-js/modules/web.url-search-params.size.js
+var web_url_search_params_size = __webpack_require__(8721);
;// CONCATENATED MODULE: ./src/shared/util.js
+
+
+
+
+
+
+
+
+
+
const isNodeJS = typeof process === "object" && process + "" === "[object process]" && !process.versions.nw && !(process.versions.electron && process.type && process.type !== "browser");
const IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0];
const FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0];
@@ -110,6 +4841,7 @@ const RenderingIntentFlag = {
ANNOTATIONS_FORMS: 0x10,
ANNOTATIONS_STORAGE: 0x20,
ANNOTATIONS_DISABLE: 0x40,
+ IS_EDITING: 0x80,
OPLIST: 0x100
};
const AnnotationMode = {
@@ -365,7 +5097,9 @@ const OPS = {
paintImageXObjectRepeat: 88,
paintImageMaskXObjectRepeat: 89,
paintSolidColorImageMask: 90,
- constructPath: 91
+ constructPath: 91,
+ setStrokeTransparent: 92,
+ setFillTransparent: 93
};
const PasswordResponses = {
NEED_PASSWORD: 1,
@@ -830,6 +5564,38 @@ const FontRenderOps = {
TRANSLATE: 8
};
+// EXTERNAL MODULE: ./node_modules/core-js/modules/es.promise.with-resolvers.js
+var es_promise_with_resolvers = __webpack_require__(4628);
+// EXTERNAL MODULE: ./node_modules/core-js/modules/esnext.iterator.map.js
+var esnext_iterator_map = __webpack_require__(1454);
+// EXTERNAL MODULE: ./node_modules/core-js/modules/esnext.set.difference.v2.js
+var esnext_set_difference_v2 = __webpack_require__(3375);
+// EXTERNAL MODULE: ./node_modules/core-js/modules/esnext.set.intersection.v2.js
+var esnext_set_intersection_v2 = __webpack_require__(9225);
+// EXTERNAL MODULE: ./node_modules/core-js/modules/esnext.set.is-disjoint-from.v2.js
+var esnext_set_is_disjoint_from_v2 = __webpack_require__(3972);
+// EXTERNAL MODULE: ./node_modules/core-js/modules/esnext.set.is-subset-of.v2.js
+var esnext_set_is_subset_of_v2 = __webpack_require__(9209);
+// EXTERNAL MODULE: ./node_modules/core-js/modules/esnext.set.is-superset-of.v2.js
+var esnext_set_is_superset_of_v2 = __webpack_require__(5714);
+// EXTERNAL MODULE: ./node_modules/core-js/modules/esnext.set.symmetric-difference.v2.js
+var esnext_set_symmetric_difference_v2 = __webpack_require__(7561);
+// EXTERNAL MODULE: ./node_modules/core-js/modules/esnext.set.union.v2.js
+var esnext_set_union_v2 = __webpack_require__(6197);
+// EXTERNAL MODULE: ./node_modules/core-js/modules/web.dom-exception.stack.js
+var web_dom_exception_stack = __webpack_require__(4979);
+// EXTERNAL MODULE: ./node_modules/core-js/modules/esnext.iterator.constructor.js
+var esnext_iterator_constructor = __webpack_require__(8992);
+// EXTERNAL MODULE: ./node_modules/core-js/modules/esnext.iterator.drop.js
+var esnext_iterator_drop = __webpack_require__(4743);
+// EXTERNAL MODULE: ./node_modules/core-js/modules/esnext.iterator.every.js
+var esnext_iterator_every = __webpack_require__(3215);
+// EXTERNAL MODULE: ./node_modules/core-js/modules/esnext.iterator.some.js
+var esnext_iterator_some = __webpack_require__(7550);
+// EXTERNAL MODULE: ./node_modules/core-js/modules/esnext.json.parse.js
+var esnext_json_parse = __webpack_require__(8335);
+// EXTERNAL MODULE: ./node_modules/core-js/modules/esnext.iterator.filter.js
+var esnext_iterator_filter = __webpack_require__(4520);
;// CONCATENATED MODULE: ./src/display/base_factory.js
class BaseFilterFactory {
@@ -991,6 +5757,19 @@ class BaseSVGFactory {
;// CONCATENATED MODULE: ./src/display/display_utils.js
+
+
+
+
+
+
+
+
+
+
+
+
+
const SVG_NS = "http://www.w3.org/2000/svg";
class PixelsPerInch {
static CSS = 96.0;
@@ -998,6 +5777,7 @@ class PixelsPerInch {
static PDF_TO_CSS_UNITS = this.CSS / this.PDF;
}
class DOMFilterFactory extends BaseFilterFactory {
+ #baseUrl;
#_cache;
#_defs;
#docId;
@@ -1061,6 +5841,20 @@ class DOMFilterFactory extends BaseFilterFactory {
}
return [bufferR.join(","), bufferG.join(","), bufferB.join(",")];
}
+ #createUrl(id) {
+ if (this.#baseUrl === undefined) {
+ this.#baseUrl = "";
+ const url = this.#document.URL;
+ if (url !== this.#document.baseURI) {
+ if (isDataScheme(url)) {
+ warn('#createUrl: ignore "data:"-URL for performance reasons.');
+ } else {
+ this.#baseUrl = url.split("#", 1)[0];
+ }
+ }
+ }
+ return `url(${this.#baseUrl}#${id})`;
+ }
addFilter(maps) {
if (!maps) {
return "none";
@@ -1077,7 +5871,7 @@ class DOMFilterFactory extends BaseFilterFactory {
return value;
}
const id = `g_${this.#docId}_transfer_map_${this.#id++}`;
- const url = `url(#${id})`;
+ const url = this.#createUrl(id);
this.#cache.set(maps, url);
this.#cache.set(key, url);
const filter = this.#createFilter(id);
@@ -1135,7 +5929,7 @@ class DOMFilterFactory extends BaseFilterFactory {
return arr.join(",");
};
this.#addTransferMapConversion(getSteps(0, 5), getSteps(1, 5), getSteps(2, 5), filter);
- info.url = `url(#${id})`;
+ info.url = this.#createUrl(id);
return info.url;
}
addAlphaFilter(map) {
@@ -1151,7 +5945,7 @@ class DOMFilterFactory extends BaseFilterFactory {
return value;
}
const id = `g_${this.#docId}_alpha_map_${this.#id++}`;
- const url = `url(#${id})`;
+ const url = this.#createUrl(id);
this.#cache.set(map, url);
this.#cache.set(key, url);
const filter = this.#createFilter(id);
@@ -1176,7 +5970,7 @@ class DOMFilterFactory extends BaseFilterFactory {
return value;
}
const id = `g_${this.#docId}_luminosity_map_${this.#id++}`;
- const url = `url(#${id})`;
+ const url = this.#createUrl(id);
this.#cache.set(map, url);
this.#cache.set(key, url);
const filter = this.#createFilter(id);
@@ -1239,7 +6033,7 @@ class DOMFilterFactory extends BaseFilterFactory {
const filter = info.filter = this.#createFilter(id);
this.#addGrayConversion(filter);
this.#addTransferMapConversion(getSteps(newFgRGB[0], newBgRGB[0], 5), getSteps(newFgRGB[1], newBgRGB[1], 5), getSteps(newFgRGB[2], newBgRGB[2], 5), filter);
- info.url = `url(#${id})`;
+ info.url = this.#createUrl(id);
return info.url;
}
destroy(keepHCM = false) {
@@ -1890,6 +6684,26 @@ class HighlightToolbar {
;// CONCATENATED MODULE: ./src/display/editor/tools.js
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
function bindEvents(obj, element, names) {
for (const name of names) {
@@ -2234,6 +7048,7 @@ class AnnotationEditorUIManager {
#editorTypes = null;
#editorsToRescale = new Set();
#enableHighlightFloatingButton = false;
+ #enableUpdatedAddImage = false;
#filterFactory = null;
#focusMainContainerTimeoutId = null;
#highlightColors = null;
@@ -2333,7 +7148,7 @@ class AnnotationEditorUIManager {
checker: arrowChecker
}]]));
}
- constructor(container, viewer, altTextManager, eventBus, pdfDocument, pageColors, highlightColors, enableHighlightFloatingButton, mlManager) {
+ constructor(container, viewer, altTextManager, eventBus, pdfDocument, pageColors, highlightColors, enableHighlightFloatingButton, enableUpdatedAddImage, mlManager) {
this._signal = this.#abortController.signal;
this.#container = container;
this.#viewer = viewer;
@@ -2351,6 +7166,7 @@ class AnnotationEditorUIManager {
this.#pageColors = pageColors;
this.#highlightColors = highlightColors || null;
this.#enableHighlightFloatingButton = enableHighlightFloatingButton;
+ this.#enableUpdatedAddImage = enableUpdatedAddImage;
this.#mlManager = mlManager || null;
this.viewParameters = {
realScale: PixelsPerInch.PDF_TO_CSS_UNITS,
@@ -2390,8 +7206,11 @@ class AnnotationEditorUIManager {
async mlGuess(data) {
return this.#mlManager?.guess(data) || null;
}
- get hasMLManager() {
- return !!this.#mlManager;
+ async isMLEnabledFor(name) {
+ return !!(await this.#mlManager?.isEnabledFor(name));
+ }
+ get useNewAltTextFlow() {
+ return this.#enableUpdatedAddImage;
}
get hcmFilter() {
return shadow(this, "hcmFilter", this.#pageColors ? this.#filterFactory.addHCMFilter(this.#pageColors.foreground, this.#pageColors.background) : "none");
@@ -2411,6 +7230,23 @@ class AnnotationEditorUIManager {
editAltText(editor) {
this.#altTextManager?.editAltText(this, editor);
}
+ switchToMode(mode, callback) {
+ this._eventBus.on("annotationeditormodechanged", callback, {
+ once: true,
+ signal: this._signal
+ });
+ this._eventBus.dispatch("showannotationeditorui", {
+ source: this,
+ mode
+ });
+ }
+ setPreference(name, value) {
+ this._eventBus.dispatch("setpreference", {
+ source: this,
+ name,
+ value
+ });
+ }
onPageChanging({
pageNumber
}) {
@@ -2462,6 +7298,20 @@ class AnnotationEditorUIManager {
}) {
return anchorNode.nodeType === Node.TEXT_NODE ? anchorNode.parentElement : anchorNode;
}
+ #getLayerForTextLayer(textLayer) {
+ const {
+ currentLayer
+ } = this;
+ if (currentLayer.hasTextLayer(textLayer)) {
+ return currentLayer;
+ }
+ for (const layer of this.#allLayers.values()) {
+ if (layer.hasTextLayer(textLayer)) {
+ return layer;
+ }
+ }
+ return null;
+ }
highlightSelection(methodOfCreation = "") {
const selection = document.getSelection();
if (!selection || selection.isCollapsed) {
@@ -2481,30 +7331,30 @@ class AnnotationEditorUIManager {
return;
}
selection.empty();
- if (this.#mode === AnnotationEditorType.NONE) {
- this._eventBus.dispatch("showannotationeditorui", {
- source: this,
- mode: AnnotationEditorType.HIGHLIGHT
+ const layer = this.#getLayerForTextLayer(textLayer);
+ const isNoneMode = this.#mode === AnnotationEditorType.NONE;
+ const callback = () => {
+ layer?.createAndAddNewEditor({
+ x: 0,
+ y: 0
+ }, false, {
+ methodOfCreation,
+ boxes,
+ anchorNode,
+ anchorOffset,
+ focusNode,
+ focusOffset,
+ text
});
- this.showAllEditors("highlight", true, true);
- }
- for (const layer of this.#allLayers.values()) {
- if (layer.hasTextLayer(textLayer)) {
- layer.createAndAddNewEditor({
- x: 0,
- y: 0
- }, false, {
- methodOfCreation,
- boxes,
- anchorNode,
- anchorOffset,
- focusNode,
- focusOffset,
- text
- });
- break;
+ if (isNoneMode) {
+ this.showAllEditors("highlight", true, true);
}
+ };
+ if (isNoneMode) {
+ this.switchToMode(AnnotationEditorType.HIGHLIGHT, callback);
+ return;
}
+ callback();
}
#displayHighlightToolbar() {
const selection = document.getSelection();
@@ -2568,11 +7418,14 @@ class AnnotationEditorUIManager {
}
this.#highlightWhenShiftUp = this.isShiftKeyDown;
if (!this.isShiftKeyDown) {
+ const activeLayer = this.#mode === AnnotationEditorType.HIGHLIGHT ? this.#getLayerForTextLayer(textLayer) : null;
+ activeLayer?.toggleDrawing();
const signal = this._signal;
const pointerup = e => {
if (e.type === "pointerup" && e.button !== 0) {
return;
}
+ activeLayer?.toggleDrawing(true);
window.removeEventListener("pointerup", pointerup);
window.removeEventListener("blur", pointerup);
if (e.type === "pointerup") {
@@ -4824,6 +9677,12 @@ class FakeEditor extends AnnotationEditor {
}
;// CONCATENATED MODULE: ./src/shared/murmurhash3.js
+
+
+
+
+
+
const SEED = 0xc3d2e1f0;
const MASK_HIGH = 0xffff0000;
const MASK_LOW = 0xffff;
@@ -4920,6 +9779,16 @@ class MurmurHash3_64 {
+
+
+
+
+
+
+
+
+
+
const SerializableEmpty = Object.freeze({
map: null,
hash: "",
@@ -4927,6 +9796,7 @@ const SerializableEmpty = Object.freeze({
});
class AnnotationStorage {
#modified = false;
+ #modifiedIds = null;
#storage = new Map();
constructor() {
this.onSetModified = null;
@@ -5078,6 +9948,25 @@ class AnnotationStorage {
}
return stats;
}
+ resetModifiedIds() {
+ this.#modifiedIds = null;
+ }
+ get modifiedIds() {
+ if (this.#modifiedIds) {
+ return this.#modifiedIds;
+ }
+ const ids = [];
+ for (const value of this.#storage.values()) {
+ if (!(value instanceof AnnotationEditor) || !value.annotationElementId || !value.serialize()) {
+ continue;
+ }
+ ids.push(value.annotationElementId);
+ }
+ return this.#modifiedIds = {
+ ids: new Set(ids),
+ hash: ids.join(",")
+ };
+ }
}
class PrintAnnotationStorage extends AnnotationStorage {
#serializable;
@@ -5103,10 +9992,25 @@ class PrintAnnotationStorage extends AnnotationStorage {
get serializable() {
return this.#serializable;
}
+ get modifiedIds() {
+ return shadow(this, "modifiedIds", {
+ ids: new Set(),
+ hash: ""
+ });
+ }
}
;// CONCATENATED MODULE: ./src/display/font_loader.js
+
+
+
+
+
+
+
+
+
class FontLoader {
#systemFonts = new Set();
constructor({
@@ -5444,6 +10348,13 @@ class FontFaceObject {
;// CONCATENATED MODULE: ./src/display/node_utils.js
+
+
+
+
+
+
+
if (isNodeJS) {
var packageCapability = Promise.withResolvers();
var packageMap = null;
@@ -5453,6 +10364,12 @@ if (isNodeJS) {
https = await import( /*webpackIgnore: true*/"https"),
url = await import( /*webpackIgnore: true*/"url");
let canvas, path2d;
+ try {
+ canvas = await import( /*webpackIgnore: true*/"canvas");
+ } catch {}
+ try {
+ path2d = await import( /*webpackIgnore: true*/"path2d");
+ } catch {}
return new Map(Object.entries({
fs,
http,
@@ -5465,6 +10382,25 @@ if (isNodeJS) {
loadPackages().then(map => {
packageMap = map;
packageCapability.resolve();
+ if (!globalThis.DOMMatrix) {
+ const DOMMatrix = map.get("canvas")?.DOMMatrix;
+ if (DOMMatrix) {
+ globalThis.DOMMatrix = DOMMatrix;
+ } else {
+ warn("Cannot polyfill `DOMMatrix`, rendering may be broken.");
+ }
+ }
+ if (!globalThis.Path2D) {
+ const CanvasRenderingContext2D = map.get("canvas")?.CanvasRenderingContext2D;
+ const applyPath2DToCanvasRenderingContext = map.get("path2d")?.applyPath2DToCanvasRenderingContext;
+ const Path2D = map.get("path2d")?.Path2D;
+ if (CanvasRenderingContext2D && applyPath2DToCanvasRenderingContext && Path2D) {
+ applyPath2DToCanvasRenderingContext(CanvasRenderingContext2D);
+ globalThis.Path2D = Path2D;
+ } else {
+ warn("Cannot polyfill `Path2D`, rendering may be broken.");
+ }
+ }
}, reason => {
warn(`loadPackages: ${reason}`);
packageMap = new Map();
@@ -5946,6 +10882,12 @@ class TilingPattern {
;// CONCATENATED MODULE: ./src/shared/image_utils.js
+
+
+
+
+
+
function convertToRGBA(params) {
switch (params.kind) {
case ImageKind.GRAYSCALE_1BPP:
@@ -6056,6 +10998,17 @@ function grayToRGBA(src, dest) {
+
+
+
+
+
+
+
+
+
+
+
const MIN_FONT_SIZE = 16;
const MAX_FONT_SIZE = 100;
const EXECUTION_TIME = 15;
@@ -6749,6 +11702,7 @@ class CanvasGraphics {
while (this.stateStack.length || this.inSMaskMode) {
this.restore();
}
+ this.current.activeSMask = null;
this.ctx.restore();
if (this.transparentCanvas) {
this.ctx = this.compositeCtx;
@@ -7655,14 +12609,17 @@ class CanvasGraphics {
this.current.patternFill = true;
}
setStrokeRGBColor(r, g, b) {
- const color = Util.makeHexColor(r, g, b);
- this.ctx.strokeStyle = color;
- this.current.strokeColor = color;
+ this.ctx.strokeStyle = this.current.strokeColor = Util.makeHexColor(r, g, b);
+ }
+ setStrokeTransparent() {
+ this.ctx.strokeStyle = this.current.strokeColor = "transparent";
}
setFillRGBColor(r, g, b) {
- const color = Util.makeHexColor(r, g, b);
- this.ctx.fillStyle = color;
- this.current.fillColor = color;
+ this.ctx.fillStyle = this.current.fillColor = Util.makeHexColor(r, g, b);
+ this.current.patternFill = false;
+ }
+ setFillTransparent() {
+ this.ctx.fillStyle = this.current.fillColor = "transparent";
this.current.patternFill = false;
}
_getPattern(objId, matrix = null) {
@@ -8252,6 +13209,7 @@ class GlobalWorkerOptions {
;// CONCATENATED MODULE: ./src/shared/message_handler.js
+
const CallbackKind = {
UNKNOWN: 0,
DATA: 1,
@@ -8934,6 +13892,16 @@ class OptionalContentConfig {
;// CONCATENATED MODULE: ./src/display/transport_stream.js
+
+
+
+
+
+
+
+
+
+
class PDFDataTransportStream {
constructor(pdfDataRangeTransport, {
disableRange = false,
@@ -9201,6 +14169,8 @@ class PDFDataTransportStreamRangeReader {
;// CONCATENATED MODULE: ./src/display/content_disposition.js
+
+
function getFilenameFromContentDispositionHeader(contentDisposition) {
let needsEncodingFixup = true;
let tmp = toParamRegExp("filename\\*", "i").exec(contentDisposition);
@@ -9393,6 +14363,14 @@ function validateResponseStatus(status) {
;// CONCATENATED MODULE: ./src/display/fetch_stream.js
+
+
+
+
+
+
+
+
function createFetchOptions(headers, withCredentials, abortController) {
return {
method: "GET",
@@ -9597,6 +14575,8 @@ class PDFFetchStreamRangeReader {
;// CONCATENATED MODULE: ./src/display/network.js
+
+
const OK_RESPONSE = 200;
const PARTIAL_CONTENT_RESPONSE = 206;
function network_getArrayBuffer(xhr) {
@@ -10004,6 +14984,14 @@ class PDFNetworkStreamRangeRequestReader {
+
+
+
+
+
+
+
+
const fileUriRegex = /^file:\/\/\/[a-zA-Z]:\//;
function parseUrl(sourceUrl) {
const url = NodePackages.get("url");
@@ -10342,6 +15330,15 @@ class PDFNodeStreamFsRangeReader extends BaseRangeReader {
;// CONCATENATED MODULE: ./src/display/text_layer.js
+
+
+
+
+
+
+
+
+
const MAX_TEXT_DIVS_TO_RENDER = 100000;
const DEFAULT_FONT_SIZE = 30;
const DEFAULT_FONT_ASCENT = 0.8;
@@ -10657,6 +15654,7 @@ class TextLayer {
div.style.opacity = 0;
div.style.lineHeight = 1;
div.style.fontSize = "1px";
+ div.style.position = "absolute";
div.textContent = "X";
document.body.append(div);
this.#minFontSize = div.getBoundingClientRect().height;
@@ -10709,39 +15707,9 @@ class TextLayer {
return ratio;
}
}
-function renderTextLayer() {
- deprecated("`renderTextLayer`, please use `TextLayer` instead.");
- const {
- textContentSource,
- container,
- viewport,
- ...rest
- } = arguments[0];
- const restKeys = Object.keys(rest);
- if (restKeys.length > 0) {
- warn("Ignoring `renderTextLayer` parameters: " + restKeys.join(", "));
- }
- const textLayer = new TextLayer({
- textContentSource,
- container,
- viewport
- });
- const {
- textDivs,
- textContentItemsStr
- } = textLayer;
- const promise = textLayer.render();
- return {
- promise,
- textDivs,
- textContentItemsStr
- };
-}
-function updateTextLayer() {
- deprecated("`updateTextLayer`, please use `TextLayer` instead.");
-}
;// CONCATENATED MODULE: ./src/display/xfa_text.js
+
class XfaText {
static textContent(xfa) {
const items = [];
@@ -10800,6 +15768,26 @@ class XfaText {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
const DEFAULT_RANGE_CHUNK_SIZE = 65536;
const RENDERING_CANCELLED_TIMEOUT = 100;
@@ -10887,7 +15875,7 @@ function getDocument(src = {}) {
}
const docParams = {
docId,
- apiVersion: "4.4.168",
+ apiVersion: "4.5.136",
data,
password,
disableAutoFetch,
@@ -11280,10 +16268,11 @@ class PDFPageProxy {
optionalContentConfigPromise = null,
annotationCanvasMap = null,
pageColors = null,
- printAnnotationStorage = null
+ printAnnotationStorage = null,
+ isEditing = false
}) {
this._stats?.time("Overall");
- const intentArgs = this._transport.getRenderingIntent(intent, annotationMode, printAnnotationStorage);
+ const intentArgs = this._transport.getRenderingIntent(intent, annotationMode, printAnnotationStorage, isEditing);
const {
renderingIntent,
cacheKey
@@ -11376,7 +16365,8 @@ class PDFPageProxy {
getOperatorList({
intent = "display",
annotationMode = AnnotationMode.ENABLE,
- printAnnotationStorage = null
+ printAnnotationStorage = null,
+ isEditing = false
} = {}) {
function operatorListChanged() {
if (intentState.operatorList.lastChunk) {
@@ -11384,7 +16374,7 @@ class PDFPageProxy {
intentState.renderTasks.delete(opListTask);
}
}
- const intentArgs = this._transport.getRenderingIntent(intent, annotationMode, printAnnotationStorage, true);
+ const intentArgs = this._transport.getRenderingIntent(intent, annotationMode, printAnnotationStorage, isEditing, true);
let intentState = this._intentStates.get(intentArgs.cacheKey);
if (!intentState) {
intentState = Object.create(null);
@@ -11542,7 +16532,8 @@ class PDFPageProxy {
_pumpOperatorList({
renderingIntent,
cacheKey,
- annotationStorageSerializable
+ annotationStorageSerializable,
+ modifiedIds
}) {
const {
map,
@@ -11552,7 +16543,8 @@ class PDFPageProxy {
pageIndex: this._pageIndex,
intent: renderingIntent,
cacheKey,
- annotationStorage: map
+ annotationStorage: map,
+ modifiedIds
}, transfer);
const reader = readableStream.getReader();
const intentState = this._intentStates.get(cacheKey);
@@ -11675,7 +16667,7 @@ const PDFWorkerUtil = {
{
if (isNodeJS) {
PDFWorkerUtil.isWorkerDisabled = true;
- GlobalWorkerOptions.workerSrc ||= "./pdf.worker.mjs";
+ GlobalWorkerOptions.workerSrc ||= "./pdf.worker.js";
}
PDFWorkerUtil.isSameOrigin = function (baseUrl, otherUrl) {
let base;
@@ -11924,7 +16916,7 @@ class WorkerTransport {
get annotationStorage() {
return shadow(this, "annotationStorage", new AnnotationStorage());
}
- getRenderingIntent(intent, annotationMode = AnnotationMode.ENABLE, printAnnotationStorage = null, isOpList = false) {
+ getRenderingIntent(intent, annotationMode = AnnotationMode.ENABLE, printAnnotationStorage = null, isEditing = false, isOpList = false) {
let renderingIntent = RenderingIntentFlag.DISPLAY;
let annotationStorageSerializable = SerializableEmpty;
switch (intent) {
@@ -11939,6 +16931,7 @@ class WorkerTransport {
default:
warn(`getRenderingIntent - invalid intent: ${intent}`);
}
+ const annotationStorage = renderingIntent & RenderingIntentFlag.PRINT && printAnnotationStorage instanceof PrintAnnotationStorage ? printAnnotationStorage : this.annotationStorage;
switch (annotationMode) {
case AnnotationMode.DISABLE:
renderingIntent += RenderingIntentFlag.ANNOTATIONS_DISABLE;
@@ -11950,19 +16943,27 @@ class WorkerTransport {
break;
case AnnotationMode.ENABLE_STORAGE:
renderingIntent += RenderingIntentFlag.ANNOTATIONS_STORAGE;
- const annotationStorage = renderingIntent & RenderingIntentFlag.PRINT && printAnnotationStorage instanceof PrintAnnotationStorage ? printAnnotationStorage : this.annotationStorage;
annotationStorageSerializable = annotationStorage.serializable;
break;
default:
warn(`getRenderingIntent - invalid annotationMode: ${annotationMode}`);
}
+ if (isEditing) {
+ renderingIntent += RenderingIntentFlag.IS_EDITING;
+ }
if (isOpList) {
renderingIntent += RenderingIntentFlag.OPLIST;
}
+ const {
+ ids: modifiedIds,
+ hash: modifiedIdsHash
+ } = annotationStorage.modifiedIds;
+ const cacheKeyBuf = [renderingIntent, annotationStorageSerializable.hash, modifiedIdsHash];
return {
renderingIntent,
- cacheKey: `${renderingIntent}_${annotationStorageSerializable.hash}`,
- annotationStorageSerializable
+ cacheKey: cacheKeyBuf.join("_"),
+ annotationStorageSerializable,
+ modifiedIds
};
}
destroy() {
@@ -12657,10 +17658,13 @@ class InternalRenderTask {
}
}
}
-const version = "4.4.168";
-const build = "19fbc8998";
+const version = "4.5.136";
+const build = "3a21f03b0";
+// EXTERNAL MODULE: ./node_modules/core-js/modules/esnext.iterator.flat-map.js
+var esnext_iterator_flat_map = __webpack_require__(670);
;// CONCATENATED MODULE: ./src/shared/scripting_utils.js
+
function makeColorComp(n) {
return Math.floor(Math.max(0, Math.min(1, n)) * 255).toString(16).padStart(2, "0");
}
@@ -12721,6 +17725,7 @@ class ColorConverters {
;// CONCATENATED MODULE: ./src/display/xfa_layer.js
+
class XfaLayer {
static setupStorage(html, id, element, storage, intent) {
const storedData = storage.getValue(id, {
@@ -12936,6 +17941,17 @@ class XfaLayer {
+
+
+
+
+
+
+
+
+
+
+
const DEFAULT_TAB_INDEX = 1000;
const annotation_layer_DEFAULT_FONT_SIZE = 9;
const GetElementsByNameSet = new WeakSet();
@@ -13042,6 +18058,9 @@ class AnnotationElement {
}) {
return !!(titleObj?.str || contentsObj?.str || richText?.str);
}
+ get _isEditable() {
+ return this.data.isEditable;
+ }
get hasPopupData() {
return AnnotationElement._hasPopupData(this.data);
}
@@ -13502,9 +18521,6 @@ class AnnotationElement {
triggers.classList.add("highlightArea");
}
}
- get _isEditable() {
- return false;
- }
_editOnDoubleClick() {
if (!this._isEditable) {
return;
@@ -14962,9 +19978,6 @@ class FreeTextAnnotationElement extends AnnotationElement {
this._editOnDoubleClick();
return this.container;
}
- get _isEditable() {
- return this.data.hasOwnCanvas;
- }
}
class LineAnnotationElement extends AnnotationElement {
#line = null;
@@ -15372,6 +20385,9 @@ class AnnotationLayer {
this.zIndex = 0;
this._annotationEditorUIManager = annotationEditorUIManager;
}
+ hasEditableAnnotations() {
+ return this.#editableAnnotations.size > 0;
+ }
#appendElement(element, id) {
const contentElement = element.firstChild || element;
contentElement.id = `${AnnotationPrefix}${id}`;
@@ -15438,7 +20454,7 @@ class AnnotationLayer {
rendered.style.visibility = "hidden";
}
this.#appendElement(rendered, data.id);
- if (element.annotationEditorType > 0) {
+ if (element._isEditable) {
this.#editableAnnotations.set(element.data.id, element);
this._annotationEditorUIManager?.renderAnnotationElement(element);
}
@@ -15495,6 +20511,9 @@ class AnnotationLayer {
+
+
+
const EOL_PATTERN = /\r\n?|\n/g;
class FreeTextEditor extends AnnotationEditor {
#boundEditorDivBlur = this.editorDivBlur.bind(this);
@@ -16113,6 +21132,20 @@ class FreeTextEditor extends AnnotationEditor {
;// CONCATENATED MODULE: ./src/display/editor/outliner.js
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Outliner {
#box;
#verticalEdges = [];
@@ -16936,6 +21969,13 @@ class ColorPicker {
+
+
+
+
+
+
+
class HighlightEditor extends AnnotationEditor {
#anchorNode = null;
#anchorOffset = 0;
@@ -17426,6 +22466,7 @@ class HighlightEditor extends AnnotationEditor {
return null;
}
const [pageWidth, pageHeight] = this.pageDimensions;
+ const [pageX, pageY] = this.pageTranslation;
const boxes = this.#boxes;
const quadPoints = new Float32Array(boxes.length * 8);
let i = 0;
@@ -17435,8 +22476,8 @@ class HighlightEditor extends AnnotationEditor {
width,
height
} of boxes) {
- const sx = x * pageWidth;
- const sy = (1 - y - height) * pageHeight;
+ const sx = x * pageWidth + pageX;
+ const sy = (1 - y - height) * pageHeight + pageY;
quadPoints[i] = quadPoints[i + 4] = sx;
quadPoints[i + 1] = quadPoints[i + 3] = sy;
quadPoints[i + 2] = quadPoints[i + 6] = sx + width * pageWidth;
@@ -17576,6 +22617,8 @@ class HighlightEditor extends AnnotationEditor {
+
+
class InkEditor extends AnnotationEditor {
#baseHeight = 0;
#baseWidth = 0;
@@ -18390,6 +23433,9 @@ class InkEditor extends AnnotationEditor {
+
+
+
class StampEditor extends AnnotationEditor {
#bitmap = null;
#bitmapId = null;
@@ -18398,6 +23444,7 @@ class StampEditor extends AnnotationEditor {
#bitmapFile = null;
#bitmapFileName = "";
#canvas = null;
+ #hasMLBeenQueried = false;
#observer = null;
#resizeTimeoutId = null;
#isSvg = false;
@@ -18645,6 +23692,37 @@ class StampEditor extends AnnotationEditor {
}
return bitmap;
}
+ async #mlGuessAltText(bitmap, width, height) {
+ if (this.#hasMLBeenQueried) {
+ return;
+ }
+ this.#hasMLBeenQueried = true;
+ const isMLEnabled = await this._uiManager.isMLEnabledFor("altText");
+ if (!isMLEnabled || this.hasAltText()) {
+ return;
+ }
+ const offscreen = new OffscreenCanvas(width, height);
+ const ctx = offscreen.getContext("2d", {
+ willReadFrequently: true
+ });
+ ctx.drawImage(bitmap, 0, 0, bitmap.width, bitmap.height, 0, 0, width, height);
+ const response = await this._uiManager.mlGuess({
+ service: "moz-image-to-text",
+ request: {
+ data: ctx.getImageData(0, 0, width, height).data,
+ width,
+ height,
+ channels: 4
+ }
+ });
+ const altText = response?.output || "";
+ if (this.parent && altText && !this.hasAltText()) {
+ this.altTextData = {
+ altText,
+ decorative: false
+ };
+ }
+ }
#drawBitmap(width, height) {
width = Math.ceil(width);
height = Math.ceil(height);
@@ -18655,28 +23733,7 @@ class StampEditor extends AnnotationEditor {
canvas.width = width;
canvas.height = height;
const bitmap = this.#isSvg ? this.#bitmap : this.#scaleBitmap(width, height);
- if (this._uiManager.hasMLManager && !this.hasAltText()) {
- const offscreen = new OffscreenCanvas(width, height);
- const ctx = offscreen.getContext("2d");
- ctx.drawImage(bitmap, 0, 0, bitmap.width, bitmap.height, 0, 0, width, height);
- this._uiManager.mlGuess({
- service: "image-to-text",
- request: {
- data: ctx.getImageData(0, 0, width, height).data,
- width,
- height,
- channels: 4
- }
- }).then(response => {
- const altText = response?.output || "";
- if (this.parent && altText && !this.hasAltText()) {
- this.altTextData = {
- altText,
- decorative: false
- };
- }
- });
- }
+ this.#mlGuessAltText(bitmap, width, height);
const ctx = canvas.getContext("2d");
ctx.filter = this._uiManager.hcmFilter;
ctx.drawImage(bitmap, 0, 0, bitmap.width, bitmap.height, 0, 0, width, height);
@@ -18815,6 +23872,14 @@ class StampEditor extends AnnotationEditor {
+
+
+
+
+
+
+
+
class AnnotationEditorLayer {
#accessibilityManager;
#allowClick = false;
@@ -18930,6 +23995,9 @@ class AnnotationEditorLayer {
addCommands(params) {
this.#uiManager.addCommands(params);
}
+ toggleDrawing(enabled = false) {
+ this.div.classList.toggle("drawing", !enabled);
+ }
togglePointerEvents(enabled = false) {
this.div.classList.toggle("disabled", !enabled);
}
@@ -19057,7 +24125,10 @@ class AnnotationEditorLayer {
}
#textLayerPointerDown(event) {
this.#uiManager.unselectAll();
- if (event.target === this.#textLayer.div) {
+ const {
+ target
+ } = event;
+ if (target === this.#textLayer.div || target.classList.contains("endOfContent") && this.#textLayer.div.contains(target)) {
const {
isMac
} = util_FeatureTest.platform;
@@ -19066,9 +24137,11 @@ class AnnotationEditorLayer {
}
this.#uiManager.showAllEditors("highlight", true, true);
this.#textLayer.div.classList.add("free");
+ this.toggleDrawing();
HighlightEditor.startHighlighting(this, this.#uiManager.direction === "ltr", event);
this.#textLayer.div.addEventListener("pointerup", () => {
this.#textLayer.div.classList.remove("free");
+ this.toggleDrawing(true);
}, {
once: true,
signal: this.#uiManager._signal
@@ -19624,8 +24697,8 @@ class DrawLayer {
-const pdfjsVersion = "4.4.168";
-const pdfjsBuild = "19fbc8998";
+const pdfjsVersion = "4.5.136";
+const pdfjsBuild = "3a21f03b0";
var __webpack_exports__AbortException = __webpack_exports__.AbortException;
var __webpack_exports__AnnotationEditorLayer = __webpack_exports__.AnnotationEditorLayer;
@@ -19644,7 +24717,6 @@ var __webpack_exports__ImageKind = __webpack_exports__.ImageKind;
var __webpack_exports__InvalidPDFException = __webpack_exports__.InvalidPDFException;
var __webpack_exports__MissingPDFException = __webpack_exports__.MissingPDFException;
var __webpack_exports__OPS = __webpack_exports__.OPS;
-var __webpack_exports__Outliner = __webpack_exports__.Outliner;
var __webpack_exports__PDFDataRangeTransport = __webpack_exports__.PDFDataRangeTransport;
var __webpack_exports__PDFDateString = __webpack_exports__.PDFDateString;
var __webpack_exports__PDFWorker = __webpack_exports__.PDFWorker;
@@ -19668,11 +24740,9 @@ var __webpack_exports__isDataScheme = __webpack_exports__.isDataScheme;
var __webpack_exports__isPdfFile = __webpack_exports__.isPdfFile;
var __webpack_exports__noContextMenu = __webpack_exports__.noContextMenu;
var __webpack_exports__normalizeUnicode = __webpack_exports__.normalizeUnicode;
-var __webpack_exports__renderTextLayer = __webpack_exports__.renderTextLayer;
var __webpack_exports__setLayerDimensions = __webpack_exports__.setLayerDimensions;
var __webpack_exports__shadow = __webpack_exports__.shadow;
-var __webpack_exports__updateTextLayer = __webpack_exports__.updateTextLayer;
var __webpack_exports__version = __webpack_exports__.version;
-export { __webpack_exports__AbortException as AbortException, __webpack_exports__AnnotationEditorLayer as AnnotationEditorLayer, __webpack_exports__AnnotationEditorParamsType as AnnotationEditorParamsType, __webpack_exports__AnnotationEditorType as AnnotationEditorType, __webpack_exports__AnnotationEditorUIManager as AnnotationEditorUIManager, __webpack_exports__AnnotationLayer as AnnotationLayer, __webpack_exports__AnnotationMode as AnnotationMode, __webpack_exports__CMapCompressionType as CMapCompressionType, __webpack_exports__ColorPicker as ColorPicker, __webpack_exports__DOMSVGFactory as DOMSVGFactory, __webpack_exports__DrawLayer as DrawLayer, __webpack_exports__FeatureTest as FeatureTest, __webpack_exports__GlobalWorkerOptions as GlobalWorkerOptions, __webpack_exports__ImageKind as ImageKind, __webpack_exports__InvalidPDFException as InvalidPDFException, __webpack_exports__MissingPDFException as MissingPDFException, __webpack_exports__OPS as OPS, __webpack_exports__Outliner as Outliner, __webpack_exports__PDFDataRangeTransport as PDFDataRangeTransport, __webpack_exports__PDFDateString as PDFDateString, __webpack_exports__PDFWorker as PDFWorker, __webpack_exports__PasswordResponses as PasswordResponses, __webpack_exports__PermissionFlag as PermissionFlag, __webpack_exports__PixelsPerInch as PixelsPerInch, __webpack_exports__RenderingCancelledException as RenderingCancelledException, __webpack_exports__TextLayer as TextLayer, __webpack_exports__UnexpectedResponseException as UnexpectedResponseException, __webpack_exports__Util as Util, __webpack_exports__VerbosityLevel as VerbosityLevel, __webpack_exports__XfaLayer as XfaLayer, __webpack_exports__build as build, __webpack_exports__createValidAbsoluteUrl as createValidAbsoluteUrl, __webpack_exports__fetchData as fetchData, __webpack_exports__getDocument as getDocument, __webpack_exports__getFilenameFromUrl as getFilenameFromUrl, __webpack_exports__getPdfFilenameFromUrl as getPdfFilenameFromUrl, __webpack_exports__getXfaPageViewport as getXfaPageViewport, __webpack_exports__isDataScheme as isDataScheme, __webpack_exports__isPdfFile as isPdfFile, __webpack_exports__noContextMenu as noContextMenu, __webpack_exports__normalizeUnicode as normalizeUnicode, __webpack_exports__renderTextLayer as renderTextLayer, __webpack_exports__setLayerDimensions as setLayerDimensions, __webpack_exports__shadow as shadow, __webpack_exports__updateTextLayer as updateTextLayer, __webpack_exports__version as version };
+export { __webpack_exports__AbortException as AbortException, __webpack_exports__AnnotationEditorLayer as AnnotationEditorLayer, __webpack_exports__AnnotationEditorParamsType as AnnotationEditorParamsType, __webpack_exports__AnnotationEditorType as AnnotationEditorType, __webpack_exports__AnnotationEditorUIManager as AnnotationEditorUIManager, __webpack_exports__AnnotationLayer as AnnotationLayer, __webpack_exports__AnnotationMode as AnnotationMode, __webpack_exports__CMapCompressionType as CMapCompressionType, __webpack_exports__ColorPicker as ColorPicker, __webpack_exports__DOMSVGFactory as DOMSVGFactory, __webpack_exports__DrawLayer as DrawLayer, __webpack_exports__FeatureTest as FeatureTest, __webpack_exports__GlobalWorkerOptions as GlobalWorkerOptions, __webpack_exports__ImageKind as ImageKind, __webpack_exports__InvalidPDFException as InvalidPDFException, __webpack_exports__MissingPDFException as MissingPDFException, __webpack_exports__OPS as OPS, __webpack_exports__PDFDataRangeTransport as PDFDataRangeTransport, __webpack_exports__PDFDateString as PDFDateString, __webpack_exports__PDFWorker as PDFWorker, __webpack_exports__PasswordResponses as PasswordResponses, __webpack_exports__PermissionFlag as PermissionFlag, __webpack_exports__PixelsPerInch as PixelsPerInch, __webpack_exports__RenderingCancelledException as RenderingCancelledException, __webpack_exports__TextLayer as TextLayer, __webpack_exports__UnexpectedResponseException as UnexpectedResponseException, __webpack_exports__Util as Util, __webpack_exports__VerbosityLevel as VerbosityLevel, __webpack_exports__XfaLayer as XfaLayer, __webpack_exports__build as build, __webpack_exports__createValidAbsoluteUrl as createValidAbsoluteUrl, __webpack_exports__fetchData as fetchData, __webpack_exports__getDocument as getDocument, __webpack_exports__getFilenameFromUrl as getFilenameFromUrl, __webpack_exports__getPdfFilenameFromUrl as getPdfFilenameFromUrl, __webpack_exports__getXfaPageViewport as getXfaPageViewport, __webpack_exports__isDataScheme as isDataScheme, __webpack_exports__isPdfFile as isPdfFile, __webpack_exports__noContextMenu as noContextMenu, __webpack_exports__normalizeUnicode as normalizeUnicode, __webpack_exports__setLayerDimensions as setLayerDimensions, __webpack_exports__shadow as shadow, __webpack_exports__version as version };
-//# sourceMappingURL=pdf.mjs.map
\ No newline at end of file
+//# sourceMappingURL=pdf.mjs.map
diff --git a/cps/static/js/libs/pdf.worker.mjs b/cps/static/js/libs/pdf.worker.js
similarity index 94%
rename from cps/static/js/libs/pdf.worker.mjs
rename to cps/static/js/libs/pdf.worker.js
index 94f1d20a..7bac155f 100644
--- a/cps/static/js/libs/pdf.worker.mjs
+++ b/cps/static/js/libs/pdf.worker.js
@@ -2,7 +2,7 @@
* @licstart The following is the entire license notice for the
* JavaScript code in this page
*
- * Copyright 2023 Mozilla Foundation
+ * Copyright 2024 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,8 +20,4499 @@
* JavaScript code in this page
*/
-/******/ // The require scope
-/******/ var __webpack_require__ = {};
+/******/ var __webpack_modules__ = ({
+
+/***/ 9306:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var isCallable = __webpack_require__(4901);
+var tryToString = __webpack_require__(6823);
+
+var $TypeError = TypeError;
+
+// `Assert: IsCallable(argument) is true`
+module.exports = function (argument) {
+ if (isCallable(argument)) return argument;
+ throw new $TypeError(tryToString(argument) + ' is not a function');
+};
+
+
+/***/ }),
+
+/***/ 3506:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var isPossiblePrototype = __webpack_require__(3925);
+
+var $String = String;
+var $TypeError = TypeError;
+
+module.exports = function (argument) {
+ if (isPossiblePrototype(argument)) return argument;
+ throw new $TypeError("Can't set " + $String(argument) + ' as a prototype');
+};
+
+
+/***/ }),
+
+/***/ 7080:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var has = (__webpack_require__(4402).has);
+
+// Perform ? RequireInternalSlot(M, [[SetData]])
+module.exports = function (it) {
+ has(it);
+ return it;
+};
+
+
+/***/ }),
+
+/***/ 679:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var isPrototypeOf = __webpack_require__(1625);
+
+var $TypeError = TypeError;
+
+module.exports = function (it, Prototype) {
+ if (isPrototypeOf(Prototype, it)) return it;
+ throw new $TypeError('Incorrect invocation');
+};
+
+
+/***/ }),
+
+/***/ 8551:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var isObject = __webpack_require__(34);
+
+var $String = String;
+var $TypeError = TypeError;
+
+// `Assert: Type(argument) is Object`
+module.exports = function (argument) {
+ if (isObject(argument)) return argument;
+ throw new $TypeError($String(argument) + ' is not an object');
+};
+
+
+/***/ }),
+
+/***/ 7811:
+/***/ ((module) => {
+
+
+// eslint-disable-next-line es/no-typed-arrays -- safe
+module.exports = typeof ArrayBuffer != 'undefined' && typeof DataView != 'undefined';
+
+
+/***/ }),
+
+/***/ 7394:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var uncurryThisAccessor = __webpack_require__(6706);
+var classof = __webpack_require__(4576);
+
+var $TypeError = TypeError;
+
+// Includes
+// - Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
+// - If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
+module.exports = uncurryThisAccessor(ArrayBuffer.prototype, 'byteLength', 'get') || function (O) {
+ if (classof(O) !== 'ArrayBuffer') throw new $TypeError('ArrayBuffer expected');
+ return O.byteLength;
+};
+
+
+/***/ }),
+
+/***/ 3238:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var uncurryThis = __webpack_require__(9504);
+var arrayBufferByteLength = __webpack_require__(7394);
+
+var slice = uncurryThis(ArrayBuffer.prototype.slice);
+
+module.exports = function (O) {
+ if (arrayBufferByteLength(O) !== 0) return false;
+ try {
+ slice(O, 0, 0);
+ return false;
+ } catch (error) {
+ return true;
+ }
+};
+
+
+/***/ }),
+
+/***/ 5636:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var global = __webpack_require__(4475);
+var uncurryThis = __webpack_require__(9504);
+var uncurryThisAccessor = __webpack_require__(6706);
+var toIndex = __webpack_require__(7696);
+var isDetached = __webpack_require__(3238);
+var arrayBufferByteLength = __webpack_require__(7394);
+var detachTransferable = __webpack_require__(4483);
+var PROPER_STRUCTURED_CLONE_TRANSFER = __webpack_require__(1548);
+
+var structuredClone = global.structuredClone;
+var ArrayBuffer = global.ArrayBuffer;
+var DataView = global.DataView;
+var TypeError = global.TypeError;
+var min = Math.min;
+var ArrayBufferPrototype = ArrayBuffer.prototype;
+var DataViewPrototype = DataView.prototype;
+var slice = uncurryThis(ArrayBufferPrototype.slice);
+var isResizable = uncurryThisAccessor(ArrayBufferPrototype, 'resizable', 'get');
+var maxByteLength = uncurryThisAccessor(ArrayBufferPrototype, 'maxByteLength', 'get');
+var getInt8 = uncurryThis(DataViewPrototype.getInt8);
+var setInt8 = uncurryThis(DataViewPrototype.setInt8);
+
+module.exports = (PROPER_STRUCTURED_CLONE_TRANSFER || detachTransferable) && function (arrayBuffer, newLength, preserveResizability) {
+ var byteLength = arrayBufferByteLength(arrayBuffer);
+ var newByteLength = newLength === undefined ? byteLength : toIndex(newLength);
+ var fixedLength = !isResizable || !isResizable(arrayBuffer);
+ var newBuffer;
+ if (isDetached(arrayBuffer)) throw new TypeError('ArrayBuffer is detached');
+ if (PROPER_STRUCTURED_CLONE_TRANSFER) {
+ arrayBuffer = structuredClone(arrayBuffer, { transfer: [arrayBuffer] });
+ if (byteLength === newByteLength && (preserveResizability || fixedLength)) return arrayBuffer;
+ }
+ if (byteLength >= newByteLength && (!preserveResizability || fixedLength)) {
+ newBuffer = slice(arrayBuffer, 0, newByteLength);
+ } else {
+ var options = preserveResizability && !fixedLength && maxByteLength ? { maxByteLength: maxByteLength(arrayBuffer) } : undefined;
+ newBuffer = new ArrayBuffer(newByteLength, options);
+ var a = new DataView(arrayBuffer);
+ var b = new DataView(newBuffer);
+ var copyLength = min(newByteLength, byteLength);
+ for (var i = 0; i < copyLength; i++) setInt8(b, i, getInt8(a, i));
+ }
+ if (!PROPER_STRUCTURED_CLONE_TRANSFER) detachTransferable(arrayBuffer);
+ return newBuffer;
+};
+
+
+/***/ }),
+
+/***/ 4644:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var NATIVE_ARRAY_BUFFER = __webpack_require__(7811);
+var DESCRIPTORS = __webpack_require__(3724);
+var global = __webpack_require__(4475);
+var isCallable = __webpack_require__(4901);
+var isObject = __webpack_require__(34);
+var hasOwn = __webpack_require__(9297);
+var classof = __webpack_require__(6955);
+var tryToString = __webpack_require__(6823);
+var createNonEnumerableProperty = __webpack_require__(6699);
+var defineBuiltIn = __webpack_require__(6840);
+var defineBuiltInAccessor = __webpack_require__(2106);
+var isPrototypeOf = __webpack_require__(1625);
+var getPrototypeOf = __webpack_require__(2787);
+var setPrototypeOf = __webpack_require__(2967);
+var wellKnownSymbol = __webpack_require__(8227);
+var uid = __webpack_require__(3392);
+var InternalStateModule = __webpack_require__(1181);
+
+var enforceInternalState = InternalStateModule.enforce;
+var getInternalState = InternalStateModule.get;
+var Int8Array = global.Int8Array;
+var Int8ArrayPrototype = Int8Array && Int8Array.prototype;
+var Uint8ClampedArray = global.Uint8ClampedArray;
+var Uint8ClampedArrayPrototype = Uint8ClampedArray && Uint8ClampedArray.prototype;
+var TypedArray = Int8Array && getPrototypeOf(Int8Array);
+var TypedArrayPrototype = Int8ArrayPrototype && getPrototypeOf(Int8ArrayPrototype);
+var ObjectPrototype = Object.prototype;
+var TypeError = global.TypeError;
+
+var TO_STRING_TAG = wellKnownSymbol('toStringTag');
+var TYPED_ARRAY_TAG = uid('TYPED_ARRAY_TAG');
+var TYPED_ARRAY_CONSTRUCTOR = 'TypedArrayConstructor';
+// Fixing native typed arrays in Opera Presto crashes the browser, see #595
+var NATIVE_ARRAY_BUFFER_VIEWS = NATIVE_ARRAY_BUFFER && !!setPrototypeOf && classof(global.opera) !== 'Opera';
+var TYPED_ARRAY_TAG_REQUIRED = false;
+var NAME, Constructor, Prototype;
+
+var TypedArrayConstructorsList = {
+ Int8Array: 1,
+ Uint8Array: 1,
+ Uint8ClampedArray: 1,
+ Int16Array: 2,
+ Uint16Array: 2,
+ Int32Array: 4,
+ Uint32Array: 4,
+ Float32Array: 4,
+ Float64Array: 8
+};
+
+var BigIntArrayConstructorsList = {
+ BigInt64Array: 8,
+ BigUint64Array: 8
+};
+
+var isView = function isView(it) {
+ if (!isObject(it)) return false;
+ var klass = classof(it);
+ return klass === 'DataView'
+ || hasOwn(TypedArrayConstructorsList, klass)
+ || hasOwn(BigIntArrayConstructorsList, klass);
+};
+
+var getTypedArrayConstructor = function (it) {
+ var proto = getPrototypeOf(it);
+ if (!isObject(proto)) return;
+ var state = getInternalState(proto);
+ return (state && hasOwn(state, TYPED_ARRAY_CONSTRUCTOR)) ? state[TYPED_ARRAY_CONSTRUCTOR] : getTypedArrayConstructor(proto);
+};
+
+var isTypedArray = function (it) {
+ if (!isObject(it)) return false;
+ var klass = classof(it);
+ return hasOwn(TypedArrayConstructorsList, klass)
+ || hasOwn(BigIntArrayConstructorsList, klass);
+};
+
+var aTypedArray = function (it) {
+ if (isTypedArray(it)) return it;
+ throw new TypeError('Target is not a typed array');
+};
+
+var aTypedArrayConstructor = function (C) {
+ if (isCallable(C) && (!setPrototypeOf || isPrototypeOf(TypedArray, C))) return C;
+ throw new TypeError(tryToString(C) + ' is not a typed array constructor');
+};
+
+var exportTypedArrayMethod = function (KEY, property, forced, options) {
+ if (!DESCRIPTORS) return;
+ if (forced) for (var ARRAY in TypedArrayConstructorsList) {
+ var TypedArrayConstructor = global[ARRAY];
+ if (TypedArrayConstructor && hasOwn(TypedArrayConstructor.prototype, KEY)) try {
+ delete TypedArrayConstructor.prototype[KEY];
+ } catch (error) {
+ // old WebKit bug - some methods are non-configurable
+ try {
+ TypedArrayConstructor.prototype[KEY] = property;
+ } catch (error2) { /* empty */ }
+ }
+ }
+ if (!TypedArrayPrototype[KEY] || forced) {
+ defineBuiltIn(TypedArrayPrototype, KEY, forced ? property
+ : NATIVE_ARRAY_BUFFER_VIEWS && Int8ArrayPrototype[KEY] || property, options);
+ }
+};
+
+var exportTypedArrayStaticMethod = function (KEY, property, forced) {
+ var ARRAY, TypedArrayConstructor;
+ if (!DESCRIPTORS) return;
+ if (setPrototypeOf) {
+ if (forced) for (ARRAY in TypedArrayConstructorsList) {
+ TypedArrayConstructor = global[ARRAY];
+ if (TypedArrayConstructor && hasOwn(TypedArrayConstructor, KEY)) try {
+ delete TypedArrayConstructor[KEY];
+ } catch (error) { /* empty */ }
+ }
+ if (!TypedArray[KEY] || forced) {
+ // V8 ~ Chrome 49-50 `%TypedArray%` methods are non-writable non-configurable
+ try {
+ return defineBuiltIn(TypedArray, KEY, forced ? property : NATIVE_ARRAY_BUFFER_VIEWS && TypedArray[KEY] || property);
+ } catch (error) { /* empty */ }
+ } else return;
+ }
+ for (ARRAY in TypedArrayConstructorsList) {
+ TypedArrayConstructor = global[ARRAY];
+ if (TypedArrayConstructor && (!TypedArrayConstructor[KEY] || forced)) {
+ defineBuiltIn(TypedArrayConstructor, KEY, property);
+ }
+ }
+};
+
+for (NAME in TypedArrayConstructorsList) {
+ Constructor = global[NAME];
+ Prototype = Constructor && Constructor.prototype;
+ if (Prototype) enforceInternalState(Prototype)[TYPED_ARRAY_CONSTRUCTOR] = Constructor;
+ else NATIVE_ARRAY_BUFFER_VIEWS = false;
+}
+
+for (NAME in BigIntArrayConstructorsList) {
+ Constructor = global[NAME];
+ Prototype = Constructor && Constructor.prototype;
+ if (Prototype) enforceInternalState(Prototype)[TYPED_ARRAY_CONSTRUCTOR] = Constructor;
+}
+
+// WebKit bug - typed arrays constructors prototype is Object.prototype
+if (!NATIVE_ARRAY_BUFFER_VIEWS || !isCallable(TypedArray) || TypedArray === Function.prototype) {
+ // eslint-disable-next-line no-shadow -- safe
+ TypedArray = function TypedArray() {
+ throw new TypeError('Incorrect invocation');
+ };
+ if (NATIVE_ARRAY_BUFFER_VIEWS) for (NAME in TypedArrayConstructorsList) {
+ if (global[NAME]) setPrototypeOf(global[NAME], TypedArray);
+ }
+}
+
+if (!NATIVE_ARRAY_BUFFER_VIEWS || !TypedArrayPrototype || TypedArrayPrototype === ObjectPrototype) {
+ TypedArrayPrototype = TypedArray.prototype;
+ if (NATIVE_ARRAY_BUFFER_VIEWS) for (NAME in TypedArrayConstructorsList) {
+ if (global[NAME]) setPrototypeOf(global[NAME].prototype, TypedArrayPrototype);
+ }
+}
+
+// WebKit bug - one more object in Uint8ClampedArray prototype chain
+if (NATIVE_ARRAY_BUFFER_VIEWS && getPrototypeOf(Uint8ClampedArrayPrototype) !== TypedArrayPrototype) {
+ setPrototypeOf(Uint8ClampedArrayPrototype, TypedArrayPrototype);
+}
+
+if (DESCRIPTORS && !hasOwn(TypedArrayPrototype, TO_STRING_TAG)) {
+ TYPED_ARRAY_TAG_REQUIRED = true;
+ defineBuiltInAccessor(TypedArrayPrototype, TO_STRING_TAG, {
+ configurable: true,
+ get: function () {
+ return isObject(this) ? this[TYPED_ARRAY_TAG] : undefined;
+ }
+ });
+ for (NAME in TypedArrayConstructorsList) if (global[NAME]) {
+ createNonEnumerableProperty(global[NAME], TYPED_ARRAY_TAG, NAME);
+ }
+}
+
+module.exports = {
+ NATIVE_ARRAY_BUFFER_VIEWS: NATIVE_ARRAY_BUFFER_VIEWS,
+ TYPED_ARRAY_TAG: TYPED_ARRAY_TAG_REQUIRED && TYPED_ARRAY_TAG,
+ aTypedArray: aTypedArray,
+ aTypedArrayConstructor: aTypedArrayConstructor,
+ exportTypedArrayMethod: exportTypedArrayMethod,
+ exportTypedArrayStaticMethod: exportTypedArrayStaticMethod,
+ getTypedArrayConstructor: getTypedArrayConstructor,
+ isView: isView,
+ isTypedArray: isTypedArray,
+ TypedArray: TypedArray,
+ TypedArrayPrototype: TypedArrayPrototype
+};
+
+
+/***/ }),
+
+/***/ 5370:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var lengthOfArrayLike = __webpack_require__(6198);
+
+module.exports = function (Constructor, list, $length) {
+ var index = 0;
+ var length = arguments.length > 2 ? $length : lengthOfArrayLike(list);
+ var result = new Constructor(length);
+ while (length > index) result[index] = list[index++];
+ return result;
+};
+
+
+/***/ }),
+
+/***/ 9617:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var toIndexedObject = __webpack_require__(5397);
+var toAbsoluteIndex = __webpack_require__(5610);
+var lengthOfArrayLike = __webpack_require__(6198);
+
+// `Array.prototype.{ indexOf, includes }` methods implementation
+var createMethod = function (IS_INCLUDES) {
+ return function ($this, el, fromIndex) {
+ var O = toIndexedObject($this);
+ var length = lengthOfArrayLike(O);
+ if (length === 0) return !IS_INCLUDES && -1;
+ var index = toAbsoluteIndex(fromIndex, length);
+ var value;
+ // Array#includes uses SameValueZero equality algorithm
+ // eslint-disable-next-line no-self-compare -- NaN check
+ if (IS_INCLUDES && el !== el) while (length > index) {
+ value = O[index++];
+ // eslint-disable-next-line no-self-compare -- NaN check
+ if (value !== value) return true;
+ // Array#indexOf ignores holes, Array#includes - not
+ } else for (;length > index; index++) {
+ if ((IS_INCLUDES || index in O) && O[index] === el) return IS_INCLUDES || index || 0;
+ } return !IS_INCLUDES && -1;
+ };
+};
+
+module.exports = {
+ // `Array.prototype.includes` method
+ // https://tc39.es/ecma262/#sec-array.prototype.includes
+ includes: createMethod(true),
+ // `Array.prototype.indexOf` method
+ // https://tc39.es/ecma262/#sec-array.prototype.indexof
+ indexOf: createMethod(false)
+};
+
+
+/***/ }),
+
+/***/ 4527:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var DESCRIPTORS = __webpack_require__(3724);
+var isArray = __webpack_require__(4376);
+
+var $TypeError = TypeError;
+// eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
+var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
+
+// Safari < 13 does not throw an error in this case
+var SILENT_ON_NON_WRITABLE_LENGTH_SET = DESCRIPTORS && !function () {
+ // makes no sense without proper strict mode support
+ if (this !== undefined) return true;
+ try {
+ // eslint-disable-next-line es/no-object-defineproperty -- safe
+ Object.defineProperty([], 'length', { writable: false }).length = 1;
+ } catch (error) {
+ return error instanceof TypeError;
+ }
+}();
+
+module.exports = SILENT_ON_NON_WRITABLE_LENGTH_SET ? function (O, length) {
+ if (isArray(O) && !getOwnPropertyDescriptor(O, 'length').writable) {
+ throw new $TypeError('Cannot set read only .length');
+ } return O.length = length;
+} : function (O, length) {
+ return O.length = length;
+};
+
+
+/***/ }),
+
+/***/ 7628:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var lengthOfArrayLike = __webpack_require__(6198);
+
+// https://tc39.es/proposal-change-array-by-copy/#sec-array.prototype.toReversed
+// https://tc39.es/proposal-change-array-by-copy/#sec-%typedarray%.prototype.toReversed
+module.exports = function (O, C) {
+ var len = lengthOfArrayLike(O);
+ var A = new C(len);
+ var k = 0;
+ for (; k < len; k++) A[k] = O[len - k - 1];
+ return A;
+};
+
+
+/***/ }),
+
+/***/ 9928:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var lengthOfArrayLike = __webpack_require__(6198);
+var toIntegerOrInfinity = __webpack_require__(1291);
+
+var $RangeError = RangeError;
+
+// https://tc39.es/proposal-change-array-by-copy/#sec-array.prototype.with
+// https://tc39.es/proposal-change-array-by-copy/#sec-%typedarray%.prototype.with
+module.exports = function (O, C, index, value) {
+ var len = lengthOfArrayLike(O);
+ var relativeIndex = toIntegerOrInfinity(index);
+ var actualIndex = relativeIndex < 0 ? len + relativeIndex : relativeIndex;
+ if (actualIndex >= len || actualIndex < 0) throw new $RangeError('Incorrect index');
+ var A = new C(len);
+ var k = 0;
+ for (; k < len; k++) A[k] = k === actualIndex ? value : O[k];
+ return A;
+};
+
+
+/***/ }),
+
+/***/ 6319:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var anObject = __webpack_require__(8551);
+var iteratorClose = __webpack_require__(9539);
+
+// call something on iterator step with safe closing on error
+module.exports = function (iterator, fn, value, ENTRIES) {
+ try {
+ return ENTRIES ? fn(anObject(value)[0], value[1]) : fn(value);
+ } catch (error) {
+ iteratorClose(iterator, 'throw', error);
+ }
+};
+
+
+/***/ }),
+
+/***/ 4576:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var uncurryThis = __webpack_require__(9504);
+
+var toString = uncurryThis({}.toString);
+var stringSlice = uncurryThis(''.slice);
+
+module.exports = function (it) {
+ return stringSlice(toString(it), 8, -1);
+};
+
+
+/***/ }),
+
+/***/ 6955:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var TO_STRING_TAG_SUPPORT = __webpack_require__(2140);
+var isCallable = __webpack_require__(4901);
+var classofRaw = __webpack_require__(4576);
+var wellKnownSymbol = __webpack_require__(8227);
+
+var TO_STRING_TAG = wellKnownSymbol('toStringTag');
+var $Object = Object;
+
+// ES3 wrong here
+var CORRECT_ARGUMENTS = classofRaw(function () { return arguments; }()) === 'Arguments';
+
+// fallback for IE11 Script Access Denied error
+var tryGet = function (it, key) {
+ try {
+ return it[key];
+ } catch (error) { /* empty */ }
+};
+
+// getting tag from ES6+ `Object.prototype.toString`
+module.exports = TO_STRING_TAG_SUPPORT ? classofRaw : function (it) {
+ var O, tag, result;
+ return it === undefined ? 'Undefined' : it === null ? 'Null'
+ // @@toStringTag case
+ : typeof (tag = tryGet(O = $Object(it), TO_STRING_TAG)) == 'string' ? tag
+ // builtinTag case
+ : CORRECT_ARGUMENTS ? classofRaw(O)
+ // ES3 arguments fallback
+ : (result = classofRaw(O)) === 'Object' && isCallable(O.callee) ? 'Arguments' : result;
+};
+
+
+/***/ }),
+
+/***/ 7740:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var hasOwn = __webpack_require__(9297);
+var ownKeys = __webpack_require__(5031);
+var getOwnPropertyDescriptorModule = __webpack_require__(7347);
+var definePropertyModule = __webpack_require__(4913);
+
+module.exports = function (target, source, exceptions) {
+ var keys = ownKeys(source);
+ var defineProperty = definePropertyModule.f;
+ var getOwnPropertyDescriptor = getOwnPropertyDescriptorModule.f;
+ for (var i = 0; i < keys.length; i++) {
+ var key = keys[i];
+ if (!hasOwn(target, key) && !(exceptions && hasOwn(exceptions, key))) {
+ defineProperty(target, key, getOwnPropertyDescriptor(source, key));
+ }
+ }
+};
+
+
+/***/ }),
+
+/***/ 2211:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var fails = __webpack_require__(9039);
+
+module.exports = !fails(function () {
+ function F() { /* empty */ }
+ F.prototype.constructor = null;
+ // eslint-disable-next-line es/no-object-getprototypeof -- required for testing
+ return Object.getPrototypeOf(new F()) !== F.prototype;
+});
+
+
+/***/ }),
+
+/***/ 2529:
+/***/ ((module) => {
+
+
+// `CreateIterResultObject` abstract operation
+// https://tc39.es/ecma262/#sec-createiterresultobject
+module.exports = function (value, done) {
+ return { value: value, done: done };
+};
+
+
+/***/ }),
+
+/***/ 6699:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var DESCRIPTORS = __webpack_require__(3724);
+var definePropertyModule = __webpack_require__(4913);
+var createPropertyDescriptor = __webpack_require__(6980);
+
+module.exports = DESCRIPTORS ? function (object, key, value) {
+ return definePropertyModule.f(object, key, createPropertyDescriptor(1, value));
+} : function (object, key, value) {
+ object[key] = value;
+ return object;
+};
+
+
+/***/ }),
+
+/***/ 6980:
+/***/ ((module) => {
+
+
+module.exports = function (bitmap, value) {
+ return {
+ enumerable: !(bitmap & 1),
+ configurable: !(bitmap & 2),
+ writable: !(bitmap & 4),
+ value: value
+ };
+};
+
+
+/***/ }),
+
+/***/ 4659:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var DESCRIPTORS = __webpack_require__(3724);
+var definePropertyModule = __webpack_require__(4913);
+var createPropertyDescriptor = __webpack_require__(6980);
+
+module.exports = function (object, key, value) {
+ if (DESCRIPTORS) definePropertyModule.f(object, key, createPropertyDescriptor(0, value));
+ else object[key] = value;
+};
+
+
+/***/ }),
+
+/***/ 2106:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var makeBuiltIn = __webpack_require__(283);
+var defineProperty = __webpack_require__(4913);
+
+module.exports = function (target, name, descriptor) {
+ if (descriptor.get) makeBuiltIn(descriptor.get, name, { getter: true });
+ if (descriptor.set) makeBuiltIn(descriptor.set, name, { setter: true });
+ return defineProperty.f(target, name, descriptor);
+};
+
+
+/***/ }),
+
+/***/ 6840:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var isCallable = __webpack_require__(4901);
+var definePropertyModule = __webpack_require__(4913);
+var makeBuiltIn = __webpack_require__(283);
+var defineGlobalProperty = __webpack_require__(9433);
+
+module.exports = function (O, key, value, options) {
+ if (!options) options = {};
+ var simple = options.enumerable;
+ var name = options.name !== undefined ? options.name : key;
+ if (isCallable(value)) makeBuiltIn(value, name, options);
+ if (options.global) {
+ if (simple) O[key] = value;
+ else defineGlobalProperty(key, value);
+ } else {
+ try {
+ if (!options.unsafe) delete O[key];
+ else if (O[key]) simple = true;
+ } catch (error) { /* empty */ }
+ if (simple) O[key] = value;
+ else definePropertyModule.f(O, key, {
+ value: value,
+ enumerable: false,
+ configurable: !options.nonConfigurable,
+ writable: !options.nonWritable
+ });
+ } return O;
+};
+
+
+/***/ }),
+
+/***/ 6279:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var defineBuiltIn = __webpack_require__(6840);
+
+module.exports = function (target, src, options) {
+ for (var key in src) defineBuiltIn(target, key, src[key], options);
+ return target;
+};
+
+
+/***/ }),
+
+/***/ 9433:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var global = __webpack_require__(4475);
+
+// eslint-disable-next-line es/no-object-defineproperty -- safe
+var defineProperty = Object.defineProperty;
+
+module.exports = function (key, value) {
+ try {
+ defineProperty(global, key, { value: value, configurable: true, writable: true });
+ } catch (error) {
+ global[key] = value;
+ } return value;
+};
+
+
+/***/ }),
+
+/***/ 3724:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var fails = __webpack_require__(9039);
+
+// Detect IE8's incomplete defineProperty implementation
+module.exports = !fails(function () {
+ // eslint-disable-next-line es/no-object-defineproperty -- required for testing
+ return Object.defineProperty({}, 1, { get: function () { return 7; } })[1] !== 7;
+});
+
+
+/***/ }),
+
+/***/ 4483:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var global = __webpack_require__(4475);
+var tryNodeRequire = __webpack_require__(9714);
+var PROPER_STRUCTURED_CLONE_TRANSFER = __webpack_require__(1548);
+
+var structuredClone = global.structuredClone;
+var $ArrayBuffer = global.ArrayBuffer;
+var $MessageChannel = global.MessageChannel;
+var detach = false;
+var WorkerThreads, channel, buffer, $detach;
+
+if (PROPER_STRUCTURED_CLONE_TRANSFER) {
+ detach = function (transferable) {
+ structuredClone(transferable, { transfer: [transferable] });
+ };
+} else if ($ArrayBuffer) try {
+ if (!$MessageChannel) {
+ WorkerThreads = tryNodeRequire('worker_threads');
+ if (WorkerThreads) $MessageChannel = WorkerThreads.MessageChannel;
+ }
+
+ if ($MessageChannel) {
+ channel = new $MessageChannel();
+ buffer = new $ArrayBuffer(2);
+
+ $detach = function (transferable) {
+ channel.port1.postMessage(null, [transferable]);
+ };
+
+ if (buffer.byteLength === 2) {
+ $detach(buffer);
+ if (buffer.byteLength === 0) detach = $detach;
+ }
+ }
+} catch (error) { /* empty */ }
+
+module.exports = detach;
+
+
+/***/ }),
+
+/***/ 4055:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var global = __webpack_require__(4475);
+var isObject = __webpack_require__(34);
+
+var document = global.document;
+// typeof document.createElement is 'object' in old IE
+var EXISTS = isObject(document) && isObject(document.createElement);
+
+module.exports = function (it) {
+ return EXISTS ? document.createElement(it) : {};
+};
+
+
+/***/ }),
+
+/***/ 6837:
+/***/ ((module) => {
+
+
+var $TypeError = TypeError;
+var MAX_SAFE_INTEGER = 0x1FFFFFFFFFFFFF; // 2 ** 53 - 1 == 9007199254740991
+
+module.exports = function (it) {
+ if (it > MAX_SAFE_INTEGER) throw $TypeError('Maximum allowed index exceeded');
+ return it;
+};
+
+
+/***/ }),
+
+/***/ 5002:
+/***/ ((module) => {
+
+
+module.exports = {
+ IndexSizeError: { s: 'INDEX_SIZE_ERR', c: 1, m: 1 },
+ DOMStringSizeError: { s: 'DOMSTRING_SIZE_ERR', c: 2, m: 0 },
+ HierarchyRequestError: { s: 'HIERARCHY_REQUEST_ERR', c: 3, m: 1 },
+ WrongDocumentError: { s: 'WRONG_DOCUMENT_ERR', c: 4, m: 1 },
+ InvalidCharacterError: { s: 'INVALID_CHARACTER_ERR', c: 5, m: 1 },
+ NoDataAllowedError: { s: 'NO_DATA_ALLOWED_ERR', c: 6, m: 0 },
+ NoModificationAllowedError: { s: 'NO_MODIFICATION_ALLOWED_ERR', c: 7, m: 1 },
+ NotFoundError: { s: 'NOT_FOUND_ERR', c: 8, m: 1 },
+ NotSupportedError: { s: 'NOT_SUPPORTED_ERR', c: 9, m: 1 },
+ InUseAttributeError: { s: 'INUSE_ATTRIBUTE_ERR', c: 10, m: 1 },
+ InvalidStateError: { s: 'INVALID_STATE_ERR', c: 11, m: 1 },
+ SyntaxError: { s: 'SYNTAX_ERR', c: 12, m: 1 },
+ InvalidModificationError: { s: 'INVALID_MODIFICATION_ERR', c: 13, m: 1 },
+ NamespaceError: { s: 'NAMESPACE_ERR', c: 14, m: 1 },
+ InvalidAccessError: { s: 'INVALID_ACCESS_ERR', c: 15, m: 1 },
+ ValidationError: { s: 'VALIDATION_ERR', c: 16, m: 0 },
+ TypeMismatchError: { s: 'TYPE_MISMATCH_ERR', c: 17, m: 1 },
+ SecurityError: { s: 'SECURITY_ERR', c: 18, m: 1 },
+ NetworkError: { s: 'NETWORK_ERR', c: 19, m: 1 },
+ AbortError: { s: 'ABORT_ERR', c: 20, m: 1 },
+ URLMismatchError: { s: 'URL_MISMATCH_ERR', c: 21, m: 1 },
+ QuotaExceededError: { s: 'QUOTA_EXCEEDED_ERR', c: 22, m: 1 },
+ TimeoutError: { s: 'TIMEOUT_ERR', c: 23, m: 1 },
+ InvalidNodeTypeError: { s: 'INVALID_NODE_TYPE_ERR', c: 24, m: 1 },
+ DataCloneError: { s: 'DATA_CLONE_ERR', c: 25, m: 1 }
+};
+
+
+/***/ }),
+
+/***/ 7290:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var IS_DENO = __webpack_require__(516);
+var IS_NODE = __webpack_require__(9088);
+
+module.exports = !IS_DENO && !IS_NODE
+ && typeof window == 'object'
+ && typeof document == 'object';
+
+
+/***/ }),
+
+/***/ 516:
+/***/ ((module) => {
+
+
+/* global Deno -- Deno case */
+module.exports = typeof Deno == 'object' && Deno && typeof Deno.version == 'object';
+
+
+/***/ }),
+
+/***/ 9088:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var global = __webpack_require__(4475);
+var classof = __webpack_require__(4576);
+
+module.exports = classof(global.process) === 'process';
+
+
+/***/ }),
+
+/***/ 9392:
+/***/ ((module) => {
+
+
+module.exports = typeof navigator != 'undefined' && String(navigator.userAgent) || '';
+
+
+/***/ }),
+
+/***/ 7388:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var global = __webpack_require__(4475);
+var userAgent = __webpack_require__(9392);
+
+var process = global.process;
+var Deno = global.Deno;
+var versions = process && process.versions || Deno && Deno.version;
+var v8 = versions && versions.v8;
+var match, version;
+
+if (v8) {
+ match = v8.split('.');
+ // in old Chrome, versions of V8 isn't V8 = Chrome / 10
+ // but their correct versions are not interesting for us
+ version = match[0] > 0 && match[0] < 4 ? 1 : +(match[0] + match[1]);
+}
+
+// BrowserFS NodeJS `process` polyfill incorrectly set `.v8` to `0.0`
+// so check `userAgent` even if `.v8` exists, but 0
+if (!version && userAgent) {
+ match = userAgent.match(/Edge\/(\d+)/);
+ if (!match || match[1] >= 74) {
+ match = userAgent.match(/Chrome\/(\d+)/);
+ if (match) version = +match[1];
+ }
+}
+
+module.exports = version;
+
+
+/***/ }),
+
+/***/ 8727:
+/***/ ((module) => {
+
+
+// IE8- don't enum bug keys
+module.exports = [
+ 'constructor',
+ 'hasOwnProperty',
+ 'isPrototypeOf',
+ 'propertyIsEnumerable',
+ 'toLocaleString',
+ 'toString',
+ 'valueOf'
+];
+
+
+/***/ }),
+
+/***/ 6193:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var uncurryThis = __webpack_require__(9504);
+
+var $Error = Error;
+var replace = uncurryThis(''.replace);
+
+var TEST = (function (arg) { return String(new $Error(arg).stack); })('zxcasd');
+// eslint-disable-next-line redos/no-vulnerable -- safe
+var V8_OR_CHAKRA_STACK_ENTRY = /\n\s*at [^:]*:[^\n]*/;
+var IS_V8_OR_CHAKRA_STACK = V8_OR_CHAKRA_STACK_ENTRY.test(TEST);
+
+module.exports = function (stack, dropEntries) {
+ if (IS_V8_OR_CHAKRA_STACK && typeof stack == 'string' && !$Error.prepareStackTrace) {
+ while (dropEntries--) stack = replace(stack, V8_OR_CHAKRA_STACK_ENTRY, '');
+ } return stack;
+};
+
+
+/***/ }),
+
+/***/ 6518:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var global = __webpack_require__(4475);
+var getOwnPropertyDescriptor = (__webpack_require__(7347).f);
+var createNonEnumerableProperty = __webpack_require__(6699);
+var defineBuiltIn = __webpack_require__(6840);
+var defineGlobalProperty = __webpack_require__(9433);
+var copyConstructorProperties = __webpack_require__(7740);
+var isForced = __webpack_require__(2796);
+
+/*
+ options.target - name of the target object
+ options.global - target is the global object
+ options.stat - export as static methods of target
+ options.proto - export as prototype methods of target
+ options.real - real prototype method for the `pure` version
+ options.forced - export even if the native feature is available
+ options.bind - bind methods to the target, required for the `pure` version
+ options.wrap - wrap constructors to preventing global pollution, required for the `pure` version
+ options.unsafe - use the simple assignment of property instead of delete + defineProperty
+ options.sham - add a flag to not completely full polyfills
+ options.enumerable - export as enumerable property
+ options.dontCallGetSet - prevent calling a getter on target
+ options.name - the .name of the function if it does not match the key
+*/
+module.exports = function (options, source) {
+ var TARGET = options.target;
+ var GLOBAL = options.global;
+ var STATIC = options.stat;
+ var FORCED, target, key, targetProperty, sourceProperty, descriptor;
+ if (GLOBAL) {
+ target = global;
+ } else if (STATIC) {
+ target = global[TARGET] || defineGlobalProperty(TARGET, {});
+ } else {
+ target = global[TARGET] && global[TARGET].prototype;
+ }
+ if (target) for (key in source) {
+ sourceProperty = source[key];
+ if (options.dontCallGetSet) {
+ descriptor = getOwnPropertyDescriptor(target, key);
+ targetProperty = descriptor && descriptor.value;
+ } else targetProperty = target[key];
+ FORCED = isForced(GLOBAL ? key : TARGET + (STATIC ? '.' : '#') + key, options.forced);
+ // contained in target
+ if (!FORCED && targetProperty !== undefined) {
+ if (typeof sourceProperty == typeof targetProperty) continue;
+ copyConstructorProperties(sourceProperty, targetProperty);
+ }
+ // add a flag to not completely full polyfills
+ if (options.sham || (targetProperty && targetProperty.sham)) {
+ createNonEnumerableProperty(sourceProperty, 'sham', true);
+ }
+ defineBuiltIn(target, key, sourceProperty, options);
+ }
+};
+
+
+/***/ }),
+
+/***/ 9039:
+/***/ ((module) => {
+
+
+module.exports = function (exec) {
+ try {
+ return !!exec();
+ } catch (error) {
+ return true;
+ }
+};
+
+
+/***/ }),
+
+/***/ 6080:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var uncurryThis = __webpack_require__(7476);
+var aCallable = __webpack_require__(9306);
+var NATIVE_BIND = __webpack_require__(616);
+
+var bind = uncurryThis(uncurryThis.bind);
+
+// optional / simple context binding
+module.exports = function (fn, that) {
+ aCallable(fn);
+ return that === undefined ? fn : NATIVE_BIND ? bind(fn, that) : function (/* ...args */) {
+ return fn.apply(that, arguments);
+ };
+};
+
+
+/***/ }),
+
+/***/ 616:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var fails = __webpack_require__(9039);
+
+module.exports = !fails(function () {
+ // eslint-disable-next-line es/no-function-prototype-bind -- safe
+ var test = (function () { /* empty */ }).bind();
+ // eslint-disable-next-line no-prototype-builtins -- safe
+ return typeof test != 'function' || test.hasOwnProperty('prototype');
+});
+
+
+/***/ }),
+
+/***/ 9565:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var NATIVE_BIND = __webpack_require__(616);
+
+var call = Function.prototype.call;
+
+module.exports = NATIVE_BIND ? call.bind(call) : function () {
+ return call.apply(call, arguments);
+};
+
+
+/***/ }),
+
+/***/ 350:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var DESCRIPTORS = __webpack_require__(3724);
+var hasOwn = __webpack_require__(9297);
+
+var FunctionPrototype = Function.prototype;
+// eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
+var getDescriptor = DESCRIPTORS && Object.getOwnPropertyDescriptor;
+
+var EXISTS = hasOwn(FunctionPrototype, 'name');
+// additional protection from minified / mangled / dropped function names
+var PROPER = EXISTS && (function something() { /* empty */ }).name === 'something';
+var CONFIGURABLE = EXISTS && (!DESCRIPTORS || (DESCRIPTORS && getDescriptor(FunctionPrototype, 'name').configurable));
+
+module.exports = {
+ EXISTS: EXISTS,
+ PROPER: PROPER,
+ CONFIGURABLE: CONFIGURABLE
+};
+
+
+/***/ }),
+
+/***/ 6706:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var uncurryThis = __webpack_require__(9504);
+var aCallable = __webpack_require__(9306);
+
+module.exports = function (object, key, method) {
+ try {
+ // eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
+ return uncurryThis(aCallable(Object.getOwnPropertyDescriptor(object, key)[method]));
+ } catch (error) { /* empty */ }
+};
+
+
+/***/ }),
+
+/***/ 7476:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var classofRaw = __webpack_require__(4576);
+var uncurryThis = __webpack_require__(9504);
+
+module.exports = function (fn) {
+ // Nashorn bug:
+ // https://github.com/zloirock/core-js/issues/1128
+ // https://github.com/zloirock/core-js/issues/1130
+ if (classofRaw(fn) === 'Function') return uncurryThis(fn);
+};
+
+
+/***/ }),
+
+/***/ 9504:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var NATIVE_BIND = __webpack_require__(616);
+
+var FunctionPrototype = Function.prototype;
+var call = FunctionPrototype.call;
+var uncurryThisWithBind = NATIVE_BIND && FunctionPrototype.bind.bind(call, call);
+
+module.exports = NATIVE_BIND ? uncurryThisWithBind : function (fn) {
+ return function () {
+ return call.apply(fn, arguments);
+ };
+};
+
+
+/***/ }),
+
+/***/ 7751:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var global = __webpack_require__(4475);
+var isCallable = __webpack_require__(4901);
+
+var aFunction = function (argument) {
+ return isCallable(argument) ? argument : undefined;
+};
+
+module.exports = function (namespace, method) {
+ return arguments.length < 2 ? aFunction(global[namespace]) : global[namespace] && global[namespace][method];
+};
+
+
+/***/ }),
+
+/***/ 1767:
+/***/ ((module) => {
+
+
+// `GetIteratorDirect(obj)` abstract operation
+// https://tc39.es/proposal-iterator-helpers/#sec-getiteratordirect
+module.exports = function (obj) {
+ return {
+ iterator: obj,
+ next: obj.next,
+ done: false
+ };
+};
+
+
+/***/ }),
+
+/***/ 851:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var classof = __webpack_require__(6955);
+var getMethod = __webpack_require__(5966);
+var isNullOrUndefined = __webpack_require__(4117);
+var Iterators = __webpack_require__(6269);
+var wellKnownSymbol = __webpack_require__(8227);
+
+var ITERATOR = wellKnownSymbol('iterator');
+
+module.exports = function (it) {
+ if (!isNullOrUndefined(it)) return getMethod(it, ITERATOR)
+ || getMethod(it, '@@iterator')
+ || Iterators[classof(it)];
+};
+
+
+/***/ }),
+
+/***/ 81:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var call = __webpack_require__(9565);
+var aCallable = __webpack_require__(9306);
+var anObject = __webpack_require__(8551);
+var tryToString = __webpack_require__(6823);
+var getIteratorMethod = __webpack_require__(851);
+
+var $TypeError = TypeError;
+
+module.exports = function (argument, usingIterator) {
+ var iteratorMethod = arguments.length < 2 ? getIteratorMethod(argument) : usingIterator;
+ if (aCallable(iteratorMethod)) return anObject(call(iteratorMethod, argument));
+ throw new $TypeError(tryToString(argument) + ' is not iterable');
+};
+
+
+/***/ }),
+
+/***/ 5966:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var aCallable = __webpack_require__(9306);
+var isNullOrUndefined = __webpack_require__(4117);
+
+// `GetMethod` abstract operation
+// https://tc39.es/ecma262/#sec-getmethod
+module.exports = function (V, P) {
+ var func = V[P];
+ return isNullOrUndefined(func) ? undefined : aCallable(func);
+};
+
+
+/***/ }),
+
+/***/ 3789:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var aCallable = __webpack_require__(9306);
+var anObject = __webpack_require__(8551);
+var call = __webpack_require__(9565);
+var toIntegerOrInfinity = __webpack_require__(1291);
+var getIteratorDirect = __webpack_require__(1767);
+
+var INVALID_SIZE = 'Invalid size';
+var $RangeError = RangeError;
+var $TypeError = TypeError;
+var max = Math.max;
+
+var SetRecord = function (set, intSize) {
+ this.set = set;
+ this.size = max(intSize, 0);
+ this.has = aCallable(set.has);
+ this.keys = aCallable(set.keys);
+};
+
+SetRecord.prototype = {
+ getIterator: function () {
+ return getIteratorDirect(anObject(call(this.keys, this.set)));
+ },
+ includes: function (it) {
+ return call(this.has, this.set, it);
+ }
+};
+
+// `GetSetRecord` abstract operation
+// https://tc39.es/proposal-set-methods/#sec-getsetrecord
+module.exports = function (obj) {
+ anObject(obj);
+ var numSize = +obj.size;
+ // NOTE: If size is undefined, then numSize will be NaN
+ // eslint-disable-next-line no-self-compare -- NaN check
+ if (numSize !== numSize) throw new $TypeError(INVALID_SIZE);
+ var intSize = toIntegerOrInfinity(numSize);
+ if (intSize < 0) throw new $RangeError(INVALID_SIZE);
+ return new SetRecord(obj, intSize);
+};
+
+
+/***/ }),
+
+/***/ 4475:
+/***/ (function(module) {
+
+
+var check = function (it) {
+ return it && it.Math === Math && it;
+};
+
+// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028
+module.exports =
+ // eslint-disable-next-line es/no-global-this -- safe
+ check(typeof globalThis == 'object' && globalThis) ||
+ check(typeof window == 'object' && window) ||
+ // eslint-disable-next-line no-restricted-globals -- safe
+ check(typeof self == 'object' && self) ||
+ check(typeof global == 'object' && global) ||
+ check(typeof this == 'object' && this) ||
+ // eslint-disable-next-line no-new-func -- fallback
+ (function () { return this; })() || Function('return this')();
+
+
+/***/ }),
+
+/***/ 9297:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var uncurryThis = __webpack_require__(9504);
+var toObject = __webpack_require__(8981);
+
+var hasOwnProperty = uncurryThis({}.hasOwnProperty);
+
+// `HasOwnProperty` abstract operation
+// https://tc39.es/ecma262/#sec-hasownproperty
+// eslint-disable-next-line es/no-object-hasown -- safe
+module.exports = Object.hasOwn || function hasOwn(it, key) {
+ return hasOwnProperty(toObject(it), key);
+};
+
+
+/***/ }),
+
+/***/ 421:
+/***/ ((module) => {
+
+
+module.exports = {};
+
+
+/***/ }),
+
+/***/ 397:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var getBuiltIn = __webpack_require__(7751);
+
+module.exports = getBuiltIn('document', 'documentElement');
+
+
+/***/ }),
+
+/***/ 5917:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var DESCRIPTORS = __webpack_require__(3724);
+var fails = __webpack_require__(9039);
+var createElement = __webpack_require__(4055);
+
+// Thanks to IE8 for its funny defineProperty
+module.exports = !DESCRIPTORS && !fails(function () {
+ // eslint-disable-next-line es/no-object-defineproperty -- required for testing
+ return Object.defineProperty(createElement('div'), 'a', {
+ get: function () { return 7; }
+ }).a !== 7;
+});
+
+
+/***/ }),
+
+/***/ 7055:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var uncurryThis = __webpack_require__(9504);
+var fails = __webpack_require__(9039);
+var classof = __webpack_require__(4576);
+
+var $Object = Object;
+var split = uncurryThis(''.split);
+
+// fallback for non-array-like ES3 and non-enumerable old V8 strings
+module.exports = fails(function () {
+ // throws an error in rhino, see https://github.com/mozilla/rhino/issues/346
+ // eslint-disable-next-line no-prototype-builtins -- safe
+ return !$Object('z').propertyIsEnumerable(0);
+}) ? function (it) {
+ return classof(it) === 'String' ? split(it, '') : $Object(it);
+} : $Object;
+
+
+/***/ }),
+
+/***/ 3167:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var isCallable = __webpack_require__(4901);
+var isObject = __webpack_require__(34);
+var setPrototypeOf = __webpack_require__(2967);
+
+// makes subclassing work correct for wrapped built-ins
+module.exports = function ($this, dummy, Wrapper) {
+ var NewTarget, NewTargetPrototype;
+ if (
+ // it can work only with native `setPrototypeOf`
+ setPrototypeOf &&
+ // we haven't completely correct pre-ES6 way for getting `new.target`, so use this
+ isCallable(NewTarget = dummy.constructor) &&
+ NewTarget !== Wrapper &&
+ isObject(NewTargetPrototype = NewTarget.prototype) &&
+ NewTargetPrototype !== Wrapper.prototype
+ ) setPrototypeOf($this, NewTargetPrototype);
+ return $this;
+};
+
+
+/***/ }),
+
+/***/ 3706:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var uncurryThis = __webpack_require__(9504);
+var isCallable = __webpack_require__(4901);
+var store = __webpack_require__(7629);
+
+var functionToString = uncurryThis(Function.toString);
+
+// this helper broken in `core-js@3.4.1-3.4.4`, so we can't use `shared` helper
+if (!isCallable(store.inspectSource)) {
+ store.inspectSource = function (it) {
+ return functionToString(it);
+ };
+}
+
+module.exports = store.inspectSource;
+
+
+/***/ }),
+
+/***/ 1181:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var NATIVE_WEAK_MAP = __webpack_require__(8622);
+var global = __webpack_require__(4475);
+var isObject = __webpack_require__(34);
+var createNonEnumerableProperty = __webpack_require__(6699);
+var hasOwn = __webpack_require__(9297);
+var shared = __webpack_require__(7629);
+var sharedKey = __webpack_require__(6119);
+var hiddenKeys = __webpack_require__(421);
+
+var OBJECT_ALREADY_INITIALIZED = 'Object already initialized';
+var TypeError = global.TypeError;
+var WeakMap = global.WeakMap;
+var set, get, has;
+
+var enforce = function (it) {
+ return has(it) ? get(it) : set(it, {});
+};
+
+var getterFor = function (TYPE) {
+ return function (it) {
+ var state;
+ if (!isObject(it) || (state = get(it)).type !== TYPE) {
+ throw new TypeError('Incompatible receiver, ' + TYPE + ' required');
+ } return state;
+ };
+};
+
+if (NATIVE_WEAK_MAP || shared.state) {
+ var store = shared.state || (shared.state = new WeakMap());
+ /* eslint-disable no-self-assign -- prototype methods protection */
+ store.get = store.get;
+ store.has = store.has;
+ store.set = store.set;
+ /* eslint-enable no-self-assign -- prototype methods protection */
+ set = function (it, metadata) {
+ if (store.has(it)) throw new TypeError(OBJECT_ALREADY_INITIALIZED);
+ metadata.facade = it;
+ store.set(it, metadata);
+ return metadata;
+ };
+ get = function (it) {
+ return store.get(it) || {};
+ };
+ has = function (it) {
+ return store.has(it);
+ };
+} else {
+ var STATE = sharedKey('state');
+ hiddenKeys[STATE] = true;
+ set = function (it, metadata) {
+ if (hasOwn(it, STATE)) throw new TypeError(OBJECT_ALREADY_INITIALIZED);
+ metadata.facade = it;
+ createNonEnumerableProperty(it, STATE, metadata);
+ return metadata;
+ };
+ get = function (it) {
+ return hasOwn(it, STATE) ? it[STATE] : {};
+ };
+ has = function (it) {
+ return hasOwn(it, STATE);
+ };
+}
+
+module.exports = {
+ set: set,
+ get: get,
+ has: has,
+ enforce: enforce,
+ getterFor: getterFor
+};
+
+
+/***/ }),
+
+/***/ 4209:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var wellKnownSymbol = __webpack_require__(8227);
+var Iterators = __webpack_require__(6269);
+
+var ITERATOR = wellKnownSymbol('iterator');
+var ArrayPrototype = Array.prototype;
+
+// check on default Array iterator
+module.exports = function (it) {
+ return it !== undefined && (Iterators.Array === it || ArrayPrototype[ITERATOR] === it);
+};
+
+
+/***/ }),
+
+/***/ 4376:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var classof = __webpack_require__(4576);
+
+// `IsArray` abstract operation
+// https://tc39.es/ecma262/#sec-isarray
+// eslint-disable-next-line es/no-array-isarray -- safe
+module.exports = Array.isArray || function isArray(argument) {
+ return classof(argument) === 'Array';
+};
+
+
+/***/ }),
+
+/***/ 1108:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var classof = __webpack_require__(6955);
+
+module.exports = function (it) {
+ var klass = classof(it);
+ return klass === 'BigInt64Array' || klass === 'BigUint64Array';
+};
+
+
+/***/ }),
+
+/***/ 4901:
+/***/ ((module) => {
+
+
+// https://tc39.es/ecma262/#sec-IsHTMLDDA-internal-slot
+var documentAll = typeof document == 'object' && document.all;
+
+// `IsCallable` abstract operation
+// https://tc39.es/ecma262/#sec-iscallable
+// eslint-disable-next-line unicorn/no-typeof-undefined -- required for testing
+module.exports = typeof documentAll == 'undefined' && documentAll !== undefined ? function (argument) {
+ return typeof argument == 'function' || argument === documentAll;
+} : function (argument) {
+ return typeof argument == 'function';
+};
+
+
+/***/ }),
+
+/***/ 2796:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var fails = __webpack_require__(9039);
+var isCallable = __webpack_require__(4901);
+
+var replacement = /#|\.prototype\./;
+
+var isForced = function (feature, detection) {
+ var value = data[normalize(feature)];
+ return value === POLYFILL ? true
+ : value === NATIVE ? false
+ : isCallable(detection) ? fails(detection)
+ : !!detection;
+};
+
+var normalize = isForced.normalize = function (string) {
+ return String(string).replace(replacement, '.').toLowerCase();
+};
+
+var data = isForced.data = {};
+var NATIVE = isForced.NATIVE = 'N';
+var POLYFILL = isForced.POLYFILL = 'P';
+
+module.exports = isForced;
+
+
+/***/ }),
+
+/***/ 4117:
+/***/ ((module) => {
+
+
+// we can't use just `it == null` since of `document.all` special case
+// https://tc39.es/ecma262/#sec-IsHTMLDDA-internal-slot-aec
+module.exports = function (it) {
+ return it === null || it === undefined;
+};
+
+
+/***/ }),
+
+/***/ 34:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var isCallable = __webpack_require__(4901);
+
+module.exports = function (it) {
+ return typeof it == 'object' ? it !== null : isCallable(it);
+};
+
+
+/***/ }),
+
+/***/ 3925:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var isObject = __webpack_require__(34);
+
+module.exports = function (argument) {
+ return isObject(argument) || argument === null;
+};
+
+
+/***/ }),
+
+/***/ 6395:
+/***/ ((module) => {
+
+
+module.exports = false;
+
+
+/***/ }),
+
+/***/ 757:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var getBuiltIn = __webpack_require__(7751);
+var isCallable = __webpack_require__(4901);
+var isPrototypeOf = __webpack_require__(1625);
+var USE_SYMBOL_AS_UID = __webpack_require__(7040);
+
+var $Object = Object;
+
+module.exports = USE_SYMBOL_AS_UID ? function (it) {
+ return typeof it == 'symbol';
+} : function (it) {
+ var $Symbol = getBuiltIn('Symbol');
+ return isCallable($Symbol) && isPrototypeOf($Symbol.prototype, $Object(it));
+};
+
+
+/***/ }),
+
+/***/ 507:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var call = __webpack_require__(9565);
+
+module.exports = function (record, fn, ITERATOR_INSTEAD_OF_RECORD) {
+ var iterator = ITERATOR_INSTEAD_OF_RECORD ? record : record.iterator;
+ var next = record.next;
+ var step, result;
+ while (!(step = call(next, iterator)).done) {
+ result = fn(step.value);
+ if (result !== undefined) return result;
+ }
+};
+
+
+/***/ }),
+
+/***/ 2652:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var bind = __webpack_require__(6080);
+var call = __webpack_require__(9565);
+var anObject = __webpack_require__(8551);
+var tryToString = __webpack_require__(6823);
+var isArrayIteratorMethod = __webpack_require__(4209);
+var lengthOfArrayLike = __webpack_require__(6198);
+var isPrototypeOf = __webpack_require__(1625);
+var getIterator = __webpack_require__(81);
+var getIteratorMethod = __webpack_require__(851);
+var iteratorClose = __webpack_require__(9539);
+
+var $TypeError = TypeError;
+
+var Result = function (stopped, result) {
+ this.stopped = stopped;
+ this.result = result;
+};
+
+var ResultPrototype = Result.prototype;
+
+module.exports = function (iterable, unboundFunction, options) {
+ var that = options && options.that;
+ var AS_ENTRIES = !!(options && options.AS_ENTRIES);
+ var IS_RECORD = !!(options && options.IS_RECORD);
+ var IS_ITERATOR = !!(options && options.IS_ITERATOR);
+ var INTERRUPTED = !!(options && options.INTERRUPTED);
+ var fn = bind(unboundFunction, that);
+ var iterator, iterFn, index, length, result, next, step;
+
+ var stop = function (condition) {
+ if (iterator) iteratorClose(iterator, 'normal', condition);
+ return new Result(true, condition);
+ };
+
+ var callFn = function (value) {
+ if (AS_ENTRIES) {
+ anObject(value);
+ return INTERRUPTED ? fn(value[0], value[1], stop) : fn(value[0], value[1]);
+ } return INTERRUPTED ? fn(value, stop) : fn(value);
+ };
+
+ if (IS_RECORD) {
+ iterator = iterable.iterator;
+ } else if (IS_ITERATOR) {
+ iterator = iterable;
+ } else {
+ iterFn = getIteratorMethod(iterable);
+ if (!iterFn) throw new $TypeError(tryToString(iterable) + ' is not iterable');
+ // optimisation for array iterators
+ if (isArrayIteratorMethod(iterFn)) {
+ for (index = 0, length = lengthOfArrayLike(iterable); length > index; index++) {
+ result = callFn(iterable[index]);
+ if (result && isPrototypeOf(ResultPrototype, result)) return result;
+ } return new Result(false);
+ }
+ iterator = getIterator(iterable, iterFn);
+ }
+
+ next = IS_RECORD ? iterable.next : iterator.next;
+ while (!(step = call(next, iterator)).done) {
+ try {
+ result = callFn(step.value);
+ } catch (error) {
+ iteratorClose(iterator, 'throw', error);
+ }
+ if (typeof result == 'object' && result && isPrototypeOf(ResultPrototype, result)) return result;
+ } return new Result(false);
+};
+
+
+/***/ }),
+
+/***/ 9539:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var call = __webpack_require__(9565);
+var anObject = __webpack_require__(8551);
+var getMethod = __webpack_require__(5966);
+
+module.exports = function (iterator, kind, value) {
+ var innerResult, innerError;
+ anObject(iterator);
+ try {
+ innerResult = getMethod(iterator, 'return');
+ if (!innerResult) {
+ if (kind === 'throw') throw value;
+ return value;
+ }
+ innerResult = call(innerResult, iterator);
+ } catch (error) {
+ innerError = true;
+ innerResult = error;
+ }
+ if (kind === 'throw') throw value;
+ if (innerError) throw innerResult;
+ anObject(innerResult);
+ return value;
+};
+
+
+/***/ }),
+
+/***/ 9462:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var call = __webpack_require__(9565);
+var create = __webpack_require__(2360);
+var createNonEnumerableProperty = __webpack_require__(6699);
+var defineBuiltIns = __webpack_require__(6279);
+var wellKnownSymbol = __webpack_require__(8227);
+var InternalStateModule = __webpack_require__(1181);
+var getMethod = __webpack_require__(5966);
+var IteratorPrototype = (__webpack_require__(7657).IteratorPrototype);
+var createIterResultObject = __webpack_require__(2529);
+var iteratorClose = __webpack_require__(9539);
+
+var TO_STRING_TAG = wellKnownSymbol('toStringTag');
+var ITERATOR_HELPER = 'IteratorHelper';
+var WRAP_FOR_VALID_ITERATOR = 'WrapForValidIterator';
+var setInternalState = InternalStateModule.set;
+
+var createIteratorProxyPrototype = function (IS_ITERATOR) {
+ var getInternalState = InternalStateModule.getterFor(IS_ITERATOR ? WRAP_FOR_VALID_ITERATOR : ITERATOR_HELPER);
+
+ return defineBuiltIns(create(IteratorPrototype), {
+ next: function next() {
+ var state = getInternalState(this);
+ // for simplification:
+ // for `%WrapForValidIteratorPrototype%.next` our `nextHandler` returns `IterResultObject`
+ // for `%IteratorHelperPrototype%.next` - just a value
+ if (IS_ITERATOR) return state.nextHandler();
+ try {
+ var result = state.done ? undefined : state.nextHandler();
+ return createIterResultObject(result, state.done);
+ } catch (error) {
+ state.done = true;
+ throw error;
+ }
+ },
+ 'return': function () {
+ var state = getInternalState(this);
+ var iterator = state.iterator;
+ state.done = true;
+ if (IS_ITERATOR) {
+ var returnMethod = getMethod(iterator, 'return');
+ return returnMethod ? call(returnMethod, iterator) : createIterResultObject(undefined, true);
+ }
+ if (state.inner) try {
+ iteratorClose(state.inner.iterator, 'normal');
+ } catch (error) {
+ return iteratorClose(iterator, 'throw', error);
+ }
+ iteratorClose(iterator, 'normal');
+ return createIterResultObject(undefined, true);
+ }
+ });
+};
+
+var WrapForValidIteratorPrototype = createIteratorProxyPrototype(true);
+var IteratorHelperPrototype = createIteratorProxyPrototype(false);
+
+createNonEnumerableProperty(IteratorHelperPrototype, TO_STRING_TAG, 'Iterator Helper');
+
+module.exports = function (nextHandler, IS_ITERATOR) {
+ var IteratorProxy = function Iterator(record, state) {
+ if (state) {
+ state.iterator = record.iterator;
+ state.next = record.next;
+ } else state = record;
+ state.type = IS_ITERATOR ? WRAP_FOR_VALID_ITERATOR : ITERATOR_HELPER;
+ state.nextHandler = nextHandler;
+ state.counter = 0;
+ state.done = false;
+ setInternalState(this, state);
+ };
+
+ IteratorProxy.prototype = IS_ITERATOR ? WrapForValidIteratorPrototype : IteratorHelperPrototype;
+
+ return IteratorProxy;
+};
+
+
+/***/ }),
+
+/***/ 713:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var call = __webpack_require__(9565);
+var aCallable = __webpack_require__(9306);
+var anObject = __webpack_require__(8551);
+var getIteratorDirect = __webpack_require__(1767);
+var createIteratorProxy = __webpack_require__(9462);
+var callWithSafeIterationClosing = __webpack_require__(6319);
+
+var IteratorProxy = createIteratorProxy(function () {
+ var iterator = this.iterator;
+ var result = anObject(call(this.next, iterator));
+ var done = this.done = !!result.done;
+ if (!done) return callWithSafeIterationClosing(iterator, this.mapper, [result.value, this.counter++], true);
+});
+
+// `Iterator.prototype.map` method
+// https://github.com/tc39/proposal-iterator-helpers
+module.exports = function map(mapper) {
+ anObject(this);
+ aCallable(mapper);
+ return new IteratorProxy(getIteratorDirect(this), {
+ mapper: mapper
+ });
+};
+
+
+/***/ }),
+
+/***/ 7657:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var fails = __webpack_require__(9039);
+var isCallable = __webpack_require__(4901);
+var isObject = __webpack_require__(34);
+var create = __webpack_require__(2360);
+var getPrototypeOf = __webpack_require__(2787);
+var defineBuiltIn = __webpack_require__(6840);
+var wellKnownSymbol = __webpack_require__(8227);
+var IS_PURE = __webpack_require__(6395);
+
+var ITERATOR = wellKnownSymbol('iterator');
+var BUGGY_SAFARI_ITERATORS = false;
+
+// `%IteratorPrototype%` object
+// https://tc39.es/ecma262/#sec-%iteratorprototype%-object
+var IteratorPrototype, PrototypeOfArrayIteratorPrototype, arrayIterator;
+
+/* eslint-disable es/no-array-prototype-keys -- safe */
+if ([].keys) {
+ arrayIterator = [].keys();
+ // Safari 8 has buggy iterators w/o `next`
+ if (!('next' in arrayIterator)) BUGGY_SAFARI_ITERATORS = true;
+ else {
+ PrototypeOfArrayIteratorPrototype = getPrototypeOf(getPrototypeOf(arrayIterator));
+ if (PrototypeOfArrayIteratorPrototype !== Object.prototype) IteratorPrototype = PrototypeOfArrayIteratorPrototype;
+ }
+}
+
+var NEW_ITERATOR_PROTOTYPE = !isObject(IteratorPrototype) || fails(function () {
+ var test = {};
+ // FF44- legacy iterators case
+ return IteratorPrototype[ITERATOR].call(test) !== test;
+});
+
+if (NEW_ITERATOR_PROTOTYPE) IteratorPrototype = {};
+else if (IS_PURE) IteratorPrototype = create(IteratorPrototype);
+
+// `%IteratorPrototype%[@@iterator]()` method
+// https://tc39.es/ecma262/#sec-%iteratorprototype%-@@iterator
+if (!isCallable(IteratorPrototype[ITERATOR])) {
+ defineBuiltIn(IteratorPrototype, ITERATOR, function () {
+ return this;
+ });
+}
+
+module.exports = {
+ IteratorPrototype: IteratorPrototype,
+ BUGGY_SAFARI_ITERATORS: BUGGY_SAFARI_ITERATORS
+};
+
+
+/***/ }),
+
+/***/ 6269:
+/***/ ((module) => {
+
+
+module.exports = {};
+
+
+/***/ }),
+
+/***/ 6198:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var toLength = __webpack_require__(8014);
+
+// `LengthOfArrayLike` abstract operation
+// https://tc39.es/ecma262/#sec-lengthofarraylike
+module.exports = function (obj) {
+ return toLength(obj.length);
+};
+
+
+/***/ }),
+
+/***/ 283:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var uncurryThis = __webpack_require__(9504);
+var fails = __webpack_require__(9039);
+var isCallable = __webpack_require__(4901);
+var hasOwn = __webpack_require__(9297);
+var DESCRIPTORS = __webpack_require__(3724);
+var CONFIGURABLE_FUNCTION_NAME = (__webpack_require__(350).CONFIGURABLE);
+var inspectSource = __webpack_require__(3706);
+var InternalStateModule = __webpack_require__(1181);
+
+var enforceInternalState = InternalStateModule.enforce;
+var getInternalState = InternalStateModule.get;
+var $String = String;
+// eslint-disable-next-line es/no-object-defineproperty -- safe
+var defineProperty = Object.defineProperty;
+var stringSlice = uncurryThis(''.slice);
+var replace = uncurryThis(''.replace);
+var join = uncurryThis([].join);
+
+var CONFIGURABLE_LENGTH = DESCRIPTORS && !fails(function () {
+ return defineProperty(function () { /* empty */ }, 'length', { value: 8 }).length !== 8;
+});
+
+var TEMPLATE = String(String).split('String');
+
+var makeBuiltIn = module.exports = function (value, name, options) {
+ if (stringSlice($String(name), 0, 7) === 'Symbol(') {
+ name = '[' + replace($String(name), /^Symbol\(([^)]*)\).*$/, '$1') + ']';
+ }
+ if (options && options.getter) name = 'get ' + name;
+ if (options && options.setter) name = 'set ' + name;
+ if (!hasOwn(value, 'name') || (CONFIGURABLE_FUNCTION_NAME && value.name !== name)) {
+ if (DESCRIPTORS) defineProperty(value, 'name', { value: name, configurable: true });
+ else value.name = name;
+ }
+ if (CONFIGURABLE_LENGTH && options && hasOwn(options, 'arity') && value.length !== options.arity) {
+ defineProperty(value, 'length', { value: options.arity });
+ }
+ try {
+ if (options && hasOwn(options, 'constructor') && options.constructor) {
+ if (DESCRIPTORS) defineProperty(value, 'prototype', { writable: false });
+ // in V8 ~ Chrome 53, prototypes of some methods, like `Array.prototype.values`, are non-writable
+ } else if (value.prototype) value.prototype = undefined;
+ } catch (error) { /* empty */ }
+ var state = enforceInternalState(value);
+ if (!hasOwn(state, 'source')) {
+ state.source = join(TEMPLATE, typeof name == 'string' ? name : '');
+ } return value;
+};
+
+// add fake Function#toString for correct work wrapped methods / constructors with methods like LoDash isNative
+// eslint-disable-next-line no-extend-native -- required
+Function.prototype.toString = makeBuiltIn(function toString() {
+ return isCallable(this) && getInternalState(this).source || inspectSource(this);
+}, 'toString');
+
+
+/***/ }),
+
+/***/ 741:
+/***/ ((module) => {
+
+
+var ceil = Math.ceil;
+var floor = Math.floor;
+
+// `Math.trunc` method
+// https://tc39.es/ecma262/#sec-math.trunc
+// eslint-disable-next-line es/no-math-trunc -- safe
+module.exports = Math.trunc || function trunc(x) {
+ var n = +x;
+ return (n > 0 ? floor : ceil)(n);
+};
+
+
+/***/ }),
+
+/***/ 6043:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var aCallable = __webpack_require__(9306);
+
+var $TypeError = TypeError;
+
+var PromiseCapability = function (C) {
+ var resolve, reject;
+ this.promise = new C(function ($$resolve, $$reject) {
+ if (resolve !== undefined || reject !== undefined) throw new $TypeError('Bad Promise constructor');
+ resolve = $$resolve;
+ reject = $$reject;
+ });
+ this.resolve = aCallable(resolve);
+ this.reject = aCallable(reject);
+};
+
+// `NewPromiseCapability` abstract operation
+// https://tc39.es/ecma262/#sec-newpromisecapability
+module.exports.f = function (C) {
+ return new PromiseCapability(C);
+};
+
+
+/***/ }),
+
+/***/ 2603:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var toString = __webpack_require__(655);
+
+module.exports = function (argument, $default) {
+ return argument === undefined ? arguments.length < 2 ? '' : $default : toString(argument);
+};
+
+
+/***/ }),
+
+/***/ 2360:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+/* global ActiveXObject -- old IE, WSH */
+var anObject = __webpack_require__(8551);
+var definePropertiesModule = __webpack_require__(6801);
+var enumBugKeys = __webpack_require__(8727);
+var hiddenKeys = __webpack_require__(421);
+var html = __webpack_require__(397);
+var documentCreateElement = __webpack_require__(4055);
+var sharedKey = __webpack_require__(6119);
+
+var GT = '>';
+var LT = '<';
+var PROTOTYPE = 'prototype';
+var SCRIPT = 'script';
+var IE_PROTO = sharedKey('IE_PROTO');
+
+var EmptyConstructor = function () { /* empty */ };
+
+var scriptTag = function (content) {
+ return LT + SCRIPT + GT + content + LT + '/' + SCRIPT + GT;
+};
+
+// Create object with fake `null` prototype: use ActiveX Object with cleared prototype
+var NullProtoObjectViaActiveX = function (activeXDocument) {
+ activeXDocument.write(scriptTag(''));
+ activeXDocument.close();
+ var temp = activeXDocument.parentWindow.Object;
+ activeXDocument = null; // avoid memory leak
+ return temp;
+};
+
+// Create object with fake `null` prototype: use iframe Object with cleared prototype
+var NullProtoObjectViaIFrame = function () {
+ // Thrash, waste and sodomy: IE GC bug
+ var iframe = documentCreateElement('iframe');
+ var JS = 'java' + SCRIPT + ':';
+ var iframeDocument;
+ iframe.style.display = 'none';
+ html.appendChild(iframe);
+ // https://github.com/zloirock/core-js/issues/475
+ iframe.src = String(JS);
+ iframeDocument = iframe.contentWindow.document;
+ iframeDocument.open();
+ iframeDocument.write(scriptTag('document.F=Object'));
+ iframeDocument.close();
+ return iframeDocument.F;
+};
+
+// Check for document.domain and active x support
+// No need to use active x approach when document.domain is not set
+// see https://github.com/es-shims/es5-shim/issues/150
+// variation of https://github.com/kitcambridge/es5-shim/commit/4f738ac066346
+// avoid IE GC bug
+var activeXDocument;
+var NullProtoObject = function () {
+ try {
+ activeXDocument = new ActiveXObject('htmlfile');
+ } catch (error) { /* ignore */ }
+ NullProtoObject = typeof document != 'undefined'
+ ? document.domain && activeXDocument
+ ? NullProtoObjectViaActiveX(activeXDocument) // old IE
+ : NullProtoObjectViaIFrame()
+ : NullProtoObjectViaActiveX(activeXDocument); // WSH
+ var length = enumBugKeys.length;
+ while (length--) delete NullProtoObject[PROTOTYPE][enumBugKeys[length]];
+ return NullProtoObject();
+};
+
+hiddenKeys[IE_PROTO] = true;
+
+// `Object.create` method
+// https://tc39.es/ecma262/#sec-object.create
+// eslint-disable-next-line es/no-object-create -- safe
+module.exports = Object.create || function create(O, Properties) {
+ var result;
+ if (O !== null) {
+ EmptyConstructor[PROTOTYPE] = anObject(O);
+ result = new EmptyConstructor();
+ EmptyConstructor[PROTOTYPE] = null;
+ // add "__proto__" for Object.getPrototypeOf polyfill
+ result[IE_PROTO] = O;
+ } else result = NullProtoObject();
+ return Properties === undefined ? result : definePropertiesModule.f(result, Properties);
+};
+
+
+/***/ }),
+
+/***/ 6801:
+/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
+
+
+var DESCRIPTORS = __webpack_require__(3724);
+var V8_PROTOTYPE_DEFINE_BUG = __webpack_require__(8686);
+var definePropertyModule = __webpack_require__(4913);
+var anObject = __webpack_require__(8551);
+var toIndexedObject = __webpack_require__(5397);
+var objectKeys = __webpack_require__(1072);
+
+// `Object.defineProperties` method
+// https://tc39.es/ecma262/#sec-object.defineproperties
+// eslint-disable-next-line es/no-object-defineproperties -- safe
+exports.f = DESCRIPTORS && !V8_PROTOTYPE_DEFINE_BUG ? Object.defineProperties : function defineProperties(O, Properties) {
+ anObject(O);
+ var props = toIndexedObject(Properties);
+ var keys = objectKeys(Properties);
+ var length = keys.length;
+ var index = 0;
+ var key;
+ while (length > index) definePropertyModule.f(O, key = keys[index++], props[key]);
+ return O;
+};
+
+
+/***/ }),
+
+/***/ 4913:
+/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
+
+
+var DESCRIPTORS = __webpack_require__(3724);
+var IE8_DOM_DEFINE = __webpack_require__(5917);
+var V8_PROTOTYPE_DEFINE_BUG = __webpack_require__(8686);
+var anObject = __webpack_require__(8551);
+var toPropertyKey = __webpack_require__(6969);
+
+var $TypeError = TypeError;
+// eslint-disable-next-line es/no-object-defineproperty -- safe
+var $defineProperty = Object.defineProperty;
+// eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
+var $getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
+var ENUMERABLE = 'enumerable';
+var CONFIGURABLE = 'configurable';
+var WRITABLE = 'writable';
+
+// `Object.defineProperty` method
+// https://tc39.es/ecma262/#sec-object.defineproperty
+exports.f = DESCRIPTORS ? V8_PROTOTYPE_DEFINE_BUG ? function defineProperty(O, P, Attributes) {
+ anObject(O);
+ P = toPropertyKey(P);
+ anObject(Attributes);
+ if (typeof O === 'function' && P === 'prototype' && 'value' in Attributes && WRITABLE in Attributes && !Attributes[WRITABLE]) {
+ var current = $getOwnPropertyDescriptor(O, P);
+ if (current && current[WRITABLE]) {
+ O[P] = Attributes.value;
+ Attributes = {
+ configurable: CONFIGURABLE in Attributes ? Attributes[CONFIGURABLE] : current[CONFIGURABLE],
+ enumerable: ENUMERABLE in Attributes ? Attributes[ENUMERABLE] : current[ENUMERABLE],
+ writable: false
+ };
+ }
+ } return $defineProperty(O, P, Attributes);
+} : $defineProperty : function defineProperty(O, P, Attributes) {
+ anObject(O);
+ P = toPropertyKey(P);
+ anObject(Attributes);
+ if (IE8_DOM_DEFINE) try {
+ return $defineProperty(O, P, Attributes);
+ } catch (error) { /* empty */ }
+ if ('get' in Attributes || 'set' in Attributes) throw new $TypeError('Accessors not supported');
+ if ('value' in Attributes) O[P] = Attributes.value;
+ return O;
+};
+
+
+/***/ }),
+
+/***/ 7347:
+/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
+
+
+var DESCRIPTORS = __webpack_require__(3724);
+var call = __webpack_require__(9565);
+var propertyIsEnumerableModule = __webpack_require__(8773);
+var createPropertyDescriptor = __webpack_require__(6980);
+var toIndexedObject = __webpack_require__(5397);
+var toPropertyKey = __webpack_require__(6969);
+var hasOwn = __webpack_require__(9297);
+var IE8_DOM_DEFINE = __webpack_require__(5917);
+
+// eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
+var $getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
+
+// `Object.getOwnPropertyDescriptor` method
+// https://tc39.es/ecma262/#sec-object.getownpropertydescriptor
+exports.f = DESCRIPTORS ? $getOwnPropertyDescriptor : function getOwnPropertyDescriptor(O, P) {
+ O = toIndexedObject(O);
+ P = toPropertyKey(P);
+ if (IE8_DOM_DEFINE) try {
+ return $getOwnPropertyDescriptor(O, P);
+ } catch (error) { /* empty */ }
+ if (hasOwn(O, P)) return createPropertyDescriptor(!call(propertyIsEnumerableModule.f, O, P), O[P]);
+};
+
+
+/***/ }),
+
+/***/ 8480:
+/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
+
+
+var internalObjectKeys = __webpack_require__(1828);
+var enumBugKeys = __webpack_require__(8727);
+
+var hiddenKeys = enumBugKeys.concat('length', 'prototype');
+
+// `Object.getOwnPropertyNames` method
+// https://tc39.es/ecma262/#sec-object.getownpropertynames
+// eslint-disable-next-line es/no-object-getownpropertynames -- safe
+exports.f = Object.getOwnPropertyNames || function getOwnPropertyNames(O) {
+ return internalObjectKeys(O, hiddenKeys);
+};
+
+
+/***/ }),
+
+/***/ 3717:
+/***/ ((__unused_webpack_module, exports) => {
+
+
+// eslint-disable-next-line es/no-object-getownpropertysymbols -- safe
+exports.f = Object.getOwnPropertySymbols;
+
+
+/***/ }),
+
+/***/ 2787:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var hasOwn = __webpack_require__(9297);
+var isCallable = __webpack_require__(4901);
+var toObject = __webpack_require__(8981);
+var sharedKey = __webpack_require__(6119);
+var CORRECT_PROTOTYPE_GETTER = __webpack_require__(2211);
+
+var IE_PROTO = sharedKey('IE_PROTO');
+var $Object = Object;
+var ObjectPrototype = $Object.prototype;
+
+// `Object.getPrototypeOf` method
+// https://tc39.es/ecma262/#sec-object.getprototypeof
+// eslint-disable-next-line es/no-object-getprototypeof -- safe
+module.exports = CORRECT_PROTOTYPE_GETTER ? $Object.getPrototypeOf : function (O) {
+ var object = toObject(O);
+ if (hasOwn(object, IE_PROTO)) return object[IE_PROTO];
+ var constructor = object.constructor;
+ if (isCallable(constructor) && object instanceof constructor) {
+ return constructor.prototype;
+ } return object instanceof $Object ? ObjectPrototype : null;
+};
+
+
+/***/ }),
+
+/***/ 1625:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var uncurryThis = __webpack_require__(9504);
+
+module.exports = uncurryThis({}.isPrototypeOf);
+
+
+/***/ }),
+
+/***/ 1828:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var uncurryThis = __webpack_require__(9504);
+var hasOwn = __webpack_require__(9297);
+var toIndexedObject = __webpack_require__(5397);
+var indexOf = (__webpack_require__(9617).indexOf);
+var hiddenKeys = __webpack_require__(421);
+
+var push = uncurryThis([].push);
+
+module.exports = function (object, names) {
+ var O = toIndexedObject(object);
+ var i = 0;
+ var result = [];
+ var key;
+ for (key in O) !hasOwn(hiddenKeys, key) && hasOwn(O, key) && push(result, key);
+ // Don't enum bug & hidden keys
+ while (names.length > i) if (hasOwn(O, key = names[i++])) {
+ ~indexOf(result, key) || push(result, key);
+ }
+ return result;
+};
+
+
+/***/ }),
+
+/***/ 1072:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var internalObjectKeys = __webpack_require__(1828);
+var enumBugKeys = __webpack_require__(8727);
+
+// `Object.keys` method
+// https://tc39.es/ecma262/#sec-object.keys
+// eslint-disable-next-line es/no-object-keys -- safe
+module.exports = Object.keys || function keys(O) {
+ return internalObjectKeys(O, enumBugKeys);
+};
+
+
+/***/ }),
+
+/***/ 8773:
+/***/ ((__unused_webpack_module, exports) => {
+
+
+var $propertyIsEnumerable = {}.propertyIsEnumerable;
+// eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
+var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
+
+// Nashorn ~ JDK8 bug
+var NASHORN_BUG = getOwnPropertyDescriptor && !$propertyIsEnumerable.call({ 1: 2 }, 1);
+
+// `Object.prototype.propertyIsEnumerable` method implementation
+// https://tc39.es/ecma262/#sec-object.prototype.propertyisenumerable
+exports.f = NASHORN_BUG ? function propertyIsEnumerable(V) {
+ var descriptor = getOwnPropertyDescriptor(this, V);
+ return !!descriptor && descriptor.enumerable;
+} : $propertyIsEnumerable;
+
+
+/***/ }),
+
+/***/ 2967:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+/* eslint-disable no-proto -- safe */
+var uncurryThisAccessor = __webpack_require__(6706);
+var isObject = __webpack_require__(34);
+var requireObjectCoercible = __webpack_require__(7750);
+var aPossiblePrototype = __webpack_require__(3506);
+
+// `Object.setPrototypeOf` method
+// https://tc39.es/ecma262/#sec-object.setprototypeof
+// Works with __proto__ only. Old v8 can't work with null proto objects.
+// eslint-disable-next-line es/no-object-setprototypeof -- safe
+module.exports = Object.setPrototypeOf || ('__proto__' in {} ? function () {
+ var CORRECT_SETTER = false;
+ var test = {};
+ var setter;
+ try {
+ setter = uncurryThisAccessor(Object.prototype, '__proto__', 'set');
+ setter(test, []);
+ CORRECT_SETTER = test instanceof Array;
+ } catch (error) { /* empty */ }
+ return function setPrototypeOf(O, proto) {
+ requireObjectCoercible(O);
+ aPossiblePrototype(proto);
+ if (!isObject(O)) return O;
+ if (CORRECT_SETTER) setter(O, proto);
+ else O.__proto__ = proto;
+ return O;
+ };
+}() : undefined);
+
+
+/***/ }),
+
+/***/ 4270:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var call = __webpack_require__(9565);
+var isCallable = __webpack_require__(4901);
+var isObject = __webpack_require__(34);
+
+var $TypeError = TypeError;
+
+// `OrdinaryToPrimitive` abstract operation
+// https://tc39.es/ecma262/#sec-ordinarytoprimitive
+module.exports = function (input, pref) {
+ var fn, val;
+ if (pref === 'string' && isCallable(fn = input.toString) && !isObject(val = call(fn, input))) return val;
+ if (isCallable(fn = input.valueOf) && !isObject(val = call(fn, input))) return val;
+ if (pref !== 'string' && isCallable(fn = input.toString) && !isObject(val = call(fn, input))) return val;
+ throw new $TypeError("Can't convert object to primitive value");
+};
+
+
+/***/ }),
+
+/***/ 5031:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var getBuiltIn = __webpack_require__(7751);
+var uncurryThis = __webpack_require__(9504);
+var getOwnPropertyNamesModule = __webpack_require__(8480);
+var getOwnPropertySymbolsModule = __webpack_require__(3717);
+var anObject = __webpack_require__(8551);
+
+var concat = uncurryThis([].concat);
+
+// all object keys, includes non-enumerable and symbols
+module.exports = getBuiltIn('Reflect', 'ownKeys') || function ownKeys(it) {
+ var keys = getOwnPropertyNamesModule.f(anObject(it));
+ var getOwnPropertySymbols = getOwnPropertySymbolsModule.f;
+ return getOwnPropertySymbols ? concat(keys, getOwnPropertySymbols(it)) : keys;
+};
+
+
+/***/ }),
+
+/***/ 7979:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var anObject = __webpack_require__(8551);
+
+// `RegExp.prototype.flags` getter implementation
+// https://tc39.es/ecma262/#sec-get-regexp.prototype.flags
+module.exports = function () {
+ var that = anObject(this);
+ var result = '';
+ if (that.hasIndices) result += 'd';
+ if (that.global) result += 'g';
+ if (that.ignoreCase) result += 'i';
+ if (that.multiline) result += 'm';
+ if (that.dotAll) result += 's';
+ if (that.unicode) result += 'u';
+ if (that.unicodeSets) result += 'v';
+ if (that.sticky) result += 'y';
+ return result;
+};
+
+
+/***/ }),
+
+/***/ 7750:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var isNullOrUndefined = __webpack_require__(4117);
+
+var $TypeError = TypeError;
+
+// `RequireObjectCoercible` abstract operation
+// https://tc39.es/ecma262/#sec-requireobjectcoercible
+module.exports = function (it) {
+ if (isNullOrUndefined(it)) throw new $TypeError("Can't call method on " + it);
+ return it;
+};
+
+
+/***/ }),
+
+/***/ 9286:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var SetHelpers = __webpack_require__(4402);
+var iterate = __webpack_require__(8469);
+
+var Set = SetHelpers.Set;
+var add = SetHelpers.add;
+
+module.exports = function (set) {
+ var result = new Set();
+ iterate(set, function (it) {
+ add(result, it);
+ });
+ return result;
+};
+
+
+/***/ }),
+
+/***/ 3440:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var aSet = __webpack_require__(7080);
+var SetHelpers = __webpack_require__(4402);
+var clone = __webpack_require__(9286);
+var size = __webpack_require__(5170);
+var getSetRecord = __webpack_require__(3789);
+var iterateSet = __webpack_require__(8469);
+var iterateSimple = __webpack_require__(507);
+
+var has = SetHelpers.has;
+var remove = SetHelpers.remove;
+
+// `Set.prototype.difference` method
+// https://github.com/tc39/proposal-set-methods
+module.exports = function difference(other) {
+ var O = aSet(this);
+ var otherRec = getSetRecord(other);
+ var result = clone(O);
+ if (size(O) <= otherRec.size) iterateSet(O, function (e) {
+ if (otherRec.includes(e)) remove(result, e);
+ });
+ else iterateSimple(otherRec.getIterator(), function (e) {
+ if (has(O, e)) remove(result, e);
+ });
+ return result;
+};
+
+
+/***/ }),
+
+/***/ 4402:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var uncurryThis = __webpack_require__(9504);
+
+// eslint-disable-next-line es/no-set -- safe
+var SetPrototype = Set.prototype;
+
+module.exports = {
+ // eslint-disable-next-line es/no-set -- safe
+ Set: Set,
+ add: uncurryThis(SetPrototype.add),
+ has: uncurryThis(SetPrototype.has),
+ remove: uncurryThis(SetPrototype['delete']),
+ proto: SetPrototype
+};
+
+
+/***/ }),
+
+/***/ 8750:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var aSet = __webpack_require__(7080);
+var SetHelpers = __webpack_require__(4402);
+var size = __webpack_require__(5170);
+var getSetRecord = __webpack_require__(3789);
+var iterateSet = __webpack_require__(8469);
+var iterateSimple = __webpack_require__(507);
+
+var Set = SetHelpers.Set;
+var add = SetHelpers.add;
+var has = SetHelpers.has;
+
+// `Set.prototype.intersection` method
+// https://github.com/tc39/proposal-set-methods
+module.exports = function intersection(other) {
+ var O = aSet(this);
+ var otherRec = getSetRecord(other);
+ var result = new Set();
+
+ if (size(O) > otherRec.size) {
+ iterateSimple(otherRec.getIterator(), function (e) {
+ if (has(O, e)) add(result, e);
+ });
+ } else {
+ iterateSet(O, function (e) {
+ if (otherRec.includes(e)) add(result, e);
+ });
+ }
+
+ return result;
+};
+
+
+/***/ }),
+
+/***/ 4449:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var aSet = __webpack_require__(7080);
+var has = (__webpack_require__(4402).has);
+var size = __webpack_require__(5170);
+var getSetRecord = __webpack_require__(3789);
+var iterateSet = __webpack_require__(8469);
+var iterateSimple = __webpack_require__(507);
+var iteratorClose = __webpack_require__(9539);
+
+// `Set.prototype.isDisjointFrom` method
+// https://tc39.github.io/proposal-set-methods/#Set.prototype.isDisjointFrom
+module.exports = function isDisjointFrom(other) {
+ var O = aSet(this);
+ var otherRec = getSetRecord(other);
+ if (size(O) <= otherRec.size) return iterateSet(O, function (e) {
+ if (otherRec.includes(e)) return false;
+ }, true) !== false;
+ var iterator = otherRec.getIterator();
+ return iterateSimple(iterator, function (e) {
+ if (has(O, e)) return iteratorClose(iterator, 'normal', false);
+ }) !== false;
+};
+
+
+/***/ }),
+
+/***/ 3838:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var aSet = __webpack_require__(7080);
+var size = __webpack_require__(5170);
+var iterate = __webpack_require__(8469);
+var getSetRecord = __webpack_require__(3789);
+
+// `Set.prototype.isSubsetOf` method
+// https://tc39.github.io/proposal-set-methods/#Set.prototype.isSubsetOf
+module.exports = function isSubsetOf(other) {
+ var O = aSet(this);
+ var otherRec = getSetRecord(other);
+ if (size(O) > otherRec.size) return false;
+ return iterate(O, function (e) {
+ if (!otherRec.includes(e)) return false;
+ }, true) !== false;
+};
+
+
+/***/ }),
+
+/***/ 8527:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var aSet = __webpack_require__(7080);
+var has = (__webpack_require__(4402).has);
+var size = __webpack_require__(5170);
+var getSetRecord = __webpack_require__(3789);
+var iterateSimple = __webpack_require__(507);
+var iteratorClose = __webpack_require__(9539);
+
+// `Set.prototype.isSupersetOf` method
+// https://tc39.github.io/proposal-set-methods/#Set.prototype.isSupersetOf
+module.exports = function isSupersetOf(other) {
+ var O = aSet(this);
+ var otherRec = getSetRecord(other);
+ if (size(O) < otherRec.size) return false;
+ var iterator = otherRec.getIterator();
+ return iterateSimple(iterator, function (e) {
+ if (!has(O, e)) return iteratorClose(iterator, 'normal', false);
+ }) !== false;
+};
+
+
+/***/ }),
+
+/***/ 8469:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var uncurryThis = __webpack_require__(9504);
+var iterateSimple = __webpack_require__(507);
+var SetHelpers = __webpack_require__(4402);
+
+var Set = SetHelpers.Set;
+var SetPrototype = SetHelpers.proto;
+var forEach = uncurryThis(SetPrototype.forEach);
+var keys = uncurryThis(SetPrototype.keys);
+var next = keys(new Set()).next;
+
+module.exports = function (set, fn, interruptible) {
+ return interruptible ? iterateSimple({ iterator: keys(set), next: next }, fn) : forEach(set, fn);
+};
+
+
+/***/ }),
+
+/***/ 4916:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var getBuiltIn = __webpack_require__(7751);
+
+var createSetLike = function (size) {
+ return {
+ size: size,
+ has: function () {
+ return false;
+ },
+ keys: function () {
+ return {
+ next: function () {
+ return { done: true };
+ }
+ };
+ }
+ };
+};
+
+module.exports = function (name) {
+ var Set = getBuiltIn('Set');
+ try {
+ new Set()[name](createSetLike(0));
+ try {
+ // late spec change, early WebKit ~ Safari 17.0 beta implementation does not pass it
+ // https://github.com/tc39/proposal-set-methods/pull/88
+ new Set()[name](createSetLike(-1));
+ return false;
+ } catch (error2) {
+ return true;
+ }
+ } catch (error) {
+ return false;
+ }
+};
+
+
+/***/ }),
+
+/***/ 5170:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var uncurryThisAccessor = __webpack_require__(6706);
+var SetHelpers = __webpack_require__(4402);
+
+module.exports = uncurryThisAccessor(SetHelpers.proto, 'size', 'get') || function (set) {
+ return set.size;
+};
+
+
+/***/ }),
+
+/***/ 3650:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var aSet = __webpack_require__(7080);
+var SetHelpers = __webpack_require__(4402);
+var clone = __webpack_require__(9286);
+var getSetRecord = __webpack_require__(3789);
+var iterateSimple = __webpack_require__(507);
+
+var add = SetHelpers.add;
+var has = SetHelpers.has;
+var remove = SetHelpers.remove;
+
+// `Set.prototype.symmetricDifference` method
+// https://github.com/tc39/proposal-set-methods
+module.exports = function symmetricDifference(other) {
+ var O = aSet(this);
+ var keysIter = getSetRecord(other).getIterator();
+ var result = clone(O);
+ iterateSimple(keysIter, function (e) {
+ if (has(O, e)) remove(result, e);
+ else add(result, e);
+ });
+ return result;
+};
+
+
+/***/ }),
+
+/***/ 4204:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var aSet = __webpack_require__(7080);
+var add = (__webpack_require__(4402).add);
+var clone = __webpack_require__(9286);
+var getSetRecord = __webpack_require__(3789);
+var iterateSimple = __webpack_require__(507);
+
+// `Set.prototype.union` method
+// https://github.com/tc39/proposal-set-methods
+module.exports = function union(other) {
+ var O = aSet(this);
+ var keysIter = getSetRecord(other).getIterator();
+ var result = clone(O);
+ iterateSimple(keysIter, function (it) {
+ add(result, it);
+ });
+ return result;
+};
+
+
+/***/ }),
+
+/***/ 6119:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var shared = __webpack_require__(5745);
+var uid = __webpack_require__(3392);
+
+var keys = shared('keys');
+
+module.exports = function (key) {
+ return keys[key] || (keys[key] = uid(key));
+};
+
+
+/***/ }),
+
+/***/ 7629:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var IS_PURE = __webpack_require__(6395);
+var globalThis = __webpack_require__(4475);
+var defineGlobalProperty = __webpack_require__(9433);
+
+var SHARED = '__core-js_shared__';
+var store = module.exports = globalThis[SHARED] || defineGlobalProperty(SHARED, {});
+
+(store.versions || (store.versions = [])).push({
+ version: '3.37.1',
+ mode: IS_PURE ? 'pure' : 'global',
+ copyright: '© 2014-2024 Denis Pushkarev (zloirock.ru)',
+ license: 'https://github.com/zloirock/core-js/blob/v3.37.1/LICENSE',
+ source: 'https://github.com/zloirock/core-js'
+});
+
+
+/***/ }),
+
+/***/ 5745:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var store = __webpack_require__(7629);
+
+module.exports = function (key, value) {
+ return store[key] || (store[key] = value || {});
+};
+
+
+/***/ }),
+
+/***/ 1548:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var global = __webpack_require__(4475);
+var fails = __webpack_require__(9039);
+var V8 = __webpack_require__(7388);
+var IS_BROWSER = __webpack_require__(7290);
+var IS_DENO = __webpack_require__(516);
+var IS_NODE = __webpack_require__(9088);
+
+var structuredClone = global.structuredClone;
+
+module.exports = !!structuredClone && !fails(function () {
+ // prevent V8 ArrayBufferDetaching protector cell invalidation and performance degradation
+ // https://github.com/zloirock/core-js/issues/679
+ if ((IS_DENO && V8 > 92) || (IS_NODE && V8 > 94) || (IS_BROWSER && V8 > 97)) return false;
+ var buffer = new ArrayBuffer(8);
+ var clone = structuredClone(buffer, { transfer: [buffer] });
+ return buffer.byteLength !== 0 || clone.byteLength !== 8;
+});
+
+
+/***/ }),
+
+/***/ 4495:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+/* eslint-disable es/no-symbol -- required for testing */
+var V8_VERSION = __webpack_require__(7388);
+var fails = __webpack_require__(9039);
+var global = __webpack_require__(4475);
+
+var $String = global.String;
+
+// eslint-disable-next-line es/no-object-getownpropertysymbols -- required for testing
+module.exports = !!Object.getOwnPropertySymbols && !fails(function () {
+ var symbol = Symbol('symbol detection');
+ // Chrome 38 Symbol has incorrect toString conversion
+ // `get-own-property-symbols` polyfill symbols converted to object are not Symbol instances
+ // nb: Do not call `String` directly to avoid this being optimized out to `symbol+''` which will,
+ // of course, fail.
+ return !$String(symbol) || !(Object(symbol) instanceof Symbol) ||
+ // Chrome 38-40 symbols are not inherited from DOM collections prototypes to instances
+ !Symbol.sham && V8_VERSION && V8_VERSION < 41;
+});
+
+
+/***/ }),
+
+/***/ 5610:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var toIntegerOrInfinity = __webpack_require__(1291);
+
+var max = Math.max;
+var min = Math.min;
+
+// Helper for a popular repeating case of the spec:
+// Let integer be ? ToInteger(index).
+// If integer < 0, let result be max((length + integer), 0); else let result be min(integer, length).
+module.exports = function (index, length) {
+ var integer = toIntegerOrInfinity(index);
+ return integer < 0 ? max(integer + length, 0) : min(integer, length);
+};
+
+
+/***/ }),
+
+/***/ 5854:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var toPrimitive = __webpack_require__(2777);
+
+var $TypeError = TypeError;
+
+// `ToBigInt` abstract operation
+// https://tc39.es/ecma262/#sec-tobigint
+module.exports = function (argument) {
+ var prim = toPrimitive(argument, 'number');
+ if (typeof prim == 'number') throw new $TypeError("Can't convert number to bigint");
+ // eslint-disable-next-line es/no-bigint -- safe
+ return BigInt(prim);
+};
+
+
+/***/ }),
+
+/***/ 7696:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var toIntegerOrInfinity = __webpack_require__(1291);
+var toLength = __webpack_require__(8014);
+
+var $RangeError = RangeError;
+
+// `ToIndex` abstract operation
+// https://tc39.es/ecma262/#sec-toindex
+module.exports = function (it) {
+ if (it === undefined) return 0;
+ var number = toIntegerOrInfinity(it);
+ var length = toLength(number);
+ if (number !== length) throw new $RangeError('Wrong length or index');
+ return length;
+};
+
+
+/***/ }),
+
+/***/ 5397:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+// toObject with fallback for non-array-like ES3 strings
+var IndexedObject = __webpack_require__(7055);
+var requireObjectCoercible = __webpack_require__(7750);
+
+module.exports = function (it) {
+ return IndexedObject(requireObjectCoercible(it));
+};
+
+
+/***/ }),
+
+/***/ 1291:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var trunc = __webpack_require__(741);
+
+// `ToIntegerOrInfinity` abstract operation
+// https://tc39.es/ecma262/#sec-tointegerorinfinity
+module.exports = function (argument) {
+ var number = +argument;
+ // eslint-disable-next-line no-self-compare -- NaN check
+ return number !== number || number === 0 ? 0 : trunc(number);
+};
+
+
+/***/ }),
+
+/***/ 8014:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var toIntegerOrInfinity = __webpack_require__(1291);
+
+var min = Math.min;
+
+// `ToLength` abstract operation
+// https://tc39.es/ecma262/#sec-tolength
+module.exports = function (argument) {
+ var len = toIntegerOrInfinity(argument);
+ return len > 0 ? min(len, 0x1FFFFFFFFFFFFF) : 0; // 2 ** 53 - 1 == 9007199254740991
+};
+
+
+/***/ }),
+
+/***/ 8981:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var requireObjectCoercible = __webpack_require__(7750);
+
+var $Object = Object;
+
+// `ToObject` abstract operation
+// https://tc39.es/ecma262/#sec-toobject
+module.exports = function (argument) {
+ return $Object(requireObjectCoercible(argument));
+};
+
+
+/***/ }),
+
+/***/ 2777:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var call = __webpack_require__(9565);
+var isObject = __webpack_require__(34);
+var isSymbol = __webpack_require__(757);
+var getMethod = __webpack_require__(5966);
+var ordinaryToPrimitive = __webpack_require__(4270);
+var wellKnownSymbol = __webpack_require__(8227);
+
+var $TypeError = TypeError;
+var TO_PRIMITIVE = wellKnownSymbol('toPrimitive');
+
+// `ToPrimitive` abstract operation
+// https://tc39.es/ecma262/#sec-toprimitive
+module.exports = function (input, pref) {
+ if (!isObject(input) || isSymbol(input)) return input;
+ var exoticToPrim = getMethod(input, TO_PRIMITIVE);
+ var result;
+ if (exoticToPrim) {
+ if (pref === undefined) pref = 'default';
+ result = call(exoticToPrim, input, pref);
+ if (!isObject(result) || isSymbol(result)) return result;
+ throw new $TypeError("Can't convert object to primitive value");
+ }
+ if (pref === undefined) pref = 'number';
+ return ordinaryToPrimitive(input, pref);
+};
+
+
+/***/ }),
+
+/***/ 6969:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var toPrimitive = __webpack_require__(2777);
+var isSymbol = __webpack_require__(757);
+
+// `ToPropertyKey` abstract operation
+// https://tc39.es/ecma262/#sec-topropertykey
+module.exports = function (argument) {
+ var key = toPrimitive(argument, 'string');
+ return isSymbol(key) ? key : key + '';
+};
+
+
+/***/ }),
+
+/***/ 2140:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var wellKnownSymbol = __webpack_require__(8227);
+
+var TO_STRING_TAG = wellKnownSymbol('toStringTag');
+var test = {};
+
+test[TO_STRING_TAG] = 'z';
+
+module.exports = String(test) === '[object z]';
+
+
+/***/ }),
+
+/***/ 655:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var classof = __webpack_require__(6955);
+
+var $String = String;
+
+module.exports = function (argument) {
+ if (classof(argument) === 'Symbol') throw new TypeError('Cannot convert a Symbol value to a string');
+ return $String(argument);
+};
+
+
+/***/ }),
+
+/***/ 9714:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var IS_NODE = __webpack_require__(9088);
+
+module.exports = function (name) {
+ try {
+ // eslint-disable-next-line no-new-func -- safe
+ if (IS_NODE) return Function('return require("' + name + '")')();
+ } catch (error) { /* empty */ }
+};
+
+
+/***/ }),
+
+/***/ 6823:
+/***/ ((module) => {
+
+
+var $String = String;
+
+module.exports = function (argument) {
+ try {
+ return $String(argument);
+ } catch (error) {
+ return 'Object';
+ }
+};
+
+
+/***/ }),
+
+/***/ 3392:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var uncurryThis = __webpack_require__(9504);
+
+var id = 0;
+var postfix = Math.random();
+var toString = uncurryThis(1.0.toString);
+
+module.exports = function (key) {
+ return 'Symbol(' + (key === undefined ? '' : key) + ')_' + toString(++id + postfix, 36);
+};
+
+
+/***/ }),
+
+/***/ 7040:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+/* eslint-disable es/no-symbol -- required for testing */
+var NATIVE_SYMBOL = __webpack_require__(4495);
+
+module.exports = NATIVE_SYMBOL
+ && !Symbol.sham
+ && typeof Symbol.iterator == 'symbol';
+
+
+/***/ }),
+
+/***/ 8686:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var DESCRIPTORS = __webpack_require__(3724);
+var fails = __webpack_require__(9039);
+
+// V8 ~ Chrome 36-
+// https://bugs.chromium.org/p/v8/issues/detail?id=3334
+module.exports = DESCRIPTORS && fails(function () {
+ // eslint-disable-next-line es/no-object-defineproperty -- required for testing
+ return Object.defineProperty(function () { /* empty */ }, 'prototype', {
+ value: 42,
+ writable: false
+ }).prototype !== 42;
+});
+
+
+/***/ }),
+
+/***/ 2812:
+/***/ ((module) => {
+
+
+var $TypeError = TypeError;
+
+module.exports = function (passed, required) {
+ if (passed < required) throw new $TypeError('Not enough arguments');
+ return passed;
+};
+
+
+/***/ }),
+
+/***/ 8622:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var global = __webpack_require__(4475);
+var isCallable = __webpack_require__(4901);
+
+var WeakMap = global.WeakMap;
+
+module.exports = isCallable(WeakMap) && /native code/.test(String(WeakMap));
+
+
+/***/ }),
+
+/***/ 8227:
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var global = __webpack_require__(4475);
+var shared = __webpack_require__(5745);
+var hasOwn = __webpack_require__(9297);
+var uid = __webpack_require__(3392);
+var NATIVE_SYMBOL = __webpack_require__(4495);
+var USE_SYMBOL_AS_UID = __webpack_require__(7040);
+
+var Symbol = global.Symbol;
+var WellKnownSymbolsStore = shared('wks');
+var createWellKnownSymbol = USE_SYMBOL_AS_UID ? Symbol['for'] || Symbol : Symbol && Symbol.withoutSetter || uid;
+
+module.exports = function (name) {
+ if (!hasOwn(WellKnownSymbolsStore, name)) {
+ WellKnownSymbolsStore[name] = NATIVE_SYMBOL && hasOwn(Symbol, name)
+ ? Symbol[name]
+ : createWellKnownSymbol('Symbol.' + name);
+ } return WellKnownSymbolsStore[name];
+};
+
+
+/***/ }),
+
+/***/ 6573:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var DESCRIPTORS = __webpack_require__(3724);
+var defineBuiltInAccessor = __webpack_require__(2106);
+var isDetached = __webpack_require__(3238);
+
+var ArrayBufferPrototype = ArrayBuffer.prototype;
+
+if (DESCRIPTORS && !('detached' in ArrayBufferPrototype)) {
+ defineBuiltInAccessor(ArrayBufferPrototype, 'detached', {
+ configurable: true,
+ get: function detached() {
+ return isDetached(this);
+ }
+ });
+}
+
+
+/***/ }),
+
+/***/ 7936:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var $ = __webpack_require__(6518);
+var $transfer = __webpack_require__(5636);
+
+// `ArrayBuffer.prototype.transferToFixedLength` method
+// https://tc39.es/proposal-arraybuffer-transfer/#sec-arraybuffer.prototype.transfertofixedlength
+if ($transfer) $({ target: 'ArrayBuffer', proto: true }, {
+ transferToFixedLength: function transferToFixedLength() {
+ return $transfer(this, arguments.length ? arguments[0] : undefined, false);
+ }
+});
+
+
+/***/ }),
+
+/***/ 8100:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var $ = __webpack_require__(6518);
+var $transfer = __webpack_require__(5636);
+
+// `ArrayBuffer.prototype.transfer` method
+// https://tc39.es/proposal-arraybuffer-transfer/#sec-arraybuffer.prototype.transfer
+if ($transfer) $({ target: 'ArrayBuffer', proto: true }, {
+ transfer: function transfer() {
+ return $transfer(this, arguments.length ? arguments[0] : undefined, true);
+ }
+});
+
+
+/***/ }),
+
+/***/ 4114:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var $ = __webpack_require__(6518);
+var toObject = __webpack_require__(8981);
+var lengthOfArrayLike = __webpack_require__(6198);
+var setArrayLength = __webpack_require__(4527);
+var doesNotExceedSafeInteger = __webpack_require__(6837);
+var fails = __webpack_require__(9039);
+
+var INCORRECT_TO_LENGTH = fails(function () {
+ return [].push.call({ length: 0x100000000 }, 1) !== 4294967297;
+});
+
+// V8 <= 121 and Safari <= 15.4; FF < 23 throws InternalError
+// https://bugs.chromium.org/p/v8/issues/detail?id=12681
+var properErrorOnNonWritableLength = function () {
+ try {
+ // eslint-disable-next-line es/no-object-defineproperty -- safe
+ Object.defineProperty([], 'length', { writable: false }).push();
+ } catch (error) {
+ return error instanceof TypeError;
+ }
+};
+
+var FORCED = INCORRECT_TO_LENGTH || !properErrorOnNonWritableLength();
+
+// `Array.prototype.push` method
+// https://tc39.es/ecma262/#sec-array.prototype.push
+$({ target: 'Array', proto: true, arity: 1, forced: FORCED }, {
+ // eslint-disable-next-line no-unused-vars -- required for `.length`
+ push: function push(item) {
+ var O = toObject(this);
+ var len = lengthOfArrayLike(O);
+ var argCount = arguments.length;
+ doesNotExceedSafeInteger(len + argCount);
+ for (var i = 0; i < argCount; i++) {
+ O[len] = arguments[i];
+ len++;
+ }
+ setArrayLength(O, len);
+ return len;
+ }
+});
+
+
+/***/ }),
+
+/***/ 4628:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var $ = __webpack_require__(6518);
+var newPromiseCapabilityModule = __webpack_require__(6043);
+
+// `Promise.withResolvers` method
+// https://github.com/tc39/proposal-promise-with-resolvers
+$({ target: 'Promise', stat: true }, {
+ withResolvers: function withResolvers() {
+ var promiseCapability = newPromiseCapabilityModule.f(this);
+ return {
+ promise: promiseCapability.promise,
+ resolve: promiseCapability.resolve,
+ reject: promiseCapability.reject
+ };
+ }
+});
+
+
+/***/ }),
+
+/***/ 9479:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var global = __webpack_require__(4475);
+var DESCRIPTORS = __webpack_require__(3724);
+var defineBuiltInAccessor = __webpack_require__(2106);
+var regExpFlags = __webpack_require__(7979);
+var fails = __webpack_require__(9039);
+
+// babel-minify and Closure Compiler transpiles RegExp('.', 'd') -> /./d and it causes SyntaxError
+var RegExp = global.RegExp;
+var RegExpPrototype = RegExp.prototype;
+
+var FORCED = DESCRIPTORS && fails(function () {
+ var INDICES_SUPPORT = true;
+ try {
+ RegExp('.', 'd');
+ } catch (error) {
+ INDICES_SUPPORT = false;
+ }
+
+ var O = {};
+ // modern V8 bug
+ var calls = '';
+ var expected = INDICES_SUPPORT ? 'dgimsy' : 'gimsy';
+
+ var addGetter = function (key, chr) {
+ // eslint-disable-next-line es/no-object-defineproperty -- safe
+ Object.defineProperty(O, key, { get: function () {
+ calls += chr;
+ return true;
+ } });
+ };
+
+ var pairs = {
+ dotAll: 's',
+ global: 'g',
+ ignoreCase: 'i',
+ multiline: 'm',
+ sticky: 'y'
+ };
+
+ if (INDICES_SUPPORT) pairs.hasIndices = 'd';
+
+ for (var key in pairs) addGetter(key, pairs[key]);
+
+ // eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
+ var result = Object.getOwnPropertyDescriptor(RegExpPrototype, 'flags').get.call(O);
+
+ return result !== expected || calls !== expected;
+});
+
+// `RegExp.prototype.flags` getter
+// https://tc39.es/ecma262/#sec-get-regexp.prototype.flags
+if (FORCED) defineBuiltInAccessor(RegExpPrototype, 'flags', {
+ configurable: true,
+ get: regExpFlags
+});
+
+
+/***/ }),
+
+/***/ 7642:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var $ = __webpack_require__(6518);
+var difference = __webpack_require__(3440);
+var setMethodAcceptSetLike = __webpack_require__(4916);
+
+// `Set.prototype.difference` method
+// https://github.com/tc39/proposal-set-methods
+$({ target: 'Set', proto: true, real: true, forced: !setMethodAcceptSetLike('difference') }, {
+ difference: difference
+});
+
+
+/***/ }),
+
+/***/ 8004:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var $ = __webpack_require__(6518);
+var fails = __webpack_require__(9039);
+var intersection = __webpack_require__(8750);
+var setMethodAcceptSetLike = __webpack_require__(4916);
+
+var INCORRECT = !setMethodAcceptSetLike('intersection') || fails(function () {
+ // eslint-disable-next-line es/no-array-from, es/no-set -- testing
+ return String(Array.from(new Set([1, 2, 3]).intersection(new Set([3, 2])))) !== '3,2';
+});
+
+// `Set.prototype.intersection` method
+// https://github.com/tc39/proposal-set-methods
+$({ target: 'Set', proto: true, real: true, forced: INCORRECT }, {
+ intersection: intersection
+});
+
+
+/***/ }),
+
+/***/ 3853:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var $ = __webpack_require__(6518);
+var isDisjointFrom = __webpack_require__(4449);
+var setMethodAcceptSetLike = __webpack_require__(4916);
+
+// `Set.prototype.isDisjointFrom` method
+// https://github.com/tc39/proposal-set-methods
+$({ target: 'Set', proto: true, real: true, forced: !setMethodAcceptSetLike('isDisjointFrom') }, {
+ isDisjointFrom: isDisjointFrom
+});
+
+
+/***/ }),
+
+/***/ 5876:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var $ = __webpack_require__(6518);
+var isSubsetOf = __webpack_require__(3838);
+var setMethodAcceptSetLike = __webpack_require__(4916);
+
+// `Set.prototype.isSubsetOf` method
+// https://github.com/tc39/proposal-set-methods
+$({ target: 'Set', proto: true, real: true, forced: !setMethodAcceptSetLike('isSubsetOf') }, {
+ isSubsetOf: isSubsetOf
+});
+
+
+/***/ }),
+
+/***/ 2475:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var $ = __webpack_require__(6518);
+var isSupersetOf = __webpack_require__(8527);
+var setMethodAcceptSetLike = __webpack_require__(4916);
+
+// `Set.prototype.isSupersetOf` method
+// https://github.com/tc39/proposal-set-methods
+$({ target: 'Set', proto: true, real: true, forced: !setMethodAcceptSetLike('isSupersetOf') }, {
+ isSupersetOf: isSupersetOf
+});
+
+
+/***/ }),
+
+/***/ 5024:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var $ = __webpack_require__(6518);
+var symmetricDifference = __webpack_require__(3650);
+var setMethodAcceptSetLike = __webpack_require__(4916);
+
+// `Set.prototype.symmetricDifference` method
+// https://github.com/tc39/proposal-set-methods
+$({ target: 'Set', proto: true, real: true, forced: !setMethodAcceptSetLike('symmetricDifference') }, {
+ symmetricDifference: symmetricDifference
+});
+
+
+/***/ }),
+
+/***/ 1698:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var $ = __webpack_require__(6518);
+var union = __webpack_require__(4204);
+var setMethodAcceptSetLike = __webpack_require__(4916);
+
+// `Set.prototype.union` method
+// https://github.com/tc39/proposal-set-methods
+$({ target: 'Set', proto: true, real: true, forced: !setMethodAcceptSetLike('union') }, {
+ union: union
+});
+
+
+/***/ }),
+
+/***/ 7467:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var arrayToReversed = __webpack_require__(7628);
+var ArrayBufferViewCore = __webpack_require__(4644);
+
+var aTypedArray = ArrayBufferViewCore.aTypedArray;
+var exportTypedArrayMethod = ArrayBufferViewCore.exportTypedArrayMethod;
+var getTypedArrayConstructor = ArrayBufferViewCore.getTypedArrayConstructor;
+
+// `%TypedArray%.prototype.toReversed` method
+// https://tc39.es/ecma262/#sec-%typedarray%.prototype.toreversed
+exportTypedArrayMethod('toReversed', function toReversed() {
+ return arrayToReversed(aTypedArray(this), getTypedArrayConstructor(this));
+});
+
+
+/***/ }),
+
+/***/ 4732:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var ArrayBufferViewCore = __webpack_require__(4644);
+var uncurryThis = __webpack_require__(9504);
+var aCallable = __webpack_require__(9306);
+var arrayFromConstructorAndList = __webpack_require__(5370);
+
+var aTypedArray = ArrayBufferViewCore.aTypedArray;
+var getTypedArrayConstructor = ArrayBufferViewCore.getTypedArrayConstructor;
+var exportTypedArrayMethod = ArrayBufferViewCore.exportTypedArrayMethod;
+var sort = uncurryThis(ArrayBufferViewCore.TypedArrayPrototype.sort);
+
+// `%TypedArray%.prototype.toSorted` method
+// https://tc39.es/ecma262/#sec-%typedarray%.prototype.tosorted
+exportTypedArrayMethod('toSorted', function toSorted(compareFn) {
+ if (compareFn !== undefined) aCallable(compareFn);
+ var O = aTypedArray(this);
+ var A = arrayFromConstructorAndList(getTypedArrayConstructor(O), O);
+ return sort(A, compareFn);
+});
+
+
+/***/ }),
+
+/***/ 9577:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var arrayWith = __webpack_require__(9928);
+var ArrayBufferViewCore = __webpack_require__(4644);
+var isBigIntArray = __webpack_require__(1108);
+var toIntegerOrInfinity = __webpack_require__(1291);
+var toBigInt = __webpack_require__(5854);
+
+var aTypedArray = ArrayBufferViewCore.aTypedArray;
+var getTypedArrayConstructor = ArrayBufferViewCore.getTypedArrayConstructor;
+var exportTypedArrayMethod = ArrayBufferViewCore.exportTypedArrayMethod;
+
+var PROPER_ORDER = !!function () {
+ try {
+ // eslint-disable-next-line no-throw-literal, es/no-typed-arrays, es/no-array-prototype-with -- required for testing
+ new Int8Array(1)['with'](2, { valueOf: function () { throw 8; } });
+ } catch (error) {
+ // some early implementations, like WebKit, does not follow the final semantic
+ // https://github.com/tc39/proposal-change-array-by-copy/pull/86
+ return error === 8;
+ }
+}();
+
+// `%TypedArray%.prototype.with` method
+// https://tc39.es/ecma262/#sec-%typedarray%.prototype.with
+exportTypedArrayMethod('with', { 'with': function (index, value) {
+ var O = aTypedArray(this);
+ var relativeIndex = toIntegerOrInfinity(index);
+ var actualValue = isBigIntArray(O) ? toBigInt(value) : +value;
+ return arrayWith(O, getTypedArrayConstructor(O), relativeIndex, actualValue);
+} }['with'], !PROPER_ORDER);
+
+
+/***/ }),
+
+/***/ 8992:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var $ = __webpack_require__(6518);
+var global = __webpack_require__(4475);
+var anInstance = __webpack_require__(679);
+var anObject = __webpack_require__(8551);
+var isCallable = __webpack_require__(4901);
+var getPrototypeOf = __webpack_require__(2787);
+var defineBuiltInAccessor = __webpack_require__(2106);
+var createProperty = __webpack_require__(4659);
+var fails = __webpack_require__(9039);
+var hasOwn = __webpack_require__(9297);
+var wellKnownSymbol = __webpack_require__(8227);
+var IteratorPrototype = (__webpack_require__(7657).IteratorPrototype);
+var DESCRIPTORS = __webpack_require__(3724);
+var IS_PURE = __webpack_require__(6395);
+
+var CONSTRUCTOR = 'constructor';
+var ITERATOR = 'Iterator';
+var TO_STRING_TAG = wellKnownSymbol('toStringTag');
+
+var $TypeError = TypeError;
+var NativeIterator = global[ITERATOR];
+
+// FF56- have non-standard global helper `Iterator`
+var FORCED = IS_PURE
+ || !isCallable(NativeIterator)
+ || NativeIterator.prototype !== IteratorPrototype
+ // FF44- non-standard `Iterator` passes previous tests
+ || !fails(function () { NativeIterator({}); });
+
+var IteratorConstructor = function Iterator() {
+ anInstance(this, IteratorPrototype);
+ if (getPrototypeOf(this) === IteratorPrototype) throw new $TypeError('Abstract class Iterator not directly constructable');
+};
+
+var defineIteratorPrototypeAccessor = function (key, value) {
+ if (DESCRIPTORS) {
+ defineBuiltInAccessor(IteratorPrototype, key, {
+ configurable: true,
+ get: function () {
+ return value;
+ },
+ set: function (replacement) {
+ anObject(this);
+ if (this === IteratorPrototype) throw new $TypeError("You can't redefine this property");
+ if (hasOwn(this, key)) this[key] = replacement;
+ else createProperty(this, key, replacement);
+ }
+ });
+ } else IteratorPrototype[key] = value;
+};
+
+if (!hasOwn(IteratorPrototype, TO_STRING_TAG)) defineIteratorPrototypeAccessor(TO_STRING_TAG, ITERATOR);
+
+if (FORCED || !hasOwn(IteratorPrototype, CONSTRUCTOR) || IteratorPrototype[CONSTRUCTOR] === Object) {
+ defineIteratorPrototypeAccessor(CONSTRUCTOR, IteratorConstructor);
+}
+
+IteratorConstructor.prototype = IteratorPrototype;
+
+// `Iterator` constructor
+// https://github.com/tc39/proposal-iterator-helpers
+$({ global: true, constructor: true, forced: FORCED }, {
+ Iterator: IteratorConstructor
+});
+
+
+/***/ }),
+
+/***/ 3215:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var $ = __webpack_require__(6518);
+var iterate = __webpack_require__(2652);
+var aCallable = __webpack_require__(9306);
+var anObject = __webpack_require__(8551);
+var getIteratorDirect = __webpack_require__(1767);
+
+// `Iterator.prototype.every` method
+// https://github.com/tc39/proposal-iterator-helpers
+$({ target: 'Iterator', proto: true, real: true }, {
+ every: function every(predicate) {
+ anObject(this);
+ aCallable(predicate);
+ var record = getIteratorDirect(this);
+ var counter = 0;
+ return !iterate(record, function (value, stop) {
+ if (!predicate(value, counter++)) return stop();
+ }, { IS_RECORD: true, INTERRUPTED: true }).stopped;
+ }
+});
+
+
+/***/ }),
+
+/***/ 4520:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var $ = __webpack_require__(6518);
+var call = __webpack_require__(9565);
+var aCallable = __webpack_require__(9306);
+var anObject = __webpack_require__(8551);
+var getIteratorDirect = __webpack_require__(1767);
+var createIteratorProxy = __webpack_require__(9462);
+var callWithSafeIterationClosing = __webpack_require__(6319);
+var IS_PURE = __webpack_require__(6395);
+
+var IteratorProxy = createIteratorProxy(function () {
+ var iterator = this.iterator;
+ var predicate = this.predicate;
+ var next = this.next;
+ var result, done, value;
+ while (true) {
+ result = anObject(call(next, iterator));
+ done = this.done = !!result.done;
+ if (done) return;
+ value = result.value;
+ if (callWithSafeIterationClosing(iterator, predicate, [value, this.counter++], true)) return value;
+ }
+});
+
+// `Iterator.prototype.filter` method
+// https://github.com/tc39/proposal-iterator-helpers
+$({ target: 'Iterator', proto: true, real: true, forced: IS_PURE }, {
+ filter: function filter(predicate) {
+ anObject(this);
+ aCallable(predicate);
+ return new IteratorProxy(getIteratorDirect(this), {
+ predicate: predicate
+ });
+ }
+});
+
+
+/***/ }),
+
+/***/ 2577:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var $ = __webpack_require__(6518);
+var iterate = __webpack_require__(2652);
+var aCallable = __webpack_require__(9306);
+var anObject = __webpack_require__(8551);
+var getIteratorDirect = __webpack_require__(1767);
+
+// `Iterator.prototype.find` method
+// https://github.com/tc39/proposal-iterator-helpers
+$({ target: 'Iterator', proto: true, real: true }, {
+ find: function find(predicate) {
+ anObject(this);
+ aCallable(predicate);
+ var record = getIteratorDirect(this);
+ var counter = 0;
+ return iterate(record, function (value, stop) {
+ if (predicate(value, counter++)) return stop(value);
+ }, { IS_RECORD: true, INTERRUPTED: true }).result;
+ }
+});
+
+
+/***/ }),
+
+/***/ 3949:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var $ = __webpack_require__(6518);
+var iterate = __webpack_require__(2652);
+var aCallable = __webpack_require__(9306);
+var anObject = __webpack_require__(8551);
+var getIteratorDirect = __webpack_require__(1767);
+
+// `Iterator.prototype.forEach` method
+// https://github.com/tc39/proposal-iterator-helpers
+$({ target: 'Iterator', proto: true, real: true }, {
+ forEach: function forEach(fn) {
+ anObject(this);
+ aCallable(fn);
+ var record = getIteratorDirect(this);
+ var counter = 0;
+ iterate(record, function (value) {
+ fn(value, counter++);
+ }, { IS_RECORD: true });
+ }
+});
+
+
+/***/ }),
+
+/***/ 1454:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var $ = __webpack_require__(6518);
+var map = __webpack_require__(713);
+var IS_PURE = __webpack_require__(6395);
+
+// `Iterator.prototype.map` method
+// https://github.com/tc39/proposal-iterator-helpers
+$({ target: 'Iterator', proto: true, real: true, forced: IS_PURE }, {
+ map: map
+});
+
+
+/***/ }),
+
+/***/ 8872:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var $ = __webpack_require__(6518);
+var iterate = __webpack_require__(2652);
+var aCallable = __webpack_require__(9306);
+var anObject = __webpack_require__(8551);
+var getIteratorDirect = __webpack_require__(1767);
+
+var $TypeError = TypeError;
+
+// `Iterator.prototype.reduce` method
+// https://github.com/tc39/proposal-iterator-helpers
+$({ target: 'Iterator', proto: true, real: true }, {
+ reduce: function reduce(reducer /* , initialValue */) {
+ anObject(this);
+ aCallable(reducer);
+ var record = getIteratorDirect(this);
+ var noInitial = arguments.length < 2;
+ var accumulator = noInitial ? undefined : arguments[1];
+ var counter = 0;
+ iterate(record, function (value) {
+ if (noInitial) {
+ noInitial = false;
+ accumulator = value;
+ } else {
+ accumulator = reducer(accumulator, value, counter);
+ }
+ counter++;
+ }, { IS_RECORD: true });
+ if (noInitial) throw new $TypeError('Reduce of empty iterator with no initial value');
+ return accumulator;
+ }
+});
+
+
+/***/ }),
+
+/***/ 7550:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var $ = __webpack_require__(6518);
+var iterate = __webpack_require__(2652);
+var aCallable = __webpack_require__(9306);
+var anObject = __webpack_require__(8551);
+var getIteratorDirect = __webpack_require__(1767);
+
+// `Iterator.prototype.some` method
+// https://github.com/tc39/proposal-iterator-helpers
+$({ target: 'Iterator', proto: true, real: true }, {
+ some: function some(predicate) {
+ anObject(this);
+ aCallable(predicate);
+ var record = getIteratorDirect(this);
+ var counter = 0;
+ return iterate(record, function (value, stop) {
+ if (predicate(value, counter++)) return stop();
+ }, { IS_RECORD: true, INTERRUPTED: true }).stopped;
+ }
+});
+
+
+/***/ }),
+
+/***/ 1795:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var $ = __webpack_require__(6518);
+var anObject = __webpack_require__(8551);
+var iterate = __webpack_require__(2652);
+var getIteratorDirect = __webpack_require__(1767);
+
+var push = [].push;
+
+// `Iterator.prototype.toArray` method
+// https://github.com/tc39/proposal-iterator-helpers
+$({ target: 'Iterator', proto: true, real: true }, {
+ toArray: function toArray() {
+ var result = [];
+ iterate(getIteratorDirect(anObject(this)), push, { that: result, IS_RECORD: true });
+ return result;
+ }
+});
+
+
+/***/ }),
+
+/***/ 3375:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+// TODO: Remove from `core-js@4`
+__webpack_require__(7642);
+
+
+/***/ }),
+
+/***/ 9225:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+// TODO: Remove from `core-js@4`
+__webpack_require__(8004);
+
+
+/***/ }),
+
+/***/ 3972:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+// TODO: Remove from `core-js@4`
+__webpack_require__(3853);
+
+
+/***/ }),
+
+/***/ 9209:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+// TODO: Remove from `core-js@4`
+__webpack_require__(5876);
+
+
+/***/ }),
+
+/***/ 5714:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+// TODO: Remove from `core-js@4`
+__webpack_require__(2475);
+
+
+/***/ }),
+
+/***/ 7561:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+// TODO: Remove from `core-js@4`
+__webpack_require__(5024);
+
+
+/***/ }),
+
+/***/ 6197:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+// TODO: Remove from `core-js@4`
+__webpack_require__(1698);
+
+
+/***/ }),
+
+/***/ 4979:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var $ = __webpack_require__(6518);
+var global = __webpack_require__(4475);
+var getBuiltIn = __webpack_require__(7751);
+var createPropertyDescriptor = __webpack_require__(6980);
+var defineProperty = (__webpack_require__(4913).f);
+var hasOwn = __webpack_require__(9297);
+var anInstance = __webpack_require__(679);
+var inheritIfRequired = __webpack_require__(3167);
+var normalizeStringArgument = __webpack_require__(2603);
+var DOMExceptionConstants = __webpack_require__(5002);
+var clearErrorStack = __webpack_require__(6193);
+var DESCRIPTORS = __webpack_require__(3724);
+var IS_PURE = __webpack_require__(6395);
+
+var DOM_EXCEPTION = 'DOMException';
+var Error = getBuiltIn('Error');
+var NativeDOMException = getBuiltIn(DOM_EXCEPTION);
+
+var $DOMException = function DOMException() {
+ anInstance(this, DOMExceptionPrototype);
+ var argumentsLength = arguments.length;
+ var message = normalizeStringArgument(argumentsLength < 1 ? undefined : arguments[0]);
+ var name = normalizeStringArgument(argumentsLength < 2 ? undefined : arguments[1], 'Error');
+ var that = new NativeDOMException(message, name);
+ var error = new Error(message);
+ error.name = DOM_EXCEPTION;
+ defineProperty(that, 'stack', createPropertyDescriptor(1, clearErrorStack(error.stack, 1)));
+ inheritIfRequired(that, this, $DOMException);
+ return that;
+};
+
+var DOMExceptionPrototype = $DOMException.prototype = NativeDOMException.prototype;
+
+var ERROR_HAS_STACK = 'stack' in new Error(DOM_EXCEPTION);
+var DOM_EXCEPTION_HAS_STACK = 'stack' in new NativeDOMException(1, 2);
+
+// eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
+var descriptor = NativeDOMException && DESCRIPTORS && Object.getOwnPropertyDescriptor(global, DOM_EXCEPTION);
+
+// Bun ~ 0.1.1 DOMException have incorrect descriptor and we can't redefine it
+// https://github.com/Jarred-Sumner/bun/issues/399
+var BUGGY_DESCRIPTOR = !!descriptor && !(descriptor.writable && descriptor.configurable);
+
+var FORCED_CONSTRUCTOR = ERROR_HAS_STACK && !BUGGY_DESCRIPTOR && !DOM_EXCEPTION_HAS_STACK;
+
+// `DOMException` constructor patch for `.stack` where it's required
+// https://webidl.spec.whatwg.org/#es-DOMException-specialness
+$({ global: true, constructor: true, forced: IS_PURE || FORCED_CONSTRUCTOR }, { // TODO: fix export logic
+ DOMException: FORCED_CONSTRUCTOR ? $DOMException : NativeDOMException
+});
+
+var PolyfilledDOMException = getBuiltIn(DOM_EXCEPTION);
+var PolyfilledDOMExceptionPrototype = PolyfilledDOMException.prototype;
+
+if (PolyfilledDOMExceptionPrototype.constructor !== PolyfilledDOMException) {
+ if (!IS_PURE) {
+ defineProperty(PolyfilledDOMExceptionPrototype, 'constructor', createPropertyDescriptor(1, PolyfilledDOMException));
+ }
+
+ for (var key in DOMExceptionConstants) if (hasOwn(DOMExceptionConstants, key)) {
+ var constant = DOMExceptionConstants[key];
+ var constantName = constant.s;
+ if (!hasOwn(PolyfilledDOMException, constantName)) {
+ defineProperty(PolyfilledDOMException, constantName, createPropertyDescriptor(6, constant.c));
+ }
+ }
+}
+
+
+/***/ }),
+
+/***/ 3611:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var $ = __webpack_require__(6518);
+var global = __webpack_require__(4475);
+var defineBuiltInAccessor = __webpack_require__(2106);
+var DESCRIPTORS = __webpack_require__(3724);
+
+var $TypeError = TypeError;
+// eslint-disable-next-line es/no-object-defineproperty -- safe
+var defineProperty = Object.defineProperty;
+var INCORRECT_VALUE = global.self !== global;
+
+// `self` getter
+// https://html.spec.whatwg.org/multipage/window-object.html#dom-self
+try {
+ if (DESCRIPTORS) {
+ // eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
+ var descriptor = Object.getOwnPropertyDescriptor(global, 'self');
+ // some engines have `self`, but with incorrect descriptor
+ // https://github.com/denoland/deno/issues/15765
+ if (INCORRECT_VALUE || !descriptor || !descriptor.get || !descriptor.enumerable) {
+ defineBuiltInAccessor(global, 'self', {
+ get: function self() {
+ return global;
+ },
+ set: function self(value) {
+ if (this !== global) throw new $TypeError('Illegal invocation');
+ defineProperty(global, 'self', {
+ value: value,
+ writable: true,
+ configurable: true,
+ enumerable: true
+ });
+ },
+ configurable: true,
+ enumerable: true
+ });
+ }
+ } else $({ global: true, simple: true, forced: INCORRECT_VALUE }, {
+ self: global
+ });
+} catch (error) { /* empty */ }
+
+
+/***/ }),
+
+/***/ 4603:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var defineBuiltIn = __webpack_require__(6840);
+var uncurryThis = __webpack_require__(9504);
+var toString = __webpack_require__(655);
+var validateArgumentsLength = __webpack_require__(2812);
+
+var $URLSearchParams = URLSearchParams;
+var URLSearchParamsPrototype = $URLSearchParams.prototype;
+var append = uncurryThis(URLSearchParamsPrototype.append);
+var $delete = uncurryThis(URLSearchParamsPrototype['delete']);
+var forEach = uncurryThis(URLSearchParamsPrototype.forEach);
+var push = uncurryThis([].push);
+var params = new $URLSearchParams('a=1&a=2&b=3');
+
+params['delete']('a', 1);
+// `undefined` case is a Chromium 117 bug
+// https://bugs.chromium.org/p/v8/issues/detail?id=14222
+params['delete']('b', undefined);
+
+if (params + '' !== 'a=2') {
+ defineBuiltIn(URLSearchParamsPrototype, 'delete', function (name /* , value */) {
+ var length = arguments.length;
+ var $value = length < 2 ? undefined : arguments[1];
+ if (length && $value === undefined) return $delete(this, name);
+ var entries = [];
+ forEach(this, function (v, k) { // also validates `this`
+ push(entries, { key: k, value: v });
+ });
+ validateArgumentsLength(length, 1);
+ var key = toString(name);
+ var value = toString($value);
+ var index = 0;
+ var dindex = 0;
+ var found = false;
+ var entriesLength = entries.length;
+ var entry;
+ while (index < entriesLength) {
+ entry = entries[index++];
+ if (found || entry.key === key) {
+ found = true;
+ $delete(this, entry.key);
+ } else dindex++;
+ }
+ while (dindex < entriesLength) {
+ entry = entries[dindex++];
+ if (!(entry.key === key && entry.value === value)) append(this, entry.key, entry.value);
+ }
+ }, { enumerable: true, unsafe: true });
+}
+
+
+/***/ }),
+
+/***/ 7566:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var defineBuiltIn = __webpack_require__(6840);
+var uncurryThis = __webpack_require__(9504);
+var toString = __webpack_require__(655);
+var validateArgumentsLength = __webpack_require__(2812);
+
+var $URLSearchParams = URLSearchParams;
+var URLSearchParamsPrototype = $URLSearchParams.prototype;
+var getAll = uncurryThis(URLSearchParamsPrototype.getAll);
+var $has = uncurryThis(URLSearchParamsPrototype.has);
+var params = new $URLSearchParams('a=1');
+
+// `undefined` case is a Chromium 117 bug
+// https://bugs.chromium.org/p/v8/issues/detail?id=14222
+if (params.has('a', 2) || !params.has('a', undefined)) {
+ defineBuiltIn(URLSearchParamsPrototype, 'has', function has(name /* , value */) {
+ var length = arguments.length;
+ var $value = length < 2 ? undefined : arguments[1];
+ if (length && $value === undefined) return $has(this, name);
+ var values = getAll(this, name); // also validates `this`
+ validateArgumentsLength(length, 1);
+ var value = toString($value);
+ var index = 0;
+ while (index < values.length) {
+ if (values[index++] === value) return true;
+ } return false;
+ }, { enumerable: true, unsafe: true });
+}
+
+
+/***/ }),
+
+/***/ 8721:
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
+
+
+var DESCRIPTORS = __webpack_require__(3724);
+var uncurryThis = __webpack_require__(9504);
+var defineBuiltInAccessor = __webpack_require__(2106);
+
+var URLSearchParamsPrototype = URLSearchParams.prototype;
+var forEach = uncurryThis(URLSearchParamsPrototype.forEach);
+
+// `URLSearchParams.prototype.size` getter
+// https://github.com/whatwg/url/pull/734
+if (DESCRIPTORS && !('size' in URLSearchParamsPrototype)) {
+ defineBuiltInAccessor(URLSearchParamsPrototype, 'size', {
+ get: function size() {
+ var count = 0;
+ forEach(this, function () { count++; });
+ return count;
+ },
+ configurable: true,
+ enumerable: true
+ });
+}
+
+
+/***/ })
+
+/******/ });
+/************************************************************************/
+/******/ // The module cache
+/******/ var __webpack_module_cache__ = {};
+/******/
+/******/ // The require function
+/******/ function __webpack_require__(moduleId) {
+/******/ // Check if module is in cache
+/******/ var cachedModule = __webpack_module_cache__[moduleId];
+/******/ if (cachedModule !== undefined) {
+/******/ return cachedModule.exports;
+/******/ }
+/******/ // Create a new module (and put it into the cache)
+/******/ var module = __webpack_module_cache__[moduleId] = {
+/******/ // no module.id needed
+/******/ // no module.loaded needed
+/******/ exports: {}
+/******/ };
+/******/
+/******/ // Execute the module function
+/******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/ // Return the exports of the module
+/******/ return module.exports;
+/******/ }
/******/
/************************************************************************/
/******/ /* webpack/runtime/define property getters */
@@ -49,7 +4540,63 @@ __webpack_require__.d(__webpack_exports__, {
WorkerMessageHandler: () => (/* reexport */ WorkerMessageHandler)
});
+// EXTERNAL MODULE: ./node_modules/core-js/modules/es.array.push.js
+var es_array_push = __webpack_require__(4114);
+// EXTERNAL MODULE: ./node_modules/core-js/modules/es.array-buffer.detached.js
+var es_array_buffer_detached = __webpack_require__(6573);
+// EXTERNAL MODULE: ./node_modules/core-js/modules/es.array-buffer.transfer.js
+var es_array_buffer_transfer = __webpack_require__(8100);
+// EXTERNAL MODULE: ./node_modules/core-js/modules/es.array-buffer.transfer-to-fixed-length.js
+var es_array_buffer_transfer_to_fixed_length = __webpack_require__(7936);
+// EXTERNAL MODULE: ./node_modules/core-js/modules/es.promise.with-resolvers.js
+var es_promise_with_resolvers = __webpack_require__(4628);
+// EXTERNAL MODULE: ./node_modules/core-js/modules/es.typed-array.to-reversed.js
+var es_typed_array_to_reversed = __webpack_require__(7467);
+// EXTERNAL MODULE: ./node_modules/core-js/modules/es.typed-array.to-sorted.js
+var es_typed_array_to_sorted = __webpack_require__(4732);
+// EXTERNAL MODULE: ./node_modules/core-js/modules/es.typed-array.with.js
+var es_typed_array_with = __webpack_require__(9577);
+// EXTERNAL MODULE: ./node_modules/core-js/modules/esnext.iterator.constructor.js
+var esnext_iterator_constructor = __webpack_require__(8992);
+// EXTERNAL MODULE: ./node_modules/core-js/modules/esnext.iterator.for-each.js
+var esnext_iterator_for_each = __webpack_require__(3949);
+// EXTERNAL MODULE: ./node_modules/core-js/modules/esnext.iterator.map.js
+var esnext_iterator_map = __webpack_require__(1454);
+// EXTERNAL MODULE: ./node_modules/core-js/modules/esnext.iterator.some.js
+var esnext_iterator_some = __webpack_require__(7550);
+// EXTERNAL MODULE: ./node_modules/core-js/modules/esnext.set.difference.v2.js
+var esnext_set_difference_v2 = __webpack_require__(3375);
+// EXTERNAL MODULE: ./node_modules/core-js/modules/esnext.set.intersection.v2.js
+var esnext_set_intersection_v2 = __webpack_require__(9225);
+// EXTERNAL MODULE: ./node_modules/core-js/modules/esnext.set.is-disjoint-from.v2.js
+var esnext_set_is_disjoint_from_v2 = __webpack_require__(3972);
+// EXTERNAL MODULE: ./node_modules/core-js/modules/esnext.set.is-subset-of.v2.js
+var esnext_set_is_subset_of_v2 = __webpack_require__(9209);
+// EXTERNAL MODULE: ./node_modules/core-js/modules/esnext.set.is-superset-of.v2.js
+var esnext_set_is_superset_of_v2 = __webpack_require__(5714);
+// EXTERNAL MODULE: ./node_modules/core-js/modules/esnext.set.symmetric-difference.v2.js
+var esnext_set_symmetric_difference_v2 = __webpack_require__(7561);
+// EXTERNAL MODULE: ./node_modules/core-js/modules/esnext.set.union.v2.js
+var esnext_set_union_v2 = __webpack_require__(6197);
+// EXTERNAL MODULE: ./node_modules/core-js/modules/web.self.js
+var web_self = __webpack_require__(3611);
+// EXTERNAL MODULE: ./node_modules/core-js/modules/web.url-search-params.delete.js
+var web_url_search_params_delete = __webpack_require__(4603);
+// EXTERNAL MODULE: ./node_modules/core-js/modules/web.url-search-params.has.js
+var web_url_search_params_has = __webpack_require__(7566);
+// EXTERNAL MODULE: ./node_modules/core-js/modules/web.url-search-params.size.js
+var web_url_search_params_size = __webpack_require__(8721);
;// CONCATENATED MODULE: ./src/shared/util.js
+
+
+
+
+
+
+
+
+
+
const isNodeJS = typeof process === "object" && process + "" === "[object process]" && !process.versions.nw && !(process.versions.electron && process.type && process.type !== "browser");
const IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0];
const FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0];
@@ -65,6 +4612,7 @@ const RenderingIntentFlag = {
ANNOTATIONS_FORMS: 0x10,
ANNOTATIONS_STORAGE: 0x20,
ANNOTATIONS_DISABLE: 0x40,
+ IS_EDITING: 0x80,
OPLIST: 0x100
};
const AnnotationMode = {
@@ -320,7 +4868,9 @@ const OPS = {
paintImageXObjectRepeat: 88,
paintImageMaskXObjectRepeat: 89,
paintSolidColorImageMask: 90,
- constructPath: 91
+ constructPath: 91,
+ setStrokeTransparent: 92,
+ setFillTransparent: 93
};
const PasswordResponses = {
NEED_PASSWORD: 1,
@@ -785,8 +5335,18 @@ const FontRenderOps = {
TRANSLATE: 8
};
+// EXTERNAL MODULE: ./node_modules/core-js/modules/esnext.iterator.every.js
+var esnext_iterator_every = __webpack_require__(3215);
;// CONCATENATED MODULE: ./src/core/primitives.js
+
+
+
+
+
+
+
+
const CIRCULAR_REF = Symbol("CIRCULAR_REF");
const EOF = Symbol("EOF");
let CmdCache = Object.create(null);
@@ -953,6 +5513,9 @@ class Dict {
}
return dict;
}
+ delete(key) {
+ delete this._map[key];
+ }
}
class Ref {
constructor(num, gen) {
@@ -1134,6 +5697,23 @@ class BaseStream {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
const PDF_VERSION_REGEXP = /^[1-9]\.\d$/;
function getLookupTableFactory(initializer) {
let lookup;
@@ -1524,6 +6104,9 @@ function getNewAnnotationsMap(annotationStorage) {
}
return newAnnotationsByPage.size > 0 ? newAnnotationsByPage : null;
}
+function stringToAsciiOrUTF16BE(str) {
+ return isAscii(str) ? str : stringToUTF16String(str, true);
+}
function isAscii(str) {
return /^[\x00-\x7F]*$/.test(str);
}
@@ -1565,6 +6148,12 @@ function getSizeInBytes(x) {
;// CONCATENATED MODULE: ./src/core/stream.js
+
+
+
+
+
+
class Stream extends BaseStream {
constructor(arrayBuffer, start, length, dict) {
super();
@@ -1634,6 +6223,21 @@ class NullStream extends Stream {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class ChunkedStream extends Stream {
constructor(length, chunkSize, manager) {
super(new Uint8Array(length), 0, length, null);
@@ -2057,11 +6661,25 @@ class ChunkedStreamManager {
}
}
+// EXTERNAL MODULE: ./node_modules/core-js/modules/esnext.iterator.filter.js
+var esnext_iterator_filter = __webpack_require__(4520);
+// EXTERNAL MODULE: ./node_modules/core-js/modules/es.regexp.flags.js
+var es_regexp_flags = __webpack_require__(9479);
+// EXTERNAL MODULE: ./node_modules/core-js/modules/esnext.iterator.find.js
+var esnext_iterator_find = __webpack_require__(2577);
+// EXTERNAL MODULE: ./node_modules/core-js/modules/esnext.iterator.reduce.js
+var esnext_iterator_reduce = __webpack_require__(8872);
;// CONCATENATED MODULE: ./src/core/colorspace.js
+
+
+
+
+
+
function resizeRgbImage(src, dest, w1, h1, w2, h2, alpha01) {
const COMPONENTS = 3;
alpha01 = alpha01 !== 1 ? 0 : alpha01;
@@ -2271,7 +6889,8 @@ class ColorSpace {
}
}
}
- throw new FormatError(`Unrecognized ColorSpace: ${cs.name}`);
+ warn(`Unrecognized ColorSpace: ${cs.name}`);
+ return this.singletons.gray;
}
}
if (Array.isArray(cs)) {
@@ -2346,10 +6965,12 @@ class ColorSpace {
const range = params.getArray("Range");
return new LabCS(whitePoint, blackPoint, range);
default:
- throw new FormatError(`Unimplemented ColorSpace object: ${mode}`);
+ warn(`Unimplemented ColorSpace object: ${mode}`);
+ return this.singletons.gray;
}
}
- throw new FormatError(`Unrecognized ColorSpace object: ${cs}`);
+ warn(`Unrecognized ColorSpace object: ${cs}`);
+ return this.singletons.gray;
}
static isDefaultDecode(decode, numComps) {
if (!Array.isArray(decode)) {
@@ -2880,6 +7501,12 @@ class LabCS extends ColorSpace {
;// CONCATENATED MODULE: ./src/core/binary_cmap.js
+
+
+
+
+
+
function hexToInt(a, size) {
let n = 0;
for (let i = 0; i <= size; i++) {
@@ -3138,6 +7765,13 @@ class BinaryCMapReader {
;// CONCATENATED MODULE: ./src/core/decode_stream.js
+
+
+
+
+
+
+
const emptyBuffer = new Uint8Array(0);
class DecodeStream extends BaseStream {
constructor(maybeMinBufferLength) {
@@ -3280,6 +7914,12 @@ class StreamsSequenceStream extends DecodeStream {
;// CONCATENATED MODULE: ./src/core/ascii_85_stream.js
+
+
+
+
+
+
class Ascii85Stream extends DecodeStream {
constructor(str, maybeLength) {
if (maybeLength) {
@@ -3397,6 +8037,12 @@ class AsciiHexStream extends DecodeStream {
;// CONCATENATED MODULE: ./src/core/ccitt.js
+
+
+
+
+
+
const ccittEOL = -2;
const ccittEOF = -1;
const twoDimPass = 0;
@@ -3949,6 +8595,13 @@ class CCITTFaxStream extends DecodeStream {
+
+
+
+
+
+
+
const codeLenCodeMap = new Int32Array([16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]);
const lengthDecode = new Int32Array([0x00003, 0x00004, 0x00005, 0x00006, 0x00007, 0x00008, 0x00009, 0x0000a, 0x1000b, 0x1000d, 0x1000f, 0x10011, 0x20013, 0x20017, 0x2001b, 0x2001f, 0x30023, 0x3002b, 0x30033, 0x3003b, 0x40043, 0x40053, 0x40063, 0x40073, 0x50083, 0x500a3, 0x500c3, 0x500e3, 0x00102, 0x00102, 0x00102]);
const distDecode = new Int32Array([0x00001, 0x00002, 0x00003, 0x00004, 0x10005, 0x10007, 0x20009, 0x2000d, 0x30011, 0x30019, 0x40021, 0x40031, 0x50041, 0x50061, 0x60081, 0x600c1, 0x70101, 0x70181, 0x80201, 0x80301, 0x90401, 0x90601, 0xa0801, 0xa0c01, 0xb1001, 0xb1801, 0xc2001, 0xc3001, 0xd4001, 0xd6001]);
@@ -4565,6 +9218,13 @@ class ArithmeticDecoder {
+
+
+
+
+
+
+
class Jbig2Error extends BaseException {
constructor(msg) {
super(msg, "Jbig2Error");
@@ -6317,6 +10977,7 @@ class Jbig2Image {
+
class Jbig2Stream extends DecodeStream {
constructor(stream, maybeLength, params) {
super(maybeLength);
@@ -6372,6 +11033,12 @@ class Jbig2Stream extends DecodeStream {
;// CONCATENATED MODULE: ./src/shared/image_utils.js
+
+
+
+
+
+
function convertToRGBA(params) {
switch (params.kind) {
case ImageKind.GRAYSCALE_1BPP:
@@ -6481,6 +11148,13 @@ function grayToRGBA(src, dest) {
+
+
+
+
+
+
+
class JpegError extends BaseException {
constructor(msg) {
super(msg, "JpegError");
@@ -7554,6 +12228,12 @@ class JpegImage {
+
+
+
+
+
+
class JpegStream extends DecodeStream {
constructor(stream, maybeLength, params) {
super(maybeLength);
@@ -7629,7 +12309,20 @@ class JpegStream extends DecodeStream {
}
}
+// EXTERNAL MODULE: ./node_modules/core-js/modules/web.dom-exception.stack.js
+var web_dom_exception_stack = __webpack_require__(4979);
;// CONCATENATED MODULE: ./external/openjpeg/openjpeg.js
+
+
+
+
+
+
+
+
+
+
+
var OpenJPEG = (() => {
var _scriptName = typeof document != 'undefined' ? document.currentScript?.src : undefined;
return function (moduleArg = {}) {
@@ -8173,6 +12866,9 @@ var OpenJPEG = (() => {
+
+
+
class JpxError extends BaseException {
constructor(msg) {
super(msg, "JpxError");
@@ -8256,6 +12952,12 @@ class JpxStream extends DecodeStream {
;// CONCATENATED MODULE: ./src/core/lzw_stream.js
+
+
+
+
+
+
class LZWStream extends DecodeStream {
constructor(str, maybeLength, earlyChange) {
super(maybeLength);
@@ -8375,6 +13077,12 @@ class LZWStream extends DecodeStream {
+
+
+
+
+
+
class PredictorStream extends DecodeStream {
constructor(str, maybeLength, params) {
super(maybeLength);
@@ -8607,6 +13315,15 @@ class RunLengthStream extends DecodeStream {
+
+
+
+
+
+
+
+
+
@@ -9676,6 +14393,9 @@ class Linearization {
+
+
+
const BUILT_IN_CMAPS = ["Adobe-GB1-UCS2", "Adobe-CNS1-UCS2", "Adobe-Japan1-UCS2", "Adobe-Korea1-UCS2", "78-EUC-H", "78-EUC-V", "78-H", "78-RKSJ-H", "78-RKSJ-V", "78-V", "78ms-RKSJ-H", "78ms-RKSJ-V", "83pv-RKSJ-H", "90ms-RKSJ-H", "90ms-RKSJ-V", "90msp-RKSJ-H", "90msp-RKSJ-V", "90pv-RKSJ-H", "90pv-RKSJ-V", "Add-H", "Add-RKSJ-H", "Add-RKSJ-V", "Add-V", "Adobe-CNS1-0", "Adobe-CNS1-1", "Adobe-CNS1-2", "Adobe-CNS1-3", "Adobe-CNS1-4", "Adobe-CNS1-5", "Adobe-CNS1-6", "Adobe-GB1-0", "Adobe-GB1-1", "Adobe-GB1-2", "Adobe-GB1-3", "Adobe-GB1-4", "Adobe-GB1-5", "Adobe-Japan1-0", "Adobe-Japan1-1", "Adobe-Japan1-2", "Adobe-Japan1-3", "Adobe-Japan1-4", "Adobe-Japan1-5", "Adobe-Japan1-6", "Adobe-Korea1-0", "Adobe-Korea1-1", "Adobe-Korea1-2", "B5-H", "B5-V", "B5pc-H", "B5pc-V", "CNS-EUC-H", "CNS-EUC-V", "CNS1-H", "CNS1-V", "CNS2-H", "CNS2-V", "ETHK-B5-H", "ETHK-B5-V", "ETen-B5-H", "ETen-B5-V", "ETenms-B5-H", "ETenms-B5-V", "EUC-H", "EUC-V", "Ext-H", "Ext-RKSJ-H", "Ext-RKSJ-V", "Ext-V", "GB-EUC-H", "GB-EUC-V", "GB-H", "GB-V", "GBK-EUC-H", "GBK-EUC-V", "GBK2K-H", "GBK2K-V", "GBKp-EUC-H", "GBKp-EUC-V", "GBT-EUC-H", "GBT-EUC-V", "GBT-H", "GBT-V", "GBTpc-EUC-H", "GBTpc-EUC-V", "GBpc-EUC-H", "GBpc-EUC-V", "H", "HKdla-B5-H", "HKdla-B5-V", "HKdlb-B5-H", "HKdlb-B5-V", "HKgccs-B5-H", "HKgccs-B5-V", "HKm314-B5-H", "HKm314-B5-V", "HKm471-B5-H", "HKm471-B5-V", "HKscs-B5-H", "HKscs-B5-V", "Hankaku", "Hiragana", "KSC-EUC-H", "KSC-EUC-V", "KSC-H", "KSC-Johab-H", "KSC-Johab-V", "KSC-V", "KSCms-UHC-H", "KSCms-UHC-HW-H", "KSCms-UHC-HW-V", "KSCms-UHC-V", "KSCpc-EUC-H", "KSCpc-EUC-V", "Katakana", "NWP-H", "NWP-V", "RKSJ-H", "RKSJ-V", "Roman", "UniCNS-UCS2-H", "UniCNS-UCS2-V", "UniCNS-UTF16-H", "UniCNS-UTF16-V", "UniCNS-UTF32-H", "UniCNS-UTF32-V", "UniCNS-UTF8-H", "UniCNS-UTF8-V", "UniGB-UCS2-H", "UniGB-UCS2-V", "UniGB-UTF16-H", "UniGB-UTF16-V", "UniGB-UTF32-H", "UniGB-UTF32-V", "UniGB-UTF8-H", "UniGB-UTF8-V", "UniJIS-UCS2-H", "UniJIS-UCS2-HW-H", "UniJIS-UCS2-HW-V", "UniJIS-UCS2-V", "UniJIS-UTF16-H", "UniJIS-UTF16-V", "UniJIS-UTF32-H", "UniJIS-UTF32-V", "UniJIS-UTF8-H", "UniJIS-UTF8-V", "UniJIS2004-UTF16-H", "UniJIS2004-UTF16-V", "UniJIS2004-UTF32-H", "UniJIS2004-UTF32-V", "UniJIS2004-UTF8-H", "UniJIS2004-UTF8-V", "UniJISPro-UCS2-HW-V", "UniJISPro-UCS2-V", "UniJISPro-UTF8-V", "UniJISX0213-UTF32-H", "UniJISX0213-UTF32-V", "UniJISX02132004-UTF32-H", "UniJISX02132004-UTF32-V", "UniKS-UCS2-H", "UniKS-UCS2-V", "UniKS-UTF16-H", "UniKS-UTF16-V", "UniKS-UTF32-H", "UniKS-UTF32-V", "UniKS-UTF8-H", "UniKS-UTF8-V", "V", "WP-Symbol"];
const MAX_MAP_RANGE = 2 ** 24 - 1;
class CMap {
@@ -10116,6 +14836,8 @@ class CMapFactory {
}
}
+// EXTERNAL MODULE: ./node_modules/core-js/modules/esnext.iterator.to-array.js
+var esnext_iterator_to_array = __webpack_require__(1795);
;// CONCATENATED MODULE: ./src/core/charsets.js
const ISOAdobeCharset = [".notdef", "space", "exclam", "quotedbl", "numbersign", "dollar", "percent", "ampersand", "quoteright", "parenleft", "parenright", "asterisk", "plus", "comma", "hyphen", "period", "slash", "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "colon", "semicolon", "less", "equal", "greater", "question", "at", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "bracketleft", "backslash", "bracketright", "asciicircum", "underscore", "quoteleft", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde", "exclamdown", "cent", "sterling", "fraction", "yen", "florin", "section", "currency", "quotesingle", "quotedblleft", "guillemotleft", "guilsinglleft", "guilsinglright", "fi", "fl", "endash", "dagger", "daggerdbl", "periodcentered", "paragraph", "bullet", "quotesinglbase", "quotedblbase", "quotedblright", "guillemotright", "ellipsis", "perthousand", "questiondown", "grave", "acute", "circumflex", "tilde", "macron", "breve", "dotaccent", "dieresis", "ring", "cedilla", "hungarumlaut", "ogonek", "caron", "emdash", "AE", "ordfeminine", "Lslash", "Oslash", "OE", "ordmasculine", "ae", "dotlessi", "lslash", "oslash", "oe", "germandbls", "onesuperior", "logicalnot", "mu", "trademark", "Eth", "onehalf", "plusminus", "Thorn", "onequarter", "divide", "brokenbar", "degree", "thorn", "threequarters", "twosuperior", "registered", "minus", "eth", "multiply", "threesuperior", "copyright", "Aacute", "Acircumflex", "Adieresis", "Agrave", "Aring", "Atilde", "Ccedilla", "Eacute", "Ecircumflex", "Edieresis", "Egrave", "Iacute", "Icircumflex", "Idieresis", "Igrave", "Ntilde", "Oacute", "Ocircumflex", "Odieresis", "Ograve", "Otilde", "Scaron", "Uacute", "Ucircumflex", "Udieresis", "Ugrave", "Yacute", "Ydieresis", "Zcaron", "aacute", "acircumflex", "adieresis", "agrave", "aring", "atilde", "ccedilla", "eacute", "ecircumflex", "edieresis", "egrave", "iacute", "icircumflex", "idieresis", "igrave", "ntilde", "oacute", "ocircumflex", "odieresis", "ograve", "otilde", "scaron", "uacute", "ucircumflex", "udieresis", "ugrave", "yacute", "ydieresis", "zcaron"];
const ExpertCharset = [".notdef", "space", "exclamsmall", "Hungarumlautsmall", "dollaroldstyle", "dollarsuperior", "ampersandsmall", "Acutesmall", "parenleftsuperior", "parenrightsuperior", "twodotenleader", "onedotenleader", "comma", "hyphen", "period", "fraction", "zerooldstyle", "oneoldstyle", "twooldstyle", "threeoldstyle", "fouroldstyle", "fiveoldstyle", "sixoldstyle", "sevenoldstyle", "eightoldstyle", "nineoldstyle", "colon", "semicolon", "commasuperior", "threequartersemdash", "periodsuperior", "questionsmall", "asuperior", "bsuperior", "centsuperior", "dsuperior", "esuperior", "isuperior", "lsuperior", "msuperior", "nsuperior", "osuperior", "rsuperior", "ssuperior", "tsuperior", "ff", "fi", "fl", "ffi", "ffl", "parenleftinferior", "parenrightinferior", "Circumflexsmall", "hyphensuperior", "Gravesmall", "Asmall", "Bsmall", "Csmall", "Dsmall", "Esmall", "Fsmall", "Gsmall", "Hsmall", "Ismall", "Jsmall", "Ksmall", "Lsmall", "Msmall", "Nsmall", "Osmall", "Psmall", "Qsmall", "Rsmall", "Ssmall", "Tsmall", "Usmall", "Vsmall", "Wsmall", "Xsmall", "Ysmall", "Zsmall", "colonmonetary", "onefitted", "rupiah", "Tildesmall", "exclamdownsmall", "centoldstyle", "Lslashsmall", "Scaronsmall", "Zcaronsmall", "Dieresissmall", "Brevesmall", "Caronsmall", "Dotaccentsmall", "Macronsmall", "figuredash", "hypheninferior", "Ogoneksmall", "Ringsmall", "Cedillasmall", "onequarter", "onehalf", "threequarters", "questiondownsmall", "oneeighth", "threeeighths", "fiveeighths", "seveneighths", "onethird", "twothirds", "zerosuperior", "onesuperior", "twosuperior", "threesuperior", "foursuperior", "fivesuperior", "sixsuperior", "sevensuperior", "eightsuperior", "ninesuperior", "zeroinferior", "oneinferior", "twoinferior", "threeinferior", "fourinferior", "fiveinferior", "sixinferior", "seveninferior", "eightinferior", "nineinferior", "centinferior", "dollarinferior", "periodinferior", "commainferior", "Agravesmall", "Aacutesmall", "Acircumflexsmall", "Atildesmall", "Adieresissmall", "Aringsmall", "AEsmall", "Ccedillasmall", "Egravesmall", "Eacutesmall", "Ecircumflexsmall", "Edieresissmall", "Igravesmall", "Iacutesmall", "Icircumflexsmall", "Idieresissmall", "Ethsmall", "Ntildesmall", "Ogravesmall", "Oacutesmall", "Ocircumflexsmall", "Otildesmall", "Odieresissmall", "OEsmall", "Oslashsmall", "Ugravesmall", "Uacutesmall", "Ucircumflexsmall", "Udieresissmall", "Yacutesmall", "Thornsmall", "Ydieresissmall"];
@@ -10154,6 +14876,13 @@ function getEncoding(encodingName) {
+
+
+
+
+
+
+
const MAX_SUBR_NESTING = 10;
const CFFStandardStrings = [".notdef", "space", "exclam", "quotedbl", "numbersign", "dollar", "percent", "ampersand", "quoteright", "parenleft", "parenright", "asterisk", "plus", "comma", "hyphen", "period", "slash", "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "colon", "semicolon", "less", "equal", "greater", "question", "at", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "bracketleft", "backslash", "bracketright", "asciicircum", "underscore", "quoteleft", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde", "exclamdown", "cent", "sterling", "fraction", "yen", "florin", "section", "currency", "quotesingle", "quotedblleft", "guillemotleft", "guilsinglleft", "guilsinglright", "fi", "fl", "endash", "dagger", "daggerdbl", "periodcentered", "paragraph", "bullet", "quotesinglbase", "quotedblbase", "quotedblright", "guillemotright", "ellipsis", "perthousand", "questiondown", "grave", "acute", "circumflex", "tilde", "macron", "breve", "dotaccent", "dieresis", "ring", "cedilla", "hungarumlaut", "ogonek", "caron", "emdash", "AE", "ordfeminine", "Lslash", "Oslash", "OE", "ordmasculine", "ae", "dotlessi", "lslash", "oslash", "oe", "germandbls", "onesuperior", "logicalnot", "mu", "trademark", "Eth", "onehalf", "plusminus", "Thorn", "onequarter", "divide", "brokenbar", "degree", "thorn", "threequarters", "twosuperior", "registered", "minus", "eth", "multiply", "threesuperior", "copyright", "Aacute", "Acircumflex", "Adieresis", "Agrave", "Aring", "Atilde", "Ccedilla", "Eacute", "Ecircumflex", "Edieresis", "Egrave", "Iacute", "Icircumflex", "Idieresis", "Igrave", "Ntilde", "Oacute", "Ocircumflex", "Odieresis", "Ograve", "Otilde", "Scaron", "Uacute", "Ucircumflex", "Udieresis", "Ugrave", "Yacute", "Ydieresis", "Zcaron", "aacute", "acircumflex", "adieresis", "agrave", "aring", "atilde", "ccedilla", "eacute", "ecircumflex", "edieresis", "egrave", "iacute", "icircumflex", "idieresis", "igrave", "ntilde", "oacute", "ocircumflex", "odieresis", "ograve", "otilde", "scaron", "uacute", "ucircumflex", "udieresis", "ugrave", "yacute", "ydieresis", "zcaron", "exclamsmall", "Hungarumlautsmall", "dollaroldstyle", "dollarsuperior", "ampersandsmall", "Acutesmall", "parenleftsuperior", "parenrightsuperior", "twodotenleader", "onedotenleader", "zerooldstyle", "oneoldstyle", "twooldstyle", "threeoldstyle", "fouroldstyle", "fiveoldstyle", "sixoldstyle", "sevenoldstyle", "eightoldstyle", "nineoldstyle", "commasuperior", "threequartersemdash", "periodsuperior", "questionsmall", "asuperior", "bsuperior", "centsuperior", "dsuperior", "esuperior", "isuperior", "lsuperior", "msuperior", "nsuperior", "osuperior", "rsuperior", "ssuperior", "tsuperior", "ff", "ffi", "ffl", "parenleftinferior", "parenrightinferior", "Circumflexsmall", "hyphensuperior", "Gravesmall", "Asmall", "Bsmall", "Csmall", "Dsmall", "Esmall", "Fsmall", "Gsmall", "Hsmall", "Ismall", "Jsmall", "Ksmall", "Lsmall", "Msmall", "Nsmall", "Osmall", "Psmall", "Qsmall", "Rsmall", "Ssmall", "Tsmall", "Usmall", "Vsmall", "Wsmall", "Xsmall", "Ysmall", "Zsmall", "colonmonetary", "onefitted", "rupiah", "Tildesmall", "exclamdownsmall", "centoldstyle", "Lslashsmall", "Scaronsmall", "Zcaronsmall", "Dieresissmall", "Brevesmall", "Caronsmall", "Dotaccentsmall", "Macronsmall", "figuredash", "hypheninferior", "Ogoneksmall", "Ringsmall", "Cedillasmall", "questiondownsmall", "oneeighth", "threeeighths", "fiveeighths", "seveneighths", "onethird", "twothirds", "zerosuperior", "foursuperior", "fivesuperior", "sixsuperior", "sevensuperior", "eightsuperior", "ninesuperior", "zeroinferior", "oneinferior", "twoinferior", "threeinferior", "fourinferior", "fiveinferior", "sixinferior", "seveninferior", "eightinferior", "nineinferior", "centinferior", "dollarinferior", "periodinferior", "commainferior", "Agravesmall", "Aacutesmall", "Acircumflexsmall", "Atildesmall", "Adieresissmall", "Aringsmall", "AEsmall", "Ccedillasmall", "Egravesmall", "Eacutesmall", "Ecircumflexsmall", "Edieresissmall", "Igravesmall", "Iacutesmall", "Icircumflexsmall", "Idieresissmall", "Ethsmall", "Ntildesmall", "Ogravesmall", "Oacutesmall", "Ocircumflexsmall", "Otildesmall", "Odieresissmall", "OEsmall", "Oslashsmall", "Ugravesmall", "Uacutesmall", "Ucircumflexsmall", "Udieresissmall", "Yacutesmall", "Thornsmall", "Ydieresissmall", "001.000", "001.001", "001.002", "001.003", "Black", "Bold", "Book", "Light", "Medium", "Regular", "Roman", "Semibold"];
const NUM_STANDARD_CFF_STRINGS = 391;
@@ -16267,6 +20996,8 @@ function clearUnicodeCaches() {
+
+
const SEAC_ANALYSIS_ENABLED = true;
const FontFlags = {
FixedPitch: 1,
@@ -16345,6 +21076,41 @@ function type1FontGlyphMapping(properties, builtInEncoding, glyphNames) {
function normalizeFontName(name) {
return name.replaceAll(/[,_]/g, "-").replaceAll(/\s/g, "");
}
+const getVerticalPresentationForm = getLookupTableFactory(t => {
+ t[0x2013] = 0xfe32;
+ t[0x2014] = 0xfe31;
+ t[0x2025] = 0xfe30;
+ t[0x2026] = 0xfe19;
+ t[0x3001] = 0xfe11;
+ t[0x3002] = 0xfe12;
+ t[0x3008] = 0xfe3f;
+ t[0x3009] = 0xfe40;
+ t[0x300a] = 0xfe3d;
+ t[0x300b] = 0xfe3e;
+ t[0x300c] = 0xfe41;
+ t[0x300d] = 0xfe42;
+ t[0x300e] = 0xfe43;
+ t[0x300f] = 0xfe44;
+ t[0x3010] = 0xfe3b;
+ t[0x3011] = 0xfe3c;
+ t[0x3014] = 0xfe39;
+ t[0x3015] = 0xfe3a;
+ t[0x3016] = 0xfe17;
+ t[0x3017] = 0xfe18;
+ t[0xfe4f] = 0xfe34;
+ t[0xff01] = 0xfe15;
+ t[0xff08] = 0xfe35;
+ t[0xff09] = 0xfe36;
+ t[0xff0c] = 0xfe10;
+ t[0xff1a] = 0xfe13;
+ t[0xff1b] = 0xfe14;
+ t[0xff1f] = 0xfe16;
+ t[0xff3b] = 0xfe47;
+ t[0xff3d] = 0xfe48;
+ t[0xff3f] = 0xfe33;
+ t[0xff5b] = 0xfe37;
+ t[0xff5d] = 0xfe38;
+});
;// CONCATENATED MODULE: ./src/core/standard_fonts.js
@@ -17374,6 +22140,15 @@ class CFFFont {
+
+
+
+
+
+
+
+
+
function getUint32(data, offset) {
return (data[offset] << 24 | data[offset + 1] << 16 | data[offset + 2] << 8 | data[offset + 3]) >>> 0;
}
@@ -21179,6 +25954,16 @@ const getFontBasicMetrics = getLookupTableFactory(function (t) {
});
;// CONCATENATED MODULE: ./src/core/glyf.js
+
+
+
+
+
+
+
+
+
+
const ON_CURVE_POINT = 1 << 0;
const X_SHORT_VECTOR = 1 << 1;
const Y_SHORT_VECTOR = 1 << 2;
@@ -21712,6 +26497,13 @@ class CompositeGlyph {
;// CONCATENATED MODULE: ./src/core/opentype_file_builder.js
+
+
+
+
+
+
+
function writeInt16(dest, offset, num) {
dest[offset] = num >> 8 & 0xff;
dest[offset + 1] = num & 0xff;
@@ -21820,6 +26612,13 @@ class OpenTypeFileBuilder {
+
+
+
+
+
+
+
const HINTING_ENABLED = false;
const COMMAND_MAP = {
hstem: [1],
@@ -22387,6 +27186,7 @@ class Type1Parser {
+
function findBlock(streamBytes, signature, startIndex) {
const streamBytesLength = streamBytes.length;
const signatureLength = signature.length;
@@ -22672,6 +27472,25 @@ class Type1Font {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
const PRIVATE_USE_AREAS = [[0xe000, 0xf8ff], [0x100000, 0x10fffd]];
@@ -24902,6 +29721,36 @@ class Font {
builder.addTable("post", createPostTable(properties));
return builder.toArray();
}
+ get _spaceWidth() {
+ const possibleSpaceReplacements = ["space", "minus", "one", "i", "I"];
+ let width;
+ for (const glyphName of possibleSpaceReplacements) {
+ if (glyphName in this.widths) {
+ width = this.widths[glyphName];
+ break;
+ }
+ const glyphsUnicodeMap = getGlyphsUnicode();
+ const glyphUnicode = glyphsUnicodeMap[glyphName];
+ let charcode = 0;
+ if (this.composite && this.cMap.contains(glyphUnicode)) {
+ charcode = this.cMap.lookup(glyphUnicode);
+ if (typeof charcode === "string") {
+ charcode = convertCidString(glyphUnicode, charcode);
+ }
+ }
+ if (!charcode && this.toUnicode) {
+ charcode = this.toUnicode.charCodeOf(glyphUnicode);
+ }
+ if (charcode <= 0) {
+ charcode = glyphUnicode;
+ }
+ width = this.widths[charcode];
+ if (width) {
+ break;
+ }
+ }
+ return shadow(this, "_spaceWidth", width || this.defaultWidth);
+ }
_charToGlyph(charcode, isSpace = false) {
let glyph = this._glyphCache[charcode];
if (glyph?.isSpace === isSpace) {
@@ -24930,6 +29779,10 @@ class Font {
const glyphName = this.differences[charcode] || this.defaultEncoding[charcode];
if ((glyphName === ".notdef" || glyphName === "") && this.type === "Type1") {
fontCharCode = 0x20;
+ if (glyphName === "") {
+ width ||= this._spaceWidth;
+ unicode = String.fromCharCode(fontCharCode);
+ }
}
fontCharCode = mapSpecialUnicodeValues(fontCharCode);
}
@@ -24954,6 +29807,12 @@ class Font {
warn(`charToGlyph - invalid fontCharCode: ${fontCharCode}`);
}
}
+ if (this.missingFile && this.vertical && fontChar.length === 1) {
+ const vertical = getVerticalPresentationForm()[fontChar.charCodeAt(0)];
+ if (vertical) {
+ fontChar = unicode = String.fromCharCode(vertical);
+ }
+ }
glyph = new fonts_Glyph(charcode, fontChar, unicode, accent, width, vmetric, operatorListId, isSpace, isInFont);
return this._glyphCache[charcode] = glyph;
}
@@ -25065,6 +29924,13 @@ class ErrorFont {
+
+
+
+
+
+
+
const ShadingType = {
FUNCTION_BASED: 1,
AXIAL: 2,
@@ -25985,6 +30851,8 @@ const SegoeuiRegularMetrics = {
+
+
const getXFAFontMap = getLookupTableFactory(function (t) {
t["MyriadPro-Regular"] = t["PdfJS-Fallback-Regular"] = {
name: "LiberationSans-Regular",
@@ -26178,6 +31046,7 @@ function getXfaFontDict(name) {
+
class PostScriptParser {
constructor(lexer) {
this.lexer = lexer;
@@ -26366,6 +31235,13 @@ class PostScriptLexer {
;// CONCATENATED MODULE: ./src/core/image_utils.js
+
+
+
+
+
+
+
class BaseLocalCache {
constructor(options) {
if (this.constructor === BaseLocalCache) {
@@ -26602,6 +31478,14 @@ class GlobalImageCache {
+
+
+
+
+
+
+
+
class PDFFunctionFactory {
constructor({
xref,
@@ -27865,6 +32749,16 @@ function bidi(str, startLevel = -1, vertical = false) {
+
+
+
+
+
+
+
+
+
+
const NORMAL = {
style: "normal",
weight: "normal"
@@ -28128,6 +33022,12 @@ function getFontSubstitution(systemFontCache, idFactory, localFontPath, baseFont
;// CONCATENATED MODULE: ./src/core/image_resizer.js
+
+
+
+
+
+
const MIN_IMAGE_DIM = 2048;
const MAX_IMAGE_DIM = 65537;
const MAX_ERROR = 128;
@@ -28371,6 +33271,12 @@ class ImageResizer {
ImageResizer._goodSquareLength = MIN_IMAGE_DIM;
;// CONCATENATED MODULE: ./src/shared/murmurhash3.js
+
+
+
+
+
+
const SEED = 0xc3d2e1f0;
const MASK_HIGH = 0xffff0000;
const MASK_LOW = 0xffff;
@@ -28465,6 +33371,20 @@ class MurmurHash3_64 {
;// CONCATENATED MODULE: ./src/core/operator_list.js
+
+
+
+
+
+
+
+
+
+
+
+
+
+
function addState(parentState, pattern, checkFn, iterateFn, processFn) {
let state = parentState;
for (let i = 0, ii = pattern.length - 1; i < ii; i++) {
@@ -28997,6 +33917,12 @@ class OperatorList {
+
+
+
+
+
+
function decodeAndClamp(value, addend, coefficient, max) {
value = addend + value * coefficient;
if (value < 0) {
@@ -29772,6 +34698,24 @@ class PDFImage {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -31153,9 +36097,7 @@ class PartialEvaluator {
resources,
localColorSpaceCache
}).then(function (colorSpace) {
- if (colorSpace) {
- stateManager.state.fillColorSpace = colorSpace;
- }
+ stateManager.state.fillColorSpace = colorSpace || ColorSpace.singletons.gray;
}));
return;
}
@@ -31171,9 +36113,7 @@ class PartialEvaluator {
resources,
localColorSpaceCache
}).then(function (colorSpace) {
- if (colorSpace) {
- stateManager.state.strokeColorSpace = colorSpace;
- }
+ stateManager.state.strokeColorSpace = colorSpace || ColorSpace.singletons.gray;
}));
return;
}
@@ -31216,7 +36156,12 @@ class PartialEvaluator {
args = ColorSpace.singletons.rgb.getRgb(args, 0);
break;
case OPS.setFillColorN:
- cs = stateManager.state.fillColorSpace;
+ cs = stateManager.state.patternFillColorSpace;
+ if (!cs) {
+ args = [];
+ fn = OPS.setFillTransparent;
+ break;
+ }
if (cs.name === "Pattern") {
next(self.handleColorN(operatorList, OPS.setFillColorN, args, cs, patterns, resources, task, localColorSpaceCache, localTilingPatternCache, localShadingPatternCache));
return;
@@ -31225,7 +36170,12 @@ class PartialEvaluator {
fn = OPS.setFillRGBColor;
break;
case OPS.setStrokeColorN:
- cs = stateManager.state.strokeColorSpace;
+ cs = stateManager.state.patternStrokeColorSpace;
+ if (!cs) {
+ args = [];
+ fn = OPS.setStrokeTransparent;
+ break;
+ }
if (cs.name === "Pattern") {
next(self.handleColorN(operatorList, OPS.setStrokeColorN, args, cs, patterns, resources, task, localColorSpaceCache, localTilingPatternCache, localShadingPatternCache));
return;
@@ -32440,6 +37390,9 @@ class PartialEvaluator {
map[charCode] = String.fromCodePoint(token);
return;
}
+ if (token.length % 2 !== 0) {
+ token = "\u0000" + token;
+ }
const str = [];
for (let k = 0; k < token.length; k += 2) {
const w1 = token.charCodeAt(k) << 8 | token.charCodeAt(k + 1);
@@ -33238,8 +38191,22 @@ class EvalState {
this.ctm = new Float32Array(IDENTITY_MATRIX);
this.font = null;
this.textRenderingMode = TextRenderingMode.FILL;
- this.fillColorSpace = ColorSpace.singletons.gray;
- this.strokeColorSpace = ColorSpace.singletons.gray;
+ this._fillColorSpace = ColorSpace.singletons.gray;
+ this._strokeColorSpace = ColorSpace.singletons.gray;
+ this.patternFillColorSpace = null;
+ this.patternStrokeColorSpace = null;
+ }
+ get fillColorSpace() {
+ return this._fillColorSpace;
+ }
+ set fillColorSpace(colorSpace) {
+ this._fillColorSpace = this.patternFillColorSpace = colorSpace;
+ }
+ get strokeColorSpace() {
+ return this._strokeColorSpace;
+ }
+ set strokeColorSpace(colorSpace) {
+ this._strokeColorSpace = this.patternStrokeColorSpace = colorSpace;
}
clone() {
return Object.create(this);
@@ -33729,6 +38696,13 @@ class EvaluatorPreprocessor {
+
+
+
+
+
+
+
class DefaultAppearanceEvaluator extends EvaluatorPreprocessor {
constructor(str) {
super(new StringStream(str));
@@ -34112,6 +39086,7 @@ class FakeUnicodeFont {
;// CONCATENATED MODULE: ./src/core/name_number_tree.js
+
class NameOrNumberTree {
constructor(root, xref, type) {
if (this.constructor === NameOrNumberTree) {
@@ -34330,6 +39305,8 @@ class FileSpec {
;// CONCATENATED MODULE: ./src/core/xml_parser.js
+
+
const XMLParserErrorCode = {
NoError: 0,
EndOfDocument: -1,
@@ -34748,6 +39725,10 @@ class SimpleXMLParser extends XMLParserBase {
;// CONCATENATED MODULE: ./src/core/metadata_parser.js
+
+
+
+
class MetadataParser {
constructor(data) {
data = this._repair(data);
@@ -34884,6 +39865,15 @@ class DecryptStream extends DecodeStream {
+
+
+
+
+
+
+
+
+
class ARCFourCipher {
constructor(key) {
this.a = 0;
@@ -36158,6 +41148,16 @@ class CipherTransformFactory {
+
+
+
+
+
+
+
+
+
+
async function writeObject(ref, obj, buffer, {
encrypt = null
}) {
@@ -36550,6 +41550,10 @@ async function incrementalUpdate({
+
+
+
+
const MAX_DEPTH = 40;
const StructElementType = {
PAGE_CONTENT: 1,
@@ -36834,19 +41838,19 @@ class StructTreeRoot {
const tagDict = new Dict(xref);
tagDict.set("S", Name.get(type));
if (title) {
- tagDict.set("T", title);
+ tagDict.set("T", stringToAsciiOrUTF16BE(title));
}
if (lang) {
tagDict.set("Lang", lang);
}
if (alt) {
- tagDict.set("Alt", alt);
+ tagDict.set("Alt", stringToAsciiOrUTF16BE(alt));
}
if (expanded) {
- tagDict.set("E", expanded);
+ tagDict.set("E", stringToAsciiOrUTF16BE(expanded));
}
if (actualText) {
- tagDict.set("ActualText", actualText);
+ tagDict.set("ActualText", stringToAsciiOrUTF16BE(actualText));
}
await this.#updateParentTag({
structTreeParent,
@@ -37261,6 +42265,17 @@ class StructTreePage {
+
+
+
+
+
+
+
+
+
+
+
function isValidExplicitDest(dest) {
@@ -37274,26 +42289,27 @@ function isValidExplicitDest(dest) {
if (!(zoom instanceof Name)) {
return false;
}
+ const argsLen = args.length;
let allowNull = true;
switch (zoom.name) {
case "XYZ":
- if (args.length !== 3) {
+ if (argsLen < 2 || argsLen > 3) {
return false;
}
break;
case "Fit":
case "FitB":
- return args.length === 0;
+ return argsLen === 0;
case "FitH":
case "FitBH":
case "FitV":
case "FitBV":
- if (args.length !== 1) {
+ if (argsLen > 1) {
return false;
}
break;
case "FitR":
- if (args.length !== 4) {
+ if (argsLen !== 4) {
return false;
}
allowNull = false;
@@ -38684,6 +43700,7 @@ class Catalog {
+
function mayHaveChildren(value) {
return value instanceof Ref || value instanceof Dict || value instanceof BaseStream || Array.isArray(value);
}
@@ -38926,6 +43943,10 @@ const NamespaceIds = {
;// CONCATENATED MODULE: ./src/core/xfa/utils.js
+
+
+
+
const dimConverters = {
pt: x => x,
cm: x => x / 2.54 * 72,
@@ -39125,6 +44146,16 @@ class HTMLResult {
+
+
+
+
+
+
+
+
+
+
class FontFinder {
constructor(pdfFonts) {
this.fonts = new Map();
@@ -39276,6 +44307,9 @@ function fonts_getMetrics(xfaFont, real = false) {
;// CONCATENATED MODULE: ./src/core/xfa/text.js
+
+
+
const WIDTH_FACTOR = 1.02;
class FontInfo {
constructor(xfaFont, margin, lineHeight, fontFinder) {
@@ -39487,6 +44521,10 @@ class TextMeasure {
;// CONCATENATED MODULE: ./src/core/xfa/som.js
+
+
+
+
const namePattern = /^[^.[]+/;
const indexPattern = /^[^\]]+/;
const operators = {
@@ -39724,6 +44762,17 @@ function createDataNode(root, container, expr) {
+
+
+
+
+
+
+
+
+
+
+
const _applyPrototype = Symbol();
const _attributes = Symbol();
const _attributeNames = Symbol();
@@ -40531,6 +45580,10 @@ class Option10 extends IntegerObject {
+
+
+
+
function measureToString(m) {
if (typeof m === "string") {
return "0px";
@@ -41031,6 +46084,9 @@ function fixURL(str) {
;// CONCATENATED MODULE: ./src/core/xfa/layout.js
+
+
+
function createLine(node, children) {
return {
name: "div",
@@ -41306,6 +46362,26 @@ function checkDimensions(node, space) {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
const TEMPLATE_NS_ID = NamespaceIds.template.id;
const SVG_NS = "http://www.w3.org/2000/svg";
@@ -46180,6 +51256,11 @@ class TemplateNamespace {
+
+
+
+
+
const bind_NS_DATASETS = NamespaceIds.datasets.id;
function createText(content) {
const node = new Text({});
@@ -46596,6 +51677,7 @@ class Binder {
;// CONCATENATED MODULE: ./src/core/xfa/data.js
+
class DataHandler {
constructor(root, data) {
this.data = data;
@@ -46649,6 +51731,12 @@ class DataHandler {
+
+
+
+
+
+
const CONFIG_NS_ID = NamespaceIds.config.id;
class Acrobat extends XFAObject {
constructor(attributes) {
@@ -48603,6 +53691,16 @@ class XdpNamespace {
+
+
+
+
+
+
+
+
+
+
const XHTML_NS_ID = NamespaceIds.xhtml.id;
const $richText = Symbol();
const VALID_STYLES = new Set(["color", "font", "font-family", "font-size", "font-stretch", "font-style", "font-weight", "margin", "margin-bottom", "margin-left", "margin-right", "margin-top", "letter-spacing", "line-height", "orphans", "page-break-after", "page-break-before", "page-break-inside", "tab-interval", "tab-stop", "text-align", "text-decoration", "text-indent", "vertical-align", "widows", "kerning-mode", "xfa-font-horizontal-scale", "xfa-font-vertical-scale", "xfa-spacerun", "xfa-tab-stops"]);
@@ -49038,6 +54136,10 @@ class UnknownNamespace {
+
+
+
+
class Root extends XFAObject {
constructor(ids) {
super(-1, "root", Object.create(null));
@@ -49203,6 +54305,14 @@ class Builder {
+
+
+
+
+
+
+
+
class XFAParser extends XMLParserBase {
constructor(rootNameSpace = null, richText = false) {
super();
@@ -49339,6 +54449,11 @@ class XFAParser extends XMLParserBase {
+
+
+
+
+
class XFAFactory {
constructor(data) {
try {
@@ -49481,6 +54596,21 @@ class XFAFactory {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -49892,7 +55022,8 @@ class Annotation {
subtype: params.subtype,
hasOwnCanvas: false,
noRotate: !!(this.flags & AnnotationFlag.NOROTATE),
- noHTML: isLocked && isContentLocked
+ noHTML: isLocked && isContentLocked,
+ isEditable: false
};
if (params.collectFields) {
const kids = dict.get("Kids");
@@ -49938,6 +55069,9 @@ class Annotation {
}
return this.printable;
}
+ mustBeViewedWhenEditing(isEditing, modifiedIds = null) {
+ return isEditing ? !this.data.isEditable : !modifiedIds?.has(this.data.id);
+ }
get viewable() {
if (this.data.quadPoints === null) {
return false;
@@ -50119,7 +55253,7 @@ class Annotation {
});
});
}
- async getOperatorList(evaluator, task, intent, renderForms, annotationStorage) {
+ async getOperatorList(evaluator, task, intent, annotationStorage) {
const {
hasOwnCanvas,
id,
@@ -50501,14 +55635,21 @@ class MarkupAnnotation extends Annotation {
this._streams.push(this.appearance, appearanceStream);
}
static async createNewAnnotation(xref, annotation, dependencies, params) {
- const annotationRef = annotation.ref ||= xref.getNewTemporaryRef();
+ let oldAnnotation;
+ if (annotation.ref) {
+ oldAnnotation = (await xref.fetchIfRefAsync(annotation.ref)).clone();
+ } else {
+ annotation.ref = xref.getNewTemporaryRef();
+ }
+ const annotationRef = annotation.ref;
const ap = await this.createNewAppearanceStream(annotation, xref, params);
const buffer = [];
let annotationDict;
if (ap) {
const apRef = xref.getNewTemporaryRef();
annotationDict = this.createNewDict(annotation, xref, {
- apRef
+ apRef,
+ oldAnnotation
});
await writeObject(apRef, ap, buffer, xref);
dependencies.push({
@@ -50516,7 +55657,9 @@ class MarkupAnnotation extends Annotation {
data: buffer.join("")
});
} else {
- annotationDict = this.createNewDict(annotation, xref, {});
+ annotationDict = this.createNewDict(annotation, xref, {
+ oldAnnotation
+ });
}
if (Number.isInteger(annotation.parentTreeId)) {
annotationDict.set("StructParent", annotation.parentTreeId);
@@ -50674,8 +55817,8 @@ class WidgetAnnotation extends Annotation {
}
return str;
}
- async getOperatorList(evaluator, task, intent, renderForms, annotationStorage) {
- if (renderForms && !(this instanceof SignatureWidgetAnnotation) && !this.data.noHTML && !this.data.hasOwnCanvas) {
+ async getOperatorList(evaluator, task, intent, annotationStorage) {
+ if (intent & RenderingIntentFlag.ANNOTATIONS_FORMS && !(this instanceof SignatureWidgetAnnotation) && !this.data.noHTML && !this.data.hasOwnCanvas) {
return {
opList: new OperatorList(),
separateForm: true,
@@ -50683,11 +55826,11 @@ class WidgetAnnotation extends Annotation {
};
}
if (!this._hasText) {
- return super.getOperatorList(evaluator, task, intent, renderForms, annotationStorage);
+ return super.getOperatorList(evaluator, task, intent, annotationStorage);
}
const content = await this._getAppearance(evaluator, task, intent, annotationStorage);
if (this.appearance && content === null) {
- return super.getOperatorList(evaluator, task, intent, renderForms, annotationStorage);
+ return super.getOperatorList(evaluator, task, intent, annotationStorage);
}
const opList = new OperatorList();
if (!this._defaultAppearance || content === null) {
@@ -50785,8 +55928,7 @@ class WidgetAnnotation extends Annotation {
path: this.data.fieldName,
value
};
- const encoder = val => isAscii(val) ? val : stringToUTF16String(val, true);
- dict.set("V", Array.isArray(value) ? value.map(encoder) : encoder(value));
+ dict.set("V", Array.isArray(value) ? value.map(stringToAsciiOrUTF16BE) : stringToAsciiOrUTF16BE(value));
this.amendSavedDict(annotationStorage, dict);
const maybeMK = this._getMKDict(rotation);
if (maybeMK) {
@@ -51253,7 +56395,7 @@ class ButtonWidgetAnnotation extends WidgetAnnotation {
warn("Invalid field flags for button widget annotation");
}
}
- async getOperatorList(evaluator, task, intent, renderForms, annotationStorage) {
+ async getOperatorList(evaluator, task, intent, annotationStorage) {
if (this.data.pushButton) {
return super.getOperatorList(evaluator, task, intent, false, annotationStorage);
}
@@ -51265,7 +56407,7 @@ class ButtonWidgetAnnotation extends WidgetAnnotation {
rotation = storageEntry ? storageEntry.rotation : null;
}
if (value === null && this.appearance) {
- return super.getOperatorList(evaluator, task, intent, renderForms, annotationStorage);
+ return super.getOperatorList(evaluator, task, intent, annotationStorage);
}
if (value === null || value === undefined) {
value = this.data.checkBox ? this.data.fieldValue === this.data.exportValue : this.data.fieldValue === this.data.buttonValue;
@@ -51278,7 +56420,7 @@ class ButtonWidgetAnnotation extends WidgetAnnotation {
appearance.dict.set("Matrix", this.getRotationMatrix(annotationStorage));
}
this.appearance = appearance;
- const operatorList = super.getOperatorList(evaluator, task, intent, renderForms, annotationStorage);
+ const operatorList = super.getOperatorList(evaluator, task, intent, annotationStorage);
this.appearance = savedAppearance;
appearance.dict.set("Matrix", savedMatrix);
return operatorList;
@@ -51895,7 +57037,8 @@ class PopupAnnotation extends Annotation {
class FreeTextAnnotation extends MarkupAnnotation {
constructor(params) {
super(params);
- this.data.hasOwnCanvas = !this.data.noHTML;
+ this.data.hasOwnCanvas = this.data.noRotate;
+ this.data.isEditable = !this.data.noHTML;
this.data.noHTML = false;
const {
evaluatorOptions,
@@ -51941,7 +57084,8 @@ class FreeTextAnnotation extends MarkupAnnotation {
}
static createNewDict(annotation, xref, {
apRef,
- ap
+ ap,
+ oldAnnotation
}) {
const {
color,
@@ -51951,19 +57095,24 @@ class FreeTextAnnotation extends MarkupAnnotation {
user,
value
} = annotation;
- const freetext = new Dict(xref);
+ const freetext = oldAnnotation || new Dict(xref);
freetext.set("Type", Name.get("Annot"));
freetext.set("Subtype", Name.get("FreeText"));
- freetext.set("CreationDate", `D:${getModificationDate()}`);
+ if (oldAnnotation) {
+ freetext.set("M", `D:${getModificationDate()}`);
+ freetext.delete("RC");
+ } else {
+ freetext.set("CreationDate", `D:${getModificationDate()}`);
+ }
freetext.set("Rect", rect);
const da = `/Helv ${fontSize} Tf ${getPdfColor(color, true)}`;
freetext.set("DA", da);
- freetext.set("Contents", isAscii(value) ? value : stringToUTF16String(value, true));
+ freetext.set("Contents", stringToAsciiOrUTF16BE(value));
freetext.set("F", 4);
freetext.set("Border", [0, 0, 0]);
freetext.set("Rotate", rotation);
if (user) {
- freetext.set("T", isAscii(user) ? user : stringToUTF16String(user, true));
+ freetext.set("T", stringToAsciiOrUTF16BE(user));
}
if (apRef || ap) {
const n = new Dict(xref);
@@ -52534,7 +57683,7 @@ class HighlightAnnotation extends MarkupAnnotation {
highlight.set("C", Array.from(color, c => c / 255));
highlight.set("CA", opacity);
if (user) {
- highlight.set("T", isAscii(user) ? user : stringToUTF16String(user, true));
+ highlight.set("T", stringToAsciiOrUTF16BE(user));
}
if (apRef || ap) {
const n = new Dict(xref);
@@ -52770,7 +57919,7 @@ class StampAnnotation extends MarkupAnnotation {
stamp.set("Border", [0, 0, 0]);
stamp.set("Rotate", rotation);
if (user) {
- stamp.set("T", isAscii(user) ? user : stringToUTF16String(user, true));
+ stamp.set("T", stringToAsciiOrUTF16BE(user));
}
if (apRef || ap) {
const n = new Dict(xref);
@@ -52835,6 +57984,7 @@ class FileAttachmentAnnotation extends MarkupAnnotation {
+
function decodeString(str) {
try {
return stringToUTF8String(str);
@@ -52895,6 +58045,20 @@ class DatasetReader {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class XRef {
#firstXRefStmPos = null;
constructor(stream, pdfManager) {
@@ -53633,6 +58797,25 @@ class XRef {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
const DEFAULT_USER_UNIT = 1.0;
@@ -53887,7 +59070,8 @@ class Page {
task,
intent,
cacheKey,
- annotationStorage = null
+ annotationStorage = null,
+ modifiedIds = null
}) {
const contentStreamPromise = this.getContentStream();
const resourcesPromise = this.loadResources(["ColorSpace", "ExtGState", "Font", "Pattern", "Properties", "Shading", "XObject"]);
@@ -53984,13 +59168,14 @@ class Page {
};
}
const renderForms = !!(intent & RenderingIntentFlag.ANNOTATIONS_FORMS),
+ isEditing = !!(intent & RenderingIntentFlag.IS_EDITING),
intentAny = !!(intent & RenderingIntentFlag.ANY),
intentDisplay = !!(intent & RenderingIntentFlag.DISPLAY),
intentPrint = !!(intent & RenderingIntentFlag.PRINT);
const opListPromises = [];
for (const annotation of annotations) {
- if (intentAny || intentDisplay && annotation.mustBeViewed(annotationStorage, renderForms) || intentPrint && annotation.mustBePrinted(annotationStorage)) {
- opListPromises.push(annotation.getOperatorList(partialEvaluator, task, intent, renderForms, annotationStorage).catch(function (reason) {
+ if (intentAny || intentDisplay && annotation.mustBeViewed(annotationStorage, renderForms) && annotation.mustBeViewedWhenEditing(isEditing, modifiedIds) || intentPrint && annotation.mustBePrinted(annotationStorage)) {
+ opListPromises.push(annotation.getOperatorList(partialEvaluator, task, intent, annotationStorage).catch(function (reason) {
warn("getOperatorList - ignoring annotation data during " + `"${task.name}" task: "${reason}".`);
return {
opList: null,
@@ -55143,6 +60328,7 @@ class NetworkPdfManager extends BasePdfManager {
;// CONCATENATED MODULE: ./src/shared/message_handler.js
+
const CallbackKind = {
UNKNOWN: 0,
DATA: 1,
@@ -55546,6 +60732,7 @@ class MessageHandler {
;// CONCATENATED MODULE: ./src/core/worker_stream.js
+
class PDFWorkerStream {
constructor(msgHandler) {
this._msgHandler = msgHandler;
@@ -55661,6 +60848,26 @@ class PDFWorkerStreamRangeReader {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class WorkerTask {
constructor(name) {
@@ -55710,7 +60917,7 @@ class WorkerMessageHandler {
docId,
apiVersion
} = docParams;
- const workerVersion = "4.4.168";
+ const workerVersion = "4.5.136";
if (apiVersion !== workerVersion) {
throw new Error(`The API version "${apiVersion}" does not match ` + `the Worker version "${workerVersion}".`);
}
@@ -56178,7 +61385,8 @@ class WorkerMessageHandler {
task,
intent: data.intent,
cacheKey: data.cacheKey,
- annotationStorage: data.annotationStorage
+ annotationStorage: data.annotationStorage,
+ modifiedIds: data.modifiedIds
}).then(function (operatorListInfo) {
finishWorkerTask(task);
if (start) {
@@ -56280,8 +61488,8 @@ if (typeof window === "undefined" && !isNodeJS && typeof self !== "undefined" &&
;// CONCATENATED MODULE: ./src/pdf.worker.js
-const pdfjsVersion = "4.4.168";
-const pdfjsBuild = "19fbc8998";
+const pdfjsVersion = "4.5.136";
+const pdfjsBuild = "3a21f03b0";
var __webpack_exports__WorkerMessageHandler = __webpack_exports__.WorkerMessageHandler;
export { __webpack_exports__WorkerMessageHandler as WorkerMessageHandler };
diff --git a/cps/static/js/libs/plugins.js b/cps/static/js/libs/plugins.js
index ee7ded31..9190ea2f 100644
--- a/cps/static/js/libs/plugins.js
+++ b/cps/static/js/libs/plugins.js
@@ -39,7 +39,7 @@
!function(t,e){"object"==typeof module&&module.exports?module.exports=e(t,require("jquery")):t.jQueryBridget=e(t,t.jQuery)}(window,(function(t,e){let i=t.console,n=void 0===i?function(){}:function(t){i.error(t)};return function(i,o,s){(s=s||e||t.jQuery)&&(o.prototype.option||(o.prototype.option=function(t){t&&(this.options=Object.assign(this.options||{},t))}),s.fn[i]=function(t,...e){return"string"==typeof t?function(t,e,o){let r,l=`$().${i}("${e}")`;return t.each((function(t,h){let a=s.data(h,i);if(!a)return void n(`${i} not initialized. Cannot call method ${l}`);let c=a[e];if(!c||"_"==e.charAt(0))return void n(`${l} is not a valid method`);let u=c.apply(a,o);r=void 0===r?u:r})),void 0!==r?r:t}(this,t,e):(r=t,this.each((function(t,e){let n=s.data(e,i);n?(n.option(r),n._init()):(n=new o(e,r),s.data(e,i,n))})),this);var r})}})),function(t,e){"object"==typeof module&&module.exports?module.exports=e():t.EvEmitter=e()}("undefined"!=typeof window?window:this,(function(){function t(){}let e=t.prototype;return e.on=function(t,e){if(!t||!e)return this;let i=this._events=this._events||{},n=i[t]=i[t]||[];return n.includes(e)||n.push(e),this},e.once=function(t,e){if(!t||!e)return this;this.on(t,e);let i=this._onceEvents=this._onceEvents||{};return(i[t]=i[t]||{})[e]=!0,this},e.off=function(t,e){let i=this._events&&this._events[t];if(!i||!i.length)return this;let n=i.indexOf(e);return-1!=n&&i.splice(n,1),this},e.emitEvent=function(t,e){let i=this._events&&this._events[t];if(!i||!i.length)return this;i=i.slice(0),e=e||[];let n=this._onceEvents&&this._onceEvents[t];for(let o of i){n&&n[o]&&(this.off(t,o),delete n[o]),o.apply(this,e)}return this},e.allOff=function(){return delete this._events,delete this._onceEvents,this},t})),function(t,e){"object"==typeof module&&module.exports?module.exports=e(t):t.fizzyUIUtils=e(t)}(this,(function(t){let e={extend:function(t,e){return Object.assign(t,e)},modulo:function(t,e){return(t%e+e)%e},makeArray:function(t){if(Array.isArray(t))return t;if(null==t)return[];return"object"==typeof t&&"number"==typeof t.length?[...t]:[t]},removeFrom:function(t,e){let i=t.indexOf(e);-1!=i&&t.splice(i,1)},getParent:function(t,e){for(;t.parentNode&&t!=document.body;)if((t=t.parentNode).matches(e))return t},getQueryElement:function(t){return"string"==typeof t?document.querySelector(t):t},handleEvent:function(t){let e="on"+t.type;this[e]&&this[e](t)},filterFindElements:function(t,i){return(t=e.makeArray(t)).filter((t=>t instanceof HTMLElement)).reduce(((t,e)=>{if(!i)return t.push(e),t;e.matches(i)&&t.push(e);let n=e.querySelectorAll(i);return t=t.concat(...n)}),[])},debounceMethod:function(t,e,i){i=i||100;let n=t.prototype[e],o=e+"Timeout";t.prototype[e]=function(){clearTimeout(this[o]);let t=arguments;this[o]=setTimeout((()=>{n.apply(this,t),delete this[o]}),i)}},docReady:function(t){let e=document.readyState;"complete"==e||"interactive"==e?setTimeout(t):document.addEventListener("DOMContentLoaded",t)},toDashed:function(t){return t.replace(/(.)([A-Z])/g,(function(t,e,i){return e+"-"+i})).toLowerCase()}},i=t.console;return e.htmlInit=function(n,o){e.docReady((function(){let s="data-"+e.toDashed(o),r=document.querySelectorAll(`[${s}]`),l=t.jQuery;[...r].forEach((t=>{let e,r=t.getAttribute(s);try{e=r&&JSON.parse(r)}catch(e){return void(i&&i.error(`Error parsing ${s} on ${t.className}: ${e}`))}let h=new n(t,e);l&&l.data(t,o,h)}))}))},e})),function(t,e){"object"==typeof module&&module.exports?module.exports=e(t,require("ev-emitter"),require("fizzy-ui-utils")):t.InfiniteScroll=e(t,t.EvEmitter,t.fizzyUIUtils)}(window,(function(t,e,i){let n=t.jQuery,o={};function s(t,e){let r=i.getQueryElement(t);if(r){if((t=r).infiniteScrollGUID){let i=o[t.infiniteScrollGUID];return i.option(e),i}this.element=t,this.options={...s.defaults},this.option(e),n&&(this.$element=n(this.element)),this.create()}else console.error("Bad element for InfiniteScroll: "+(r||t))}s.defaults={},s.create={},s.destroy={};let r=s.prototype;Object.assign(r,e.prototype);let l=0;r.create=function(){let t=this.guid=++l;if(this.element.infiniteScrollGUID=t,o[t]=this,this.pageIndex=1,this.loadCount=0,this.updateGetPath(),this.getPath&&this.getPath()){this.updateGetAbsolutePath(),this.log("initialized",[this.element.className]),this.callOnInit();for(let t in s.create)s.create[t].call(this)}else console.error("Disabling InfiniteScroll")},r.option=function(t){Object.assign(this.options,t)},r.callOnInit=function(){let t=this.options.onInit;t&&t.call(this,this)},r.dispatchEvent=function(t,e,i){this.log(t,i);let o=e?[e].concat(i):i;if(this.emitEvent(t,o),!n||!this.$element)return;let s=t+=".infiniteScroll";if(e){let i=n.Event(e);i.type=t,s=i}this.$element.trigger(s,i)};let h={initialized:t=>`on ${t}`,request:t=>`URL: ${t}`,load:(t,e)=>`${t.title||""}. URL: ${e}`,error:(t,e)=>`${t}. URL: ${e}`,append:(t,e,i)=>`${i.length} items. URL: ${e}`,last:(t,e)=>`URL: ${e}`,history:(t,e)=>`URL: ${e}`,pageIndex:function(t,e){return`current page determined to be: ${t} from ${e}`}};r.log=function(t,e){if(!this.options.debug)return;let i=`[InfiniteScroll] ${t}`,n=h[t];n&&(i+=". "+n.apply(this,e)),console.log(i)},r.updateMeasurements=function(){this.windowHeight=t.innerHeight;let e=this.element.getBoundingClientRect();this.top=e.top+t.scrollY},r.updateScroller=function(){let e=this.options.elementScroll;if(e){if(this.scroller=!0===e?this.element:i.getQueryElement(e),!this.scroller)throw new Error(`Unable to find elementScroll: ${e}`)}else this.scroller=t},r.updateGetPath=function(){let t=this.options.path;if(!t)return void console.error(`InfiniteScroll path option required. Set as: ${t}`);let e=typeof t;"function"!=e?"string"==e&&t.match("{{#}}")?this.updateGetPathTemplate(t):this.updateGetPathSelector(t):this.getPath=t},r.updateGetPathTemplate=function(t){this.getPath=()=>{let e=this.pageIndex+1;return t.replace("{{#}}",e)};let e=t.replace(/(\\\?|\?)/,"\\?").replace("{{#}}","(\\d\\d?\\d?)"),i=new RegExp(e),n=location.href.match(i);n&&(this.pageIndex=parseInt(n[1],10),this.log("pageIndex",[this.pageIndex,"template string"]))};let a=[/^(.*?\/?page\/?)(\d\d?\d?)(.*?$)/,/^(.*?\/?\?page=)(\d\d?\d?)(.*?$)/,/(.*?)(\d\d?\d?)(?!.*\d)(.*?$)/],c=s.getPathParts=function(t){if(t)for(let e of a){let i=t.match(e);if(i){let[,t,e,n]=i;return{begin:t,index:e,end:n}}}};r.updateGetPathSelector=function(t){let e=document.querySelector(t);if(!e)return void console.error(`Bad InfiniteScroll path option. Next link not found: ${t}`);let i=e.getAttribute("href"),n=c(i);if(!n)return void console.error(`InfiniteScroll unable to parse next link href: ${i}`);let{begin:o,index:s,end:r}=n;this.isPathSelector=!0,this.getPath=()=>o+(this.pageIndex+1)+r,this.pageIndex=parseInt(s,10)-1,this.log("pageIndex",[this.pageIndex,"next link"])},r.updateGetAbsolutePath=function(){let t=this.getPath();if(t.match(/^http/)||t.match(/^\//))return void(this.getAbsolutePath=this.getPath);let{pathname:e}=location,i=t.match(/^\?/),n=e.substring(0,e.lastIndexOf("/")),o=i?e:n+"/";this.getAbsolutePath=()=>o+this.getPath()},s.create.hideNav=function(){let t=i.getQueryElement(this.options.hideNav);t&&(t.style.display="none",this.nav=t)},s.destroy.hideNav=function(){this.nav&&(this.nav.style.display="")},r.destroy=function(){this.allOff();for(let t in s.destroy)s.destroy[t].call(this);delete this.element.infiniteScrollGUID,delete o[this.guid],n&&this.$element&&n.removeData(this.element,"infiniteScroll")},s.throttle=function(t,e){let i,n;return e=e||200,function(){let o=+new Date,s=arguments,r=()=>{i=o,t.apply(this,s)};i&&o{if(!i.ok){let t=new Error(i.statusText);return this.onPageError(t,o,i),{response:i}}return i[t]().then((s=>("text"==t&&e&&(s=n.parseFromString(s,"text/html")),204==i.status?(this.lastPageReached(s,o),{body:s,response:i}):this.onPageLoad(s,o,i))))})).catch((t=>{this.onPageError(t,o)}));return this.dispatchEvent("request",null,[o,s]),s},i.onPageLoad=function(t,e,i){return this.options.append||(this.isLoading=!1),this.pageIndex++,this.loadCount++,this.dispatchEvent("load",null,[t,e,i]),this.appendNextPage(t,e,i)},i.appendNextPage=function(t,e,i){let{append:n,responseBody:s,domParseResponse:r}=this.options;if(!("text"==s&&r)||!n)return{body:t,response:i};let l=t.querySelectorAll(n),h={body:t,response:i,items:l};if(!l||!l.length)return this.lastPageReached(t,e),h;let a=o(l),c=()=>(this.appendItems(l,a),this.isLoading=!1,this.dispatchEvent("append",null,[t,e,l,i]),h);return this.options.outlayer?this.appendOutlayerItems(a,c):c()},i.appendItems=function(t,e){t&&t.length&&(function(t){let e=t.querySelectorAll("script");for(let t of e){let e=document.createElement("script"),i=t.attributes;for(let t of i)e.setAttribute(t.name,t.value);e.innerHTML=t.innerHTML,t.parentNode.replaceChild(e,t)}}(e=e||o(t)),this.element.appendChild(e))},i.appendOutlayerItems=function(i,n){let o=e.imagesLoaded||t.imagesLoaded;return o?new Promise((function(t){o(i,(function(){let e=n();t(e)}))})):(console.error("[InfiniteScroll] imagesLoaded required for outlayer option"),void(this.isLoading=!1))},i.onAppendOutlayer=function(t,e,i){this.options.outlayer.appended(i)},i.checkLastPage=function(t,e){let i,{checkLastPage:n,path:o}=this.options;if(n){if("function"==typeof o){if(!this.getPath())return void this.lastPageReached(t,e)}"string"==typeof n?i=n:this.isPathSelector&&(i=o),i&&t.querySelector&&(t.querySelector(i)||this.lastPageReached(t,e))}},i.lastPageReached=function(t,e){this.canLoad=!1,this.dispatchEvent("last",null,[t,e])},i.onPageError=function(t,e,i){return this.isLoading=!1,this.canLoad=!1,this.dispatchEvent("error",null,[t,e,i]),t},e.create.prefill=function(){if(!this.options.prefill)return;let t=this.options.append;t?(this.updateMeasurements(),this.updateScroller(),this.isPrefilling=!0,this.on("append",this.prefill),this.once("error",this.stopPrefill),this.once("last",this.stopPrefill),this.prefill()):console.error(`append option required for prefill. Set as :${t}`)},i.prefill=function(){let t=this.getPrefillDistance();this.isPrefilling=t>=0,this.isPrefilling?(this.log("prefill"),this.loadNextPage()):this.stopPrefill()},i.getPrefillDistance=function(){return this.options.elementScroll?this.scroller.clientHeight-this.scroller.scrollHeight:this.windowHeight-this.element.clientHeight},i.stopPrefill=function(){this.log("stopPrefill"),this.off("append",this.prefill)},e})),function(t,e){"object"==typeof module&&module.exports?module.exports=e(t,require("./core"),require("fizzy-ui-utils")):e(t,t.InfiniteScroll,t.fizzyUIUtils)}(window,(function(t,e,i){let n=e.prototype;return Object.assign(e.defaults,{scrollThreshold:400}),e.create.scrollWatch=function(){this.pageScrollHandler=this.onPageScroll.bind(this),this.resizeHandler=this.onResize.bind(this);let t=this.options.scrollThreshold;(t||0===t)&&this.enableScrollWatch()},e.destroy.scrollWatch=function(){this.disableScrollWatch()},n.enableScrollWatch=function(){this.isScrollWatching||(this.isScrollWatching=!0,this.updateMeasurements(),this.updateScroller(),this.on("last",this.disableScrollWatch),this.bindScrollWatchEvents(!0))},n.disableScrollWatch=function(){this.isScrollWatching&&(this.bindScrollWatchEvents(!1),delete this.isScrollWatching)},n.bindScrollWatchEvents=function(e){let i=e?"addEventListener":"removeEventListener";this.scroller[i]("scroll",this.pageScrollHandler),t[i]("resize",this.resizeHandler)},n.onPageScroll=e.throttle((function(){this.getBottomDistance()<=this.options.scrollThreshold&&this.dispatchEvent("scrollThreshold")})),n.getBottomDistance=function(){let e,i;return this.options.elementScroll?(e=this.scroller.scrollHeight,i=this.scroller.scrollTop+this.scroller.clientHeight):(e=this.top+this.element.clientHeight,i=t.scrollY+this.windowHeight),e-i},n.onResize=function(){this.updateMeasurements()},i.debounceMethod(e,"onResize",150),e})),function(t,e){"object"==typeof module&&module.exports?module.exports=e(t,require("./core"),require("fizzy-ui-utils")):e(t,t.InfiniteScroll,t.fizzyUIUtils)}(window,(function(t,e,i){let n=e.prototype;Object.assign(e.defaults,{history:"replace"});let o=document.createElement("a");return e.create.history=function(){if(!this.options.history)return;o.href=this.getAbsolutePath(),(o.origin||o.protocol+"//"+o.host)==location.origin?this.options.append?this.createHistoryAppend():this.createHistoryPageLoad():console.error(`[InfiniteScroll] cannot set history with different origin: ${o.origin} on ${location.origin} . History behavior disabled.`)},n.createHistoryAppend=function(){this.updateMeasurements(),this.updateScroller(),this.scrollPages=[{top:0,path:location.href,title:document.title}],this.scrollPage=this.scrollPages[0],this.scrollHistoryHandler=this.onScrollHistory.bind(this),this.unloadHandler=this.onUnload.bind(this),this.scroller.addEventListener("scroll",this.scrollHistoryHandler),this.on("append",this.onAppendHistory),this.bindHistoryAppendEvents(!0)},n.bindHistoryAppendEvents=function(e){let i=e?"addEventListener":"removeEventListener";this.scroller[i]("scroll",this.scrollHistoryHandler),t[i]("unload",this.unloadHandler)},n.createHistoryPageLoad=function(){this.on("load",this.onPageLoadHistory)},e.destroy.history=n.destroyHistory=function(){this.options.history&&this.options.append&&this.bindHistoryAppendEvents(!1)},n.onAppendHistory=function(t,e,i){if(!i||!i.length)return;let n=i[0],s=this.getElementScrollY(n);o.href=e,this.scrollPages.push({top:s,path:o.href,title:t.title})},n.getElementScrollY=function(e){if(this.options.elementScroll)return e.offsetTop-this.top;return e.getBoundingClientRect().top+t.scrollY},n.onScrollHistory=function(){let t=this.getClosestScrollPage();t!=this.scrollPage&&(this.scrollPage=t,this.setHistory(t.title,t.path))},i.debounceMethod(e,"onScrollHistory",150),n.getClosestScrollPage=function(){let e,i;e=this.options.elementScroll?this.scroller.scrollTop+this.scroller.clientHeight/2:t.scrollY+this.windowHeight/2;for(let t of this.scrollPages){if(t.top>=e)break;i=t}return i},n.setHistory=function(t,e){let i=this.options.history;i&&history[i+"State"]&&(history[i+"State"](null,t,e),this.options.historyTitle&&(document.title=t),this.dispatchEvent("history",null,[t,e]))},n.onUnload=function(){if(0===this.scrollPage.top)return;let e=t.scrollY-this.scrollPage.top+this.top;this.destroyHistory(),scrollTo(0,e)},n.onPageLoadHistory=function(t,e){this.setHistory(t.title,e)},e})),function(t,e){"object"==typeof module&&module.exports?module.exports=e(t,require("./core"),require("fizzy-ui-utils")):e(t,t.InfiniteScroll,t.fizzyUIUtils)}(window,(function(t,e,i){class n{constructor(t,e){this.element=t,this.infScroll=e,this.clickHandler=this.onClick.bind(this),this.element.addEventListener("click",this.clickHandler),e.on("request",this.disable.bind(this)),e.on("load",this.enable.bind(this)),e.on("error",this.hide.bind(this)),e.on("last",this.hide.bind(this))}onClick(t){t.preventDefault(),this.infScroll.loadNextPage()}enable(){this.element.removeAttribute("disabled")}disable(){this.element.disabled="disabled"}hide(){this.element.style.display="none"}destroy(){this.element.removeEventListener("click",this.clickHandler)}}return e.create.button=function(){let t=i.getQueryElement(this.options.button);t&&(this.button=new n(t,this))},e.destroy.button=function(){this.button&&this.button.destroy()},e.Button=n,e})),function(t,e){"object"==typeof module&&module.exports?module.exports=e(t,require("./core"),require("fizzy-ui-utils")):e(t,t.InfiniteScroll,t.fizzyUIUtils)}(window,(function(t,e,i){let n=e.prototype;function o(t){r(t,"none")}function s(t){r(t,"block")}function r(t,e){t&&(t.style.display=e)}return e.create.status=function(){let t=i.getQueryElement(this.options.status);t&&(this.statusElement=t,this.statusEventElements={request:t.querySelector(".infinite-scroll-request"),error:t.querySelector(".infinite-scroll-error"),last:t.querySelector(".infinite-scroll-last")},this.on("request",this.showRequestStatus),this.on("error",this.showErrorStatus),this.on("last",this.showLastStatus),this.bindHideStatus("on"))},n.bindHideStatus=function(t){let e=this.options.append?"append":"load";this[t](e,this.hideAllStatus)},n.showRequestStatus=function(){this.showStatus("request")},n.showErrorStatus=function(){this.showStatus("error")},n.showLastStatus=function(){this.showStatus("last"),this.bindHideStatus("off")},n.showStatus=function(t){s(this.statusElement),this.hideStatusEventElements(),s(this.statusEventElements[t])},n.hideAllStatus=function(){o(this.statusElement),this.hideStatusEventElements()},n.hideStatusEventElements=function(){for(let t in this.statusEventElements){o(this.statusEventElements[t])}},e})),
/*!
* imagesLoaded v4.1.4
- * JavaScript is all like "You images are done yet or what?"
+ * JavaScript is all like "Your images are done yet or what?"
* MIT License
*/
function(t,e){"use strict";"function"==typeof define&&define.amd?define(["ev-emitter/ev-emitter"],(function(i){return e(t,i)})):"object"==typeof module&&module.exports?module.exports=e(t,require("ev-emitter")):t.imagesLoaded=e(t,t.EvEmitter)}("undefined"!=typeof window?window:this,(function(t,e){"use strict";var i=t.jQuery,n=t.console;function o(t,e){for(var i in e)t[i]=e[i];return t}var s=Array.prototype.slice;function r(t,e,l){if(!(this instanceof r))return new r(t,e,l);var h,a=t;("string"==typeof t&&(a=document.querySelectorAll(t)),a)?(this.elements=(h=a,Array.isArray(h)?h:"object"==typeof h&&"number"==typeof h.length?s.call(h):[h]),this.options=o({},this.options),"function"==typeof e?l=e:o(this.options,e),l&&this.on("always",l),this.getImages(),i&&(this.jqDeferred=new i.Deferred),setTimeout(this.check.bind(this))):n.error("Bad element for imagesLoaded "+(a||t))}r.prototype=Object.create(e.prototype),r.prototype.options={},r.prototype.getImages=function(){this.images=[],this.elements.forEach(this.addElementImages,this)},r.prototype.addElementImages=function(t){"IMG"==t.nodeName&&this.addImage(t),!0===this.options.background&&this.addElementBackgroundImages(t);var e=t.nodeType;if(e&&l[e]){for(var i=t.querySelectorAll("img"),n=0;n 1;
- (function checkCanvasSizeLimitation() {
+ (function () {
if (isIOS || isAndroid) {
- compatibilityParams.maxCanvasPixels = 5242880;
+ compatParams.set("maxCanvasPixels", 5242880);
+ }
+ })();
+ (function () {
+ if (isAndroid) {
+ compatParams.set("useSystemFonts", false);
}
})();
}
@@ -552,9 +557,21 @@ const OptionKind = {
VIEWER: 0x02,
API: 0x04,
WORKER: 0x08,
+ EVENT_DISPATCH: 0x10,
PREFERENCE: 0x80
};
+const Type = {
+ BOOLEAN: 0x01,
+ NUMBER: 0x02,
+ OBJECT: 0x04,
+ STRING: 0x08,
+ UNDEFINED: 0x10
+};
const defaultOptions = {
+ allowedGlobalEvents: {
+ value: null,
+ kind: OptionKind.BROWSER
+ },
canvasMaxAreaInBytes: {
value: -1,
kind: OptionKind.BROWSER + OptionKind.API
@@ -563,6 +580,16 @@ const defaultOptions = {
value: false,
kind: OptionKind.BROWSER
},
+ localeProperties: {
+ value: {
+ lang: navigator.language || "en-US"
+ },
+ kind: OptionKind.BROWSER
+ },
+ nimbusDataStr: {
+ value: "",
+ kind: OptionKind.BROWSER
+ },
supportsCaretBrowsingMode: {
value: false,
kind: OptionKind.BROWSER
@@ -587,6 +614,14 @@ const defaultOptions = {
value: true,
kind: OptionKind.BROWSER
},
+ toolbarDensity: {
+ value: 0,
+ kind: OptionKind.BROWSER + OptionKind.EVENT_DISPATCH
+ },
+ altTextLearnMoreUrl: {
+ value: "",
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
annotationEditorMode: {
value: 0,
kind: OptionKind.VIEWER + OptionKind.PREFERENCE
@@ -619,6 +654,14 @@ const defaultOptions = {
value: false,
kind: OptionKind.VIEWER + OptionKind.PREFERENCE
},
+ enableAltText: {
+ value: false,
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
+ enableGuessAltText: {
+ value: true,
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
enableHighlightEditor: {
value: false,
kind: OptionKind.VIEWER + OptionKind.PREFERENCE
@@ -627,10 +670,6 @@ const defaultOptions = {
value: false,
kind: OptionKind.VIEWER + OptionKind.PREFERENCE
},
- enableML: {
- value: false,
- kind: OptionKind.VIEWER + OptionKind.PREFERENCE
- },
enablePermissions: {
value: false,
kind: OptionKind.VIEWER + OptionKind.PREFERENCE
@@ -643,8 +682,8 @@ const defaultOptions = {
value: true,
kind: OptionKind.VIEWER + OptionKind.PREFERENCE
},
- enableStampEditor: {
- value: true,
+ enableUpdatedAddImage: {
+ value: false,
kind: OptionKind.VIEWER + OptionKind.PREFERENCE
},
externalLinkRel: {
@@ -775,6 +814,11 @@ const defaultOptions = {
value: "../web/standard_fonts/",
kind: OptionKind.API
},
+ useSystemFonts: {
+ value: undefined,
+ kind: OptionKind.API,
+ type: Type.BOOLEAN + Type.UNDEFINED
+ },
verbosity: {
value: 1,
kind: OptionKind.API
@@ -784,7 +828,7 @@ const defaultOptions = {
kind: OptionKind.WORKER
},
workerSrc: {
- value: "../build/pdf.worker.mjs",
+ value: "../build/pdf.worker.js",
kind: OptionKind.WORKER
}
};
@@ -807,62 +851,80 @@ const defaultOptions = {
value: false,
kind: OptionKind.VIEWER
};
- defaultOptions.locale = {
- value: navigator.language || "en-US",
- kind: OptionKind.VIEWER
- };
}
-const userOptions = Object.create(null);
+const userOptions = new Map();
{
- for (const name in compatibilityParams) {
- userOptions[name] = compatibilityParams[name];
+ for (const [name, value] of compatParams) {
+ userOptions.set(name, value);
}
}
class AppOptions {
+ static eventBus;
constructor() {
throw new Error("Cannot initialize AppOptions.");
}
static get(name) {
- return userOptions[name] ?? defaultOptions[name]?.value ?? undefined;
+ return userOptions.has(name) ? userOptions.get(name) : defaultOptions[name]?.value;
}
static getAll(kind = null, defaultOnly = false) {
const options = Object.create(null);
for (const name in defaultOptions) {
- const defaultOption = defaultOptions[name];
- if (kind && !(kind & defaultOption.kind)) {
+ const defaultOpt = defaultOptions[name];
+ if (kind && !(kind & defaultOpt.kind)) {
continue;
}
- options[name] = defaultOnly ? defaultOption.value : userOptions[name] ?? defaultOption.value;
+ options[name] = !defaultOnly && userOptions.has(name) ? userOptions.get(name) : defaultOpt.value;
}
return options;
}
static set(name, value) {
- userOptions[name] = value;
+ this.setAll({
+ [name]: value
+ });
}
- static setAll(options, init = false) {
- if (init) {
- if (this.get("disablePreferences")) {
- return;
- }
- for (const name in userOptions) {
- if (compatibilityParams[name] !== undefined) {
- continue;
- }
- console.warn("setAll: The Preferences may override manually set AppOptions; " + 'please use the "disablePreferences"-option in order to prevent that.');
- break;
- }
- }
+ static setAll(options, prefs = false) {
+ let events;
for (const name in options) {
- userOptions[name] = options[name];
+ const defaultOpt = defaultOptions[name],
+ userOpt = options[name];
+ if (!defaultOpt || !(typeof userOpt === typeof defaultOpt.value || Type[(typeof userOpt).toUpperCase()] & defaultOpt.type)) {
+ continue;
+ }
+ const {
+ kind
+ } = defaultOpt;
+ if (prefs && !(kind & OptionKind.BROWSER || kind & OptionKind.PREFERENCE)) {
+ continue;
+ }
+ if (this.eventBus && kind & OptionKind.EVENT_DISPATCH) {
+ (events ||= new Map()).set(name, userOpt);
+ }
+ userOptions.set(name, userOpt);
+ }
+ if (events) {
+ for (const [name, value] of events) {
+ this.eventBus.dispatch(name.toLowerCase(), {
+ source: this,
+ value
+ });
+ }
}
}
- static remove(name) {
- delete userOptions[name];
- const val = compatibilityParams[name];
- if (val !== undefined) {
- userOptions[name] = val;
+}
+{
+ AppOptions._checkDisablePreferences = () => {
+ if (AppOptions.get("disablePreferences")) {
+ return true;
}
- }
+ for (const [name] of userOptions) {
+ if (compatParams.has(name)) {
+ continue;
+ }
+ console.warn("The Preferences may override manually set AppOptions; " + 'please use the "disablePreferences"-option to prevent that.');
+ break;
+ }
+ return false;
+ };
}
;// CONCATENATED MODULE: ./web/pdf_link_service.js
@@ -1171,26 +1233,27 @@ class PDFLinkService {
if (!(typeof zoom === "object" && typeof zoom?.name === "string")) {
return false;
}
+ const argsLen = args.length;
let allowNull = true;
switch (zoom.name) {
case "XYZ":
- if (args.length !== 3) {
+ if (argsLen < 2 || argsLen > 3) {
return false;
}
break;
case "Fit":
case "FitB":
- return args.length === 0;
+ return argsLen === 0;
case "FitH":
case "FitBH":
case "FitV":
case "FitBV":
- if (args.length !== 1) {
+ if (argsLen > 1) {
return false;
}
break;
case "FitR":
- if (args.length !== 4) {
+ if (argsLen !== 4) {
return false;
}
allowNull = false;
@@ -1240,7 +1303,6 @@ const {
noContextMenu,
normalizeUnicode,
OPS,
- Outliner,
PasswordResponses,
PDFDataRangeTransport,
PDFDateString,
@@ -1248,12 +1310,10 @@ const {
PermissionFlag,
PixelsPerInch,
RenderingCancelledException,
- renderTextLayer,
setLayerDimensions,
shadow,
TextLayer,
UnexpectedResponseException,
- updateTextLayer,
Util,
VerbosityLevel,
version,
@@ -1401,40 +1461,28 @@ class BaseExternalServices {
updateEditorStates(data) {
throw new Error("Not implemented: updateEditorStates");
}
- async getNimbusExperimentData() {}
- async getGlobalEventNames() {
- return null;
- }
dispatchGlobalEvent(_event) {}
}
;// CONCATENATED MODULE: ./web/preferences.js
class BasePreferences {
- #browserDefaults = Object.freeze({
- canvasMaxAreaInBytes: -1,
- isInAutomation: false,
- supportsCaretBrowsingMode: false,
- supportsDocumentFonts: true,
- supportsIntegratedFind: false,
- supportsMouseWheelZoomCtrlKey: true,
- supportsMouseWheelZoomMetaKey: true,
- supportsPinchToZoom: true
- });
#defaults = Object.freeze({
+ altTextLearnMoreUrl: "",
annotationEditorMode: 0,
annotationMode: 2,
cursorToolOnLoad: 0,
defaultZoomDelay: 400,
defaultZoomValue: "",
disablePageLabels: false,
+ enableAltText: false,
+ enableGuessAltText: true,
enableHighlightEditor: false,
enableHighlightFloatingButton: false,
- enableML: false,
enablePermissions: false,
enablePrintAutoRotate: true,
enableScripting: true,
- enableStampEditor: true,
+ enableUpdatedAddImage: false,
externalLinkTarget: 0,
highlightEditorColors: "yellow=#FFFF98,green=#53FFBC,blue=#80EBFF,pink=#FFCBE6,red=#FF4F5F",
historyUpdateUrl: false,
@@ -1456,7 +1504,6 @@ class BasePreferences {
enableXfa: true,
viewerCssTheme: 0
});
- #prefs = Object.create(null);
#initializedPromise = null;
constructor() {
if (this.constructor === BasePreferences) {
@@ -1466,16 +1513,13 @@ class BasePreferences {
browserPrefs,
prefs
}) => {
- const options = Object.create(null);
- for (const [name, val] of Object.entries(this.#browserDefaults)) {
- const prefVal = browserPrefs?.[name];
- options[name] = typeof prefVal === typeof val ? prefVal : val;
+ if (AppOptions._checkDisablePreferences()) {
+ return;
}
- for (const [name, val] of Object.entries(this.#defaults)) {
- const prefVal = prefs?.[name];
- options[name] = this.#prefs[name] = typeof prefVal === typeof val ? prefVal : val;
- }
- AppOptions.setAll(options, true);
+ AppOptions.setAll({
+ ...browserPrefs,
+ ...prefs
+ }, true);
});
}
async _writeToStorage(prefObj) {
@@ -1484,58 +1528,21 @@ class BasePreferences {
async _readFromStorage(prefObj) {
throw new Error("Not implemented: _readFromStorage");
}
- #updatePref({
- name,
- value
- }) {
- throw new Error("Not implemented: #updatePref");
- }
async reset() {
await this.#initializedPromise;
- const oldPrefs = structuredClone(this.#prefs);
- this.#prefs = Object.create(null);
- try {
- await this._writeToStorage(this.#defaults);
- } catch (reason) {
- this.#prefs = oldPrefs;
- throw reason;
- }
+ AppOptions.setAll(this.#defaults, true);
+ await this._writeToStorage(this.#defaults);
}
async set(name, value) {
await this.#initializedPromise;
- const defaultValue = this.#defaults[name],
- oldPrefs = structuredClone(this.#prefs);
- if (defaultValue === undefined) {
- throw new Error(`Set preference: "${name}" is undefined.`);
- } else if (value === undefined) {
- throw new Error("Set preference: no value is specified.");
- }
- const valueType = typeof value,
- defaultType = typeof defaultValue;
- if (valueType !== defaultType) {
- if (valueType === "number" && defaultType === "string") {
- value = value.toString();
- } else {
- throw new Error(`Set preference: "${value}" is a ${valueType}, expected a ${defaultType}.`);
- }
- } else if (valueType === "number" && !Number.isInteger(value)) {
- throw new Error(`Set preference: "${value}" must be an integer.`);
- }
- this.#prefs[name] = value;
- try {
- await this._writeToStorage(this.#prefs);
- } catch (reason) {
- this.#prefs = oldPrefs;
- throw reason;
- }
+ AppOptions.setAll({
+ [name]: value
+ }, true);
+ await this._writeToStorage(AppOptions.getAll(OptionKind.PREFERENCE));
}
async get(name) {
await this.#initializedPromise;
- const defaultValue = this.#defaults[name];
- if (defaultValue === undefined) {
- throw new Error(`Get preference: "${name}" is undefined.`);
- }
- return this.#prefs[name] ?? defaultValue;
+ return AppOptions.get(name);
}
get initializedPromise() {
return this.#initializedPromise;
@@ -3098,13 +3105,19 @@ class Preferences extends BasePreferences {
}
class ExternalServices extends BaseExternalServices {
async createL10n() {
- return new genericl10n_GenericL10n(AppOptions.get("locale"));
+ return new genericl10n_GenericL10n(AppOptions.get("localeProperties")?.lang);
}
createScripting() {
return new GenericScripting(AppOptions.get("sandboxBundleSrc"));
}
}
class MLManager {
+ async isEnabledFor(_name) {
+ return false;
+ }
+ async deleteModel(_service) {
+ return null;
+ }
async guess() {
return null;
}
@@ -8411,6 +8424,9 @@ class AnnotationLayerBuilder {
}
this.div.hidden = true;
}
+ hasEditableAnnotations() {
+ return !!this.annotationLayer?.hasEditableAnnotations();
+ }
#updatePresentationModeState(state) {
if (!this.div) {
return;
@@ -9142,6 +9158,7 @@ class PDFPageView {
#annotationMode = AnnotationMode.ENABLE_FORMS;
#enableHWA = false;
#hasRestrictedScaling = false;
+ #isEditing = false;
#layerProperties = null;
#loadingId = null;
#previousRotation = null;
@@ -9296,6 +9313,9 @@ class PDFPageView {
this.reset();
this.pdfPage?.cleanup();
}
+ hasEditableAnnotations() {
+ return !!this.annotationLayer?.hasEditableAnnotations();
+ }
get _textHighlighter() {
return shadow(this, "_textHighlighter", new TextHighlighter({
pageIndex: this.id - 1,
@@ -9472,6 +9492,19 @@ class PDFPageView {
this._resetZoomLayer();
}
}
+ toggleEditingMode(isEditing) {
+ if (!this.hasEditableAnnotations()) {
+ return;
+ }
+ this.#isEditing = isEditing;
+ this.reset({
+ keepZoomLayer: true,
+ keepAnnotationLayer: true,
+ keepAnnotationEditorLayer: true,
+ keepXfaLayer: true,
+ keepTextLayer: true
+ });
+ }
update({
scale = 0,
rotation = null,
@@ -9822,7 +9855,8 @@ class PDFPageView {
annotationMode: this.#annotationMode,
optionalContentConfigPromise: this._optionalContentConfigPromise,
annotationCanvasMap: this._annotationCanvasMap,
- pageColors
+ pageColors,
+ isEditing: this.#isEditing
};
const renderTask = this.renderTask = pdfPage.render(renderContext);
renderTask.onContinue = renderContinueCallback;
@@ -9982,8 +10016,11 @@ class PDFViewer {
#enableHWA = false;
#enableHighlightFloatingButton = false;
#enablePermissions = false;
+ #enableUpdatedAddImage = false;
#eventAbortController = null;
#mlManager = null;
+ #onPageRenderedCallback = null;
+ #switchAnnotationEditorModeTimeoutId = null;
#getAllTextInProgress = false;
#hiddenCopyElement = null;
#interruptCopyCondition = false;
@@ -9993,7 +10030,7 @@ class PDFViewer {
#scaleTimeoutId = null;
#textLayerMode = TextLayerMode.ENABLE;
constructor(options) {
- const viewerVersion = "4.4.168";
+ const viewerVersion = "4.5.136";
if (version !== viewerVersion) {
throw new Error(`The API version "${version}" does not match the Viewer version "${viewerVersion}".`);
}
@@ -10020,6 +10057,7 @@ class PDFViewer {
this.#annotationEditorMode = options.annotationEditorMode ?? AnnotationEditorType.NONE;
this.#annotationEditorHighlightColors = options.annotationEditorHighlightColors || null;
this.#enableHighlightFloatingButton = options.enableHighlightFloatingButton === true;
+ this.#enableUpdatedAddImage = options.enableUpdatedAddImage === true;
this.imageResourcesPath = options.imageResourcesPath || "";
this.enablePrintAutoRotate = options.enablePrintAutoRotate || false;
this.removePageBorders = options.removePageBorders || false;
@@ -10425,7 +10463,7 @@ class PDFViewer {
if (pdfDocument.isPureXfa) {
console.warn("Warning: XFA-editing is not implemented.");
} else if (isValidAnnotationEditorMode(mode)) {
- this.#annotationEditorUIManager = new AnnotationEditorUIManager(this.container, viewer, this.#altTextManager, eventBus, pdfDocument, pageColors, this.#annotationEditorHighlightColors, this.#enableHighlightFloatingButton, this.#mlManager);
+ this.#annotationEditorUIManager = new AnnotationEditorUIManager(this.container, viewer, this.#altTextManager, eventBus, pdfDocument, pageColors, this.#annotationEditorHighlightColors, this.#enableHighlightFloatingButton, this.#enableUpdatedAddImage, this.#mlManager);
eventBus.dispatch("annotationeditoruimanager", {
source: this,
uiManager: this.#annotationEditorUIManager
@@ -10584,6 +10622,7 @@ class PDFViewer {
this.viewer.removeAttribute("lang");
this.#hiddenCopyElement?.remove();
this.#hiddenCopyElement = null;
+ this.#cleanupSwitchAnnotationEditorMode();
}
#ensurePageViewVisible() {
if (this._scrollMode !== ScrollMode.PAGE) {
@@ -10956,6 +10995,34 @@ class PDFViewer {
location: this._location
});
}
+ #switchToEditAnnotationMode() {
+ const visible = this._getVisiblePages();
+ const pagesToRefresh = [];
+ const {
+ ids,
+ views
+ } = visible;
+ for (const page of views) {
+ const {
+ view
+ } = page;
+ if (!view.hasEditableAnnotations()) {
+ ids.delete(view.id);
+ continue;
+ }
+ pagesToRefresh.push(page);
+ }
+ if (pagesToRefresh.length === 0) {
+ return null;
+ }
+ this.renderingQueue.renderHighestPriority({
+ first: pagesToRefresh[0],
+ last: pagesToRefresh.at(-1),
+ views: pagesToRefresh,
+ ids
+ });
+ return ids;
+ }
containsElement(element) {
return this.container.contains(element);
}
@@ -11388,6 +11455,16 @@ class PDFViewer {
get containerTopLeft() {
return this.#containerTopLeft ||= [this.container.offsetTop, this.container.offsetLeft];
}
+ #cleanupSwitchAnnotationEditorMode() {
+ if (this.#onPageRenderedCallback) {
+ this.eventBus._off("pagerendered", this.#onPageRenderedCallback);
+ this.#onPageRenderedCallback = null;
+ }
+ if (this.#switchAnnotationEditorModeTimeoutId !== null) {
+ clearTimeout(this.#switchAnnotationEditorModeTimeoutId);
+ this.#switchAnnotationEditorModeTimeoutId = null;
+ }
+ }
get annotationEditorMode() {
return this.#annotationEditorUIManager ? this.#annotationEditorMode : AnnotationEditorType.DISABLE;
}
@@ -11408,12 +11485,47 @@ class PDFViewer {
if (!this.pdfDocument) {
return;
}
- this.#annotationEditorMode = mode;
- this.eventBus.dispatch("annotationeditormodechanged", {
- source: this,
- mode
- });
- this.#annotationEditorUIManager.updateMode(mode, editId, isFromKeyboard);
+ const {
+ eventBus
+ } = this;
+ const updater = () => {
+ this.#cleanupSwitchAnnotationEditorMode();
+ this.#annotationEditorMode = mode;
+ this.#annotationEditorUIManager.updateMode(mode, editId, isFromKeyboard);
+ eventBus.dispatch("annotationeditormodechanged", {
+ source: this,
+ mode
+ });
+ };
+ if (mode === AnnotationEditorType.NONE || this.#annotationEditorMode === AnnotationEditorType.NONE) {
+ const isEditing = mode !== AnnotationEditorType.NONE;
+ if (!isEditing) {
+ this.pdfDocument.annotationStorage.resetModifiedIds();
+ }
+ for (const pageView of this._pages) {
+ pageView.toggleEditingMode(isEditing);
+ }
+ const idsToRefresh = this.#switchToEditAnnotationMode();
+ if (isEditing && idsToRefresh) {
+ this.#cleanupSwitchAnnotationEditorMode();
+ this.#onPageRenderedCallback = ({
+ pageNumber
+ }) => {
+ idsToRefresh.delete(pageNumber);
+ if (idsToRefresh.size === 0) {
+ this.#switchAnnotationEditorModeTimeoutId = setTimeout(updater, 0);
+ }
+ };
+ const {
+ signal
+ } = this.#eventAbortController;
+ eventBus._on("pagerendered", this.#onPageRenderedCallback, {
+ signal
+ });
+ return;
+ }
+ }
+ updater();
}
set annotationEditorParams({
type,
@@ -11721,7 +11833,7 @@ class SecondaryToolbar {
class Toolbar {
#opts;
- constructor(options, eventBus) {
+ constructor(options, eventBus, toolbarDensity = 0) {
this.#opts = options;
this.eventBus = eventBus;
const buttons = [{
@@ -11806,8 +11918,13 @@ class Toolbar {
break;
}
});
+ eventBus._on("toolbardensity", this.#updateToolbarDensity.bind(this));
+ this.#updateToolbarDensity({
+ value: toolbarDensity
+ });
this.reset();
}
+ #updateToolbarDensity() {}
#setAnnotationEditorUIManager(uiManager, parentContainer) {
const colorPicker = new ColorPicker({
uiManager
@@ -12078,7 +12195,6 @@ class ViewHistory {
const FORCE_PAGES_LOADED_TIMEOUT = 10000;
-const WHEEL_ZOOM_DISABLED_TIMEOUT = 1000;
const ViewOnLoad = {
UNKNOWN: -1,
PREVIOUS: 0,
@@ -12110,18 +12226,17 @@ const PDFViewerApplication = {
store: null,
downloadManager: null,
overlayManager: null,
- preferences: null,
+ preferences: new Preferences(),
toolbar: null,
secondaryToolbar: null,
eventBus: null,
l10n: null,
annotationEditorParams: null,
isInitialViewSet: false,
- downloadComplete: false,
isViewerEmbedded: window.parent !== window,
url: "",
baseUrl: "",
- _allowedGlobalEventsPromise: null,
+ mlManager: null,
_downloadUrl: "",
_eventBusAbortController: null,
_windowAbortController: null,
@@ -12141,11 +12256,9 @@ const PDFViewerApplication = {
_printAnnotationStoragePromise: null,
_touchInfo: null,
_isCtrlKeyDown: false,
- _nimbusDataPromise: null,
_caretBrowsing: null,
_isScrolling: false,
async initialize(appConfig) {
- let l10nPromise;
this.appConfig = appConfig;
try {
await this.preferences.initializedPromise;
@@ -12167,8 +12280,7 @@ const PDFViewerApplication = {
if (mode) {
document.documentElement.classList.add(mode);
}
- l10nPromise = this.externalServices.createL10n();
- this.l10n = await l10nPromise;
+ this.l10n = await this.externalServices.createL10n();
document.getElementsByTagName("html")[0].dir = this.l10n.getDirection();
this.l10n.translate(appConfig.appContainer || document.documentElement);
if (this.isViewerEmbedded && AppOptions.get("externalLinkTarget") === LinkTarget.NONE) {
@@ -12257,7 +12369,9 @@ const PDFViewerApplication = {
}
}
if (params.has("locale")) {
- AppOptions.set("locale", params.get("locale"));
+ AppOptions.set("localeProperties", {
+ lang: params.get("locale")
+ });
}
},
async _initializeViewerComponents() {
@@ -12318,6 +12432,7 @@ const PDFViewerApplication = {
annotationEditorMode,
annotationEditorHighlightColors: AppOptions.get("highlightEditorColors"),
enableHighlightFloatingButton: AppOptions.get("enableHighlightFloatingButton"),
+ enableUpdatedAddImage: AppOptions.get("enableUpdatedAddImage"),
imageResourcesPath: AppOptions.get("imageResourcesPath"),
enablePrintAutoRotate: AppOptions.get("enablePrintAutoRotate"),
maxCanvasPixels: AppOptions.get("maxCanvasPixels"),
@@ -12355,9 +12470,6 @@ const PDFViewerApplication = {
}
if (appConfig.annotationEditorParams) {
if (annotationEditorMode !== AnnotationEditorType.DISABLE) {
- if (AppOptions.get("enableStampEditor")) {
- appConfig.toolbar?.editorStampButton?.classList.remove("hidden");
- }
const editorHighlightButton = appConfig.toolbar?.editorHighlightButton;
if (editorHighlightButton && AppOptions.get("enableHighlightEditor")) {
editorHighlightButton.hidden = false;
@@ -12380,7 +12492,7 @@ const PDFViewerApplication = {
});
}
if (appConfig.toolbar) {
- this.toolbar = new Toolbar(appConfig.toolbar, eventBus);
+ this.toolbar = new Toolbar(appConfig.toolbar, eventBus, AppOptions.get("toolbarDensity"));
}
if (appConfig.secondaryToolbar) {
this.secondaryToolbar = new SecondaryToolbar(appConfig.secondaryToolbar, eventBus);
@@ -12437,7 +12549,6 @@ const PDFViewerApplication = {
}
},
async run(config) {
- this.preferences = new Preferences();
await this.initialize(config);
const {
appConfig,
@@ -12514,9 +12625,6 @@ const PDFViewerApplication = {
get externalServices() {
return shadow(this, "externalServices", new ExternalServices());
},
- get mlManager() {
- return shadow(this, "mlManager", AppOptions.get("enableML") === true ? new MLManager() : null);
- },
get initialized() {
return this._initializedCapability.settled;
},
@@ -12597,12 +12705,10 @@ const PDFViewerApplication = {
let title = pdfjs_getPdfFilenameFromUrl(url, "");
if (!title) {
try {
- title = decodeURIComponent(getFilenameFromUrl(url)) || url;
- } catch {
- title = url;
- }
+ title = decodeURIComponent(getFilenameFromUrl(url));
+ } catch {}
}
- this.setTitle(title);
+ this.setTitle(title || url);
},
setTitle(title = this._title) {
this._title = title;
@@ -12648,7 +12754,6 @@ const PDFViewerApplication = {
this.pdfLinkService.externalLinkEnabled = true;
this.store = null;
this.isInitialViewSet = false;
- this.downloadComplete = false;
this.url = "";
this.baseUrl = "";
this._downloadUrl = "";
@@ -12724,9 +12829,7 @@ const PDFViewerApplication = {
async download(options = {}) {
let data;
try {
- if (this.downloadComplete) {
- data = await this.pdfDocument.getData();
- }
+ data = await this.pdfDocument.getData();
} catch {}
this.downloadManager.download(data, this._downloadUrl, this._docFilename, options);
},
@@ -12793,11 +12896,8 @@ const PDFViewerApplication = {
return message;
},
progress(level) {
- if (!this.loadingBar || this.downloadComplete) {
- return;
- }
const percent = Math.round(level * 100);
- if (percent <= this.loadingBar.percent) {
+ if (!this.loadingBar || percent <= this.loadingBar.percent) {
return;
}
this.loadingBar.percent = percent;
@@ -12811,7 +12911,6 @@ const PDFViewerApplication = {
length
}) => {
this._contentLength = length;
- this.downloadComplete = true;
this.loadingBar?.hide();
firstPagePromise.then(() => {
this.eventBus.dispatch("documentloaded", {
@@ -13413,9 +13512,6 @@ const PDFViewerApplication = {
});
}
addWindowResolutionChange();
- window.addEventListener("visibilitychange", webViewerVisibilityChange, {
- signal
- });
window.addEventListener("wheel", webViewerWheel, {
passive: false,
signal
@@ -13730,7 +13826,7 @@ function webViewerHashchange(evt) {
}
}
{
- /*var webViewerFileInputChange = function (evt) {
+ var webViewerFileInputChange = function (evt) {
if (PDFViewerApplication.pdfViewer?.isInPresentationMode) {
return;
}
@@ -13742,7 +13838,7 @@ function webViewerHashchange(evt) {
};
var webViewerOpenFile = function (evt) {
PDFViewerApplication._openFileInput?.click();
- };*/
+ };
}
function webViewerPresentationMode() {
PDFViewerApplication.requestPresentationMode();
@@ -13876,20 +13972,6 @@ function webViewerPageChanging({
function webViewerResolutionChange(evt) {
PDFViewerApplication.pdfViewer.refresh();
}
-function webViewerVisibilityChange(evt) {
- if (document.visibilityState === "visible") {
- setZoomDisabledTimeout();
- }
-}
-let zoomDisabledTimeout = null;
-function setZoomDisabledTimeout() {
- if (zoomDisabledTimeout) {
- clearTimeout(zoomDisabledTimeout);
- }
- zoomDisabledTimeout = setTimeout(function () {
- zoomDisabledTimeout = null;
- }, WHEEL_ZOOM_DISABLED_TIMEOUT);
-}
function webViewerWheel(evt) {
const {
pdfViewer,
@@ -13907,7 +13989,7 @@ function webViewerWheel(evt) {
const origin = [evt.clientX, evt.clientY];
if (isPinchToZoom || evt.ctrlKey && supportsMouseWheelZoomCtrlKey || evt.metaKey && supportsMouseWheelZoomMetaKey) {
evt.preventDefault();
- if (PDFViewerApplication._isScrolling || zoomDisabledTimeout || document.visibilityState === "hidden" || PDFViewerApplication.overlayManager.active) {
+ if (PDFViewerApplication._isScrolling || document.visibilityState === "hidden" || PDFViewerApplication.overlayManager.active) {
return;
}
if (isPinchToZoom && supportsPinchToZoom) {
@@ -14335,14 +14417,20 @@ function webViewerReportTelemetry({
}) {
PDFViewerApplication.externalServices.reportTelemetry(details);
}
+function webViewerSetPreference({
+ name,
+ value
+}) {
+ PDFViewerApplication.preferences.set(name, value);
+}
;// CONCATENATED MODULE: ./web/viewer.js
-const pdfjsVersion = "4.4.168";
-const pdfjsBuild = "19fbc8998";
+const pdfjsVersion = "4.5.136";
+const pdfjsBuild = "3a21f03b0";
const AppConstants = {
LinkTarget: LinkTarget,
RenderingStates: RenderingStates,
diff --git a/cps/static/js/main.js b/cps/static/js/main.js
index 72f01867..505d5d9e 100644
--- a/cps/static/js/main.js
+++ b/cps/static/js/main.js
@@ -49,7 +49,7 @@ function elementSorter(a, b) {
return 0;
}
-// Generic control/related handler to show/hide fields based on a checkbox' value
+// Generic control/related handler to show/hide fields based on a 'checkbox' value
// e.g.
//
// ...
@@ -63,7 +63,7 @@ $(document).on("change", "input[type=\"checkbox\"][data-control]", function () {
});
});
-// Generic control/related handler to show/hide fields based on a select' value
+// Generic control/related handler to show/hide fields based on a 'select' value
$(document).on("change", "select[data-control]", function() {
var $this = $(this);
var name = $this.data("control");
@@ -79,7 +79,7 @@ $(document).on("change", "select[data-control]", function() {
}
});
-// Generic control/related handler to show/hide fields based on a select' value
+// Generic control/related handler to show/hide fields based on a 'select' value
// this one is made to show all values if select value is not 0
$(document).on("change", "select[data-controlall]", function() {
var $this = $(this);
@@ -130,8 +130,13 @@ $(".container-fluid").bind('drop', function (e) {
}
});
if (dt.files.length) {
- $("#btn-upload")[0].files = dt.files;
- $("#form-upload").submit();
+ if($("#btn-upload-format").length) {
+ $("#btn-upload-format")[0].files = dt.files;
+ $("#form-upload-format").submit();
+ } else {
+ $("#btn-upload")[0].files = dt.files;
+ $("#form-upload").submit();
+ }
}
}
});
@@ -140,12 +145,25 @@ $("#btn-upload").change(function() {
$("#form-upload").submit();
});
+$("#btn-upload-format").change(function() {
+ $("#form-upload-format").submit();
+});
+
+
$("#form-upload").uploadprogress({
- redirect_url: getPath() + "/", //"{{ url_for('web.index')}}",
- uploadedMsg: $("#form-upload").data("message"), //"{{_('Upload done, processing, please wait...')}}",
- modalTitle: $("#form-upload").data("title"), //"{{_('Uploading...')}}",
- modalFooter: $("#form-upload").data("footer"), //"{{_('Close')}}",
- modalTitleFailed: $("#form-upload").data("failed") //"{{_('Error')}}"
+ redirect_url: getPath() + "/",
+ uploadedMsg: $("#form-upload").data("message"),
+ modalTitle: $("#form-upload").data("title"),
+ modalFooter: $("#form-upload").data("footer"),
+ modalTitleFailed: $("#form-upload").data("failed")
+});
+
+$("#form-upload-format").uploadprogress({
+ redirect_url: getPath() + "/",
+ uploadedMsg: $("#form-upload-format").data("message"),
+ modalTitle: $("#form-upload-format").data("title"),
+ modalFooter: $("#form-upload-format").data("footer"),
+ modalTitleFailed: $("#form-upload-format").data("failed")
});
$(document).ready(function() {
@@ -604,6 +622,7 @@ $(function() {
});
$("#toggle_order_shelf").click(function() {
+ $("#toggle_order_shelf").toggleClass("dummy");
$("#new").toggleClass("disabled");
$("#old").toggleClass("disabled");
$("#asc").toggleClass("disabled");
@@ -612,9 +631,20 @@ $(function() {
$("#auth_za").toggleClass("disabled");
$("#pub_new").toggleClass("disabled");
$("#pub_old").toggleClass("disabled");
+ $("#shelf_new").toggleClass("disabled");
+ $("#shelf_old").toggleClass("disabled");
var alternative_text = $("#toggle_order_shelf").data('alt-text');
+ var status = $("#toggle_order_shelf").hasClass("dummy") ? "on" : "off";
$("#toggle_order_shelf").data('alt-text', $("#toggle_order_shelf").html());
$("#toggle_order_shelf").html(alternative_text);
+
+ $.ajax({
+ method:"post",
+ contentType: "application/json; charset=utf-8",
+ dataType: "json",
+ url: getPath() + "/ajax/view",
+ data: "{\"shelf\": {\"man\": \"" + status + "\"}}",
+ });
});
$("#btndeluser").click(function() {
@@ -696,20 +726,20 @@ $(function() {
url: getPath() + "/ajax/simulatedbchange",
data: {config_calibre_dir: $("#config_calibre_dir").val(), csrf_token: $("input[name='csrf_token']").val()},
success: function success(data) {
- if ( data.change ) {
- if ( data.valid ) {
+ if ( !data.valid ) {
+ $("#InvalidDialog").modal('show');
+ }
+ else{
+ if ( data.change ) {
confirmDialog(
"db_submit",
"GeneralChangeModal",
0,
changeDbSettings
);
- }
- else {
- $("#InvalidDialog").modal('show');
- }
- } else {
+ } else {
changeDbSettings();
+ }
}
}
});
diff --git a/cps/static/js/reading/epub-progress.js b/cps/static/js/reading/epub-progress.js
deleted file mode 100644
index b8fc11d0..00000000
--- a/cps/static/js/reading/epub-progress.js
+++ /dev/null
@@ -1,54 +0,0 @@
-/**
- * waits until queue is finished, meaning the book is done loading
- * @param callback
- */
-function qFinished(callback){
- let timeout=setInterval(()=>{
- if(reader.rendition.q.running===undefined)
- clearInterval(timeout);
- callback();
- },300
- )
-}
-
-function calculateProgress(){
- let data=reader.rendition.location.end;
- return Math.round(epub.locations.percentageFromCfi(data.cfi)*100);
-}
-
-// register new event emitter locationchange that fires on urlchange
-// source: https://stackoverflow.com/a/52809105/21941129
-(() => {
- let oldPushState = history.pushState;
- history.pushState = function pushState() {
- let ret = oldPushState.apply(this, arguments);
- window.dispatchEvent(new Event('locationchange'));
- return ret;
- };
-
- let oldReplaceState = history.replaceState;
- history.replaceState = function replaceState() {
- let ret = oldReplaceState.apply(this, arguments);
- window.dispatchEvent(new Event('locationchange'));
- return ret;
- };
-
- window.addEventListener('popstate', () => {
- window.dispatchEvent(new Event('locationchange'));
- });
-})();
-
-window.addEventListener('locationchange',()=>{
- let newPos=calculateProgress();
- progressDiv.textContent=newPos+"%";
-});
-
-var epub=ePub(calibre.bookUrl)
-
-let progressDiv=document.getElementById("progress");
-
-qFinished(()=>{
- epub.locations.generate().then(()=> {
- window.dispatchEvent(new Event('locationchange'))
-});
-})
diff --git a/cps/static/js/reading/epub.js b/cps/static/js/reading/epub.js
index a552da05..8d299ce8 100644
--- a/cps/static/js/reading/epub.js
+++ b/cps/static/js/reading/epub.js
@@ -52,6 +52,32 @@ var reader;
}
});
+ // Update progress percentage
+ let progressDiv = document.getElementById("progress");
+ reader.book.ready.then((()=>{
+ let locations_key = reader.book.key()+'-locations';
+ let stored_locations = localStorage.getItem(locations_key);
+ let make_locations, save_locations;
+ if (stored_locations) {
+ make_locations = Promise.resolve(reader.book.locations.load(stored_locations));
+ // No-op because locations are already saved
+ save_locations = ()=>{};
+ } else {
+ make_locations = reader.book.locations.generate();
+ save_locations = ()=>{
+ localStorage.setItem(locations_key, reader.book.locations.save());
+ };
+ }
+ make_locations.then(()=>{
+ reader.rendition.on('relocated', (location)=>{
+ let percentage = Math.round(location.end.percentage*100);
+ progressDiv.textContent=percentage+"%";
+ });
+ reader.rendition.reportLocation();
+ progressDiv.style.visibility = "visible";
+ }).then(save_locations);
+ }));
+
/**
* @param {string} action - Add or remove bookmark
* @param {string|int} location - Location or zero
diff --git a/cps/static/js/reading/locationchange-polyfill.js b/cps/static/js/reading/locationchange-polyfill.js
new file mode 100644
index 00000000..4845ea84
--- /dev/null
+++ b/cps/static/js/reading/locationchange-polyfill.js
@@ -0,0 +1,21 @@
+// register new event emitter locationchange that fires on urlchange
+// source: https://stackoverflow.com/a/52809105/21941129
+(() => {
+ let oldPushState = history.pushState;
+ history.pushState = function pushState() {
+ let ret = oldPushState.apply(this, arguments);
+ window.dispatchEvent(new Event('locationchange'));
+ return ret;
+ };
+
+ let oldReplaceState = history.replaceState;
+ history.replaceState = function replaceState() {
+ let ret = oldReplaceState.apply(this, arguments);
+ window.dispatchEvent(new Event('locationchange'));
+ return ret;
+ };
+
+ window.addEventListener('popstate', () => {
+ window.dispatchEvent(new Event('locationchange'));
+ });
+})();
diff --git a/cps/static/js/table.js b/cps/static/js/table.js
index 36361c3c..7f210eb1 100644
--- a/cps/static/js/table.js
+++ b/cps/static/js/table.js
@@ -685,6 +685,17 @@ function ratingFormatter(value, row) {
return (value/2);
}
+function seriesIndexFormatter(value, row) {
+ if (!value) {
+ return value;
+ }
+ formated_value = Number(value).toFixed(2);
+ if (formated_value.endsWith(".00")) {
+ formated_value = parseInt(formated_value).toString();
+ }
+ return formated_value;
+}
+
/* Do some hiding disabling after user list is loaded */
function loadSuccess() {
@@ -849,6 +860,7 @@ function BookCheckboxChange(checkbox, userId, field) {
},
success: handleListServerResponse
});
+ console.log("test");
}
diff --git a/setup.py b/cps/string_helper.py
similarity index 50%
rename from setup.py
rename to cps/string_helper.py
index 8dcbee25..d263dd2f 100644
--- a/setup.py
+++ b/cps/string_helper.py
@@ -1,8 +1,7 @@
-#!/usr/bin/env python
# -*- coding: utf-8 -*-
# This file is part of the Calibre-Web (https://github.com/janeczku/calibre-web)
-# Copyright (C) 2019 decentral1se
+# Copyright (C) 2024 OzzieIsaacs
#
# 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
@@ -16,28 +15,9 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-#
-# """Calibre-web distribution package setuptools installer."""
-
-from setuptools import setup
-import os
import re
-import codecs
-here = os.path.abspath(os.path.dirname(__file__))
-def read(*parts):
- with codecs.open(os.path.join(here, *parts), 'r') as fp:
- return fp.read()
+def strip_whitespaces(text):
+ return re.sub(r"(^[\s\u200B-\u200D\ufeff]+)|([\s\u200B-\u200D\ufeff]+$)","", text)
-def find_version(*file_paths):
- version_file = read(*file_paths)
- version_match = re.search(r"^STABLE_VERSION\s+=\s+{['\"]version['\"]:\s*['\"](.*)['\"]}",
- version_file, re.M)
- if version_match:
- return version_match.group(1)
- raise RuntimeError("Unable to find version string.")
-
-setup(
- version=find_version("src", "calibreweb", "cps", "constants.py")
-)
diff --git a/cps/tasks/convert.py b/cps/tasks/convert.py
index 3bef81a9..dc0af0c4 100644
--- a/cps/tasks/convert.py
+++ b/cps/tasks/convert.py
@@ -1,339 +1,355 @@
-# -*- coding: utf-8 -*-
-
-# This file is part of the Calibre-Web (https://github.com/janeczku/calibre-web)
-# Copyright (C) 2020 pwr
-#
-# 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 .
-
-import os
-import re
-from glob import glob
-from shutil import copyfile, copyfileobj
-from markupsafe import escape
-from time import time
-from uuid import uuid4
-
-from sqlalchemy.exc import SQLAlchemyError
-from flask_babel import lazy_gettext as N_
-
-from cps.services.worker import CalibreTask
-from cps import db
-from cps import logger, config
-from cps.subproc_wrapper import process_open
-from flask_babel import gettext as _
-from cps.kobo_sync_status import remove_synced_book
-from cps.ub import init_db_thread
-from cps.file_helper import get_temp_dir
-
-from cps.tasks.mail import TaskEmail
-from cps import gdriveutils, helper
-from cps.constants import SUPPORTED_CALIBRE_BINARIES
-
-log = logger.create()
-
-current_milli_time = lambda: int(round(time() * 1000))
-
-
-class TaskConvert(CalibreTask):
- def __init__(self, file_path, book_id, task_message, settings, ereader_mail, user=None):
- super(TaskConvert, self).__init__(task_message)
- self.worker_thread = None
- self.file_path = file_path
- self.book_id = book_id
- self.title = ""
- self.settings = settings
- self.ereader_mail = ereader_mail
- self.user = user
-
- self.results = dict()
-
- def run(self, worker_thread):
- self.worker_thread = worker_thread
- if config.config_use_google_drive:
- worker_db = db.CalibreDB(expire_on_commit=False, init=True)
- cur_book = worker_db.get_book(self.book_id)
- self.title = cur_book.title
- data = worker_db.get_book_format(self.book_id, self.settings['old_book_format'])
- df = gdriveutils.getFileFromEbooksFolder(cur_book.path,
- data.name + "." + self.settings['old_book_format'].lower())
- df_cover = gdriveutils.getFileFromEbooksFolder(cur_book.path, "cover.jpg")
- if df:
- datafile_cover = None
- datafile = os.path.join(config.get_book_path(),
- cur_book.path,
- data.name + "." + self.settings['old_book_format'].lower())
- if df_cover:
- datafile_cover = os.path.join(config.get_book_path(),
- cur_book.path, "cover.jpg")
- if not os.path.exists(os.path.join(config.get_book_path(), cur_book.path)):
- os.makedirs(os.path.join(config.get_book_path(), cur_book.path))
- df.GetContentFile(datafile)
- if df_cover:
- df_cover.GetContentFile(datafile_cover)
- worker_db.session.close()
- else:
- # ToDo Include cover in error handling
- error_message = _("%(format)s not found on Google Drive: %(fn)s",
- format=self.settings['old_book_format'],
- fn=data.name + "." + self.settings['old_book_format'].lower())
- worker_db.session.close()
- return self._handleError(error_message)
-
- filename = self._convert_ebook_format()
- if config.config_use_google_drive:
- os.remove(self.file_path + '.' + self.settings['old_book_format'].lower())
- if df_cover:
- os.remove(os.path.join(config.config_calibre_dir, cur_book.path, "cover.jpg"))
-
- if filename:
- if config.config_use_google_drive:
- # Upload files to gdrive
- gdriveutils.updateGdriveCalibreFromLocal()
- self._handleSuccess()
- if self.ereader_mail:
- # if we're sending to E-Reader after converting, create a one-off task and run it immediately
- # todo: figure out how to incorporate this into the progress
- try:
- EmailText = N_(u"%(book)s send to E-Reader", book=escape(self.title))
- for email in self.ereader_mail.split(','):
- email = email.strip()
- worker_thread.add(self.user, TaskEmail(self.settings['subject'],
- self.results["path"],
- filename,
- self.settings,
- email,
- EmailText,
- self.settings['body'],
- id=self.book_id,
- internal=True)
- )
- except Exception as ex:
- return self._handleError(str(ex))
-
- def _convert_ebook_format(self):
- error_message = None
- local_db = db.CalibreDB(expire_on_commit=False, init=True)
- file_path = self.file_path
- book_id = self.book_id
- format_old_ext = '.' + self.settings['old_book_format'].lower()
- format_new_ext = '.' + self.settings['new_book_format'].lower()
-
- # check to see if destination format already exists - or if book is in database
- # if it does - mark the conversion task as complete and return a success
- # this will allow to send to E-Reader workflow to continue to work
- if os.path.isfile(file_path + format_new_ext) or\
- local_db.get_book_format(self.book_id, self.settings['new_book_format']):
- log.info("Book id %d already converted to %s", book_id, format_new_ext)
- cur_book = local_db.get_book(book_id)
- self.title = cur_book.title
- self.results['path'] = cur_book.path
- self.results['title'] = self.title
- new_format = local_db.session.query(db.Data).filter(db.Data.book == book_id)\
- .filter(db.Data.format == self.settings['new_book_format'].upper()).one_or_none()
- if not new_format:
- new_format = db.Data(name=os.path.basename(file_path),
- book_format=self.settings['new_book_format'].upper(),
- book=book_id, uncompressed_size=os.path.getsize(file_path + format_new_ext))
- try:
- local_db.session.merge(new_format)
- local_db.session.commit()
- except SQLAlchemyError as e:
- local_db.session.rollback()
- log.error("Database error: %s", e)
- local_db.session.close()
- self._handleError(N_("Oops! Database Error: %(error)s.", error=e))
- return
- self._handleSuccess()
- local_db.session.close()
- return os.path.basename(file_path + format_new_ext)
- else:
- log.info("Book id %d - target format of %s does not exist. Moving forward with convert.",
- book_id,
- format_new_ext)
-
- if config.config_kepubifypath and format_old_ext == '.epub' and format_new_ext == '.kepub':
- check, error_message = self._convert_kepubify(file_path,
- format_old_ext,
- format_new_ext)
- else:
- # check if calibre converter-executable is existing
- if not os.path.exists(config.config_converterpath):
- self._handleError(N_("Calibre ebook-convert %(tool)s not found", tool=config.config_converterpath))
- return
- has_cover = local_db.get_book(book_id).has_cover
- check, error_message = self._convert_calibre(file_path, format_old_ext, format_new_ext, has_cover)
-
- if check == 0:
- cur_book = local_db.get_book(book_id)
- if os.path.isfile(file_path + format_new_ext):
- new_format = local_db.session.query(db.Data).filter(db.Data.book == book_id) \
- .filter(db.Data.format == self.settings['new_book_format'].upper()).one_or_none()
- if not new_format:
- new_format = db.Data(name=cur_book.data[0].name,
- book_format=self.settings['new_book_format'].upper(),
- book=book_id, uncompressed_size=os.path.getsize(file_path + format_new_ext))
- try:
- local_db.session.merge(new_format)
- local_db.session.commit()
- if self.settings['new_book_format'].upper() in ['KEPUB', 'EPUB', 'EPUB3']:
- ub_session = init_db_thread()
- remove_synced_book(book_id, True, ub_session)
- ub_session.close()
- except SQLAlchemyError as e:
- local_db.session.rollback()
- log.error("Database error: %s", e)
- local_db.session.close()
- self._handleError(error_message)
- return
- self.results['path'] = cur_book.path
- self.title = cur_book.title
- self.results['title'] = self.title
- if not config.config_use_google_drive:
- self._handleSuccess()
- return os.path.basename(file_path + format_new_ext)
- else:
- error_message = N_('%(format)s format not found on disk', format=format_new_ext.upper())
- local_db.session.close()
- log.info("ebook converter failed with error while converting book")
- if not error_message:
- error_message = N_('Ebook converter failed with unknown error')
- else:
- log.error(error_message)
- self._handleError(error_message)
- return
-
- def _convert_kepubify(self, file_path, format_old_ext, format_new_ext):
- if config.config_embed_metadata and config.config_binariesdir:
- tmp_dir, temp_file_name = helper.do_calibre_export(self.book_id, format_old_ext[1:])
- filename = os.path.join(tmp_dir, temp_file_name + format_old_ext)
- temp_file_path = tmp_dir
- else:
- filename = file_path + format_old_ext
- temp_file_path = os.path.dirname(file_path)
- quotes = [1, 3]
- command = [config.config_kepubifypath, filename, '-o', temp_file_path, '-i']
- try:
- p = process_open(command, quotes)
- except OSError as e:
- return 1, N_("Kepubify-converter failed: %(error)s", error=e)
- self.progress = 0.01
- while True:
- nextline = p.stdout.readlines()
- nextline = [x.strip('\n') for x in nextline if x != '\n']
- for line in nextline:
- log.debug(line)
- if p.poll() is not None:
- break
-
- # process returncode
- check = p.returncode
-
- # move file
- if check == 0:
- converted_file = glob(os.path.splitext(filename)[0] + "*.kepub.epub")
- if len(converted_file) == 1:
- copyfile(converted_file[0], (file_path + format_new_ext))
- os.unlink(converted_file[0])
- else:
- return 1, N_("Converted file not found or more than one file in folder %(folder)s",
- folder=os.path.dirname(file_path))
- return check, None
-
- def _convert_calibre(self, file_path, format_old_ext, format_new_ext, has_cover):
- path_tmp_opf = None
- try:
- # path_tmp_opf = self._embed_metadata()
- if config.config_embed_metadata:
- quotes = [5]
- tmp_dir = get_temp_dir()
- calibredb_binarypath = os.path.join(config.config_binariesdir, SUPPORTED_CALIBRE_BINARIES["calibredb"])
- my_env = os.environ.copy()
- if config.config_calibre_split:
- my_env['CALIBRE_OVERRIDE_DATABASE_PATH'] = os.path.join(config.config_calibre_dir, "metadata.db")
- library_path = config.config_calibre_split_dir
- else:
- library_path = config.config_calibre_dir
-
- opf_command = [calibredb_binarypath, 'show_metadata', '--as-opf', str(self.book_id),
- '--with-library', library_path]
- p = process_open(opf_command, quotes, my_env)
- p.wait()
- check = p.returncode
- calibre_traceback = p.stderr.readlines()
- if check == 0:
- path_tmp_opf = os.path.join(tmp_dir, "metadata_" + str(uuid4()) + ".opf")
- with open(path_tmp_opf, 'w') as fd:
- copyfileobj(p.stdout, fd)
- else:
- error_message = ""
- for ele in calibre_traceback:
- if not ele.startswith('Traceback') and not ele.startswith(' File'):
- error_message = N_("Calibre failed with error: %(error)s", error=ele)
- return check, error_message
- quotes = [1, 2, 4, 6]
- command = [config.config_converterpath, (file_path + format_old_ext),
- (file_path + format_new_ext)]
- if config.config_embed_metadata:
- command.extend(['--from-opf', path_tmp_opf])
- if has_cover:
- command.extend(['--cover', os.path.join(os.path.dirname(file_path), 'cover.jpg')])
- quotes_index = 3
- if config.config_calibre:
- parameters = config.config_calibre.split(" ")
- for param in parameters:
- command.append(param)
- quotes.append(quotes_index)
- quotes_index += 1
-
- p = process_open(command, quotes, newlines=False)
- except OSError as e:
- return 1, N_("Ebook-converter failed: %(error)s", error=e)
-
- while p.poll() is None:
- nextline = p.stdout.readline()
- if isinstance(nextline, bytes):
- nextline = nextline.decode('utf-8', errors="ignore").strip('\r\n')
- if nextline:
- log.debug(nextline)
- # parse progress string from calibre-converter
- progress = re.search(r"(\d+)%\s.*", nextline)
- if progress:
- self.progress = int(progress.group(1)) / 100
- if config.config_use_google_drive:
- self.progress *= 0.9
-
- # process returncode
- check = p.returncode
- calibre_traceback = p.stderr.readlines()
- error_message = ""
- for ele in calibre_traceback:
- ele = ele.decode('utf-8', errors="ignore").strip('\n')
- log.debug(ele)
- if not ele.startswith('Traceback') and not ele.startswith(' File'):
- error_message = N_("Calibre failed with error: %(error)s", error=ele)
- return check, error_message
-
- @property
- def name(self):
- return N_("Convert")
-
- def __str__(self):
- if self.ereader_mail:
- return "Convert Book {} and mail it to {}".format(self.book_id, self.ereader_mail)
- else:
- return "Convert Book {}".format(self.book_id)
-
- @property
- def is_cancellable(self):
- return False
+# -*- coding: utf-8 -*-
+
+# This file is part of the Calibre-Web (https://github.com/janeczku/calibre-web)
+# Copyright (C) 2020 pwr
+#
+# 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 .
+
+import os
+import re
+import glob
+from shutil import copyfile, copyfileobj
+from markupsafe import escape
+from time import time
+from uuid import uuid4
+
+from sqlalchemy.exc import SQLAlchemyError
+from flask_babel import lazy_gettext as N_
+
+from cps.services.worker import CalibreTask
+from cps import db, app
+from cps import logger, config
+from cps.subproc_wrapper import process_open
+from flask_babel import gettext as _
+from cps.kobo_sync_status import remove_synced_book
+from cps.ub import init_db_thread
+from cps.file_helper import get_temp_dir
+
+from cps.tasks.mail import TaskEmail
+from cps import gdriveutils, helper
+from cps.constants import SUPPORTED_CALIBRE_BINARIES
+from cps.string_helper import strip_whitespaces
+
+log = logger.create()
+
+current_milli_time = lambda: int(round(time() * 1000))
+
+
+class TaskConvert(CalibreTask):
+ def __init__(self, file_path, book_id, task_message, settings, ereader_mail, user=None):
+ super(TaskConvert, self).__init__(task_message)
+ self.worker_thread = None
+ self.file_path = file_path
+ self.book_id = book_id
+ self.title = ""
+ self.settings = settings
+ self.ereader_mail = ereader_mail
+ self.user = user
+
+ self.results = dict()
+
+ def run(self, worker_thread):
+ df_cover = None
+ cur_book = None
+ self.worker_thread = worker_thread
+ if config.config_use_google_drive:
+ with app.app_context():
+ worker_db = db.CalibreDB(app)
+ cur_book = worker_db.get_book(self.book_id)
+ self.title = cur_book.title
+ data = worker_db.get_book_format(self.book_id, self.settings['old_book_format'])
+ df = gdriveutils.getFileFromEbooksFolder(cur_book.path,
+ data.name + "." + self.settings['old_book_format'].lower())
+ df_cover = gdriveutils.getFileFromEbooksFolder(cur_book.path, "cover.jpg")
+ if df:
+ datafile_cover = None
+ datafile = os.path.join(config.get_book_path(),
+ cur_book.path,
+ data.name + "." + self.settings['old_book_format'].lower())
+ if df_cover:
+ datafile_cover = os.path.join(config.get_book_path(),
+ cur_book.path, "cover.jpg")
+ if not os.path.exists(os.path.join(config.get_book_path(), cur_book.path)):
+ os.makedirs(os.path.join(config.get_book_path(), cur_book.path))
+ df.GetContentFile(datafile)
+ if df_cover:
+ df_cover.GetContentFile(datafile_cover)
+ # worker_db.session.close()
+ else:
+ # ToDo Include cover in error handling
+ error_message = _("%(format)s not found on Google Drive: %(fn)s",
+ format=self.settings['old_book_format'],
+ fn=data.name + "." + self.settings['old_book_format'].lower())
+ # worker_db.session.close()
+ return self._handleError(error_message)
+
+ filename = self._convert_ebook_format()
+ if config.config_use_google_drive:
+ os.remove(self.file_path + '.' + self.settings['old_book_format'].lower())
+ if df_cover:
+ os.remove(os.path.join(config.config_calibre_dir, cur_book.path, "cover.jpg"))
+
+ if filename:
+ if config.config_use_google_drive:
+ # Upload files to gdrive
+ gdriveutils.updateGdriveCalibreFromLocal()
+ self._handleSuccess()
+ if self.ereader_mail:
+ # if we're sending to E-Reader after converting, create a one-off task and run it immediately
+ # todo: figure out how to incorporate this into the progress
+ try:
+ EmailText = N_(u"%(book)s send to E-Reader", book=escape(self.title))
+ for email in self.ereader_mail.split(','):
+ email = strip_whitespaces(email)
+ worker_thread.add(self.user, TaskEmail(self.settings['subject'],
+ self.results["path"],
+ filename,
+ self.settings,
+ email,
+ EmailText,
+ self.settings['body'],
+ id=self.book_id,
+ internal=True)
+ )
+ except Exception as ex:
+ return self._handleError(str(ex))
+
+ def _convert_ebook_format(self):
+ error_message = None
+ with app.app_context():
+ local_db = db.CalibreDB(app)
+ file_path = self.file_path
+ book_id = self.book_id
+ format_old_ext = '.' + self.settings['old_book_format'].lower()
+ format_new_ext = '.' + self.settings['new_book_format'].lower()
+
+ # check to see if destination format already exists - or if book is in database
+ # if it does - mark the conversion task as complete and return a success
+ # this will allow to send to E-Reader workflow to continue to work
+ if os.path.isfile(file_path + format_new_ext) or\
+ local_db.get_book_format(self.book_id, self.settings['new_book_format']):
+ log.info("Book id %d already converted to %s", book_id, format_new_ext)
+ cur_book = local_db.get_book(book_id)
+ self.title = cur_book.title
+ self.results['path'] = cur_book.path
+ self.results['title'] = self.title
+ new_format = local_db.session.query(db.Data).filter(db.Data.book == book_id)\
+ .filter(db.Data.format == self.settings['new_book_format'].upper()).one_or_none()
+ if not new_format:
+ new_format = db.Data(name=os.path.basename(file_path),
+ book_format=self.settings['new_book_format'].upper(),
+ book=book_id, uncompressed_size=os.path.getsize(file_path + format_new_ext))
+ try:
+ local_db.session.merge(new_format)
+ local_db.session.commit()
+ except SQLAlchemyError as e:
+ local_db.session.rollback()
+ log.error("Database error: %s", e)
+ local_db.session.close()
+ self._handleError(N_("Oops! Database Error: %(error)s.", error=e))
+ return
+ self._handleSuccess()
+ local_db.session.close()
+ return os.path.basename(file_path + format_new_ext)
+ else:
+ log.info("Book id %d - target format of %s does not exist. Moving forward with convert.",
+ book_id,
+ format_new_ext)
+
+ if config.config_kepubifypath and format_old_ext == '.epub' and format_new_ext == '.kepub':
+ check, error_message = self._convert_kepubify(file_path,
+ format_old_ext,
+ format_new_ext)
+ else:
+ # check if calibre converter-executable is existing
+ if not os.path.exists(config.config_converterpath):
+ self._handleError(N_("Calibre ebook-convert %(tool)s not found", tool=config.config_converterpath))
+ return
+ has_cover = local_db.get_book(book_id).has_cover
+ check, error_message = self._convert_calibre(file_path, format_old_ext, format_new_ext, has_cover)
+
+ if check == 0:
+ cur_book = local_db.get_book(book_id)
+ if os.path.isfile(file_path + format_new_ext):
+ new_format = local_db.session.query(db.Data).filter(db.Data.book == book_id) \
+ .filter(db.Data.format == self.settings['new_book_format'].upper()).one_or_none()
+ if not new_format:
+ new_format = db.Data(name=cur_book.data[0].name,
+ book_format=self.settings['new_book_format'].upper(),
+ book=book_id, uncompressed_size=os.path.getsize(file_path + format_new_ext))
+ try:
+ local_db.session.merge(new_format)
+ local_db.session.commit()
+ if self.settings['new_book_format'].upper() in ['KEPUB', 'EPUB', 'EPUB3']:
+ ub_session = init_db_thread()
+ remove_synced_book(book_id, True, ub_session)
+ ub_session.close()
+ except SQLAlchemyError as e:
+ local_db.session.rollback()
+ log.error("Database error: %s", e)
+ local_db.session.close()
+ self._handleError(error_message)
+ return
+ self.results['path'] = cur_book.path
+ self.title = cur_book.title
+ self.results['title'] = self.title
+ if not config.config_use_google_drive:
+ self._handleSuccess()
+ return os.path.basename(file_path + format_new_ext)
+ else:
+ error_message = N_('%(format)s format not found on disk', format=format_new_ext.upper())
+ local_db.session.close()
+ log.info("ebook converter failed with error while converting book")
+ if not error_message:
+ error_message = N_('Ebook converter failed with unknown error')
+ else:
+ log.error(error_message)
+ self._handleError(error_message)
+ return
+
+ def _convert_kepubify(self, file_path, format_old_ext, format_new_ext):
+ if config.config_embed_metadata and config.config_binariesdir:
+ tmp_dir, temp_file_name = helper.do_calibre_export(self.book_id, format_old_ext[1:])
+ filename = os.path.join(tmp_dir, temp_file_name + format_old_ext)
+ temp_file_path = tmp_dir
+ else:
+ filename = file_path + format_old_ext
+ temp_file_path = os.path.dirname(file_path)
+ quotes = [1, 3]
+ command = [config.config_kepubifypath, filename, '-o', temp_file_path, '-i']
+ try:
+ p = process_open(command, quotes)
+ except OSError as e:
+ return 1, N_("Kepubify-converter failed: %(error)s", error=e)
+ self.progress = 0.01
+ while True:
+ nextline = p.stdout.readlines()
+ nextline = [x.strip('\n') for x in nextline if x != '\n']
+ for line in nextline:
+ log.debug(line)
+ if p.poll() is not None:
+ break
+
+ # process returncode
+ check = p.returncode
+
+ # move file
+ if check == 0:
+ converted_file = glob.glob(glob.escape(os.path.splitext(filename)[0]) + "*.kepub.epub")
+ if len(converted_file) == 1:
+ copyfile(converted_file[0], (file_path + format_new_ext))
+ os.unlink(converted_file[0])
+ else:
+ return 1, N_("Converted file not found or more than one file in folder %(folder)s",
+ folder=os.path.dirname(file_path))
+ return check, None
+
+ def _convert_calibre(self, file_path, format_old_ext, format_new_ext, has_cover):
+ path_tmp_opf = None
+ try:
+ # path_tmp_opf = self._embed_metadata()
+ if config.config_embed_metadata:
+ quotes = [5]
+ tmp_dir = get_temp_dir()
+ calibredb_binarypath = os.path.join(config.config_binariesdir, SUPPORTED_CALIBRE_BINARIES["calibredb"])
+ my_env = os.environ.copy()
+ if config.config_calibre_split:
+ my_env['CALIBRE_OVERRIDE_DATABASE_PATH'] = os.path.join(config.config_calibre_dir, "metadata.db")
+ library_path = config.config_calibre_split_dir
+ else:
+ library_path = config.config_calibre_dir
+
+ opf_command = [calibredb_binarypath, 'show_metadata', '--as-opf', str(self.book_id),
+ '--with-library', library_path]
+ p = process_open(opf_command, quotes, my_env, newlines=False)
+ lines = list()
+ while p.poll() is None:
+ lines.append(p.stdout.readline())
+ check = p.returncode
+ calibre_traceback = p.stderr.readlines()
+ if check == 0:
+ path_tmp_opf = os.path.join(tmp_dir, "metadata_" + str(uuid4()) + ".opf")
+ with open(path_tmp_opf, 'wb') as fd:
+ fd.write(b''.join(lines))
+ else:
+ error_message = ""
+ for ele in calibre_traceback:
+ if not ele.startswith('Traceback') and not ele.startswith(' File'):
+ error_message = N_("Calibre failed with error: %(error)s", error=ele)
+ return check, error_message
+ quotes = [1, 2]
+ quotes_index = 3
+ command = [config.config_converterpath, (file_path + format_old_ext),
+ (file_path + format_new_ext)]
+ if config.config_embed_metadata:
+ quotes.append(4)
+ quotes_index = 5
+ command.extend(['--from-opf', path_tmp_opf])
+ if has_cover:
+ quotes.append(6)
+ command.extend(['--cover', os.path.join(os.path.dirname(file_path), 'cover.jpg')])
+ quotes_index = 7
+ if config.config_calibre:
+ parameters = re.findall(r"(--[\w-]+)(?:(\s(?:(\".+\")|(?:.+?)))(?:\s|$))?",
+ config.config_calibre, re.IGNORECASE | re.UNICODE)
+ if parameters:
+ for param in parameters:
+ command.append(strip_whitespaces(param[0]))
+ quotes_index += 1
+ if param[1] != "":
+ parsed = strip_whitespaces(param[1]).strip("\"")
+ command.append(parsed)
+ quotes.append(quotes_index)
+ quotes_index += 1
+ p = process_open(command, quotes, newlines=False)
+ except OSError as e:
+ return 1, N_("Ebook-converter failed: %(error)s", error=e)
+
+ while p.poll() is None:
+ nextline = p.stdout.readline()
+ if isinstance(nextline, bytes):
+ nextline = nextline.decode('utf-8', errors="ignore").strip('\r\n')
+ if nextline:
+ log.debug(nextline)
+ # parse progress string from calibre-converter
+ progress = re.search(r"(\d+)%\s.*", nextline)
+ if progress:
+ self.progress = int(progress.group(1)) / 100
+ if config.config_use_google_drive:
+ self.progress *= 0.9
+
+ # process returncode
+ check = p.returncode
+ calibre_traceback = p.stderr.readlines()
+ error_message = ""
+ for ele in calibre_traceback:
+ ele = ele.decode('utf-8', errors="ignore").strip('\n')
+ log.debug(ele)
+ if not ele.startswith('Traceback') and not ele.startswith(' File'):
+ error_message = N_("Calibre failed with error: %(error)s", error=ele)
+ return check, error_message
+
+ @property
+ def name(self):
+ return N_("Convert")
+
+ def __str__(self):
+ if self.ereader_mail:
+ return "Convert Book {} and mail it to {}".format(self.book_id, self.ereader_mail)
+ else:
+ return "Convert Book {}".format(self.book_id)
+
+ @property
+ def is_cancellable(self):
+ return False
diff --git a/cps/tasks/database.py b/cps/tasks/database.py
index c9c30d43..e5f630c6 100644
--- a/cps/tasks/database.py
+++ b/cps/tasks/database.py
@@ -18,7 +18,7 @@
from flask_babel import lazy_gettext as N_
-from cps import config, logger, db, ub
+from cps import config, logger, db, ub, app
from cps.services.worker import CalibreTask
@@ -26,11 +26,13 @@ class TaskReconnectDatabase(CalibreTask):
def __init__(self, task_message=N_('Reconnecting Calibre database')):
super(TaskReconnectDatabase, self).__init__(task_message)
self.log = logger.create()
- self.calibre_db = db.CalibreDB(expire_on_commit=False, init=True)
+ # self.calibre_db = db.CalibreDB(expire_on_commit=False, init=True)
def run(self, worker_thread):
- self.calibre_db.reconnect_db(config, ub.app_DB_path)
- self.calibre_db.session.close()
+ with app.app_context():
+ calibre_db = db.CalibreDB(app)
+ calibre_db.reconnect_db(config, ub.app_DB_path)
+ # self.calibre_db.session.close()
self._handleSuccess()
@property
diff --git a/cps/tasks/mail.py b/cps/tasks/mail.py
index 4f85eefa..707a29a3 100644
--- a/cps/tasks/mail.py
+++ b/cps/tasks/mail.py
@@ -25,7 +25,7 @@ import mimetypes
from io import StringIO
from email.message import EmailMessage
-from email.utils import formatdate, parseaddr
+from email.utils import formatdate, parseaddr, make_msgid
from email.generator import Generator
from flask_babel import lazy_gettext as N_
@@ -34,7 +34,8 @@ from cps.services import gmail
from cps.embed_helper import do_calibre_export
from cps import logger, config
from cps import gdriveutils
-import uuid
+from cps.string_helper import strip_whitespaces
+
log = logger.create()
@@ -54,8 +55,8 @@ class EmailBase:
return (code, resp)
def send(self, strg):
- """Send `strg' to the server."""
- log.debug_no_auth('send: {}'.format(strg[:300]))
+ """Send 'strg' to the server."""
+ log.debug_no_auth('send: {}'.format(strg[:300]), stacklevel=2)
if hasattr(self, 'sock') and self.sock:
try:
if self.transferSize:
@@ -101,7 +102,7 @@ class Email(EmailBase, smtplib.SMTP):
smtplib.SMTP.__init__(self, *args, **kwargs)
-# Class for sending ssl encrypted email with ability to get current progress, , derived from emailbase class
+# Class for sending ssl encrypted email with ability to get current progress, derived from emailbase class
class EmailSSL(EmailBase, smtplib.SMTP_SSL):
def __init__(self, *args, **kwargs):
@@ -127,9 +128,9 @@ class TaskEmail(CalibreTask):
try:
# Parse out the address from the From line, and then the domain from that
from_email = parseaddr(self.settings["mail_from"])[1]
- msgid_domain = from_email.partition('@')[2].strip()
+ msgid_domain = strip_whitespaces(from_email.partition('@')[2])
# This can sometimes sneak through parseaddr if the input is malformed
- msgid_domain = msgid_domain.rstrip('>').strip()
+ msgid_domain = strip_whitespaces(msgid_domain.rstrip('>'))
except Exception:
msgid_domain = ''
return msgid_domain or 'calibre-web.com'
@@ -141,7 +142,7 @@ class TaskEmail(CalibreTask):
message['To'] = self.recipient
message['Subject'] = self.subject
message['Date'] = formatdate(localtime=True)
- message['Message-Id'] = "{}@{}".format(uuid.uuid4(), self.get_msgid_domain())
+ message['Message-ID'] = make_msgid(domain=self.get_msgid_domain())
message.set_content(self.text.encode('UTF-8'), "text", "plain")
if self.attachment:
data = self._get_attachment(self.filepath, self.attachment)
@@ -168,10 +169,14 @@ class TaskEmail(CalibreTask):
else:
self.send_gmail_email(msg)
except MemoryError as e:
- log.error_or_exception(e, stacklevel=3)
+ log.error_or_exception(e, stacklevel=2)
self._handleError('MemoryError sending e-mail: {}'.format(str(e)))
+ except (smtplib.SMTPRecipientsRefused) as e:
+ log.error_or_exception(e, stacklevel=2)
+ self._handleError('Smtplib Error sending e-mail: {}'.format(
+ (list(e.args[0].values())[0][1]).decode('utf-8)').replace("\n", '. ')))
except (smtplib.SMTPException, smtplib.SMTPAuthenticationError) as e:
- log.error_or_exception(e, stacklevel=3)
+ log.error_or_exception(e, stacklevel=2)
if hasattr(e, "smtp_error"):
text = e.smtp_error.decode('utf-8').replace("\n", '. ')
elif hasattr(e, "message"):
@@ -182,10 +187,10 @@ class TaskEmail(CalibreTask):
text = ''
self._handleError('Smtplib Error sending e-mail: {}'.format(text))
except (socket.error) as e:
- log.error_or_exception(e, stacklevel=3)
+ log.error_or_exception(e, stacklevel=2)
self._handleError('Socket Error sending e-mail: {}'.format(e.strerror))
except Exception as ex:
- log.error_or_exception(ex, stacklevel=3)
+ log.error_or_exception(ex, stacklevel=2)
self._handleError('Error sending e-mail: {}'.format(ex))
def send_standard_email(self, msg):
@@ -268,7 +273,7 @@ class TaskEmail(CalibreTask):
if config.config_binariesdir and config.config_embed_metadata:
os.remove(datafile)
except IOError as e:
- log.error_or_exception(e, stacklevel=3)
+ log.error_or_exception(e, stacklevel=2)
log.error('The requested file could not be read. Maybe wrong permissions?')
return None
return data
diff --git a/cps/tasks/metadata_backup.py b/cps/tasks/metadata_backup.py
index 5e0bb96a..048fcf7c 100644
--- a/cps/tasks/metadata_backup.py
+++ b/cps/tasks/metadata_backup.py
@@ -19,7 +19,7 @@
import os
from lxml import etree
-from cps import config, db, gdriveutils, logger
+from cps import config, db, gdriveutils, logger, app
from cps.services.worker import CalibreTask
from flask_babel import lazy_gettext as N_
@@ -34,7 +34,7 @@ class TaskBackupMetadata(CalibreTask):
task_message=N_('Backing up Metadata')):
super(TaskBackupMetadata, self).__init__(task_message)
self.log = logger.create()
- self.calibre_db = db.CalibreDB(expire_on_commit=False, init=True)
+ # self.calibre_db = db.CalibreDB(expire_on_commit=False, init=True)
self.export_language = export_language
self.translated_title = translated_title
self.set_dirty = set_dirty
@@ -46,47 +46,51 @@ class TaskBackupMetadata(CalibreTask):
self.backup_metadata()
def set_all_books_dirty(self):
- try:
- books = self.calibre_db.session.query(db.Books).all()
- for book in books:
- self.calibre_db.set_metadata_dirty(book.id)
- self.calibre_db.session.commit()
- self._handleSuccess()
- except Exception as ex:
- self.log.debug('Error adding book for backup: ' + str(ex))
- self._handleError('Error adding book for backup: ' + str(ex))
- self.calibre_db.session.rollback()
- self.calibre_db.session.close()
+ with app.app_context():
+ calibre_dbb = db.CalibreDB(app)
+ try:
+ books = calibre_dbb.session.query(db.Books).all()
+ for book in books:
+ calibre_dbb.set_metadata_dirty(book.id)
+ calibre_dbb.session.commit()
+ self._handleSuccess()
+ except Exception as ex:
+ self.log.debug('Error adding book for backup: ' + str(ex))
+ self._handleError('Error adding book for backup: ' + str(ex))
+ calibre_dbb.session.rollback()
+ # self.calibre_db.session.close()
def backup_metadata(self):
- try:
- metadata_backup = self.calibre_db.session.query(db.Metadata_Dirtied).all()
- custom_columns = (self.calibre_db.session.query(db.CustomColumns)
- .filter(db.CustomColumns.mark_for_delete == 0)
- .filter(db.CustomColumns.datatype.notin_(db.cc_exceptions))
- .order_by(db.CustomColumns.label).all())
- count = len(metadata_backup)
- i = 0
- for backup in metadata_backup:
- book = self.calibre_db.session.query(db.Books).filter(db.Books.id == backup.book).one_or_none()
- self.calibre_db.session.query(db.Metadata_Dirtied).filter(
- db.Metadata_Dirtied.book == backup.book).delete()
- self.calibre_db.session.commit()
- if book:
- self.open_metadata(book, custom_columns)
- else:
- self.log.error("Book {} not found in database".format(backup.book))
- i += 1
- self.progress = (1.0 / count) * i
- self._handleSuccess()
- self.calibre_db.session.close()
+ with app.app_context():
+ try:
+ calibre_dbb = db.CalibreDB(app)
+ metadata_backup = calibre_dbb.session.query(db.Metadata_Dirtied).all()
+ custom_columns = (calibre_dbb.session.query(db.CustomColumns)
+ .filter(db.CustomColumns.mark_for_delete == 0)
+ .filter(db.CustomColumns.datatype.notin_(db.cc_exceptions))
+ .order_by(db.CustomColumns.label).all())
+ count = len(metadata_backup)
+ i = 0
+ for backup in metadata_backup:
+ book = calibre_dbb.session.query(db.Books).filter(db.Books.id == backup.book).one_or_none()
+ calibre_dbb.session.query(db.Metadata_Dirtied).filter(
+ db.Metadata_Dirtied.book == backup.book).delete()
+ calibre_dbb.session.commit()
+ if book:
+ self.open_metadata(book, custom_columns)
+ else:
+ self.log.error("Book {} not found in database".format(backup.book))
+ i += 1
+ self.progress = (1.0 / count) * i
+ self._handleSuccess()
+ # self.calibre_db.session.close()
- except Exception as ex:
- b = "NaN" if not hasattr(book, 'id') else book.id
- self.log.debug('Error creating metadata backup for book {}: '.format(b) + str(ex))
- self._handleError('Error creating metadata backup: ' + str(ex))
- self.calibre_db.session.rollback()
- self.calibre_db.session.close()
+ except Exception as ex:
+ b = "NaN" if not hasattr(book, 'id') else book.id
+ self.log.debug('Error creating metadata backup for book {}: '.format(b) + str(ex))
+ self._handleError('Error creating metadata backup: ' + str(ex))
+ calibre_dbb.session.rollback()
+ # self.calibre_db.session.close()
def open_metadata(self, book, custom_columns):
# package = self.create_new_metadata_backup(book, custom_columns)
diff --git a/cps/tasks/thumbnail.py b/cps/tasks/thumbnail.py
index d2179dd9..358f4ad1 100644
--- a/cps/tasks/thumbnail.py
+++ b/cps/tasks/thumbnail.py
@@ -20,11 +20,11 @@ import os
from shutil import copyfile, copyfileobj
from urllib.request import urlopen
from io import BytesIO
+from datetime import datetime, timezone
from .. import constants
-from cps import config, db, fs, gdriveutils, logger, ub
+from cps import config, db, fs, gdriveutils, logger, ub, app
from cps.services.worker import CalibreTask, STAT_CANCELLED, STAT_ENDED
-from datetime import datetime
from sqlalchemy import func, text, or_
from flask_babel import lazy_gettext as N_
@@ -36,7 +36,7 @@ except (ImportError, RuntimeError) as e:
def get_resize_height(resolution):
- return int(225 * resolution)
+ return int(255 * resolution)
def get_resize_width(resolution, original_width, original_height):
@@ -73,7 +73,8 @@ class TaskGenerateCoverThumbnails(CalibreTask):
self.cache = fs.FileSystem()
self.resolutions = [
constants.COVER_THUMBNAIL_SMALL,
- constants.COVER_THUMBNAIL_MEDIUM
+ constants.COVER_THUMBNAIL_MEDIUM,
+ constants.COVER_THUMBNAIL_LARGE
]
def run(self, worker_thread):
@@ -113,9 +114,10 @@ class TaskGenerateCoverThumbnails(CalibreTask):
@staticmethod
def get_books_with_covers(book_id=-1):
filter_exp = (db.Books.id == book_id) if book_id != -1 else True
- calibre_db = db.CalibreDB(expire_on_commit=False, init=True)
- books_cover = calibre_db.session.query(db.Books).filter(db.Books.has_cover == 1).filter(filter_exp).all()
- calibre_db.session.close()
+ with app.app_context():
+ calibre_db = db.CalibreDB(app) #, expire_on_commit=False, init=True)
+ books_cover = calibre_db.session.query(db.Books).filter(db.Books.has_cover == 1).filter(filter_exp).all()
+ # calibre_db.session.close()
return books_cover
def get_book_cover_thumbnails(self, book_id):
@@ -123,7 +125,7 @@ class TaskGenerateCoverThumbnails(CalibreTask):
.query(ub.Thumbnail) \
.filter(ub.Thumbnail.type == constants.THUMBNAIL_TYPE_COVER) \
.filter(ub.Thumbnail.entity_id == book_id) \
- .filter(or_(ub.Thumbnail.expiration.is_(None), ub.Thumbnail.expiration > datetime.utcnow())) \
+ .filter(or_(ub.Thumbnail.expiration.is_(None), ub.Thumbnail.expiration > datetime.now(timezone.utc))) \
.all()
def create_book_cover_thumbnails(self, book):
@@ -165,7 +167,7 @@ class TaskGenerateCoverThumbnails(CalibreTask):
self.app_db_session.rollback()
def update_book_cover_thumbnail(self, book, thumbnail):
- thumbnail.generated_at = datetime.utcnow()
+ thumbnail.generated_at = datetime.now(timezone.utc)
try:
self.app_db_session.commit()
@@ -197,9 +199,11 @@ class TaskGenerateCoverThumbnails(CalibreTask):
img.format = thumbnail.format
img.save(filename=filename)
else:
- with open(filename, 'rb') as fd:
+ stream.seek(0)
+ with open(filename, 'wb') as fd:
copyfileobj(stream, fd)
+
except Exception as ex:
# Bubble exception to calling function
self.log.debug('Error generating thumbnail file: ' + str(ex))
@@ -244,7 +248,7 @@ class TaskGenerateSeriesThumbnails(CalibreTask):
super(TaskGenerateSeriesThumbnails, self).__init__(task_message)
self.log = logger.create()
self.app_db_session = ub.get_new_session_instance()
- self.calibre_db = db.CalibreDB(expire_on_commit=False, init=True)
+ # self.calibre_db = db.CalibreDB(expire_on_commit=False, init=True)
self.cache = fs.FileSystem()
self.resolutions = [
constants.COVER_THUMBNAIL_SMALL,
@@ -252,58 +256,60 @@ class TaskGenerateSeriesThumbnails(CalibreTask):
]
def run(self, worker_thread):
- if self.calibre_db.session and use_IM and self.stat != STAT_CANCELLED and self.stat != STAT_ENDED:
- self.message = 'Scanning Series'
- all_series = self.get_series_with_four_plus_books()
- count = len(all_series)
+ with app.app_context():
+ calibre_db = db.CalibreDB(app)
+ if calibre_db.session and use_IM and self.stat != STAT_CANCELLED and self.stat != STAT_ENDED:
+ self.message = 'Scanning Series'
+ all_series = self.get_series_with_four_plus_books(calibre_db)
+ count = len(all_series)
- total_generated = 0
- for i, series in enumerate(all_series):
- generated = 0
- series_thumbnails = self.get_series_thumbnails(series.id)
- series_books = self.get_series_books(series.id)
+ total_generated = 0
+ for i, series in enumerate(all_series):
+ generated = 0
+ series_thumbnails = self.get_series_thumbnails(series.id)
+ series_books = self.get_series_books(series.id, calibre_db)
- # Generate new thumbnails for missing covers
- resolutions = list(map(lambda t: t.resolution, series_thumbnails))
- missing_resolutions = list(set(self.resolutions).difference(resolutions))
- for resolution in missing_resolutions:
- generated += 1
- self.create_series_thumbnail(series, series_books, resolution)
-
- # Replace outdated or missing thumbnails
- for thumbnail in series_thumbnails:
- if any(book.last_modified > thumbnail.generated_at for book in series_books):
+ # Generate new thumbnails for missing covers
+ resolutions = list(map(lambda t: t.resolution, series_thumbnails))
+ missing_resolutions = list(set(self.resolutions).difference(resolutions))
+ for resolution in missing_resolutions:
generated += 1
- self.update_series_thumbnail(series_books, thumbnail)
+ self.create_series_thumbnail(series, series_books, resolution)
- elif not self.cache.get_cache_file_exists(thumbnail.filename, constants.CACHE_TYPE_THUMBNAILS):
- generated += 1
- self.update_series_thumbnail(series_books, thumbnail)
+ # Replace outdated or missing thumbnails
+ for thumbnail in series_thumbnails:
+ if any(book.last_modified > thumbnail.generated_at for book in series_books):
+ generated += 1
+ self.update_series_thumbnail(series_books, thumbnail)
- # Increment the progress
- self.progress = (1.0 / count) * i
+ elif not self.cache.get_cache_file_exists(thumbnail.filename, constants.CACHE_TYPE_THUMBNAILS):
+ generated += 1
+ self.update_series_thumbnail(series_books, thumbnail)
- if generated > 0:
- total_generated += generated
- self.message = N_('Generated {0} series thumbnails').format(total_generated)
+ # Increment the progress
+ self.progress = (1.0 / count) * i
- # Check if job has been cancelled or ended
- if self.stat == STAT_CANCELLED:
- self.log.info(f'GenerateSeriesThumbnails task has been cancelled.')
- return
+ if generated > 0:
+ total_generated += generated
+ self.message = N_('Generated {0} series thumbnails').format(total_generated)
- if self.stat == STAT_ENDED:
- self.log.info(f'GenerateSeriesThumbnails task has been ended.')
- return
+ # Check if job has been cancelled or ended
+ if self.stat == STAT_CANCELLED:
+ self.log.info(f'GenerateSeriesThumbnails task has been cancelled.')
+ return
- if total_generated == 0:
- self.self_cleanup = True
+ if self.stat == STAT_ENDED:
+ self.log.info(f'GenerateSeriesThumbnails task has been ended.')
+ return
- self._handleSuccess()
- self.app_db_session.remove()
+ if total_generated == 0:
+ self.self_cleanup = True
- def get_series_with_four_plus_books(self):
- return self.calibre_db.session \
+ self._handleSuccess()
+ self.app_db_session.remove()
+
+ def get_series_with_four_plus_books(self, calibre_db):
+ return calibre_db.session \
.query(db.Series) \
.join(db.books_series_link) \
.join(db.Books) \
@@ -312,8 +318,8 @@ class TaskGenerateSeriesThumbnails(CalibreTask):
.having(func.count('book_series_link') > 3) \
.all()
- def get_series_books(self, series_id):
- return self.calibre_db.session \
+ def get_series_books(self, series_id, calibre_db):
+ return calibre_db.session \
.query(db.Books) \
.join(db.books_series_link) \
.join(db.Series) \
@@ -322,12 +328,12 @@ class TaskGenerateSeriesThumbnails(CalibreTask):
.all()
def get_series_thumbnails(self, series_id):
- return self.app_db_session \
- .query(ub.Thumbnail) \
- .filter(ub.Thumbnail.type == constants.THUMBNAIL_TYPE_SERIES) \
- .filter(ub.Thumbnail.entity_id == series_id) \
- .filter(or_(ub.Thumbnail.expiration.is_(None), ub.Thumbnail.expiration > datetime.utcnow())) \
- .all()
+ return (self.app_db_session
+ .query(ub.Thumbnail)
+ .filter(ub.Thumbnail.type == constants.THUMBNAIL_TYPE_SERIES)
+ .filter(ub.Thumbnail.entity_id == series_id)
+ .filter(or_(ub.Thumbnail.expiration.is_(None), ub.Thumbnail.expiration > datetime.now(timezone.utc)))
+ .all())
def create_series_thumbnail(self, series, series_books, resolution):
thumbnail = ub.Thumbnail()
@@ -346,7 +352,7 @@ class TaskGenerateSeriesThumbnails(CalibreTask):
self.app_db_session.rollback()
def update_series_thumbnail(self, series_books, thumbnail):
- thumbnail.generated_at = datetime.utcnow()
+ thumbnail.generated_at = datetime.now(timezone.utc)
try:
self.app_db_session.commit()
@@ -459,13 +465,15 @@ class TaskClearCoverThumbnailCache(CalibreTask):
def run(self, worker_thread):
if self.app_db_session:
- if self.book_id == 0: # delete superfluous thumbnails
- calibre_db = db.CalibreDB(expire_on_commit=False, init=True)
- thumbnails = (calibre_db.session.query(ub.Thumbnail)
- .join(db.Books, ub.Thumbnail.entity_id == db.Books.id, isouter=True)
- .filter(db.Books.id==None)
- .all())
- calibre_db.session.close()
+ # delete superfluous thumbnails
+ if self.book_id == 0:
+ with app.app_context():
+ calibre_db = db.CalibreDB(app)
+ thumbnails = (calibre_db.session.query(ub.Thumbnail)
+ .join(db.Books, ub.Thumbnail.entity_id == db.Books.id, isouter=True)
+ .filter(db.Books.id==None)
+ .all())
+ # calibre_db.session.close()
elif self.book_id > 0: # make sure single book is selected
thumbnails = self.get_thumbnails_for_book(self.book_id)
if self.book_id < 0:
diff --git a/cps/templates/author.html b/cps/templates/author.html
index f7314586..a01bb40b 100644
--- a/cps/templates/author.html
+++ b/cps/templates/author.html
@@ -62,18 +62,16 @@
{{author.name.replace('|',',')|shortentitle(30)}}
{% endif %}
{% endfor %}
- {% for format in entry.Books.data %}
- {% if format.format|lower in g.constants.EXTENSIONS_AUDIO %}
+ {% if entry.Books.data|music %}
- {% endif %}
- {% endfor %}
+ {% endif %}
{% if entry.Books.series.__len__() > 0 %}
{{entry.Books.series[0].name}}
- ({{entry.Books.series_index|formatseriesindex}})
+ ({{entry.Books.series_index|formatfloat(2)}})
{% endif %}
{% if entry.Books.ratings.__len__() > 0 %}
@@ -124,7 +122,7 @@
{{entry.series[0].name}}
- ({{entry.series_index|formatseriesindex}})
+ ({{entry.series_index|formatfloat(2)}})
{% endif %}
diff --git a/cps/templates/basic_detail.html b/cps/templates/basic_detail.html
new file mode 100644
index 00000000..1996497b
--- /dev/null
+++ b/cps/templates/basic_detail.html
@@ -0,0 +1,81 @@
+{% extends "basic_layout.html" %}
+
+{% block body %}
+
+
+
{{ entry.title }}
+
+ {% for author in entry.ordered_authors %}
+
{{ author.name.replace("|",",") }}
+ {% endfor %}
+
+
+
+
 }})
+
+
+{% if current_user.role_download() %}
+ {% if entry.data|length %}
+
+ {% endif %}
+{% endif %}
+
+
Details
+
+{% if entry.series|length > 0 %}
+
{{ _("Book %(index)s of %(range)s", index=entry.series_index | formatfloat(2), range=(entry.series[0].name)|safe) }}
+{% endif %}
+
+{% if entry.languages|length > 0 %}
+
+
+
+ {{_('Language')}}: {% for language in entry.languages %}{{language.language_name}}{% if not loop.last %}, {% endif %}{% endfor %}
+
+
+
+{% endif %}
+
+{% if entry.identifiers|length > 0 %}
+
+
+
+ {% for identifier in entry.identifiers %}
+
{{ identifier.format_type() }}: {{ identifier|escape }}
+ {% endfor %}
+
+
+{% endif %}
+
+{% if entry.publishers|length > 0 %}
+
+
+ {{ _('Publisher') }}:
+ {{ entry.publishers[0].name }}
+
+
+
+{% endif %}
+
+{% if (entry.pubdate|string)[:10] != '0101-01-01' %}
+
+
{{ _('Published') }}: {{ entry.pubdate|formatdate }}
+
+{% endif %}
+
+{% if entry.comments|length > 0 and entry.comments[0].text|length > 0 %}
+
+
{{ _('Description:') }}
+ {{ entry.comments[0].text|safe }}
+
+{% endif %}
+
+{% endblock %}
diff --git a/cps/templates/basic_index.html b/cps/templates/basic_index.html
new file mode 100644
index 00000000..ae88087f
--- /dev/null
+++ b/cps/templates/basic_index.html
@@ -0,0 +1,32 @@
+{% extends "basic_layout.html" %}
+{% block body %}
+
+
+
+{% if entries|length < 1 %}
+
{{_('No Results Found')}}
+{% endif %}
+
+{% for entry in entries %}
+ {% if entry.Books.authors %}
+ {% set author = entry.Books.authors[0].name.replace('|',',')|shortentitle(30) %}
+ {% else %}
+ {% set author = '' %}
+ {% endif %}
+
+ {{ author }} - {{entry.Books.title|shortentitle}}
+
+{% endfor %}
+
+{% endblock %}
diff --git a/cps/templates/basic_layout.html b/cps/templates/basic_layout.html
new file mode 100644
index 00000000..b3000be8
--- /dev/null
+++ b/cps/templates/basic_layout.html
@@ -0,0 +1,47 @@
+
+
+
+
+
{{instance}} | {{title}}
+
+
+
+
+
+
+
+
+ {% if current_user.is_authenticated or g.allow_anonymous %}
+
+
+ {% endif %}
+
+
+
+ {% block body %}
+ {% endblock %}
+
+
+
+
diff --git a/cps/templates/book_edit.html b/cps/templates/book_edit.html
index 57fe701c..615b40c2 100644
--- a/cps/templates/book_edit.html
+++ b/cps/templates/book_edit.html
@@ -47,42 +47,37 @@
{% endif %}
+{% if current_user.role_upload() and g.allow_upload %}
+
+{% endif %}
+