From 5aa5628465d9583833a09c38c2d8861416538305 Mon Sep 17 00:00:00 2001 From: Anthony Stirling <77850077+Frooodle@users.noreply.github.com> Date: Thu, 31 Oct 2024 10:59:51 +0000 Subject: [PATCH 01/23] [bug fix] Update compress-pdf.html (#2138) Update compress-pdf.html --- src/main/resources/templates/misc/compress-pdf.html | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/resources/templates/misc/compress-pdf.html b/src/main/resources/templates/misc/compress-pdf.html index 8c4d3c2f..99dda30d 100644 --- a/src/main/resources/templates/misc/compress-pdf.html +++ b/src/main/resources/templates/misc/compress-pdf.html @@ -20,7 +20,6 @@
-
@@ -53,4 +52,4 @@ - \ No newline at end of file + From 5f7a0537f9381a63f64594b072be59eac9db9917 Mon Sep 17 00:00:00 2001 From: Anthony Stirling <77850077+Frooodle@users.noreply.github.com> Date: Thu, 31 Oct 2024 13:06:12 +0000 Subject: [PATCH 02/23] Update build.gradle --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 51b8bf5f..8302ffdf 100644 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,7 @@ ext { } group = "stirling.software" -version = "0.31.0" +version = "0.31.1" java { // 17 is lowest but we support and recommend 21 From 384c3ee88f8aae63a5984365c992635ab1490a4c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 31 Oct 2024 13:06:55 +0000 Subject: [PATCH 03/23] :floppy_disk: Update Version (#2139) :floppy_disk: Sync Versions > Made via sync_files.yml Co-authored-by: github-actions[bot] --- chart/stirling-pdf/Chart.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/chart/stirling-pdf/Chart.yaml b/chart/stirling-pdf/Chart.yaml index 11b7c861..1aa262e1 100644 --- a/chart/stirling-pdf/Chart.yaml +++ b/chart/stirling-pdf/Chart.yaml @@ -1,5 +1,5 @@ apiVersion: v2 -appVersion: 0.31.0 +appVersion: 0.31.1 description: locally hosted web application that allows you to perform various operations on PDF files home: https://github.com/Stirling-Tools/Stirling-PDF @@ -13,4 +13,4 @@ maintainers: name: stirling-pdf-chart sources: - https://github.com/Stirling-Tools/Stirling-PDF -version: 1.0.0 +version: 1.0.1 From 0e3c9bcc10983d3f48d9edc8c419fe858ab5eac1 Mon Sep 17 00:00:00 2001 From: Anthony Stirling <77850077+Frooodle@users.noreply.github.com> Date: Thu, 31 Oct 2024 14:52:41 +0000 Subject: [PATCH 04/23] Update README.md --- README.md | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 36c7c85f..83c83114 100644 --- a/README.md +++ b/README.md @@ -280,14 +280,44 @@ security: useAsUsername: email # Default is 'email'; custom fields can be used as the username scopes: openid, profile, email # Specify the scopes for which the application will request permissions provider: google # Set this to your OAuth provider's name, e.g., 'google' or 'keycloak' + saml2: + enabled: false # Currently in alpha, not recommended for use yet, enableAlphaFunctionality must be set to true + autoCreateUser: false # set to 'true' to allow auto-creation of non-existing users + blockRegistration: false # set to 'true' to deny login with SSO without prior registration by an admin + registrationId: stirling + idpMetadataUri: https://dev-XXXXXXXX.okta.com/app/externalKey/sso/saml/metadata + idpSingleLogoutUrl: https://dev-XXXXXXXX.okta.com/app/dev-XXXXXXXX_stirlingpdf_1/externalKey/slo/saml + idpSingleLoginUrl: https://dev-XXXXXXXX.okta.com/app/dev-XXXXXXXX_stirlingpdf_1/externalKey/sso/saml + idpIssuer: http://www.okta.com/externalKey + idpCert: classpath:octa.crt + privateKey: classpath:saml-private-key.key + spCert: classpath:saml-public-cert.crt + +enterpriseEdition: + enabled: false # set to 'true' to enable enterprise edition + key: 00000000-0000-0000-0000-000000000000 + CustomMetadata: + autoUpdateMetadata: false # set to 'true' to automatically update metadata with below values + author: username # Supports text such as 'John Doe' or types such as username to autopopulate with users username + creator: Stirling-PDF # Supports text such as 'Company-PDF' + producer: Stirling-PDF # Supports text such as 'Company-PDF' + +legal: + termsAndConditions: https://www.stirlingpdf.com/terms-and-conditions # URL to the terms and conditions of your application (e.g. https://example.com/terms) Empty string to disable or filename to load from local file in static folder + privacyPolicy: https://www.stirlingpdf.com/privacy-policy # URL to the privacy policy of your application (e.g. https://example.com/privacy) Empty string to disable or filename to load from local file in static folder + accessibilityStatement: '' # URL to the accessibility statement of your application (e.g. https://example.com/accessibility) Empty string to disable or filename to load from local file in static folder + cookiePolicy: '' # URL to the cookie policy of your application (e.g. https://example.com/cookie) Empty string to disable or filename to load from local file in static folder + impressum: '' # URL to the impressum of your application (e.g. https://example.com/impressum) Empty string to disable or filename to load from local file in static folder system: - defaultLocale: 'en-US' # Set the default language (e.g. 'de-DE', 'fr-FR', etc) + defaultLocale: en-US # Set the default language (e.g. 'de-DE', 'fr-FR', etc) googlevisibility: false # 'true' to allow Google visibility (via robots.txt), 'false' to disallow enableAlphaFunctionality: false # Set to enable functionality which might need more testing before it fully goes live (This feature might make no changes) - showUpdate: true # see when a new update is available + showUpdate: false # see when a new update is available showUpdateOnlyAdmin: false # Only admins can see when a new update is available, depending on showUpdate it must be set to 'true' customHTMLFiles: false # enable to have files placed in /customFiles/templates override the existing template html files + tessdataDir: /usr/share/tessdata # Path to the directory containing the Tessdata files. This setting is relevant for Windows systems. For Windows users, this path should be adjusted to point to the appropriate directory where the Tessdata files are stored. + enableAnalytics: undefined # Set to 'true' to enable analytics, set to 'false' to disable analytics, for enterprise users this is set to true ui: appName: '' # Application's visible name @@ -300,6 +330,11 @@ endpoints: metrics: enabled: true # 'true' to enable Info APIs (`/api/*`) endpoints, 'false' to disable + +# Automatically Generated Settings (Do Not Edit Directly) +AutomaticallyGenerated: + key: example + UUID: example ``` There is an additional config file ``/configs/custom_settings.yml`` were users familiar with java and spring application.properties can input their own settings on-top of Stirling-PDFs existing ones From c5abb4740368b33f2be51fc0ee7fe6c87906c6d6 Mon Sep 17 00:00:00 2001 From: "Philip H." <47042125+pheiduck@users.noreply.github.com> Date: Thu, 31 Oct 2024 18:45:44 +0100 Subject: [PATCH 05/23] navbar.css: prevent overlapping of elements (#2140) go-pro-link is overlapping the settings button --- src/main/resources/static/css/navbar.css | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/resources/static/css/navbar.css b/src/main/resources/static/css/navbar.css index 659940b9..23fe0e27 100644 --- a/src/main/resources/static/css/navbar.css +++ b/src/main/resources/static/css/navbar.css @@ -329,11 +329,14 @@ span.icon-text::after { } } - .go-pro-link { +.go-pro-link { position: relative; padding: 0.5rem 1rem; transition: all 0.3s ease; - } + z-index: 1; + display: inline-block; + width: auto; +} .go-pro-badge { display: inline-block; @@ -350,4 +353,4 @@ span.icon-text::after { .go-pro-link:hover .go-pro-badge { background-color: #0056b3; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); -} \ No newline at end of file +} From febc3cf48b7bc9dc65bbd01b748b508c33edfa9f Mon Sep 17 00:00:00 2001 From: Anthony Stirling <77850077+Frooodle@users.noreply.github.com> Date: Thu, 31 Oct 2024 17:46:30 +0000 Subject: [PATCH 06/23] Update pull_request_template.md --- .github/pull_request_template.md | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index fd762f6d..349c991d 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -8,6 +8,7 @@ Closes #(issue_number) - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have performed a self-review of my own code +- [ ] I have attached images of the change if it is UI based - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] My changes generate no new warnings - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) From 94702dbafa78747d593729f27370ae3699e2848e Mon Sep 17 00:00:00 2001 From: Eric <71648843+sbplat@users.noreply.github.com> Date: Thu, 31 Oct 2024 16:18:42 -0400 Subject: [PATCH 07/23] fix signature logo not loading and add option to disable it (#2143) * fix signature logo not loading and add option to disable it * Hardening suggestions for Stirling-PDF / fix-sig-logo (#2144) Modernize and secure temp file creation Co-authored-by: pixeebot[bot] <104101892+pixeebot[bot]@users.noreply.github.com> --------- Co-authored-by: pixeebot[bot] <104101892+pixeebot[bot]@users.noreply.github.com> --- .../api/security/CertSignController.java | 27 +++++++++++++------ .../api/security/SignPDFWithCertRequest.java | 3 +++ src/main/resources/messages_en_GB.properties | 1 + src/main/resources/messages_en_US.properties | 1 + .../templates/security/cert-sign.html | 6 ++++- 5 files changed, 29 insertions(+), 9 deletions(-) diff --git a/src/main/java/stirling/software/SPDF/controller/api/security/CertSignController.java b/src/main/java/stirling/software/SPDF/controller/api/security/CertSignController.java index f8e5f25e..27262feb 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/security/CertSignController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/security/CertSignController.java @@ -8,6 +8,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; +import java.nio.file.Files; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; @@ -21,6 +22,7 @@ import java.security.cert.X509Certificate; import java.util.Calendar; import java.util.List; +import org.apache.commons.io.FileUtils; import org.apache.pdfbox.examples.signature.CreateSignatureBase; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDPage; @@ -92,7 +94,7 @@ public class CertSignController { } class CreateSignature extends CreateSignatureBase { - File imageFile; + File logoFile; public CreateSignature(KeyStore keystore, char[] pin) throws KeyStoreException, @@ -102,11 +104,17 @@ public class CertSignController { CertificateException { super(keystore, pin); ClassPathResource resource = new ClassPathResource("static/images/signature.png"); - imageFile = resource.getFile(); + try (InputStream is = resource.getInputStream()) { + logoFile = Files.createTempFile("signature", ".png").toFile(); + FileUtils.copyInputStreamToFile(is, logoFile); + } catch (IOException e) { + logger.error("Failed to load image signature file"); + throw e; + } } public InputStream createVisibleSignature( - PDDocument srcDoc, PDSignature signature, Integer pageNumber, Boolean showImage) + PDDocument srcDoc, PDSignature signature, Integer pageNumber, Boolean showLogo) throws IOException { // modified from org.apache.pdfbox.examples.signature.CreateVisibleSignature2 try (PDDocument doc = new PDDocument()) { @@ -145,7 +153,7 @@ public class CertSignController { widget.setAppearance(appearance); try (PDPageContentStream cs = new PDPageContentStream(doc, appearanceStream)) { - if (showImage) { + if (showLogo) { cs.saveGraphicsState(); PDExtendedGraphicsState extState = new PDExtendedGraphicsState(); extState.setBlendMode(BlendMode.MULTIPLY); @@ -153,7 +161,7 @@ public class CertSignController { cs.setGraphicsStateParameters(extState); cs.transform(Matrix.getScaleInstance(0.08f, 0.08f)); PDImageXObject img = - PDImageXObject.createFromFileByExtension(imageFile, doc); + PDImageXObject.createFromFileByExtension(logoFile, doc); cs.drawImage(img, 100, 0); cs.restoreGraphicsState(); } @@ -219,6 +227,7 @@ public class CertSignController { String location = request.getLocation(); String name = request.getName(); Integer pageNumber = request.getPageNumber() - 1; + Boolean showLogo = request.isShowLogo(); if (certType == null) { throw new IllegalArgumentException("Cert type must be provided"); @@ -258,7 +267,8 @@ public class CertSignController { pageNumber, name, location, - reason); + reason, + showLogo); return WebResponseUtils.boasToWebResponse( baos, Filenames.toSimpleFileName(pdf.getOriginalFilename()).replaceFirst("[.][^.]+$", "") @@ -274,7 +284,8 @@ public class CertSignController { Integer pageNumber, String name, String location, - String reason) { + String reason, + Boolean showLogo) { try (PDDocument doc = pdfDocumentFactory.load(input)) { PDSignature signature = new PDSignature(); signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE); @@ -287,7 +298,7 @@ public class CertSignController { if (showSignature) { SignatureOptions signatureOptions = new SignatureOptions(); signatureOptions.setVisualSignature( - instance.createVisibleSignature(doc, signature, pageNumber, true)); + instance.createVisibleSignature(doc, signature, pageNumber, showLogo)); signatureOptions.setPage(pageNumber); doc.addSignature(signature, instance, signatureOptions); diff --git a/src/main/java/stirling/software/SPDF/model/api/security/SignPDFWithCertRequest.java b/src/main/java/stirling/software/SPDF/model/api/security/SignPDFWithCertRequest.java index d3399db9..6949a95e 100644 --- a/src/main/java/stirling/software/SPDF/model/api/security/SignPDFWithCertRequest.java +++ b/src/main/java/stirling/software/SPDF/model/api/security/SignPDFWithCertRequest.java @@ -50,4 +50,7 @@ public class SignPDFWithCertRequest extends PDFFile { description = "The page number where the signature should be visible. This is required if showSignature is set to true") private Integer pageNumber; + + @Schema(description = "Whether to visually show a signature logo along with the signature") + private boolean showLogo; } diff --git a/src/main/resources/messages_en_GB.properties b/src/main/resources/messages_en_GB.properties index 019930d8..f124bec8 100644 --- a/src/main/resources/messages_en_GB.properties +++ b/src/main/resources/messages_en_GB.properties @@ -750,6 +750,7 @@ certSign.showSig=Show Signature certSign.reason=Reason certSign.location=Location certSign.name=Name +certSign.showLogo=Show Logo certSign.submit=Sign PDF diff --git a/src/main/resources/messages_en_US.properties b/src/main/resources/messages_en_US.properties index bfb5d8e7..2da78640 100644 --- a/src/main/resources/messages_en_US.properties +++ b/src/main/resources/messages_en_US.properties @@ -750,6 +750,7 @@ certSign.showSig=Show Signature certSign.reason=Reason certSign.location=Location certSign.name=Name +certSign.showLogo=Show Logo certSign.submit=Sign PDF diff --git a/src/main/resources/templates/security/cert-sign.html b/src/main/resources/templates/security/cert-sign.html index ab9a755a..e69c4fa1 100644 --- a/src/main/resources/templates/security/cert-sign.html +++ b/src/main/resources/templates/security/cert-sign.html @@ -71,7 +71,11 @@
- + +
+
+ +
From d3dc3e07b20a2d337d31a7dfdbd1db8f0488882c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 31 Oct 2024 20:22:11 +0000 Subject: [PATCH 08/23] Update translation files (#2145) Signed-off-by: GitHub Action Co-authored-by: GitHub Action --- src/main/resources/messages_ar_AR.properties | 1 + src/main/resources/messages_bg_BG.properties | 1 + src/main/resources/messages_ca_CA.properties | 1 + src/main/resources/messages_cs_CZ.properties | 1 + src/main/resources/messages_da_DK.properties | 1 + src/main/resources/messages_de_DE.properties | 1 + src/main/resources/messages_el_GR.properties | 1 + src/main/resources/messages_es_ES.properties | 1 + src/main/resources/messages_eu_ES.properties | 1 + src/main/resources/messages_fr_FR.properties | 1 + src/main/resources/messages_ga_IE.properties | 1 + src/main/resources/messages_hi_IN.properties | 1 + src/main/resources/messages_hr_HR.properties | 1 + src/main/resources/messages_hu_HU.properties | 1 + src/main/resources/messages_id_ID.properties | 1 + src/main/resources/messages_it_IT.properties | 1 + src/main/resources/messages_ja_JP.properties | 1 + src/main/resources/messages_ko_KR.properties | 1 + src/main/resources/messages_nl_NL.properties | 1 + src/main/resources/messages_no_NB.properties | 1 + src/main/resources/messages_pl_PL.properties | 1 + src/main/resources/messages_pt_BR.properties | 1 + src/main/resources/messages_pt_PT.properties | 1 + src/main/resources/messages_ro_RO.properties | 1 + src/main/resources/messages_ru_RU.properties | 1 + src/main/resources/messages_sk_SK.properties | 1 + src/main/resources/messages_sr_LATN_RS.properties | 1 + src/main/resources/messages_sv_SE.properties | 1 + src/main/resources/messages_th_TH.properties | 1 + src/main/resources/messages_tr_TR.properties | 1 + src/main/resources/messages_uk_UA.properties | 1 + src/main/resources/messages_vi_VN.properties | 1 + src/main/resources/messages_zh_CN.properties | 1 + src/main/resources/messages_zh_TW.properties | 1 + 34 files changed, 34 insertions(+) diff --git a/src/main/resources/messages_ar_AR.properties b/src/main/resources/messages_ar_AR.properties index 0a0b4254..fc34aa3f 100644 --- a/src/main/resources/messages_ar_AR.properties +++ b/src/main/resources/messages_ar_AR.properties @@ -750,6 +750,7 @@ certSign.showSig=إظهار التوقيع certSign.reason=السبب certSign.location=الموقع certSign.name=الاسم +certSign.showLogo=Show Logo certSign.submit=توقيع PDF diff --git a/src/main/resources/messages_bg_BG.properties b/src/main/resources/messages_bg_BG.properties index 283b8490..8f9dc2db 100644 --- a/src/main/resources/messages_bg_BG.properties +++ b/src/main/resources/messages_bg_BG.properties @@ -750,6 +750,7 @@ certSign.showSig=Показване на подпис certSign.reason=Причина certSign.location=Местоположение certSign.name=Име +certSign.showLogo=Show Logo certSign.submit=Подпишете PDF diff --git a/src/main/resources/messages_ca_CA.properties b/src/main/resources/messages_ca_CA.properties index 88a70793..8569f410 100644 --- a/src/main/resources/messages_ca_CA.properties +++ b/src/main/resources/messages_ca_CA.properties @@ -750,6 +750,7 @@ certSign.showSig=Mostra la signatura certSign.reason=Motiu certSign.location=Ubicació certSign.name=Nom +certSign.showLogo=Show Logo certSign.submit=Firma PDF diff --git a/src/main/resources/messages_cs_CZ.properties b/src/main/resources/messages_cs_CZ.properties index 6beb4aea..e4920e4f 100644 --- a/src/main/resources/messages_cs_CZ.properties +++ b/src/main/resources/messages_cs_CZ.properties @@ -750,6 +750,7 @@ certSign.showSig=Ukázat podpis certSign.reason=Důvod certSign.location=Umístění certSign.name=Název +certSign.showLogo=Show Logo certSign.submit=Podepsat PDF diff --git a/src/main/resources/messages_da_DK.properties b/src/main/resources/messages_da_DK.properties index 2a670854..47740a2d 100644 --- a/src/main/resources/messages_da_DK.properties +++ b/src/main/resources/messages_da_DK.properties @@ -750,6 +750,7 @@ certSign.showSig=Vis Underskrift certSign.reason=Årsag certSign.location=Placering certSign.name=Navn +certSign.showLogo=Show Logo certSign.submit=Underskriv PDF diff --git a/src/main/resources/messages_de_DE.properties b/src/main/resources/messages_de_DE.properties index 6eb719ba..87dc3f79 100644 --- a/src/main/resources/messages_de_DE.properties +++ b/src/main/resources/messages_de_DE.properties @@ -750,6 +750,7 @@ certSign.showSig=Signatur anzeigen certSign.reason=Grund certSign.location=Standort certSign.name=Name +certSign.showLogo=Show Logo certSign.submit=PDF signieren diff --git a/src/main/resources/messages_el_GR.properties b/src/main/resources/messages_el_GR.properties index 02574333..e6939cf5 100644 --- a/src/main/resources/messages_el_GR.properties +++ b/src/main/resources/messages_el_GR.properties @@ -750,6 +750,7 @@ certSign.showSig=Εμφάνιση Υπογραφής certSign.reason=Αιτία certSign.location=Τοποθεσία certSign.name=Όνομα +certSign.showLogo=Show Logo certSign.submit=Υπογραφή PDF diff --git a/src/main/resources/messages_es_ES.properties b/src/main/resources/messages_es_ES.properties index e5a2556b..a5b9a212 100644 --- a/src/main/resources/messages_es_ES.properties +++ b/src/main/resources/messages_es_ES.properties @@ -750,6 +750,7 @@ certSign.showSig=Mostrar firma certSign.reason=Razón certSign.location=Ubicación certSign.name=Nombre +certSign.showLogo=Show Logo certSign.submit=Firmar PDF diff --git a/src/main/resources/messages_eu_ES.properties b/src/main/resources/messages_eu_ES.properties index 84116338..8bbb78d2 100644 --- a/src/main/resources/messages_eu_ES.properties +++ b/src/main/resources/messages_eu_ES.properties @@ -750,6 +750,7 @@ certSign.showSig=Erakutsi sinadura certSign.reason=Arrazoia certSign.location=Kokalekua certSign.name=Izena +certSign.showLogo=Show Logo certSign.submit=Sinatu PDFa diff --git a/src/main/resources/messages_fr_FR.properties b/src/main/resources/messages_fr_FR.properties index 2918d5f1..ff7277c8 100644 --- a/src/main/resources/messages_fr_FR.properties +++ b/src/main/resources/messages_fr_FR.properties @@ -750,6 +750,7 @@ certSign.showSig=Afficher la signature certSign.reason=Raison certSign.location=Emplacement certSign.name=Nom +certSign.showLogo=Show Logo certSign.submit=Signer diff --git a/src/main/resources/messages_ga_IE.properties b/src/main/resources/messages_ga_IE.properties index ca6839d6..07735d0c 100644 --- a/src/main/resources/messages_ga_IE.properties +++ b/src/main/resources/messages_ga_IE.properties @@ -750,6 +750,7 @@ certSign.showSig=Taispeáin Síniú certSign.reason=Cúis certSign.location=Suíomh certSign.name=Ainm +certSign.showLogo=Show Logo certSign.submit=Sínigh PDF diff --git a/src/main/resources/messages_hi_IN.properties b/src/main/resources/messages_hi_IN.properties index 68a2ee69..65fd2e69 100644 --- a/src/main/resources/messages_hi_IN.properties +++ b/src/main/resources/messages_hi_IN.properties @@ -750,6 +750,7 @@ certSign.showSig=हस्ताक्षर दिखाएं certSign.reason=कारण certSign.location=स्थान certSign.name=नाम +certSign.showLogo=Show Logo certSign.submit=पीडीएफ़ पर हस्ताक्षर करें diff --git a/src/main/resources/messages_hr_HR.properties b/src/main/resources/messages_hr_HR.properties index e39f5282..acc2b3d0 100644 --- a/src/main/resources/messages_hr_HR.properties +++ b/src/main/resources/messages_hr_HR.properties @@ -750,6 +750,7 @@ certSign.showSig=Prikaži potpis certSign.reason=Razlog certSign.location=Mjesto certSign.name=Ime +certSign.showLogo=Show Logo certSign.submit=Potpiši PDF diff --git a/src/main/resources/messages_hu_HU.properties b/src/main/resources/messages_hu_HU.properties index 4dcc0297..50d22e1b 100644 --- a/src/main/resources/messages_hu_HU.properties +++ b/src/main/resources/messages_hu_HU.properties @@ -750,6 +750,7 @@ certSign.showSig=Aláírás megjelenítése certSign.reason=Ok certSign.location=Hely certSign.name=Név +certSign.showLogo=Show Logo certSign.submit=PDF aláírása diff --git a/src/main/resources/messages_id_ID.properties b/src/main/resources/messages_id_ID.properties index 1b79be4d..80611663 100644 --- a/src/main/resources/messages_id_ID.properties +++ b/src/main/resources/messages_id_ID.properties @@ -750,6 +750,7 @@ certSign.showSig=Tampilkan Tanda Tangan certSign.reason=Alasan certSign.location=Lokasi certSign.name=Nama +certSign.showLogo=Show Logo certSign.submit=Tanda tangani PDF diff --git a/src/main/resources/messages_it_IT.properties b/src/main/resources/messages_it_IT.properties index 6c15ecd8..efafe94f 100644 --- a/src/main/resources/messages_it_IT.properties +++ b/src/main/resources/messages_it_IT.properties @@ -750,6 +750,7 @@ certSign.showSig=Mostra firma certSign.reason=Motivo certSign.location=Posizione certSign.name=Nome +certSign.showLogo=Show Logo certSign.submit=Firma PDF diff --git a/src/main/resources/messages_ja_JP.properties b/src/main/resources/messages_ja_JP.properties index f66ad798..992ddcb5 100644 --- a/src/main/resources/messages_ja_JP.properties +++ b/src/main/resources/messages_ja_JP.properties @@ -750,6 +750,7 @@ certSign.showSig=署名を表示 certSign.reason=理由 certSign.location=場所 certSign.name=名前 +certSign.showLogo=Show Logo certSign.submit=PDFに署名 diff --git a/src/main/resources/messages_ko_KR.properties b/src/main/resources/messages_ko_KR.properties index c13a08f2..a26578d2 100644 --- a/src/main/resources/messages_ko_KR.properties +++ b/src/main/resources/messages_ko_KR.properties @@ -750,6 +750,7 @@ certSign.showSig=서명 보기 certSign.reason=이유 certSign.location=위치 certSign.name=이름 +certSign.showLogo=Show Logo certSign.submit=PDF 서명 diff --git a/src/main/resources/messages_nl_NL.properties b/src/main/resources/messages_nl_NL.properties index cbd79df3..cdbfbe71 100644 --- a/src/main/resources/messages_nl_NL.properties +++ b/src/main/resources/messages_nl_NL.properties @@ -750,6 +750,7 @@ certSign.showSig=Toon handtekening certSign.reason=Reden certSign.location=Locatie certSign.name=Naam +certSign.showLogo=Show Logo certSign.submit=PDF ondertekenen diff --git a/src/main/resources/messages_no_NB.properties b/src/main/resources/messages_no_NB.properties index 8515427e..3b174504 100644 --- a/src/main/resources/messages_no_NB.properties +++ b/src/main/resources/messages_no_NB.properties @@ -750,6 +750,7 @@ certSign.showSig=Vis signatur certSign.reason=Årsak certSign.location=Sted certSign.name=Navn +certSign.showLogo=Show Logo certSign.submit=Signer PDF diff --git a/src/main/resources/messages_pl_PL.properties b/src/main/resources/messages_pl_PL.properties index 35cc8758..a384c870 100755 --- a/src/main/resources/messages_pl_PL.properties +++ b/src/main/resources/messages_pl_PL.properties @@ -750,6 +750,7 @@ certSign.showSig=Wyświetl podpis certSign.reason=Organizacja certSign.location=Lokalizacja certSign.name=Nazwa +certSign.showLogo=Show Logo certSign.submit=Podpisz PDF diff --git a/src/main/resources/messages_pt_BR.properties b/src/main/resources/messages_pt_BR.properties index e495bb2b..5cc5c8db 100644 --- a/src/main/resources/messages_pt_BR.properties +++ b/src/main/resources/messages_pt_BR.properties @@ -750,6 +750,7 @@ certSign.showSig=Mostrar Assinatura certSign.reason=Razão certSign.location=Localização certSign.name=Nome +certSign.showLogo=Show Logo certSign.submit=Assinar PDF diff --git a/src/main/resources/messages_pt_PT.properties b/src/main/resources/messages_pt_PT.properties index 847b833c..6ee92eb6 100644 --- a/src/main/resources/messages_pt_PT.properties +++ b/src/main/resources/messages_pt_PT.properties @@ -750,6 +750,7 @@ certSign.showSig=Mostrar Assinatura certSign.reason=Razão certSign.location=Localização certSign.name=Nome +certSign.showLogo=Show Logo certSign.submit=Assinar PDF diff --git a/src/main/resources/messages_ro_RO.properties b/src/main/resources/messages_ro_RO.properties index 8936dbb6..3d1f7d47 100644 --- a/src/main/resources/messages_ro_RO.properties +++ b/src/main/resources/messages_ro_RO.properties @@ -750,6 +750,7 @@ certSign.showSig=Afișează semnătura certSign.reason=Motivul certSign.location=Locația certSign.name=Numele +certSign.showLogo=Show Logo certSign.submit=Semnează PDF diff --git a/src/main/resources/messages_ru_RU.properties b/src/main/resources/messages_ru_RU.properties index 62e8d3d0..8c915bb4 100644 --- a/src/main/resources/messages_ru_RU.properties +++ b/src/main/resources/messages_ru_RU.properties @@ -750,6 +750,7 @@ certSign.showSig=Показать подпись certSign.reason=Причина certSign.location=Местоположение certSign.name=Имя +certSign.showLogo=Show Logo certSign.submit=Подписать PDF diff --git a/src/main/resources/messages_sk_SK.properties b/src/main/resources/messages_sk_SK.properties index 05696f3e..d87128a6 100644 --- a/src/main/resources/messages_sk_SK.properties +++ b/src/main/resources/messages_sk_SK.properties @@ -750,6 +750,7 @@ certSign.showSig=Zobraziť podpis certSign.reason=Dôvod certSign.location=Miesto certSign.name=Meno +certSign.showLogo=Show Logo certSign.submit=Podpísať PDF diff --git a/src/main/resources/messages_sr_LATN_RS.properties b/src/main/resources/messages_sr_LATN_RS.properties index 75338172..61a7d942 100644 --- a/src/main/resources/messages_sr_LATN_RS.properties +++ b/src/main/resources/messages_sr_LATN_RS.properties @@ -750,6 +750,7 @@ certSign.showSig=Prikaži potpis certSign.reason=Razlog certSign.location=Lokacija certSign.name=Ime +certSign.showLogo=Show Logo certSign.submit=Potpiši PDF diff --git a/src/main/resources/messages_sv_SE.properties b/src/main/resources/messages_sv_SE.properties index 2e894543..d39d4b3a 100644 --- a/src/main/resources/messages_sv_SE.properties +++ b/src/main/resources/messages_sv_SE.properties @@ -750,6 +750,7 @@ certSign.showSig=Visa signatur certSign.reason=Anledning certSign.location=Plats certSign.name=Namn +certSign.showLogo=Show Logo certSign.submit=Signera PDF diff --git a/src/main/resources/messages_th_TH.properties b/src/main/resources/messages_th_TH.properties index dda8151d..68b9d36d 100644 --- a/src/main/resources/messages_th_TH.properties +++ b/src/main/resources/messages_th_TH.properties @@ -750,6 +750,7 @@ certSign.showSig=แสดงลายเซ็น certSign.reason=เหตุผล certSign.location=ตำแหน่ง certSign.name=ชื่อ +certSign.showLogo=Show Logo certSign.submit=เซ็นชื่อ PDF diff --git a/src/main/resources/messages_tr_TR.properties b/src/main/resources/messages_tr_TR.properties index 42f47f8a..60e2e5f4 100644 --- a/src/main/resources/messages_tr_TR.properties +++ b/src/main/resources/messages_tr_TR.properties @@ -750,6 +750,7 @@ certSign.showSig=İmzayı Göster certSign.reason=Neden certSign.location=Konum certSign.name=İsim +certSign.showLogo=Show Logo certSign.submit=PDF'i İmzala diff --git a/src/main/resources/messages_uk_UA.properties b/src/main/resources/messages_uk_UA.properties index 78b71aab..2027a834 100644 --- a/src/main/resources/messages_uk_UA.properties +++ b/src/main/resources/messages_uk_UA.properties @@ -750,6 +750,7 @@ certSign.showSig=Показати підпис certSign.reason=Причина certSign.location=Місцезнаходження certSign.name=Ім'я +certSign.showLogo=Show Logo certSign.submit=Підписати PDF diff --git a/src/main/resources/messages_vi_VN.properties b/src/main/resources/messages_vi_VN.properties index 0d11b6e1..b7a4d1ed 100644 --- a/src/main/resources/messages_vi_VN.properties +++ b/src/main/resources/messages_vi_VN.properties @@ -750,6 +750,7 @@ certSign.showSig=Hiển thị chữ ký certSign.reason=Lý do certSign.location=Vị trí certSign.name=Tên +certSign.showLogo=Show Logo certSign.submit=Ký PDF diff --git a/src/main/resources/messages_zh_CN.properties b/src/main/resources/messages_zh_CN.properties index 614ac1f7..7be7cb78 100644 --- a/src/main/resources/messages_zh_CN.properties +++ b/src/main/resources/messages_zh_CN.properties @@ -750,6 +750,7 @@ certSign.showSig=显示签名 certSign.reason=原因 certSign.location=位置 certSign.name=名称 +certSign.showLogo=Show Logo certSign.submit=给PDF签名 diff --git a/src/main/resources/messages_zh_TW.properties b/src/main/resources/messages_zh_TW.properties index 24ab70d9..fd212da9 100644 --- a/src/main/resources/messages_zh_TW.properties +++ b/src/main/resources/messages_zh_TW.properties @@ -750,6 +750,7 @@ certSign.showSig=顯示簽章 certSign.reason=原因 certSign.location=位置 certSign.name=名稱 +certSign.showLogo=Show Logo certSign.submit=簽章 PDF From 217404be7f0206cfd7acedba8e0917ff78e7a200 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 31 Oct 2024 20:33:03 +0000 Subject: [PATCH 09/23] :memo: Update README: Translation Progress Table (#2136) :memo: Sync README > Made via sync_files.yml Co-authored-by: github-actions[bot] --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 83c83114..4a16e47b 100644 --- a/README.md +++ b/README.md @@ -179,7 +179,7 @@ Stirling PDF currently supports 38! | Language | Progress | | ------------------------------------------- | -------------------------------------- | -| Arabic (العربية) (ar_AR) | ![93%](https://geps.dev/progress/93) | +| Arabic (العربية) (ar_AR) | ![92%](https://geps.dev/progress/92) | | Basque (Euskara) (eu_ES) | ![56%](https://geps.dev/progress/56) | | Bulgarian (Български) (bg_BG) | ![98%](https://geps.dev/progress/98) | | Catalan (Català) (ca_CA) | ![44%](https://geps.dev/progress/44) | @@ -196,7 +196,7 @@ Stirling PDF currently supports 38! | Hungarian (Magyar) (hu_HU) | ![69%](https://geps.dev/progress/69) | | Indonesia (Bahasa Indonesia) (id_ID) | ![95%](https://geps.dev/progress/95) | | Irish (Gaeilge) (ga_IE) | ![89%](https://geps.dev/progress/89) | -| Italian (Italiano) (it_IT) | ![98%](https://geps.dev/progress/98) | +| Italian (Italiano) (it_IT) | ![99%](https://geps.dev/progress/99) | | Japanese (日本語) (ja_JP) | ![86%](https://geps.dev/progress/86) | | Korean (한국어) (ko_KR) | ![76%](https://geps.dev/progress/76) | | Norwegian (Norsk) (no_NB) | ![89%](https://geps.dev/progress/89) | From 2be14788b1c743e5b8a653bec335e8d14ef604f2 Mon Sep 17 00:00:00 2001 From: albanobattistella <34811668+albanobattistella@users.noreply.github.com> Date: Fri, 1 Nov 2024 17:32:52 +0100 Subject: [PATCH 10/23] Update messages_it_IT.properties (#2146) --- src/main/resources/messages_it_IT.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/messages_it_IT.properties b/src/main/resources/messages_it_IT.properties index efafe94f..899b9d73 100644 --- a/src/main/resources/messages_it_IT.properties +++ b/src/main/resources/messages_it_IT.properties @@ -750,7 +750,7 @@ certSign.showSig=Mostra firma certSign.reason=Motivo certSign.location=Posizione certSign.name=Nome -certSign.showLogo=Show Logo +certSign.showLogo=Mostra Logo certSign.submit=Firma PDF From a5aac01b4d47f872cb6801d69aa1ae63ba9401d2 Mon Sep 17 00:00:00 2001 From: Ludy Date: Sun, 3 Nov 2024 08:20:10 +0100 Subject: [PATCH 11/23] fixed minor bugs in Markdown (#2152) --- DATABASE.md | 3 +- DeveloperGuide.md | 108 ++++--- FolderScanning.md | 36 ++- HowToAddNewLanguage.md | 42 +-- HowToUseOCR.md | 35 +- LocalRunGuide.md | 147 ++++----- PipelineFeature.md | 18 +- README.md | 395 +++++++++++------------ Version-groups.md | 4 +- src/main/resources/settings.yml.template | 86 ++--- 10 files changed, 447 insertions(+), 427 deletions(-) diff --git a/DATABASE.md b/DATABASE.md index efc1e467..e8e0c838 100644 --- a/DATABASE.md +++ b/DATABASE.md @@ -1,6 +1,7 @@ # New Database Backup and Import Functionality -**Full activation will take place on approximately January 5th, 2025!** +> [!IMPORTANT] +> **Full activation will take place on approximately January 5th, 2025!** Why is the waiting time six months? diff --git a/DeveloperGuide.md b/DeveloperGuide.md index eaed2afb..23cb6108 100644 --- a/DeveloperGuide.md +++ b/DeveloperGuide.md @@ -7,6 +7,7 @@ Stirling-PDF is a robust, locally hosted web-based PDF manipulation tool. This g ## 2. Project Overview Stirling-PDF is built using: + - Spring Boot + Thymeleaf - PDFBox - LibreOffice @@ -20,14 +21,17 @@ Stirling-PDF is built using: ## 3. Development Environment Setup ### Prerequisites + - Docker - Git - Java JDK 17 or later - Gradle 7.0 or later (Included within repo) ### Setup Steps + 1. Clone the repository: - ``` + + ```bash git clone https://github.com/Stirling-Tools/Stirling-PDF.git cd Stirling-PDF ``` @@ -43,10 +47,9 @@ Visit the [Lombok website](https://projectlombok.org/setup/) for installation in 5. Add environment variable For local testing you should generally be testing the full 'Security' version of Stirling-PDF to do this you must add the environment flag DOCKER_ENABLE_SECURITY=true to your system and/or IDE build/run step - ## 4. Project Structure -``` +```bash Stirling-PDF/ ├── .github/ # GitHub-specific files (workflows, issue templates) ├── configs/ # Configuration files used by stirling at runtime (generated at runtime) @@ -92,6 +95,7 @@ Stirling-PDF/ ## 5. Docker-based Development Stirling-PDF offers several Docker versions: + - Full: All features included - Ultra-Lite: Basic PDF operations only - Fat: Includes additional libraries and fonts predownloaded @@ -153,11 +157,13 @@ docker-compose -f exampleYmlFiles/docker-compose-latest-security.yml up Stirling-PDF uses different Docker images for various configurations. The build process is controlled by environment variables and uses specific Dockerfile variants. Here's how to build the Docker images: 1. Set the security environment variable: + ```bash export DOCKER_ENABLE_SECURITY=false # or true for security-enabled builds ``` 2. Build the project with Gradle: + ```bash ./gradlew clean build ``` @@ -165,16 +171,19 @@ Stirling-PDF uses different Docker images for various configurations. The build 3. Build the Docker images: For the latest version: + ```bash docker build --no-cache --pull --build-arg VERSION_TAG=alpha -t frooodle/s-pdf:latest -f ./Dockerfile . ``` For the ultra-lite version: + ```bash docker build --no-cache --pull --build-arg VERSION_TAG=alpha -t frooodle/s-pdf:latest-ultra-lite -f ./Dockerfile-ultra-lite . ``` For the fat version (with security enabled): + ```bash export DOCKER_ENABLE_SECURITY=true docker build --no-cache --pull --build-arg VERSION_TAG=alpha -t frooodle/s-pdf:latest-fat -f ./Dockerfile-fat . @@ -182,8 +191,6 @@ Stirling-PDF uses different Docker images for various configurations. The build Note: The `--no-cache` and `--pull` flags ensure that the build process uses the latest base images and doesn't use cached layers, which is useful for testing and ensuring reproducible builds. however to improve build times these can often be removed depending on your usecase - - ## 6. Testing ### Comprehensive Testing Script @@ -197,6 +204,7 @@ To run the test script: ``` This script performs the following actions: + 1. Builds all Docker images (full, ultra-lite, fat) 2. Runs each version to ensure it starts correctly 3. Executes Cucumber tests against main version and ensures feature compatibility, in the event these tests fail your PR will not be merged @@ -209,7 +217,6 @@ Note: The `test.sh` script will run automatically when you raise a PR. However, 2. Access the application at `http://localhost:8080` and manually test all features developed. - ### Local Testing (Java and UI Components) For quick iterations and development of Java backend, JavaScript, and UI components, you can run and test Stirling-PDF locally without Docker. This approach allows you to work on and verify changes to: @@ -223,7 +230,8 @@ For quick iterations and development of Java backend, JavaScript, and UI compone To run Stirling-PDF locally: 1. Compile and run the project using built in IDE methods or by running: - ``` + + ```bash ./gradlew bootRun ``` @@ -234,11 +242,11 @@ To run Stirling-PDF locally: 4. For API changes, use tools like Postman or curl to test endpoints directly. Important notes: + - Local testing doesn't include features that depend on external tools like OCRmyPDF, LibreOffice, or Python scripts. - There are currently no automated unit tests. All testing is done manually through the UI or API calls. (You are welcome to add JUnits!) - Always verify your changes in the full Docker environment before submitting pull requests, as some integrations and features will only work in the complete setup. - ## 7. Contributing 1. Fork the repository on GitHub. @@ -246,14 +254,17 @@ Important notes: 3. Make your changes and commit them with clear, descriptive messages and ensure any documentation is updated related to your changes. 4. Test your changes thoroughly in the Docker environment. 5. Run the `test.sh` script to ensure all versions build correctly and pass the Cucumber tests: + ```bash ./test.sh ``` + 6. Push your changes to your fork. -7. Submit a pull request to the main repository. +7. Submit a pull request to the main repository. 8. See additional [contributing guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) When you raise a PR: + - The `test.sh` script will run automatically against your PR. - The PR checks will verify versioning and dependency updates. - Documentation will be automatically updated for dependency changes. @@ -268,6 +279,7 @@ API documentation is available at `/swagger-ui/index.html` when running the appl ## 9. Customization Stirling-PDF can be customized through environment variables or a `settings.yml` file. Key customization options include: + - Application name and branding - Security settings - UI customization @@ -276,7 +288,8 @@ Stirling-PDF can be customized through environment variables or a `settings.yml` When using Docker, pass environment variables using the `-e` flag or in your `docker-compose.yml` file. Example: -``` + +```bash docker run -p 8080:8080 -e APP_NAME="My PDF Tool" stirling-pdf:full ``` @@ -293,16 +306,14 @@ For managing language translations that affect multiple files, Stirling-PDF prov This script helps you make consistent replacements across language files. When contributing translations: + 1. Use the helper script for multi-file changes. 2. Ensure all language files are updated consistently. 3. The PR checks will verify consistency in language file updates. Remember to test your changes thoroughly to ensure they don't break any existing functionality. - - - -# Code examples +## Code examples ### Overview of Thymeleaf @@ -311,22 +322,28 @@ Thymeleaf is a server-side Java HTML template engine. It is used in Stirling-PD ### Thymeleaf overview In Stirling-PDF, Thymeleaf is used to create HTML templates that are rendered on the server side. These templates are located in the `src/main/resources/templates` directory. Thymeleaf templates use a combination of HTML and special Thymeleaf attributes to dynamically generate content. -Some examples of this are + +Some examples of this are: + ```html or ``` + Where it uses the th:block, th: indicating its a special thymeleaf element to be used serverside in generating the html, and block being the actual element type. In this case we are inserting the ``navbar`` entry within the ``fragments/navbar.html`` fragment into the ``th:block`` element. -They can be more complex such as +They can be more complex such as: + ```html ``` + Which is the same as above but passes the parameters title and header into the fragment common.html to be used in its HTML generation Thymeleaf can also be used to loop through objects or pass things from java side into html side. + ```java @GetMapping public String newFeaturePage(Model model) { @@ -334,7 +351,9 @@ Thymeleaf can also be used to loop through objects or pass things from java side return "new-feature"; } ``` + in above example if exampleData is a list of plain java objects of class Person and within it you had id, name, age etc. You can reference it like so + ```html @@ -346,6 +365,7 @@ in above example if exampleData is a list of plain java objects of class Person ``` + This would generate n entries of tr for each person in exampleData ### Adding a New Feature to the Backend (API) @@ -397,34 +417,35 @@ This would generate n entries of tr for each person in exampleData ``` 2b. **Integrate the Service with the Controller:** - - Autowire the service class in the controller and use it to handle the API request. - ```java - package stirling.software.SPDF.controller.api; +- Autowire the service class in the controller and use it to handle the API request. - import org.springframework.beans.factory.annotation.Autowired; - import org.springframework.web.bind.annotation.GetMapping; - import org.springframework.web.bind.annotation.RequestMapping; - import org.springframework.web.bind.annotation.RestController; - import stirling.software.SPDF.service.NewFeatureService; - import io.swagger.v3.oas.annotations.Operation; - import io.swagger.v3.oas.annotations.tags.Tag; + ```java + package stirling.software.SPDF.controller.api; - @RestController - @RequestMapping("/api/v1/new-feature") - @Tag(name = "General", description = "General APIs") - public class NewFeatureController { + import org.springframework.beans.factory.annotation.Autowired; + import org.springframework.web.bind.annotation.GetMapping; + import org.springframework.web.bind.annotation.RequestMapping; + import org.springframework.web.bind.annotation.RestController; + import stirling.software.SPDF.service.NewFeatureService; + import io.swagger.v3.oas.annotations.Operation; + import io.swagger.v3.oas.annotations.tags.Tag; - @Autowired - private NewFeatureService newFeatureService; + @RestController + @RequestMapping("/api/v1/new-feature") + @Tag(name = "General", description = "General APIs") + public class NewFeatureController { - @GetMapping - @Operation(summary = "New Feature", description = "This is a new feature endpoint.") - public String newFeature() { - return newFeatureService.getNewFeatureData(); - } - } - ``` + @Autowired + private NewFeatureService newFeatureService; + + @GetMapping + @Operation(summary = "New Feature", description = "This is a new feature endpoint.") + public String newFeature() { + return newFeatureService.getNewFeatureData(); + } + } + ``` ### Adding a New Feature to the Frontend (UI) @@ -511,7 +532,6 @@ This would generate n entries of tr for each person in exampleData ``` - ## Adding New Translations to Existing Language Files in Stirling-PDF When adding a new feature or modifying existing ones in Stirling-PDF, you'll need to add new translation entries to the existing language files. Here's a step-by-step guide: @@ -522,13 +542,13 @@ Find the existing `messages.properties` files in the `src/main/resources` direct - `messages.properties` (default, usually English) - `messages_en_GB.properties` -- `messages_fr.properties` -- `messages_de.properties` +- `messages_fr_FR.properties` +- `messages_de_DE.properties` - etc. ### 2. Add New Translation Entries -Open each of these files and add your new translation entries. For example, if you're adding a new feature called "PDF Splitter", +Open each of these files and add your new translation entries. For example, if you're adding a new feature called "PDF Splitter", Use descriptive, hierarchical keys (e.g., `feature.element.description`) you might add: @@ -552,6 +572,4 @@ In your Thymeleaf templates, use the `#{key}` syntax to reference the new transl ``` - - Remember, never hard-code text in your templates or Java code. Always use translation keys to ensure proper localization. diff --git a/FolderScanning.md b/FolderScanning.md index 140c9f5f..66707a10 100644 --- a/FolderScanning.md +++ b/FolderScanning.md @@ -1,33 +1,41 @@ ## User Guide for Local Directory Scanning and File Processing -### Setting Up Watched Folders: +### Setting Up Watched Folders + - Create a folder where you want your files to be monitored. This is your 'watched folder'. -- The default directory for this is `./pipeline/watchedFolders/` -- Place any directories you want to be scanned into this folder, this folder should contain multiple folders each for their own tasks and pipelines. +- The default directory for this is `./pipeline/watchedFolders/`. +- Place any directories you want to be scanned into this folder. This folder should contain multiple folders, each for their own tasks and pipelines. -### Configuring Processing with JSON Files: -- In each directory you want processed (e.g `./pipeline/watchedFolders/officePrinter`), include a JSON configuration file. -- This JSON file should specify how you want the files in the directory to be handled (e.g., what operations to perform on them) which can be made, configured and downloaded from Stirling-PDF Pipeline interface.r +### Configuring Processing with JSON Files + +- In each directory you want processed (e.g., `./pipeline/watchedFolders/officePrinter`), include a JSON configuration file. +- This JSON file should specify how you want the files in the directory to be handled (e.g., what operations to perform on them). This can be made, configured, and downloaded from the Stirling-PDF Pipeline interface. + +### Automatic Scanning and Processing -### Automatic Scanning and Processing: - The system automatically checks the watched folder every minute for new directories and files to process. -- When a directory with a valid JSON configuration file is found, it begins processing the files inside as per the configuration. +- When a directory with a valid JSON configuration file is found, it begins processing the files inside according to the configuration. + +### Processing Steps -### Processing Steps: - Files in each directory are processed according to the instructions in the JSON file. -- This might involve file conversions, data filtering, renaming files, etc. If the output of a step is a zip, this zip will be automatically unzipped as it passes to next process. +- This might involve file conversions, data filtering, renaming files, etc. If the output of a step is a zip, this zip will be automatically unzipped as it passes to the next process. + +### Results and Output -### Results and Output: - After processing, the results are saved in a specified output location. This could be a different folder or location as defined in the JSON file or the default location `./pipeline/finishedFolders/`. - Each processed file is named and organized according to the rules set in the JSON configuration. -### Completion and Cleanup: +### Completion and Cleanup + - Once processing is complete, the original files in the watched folder's directory are removed. - You can find the processed files in the designated output location. -### Error Handling: +### Error Handling + - If there's an error during processing, the system will not delete the original files, allowing you to check and retry if necessary. -### User Interaction: +### User Interaction + - As a user, your main tasks are to set up the watched folders, place directories with files for processing, and create the corresponding JSON configuration files. - The system handles the rest, including scanning, processing, and outputting results. diff --git a/HowToAddNewLanguage.md b/HowToAddNewLanguage.md index ed4208b9..7ab6f53a 100644 --- a/HowToAddNewLanguage.md +++ b/HowToAddNewLanguage.md @@ -1,43 +1,47 @@ -


Stirling-PDF

+

+ +
+

Stirling-PDF

# How to add new languages to Stirling-PDF -Fork Stirling-PDF and make a new branch out of Main +Fork Stirling-PDF and create a new branch out of `main`. -Then add reference to the language in the navbar by adding a new language entry to the dropdown +Then add a reference to the language in the navbar by adding a new language entry to the dropdown: -https://github.com/Stirling-Tools/Stirling-PDF/blob/main/src/main/resources/templates/fragments/languages.html -and add a flag svg file to -https://github.com/Stirling-Tools/Stirling-PDF/tree/main/src/main/resources/static/images/flags -Any SVG flags are fine, i got most of mine from [here](https://flagicons.lipis.dev/) -If your language isn't represented by a flag just find whichever closely matches it, such as for Arabic i chose Saudi Arabia +- Edit the file: [languages.html](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/src/main/resources/templates/fragments/languages.html) +- Add a flag SVG file to: [flags directory](https://github.com/Stirling-Tools/Stirling-PDF/tree/main/src/main/resources/static/images/flags) -For example to add Polish you would add +Any SVG flags are fine; most of the current ones were sourced from [here](https://flagicons.lipis.dev/). If your language isn't represented by a flag, choose a similar one, such as Saudi Arabia's flag for Arabic. + +For example, to add Polish, you would add: ```html - + icon Polski ``` -The data-language-code is the code used to reference the file in the next step. +The `data-bs-language-code` is the code used to reference the file in the next step. -Start by copying the existing english property file +### Add Language Property File -[https://github.com/Stirling-Tools/Stirling-PDF/blob/main/src/main/resources/messages_en_GB.properties](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/src/main/resources/messages_en_GB.properties) +Start by copying the existing English property file: -Copy and rename it to messages_{your data-language-code here}.properties, in the polish example you would set the name to messages_pl_PL.properties +- [messages_en_GB.properties](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/src/main/resources/messages_en_GB.properties) -Then simply translate all property entries within that file and make a PR into main for others to use! +Copy and rename it to `messages_{your data-bs-language-code here}.properties`. In the Polish example, you would set the name to `messages_pl_PL.properties`. -If you do not have a java IDE i am happy to verify the changes worked once you raise PR (but won't be able to verify the translations themselves) +Then simply translate all property entries within that file and make a Pull Request (PR) into `main` for others to use! + +If you do not have a Java IDE, I am happy to verify that the changes work once you raise the PR (but I won't be able to verify the translations themselves). ## Handling Untranslatable Strings Sometimes, certain strings in the properties file may not require translation because they are the same in the target language or are universal (like names of protocols, certain terminologies, etc.). To ensure accurate statistics for language progress, these strings should be added to the `ignore_translation.toml` file located in the `scripts` directory. This will exclude them from the translation progress calculations. -For example, if the English string error=Error does not need translation in Polish, add it to the ignore_translation.toml under the Polish section: +For example, if the English string `error=Error` does not need translation in Polish, add it to the `ignore_translation.toml` under the Polish section: ```toml [pl_PL] @@ -49,7 +53,9 @@ ignore = [ ## Add New Translation Tags -- **Important**: If you add any new translation tags, they must first be added to the `messages_en_GB.properties` file. This ensures consistency across all language files. +> [!IMPORTANT] +> If you add any new translation tags, they must first be added to the `messages_en_GB.properties` file. This ensures consistency across all language files. + - New translation tags **must be added** to the `messages_en_GB.properties` file to maintain a reference for other languages. - After adding the new tags to `messages_en_GB.properties`, add and translate them in the respective language file (e.g., `messages_pl_PL.properties`). diff --git a/HowToUseOCR.md b/HowToUseOCR.md index 8607c28d..ecb187c5 100644 --- a/HowToUseOCR.md +++ b/HowToUseOCR.md @@ -3,34 +3,36 @@ This document provides instructions on how to add additional language packs for the OCR tab in Stirling-PDF, both inside and outside of Docker. ## My OCR used to work and now doesn't! -The paths have changed for the tessadata locations on new docker images, please use ``/usr/share/tessdata`` (Others should still work for backwards compatibility but might not) + +The paths have changed for the tessdata locations on new Docker images. Please use `/usr/share/tessdata` (Others should still work for backward compatibility but might not). ## How does the OCR Work -Stirling-PDF uses [OCRmyPDF](https://github.com/ocrmypdf/OCRmyPDF) which in turn uses tesseract for its text recognition. -All credit goes to them for this awesome work! + +Stirling-PDF uses [OCRmyPDF](https://github.com/ocrmypdf/OCRmyPDF), which in turn uses Tesseract for its text recognition. All credit goes to them for this awesome work! ## Language Packs Tesseract OCR supports a variety of languages. You can find additional language packs in the Tesseract GitHub repositories: -- [tessdata_fast](https://github.com/tesseract-ocr/tessdata_fast): These language packs are smaller and faster to load, but may provide lower recognition accuracy. +- [tessdata_fast](https://github.com/tesseract-ocr/tessdata_fast): These language packs are smaller and faster to load but may provide lower recognition accuracy. - [tessdata](https://github.com/tesseract-ocr/tessdata): These language packs are larger and provide better recognition accuracy, but may take longer to load. -Depending on your requirements, you can choose the appropriate language pack for your use case. By default Stirling-PDF uses the tessdata_fast eng but this can be replaced. +Depending on your requirements, you can choose the appropriate language pack for your use case. By default, Stirling-PDF uses `tessdata_fast` for English, but this can be replaced. ### Installing Language Packs 1. Download the desired language pack(s) by selecting the `.traineddata` file(s) for the language(s) you need. 2. Place the `.traineddata` files in the Tesseract tessdata directory: `/usr/share/tessdata` -# DO NOT REMOVE EXISTING ENG.TRAINEDDATA, IT'S REQUIRED. +**DO NOT REMOVE EXISTING `eng.traineddata`, IT'S REQUIRED.** -#### Docker +### Docker Setup If you are using Docker, you need to expose the Tesseract tessdata directory as a volume in order to use the additional language packs. -#### Docker Compose -Modify your `docker-compose.yml` file to include the following volume configuration: +#### Docker Compose + +Modify your `docker-compose.yml` file to include the following volume configuration: ```yaml services: @@ -40,18 +42,19 @@ services: - /location/of/trainingData:/usr/share/tessdata ``` +#### Docker Run + +Add the following to your existing Docker run command: -#### Docker run -Add the following to your existing docker run command ```bash -v /location/of/trainingData:/usr/share/tessdata ``` -#### Non-Docker -If you are not using Docker, you need to install the OCR components, including the ocrmypdf app. -You can see [OCRmyPDF install guide](https://ocrmypdf.readthedocs.io/en/latest/installation.html) +### Non-Docker Setup -Debian based systems, install languages with this command: +If you are not using Docker, you need to install the OCR components, including the `ocrmypdf` app. You can see the [OCRmyPDF install guide](https://ocrmypdf.readthedocs.io/en/latest/installation.html). + +For Debian-based systems, install languages with this command: ```bash sudo apt update &&\ @@ -65,7 +68,7 @@ apt search tesseract-ocr- dpkg-query -W tesseract-ocr- | sed 's/tesseract-ocr-//g' ``` -Fedora: +For Fedora: ```bash # All languages diff --git a/LocalRunGuide.md b/LocalRunGuide.md index edb136ec..027c7b22 100644 --- a/LocalRunGuide.md +++ b/LocalRunGuide.md @@ -1,48 +1,35 @@ - To run the application without Docker/Podman, you will need to manually install all dependencies and build the necessary components. Note that some dependencies might not be available in the standard repositories of all Linux distributions, and may require additional steps to install. The following guide assumes you have a basic understanding of using a command line interface in your operating system. -It should work on most Linux distributions and MacOS. For Windows, you might need to use Windows Subsystem for Linux (WSL) for certain steps. -The amount of dependencies is to actually reduce overall size, ie installing LibreOffice sub components rather than full LibreOffice package. +It should work on most Linux distributions and MacOS. For Windows, you might need to use Windows Subsystem for Linux (WSL) for certain steps. The amount of dependencies is to actually reduce overall size, i.e., installing LibreOffice subcomponents rather than the full LibreOffice package. -You could theoretically use a Distrobox/Toolbox, if your Distribution has old or not all Packages. But you might just as well use the Docker Container then. +You could theoretically use a Distrobox/Toolbox if your distribution has old or not all packages. But you might just as well use the Docker container then. ### Step 1: Prerequisites Install the following software, if not already installed: - Java 17 or later (21 recommended) - - Gradle 7.0 or later (included within repo so not needed on server) - - Git - - Python 3.8 (with pip) - - Make - - GCC/G++ - - Automake - - Autoconf - - libtool - - pkg-config - - zlib1g-dev - - libleptonica-dev For Debian-based systems, you can use the following command: ```bash sudo apt-get update -sudo apt-get install -y git automake autoconf libtool libleptonica-dev pkg-config zlib1g-dev make g++ openjdk-21-jdk python3 python3-pip +sudo apt-get install -y git automake autoconf libtool libleptonica-dev pkg-config zlib1g-dev make g++ openjdk-21-jdk python3 python3-pip ``` For Fedora-based systems use this command: @@ -52,6 +39,7 @@ sudo dnf install -y git automake autoconf libtool leptonica-devel pkg-config zli ``` For non-root users with Nix Package Manager, use the following command: + ```bash nix-channel --update nix-env -iA nixpkgs.jdk21 nixpkgs.git nixpkgs.python38 nixpkgs.gnumake nixpkgs.libgcc nixpkgs.automake nixpkgs.autoconf nixpkgs.libtool nixpkgs.pkg-config nixpkgs.zlib nixpkgs.leptonica @@ -63,45 +51,37 @@ For Debian and Fedora, you can build it from source using the following commands ```bash mkdir ~/.git -cd ~/.git &&\ -git clone https://github.com/agl/jbig2enc.git &&\ -cd jbig2enc &&\ -./autogen.sh &&\ -./configure &&\ -make &&\ +cd ~/.git && \ +git clone https://github.com/agl/jbig2enc.git && \ +cd jbig2enc && \ +./autogen.sh && \ +./configure && \ +make && \ sudo make install ``` For Nix, you will face `Leptonica not detected`. Bypass this by installing it directly using the following command: + ```bash nix-env -iA nixpkgs.jbig2enc ``` ### Step 3: Install Additional Software -Next we need to install LibreOffice for conversions, ocrmypdf for OCR, and opencv for pattern recognition functionality. + +Next we need to install LibreOffice for conversions, ocrmypdf for OCR, and OpenCV for pattern recognition functionality. Install the following software: - libreoffice-core - - libreoffice-common - - libreoffice-writer - - libreoffice-calc - - libreoffice-impress - - python3-uno - - unoconv - - pngquant - - unpaper - - ocrmypdf - - opencv-python-headless For Debian-based systems, you can use the following command: @@ -128,51 +108,52 @@ pip3 install uno opencv-python-headless unoconv pngquant WeasyPrint ### Step 4: Clone and Build Stirling-PDF ```bash -cd ~/.git &&\ -git clone https://github.com/Stirling-Tools/Stirling-PDF.git &&\ -cd Stirling-PDF &&\ -chmod +x ./gradlew &&\ +cd ~/.git && \ +git clone https://github.com/Stirling-Tools/Stirling-PDF.git && \ +cd Stirling-PDF && \ +chmod +x ./gradlew && \ ./gradlew build ``` -### Step 5: Move jar to desired location +### Step 5: Move Jar to Desired Location -After the build process, a `.jar` file will be generated in the `build/libs` directory. -You can move this file to a desired location, for example, `/opt/Stirling-PDF/`. -You must also move the Script folder within the Stirling-PDF repo that you have downloaded to this directory. -This folder is required for the python scripts using OpenCV. +After the build process, a `.jar` file will be generated in the `build/libs` directory. You can move this file to a desired location, for example, `/opt/Stirling-PDF/`. You must also move the Script folder within the Stirling-PDF repo that you have downloaded to this directory. This folder is required for the Python scripts using OpenCV. ```bash -sudo mkdir /opt/Stirling-PDF &&\ -sudo mv ./build/libs/Stirling-PDF-*.jar /opt/Stirling-PDF/ &&\ -sudo mv scripts /opt/Stirling-PDF/ &&\ +sudo mkdir /opt/Stirling-PDF && \ +sudo mv ./build/libs/Stirling-PDF-*.jar /opt/Stirling-PDF/ && \ +sudo mv scripts /opt/Stirling-PDF/ && \ echo "Scripts installed." ``` For non-root users, you can just keep the jar in the main directory of Stirling-PDF using the following command: + ```bash mv ./build/libs/Stirling-PDF-*.jar ./Stirling-PDF-*.jar ``` -### Step 6: Other files +### Step 6: Other Files + #### OCR -If you plan to use the OCR (Optical Character Recognition) functionality, you might need to install language packs for Tesseract if running non-english scanning. + +If you plan to use the OCR (Optical Character Recognition) functionality, you might need to install language packs for Tesseract if running non-English scanning. ##### Installing Language Packs -Easiest is to use the langpacks provided by your repositories. Skip the other steps. -Manual: +The easiest method is to use the language packs provided by your repositories. Skip the other steps if they are available. + +**Manual:** 1. Download the desired language pack(s) by selecting the `.traineddata` file(s) for the language(s) you need. 2. Place the `.traineddata` files in the Tesseract tessdata directory: `/usr/share/tessdata` -3. Please view [OCRmyPDF install guide](https://ocrmypdf.readthedocs.io/en/latest/installation.html) for more info. +3. Please view [OCRmyPDF install guide](https://ocrmypdf.readthedocs.io/en/latest/installation.html) for more info. **IMPORTANT:** DO NOT REMOVE EXISTING `eng.traineddata`, IT'S REQUIRED. -Debian based systems, install languages with this command: +**Debian-based systems**, install languages with this command: ```bash -sudo apt update &&\ +sudo apt update && \ # All languages # sudo apt install -y 'tesseract-ocr-*' @@ -183,7 +164,7 @@ apt search tesseract-ocr- dpkg-query -W tesseract-ocr- | sed 's/tesseract-ocr-//g' ``` -Fedora: +**Fedora:** ```bash # All languages @@ -196,13 +177,13 @@ dnf search -C tesseract-langpack- rpm -qa | grep tesseract-langpack | sed 's/tesseract-langpack-//g' ``` -Nix: +**Nix:** ```bash nix-env -iA nixpkgs.tesseract ``` -**Note:** Nix Package Manager pre-installs almost all the language packs when tesseract is installed. +**Note:** Nix Package Manager pre-installs almost all the language packs when Tesseract is installed. ### Step 7: Run Stirling-PDF @@ -214,11 +195,13 @@ or java -jar /opt/Stirling-PDF/Stirling-PDF-*.jar ``` -Since libreoffice, soffice, and conversion tools have their dbus_tmp_dir set as `dbus_tmp_dir="/run/user/$(id -u)/libreoffice-dbus"`, you might get the following error when using their endpoints: +Since LibreOffice, soffice, and conversion tools have their dbus_tmp_dir set as `dbus_tmp_dir="/run/user/$(id -u)/libreoffice-dbus"`, you might get the following error when using their endpoints: + ``` [Thread-7] INFO s.s.SPDF.utils.ProcessExecutor - mkdir: cannot create directory ‘/run/user/1501’: Permission denied ``` -To resolve this, before starting the Stirling-PDF, you have to set the environment variable to a directory you have write access to by using the following commands: + +To resolve this, before starting Stirling-PDF, you have to set the environment variable to a directory you have write access to by using the following commands: ```bash mkdir temp @@ -228,9 +211,10 @@ or java -jar ./Stirling-PDF-*.jar ``` -### Step 8: Adding a Desktop icon +### Step 8: Adding a Desktop Icon + +This will add a modified app starter to your app menu. -This will add a modified Appstarter to your Appmenu. ```bash location=$(pwd)/gradlew image=$(pwd)/docs/stirling-transparent.svg @@ -251,35 +235,40 @@ EOF Note: Currently the app will run in the background until manually closed. -### Optional: Changing the host and port of the application: +### Optional: Changing the Host and Port of the Application To override the default configuration, you can add the following to `/.git/Stirling-PDF/configs/custom_settings.yml` file: -```bash +```yaml server: host: 0.0.0.0 # Not working - use instead address address: 0.0.0.0 port: 3000 ``` -'-Djava.net.preferIPv4Stack=true' --> To force ipv4 only in the java starting command + +`-Djava.net.preferIPv4Stack=true` --> To force IPv4 only in the Java starting command **Note:** This file is created after the first application launch. To have it before that, you can create the directory and add the file yourself. -### Optional: Run Stirling-PDF as a service (requires root). +### Optional: Run Stirling-PDF as a Service (requires root) -First create a .env file, where you can store environment variables: -``` +First create a `.env` file, where you can store environment variables: + +```bash touch /opt/Stirling-PDF/.env ``` -In this file you can add all variables, one variable per line, as stated in the main readme (for example SYSTEM_DEFAULTLOCALE="de-DE"). -Create a new file where we store our service settings and open it with nano editor: -``` +In this file, you can add all variables, one variable per line, as stated in the main readme (for example `SYSTEM_DEFAULTLOCALE="de-DE"`). + +Create a new file where we store our service settings and open it with the nano editor: + +```bash nano /etc/systemd/system/stirlingpdf.service ``` -Paste this content, make sure to update the filename of the jar-file. Press Ctrl+S and Ctrl+X to save and exit the nano editor: -``` +Paste this content, make sure to update the filename of the jar file. Press `Ctrl+S` and `Ctrl+X` to save and exit the nano editor: + +```ini [Unit] Description=Stirling-PDF service After=syslog.target network.target @@ -303,22 +292,25 @@ WantedBy=multi-user.target Notify systemd that it has to rebuild its internal service database (you have to run this command every time you make a change in the service file): -``` +```bash sudo systemctl daemon-reload ``` -Enable the service to tell the service to start it automatically: -``` +Enable the service to tell it to start automatically: + +```bash sudo systemctl enable stirlingpdf.service ``` See the status of the service: -``` + +```bash sudo systemctl status stirlingpdf.service ``` Manually start/stop/restart the service: -``` + +```bash sudo systemctl start stirlingpdf.service sudo systemctl stop stirlingpdf.service sudo systemctl restart stirlingpdf.service @@ -326,12 +318,11 @@ sudo systemctl restart stirlingpdf.service --- -Remember to set the necessary environment variables before running the project if you want to customize the application the list can be seen in the main readme. +Remember to set the necessary environment variables before running the project if you want to customize the application. The list can be seen in the main readme. -You can do this in the terminal by using the `export` command or -D argument to java -jar command: +You can do this in the terminal by using the `export` command or `-D` argument to the Java `-jar` command: ```bash export APP_HOME_NAME="Stirling PDF" or -DAPP_HOME_NAME="Stirling PDF" -``` diff --git a/PipelineFeature.md b/PipelineFeature.md index 7edbb089..db1daa4f 100644 --- a/PipelineFeature.md +++ b/PipelineFeature.md @@ -1,6 +1,7 @@ # Pipeline Configuration and Usage Tutorial -- Configure the pipeline config file and input files to run files against it -- For reuse, download the config file and re-upload it when needed, or place it in /pipeline/defaultWebUIConfigs/ to auto-load in the web UI for all users + +- Configure the pipeline config file and input files to run files against it. +- For reuse, download the config file and re-upload it when needed, or place it in `/pipeline/defaultWebUIConfigs/` to auto-load in the web UI for all users. ## Steps to Configure and Use Your Pipeline @@ -26,19 +27,16 @@ - Use the **Validation** button to check your pipeline. A green indicator signifies correct setup; a pop-out error indicates issues. 8. **Download Pipeline Configuration** - - To use the configuration for folder scanning (or save it for future use and reupload it), you can also download a JSON file in this menu. You can also pre-load this for future use by placing it in ``/pipeline/defaultWebUIConfigs/``. It will then appear in the dropdown menu for all users to use. + - To use the configuration for folder scanning (or save it for future use and re-upload it), download a JSON file in this menu. You can also pre-load it for future use by placing it in `/pipeline/defaultWebUIConfigs/`. It will then appear in the dropdown menu for all users to use. 9. **Submit Files for Processing** - - If your pipeline is correctly set up close the configure menu, input the files and hit **Submit**. + - If your pipeline is correctly set up, close the configure menu, input the files, and hit **Submit**. 10. **Note on Web UI Limitations** - The current web UI version does not support operations that require multiple different types of inputs, such as adding a separate image to a PDF. - ### Current Limitations -- Cannot have more than one of the same operation -- Cannot input additional files via UI -- All files and operations run in serial mode - - \ No newline at end of file +- Cannot have more than one of the same operation. +- Cannot input additional files via UI. +- All files and operations run in serial mode. diff --git a/README.md b/README.md index 4a16e47b..91adb90f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -

+

Stirling-PDF

[![Docker Pulls](https://img.shields.io/docker/pulls/frooodle/s-pdf)](https://hub.docker.com/r/frooodle/s-pdf) @@ -9,9 +9,9 @@ [![Deploy to DO](https://www.deploytodo.com/do-btn-blue.svg)](https://cloud.digitalocean.com/apps/new?repo=https://github.com/Stirling-Tools/Stirling-PDF/tree/digitalOcean&refcode=c3210994b1af) [Name](https://www.ssdnodes.com/manage/aff.php?aff=2216®ister=true) -This is a robust, locally hosted web-based PDF manipulation tool using Docker. It enables you to carry out various operations on PDF files, including splitting, merging, converting, reorganizing, adding images, rotating, compressing, and more. This locally hosted web application has evolved to encompass a comprehensive set of features, addressing all your PDF requirements. +Stirling-PDF is a robust, locally hosted web-based PDF manipulation tool using Docker. It enables you to carry out various operations on PDF files, including splitting, merging, converting, reorganizing, adding images, rotating, compressing, and more. This locally hosted web application has evolved to encompass a comprehensive set of features, addressing all your PDF requirements. -Stirling PDF does not initiate any outbound calls for record-keeping or tracking purposes. +Stirling-PDF does not initiate any outbound calls for record-keeping or tracking purposes. All files and PDFs exist either exclusively on the client side, reside in server memory only during task execution, or temporarily reside in a file solely for the execution of the task. Any file downloaded by the user will have been deleted from the server by that point. @@ -19,7 +19,7 @@ All files and PDFs exist either exclusively on the client side, reside in server ## Features -- Dark mode support. +- Dark mode support - Custom download options - Parallel file processing and downloads - Custom 'Pipelines' to run multiple features in a queue @@ -27,68 +27,68 @@ All files and PDFs exist either exclusively on the client side, reside in server - Optional Login and Authentication support (see [here](https://github.com/Stirling-Tools/Stirling-PDF/tree/main#login-authentication) for documentation) - Database Backup and Import (see [here](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DATABASE.md) for documentation) -## **PDF Features** +## PDF Features -### **Page Operations** +### Page Operations -- View and modify PDFs - View multi page PDFs with custom viewing sorting and searching. Plus on page edit features like annotate, draw and adding text and images. (Using PDF.js with Joxit and Liberation.Liberation fonts) -- Full interactive GUI for merging/splitting/rotating/moving PDFs and their pages. -- Merge multiple PDFs together into a single resultant file. -- Split PDFs into multiple files at specified page numbers or extract all pages as individual files. -- Reorganize PDF pages into different orders. -- Rotate PDFs in 90-degree increments. -- Remove pages. -- Multi-page layout (Format PDFs into a multi-paged page). -- Scale page contents size by set %. -- Adjust Contrast. -- Crop PDF. -- Auto Split PDF (With physically scanned page dividers). -- Extract page(s). -- Convert PDF to a single page. -- Overlay PDFs ontop of each other +- View and modify PDFs - View multi-page PDFs with custom viewing, sorting, and searching. Plus on-page edit features like annotate, draw, and adding text and images. (Using PDF.js with Joxit and Liberation fonts) +- Full interactive GUI for merging/splitting/rotating/moving PDFs and their pages +- Merge multiple PDFs into a single resultant file +- Split PDFs into multiple files at specified page numbers or extract all pages as individual files +- Reorganize PDF pages into different orders +- Rotate PDFs in 90-degree increments +- Remove pages +- Multi-page layout (format PDFs into a multi-paged page) +- Scale page contents size by set percentage +- Adjust contrast +- Crop PDF +- Auto split PDF (with physically scanned page dividers) +- Extract page(s) +- Convert PDF to a single page +- Overlay PDFs on top of each other -### **Conversion Operations** +### Conversion Operations -- Convert PDFs to and from images. -- Convert any common file to PDF (using LibreOffice). -- Convert PDF to Word/Powerpoint/Others (using LibreOffice). -- Convert HTML to PDF. -- URL to PDF. -- Markdown to PDF. +- Convert PDFs to and from images +- Convert any common file to PDF (using LibreOffice) +- Convert PDF to Word/PowerPoint/others (using LibreOffice) +- Convert HTML to PDF +- URL to PDF +- Markdown to PDF -### **Security & Permissions** +### Security & Permissions -- Add and remove passwords. -- Change/set PDF Permissions. -- Add watermark(s). -- Certify/sign PDFs. -- Sanitize PDFs. -- Auto-redact text. +- Add and remove passwords +- Change/set PDF permissions +- Add watermark(s) +- Certify/sign PDFs +- Sanitize PDFs +- Auto-redact text -### **Other Operations** +### Other Operations -- Add/Generate/Write signatures. -- Repair PDFs. -- Detect and remove blank pages. -- Compare 2 PDFs and show differences in text. -- Add images to PDFs. -- Compress PDFs to decrease their filesize (Using OCRMyPDF). -- Extract images from PDF. -- Extract images from Scans. -- Add page numbers. -- Auto rename file by detecting PDF header text. -- OCR on PDF (Using OCRMyPDF). -- PDF/A conversion (Using OCRMyPDF). -- Edit metadata. -- Flatten PDFs. -- Get all information on a PDF to view or export as JSON. -- Show/Detect embedded Javascript +- Add/generate/write signatures +- Repair PDFs +- Detect and remove blank pages +- Compare two PDFs and show differences in text +- Add images to PDFs +- Compress PDFs to decrease their filesize (using OCRMyPDF) +- Extract images from PDF +- Extract images from scans +- Add page numbers +- Auto rename file by detecting PDF header text +- OCR on PDF (using OCRMyPDF) +- PDF/A conversion (using OCRMyPDF) +- Edit metadata +- Flatten PDFs +- Get all information on a PDF to view or export as JSON +- Show/detect embedded JavaScript -For a overview of the tasks and the technology each uses please view [Endpoint-groups.md](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/Endpoint-groups.md) +For an overview of the tasks and the technology each uses, please view [Endpoint-groups.md](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/Endpoint-groups.md). -Demo of the app is available [here](https://stirlingpdf.io). +A demo of the app is available [here](https://stirlingpdf.io). -## Technologies used +## Technologies Used - Spring Boot + Thymeleaf - [PDFBox](https://github.com/apache/pdfbox/tree/trunk) @@ -99,27 +99,28 @@ Demo of the app is available [here](https://stirlingpdf.io). - [PDF.js](https://github.com/mozilla/pdf.js) - [PDF-LIB.js](https://github.com/Hopding/pdf-lib) -## How to use +## How to Use + ### Windows -For windows users download the latest Stirling-PDF.exe from our [release](https://github.com/Stirling-Tools/Stirling-PDF/releases) section or by clicking [here](https://github.com/Stirling-Tools/Stirling-PDF/releases/latest/download/Stirling-PDF.exe) + +For Windows users, download the latest Stirling-PDF.exe from our [release](https://github.com/Stirling-Tools/Stirling-PDF/releases) section or by clicking [here](https://github.com/Stirling-Tools/Stirling-PDF/releases/latest/download/Stirling-PDF.exe). ### Locally -Please view https://github.com/Stirling-Tools/Stirling-PDF/blob/main/LocalRunGuide.md +Please view the [LocalRunGuide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/LocalRunGuide.md). ### Docker / Podman -https://hub.docker.com/r/frooodle/s-pdf +> [!NOTE] +> + +Stirling-PDF has three different versions: a full version, an ultra-lite version, and a 'fat' version. Depending on the types of features you use, you may want a smaller image to save on space. To see what the different versions offer, please look at our [version mapping](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/Version-groups.md). For people that don't mind space optimization, just use the latest tag. -Stirling PDF has 3 different versions, a Full version and ultra-Lite version as well as a 'Fat' version. Depending on the types of features you use you may want a smaller image to save on space. -To see what the different versions offer please look at our [version mapping](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/Version-groups.md) -For people that don't mind about space optimization just use the latest tag. ![Docker Image Size (tag)](https://img.shields.io/docker/image-size/frooodle/s-pdf/latest?label=Stirling-PDF%20Full) ![Docker Image Size (tag)](https://img.shields.io/docker/image-size/frooodle/s-pdf/latest-ultra-lite?label=Stirling-PDF%20Ultra-Lite) ![Docker Image Size (tag)](https://img.shields.io/docker/image-size/frooodle/s-pdf/latest-fat?label=Stirling-PDF%20Fat) -Please note in below examples you may need to change the volume paths as needed, current examples install them to the current working directory -eg ``./extraConfigs:/configs`` to ``/opt/stirlingpdf/extraConfigs:/configs`` +Please note in the examples below, you may need to change the volume paths as needed, e.g., `./extraConfigs:/configs` to `/opt/stirlingpdf/extraConfigs:/configs`. ### Docker Run @@ -129,15 +130,13 @@ docker run -d \ -v ./trainingData:/usr/share/tessdata \ -v ./extraConfigs:/configs \ -v ./logs:/logs \ +# Optional customization (not required) +# -v /location/of/customFiles:/customFiles \ -e DOCKER_ENABLE_SECURITY=false \ -e INSTALL_BOOK_AND_ADVANCED_HTML_OPS=false \ -e LANGS=en_GB \ --name stirling-pdf \ frooodle/s-pdf:latest - - Can also add these for customisation but are not required - - -v /location/of/customFiles:/customFiles \ ``` ### Docker Compose @@ -150,7 +149,7 @@ services: ports: - '8080:8080' volumes: - - ./trainingData:/usr/share/tessdata #Required for extra OCR languages + - ./trainingData:/usr/share/tessdata # Required for extra OCR languages - ./extraConfigs:/configs # - ./customFiles:/customFiles/ # - ./logs:/logs/ @@ -162,126 +161,123 @@ services: Note: Podman is CLI-compatible with Docker, so simply replace "docker" with "podman". -## Enable OCR/Compression feature +## Enable OCR/Compression Feature -Please view https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToUseOCR.md +Please view the [HowToUseOCR.md](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToUseOCR.md). -## Reuse stored files +## Reuse Stored Files -Certain functionality like ``Sign`` Supports pre-saved files stored at ``/customFiles/signatures/``, image files placed within here will be accesable to be used via webUI -Currently this supports two folder types -- ``/customFiles/signatures/ALL_USERS`` accessible to all users, useful for orginasations were many users use same files or for users not using authentication -- ``/customFiles/signatures/{username}`` such as ``/customFiles/signatures/froodle`` accessible to only the ``froodle`` username, private for all others +Certain functionality like `Sign` supports pre-saved files stored at `/customFiles/signatures/`. Image files placed within here will be accessible to be used via the web UI. Currently, this supports two folder types: + +- `/customFiles/signatures/ALL_USERS`: Accessible to all users, useful for organizations where many users use the same files or for users not using authentication +- `/customFiles/signatures/{username}`: Such as `/customFiles/signatures/froodle`, accessible only to the `froodle` username, private for all others ## Supported Languages -Stirling PDF currently supports 38! +Stirling-PDF currently supports 36 languages! -| Language | Progress | -| ------------------------------------------- | -------------------------------------- | -| Arabic (العربية) (ar_AR) | ![92%](https://geps.dev/progress/92) | -| Basque (Euskara) (eu_ES) | ![56%](https://geps.dev/progress/56) | -| Bulgarian (Български) (bg_BG) | ![98%](https://geps.dev/progress/98) | -| Catalan (Català) (ca_CA) | ![44%](https://geps.dev/progress/44) | -| Croatian (Hrvatski) (hr_HR) | ![86%](https://geps.dev/progress/86) | -| Czech (Česky) (cs_CZ) | ![82%](https://geps.dev/progress/82) | -| Danish (Dansk) (da_DK) | ![90%](https://geps.dev/progress/90) | -| Dutch (Nederlands) (nl_NL) | ![87%](https://geps.dev/progress/87) | -| English (English) (en_GB) | ![100%](https://geps.dev/progress/100) | -| English (US) (en_US) | ![100%](https://geps.dev/progress/100) | -| French (Français) (fr_FR) | ![94%](https://geps.dev/progress/94) | -| German (Deutsch) (de_DE) | ![97%](https://geps.dev/progress/97) | -| Greek (Ελληνικά) (el_GR) | ![75%](https://geps.dev/progress/75) | -| Hindi (हिंदी) (hi_IN) | ![71%](https://geps.dev/progress/71) | -| Hungarian (Magyar) (hu_HU) | ![69%](https://geps.dev/progress/69) | -| Indonesia (Bahasa Indonesia) (id_ID) | ![95%](https://geps.dev/progress/95) | -| Irish (Gaeilge) (ga_IE) | ![89%](https://geps.dev/progress/89) | -| Italian (Italiano) (it_IT) | ![99%](https://geps.dev/progress/99) | -| Japanese (日本語) (ja_JP) | ![86%](https://geps.dev/progress/86) | -| Korean (한국어) (ko_KR) | ![76%](https://geps.dev/progress/76) | -| Norwegian (Norsk) (no_NB) | ![89%](https://geps.dev/progress/89) | -| Polish (Polski) (pl_PL) | ![98%](https://geps.dev/progress/98) | -| Portuguese (Português) (pt_PT) | ![71%](https://geps.dev/progress/71) | -| Portuguese Brazilian (Português) (pt_BR) | ![98%](https://geps.dev/progress/98) | -| Romanian (Română) (ro_RO) | ![91%](https://geps.dev/progress/91) | -| Russian (Русский) (ru_RU) | ![76%](https://geps.dev/progress/76) | +| Language | Progress | +| -------------------------------------------- | -------------------------------------- | +| Arabic (العربية) (ar_AR) | ![92%](https://geps.dev/progress/92) | +| Basque (Euskara) (eu_ES) | ![56%](https://geps.dev/progress/56) | +| Bulgarian (Български) (bg_BG) | ![98%](https://geps.dev/progress/98) | +| Catalan (Català) (ca_CA) | ![44%](https://geps.dev/progress/44) | +| Croatian (Hrvatski) (hr_HR) | ![86%](https://geps.dev/progress/86) | +| Czech (Česky) (cs_CZ) | ![82%](https://geps.dev/progress/82) | +| Danish (Dansk) (da_DK) | ![90%](https://geps.dev/progress/90) | +| Dutch (Nederlands) (nl_NL) | ![87%](https://geps.dev/progress/87) | +| English (English) (en_GB) | ![100%](https://geps.dev/progress/100) | +| English (US) (en_US) | ![100%](https://geps.dev/progress/100) | +| French (Français) (fr_FR) | ![94%](https://geps.dev/progress/94) | +| German (Deutsch) (de_DE) | ![97%](https://geps.dev/progress/97) | +| Greek (Ελληνικά) (el_GR) | ![75%](https://geps.dev/progress/75) | +| Hindi (हिंदी) (hi_IN) | ![71%](https://geps.dev/progress/71) | +| Hungarian (Magyar) (hu_HU) | ![69%](https://geps.dev/progress/69) | +| Indonesian (Bahasa Indonesia) (id_ID) | ![95%](https://geps.dev/progress/95) | +| Irish (Gaeilge) (ga_IE) | ![89%](https://geps.dev/progress/89) | +| Italian (Italiano) (it_IT) | ![99%](https://geps.dev/progress/99) | +| Japanese (日本語) (ja_JP) | ![86%](https://geps.dev/progress/86) | +| Korean (한국어) (ko_KR) | ![76%](https://geps.dev/progress/76) | +| Norwegian (Norsk) (no_NB) | ![89%](https://geps.dev/progress/89) | +| Polish (Polski) (pl_PL) | ![98%](https://geps.dev/progress/98) | +| Portuguese (Português) (pt_PT) | ![71%](https://geps.dev/progress/71) | +| Portuguese Brazilian (Português) (pt_BR) | ![98%](https://geps.dev/progress/98) | +| Romanian (Română) (ro_RO) | ![91%](https://geps.dev/progress/91) | +| Russian (Русский) (ru_RU) | ![76%](https://geps.dev/progress/76) | | Serbian Latin alphabet (Srpski) (sr_LATN_RS) | ![71%](https://geps.dev/progress/71) | -| Simplified Chinese (简体中文) (zh_CN) | ![92%](https://geps.dev/progress/92) | -| Slovakian (Slovensky) (sk_SK) | ![83%](https://geps.dev/progress/83) | -| Spanish (Español) (es_ES) | ![97%](https://geps.dev/progress/97) | -| Swedish (Svenska) (sv_SE) | ![93%](https://geps.dev/progress/93) | -| Thai (ไทย) (th_TH) | ![90%](https://geps.dev/progress/90) | -| Traditional Chinese (繁體中文) (zh_TW) | ![98%](https://geps.dev/progress/98) | -| Turkish (Türkçe) (tr_TR) | ![93%](https://geps.dev/progress/93) | -| Ukrainian (Українська) (uk_UA) | ![81%](https://geps.dev/progress/81) | -| Vietnamese (Tiếng Việt) (vi_VN) | ![90%](https://geps.dev/progress/90) | +| Simplified Chinese (简体中文) (zh_CN) | ![92%](https://geps.dev/progress/92) | +| Slovakian (Slovensky) (sk_SK) | ![83%](https://geps.dev/progress/83) | +| Spanish (Español) (es_ES) | ![97%](https://geps.dev/progress/97) | +| Swedish (Svenska) (sv_SE) | ![93%](https://geps.dev/progress/93) | +| Thai (ไทย) (th_TH) | ![90%](https://geps.dev/progress/90) | +| Traditional Chinese (繁體中文) (zh_TW) | ![98%](https://geps.dev/progress/98) | +| Turkish (Türkçe) (tr_TR) | ![93%](https://geps.dev/progress/93) | +| Ukrainian (Українська) (uk_UA) | ![81%](https://geps.dev/progress/81) | +| Vietnamese (Tiếng Việt) (vi_VN) | ![90%](https://geps.dev/progress/90) | -## Contributing (creating issues, translations, fixing bugs, etc.) +## Contributing (Creating Issues, Translations, Fixing Bugs, etc.) -Please see our [Contributing Guide](CONTRIBUTING.md)! +Please see our [Contributing Guide](CONTRIBUTING.md). -## Customisation +## Customization -Stirling PDF allows easy customization of the app. -Includes things like +Stirling-PDF allows easy customization of the app, including things like: - Custom application name -- Custom slogans, icons, HTML, images CSS etc (via file overrides) +- Custom slogans, icons, HTML, images, CSS, etc. (via file overrides) -There are two options for this, either using the generated settings file ``settings.yml`` -This file is located in the ``/configs`` directory and follows standard YAML formatting +There are two options for this, either using the generated settings file `settings.yml`, which is located in the `/configs` directory and follows standard YAML formatting, or using environment variables, which would override the settings file. -Environment variables are also supported and would override the settings file -For example in the settings.yml you have +For example, in `settings.yml`, you might have: ```yaml security: enableLogin: 'true' ``` -To have this via an environment variable you would have ``SECURITY_ENABLELOGIN`` +To have this via an environment variable, you would use `SECURITY_ENABLELOGIN`. -The Current list of settings is +The current list of settings is: ```yaml security: enableLogin: false # set to 'true' to enable login - csrfDisabled: true # Set to 'true' to disable CSRF protection (not recommended for production) + csrfDisabled: true # set to 'true' to disable CSRF protection (not recommended for production) loginAttemptCount: 5 # lock user account after 5 tries; when using e.g. Fail2Ban you can deactivate the function with -1 loginResetTimeMinutes: 120 # lock account for 2 hours after x attempts loginMethod: all # 'all' (Login Username/Password and OAuth2[must be enabled and configured]), 'normal'(only Login with Username/Password) or 'oauth2'(only Login with OAuth2) initialLogin: - username: '' # Initial username for the first login - password: '' # Initial password for the first login + username: '' # initial username for the first login + password: '' # initial password for the first login oauth2: enabled: false # set to 'true' to enable login (Note: enableLogin must also be 'true' for this to work) client: keycloak: issuer: '' # URL of the Keycloak realm's OpenID Connect Discovery endpoint - clientId: '' # Client ID for Keycloak OAuth2 - clientSecret: '' # Client Secret for Keycloak OAuth2 - scopes: openid, profile, email # Scopes for Keycloak OAuth2 - useAsUsername: preferred_username # Field to use as the username for Keycloak OAuth2 + clientId: '' # client ID for Keycloak OAuth2 + clientSecret: '' # client secret for Keycloak OAuth2 + scopes: openid, profile, email # scopes for Keycloak OAuth2 + useAsUsername: preferred_username # field to use as the username for Keycloak OAuth2 google: - clientId: '' # Client ID for Google OAuth2 - clientSecret: '' # Client Secret for Google OAuth2 - scopes: https://www.googleapis.com/auth/userinfo.email, https://www.googleapis.com/auth/userinfo.profile # Scopes for Google OAuth2 - useAsUsername: email # Field to use as the username for Google OAuth2 + clientId: '' # client ID for Google OAuth2 + clientSecret: '' # client secret for Google OAuth2 + scopes: https://www.googleapis.com/auth/userinfo.email, https://www.googleapis.com/auth/userinfo.profile # scopes for Google OAuth2 + useAsUsername: email # field to use as the username for Google OAuth2 github: - clientId: '' # Client ID for GitHub OAuth2 - clientSecret: '' # Client Secret for GitHub OAuth2 - scopes: read:user # Scope for GitHub OAuth2 - useAsUsername: login # Field to use as the username for GitHub OAuth2 - issuer: '' # set to any provider that supports OpenID Connect Discovery (/.well-known/openid-configuration) end-point - clientId: '' # Client ID from your provider - clientSecret: '' # Client Secret from your provider + clientId: '' # client ID for GitHub OAuth2 + clientSecret: '' # client secret for GitHub OAuth2 + scopes: read:user # scope for GitHub OAuth2 + useAsUsername: login # field to use as the username for GitHub OAuth2 + issuer: '' # set to any provider that supports OpenID Connect Discovery (/.well-known/openid-configuration) endpoint + clientId: '' # client ID from your provider + clientSecret: '' # client secret from your provider autoCreateUser: false # set to 'true' to allow auto-creation of non-existing users blockRegistration: false # set to 'true' to deny login with SSO without prior registration by an admin - useAsUsername: email # Default is 'email'; custom fields can be used as the username - scopes: openid, profile, email # Specify the scopes for which the application will request permissions - provider: google # Set this to your OAuth provider's name, e.g., 'google' or 'keycloak' - saml2: - enabled: false # Currently in alpha, not recommended for use yet, enableAlphaFunctionality must be set to true + useAsUsername: email # default is 'email'; custom fields can be used as the username + scopes: openid, profile, email # specify the scopes for which the application will request permissions + provider: google # set this to your OAuth provider's name, e.g., 'google' or 'keycloak' + saml2: + enabled: false # currently in alpha, not recommended for use yet, enableAlphaFunctionality must be set to true autoCreateUser: false # set to 'true' to allow auto-creation of non-existing users blockRegistration: false # set to 'true' to deny login with SSO without prior registration by an admin registrationId: stirling @@ -289,7 +285,7 @@ security: idpSingleLogoutUrl: https://dev-XXXXXXXX.okta.com/app/dev-XXXXXXXX_stirlingpdf_1/externalKey/slo/saml idpSingleLoginUrl: https://dev-XXXXXXXX.okta.com/app/dev-XXXXXXXX_stirlingpdf_1/externalKey/sso/saml idpIssuer: http://www.okta.com/externalKey - idpCert: classpath:octa.crt + idpCert: classpath:okta.crt privateKey: classpath:saml-private-key.key spCert: classpath:saml-public-cert.crt @@ -298,35 +294,35 @@ enterpriseEdition: key: 00000000-0000-0000-0000-000000000000 CustomMetadata: autoUpdateMetadata: false # set to 'true' to automatically update metadata with below values - author: username # Supports text such as 'John Doe' or types such as username to autopopulate with users username - creator: Stirling-PDF # Supports text such as 'Company-PDF' - producer: Stirling-PDF # Supports text such as 'Company-PDF' + author: username # supports text such as 'John Doe' or types such as username to autopopulate with user's username + creator: Stirling-PDF # supports text such as 'Company-PDF' + producer: Stirling-PDF # supports text such as 'Company-PDF' legal: - termsAndConditions: https://www.stirlingpdf.com/terms-and-conditions # URL to the terms and conditions of your application (e.g. https://example.com/terms) Empty string to disable or filename to load from local file in static folder - privacyPolicy: https://www.stirlingpdf.com/privacy-policy # URL to the privacy policy of your application (e.g. https://example.com/privacy) Empty string to disable or filename to load from local file in static folder - accessibilityStatement: '' # URL to the accessibility statement of your application (e.g. https://example.com/accessibility) Empty string to disable or filename to load from local file in static folder - cookiePolicy: '' # URL to the cookie policy of your application (e.g. https://example.com/cookie) Empty string to disable or filename to load from local file in static folder - impressum: '' # URL to the impressum of your application (e.g. https://example.com/impressum) Empty string to disable or filename to load from local file in static folder + termsAndConditions: https://www.stirlingpdf.com/terms-and-conditions # URL to the terms and conditions of your application (e.g. https://example.com/terms). Empty string to disable or filename to load from local file in static folder + privacyPolicy: https://www.stirlingpdf.com/privacy-policy # URL to the privacy policy of your application (e.g. https://example.com/privacy). Empty string to disable or filename to load from local file in static folder + accessibilityStatement: '' # URL to the accessibility statement of your application (e.g. https://example.com/accessibility). Empty string to disable or filename to load from local file in static folder + cookiePolicy: '' # URL to the cookie policy of your application (e.g. https://example.com/cookie). Empty string to disable or filename to load from local file in static folder + impressum: '' # URL to the impressum of your application (e.g. https://example.com/impressum). Empty string to disable or filename to load from local file in static folder system: - defaultLocale: en-US # Set the default language (e.g. 'de-DE', 'fr-FR', etc) + defaultLocale: en-US # set the default language (e.g. 'de-DE', 'fr-FR', etc) googlevisibility: false # 'true' to allow Google visibility (via robots.txt), 'false' to disallow - enableAlphaFunctionality: false # Set to enable functionality which might need more testing before it fully goes live (This feature might make no changes) + enableAlphaFunctionality: false # set to enable functionality which might need more testing before it fully goes live (this feature might make no changes) showUpdate: false # see when a new update is available - showUpdateOnlyAdmin: false # Only admins can see when a new update is available, depending on showUpdate it must be set to 'true' - customHTMLFiles: false # enable to have files placed in /customFiles/templates override the existing template html files - tessdataDir: /usr/share/tessdata # Path to the directory containing the Tessdata files. This setting is relevant for Windows systems. For Windows users, this path should be adjusted to point to the appropriate directory where the Tessdata files are stored. - enableAnalytics: undefined # Set to 'true' to enable analytics, set to 'false' to disable analytics, for enterprise users this is set to true + showUpdateOnlyAdmin: false # only admins can see when a new update is available, depending on showUpdate it must be set to 'true' + customHTMLFiles: false # enable to have files placed in /customFiles/templates override the existing template HTML files + tessdataDir: /usr/share/tessdata # path to the directory containing the Tessdata files. This setting is relevant for Windows systems. For Windows users, this path should be adjusted to point to the appropriate directory where the Tessdata files are stored. + enableAnalytics: undefined # set to 'true' to enable analytics, set to 'false' to disable analytics; for enterprise users, this is set to true ui: - appName: '' # Application's visible name - homeDescription: '' # Short description or tagline shown on homepage. - appNameNavbar: '' # Name displayed on the navigation bar + appName: '' # application's visible name + homeDescription: '' # short description or tagline shown on the homepage + appNameNavbar: '' # name displayed on the navigation bar endpoints: - toRemove: [] # List endpoints to disable (e.g. ['img-to-pdf', 'remove-pages']) - groupsToRemove: [] # List groups to disable (e.g. ['LibreOffice']) + toRemove: [] # list endpoints to disable (e.g. ['img-to-pdf', 'remove-pages']) + groupsToRemove: [] # list groups to disable (e.g. ['LibreOffice']) metrics: enabled: true # 'true' to enable Info APIs (`/api/*`) endpoints, 'false' to disable @@ -337,63 +333,62 @@ AutomaticallyGenerated: UUID: example ``` -There is an additional config file ``/configs/custom_settings.yml`` were users familiar with java and spring application.properties can input their own settings on-top of Stirling-PDFs existing ones +There is an additional config file `/configs/custom_settings.yml` where users familiar with Java and Spring `application.properties` can input their own settings on top of Stirling-PDF's existing ones. -### Extra notes +### Extra Notes -- Endpoints. Currently, the endpoints ENDPOINTS_TO_REMOVE and GROUPS_TO_REMOVE can include comma separate lists of endpoints and groups to disable as example ENDPOINTS_TO_REMOVE=img-to-pdf,remove-pages would disable both image-to-pdf and remove pages, GROUPS_TO_REMOVE=LibreOffice Would disable all things that use LibreOffice. You can see a list of all endpoints and groups [here](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/Endpoint-groups.md) -- customStaticFilePath. Customise static files such as the app logo by placing files in the /customFiles/static/ directory. An example of customising app logo is placing a /customFiles/static/favicon.svg to override current SVG. This can be used to change any images/icons/css/fonts/js etc in Stirling-PDF +- **Endpoints**: Currently, the `ENDPOINTS_TO_REMOVE` and `GROUPS_TO_REMOVE` endpoints can include comma-separated lists of endpoints and groups to disable. For example, `ENDPOINTS_TO_REMOVE=img-to-pdf,remove-pages` would disable both image-to-pdf and remove pages, while `GROUPS_TO_REMOVE=LibreOffice` would disable all things that use LibreOffice. You can see a list of all endpoints and groups [here](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/Endpoint-groups.md). +- **customStaticFilePath**: Customize static files such as the app logo by placing files in the `/customFiles/static/` directory. An example of customizing the app logo is placing `/customFiles/static/favicon.svg` to override the current SVG. This can be used to change any `images/icons/css/fonts/js`, etc. in Stirling-PDF. -### Environment only parameters +### Environment-Only Parameters -- ``SYSTEM_ROOTURIPATH`` ie set to ``/pdf-app`` to Set the application's root URI to ``localhost:8080/pdf-app`` -- ``SYSTEM_CONNECTIONTIMEOUTMINUTES`` to set custom connection timeout values -- ``DOCKER_ENABLE_SECURITY`` to tell docker to download security jar (required as true for auth login) -- ``INSTALL_BOOK_AND_ADVANCED_HTML_OPS`` to download calibre onto stirling-pdf enabling pdf to/from book and advanced html conversion -- ``LANGS`` to define custom font libraries to install for use for document conversions +- `SYSTEM_ROOTURIPATH` - Set the application's root URI (e.g. `/pdf-app` to set the root URI to `localhost:8080/pdf-app`) +- `SYSTEM_CONNECTIONTIMEOUTMINUTES` - Set custom connection timeout values +- `DOCKER_ENABLE_SECURITY` - Set to `true` to download security jar (required for authentication login) +- `INSTALL_BOOK_AND_ADVANCED_HTML_OPS` - Download Calibre onto Stirling-PDF to enable PDF to/from book and advanced HTML conversion +- `LANGS` - Define custom font libraries to install for document conversions ## API -For those wanting to use Stirling-PDFs backend API to link with their own custom scripting to edit PDFs you can view all existing API documentation -[here](https://app.swaggerhub.com/apis-docs/Stirling-Tools/Stirling-PDF/) or navigate to /swagger-ui/index.html of your stirling-pdf instance for your versions documentation (Or by following the API button in your settings of Stirling-PDF) +For those wanting to use Stirling-PDF's backend API to link with their own custom scripting to edit PDFs, you can view all existing API documentation [here](https://app.swaggerhub.com/apis-docs/Stirling-Tools/Stirling-PDF/), or navigate to `/swagger-ui/index.html` of your Stirling-PDF instance for your version's documentation (or by following the API button in the settings of Stirling-PDF). -## Login authentication +## Login Authentication ![stirling-login](images/login-light.png) ### Prerequisites -- User must have the folder ./configs volumed within docker so that it is retained during updates. -- Docker users must download the security jar version by setting ``DOCKER_ENABLE_SECURITY`` to ``true`` in environment variables. -- Then either enable login via the settings.yml file or via setting ``SECURITY_ENABLE_LOGIN`` to ``true`` -- Now the initial user will be generated with username ``admin`` and password ``stirling``. On login you will be forced to change the password to a new one. You can also use the environment variables ``SECURITY_INITIALLOGIN_USERNAME`` and ``SECURITY_INITIALLOGIN_PASSWORD`` to set your own straight away (Recommended to remove them after user creation). +- User must have the folder `./configs` volumed within Docker so that it is retained during updates. +- Docker users must download the security jar version by setting `DOCKER_ENABLE_SECURITY` to `true` in environment variables. +- Then either enable login via the `settings.yml` file or set `SECURITY_ENABLE_LOGIN` to `true`. +- Now the initial user will be generated with username `admin` and password `stirling`. On login, you will be forced to change the password to a new one. You can also use the environment variables `SECURITY_INITIALLOGIN_USERNAME` and `SECURITY_INITIALLOGIN_PASSWORD` to set your own credentials straight away (recommended to remove them after user creation). -Once the above has been done, on restart, a new stirling-pdf-DB.mv.db will show if everything worked. +Once the above has been done, on restart, a new `stirling-pdf-DB.mv.db` will show if everything worked. -When you login to Stirling PDF you will be redirected to /login page to login with those default credentials. After login everything should function as normal +When you log in to Stirling-PDF, you will be redirected to the `/login` page to log in with those default credentials. After login, everything should function as normal. -To access your account settings go to Account settings in the settings cog menu (top right in navbar) This Account settings menu is also where you find your API key. +To access your account settings, go to Account Settings in the settings cog menu (top right in the navbar). This Account Settings menu is also where you find your API key. -To add new users go to the bottom of Account settings and hit 'Admin Settings', here you can add new users. The different roles mentioned within this are for rate limiting. This is a Work in progress which will be expanding on more in future +To add new users, go to the bottom of Account Settings and hit 'Admin Settings'. Here you can add new users. The different roles mentioned within this are for rate limiting. This is a work in progress and will be expanded on more in the future. -For API usage you must provide a header with 'X-API-Key' and the associated API key for that user. +For API usage, you must provide a header with `X-API-Key` and the associated API key for that user. ## FAQ ### Q1: What are your planned features? -- Progress bar/Tracking -- Full custom logic pipelines to combine multiple operations together. -- Folder support with auto scanning to perform operations on -- Redact text (Via UI not just automated way) -- Add Forms -- Multi page layout (Stich PDF pages together) support x rows y columns and custom page sizing +- Progress bar/tracking +- Full custom logic pipelines to combine multiple operations together +- Folder support with auto-scanning to perform operations on +- Redact text (via UI, not just automated) +- Add forms +- Multi-page layout (stitch PDF pages together) support x rows y columns and custom page sizing - Fill forms manually or automatically ### Q2: Why is my application downloading .htm files? -This is an issue caused commonly by your NGINX configuration. The default file upload size for NGINX is 1MB, you need to add the following in your Nginx sites-available file. ``client_max_body_size SIZE;`` Where "SIZE" is 50M for example for 50MB files. +This is an issue commonly caused by your NGINX configuration. The default file upload size for NGINX is 1MB. You need to add the following in your Nginx sites-available file: `client_max_body_size SIZE;` (where "SIZE" is 50M for example for 50MB files). -### Q3: Why is my download timing out +### Q3: Why is my download timing out? -NGINX has timeout values by default so if you are running Stirling-PDF behind NGINX you may need to set a timeout value such as adding the config ``proxy_read_timeout 3600;`` +NGINX has timeout values by default, so if you are running Stirling-PDF behind NGINX, you may need to set a timeout value, such as adding the config `proxy_read_timeout 3600;`. diff --git a/Version-groups.md b/Version-groups.md index 0e1bc092..84bf749d 100644 --- a/Version-groups.md +++ b/Version-groups.md @@ -1,7 +1,7 @@ |All versions in a Docker environment can download Calibre as a optional extra at runtime to support `book-to-pdf` and `pdf-to-book` using parameter ``INSTALL_BOOK_AND_ADVANCED_HTML_OPS``. -The 'Fat' container contains all those found in 'Full' with security jar along with this Calibre install. +The 'Fat' container contains all those found in 'Full' with security jar along with this Calibre install. -Technology | Ultra-Lite | Full | +| Technology | Ultra-Lite | Full | | ---------- | :--------: | :---: | | Java | ✔️ | ✔️ | | JavaScript | ✔️ | ✔️ | diff --git a/src/main/resources/settings.yml.template b/src/main/resources/settings.yml.template index 0381d2cf..84f628ba 100644 --- a/src/main/resources/settings.yml.template +++ b/src/main/resources/settings.yml.template @@ -13,42 +13,42 @@ security: enableLogin: false # set to 'true' to enable login - csrfDisabled: true # Set to 'true' to disable CSRF protection (not recommended for production) + csrfDisabled: true # set to 'true' to disable CSRF protection (not recommended for production) loginAttemptCount: 5 # lock user account after 5 tries; when using e.g. Fail2Ban you can deactivate the function with -1 loginResetTimeMinutes: 120 # lock account for 2 hours after x attempts loginMethod: all # 'all' (Login Username/Password and OAuth2[must be enabled and configured]), 'normal'(only Login with Username/Password) or 'oauth2'(only Login with OAuth2) initialLogin: - username: '' # Initial username for the first login - password: '' # Initial password for the first login + username: '' # initial username for the first login + password: '' # initial password for the first login oauth2: enabled: false # set to 'true' to enable login (Note: enableLogin must also be 'true' for this to work) client: keycloak: issuer: '' # URL of the Keycloak realm's OpenID Connect Discovery endpoint - clientId: '' # Client ID for Keycloak OAuth2 - clientSecret: '' # Client Secret for Keycloak OAuth2 - scopes: openid, profile, email # Scopes for Keycloak OAuth2 - useAsUsername: preferred_username # Field to use as the username for Keycloak OAuth2 + clientId: '' # client ID for Keycloak OAuth2 + clientSecret: '' # client secret for Keycloak OAuth2 + scopes: openid, profile, email # scopes for Keycloak OAuth2 + useAsUsername: preferred_username # field to use as the username for Keycloak OAuth2 google: - clientId: '' # Client ID for Google OAuth2 - clientSecret: '' # Client Secret for Google OAuth2 - scopes: https://www.googleapis.com/auth/userinfo.email, https://www.googleapis.com/auth/userinfo.profile # Scopes for Google OAuth2 - useAsUsername: email # Field to use as the username for Google OAuth2 + clientId: '' # client ID for Google OAuth2 + clientSecret: '' # client secret for Google OAuth2 + scopes: https://www.googleapis.com/auth/userinfo.email, https://www.googleapis.com/auth/userinfo.profile # scopes for Google OAuth2 + useAsUsername: email # field to use as the username for Google OAuth2 github: - clientId: '' # Client ID for GitHub OAuth2 - clientSecret: '' # Client Secret for GitHub OAuth2 - scopes: read:user # Scope for GitHub OAuth2 - useAsUsername: login # Field to use as the username for GitHub OAuth2 - issuer: '' # set to any provider that supports OpenID Connect Discovery (/.well-known/openid-configuration) end-point - clientId: '' # Client ID from your provider - clientSecret: '' # Client Secret from your provider + clientId: '' # client ID for GitHub OAuth2 + clientSecret: '' # client secret for GitHub OAuth2 + scopes: read:user # scope for GitHub OAuth2 + useAsUsername: login # field to use as the username for GitHub OAuth2 + issuer: '' # set to any provider that supports OpenID Connect Discovery (/.well-known/openid-configuration) endpoint + clientId: '' # client ID from your provider + clientSecret: '' # client secret from your provider autoCreateUser: false # set to 'true' to allow auto-creation of non-existing users blockRegistration: false # set to 'true' to deny login with SSO without prior registration by an admin - useAsUsername: email # Default is 'email'; custom fields can be used as the username - scopes: openid, profile, email # Specify the scopes for which the application will request permissions - provider: google # Set this to your OAuth provider's name, e.g., 'google' or 'keycloak' - saml2: - enabled: false # Currently in alpha, not recommended for use yet, enableAlphaFunctionality must be set to true + useAsUsername: email # default is 'email'; custom fields can be used as the username + scopes: openid, profile, email # specify the scopes for which the application will request permissions + provider: google # set this to your OAuth provider's name, e.g., 'google' or 'keycloak' + saml2: + enabled: false # currently in alpha, not recommended for use yet, enableAlphaFunctionality must be set to true autoCreateUser: false # set to 'true' to allow auto-creation of non-existing users blockRegistration: false # set to 'true' to deny login with SSO without prior registration by an admin registrationId: stirling @@ -56,7 +56,7 @@ security: idpSingleLogoutUrl: https://dev-XXXXXXXX.okta.com/app/dev-XXXXXXXX_stirlingpdf_1/externalKey/slo/saml idpSingleLoginUrl: https://dev-XXXXXXXX.okta.com/app/dev-XXXXXXXX_stirlingpdf_1/externalKey/sso/saml idpIssuer: http://www.okta.com/externalKey - idpCert: classpath:octa.crt + idpCert: classpath:okta.crt privateKey: classpath:saml-private-key.key spCert: classpath:saml-public-cert.crt @@ -65,35 +65,35 @@ enterpriseEdition: key: 00000000-0000-0000-0000-000000000000 CustomMetadata: autoUpdateMetadata: false # set to 'true' to automatically update metadata with below values - author: username # Supports text such as 'John Doe' or types such as username to autopopulate with users username - creator: Stirling-PDF # Supports text such as 'Company-PDF' - producer: Stirling-PDF # Supports text such as 'Company-PDF' + author: username # supports text such as 'John Doe' or types such as username to autopopulate with user's username + creator: Stirling-PDF # supports text such as 'Company-PDF' + producer: Stirling-PDF # supports text such as 'Company-PDF' legal: - termsAndConditions: https://www.stirlingpdf.com/terms-and-conditions # URL to the terms and conditions of your application (e.g. https://example.com/terms) Empty string to disable or filename to load from local file in static folder - privacyPolicy: https://www.stirlingpdf.com/privacy-policy # URL to the privacy policy of your application (e.g. https://example.com/privacy) Empty string to disable or filename to load from local file in static folder - accessibilityStatement: '' # URL to the accessibility statement of your application (e.g. https://example.com/accessibility) Empty string to disable or filename to load from local file in static folder - cookiePolicy: '' # URL to the cookie policy of your application (e.g. https://example.com/cookie) Empty string to disable or filename to load from local file in static folder - impressum: '' # URL to the impressum of your application (e.g. https://example.com/impressum) Empty string to disable or filename to load from local file in static folder + termsAndConditions: https://www.stirlingpdf.com/terms-and-conditions # URL to the terms and conditions of your application (e.g. https://example.com/terms). Empty string to disable or filename to load from local file in static folder + privacyPolicy: https://www.stirlingpdf.com/privacy-policy # URL to the privacy policy of your application (e.g. https://example.com/privacy). Empty string to disable or filename to load from local file in static folder + accessibilityStatement: '' # URL to the accessibility statement of your application (e.g. https://example.com/accessibility). Empty string to disable or filename to load from local file in static folder + cookiePolicy: '' # URL to the cookie policy of your application (e.g. https://example.com/cookie). Empty string to disable or filename to load from local file in static folder + impressum: '' # URL to the impressum of your application (e.g. https://example.com/impressum). Empty string to disable or filename to load from local file in static folder system: - defaultLocale: en-US # Set the default language (e.g. 'de-DE', 'fr-FR', etc) + defaultLocale: en-US # set the default language (e.g. 'de-DE', 'fr-FR', etc) googlevisibility: false # 'true' to allow Google visibility (via robots.txt), 'false' to disallow - enableAlphaFunctionality: false # Set to enable functionality which might need more testing before it fully goes live (This feature might make no changes) + enableAlphaFunctionality: false # set to enable functionality which might need more testing before it fully goes live (this feature might make no changes) showUpdate: false # see when a new update is available - showUpdateOnlyAdmin: false # Only admins can see when a new update is available, depending on showUpdate it must be set to 'true' - customHTMLFiles: false # enable to have files placed in /customFiles/templates override the existing template html files - tessdataDir: /usr/share/tessdata # Path to the directory containing the Tessdata files. This setting is relevant for Windows systems. For Windows users, this path should be adjusted to point to the appropriate directory where the Tessdata files are stored. - enableAnalytics: undefined # Set to 'true' to enable analytics, set to 'false' to disable analytics, for enterprise users this is set to true + showUpdateOnlyAdmin: false # only admins can see when a new update is available, depending on showUpdate it must be set to 'true' + customHTMLFiles: false # enable to have files placed in /customFiles/templates override the existing template HTML files + tessdataDir: /usr/share/tessdata # path to the directory containing the Tessdata files. This setting is relevant for Windows systems. For Windows users, this path should be adjusted to point to the appropriate directory where the Tessdata files are stored. + enableAnalytics: undefined # set to 'true' to enable analytics, set to 'false' to disable analytics; for enterprise users, this is set to true ui: - appName: '' # Application's visible name - homeDescription: '' # Short description or tagline shown on homepage. - appNameNavbar: '' # Name displayed on the navigation bar + appName: '' # application's visible name + homeDescription: '' # short description or tagline shown on the homepage + appNameNavbar: '' # name displayed on the navigation bar endpoints: - toRemove: [] # List endpoints to disable (e.g. ['img-to-pdf', 'remove-pages']) - groupsToRemove: [] # List groups to disable (e.g. ['LibreOffice']) + toRemove: [] # list endpoints to disable (e.g. ['img-to-pdf', 'remove-pages']) + groupsToRemove: [] # list groups to disable (e.g. ['LibreOffice']) metrics: enabled: true # 'true' to enable Info APIs (`/api/*`) endpoints, 'false' to disable From a8d0d1a8712f0aa84be4f1a651e233b4090fabe8 Mon Sep 17 00:00:00 2001 From: Ludy Date: Sun, 3 Nov 2024 08:21:56 +0100 Subject: [PATCH 12/23] re-config labeler & add new labels (#2153) Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com> --- .github/labeler-config.yml | 17 +++++++++++++---- .github/labels.yml | 21 +++++++++++++++++++-- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/.github/labeler-config.yml b/.github/labeler-config.yml index f777e3ea..d91bca36 100644 --- a/.github/labeler-config.yml +++ b/.github/labeler-config.yml @@ -16,21 +16,27 @@ Java: Back End: - changed-files: - - any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/config/security/**/*' - - any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/config/model/provider/**/*' + - any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/config/**/*' + - any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/controller/**/*' - any-glob-to-any-file: 'src/main/resources/settings.yml.template' + - any-glob-to-any-file: 'src/main/resources/application.properties' - any-glob-to-any-file: 'src/main/resources/banner.txt' + - any-glob-to-any-file: 'scripts/png_to_webp.py' + - any-glob-to-any-file: 'split_photos.py' Security: - changed-files: - any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/config/security/**/*' - - any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/config/model/provider/**/*' - - any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/config/model/AuthenticationType.java' + - any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/model/provider/**/*' + - any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/model/AuthenticationType.java' + - any-glob-to-any-file: 'scripts/download-security-jar.sh' API: - changed-files: - any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/controller/web/MetricsController.java' - any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/controller/api/**/*' + - any-glob-to-any-file: 'scripts/png_to_webp.py' + - any-glob-to-any-file: 'split_photos.py' Documentation: - changed-files: @@ -43,6 +49,9 @@ Docker: - any-glob-to-any-file: 'Dockerfile' - any-glob-to-any-file: 'Dockerfile-*' - any-glob-to-any-file: 'exampleYmlFiles/*.yml' + - any-glob-to-any-file: 'scripts/init.sh' + - any-glob-to-any-file: 'scripts/init-without-ocr.sh' + - any-glob-to-any-file: 'scripts/installFonts.sh' Test: - changed-files: diff --git a/.github/labels.yml b/.github/labels.yml index 1d717e6f..47f4be7f 100644 --- a/.github/labels.yml +++ b/.github/labels.yml @@ -3,9 +3,12 @@ # # The repository labels will be automatically configured using this file and # the GitHub Action https://github.com/marketplace/actions/github-labeler. +- name: "Licenses" + color: "EDEDED" + from_name: "licenses" - name: "Back End" color: "20CE6C" - description: "Issues related to back-end development" + description: "Issues or pull requests related to back-end development" from_name: "Back end" - name: "Bug" description: "Something isn't working" @@ -24,6 +27,7 @@ from_name: "documentation" - name: "Done for next release" color: "0CDBD1" + description: "Items that are completed and will be included in the next release" - name: "Done" color: "60F13B" - name: "duplicate" @@ -37,7 +41,7 @@ description: "Fix needs to be confirmed" - name: "Front End" color: "BBD2F1" - description: "Issues related to front-end development" + description: "Issues or pull requests related to front-end development" - name: "github-actions" description: "Pull requests that update GitHub Actions code" color: "999999" @@ -91,3 +95,16 @@ description: "Testing-related issues or pull requests" - name: "Stale" color: "000000" + description: "Issues or pull requests that have become inactive" +- name: "Priority: Critical" + color: "000000" + description: "Issues or pull requests with the highest priority" +- name: "Priority: High" + color: "FF0000" + description: "Issues or pull requests with high priority" +- name: "Priority: Medium" + color: "FFFF00" + description: "Issues or pull requests with medium priority" +- name: "Priority: Low" + color: "00FF00" + description: "Issues or pull requests with low priority" From cf13803fd46f10f4555de54f4a9f418d12f1e610 Mon Sep 17 00:00:00 2001 From: Ludy Date: Sun, 3 Nov 2024 08:24:16 +0100 Subject: [PATCH 13/23] Fix: redeclaration of const and add: tranlation placeholder for Session Expiry Messages (#2158) Fix: redeclaration of const --- src/main/resources/messages_ar_AR.properties | 1 + src/main/resources/messages_bg_BG.properties | 1 + src/main/resources/messages_ca_CA.properties | 1 + src/main/resources/messages_cs_CZ.properties | 1 + src/main/resources/messages_da_DK.properties | 1 + src/main/resources/messages_de_DE.properties | 1 + src/main/resources/messages_el_GR.properties | 1 + src/main/resources/messages_en_GB.properties | 1 + src/main/resources/messages_en_US.properties | 1 + src/main/resources/messages_es_ES.properties | 1 + src/main/resources/messages_eu_ES.properties | 1 + src/main/resources/messages_fr_FR.properties | 1 + src/main/resources/messages_ga_IE.properties | 1 + src/main/resources/messages_hi_IN.properties | 1 + src/main/resources/messages_hr_HR.properties | 1 + src/main/resources/messages_hu_HU.properties | 1 + src/main/resources/messages_id_ID.properties | 1 + src/main/resources/messages_it_IT.properties | 1 + src/main/resources/messages_ja_JP.properties | 1 + src/main/resources/messages_ko_KR.properties | 1 + src/main/resources/messages_nl_NL.properties | 1 + src/main/resources/messages_no_NB.properties | 1 + src/main/resources/messages_pl_PL.properties | 1 + src/main/resources/messages_pt_BR.properties | 1 + src/main/resources/messages_pt_PT.properties | 1 + src/main/resources/messages_ro_RO.properties | 1 + src/main/resources/messages_ru_RU.properties | 1 + src/main/resources/messages_sk_SK.properties | 1 + .../resources/messages_sr_LATN_RS.properties | 1 + src/main/resources/messages_sv_SE.properties | 1 + src/main/resources/messages_th_TH.properties | 1 + src/main/resources/messages_tr_TR.properties | 1 + src/main/resources/messages_uk_UA.properties | 1 + src/main/resources/messages_vi_VN.properties | 1 + src/main/resources/messages_zh_CN.properties | 1 + src/main/resources/messages_zh_TW.properties | 1 + src/main/resources/static/js/downloader.js | 546 +++++++++--------- .../resources/templates/fragments/common.html | 20 +- 38 files changed, 326 insertions(+), 276 deletions(-) diff --git a/src/main/resources/messages_ar_AR.properties b/src/main/resources/messages_ar_AR.properties index fc34aa3f..37673674 100644 --- a/src/main/resources/messages_ar_AR.properties +++ b/src/main/resources/messages_ar_AR.properties @@ -246,6 +246,7 @@ database.fileNullOrEmpty=يجب ألا يكون الملف فارغًا أو خ database.failedImportFile=فشل استيراد الملف session.expired=Your session has expired. Please refresh the page and try again. +session.refreshPage=Refresh Page ############# # HOME-PAGE # diff --git a/src/main/resources/messages_bg_BG.properties b/src/main/resources/messages_bg_BG.properties index 8f9dc2db..4d92ae1f 100644 --- a/src/main/resources/messages_bg_BG.properties +++ b/src/main/resources/messages_bg_BG.properties @@ -246,6 +246,7 @@ database.fileNullOrEmpty=Файлът не трябва да е нулев ил database.failedImportFile=Неуспешно импортиране на файл session.expired=Вашата сесия е изтекла. Моля, опреснете страницата и опитайте отново. +session.refreshPage=Refresh Page ############# # HOME-PAGE # diff --git a/src/main/resources/messages_ca_CA.properties b/src/main/resources/messages_ca_CA.properties index 8569f410..02d1c556 100644 --- a/src/main/resources/messages_ca_CA.properties +++ b/src/main/resources/messages_ca_CA.properties @@ -246,6 +246,7 @@ database.fileNullOrEmpty=File must not be null or empty database.failedImportFile=Failed Import File session.expired=Your session has expired. Please refresh the page and try again. +session.refreshPage=Refresh Page ############# # HOME-PAGE # diff --git a/src/main/resources/messages_cs_CZ.properties b/src/main/resources/messages_cs_CZ.properties index e4920e4f..1fd579b2 100644 --- a/src/main/resources/messages_cs_CZ.properties +++ b/src/main/resources/messages_cs_CZ.properties @@ -246,6 +246,7 @@ database.fileNullOrEmpty=File must not be null or empty database.failedImportFile=Failed Import File session.expired=Your session has expired. Please refresh the page and try again. +session.refreshPage=Refresh Page ############# # HOME-PAGE # diff --git a/src/main/resources/messages_da_DK.properties b/src/main/resources/messages_da_DK.properties index 47740a2d..bc236d05 100644 --- a/src/main/resources/messages_da_DK.properties +++ b/src/main/resources/messages_da_DK.properties @@ -246,6 +246,7 @@ database.fileNullOrEmpty=Fil må ikke være null eller tom database.failedImportFile=Kunne ikke importere fil session.expired=Your session has expired. Please refresh the page and try again. +session.refreshPage=Refresh Page ############# # HOME-PAGE # diff --git a/src/main/resources/messages_de_DE.properties b/src/main/resources/messages_de_DE.properties index 87dc3f79..41791505 100644 --- a/src/main/resources/messages_de_DE.properties +++ b/src/main/resources/messages_de_DE.properties @@ -246,6 +246,7 @@ database.fileNullOrEmpty=Datei darf nicht null oder leer sein database.failedImportFile=Dateiimport fehlgeschlagen session.expired=Your session has expired. Please refresh the page and try again. +session.refreshPage=Refresh Page ############# # HOME-PAGE # diff --git a/src/main/resources/messages_el_GR.properties b/src/main/resources/messages_el_GR.properties index e6939cf5..bdc60f14 100644 --- a/src/main/resources/messages_el_GR.properties +++ b/src/main/resources/messages_el_GR.properties @@ -246,6 +246,7 @@ database.fileNullOrEmpty=File must not be null or empty database.failedImportFile=Failed Import File session.expired=Your session has expired. Please refresh the page and try again. +session.refreshPage=Refresh Page ############# # HOME-PAGE # diff --git a/src/main/resources/messages_en_GB.properties b/src/main/resources/messages_en_GB.properties index f124bec8..ebfce1f5 100644 --- a/src/main/resources/messages_en_GB.properties +++ b/src/main/resources/messages_en_GB.properties @@ -246,6 +246,7 @@ database.fileNullOrEmpty=File must not be null or empty database.failedImportFile=Failed to import file session.expired=Your session has expired. Please refresh the page and try again. +session.refreshPage=Refresh Page ############# # HOME-PAGE # diff --git a/src/main/resources/messages_en_US.properties b/src/main/resources/messages_en_US.properties index 2da78640..363e8345 100644 --- a/src/main/resources/messages_en_US.properties +++ b/src/main/resources/messages_en_US.properties @@ -246,6 +246,7 @@ database.fileNullOrEmpty=File must not be null or empty database.failedImportFile=Failed Import File session.expired=Your session has expired. Please refresh the page and try again. +session.refreshPage=Refresh Page ############# # HOME-PAGE # diff --git a/src/main/resources/messages_es_ES.properties b/src/main/resources/messages_es_ES.properties index a5b9a212..04951c50 100644 --- a/src/main/resources/messages_es_ES.properties +++ b/src/main/resources/messages_es_ES.properties @@ -246,6 +246,7 @@ database.fileNullOrEmpty=El archivo no debe ser nulo o vacío. database.failedImportFile=Archivo de importación fallido session.expired=Tu sesión ha caducado. Actualice la página e inténtelo de nuevo. +session.refreshPage=Refresh Page ############# # HOME-PAGE # diff --git a/src/main/resources/messages_eu_ES.properties b/src/main/resources/messages_eu_ES.properties index 8bbb78d2..a778d12a 100644 --- a/src/main/resources/messages_eu_ES.properties +++ b/src/main/resources/messages_eu_ES.properties @@ -246,6 +246,7 @@ database.fileNullOrEmpty=File must not be null or empty database.failedImportFile=Failed Import File session.expired=Your session has expired. Please refresh the page and try again. +session.refreshPage=Refresh Page ############# # HOME-PAGE # diff --git a/src/main/resources/messages_fr_FR.properties b/src/main/resources/messages_fr_FR.properties index ff7277c8..8d4b4024 100644 --- a/src/main/resources/messages_fr_FR.properties +++ b/src/main/resources/messages_fr_FR.properties @@ -246,6 +246,7 @@ database.fileNullOrEmpty=File must not be null or empty database.failedImportFile=Failed Import File session.expired=Votre session a expiré. Veuillez recharger la page et réessayer. +session.refreshPage=Refresh Page ############# # HOME-PAGE # diff --git a/src/main/resources/messages_ga_IE.properties b/src/main/resources/messages_ga_IE.properties index 07735d0c..c4d7fde6 100644 --- a/src/main/resources/messages_ga_IE.properties +++ b/src/main/resources/messages_ga_IE.properties @@ -246,6 +246,7 @@ database.fileNullOrEmpty=Níor cheart go mbeadh an comhad ar neamhní nó folamh database.failedImportFile=Theip ar iompórtáil an chomhaid session.expired=Your session has expired. Please refresh the page and try again. +session.refreshPage=Refresh Page ############# # HOME-PAGE # diff --git a/src/main/resources/messages_hi_IN.properties b/src/main/resources/messages_hi_IN.properties index 65fd2e69..f7b4b0a5 100644 --- a/src/main/resources/messages_hi_IN.properties +++ b/src/main/resources/messages_hi_IN.properties @@ -246,6 +246,7 @@ database.fileNullOrEmpty=File must not be null or empty database.failedImportFile=Failed Import File session.expired=Your session has expired. Please refresh the page and try again. +session.refreshPage=Refresh Page ############# # HOME-PAGE # diff --git a/src/main/resources/messages_hr_HR.properties b/src/main/resources/messages_hr_HR.properties index acc2b3d0..2ec26341 100644 --- a/src/main/resources/messages_hr_HR.properties +++ b/src/main/resources/messages_hr_HR.properties @@ -246,6 +246,7 @@ database.fileNullOrEmpty=File must not be null or empty database.failedImportFile=Failed Import File session.expired=Your session has expired. Please refresh the page and try again. +session.refreshPage=Refresh Page ############# # HOME-PAGE # diff --git a/src/main/resources/messages_hu_HU.properties b/src/main/resources/messages_hu_HU.properties index 50d22e1b..98e4aebb 100644 --- a/src/main/resources/messages_hu_HU.properties +++ b/src/main/resources/messages_hu_HU.properties @@ -246,6 +246,7 @@ database.fileNullOrEmpty=File must not be null or empty database.failedImportFile=Failed Import File session.expired=Your session has expired. Please refresh the page and try again. +session.refreshPage=Refresh Page ############# # HOME-PAGE # diff --git a/src/main/resources/messages_id_ID.properties b/src/main/resources/messages_id_ID.properties index 80611663..94ea40a4 100644 --- a/src/main/resources/messages_id_ID.properties +++ b/src/main/resources/messages_id_ID.properties @@ -246,6 +246,7 @@ database.fileNullOrEmpty=Berkas tidak boleh null atau kosong database.failedImportFile=Impor Berkas Gagal session.expired=Sesi Anda telah kedaluwarsa. Silakan muat ulang halaman dan coba lagi. +session.refreshPage=Refresh Page ############# # HOME-PAGE # diff --git a/src/main/resources/messages_it_IT.properties b/src/main/resources/messages_it_IT.properties index 899b9d73..0899a191 100644 --- a/src/main/resources/messages_it_IT.properties +++ b/src/main/resources/messages_it_IT.properties @@ -246,6 +246,7 @@ database.fileNullOrEmpty=Il file non deve essere nullo o vuoto database.failedImportFile=Importazione file non riuscita session.expired=La tua sessione è scaduta. Aggiorna la pagina e riprova. +session.refreshPage=Refresh Page ############# # HOME-PAGE # diff --git a/src/main/resources/messages_ja_JP.properties b/src/main/resources/messages_ja_JP.properties index 992ddcb5..94e6ba1b 100644 --- a/src/main/resources/messages_ja_JP.properties +++ b/src/main/resources/messages_ja_JP.properties @@ -246,6 +246,7 @@ database.fileNullOrEmpty=ファイルは null または空であってはなり database.failedImportFile=ファイルのインポートに失敗 session.expired=Your session has expired. Please refresh the page and try again. +session.refreshPage=Refresh Page ############# # HOME-PAGE # diff --git a/src/main/resources/messages_ko_KR.properties b/src/main/resources/messages_ko_KR.properties index a26578d2..794a2b79 100644 --- a/src/main/resources/messages_ko_KR.properties +++ b/src/main/resources/messages_ko_KR.properties @@ -246,6 +246,7 @@ database.fileNullOrEmpty=File must not be null or empty database.failedImportFile=Failed Import File session.expired=Your session has expired. Please refresh the page and try again. +session.refreshPage=Refresh Page ############# # HOME-PAGE # diff --git a/src/main/resources/messages_nl_NL.properties b/src/main/resources/messages_nl_NL.properties index cdbfbe71..124a2a89 100644 --- a/src/main/resources/messages_nl_NL.properties +++ b/src/main/resources/messages_nl_NL.properties @@ -246,6 +246,7 @@ database.fileNullOrEmpty=File must not be null or empty database.failedImportFile=Failed Import File session.expired=Your session has expired. Please refresh the page and try again. +session.refreshPage=Refresh Page ############# # HOME-PAGE # diff --git a/src/main/resources/messages_no_NB.properties b/src/main/resources/messages_no_NB.properties index 3b174504..e86f4b9e 100644 --- a/src/main/resources/messages_no_NB.properties +++ b/src/main/resources/messages_no_NB.properties @@ -246,6 +246,7 @@ database.fileNullOrEmpty=Fil må ikke være tom eller null database.failedImportFile=Import av fil mislyktes session.expired=Your session has expired. Please refresh the page and try again. +session.refreshPage=Refresh Page ############# # HOME-PAGE # diff --git a/src/main/resources/messages_pl_PL.properties b/src/main/resources/messages_pl_PL.properties index a384c870..4db148c1 100755 --- a/src/main/resources/messages_pl_PL.properties +++ b/src/main/resources/messages_pl_PL.properties @@ -246,6 +246,7 @@ database.fileNullOrEmpty=Plik nie może być pusty database.failedImportFile=Nie udało się zaimportować pliku session.expired=Twoja sesja wygasła. Odśwież stronę i spróbuj ponownie. +session.refreshPage=Refresh Page ############# # HOME-PAGE # diff --git a/src/main/resources/messages_pt_BR.properties b/src/main/resources/messages_pt_BR.properties index 5cc5c8db..10605c7b 100644 --- a/src/main/resources/messages_pt_BR.properties +++ b/src/main/resources/messages_pt_BR.properties @@ -246,6 +246,7 @@ database.fileNullOrEmpty=O arquivo não pode estar nulo ou vazio database.failedImportFile=Falha ao importar arquivo session.expired=Sua sessão expirou. Por gentileza atualize a página e tente novamente. +session.refreshPage=Refresh Page ############# # HOME-PAGE # diff --git a/src/main/resources/messages_pt_PT.properties b/src/main/resources/messages_pt_PT.properties index 6ee92eb6..7624092e 100644 --- a/src/main/resources/messages_pt_PT.properties +++ b/src/main/resources/messages_pt_PT.properties @@ -246,6 +246,7 @@ database.fileNullOrEmpty=File must not be null or empty database.failedImportFile=Failed Import File session.expired=Your session has expired. Please refresh the page and try again. +session.refreshPage=Refresh Page ############# # HOME-PAGE # diff --git a/src/main/resources/messages_ro_RO.properties b/src/main/resources/messages_ro_RO.properties index 3d1f7d47..f86a2d73 100644 --- a/src/main/resources/messages_ro_RO.properties +++ b/src/main/resources/messages_ro_RO.properties @@ -246,6 +246,7 @@ database.fileNullOrEmpty=Fișierul nu trebuie să fie nul sau gol database.failedImportFile=Importul Fișierului a Eșuat session.expired=Your session has expired. Please refresh the page and try again. +session.refreshPage=Refresh Page ############# # HOME-PAGE # diff --git a/src/main/resources/messages_ru_RU.properties b/src/main/resources/messages_ru_RU.properties index 8c915bb4..097ef55c 100644 --- a/src/main/resources/messages_ru_RU.properties +++ b/src/main/resources/messages_ru_RU.properties @@ -246,6 +246,7 @@ database.fileNullOrEmpty=File must not be null or empty database.failedImportFile=Failed Import File session.expired=Your session has expired. Please refresh the page and try again. +session.refreshPage=Refresh Page ############# # HOME-PAGE # diff --git a/src/main/resources/messages_sk_SK.properties b/src/main/resources/messages_sk_SK.properties index d87128a6..f2881d77 100644 --- a/src/main/resources/messages_sk_SK.properties +++ b/src/main/resources/messages_sk_SK.properties @@ -246,6 +246,7 @@ database.fileNullOrEmpty=File must not be null or empty database.failedImportFile=Failed Import File session.expired=Your session has expired. Please refresh the page and try again. +session.refreshPage=Refresh Page ############# # HOME-PAGE # diff --git a/src/main/resources/messages_sr_LATN_RS.properties b/src/main/resources/messages_sr_LATN_RS.properties index 61a7d942..f0ff41eb 100644 --- a/src/main/resources/messages_sr_LATN_RS.properties +++ b/src/main/resources/messages_sr_LATN_RS.properties @@ -246,6 +246,7 @@ database.fileNullOrEmpty=File must not be null or empty database.failedImportFile=Failed Import File session.expired=Your session has expired. Please refresh the page and try again. +session.refreshPage=Refresh Page ############# # HOME-PAGE # diff --git a/src/main/resources/messages_sv_SE.properties b/src/main/resources/messages_sv_SE.properties index d39d4b3a..9943f946 100644 --- a/src/main/resources/messages_sv_SE.properties +++ b/src/main/resources/messages_sv_SE.properties @@ -246,6 +246,7 @@ database.fileNullOrEmpty=Filen får inte vara null eller tom database.failedImportFile=Misslyckades med att importera fil session.expired=Din session har löpt ut. Uppdatera sidan och försök igen. +session.refreshPage=Refresh Page ############# # HOME-PAGE # diff --git a/src/main/resources/messages_th_TH.properties b/src/main/resources/messages_th_TH.properties index 68b9d36d..25ca1d57 100644 --- a/src/main/resources/messages_th_TH.properties +++ b/src/main/resources/messages_th_TH.properties @@ -246,6 +246,7 @@ database.fileNullOrEmpty=ไฟล์ต้องไม่ว่างเปล database.failedImportFile=การนำเข้าไฟล์ล้มเหลว session.expired=Your session has expired. Please refresh the page and try again. +session.refreshPage=Refresh Page ############# # HOME-PAGE # diff --git a/src/main/resources/messages_tr_TR.properties b/src/main/resources/messages_tr_TR.properties index 60e2e5f4..b731da02 100644 --- a/src/main/resources/messages_tr_TR.properties +++ b/src/main/resources/messages_tr_TR.properties @@ -246,6 +246,7 @@ database.fileNullOrEmpty=Dosya yok veya boş olmamalıdır database.failedImportFile=Dosya İçe Aktarılamadı session.expired=Your session has expired. Please refresh the page and try again. +session.refreshPage=Refresh Page ############# # HOME-PAGE # diff --git a/src/main/resources/messages_uk_UA.properties b/src/main/resources/messages_uk_UA.properties index 2027a834..ca018b93 100644 --- a/src/main/resources/messages_uk_UA.properties +++ b/src/main/resources/messages_uk_UA.properties @@ -246,6 +246,7 @@ database.fileNullOrEmpty=File must not be null or empty database.failedImportFile=Failed Import File session.expired=Your session has expired. Please refresh the page and try again. +session.refreshPage=Refresh Page ############# # HOME-PAGE # diff --git a/src/main/resources/messages_vi_VN.properties b/src/main/resources/messages_vi_VN.properties index b7a4d1ed..15ca0653 100644 --- a/src/main/resources/messages_vi_VN.properties +++ b/src/main/resources/messages_vi_VN.properties @@ -246,6 +246,7 @@ database.fileNullOrEmpty=Tệp không được để trống hoặc rỗng database.failedImportFile=Không thể nhập tệp session.expired=Your session has expired. Please refresh the page and try again. +session.refreshPage=Refresh Page ############# # HOME-PAGE # diff --git a/src/main/resources/messages_zh_CN.properties b/src/main/resources/messages_zh_CN.properties index 7be7cb78..506dee41 100644 --- a/src/main/resources/messages_zh_CN.properties +++ b/src/main/resources/messages_zh_CN.properties @@ -246,6 +246,7 @@ database.fileNullOrEmpty=文件不能为空 database.failedImportFile=导入文件失败 session.expired=Your session has expired. Please refresh the page and try again. +session.refreshPage=Refresh Page ############# # HOME-PAGE # diff --git a/src/main/resources/messages_zh_TW.properties b/src/main/resources/messages_zh_TW.properties index fd212da9..98d72902 100644 --- a/src/main/resources/messages_zh_TW.properties +++ b/src/main/resources/messages_zh_TW.properties @@ -246,6 +246,7 @@ database.fileNullOrEmpty=檔案不得為空或空白 database.failedImportFile=匯入檔案失敗 session.expired=您的工作階段已過期。請重新整理頁面並再試一次。 +session.refreshPage=Refresh Page ############# # HOME-PAGE # diff --git a/src/main/resources/static/js/downloader.js b/src/main/resources/static/js/downloader.js index bbe16ba5..1933c4fb 100644 --- a/src/main/resources/static/js/downloader.js +++ b/src/main/resources/static/js/downloader.js @@ -1,288 +1,294 @@ -function showErrorBanner(message, stackTrace) { - const errorContainer = document.getElementById("errorContainer"); - errorContainer.style.display = "block"; // Display the banner - document.querySelector("#errorContainer .alert-heading").textContent = "Error"; - document.querySelector("#errorContainer p").textContent = message; - document.querySelector("#traceContent").textContent = stackTrace; -} +(function() { -function showSessionExpiredPrompt() { - const errorContainer = document.getElementById("errorContainer"); - errorContainer.style.display = "block"; - document.querySelector("#errorContainer .alert-heading").textContent = sessionExpired; - document.querySelector("#errorContainer p").textContent = sessionExpired; - document.querySelector("#traceContent").textContent = ""; + const { pdfPasswordPrompt, multipleInputsForSingleRequest, disableMultipleFiles, remoteCall, sessionExpired, refreshPage, error } = window.stirlingPDF; - // Optional: Add a refresh button - const refreshButton = document.createElement("button"); - refreshButton.textContent = "Refresh Page"; - refreshButton.className = "btn btn-primary mt-3"; - refreshButton.onclick = () => location.reload(); - errorContainer.appendChild(refreshButton); -} + function showErrorBanner(message, stackTrace) { + const errorContainer = document.getElementById("errorContainer"); + errorContainer.style.display = "block"; // Display the banner + errorContainer.querySelector(".alert-heading").textContent = error; + errorContainer.querySelector("p").textContent = message; + document.querySelector("#traceContent").textContent = stackTrace; + } -let firstErrorOccurred = false; + function showSessionExpiredPrompt() { + const errorContainer = document.getElementById("errorContainer"); + errorContainer.style.display = "block"; + errorContainer.querySelector(".alert-heading").textContent = sessionExpired; + errorContainer.querySelector("p").textContent = sessionExpired; + document.querySelector("#traceContent").textContent = ""; -$(document).ready(function () { - $("form").submit(async function (event) { - event.preventDefault(); - firstErrorOccurred = false; - const url = this.action; - const files = $("#fileInput-input")[0].files; - const formData = new FormData(this); + // Optional: Add a refresh button + const refreshButton = document.createElement("button"); + refreshButton.textContent = refreshPage; + refreshButton.className = "btn btn-primary mt-3"; + refreshButton.onclick = () => location.reload(); + errorContainer.appendChild(refreshButton); + } + let firstErrorOccurred = false; + + $(document).ready(function () { + $("form").submit(async function (event) { + event.preventDefault(); + firstErrorOccurred = false; + const url = this.action; + const files = $("#fileInput-input")[0].files; + const formData = new FormData(this); + + // Remove empty file entries + for (let [key, value] of formData.entries()) { + if (value instanceof File && !value.name) { + formData.delete(key); + } + } + const override = $("#override").val() || ""; + const originalButtonText = $("#submitBtn").text(); + $("#submitBtn").text("Processing..."); + console.log(override); + + // Set a timeout to show the game button if operation takes more than 5 seconds + const timeoutId = setTimeout(() => { + var boredWaiting = localStorage.getItem("boredWaiting") || "disabled"; + const showGameBtn = document.getElementById("show-game-btn"); + if (boredWaiting === "enabled" && showGameBtn) { + showGameBtn.style.display = "block"; + showGameBtn.parentNode.insertBefore(document.createElement('br'), showGameBtn.nextSibling); + } + }, 5000); + + try { + if (remoteCall === true) { + if (override === "multi" || (!multipleInputsForSingleRequest && files.length > 1 && override !== "single")) { + await submitMultiPdfForm(url, files); + } else { + await handleSingleDownload(url, formData); + } + } + clearTimeout(timeoutId); + $("#submitBtn").text(originalButtonText); + + // After process finishes, check for boredWaiting and gameDialog open status + const boredWaiting = localStorage.getItem("boredWaiting") || "disabled"; + const gameDialog = document.getElementById('game-container-wrapper'); + if (boredWaiting === "enabled" && gameDialog && gameDialog.open) { + // Display a green banner at the bottom of the screen saying "Download complete" + let downloadCompleteText = "Download Complete"; + if(window.downloadCompleteText){ + downloadCompleteText = window.downloadCompleteText; + } + $("body").append('
'+ downloadCompleteText + '
'); + setTimeout(function() { + $("#download-complete-banner").fadeOut("slow", function() { + $(this).remove(); // Remove the banner after fading out + }); + }, 5000); // Banner will fade out after 5 seconds + } + + } catch (error) { + clearTimeout(timeoutId); + handleDownloadError(error); + $("#submitBtn").text(originalButtonText); + console.error(error); + } + }); + }); + + async function handleSingleDownload(url, formData, isMulti = false, isZip = false) { + try { + const response = await fetch(url, { method: "POST", body: formData }); + const contentType = response.headers.get("content-type"); + + if (!response.ok) { + if (response.status === 401) { + // Handle 401 Unauthorized error + showSessionExpiredPrompt(); + return; + } + if (contentType && contentType.includes("application/json")) { + console.error("Throwing error banner, response was not okay"); + return handleJsonResponse(response); + } + throw new Error(`HTTP error! status: ${response.status}`); + } + + const contentDisposition = response.headers.get("Content-Disposition"); + let filename = getFilenameFromContentDisposition(contentDisposition); + + const blob = await response.blob(); + if (contentType.includes("application/pdf") || contentType.includes("image/")) { + return handleResponse(blob, filename, !isMulti, isZip); + } else { + return handleResponse(blob, filename, false, isZip); + } + } catch (error) { + console.error("Error in handleSingleDownload:", error); + throw error; + } + } + + function getFilenameFromContentDisposition(contentDisposition) { + let filename; + + if (contentDisposition && contentDisposition.indexOf("attachment") !== -1) { + filename = decodeURIComponent(contentDisposition.split("filename=")[1].replace(/"/g, "")).trim(); + } else { + // If the Content-Disposition header is not present or does not contain the filename, use a default filename + filename = "download"; + } + + return filename; + } + + async function handleJsonResponse(response) { + const json = await response.json(); + const errorMessage = JSON.stringify(json, null, 2); + if ( + errorMessage.toLowerCase().includes("the password is incorrect") || + errorMessage.toLowerCase().includes("Password is not provided") || + errorMessage.toLowerCase().includes("PDF contains an encryption dictionary") + ) { + if (!firstErrorOccurred) { + firstErrorOccurred = true; + alert(pdfPasswordPrompt); + } + } else { + showErrorBanner(json.error + ":" + json.message, json.trace); + } + } + + async function handleResponse(blob, filename, considerViewOptions = false, isZip = false) { + if (!blob) return; + const downloadOption = localStorage.getItem("downloadOption"); + if (considerViewOptions) { + if (downloadOption === "sameWindow") { + const url = URL.createObjectURL(blob); + window.location.href = url; + return; + } else if (downloadOption === "newWindow") { + const url = URL.createObjectURL(blob); + window.open(url, "_blank"); + return; + } + } + if (!isZip) { + downloadFile(blob, filename); + } + return { filename, blob }; + } + + function handleDownloadError(error) { + const errorMessage = error.message; + showErrorBanner(errorMessage); + } + + let urls = []; // An array to hold all the URLs + + function downloadFile(blob, filename) { + if (!(blob instanceof Blob)) { + console.error("Invalid blob passed to downloadFile function"); + return; + } + const url = URL.createObjectURL(blob); + const a = document.createElement("a"); + a.href = url; + a.download = filename; + a.click(); + urls.push(url); // Store the URL so it doesn't get garbage collected too soon + + return { filename, blob }; + } + + async function submitMultiPdfForm(url, files) { + const zipThreshold = parseInt(localStorage.getItem("zipThreshold"), 10) || 4; + const zipFiles = files.length > zipThreshold; + let jszip = null; + // Add Space below Progress Bar before Showing + $('.progressBarContainer').after($('
')); + $(".progressBarContainer").show(); + // Initialize the progress bar + + let progressBar = $(".progressBar"); + progressBar.css("width", "0%"); + progressBar.attr("aria-valuenow", 0); + progressBar.attr("aria-valuemax", files.length); + + if (zipFiles) { + jszip = new JSZip(); + } + + // Get the form with the method attribute set to POST + let postForm = document.querySelector('form[method="POST"]'); + + // Get existing form data + let formData; + if (postForm) { + formData = new FormData($(postForm)[0]); // Convert the form to a jQuery object and get the raw DOM element + } else { + console.log("No form with POST method found."); + } + //Remove file to reuse parameters for other runs + formData.delete("fileInput"); // Remove empty file entries for (let [key, value] of formData.entries()) { if (value instanceof File && !value.name) { formData.delete(key); } } - const override = $("#override").val() || ""; - const originalButtonText = $("#submitBtn").text(); - $("#submitBtn").text("Processing..."); - console.log(override); + const CONCURRENCY_LIMIT = 8; + const chunks = []; + for (let i = 0; i < Array.from(files).length; i += CONCURRENCY_LIMIT) { + chunks.push(Array.from(files).slice(i, i + CONCURRENCY_LIMIT)); + } - // Set a timeout to show the game button if operation takes more than 5 seconds - const timeoutId = setTimeout(() => { - var boredWaiting = localStorage.getItem("boredWaiting") || "disabled"; - const showGameBtn = document.getElementById("show-game-btn"); - if (boredWaiting === "enabled" && showGameBtn) { - showGameBtn.style.display = "block"; - showGameBtn.parentNode.insertBefore(document.createElement('br'), showGameBtn.nextSibling); - } - }, 5000); + for (const chunk of chunks) { + const promises = chunk.map(async (file) => { + let fileFormData = new FormData(); + fileFormData.append("fileInput", file); + console.log(fileFormData); + // Add other form data + for (let pair of formData.entries()) { + fileFormData.append(pair[0], pair[1]); + console.log(pair[0] + ", " + pair[1]); + } - try { - if (remoteCall === true) { - if (override === "multi" || (!multipleInputsForSingleRequest && files.length > 1 && override !== "single")) { - await submitMultiPdfForm(url, files); - } else { - await handleSingleDownload(url, formData); + try { + const downloadDetails = await handleSingleDownload(url, fileFormData, true, zipFiles); + console.log(downloadDetails); + if (zipFiles) { + jszip.file(downloadDetails.filename, downloadDetails.blob); + } else { + //downloadFile(downloadDetails.blob, downloadDetails.filename); + } + updateProgressBar(progressBar, Array.from(files).length); + } catch (error) { + handleDownloadError(error); + console.error(error); } + }); + await Promise.all(promises); + } + + if (zipFiles) { + try { + const content = await jszip.generateAsync({ type: "blob" }); + downloadFile(content, "files.zip"); + } catch (error) { + console.error("Error generating ZIP file: " + error); } - clearTimeout(timeoutId); - $("#submitBtn").text(originalButtonText); - - // After process finishes, check for boredWaiting and gameDialog open status - const boredWaiting = localStorage.getItem("boredWaiting") || "disabled"; - const gameDialog = document.getElementById('game-container-wrapper'); - if (boredWaiting === "enabled" && gameDialog && gameDialog.open) { - // Display a green banner at the bottom of the screen saying "Download complete" - let downloadCompleteText = "Download Complete"; - if(window.downloadCompleteText){ - downloadCompleteText = window.downloadCompleteText; - } - $("body").append('
'+ downloadCompleteText + '
'); - setTimeout(function() { - $("#download-complete-banner").fadeOut("slow", function() { - $(this).remove(); // Remove the banner after fading out - }); - }, 5000); // Banner will fade out after 5 seconds - } - - } catch (error) { - clearTimeout(timeoutId); - handleDownloadError(error); - $("#submitBtn").text(originalButtonText); - console.error(error); + } + progressBar.css("width", "100%"); + progressBar.attr("aria-valuenow", Array.from(files).length); + } + + function updateProgressBar(progressBar, files) { + let progress = (progressBar.attr("aria-valuenow") / files.length) * 100 + 100 / files.length; + progressBar.css("width", progress + "%"); + progressBar.attr("aria-valuenow", parseInt(progressBar.attr("aria-valuenow")) + 1); + } + window.addEventListener("unload", () => { + for (const url of urls) { + URL.revokeObjectURL(url); } }); -}); -async function handleSingleDownload(url, formData, isMulti = false, isZip = false) { - try { - const response = await fetch(url, { method: "POST", body: formData }); - const contentType = response.headers.get("content-type"); - - if (!response.ok) { - if (response.status === 401) { - // Handle 401 Unauthorized error - showSessionExpiredPrompt(); - return; - } - if (contentType && contentType.includes("application/json")) { - console.error("Throwing error banner, response was not okay"); - return handleJsonResponse(response); - } - throw new Error(`HTTP error! status: ${response.status}`); - } - - const contentDisposition = response.headers.get("Content-Disposition"); - let filename = getFilenameFromContentDisposition(contentDisposition); - - const blob = await response.blob(); - if (contentType.includes("application/pdf") || contentType.includes("image/")) { - return handleResponse(blob, filename, !isMulti, isZip); - } else { - return handleResponse(blob, filename, false, isZip); - } - } catch (error) { - console.error("Error in handleSingleDownload:", error); - throw error; - } -} - -function getFilenameFromContentDisposition(contentDisposition) { - let filename; - - if (contentDisposition && contentDisposition.indexOf("attachment") !== -1) { - filename = decodeURIComponent(contentDisposition.split("filename=")[1].replace(/"/g, "")).trim(); - } else { - // If the Content-Disposition header is not present or does not contain the filename, use a default filename - filename = "download"; - } - - return filename; -} - -async function handleJsonResponse(response) { - const json = await response.json(); - const errorMessage = JSON.stringify(json, null, 2); - if ( - errorMessage.toLowerCase().includes("the password is incorrect") || - errorMessage.toLowerCase().includes("Password is not provided") || - errorMessage.toLowerCase().includes("PDF contains an encryption dictionary") - ) { - if (!firstErrorOccurred) { - firstErrorOccurred = true; - alert(pdfPasswordPrompt); - } - } else { - showErrorBanner(json.error + ":" + json.message, json.trace); - } -} - -async function handleResponse(blob, filename, considerViewOptions = false, isZip = false) { - if (!blob) return; - const downloadOption = localStorage.getItem("downloadOption"); - if (considerViewOptions) { - if (downloadOption === "sameWindow") { - const url = URL.createObjectURL(blob); - window.location.href = url; - return; - } else if (downloadOption === "newWindow") { - const url = URL.createObjectURL(blob); - window.open(url, "_blank"); - return; - } - } - if (!isZip) { - downloadFile(blob, filename); - } - return { filename, blob }; -} - -function handleDownloadError(error) { - const errorMessage = error.message; - showErrorBanner(errorMessage); -} - -let urls = []; // An array to hold all the URLs - -function downloadFile(blob, filename) { - if (!(blob instanceof Blob)) { - console.error("Invalid blob passed to downloadFile function"); - return; - } - const url = URL.createObjectURL(blob); - const a = document.createElement("a"); - a.href = url; - a.download = filename; - a.click(); - urls.push(url); // Store the URL so it doesn't get garbage collected too soon - - return { filename, blob }; -} - -async function submitMultiPdfForm(url, files) { - const zipThreshold = parseInt(localStorage.getItem("zipThreshold"), 10) || 4; - const zipFiles = files.length > zipThreshold; - let jszip = null; - // Add Space below Progress Bar before Showing - $('.progressBarContainer').after($('
')); - $(".progressBarContainer").show(); - // Initialize the progress bar - - let progressBar = $(".progressBar"); - progressBar.css("width", "0%"); - progressBar.attr("aria-valuenow", 0); - progressBar.attr("aria-valuemax", files.length); - - if (zipFiles) { - jszip = new JSZip(); - } - - // Get the form with the method attribute set to POST - let postForm = document.querySelector('form[method="POST"]'); - - // Get existing form data - let formData; - if (postForm) { - formData = new FormData($(postForm)[0]); // Convert the form to a jQuery object and get the raw DOM element - } else { - console.log("No form with POST method found."); - } - //Remove file to reuse parameters for other runs - formData.delete("fileInput"); - // Remove empty file entries - for (let [key, value] of formData.entries()) { - if (value instanceof File && !value.name) { - formData.delete(key); - } - } - const CONCURRENCY_LIMIT = 8; - const chunks = []; - for (let i = 0; i < Array.from(files).length; i += CONCURRENCY_LIMIT) { - chunks.push(Array.from(files).slice(i, i + CONCURRENCY_LIMIT)); - } - - for (const chunk of chunks) { - const promises = chunk.map(async (file) => { - let fileFormData = new FormData(); - fileFormData.append("fileInput", file); - console.log(fileFormData); - // Add other form data - for (let pair of formData.entries()) { - fileFormData.append(pair[0], pair[1]); - console.log(pair[0] + ", " + pair[1]); - } - - try { - const downloadDetails = await handleSingleDownload(url, fileFormData, true, zipFiles); - console.log(downloadDetails); - if (zipFiles) { - jszip.file(downloadDetails.filename, downloadDetails.blob); - } else { - //downloadFile(downloadDetails.blob, downloadDetails.filename); - } - updateProgressBar(progressBar, Array.from(files).length); - } catch (error) { - handleDownloadError(error); - console.error(error); - } - }); - await Promise.all(promises); - } - - if (zipFiles) { - try { - const content = await jszip.generateAsync({ type: "blob" }); - downloadFile(content, "files.zip"); - } catch (error) { - console.error("Error generating ZIP file: " + error); - } - } - progressBar.css("width", "100%"); - progressBar.attr("aria-valuenow", Array.from(files).length); -} - -function updateProgressBar(progressBar, files) { - let progress = (progressBar.attr("aria-valuenow") / files.length) * 100 + 100 / files.length; - progressBar.css("width", progress + "%"); - progressBar.attr("aria-valuenow", parseInt(progressBar.attr("aria-valuenow")) + 1); -} -window.addEventListener("unload", () => { - for (const url of urls) { - URL.revokeObjectURL(url); - } -}); +})(); diff --git a/src/main/resources/templates/fragments/common.html b/src/main/resources/templates/fragments/common.html index 293a8549..dd74d388 100644 --- a/src/main/resources/templates/fragments/common.html +++ b/src/main/resources/templates/fragments/common.html @@ -21,6 +21,10 @@ + + @@ -187,11 +191,15 @@ @@ -210,4 +218,4 @@
- + \ No newline at end of file From 6f42d976f6a244e2acb7b1d08fb61da27d723fe4 Mon Sep 17 00:00:00 2001 From: Ludy Date: Sun, 3 Nov 2024 08:26:45 +0100 Subject: [PATCH 14/23] Fix: Path correction to draggable.js #2154 + little makeup (#2159) --- src/main/resources/templates/sign.html | 745 ++++++++++++------------- 1 file changed, 343 insertions(+), 402 deletions(-) diff --git a/src/main/resources/templates/sign.html b/src/main/resources/templates/sign.html index 32d7ad6c..63d976e4 100644 --- a/src/main/resources/templates/sign.html +++ b/src/main/resources/templates/sign.html @@ -1,12 +1,10 @@ - - - + + - + - + - + - - - + + + - -
-
- -

-
-
-
-
- signature - -
+ +
+
+ +

+
+
+
+
+ signature + +
- -
-
- - + - -
-
-
-
- -
+ }); + -
- -
- - - -
- - - - - - - -
-
- -
- -
- - - - - -
- -
-
-
-
- -
- -
+ }); +
-
- -
-
-
-
- -
- -
-
-
-
- - - -
-
-

No saved signatures found

-
-
- - - - - - - - - - - -
- - - - -
- -
- + function addDraggableFromPad() { + if (signaturePad.isEmpty()) return; + const startTime = Date.now(); + const croppedDataUrl = getCroppedCanvasDataUrl(signaturePadCanvas); + console.log(Date.now() - startTime); + DraggableUtils.createDraggableCanvasFromUrl(croppedDataUrl); + } + + function getCroppedCanvasDataUrl(canvas) { + let originalCtx = canvas.getContext('2d'); + let originalWidth = canvas.width; + let originalHeight = canvas.height; + let imageData = originalCtx.getImageData(0, 0, originalWidth, originalHeight); + + let minX = originalWidth + 1, maxX = -1, minY = originalHeight + 1, maxY = -1, x = 0, y = 0, currentPixelColorValueIndex; + + for (y = 0; y < originalHeight; y++) { + for (x = 0; x < originalWidth; x++) { + currentPixelColorValueIndex = (y * originalWidth + x) * 4; + let currentPixelAlphaValue = imageData.data[currentPixelColorValueIndex + 3]; + if (currentPixelAlphaValue > 0) { + if (minX > x) minX = x; + if (maxX < x) maxX = x; + if (minY > y) minY = y; + if (maxY < y) maxY = y; + } + } + } + + let croppedWidth = maxX - minX; + let croppedHeight = maxY - minY; + if (croppedWidth < 0 || croppedHeight < 0) return null; + let cuttedImageData = originalCtx.getImageData(minX, minY, croppedWidth, croppedHeight); + + let croppedCanvas = document.createElement('canvas'), + croppedCtx = croppedCanvas.getContext('2d'); + + croppedCanvas.width = croppedWidth; + croppedCanvas.height = croppedHeight; + croppedCtx.putImageData(cuttedImageData, 0, 0); + + return croppedCanvas.toDataURL(); + } + + function resizeCanvas() { + var ratio = Math.max(window.devicePixelRatio || 1, 1); + var additionalFactor = 10; + + signaturePadCanvas.width = signaturePadCanvas.offsetWidth * ratio * additionalFactor; + signaturePadCanvas.height = signaturePadCanvas.offsetHeight * ratio * additionalFactor; + signaturePadCanvas.getContext("2d").scale(ratio * additionalFactor, ratio * additionalFactor); + + signaturePad.clear(); + } + + new IntersectionObserver((entries, observer) => { + if (entries.some(entry => entry.intersectionRatio > 0)) { + resizeCanvas(); + } + }).observe(signaturePadCanvas); + + new ResizeObserver(resizeCanvas).observe(signaturePadCanvas); + +
+ +
+
+ +
+ +
+ + + + + +
+ +
+
+
+
+ +
+
+
+
+ + +
+
+
+
+ +
+
+
+
+
+ + + +
+
+

No saved signatures found

+
+
+ +
+ + + + +
+ +
+ +
-
- -
- - - -
- - - + +
+ + + +
+ + + +
-
- -
- -
+ +
+ +
- + +
+
- - -
- - - - - + + + \ No newline at end of file From 7ec343d9ce84107d515c3ceaeb22ca8ea1d50592 Mon Sep 17 00:00:00 2001 From: Ludy Date: Sun, 3 Nov 2024 08:55:39 +0100 Subject: [PATCH 15/23] Fix: Add missing .map file for minified files (#2156) --- src/main/resources/static/css/bootstrap.min.css.map | 1 + src/main/resources/static/js/thirdParty/bootstrap.min.js.map | 1 + src/main/resources/static/js/thirdParty/interact.min.js.map | 1 + src/main/resources/static/js/thirdParty/pdf-lib.min.js.map | 1 + src/main/resources/static/js/thirdParty/popper.min.js.map | 1 + .../resources/static/js/thirdParty/signature_pad.umd.min.js.map | 1 + 6 files changed, 6 insertions(+) create mode 100644 src/main/resources/static/css/bootstrap.min.css.map create mode 100644 src/main/resources/static/js/thirdParty/bootstrap.min.js.map create mode 100644 src/main/resources/static/js/thirdParty/interact.min.js.map create mode 100644 src/main/resources/static/js/thirdParty/pdf-lib.min.js.map create mode 100644 src/main/resources/static/js/thirdParty/popper.min.js.map create mode 100644 src/main/resources/static/js/thirdParty/signature_pad.umd.min.js.map diff --git a/src/main/resources/static/css/bootstrap.min.css.map b/src/main/resources/static/css/bootstrap.min.css.map new file mode 100644 index 00000000..3fe6cda5 --- /dev/null +++ b/src/main/resources/static/css/bootstrap.min.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../scss/bootstrap.scss","../../scss/_root.scss","../../scss/_reboot.scss","dist/css/bootstrap.css","../../scss/vendor/_rfs.scss","../../scss/mixins/_border-radius.scss","../../scss/_type.scss","../../scss/mixins/_lists.scss","../../scss/_images.scss","../../scss/mixins/_image.scss","../../scss/_containers.scss","../../scss/mixins/_container.scss","../../scss/mixins/_breakpoints.scss","../../scss/_grid.scss","../../scss/mixins/_grid.scss","../../scss/_tables.scss","../../scss/mixins/_table-variants.scss","../../scss/forms/_labels.scss","../../scss/forms/_form-text.scss","../../scss/forms/_form-control.scss","../../scss/mixins/_transition.scss","../../scss/mixins/_gradients.scss","../../scss/forms/_form-select.scss","../../scss/forms/_form-check.scss","../../scss/forms/_form-range.scss","../../scss/forms/_floating-labels.scss","../../scss/forms/_input-group.scss","../../scss/mixins/_forms.scss","../../scss/_buttons.scss","../../scss/mixins/_buttons.scss","../../scss/_transitions.scss","../../scss/_dropdown.scss","../../scss/mixins/_caret.scss","../../scss/_button-group.scss","../../scss/_nav.scss","../../scss/_navbar.scss","../../scss/_card.scss","../../scss/_accordion.scss","../../scss/_breadcrumb.scss","../../scss/_pagination.scss","../../scss/mixins/_pagination.scss","../../scss/_badge.scss","../../scss/_alert.scss","../../scss/mixins/_alert.scss","../../scss/_progress.scss","../../scss/_list-group.scss","../../scss/mixins/_list-group.scss","../../scss/_close.scss","../../scss/_toasts.scss","../../scss/_modal.scss","../../scss/_tooltip.scss","../../scss/mixins/_reset-text.scss","../../scss/_popover.scss","../../scss/_carousel.scss","../../scss/mixins/_clearfix.scss","../../scss/_spinners.scss","../../scss/_offcanvas.scss","../../scss/helpers/_colored-links.scss","../../scss/helpers/_ratio.scss","../../scss/helpers/_position.scss","../../scss/helpers/_visually-hidden.scss","../../scss/mixins/_visually-hidden.scss","../../scss/helpers/_stretched-link.scss","../../scss/helpers/_text-truncation.scss","../../scss/mixins/_text-truncate.scss","../../scss/mixins/_utilities.scss","../../scss/utilities/_api.scss"],"names":[],"mappings":"iBAAA;;;;;ACAA,MAGI,UAAA,QAAA,YAAA,QAAA,YAAA,QAAA,UAAA,QAAA,SAAA,QAAA,YAAA,QAAA,YAAA,QAAA,WAAA,QAAA,UAAA,QAAA,UAAA,QAAA,WAAA,KAAA,UAAA,QAAA,eAAA,QAIA,aAAA,QAAA,eAAA,QAAA,aAAA,QAAA,UAAA,QAAA,aAAA,QAAA,YAAA,QAAA,WAAA,QAAA,UAAA,QAKF,qBAAA,SAAA,CAAA,aAAA,CAAA,UAAA,CAAA,MAAA,CAAA,gBAAA,CAAA,KAAA,CAAA,WAAA,CAAA,iBAAA,CAAA,UAAA,CAAA,mBAAA,CAAA,gBAAA,CAAA,iBAAA,CAAA,mBACA,oBAAA,cAAA,CAAA,KAAA,CAAA,MAAA,CAAA,QAAA,CAAA,iBAAA,CAAA,aAAA,CAAA,UACA,cAAA,2ECCF,ECqBA,QADA,SDjBE,WAAA,WAaE,8CAJJ,MAKM,gBAAA,QAaN,KACE,OAAA,EACA,YAAA,0BEsPI,UAAA,KFpPJ,YAAA,IACA,YAAA,IACA,MAAA,QAEA,iBAAA,KACA,yBAAA,KACA,4BAAA,YASF,GACE,OAAA,KAAA,EACA,MAAA,QACA,iBAAA,aACA,OAAA,EACA,QAAA,IAGF,eACE,OAAA,IAUF,IAAA,IAAA,IAAA,IAAA,IAAA,IAAA,GAAA,GAAA,GAAA,GAAA,GAAA,GACE,WAAA,EACA,cAAA,MAGA,YAAA,IACA,YAAA,IAIF,IAAA,GE4MQ,UAAA,uBAlKJ,0BF1CJ,IAAA,GEmNQ,UAAA,QF9MR,IAAA,GEuMQ,UAAA,sBAlKJ,0BFrCJ,IAAA,GE8MQ,UAAA,MFzMR,IAAA,GEkMQ,UAAA,oBAlKJ,0BFhCJ,IAAA,GEyMQ,UAAA,SFpMR,IAAA,GE6LQ,UAAA,sBAlKJ,0BF3BJ,IAAA,GEoMQ,UAAA,QF/LR,IAAA,GEoLM,UAAA,QF/KN,IAAA,GE+KM,UAAA,KFpKN,EACE,WAAA,EACA,cAAA,KCJF,6BDeA,YAEE,wBAAA,UAAA,OAAA,gBAAA,UAAA,OACA,OAAA,KACA,iCAAA,KAAA,yBAAA,KAMF,QACE,cAAA,KACA,WAAA,OACA,YAAA,QAMF,GCnBA,GDqBE,aAAA,KCfF,GDkBA,GCnBA,GDsBE,WAAA,EACA,cAAA,KAGF,MClBA,MACA,MAFA,MDuBE,cAAA,EAGF,GACE,YAAA,IAKF,GACE,cAAA,MACA,YAAA,EAMF,WACE,OAAA,EAAA,EAAA,KAQF,EC7BA,OD+BE,YAAA,OAQF,OAAA,MEgFM,UAAA,OFzEN,MAAA,KACE,QAAA,KACA,iBAAA,QASF,IC3CA,ID6CE,SAAA,SE4DI,UAAA,MF1DJ,YAAA,EACA,eAAA,SAGF,IAAM,OAAA,OACN,IAAM,IAAA,MAKN,EACE,MAAA,QACA,gBAAA,UAEA,QACE,MAAA,QAWF,2BAAA,iCAEE,MAAA,QACA,gBAAA,KC/CJ,KACA,IDqDA,ICpDA,KDwDE,YAAA,yBEkBI,UAAA,IFhBJ,UAAA,IACA,aAAA,cAOF,IACE,QAAA,MACA,WAAA,EACA,cAAA,KACA,SAAA,KEII,UAAA,OFCJ,SEDI,UAAA,QFGF,MAAA,QACA,WAAA,OAIJ,KERM,UAAA,OFUJ,MAAA,QACA,UAAA,WAGA,OACE,MAAA,QAIJ,IACE,QAAA,MAAA,MEpBI,UAAA,OFsBJ,MAAA,KACA,iBAAA,QGzSE,cAAA,MH4SF,QACE,QAAA,EE3BE,UAAA,IF6BF,YAAA,IASJ,OACE,OAAA,EAAA,EAAA,KAMF,ICxEA,ID0EE,eAAA,OAQF,MACE,aAAA,OACA,gBAAA,SAGF,QACE,YAAA,MACA,eAAA,MACA,MAAA,QACA,WAAA,KAOF,GAEE,WAAA,QACA,WAAA,qBC/EF,MAGA,GAFA,MAGA,GD8EA,MChFA,GDsFE,aAAA,QACA,aAAA,MACA,aAAA,EAQF,MACE,QAAA,aAMF,OAEE,cAAA,EAQF,iCACE,QAAA,EC7FF,ODkGA,MChGA,SADA,OAEA,SDoGE,OAAA,EACA,YAAA,QE1HI,UAAA,QF4HJ,YAAA,QAIF,OCnGA,ODqGE,eAAA,KAKF,cACE,OAAA,QAGF,OAGE,UAAA,OAGA,gBACE,QAAA,EAOJ,0CACE,QAAA,KCzGF,cACA,aACA,cD+GA,OAIE,mBAAA,OC/GF,6BACA,4BACA,6BDgHI,sBACE,OAAA,QAON,mBACE,QAAA,EACA,aAAA,KAKF,SACE,OAAA,SAUF,SACE,UAAA,EACA,QAAA,EACA,OAAA,EACA,OAAA,EAQF,OACE,MAAA,KACA,MAAA,KACA,QAAA,EACA,cAAA,ME/MM,UAAA,sBFkNN,YAAA,QEpXE,0BF6WJ,OEpMQ,UAAA,QF6MN,SACE,MAAA,KCvHJ,kCD8HA,uCC/HA,mCADA,+BAGA,oCAJA,6BAKA,mCDmIE,QAAA,EAGF,4BACE,OAAA,KASF,cACE,eAAA,KACA,mBAAA,UAmBF,4BACE,mBAAA,KAKF,+BACE,QAAA,EAMF,uBACE,KAAA,QAMF,6BACE,KAAA,QACA,mBAAA,OAKF,OACE,QAAA,aAKF,OACE,OAAA,EAOF,QACE,QAAA,UACA,OAAA,QAQF,SACE,eAAA,SAQF,SACE,QAAA,eI/kBF,MFyQM,UAAA,QEvQJ,YAAA,IAKA,WFsQM,UAAA,uBEpQJ,YAAA,IACA,YAAA,IFiGA,0BEpGF,WF6QM,UAAA,ME7QN,WFsQM,UAAA,uBEpQJ,YAAA,IACA,YAAA,IFiGA,0BEpGF,WF6QM,UAAA,QE7QN,WFsQM,UAAA,uBEpQJ,YAAA,IACA,YAAA,IFiGA,0BEpGF,WF6QM,UAAA,ME7QN,WFsQM,UAAA,uBEpQJ,YAAA,IACA,YAAA,IFiGA,0BEpGF,WF6QM,UAAA,QE7QN,WFsQM,UAAA,uBEpQJ,YAAA,IACA,YAAA,IFiGA,0BEpGF,WF6QM,UAAA,ME7QN,WFsQM,UAAA,uBEpQJ,YAAA,IACA,YAAA,IFiGA,0BEpGF,WF6QM,UAAA,QEvPR,eCrDE,aAAA,EACA,WAAA,KDyDF,aC1DE,aAAA,EACA,WAAA,KD4DF,kBACE,QAAA,aAEA,mCACE,aAAA,MAUJ,YFsNM,UAAA,OEpNJ,eAAA,UAIF,YACE,cAAA,KF+MI,UAAA,QE5MJ,wBACE,cAAA,EAIJ,mBACE,WAAA,MACA,cAAA,KFqMI,UAAA,OEnMJ,MAAA,QAEA,2BACE,QAAA,KE9FJ,WCIE,UAAA,KAGA,OAAA,KDDF,eACE,QAAA,OACA,iBAAA,KACA,OAAA,IAAA,MAAA,QHGE,cAAA,OIRF,UAAA,KAGA,OAAA,KDcF,QAEE,QAAA,aAGF,YACE,cAAA,MACA,YAAA,EAGF,gBJ+PM,UAAA,OI7PJ,MAAA,QElCA,WP0kBF,iBAGA,cACA,cACA,cAHA,cADA,eQ9kBE,MAAA,KACA,cAAA,0BACA,aAAA,0BACA,aAAA,KACA,YAAA,KCwDE,yBF5CE,WAAA,cACE,UAAA,OE2CJ,yBF5CE,WAAA,cAAA,cACE,UAAA,OE2CJ,yBF5CE,WAAA,cAAA,cAAA,cACE,UAAA,OE2CJ,0BF5CE,WAAA,cAAA,cAAA,cAAA,cACE,UAAA,QE2CJ,0BF5CE,WAAA,cAAA,cAAA,cAAA,cAAA,eACE,UAAA,QGfN,KCAA,cAAA,OACA,cAAA,EACA,QAAA,KACA,UAAA,KACA,WAAA,8BACA,aAAA,+BACA,YAAA,+BDHE,OCYF,YAAA,EACA,MAAA,KACA,UAAA,KACA,cAAA,8BACA,aAAA,8BACA,WAAA,mBA+CI,KACE,KAAA,EAAA,EAAA,GAGF,iBApCJ,KAAA,EAAA,EAAA,KACA,MAAA,KAcA,cACE,KAAA,EAAA,EAAA,KACA,MAAA,KAFF,cACE,KAAA,EAAA,EAAA,KACA,MAAA,IAFF,cACE,KAAA,EAAA,EAAA,KACA,MAAA,eAFF,cACE,KAAA,EAAA,EAAA,KACA,MAAA,IAFF,cACE,KAAA,EAAA,EAAA,KACA,MAAA,IAFF,cACE,KAAA,EAAA,EAAA,KACA,MAAA,eFMA,yBESE,QACE,KAAA,EAAA,EAAA,GAGF,oBApCJ,KAAA,EAAA,EAAA,KACA,MAAA,KAcA,iBACE,KAAA,EAAA,EAAA,KACA,MAAA,KAFF,iBACE,KAAA,EAAA,EAAA,KACA,MAAA,IAFF,iBACE,KAAA,EAAA,EAAA,KACA,MAAA,eAFF,iBACE,KAAA,EAAA,EAAA,KACA,MAAA,IAFF,iBACE,KAAA,EAAA,EAAA,KACA,MAAA,IAFF,iBACE,KAAA,EAAA,EAAA,KACA,MAAA,gBFMA,yBESE,QACE,KAAA,EAAA,EAAA,GAGF,oBApCJ,KAAA,EAAA,EAAA,KACA,MAAA,KAcA,iBACE,KAAA,EAAA,EAAA,KACA,MAAA,KAFF,iBACE,KAAA,EAAA,EAAA,KACA,MAAA,IAFF,iBACE,KAAA,EAAA,EAAA,KACA,MAAA,eAFF,iBACE,KAAA,EAAA,EAAA,KACA,MAAA,IAFF,iBACE,KAAA,EAAA,EAAA,KACA,MAAA,IAFF,iBACE,KAAA,EAAA,EAAA,KACA,MAAA,gBFMA,yBESE,QACE,KAAA,EAAA,EAAA,GAGF,oBApCJ,KAAA,EAAA,EAAA,KACA,MAAA,KAcA,iBACE,KAAA,EAAA,EAAA,KACA,MAAA,KAFF,iBACE,KAAA,EAAA,EAAA,KACA,MAAA,IAFF,iBACE,KAAA,EAAA,EAAA,KACA,MAAA,eAFF,iBACE,KAAA,EAAA,EAAA,KACA,MAAA,IAFF,iBACE,KAAA,EAAA,EAAA,KACA,MAAA,IAFF,iBACE,KAAA,EAAA,EAAA,KACA,MAAA,gBFMA,0BESE,QACE,KAAA,EAAA,EAAA,GAGF,oBApCJ,KAAA,EAAA,EAAA,KACA,MAAA,KAcA,iBACE,KAAA,EAAA,EAAA,KACA,MAAA,KAFF,iBACE,KAAA,EAAA,EAAA,KACA,MAAA,IAFF,iBACE,KAAA,EAAA,EAAA,KACA,MAAA,eAFF,iBACE,KAAA,EAAA,EAAA,KACA,MAAA,IAFF,iBACE,KAAA,EAAA,EAAA,KACA,MAAA,IAFF,iBACE,KAAA,EAAA,EAAA,KACA,MAAA,gBFMA,0BESE,SACE,KAAA,EAAA,EAAA,GAGF,qBApCJ,KAAA,EAAA,EAAA,KACA,MAAA,KAcA,kBACE,KAAA,EAAA,EAAA,KACA,MAAA,KAFF,kBACE,KAAA,EAAA,EAAA,KACA,MAAA,IAFF,kBACE,KAAA,EAAA,EAAA,KACA,MAAA,eAFF,kBACE,KAAA,EAAA,EAAA,KACA,MAAA,IAFF,kBACE,KAAA,EAAA,EAAA,KACA,MAAA,IAFF,kBACE,KAAA,EAAA,EAAA,KACA,MAAA,gBAqCE,UAtDJ,KAAA,EAAA,EAAA,KACA,MAAA,KA2DQ,OAtEN,KAAA,EAAA,EAAA,KACA,MAAA,YAqEM,OAtEN,KAAA,EAAA,EAAA,KACA,MAAA,aAqEM,OAtEN,KAAA,EAAA,EAAA,KACA,MAAA,IAqEM,OAtEN,KAAA,EAAA,EAAA,KACA,MAAA,aAqEM,OAtEN,KAAA,EAAA,EAAA,KACA,MAAA,aAqEM,OAtEN,KAAA,EAAA,EAAA,KACA,MAAA,IAqEM,OAtEN,KAAA,EAAA,EAAA,KACA,MAAA,aAqEM,OAtEN,KAAA,EAAA,EAAA,KACA,MAAA,aAqEM,OAtEN,KAAA,EAAA,EAAA,KACA,MAAA,IAqEM,QAtEN,KAAA,EAAA,EAAA,KACA,MAAA,aAqEM,QAtEN,KAAA,EAAA,EAAA,KACA,MAAA,aAqEM,QAtEN,KAAA,EAAA,EAAA,KACA,MAAA,KA6EQ,UA9DV,YAAA,YA8DU,UA9DV,YAAA,aA8DU,UA9DV,YAAA,IA8DU,UA9DV,YAAA,aA8DU,UA9DV,YAAA,aA8DU,UA9DV,YAAA,IA8DU,UA9DV,YAAA,aA8DU,UA9DV,YAAA,aA8DU,UA9DV,YAAA,IA8DU,WA9DV,YAAA,aA8DU,WA9DV,YAAA,aAyEM,KX82BR,MW52BU,cAAA,EAGF,KX82BR,MW52BU,cAAA,EAPF,KXw3BR,MWt3BU,cAAA,QAGF,KXw3BR,MWt3BU,cAAA,QAPF,KXk4BR,MWh4BU,cAAA,OAGF,KXk4BR,MWh4BU,cAAA,OAPF,KX44BR,MW14BU,cAAA,KAGF,KX44BR,MW14BU,cAAA,KAPF,KXs5BR,MWp5BU,cAAA,OAGF,KXs5BR,MWp5BU,cAAA,OAPF,KXg6BR,MW95BU,cAAA,KAGF,KXg6BR,MW95BU,cAAA,KF/DN,yBE+BE,aAtDJ,KAAA,EAAA,EAAA,KACA,MAAA,KA2DQ,UAtEN,KAAA,EAAA,EAAA,KACA,MAAA,YAqEM,UAtEN,KAAA,EAAA,EAAA,KACA,MAAA,aAqEM,UAtEN,KAAA,EAAA,EAAA,KACA,MAAA,IAqEM,UAtEN,KAAA,EAAA,EAAA,KACA,MAAA,aAqEM,UAtEN,KAAA,EAAA,EAAA,KACA,MAAA,aAqEM,UAtEN,KAAA,EAAA,EAAA,KACA,MAAA,IAqEM,UAtEN,KAAA,EAAA,EAAA,KACA,MAAA,aAqEM,UAtEN,KAAA,EAAA,EAAA,KACA,MAAA,aAqEM,UAtEN,KAAA,EAAA,EAAA,KACA,MAAA,IAqEM,WAtEN,KAAA,EAAA,EAAA,KACA,MAAA,aAqEM,WAtEN,KAAA,EAAA,EAAA,KACA,MAAA,aAqEM,WAtEN,KAAA,EAAA,EAAA,KACA,MAAA,KA6EQ,aA9DV,YAAA,EA8DU,aA9DV,YAAA,YA8DU,aA9DV,YAAA,aA8DU,aA9DV,YAAA,IA8DU,aA9DV,YAAA,aA8DU,aA9DV,YAAA,aA8DU,aA9DV,YAAA,IA8DU,aA9DV,YAAA,aA8DU,aA9DV,YAAA,aA8DU,aA9DV,YAAA,IA8DU,cA9DV,YAAA,aA8DU,cA9DV,YAAA,aAyEM,QX4hCR,SW1hCU,cAAA,EAGF,QX4hCR,SW1hCU,cAAA,EAPF,QXsiCR,SWpiCU,cAAA,QAGF,QXsiCR,SWpiCU,cAAA,QAPF,QXgjCR,SW9iCU,cAAA,OAGF,QXgjCR,SW9iCU,cAAA,OAPF,QX0jCR,SWxjCU,cAAA,KAGF,QX0jCR,SWxjCU,cAAA,KAPF,QXokCR,SWlkCU,cAAA,OAGF,QXokCR,SWlkCU,cAAA,OAPF,QX8kCR,SW5kCU,cAAA,KAGF,QX8kCR,SW5kCU,cAAA,MF/DN,yBE+BE,aAtDJ,KAAA,EAAA,EAAA,KACA,MAAA,KA2DQ,UAtEN,KAAA,EAAA,EAAA,KACA,MAAA,YAqEM,UAtEN,KAAA,EAAA,EAAA,KACA,MAAA,aAqEM,UAtEN,KAAA,EAAA,EAAA,KACA,MAAA,IAqEM,UAtEN,KAAA,EAAA,EAAA,KACA,MAAA,aAqEM,UAtEN,KAAA,EAAA,EAAA,KACA,MAAA,aAqEM,UAtEN,KAAA,EAAA,EAAA,KACA,MAAA,IAqEM,UAtEN,KAAA,EAAA,EAAA,KACA,MAAA,aAqEM,UAtEN,KAAA,EAAA,EAAA,KACA,MAAA,aAqEM,UAtEN,KAAA,EAAA,EAAA,KACA,MAAA,IAqEM,WAtEN,KAAA,EAAA,EAAA,KACA,MAAA,aAqEM,WAtEN,KAAA,EAAA,EAAA,KACA,MAAA,aAqEM,WAtEN,KAAA,EAAA,EAAA,KACA,MAAA,KA6EQ,aA9DV,YAAA,EA8DU,aA9DV,YAAA,YA8DU,aA9DV,YAAA,aA8DU,aA9DV,YAAA,IA8DU,aA9DV,YAAA,aA8DU,aA9DV,YAAA,aA8DU,aA9DV,YAAA,IA8DU,aA9DV,YAAA,aA8DU,aA9DV,YAAA,aA8DU,aA9DV,YAAA,IA8DU,cA9DV,YAAA,aA8DU,cA9DV,YAAA,aAyEM,QX0sCR,SWxsCU,cAAA,EAGF,QX0sCR,SWxsCU,cAAA,EAPF,QXotCR,SWltCU,cAAA,QAGF,QXotCR,SWltCU,cAAA,QAPF,QX8tCR,SW5tCU,cAAA,OAGF,QX8tCR,SW5tCU,cAAA,OAPF,QXwuCR,SWtuCU,cAAA,KAGF,QXwuCR,SWtuCU,cAAA,KAPF,QXkvCR,SWhvCU,cAAA,OAGF,QXkvCR,SWhvCU,cAAA,OAPF,QX4vCR,SW1vCU,cAAA,KAGF,QX4vCR,SW1vCU,cAAA,MF/DN,yBE+BE,aAtDJ,KAAA,EAAA,EAAA,KACA,MAAA,KA2DQ,UAtEN,KAAA,EAAA,EAAA,KACA,MAAA,YAqEM,UAtEN,KAAA,EAAA,EAAA,KACA,MAAA,aAqEM,UAtEN,KAAA,EAAA,EAAA,KACA,MAAA,IAqEM,UAtEN,KAAA,EAAA,EAAA,KACA,MAAA,aAqEM,UAtEN,KAAA,EAAA,EAAA,KACA,MAAA,aAqEM,UAtEN,KAAA,EAAA,EAAA,KACA,MAAA,IAqEM,UAtEN,KAAA,EAAA,EAAA,KACA,MAAA,aAqEM,UAtEN,KAAA,EAAA,EAAA,KACA,MAAA,aAqEM,UAtEN,KAAA,EAAA,EAAA,KACA,MAAA,IAqEM,WAtEN,KAAA,EAAA,EAAA,KACA,MAAA,aAqEM,WAtEN,KAAA,EAAA,EAAA,KACA,MAAA,aAqEM,WAtEN,KAAA,EAAA,EAAA,KACA,MAAA,KA6EQ,aA9DV,YAAA,EA8DU,aA9DV,YAAA,YA8DU,aA9DV,YAAA,aA8DU,aA9DV,YAAA,IA8DU,aA9DV,YAAA,aA8DU,aA9DV,YAAA,aA8DU,aA9DV,YAAA,IA8DU,aA9DV,YAAA,aA8DU,aA9DV,YAAA,aA8DU,aA9DV,YAAA,IA8DU,cA9DV,YAAA,aA8DU,cA9DV,YAAA,aAyEM,QXw3CR,SWt3CU,cAAA,EAGF,QXw3CR,SWt3CU,cAAA,EAPF,QXk4CR,SWh4CU,cAAA,QAGF,QXk4CR,SWh4CU,cAAA,QAPF,QX44CR,SW14CU,cAAA,OAGF,QX44CR,SW14CU,cAAA,OAPF,QXs5CR,SWp5CU,cAAA,KAGF,QXs5CR,SWp5CU,cAAA,KAPF,QXg6CR,SW95CU,cAAA,OAGF,QXg6CR,SW95CU,cAAA,OAPF,QX06CR,SWx6CU,cAAA,KAGF,QX06CR,SWx6CU,cAAA,MF/DN,0BE+BE,aAtDJ,KAAA,EAAA,EAAA,KACA,MAAA,KA2DQ,UAtEN,KAAA,EAAA,EAAA,KACA,MAAA,YAqEM,UAtEN,KAAA,EAAA,EAAA,KACA,MAAA,aAqEM,UAtEN,KAAA,EAAA,EAAA,KACA,MAAA,IAqEM,UAtEN,KAAA,EAAA,EAAA,KACA,MAAA,aAqEM,UAtEN,KAAA,EAAA,EAAA,KACA,MAAA,aAqEM,UAtEN,KAAA,EAAA,EAAA,KACA,MAAA,IAqEM,UAtEN,KAAA,EAAA,EAAA,KACA,MAAA,aAqEM,UAtEN,KAAA,EAAA,EAAA,KACA,MAAA,aAqEM,UAtEN,KAAA,EAAA,EAAA,KACA,MAAA,IAqEM,WAtEN,KAAA,EAAA,EAAA,KACA,MAAA,aAqEM,WAtEN,KAAA,EAAA,EAAA,KACA,MAAA,aAqEM,WAtEN,KAAA,EAAA,EAAA,KACA,MAAA,KA6EQ,aA9DV,YAAA,EA8DU,aA9DV,YAAA,YA8DU,aA9DV,YAAA,aA8DU,aA9DV,YAAA,IA8DU,aA9DV,YAAA,aA8DU,aA9DV,YAAA,aA8DU,aA9DV,YAAA,IA8DU,aA9DV,YAAA,aA8DU,aA9DV,YAAA,aA8DU,aA9DV,YAAA,IA8DU,cA9DV,YAAA,aA8DU,cA9DV,YAAA,aAyEM,QXsiDR,SWpiDU,cAAA,EAGF,QXsiDR,SWpiDU,cAAA,EAPF,QXgjDR,SW9iDU,cAAA,QAGF,QXgjDR,SW9iDU,cAAA,QAPF,QX0jDR,SWxjDU,cAAA,OAGF,QX0jDR,SWxjDU,cAAA,OAPF,QXokDR,SWlkDU,cAAA,KAGF,QXokDR,SWlkDU,cAAA,KAPF,QX8kDR,SW5kDU,cAAA,OAGF,QX8kDR,SW5kDU,cAAA,OAPF,QXwlDR,SWtlDU,cAAA,KAGF,QXwlDR,SWtlDU,cAAA,MF/DN,0BE+BE,cAtDJ,KAAA,EAAA,EAAA,KACA,MAAA,KA2DQ,WAtEN,KAAA,EAAA,EAAA,KACA,MAAA,YAqEM,WAtEN,KAAA,EAAA,EAAA,KACA,MAAA,aAqEM,WAtEN,KAAA,EAAA,EAAA,KACA,MAAA,IAqEM,WAtEN,KAAA,EAAA,EAAA,KACA,MAAA,aAqEM,WAtEN,KAAA,EAAA,EAAA,KACA,MAAA,aAqEM,WAtEN,KAAA,EAAA,EAAA,KACA,MAAA,IAqEM,WAtEN,KAAA,EAAA,EAAA,KACA,MAAA,aAqEM,WAtEN,KAAA,EAAA,EAAA,KACA,MAAA,aAqEM,WAtEN,KAAA,EAAA,EAAA,KACA,MAAA,IAqEM,YAtEN,KAAA,EAAA,EAAA,KACA,MAAA,aAqEM,YAtEN,KAAA,EAAA,EAAA,KACA,MAAA,aAqEM,YAtEN,KAAA,EAAA,EAAA,KACA,MAAA,KA6EQ,cA9DV,YAAA,EA8DU,cA9DV,YAAA,YA8DU,cA9DV,YAAA,aA8DU,cA9DV,YAAA,IA8DU,cA9DV,YAAA,aA8DU,cA9DV,YAAA,aA8DU,cA9DV,YAAA,IA8DU,cA9DV,YAAA,aA8DU,cA9DV,YAAA,aA8DU,cA9DV,YAAA,IA8DU,eA9DV,YAAA,aA8DU,eA9DV,YAAA,aAyEM,SXotDR,UWltDU,cAAA,EAGF,SXotDR,UWltDU,cAAA,EAPF,SX8tDR,UW5tDU,cAAA,QAGF,SX8tDR,UW5tDU,cAAA,QAPF,SXwuDR,UWtuDU,cAAA,OAGF,SXwuDR,UWtuDU,cAAA,OAPF,SXkvDR,UWhvDU,cAAA,KAGF,SXkvDR,UWhvDU,cAAA,KAPF,SX4vDR,UW1vDU,cAAA,OAGF,SX4vDR,UW1vDU,cAAA,OAPF,SXswDR,UWpwDU,cAAA,KAGF,SXswDR,UWpwDU,cAAA,MC1HV,OACE,cAAA,YACA,qBAAA,YACA,yBAAA,QACA,sBAAA,oBACA,wBAAA,QACA,qBAAA,mBACA,uBAAA,QACA,oBAAA,qBAEA,MAAA,KACA,cAAA,KACA,MAAA,QACA,eAAA,IACA,aAAA,QAOA,yBACE,QAAA,MAAA,MACA,iBAAA,mBACA,oBAAA,IACA,WAAA,MAAA,EAAA,EAAA,EAAA,OAAA,0BAGF,aACE,eAAA,QAGF,aACE,eAAA,OAIF,uCACE,oBAAA,aASJ,aACE,aAAA,IAUA,4BACE,QAAA,OAAA,OAeF,gCACE,aAAA,IAAA,EAGA,kCACE,aAAA,EAAA,IAOJ,oCACE,oBAAA,EASF,yCACE,qBAAA,2BACA,MAAA,8BAQJ,cACE,qBAAA,0BACA,MAAA,6BAQA,4BACE,qBAAA,yBACA,MAAA,4BCxHF,eAME,cAAA,QACA,sBAAA,QACA,yBAAA,KACA,qBAAA,QACA,wBAAA,KACA,oBAAA,QACA,uBAAA,KAEA,MAAA,KACA,aAAA,QAfF,iBAME,cAAA,QACA,sBAAA,QACA,yBAAA,KACA,qBAAA,QACA,wBAAA,KACA,oBAAA,QACA,uBAAA,KAEA,MAAA,KACA,aAAA,QAfF,eAME,cAAA,QACA,sBAAA,QACA,yBAAA,KACA,qBAAA,QACA,wBAAA,KACA,oBAAA,QACA,uBAAA,KAEA,MAAA,KACA,aAAA,QAfF,YAME,cAAA,QACA,sBAAA,QACA,yBAAA,KACA,qBAAA,QACA,wBAAA,KACA,oBAAA,QACA,uBAAA,KAEA,MAAA,KACA,aAAA,QAfF,eAME,cAAA,QACA,sBAAA,QACA,yBAAA,KACA,qBAAA,QACA,wBAAA,KACA,oBAAA,QACA,uBAAA,KAEA,MAAA,KACA,aAAA,QAfF,cAME,cAAA,QACA,sBAAA,QACA,yBAAA,KACA,qBAAA,QACA,wBAAA,KACA,oBAAA,QACA,uBAAA,KAEA,MAAA,KACA,aAAA,QAfF,aAME,cAAA,QACA,sBAAA,QACA,yBAAA,KACA,qBAAA,QACA,wBAAA,KACA,oBAAA,QACA,uBAAA,KAEA,MAAA,KACA,aAAA,QAfF,YAME,cAAA,QACA,sBAAA,QACA,yBAAA,KACA,qBAAA,QACA,wBAAA,KACA,oBAAA,QACA,uBAAA,KAEA,MAAA,KACA,aAAA,QDgIA,kBACE,WAAA,KACA,2BAAA,MHvEF,4BGqEA,qBACE,WAAA,KACA,2BAAA,OHvEF,4BGqEA,qBACE,WAAA,KACA,2BAAA,OHvEF,4BGqEA,qBACE,WAAA,KACA,2BAAA,OHvEF,6BGqEA,qBACE,WAAA,KACA,2BAAA,OHvEF,6BGqEA,sBACE,WAAA,KACA,2BAAA,OE/IN,YACE,cAAA,MASF,gBACE,YAAA,oBACA,eAAA,oBACA,cAAA,EboRI,UAAA,QahRJ,YAAA,IAIF,mBACE,YAAA,kBACA,eAAA,kBb0QI,UAAA,QatQN,mBACE,YAAA,mBACA,eAAA,mBboQI,UAAA,QcjSN,WACE,WAAA,OdgSI,UAAA,Oc5RJ,MAAA,QCLF,cACE,QAAA,MACA,MAAA,KACA,QAAA,QAAA,Of8RI,UAAA,Ke3RJ,YAAA,IACA,YAAA,IACA,MAAA,QACA,iBAAA,KACA,gBAAA,YACA,OAAA,IAAA,MAAA,QACA,mBAAA,KAAA,gBAAA,KAAA,WAAA,KdGE,cAAA,OeHE,WAAA,aAAA,KAAA,WAAA,CAAA,WAAA,KAAA,YAIA,uCDhBN,cCiBQ,WAAA,MDGN,yBACE,SAAA,OAEA,wDACE,OAAA,QAKJ,oBACE,MAAA,QACA,iBAAA,KACA,aAAA,QACA,QAAA,EAKE,WAAA,EAAA,EAAA,EAAA,OAAA,qBAOJ,2CAEE,OAAA,MAIF,gCACE,MAAA,QAEA,QAAA,EAHF,2BACE,MAAA,QAEA,QAAA,EAQF,uBAAA,wBAEE,iBAAA,QAGA,QAAA,EAIF,oCACE,QAAA,QAAA,OACA,OAAA,SAAA,QACA,mBAAA,OAAA,kBAAA,OACA,MAAA,QE3EF,iBAAA,QF6EE,eAAA,KACA,aAAA,QACA,aAAA,MACA,aAAA,EACA,wBAAA,IACA,cAAA,ECtEE,WAAA,MAAA,KAAA,WAAA,CAAA,iBAAA,KAAA,WAAA,CAAA,aAAA,KAAA,WAAA,CAAA,WAAA,KAAA,YAIA,uCDuDJ,oCCtDM,WAAA,MDqEN,yEACE,iBAAA,QAGF,0CACE,QAAA,QAAA,OACA,OAAA,SAAA,QACA,mBAAA,OAAA,kBAAA,OACA,MAAA,QE9FF,iBAAA,QFgGE,eAAA,KACA,aAAA,QACA,aAAA,MACA,aAAA,EACA,wBAAA,IACA,cAAA,ECzFE,mBAAA,MAAA,KAAA,WAAA,CAAA,iBAAA,KAAA,WAAA,CAAA,aAAA,KAAA,WAAA,CAAA,WAAA,KAAA,YAAA,WAAA,MAAA,KAAA,WAAA,CAAA,iBAAA,KAAA,WAAA,CAAA,aAAA,KAAA,WAAA,CAAA,WAAA,KAAA,YAIA,uCD0EJ,0CCzEM,mBAAA,KAAA,WAAA,MDwFN,+EACE,iBAAA,QASJ,wBACE,QAAA,MACA,MAAA,KACA,QAAA,QAAA,EACA,cAAA,EACA,YAAA,IACA,MAAA,QACA,iBAAA,YACA,OAAA,MAAA,YACA,aAAA,IAAA,EAEA,wCAAA,wCAEE,cAAA,EACA,aAAA,EAWJ,iBACE,WAAA,4BACA,QAAA,OAAA,MfmJI,UAAA,QClRF,cAAA,McmIF,uCACE,QAAA,OAAA,MACA,OAAA,QAAA,OACA,mBAAA,MAAA,kBAAA,MAGF,6CACE,QAAA,OAAA,MACA,OAAA,QAAA,OACA,mBAAA,MAAA,kBAAA,MAIJ,iBACE,WAAA,2BACA,QAAA,MAAA,KfgII,UAAA,QClRF,cAAA,McsJF,uCACE,QAAA,MAAA,KACA,OAAA,OAAA,MACA,mBAAA,KAAA,kBAAA,KAGF,6CACE,QAAA,MAAA,KACA,OAAA,OAAA,MACA,mBAAA,KAAA,kBAAA,KAQF,sBACE,WAAA,6BAGF,yBACE,WAAA,4BAGF,yBACE,WAAA,2BAKJ,oBACE,UAAA,KACA,OAAA,KACA,QAAA,QAEA,mDACE,OAAA,QAGF,uCACE,OAAA,Md/LA,cAAA,OcmMF,0CACE,OAAA,MdpMA,cAAA,OiBdJ,aACE,QAAA,MACA,MAAA,KACA,QAAA,QAAA,QAAA,QAAA,OAEA,mBAAA,oBlB2RI,UAAA,KkBxRJ,YAAA,IACA,YAAA,IACA,MAAA,QACA,iBAAA,KACA,iBAAA,gOACA,kBAAA,UACA,oBAAA,MAAA,OAAA,OACA,gBAAA,KAAA,KACA,OAAA,IAAA,MAAA,QjBFE,cAAA,OeHE,WAAA,aAAA,KAAA,WAAA,CAAA,WAAA,KAAA,YESJ,mBAAA,KAAA,gBAAA,KAAA,WAAA,KFLI,uCEfN,aFgBQ,WAAA,MEMN,mBACE,aAAA,QACA,QAAA,EAKE,WAAA,EAAA,EAAA,EAAA,OAAA,qBAIJ,uBAAA,mCAEE,cAAA,OACA,iBAAA,KAGF,sBAEE,iBAAA,QAKF,4BACE,MAAA,YACA,YAAA,EAAA,EAAA,EAAA,QAIJ,gBACE,YAAA,OACA,eAAA,OACA,aAAA,MlByOI,UAAA,QkBrON,gBACE,YAAA,MACA,eAAA,MACA,aAAA,KlBkOI,UAAA,QmBjSN,YACE,QAAA,MACA,WAAA,OACA,aAAA,MACA,cAAA,QAEA,8BACE,MAAA,KACA,YAAA,OAIJ,kBACE,MAAA,IACA,OAAA,IACA,WAAA,MACA,eAAA,IACA,iBAAA,KACA,kBAAA,UACA,oBAAA,OACA,gBAAA,QACA,OAAA,IAAA,MAAA,gBACA,mBAAA,KAAA,gBAAA,KAAA,WAAA,KACA,2BAAA,MAAA,aAAA,MAGA,iClBXE,cAAA,MkBeF,8BAEE,cAAA,IAGF,yBACE,OAAA,gBAGF,wBACE,aAAA,QACA,QAAA,EACA,WAAA,EAAA,EAAA,EAAA,OAAA,qBAGF,0BACE,iBAAA,QACA,aAAA,QAEA,yCAII,iBAAA,8NAIJ,sCAII,iBAAA,sIAKN,+CACE,iBAAA,QACA,aAAA,QAKE,iBAAA,wNAIJ,2BACE,eAAA,KACA,OAAA,KACA,QAAA,GAOA,6CAAA,8CACE,QAAA,GAcN,aACE,aAAA,MAEA,+BACE,MAAA,IACA,YAAA,OACA,iBAAA,uJACA,oBAAA,KAAA,OlB9FA,cAAA,IeHE,WAAA,oBAAA,KAAA,YAIA,uCGyFJ,+BHxFM,WAAA,MGgGJ,qCACE,iBAAA,yIAGF,uCACE,oBAAA,MAAA,OAKE,iBAAA,sIAMR,mBACE,QAAA,aACA,aAAA,KAGF,WACE,SAAA,SACA,KAAA,cACA,eAAA,KAIE,yBAAA,0BACE,eAAA,KACA,OAAA,KACA,QAAA,IC9IN,YACE,MAAA,KACA,OAAA,OACA,QAAA,EACA,iBAAA,YACA,mBAAA,KAAA,gBAAA,KAAA,WAAA,KAEA,kBACE,QAAA,EAIA,wCAA0B,WAAA,EAAA,EAAA,EAAA,IAAA,IAAA,CAAA,EAAA,EAAA,EAAA,OAAA,qBAC1B,oCAA0B,WAAA,EAAA,EAAA,EAAA,IAAA,IAAA,CAAA,EAAA,EAAA,EAAA,OAAA,qBAG5B,8BACE,OAAA,EAGF,kCACE,MAAA,KACA,OAAA,KACA,WAAA,QHzBF,iBAAA,QG2BE,OAAA,EnBZA,cAAA,KeHE,mBAAA,iBAAA,KAAA,WAAA,CAAA,aAAA,KAAA,WAAA,CAAA,WAAA,KAAA,YAAA,WAAA,iBAAA,KAAA,WAAA,CAAA,aAAA,KAAA,WAAA,CAAA,WAAA,KAAA,YImBF,mBAAA,KAAA,WAAA,KJfE,uCIMJ,kCJLM,mBAAA,KAAA,WAAA,MIgBJ,yCHjCF,iBAAA,QGsCA,2CACE,MAAA,KACA,OAAA,MACA,MAAA,YACA,OAAA,QACA,iBAAA,QACA,aAAA,YnB7BA,cAAA,KmBkCF,8BACE,MAAA,KACA,OAAA,KHnDF,iBAAA,QGqDE,OAAA,EnBtCA,cAAA,KeHE,gBAAA,iBAAA,KAAA,WAAA,CAAA,aAAA,KAAA,WAAA,CAAA,WAAA,KAAA,YAAA,WAAA,iBAAA,KAAA,WAAA,CAAA,aAAA,KAAA,WAAA,CAAA,WAAA,KAAA,YI6CF,gBAAA,KAAA,WAAA,KJzCE,uCIiCJ,8BJhCM,gBAAA,KAAA,WAAA,MI0CJ,qCH3DF,iBAAA,QGgEA,8BACE,MAAA,KACA,OAAA,MACA,MAAA,YACA,OAAA,QACA,iBAAA,QACA,aAAA,YnBvDA,cAAA,KmB4DF,qBACE,eAAA,KAEA,2CACE,iBAAA,QAGF,uCACE,iBAAA,QCvFN,eACE,SAAA,SAEA,6BtByhFF,4BsBvhFI,OAAA,mBACA,YAAA,KAGF,qBACE,SAAA,SACA,IAAA,EACA,KAAA,EACA,OAAA,KACA,QAAA,KAAA,OACA,eAAA,KACA,OAAA,IAAA,MAAA,YACA,iBAAA,EAAA,ELDE,WAAA,QAAA,IAAA,WAAA,CAAA,UAAA,IAAA,YAIA,uCKXJ,qBLYM,WAAA,MKCN,6BACE,QAAA,KAAA,OAEA,+CACE,MAAA,YADF,0CACE,MAAA,YAGF,0DAEE,YAAA,SACA,eAAA,QAHF,mCAAA,qDAEE,YAAA,SACA,eAAA,QAGF,8CACE,YAAA,SACA,eAAA,QAIJ,4BACE,YAAA,SACA,eAAA,QAMA,gEACE,QAAA,IACA,UAAA,WAAA,mBAAA,mBAFF,yCtB6hFJ,2DACA,kCsB7hFM,QAAA,IACA,UAAA,WAAA,mBAAA,mBAKF,oDACE,QAAA,IACA,UAAA,WAAA,mBAAA,mBCtDN,aACE,SAAA,SACA,QAAA,KACA,UAAA,KACA,YAAA,QACA,MAAA,KAEA,2BvBqlFF,0BuBnlFI,SAAA,SACA,KAAA,EAAA,EAAA,KACA,MAAA,GACA,UAAA,EAIF,iCvBmlFF,gCuBjlFI,QAAA,EAMF,kBACE,SAAA,SACA,QAAA,EAEA,wBACE,QAAA,EAWN,kBACE,QAAA,KACA,YAAA,OACA,QAAA,QAAA,OtBsPI,UAAA,KsBpPJ,YAAA,IACA,YAAA,IACA,MAAA,QACA,WAAA,OACA,YAAA,OACA,iBAAA,QACA,OAAA,IAAA,MAAA,QrBpCE,cAAA,OFinFJ,qBuBnkFA,8BvBikFA,6BACA,kCuB9jFE,QAAA,MAAA,KtBgOI,UAAA,QClRF,cAAA,MF0nFJ,qBuBnkFA,8BvBikFA,6BACA,kCuB9jFE,QAAA,OAAA,MtBuNI,UAAA,QClRF,cAAA,MqBgEJ,6BvBikFA,6BuB/jFE,cAAA,KvBokFF,uEuBvjFI,8FrB/DA,wBAAA,EACA,2BAAA,EF0nFJ,iEuBrjFI,2FrBtEA,wBAAA,EACA,2BAAA,EqBgFF,0IACE,YAAA,KrBpEA,uBAAA,EACA,0BAAA,EsBzBF,gBACE,QAAA,KACA,MAAA,KACA,WAAA,OvByQE,UAAA,OuBtQF,MAAA,QAGF,eACE,SAAA,SACA,IAAA,KACA,QAAA,EACA,QAAA,KACA,UAAA,KACA,QAAA,OAAA,MACA,WAAA,MvB4PE,UAAA,QuBzPF,MAAA,KACA,iBAAA,mBtB1BA,cAAA,OF6qFJ,0BACA,yBwB/oFI,sCxB6oFJ,qCwB3oFM,QAAA,MA9CF,uBAAA,mCAoDE,aAAA,QAGE,cAAA,qBACA,iBAAA,2OACA,kBAAA,UACA,oBAAA,MAAA,wBAAA,OACA,gBAAA,sBAAA,sBAGF,6BAAA,yCACE,aAAA,QACA,WAAA,EAAA,EAAA,EAAA,OAAA,oBAhEJ,2CAAA,+BAyEI,cAAA,qBACA,oBAAA,IAAA,wBAAA,MAAA,wBA1EJ,sBAAA,kCAiFE,aAAA,QAGE,kDAAA,gDAAA,8DAAA,4DAEE,cAAA,SACA,iBAAA,+NAAA,CAAA,2OACA,oBAAA,MAAA,OAAA,MAAA,CAAA,OAAA,MAAA,QACA,gBAAA,KAAA,IAAA,CAAA,sBAAA,sBAIJ,4BAAA,wCACE,aAAA,QACA,WAAA,EAAA,EAAA,EAAA,OAAA,oBA/FJ,2BAAA,uCAsGE,aAAA,QAEA,mCAAA,+CACE,iBAAA,QAGF,iCAAA,6CACE,WAAA,EAAA,EAAA,EAAA,OAAA,oBAGF,6CAAA,yDACE,MAAA,QAKJ,qDACE,YAAA,KAvHF,oCxBkvFJ,mCwBlvFI,gDxBivFJ,+CwBlnFQ,QAAA,EAIF,0CxBonFN,yCwBpnFM,sDxBmnFN,qDwBlnFQ,QAAA,EAjHN,kBACE,QAAA,KACA,MAAA,KACA,WAAA,OvByQE,UAAA,OuBtQF,MAAA,QAGF,iBACE,SAAA,SACA,IAAA,KACA,QAAA,EACA,QAAA,KACA,UAAA,KACA,QAAA,OAAA,MACA,WAAA,MvB4PE,UAAA,QuBzPF,MAAA,KACA,iBAAA,mBtB1BA,cAAA,OFswFJ,8BACA,6BwBxuFI,0CxBsuFJ,yCwBpuFM,QAAA,MA9CF,yBAAA,qCAoDE,aAAA,QAGE,cAAA,qBACA,iBAAA,2TACA,kBAAA,UACA,oBAAA,MAAA,wBAAA,OACA,gBAAA,sBAAA,sBAGF,+BAAA,2CACE,aAAA,QACA,WAAA,EAAA,EAAA,EAAA,OAAA,oBAhEJ,6CAAA,iCAyEI,cAAA,qBACA,oBAAA,IAAA,wBAAA,MAAA,wBA1EJ,wBAAA,oCAiFE,aAAA,QAGE,oDAAA,kDAAA,gEAAA,8DAEE,cAAA,SACA,iBAAA,+NAAA,CAAA,2TACA,oBAAA,MAAA,OAAA,MAAA,CAAA,OAAA,MAAA,QACA,gBAAA,KAAA,IAAA,CAAA,sBAAA,sBAIJ,8BAAA,0CACE,aAAA,QACA,WAAA,EAAA,EAAA,EAAA,OAAA,oBA/FJ,6BAAA,yCAsGE,aAAA,QAEA,qCAAA,iDACE,iBAAA,QAGF,mCAAA,+CACE,WAAA,EAAA,EAAA,EAAA,OAAA,oBAGF,+CAAA,2DACE,MAAA,QAKJ,uDACE,YAAA,KAvHF,sCxB20FJ,qCwB30FI,kDxB00FJ,iDwBzsFQ,QAAA,EAEF,4CxB6sFN,2CwB7sFM,wDxB4sFN,uDwB3sFQ,QAAA,ECtIR,KACE,QAAA,aAEA,YAAA,IACA,YAAA,IACA,MAAA,QACA,WAAA,OACA,gBAAA,KAEA,eAAA,OACA,OAAA,QACA,oBAAA,KAAA,iBAAA,KAAA,YAAA,KACA,iBAAA,YACA,OAAA,IAAA,MAAA,YC8GA,QAAA,QAAA,OzBsKI,UAAA,KClRF,cAAA,OeHE,WAAA,MAAA,KAAA,WAAA,CAAA,iBAAA,KAAA,WAAA,CAAA,aAAA,KAAA,WAAA,CAAA,WAAA,KAAA,YAIA,uCQhBN,KRiBQ,WAAA,MQAN,WACE,MAAA,QAIF,sBAAA,WAEE,QAAA,EACA,WAAA,EAAA,EAAA,EAAA,OAAA,qBAcF,cAAA,cAAA,uBAGE,eAAA,KACA,QAAA,IAYF,aCvCA,MAAA,KRhBA,iBAAA,QQkBA,aAAA,QAGA,mBACE,MAAA,KRtBF,iBAAA,QQwBE,aAAA,QAGF,8BAAA,mBAEE,MAAA,KR7BF,iBAAA,QQ+BE,aAAA,QAKE,WAAA,EAAA,EAAA,EAAA,OAAA,oBAIJ,+BAAA,gCAAA,oBAAA,oBAAA,mCAKE,MAAA,KACA,iBAAA,QAGA,aAAA,QAEA,qCAAA,sCAAA,0BAAA,0BAAA,yCAKI,WAAA,EAAA,EAAA,EAAA,OAAA,oBAKN,sBAAA,sBAEE,MAAA,KACA,iBAAA,QAGA,aAAA,QDZF,eCvCA,MAAA,KRhBA,iBAAA,QQkBA,aAAA,QAGA,qBACE,MAAA,KRtBF,iBAAA,QQwBE,aAAA,QAGF,gCAAA,qBAEE,MAAA,KR7BF,iBAAA,QQ+BE,aAAA,QAKE,WAAA,EAAA,EAAA,EAAA,OAAA,qBAIJ,iCAAA,kCAAA,sBAAA,sBAAA,qCAKE,MAAA,KACA,iBAAA,QAGA,aAAA,QAEA,uCAAA,wCAAA,4BAAA,4BAAA,2CAKI,WAAA,EAAA,EAAA,EAAA,OAAA,qBAKN,wBAAA,wBAEE,MAAA,KACA,iBAAA,QAGA,aAAA,QDZF,aCvCA,MAAA,KRhBA,iBAAA,QQkBA,aAAA,QAGA,mBACE,MAAA,KRtBF,iBAAA,QQwBE,aAAA,QAGF,8BAAA,mBAEE,MAAA,KR7BF,iBAAA,QQ+BE,aAAA,QAKE,WAAA,EAAA,EAAA,EAAA,OAAA,oBAIJ,+BAAA,gCAAA,oBAAA,oBAAA,mCAKE,MAAA,KACA,iBAAA,QAGA,aAAA,QAEA,qCAAA,sCAAA,0BAAA,0BAAA,yCAKI,WAAA,EAAA,EAAA,EAAA,OAAA,oBAKN,sBAAA,sBAEE,MAAA,KACA,iBAAA,QAGA,aAAA,QDZF,UCvCA,MAAA,KRhBA,iBAAA,QQkBA,aAAA,QAGA,gBACE,MAAA,KRtBF,iBAAA,QQwBE,aAAA,QAGF,2BAAA,gBAEE,MAAA,KR7BF,iBAAA,QQ+BE,aAAA,QAKE,WAAA,EAAA,EAAA,EAAA,OAAA,oBAIJ,4BAAA,6BAAA,iBAAA,iBAAA,gCAKE,MAAA,KACA,iBAAA,QAGA,aAAA,QAEA,kCAAA,mCAAA,uBAAA,uBAAA,sCAKI,WAAA,EAAA,EAAA,EAAA,OAAA,oBAKN,mBAAA,mBAEE,MAAA,KACA,iBAAA,QAGA,aAAA,QDZF,aCvCA,MAAA,KRhBA,iBAAA,QQkBA,aAAA,QAGA,mBACE,MAAA,KRtBF,iBAAA,QQwBE,aAAA,QAGF,8BAAA,mBAEE,MAAA,KR7BF,iBAAA,QQ+BE,aAAA,QAKE,WAAA,EAAA,EAAA,EAAA,OAAA,mBAIJ,+BAAA,gCAAA,oBAAA,oBAAA,mCAKE,MAAA,KACA,iBAAA,QAGA,aAAA,QAEA,qCAAA,sCAAA,0BAAA,0BAAA,yCAKI,WAAA,EAAA,EAAA,EAAA,OAAA,mBAKN,sBAAA,sBAEE,MAAA,KACA,iBAAA,QAGA,aAAA,QDZF,YCvCA,MAAA,KRhBA,iBAAA,QQkBA,aAAA,QAGA,kBACE,MAAA,KRtBF,iBAAA,QQwBE,aAAA,QAGF,6BAAA,kBAEE,MAAA,KR7BF,iBAAA,QQ+BE,aAAA,QAKE,WAAA,EAAA,EAAA,EAAA,OAAA,mBAIJ,8BAAA,+BAAA,mBAAA,mBAAA,kCAKE,MAAA,KACA,iBAAA,QAGA,aAAA,QAEA,oCAAA,qCAAA,yBAAA,yBAAA,wCAKI,WAAA,EAAA,EAAA,EAAA,OAAA,mBAKN,qBAAA,qBAEE,MAAA,KACA,iBAAA,QAGA,aAAA,QDZF,WCvCA,MAAA,KRhBA,iBAAA,QQkBA,aAAA,QAGA,iBACE,MAAA,KRtBF,iBAAA,QQwBE,aAAA,QAGF,4BAAA,iBAEE,MAAA,KR7BF,iBAAA,QQ+BE,aAAA,QAKE,WAAA,EAAA,EAAA,EAAA,OAAA,qBAIJ,6BAAA,8BAAA,kBAAA,kBAAA,iCAKE,MAAA,KACA,iBAAA,QAGA,aAAA,QAEA,mCAAA,oCAAA,wBAAA,wBAAA,uCAKI,WAAA,EAAA,EAAA,EAAA,OAAA,qBAKN,oBAAA,oBAEE,MAAA,KACA,iBAAA,QAGA,aAAA,QDZF,UCvCA,MAAA,KRhBA,iBAAA,QQkBA,aAAA,QAGA,gBACE,MAAA,KRtBF,iBAAA,QQwBE,aAAA,QAGF,2BAAA,gBAEE,MAAA,KR7BF,iBAAA,QQ+BE,aAAA,QAKE,WAAA,EAAA,EAAA,EAAA,OAAA,kBAIJ,4BAAA,6BAAA,iBAAA,iBAAA,gCAKE,MAAA,KACA,iBAAA,QAGA,aAAA,QAEA,kCAAA,mCAAA,uBAAA,uBAAA,sCAKI,WAAA,EAAA,EAAA,EAAA,OAAA,kBAKN,mBAAA,mBAEE,MAAA,KACA,iBAAA,QAGA,aAAA,QDNF,qBCmBA,MAAA,QACA,aAAA,QAEA,2BACE,MAAA,KACA,iBAAA,QACA,aAAA,QAGF,sCAAA,2BAEE,WAAA,EAAA,EAAA,EAAA,OAAA,oBAGF,uCAAA,wCAAA,4BAAA,0CAAA,4BAKE,MAAA,KACA,iBAAA,QACA,aAAA,QAEA,6CAAA,8CAAA,kCAAA,gDAAA,kCAKI,WAAA,EAAA,EAAA,EAAA,OAAA,oBAKN,8BAAA,8BAEE,MAAA,QACA,iBAAA,YDvDF,uBCmBA,MAAA,QACA,aAAA,QAEA,6BACE,MAAA,KACA,iBAAA,QACA,aAAA,QAGF,wCAAA,6BAEE,WAAA,EAAA,EAAA,EAAA,OAAA,qBAGF,yCAAA,0CAAA,8BAAA,4CAAA,8BAKE,MAAA,KACA,iBAAA,QACA,aAAA,QAEA,+CAAA,gDAAA,oCAAA,kDAAA,oCAKI,WAAA,EAAA,EAAA,EAAA,OAAA,qBAKN,gCAAA,gCAEE,MAAA,QACA,iBAAA,YDvDF,qBCmBA,MAAA,QACA,aAAA,QAEA,2BACE,MAAA,KACA,iBAAA,QACA,aAAA,QAGF,sCAAA,2BAEE,WAAA,EAAA,EAAA,EAAA,OAAA,mBAGF,uCAAA,wCAAA,4BAAA,0CAAA,4BAKE,MAAA,KACA,iBAAA,QACA,aAAA,QAEA,6CAAA,8CAAA,kCAAA,gDAAA,kCAKI,WAAA,EAAA,EAAA,EAAA,OAAA,mBAKN,8BAAA,8BAEE,MAAA,QACA,iBAAA,YDvDF,kBCmBA,MAAA,QACA,aAAA,QAEA,wBACE,MAAA,KACA,iBAAA,QACA,aAAA,QAGF,mCAAA,wBAEE,WAAA,EAAA,EAAA,EAAA,OAAA,oBAGF,oCAAA,qCAAA,yBAAA,uCAAA,yBAKE,MAAA,KACA,iBAAA,QACA,aAAA,QAEA,0CAAA,2CAAA,+BAAA,6CAAA,+BAKI,WAAA,EAAA,EAAA,EAAA,OAAA,oBAKN,2BAAA,2BAEE,MAAA,QACA,iBAAA,YDvDF,qBCmBA,MAAA,QACA,aAAA,QAEA,2BACE,MAAA,KACA,iBAAA,QACA,aAAA,QAGF,sCAAA,2BAEE,WAAA,EAAA,EAAA,EAAA,OAAA,mBAGF,uCAAA,wCAAA,4BAAA,0CAAA,4BAKE,MAAA,KACA,iBAAA,QACA,aAAA,QAEA,6CAAA,8CAAA,kCAAA,gDAAA,kCAKI,WAAA,EAAA,EAAA,EAAA,OAAA,mBAKN,8BAAA,8BAEE,MAAA,QACA,iBAAA,YDvDF,oBCmBA,MAAA,QACA,aAAA,QAEA,0BACE,MAAA,KACA,iBAAA,QACA,aAAA,QAGF,qCAAA,0BAEE,WAAA,EAAA,EAAA,EAAA,OAAA,mBAGF,sCAAA,uCAAA,2BAAA,yCAAA,2BAKE,MAAA,KACA,iBAAA,QACA,aAAA,QAEA,4CAAA,6CAAA,iCAAA,+CAAA,iCAKI,WAAA,EAAA,EAAA,EAAA,OAAA,mBAKN,6BAAA,6BAEE,MAAA,QACA,iBAAA,YDvDF,mBCmBA,MAAA,QACA,aAAA,QAEA,yBACE,MAAA,KACA,iBAAA,QACA,aAAA,QAGF,oCAAA,yBAEE,WAAA,EAAA,EAAA,EAAA,OAAA,qBAGF,qCAAA,sCAAA,0BAAA,wCAAA,0BAKE,MAAA,KACA,iBAAA,QACA,aAAA,QAEA,2CAAA,4CAAA,gCAAA,8CAAA,gCAKI,WAAA,EAAA,EAAA,EAAA,OAAA,qBAKN,4BAAA,4BAEE,MAAA,QACA,iBAAA,YDvDF,kBCmBA,MAAA,QACA,aAAA,QAEA,wBACE,MAAA,KACA,iBAAA,QACA,aAAA,QAGF,mCAAA,wBAEE,WAAA,EAAA,EAAA,EAAA,OAAA,kBAGF,oCAAA,qCAAA,yBAAA,uCAAA,yBAKE,MAAA,KACA,iBAAA,QACA,aAAA,QAEA,0CAAA,2CAAA,+BAAA,6CAAA,+BAKI,WAAA,EAAA,EAAA,EAAA,OAAA,kBAKN,2BAAA,2BAEE,MAAA,QACA,iBAAA,YD3CJ,UACE,YAAA,IACA,MAAA,QACA,gBAAA,UAEA,gBACE,MAAA,QAQF,mBAAA,mBAEE,MAAA,QAWJ,mBAAA,QCuBE,QAAA,MAAA,KzBsKI,UAAA,QClRF,cAAA,MuByFJ,mBAAA,QCmBE,QAAA,OAAA,MzBsKI,UAAA,QClRF,cAAA,MyBnBJ,MVgBM,WAAA,QAAA,KAAA,OAIA,uCUpBN,MVqBQ,WAAA,MUlBN,iBACE,QAAA,EAMF,qBACE,QAAA,KAIJ,YACE,OAAA,EACA,SAAA,OVDI,WAAA,OAAA,KAAA,KAIA,uCULN,YVMQ,WAAA,MjBs1GR,UADA,SAEA,W4B32GA,QAIE,SAAA,SAGF,iBACE,YAAA,OCqBE,wBACE,QAAA,aACA,YAAA,OACA,eAAA,OACA,QAAA,GAhCJ,WAAA,KAAA,MACA,aAAA,KAAA,MAAA,YACA,cAAA,EACA,YAAA,KAAA,MAAA,YAqDE,8BACE,YAAA,ED3CN,eACE,SAAA,SACA,QAAA,KACA,QAAA,KACA,UAAA,MACA,QAAA,MAAA,EACA,OAAA,E3B+QI,UAAA,K2B7QJ,MAAA,QACA,WAAA,KACA,WAAA,KACA,iBAAA,KACA,gBAAA,YACA,OAAA,IAAA,MAAA,gB1BVE,cAAA,O0BcF,+BACE,IAAA,KACA,KAAA,EACA,WAAA,QAYA,qBACE,cAAA,MAEA,qCACE,MAAA,KACA,KAAA,EAIJ,mBACE,cAAA,IAEA,mCACE,MAAA,EACA,KAAA,KnBCJ,yBmBfA,wBACE,cAAA,MAEA,wCACE,MAAA,KACA,KAAA,EAIJ,sBACE,cAAA,IAEA,sCACE,MAAA,EACA,KAAA,MnBCJ,yBmBfA,wBACE,cAAA,MAEA,wCACE,MAAA,KACA,KAAA,EAIJ,sBACE,cAAA,IAEA,sCACE,MAAA,EACA,KAAA,MnBCJ,yBmBfA,wBACE,cAAA,MAEA,wCACE,MAAA,KACA,KAAA,EAIJ,sBACE,cAAA,IAEA,sCACE,MAAA,EACA,KAAA,MnBCJ,0BmBfA,wBACE,cAAA,MAEA,wCACE,MAAA,KACA,KAAA,EAIJ,sBACE,cAAA,IAEA,sCACE,MAAA,EACA,KAAA,MnBCJ,0BmBfA,yBACE,cAAA,MAEA,yCACE,MAAA,KACA,KAAA,EAIJ,uBACE,cAAA,IAEA,uCACE,MAAA,EACA,KAAA,MAUN,uCACE,IAAA,KACA,OAAA,KACA,WAAA,EACA,cAAA,QC9CA,gCACE,QAAA,aACA,YAAA,OACA,eAAA,OACA,QAAA,GAzBJ,WAAA,EACA,aAAA,KAAA,MAAA,YACA,cAAA,KAAA,MACA,YAAA,KAAA,MAAA,YA8CE,sCACE,YAAA,ED0BJ,wCACE,IAAA,EACA,MAAA,KACA,KAAA,KACA,WAAA,EACA,YAAA,QC5DA,iCACE,QAAA,aACA,YAAA,OACA,eAAA,OACA,QAAA,GAlBJ,WAAA,KAAA,MAAA,YACA,aAAA,EACA,cAAA,KAAA,MAAA,YACA,YAAA,KAAA,MAuCE,uCACE,YAAA,EDoCF,iCACE,eAAA,EAMJ,0CACE,IAAA,EACA,MAAA,KACA,KAAA,KACA,WAAA,EACA,aAAA,QC7EA,mCACE,QAAA,aACA,YAAA,OACA,eAAA,OACA,QAAA,GAWA,mCACE,QAAA,KAGF,oCACE,QAAA,aACA,aAAA,OACA,eAAA,OACA,QAAA,GA9BN,WAAA,KAAA,MAAA,YACA,aAAA,KAAA,MACA,cAAA,KAAA,MAAA,YAiCE,yCACE,YAAA,EDqDF,oCACE,eAAA,EAON,kBACE,OAAA,EACA,OAAA,MAAA,EACA,SAAA,OACA,WAAA,IAAA,MAAA,gBAMF,eACE,QAAA,MACA,MAAA,KACA,QAAA,OAAA,KACA,MAAA,KACA,YAAA,IACA,MAAA,QACA,WAAA,QACA,gBAAA,KACA,YAAA,OACA,iBAAA,YACA,OAAA,EAcA,qBAAA,qBAEE,MAAA,QVzJF,iBAAA,QU8JA,sBAAA,sBAEE,MAAA,KACA,gBAAA,KVjKF,iBAAA,QUqKA,wBAAA,wBAEE,MAAA,QACA,eAAA,KACA,iBAAA,YAMJ,oBACE,QAAA,MAIF,iBACE,QAAA,MACA,QAAA,MAAA,KACA,cAAA,E3B0GI,UAAA,Q2BxGJ,MAAA,QACA,YAAA,OAIF,oBACE,QAAA,MACA,QAAA,OAAA,KACA,MAAA,QAIF,oBACE,MAAA,QACA,iBAAA,QACA,aAAA,gBAGA,mCACE,MAAA,QAEA,yCAAA,yCAEE,MAAA,KVhNJ,iBAAA,sBUoNE,0CAAA,0CAEE,MAAA,KVtNJ,iBAAA,QU0NE,4CAAA,4CAEE,MAAA,QAIJ,sCACE,aAAA,gBAGF,wCACE,MAAA,QAGF,qCACE,MAAA,QE5OJ,W9B2pHA,oB8BzpHE,SAAA,SACA,QAAA,YACA,eAAA,O9B6pHF,yB8B3pHE,gBACE,SAAA,SACA,KAAA,EAAA,EAAA,K9BmqHJ,4CACA,0CAIA,gCADA,gCADA,+BADA,+B8BhqHE,mC9BypHF,iCAIA,uBADA,uBADA,sBADA,sB8BppHI,QAAA,EAKJ,aACE,QAAA,KACA,UAAA,KACA,gBAAA,WAEA,0BACE,MAAA,K9BgqHJ,wC8B1pHE,kCAEE,YAAA,K9B4pHJ,4C8BxpHE,uD5BRE,wBAAA,EACA,2BAAA,EFqqHJ,6C8BrpHE,+B9BopHF,iCEvpHI,uBAAA,EACA,0BAAA,E4BqBJ,uBACE,cAAA,SACA,aAAA,SAEA,8BAAA,uCAAA,sCAGE,YAAA,EAGF,0CACE,aAAA,EAIJ,0CAAA,+BACE,cAAA,QACA,aAAA,QAGF,0CAAA,+BACE,cAAA,OACA,aAAA,OAoBF,oBACE,eAAA,OACA,YAAA,WACA,gBAAA,OAEA,yB9BmnHF,+B8BjnHI,MAAA,K9BqnHJ,iD8BlnHE,2CAEE,WAAA,K9BonHJ,qD8BhnHE,gE5BvFE,2BAAA,EACA,0BAAA,EF2sHJ,sD8BhnHE,8B5B1GE,uBAAA,EACA,wBAAA,E6BxBJ,KACE,QAAA,KACA,UAAA,KACA,aAAA,EACA,cAAA,EACA,WAAA,KAGF,UACE,QAAA,MACA,QAAA,MAAA,KAGA,MAAA,QACA,gBAAA,KdHI,WAAA,MAAA,KAAA,WAAA,CAAA,iBAAA,KAAA,WAAA,CAAA,aAAA,KAAA,YAIA,uCcPN,UdQQ,WAAA,McCN,gBAAA,gBAEE,MAAA,QAKF,mBACE,MAAA,QACA,eAAA,KACA,OAAA,QAQJ,UACE,cAAA,IAAA,MAAA,QAEA,oBACE,cAAA,KACA,WAAA,IACA,OAAA,IAAA,MAAA,Y7BlBA,uBAAA,OACA,wBAAA,O6BoBA,0BAAA,0BAEE,aAAA,QAAA,QAAA,QAEA,UAAA,QAGF,6BACE,MAAA,QACA,iBAAA,YACA,aAAA,Y/BivHN,mC+B7uHE,2BAEE,MAAA,QACA,iBAAA,KACA,aAAA,QAAA,QAAA,KAGF,yBAEE,WAAA,K7B5CA,uBAAA,EACA,wBAAA,E6BuDF,qBACE,WAAA,IACA,OAAA,E7BnEA,cAAA,O6BuEF,4B/BmuHF,2B+BjuHI,MAAA,KbxFF,iBAAA,QlB+zHF,oB+B5tHE,oBAEE,KAAA,EAAA,EAAA,KACA,WAAA,O/B+tHJ,yB+B1tHE,yBAEE,WAAA,EACA,UAAA,EACA,WAAA,OAMF,8B/ButHF,mC+BttHI,MAAA,KAUF,uBACE,QAAA,KAEF,qBACE,QAAA,MCxHJ,QACE,SAAA,SACA,QAAA,KACA,UAAA,KACA,YAAA,OACA,gBAAA,cACA,YAAA,MAEA,eAAA,MAOA,mBhCs0HF,yBAGA,sBADA,sBADA,sBAGA,sBACA,uBgC10HI,QAAA,KACA,UAAA,QACA,YAAA,OACA,gBAAA,cAoBJ,cACE,YAAA,SACA,eAAA,SACA,aAAA,K/B2OI,UAAA,Q+BzOJ,gBAAA,KACA,YAAA,OAaF,YACE,QAAA,KACA,eAAA,OACA,aAAA,EACA,cAAA,EACA,WAAA,KAEA,sBACE,cAAA,EACA,aAAA,EAGF,2BACE,SAAA,OASJ,aACE,YAAA,MACA,eAAA,MAYF,iBACE,WAAA,KACA,UAAA,EAGA,YAAA,OAIF,gBACE,QAAA,OAAA,O/B6KI,UAAA,Q+B3KJ,YAAA,EACA,iBAAA,YACA,OAAA,IAAA,MAAA,Y9BzGE,cAAA,OeHE,WAAA,WAAA,KAAA,YAIA,uCemGN,gBflGQ,WAAA,Me2GN,sBACE,gBAAA,KAGF,sBACE,gBAAA,KACA,QAAA,EACA,WAAA,EAAA,EAAA,EAAA,OAMJ,qBACE,QAAA,aACA,MAAA,MACA,OAAA,MACA,eAAA,OACA,kBAAA,UACA,oBAAA,OACA,gBAAA,KAGF,mBACE,WAAA,6BACA,WAAA,KvB1FE,yBuBsGA,kBAEI,UAAA,OACA,gBAAA,WAEA,8BACE,eAAA,IAEA,6CACE,SAAA,SAGF,wCACE,cAAA,MACA,aAAA,MAIJ,qCACE,SAAA,QAGF,mCACE,QAAA,eACA,WAAA,KAGF,kCACE,QAAA,MvBlIN,yBuBsGA,kBAEI,UAAA,OACA,gBAAA,WAEA,8BACE,eAAA,IAEA,6CACE,SAAA,SAGF,wCACE,cAAA,MACA,aAAA,MAIJ,qCACE,SAAA,QAGF,mCACE,QAAA,eACA,WAAA,KAGF,kCACE,QAAA,MvBlIN,yBuBsGA,kBAEI,UAAA,OACA,gBAAA,WAEA,8BACE,eAAA,IAEA,6CACE,SAAA,SAGF,wCACE,cAAA,MACA,aAAA,MAIJ,qCACE,SAAA,QAGF,mCACE,QAAA,eACA,WAAA,KAGF,kCACE,QAAA,MvBlIN,0BuBsGA,kBAEI,UAAA,OACA,gBAAA,WAEA,8BACE,eAAA,IAEA,6CACE,SAAA,SAGF,wCACE,cAAA,MACA,aAAA,MAIJ,qCACE,SAAA,QAGF,mCACE,QAAA,eACA,WAAA,KAGF,kCACE,QAAA,MvBlIN,0BuBsGA,mBAEI,UAAA,OACA,gBAAA,WAEA,+BACE,eAAA,IAEA,8CACE,SAAA,SAGF,yCACE,cAAA,MACA,aAAA,MAIJ,sCACE,SAAA,QAGF,oCACE,QAAA,eACA,WAAA,KAGF,mCACE,QAAA,MA5BN,eAEI,UAAA,OACA,gBAAA,WAEA,2BACE,eAAA,IAEA,0CACE,SAAA,SAGF,qCACE,cAAA,MACA,aAAA,MAIJ,kCACE,SAAA,QAGF,gCACE,QAAA,eACA,WAAA,KAGF,+BACE,QAAA,KAeR,4BACE,MAAA,eAEA,kCAAA,kCAEE,MAAA,eAKF,oCACE,MAAA,gBAEA,0CAAA,0CAEE,MAAA,eAGF,6CACE,MAAA,ehCg4HR,2CgC53HI,0CAEE,MAAA,eAIJ,8BACE,MAAA,gBACA,aAAA,eAGF,mCACE,iBAAA,4OAGF,2BACE,MAAA,gBAEA,6BhCy3HJ,mCADA,mCgCr3HM,MAAA,eAOJ,2BACE,MAAA,KAEA,iCAAA,iCAEE,MAAA,KAKF,mCACE,MAAA,sBAEA,yCAAA,yCAEE,MAAA,sBAGF,4CACE,MAAA,sBhCg3HR,0CgC52HI,yCAEE,MAAA,KAIJ,6BACE,MAAA,sBACA,aAAA,qBAGF,kCACE,iBAAA,kPAGF,0BACE,MAAA,sBACA,4BhC02HJ,kCADA,kCgCt2HM,MAAA,KC1SN,MACE,SAAA,SACA,QAAA,KACA,eAAA,OACA,UAAA,EAEA,UAAA,WACA,iBAAA,KACA,gBAAA,WACA,OAAA,IAAA,MAAA,iB/BME,cAAA,O+BHF,SACE,aAAA,EACA,YAAA,EAGF,kBACE,WAAA,QACA,cAAA,QAEA,8BACE,iBAAA,E/BEF,uBAAA,mBACA,wBAAA,mB+BCA,6BACE,oBAAA,E/BWF,2BAAA,mBACA,0BAAA,mB+BLF,+BjCipIF,+BiC/oII,WAAA,EAIJ,WAGE,KAAA,EAAA,EAAA,KACA,QAAA,KAAA,KAIF,YACE,cAAA,MAGF,eACE,WAAA,QACA,cAAA,EAGF,sBACE,cAAA,EAIA,iBACE,gBAAA,KAGF,sBACE,YAAA,KAQJ,aACE,QAAA,MAAA,KACA,cAAA,EAEA,iBAAA,gBACA,cAAA,IAAA,MAAA,iBAEA,yB/BnEE,cAAA,mBAAA,mBAAA,EAAA,E+BwEJ,aACE,QAAA,MAAA,KAEA,iBAAA,gBACA,WAAA,IAAA,MAAA,iBAEA,wB/B9EE,cAAA,EAAA,EAAA,mBAAA,mB+BwFJ,kBACE,aAAA,OACA,cAAA,OACA,YAAA,OACA,cAAA,EAUF,mBACE,aAAA,OACA,YAAA,OAIF,kBACE,SAAA,SACA,IAAA,EACA,MAAA,EACA,OAAA,EACA,KAAA,EACA,QAAA,K/BlHE,cAAA,mB+BsHJ,UjCsnIA,iBADA,ciClnIE,MAAA,KAGF,UjCqnIA,cExuII,uBAAA,mBACA,wBAAA,mB+BuHJ,UjCsnIA,iBEhuII,2BAAA,mBACA,0BAAA,mB+BsHF,kBACE,cAAA,OxBnGA,yBwB+FJ,YAQI,QAAA,KACA,UAAA,IAAA,KAGA,kBAEE,KAAA,EAAA,EAAA,GACA,cAAA,EAEA,wBACE,YAAA,EACA,YAAA,EAKA,mC/BnJJ,wBAAA,EACA,2BAAA,EFgwIJ,gDiC3mIU,iDAGE,wBAAA,EjC4mIZ,gDiC1mIU,oDAGE,2BAAA,EAIJ,oC/BpJJ,uBAAA,EACA,0BAAA,EF8vIJ,iDiCxmIU,kDAGE,uBAAA,EjCymIZ,iDiCvmIU,qDAGE,0BAAA,GC5MZ,kBACE,SAAA,SACA,QAAA,KACA,YAAA,OACA,MAAA,KACA,QAAA,KAAA,QjC4RI,UAAA,KiC1RJ,MAAA,QACA,WAAA,KACA,iBAAA,KACA,OAAA,EhCKE,cAAA,EgCHF,gBAAA,KjBAI,WAAA,MAAA,KAAA,WAAA,CAAA,iBAAA,KAAA,WAAA,CAAA,aAAA,KAAA,WAAA,CAAA,WAAA,KAAA,WAAA,CAAA,cAAA,KAAA,KAIA,uCiBhBN,kBjBiBQ,WAAA,MiBFN,kCACE,MAAA,QACA,iBAAA,QACA,WAAA,MAAA,EAAA,KAAA,EAAA,iBAEA,yCACE,iBAAA,gRACA,UAAA,gBAKJ,yBACE,YAAA,EACA,MAAA,QACA,OAAA,QACA,YAAA,KACA,QAAA,GACA,iBAAA,gRACA,kBAAA,UACA,gBAAA,QjBvBE,WAAA,UAAA,IAAA,YAIA,uCiBWJ,yBjBVM,WAAA,MiBsBN,wBACE,QAAA,EAGF,wBACE,QAAA,EACA,aAAA,QACA,QAAA,EACA,WAAA,EAAA,EAAA,EAAA,OAAA,qBAIJ,kBACE,cAAA,EAGF,gBACE,iBAAA,KACA,OAAA,IAAA,MAAA,iBAEA,8BhCnCE,uBAAA,OACA,wBAAA,OgCqCA,gDhCtCA,uBAAA,mBACA,wBAAA,mBgC0CF,oCACE,WAAA,EAIF,6BhClCE,2BAAA,OACA,0BAAA,OgCqCE,yDhCtCF,2BAAA,mBACA,0BAAA,mBgC0CA,iDhC3CA,2BAAA,OACA,0BAAA,OgCgDJ,gBACE,QAAA,KAAA,QASA,qCACE,aAAA,EAGF,iCACE,aAAA,EACA,YAAA,EhCxFA,cAAA,EgC2FA,6CAAgB,WAAA,EAChB,4CAAe,cAAA,EAEf,mDhC9FA,cAAA,EiCnBJ,YACE,QAAA,KACA,UAAA,KACA,QAAA,EAAA,EACA,cAAA,KAEA,WAAA,KAOA,kCACE,aAAA,MAEA,0CACE,MAAA,KACA,cAAA,MACA,MAAA,QACA,QAAA,kCAIJ,wBACE,MAAA,QCzBJ,YACE,QAAA,KhCGA,aAAA,EACA,WAAA,KgCAF,WACE,SAAA,SACA,QAAA,MACA,MAAA,QACA,gBAAA,KACA,iBAAA,KACA,OAAA,IAAA,MAAA,QnBKI,WAAA,MAAA,KAAA,WAAA,CAAA,iBAAA,KAAA,WAAA,CAAA,aAAA,KAAA,WAAA,CAAA,WAAA,KAAA,YAIA,uCmBfN,WnBgBQ,WAAA,MmBPN,iBACE,QAAA,EACA,MAAA,QAEA,iBAAA,QACA,aAAA,QAGF,iBACE,QAAA,EACA,MAAA,QACA,iBAAA,QACA,QAAA,EACA,WAAA,EAAA,EAAA,EAAA,OAAA,qBAKF,wCACE,YAAA,KAGF,6BACE,QAAA,EACA,MAAA,KlBlCF,iBAAA,QkBoCE,aAAA,QAGF,+BACE,MAAA,QACA,eAAA,KACA,iBAAA,KACA,aAAA,QC3CF,WACE,QAAA,QAAA,OAOI,kCnCqCJ,uBAAA,OACA,0BAAA,OmChCI,iCnCiBJ,wBAAA,OACA,2BAAA,OmChCF,0BACE,QAAA,OAAA,OpCgSE,UAAA,QoCzRE,iDnCqCJ,uBAAA,MACA,0BAAA,MmChCI,gDnCiBJ,wBAAA,MACA,2BAAA,MmChCF,0BACE,QAAA,OAAA,MpCgSE,UAAA,QoCzRE,iDnCqCJ,uBAAA,MACA,0BAAA,MmChCI,gDnCiBJ,wBAAA,MACA,2BAAA,MoC/BJ,OACE,QAAA,aACA,QAAA,MAAA,MrC8RI,UAAA,MqC5RJ,YAAA,IACA,YAAA,EACA,MAAA,KACA,WAAA,OACA,YAAA,OACA,eAAA,SpCKE,cAAA,OoCAF,aACE,QAAA,KAKJ,YACE,SAAA,SACA,IAAA,KCvBF,OACE,SAAA,SACA,QAAA,KAAA,KACA,cAAA,KACA,OAAA,IAAA,MAAA,YrCWE,cAAA,OqCNJ,eAEE,MAAA,QAIF,YACE,YAAA,IAQF,mBACE,cAAA,KAGA,8BACE,SAAA,SACA,IAAA,EACA,MAAA,EACA,QAAA,EACA,QAAA,QAAA,KAeF,eClDA,MAAA,QtBEA,iBAAA,QsBAA,aAAA,QAEA,2BACE,MAAA,QD6CF,iBClDA,MAAA,QtBEA,iBAAA,QsBAA,aAAA,QAEA,6BACE,MAAA,QD6CF,eClDA,MAAA,QtBEA,iBAAA,QsBAA,aAAA,QAEA,2BACE,MAAA,QD6CF,YClDA,MAAA,QtBEA,iBAAA,QsBAA,aAAA,QAEA,wBACE,MAAA,QD6CF,eClDA,MAAA,QtBEA,iBAAA,QsBAA,aAAA,QAEA,2BACE,MAAA,QD6CF,cClDA,MAAA,QtBEA,iBAAA,QsBAA,aAAA,QAEA,0BACE,MAAA,QD6CF,aClDA,MAAA,QtBEA,iBAAA,QsBAA,aAAA,QAEA,yBACE,MAAA,QD6CF,YClDA,MAAA,QtBEA,iBAAA,QsBAA,aAAA,QAEA,wBACE,MAAA,QCHF,wCACE,GAAK,sBAAA,MADP,gCACE,GAAK,sBAAA,MAKT,UACE,QAAA,KACA,OAAA,KACA,SAAA,OxCwRI,UAAA,OwCtRJ,iBAAA,QvCIE,cAAA,OuCCJ,cACE,QAAA,KACA,eAAA,OACA,gBAAA,OACA,SAAA,OACA,MAAA,KACA,WAAA,OACA,YAAA,OACA,iBAAA,QxBZI,WAAA,MAAA,IAAA,KAIA,uCwBAN,cxBCQ,WAAA,MwBWR,sBvBYE,iBAAA,iKuBVA,gBAAA,KAAA,KAIA,uBACE,kBAAA,GAAA,OAAA,SAAA,qBAAA,UAAA,GAAA,OAAA,SAAA,qBAGE,uCAJJ,uBAKM,kBAAA,KAAA,UAAA,MCvCR,YACE,QAAA,KACA,eAAA,OAGA,aAAA,EACA,cAAA,ExCSE,cAAA,OwCLJ,qBACE,gBAAA,KACA,cAAA,QAEA,gCAEE,QAAA,uBAAA,KACA,kBAAA,QAUJ,wBACE,MAAA,KACA,MAAA,QACA,WAAA,QAGA,8BAAA,8BAEE,QAAA,EACA,MAAA,QACA,gBAAA,KACA,iBAAA,QAGF,+BACE,MAAA,QACA,iBAAA,QASJ,iBACE,SAAA,SACA,QAAA,MACA,QAAA,MAAA,KACA,MAAA,QACA,gBAAA,KACA,iBAAA,KACA,OAAA,IAAA,MAAA,iBAEA,6BxCrCE,uBAAA,QACA,wBAAA,QwCwCF,4BxC3BE,2BAAA,QACA,0BAAA,QwC8BF,0BAAA,0BAEE,MAAA,QACA,eAAA,KACA,iBAAA,KAIF,wBACE,QAAA,EACA,MAAA,KACA,iBAAA,QACA,aAAA,QAGF,kCACE,iBAAA,EAEA,yCACE,WAAA,KACA,iBAAA,IAcF,uBACE,eAAA,IAGE,oDxCrCJ,0BAAA,OAZA,wBAAA,EwCsDI,mDxCtDJ,wBAAA,OAYA,0BAAA,EwC+CI,+CACE,WAAA,EAGF,yDACE,iBAAA,IACA,kBAAA,EAEA,gEACE,YAAA,KACA,kBAAA,IjCpER,yBiC4CA,0BACE,eAAA,IAGE,uDxCrCJ,0BAAA,OAZA,wBAAA,EwCsDI,sDxCtDJ,wBAAA,OAYA,0BAAA,EwC+CI,kDACE,WAAA,EAGF,4DACE,iBAAA,IACA,kBAAA,EAEA,mEACE,YAAA,KACA,kBAAA,KjCpER,yBiC4CA,0BACE,eAAA,IAGE,uDxCrCJ,0BAAA,OAZA,wBAAA,EwCsDI,sDxCtDJ,wBAAA,OAYA,0BAAA,EwC+CI,kDACE,WAAA,EAGF,4DACE,iBAAA,IACA,kBAAA,EAEA,mEACE,YAAA,KACA,kBAAA,KjCpER,yBiC4CA,0BACE,eAAA,IAGE,uDxCrCJ,0BAAA,OAZA,wBAAA,EwCsDI,sDxCtDJ,wBAAA,OAYA,0BAAA,EwC+CI,kDACE,WAAA,EAGF,4DACE,iBAAA,IACA,kBAAA,EAEA,mEACE,YAAA,KACA,kBAAA,KjCpER,0BiC4CA,0BACE,eAAA,IAGE,uDxCrCJ,0BAAA,OAZA,wBAAA,EwCsDI,sDxCtDJ,wBAAA,OAYA,0BAAA,EwC+CI,kDACE,WAAA,EAGF,4DACE,iBAAA,IACA,kBAAA,EAEA,mEACE,YAAA,KACA,kBAAA,KjCpER,0BiC4CA,2BACE,eAAA,IAGE,wDxCrCJ,0BAAA,OAZA,wBAAA,EwCsDI,uDxCtDJ,wBAAA,OAYA,0BAAA,EwC+CI,mDACE,WAAA,EAGF,6DACE,iBAAA,IACA,kBAAA,EAEA,oEACE,YAAA,KACA,kBAAA,KAcZ,kBxC9HI,cAAA,EwCiIF,mCACE,aAAA,EAAA,EAAA,IAEA,8CACE,oBAAA,ECpJJ,yBACE,MAAA,QACA,iBAAA,QAGE,sDAAA,sDAEE,MAAA,QACA,iBAAA,QAGF,uDACE,MAAA,KACA,iBAAA,QACA,aAAA,QAdN,2BACE,MAAA,QACA,iBAAA,QAGE,wDAAA,wDAEE,MAAA,QACA,iBAAA,QAGF,yDACE,MAAA,KACA,iBAAA,QACA,aAAA,QAdN,yBACE,MAAA,QACA,iBAAA,QAGE,sDAAA,sDAEE,MAAA,QACA,iBAAA,QAGF,uDACE,MAAA,KACA,iBAAA,QACA,aAAA,QAdN,sBACE,MAAA,QACA,iBAAA,QAGE,mDAAA,mDAEE,MAAA,QACA,iBAAA,QAGF,oDACE,MAAA,KACA,iBAAA,QACA,aAAA,QAdN,yBACE,MAAA,QACA,iBAAA,QAGE,sDAAA,sDAEE,MAAA,QACA,iBAAA,QAGF,uDACE,MAAA,KACA,iBAAA,QACA,aAAA,QAdN,wBACE,MAAA,QACA,iBAAA,QAGE,qDAAA,qDAEE,MAAA,QACA,iBAAA,QAGF,sDACE,MAAA,KACA,iBAAA,QACA,aAAA,QAdN,uBACE,MAAA,QACA,iBAAA,QAGE,oDAAA,oDAEE,MAAA,QACA,iBAAA,QAGF,qDACE,MAAA,KACA,iBAAA,QACA,aAAA,QAdN,sBACE,MAAA,QACA,iBAAA,QAGE,mDAAA,mDAEE,MAAA,QACA,iBAAA,QAGF,oDACE,MAAA,KACA,iBAAA,QACA,aAAA,QCbR,WACE,WAAA,YACA,MAAA,IACA,OAAA,IACA,QAAA,MAAA,MACA,MAAA,KACA,WAAA,YAAA,0TAAA,MAAA,CAAA,IAAA,KAAA,UACA,OAAA,E1COE,cAAA,O0CLF,QAAA,GAGA,iBACE,MAAA,KACA,gBAAA,KACA,QAAA,IAGF,iBACE,QAAA,EACA,WAAA,EAAA,EAAA,EAAA,OAAA,qBACA,QAAA,EAGF,oBAAA,oBAEE,eAAA,KACA,oBAAA,KAAA,iBAAA,KAAA,YAAA,KACA,QAAA,IAIJ,iBACE,OAAA,UAAA,gBAAA,iBCtCF,OACE,MAAA,MACA,UAAA,K5CmSI,UAAA,Q4ChSJ,eAAA,KACA,iBAAA,sBACA,gBAAA,YACA,OAAA,IAAA,MAAA,eACA,WAAA,EAAA,MAAA,KAAA,gB3CUE,cAAA,O2CPF,gCACE,QAAA,EAGF,YACE,QAAA,KAIJ,iBACE,MAAA,oBAAA,MAAA,iBAAA,MAAA,YACA,UAAA,KACA,eAAA,KAEA,mCACE,cAAA,OAIJ,cACE,QAAA,KACA,YAAA,OACA,QAAA,MAAA,OACA,MAAA,QACA,iBAAA,sBACA,gBAAA,YACA,cAAA,IAAA,MAAA,gB3CVE,uBAAA,mBACA,wBAAA,mB2CYF,yBACE,aAAA,SACA,YAAA,OAIJ,YACE,QAAA,OACA,UAAA,WC1CF,OACE,SAAA,MACA,IAAA,EACA,KAAA,EACA,QAAA,KACA,QAAA,KACA,MAAA,KACA,OAAA,KACA,WAAA,OACA,WAAA,KAGA,QAAA,EAOF,cACE,SAAA,SACA,MAAA,KACA,OAAA,MAEA,eAAA,KAGA,0B7BlBI,WAAA,UAAA,IAAA,S6BoBF,UAAA,mB7BhBE,uC6BcJ,0B7BbM,WAAA,M6BiBN,0BACE,UAAA,KAIF,kCACE,UAAA,YAIJ,yBACE,OAAA,kBAEA,wCACE,WAAA,KACA,SAAA,OAGF,qCACE,WAAA,KAIJ,uBACE,QAAA,KACA,YAAA,OACA,WAAA,kBAIF,eACE,SAAA,SACA,QAAA,KACA,eAAA,OACA,MAAA,KAGA,eAAA,KACA,iBAAA,KACA,gBAAA,YACA,OAAA,IAAA,MAAA,e5C3DE,cAAA,M4C+DF,QAAA,EAIF,gBACE,SAAA,MACA,IAAA,EACA,KAAA,EACA,QAAA,KACA,MAAA,MACA,OAAA,MACA,iBAAA,KAGA,qBAAS,QAAA,EACT,qBAAS,QAAA,GAKX,cACE,QAAA,KACA,YAAA,EACA,YAAA,OACA,gBAAA,cACA,QAAA,KAAA,KACA,cAAA,IAAA,MAAA,Q5ChFE,uBAAA,kBACA,wBAAA,kB4CkFF,yBACE,QAAA,MAAA,MACA,OAAA,OAAA,OAAA,OAAA,KAKJ,aACE,cAAA,EACA,YAAA,IAKF,YACE,SAAA,SAGA,KAAA,EAAA,EAAA,KACA,QAAA,KAIF,cACE,QAAA,KACA,UAAA,KACA,YAAA,EACA,YAAA,OACA,gBAAA,SACA,QAAA,OACA,WAAA,IAAA,MAAA,Q5CnGE,2BAAA,kBACA,0BAAA,kB4CwGF,gBACE,OAAA,OrCrFA,yBqC4FF,cACE,UAAA,MACA,OAAA,QAAA,KAGF,yBACE,OAAA,oBAGF,uBACE,WAAA,oBAOF,UAAY,UAAA,OrC7GV,yBqCiHF,U9CgkKF,U8C9jKI,UAAA,OrCnHA,0BqCwHF,UAAY,UAAA,QASV,kBACE,MAAA,MACA,UAAA,KACA,OAAA,KACA,OAAA,EAEA,iCACE,OAAA,KACA,OAAA,E5CrLJ,cAAA,E4CyLE,gC5CzLF,cAAA,E4C6LE,8BACE,WAAA,KAGF,gC5CjMF,cAAA,EOyDA,4BqCoHA,0BACE,MAAA,MACA,UAAA,KACA,OAAA,KACA,OAAA,EAEA,yCACE,OAAA,KACA,OAAA,E5CrLJ,cAAA,E4CyLE,wC5CzLF,cAAA,E4C6LE,sCACE,WAAA,KAGF,wC5CjMF,cAAA,GOyDA,4BqCoHA,0BACE,MAAA,MACA,UAAA,KACA,OAAA,KACA,OAAA,EAEA,yCACE,OAAA,KACA,OAAA,E5CrLJ,cAAA,E4CyLE,wC5CzLF,cAAA,E4C6LE,sCACE,WAAA,KAGF,wC5CjMF,cAAA,GOyDA,4BqCoHA,0BACE,MAAA,MACA,UAAA,KACA,OAAA,KACA,OAAA,EAEA,yCACE,OAAA,KACA,OAAA,E5CrLJ,cAAA,E4CyLE,wC5CzLF,cAAA,E4C6LE,sCACE,WAAA,KAGF,wC5CjMF,cAAA,GOyDA,6BqCoHA,0BACE,MAAA,MACA,UAAA,KACA,OAAA,KACA,OAAA,EAEA,yCACE,OAAA,KACA,OAAA,E5CrLJ,cAAA,E4CyLE,wC5CzLF,cAAA,E4C6LE,sCACE,WAAA,KAGF,wC5CjMF,cAAA,GOyDA,6BqCoHA,2BACE,MAAA,MACA,UAAA,KACA,OAAA,KACA,OAAA,EAEA,0CACE,OAAA,KACA,OAAA,E5CrLJ,cAAA,E4CyLE,yC5CzLF,cAAA,E4C6LE,uCACE,WAAA,KAGF,yC5CjMF,cAAA,G6ClBJ,SACE,SAAA,SACA,QAAA,KACA,QAAA,MACA,OAAA,ECJA,YAAA,0BAEA,WAAA,OACA,YAAA,IACA,YAAA,IACA,WAAA,KACA,WAAA,MACA,gBAAA,KACA,YAAA,KACA,eAAA,KACA,eAAA,OACA,WAAA,OACA,aAAA,OACA,YAAA,OACA,WAAA,K/CsRI,UAAA,Q8C1RJ,UAAA,WACA,QAAA,EAEA,cAAS,QAAA,GAET,wBACE,SAAA,SACA,QAAA,MACA,MAAA,MACA,OAAA,MAEA,gCACE,SAAA,SACA,QAAA,GACA,aAAA,YACA,aAAA,MAKN,6CAAA,gBACE,QAAA,MAAA,EAEA,4DAAA,+BACE,OAAA,EAEA,oEAAA,uCACE,IAAA,KACA,aAAA,MAAA,MAAA,EACA,iBAAA,KAKN,+CAAA,gBACE,QAAA,EAAA,MAEA,8DAAA,+BACE,KAAA,EACA,MAAA,MACA,OAAA,MAEA,sEAAA,uCACE,MAAA,KACA,aAAA,MAAA,MAAA,MAAA,EACA,mBAAA,KAKN,gDAAA,mBACE,QAAA,MAAA,EAEA,+DAAA,kCACE,IAAA,EAEA,uEAAA,0CACE,OAAA,KACA,aAAA,EAAA,MAAA,MACA,oBAAA,KAKN,8CAAA,kBACE,QAAA,EAAA,MAEA,6DAAA,iCACE,MAAA,EACA,MAAA,MACA,OAAA,MAEA,qEAAA,yCACE,KAAA,KACA,aAAA,MAAA,EAAA,MAAA,MACA,kBAAA,KAqBN,eACE,UAAA,MACA,QAAA,OAAA,MACA,MAAA,KACA,WAAA,OACA,iBAAA,K7C7FE,cAAA,O+CnBJ,SACE,SAAA,SACA,IAAA,EACA,KAAA,EACA,QAAA,KACA,QAAA,MACA,UAAA,MDLA,YAAA,0BAEA,WAAA,OACA,YAAA,IACA,YAAA,IACA,WAAA,KACA,WAAA,MACA,gBAAA,KACA,YAAA,KACA,eAAA,KACA,eAAA,OACA,WAAA,OACA,aAAA,OACA,YAAA,OACA,WAAA,K/CsRI,UAAA,QgDzRJ,UAAA,WACA,iBAAA,KACA,gBAAA,YACA,OAAA,IAAA,MAAA,e/CIE,cAAA,M+CAF,wBACE,SAAA,SACA,QAAA,MACA,MAAA,KACA,OAAA,MAEA,+BAAA,gCAEE,SAAA,SACA,QAAA,MACA,QAAA,GACA,aAAA,YACA,aAAA,MAMJ,4DAAA,+BACE,OAAA,mBAEA,oEAAA,uCACE,OAAA,EACA,aAAA,MAAA,MAAA,EACA,iBAAA,gBAGF,mEAAA,sCACE,OAAA,IACA,aAAA,MAAA,MAAA,EACA,iBAAA,KAMJ,8DAAA,+BACE,KAAA,mBACA,MAAA,MACA,OAAA,KAEA,sEAAA,uCACE,KAAA,EACA,aAAA,MAAA,MAAA,MAAA,EACA,mBAAA,gBAGF,qEAAA,sCACE,KAAA,IACA,aAAA,MAAA,MAAA,MAAA,EACA,mBAAA,KAMJ,+DAAA,kCACE,IAAA,mBAEA,uEAAA,0CACE,IAAA,EACA,aAAA,EAAA,MAAA,MAAA,MACA,oBAAA,gBAGF,sEAAA,yCACE,IAAA,IACA,aAAA,EAAA,MAAA,MAAA,MACA,oBAAA,KAKJ,wEAAA,2CACE,SAAA,SACA,IAAA,EACA,KAAA,IACA,QAAA,MACA,MAAA,KACA,YAAA,OACA,QAAA,GACA,cAAA,IAAA,MAAA,QAKF,6DAAA,iCACE,MAAA,mBACA,MAAA,MACA,OAAA,KAEA,qEAAA,yCACE,MAAA,EACA,aAAA,MAAA,EAAA,MAAA,MACA,kBAAA,gBAGF,oEAAA,wCACE,MAAA,IACA,aAAA,MAAA,EAAA,MAAA,MACA,kBAAA,KAqBN,gBACE,QAAA,MAAA,KACA,cAAA,EhDuJI,UAAA,KgDpJJ,iBAAA,QACA,cAAA,IAAA,MAAA,e/CtHE,uBAAA,kBACA,wBAAA,kB+CwHF,sBACE,QAAA,KAIJ,cACE,QAAA,KAAA,KACA,MAAA,QC/IF,UACE,SAAA,SAGF,wBACE,aAAA,MAGF,gBACE,SAAA,SACA,MAAA,KACA,SAAA,OCtBA,uBACE,QAAA,MACA,MAAA,KACA,QAAA,GDuBJ,eACE,SAAA,SACA,QAAA,KACA,MAAA,KACA,MAAA,KACA,aAAA,MACA,4BAAA,OAAA,oBAAA,OjClBI,WAAA,UAAA,IAAA,YAIA,uCiCQN,ejCPQ,WAAA,MjBinLR,oBACA,oBkDjmLA,sBAGE,QAAA,MlDomLF,0BkDhmLA,8CAEE,UAAA,iBlDmmLF,4BkDhmLA,4CAEE,UAAA,kBAWA,8BACE,QAAA,EACA,oBAAA,QACA,UAAA,KlD2lLJ,uDACA,qDkDzlLE,qCAGE,QAAA,EACA,QAAA,ElD0lLJ,yCkDvlLE,2CAEE,QAAA,EACA,QAAA,EjC/DE,WAAA,QAAA,GAAA,IAIA,uCjBspLN,yCkD9lLE,2CjCvDM,WAAA,MjB2pLR,uBkDvlLA,uBAEE,SAAA,SACA,IAAA,EACA,OAAA,EACA,QAAA,EAEA,QAAA,KACA,YAAA,OACA,gBAAA,OACA,MAAA,IACA,QAAA,EACA,MAAA,KACA,WAAA,OACA,WAAA,IACA,OAAA,EACA,QAAA,GjCzFI,WAAA,QAAA,KAAA,KAIA,uCjB+qLN,uBkD1mLA,uBjCpEQ,WAAA,MjBorLR,6BADA,6BkD3lLE,6BAAA,6BAEE,MAAA,KACA,gBAAA,KACA,QAAA,EACA,QAAA,GAGJ,uBACE,KAAA,EAGF,uBACE,MAAA,ElD+lLF,4BkD1lLA,4BAEE,QAAA,aACA,MAAA,KACA,OAAA,KACA,kBAAA,UACA,oBAAA,IACA,gBAAA,KAAA,KAWF,4BACE,iBAAA,wPAEF,4BACE,iBAAA,yPAQF,qBACE,SAAA,SACA,MAAA,EACA,OAAA,EACA,KAAA,EACA,QAAA,EACA,QAAA,KACA,gBAAA,OACA,QAAA,EAEA,aAAA,IACA,cAAA,KACA,YAAA,IACA,WAAA,KAEA,sCACE,WAAA,YACA,KAAA,EAAA,EAAA,KACA,MAAA,KACA,OAAA,IACA,QAAA,EACA,aAAA,IACA,YAAA,IACA,YAAA,OACA,OAAA,QACA,iBAAA,KACA,gBAAA,YACA,OAAA,EAEA,WAAA,KAAA,MAAA,YACA,cAAA,KAAA,MAAA,YACA,QAAA,GjC5KE,WAAA,QAAA,IAAA,KAIA,uCiCwJJ,sCjCvJM,WAAA,MiC2KN,6BACE,QAAA,EASJ,kBACE,SAAA,SACA,MAAA,IACA,OAAA,QACA,KAAA,IACA,YAAA,QACA,eAAA,QACA,MAAA,KACA,WAAA,OlDqlLF,2CkD/kLE,2CAEE,OAAA,UAAA,eAGF,qDACE,iBAAA,KAGF,iCACE,MAAA,KE7NJ,kCACE,GAAK,UAAA,gBADP,0BACE,GAAK,UAAA,gBAIP,gBACE,QAAA,aACA,MAAA,KACA,OAAA,KACA,eAAA,QACA,OAAA,MAAA,MAAA,aACA,mBAAA,YAEA,cAAA,IACA,kBAAA,KAAA,OAAA,SAAA,eAAA,UAAA,KAAA,OAAA,SAAA,eAGF,mBACE,MAAA,KACA,OAAA,KACA,aAAA,KAQF,gCACE,GACE,UAAA,SAEF,IACE,QAAA,EACA,UAAA,MANJ,wBACE,GACE,UAAA,SAEF,IACE,QAAA,EACA,UAAA,MAKJ,cACE,QAAA,aACA,MAAA,KACA,OAAA,KACA,eAAA,QACA,iBAAA,aAEA,cAAA,IACA,QAAA,EACA,kBAAA,KAAA,OAAA,SAAA,aAAA,UAAA,KAAA,OAAA,SAAA,aAGF,iBACE,MAAA,KACA,OAAA,KAIA,uCACE,gBpDqzLJ,coDnzLM,2BAAA,KAAA,mBAAA,MCjEN,WACE,SAAA,MACA,OAAA,EACA,QAAA,KACA,QAAA,KACA,eAAA,OACA,UAAA,KAEA,WAAA,OACA,iBAAA,KACA,gBAAA,YACA,QAAA,EpCKI,WAAA,UAAA,IAAA,YAIA,uCoCpBN,WpCqBQ,WAAA,MoCLR,kBACE,QAAA,KACA,YAAA,OACA,gBAAA,cACA,QAAA,KAAA,KAEA,6BACE,QAAA,MAAA,MACA,WAAA,OACA,aAAA,OACA,cAAA,OAIJ,iBACE,cAAA,EACA,YAAA,IAGF,gBACE,UAAA,EACA,QAAA,KAAA,KACA,WAAA,KAGF,iBACE,IAAA,EACA,KAAA,EACA,MAAA,MACA,aAAA,IAAA,MAAA,eACA,UAAA,kBAGF,eACE,IAAA,EACA,MAAA,EACA,MAAA,MACA,YAAA,IAAA,MAAA,eACA,UAAA,iBAGF,eACE,IAAA,EACA,MAAA,EACA,KAAA,EACA,OAAA,KACA,WAAA,KACA,cAAA,IAAA,MAAA,eACA,UAAA,kBAGF,kBACE,MAAA,EACA,KAAA,EACA,OAAA,KACA,WAAA,KACA,WAAA,IAAA,MAAA,eACA,UAAA,iBAGF,gBACE,UAAA,KF3EA,iBACE,QAAA,MACA,MAAA,KACA,QAAA,GGJF,cACE,MAAA,QAGE,oBAAA,oBAEE,MAAA,QANN,gBACE,MAAA,QAGE,sBAAA,sBAEE,MAAA,QANN,cACE,MAAA,QAGE,oBAAA,oBAEE,MAAA,QANN,WACE,MAAA,QAGE,iBAAA,iBAEE,MAAA,QANN,cACE,MAAA,QAGE,oBAAA,oBAEE,MAAA,QANN,aACE,MAAA,QAGE,mBAAA,mBAEE,MAAA,QANN,YACE,MAAA,QAGE,kBAAA,kBAEE,MAAA,QANN,WACE,MAAA,QAGE,iBAAA,iBAEE,MAAA,QCLR,OACE,SAAA,SACA,MAAA,KAEA,eACE,QAAA,MACA,YAAA,uBACA,QAAA,GAGF,SACE,SAAA,SACA,IAAA,EACA,KAAA,EACA,MAAA,KACA,OAAA,KAKF,WACE,kBAAA,KADF,WACE,kBAAA,mBADF,YACE,kBAAA,oBADF,YACE,kBAAA,oBCrBJ,WACE,SAAA,MACA,IAAA,EACA,MAAA,EACA,KAAA,EACA,QAAA,KAGF,cACE,SAAA,MACA,MAAA,EACA,OAAA,EACA,KAAA,EACA,QAAA,KAQE,YACE,SAAA,eAAA,SAAA,OACA,IAAA,EACA,QAAA,K/CqCF,yB+CxCA,eACE,SAAA,eAAA,SAAA,OACA,IAAA,EACA,QAAA,M/CqCF,yB+CxCA,eACE,SAAA,eAAA,SAAA,OACA,IAAA,EACA,QAAA,M/CqCF,yB+CxCA,eACE,SAAA,eAAA,SAAA,OACA,IAAA,EACA,QAAA,M/CqCF,0B+CxCA,eACE,SAAA,eAAA,SAAA,OACA,IAAA,EACA,QAAA,M/CqCF,0B+CxCA,gBACE,SAAA,eAAA,SAAA,OACA,IAAA,EACA,QAAA,MCtBN,iBzDsmMA,0D0DlmME,SAAA,mBACA,MAAA,cACA,OAAA,cACA,QAAA,YACA,OAAA,eACA,SAAA,iBACA,KAAA,wBACA,YAAA,iBACA,OAAA,YCXA,uBACE,SAAA,SACA,IAAA,EACA,MAAA,EACA,OAAA,EACA,KAAA,EACA,QAAA,EACA,QAAA,GCRJ,eCAE,SAAA,OACA,cAAA,SACA,YAAA,OC2CI,gBAEI,eAAA,mBAFJ,WAEI,eAAA,cAFJ,cAEI,eAAA,iBAFJ,cAEI,eAAA,iBAFJ,mBAEI,eAAA,sBAFJ,gBAEI,eAAA,mBAFJ,aAEI,MAAA,eAFJ,WAEI,MAAA,gBAFJ,YAEI,MAAA,eAFJ,eAEI,SAAA,eAFJ,iBAEI,SAAA,iBAFJ,kBAEI,SAAA,kBAFJ,iBAEI,SAAA,iBAFJ,UAEI,QAAA,iBAFJ,gBAEI,QAAA,uBAFJ,SAEI,QAAA,gBAFJ,QAEI,QAAA,eAFJ,SAEI,QAAA,gBAFJ,aAEI,QAAA,oBAFJ,cAEI,QAAA,qBAFJ,QAEI,QAAA,eAFJ,eAEI,QAAA,sBAFJ,QAEI,QAAA,eAFJ,QAEI,WAAA,EAAA,MAAA,KAAA,0BAFJ,WAEI,WAAA,EAAA,QAAA,OAAA,2BAFJ,WAEI,WAAA,EAAA,KAAA,KAAA,2BAFJ,aAEI,WAAA,eAFJ,iBAEI,SAAA,iBAFJ,mBAEI,SAAA,mBAFJ,mBAEI,SAAA,mBAFJ,gBAEI,SAAA,gBAFJ,iBAEI,SAAA,yBAAA,SAAA,iBAFJ,OAEI,IAAA,YAFJ,QAEI,IAAA,cAFJ,SAEI,IAAA,eAFJ,UAEI,OAAA,YAFJ,WAEI,OAAA,cAFJ,YAEI,OAAA,eAFJ,SAEI,KAAA,YAFJ,UAEI,KAAA,cAFJ,WAEI,KAAA,eAFJ,OAEI,MAAA,YAFJ,QAEI,MAAA,cAFJ,SAEI,MAAA,eAFJ,kBAEI,UAAA,+BAFJ,oBAEI,UAAA,2BAFJ,oBAEI,UAAA,2BAFJ,QAEI,OAAA,IAAA,MAAA,kBAFJ,UAEI,OAAA,YAFJ,YAEI,WAAA,IAAA,MAAA,kBAFJ,cAEI,WAAA,YAFJ,YAEI,aAAA,IAAA,MAAA,kBAFJ,cAEI,aAAA,YAFJ,eAEI,cAAA,IAAA,MAAA,kBAFJ,iBAEI,cAAA,YAFJ,cAEI,YAAA,IAAA,MAAA,kBAFJ,gBAEI,YAAA,YAFJ,gBAEI,aAAA,kBAFJ,kBAEI,aAAA,kBAFJ,gBAEI,aAAA,kBAFJ,aAEI,aAAA,kBAFJ,gBAEI,aAAA,kBAFJ,eAEI,aAAA,kBAFJ,cAEI,aAAA,kBAFJ,aAEI,aAAA,kBAFJ,cAEI,aAAA,eAFJ,UAEI,aAAA,cAFJ,UAEI,aAAA,cAFJ,UAEI,aAAA,cAFJ,UAEI,aAAA,cAFJ,UAEI,aAAA,cAFJ,MAEI,MAAA,cAFJ,MAEI,MAAA,cAFJ,MAEI,MAAA,cAFJ,OAEI,MAAA,eAFJ,QAEI,MAAA,eAFJ,QAEI,UAAA,eAFJ,QAEI,MAAA,gBAFJ,YAEI,UAAA,gBAFJ,MAEI,OAAA,cAFJ,MAEI,OAAA,cAFJ,MAEI,OAAA,cAFJ,OAEI,OAAA,eAFJ,QAEI,OAAA,eAFJ,QAEI,WAAA,eAFJ,QAEI,OAAA,gBAFJ,YAEI,WAAA,gBAFJ,WAEI,KAAA,EAAA,EAAA,eAFJ,UAEI,eAAA,cAFJ,aAEI,eAAA,iBAFJ,kBAEI,eAAA,sBAFJ,qBAEI,eAAA,yBAFJ,aAEI,UAAA,YAFJ,aAEI,UAAA,YAFJ,eAEI,YAAA,YAFJ,eAEI,YAAA,YAFJ,WAEI,UAAA,eAFJ,aAEI,UAAA,iBAFJ,mBAEI,UAAA,uBAFJ,OAEI,IAAA,YAFJ,OAEI,IAAA,iBAFJ,OAEI,IAAA,gBAFJ,OAEI,IAAA,eAFJ,OAEI,IAAA,iBAFJ,OAEI,IAAA,eAFJ,uBAEI,gBAAA,qBAFJ,qBAEI,gBAAA,mBAFJ,wBAEI,gBAAA,iBAFJ,yBAEI,gBAAA,wBAFJ,wBAEI,gBAAA,uBAFJ,wBAEI,gBAAA,uBAFJ,mBAEI,YAAA,qBAFJ,iBAEI,YAAA,mBAFJ,oBAEI,YAAA,iBAFJ,sBAEI,YAAA,mBAFJ,qBAEI,YAAA,kBAFJ,qBAEI,cAAA,qBAFJ,mBAEI,cAAA,mBAFJ,sBAEI,cAAA,iBAFJ,uBAEI,cAAA,wBAFJ,sBAEI,cAAA,uBAFJ,uBAEI,cAAA,kBAFJ,iBAEI,WAAA,eAFJ,kBAEI,WAAA,qBAFJ,gBAEI,WAAA,mBAFJ,mBAEI,WAAA,iBAFJ,qBAEI,WAAA,mBAFJ,oBAEI,WAAA,kBAFJ,aAEI,MAAA,aAFJ,SAEI,MAAA,YAFJ,SAEI,MAAA,YAFJ,SAEI,MAAA,YAFJ,SAEI,MAAA,YAFJ,SAEI,MAAA,YAFJ,SAEI,MAAA,YAFJ,YAEI,MAAA,YAFJ,KAEI,OAAA,YAFJ,KAEI,OAAA,iBAFJ,KAEI,OAAA,gBAFJ,KAEI,OAAA,eAFJ,KAEI,OAAA,iBAFJ,KAEI,OAAA,eAFJ,QAEI,OAAA,eAFJ,MAEI,aAAA,YAAA,YAAA,YAFJ,MAEI,aAAA,iBAAA,YAAA,iBAFJ,MAEI,aAAA,gBAAA,YAAA,gBAFJ,MAEI,aAAA,eAAA,YAAA,eAFJ,MAEI,aAAA,iBAAA,YAAA,iBAFJ,MAEI,aAAA,eAAA,YAAA,eAFJ,SAEI,aAAA,eAAA,YAAA,eAFJ,MAEI,WAAA,YAAA,cAAA,YAFJ,MAEI,WAAA,iBAAA,cAAA,iBAFJ,MAEI,WAAA,gBAAA,cAAA,gBAFJ,MAEI,WAAA,eAAA,cAAA,eAFJ,MAEI,WAAA,iBAAA,cAAA,iBAFJ,MAEI,WAAA,eAAA,cAAA,eAFJ,SAEI,WAAA,eAAA,cAAA,eAFJ,MAEI,WAAA,YAFJ,MAEI,WAAA,iBAFJ,MAEI,WAAA,gBAFJ,MAEI,WAAA,eAFJ,MAEI,WAAA,iBAFJ,MAEI,WAAA,eAFJ,SAEI,WAAA,eAFJ,MAEI,aAAA,YAFJ,MAEI,aAAA,iBAFJ,MAEI,aAAA,gBAFJ,MAEI,aAAA,eAFJ,MAEI,aAAA,iBAFJ,MAEI,aAAA,eAFJ,SAEI,aAAA,eAFJ,MAEI,cAAA,YAFJ,MAEI,cAAA,iBAFJ,MAEI,cAAA,gBAFJ,MAEI,cAAA,eAFJ,MAEI,cAAA,iBAFJ,MAEI,cAAA,eAFJ,SAEI,cAAA,eAFJ,MAEI,YAAA,YAFJ,MAEI,YAAA,iBAFJ,MAEI,YAAA,gBAFJ,MAEI,YAAA,eAFJ,MAEI,YAAA,iBAFJ,MAEI,YAAA,eAFJ,SAEI,YAAA,eAFJ,KAEI,QAAA,YAFJ,KAEI,QAAA,iBAFJ,KAEI,QAAA,gBAFJ,KAEI,QAAA,eAFJ,KAEI,QAAA,iBAFJ,KAEI,QAAA,eAFJ,MAEI,cAAA,YAAA,aAAA,YAFJ,MAEI,cAAA,iBAAA,aAAA,iBAFJ,MAEI,cAAA,gBAAA,aAAA,gBAFJ,MAEI,cAAA,eAAA,aAAA,eAFJ,MAEI,cAAA,iBAAA,aAAA,iBAFJ,MAEI,cAAA,eAAA,aAAA,eAFJ,MAEI,YAAA,YAAA,eAAA,YAFJ,MAEI,YAAA,iBAAA,eAAA,iBAFJ,MAEI,YAAA,gBAAA,eAAA,gBAFJ,MAEI,YAAA,eAAA,eAAA,eAFJ,MAEI,YAAA,iBAAA,eAAA,iBAFJ,MAEI,YAAA,eAAA,eAAA,eAFJ,MAEI,YAAA,YAFJ,MAEI,YAAA,iBAFJ,MAEI,YAAA,gBAFJ,MAEI,YAAA,eAFJ,MAEI,YAAA,iBAFJ,MAEI,YAAA,eAFJ,MAEI,cAAA,YAFJ,MAEI,cAAA,iBAFJ,MAEI,cAAA,gBAFJ,MAEI,cAAA,eAFJ,MAEI,cAAA,iBAFJ,MAEI,cAAA,eAFJ,MAEI,eAAA,YAFJ,MAEI,eAAA,iBAFJ,MAEI,eAAA,gBAFJ,MAEI,eAAA,eAFJ,MAEI,eAAA,iBAFJ,MAEI,eAAA,eAFJ,MAEI,aAAA,YAFJ,MAEI,aAAA,iBAFJ,MAEI,aAAA,gBAFJ,MAEI,aAAA,eAFJ,MAEI,aAAA,iBAFJ,MAEI,aAAA,eAFJ,gBAEI,YAAA,mCAFJ,MAEI,UAAA,iCAFJ,MAEI,UAAA,gCAFJ,MAEI,UAAA,8BAFJ,MAEI,UAAA,gCAFJ,MAEI,UAAA,kBAFJ,MAEI,UAAA,eAFJ,YAEI,WAAA,iBAFJ,YAEI,WAAA,iBAFJ,UAEI,YAAA,cAFJ,YAEI,YAAA,kBAFJ,WAEI,YAAA,cAFJ,SAEI,YAAA,cAFJ,WAEI,YAAA,iBAFJ,MAEI,YAAA,YAFJ,OAEI,YAAA,eAFJ,SAEI,YAAA,cAFJ,OAEI,YAAA,YAFJ,YAEI,WAAA,eAFJ,UAEI,WAAA,gBAFJ,aAEI,WAAA,iBAFJ,sBAEI,gBAAA,eAFJ,2BAEI,gBAAA,oBAFJ,8BAEI,gBAAA,uBAFJ,gBAEI,eAAA,oBAFJ,gBAEI,eAAA,oBAFJ,iBAEI,eAAA,qBAFJ,WAEI,YAAA,iBAFJ,aAEI,YAAA,iBAFJ,YAEI,UAAA,qBAAA,WAAA,qBAFJ,cAEI,MAAA,kBAFJ,gBAEI,MAAA,kBAFJ,cAEI,MAAA,kBAFJ,WAEI,MAAA,kBAFJ,cAEI,MAAA,kBAFJ,aAEI,MAAA,kBAFJ,YAEI,MAAA,kBAFJ,WAEI,MAAA,kBAFJ,YAEI,MAAA,eAFJ,WAEI,MAAA,kBAFJ,YAEI,MAAA,kBAFJ,eAEI,MAAA,yBAFJ,eAEI,MAAA,+BAFJ,YAEI,MAAA,kBAFJ,YAEI,iBAAA,kBAFJ,cAEI,iBAAA,kBAFJ,YAEI,iBAAA,kBAFJ,SAEI,iBAAA,kBAFJ,YAEI,iBAAA,kBAFJ,WAEI,iBAAA,kBAFJ,UAEI,iBAAA,kBAFJ,SAEI,iBAAA,kBAFJ,SAEI,iBAAA,eAFJ,UAEI,iBAAA,eAFJ,gBAEI,iBAAA,sBAFJ,aAEI,iBAAA,6BAFJ,iBAEI,oBAAA,cAAA,iBAAA,cAAA,YAAA,cAFJ,kBAEI,oBAAA,eAAA,iBAAA,eAAA,YAAA,eAFJ,kBAEI,oBAAA,eAAA,iBAAA,eAAA,YAAA,eAFJ,SAEI,eAAA,eAFJ,SAEI,eAAA,eAFJ,SAEI,cAAA,iBAFJ,WAEI,cAAA,YAFJ,WAEI,cAAA,gBAFJ,WAEI,cAAA,iBAFJ,WAEI,cAAA,gBAFJ,gBAEI,cAAA,cAFJ,cAEI,cAAA,gBAFJ,aAEI,uBAAA,iBAAA,wBAAA,iBAFJ,aAEI,wBAAA,iBAAA,2BAAA,iBAFJ,gBAEI,2BAAA,iBAAA,0BAAA,iBAFJ,eAEI,0BAAA,iBAAA,uBAAA,iBAFJ,SAEI,WAAA,kBAFJ,WAEI,WAAA,iBrDYN,yBqDdE,gBAEI,MAAA,eAFJ,cAEI,MAAA,gBAFJ,eAEI,MAAA,eAFJ,aAEI,QAAA,iBAFJ,mBAEI,QAAA,uBAFJ,YAEI,QAAA,gBAFJ,WAEI,QAAA,eAFJ,YAEI,QAAA,gBAFJ,gBAEI,QAAA,oBAFJ,iBAEI,QAAA,qBAFJ,WAEI,QAAA,eAFJ,kBAEI,QAAA,sBAFJ,WAEI,QAAA,eAFJ,cAEI,KAAA,EAAA,EAAA,eAFJ,aAEI,eAAA,cAFJ,gBAEI,eAAA,iBAFJ,qBAEI,eAAA,sBAFJ,wBAEI,eAAA,yBAFJ,gBAEI,UAAA,YAFJ,gBAEI,UAAA,YAFJ,kBAEI,YAAA,YAFJ,kBAEI,YAAA,YAFJ,cAEI,UAAA,eAFJ,gBAEI,UAAA,iBAFJ,sBAEI,UAAA,uBAFJ,UAEI,IAAA,YAFJ,UAEI,IAAA,iBAFJ,UAEI,IAAA,gBAFJ,UAEI,IAAA,eAFJ,UAEI,IAAA,iBAFJ,UAEI,IAAA,eAFJ,0BAEI,gBAAA,qBAFJ,wBAEI,gBAAA,mBAFJ,2BAEI,gBAAA,iBAFJ,4BAEI,gBAAA,wBAFJ,2BAEI,gBAAA,uBAFJ,2BAEI,gBAAA,uBAFJ,sBAEI,YAAA,qBAFJ,oBAEI,YAAA,mBAFJ,uBAEI,YAAA,iBAFJ,yBAEI,YAAA,mBAFJ,wBAEI,YAAA,kBAFJ,wBAEI,cAAA,qBAFJ,sBAEI,cAAA,mBAFJ,yBAEI,cAAA,iBAFJ,0BAEI,cAAA,wBAFJ,yBAEI,cAAA,uBAFJ,0BAEI,cAAA,kBAFJ,oBAEI,WAAA,eAFJ,qBAEI,WAAA,qBAFJ,mBAEI,WAAA,mBAFJ,sBAEI,WAAA,iBAFJ,wBAEI,WAAA,mBAFJ,uBAEI,WAAA,kBAFJ,gBAEI,MAAA,aAFJ,YAEI,MAAA,YAFJ,YAEI,MAAA,YAFJ,YAEI,MAAA,YAFJ,YAEI,MAAA,YAFJ,YAEI,MAAA,YAFJ,YAEI,MAAA,YAFJ,eAEI,MAAA,YAFJ,QAEI,OAAA,YAFJ,QAEI,OAAA,iBAFJ,QAEI,OAAA,gBAFJ,QAEI,OAAA,eAFJ,QAEI,OAAA,iBAFJ,QAEI,OAAA,eAFJ,WAEI,OAAA,eAFJ,SAEI,aAAA,YAAA,YAAA,YAFJ,SAEI,aAAA,iBAAA,YAAA,iBAFJ,SAEI,aAAA,gBAAA,YAAA,gBAFJ,SAEI,aAAA,eAAA,YAAA,eAFJ,SAEI,aAAA,iBAAA,YAAA,iBAFJ,SAEI,aAAA,eAAA,YAAA,eAFJ,YAEI,aAAA,eAAA,YAAA,eAFJ,SAEI,WAAA,YAAA,cAAA,YAFJ,SAEI,WAAA,iBAAA,cAAA,iBAFJ,SAEI,WAAA,gBAAA,cAAA,gBAFJ,SAEI,WAAA,eAAA,cAAA,eAFJ,SAEI,WAAA,iBAAA,cAAA,iBAFJ,SAEI,WAAA,eAAA,cAAA,eAFJ,YAEI,WAAA,eAAA,cAAA,eAFJ,SAEI,WAAA,YAFJ,SAEI,WAAA,iBAFJ,SAEI,WAAA,gBAFJ,SAEI,WAAA,eAFJ,SAEI,WAAA,iBAFJ,SAEI,WAAA,eAFJ,YAEI,WAAA,eAFJ,SAEI,aAAA,YAFJ,SAEI,aAAA,iBAFJ,SAEI,aAAA,gBAFJ,SAEI,aAAA,eAFJ,SAEI,aAAA,iBAFJ,SAEI,aAAA,eAFJ,YAEI,aAAA,eAFJ,SAEI,cAAA,YAFJ,SAEI,cAAA,iBAFJ,SAEI,cAAA,gBAFJ,SAEI,cAAA,eAFJ,SAEI,cAAA,iBAFJ,SAEI,cAAA,eAFJ,YAEI,cAAA,eAFJ,SAEI,YAAA,YAFJ,SAEI,YAAA,iBAFJ,SAEI,YAAA,gBAFJ,SAEI,YAAA,eAFJ,SAEI,YAAA,iBAFJ,SAEI,YAAA,eAFJ,YAEI,YAAA,eAFJ,QAEI,QAAA,YAFJ,QAEI,QAAA,iBAFJ,QAEI,QAAA,gBAFJ,QAEI,QAAA,eAFJ,QAEI,QAAA,iBAFJ,QAEI,QAAA,eAFJ,SAEI,cAAA,YAAA,aAAA,YAFJ,SAEI,cAAA,iBAAA,aAAA,iBAFJ,SAEI,cAAA,gBAAA,aAAA,gBAFJ,SAEI,cAAA,eAAA,aAAA,eAFJ,SAEI,cAAA,iBAAA,aAAA,iBAFJ,SAEI,cAAA,eAAA,aAAA,eAFJ,SAEI,YAAA,YAAA,eAAA,YAFJ,SAEI,YAAA,iBAAA,eAAA,iBAFJ,SAEI,YAAA,gBAAA,eAAA,gBAFJ,SAEI,YAAA,eAAA,eAAA,eAFJ,SAEI,YAAA,iBAAA,eAAA,iBAFJ,SAEI,YAAA,eAAA,eAAA,eAFJ,SAEI,YAAA,YAFJ,SAEI,YAAA,iBAFJ,SAEI,YAAA,gBAFJ,SAEI,YAAA,eAFJ,SAEI,YAAA,iBAFJ,SAEI,YAAA,eAFJ,SAEI,cAAA,YAFJ,SAEI,cAAA,iBAFJ,SAEI,cAAA,gBAFJ,SAEI,cAAA,eAFJ,SAEI,cAAA,iBAFJ,SAEI,cAAA,eAFJ,SAEI,eAAA,YAFJ,SAEI,eAAA,iBAFJ,SAEI,eAAA,gBAFJ,SAEI,eAAA,eAFJ,SAEI,eAAA,iBAFJ,SAEI,eAAA,eAFJ,SAEI,aAAA,YAFJ,SAEI,aAAA,iBAFJ,SAEI,aAAA,gBAFJ,SAEI,aAAA,eAFJ,SAEI,aAAA,iBAFJ,SAEI,aAAA,eAFJ,eAEI,WAAA,eAFJ,aAEI,WAAA,gBAFJ,gBAEI,WAAA,kBrDYN,yBqDdE,gBAEI,MAAA,eAFJ,cAEI,MAAA,gBAFJ,eAEI,MAAA,eAFJ,aAEI,QAAA,iBAFJ,mBAEI,QAAA,uBAFJ,YAEI,QAAA,gBAFJ,WAEI,QAAA,eAFJ,YAEI,QAAA,gBAFJ,gBAEI,QAAA,oBAFJ,iBAEI,QAAA,qBAFJ,WAEI,QAAA,eAFJ,kBAEI,QAAA,sBAFJ,WAEI,QAAA,eAFJ,cAEI,KAAA,EAAA,EAAA,eAFJ,aAEI,eAAA,cAFJ,gBAEI,eAAA,iBAFJ,qBAEI,eAAA,sBAFJ,wBAEI,eAAA,yBAFJ,gBAEI,UAAA,YAFJ,gBAEI,UAAA,YAFJ,kBAEI,YAAA,YAFJ,kBAEI,YAAA,YAFJ,cAEI,UAAA,eAFJ,gBAEI,UAAA,iBAFJ,sBAEI,UAAA,uBAFJ,UAEI,IAAA,YAFJ,UAEI,IAAA,iBAFJ,UAEI,IAAA,gBAFJ,UAEI,IAAA,eAFJ,UAEI,IAAA,iBAFJ,UAEI,IAAA,eAFJ,0BAEI,gBAAA,qBAFJ,wBAEI,gBAAA,mBAFJ,2BAEI,gBAAA,iBAFJ,4BAEI,gBAAA,wBAFJ,2BAEI,gBAAA,uBAFJ,2BAEI,gBAAA,uBAFJ,sBAEI,YAAA,qBAFJ,oBAEI,YAAA,mBAFJ,uBAEI,YAAA,iBAFJ,yBAEI,YAAA,mBAFJ,wBAEI,YAAA,kBAFJ,wBAEI,cAAA,qBAFJ,sBAEI,cAAA,mBAFJ,yBAEI,cAAA,iBAFJ,0BAEI,cAAA,wBAFJ,yBAEI,cAAA,uBAFJ,0BAEI,cAAA,kBAFJ,oBAEI,WAAA,eAFJ,qBAEI,WAAA,qBAFJ,mBAEI,WAAA,mBAFJ,sBAEI,WAAA,iBAFJ,wBAEI,WAAA,mBAFJ,uBAEI,WAAA,kBAFJ,gBAEI,MAAA,aAFJ,YAEI,MAAA,YAFJ,YAEI,MAAA,YAFJ,YAEI,MAAA,YAFJ,YAEI,MAAA,YAFJ,YAEI,MAAA,YAFJ,YAEI,MAAA,YAFJ,eAEI,MAAA,YAFJ,QAEI,OAAA,YAFJ,QAEI,OAAA,iBAFJ,QAEI,OAAA,gBAFJ,QAEI,OAAA,eAFJ,QAEI,OAAA,iBAFJ,QAEI,OAAA,eAFJ,WAEI,OAAA,eAFJ,SAEI,aAAA,YAAA,YAAA,YAFJ,SAEI,aAAA,iBAAA,YAAA,iBAFJ,SAEI,aAAA,gBAAA,YAAA,gBAFJ,SAEI,aAAA,eAAA,YAAA,eAFJ,SAEI,aAAA,iBAAA,YAAA,iBAFJ,SAEI,aAAA,eAAA,YAAA,eAFJ,YAEI,aAAA,eAAA,YAAA,eAFJ,SAEI,WAAA,YAAA,cAAA,YAFJ,SAEI,WAAA,iBAAA,cAAA,iBAFJ,SAEI,WAAA,gBAAA,cAAA,gBAFJ,SAEI,WAAA,eAAA,cAAA,eAFJ,SAEI,WAAA,iBAAA,cAAA,iBAFJ,SAEI,WAAA,eAAA,cAAA,eAFJ,YAEI,WAAA,eAAA,cAAA,eAFJ,SAEI,WAAA,YAFJ,SAEI,WAAA,iBAFJ,SAEI,WAAA,gBAFJ,SAEI,WAAA,eAFJ,SAEI,WAAA,iBAFJ,SAEI,WAAA,eAFJ,YAEI,WAAA,eAFJ,SAEI,aAAA,YAFJ,SAEI,aAAA,iBAFJ,SAEI,aAAA,gBAFJ,SAEI,aAAA,eAFJ,SAEI,aAAA,iBAFJ,SAEI,aAAA,eAFJ,YAEI,aAAA,eAFJ,SAEI,cAAA,YAFJ,SAEI,cAAA,iBAFJ,SAEI,cAAA,gBAFJ,SAEI,cAAA,eAFJ,SAEI,cAAA,iBAFJ,SAEI,cAAA,eAFJ,YAEI,cAAA,eAFJ,SAEI,YAAA,YAFJ,SAEI,YAAA,iBAFJ,SAEI,YAAA,gBAFJ,SAEI,YAAA,eAFJ,SAEI,YAAA,iBAFJ,SAEI,YAAA,eAFJ,YAEI,YAAA,eAFJ,QAEI,QAAA,YAFJ,QAEI,QAAA,iBAFJ,QAEI,QAAA,gBAFJ,QAEI,QAAA,eAFJ,QAEI,QAAA,iBAFJ,QAEI,QAAA,eAFJ,SAEI,cAAA,YAAA,aAAA,YAFJ,SAEI,cAAA,iBAAA,aAAA,iBAFJ,SAEI,cAAA,gBAAA,aAAA,gBAFJ,SAEI,cAAA,eAAA,aAAA,eAFJ,SAEI,cAAA,iBAAA,aAAA,iBAFJ,SAEI,cAAA,eAAA,aAAA,eAFJ,SAEI,YAAA,YAAA,eAAA,YAFJ,SAEI,YAAA,iBAAA,eAAA,iBAFJ,SAEI,YAAA,gBAAA,eAAA,gBAFJ,SAEI,YAAA,eAAA,eAAA,eAFJ,SAEI,YAAA,iBAAA,eAAA,iBAFJ,SAEI,YAAA,eAAA,eAAA,eAFJ,SAEI,YAAA,YAFJ,SAEI,YAAA,iBAFJ,SAEI,YAAA,gBAFJ,SAEI,YAAA,eAFJ,SAEI,YAAA,iBAFJ,SAEI,YAAA,eAFJ,SAEI,cAAA,YAFJ,SAEI,cAAA,iBAFJ,SAEI,cAAA,gBAFJ,SAEI,cAAA,eAFJ,SAEI,cAAA,iBAFJ,SAEI,cAAA,eAFJ,SAEI,eAAA,YAFJ,SAEI,eAAA,iBAFJ,SAEI,eAAA,gBAFJ,SAEI,eAAA,eAFJ,SAEI,eAAA,iBAFJ,SAEI,eAAA,eAFJ,SAEI,aAAA,YAFJ,SAEI,aAAA,iBAFJ,SAEI,aAAA,gBAFJ,SAEI,aAAA,eAFJ,SAEI,aAAA,iBAFJ,SAEI,aAAA,eAFJ,eAEI,WAAA,eAFJ,aAEI,WAAA,gBAFJ,gBAEI,WAAA,kBrDYN,yBqDdE,gBAEI,MAAA,eAFJ,cAEI,MAAA,gBAFJ,eAEI,MAAA,eAFJ,aAEI,QAAA,iBAFJ,mBAEI,QAAA,uBAFJ,YAEI,QAAA,gBAFJ,WAEI,QAAA,eAFJ,YAEI,QAAA,gBAFJ,gBAEI,QAAA,oBAFJ,iBAEI,QAAA,qBAFJ,WAEI,QAAA,eAFJ,kBAEI,QAAA,sBAFJ,WAEI,QAAA,eAFJ,cAEI,KAAA,EAAA,EAAA,eAFJ,aAEI,eAAA,cAFJ,gBAEI,eAAA,iBAFJ,qBAEI,eAAA,sBAFJ,wBAEI,eAAA,yBAFJ,gBAEI,UAAA,YAFJ,gBAEI,UAAA,YAFJ,kBAEI,YAAA,YAFJ,kBAEI,YAAA,YAFJ,cAEI,UAAA,eAFJ,gBAEI,UAAA,iBAFJ,sBAEI,UAAA,uBAFJ,UAEI,IAAA,YAFJ,UAEI,IAAA,iBAFJ,UAEI,IAAA,gBAFJ,UAEI,IAAA,eAFJ,UAEI,IAAA,iBAFJ,UAEI,IAAA,eAFJ,0BAEI,gBAAA,qBAFJ,wBAEI,gBAAA,mBAFJ,2BAEI,gBAAA,iBAFJ,4BAEI,gBAAA,wBAFJ,2BAEI,gBAAA,uBAFJ,2BAEI,gBAAA,uBAFJ,sBAEI,YAAA,qBAFJ,oBAEI,YAAA,mBAFJ,uBAEI,YAAA,iBAFJ,yBAEI,YAAA,mBAFJ,wBAEI,YAAA,kBAFJ,wBAEI,cAAA,qBAFJ,sBAEI,cAAA,mBAFJ,yBAEI,cAAA,iBAFJ,0BAEI,cAAA,wBAFJ,yBAEI,cAAA,uBAFJ,0BAEI,cAAA,kBAFJ,oBAEI,WAAA,eAFJ,qBAEI,WAAA,qBAFJ,mBAEI,WAAA,mBAFJ,sBAEI,WAAA,iBAFJ,wBAEI,WAAA,mBAFJ,uBAEI,WAAA,kBAFJ,gBAEI,MAAA,aAFJ,YAEI,MAAA,YAFJ,YAEI,MAAA,YAFJ,YAEI,MAAA,YAFJ,YAEI,MAAA,YAFJ,YAEI,MAAA,YAFJ,YAEI,MAAA,YAFJ,eAEI,MAAA,YAFJ,QAEI,OAAA,YAFJ,QAEI,OAAA,iBAFJ,QAEI,OAAA,gBAFJ,QAEI,OAAA,eAFJ,QAEI,OAAA,iBAFJ,QAEI,OAAA,eAFJ,WAEI,OAAA,eAFJ,SAEI,aAAA,YAAA,YAAA,YAFJ,SAEI,aAAA,iBAAA,YAAA,iBAFJ,SAEI,aAAA,gBAAA,YAAA,gBAFJ,SAEI,aAAA,eAAA,YAAA,eAFJ,SAEI,aAAA,iBAAA,YAAA,iBAFJ,SAEI,aAAA,eAAA,YAAA,eAFJ,YAEI,aAAA,eAAA,YAAA,eAFJ,SAEI,WAAA,YAAA,cAAA,YAFJ,SAEI,WAAA,iBAAA,cAAA,iBAFJ,SAEI,WAAA,gBAAA,cAAA,gBAFJ,SAEI,WAAA,eAAA,cAAA,eAFJ,SAEI,WAAA,iBAAA,cAAA,iBAFJ,SAEI,WAAA,eAAA,cAAA,eAFJ,YAEI,WAAA,eAAA,cAAA,eAFJ,SAEI,WAAA,YAFJ,SAEI,WAAA,iBAFJ,SAEI,WAAA,gBAFJ,SAEI,WAAA,eAFJ,SAEI,WAAA,iBAFJ,SAEI,WAAA,eAFJ,YAEI,WAAA,eAFJ,SAEI,aAAA,YAFJ,SAEI,aAAA,iBAFJ,SAEI,aAAA,gBAFJ,SAEI,aAAA,eAFJ,SAEI,aAAA,iBAFJ,SAEI,aAAA,eAFJ,YAEI,aAAA,eAFJ,SAEI,cAAA,YAFJ,SAEI,cAAA,iBAFJ,SAEI,cAAA,gBAFJ,SAEI,cAAA,eAFJ,SAEI,cAAA,iBAFJ,SAEI,cAAA,eAFJ,YAEI,cAAA,eAFJ,SAEI,YAAA,YAFJ,SAEI,YAAA,iBAFJ,SAEI,YAAA,gBAFJ,SAEI,YAAA,eAFJ,SAEI,YAAA,iBAFJ,SAEI,YAAA,eAFJ,YAEI,YAAA,eAFJ,QAEI,QAAA,YAFJ,QAEI,QAAA,iBAFJ,QAEI,QAAA,gBAFJ,QAEI,QAAA,eAFJ,QAEI,QAAA,iBAFJ,QAEI,QAAA,eAFJ,SAEI,cAAA,YAAA,aAAA,YAFJ,SAEI,cAAA,iBAAA,aAAA,iBAFJ,SAEI,cAAA,gBAAA,aAAA,gBAFJ,SAEI,cAAA,eAAA,aAAA,eAFJ,SAEI,cAAA,iBAAA,aAAA,iBAFJ,SAEI,cAAA,eAAA,aAAA,eAFJ,SAEI,YAAA,YAAA,eAAA,YAFJ,SAEI,YAAA,iBAAA,eAAA,iBAFJ,SAEI,YAAA,gBAAA,eAAA,gBAFJ,SAEI,YAAA,eAAA,eAAA,eAFJ,SAEI,YAAA,iBAAA,eAAA,iBAFJ,SAEI,YAAA,eAAA,eAAA,eAFJ,SAEI,YAAA,YAFJ,SAEI,YAAA,iBAFJ,SAEI,YAAA,gBAFJ,SAEI,YAAA,eAFJ,SAEI,YAAA,iBAFJ,SAEI,YAAA,eAFJ,SAEI,cAAA,YAFJ,SAEI,cAAA,iBAFJ,SAEI,cAAA,gBAFJ,SAEI,cAAA,eAFJ,SAEI,cAAA,iBAFJ,SAEI,cAAA,eAFJ,SAEI,eAAA,YAFJ,SAEI,eAAA,iBAFJ,SAEI,eAAA,gBAFJ,SAEI,eAAA,eAFJ,SAEI,eAAA,iBAFJ,SAEI,eAAA,eAFJ,SAEI,aAAA,YAFJ,SAEI,aAAA,iBAFJ,SAEI,aAAA,gBAFJ,SAEI,aAAA,eAFJ,SAEI,aAAA,iBAFJ,SAEI,aAAA,eAFJ,eAEI,WAAA,eAFJ,aAEI,WAAA,gBAFJ,gBAEI,WAAA,kBrDYN,0BqDdE,gBAEI,MAAA,eAFJ,cAEI,MAAA,gBAFJ,eAEI,MAAA,eAFJ,aAEI,QAAA,iBAFJ,mBAEI,QAAA,uBAFJ,YAEI,QAAA,gBAFJ,WAEI,QAAA,eAFJ,YAEI,QAAA,gBAFJ,gBAEI,QAAA,oBAFJ,iBAEI,QAAA,qBAFJ,WAEI,QAAA,eAFJ,kBAEI,QAAA,sBAFJ,WAEI,QAAA,eAFJ,cAEI,KAAA,EAAA,EAAA,eAFJ,aAEI,eAAA,cAFJ,gBAEI,eAAA,iBAFJ,qBAEI,eAAA,sBAFJ,wBAEI,eAAA,yBAFJ,gBAEI,UAAA,YAFJ,gBAEI,UAAA,YAFJ,kBAEI,YAAA,YAFJ,kBAEI,YAAA,YAFJ,cAEI,UAAA,eAFJ,gBAEI,UAAA,iBAFJ,sBAEI,UAAA,uBAFJ,UAEI,IAAA,YAFJ,UAEI,IAAA,iBAFJ,UAEI,IAAA,gBAFJ,UAEI,IAAA,eAFJ,UAEI,IAAA,iBAFJ,UAEI,IAAA,eAFJ,0BAEI,gBAAA,qBAFJ,wBAEI,gBAAA,mBAFJ,2BAEI,gBAAA,iBAFJ,4BAEI,gBAAA,wBAFJ,2BAEI,gBAAA,uBAFJ,2BAEI,gBAAA,uBAFJ,sBAEI,YAAA,qBAFJ,oBAEI,YAAA,mBAFJ,uBAEI,YAAA,iBAFJ,yBAEI,YAAA,mBAFJ,wBAEI,YAAA,kBAFJ,wBAEI,cAAA,qBAFJ,sBAEI,cAAA,mBAFJ,yBAEI,cAAA,iBAFJ,0BAEI,cAAA,wBAFJ,yBAEI,cAAA,uBAFJ,0BAEI,cAAA,kBAFJ,oBAEI,WAAA,eAFJ,qBAEI,WAAA,qBAFJ,mBAEI,WAAA,mBAFJ,sBAEI,WAAA,iBAFJ,wBAEI,WAAA,mBAFJ,uBAEI,WAAA,kBAFJ,gBAEI,MAAA,aAFJ,YAEI,MAAA,YAFJ,YAEI,MAAA,YAFJ,YAEI,MAAA,YAFJ,YAEI,MAAA,YAFJ,YAEI,MAAA,YAFJ,YAEI,MAAA,YAFJ,eAEI,MAAA,YAFJ,QAEI,OAAA,YAFJ,QAEI,OAAA,iBAFJ,QAEI,OAAA,gBAFJ,QAEI,OAAA,eAFJ,QAEI,OAAA,iBAFJ,QAEI,OAAA,eAFJ,WAEI,OAAA,eAFJ,SAEI,aAAA,YAAA,YAAA,YAFJ,SAEI,aAAA,iBAAA,YAAA,iBAFJ,SAEI,aAAA,gBAAA,YAAA,gBAFJ,SAEI,aAAA,eAAA,YAAA,eAFJ,SAEI,aAAA,iBAAA,YAAA,iBAFJ,SAEI,aAAA,eAAA,YAAA,eAFJ,YAEI,aAAA,eAAA,YAAA,eAFJ,SAEI,WAAA,YAAA,cAAA,YAFJ,SAEI,WAAA,iBAAA,cAAA,iBAFJ,SAEI,WAAA,gBAAA,cAAA,gBAFJ,SAEI,WAAA,eAAA,cAAA,eAFJ,SAEI,WAAA,iBAAA,cAAA,iBAFJ,SAEI,WAAA,eAAA,cAAA,eAFJ,YAEI,WAAA,eAAA,cAAA,eAFJ,SAEI,WAAA,YAFJ,SAEI,WAAA,iBAFJ,SAEI,WAAA,gBAFJ,SAEI,WAAA,eAFJ,SAEI,WAAA,iBAFJ,SAEI,WAAA,eAFJ,YAEI,WAAA,eAFJ,SAEI,aAAA,YAFJ,SAEI,aAAA,iBAFJ,SAEI,aAAA,gBAFJ,SAEI,aAAA,eAFJ,SAEI,aAAA,iBAFJ,SAEI,aAAA,eAFJ,YAEI,aAAA,eAFJ,SAEI,cAAA,YAFJ,SAEI,cAAA,iBAFJ,SAEI,cAAA,gBAFJ,SAEI,cAAA,eAFJ,SAEI,cAAA,iBAFJ,SAEI,cAAA,eAFJ,YAEI,cAAA,eAFJ,SAEI,YAAA,YAFJ,SAEI,YAAA,iBAFJ,SAEI,YAAA,gBAFJ,SAEI,YAAA,eAFJ,SAEI,YAAA,iBAFJ,SAEI,YAAA,eAFJ,YAEI,YAAA,eAFJ,QAEI,QAAA,YAFJ,QAEI,QAAA,iBAFJ,QAEI,QAAA,gBAFJ,QAEI,QAAA,eAFJ,QAEI,QAAA,iBAFJ,QAEI,QAAA,eAFJ,SAEI,cAAA,YAAA,aAAA,YAFJ,SAEI,cAAA,iBAAA,aAAA,iBAFJ,SAEI,cAAA,gBAAA,aAAA,gBAFJ,SAEI,cAAA,eAAA,aAAA,eAFJ,SAEI,cAAA,iBAAA,aAAA,iBAFJ,SAEI,cAAA,eAAA,aAAA,eAFJ,SAEI,YAAA,YAAA,eAAA,YAFJ,SAEI,YAAA,iBAAA,eAAA,iBAFJ,SAEI,YAAA,gBAAA,eAAA,gBAFJ,SAEI,YAAA,eAAA,eAAA,eAFJ,SAEI,YAAA,iBAAA,eAAA,iBAFJ,SAEI,YAAA,eAAA,eAAA,eAFJ,SAEI,YAAA,YAFJ,SAEI,YAAA,iBAFJ,SAEI,YAAA,gBAFJ,SAEI,YAAA,eAFJ,SAEI,YAAA,iBAFJ,SAEI,YAAA,eAFJ,SAEI,cAAA,YAFJ,SAEI,cAAA,iBAFJ,SAEI,cAAA,gBAFJ,SAEI,cAAA,eAFJ,SAEI,cAAA,iBAFJ,SAEI,cAAA,eAFJ,SAEI,eAAA,YAFJ,SAEI,eAAA,iBAFJ,SAEI,eAAA,gBAFJ,SAEI,eAAA,eAFJ,SAEI,eAAA,iBAFJ,SAEI,eAAA,eAFJ,SAEI,aAAA,YAFJ,SAEI,aAAA,iBAFJ,SAEI,aAAA,gBAFJ,SAEI,aAAA,eAFJ,SAEI,aAAA,iBAFJ,SAEI,aAAA,eAFJ,eAEI,WAAA,eAFJ,aAEI,WAAA,gBAFJ,gBAEI,WAAA,kBrDYN,0BqDdE,iBAEI,MAAA,eAFJ,eAEI,MAAA,gBAFJ,gBAEI,MAAA,eAFJ,cAEI,QAAA,iBAFJ,oBAEI,QAAA,uBAFJ,aAEI,QAAA,gBAFJ,YAEI,QAAA,eAFJ,aAEI,QAAA,gBAFJ,iBAEI,QAAA,oBAFJ,kBAEI,QAAA,qBAFJ,YAEI,QAAA,eAFJ,mBAEI,QAAA,sBAFJ,YAEI,QAAA,eAFJ,eAEI,KAAA,EAAA,EAAA,eAFJ,cAEI,eAAA,cAFJ,iBAEI,eAAA,iBAFJ,sBAEI,eAAA,sBAFJ,yBAEI,eAAA,yBAFJ,iBAEI,UAAA,YAFJ,iBAEI,UAAA,YAFJ,mBAEI,YAAA,YAFJ,mBAEI,YAAA,YAFJ,eAEI,UAAA,eAFJ,iBAEI,UAAA,iBAFJ,uBAEI,UAAA,uBAFJ,WAEI,IAAA,YAFJ,WAEI,IAAA,iBAFJ,WAEI,IAAA,gBAFJ,WAEI,IAAA,eAFJ,WAEI,IAAA,iBAFJ,WAEI,IAAA,eAFJ,2BAEI,gBAAA,qBAFJ,yBAEI,gBAAA,mBAFJ,4BAEI,gBAAA,iBAFJ,6BAEI,gBAAA,wBAFJ,4BAEI,gBAAA,uBAFJ,4BAEI,gBAAA,uBAFJ,uBAEI,YAAA,qBAFJ,qBAEI,YAAA,mBAFJ,wBAEI,YAAA,iBAFJ,0BAEI,YAAA,mBAFJ,yBAEI,YAAA,kBAFJ,yBAEI,cAAA,qBAFJ,uBAEI,cAAA,mBAFJ,0BAEI,cAAA,iBAFJ,2BAEI,cAAA,wBAFJ,0BAEI,cAAA,uBAFJ,2BAEI,cAAA,kBAFJ,qBAEI,WAAA,eAFJ,sBAEI,WAAA,qBAFJ,oBAEI,WAAA,mBAFJ,uBAEI,WAAA,iBAFJ,yBAEI,WAAA,mBAFJ,wBAEI,WAAA,kBAFJ,iBAEI,MAAA,aAFJ,aAEI,MAAA,YAFJ,aAEI,MAAA,YAFJ,aAEI,MAAA,YAFJ,aAEI,MAAA,YAFJ,aAEI,MAAA,YAFJ,aAEI,MAAA,YAFJ,gBAEI,MAAA,YAFJ,SAEI,OAAA,YAFJ,SAEI,OAAA,iBAFJ,SAEI,OAAA,gBAFJ,SAEI,OAAA,eAFJ,SAEI,OAAA,iBAFJ,SAEI,OAAA,eAFJ,YAEI,OAAA,eAFJ,UAEI,aAAA,YAAA,YAAA,YAFJ,UAEI,aAAA,iBAAA,YAAA,iBAFJ,UAEI,aAAA,gBAAA,YAAA,gBAFJ,UAEI,aAAA,eAAA,YAAA,eAFJ,UAEI,aAAA,iBAAA,YAAA,iBAFJ,UAEI,aAAA,eAAA,YAAA,eAFJ,aAEI,aAAA,eAAA,YAAA,eAFJ,UAEI,WAAA,YAAA,cAAA,YAFJ,UAEI,WAAA,iBAAA,cAAA,iBAFJ,UAEI,WAAA,gBAAA,cAAA,gBAFJ,UAEI,WAAA,eAAA,cAAA,eAFJ,UAEI,WAAA,iBAAA,cAAA,iBAFJ,UAEI,WAAA,eAAA,cAAA,eAFJ,aAEI,WAAA,eAAA,cAAA,eAFJ,UAEI,WAAA,YAFJ,UAEI,WAAA,iBAFJ,UAEI,WAAA,gBAFJ,UAEI,WAAA,eAFJ,UAEI,WAAA,iBAFJ,UAEI,WAAA,eAFJ,aAEI,WAAA,eAFJ,UAEI,aAAA,YAFJ,UAEI,aAAA,iBAFJ,UAEI,aAAA,gBAFJ,UAEI,aAAA,eAFJ,UAEI,aAAA,iBAFJ,UAEI,aAAA,eAFJ,aAEI,aAAA,eAFJ,UAEI,cAAA,YAFJ,UAEI,cAAA,iBAFJ,UAEI,cAAA,gBAFJ,UAEI,cAAA,eAFJ,UAEI,cAAA,iBAFJ,UAEI,cAAA,eAFJ,aAEI,cAAA,eAFJ,UAEI,YAAA,YAFJ,UAEI,YAAA,iBAFJ,UAEI,YAAA,gBAFJ,UAEI,YAAA,eAFJ,UAEI,YAAA,iBAFJ,UAEI,YAAA,eAFJ,aAEI,YAAA,eAFJ,SAEI,QAAA,YAFJ,SAEI,QAAA,iBAFJ,SAEI,QAAA,gBAFJ,SAEI,QAAA,eAFJ,SAEI,QAAA,iBAFJ,SAEI,QAAA,eAFJ,UAEI,cAAA,YAAA,aAAA,YAFJ,UAEI,cAAA,iBAAA,aAAA,iBAFJ,UAEI,cAAA,gBAAA,aAAA,gBAFJ,UAEI,cAAA,eAAA,aAAA,eAFJ,UAEI,cAAA,iBAAA,aAAA,iBAFJ,UAEI,cAAA,eAAA,aAAA,eAFJ,UAEI,YAAA,YAAA,eAAA,YAFJ,UAEI,YAAA,iBAAA,eAAA,iBAFJ,UAEI,YAAA,gBAAA,eAAA,gBAFJ,UAEI,YAAA,eAAA,eAAA,eAFJ,UAEI,YAAA,iBAAA,eAAA,iBAFJ,UAEI,YAAA,eAAA,eAAA,eAFJ,UAEI,YAAA,YAFJ,UAEI,YAAA,iBAFJ,UAEI,YAAA,gBAFJ,UAEI,YAAA,eAFJ,UAEI,YAAA,iBAFJ,UAEI,YAAA,eAFJ,UAEI,cAAA,YAFJ,UAEI,cAAA,iBAFJ,UAEI,cAAA,gBAFJ,UAEI,cAAA,eAFJ,UAEI,cAAA,iBAFJ,UAEI,cAAA,eAFJ,UAEI,eAAA,YAFJ,UAEI,eAAA,iBAFJ,UAEI,eAAA,gBAFJ,UAEI,eAAA,eAFJ,UAEI,eAAA,iBAFJ,UAEI,eAAA,eAFJ,UAEI,aAAA,YAFJ,UAEI,aAAA,iBAFJ,UAEI,aAAA,gBAFJ,UAEI,aAAA,eAFJ,UAEI,aAAA,iBAFJ,UAEI,aAAA,eAFJ,gBAEI,WAAA,eAFJ,cAEI,WAAA,gBAFJ,iBAEI,WAAA,kBChCV,0BD8BM,MAEI,UAAA,iBAFJ,MAEI,UAAA,eAFJ,MAEI,UAAA,kBAFJ,MAEI,UAAA,kBCbV,aDWM,gBAEI,QAAA,iBAFJ,sBAEI,QAAA,uBAFJ,eAEI,QAAA,gBAFJ,cAEI,QAAA,eAFJ,eAEI,QAAA,gBAFJ,mBAEI,QAAA,oBAFJ,oBAEI,QAAA,qBAFJ,cAEI,QAAA,eAFJ,qBAEI,QAAA,sBAFJ,cAEI,QAAA","sourcesContent":["/*!\n * Bootstrap v5.0.2 (https://getbootstrap.com/)\n * Copyright 2011-2021 The Bootstrap Authors\n * Copyright 2011-2021 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n */\n\n// scss-docs-start import-stack\n// Configuration\n@import \"functions\";\n@import \"variables\";\n@import \"mixins\";\n@import \"utilities\";\n\n// Layout & components\n@import \"root\";\n@import \"reboot\";\n@import \"type\";\n@import \"images\";\n@import \"containers\";\n@import \"grid\";\n@import \"tables\";\n@import \"forms\";\n@import \"buttons\";\n@import \"transitions\";\n@import \"dropdown\";\n@import \"button-group\";\n@import \"nav\";\n@import \"navbar\";\n@import \"card\";\n@import \"accordion\";\n@import \"breadcrumb\";\n@import \"pagination\";\n@import \"badge\";\n@import \"alert\";\n@import \"progress\";\n@import \"list-group\";\n@import \"close\";\n@import \"toasts\";\n@import \"modal\";\n@import \"tooltip\";\n@import \"popover\";\n@import \"carousel\";\n@import \"spinners\";\n@import \"offcanvas\";\n\n// Helpers\n@import \"helpers\";\n\n// Utilities\n@import \"utilities/api\";\n// scss-docs-end import-stack\n",":root {\n // Custom variable values only support SassScript inside `#{}`.\n @each $color, $value in $colors {\n --#{$variable-prefix}#{$color}: #{$value};\n }\n\n @each $color, $value in $theme-colors {\n --#{$variable-prefix}#{$color}: #{$value};\n }\n\n // Use `inspect` for lists so that quoted items keep the quotes.\n // See https://github.com/sass/sass/issues/2383#issuecomment-336349172\n --#{$variable-prefix}font-sans-serif: #{inspect($font-family-sans-serif)};\n --#{$variable-prefix}font-monospace: #{inspect($font-family-monospace)};\n --#{$variable-prefix}gradient: #{$gradient};\n}\n","// stylelint-disable declaration-no-important, selector-no-qualifying-type, property-no-vendor-prefix\n\n\n// Reboot\n//\n// Normalization of HTML elements, manually forked from Normalize.css to remove\n// styles targeting irrelevant browsers while applying new styles.\n//\n// Normalize is licensed MIT. https://github.com/necolas/normalize.css\n\n\n// Document\n//\n// Change from `box-sizing: content-box` so that `width` is not affected by `padding` or `border`.\n\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\n\n// Root\n//\n// Ability to the value of the root font sizes, affecting the value of `rem`.\n// null by default, thus nothing is generated.\n\n:root {\n font-size: $font-size-root;\n\n @if $enable-smooth-scroll {\n @media (prefers-reduced-motion: no-preference) {\n scroll-behavior: smooth;\n }\n }\n}\n\n\n// Body\n//\n// 1. Remove the margin in all browsers.\n// 2. As a best practice, apply a default `background-color`.\n// 3. Prevent adjustments of font size after orientation changes in iOS.\n// 4. Change the default tap highlight to be completely transparent in iOS.\n\nbody {\n margin: 0; // 1\n font-family: $font-family-base;\n @include font-size($font-size-base);\n font-weight: $font-weight-base;\n line-height: $line-height-base;\n color: $body-color;\n text-align: $body-text-align;\n background-color: $body-bg; // 2\n -webkit-text-size-adjust: 100%; // 3\n -webkit-tap-highlight-color: rgba($black, 0); // 4\n}\n\n\n// Content grouping\n//\n// 1. Reset Firefox's gray color\n// 2. Set correct height and prevent the `size` attribute to make the `hr` look like an input field\n\nhr {\n margin: $hr-margin-y 0;\n color: $hr-color; // 1\n background-color: currentColor;\n border: 0;\n opacity: $hr-opacity;\n}\n\nhr:not([size]) {\n height: $hr-height; // 2\n}\n\n\n// Typography\n//\n// 1. Remove top margins from headings\n// By default, `

`-`

` all receive top and bottom margins. We nuke the top\n// margin for easier control within type scales as it avoids margin collapsing.\n\n%heading {\n margin-top: 0; // 1\n margin-bottom: $headings-margin-bottom;\n font-family: $headings-font-family;\n font-style: $headings-font-style;\n font-weight: $headings-font-weight;\n line-height: $headings-line-height;\n color: $headings-color;\n}\n\nh1 {\n @extend %heading;\n @include font-size($h1-font-size);\n}\n\nh2 {\n @extend %heading;\n @include font-size($h2-font-size);\n}\n\nh3 {\n @extend %heading;\n @include font-size($h3-font-size);\n}\n\nh4 {\n @extend %heading;\n @include font-size($h4-font-size);\n}\n\nh5 {\n @extend %heading;\n @include font-size($h5-font-size);\n}\n\nh6 {\n @extend %heading;\n @include font-size($h6-font-size);\n}\n\n\n// Reset margins on paragraphs\n//\n// Similarly, the top margin on `

`s get reset. However, we also reset the\n// bottom margin to use `rem` units instead of `em`.\n\np {\n margin-top: 0;\n margin-bottom: $paragraph-margin-bottom;\n}\n\n\n// Abbreviations\n//\n// 1. Duplicate behavior to the data-bs-* attribute for our tooltip plugin\n// 2. Add the correct text decoration in Chrome, Edge, Opera, and Safari.\n// 3. Add explicit cursor to indicate changed behavior.\n// 4. Prevent the text-decoration to be skipped.\n\nabbr[title],\nabbr[data-bs-original-title] { // 1\n text-decoration: underline dotted; // 2\n cursor: help; // 3\n text-decoration-skip-ink: none; // 4\n}\n\n\n// Address\n\naddress {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit;\n}\n\n\n// Lists\n\nol,\nul {\n padding-left: 2rem;\n}\n\nol,\nul,\ndl {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n margin-bottom: 0;\n}\n\ndt {\n font-weight: $dt-font-weight;\n}\n\n// 1. Undo browser default\n\ndd {\n margin-bottom: .5rem;\n margin-left: 0; // 1\n}\n\n\n// Blockquote\n\nblockquote {\n margin: 0 0 1rem;\n}\n\n\n// Strong\n//\n// Add the correct font weight in Chrome, Edge, and Safari\n\nb,\nstrong {\n font-weight: $font-weight-bolder;\n}\n\n\n// Small\n//\n// Add the correct font size in all browsers\n\nsmall {\n @include font-size($small-font-size);\n}\n\n\n// Mark\n\nmark {\n padding: $mark-padding;\n background-color: $mark-bg;\n}\n\n\n// Sub and Sup\n//\n// Prevent `sub` and `sup` elements from affecting the line height in\n// all browsers.\n\nsub,\nsup {\n position: relative;\n @include font-size($sub-sup-font-size);\n line-height: 0;\n vertical-align: baseline;\n}\n\nsub { bottom: -.25em; }\nsup { top: -.5em; }\n\n\n// Links\n\na {\n color: $link-color;\n text-decoration: $link-decoration;\n\n &:hover {\n color: $link-hover-color;\n text-decoration: $link-hover-decoration;\n }\n}\n\n// And undo these styles for placeholder links/named anchors (without href).\n// It would be more straightforward to just use a[href] in previous block, but that\n// causes specificity issues in many other styles that are too complex to fix.\n// See https://github.com/twbs/bootstrap/issues/19402\n\na:not([href]):not([class]) {\n &,\n &:hover {\n color: inherit;\n text-decoration: none;\n }\n}\n\n\n// Code\n\npre,\ncode,\nkbd,\nsamp {\n font-family: $font-family-code;\n @include font-size(1em); // Correct the odd `em` font sizing in all browsers.\n direction: ltr #{\"/* rtl:ignore */\"};\n unicode-bidi: bidi-override;\n}\n\n// 1. Remove browser default top margin\n// 2. Reset browser default of `1em` to use `rem`s\n// 3. Don't allow content to break outside\n\npre {\n display: block;\n margin-top: 0; // 1\n margin-bottom: 1rem; // 2\n overflow: auto; // 3\n @include font-size($code-font-size);\n color: $pre-color;\n\n // Account for some code outputs that place code tags in pre tags\n code {\n @include font-size(inherit);\n color: inherit;\n word-break: normal;\n }\n}\n\ncode {\n @include font-size($code-font-size);\n color: $code-color;\n word-wrap: break-word;\n\n // Streamline the style when inside anchors to avoid broken underline and more\n a > & {\n color: inherit;\n }\n}\n\nkbd {\n padding: $kbd-padding-y $kbd-padding-x;\n @include font-size($kbd-font-size);\n color: $kbd-color;\n background-color: $kbd-bg;\n @include border-radius($border-radius-sm);\n\n kbd {\n padding: 0;\n @include font-size(1em);\n font-weight: $nested-kbd-font-weight;\n }\n}\n\n\n// Figures\n//\n// Apply a consistent margin strategy (matches our type styles).\n\nfigure {\n margin: 0 0 1rem;\n}\n\n\n// Images and content\n\nimg,\nsvg {\n vertical-align: middle;\n}\n\n\n// Tables\n//\n// Prevent double borders\n\ntable {\n caption-side: bottom;\n border-collapse: collapse;\n}\n\ncaption {\n padding-top: $table-cell-padding-y;\n padding-bottom: $table-cell-padding-y;\n color: $table-caption-color;\n text-align: left;\n}\n\n// 1. Removes font-weight bold by inheriting\n// 2. Matches default `` alignment by inheriting `text-align`.\n// 3. Fix alignment for Safari\n\nth {\n font-weight: $table-th-font-weight; // 1\n text-align: inherit; // 2\n text-align: -webkit-match-parent; // 3\n}\n\nthead,\ntbody,\ntfoot,\ntr,\ntd,\nth {\n border-color: inherit;\n border-style: solid;\n border-width: 0;\n}\n\n\n// Forms\n//\n// 1. Allow labels to use `margin` for spacing.\n\nlabel {\n display: inline-block; // 1\n}\n\n// Remove the default `border-radius` that macOS Chrome adds.\n// See https://github.com/twbs/bootstrap/issues/24093\n\nbutton {\n // stylelint-disable-next-line property-disallowed-list\n border-radius: 0;\n}\n\n// Explicitly remove focus outline in Chromium when it shouldn't be\n// visible (e.g. as result of mouse click or touch tap). It already\n// should be doing this automatically, but seems to currently be\n// confused and applies its very visible two-tone outline anyway.\n\nbutton:focus:not(:focus-visible) {\n outline: 0;\n}\n\n// 1. Remove the margin in Firefox and Safari\n\ninput,\nbutton,\nselect,\noptgroup,\ntextarea {\n margin: 0; // 1\n font-family: inherit;\n @include font-size(inherit);\n line-height: inherit;\n}\n\n// Remove the inheritance of text transform in Firefox\nbutton,\nselect {\n text-transform: none;\n}\n// Set the cursor for non-`