From f5c885cbda8ffd14ffcf1ab258dbba09dde3e2a4 Mon Sep 17 00:00:00 2001 From: Luis Rodriguez Date: Wed, 8 Apr 2026 13:02:57 +0200 Subject: [PATCH 1/8] [ADD] website_altcha: Add module --- website_altcha/README.rst | 83 + website_altcha/__init__.py | 10 + website_altcha/__manifest__.py | 28 + website_altcha/controllers/__init__.py | 1 + website_altcha/controllers/altcha.py | 29 + website_altcha/models/__init__.py | 2 + website_altcha/models/altcha_key.py | 24 + website_altcha/models/ir_http.py | 81 + website_altcha/pyproject.toml | 3 + website_altcha/readme/DESCRIPTION.md | 12 + website_altcha/static/description/index.html | 427 +++ website_altcha/static/lib/altcha-l10n.js | 1155 ++++++ website_altcha/static/lib/altcha.js | 3106 +++++++++++++++++ .../static/src/altcha/altcha.esm.js | 53 + website_altcha/static/src/signup/altcha.scss | 4 + website_altcha/static/src/signup/altcha.xml | 19 + .../static/src/signup/signup.esm.js | 66 + 17 files changed, 5103 insertions(+) create mode 100644 website_altcha/README.rst create mode 100644 website_altcha/__init__.py create mode 100644 website_altcha/__manifest__.py create mode 100644 website_altcha/controllers/__init__.py create mode 100644 website_altcha/controllers/altcha.py create mode 100644 website_altcha/models/__init__.py create mode 100644 website_altcha/models/altcha_key.py create mode 100644 website_altcha/models/ir_http.py create mode 100644 website_altcha/pyproject.toml create mode 100644 website_altcha/readme/DESCRIPTION.md create mode 100644 website_altcha/static/description/index.html create mode 100644 website_altcha/static/lib/altcha-l10n.js create mode 100644 website_altcha/static/lib/altcha.js create mode 100644 website_altcha/static/src/altcha/altcha.esm.js create mode 100644 website_altcha/static/src/signup/altcha.scss create mode 100644 website_altcha/static/src/signup/altcha.xml create mode 100644 website_altcha/static/src/signup/signup.esm.js diff --git a/website_altcha/README.rst b/website_altcha/README.rst new file mode 100644 index 0000000000..1b8bca2506 --- /dev/null +++ b/website_altcha/README.rst @@ -0,0 +1,83 @@ +======================== +Website Friendly Captcha +======================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:ad4756a7f15fb03bdbfe14d8f738109df9bc20d0af3d9c500b00fa14eb8aa46b + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fwebsite-lightgray.png?logo=github + :target: https://github.com/OCA/website/tree/18.0/website_altcha + :alt: OCA/website +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/website-18-0/website-18-0-website_altcha + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/website&target_branch=18.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +[ This file is not always required; it should explain **how to configure +the module before using it**; it is aimed at users with administration +privileges. + +Please be detailed on the path to configuration (eg: do you need to +activate developer mode?), describe step by step configurations and the +use of screenshots is strongly recommended.] + +To configure this module, you need to: + +- Go to *App* > Menu > Menu item +- Activate boolean… > save +- … + +**Table of contents** + +.. contents:: + :local: + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +------- + +* Dixmit + +Maintainers +----------- + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +This module is part of the `OCA/website `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/website_altcha/__init__.py b/website_altcha/__init__.py new file mode 100644 index 0000000000..61aa1f0e5e --- /dev/null +++ b/website_altcha/__init__.py @@ -0,0 +1,10 @@ +from . import controllers +from . import models +import uuid + + +def post_init_hook(env): + """Ensure that the altcha.key parameter exists in the ir_config_parameter table.""" + param_obj = env["ir.config_parameter"].sudo() + if not param_obj.get_param("altcha.key"): + param_obj.set_param("altcha.key", str(uuid.uuid1())) diff --git a/website_altcha/__manifest__.py b/website_altcha/__manifest__.py new file mode 100644 index 0000000000..0525fe10b1 --- /dev/null +++ b/website_altcha/__manifest__.py @@ -0,0 +1,28 @@ +# Copyright 2025 Dixmit +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +{ + "name": "Website Friendly Captcha", + "summary": """Use Friendly Captcha for verifying users""", + "version": "18.0.1.0.0", + "license": "AGPL-3", + "author": "Dixmit,Odoo Community Association (OCA)", + "website": "https://github.com/OCA/website", + "depends": [ + "website", + ], + "assets": { + "web.assets_frontend": [ + "website_altcha/static/src/**/*.esm.js", + "website_altcha/static/src/**/*.xml", + "website_altcha/static/src/**/*.scss", + ], + "web.altcha_libs": [ + "website_altcha/static/lib/altcha.js", + "website_altcha/static/lib/altcha-l10n.js", + ], + }, + "post_init_hook": "post_init_hook", + "data": [], + "demo": [], +} diff --git a/website_altcha/controllers/__init__.py b/website_altcha/controllers/__init__.py new file mode 100644 index 0000000000..1de6122068 --- /dev/null +++ b/website_altcha/controllers/__init__.py @@ -0,0 +1 @@ +from . import altcha diff --git a/website_altcha/controllers/altcha.py b/website_altcha/controllers/altcha.py new file mode 100644 index 0000000000..40734f2999 --- /dev/null +++ b/website_altcha/controllers/altcha.py @@ -0,0 +1,29 @@ +import json +from datetime import timedelta + +import altcha.v1 as altcha + +from odoo import fields, http +from odoo.http import request + + +class AltchaController(http.Controller): + @http.route("/altcha", type="http", auth="public") + def generate_altcha_challenge(self): + expires = fields.Datetime.now() + timedelta(minutes=5) + # TODO: Set the time dynamically based on config + options = altcha.ChallengeOptions( + hmac_key=request.env["ir.config_parameter"].sudo().get_param("altcha.key"), + expires=expires, + ) + challenge = altcha.create_challenge(options) + request.env["altcha.key"].sudo().create( + { + "key": request.env["ir.http"]._get_altcha_key(challenge.signature), + "expires_at": expires, + } + ) + return request.make_response( + json.dumps(challenge.to_dict()), + headers=[("Content-Type", "application/json")], + ) diff --git a/website_altcha/models/__init__.py b/website_altcha/models/__init__.py new file mode 100644 index 0000000000..bf0ada1e6d --- /dev/null +++ b/website_altcha/models/__init__.py @@ -0,0 +1,2 @@ +from . import ir_http +from . import altcha_key diff --git a/website_altcha/models/altcha_key.py b/website_altcha/models/altcha_key.py new file mode 100644 index 0000000000..bb3758d536 --- /dev/null +++ b/website_altcha/models/altcha_key.py @@ -0,0 +1,24 @@ +# Copyright 2025 Dixmit +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models + + +class AltchaKey(models.Model): + _name = "altcha.key" + _description = "Altcha Key" # TODO + + key = fields.Char(required=True) + expires_at = fields.Datetime(required=True) + used = fields.Boolean(default=False) + + _sql_constraints = [ + ("key_uniq", "unique(key)", "The Altcha key must be unique."), + ] + + @api.autovacuum + def _autovacuum_expired_keys(self): + """Delete expired Altcha keys.""" + now = fields.Datetime.now() + expired_keys = self.search([("expires_at", "<", now)]) + expired_keys.unlink() diff --git a/website_altcha/models/ir_http.py b/website_altcha/models/ir_http.py new file mode 100644 index 0000000000..09950aa373 --- /dev/null +++ b/website_altcha/models/ir_http.py @@ -0,0 +1,81 @@ +# Copyright 2025 Dixmit +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +import base64 +import hashlib +import hmac +import json +import logging + +import altcha.v1 as altcha + +from odoo import _, api, models +from odoo.exceptions import UserError +from odoo.http import request + +_logger = logging.getLogger(__name__) + + +class IrHttp(models.AbstractModel): + _inherit = "ir.http" + + def session_info(self): + session_info = super().session_info() + return self._add_altcha_public_key_to_session_info(session_info) + + @api.model + def get_frontend_session_info(self): + frontend_session_info = super().get_frontend_session_info() + return self._add_altcha_public_key_to_session_info(frontend_session_info) + + @api.model + def _add_altcha_public_key_to_session_info(self, session_info): + """Add the Altcha public key to the given session_info object""" + session_info["altcha_public_key"] = bool( + self.env["ir.config_parameter"].sudo().get_param("altcha.key") + ) + return session_info + + @api.model + def _get_altcha_key(self, signature): + return hmac.new( + signature.encode("utf-8"), + request.httprequest.remote_addr.encode("utf-8"), + digestmod=hashlib.sha256, + ).hexdigest() + + @api.model + def _verify_request_recaptcha_token(self, action): + result = super()._verify_request_recaptcha_token(action) + if not result: + return result + altcha_signature = request.params.get("altcha") + if not altcha_signature: + _logger.warning("Altcha token missing in request") + raise UserError(_("Suspicious activity detected by Altcha")) + altcha_request = json.loads(base64.b64decode(altcha_signature)) + is_valid, error = altcha.verify_solution( + altcha_request, + self.env["ir.config_parameter"].sudo().get_param("altcha.key"), + True, + ) + if not is_valid: + _logger.warning("Altcha verification failed: %s", error) + raise UserError(_("Suspicious activity detected by Altcha")) + unique_id = self._get_altcha_key(altcha_request["signature"]) + record = ( + self.env["altcha.key"] + .sudo() + .search( + [ + ("key", "=", unique_id), + ("used", "=", False), + ], + limit=1, + ) + ) + if not record: + _logger.warning(f"Altcha key not found or already used: {unique_id}") + raise UserError(_("Suspicious activity detected by Altcha")) + record.used = True + return result diff --git a/website_altcha/pyproject.toml b/website_altcha/pyproject.toml new file mode 100644 index 0000000000..4231d0cccb --- /dev/null +++ b/website_altcha/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/website_altcha/readme/DESCRIPTION.md b/website_altcha/readme/DESCRIPTION.md new file mode 100644 index 0000000000..86245d1735 --- /dev/null +++ b/website_altcha/readme/DESCRIPTION.md @@ -0,0 +1,12 @@ +[ This file is not always required; it should explain **how to configure the module +before using it**; it is aimed at users with administration privileges. + +Please be detailed on the path to configuration (eg: do you need to activate developer +mode?), describe step by step configurations and the use of screenshots is strongly +recommended.] + +To configure this module, you need to: + +- Go to _App_ > Menu > Menu item +- Activate boolean… > save +- … diff --git a/website_altcha/static/description/index.html b/website_altcha/static/description/index.html new file mode 100644 index 0000000000..ad9e21a436 --- /dev/null +++ b/website_altcha/static/description/index.html @@ -0,0 +1,427 @@ + + + + + +Website Friendly Captcha + + + +
+

Website Friendly Captcha

+ + +

Beta License: AGPL-3 OCA/website Translate me on Weblate Try me on Runboat

+

[ This file is not always required; it should explain how to configure +the module before using it; it is aimed at users with administration +privileges.

+

Please be detailed on the path to configuration (eg: do you need to +activate developer mode?), describe step by step configurations and the +use of screenshots is strongly recommended.]

+

To configure this module, you need to:

+
    +
  • Go to App > Menu > Menu item
  • +
  • Activate boolean… > save
  • +
  • +
+

Table of contents

+ +
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Dixmit
  • +
+
+
+

Maintainers

+

This module is maintained by the OCA.

+ +Odoo Community Association + +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

This module is part of the OCA/website project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/website_altcha/static/lib/altcha-l10n.js b/website_altcha/static/lib/altcha-l10n.js new file mode 100644 index 0000000000..f414c7fe22 --- /dev/null +++ b/website_altcha/static/lib/altcha-l10n.js @@ -0,0 +1,1155 @@ +/* @odoo-module */ +const n = () => { +}; +function b(e, a) { + return e != e ? a == a : e !== a || e !== null && typeof e == "object" || typeof e == "function"; +} +let g = !1; +function v(e) { + var a = g; + try { + return g = !0, e(); + } finally { + g = a; + } +} +function A(e, a, r) { + if (e == null) + return a(void 0), n; + const t = v( + () => e.subscribe( + a, + // @ts-expect-error + r + ) + ); + return t.unsubscribe ? () => t.unsubscribe() : t; +} +const l = []; +function k(e, a = n) { + let r = null; + const t = /* @__PURE__ */ new Set(); + function d(o) { + if (b(e, o) && (e = o, r)) { + const s = !l.length; + for (const i of t) + i[1](), l.push(i, e); + if (s) { + for (let i = 0; i < l.length; i += 2) + l[i][0](l[i + 1]); + l.length = 0; + } + } + } + function c(o) { + d(o( + /** @type {T} */ + e + )); + } + function u(o, s = n) { + const i = [o, s]; + return t.add(i), t.size === 1 && (r = a(d, c) || n), o( + /** @type {T} */ + e + ), () => { + t.delete(i), t.size === 0 && r && (r(), r = null); + }; + } + return { set: d, update: c, subscribe: u }; +} +function h(e) { + let a; + return A(e, (r) => a = r)(), a; +} +globalThis.altchaPlugins = globalThis.altchaPlugins || []; +globalThis.altchaI18n = globalThis.altchaI18n || { + get: (e) => h(globalThis.altchaI18n.store)[e], + set: (e, a) => { + Object.assign(h(globalThis.altchaI18n.store), { + [e]: a + }), globalThis.altchaI18n.store.set(h(globalThis.altchaI18n.store)); + }, + store: k({}) +}; +const p = { + ariaLinkLabel: "زور Altcha.org", + enterCode: "أدخل الرمز", + enterCodeAria: "أدخل الرمز الذي تسمعه. اضغط على المسافة لتشغيل الصوت.", + error: "فشل التحقق. حاول مرة أخرى لاحقاً.", + expired: "انتهت صلاحية التحقق. حاول مرة أخرى.", + verificationRequired: "مطلوب التحقق!", + footer: 'محمي بواسطة ALTCHA', + getAudioChallenge: "احصل على تحدي صوتي", + label: "أنا لست روبوتاً", + loading: "جارٍ التحميل...", + reload: "إعادة تحميل", + verify: "تحقق", + verified: "تم التحقق", + verifying: "جارٍ التحقق...", + waitAlert: "جارٍ التحقق... يرجى الانتظار." +}; +globalThis.altchaI18n.set("ar", p); +const C = { + ariaLinkLabel: "Посетете Altcha.org", + enterCode: "Въведете код", + enterCodeAria: "Въведете кода, който чувате. Натиснете Space за възпроизвеждане на аудио.", + error: "Проверката неуспешна. Моля, опитайте по-късно.", + expired: "Времето за проверка изтече. Моля, опитайте отново.", + verificationRequired: "Изисква се проверка!", + footer: 'Защитено от ALTCHA', + getAudioChallenge: "Аудио проверка", + label: "Аз не съм робот", + loading: "Зареждане...", + reload: "Презареди", + verify: "Провери", + verified: "Проверено", + verifying: "Проверява се...", + waitAlert: "Проверката е в процес... моля изчакайте." +}; +globalThis.altchaI18n.set("bg", C); +const y = { + ariaLinkLabel: "Наведаць Altcha.org", + enterCode: "Увядзіце код", + enterCodeAria: "Увядзіце код, які вы чуеце. Націсніце прабел, каб прайграць аўдыё.", + error: "Праверка не прайшла. Паспрабуйце пазней.", + expired: "Тэрмін праверкі скончыўся. Паспрабуйце зноў.", + footer: 'Абаронена ALTCHA', + getAudioChallenge: "Атрымаць аўдыё выклік", + label: "Я не робат", + loading: "Загрузка...", + reload: "Перазагрузіць", + verify: "Праверыць", + verificationRequired: "Патрабуецца праверка!", + verified: "Праверана", + verifying: "Правяраем...", + waitAlert: "Праверка... калі ласка, пачакайце." +}; +globalThis.altchaI18n.set("be", y); +const L = { + ariaLinkLabel: "Posjetite Altcha.org", + enterCode: "Unesite kod", + enterCodeAria: "Unesite kod koji čujete. Pritisnite Space da biste pustili zvuk.", + error: "Verifikacija nije uspjela. Pokušajte ponovo kasnije.", + expired: "Verifikacija je istekla. Pokušajte ponovo.", + footer: 'Zaštićeno od strane ALTCHA', + getAudioChallenge: "Dohvatite audio izazov", + label: "Nisam robot", + loading: "Učitavanje...", + reload: "Ponovno učitaj", + verify: "Verifikuj", + verificationRequired: "Verifikacija je obavezna!", + verified: "Verifikovano", + verifying: "Verifikacija u toku...", + waitAlert: "Verifikacija u toku... molimo vas da sačekate." +}; +globalThis.altchaI18n.set("bs", L); +const m = { + ariaLinkLabel: "Visita Altcha.org", + enterCode: "Introdueix el codi", + enterCodeAria: "Introdueix el codi que escoltes. Prem Espai per reproduir l’àudio.", + error: "Verificació fallida. Torna-ho a provar més tard.", + expired: "Verificació expirada. Torna-ho a provar.", + footer: 'Protegit per ALTCHA', + getAudioChallenge: "Obtenir un desafiament d’àudio", + label: "No sóc un robot", + loading: "Carregant...", + reload: "Torna a carregar", + verify: "Verificar", + verificationRequired: "Es requereix verificació!", + verified: "Verificat", + verifying: "Verificant...", + waitAlert: "Verificant... si us plau, espera." +}; +globalThis.altchaI18n.set("ca", m); +const j = { + ariaLinkLabel: "Navštivte Altcha.org", + enterCode: "Zadejte kód", + enterCodeAria: "Zadejte kód, který slyšíte. Stisknutím mezerníku přehrajete zvuk.", + error: "Ověření selhalo. Zkuste to prosím později.", + expired: "Ověření vypršelo. Zkuste to prosím znovu.", + verificationRequired: "Vyžaduje se ověření!", + footer: 'Chráněno pomocí ALTCHA', + getAudioChallenge: "Získat audio výzvu", + label: "Nejsem robot", + loading: "Načítání...", + reload: "Znovu načíst", + verify: "Ověřit", + verified: "Ověřeno", + verifying: "Ověřování...", + waitAlert: "Probíhá ověření... prosím počkejte." +}; +globalThis.altchaI18n.set("cs", j); +const T = { + ariaLinkLabel: "Besøg Altcha.org", + enterCode: "Indtast kode", + enterCodeAria: "Indtast den kode, du hører. Tryk på mellemrumstasten for at afspille lyd.", + error: "Verificering mislykkedes. Prøv venligst igen senere.", + expired: "Verificering udløbet. Prøv venligst igen.", + verificationRequired: "Verificering kræves!", + footer: 'Beskyttet af ALTCHA', + getAudioChallenge: "Hent lydudfordring", + label: "Jeg er ikke en robot", + loading: "Indlæser...", + reload: "Genindlæs", + verify: "Verificer", + verified: "Verificeret", + verifying: "Verificerer...", + waitAlert: "Verificerer... vent venligst." +}; +globalThis.altchaI18n.set("da", T); +const V = { + ariaLinkLabel: "Besuche Altcha.org", + enterCode: "Code eingeben", + enterCodeAria: "Geben Sie den Code ein, den Sie hören. Drücken Sie die Leertaste, um die Audio abzuspielen.", + error: "Überprüfung fehlgeschlagen. Bitte versuchen Sie es später erneut.", + expired: "Überprüfung abgelaufen. Bitte versuchen Sie es erneut.", + verificationRequired: "Überprüfung erforderlich!", + footer: 'Geschützt durch ALTCHA', + getAudioChallenge: "Audio-Herausforderung anfordern", + label: "Ich bin kein Roboter", + loading: "Lade...", + reload: "Neu laden", + verify: "Überprüfen", + verified: "Überprüft", + verifying: "Wird überprüft...", + waitAlert: "Überprüfung läuft... bitte warten." +}; +globalThis.altchaI18n.set("de", V); +const z = { + ariaLinkLabel: "Επισκεφθείτε το Altcha.org", + enterCode: "Εισαγάγετε κωδικό", + enterCodeAria: "Εισαγάγετε τον κωδικό που ακούτε. Πατήστε Space για να παίξετε τον ήχο.", + error: "Η επαλήθευση απέτυχε. Δοκιμάστε ξανά αργότερα.", + expired: "Η επαλήθευση έληξε. Δοκιμάστε ξανά.", + verificationRequired: "Απαιτείται έλεγχος!", + footer: 'Προστατεύεται από το ALTCHA', + getAudioChallenge: "Λήψη ηχητικής δοκιμασίας", + label: "Δεν είμαι ρομπότ", + loading: "Φόρτωση...", + reload: "Επαναφόρτωση", + verify: "Επαλήθευση", + verified: "Επαληθεύτηκε", + verifying: "Γίνεται επαλήθευση...", + waitAlert: "Γίνεται επαλήθευση... παρακαλώ περιμένετε." +}; +globalThis.altchaI18n.set("el", z); +const w = { + ariaLinkLabel: "Visitar Altcha.org", + enterCode: "Introduce el código", + enterCodeAria: "Introduce el código que escuchas. Pulsa Espacio para reproducir el audio.", + error: "Falló la verificación. Por favor intente nuevamente más tarde.", + expired: "Verificación expirada. Por favor intente nuevamente.", + verificationRequired: "¡Verificación requerida!", + footer: 'Protegido por ALTCHA', + getAudioChallenge: "Obtener un desafío de audio", + label: "No soy un robot", + loading: "Cargando...", + reload: "Recargar", + verify: "Verificar", + verified: "Verificado", + verifying: "Verificando...", + waitAlert: "Verificando... por favor espere." +}; +globalThis.altchaI18n.set("es-es", w); +const I = { + ariaLinkLabel: "Visitar Altcha.org", + enterCode: "Ingresa el código", + enterCodeAria: "Ingresa el código que escuchas. Presiona Espacio para reproducir el audio.", + error: "Falló la verificación. Por favor vuelve a intentarlo más tarde.", + expired: "La verificación expiró. Por favor inténtalo de nuevo.", + verificationRequired: "¡Verificación requerida!", + footer: 'Protegido por ALTCHA', + getAudioChallenge: "Obtener un reto de audio", + label: "No soy un robot", + loading: "Cargando...", + reload: "Volver a cargar", + verify: "Verificar", + verified: "Verificado", + verifying: "Verificando...", + waitAlert: "Verificando... por favor espera." +}; +globalThis.altchaI18n.set("es-419", I); +const P = { + ariaLinkLabel: "Külasta Altcha.org", + enterCode: "Sisesta kood", + enterCodeAria: "Sisestage kuuldu kood. Vajutage tühikut, et esitada heli.", + error: "Kinnitamine ebaõnnestus. Proovi hiljem uuesti.", + expired: "Kinnitamine aegus. Proovi uuesti.", + verificationRequired: "Kontroll on vajalik!", + footer: 'Kaitstud ALTCHA poolt', + getAudioChallenge: "Hangi heliülesanne", + label: "Ma ei ole robot", + loading: "Laadimine...", + reload: "Laadi uuesti", + verify: "Kinnita", + verified: "Kinnitatud", + verifying: "Kinnitamine...", + waitAlert: "Kinnitamine... palun oota." +}; +globalThis.altchaI18n.set("et", P); +const q = { + ariaLinkLabel: "Bisitatu Altcha.org", + enterCode: "Sartu kodea", + enterCodeAria: "Sartu entzun duzun kodea. Sakatu Espazioa audioa erreproduzitzeko.", + error: "Egiaztatzeak huts egin du. Saiatu berriro geroago.", + expired: "Egiaztatzea iraungi da. Saiatu berriro.", + verificationRequired: "Egiaztatzea beharrezkoa da!", + footer: 'ALTCHAk babestuta', + getAudioChallenge: "Jaso audio-erronka bat", + label: "Ez naiz robot bat", + loading: "Kargatzen...", + reload: "Birkargatu", + verify: "Egiaztatu", + verified: "Egiaztatuta", + verifying: "Egiaztatzen...", + waitAlert: "Egiaztatzen... itxaron mesedez." +}; +globalThis.altchaI18n.set("eu", q); +const x = { + ariaLinkLabel: "بازدید از Altcha.org", + enterCode: "کد را وارد کنید", + enterCodeAria: "کدی که می‌شنوید را وارد کنید. برای پخش صدا Space را فشار دهید.", + error: "احراز هویت ناموفق بود. بعداً دوباره تلاش کنید.", + expired: "احراز هویت منقضی شد. دوباره تلاش کنید.", + footer: 'محافظت شده توسط ALTCHA', + getAudioChallenge: "دریافت چالش صوتی", + label: "من ربات نیستم", + loading: "در حال بارگذاری...", + reload: "بارگذاری مجدد", + verify: "تایید", + verificationRequired: "احراز هویت لازم است!", + verified: "تایید شد", + verifying: "در حال تایید...", + waitAlert: "در حال تایید... لطفا منتظر بمانید." +}; +globalThis.altchaI18n.set("fa", x); +const R = { + ariaLinkLabel: "Besicht Altcha.org", + enterCode: "Code aginn", + enterCodeAria: "Gitt de Code an deen dir héiert. Dréckt op d'Weltraumtast fir Audio ofzespillen.", + error: "Verifikatioun ass feelgeschloen. Probéiert méi spéit nach emol.", + expired: "Verifikatioun ofgelaf. Probéiert nach emol.", + footer: 'Geschützt vun ALTCHA', + getAudioChallenge: "Kritt eng Audio-Herausfuerderung", + label: "Ech sinn keen Robot", + loading: "Lueden...", + reload: "Nei lueden", + verify: "Verifizéieren", + verificationRequired: "Verifikatioun néideg!", + verified: "Verifizéiert", + verifying: "Verifizéieren...", + waitAlert: "Verifizéieren... waart wgl." +}; +globalThis.altchaI18n.set("lb", R); +const H = { + ariaLinkLabel: "Vieraile sivulla Altcha.org", + enterCode: "Syötä koodi", + enterCodeAria: "Kirjoita kuulemasi koodi. Paina välilyöntiä toistaaksesi äänen.", + error: "Varmennus epäonnistui. Yritä myöhemmin uudelleen.", + expired: "Varmennus vanhentui. Yritä uudelleen.", + verificationRequired: "Vahvistus vaaditaan!", + footer: 'Suojattu ALTCHA:lla', + getAudioChallenge: "Hae äänitehtävä", + label: "En ole robotti", + loading: "Ladataan...", + reload: "Lataa uudelleen", + verify: "Vahvista", + verified: "Vahvistettu", + verifying: "Vahvistetaan...", + waitAlert: "Vahvistetaan... odota hetki." +}; +globalThis.altchaI18n.set("fi", H); +const _ = { + ariaLinkLabel: "Visitez Altcha.org", + enterCode: "Entrez le code", + enterCodeAria: "Entrez le code que vous entendez. Appuyez sur la barre d'espace pour écouter l'audio.", + error: "Échec de la vérification. Réessayez plus tard.", + expired: "La vérification a expiré. Réessayez.", + verificationRequired: "Vérification requise !", + footer: 'Protégé par ALTCHA', + getAudioChallenge: "Obtenir un défi audio", + label: "Pas un robot", + loading: "Chargement...", + reload: "Recharger", + verify: "Vérifier", + verified: "Vérifié", + verifying: "Vérification en cours...", + waitAlert: "Vérification en cours... veuillez patienter." +}; +globalThis.altchaI18n.set("fr-ca", _); +const S = { + ariaLinkLabel: "Visitez Altcha.org", + enterCode: "Entrez le code", + enterCodeAria: "Entrez le code que vous entendez. Appuyez sur Espace pour écouter l'audio.", + error: "Échec de la vérification. Essayez à nouveau plus tard.", + expired: "La vérification a expiré. Essayez à nouveau.", + verificationRequired: "Vérification requise !", + footer: 'Protégé par ALTCHA', + getAudioChallenge: "Obtenir un défi audio", + label: "Pas un robot", + loading: "Chargement...", + reload: "Recharger", + verify: "Vérifier", + verified: "Vérifié", + verifying: "Vérification en cours...", + waitAlert: "Vérification en cours... veuillez patienter." +}; +globalThis.altchaI18n.set("fr-fr", S); +const $ = { + ariaLinkLabel: "Tabhair cuairt ar Altcha.org", + enterCode: "Iontráil cód", + enterCodeAria: "Cuir isteach an cód a chloiseann tú. Brúigh Spás chun an fuaime a sheinm.", + error: "Theip ar an bhfíorú. Bain triail eile as níos déanaí.", + expired: "Tá an fíorú as feidhm. Bain triail eile as.", + verificationRequired: "Fíorú riachtanach!", + footer: 'Cosanta ag ALTCHA', + getAudioChallenge: "Faigh dúshlán fuaime", + label: "Níl mé i mo róbat", + loading: "Á luchtú...", + reload: "Athluchtaigh", + verify: "Fíoraigh", + verified: "Fíoraithe", + verifying: "Fíorú ar siúl...", + waitAlert: "Fíorú ar siúl... fan go fóill." +}; +globalThis.altchaI18n.set("ga", $); +const E = { + ariaLinkLabel: "Posjetite Altcha.org", + enterCode: "Unesite kod", + enterCodeAria: "Unesite kod koji čujete. Pritisnite razmaknicu za reprodukciju zvuka.", + error: "Provjera nije uspjela. Molimo pokušajte kasnije.", + expired: "Provjera je istekla. Molimo pokušajte ponovo.", + verificationRequired: "Potrebna je provjera!", + footer: 'Zaštićeno od strane ALTCHA', + getAudioChallenge: "Audio provjera", + label: "Ja nisam robot", + loading: "Učitavanje...", + reload: "Ponovno učitaj", + verify: "Provjeri", + verified: "Provjereno", + verifying: "Provjeravanje...", + waitAlert: "Provjera je u tijeku... molimo pričekajte." +}; +globalThis.altchaI18n.set("hr", E); +const B = { + ariaLinkLabel: "Látogass el az Altcha.org oldalra", + enterCode: "Írja be a kódot", + enterCodeAria: "Írja be a hallott kódot. Nyomja meg a Szóköz billentyűt a hang lejátszásához.", + error: "A hitelesítés nem sikerült. Próbáld meg később újra.", + expired: "A hitelesítés lejárt. Próbáld újra.", + verificationRequired: "Ellenőrzés szükséges!", + footer: 'Védve a következő által: ALTCHA', + getAudioChallenge: "Hangalapú kihívás kérése", + label: "Nem vagyok robot", + loading: "Betöltés...", + reload: "Újratöltés", + verify: "Ellenőrzés", + verified: "Ellenőrizve", + verifying: "Ellenőrzés folyamatban...", + waitAlert: "Ellenőrzés folyamatban... kérlek várj." +}; +globalThis.altchaI18n.set("hu", B); +const N = { + ariaLinkLabel: "Heimsækja Altcha.org", + enterCode: "Sláðu inn kóða", + enterCodeAria: "Sláðu inn kóðann sem þú heyrir. Ýttu á Space til að spila hljóðið.", + error: "Staðfesting mistókst. Reyndu aftur síðar.", + expired: "Staðfesting er útrunnin. Reyndu aftur.", + footer: 'Verndað af ALTCHA', + getAudioChallenge: "Fá hljóðáskorun", + label: "Ég er ekki robot", + loading: "Hleður...", + reload: "Hleð aftur", + verify: "Staðfesta", + verificationRequired: "Staðfesting er nauðsynleg!", + verified: "Staðfest", + verifying: "Að staðfesta...", + waitAlert: "Að staðfesta... vinsamlegast bíða." +}; +globalThis.altchaI18n.set("is", N); +const D = { + ariaLinkLabel: "Visita Altcha.org", + enterCode: "Inserisci il codice", + enterCodeAria: "Inserisci il codice che senti. Premi Spazio per riprodurre l'audio.", + error: "Verifica fallita. Riprova più tardi.", + expired: "Verifica scaduta. Riprova.", + verificationRequired: "Verifica richiesta!", + footer: 'Protetto da ALTCHA', + getAudioChallenge: "Ottieni una sfida audio", + label: "Non sono un robot", + loading: "Caricamento...", + reload: "Ricarica", + verify: "Verifica", + verified: "Verificato", + verifying: "Verifica in corso...", + waitAlert: "Verifica in corso... attendere." +}; +globalThis.altchaI18n.set("it", D); +const O = { + ariaLinkLabel: "Apsilankykite Altcha.org", + enterCode: "Įveskite kodą", + enterCodeAria: "Įveskite girdimą kodą. Paspauskite tarpo klavišą, kad grotumėte garso įrašą.", + error: "Patvirtinimas nepavyko. Bandykite vėliau.", + expired: "Patvirtinimo laikas baigėsi. Bandykite dar kartą.", + verificationRequired: "Reikalingas patvirtinimas!", + footer: 'Apsaugota ALTCHA', + getAudioChallenge: "Gauti garso užduotį", + label: "Aš nesu robotas", + loading: "Įkeliama...", + reload: "Įkelti iš naujo", + verify: "Patvirtinti", + verified: "Patvirtinta", + verifying: "Tikrinama...", + waitAlert: "Tikrinama... prašome palaukti." +}; +globalThis.altchaI18n.set("lt", O); +const K = { + ariaLinkLabel: "Apmeklējiet Altcha.org", + enterCode: "Ievadiet kodu", + enterCodeAria: "Ievadiet dzirdamo kodu. Nospiediet atstarpes taustiņu, lai atskaņotu audio.", + error: "Verifikācija neizdevās. Mēģiniet vēlāk vēlreiz.", + expired: "Verifikācijas laiks ir beidzies. Mēģiniet vēlreiz.", + verificationRequired: "Nepieciešama verifikācija!", + footer: 'Aizsargāts ar ALTCHA', + getAudioChallenge: "Saņemt audio izaicinājumu", + label: "Es neesmu robots", + loading: "Notiek ielāde...", + reload: "Pārlādēt", + verify: "Verificēt", + verified: "Verificēts", + verifying: "Notiek verifikācija...", + waitAlert: "Notiek verifikācija... lūdzu, uzgaidiet." +}; +globalThis.altchaI18n.set("lv", K); +const F = { + ariaLinkLabel: "Żur Altcha.org", + enterCode: "Idħol il-kodiċi", + enterCodeAria: "Idħol il-kodiċi li tisma'. Agħfas Spazju biex tindaqq l-awdjo.", + error: "Il-verifika falliet. Erġa’ pprova aktar tard.", + expired: "Il-verifika skadiet. Erġa’ pprova.", + verificationRequired: "Verifika meħtieġa!", + footer: 'Protett minn ALTCHA', + getAudioChallenge: "Ikseb sfida bl-awdjo", + label: "M’inix robot", + loading: "Qed jitgħabba...", + reload: "Ittella’ mill-ġdid", + verify: "Ivverifika", + verified: "Ivverifikat", + verifying: "Verifika għaddejja...", + waitAlert: "Verifika għaddejja... stenna ftit." +}; +globalThis.altchaI18n.set("mt", F); +const f = { + ariaLinkLabel: "Besøk Altcha.org", + enterCode: "Skriv inn kode", + enterCodeAria: "Skriv inn koden du hører. Trykk på Space for å spille av lyden.", + error: "Verifisering mislyktes. Prøv igjen senere.", + expired: "Verifiseringen utløp. Prøv igjen.", + footer: 'Beskyttet av ALTCHA', + getAudioChallenge: "Få en lydutfordring", + label: "Jeg er ikke en robot", + loading: "Laster...", + reload: "Last på nytt", + verify: "Verifiser", + verificationRequired: "Verifisering kreves!", + verified: "Verifisert", + verifying: "Verifiserer...", + waitAlert: "Verifiserer... vennligst vent." +}; +globalThis.altchaI18n.set("nb", f); +globalThis.altchaI18n.set("no", f); +const M = { + ariaLinkLabel: "Bezoek Altcha.org", + enterCode: "Voer code in", + enterCodeAria: "Voer de code in die je hoort. Druk op Spatie om de audio af te spelen.", + error: "Verificatie mislukt. Probeer het later opnieuw.", + expired: "Verificatie verlopen. Probeer het opnieuw.", + verificationRequired: "Verificatie vereist!", + footer: 'Beschermd door ALTCHA', + getAudioChallenge: "Audio-uitdaging ontvangen", + label: "Ik ben geen robot", + loading: "Laden...", + reload: "Herladen", + verify: "Verifiëren", + verified: "Geverifieerd", + verifying: "Bezig met verifiëren...", + waitAlert: "Bezig met verifiëren... even geduld a.u.b." +}; +globalThis.altchaI18n.set("nl", M); +const Z = { + ariaLinkLabel: "Odwiedź Altcha.org", + enterCode: "Wprowadź kod", + enterCodeAria: "Wpisz kod, który słyszysz. Naciśnij Spację, aby odtworzyć dźwięk.", + error: "Weryfikacja nie powiodła się. Spróbuj ponownie później.", + expired: "Weryfikacja wygasła. Spróbuj ponownie.", + verificationRequired: "Wymagana weryfikacja!", + footer: 'Chronione przez ALTCHA', + getAudioChallenge: "Pobierz zadanie dźwiękowe", + label: "Nie jestem robotem", + loading: "Ładowanie...", + reload: "Odśwież", + verify: "Zweryfikuj", + verified: "Zweryfikowano", + verifying: "Weryfikacja...", + waitAlert: "Trwa weryfikacja... proszę czekać." +}; +globalThis.altchaI18n.set("pl", Z); +const U = { + ariaLinkLabel: "Visitar Altcha.org", + enterCode: "Introduza o código", + enterCodeAria: "Introduza o código que ouve. Prima Espaço para reproduzir o áudio.", + error: "A verificação falhou. Por favor, tente novamente mais tarde.", + expired: "Verificação expirada. Por favor, tente novamente.", + verificationRequired: "Verificação necessária!", + footer: 'Protegido por ALTCHA', + getAudioChallenge: "Obter desafio de áudio", + label: "Não sou um robô", + loading: "A carregar...", + reload: "Recarregar", + verify: "Verificar", + verified: "Verificado", + verifying: "A verificar...", + waitAlert: "A verificar... por favor aguarde." +}; +globalThis.altchaI18n.set("pt-pt", U); +const G = { + ariaLinkLabel: "Visitar Altcha.org", + enterCode: "Digite o código", + enterCodeAria: "Digite o código que você ouve. Pressione Espaço para reproduzir o áudio.", + error: "Falha na verificação. Por favor, tente novamente mais tarde.", + expired: "Verificação expirada. Por favor, tente novamente.", + verificationRequired: "Verificação necessária!", + footer: 'Protegido por ALTCHA', + getAudioChallenge: "Obter desafio de áudio", + label: "Eu não sou um robô", + loading: "Carregando...", + reload: "Recarregar", + verify: "Verificar", + verified: "Verificado", + verifying: "Verificando...", + waitAlert: "Verificando... por favor aguarde." +}; +globalThis.altchaI18n.set("pt-br", G); +const W = { + ariaLinkLabel: "Vizitează Altcha.org", + enterCode: "Introduceți codul", + enterCodeAria: "Introduceți codul pe care îl auziți. Apăsați Spațiu pentru a reda audio.", + error: "Verificarea a eșuat. Încearcă din nou mai târziu.", + expired: "Verificarea a expirat. Încearcă din nou.", + verificationRequired: "Verificare necesară!", + footer: 'Protejat de ALTCHA', + getAudioChallenge: "Obține o provocare audio", + label: "Nu sunt un robot", + loading: "Se încarcă...", + reload: "Reîncarcă", + verify: "Verifică", + verified: "Verificat", + verifying: "Se verifică...", + waitAlert: "Se verifică... te rugăm să aștepți." +}; +globalThis.altchaI18n.set("ro", W); +const J = { + ariaLinkLabel: "Перейти на Altcha.org", + enterCode: "Введите код", + enterCodeAria: "Введите код, который слышите. Нажмите пробел для воспроизведения аудио.", + error: "Ошибка верификации. Попробуйте позже.", + expired: "Срок действия верификации истек. Попробуйте снова.", + verificationRequired: "Требуется проверка!", + footer: 'Защищено ALTCHA', + getAudioChallenge: "Получить аудио задачу", + label: "Я не робот", + loading: "Загрузка...", + reload: "Перезагрузить", + verify: "Проверить", + verified: "Проверено", + verifying: "Идет проверка...", + waitAlert: "Идет проверка... Пожалуйста, подождите." +}; +globalThis.altchaI18n.set("ru", J); +const Y = { + ariaLinkLabel: "Navštívte Altcha.org", + enterCode: "Zadajte kód", + enterCodeAria: "Zadajte kód, ktorý počujete. Stlačením medzerníka prehráte zvuk.", + error: "Verifikácia zlyhala. Skúste to znova neskôr.", + expired: "Verifikácia vypršala. Skúste to znova.", + verificationRequired: "Vyžaduje sa overenie!", + footer: 'Chránené ALTCHA', + getAudioChallenge: "Získať audio výzvu", + label: "Nie som robot", + loading: "Načítava sa...", + reload: "Obnoviť", + verify: "Verifikovať", + verified: "Verifikované", + verifying: "Prebieha verifikácia...", + waitAlert: "Prebieha verifikácia... prosím čakajte." +}; +globalThis.altchaI18n.set("sk", Y); +const Q = { + ariaLinkLabel: "Obiščite Altcha.org", + enterCode: "Vnesite kodo", + enterCodeAria: "Vnesite kodo, ki jo slišite. Pritisnite preslednico za predvajanje zvoka.", + error: "Preverjanje ni uspelo. Poskusite znova kasneje.", + expired: "Preverjanje je poteklo. Poskusite znova.", + verificationRequired: "Potrebna je preveritev!", + footer: 'Zaščiteno z ALTCHA', + getAudioChallenge: "Pridobite zvočni izziv", + label: "Nisem robot", + loading: "Nalagam...", + reload: "Ponovno naloži", + verify: "Preveri", + verified: "Preverjeno", + verifying: "Preverjanje...", + waitAlert: "Preverjanje... prosim počakajte." +}; +globalThis.altchaI18n.set("sl", Q); +const X = { + ariaLinkLabel: "Vizitoni Altcha.org", + enterCode: "Fut kodin", + enterCodeAria: "Fut kodin që dëgjon. Shtypni Hapësirë për të luajtur audio.", + error: "Verifikimi dështoi. Provoni përsëri më vonë.", + expired: "Verifikimi ka skaduar. Provoni përsëri.", + footer: 'I mbrojtur nga ALTCHA', + getAudioChallenge: "Merr një sfidë audio", + label: "Unë nuk jam një robot", + loading: "Duke u ngarkuar...", + reload: "Ringarko", + verify: "Verifiko", + verificationRequired: "Kërkohet verifikimi!", + verified: "I verifikuar", + verifying: "Duke verifikuar...", + waitAlert: "Duke verifikuar... ju lutem prisni." +}; +globalThis.altchaI18n.set("sq", X); +const ee = { + ariaLinkLabel: "Posetite Altcha.org", + enterCode: "Unesite kod", + enterCodeAria: "Unesite kod koji čujete. Pritisnite Space da biste pustili zvuk.", + error: "Verifikacija nije uspela. Pokušajte ponovo kasnije.", + expired: "Verifikacija je istekla. Pokušajte ponovo.", + footer: 'Zaštićeno od strane ALTCHA', + getAudioChallenge: "Dohvatite audio izazov", + label: "Nisam robot", + loading: "Učitavanje...", + reload: "Ponovo učitaj", + verify: "Verifikuj", + verificationRequired: "Verifikacija je obavezna!", + verified: "Verifikovano", + verifying: "Verifikacija u toku...", + waitAlert: "Verifikacija u toku... molimo vas da sačekate." +}; +globalThis.altchaI18n.set("sr", ee); +const ae = { + ariaLinkLabel: "Besök Altcha.org", + enterCode: "Ange kod", + enterCodeAria: "Ange koden du hör. Tryck på mellanslag för att spela upp ljudet.", + error: "Verifiering misslyckades. Försök igen senare.", + expired: "Verifieringen har gått ut. Försök igen.", + verificationRequired: "Verifiering krävs!", + footer: 'Skyddad av ALTCHA', + getAudioChallenge: "Få ljudutmaning", + label: "Jag är inte en robot", + loading: "Laddar...", + reload: "Ladda om", + verify: "Verifiera", + verified: "Verifierad", + verifying: "Verifierar...", + waitAlert: "Verifierar... vänligen vänta." +}; +globalThis.altchaI18n.set("sv", ae); +const ie = { + ariaLinkLabel: "Altcha.org'yu ziyaret edin", + enterCode: "Kodu girin", + enterCodeAria: "Duyduğunuz kodu girin. Ses dosyasını oynatmak için Boşluk tuşuna basın.", + error: "Doğrulama başarısız oldu. Lütfen daha sonra tekrar deneyin.", + expired: "Doğrulama süresi doldu. Lütfen tekrar deneyin.", + verificationRequired: "Doğrulama gerekli!", + footer: `ALTCHA tarafından korunuyor ALTCHA`, + getAudioChallenge: "Sesli doğrulama al", + label: "Ben robot değilim", + loading: "Yükleniyor...", + reload: "Yeniden yükle", + verify: "Doğrula", + verified: "Doğrulandı", + verifying: "Doğrulama yapılıyor...", + waitAlert: "Doğrulama yapılıyor... lütfen bekleyin." +}; +globalThis.altchaI18n.set("tr", ie); +const re = { + ariaLinkLabel: "Відвідати Altcha.org", + enterCode: "Введіть код", + enterCodeAria: "Введіть код, який ви чуєте. Натисніть пробіл, щоб відтворити аудіо.", + error: "Перевірка не вдалася. Спробуйте пізніше.", + expired: "Перевірка прострочена. Спробуйте знову.", + verificationRequired: "Потрібна перевірка!", + footer: 'Захищено ALTCHA', + getAudioChallenge: "Отримати аудіо-челлендж", + label: "Я не робот", + loading: "Завантаження...", + reload: "Перезавантажити", + verify: "Перевірити", + verified: "Перевірено", + verifying: "Перевіряється...", + waitAlert: "Перевірка... будь ласка, зачекайте." +}; +globalThis.altchaI18n.set("uk", re); +const te = { + ariaLinkLabel: "Besoek Altcha.org", + enterCode: "Voer kode in", + enterCodeAria: "Voer die kode in wat jy hoor. Druk Spasie om die klank af te speel.", + error: "Verifikasie het misluk. Probeer later weer.", + expired: "Verifikasie het verval. Probeer weer.", + footer: 'Beskerm deur ALTCHA', + getAudioChallenge: "Kry 'n klankuitdaging", + label: "Ek is nie 'n robot nie", + loading: "Laai...", + reload: "Laai weer", + verify: "Verifieer", + verificationRequired: "Verifikasie is vereis!", + verified: "Geverifieer", + verifying: "Verifieer...", + waitAlert: "Verifieer... wag asseblief." +}; +globalThis.altchaI18n.set("af", te); +const oe = { + ariaLinkLabel: "Altcha.org ይጎብኙ", + enterCode: "ኮድ አስገባ", + enterCodeAria: "የሚሰማዎትን ኮድ ያስገቡ። ድምጽ ለመጫወት Space ን ይጫኑ።", + error: "ማረጋገጫ አልተሳካም። በኋላ ላይ እንደገና ይሞክሩ።", + expired: "ማረጋገጫው ጊዜው አልፏል። እንደገና ይሞክሩ።", + footer: 'በ ALTCHA የተጠበቀ', + getAudioChallenge: "የድምጽ ፈተና ያግኙ", + label: "እኔ ሮቦት አይደለሁም", + loading: "በመጫን ላይ...", + reload: "እንደገና ጫን", + verify: "አረጋግጥ", + verificationRequired: "ማረጋገጫ ያስፈልጋል!", + verified: "ተረጋግጧል", + verifying: "በማረጋገጥ ላይ...", + waitAlert: "በማረጋገጥ ላይ... እባክዎ ይጠብቁ።" +}; +globalThis.altchaI18n.set("am", oe); +const le = { + ariaLinkLabel: "Tembelea Altcha.org", + enterCode: "Weka nambari", + enterCodeAria: "Weka nambari unayosikia. Bonyeza Space kucheza sauti.", + error: "Uthibitishaji umeshindwa. Jaribu tena baadaye.", + expired: "Uthibitishaji umeisha. Jaribu tena.", + footer: 'Imealindwa na ALTCHA', + getAudioChallenge: "Pata changamoto ya sauti", + label: "Mimi sio roboti", + loading: "Inapakia...", + reload: "Pakia tena", + verify: "Thibitisha", + verificationRequired: "Uthibitishaji unahitajika!", + verified: "Imethibitishwa", + verifying: "Inathibitisha...", + waitAlert: "Inathibitisha... tafadhali subiri." +}; +globalThis.altchaI18n.set("sw", le); +const ne = { + ariaLinkLabel: "Ṣe abẹwo si Altcha.org", + enterCode: "Tẹ koodu sii", + enterCodeAria: "Tẹ koodu ti o ngbọ sii. Tẹ Space lati ṣe ohun orin.", + error: "Ìdájọ́kòwò kò ṣẹ́ṣe. Gbiyanju lẹẹkansi ni ọjọ́ iwájú.", + expired: "Ìdájọ́kòwò ti pari. Gbiyanju lẹẹkansi.", + footer: 'Ti wa ni ààbò nipasẹ ALTCHA', + getAudioChallenge: "Gba ìjàdú ohùn", + label: "Emi kii ṣe ẹrọ", + loading: "Ó ń gbé sílẹ̀...", + reload: "Tún gbé wọlé", + verify: "Ṣàdájọ́", + verificationRequired: "Ìdájọ́kòwò ni a nílò!", + verified: "A ti dájọ́", + verifying: "Ó ń ṣàdájọ́...", + waitAlert: "Ó ń ṣàdájọ́... ẹ jọ̀ọ́ ẹ duro." +}; +globalThis.altchaI18n.set("yo", ne); +const de = { + ariaLinkLabel: "Altcha.org পরিদর্শন করুন", + enterCode: "কোড লিখুন", + enterCodeAria: "আপনি যে কোড শুনতে পান তা লিখুন। অডিও প্লে করতে স্পেস বাটন টিপুন।", + error: "যাচাইকরণ ব্যর্থ হয়েছে। পরে আবার চেষ্টা করুন।", + expired: "যাচাইকরণ সময়সীমা শেষ হয়েছে। আবার চেষ্টা করুন।", + verificationRequired: "যাচাই প্রয়োজন!", + footer: 'দ্বারা সুরক্ষিত ALTCHA', + getAudioChallenge: "অডিও চ্যালেঞ্জ নিন", + label: "আমি রোবট নই", + loading: "লোড হচ্ছে...", + reload: "পুনরায় লোড করুন", + verify: "যাচাই করুন", + verified: "যাচাই করা হয়েছে", + verifying: "যাচাই করা হচ্ছে...", + waitAlert: "যাচাই করা হচ্ছে... দয়া করে অপেক্ষা করুন।" +}; +globalThis.altchaI18n.set("bn", de); +const se = { + ariaLinkLabel: "בקר באתר Altcha.org", + enterCode: "הזן קוד", + enterCodeAria: "הזן את הקוד שאתה שומע. לחץ על רווח להפעלת השמע.", + error: "האימות נכשל. נסה שוב מאוחר יותר.", + expired: "תוקף האימות פג. נסה שוב.", + verificationRequired: "נדרש אימות!", + footer: 'מוגן על ידי ALTCHA', + getAudioChallenge: "קבל אתגר שמע", + label: "אני לא רובוט", + loading: "טוען...", + reload: "טען מחדש", + verify: "אמת", + verified: "אומת", + verifying: "מאמת...", + waitAlert: "מבצע אימות... אנא המתן." +}; +globalThis.altchaI18n.set("he", se); +const ge = { + ariaLinkLabel: "Altcha.org पर जाएं", + enterCode: "कोड दर्ज करेंं", + enterCodeAria: "आप जो कोड सुनते हैं उसे दर्ज करें। ऑडियो चलाने के लिए स्पेस दबाएं।", + error: "सत्यापन विफल। कृपया बाद में फिर से प्रयास करें।", + expired: "सत्यापन समाप्त हो गया है। कृपया पुनः प्रयास करें।", + verificationRequired: "सत्यापन आवश्यक है!", + footer: 'द्वारा संरक्षित ALTCHA', + getAudioChallenge: "ऑडियो चुनौती प्राप्त करें", + label: "मैं रोबोट नहीं हूँ", + loading: "लोड हो रहा है...", + reload: "पुनः लोड करें", + verify: "सत्यापित करें", + verified: "सत्यापित", + verifying: "सत्यापित कर रहे हैं...", + waitAlert: "सत्यापित किया जा रहा है... कृपया प्रतीक्षा करें।" +}; +globalThis.altchaI18n.set("hi", ge); +const he = { + ariaLinkLabel: "Kunjungi Altcha.org", + enterCode: "Masukkan kode", + enterCodeAria: "Masukkan kode yang Anda dengar. Tekan Spasi untuk memutar audio.", + error: "Verifikasi gagal. Coba lagi nanti.", + expired: "Verifikasi telah kedaluwarsa. Coba lagi.", + verificationRequired: "Verifikasi diperlukan!", + footer: 'Dilindungi oleh ALTCHA', + getAudioChallenge: "Dapatkan tantangan audio", + label: "Saya bukan robot", + loading: "Memuat...", + reload: "Muat ulang", + verify: "Verifikasi", + verified: "Terverifikasi", + verifying: "Memverifikasi...", + waitAlert: "Memverifikasi... harap tunggu." +}; +globalThis.altchaI18n.set("id", he); +const ce = { + ariaLinkLabel: "Altcha.orgを訪問", + enterCode: "コードを入力", + enterCodeAria: "聞こえるコードを入力してください。スペースキーを押して音声を再生します。", + error: "認証に失敗しました。後でもう一度試してください。", + expired: "認証が期限切れです。再試行してください。", + verificationRequired: "認証が必要です!", + footer: '保護されています ALTCHA', + getAudioChallenge: "音声チャレンジを取得", + label: "私はロボットではありません", + loading: "読み込み中...", + reload: "再読み込み", + verify: "確認", + verified: "確認済み", + verifying: "確認中...", + waitAlert: "確認中...少々お待ちください。" +}; +globalThis.altchaI18n.set("ja", ce); +const fe = { + ariaLinkLabel: "Altcha.org 방문하기", + enterCode: "코드 입력", + enterCodeAria: "들리는 코드를 입력하세요. 스페이스 바를 눌러 오디오를 재생합니다.", + error: "인증 실패. 나중에 다시 시도해주세요.", + expired: "인증이 만료되었습니다. 다시 시도해주세요.", + verificationRequired: "인증이 필요합니다!", + footer: 'ALTCHA에서 보호됨 ALTCHA', + getAudioChallenge: "오디오 챌린지 받기", + label: "저는 로봇이 아닙니다", + loading: "로딩 중...", + reload: "새로 고침", + verify: "확인", + verified: "확인됨", + verifying: "확인 중...", + waitAlert: "확인 중... 잠시만 기다려주세요." +}; +globalThis.altchaI18n.set("ko", fe); +const ue = { + ariaLinkLabel: "Altcha.org сайтына кіру", + enterCode: "Кодты енгізіңіз", + enterCodeAria: "Естіген кодыңызды енгізіңіз. Аудионы ойнату үшін Бос орынды басыңыз.", + error: "Тексеру сәтсіз аяқталды. Кейінірек қайталаңыз.", + expired: "Тексеру мерзімі аяқталды. Қайталаңыз.", + footer: 'ALTCHA қорғайды', + getAudioChallenge: "Аудио сынақ алу", + label: "Мен робот емеспін", + loading: "Жүктелуде...", + reload: "Қайта жүктеу", + verify: "Тексеру", + verificationRequired: "Тексеру талап етіледі!", + verified: "Тексерілді", + verifying: "Тексеруде...", + waitAlert: "Тексерілуде... күте тұрыңыз." +}; +globalThis.altchaI18n.set("kk", ue); +const be = { + ariaLinkLabel: "Altcha.org भेट द्या", + enterCode: "कोड टाकाा", + enterCodeAria: "तुम्ही ऐकत असलेला कोड टाका. ऑडिओ प्ले करण्यासाठी स्पेस दाबा.", + error: "पुष्टीकरण अयशस्वी झाले. कृपया नंतर पुन्हा प्रयत्न करा.", + expired: "पुष्टीकरण कालबाह्य झाले आहे. कृपया पुन्हा प्रयत्न करा.", + verificationRequired: "पडताळणी आवश्यक आहे!", + footer: 'द्वारे संरक्षित ALTCHA', + getAudioChallenge: "ऑडिओ चॅलेंज मिळवा", + label: "मी रोबोट नाही", + loading: "लोड होत आहे...", + reload: "पुन्हा लोड करा", + verify: "पुष्टीकरण करा", + verified: "पुष्टीकरण झाले", + verifying: "पुष्टीकरण करत आहे...", + waitAlert: "पुष्टीकरण करत आहे... कृपया थोडा वेळ थांबा." +}; +globalThis.altchaI18n.set("mr", be); +const ve = { + ariaLinkLabel: "Altcha.org ஐ பார்வையிடவும்", + enterCode: "குறியீட்டை உள்ளிடவும்", + enterCodeAria: "நீங்கள் கேட்கும் குறியீட்டை உள்ளிடவும். ஆடியோவை இயக்க Space ஐ அழுத்தவும்.", + error: "சரிபார்ப்பு தோல்வி. பிறகு மீண்டும் முயற்சிக்கவும்.", + expired: "சரிபார்ப்பு காலாவதியானது. மீண்டும் முயற்சிக்கவும்.", + verificationRequired: "சரிபார்ப்பு தேவை!", + footer: 'மூலமாக பாதுகாக்கப்பட்டவை ALTCHA', + getAudioChallenge: "ஒலி சவாலை பெறவும்", + label: "நான் ரோபோடான அல்ல", + loading: "செயலாக்கம்...", + reload: "மீண்டும் புதுப்பிக்கவும்", + verify: "சரிபார்க்கவும்", + verified: "சரிபார்க்கப்பட்டது", + verifying: "சரிபார்க்கப்படுகிறது...", + waitAlert: "சரிபார்க்கப்படுகிறது... தயவுசெய்து காத்திருக்கவும்." +}; +globalThis.altchaI18n.set("ta", ve); +const Ae = { + ariaLinkLabel: "Altcha.org సందర్శించండి", + enterCode: "కోడ్‌ని నమోదు చేయండి", + enterCodeAria: "మీరు విన్న కోడ్‌ని నమోదు చేయండి. ఆడియో ప్లే చేయడానికి స్పేస్‌ను నొక్కండి.", + error: "చెకింగ్ విఫలమైంది. దయచేసి మరల ప్రయత్నించండి.", + expired: "చెకింగ్ కాలం ముగిసింది. దయచేసి మరల ప్రయత్నించండి.", + verificationRequired: "ధృవీకరణ అవసరం!", + footer: 'ఈ సైట్ రక్షించబడింది ALTCHA', + getAudioChallenge: "ఆడియో ఛాలెంజ్ పొందండి", + label: "నేను రోబోట్ కాదు", + loading: "లోడ్ అవుతోంది...", + reload: "మళ్ళీ లోడ్ చేయండి", + verify: "ధ్రువీకరించు", + verified: "ధ్రువీకరించబడింది", + verifying: "ధ్రువీకరణ జరుగుతుంది...", + waitAlert: "ధ్రువీకరణ జరుగుతుంది... దయచేసి వేచి ఉండండి." +}; +globalThis.altchaI18n.set("te", Ae); +const ke = { + ariaLinkLabel: "เยี่ยมชม Altcha.org", + enterCode: "ป้อนรหัส", + enterCodeAria: "ป้อนรหัสที่คุณได้ยิน กด Space เพื่อเล่นเสียง", + error: "การตรวจสอบล้มเหลว กรุณาลองอีกครั้งภายหลัง", + expired: "การตรวจสอบหมดอายุ กรุณาลองใหม่", + verificationRequired: "จำเป็นต้องตรวจสอบ!", + footer: 'ป้องกันโดย ALTCHA', + getAudioChallenge: "รับการท้าทายเสียง", + label: "ฉันไม่ใช่บอท", + loading: "กำลังโหลด...", + reload: "โหลดใหม่", + verify: "ตรวจสอบ", + verified: "ตรวจสอบแล้ว", + verifying: "กำลังตรวจสอบ...", + waitAlert: "กำลังตรวจสอบ... กรุณารอ" +}; +globalThis.altchaI18n.set("th", ke); +const pe = { + ariaLinkLabel: "Altcha.org پر جائیں", + enterCode: "کوڈ درج کریں", + enterCodeAria: "جو کوڈ آپ سنتے ہیں وہ درج کریں۔ آڈیو چلانے کے لیے اسپیس دبائیں۔", + error: "توثیق ناکام ہو گئی۔ براہ کرم بعد میں دوبارہ کوشش کریں۔", + expired: "توثیق کی مدت ختم ہو گئی ہے۔ براہ کرم دوبارہ کوشش کریں۔", + verificationRequired: "تصدیق ضروری ہے!", + footer: 'کے ذریعے محفوظ ALTCHA', + getAudioChallenge: "آڈیو چیلنج حاصل کریں", + label: "میں روبوٹ نہیں ہوں", + loading: "لوڈ ہو رہا ہے...", + reload: "دوبارہ لوڈ کریں", + verify: "توثیق کریں", + verified: "توثیق شدہ", + verifying: "توثیق ہو رہی ہے...", + waitAlert: "توثیق ہو رہی ہے... براہ کرم انتظار کریں۔" +}; +globalThis.altchaI18n.set("ur", pe); +const Ce = { + ariaLinkLabel: "Altcha.org saytiga tashrif buyuring", + enterCode: "Kodni kiriting", + enterCodeAria: "Eshitgan kodingizni kiriting. Audioni ijro etish uchun Bo'sh joy tugmasini bosing.", + error: "Tekshiruv muvaffaqiyatsiz tugadi. Keyinroq qayta urinib ko'ring.", + expired: "Tekshiruv muddati tugadi. Qayta urinib ko'ring.", + footer: 'ALTCHA tomonidan himoyalangan', + getAudioChallenge: "Audio sinovni olish", + label: "Men robot emasman", + loading: "Yuklanmoqda...", + reload: "Qayta yuklash", + verify: "Tekshirish", + verificationRequired: "Tekshiruv talab qilinadi!", + verified: "Tekshirildi", + verifying: "Tekshirilmoqda...", + waitAlert: "Tekshirilmoqda... iltimos kuting." +}; +globalThis.altchaI18n.set("uz", Ce); +const ye = { + ariaLinkLabel: "Truy cập Altcha.org", + enterCode: "Nhập mã", + enterCodeAria: "Nhập mã bạn nghe được. Nhấn Phím cách để phát âm thanh.", + error: "Xác minh thất bại. Vui lòng thử lại sau.", + expired: "Xác minh đã hết hạn. Vui lòng thử lại.", + verificationRequired: "Yêu cầu xác minh!", + footer: 'Được bảo vệ bởi ALTCHA', + getAudioChallenge: "Nhận thử thách âm thanh", + label: "Tôi không phải là robot", + loading: "Đang tải...", + reload: "Tải lại", + verify: "Xác minh", + verified: "Đã xác minh", + verifying: "Đang xác minh...", + waitAlert: "Đang xác minh... vui lòng chờ." +}; +globalThis.altchaI18n.set("vi", ye); +const Le = { + ariaLinkLabel: "访问 Altcha.org", + enterCode: "输入代码", + enterCodeAria: "输入您听到的代码。按空格键播放音频。", + error: "验证失败。稍后再试。", + expired: "验证已过期。请重试。", + verificationRequired: "需要验证!", + footer: '由 ALTCHA 保护', + getAudioChallenge: "获取音频挑战", + label: "我不是机器人", + loading: "加载中...", + reload: "重新加载", + verify: "验证", + verified: "已验证", + verifying: "正在验证...", + waitAlert: "正在验证... 请稍等。" +}; +globalThis.altchaI18n.set("zh-cn", Le); +const me = { + ariaLinkLabel: "訪問 Altcha.org", + enterCode: "輸入代碼", + enterCodeAria: "輸入您聽到的代碼。按空格鍵播放音頻。", + error: "驗證失敗。稍後再試。", + expired: "驗證已過期。請重試。", + verificationRequired: "需要驗證!", + footer: '由 ALTCHA 保護', + getAudioChallenge: "獲取音頻挑戰", + label: "我不是機器人", + loading: "載入中...", + reload: "重新載入", + verify: "驗證", + verified: "已驗證", + verifying: "正在驗證...", + waitAlert: "正在驗證... 請稍等。" +}; +globalThis.altchaI18n.set("zh-tw", me); diff --git a/website_altcha/static/lib/altcha.js b/website_altcha/static/lib/altcha.js new file mode 100644 index 0000000000..018773fca6 --- /dev/null +++ b/website_altcha/static/lib/altcha.js @@ -0,0 +1,3106 @@ +/** @odoo-module **/ +const Yn = `(function(){"use strict";const d=new TextEncoder;function p(e){return[...new Uint8Array(e)].map(t=>t.toString(16).padStart(2,"0")).join("")}async function b(e,t,r){if(typeof crypto>"u"||!("subtle"in crypto)||!("digest"in crypto.subtle))throw new Error("Web Crypto is not available. Secure context is required (https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts).");return p(await crypto.subtle.digest(r.toUpperCase(),d.encode(e+t)))}function w(e,t,r="SHA-256",n=1e6,l=0){const o=new AbortController,a=Date.now();return{promise:(async()=>{for(let c=l;c<=n;c+=1){if(o.signal.aborted)return null;if(await b(t,c,r)===e)return{number:c,took:Date.now()-a}}return null})(),controller:o}}function h(e){const t=atob(e),r=new Uint8Array(t.length);for(let n=0;n{for(let i=n;i<=r;i+=1){if(o.signal.aborted||!c||!u)return null;try{const f=await crypto.subtle.decrypt({name:l,iv:g(i)},c,u);if(f)return{clearText:new TextDecoder().decode(f),took:Date.now()-a}}catch{}}return null};let c=null,u=null;try{u=h(e);const i=await crypto.subtle.digest("SHA-256",d.encode(t));c=await crypto.subtle.importKey("raw",i,l,!1,["decrypt"])}catch{return{promise:Promise.reject(),controller:o}}return{promise:s(),controller:o}}let y;onmessage=async e=>{const{type:t,payload:r,start:n,max:l}=e.data;let o=null;if(t==="abort")y?.abort(),y=void 0;else if(t==="work"){if("obfuscated"in r){const{key:a,obfuscated:s}=r||{};o=await m(s,a,l,n)}else{const{algorithm:a,challenge:s,salt:c}=r||{};o=w(s,c,a,l,n)}y=o.controller,o.promise.then(a=>{self.postMessage(a&&{...a,worker:!0})})}}})(); +`, Dn = typeof self < "u" && self.Blob && new Blob(["(self.URL || self.webkitURL).revokeObjectURL(self.location.href);", Yn], { type: "text/javascript;charset=utf-8" }); +function Ni(e) { + let t; + try { + if (t = Dn && (self.URL || self.webkitURL).createObjectURL(Dn), !t) throw ""; + const r = new Worker(t, { + name: e?.name + }); + return r.addEventListener("error", () => { + (self.URL || self.webkitURL).revokeObjectURL(t); + }), r; + } catch { + return new Worker( + "data:text/javascript;charset=utf-8," + encodeURIComponent(Yn), + { + name: e?.name + } + ); + } +} +const Li = "5"; +typeof window < "u" && ((window.__svelte ??= {}).v ??= /* @__PURE__ */ new Set()).add(Li); +const Pi = 1, Oi = 4, Fi = 8, Mi = 16, Vi = 1, Ui = 2, Mr = "[", Zn = "[!", zn = "]", bt = {}, ae = Symbol(), ji = "http://www.w3.org/1999/xhtml", Nn = !1; +function Jn(e) { + throw new Error("https://svelte.dev/e/lifecycle_outside_component"); +} +var Kn = Array.isArray, qi = Array.prototype.indexOf, Bi = Array.from, or = Object.keys, Mt = Object.defineProperty, rt = Object.getOwnPropertyDescriptor, Hi = Object.getOwnPropertyDescriptors, Gi = Object.prototype, Wi = Array.prototype, Xn = Object.getPrototypeOf, Ln = Object.isExtensible; +const yt = () => { +}; +function Qn(e) { + for (var t = 0; t < e.length; t++) + e[t](); +} +function Yi(e, t, r = !1) { + return e === void 0 ? r ? ( + /** @type {() => V} */ + t() + ) : ( + /** @type {V} */ + t + ) : e; +} +const me = 2, eo = 4, fr = 8, Vr = 16, De = 32, it = 64, ir = 128, fe = 256, ar = 512, le = 1024, Ie = 2048, at = 4096, wt = 8192, dr = 16384, Zi = 32768, Ur = 65536, zi = 1 << 19, to = 1 << 20, Sr = 1 << 21, Ot = Symbol("$state"), ro = Symbol("legacy props"), Ji = Symbol(""); +function Ki(e) { + throw new Error("https://svelte.dev/e/effect_in_teardown"); +} +function Xi() { + throw new Error("https://svelte.dev/e/effect_in_unowned_derived"); +} +function Qi(e) { + throw new Error("https://svelte.dev/e/effect_orphan"); +} +function ea() { + throw new Error("https://svelte.dev/e/effect_update_depth_exceeded"); +} +function ta() { + throw new Error("https://svelte.dev/e/hydration_failed"); +} +function ra(e) { + throw new Error("https://svelte.dev/e/props_invalid_value"); +} +function na() { + throw new Error("https://svelte.dev/e/state_descriptors_fixed"); +} +function oa() { + throw new Error("https://svelte.dev/e/state_prototype_fixed"); +} +function ia() { + throw new Error("https://svelte.dev/e/state_unsafe_mutation"); +} +function hr(e) { + console.warn("https://svelte.dev/e/hydration_mismatch"); +} +let O = !1; +function _t(e) { + O = e; +} +let P; +function Ue(e) { + if (e === null) + throw hr(), bt; + return P = e; +} +function Et() { + return Ue( + /** @type {TemplateNode} */ + /* @__PURE__ */ Be(P) + ); +} +function Z(e) { + if (O) { + if (/* @__PURE__ */ Be(P) !== null) + throw hr(), bt; + P = e; + } +} +function aa() { + for (var e = 0, t = P; ; ) { + if (t.nodeType === 8) { + var r = ( + /** @type {Comment} */ + t.data + ); + if (r === zn) { + if (e === 0) return t; + e -= 1; + } else (r === Mr || r === Zn) && (e += 1); + } + var o = ( + /** @type {TemplateNode} */ + /* @__PURE__ */ Be(t) + ); + t.remove(), t = o; + } +} +let la = !1; +function Me(e) { + if (typeof e != "object" || e === null || Ot in e) + return e; + const t = Xn(e); + if (t !== Gi && t !== Wi) + return e; + var r = /* @__PURE__ */ new Map(), o = Kn(e), l = /* @__PURE__ */ N(0), a = $, s = (c) => { + var f = $; + Re(a); + var d = c(); + return Re(f), d; + }; + return o && r.set("length", /* @__PURE__ */ N( + /** @type {any[]} */ + e.length + )), new Proxy( + /** @type {any} */ + e, + { + defineProperty(c, f, d) { + (!("value" in d) || d.configurable === !1 || d.enumerable === !1 || d.writable === !1) && na(); + var m = r.get(f); + return m === void 0 ? (m = s(() => /* @__PURE__ */ N(d.value)), r.set(f, m)) : b( + m, + s(() => Me(d.value)) + ), !0; + }, + deleteProperty(c, f) { + var d = r.get(f); + if (d === void 0) + f in c && (r.set( + f, + s(() => /* @__PURE__ */ N(ae)) + ), Ir(l)); + else { + if (o && typeof f == "string") { + var m = ( + /** @type {Source} */ + r.get("length") + ), v = Number(f); + Number.isInteger(v) && v < m.v && b(m, v); + } + b(d, ae), Ir(l); + } + return !0; + }, + get(c, f, d) { + if (f === Ot) + return e; + var m = r.get(f), v = f in c; + if (m === void 0 && (!v || rt(c, f)?.writable) && (m = s(() => /* @__PURE__ */ N(Me(v ? c[f] : ae))), r.set(f, m)), m !== void 0) { + var _ = i(m); + return _ === ae ? void 0 : _; + } + return Reflect.get(c, f, d); + }, + getOwnPropertyDescriptor(c, f) { + var d = Reflect.getOwnPropertyDescriptor(c, f); + if (d && "value" in d) { + var m = r.get(f); + m && (d.value = i(m)); + } else if (d === void 0) { + var v = r.get(f), _ = v?.v; + if (v !== void 0 && _ !== ae) + return { + enumerable: !0, + configurable: !0, + value: _, + writable: !0 + }; + } + return d; + }, + has(c, f) { + if (f === Ot) + return !0; + var d = r.get(f), m = d !== void 0 && d.v !== ae || Reflect.has(c, f); + if (d !== void 0 || S !== null && (!m || rt(c, f)?.writable)) { + d === void 0 && (d = s(() => /* @__PURE__ */ N(m ? Me(c[f]) : ae)), r.set(f, d)); + var v = i(d); + if (v === ae) + return !1; + } + return m; + }, + set(c, f, d, m) { + var v = r.get(f), _ = f in c; + if (o && f === "length") + for (var w = d; w < /** @type {Source} */ + v.v; w += 1) { + var F = r.get(w + ""); + F !== void 0 ? b(F, ae) : w in c && (F = s(() => /* @__PURE__ */ N(ae)), r.set(w + "", F)); + } + v === void 0 ? (!_ || rt(c, f)?.writable) && (v = s(() => /* @__PURE__ */ N(void 0)), b( + v, + s(() => Me(d)) + ), r.set(f, v)) : (_ = v.v !== ae, b( + v, + s(() => Me(d)) + )); + var M = Reflect.getOwnPropertyDescriptor(c, f); + if (M?.set && M.set.call(m, d), !_) { + if (o && typeof f == "string") { + var U = ( + /** @type {Source} */ + r.get("length") + ), I = Number(f); + Number.isInteger(I) && I >= U.v && b(U, I + 1); + } + Ir(l); + } + return !0; + }, + ownKeys(c) { + i(l); + var f = Reflect.ownKeys(c).filter((v) => { + var _ = r.get(v); + return _ === void 0 || _.v !== ae; + }); + for (var [d, m] of r) + m.v !== ae && !(d in c) && f.push(d); + return f; + }, + setPrototypeOf() { + oa(); + } + } + ); +} +function Ir(e, t = 1) { + b(e, e.v + t); +} +var Pn, no, oo, io; +function Tr() { + if (Pn === void 0) { + Pn = window, no = /Firefox/.test(navigator.userAgent); + var e = Element.prototype, t = Node.prototype, r = Text.prototype; + oo = rt(t, "firstChild").get, io = rt(t, "nextSibling").get, Ln(e) && (e.__click = void 0, e.__className = void 0, e.__attributes = null, e.__style = void 0, e.__e = void 0), Ln(r) && (r.__t = void 0); + } +} +function vr(e = "") { + return document.createTextNode(e); +} +// @__NO_SIDE_EFFECTS__ +function ve(e) { + return oo.call(e); +} +// @__NO_SIDE_EFFECTS__ +function Be(e) { + return io.call(e); +} +function z(e, t) { + if (!O) + return /* @__PURE__ */ ve(e); + var r = ( + /** @type {TemplateNode} */ + /* @__PURE__ */ ve(P) + ); + return r === null && (r = P.appendChild(vr())), Ue(r), r; +} +function Nt(e, t) { + if (!O) { + var r = ( + /** @type {DocumentFragment} */ + /* @__PURE__ */ ve( + /** @type {Node} */ + e + ) + ); + return r instanceof Comment && r.data === "" ? /* @__PURE__ */ Be(r) : r; + } + return P; +} +function J(e, t = 1, r = !1) { + let o = O ? P : e; + for (var l; t--; ) + l = o, o = /** @type {TemplateNode} */ + /* @__PURE__ */ Be(o); + if (!O) + return o; + var a = o?.nodeType; + if (r && a !== 3) { + var s = vr(); + return o === null ? l?.after(s) : o.before(s), Ue(s), s; + } + return Ue(o), /** @type {TemplateNode} */ + o; +} +function sa(e) { + e.textContent = ""; +} +function ao(e) { + return e === this.v; +} +function lo(e, t) { + return e != e ? t == t : e !== t || e !== null && typeof e == "object" || typeof e == "function"; +} +function jr(e) { + return !lo(e, this.v); +} +// @__NO_SIDE_EFFECTS__ +function gr(e) { + var t = me | Ie, r = $ !== null && ($.f & me) !== 0 ? ( + /** @type {Derived} */ + $ + ) : null; + return S === null || r !== null && (r.f & fe) !== 0 ? t |= fe : S.f |= to, { + ctx: ne, + deps: null, + effects: null, + equals: ao, + f: t, + fn: e, + reactions: null, + rv: 0, + v: ( + /** @type {V} */ + null + ), + wv: 0, + parent: r ?? S + }; +} +// @__NO_SIDE_EFFECTS__ +function Lt(e) { + const t = /* @__PURE__ */ gr(e); + return wo(t), t; +} +// @__NO_SIDE_EFFECTS__ +function ua(e) { + const t = /* @__PURE__ */ gr(e); + return t.equals = jr, t; +} +function so(e) { + var t = e.effects; + if (t !== null) { + e.effects = null; + for (var r = 0; r < t.length; r += 1) + je( + /** @type {Effect} */ + t[r] + ); + } +} +function ca(e) { + for (var t = e.parent; t !== null; ) { + if ((t.f & me) === 0) + return ( + /** @type {Effect} */ + t + ); + t = t.parent; + } + return null; +} +function uo(e) { + var t, r = S; + qe(ca(e)); + try { + so(e), t = ko(e); + } finally { + qe(r); + } + return t; +} +function co(e) { + var t = uo(e), r = (Ve || (e.f & fe) !== 0) && e.deps !== null ? at : le; + _e(e, r), e.equals(t) || (e.v = t, e.wv = xo()); +} +function fa(e) { + S === null && $ === null && Qi(), $ !== null && ($.f & fe) !== 0 && S === null && Xi(), qt && Ki(); +} +function da(e, t) { + var r = t.last; + r === null ? t.last = t.first = e : (r.next = e, e.prev = r, t.last = e); +} +function lt(e, t, r, o = !0) { + var l = S, a = { + ctx: ne, + deps: null, + nodes_start: null, + nodes_end: null, + f: e | Ie, + first: null, + fn: t, + last: null, + next: null, + parent: l, + prev: null, + teardown: null, + transitions: null, + wv: 0 + }; + if (r) + try { + Wr(a), a.f |= Zi; + } catch (f) { + throw je(a), f; + } + else t !== null && mr(a); + var s = r && a.deps === null && a.first === null && a.nodes_start === null && a.teardown === null && (a.f & (to | ir)) === 0; + if (!s && o && (l !== null && da(a, l), $ !== null && ($.f & me) !== 0)) { + var c = ( + /** @type {Derived} */ + $ + ); + (c.effects ??= []).push(a); + } + return a; +} +function qr(e) { + const t = lt(fr, null, !1); + return _e(t, le), t.teardown = e, t; +} +function Dr(e) { + fa(); + var t = S !== null && (S.f & De) !== 0 && ne !== null && !ne.m; + if (t) { + var r = ( + /** @type {ComponentContext} */ + ne + ); + (r.e ??= []).push({ + fn: e, + effect: S, + reaction: $ + }); + } else { + var o = Br(e); + return o; + } +} +function ha(e) { + const t = lt(it, e, !0); + return () => { + je(t); + }; +} +function va(e) { + const t = lt(it, e, !0); + return (r = {}) => new Promise((o) => { + r.outro ? Lr(t, () => { + je(t), o(void 0); + }) : (je(t), o(void 0)); + }); +} +function Br(e) { + return lt(eo, e, !1); +} +function Hr(e) { + return lt(fr, e, !0); +} +function Ce(e, t = [], r = gr) { + const o = t.map(r); + return fo(() => e(...o.map(i))); +} +function fo(e, t = 0) { + return lt(fr | Vr | t, e, !0); +} +function Nr(e, t = !0) { + return lt(fr | De, e, !0, t); +} +function ho(e) { + var t = e.teardown; + if (t !== null) { + const r = qt, o = $; + Fn(!0), Re(null); + try { + t.call(null); + } finally { + Fn(r), Re(o); + } + } +} +function vo(e, t = !1) { + var r = e.first; + for (e.first = e.last = null; r !== null; ) { + var o = r.next; + (r.f & it) !== 0 ? r.parent = null : je(r, t), r = o; + } +} +function ga(e) { + for (var t = e.first; t !== null; ) { + var r = t.next; + (t.f & De) === 0 && je(t), t = r; + } +} +function je(e, t = !0) { + var r = !1; + (t || (e.f & zi) !== 0) && e.nodes_start !== null && (go( + e.nodes_start, + /** @type {TemplateNode} */ + e.nodes_end + ), r = !0), vo(e, t && !r), cr(e, 0), _e(e, dr); + var o = e.transitions; + if (o !== null) + for (const a of o) + a.stop(); + ho(e); + var l = e.parent; + l !== null && l.first !== null && po(e), e.next = e.prev = e.teardown = e.ctx = e.deps = e.fn = e.nodes_start = e.nodes_end = null; +} +function go(e, t) { + for (; e !== null; ) { + var r = e === t ? null : ( + /** @type {TemplateNode} */ + /* @__PURE__ */ Be(e) + ); + e.remove(), e = r; + } +} +function po(e) { + var t = e.parent, r = e.prev, o = e.next; + r !== null && (r.next = o), o !== null && (o.prev = r), t !== null && (t.first === e && (t.first = o), t.last === e && (t.last = r)); +} +function Lr(e, t) { + var r = []; + mo(e, r, !0), pa(r, () => { + je(e), t && t(); + }); +} +function pa(e, t) { + var r = e.length; + if (r > 0) { + var o = () => --r || t(); + for (var l of e) + l.out(o); + } else + t(); +} +function mo(e, t, r) { + if ((e.f & wt) === 0) { + if (e.f ^= wt, e.transitions !== null) + for (const s of e.transitions) + (s.is_global || r) && t.push(s); + for (var o = e.first; o !== null; ) { + var l = o.next, a = (o.f & Ur) !== 0 || (o.f & De) !== 0; + mo(o, t, a ? r : !1), o = l; + } + } +} +function On(e) { + _o(e, !0); +} +function _o(e, t) { + if ((e.f & wt) !== 0) { + e.f ^= wt, (e.f & le) === 0 && (e.f ^= le), Bt(e) && (_e(e, Ie), mr(e)); + for (var r = e.first; r !== null; ) { + var o = r.next, l = (r.f & Ur) !== 0 || (r.f & De) !== 0; + _o(r, l ? t : !1), r = o; + } + if (e.transitions !== null) + for (const a of e.transitions) + (a.is_global || t) && a.in(); + } +} +const ma = typeof requestIdleCallback > "u" ? (e) => setTimeout(e, 1) : requestIdleCallback; +let Vt = [], Ut = []; +function bo() { + var e = Vt; + Vt = [], Qn(e); +} +function yo() { + var e = Ut; + Ut = [], Qn(e); +} +function Gr(e) { + Vt.length === 0 && queueMicrotask(bo), Vt.push(e); +} +function _a(e) { + Ut.length === 0 && ma(yo), Ut.push(e); +} +function ba() { + Vt.length > 0 && bo(), Ut.length > 0 && yo(); +} +let tr = !1, lr = !1, sr = null, nt = !1, qt = !1; +function Fn(e) { + qt = e; +} +let Ft = []; +let $ = null, ke = !1; +function Re(e) { + $ = e; +} +let S = null; +function qe(e) { + S = e; +} +let Te = null; +function wo(e) { + $ !== null && $.f & Sr && (Te === null ? Te = [e] : Te.push(e)); +} +let re = null, ce = 0, he = null; +function ya(e) { + he = e; +} +let Eo = 1, ur = 0, Ve = !1; +function xo() { + return ++Eo; +} +function Bt(e) { + var t = e.f; + if ((t & Ie) !== 0) + return !0; + if ((t & at) !== 0) { + var r = e.deps, o = (t & fe) !== 0; + if (r !== null) { + var l, a, s = (t & ar) !== 0, c = o && S !== null && !Ve, f = r.length; + if (s || c) { + var d = ( + /** @type {Derived} */ + e + ), m = d.parent; + for (l = 0; l < f; l++) + a = r[l], (s || !a?.reactions?.includes(d)) && (a.reactions ??= []).push(d); + s && (d.f ^= ar), c && m !== null && (m.f & fe) === 0 && (d.f ^= fe); + } + for (l = 0; l < f; l++) + if (a = r[l], Bt( + /** @type {Derived} */ + a + ) && co( + /** @type {Derived} */ + a + ), a.wv > e.wv) + return !0; + } + (!o || S !== null && !Ve) && _e(e, le); + } + return !1; +} +function wa(e, t) { + for (var r = t; r !== null; ) { + if ((r.f & ir) !== 0) + try { + r.fn(e); + return; + } catch { + r.f ^= ir; + } + r = r.parent; + } + throw tr = !1, e; +} +function Mn(e) { + return (e.f & dr) === 0 && (e.parent === null || (e.parent.f & ir) === 0); +} +function pr(e, t, r, o) { + if (tr) { + if (r === null && (tr = !1), Mn(t)) + throw e; + return; + } + if (r !== null && (tr = !0), wa(e, t), Mn(t)) + throw e; +} +function Co(e, t, r = !0) { + var o = e.reactions; + if (o !== null) + for (var l = 0; l < o.length; l++) { + var a = o[l]; + Te?.includes(e) || ((a.f & me) !== 0 ? Co( + /** @type {Derived} */ + a, + t, + !1 + ) : t === a && (r ? _e(a, Ie) : (a.f & le) !== 0 && _e(a, at), mr( + /** @type {Effect} */ + a + ))); + } +} +function ko(e) { + var t = re, r = ce, o = he, l = $, a = Ve, s = Te, c = ne, f = ke, d = e.f; + re = /** @type {null | Value[]} */ + null, ce = 0, he = null, Ve = (d & fe) !== 0 && (ke || !nt || $ === null), $ = (d & (De | it)) === 0 ? e : null, Te = null, Vn(e.ctx), ke = !1, ur++, e.f |= Sr; + try { + var m = ( + /** @type {Function} */ + (0, e.fn)() + ), v = e.deps; + if (re !== null) { + var _; + if (cr(e, ce), v !== null && ce > 0) + for (v.length = ce + re.length, _ = 0; _ < re.length; _++) + v[ce + _] = re[_]; + else + e.deps = v = re; + if (!Ve) + for (_ = ce; _ < v.length; _++) + (v[_].reactions ??= []).push(e); + } else v !== null && ce < v.length && (cr(e, ce), v.length = ce); + if (To() && he !== null && !ke && v !== null && (e.f & (me | at | Ie)) === 0) + for (_ = 0; _ < /** @type {Source[]} */ + he.length; _++) + Co( + he[_], + /** @type {Effect} */ + e + ); + return l !== null && l !== e && (ur++, he !== null && (o === null ? o = he : o.push(.../** @type {Source[]} */ + he))), m; + } finally { + re = t, ce = r, he = o, $ = l, Ve = a, Te = s, Vn(c), ke = f, e.f ^= Sr; + } +} +function Ea(e, t) { + let r = t.reactions; + if (r !== null) { + var o = qi.call(r, e); + if (o !== -1) { + var l = r.length - 1; + l === 0 ? r = t.reactions = null : (r[o] = r[l], r.pop()); + } + } + r === null && (t.f & me) !== 0 && // Destroying a child effect while updating a parent effect can cause a dependency to appear + // to be unused, when in fact it is used by the currently-updating parent. Checking `new_deps` + // allows us to skip the expensive work of disconnecting and immediately reconnecting it + (re === null || !re.includes(t)) && (_e(t, at), (t.f & (fe | ar)) === 0 && (t.f ^= ar), so( + /** @type {Derived} **/ + t + ), cr( + /** @type {Derived} **/ + t, + 0 + )); +} +function cr(e, t) { + var r = e.deps; + if (r !== null) + for (var o = t; o < r.length; o++) + Ea(e, r[o]); +} +function Wr(e) { + var t = e.f; + if ((t & dr) === 0) { + _e(e, le); + var r = S, o = ne, l = nt; + S = e, nt = !0; + try { + (t & Vr) !== 0 ? ga(e) : vo(e), ho(e); + var a = ko(e); + e.teardown = typeof a == "function" ? a : null, e.wv = Eo; + var s = e.deps, c; + Nn && la && e.f & Ie; + } catch (f) { + pr(f, e, r, o || e.ctx); + } finally { + nt = l, S = r; + } + } +} +function xa() { + try { + ea(); + } catch (e) { + if (sr !== null) + pr(e, sr, null); + else + throw e; + } +} +function Ao() { + var e = nt; + try { + var t = 0; + for (nt = !0; Ft.length > 0; ) { + t++ > 1e3 && xa(); + var r = Ft, o = r.length; + Ft = []; + for (var l = 0; l < o; l++) { + var a = ka(r[l]); + Ca(a); + } + jt.clear(); + } + } finally { + lr = !1, nt = e, sr = null; + } +} +function Ca(e) { + var t = e.length; + if (t !== 0) + for (var r = 0; r < t; r++) { + var o = e[r]; + if ((o.f & (dr | wt)) === 0) + try { + Bt(o) && (Wr(o), o.deps === null && o.first === null && o.nodes_start === null && (o.teardown === null ? po(o) : o.fn = null)); + } catch (l) { + pr(l, o, null, o.ctx); + } + } +} +function mr(e) { + lr || (lr = !0, queueMicrotask(Ao)); + for (var t = sr = e; t.parent !== null; ) { + t = t.parent; + var r = t.f; + if ((r & (it | De)) !== 0) { + if ((r & le) === 0) return; + t.f ^= le; + } + } + Ft.push(t); +} +function ka(e) { + for (var t = [], r = e; r !== null; ) { + var o = r.f, l = (o & (De | it)) !== 0, a = l && (o & le) !== 0; + if (!a && (o & wt) === 0) { + if ((o & eo) !== 0) + t.push(r); + else if (l) + r.f ^= le; + else + try { + Bt(r) && Wr(r); + } catch (f) { + pr(f, r, null, r.ctx); + } + var s = r.first; + if (s !== null) { + r = s; + continue; + } + } + var c = r.parent; + for (r = r.next; r === null && c !== null; ) + r = c.next, c = c.parent; + } + return t; +} +function E(e) { + for (var t; ; ) { + if (ba(), Ft.length === 0) + return ( + /** @type {T} */ + t + ); + lr = !0, Ao(); + } +} +async function Rr() { + await Promise.resolve(), E(); +} +function i(e) { + var t = e.f, r = (t & me) !== 0; + if ($ !== null && !ke) { + if (!Te?.includes(e)) { + var o = $.deps; + e.rv < ur && (e.rv = ur, re === null && o !== null && o[ce] === e ? ce++ : re === null ? re = [e] : (!Ve || !re.includes(e)) && re.push(e)); + } + } else if (r && /** @type {Derived} */ + e.deps === null && /** @type {Derived} */ + e.effects === null) { + var l = ( + /** @type {Derived} */ + e + ), a = l.parent; + a !== null && (a.f & fe) === 0 && (l.f ^= fe); + } + return r && (l = /** @type {Derived} */ + e, Bt(l) && co(l)), qt && jt.has(e) ? jt.get(e) : e.v; +} +function ot(e) { + var t = ke; + try { + return ke = !0, e(); + } finally { + ke = t; + } +} +const Aa = -7169; +function _e(e, t) { + e.f = e.f & Aa | t; +} +const jt = /* @__PURE__ */ new Map(); +function Io(e, t) { + var r = { + f: 0, + // TODO ideally we could skip this altogether, but it causes type errors + v: e, + reactions: null, + equals: ao, + rv: 0, + wv: 0 + }; + return r; +} +// @__NO_SIDE_EFFECTS__ +function N(e, t) { + const r = Io(e); + return wo(r), r; +} +// @__NO_SIDE_EFFECTS__ +function Yr(e, t = !1) { + const r = Io(e); + return t || (r.equals = jr), r; +} +function b(e, t, r = !1) { + $ !== null && !ke && To() && ($.f & (me | Vr)) !== 0 && !Te?.includes(e) && ia(); + let o = r ? Me(t) : t; + return Ia(e, o); +} +function Ia(e, t) { + if (!e.equals(t)) { + var r = e.v; + qt ? jt.set(e, t) : jt.set(e, r), e.v = t, (e.f & me) !== 0 && ((e.f & Ie) !== 0 && uo( + /** @type {Derived} */ + e + ), _e(e, (e.f & fe) === 0 ? le : at)), e.wv = xo(), Ro(e, Ie), S !== null && (S.f & le) !== 0 && (S.f & (De | it)) === 0 && (he === null ? ya([e]) : he.push(e)); + } + return t; +} +function Ro(e, t) { + var r = e.reactions; + if (r !== null) + for (var o = r.length, l = 0; l < o; l++) { + var a = r[l], s = a.f; + (s & Ie) === 0 && (_e(a, t), (s & (le | fe)) !== 0 && ((s & me) !== 0 ? Ro( + /** @type {Derived} */ + a, + at + ) : mr( + /** @type {Effect} */ + a + ))); + } +} +let ne = null; +function Vn(e) { + ne = e; +} +function $o(e, t = !1, r) { + var o = ne = { + p: ne, + c: null, + d: !1, + e: null, + m: !1, + s: e, + x: null, + l: null + }; + qr(() => { + o.d = !0; + }); +} +function So(e) { + const t = ne; + if (t !== null) { + e !== void 0 && (t.x = e); + const s = t.e; + if (s !== null) { + var r = S, o = $; + t.e = null; + try { + for (var l = 0; l < s.length; l++) { + var a = s[l]; + qe(a.effect), Re(a.reaction), Br(a.fn); + } + } finally { + qe(r), Re(o); + } + } + ne = t.p, t.m = !0; + } + return e || /** @type {T} */ + {}; +} +function To() { + return !0; +} +const Ra = ["touchstart", "touchmove"]; +function $a(e) { + return Ra.includes(e); +} +function Sa(e, t) { + if (t) { + const r = document.body; + e.autofocus = !0, Gr(() => { + document.activeElement === r && e.focus(); + }); + } +} +let Un = !1; +function Do() { + Un || (Un = !0, document.addEventListener( + "reset", + (e) => { + Promise.resolve().then(() => { + if (!e.defaultPrevented) + for ( + const t of + /**@type {HTMLFormElement} */ + e.target.elements + ) + t.__on_r?.(); + }); + }, + // In the capture phase to guarantee we get noticed of it (no possiblity of stopPropagation) + { capture: !0 } + )); +} +function No(e) { + var t = $, r = S; + Re(null), qe(null); + try { + return e(); + } finally { + Re(t), qe(r); + } +} +function Ta(e, t, r, o = r) { + e.addEventListener(t, () => No(r)); + const l = e.__on_r; + l ? e.__on_r = () => { + l(), o(!0); + } : e.__on_r = () => o(!0), Do(); +} +const Lo = /* @__PURE__ */ new Set(), Pr = /* @__PURE__ */ new Set(); +function Da(e, t, r, o = {}) { + function l(a) { + if (o.capture || Pt.call(t, a), !a.cancelBubble) + return No(() => r?.call(this, a)); + } + return e.startsWith("pointer") || e.startsWith("touch") || e === "wheel" ? Gr(() => { + t.addEventListener(e, l, o); + }) : t.addEventListener(e, l, o), l; +} +function Fe(e, t, r, o, l) { + var a = { capture: o, passive: l }, s = Da(e, t, r, a); + (t === document.body || t === window || t === document) && qr(() => { + t.removeEventListener(e, s, a); + }); +} +function Na(e) { + for (var t = 0; t < e.length; t++) + Lo.add(e[t]); + for (var r of Pr) + r(e); +} +function Pt(e) { + var t = this, r = ( + /** @type {Node} */ + t.ownerDocument + ), o = e.type, l = e.composedPath?.() || [], a = ( + /** @type {null | Element} */ + l[0] || e.target + ), s = 0, c = e.__root; + if (c) { + var f = l.indexOf(c); + if (f !== -1 && (t === document || t === /** @type {any} */ + window)) { + e.__root = t; + return; + } + var d = l.indexOf(t); + if (d === -1) + return; + f <= d && (s = f); + } + if (a = /** @type {Element} */ + l[s] || e.target, a !== t) { + Mt(e, "currentTarget", { + configurable: !0, + get() { + return a || r; + } + }); + var m = $, v = S; + Re(null), qe(null); + try { + for (var _, w = []; a !== null; ) { + var F = a.assignedSlot || a.parentNode || /** @type {any} */ + a.host || null; + try { + var M = a["__" + o]; + if (M != null && (!/** @type {any} */ + a.disabled || // DOM could've been updated already by the time this is reached, so we check this as well + // -> the target could not have been disabled because it emits the event in the first place + e.target === a)) + if (Kn(M)) { + var [U, ...I] = M; + U.apply(a, [e, ...I]); + } else + M.call(a, e); + } catch (ee) { + _ ? w.push(ee) : _ = ee; + } + if (e.cancelBubble || F === t || F === null) + break; + a = F; + } + if (_) { + for (let ee of w) + queueMicrotask(() => { + throw ee; + }); + throw _; + } + } finally { + e.__root = t, delete e.currentTarget, Re(m), qe(v); + } + } +} +function Zr(e) { + var t = document.createElement("template"); + return t.innerHTML = e, t.content; +} +function Ae(e, t) { + var r = ( + /** @type {Effect} */ + S + ); + r.nodes_start === null && (r.nodes_start = e, r.nodes_end = t); +} +// @__NO_SIDE_EFFECTS__ +function be(e, t) { + var r = (t & Vi) !== 0, o = (t & Ui) !== 0, l, a = !e.startsWith(""); + return () => { + if (O) + return Ae(P, null), P; + l === void 0 && (l = Zr(a ? e : "" + e), r || (l = /** @type {Node} */ + /* @__PURE__ */ ve(l))); + var s = ( + /** @type {TemplateNode} */ + o || no ? document.importNode(l, !0) : l.cloneNode(!0) + ); + if (r) { + var c = ( + /** @type {TemplateNode} */ + /* @__PURE__ */ ve(s) + ), f = ( + /** @type {TemplateNode} */ + s.lastChild + ); + Ae(c, f); + } else + Ae(s, s); + return s; + }; +} +// @__NO_SIDE_EFFECTS__ +function _r(e, t, r = "svg") { + var o = !e.startsWith(""), l = `<${r}>${o ? e : "" + e}`, a; + return () => { + if (O) + return Ae(P, null), P; + if (!a) { + var s = ( + /** @type {DocumentFragment} */ + Zr(l) + ), c = ( + /** @type {Element} */ + /* @__PURE__ */ ve(s) + ); + a = /** @type {Element} */ + /* @__PURE__ */ ve(c); + } + var f = ( + /** @type {TemplateNode} */ + a.cloneNode(!0) + ); + return Ae(f, f), f; + }; +} +function Xt() { + if (O) + return Ae(P, null), P; + var e = document.createDocumentFragment(), t = document.createComment(""), r = vr(); + return e.append(t, r), Ae(t, r), e; +} +function B(e, t) { + if (O) { + S.nodes_end = P, Et(); + return; + } + e !== null && e.before( + /** @type {Node} */ + t + ); +} +function La(e, t) { + var r = t == null ? "" : typeof t == "object" ? t + "" : t; + r !== (e.__t ??= e.nodeValue) && (e.__t = r, e.nodeValue = r + ""); +} +function Po(e, t) { + return Oo(e, t); +} +function Pa(e, t) { + Tr(), t.intro = t.intro ?? !1; + const r = t.target, o = O, l = P; + try { + for (var a = ( + /** @type {TemplateNode} */ + /* @__PURE__ */ ve(r) + ); a && (a.nodeType !== 8 || /** @type {Comment} */ + a.data !== Mr); ) + a = /** @type {TemplateNode} */ + /* @__PURE__ */ Be(a); + if (!a) + throw bt; + _t(!0), Ue( + /** @type {Comment} */ + a + ), Et(); + const s = Oo(e, { ...t, anchor: a }); + if (P === null || P.nodeType !== 8 || /** @type {Comment} */ + P.data !== zn) + throw hr(), bt; + return _t(!1), /** @type {Exports} */ + s; + } catch (s) { + if (s === bt) + return t.recover === !1 && ta(), Tr(), sa(r), _t(!1), Po(e, t); + throw s; + } finally { + _t(o), Ue(l); + } +} +const pt = /* @__PURE__ */ new Map(); +function Oo(e, { target: t, anchor: r, props: o = {}, events: l, context: a, intro: s = !0 }) { + Tr(); + var c = /* @__PURE__ */ new Set(), f = (v) => { + for (var _ = 0; _ < v.length; _++) { + var w = v[_]; + if (!c.has(w)) { + c.add(w); + var F = $a(w); + t.addEventListener(w, Pt, { passive: F }); + var M = pt.get(w); + M === void 0 ? (document.addEventListener(w, Pt, { passive: F }), pt.set(w, 1)) : pt.set(w, M + 1); + } + } + }; + f(Bi(Lo)), Pr.add(f); + var d = void 0, m = va(() => { + var v = r ?? t.appendChild(vr()); + return Nr(() => { + if (a) { + $o({}); + var _ = ( + /** @type {ComponentContext} */ + ne + ); + _.c = a; + } + l && (o.$$events = l), O && Ae( + /** @type {TemplateNode} */ + v, + null + ), d = e(v, o) || {}, O && (S.nodes_end = P), a && So(); + }), () => { + for (var _ of c) { + t.removeEventListener(_, Pt); + var w = ( + /** @type {number} */ + pt.get(_) + ); + --w === 0 ? (document.removeEventListener(_, Pt), pt.delete(_)) : pt.set(_, w); + } + Pr.delete(f), v !== r && v.parentNode?.removeChild(v); + }; + }); + return Or.set(d, m), d; +} +let Or = /* @__PURE__ */ new WeakMap(); +function Oa(e, t) { + const r = Or.get(e); + return r ? (Or.delete(e), r(t)) : Promise.resolve(); +} +function K(e, t, [r, o] = [0, 0]) { + O && r === 0 && Et(); + var l = e, a = null, s = null, c = ae, f = r > 0 ? Ur : 0, d = !1; + const m = (_, w = !0) => { + d = !0, v(w, _); + }, v = (_, w) => { + if (c === (c = _)) return; + let F = !1; + if (O && o !== -1) { + if (r === 0) { + const U = ( + /** @type {Comment} */ + l.data + ); + U === Mr ? o = 0 : U === Zn ? o = 1 / 0 : (o = parseInt(U.substring(1)), o !== o && (o = c ? 1 / 0 : -1)); + } + const M = o > r; + !!c === M && (l = aa(), Ue(l), _t(!1), F = !0, o = -1); + } + c ? (a ? On(a) : w && (a = Nr(() => w(l))), s && Lr(s, () => { + s = null; + })) : (s ? On(s) : w && (s = Nr(() => w(l, [r + 1, o]))), a && Lr(a, () => { + a = null; + })), F && _t(!0); + }; + fo(() => { + d = !1, t(m), d || v(null, null); + }, f), O && (l = P); +} +function tt(e, t, r = !1, o = !1, l = !1) { + var a = e, s = ""; + Ce(() => { + var c = ( + /** @type {Effect} */ + S + ); + if (s === (s = t() ?? "")) { + O && Et(); + return; + } + if (c.nodes_start !== null && (go( + c.nodes_start, + /** @type {TemplateNode} */ + c.nodes_end + ), c.nodes_start = c.nodes_end = null), s !== "") { + if (O) { + P.data; + for (var f = Et(), d = f; f !== null && (f.nodeType !== 8 || /** @type {Comment} */ + f.data !== ""); ) + d = f, f = /** @type {TemplateNode} */ + /* @__PURE__ */ Be(f); + if (f === null) + throw hr(), bt; + Ae(P, d), a = Ue(f); + return; + } + var m = s + ""; + r ? m = `${m}` : o && (m = `${m}`); + var v = Zr(m); + if ((r || o) && (v = /** @type {Element} */ + /* @__PURE__ */ ve(v)), Ae( + /** @type {TemplateNode} */ + /* @__PURE__ */ ve(v), + /** @type {TemplateNode} */ + v.lastChild + ), r || o) + for (; /* @__PURE__ */ ve(v); ) + a.before( + /** @type {Node} */ + /* @__PURE__ */ ve(v) + ); + else + a.before(v); + } + }); +} +function Fa(e, t, r, o, l) { + O && Et(); + var a = t.$$slots?.[r], s = !1; + a === !0 && (a = t.children, s = !0), a === void 0 || a(e, s ? () => o : o); +} +const jn = [...` +\r\f \v\uFEFF`]; +function Ma(e, t, r) { + var o = "" + e; + if (r) { + for (var l in r) + if (r[l]) + o = o ? o + " " + l : l; + else if (o.length) + for (var a = l.length, s = 0; (s = o.indexOf(l, s)) >= 0; ) { + var c = s + a; + (s === 0 || jn.includes(o[s - 1])) && (c === o.length || jn.includes(o[c])) ? o = (s === 0 ? "" : o.substring(0, s)) + o.substring(c + 1) : s = c; + } + } + return o === "" ? null : o; +} +function Va(e, t, r, o, l, a) { + var s = e.__className; + if (O || s !== r || s === void 0) { + var c = Ma(r, o, a); + (!O || c !== e.getAttribute("class")) && (c == null ? e.removeAttribute("class") : e.className = c), e.__className = r; + } else if (a && l !== a) + for (var f in a) { + var d = !!a[f]; + (l == null || d !== !!l[f]) && e.classList.toggle(f, d); + } + return a; +} +const Ua = Symbol("is custom element"), ja = Symbol("is html"); +function qn(e) { + if (O) { + var t = !1, r = () => { + if (!t) { + if (t = !0, e.hasAttribute("value")) { + var o = e.value; + R(e, "value", null), e.value = o; + } + if (e.hasAttribute("checked")) { + var l = e.checked; + R(e, "checked", null), e.checked = l; + } + } + }; + e.__on_r = r, _a(r), Do(); + } +} +function qa(e, t) { + var r = Fo(e); + r.value === (r.value = // treat null and undefined the same for the initial value + t ?? void 0) || // @ts-expect-error + // `progress` elements always need their value set when it's `0` + e.value === t && (t !== 0 || e.nodeName !== "PROGRESS") || (e.value = t ?? ""); +} +function R(e, t, r, o) { + var l = Fo(e); + O && (l[t] = e.getAttribute(t), t === "src" || t === "srcset" || t === "href" && e.nodeName === "LINK") || l[t] !== (l[t] = r) && (t === "loading" && (e[Ji] = r), r == null ? e.removeAttribute(t) : typeof r != "string" && Ba(e).includes(t) ? e[t] = r : e.setAttribute(t, r)); +} +function Fo(e) { + return ( + /** @type {Record} **/ + // @ts-expect-error + e.__attributes ??= { + [Ua]: e.nodeName.includes("-"), + [ja]: e.namespaceURI === ji + } + ); +} +var Bn = /* @__PURE__ */ new Map(); +function Ba(e) { + var t = Bn.get(e.nodeName); + if (t) return t; + Bn.set(e.nodeName, t = []); + for (var r, o = e, l = Element.prototype; l !== o; ) { + r = Hi(o); + for (var a in r) + r[a].set && t.push(a); + o = Xn(o); + } + return t; +} +function Ha(e, t, r = t) { + Ta(e, "change", (o) => { + var l = o ? e.defaultChecked : e.checked; + r(l); + }), // If we are hydrating and the value has since changed, + // then use the update value from the input instead. + (O && e.defaultChecked !== e.checked || // If defaultChecked is set, then checked == defaultChecked + ot(t) == null) && r(e.checked), Hr(() => { + var o = t(); + e.checked = !!o; + }); +} +function Hn(e, t) { + return e === t || e?.[Ot] === t; +} +function Qt(e = {}, t, r, o) { + return Br(() => { + var l, a; + return Hr(() => { + l = a, a = [], ot(() => { + e !== r(...a) && (t(e, ...a), l && Hn(r(...l), e) && t(null, ...l)); + }); + }), () => { + Gr(() => { + a && Hn(r(...a), e) && t(null, ...a); + }); + }; + }), e; +} +function Mo(e) { + ne === null && Jn(), Dr(() => { + const t = ot(e); + if (typeof t == "function") return ( + /** @type {() => void} */ + t + ); + }); +} +function Ga(e) { + ne === null && Jn(), Mo(() => () => ot(e)); +} +function Vo(e, t, r) { + if (e == null) + return t(void 0), yt; + const o = ot( + () => e.subscribe( + t, + // @ts-expect-error + r + ) + ); + return o.unsubscribe ? () => o.unsubscribe() : o; +} +const mt = []; +function Wa(e, t = yt) { + let r = null; + const o = /* @__PURE__ */ new Set(); + function l(c) { + if (lo(e, c) && (e = c, r)) { + const f = !mt.length; + for (const d of o) + d[1](), mt.push(d, e); + if (f) { + for (let d = 0; d < mt.length; d += 2) + mt[d][0](mt[d + 1]); + mt.length = 0; + } + } + } + function a(c) { + l(c( + /** @type {T} */ + e + )); + } + function s(c, f = yt) { + const d = [c, f]; + return o.add(d), o.size === 1 && (r = t(l, a) || yt), c( + /** @type {T} */ + e + ), () => { + o.delete(d), o.size === 0 && r && (r(), r = null); + }; + } + return { set: l, update: a, subscribe: s }; +} +function rr(e) { + let t; + return Vo(e, (r) => t = r)(), t; +} +let er = !1, Fr = Symbol(); +function Ya(e, t, r) { + const o = r[t] ??= { + store: null, + source: /* @__PURE__ */ Yr(void 0), + unsubscribe: yt + }; + if (o.store !== e && !(Fr in r)) + if (o.unsubscribe(), o.store = e ?? null, e == null) + o.source.v = void 0, o.unsubscribe = yt; + else { + var l = !0; + o.unsubscribe = Vo(e, (a) => { + l ? o.source.v = a : b(o.source, a); + }), l = !1; + } + return e && Fr in r ? rr(e) : i(o.source); +} +function Za() { + const e = {}; + function t() { + qr(() => { + for (var r in e) + e[r].unsubscribe(); + Mt(e, Fr, { + enumerable: !1, + value: !0 + }); + }); + } + return [e, t]; +} +function za(e) { + var t = er; + try { + return er = !1, [e(), er]; + } finally { + er = t; + } +} +function Gn(e) { + return e.ctx?.d ?? !1; +} +function x(e, t, r, o) { + var l = (r & Pi) !== 0, a = !0, s = (r & Fi) !== 0, c = (r & Mi) !== 0, f = !1, d; + s ? [d, f] = za(() => ( + /** @type {V} */ + e[t] + )) : d = /** @type {V} */ + e[t]; + var m = Ot in e || ro in e, v = s && (rt(e, t)?.set ?? (m && t in e && ((j) => e[t] = j))) || void 0, _ = ( + /** @type {V} */ + o + ), w = !0, F = !1, M = () => (F = !0, w && (w = !1, c ? _ = ot( + /** @type {() => V} */ + o + ) : _ = /** @type {V} */ + o), _); + d === void 0 && o !== void 0 && (v && a && ra(), d = M(), v && v(d)); + var U; + if (U = () => { + var j = ( + /** @type {V} */ + e[t] + ); + return j === void 0 ? M() : (w = !0, F = !1, j); + }, (r & Oi) === 0) + return U; + if (v) { + var I = e.$$legacy; + return function(j, se) { + return arguments.length > 0 ? ((!se || I || f) && v(se ? U() : j), j) : U(); + }; + } + var ee = !1, $e = /* @__PURE__ */ Yr(d), X = /* @__PURE__ */ gr(() => { + var j = U(), se = i($e); + return ee ? (ee = !1, se) : $e.v = j; + }); + return s && i(X), l || (X.equals = jr), function(j, se) { + if (arguments.length > 0) { + const He = se ? i(X) : s ? Me(j) : j; + if (!X.equals(He)) { + if (ee = !0, b($e, He), F && _ !== void 0 && (_ = He), Gn(X)) + return j; + ot(() => i(X)); + } + return j; + } + return Gn(X) ? X.v : i(X); + }; +} +function Ja(e) { + return new Ka(e); +} +class Ka { + /** @type {any} */ + #t; + /** @type {Record} */ + #e; + /** + * @param {ComponentConstructorOptions & { + * component: any; + * }} options + */ + constructor(t) { + var r = /* @__PURE__ */ new Map(), o = (a, s) => { + var c = /* @__PURE__ */ Yr(s); + return r.set(a, c), c; + }; + const l = new Proxy( + { ...t.props || {}, $$events: {} }, + { + get(a, s) { + return i(r.get(s) ?? o(s, Reflect.get(a, s))); + }, + has(a, s) { + return s === ro ? !0 : (i(r.get(s) ?? o(s, Reflect.get(a, s))), Reflect.has(a, s)); + }, + set(a, s, c) { + return b(r.get(s) ?? o(s, c), c), Reflect.set(a, s, c); + } + } + ); + this.#e = (t.hydrate ? Pa : Po)(t.component, { + target: t.target, + anchor: t.anchor, + props: l, + context: t.context, + intro: t.intro ?? !1, + recover: t.recover + }), (!t?.props?.$$host || t.sync === !1) && E(), this.#t = l.$$events; + for (const a of Object.keys(this.#e)) + a === "$set" || a === "$destroy" || a === "$on" || Mt(this, a, { + get() { + return this.#e[a]; + }, + /** @param {any} value */ + set(s) { + this.#e[a] = s; + }, + enumerable: !0 + }); + this.#e.$set = /** @param {Record} next */ + (a) => { + Object.assign(l, a); + }, this.#e.$destroy = () => { + Oa(this.#e); + }; + } + /** @param {Record} props */ + $set(t) { + this.#e.$set(t); + } + /** + * @param {string} event + * @param {(...args: any[]) => any} callback + * @returns {any} + */ + $on(t, r) { + this.#t[t] = this.#t[t] || []; + const o = (...l) => r.call(this, ...l); + return this.#t[t].push(o), () => { + this.#t[t] = this.#t[t].filter( + /** @param {any} fn */ + (l) => l !== o + ); + }; + } + $destroy() { + this.#e.$destroy(); + } +} +let Uo; +typeof HTMLElement == "function" && (Uo = class extends HTMLElement { + /** The Svelte component constructor */ + $$ctor; + /** Slots */ + $$s; + /** @type {any} The Svelte component instance */ + $$c; + /** Whether or not the custom element is connected */ + $$cn = !1; + /** @type {Record} Component props data */ + $$d = {}; + /** `true` if currently in the process of reflecting component props back to attributes */ + $$r = !1; + /** @type {Record} Props definition (name, reflected, type etc) */ + $$p_d = {}; + /** @type {Record} Event listeners */ + $$l = {}; + /** @type {Map} Event listener unsubscribe functions */ + $$l_u = /* @__PURE__ */ new Map(); + /** @type {any} The managed render effect for reflecting attributes */ + $$me; + /** + * @param {*} $$componentCtor + * @param {*} $$slots + * @param {*} use_shadow_dom + */ + constructor(e, t, r) { + super(), this.$$ctor = e, this.$$s = t, r && this.attachShadow({ mode: "open" }); + } + /** + * @param {string} type + * @param {EventListenerOrEventListenerObject} listener + * @param {boolean | AddEventListenerOptions} [options] + */ + addEventListener(e, t, r) { + if (this.$$l[e] = this.$$l[e] || [], this.$$l[e].push(t), this.$$c) { + const o = this.$$c.$on(e, t); + this.$$l_u.set(t, o); + } + super.addEventListener(e, t, r); + } + /** + * @param {string} type + * @param {EventListenerOrEventListenerObject} listener + * @param {boolean | AddEventListenerOptions} [options] + */ + removeEventListener(e, t, r) { + if (super.removeEventListener(e, t, r), this.$$c) { + const o = this.$$l_u.get(t); + o && (o(), this.$$l_u.delete(t)); + } + } + async connectedCallback() { + if (this.$$cn = !0, !this.$$c) { + let e = function(o) { + return (l) => { + const a = document.createElement("slot"); + o !== "default" && (a.name = o), B(l, a); + }; + }; + if (await Promise.resolve(), !this.$$cn || this.$$c) + return; + const t = {}, r = Xa(this); + for (const o of this.$$s) + o in r && (o === "default" && !this.$$d.children ? (this.$$d.children = e(o), t.default = !0) : t[o] = e(o)); + for (const o of this.attributes) { + const l = this.$$g_p(o.name); + l in this.$$d || (this.$$d[l] = nr(l, o.value, this.$$p_d, "toProp")); + } + for (const o in this.$$p_d) + !(o in this.$$d) && this[o] !== void 0 && (this.$$d[o] = this[o], delete this[o]); + this.$$c = Ja({ + component: this.$$ctor, + target: this.shadowRoot || this, + props: { + ...this.$$d, + $$slots: t, + $$host: this + } + }), this.$$me = ha(() => { + Hr(() => { + this.$$r = !0; + for (const o of or(this.$$c)) { + if (!this.$$p_d[o]?.reflect) continue; + this.$$d[o] = this.$$c[o]; + const l = nr( + o, + this.$$d[o], + this.$$p_d, + "toAttribute" + ); + l == null ? this.removeAttribute(this.$$p_d[o].attribute || o) : this.setAttribute(this.$$p_d[o].attribute || o, l); + } + this.$$r = !1; + }); + }); + for (const o in this.$$l) + for (const l of this.$$l[o]) { + const a = this.$$c.$on(o, l); + this.$$l_u.set(l, a); + } + this.$$l = {}; + } + } + // We don't need this when working within Svelte code, but for compatibility of people using this outside of Svelte + // and setting attributes through setAttribute etc, this is helpful + /** + * @param {string} attr + * @param {string} _oldValue + * @param {string} newValue + */ + attributeChangedCallback(e, t, r) { + this.$$r || (e = this.$$g_p(e), this.$$d[e] = nr(e, r, this.$$p_d, "toProp"), this.$$c?.$set({ [e]: this.$$d[e] })); + } + disconnectedCallback() { + this.$$cn = !1, Promise.resolve().then(() => { + !this.$$cn && this.$$c && (this.$$c.$destroy(), this.$$me(), this.$$c = void 0); + }); + } + /** + * @param {string} attribute_name + */ + $$g_p(e) { + return or(this.$$p_d).find( + (t) => this.$$p_d[t].attribute === e || !this.$$p_d[t].attribute && t.toLowerCase() === e + ) || e; + } +}); +function nr(e, t, r, o) { + const l = r[e]?.type; + if (t = l === "Boolean" && typeof t != "boolean" ? t != null : t, !o || !r[e]) + return t; + if (o === "toAttribute") + switch (l) { + case "Object": + case "Array": + return t == null ? null : JSON.stringify(t); + case "Boolean": + return t ? "" : null; + case "Number": + return t ?? null; + default: + return t; + } + else + switch (l) { + case "Object": + case "Array": + return t && JSON.parse(t); + case "Boolean": + return t; + // conversion already handled above + case "Number": + return t != null ? +t : t; + default: + return t; + } +} +function Xa(e) { + const t = {}; + return e.childNodes.forEach((r) => { + t[ + /** @type {Element} node */ + r.slot || "default" + ] = !0; + }), t; +} +function Qa(e, t, r, o, l, a) { + let s = class extends Uo { + constructor() { + super(e, r, l), this.$$p_d = t; + } + static get observedAttributes() { + return or(t).map( + (c) => (t[c].attribute || c).toLowerCase() + ); + } + }; + return or(t).forEach((c) => { + Mt(s.prototype, c, { + get() { + return this.$$c && c in this.$$c ? this.$$c[c] : this.$$d[c]; + }, + set(f) { + f = nr(c, f, t), this.$$d[c] = f; + var d = this.$$c; + if (d) { + var m = rt(d, c)?.get; + m ? d[c] = f : d.$set({ [c]: f }); + } + } + }); + }), o.forEach((c) => { + Mt(s.prototype, c, { + get() { + return this.$$c?.[c]; + } + }); + }), e.element = /** @type {any} */ + s, s; +} +const jo = new TextEncoder(); +function el(e) { + return [...new Uint8Array(e)].map((t) => t.toString(16).padStart(2, "0")).join(""); +} +async function tl(e, t = "SHA-256", r = 1e5) { + const o = Date.now().toString(16); + e || (e = Math.round(Math.random() * r)); + const l = await qo(o, e, t); + return { + algorithm: t, + challenge: l, + salt: o, + signature: "" + }; +} +async function qo(e, t, r) { + if (typeof crypto > "u" || !("subtle" in crypto) || !("digest" in crypto.subtle)) + throw new Error("Web Crypto is not available. Secure context is required (https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts)."); + return el( + await crypto.subtle.digest( + r.toUpperCase(), + jo.encode(e + t) + ) + ); +} +function rl(e, t, r = "SHA-256", o = 1e6, l = 0) { + const a = new AbortController(), s = Date.now(); + return { + promise: (async () => { + for (let f = l; f <= o; f += 1) { + if (a.signal.aborted) + return null; + if (await qo(t, f, r) === e) + return { + number: f, + took: Date.now() - s + }; + } + return null; + })(), + controller: a + }; +} +function Wn() { + try { + return Intl.DateTimeFormat().resolvedOptions().timeZone; + } catch { + } +} +function nl(e) { + const t = atob(e), r = new Uint8Array(t.length); + for (let o = 0; o < t.length; o++) + r[o] = t.charCodeAt(o); + return r; +} +function ol(e, t = 12) { + const r = new Uint8Array(t); + for (let o = 0; o < t; o++) + r[o] = e % 256, e = Math.floor(e / 256); + return r; +} +async function il(e, t = "", r = 1e6, o = 0) { + const l = "AES-GCM", a = new AbortController(), s = Date.now(), c = async () => { + for (let m = o; m <= r; m += 1) { + if (a.signal.aborted || !f || !d) + return null; + try { + const v = await crypto.subtle.decrypt( + { + name: l, + iv: ol(m) + }, + f, + d + ); + if (v) + return { + clearText: new TextDecoder().decode(v), + took: Date.now() - s + }; + } catch { + } + } + return null; + }; + let f = null, d = null; + try { + d = nl(e); + const m = await crypto.subtle.digest( + "SHA-256", + jo.encode(t) + ); + f = await crypto.subtle.importKey( + "raw", + m, + l, + !1, + ["decrypt"] + ); + } catch { + return { + promise: Promise.reject(), + controller: a + }; + } + return { + promise: c(), + controller: a + }; +} +var y = /* @__PURE__ */ ((e) => (e.CODE = "code", e.ERROR = "error", e.VERIFIED = "verified", e.VERIFYING = "verifying", e.UNVERIFIED = "unverified", e.EXPIRED = "expired", e))(y || {}), Q = /* @__PURE__ */ ((e) => (e.ERROR = "error", e.LOADING = "loading", e.PLAYING = "playing", e.PAUSED = "paused", e.READY = "ready", e))(Q || {}); +globalThis.altchaPlugins = globalThis.altchaPlugins || []; +globalThis.altchaI18n = globalThis.altchaI18n || { + get: (e) => rr(globalThis.altchaI18n.store)[e], + set: (e, t) => { + Object.assign(rr(globalThis.altchaI18n.store), { + [e]: t + }), globalThis.altchaI18n.store.set(rr(globalThis.altchaI18n.store)); + }, + store: Wa({}) +}; +const al = { + ariaLinkLabel: "Visit Altcha.org", + enterCode: "Enter code", + enterCodeAria: "Enter code you hear. Press Space to play audio.", + error: "Verification failed. Try again later.", + expired: "Verification expired. Try again.", + footer: 'Protected by ALTCHA', + getAudioChallenge: "Get an audio challenge", + label: "I'm not a robot", + loading: "Loading...", + reload: "Reload", + verify: "Verify", + verificationRequired: "Verification required!", + verified: "Verified", + verifying: "Verifying...", + waitAlert: "Verifying... please wait." +}; +globalThis.altchaI18n.set("en", al); +const $r = (e, t) => { + let r = /* @__PURE__ */ ua(() => Yi(t?.(), 24)); + var o = cl(); + Ce(() => { + R(o, "width", i(r)), R(o, "height", i(r)); + }), B(e, o); +}; +function ll(e, t) { + e.code === "Space" && (e.preventDefault(), e.stopImmediatePropagation(), t()); +} +function sl(e, t) { + e.preventDefault(), t(); +} +function ul(e, t, r, o, l, a, s, c) { + [ + y.UNVERIFIED, + y.ERROR, + y.EXPIRED, + y.CODE + ].includes(i(t)) ? r() !== !1 && i(o)?.reportValidity() === !1 ? b(l, !1) : a() ? s() : c() : b(l, !0); +} +var cl = /* @__PURE__ */ _r(''), fl = /* @__PURE__ */ be(''), dl = /* @__PURE__ */ be('
'), hl = /* @__PURE__ */ _r(''), vl = /* @__PURE__ */ _r(''), gl = /* @__PURE__ */ _r(''), pl = /* @__PURE__ */ be(''), ml = /* @__PURE__ */ be(""), _l = /* @__PURE__ */ be(''), bl = /* @__PURE__ */ be("
"), yl = /* @__PURE__ */ be("
"), wl = /* @__PURE__ */ be('
'), El = /* @__PURE__ */ be(''), xl = /* @__PURE__ */ be('
'), Cl = /* @__PURE__ */ be('
', 1); +function kl(e, t) { + $o(t, !0); + const [r, o] = Za(), l = () => Ya(Wo, "$altchaI18nStore", r); + let a = x(t, "auto", 7, void 0), s = x(t, "blockspam", 7, void 0), c = x(t, "challengeurl", 7, void 0), f = x(t, "challengejson", 7, void 0), d = x(t, "credentials", 7, void 0), m = x(t, "customfetch", 7, void 0), v = x(t, "debug", 7, !1), _ = x(t, "delay", 7, 0), w = x(t, "disableautofocus", 7, !1), F = x(t, "refetchonexpire", 7, !0), M = x(t, "disablerefetchonexpire", 23, () => !F()), U = x(t, "expire", 7, void 0), I = x(t, "floating", 7, void 0), ee = x(t, "floatinganchor", 7, void 0), $e = x(t, "floatingoffset", 7, void 0), X = x(t, "floatingpersist", 7, !1), j = x(t, "hidefooter", 7, !1), se = x(t, "hidelogo", 7, !1), He = x(t, "id", 7, void 0), Ht = x(t, "language", 7, void 0), Ge = x(t, "name", 7, "altcha"), We = x(t, "maxnumber", 7, 1e6), xt = x(t, "mockerror", 7, !1), Ne = x(t, "obfuscated", 7, void 0), ge = x(t, "overlay", 7, void 0), Ct = x(t, "overlaycontent", 7, void 0), Gt = x(t, "plugins", 7, void 0), Ye = x(t, "sentinel", 7, void 0), ye = x(t, "spamfilter", 7, !1), st = x(t, "strings", 7, void 0), de = x(t, "test", 7, !1), te = x(t, "verifyurl", 7, void 0), ut = x(t, "workers", 23, () => Math.min(16, navigator.hardwareConcurrency || 8)), kt = x(t, "workerurl", 7, void 0); + const { altchaI18n: Go } = globalThis, Wo = Go.store, zr = ["SHA-256", "SHA-384", "SHA-512"], Yo = "https://altcha.org/", Le = (n, u) => { + t.$$host.dispatchEvent(new CustomEvent(n, { detail: u })); + }, Jr = document.documentElement.lang?.split("-")?.[0], br = /* @__PURE__ */ Lt(() => c() && new URL(c(), location.origin).host.endsWith(".altcha.org") && !!c()?.includes("apiKey=ckey_")), Wt = /* @__PURE__ */ Lt(() => f() ? fn(f()) : void 0), Zo = /* @__PURE__ */ Lt(() => st() ? fn(st()) : {}), L = /* @__PURE__ */ Lt(() => ({ + ...Qr(l()), + ...i(Zo) + })), Kr = /* @__PURE__ */ Lt(() => `${He() || Ge()}_checkbox_${Math.round(Math.random() * 1e8)}`); + let Ze = /* @__PURE__ */ N(null), At = /* @__PURE__ */ N(!1), G = /* @__PURE__ */ N(null), k = /* @__PURE__ */ N(Me(y.UNVERIFIED)), V = /* @__PURE__ */ N(void 0), It = /* @__PURE__ */ N(null), Pe = /* @__PURE__ */ N(null), ue = /* @__PURE__ */ N(null), yr = /* @__PURE__ */ N(null), ct = /* @__PURE__ */ N(null), T = /* @__PURE__ */ N(null), Rt = /* @__PURE__ */ N(null), ze = /* @__PURE__ */ N(null), we = null, W = /* @__PURE__ */ N(null), Je = /* @__PURE__ */ N(!1), Oe = [], wr = /* @__PURE__ */ N(!1), Ee = /* @__PURE__ */ N(null); + Dr(() => { + li(i(ze)); + }), Dr(() => { + si(i(k)); + }), Ga(() => { + zo(), b(Rt, null), i(T) && (i(T).removeEventListener("submit", an), i(T).removeEventListener("reset", ln), i(T).removeEventListener("focusin", on), b(T, null)), we && (clearTimeout(we), we = null), document.removeEventListener("click", rn), document.removeEventListener("scroll", nn), window.removeEventListener("resize", cn); + }), Mo(() => { + A("mounted", "2.2.4"), A("workers", ut()), Qo(), A("plugins", Oe.length ? Oe.map((n) => n.constructor.pluginName).join(", ") : "none"), de() && A("using test mode"), U() && xr(U()), a() !== void 0 && A("auto", a()), I() !== void 0 && gn(I()), b(T, i(V)?.closest("form"), !0), i(T) && (i(T).addEventListener("submit", an, { capture: !0 }), i(T).addEventListener("reset", ln), (a() === "onfocus" || X() === "focus") && i(T).addEventListener("focusin", on)), ge() && pn(!0), a() === "onload" && (Ne() ? $t() : Se()), i(br) && (j() || se()) && A("Attributes hidefooter and hidelogo ignored because usage with free API Keys requires attribution."), requestAnimationFrame(() => { + Le("load"); + }); + }); + function Yt(n, u) { + return btoa(JSON.stringify({ + algorithm: n.algorithm, + challenge: n.challenge, + number: u.number, + salt: n.salt, + signature: n.signature, + test: de() ? !0 : void 0, + took: u.took + })); + } + function zo() { + for (const n of Oe) + n.destroy(); + } + function Xr() { + c() && !M() && i(k) === y.VERIFIED ? Se() : Ke(y.EXPIRED, i(L).expired); + } + async function Jo() { + if (xt()) + throw A("mocking error"), new Error("Mocked error."); + if (i(Wt)) + return A("using provided json data"), dn(i(Wt).salt), i(Wt); + if (de()) + return A("generating test challenge", { test: de() }), tl(typeof de() != "boolean" ? +de() : void 0); + { + if (!c() && i(T)) { + const g = i(T).getAttribute("action"); + g?.includes("/form/") && c(g + "/altcha"); + } + if (!c()) + throw new Error("Attribute challengeurl not set."); + A("fetching challenge from", c()); + const n = { + credentials: typeof d() == "boolean" ? "include" : d(), + headers: ye() !== !1 ? { "x-altcha-spam-filter": "1" } : {} + }, u = await Er()(c(), n); + if (!u || !(u instanceof Response)) + throw new Error("Custom fetch function did not return a response."); + if (u.status !== 200) + throw new Error(`Server responded with ${u.status}.`); + const h = u.headers.get("X-Altcha-Config"), p = await u.json(); + if (dn(p.salt), h) + try { + const g = JSON.parse(h); + g && typeof g == "object" && (g.verifyurl && !g.verifyurl.startsWith("fn:") && (g.verifyurl = tn(g.verifyurl)), bn(g)); + } catch (g) { + A("unable to configure from X-Altcha-Config", g); + } + return p; + } + } + function Ko(n) { + const u = i(T)?.querySelector(typeof n == "string" ? `input[name="${n}"]` : 'input[type="email"]:not([data-no-spamfilter])'); + return u?.value?.slice(u.value.indexOf("@")) || void 0; + } + function Er() { + let n = fetch; + if (m()) + if (A("using customfetch"), typeof m() == "string") { + if (n = globalThis[m()] || null, !n) + throw new Error(`Custom fetch function not found: ${m()}`); + } else + n = m(); + return n; + } + function Qr(n, u = [ + Ht() || "", + document.documentElement.lang || "", + ...navigator.languages + ]) { + const h = Object.keys(n).map((g) => g.toLowerCase()), p = u.reduce( + (g, C) => (C = C.toLowerCase(), g || (n[C] ? C : null) || h.find((D) => C.split("-")[0] === D.split("-")[0]) || null), + null + ); + return n[p || "en"]; + } + function Xo() { + return ye() === "ipAddress" ? { + blockedCountries: void 0, + classifier: void 0, + disableRules: void 0, + email: !1, + expectedCountries: void 0, + expectedLanguages: void 0, + fields: !1, + ipAddress: void 0, + text: void 0, + timeZone: void 0 + } : typeof ye() == "object" ? ye() : { + blockedCountries: void 0, + classifier: void 0, + disableRules: void 0, + email: void 0, + expectedCountries: void 0, + expectedLanguages: void 0, + fields: void 0, + ipAddress: void 0, + text: void 0, + timeZone: void 0 + }; + } + function en(n) { + return [ + ...i(T)?.querySelectorAll(n?.length ? n.map((h) => `input[name="${h}"]`).join(", ") : 'input[type="text"]:not([data-no-spamfilter]), textarea:not([data-no-spamfilter])') || [] + ].reduce( + (h, p) => { + const g = p.name, C = p.value; + return g && C && (h[g] = /\n/.test(C) ? C.replace(new RegExp("(? u instanceof Error)) && console[n[0] instanceof Error ? "error" : "log"]("ALTCHA", `[name=${Ge()}]`, ...n); + } + function ei() { + b(W, Q.PAUSED, !0); + } + function ti(n) { + b(W, Q.ERROR, !0); + } + function ri() { + b(W, Q.READY, !0); + } + function ni() { + b(W, Q.LOADING, !0); + } + function oi() { + b(W, Q.PLAYING, !0); + } + function ii() { + b(W, Q.PAUSED, !0); + } + function ai(n) { + if (n.preventDefault(), n.stopPropagation(), i(G)) { + const u = new FormData(n.target), h = String(u.get("code")); + if (te()?.startsWith("fn:")) { + const p = te().replace(/^fn:/, ""); + if (A(`calling ${p} function instead of verifyurl`), !(p in globalThis)) + throw new Error(`Global function "${p}" is undefined.`); + return globalThis[p]({ + challenge: i(G).challenge, + code: h, + solution: i(G).solution + }); + } + b(Je, !0), hn(Yt(i(G).challenge, i(G).solution), h).then(({ reason: p, verified: g }) => { + g ? (b(G, null), xe(y.VERIFIED), A("verified"), Rr().then(() => { + i(yr)?.focus(), Le("verified", { payload: i(Ee) }), a() === "onsubmit" ? vn(i(Rt)) : ge() && St(); + })) : (Ke(), b(ze, p || "Verification failed", !0)); + }).catch((p) => { + b(G, null), xe(y.ERROR, p), A("sentinel verification failed:", p); + }).finally(() => { + b(Je, !1); + }); + } + } + function rn(n) { + const u = n.target; + I() && u && !i(V).contains(u) && (i(k) === y.VERIFIED && X() === !1 || i(k) === y.VERIFIED && X() === "focus" && !i(T)?.matches(":focus-within") || a() === "off" && i(k) === y.UNVERIFIED) && St(); + } + function nn() { + I() && i(k) !== y.UNVERIFIED && Tt(); + } + function li(n) { + for (const u of Oe) + typeof u.onErrorChange == "function" && u.onErrorChange(i(ze)); + } + function on(n) { + i(k) === y.UNVERIFIED ? Se() : I() && X() === "focus" && i(k) === y.VERIFIED && Zt(); + } + function an(n) { + n.target?.hasAttribute("data-code-challenge-form") || (b(Rt, n.submitter, !0), i(T) && a() === "onsubmit" ? (i(Rt)?.blur(), i(k) === y.UNVERIFIED ? (n.preventDefault(), n.stopPropagation(), Se().then(() => { + vn(i(Rt)); + })) : i(k) !== y.VERIFIED && (n.preventDefault(), n.stopPropagation(), i(k) === y.VERIFYING && sn())) : i(T) && I() && a() === "off" && i(k) === y.UNVERIFIED && (n.preventDefault(), n.stopPropagation(), Zt())); + } + function ln() { + Ke(); + } + function sn() { + i(k) === y.VERIFYING && i(L).waitAlert && alert(i(L).waitAlert); + } + function un() { + i(Pe) ? i(Pe).paused ? (i(Pe).currentTime = 0, i(Pe).play()) : i(Pe).pause() : (b(wr, !0), requestAnimationFrame(() => { + i(Pe)?.play(); + })); + } + function si(n) { + for (const u of Oe) + typeof u.onStateChange == "function" && u.onStateChange(i(k)); + I() && i(k) !== y.UNVERIFIED && requestAnimationFrame(() => { + Tt(); + }), b(At, i(k) === y.VERIFIED), ge() && i(ue) && (i(k) !== y.UNVERIFIED ? Zt() : St()); + } + function cn() { + I() && Tt(); + } + function fn(n) { + return JSON.parse(n); + } + function dn(n) { + const u = new URLSearchParams(n.split("?")?.[1]), h = u.get("expires") || u.get("expire"); + if (h) { + const p = new Date(+h * 1e3), g = isNaN(p.getTime()) ? 0 : p.getTime() - Date.now(); + g > 0 && xr(g); + } else we && (clearTimeout(we), we = null); + } + async function ui(n) { + if (!te()) + throw new Error("Attribute verifyurl not set."); + A("requesting server verification from", te()); + const u = { payload: n }; + if (ye() !== !1) { + const { + blockedCountries: g, + classifier: C, + disableRules: D, + email: H, + expectedLanguages: q, + expectedCountries: oe, + fields: ie, + ipAddress: Qe, + text: dt, + timeZone: et + } = Xo(); + u.blockedCountries = g, u.classifier = C, u.disableRules = D, u.email = H === !1 ? void 0 : Ko(H), u.expectedCountries = oe, u.expectedLanguages = q || (Jr ? [Jr] : void 0), u.fields = ie === !1 ? void 0 : en(ie), u.ipAddress = Qe === !1 ? void 0 : Qe || "auto", u.text = dt, u.timeZone = et === !1 ? void 0 : et || Wn(); + } + const h = await Er()(te(), { + body: JSON.stringify(u), + headers: { "content-type": "application/json" }, + method: "POST" + }); + if (!h || !(h instanceof Response)) + throw new Error("Custom fetch function did not return a response."); + if (h.status !== 200) + throw new Error(`Server responded with ${h.status}.`); + const p = await h.json(); + if (p?.payload && b(Ee, p.payload, !0), Le("serververification", p), s() && p.classification === "BAD") + throw new Error("SpamFilter returned negative classification."); + } + async function hn(n, u) { + if (!te()) + throw new Error("Attribute verifyurl not set."); + A("requesting sentinel verification from", te()); + const h = { code: u, payload: n }; + Ye() && (h.fields = Ye().fields ? en() : void 0, h.timeZone = Ye().timeZone ? Wn() : void 0); + const p = await Er()(te(), { + body: JSON.stringify(h), + headers: { "content-type": "application/json" }, + method: "POST" + }); + if (!p || !(p instanceof Response)) + throw new Error("Fetch function did not return a response."); + if (p.status !== 200) + throw new Error(`Server responded with ${p.status}.`); + const g = await p.json(); + return g?.payload && b(Ee, g.payload, !0), Le("sentinelverification", g), g; + } + function vn(n) { + i(T) && "requestSubmit" in i(T) ? i(T).requestSubmit(n) : i(T)?.reportValidity() && (n ? n.click() : i(T).submit()); + } + function xr(n) { + A("expire", n), we && (clearTimeout(we), we = null), n < 1 ? Xr() : we = setTimeout(Xr, n); + } + function gn(n) { + A("floating", n), I() !== n && (i(V).style.left = "", i(V).style.top = ""), I(n === !0 || n === "" ? "auto" : n === !1 || n === "false" ? void 0 : I()), I() ? (a() || a("onsubmit"), document.addEventListener("scroll", nn), document.addEventListener("click", rn), window.addEventListener("resize", cn)) : a() === "onsubmit" && a(void 0); + } + function pn(n) { + if (A("overlay", n), ge(n), n) { + if (a() || a("onsubmit"), i(ue) && i(V).parentElement && i(ue).replaceWith(i(V).parentElement), i(V)?.parentElement?.parentElement) { + b(ue, document.createElement("div"), !0), i(V).parentElement.parentElement.appendChild(i(ue)); + const u = document.createElement("div"), h = document.createElement("button"); + h.type = "button", h.innerHTML = "×", h.addEventListener("click", (p) => { + p.preventDefault(), Ke(); + }), i(ue).classList.add("altcha-overlay-backdrop"), h.classList.add("altcha-overlay-close-button"), u.classList.add("altcha-overlay"), i(ue).append(u), u.append(h), Ct() && u.append(...document.querySelectorAll(Ct())), u.append(i(V).parentElement); + } + } else i(ue) && i(V).parentElement && (i(ue).replaceWith(i(V).parentElement), i(V).style.display = "block"); + } + function mn(n) { + if (!n.algorithm) + throw new Error("Invalid challenge. Property algorithm is missing."); + if (n.signature === void 0) + throw new Error("Invalid challenge. Property signature is missing."); + if (!zr.includes(n.algorithm.toUpperCase())) + throw new Error(`Unknown algorithm value. Allowed values: ${zr.join(", ")}`); + if (!n.challenge || n.challenge.length < 40) + throw new Error("Challenge is too short. Min. 40 chars."); + if (!n.salt || n.salt.length < 10) + throw new Error("Salt is too short. Min. 10 chars."); + } + async function _n(n) { + let u = null, h = null; + if ("Worker" in window) { + try { + u = ci(n, n.maxNumber || n.maxnumber || We()), b(Ze, u.controller, !0), h = await u.promise; + } catch (p) { + A(p); + } finally { + b(Ze, null); + } + if (h === null || h?.number !== void 0 || "obfuscated" in n) + return { data: n, solution: h }; + } + if ("obfuscated" in n) { + const p = await il(n.obfuscated, n.key, n.maxNumber || n.maxnumber); + return { data: n, solution: await p.promise }; + } + u = rl(n.challenge, n.salt, n.algorithm, n.maxNumber || n.maxnumber || We()), b(Ze, u.controller, !0); + try { + h = await u.promise; + } catch (p) { + A(p); + } finally { + b(Ze, null); + } + return { data: n, solution: h }; + } + function ci(n, u = typeof de() == "number" ? de() : n.maxNumber || n.maxnumber || We(), h = Math.ceil(ut())) { + const p = new AbortController(), g = []; + h = Math.min(16, u, Math.max(1, h)); + for (let H = 0; H < h; H++) + g.push(altchaCreateWorker(kt())); + const C = Math.ceil(u / h); + return { promise: (async () => { + const H = await Promise.all(g.map((q, oe) => { + const ie = oe * C; + return p.signal.addEventListener("abort", () => { + q.postMessage({ type: "abort" }); + }), new Promise((Qe) => { + q.addEventListener("message", (dt) => { + if (dt.data) + for (const et of g) + et !== q && et.postMessage({ type: "abort" }); + Qe(dt.data); + }), q.postMessage({ + payload: n, + max: ie + C, + start: ie, + type: "work" + }); + }); + })); + for (const q of g) + q.terminate(); + return H.find((q) => !!q) || null; + })(), controller: p }; + } + async function $t() { + if (!Ne()) { + xe(y.ERROR); + return; + } + const n = Oe.find((u) => u.constructor.pluginName === "obfuscation"); + if (!n || !("clarify" in n)) { + xe(y.ERROR), A("Plugin `obfuscation` not found. Import `altcha/plugins/obfuscation` to load it."); + return; + } + if ("clarify" in n && typeof n.clarify == "function") + return n.clarify(); + } + function bn(n) { + n.obfuscated !== void 0 && Ne(n.obfuscated), n.auto !== void 0 && (a(n.auto), a() === "onload" && (Ne() ? $t() : Se())), n.blockspam !== void 0 && s(!!n.blockspam), n.customfetch !== void 0 && m(n.customfetch), n.floatinganchor !== void 0 && ee(n.floatinganchor), n.delay !== void 0 && _(n.delay), n.floatingoffset !== void 0 && $e(n.floatingoffset), n.floating !== void 0 && gn(n.floating), n.expire !== void 0 && (xr(n.expire), U(n.expire)), n.challenge && (f(typeof n.challenge == "string" ? n.challenge : JSON.stringify(n.challenge)), mn(i(Wt))), n.challengeurl !== void 0 && c(n.challengeurl), n.debug !== void 0 && v(!!n.debug), n.hidefooter !== void 0 && j(!!n.hidefooter), n.hidelogo !== void 0 && se(!!n.hidelogo), n.language !== void 0 && st(Qr(l(), [n.language])), n.maxnumber !== void 0 && We(+n.maxnumber), n.mockerror !== void 0 && xt(!!n.mockerror), n.name !== void 0 && Ge(n.name), n.overlaycontent !== void 0 && Ct(n.overlaycontent), n.overlay !== void 0 && pn(n.overlay), n.refetchonexpire !== void 0 && M(!n.refetchonexpire), n.disablerefetchonexpire !== void 0 && M(!n.disablerefetchonexpire), n.sentinel !== void 0 && typeof n.sentinel == "object" && Ye(n.sentinel), n.spamfilter !== void 0 && ye(typeof n.spamfilter == "object" ? n.spamfilter : !!n.spamfilter), n.strings && st(typeof n.strings == "string" ? n.strings : JSON.stringify(n.strings)), n.test !== void 0 && de(typeof n.test == "number" ? n.test : !!n.test), n.verifyurl !== void 0 && te(n.verifyurl), n.workers !== void 0 && ut(+n.workers), n.workerurl !== void 0 && kt(n.workerurl); + } + function yn() { + return { + auto: a(), + blockspam: s(), + challengeurl: c(), + debug: v(), + delay: _(), + disableautofocus: w(), + disablerefetchonexpire: M(), + expire: U(), + floating: I(), + floatinganchor: ee(), + floatingoffset: $e(), + hidefooter: j(), + hidelogo: se(), + name: Ge(), + maxnumber: We(), + mockerror: xt(), + obfuscated: Ne(), + overlay: ge(), + refetchonexpire: !M(), + spamfilter: ye(), + strings: i(L), + test: de(), + verifyurl: te(), + workers: ut(), + workerurl: kt() + }; + } + function wn() { + return i(ct); + } + function fi(n) { + return Oe.find((u) => u.constructor.pluginName === n); + } + function En() { + return i(k); + } + function St() { + i(V).style.display = "none", ge() && i(ue) && (i(ue).style.display = "none"); + } + function Tt(n = 20) { + if (i(V)) + if (i(ct) || b(ct, (ee() ? document.querySelector(ee()) : i(T)?.querySelector('input[type="submit"], button[type="submit"], button:not([type="button"]):not([type="reset"])')) || i(T), !0), i(ct)) { + const u = parseInt($e(), 10) || 12, h = i(ct).getBoundingClientRect(), p = i(V).getBoundingClientRect(), g = document.documentElement.clientHeight, C = document.documentElement.clientWidth, D = I() === "auto" ? h.bottom + p.height + u + n > g : I() === "top", H = Math.max(n, Math.min(C - n - p.width, h.left + h.width / 2 - p.width / 2)); + if (D ? i(V).style.top = `${h.top - (p.height + u)}px` : i(V).style.top = `${h.bottom + u}px`, i(V).style.left = `${H}px`, i(V).setAttribute("data-floating", D ? "top" : "bottom"), i(It)) { + const q = i(It).getBoundingClientRect(); + i(It).style.left = h.left - H + h.width / 2 - q.width / 2 + "px"; + } + } else + A("unable to find floating anchor element"); + } + function Ke(n = y.UNVERIFIED, u = null) { + i(Ze) && (i(Ze).abort(), b(Ze, null)), b(At, !1), b(Ee, null), b(G, null), b(wr, !1), b(W, null), xe(n, u); + } + function xn(n) { + b(ct, n, !0); + } + function xe(n, u = null) { + b(k, n, !0), b(ze, u, !0), Le("statechange", { + payload: i(Ee), + state: i(k) + }); + } + function Zt() { + i(V).style.display = "block", I() && Tt(), ge() && i(ue) && (i(ue).style.display = "flex"); + } + async function Se() { + return Ke(y.VERIFYING), await new Promise((n) => setTimeout(n, _() || 0)), Jo().then((n) => (mn(n), A("challenge", n), _n(n))).then(({ data: n, solution: u }) => { + if (A("solution", u), !u || n && "challenge" in n && !("clearText" in u)) { + if (u?.number !== void 0 && "challenge" in n) + if (te() && "codeChallenge" in n) + ["INPUT", "BUTTON", "SELECT", "TEXTAREA"].includes(document.activeElement?.tagName || "") && w() === !1 && document.activeElement.blur(), b(G, { challenge: n, solution: u }, !0); + else { + if (te() && Ye() !== void 0) + return hn(Yt(n, u)); + if (te()) + return ui(Yt(n, u)); + b(Ee, Yt(n, u), !0), A("payload", i(Ee)); + } + else if (i(k) !== y.EXPIRED) + throw A("Unable to find a solution. Ensure that the 'maxnumber' attribute is greater than the randomly generated number."), new Error("Unexpected result returned."); + } + }).then(() => { + i(G) ? (xe(y.CODE), Rr().then(() => { + Le("code", { codeChallenge: i(G) }); + })) : i(Ee) && (xe(y.VERIFIED), A("verified"), Rr().then(() => { + Le("verified", { payload: i(Ee) }), ge() && St(); + })); + }).catch((n) => { + A(n), xe(y.ERROR, n.message); + }); + } + var Cn = Cl(), kn = Nt(Cn); + Fa(kn, t, "default", {}); + var ft = J(kn, 2), Cr = z(ft), zt = z(Cr); + let An; + var In = z(zt); + { + var di = (n) => { + $r(n); + }; + K(In, (n) => { + i(k) === y.VERIFYING && n(di); + }); + } + var Xe = J(In, 2); + qn(Xe), Xe.__change = [ + ul, + k, + ye, + T, + At, + Ne, + $t, + Se + ], Qt(Xe, (n) => b(yr, n), () => i(yr)), Z(zt); + var Jt = J(zt, 2), hi = z(Jt); + { + var vi = (n) => { + var u = Xt(), h = Nt(u); + tt(h, () => i(L).verified), B(n, u); + }, gi = (n, u) => { + { + var h = (g) => { + var C = Xt(), D = Nt(C); + tt(D, () => i(L).verifying), B(g, C); + }, p = (g, C) => { + { + var D = (q) => { + var oe = Xt(), ie = Nt(oe); + tt(ie, () => i(L).verificationRequired), B(q, oe); + }, H = (q) => { + var oe = Xt(), ie = Nt(oe); + tt(ie, () => i(L).label), B(q, oe); + }; + K( + g, + (q) => { + i(k) === y.CODE ? q(D) : q(H, !1); + }, + C + ); + } + }; + K( + n, + (g) => { + i(k) === y.VERIFYING ? g(h) : g(p, !1); + }, + u + ); + } + }; + K(hi, (n) => { + i(k) === y.VERIFIED ? n(vi) : n(gi, !1); + }); + } + Z(Jt); + var Rn = J(Jt, 2); + { + var pi = (n) => { + var u = fl(); + qn(u), Ce(() => { + R(u, "name", Ge()), qa(u, i(Ee)); + }), B(n, u); + }; + K(Rn, (n) => { + i(k) === y.VERIFIED && n(pi); + }); + } + var $n = J(Rn, 2); + { + var mi = (n) => { + var u = dl(), h = z(u); + R(h, "href", Yo), Z(u), Ce(() => R(h, "aria-label", i(L).ariaLinkLabel)), B(n, u); + }; + K($n, (n) => { + (se() !== !0 || i(br)) && n(mi); + }); + } + var _i = J($n, 2); + { + var bi = (n) => { + var u = _l(), h = J(z(u), 2), p = z(h), g = J(p, 2); + Sa(g, !w()), g.__keydown = [ + ll, + un + ]; + var C = J(g, 2), D = z(C), H = z(D); + { + var q = (pe) => { + var Y = pl(); + Y.__click = un; + var Kt = z(Y); + { + var Dt = (ht) => { + $r(ht, () => 20); + }, Ii = (ht, Ri) => { + { + var $i = (vt) => { + var kr = hl(); + B(vt, kr); + }, Si = (vt, kr) => { + { + var Ti = (gt) => { + var Ar = vl(); + B(gt, Ar); + }, Di = (gt) => { + var Ar = gl(); + B(gt, Ar); + }; + K( + vt, + (gt) => { + i(W) === Q.PLAYING ? gt(Ti) : gt(Di, !1); + }, + kr + ); + } + }; + K( + ht, + (vt) => { + i(W) === Q.ERROR ? vt($i) : vt(Si, !1); + }, + Ri + ); + } + }; + K(Kt, (ht) => { + i(W) === Q.LOADING ? ht(Dt) : ht(Ii, !1); + }); + } + Z(Y), Ce(() => { + R(Y, "title", i(L).getAudioChallenge), Y.disabled = i(W) === Q.LOADING || i(W) === Q.ERROR || i(Je), R(Y, "aria-label", i(W) === Q.LOADING ? i(L).loading : i(L).getAudioChallenge); + }), B(pe, Y); + }; + K(H, (pe) => { + i(G).challenge.codeChallenge.audio && pe(q); + }); + } + var oe = J(H, 2); + oe.__click = [sl, Se], Z(D); + var ie = J(D, 2), Qe = z(ie); + { + var dt = (pe) => { + $r(pe, () => 16); + }; + K(Qe, (pe) => { + i(Je) && pe(dt); + }); + } + var et = J(Qe); + Z(ie), Z(C); + var ki = J(C, 2); + { + var Ai = (pe) => { + var Y = ml(), Kt = z(Y); + Z(Y), Qt(Y, (Dt) => b(Pe, Dt), () => i(Pe)), Ce((Dt) => R(Kt, "src", Dt), [ + () => tn(i(G).challenge.codeChallenge.audio, { language: Ht() }) + ]), Fe("loadstart", Y, ni), Fe("canplay", Y, ri), Fe("pause", Y, ii), Fe("playing", Y, oi), Fe("ended", Y, ei), Fe("error", Kt, ti), B(pe, Y); + }; + K(ki, (pe) => { + i(G).challenge.codeChallenge.audio && i(wr) && pe(Ai); + }); + } + Z(h), Z(u), Ce(() => { + R(u, "aria-label", i(L).verificationRequired), R(p, "src", i(G).challenge.codeChallenge.image), R(g, "minlength", i(G).challenge.codeChallenge.length || 1), R(g, "maxlength", i(G).challenge.codeChallenge.length), R(g, "placeholder", i(L).enterCode), R(g, "aria-label", i(W) === Q.LOADING ? i(L).loading : i(W) === Q.PLAYING ? "" : i(L).enterCodeAria), R(g, "aria-live", i(W) ? "assertive" : "polite"), R(g, "aria-busy", i(W) === Q.LOADING), g.disabled = i(Je), R(oe, "aria-label", i(L).reload), R(oe, "title", i(L).reload), oe.disabled = i(Je), ie.disabled = i(Je), R(ie, "aria-label", i(L).verify), La(et, ` ${i(L).verify ?? ""}`); + }), Fe("submit", h, ai, !0), B(n, u); + }; + K(_i, (n) => { + i(G)?.challenge.codeChallenge && n(bi); + }); + } + Z(Cr); + var Sn = J(Cr, 2); + { + var yi = (n) => { + var u = wl(), h = J(z(u), 2); + { + var p = (C) => { + var D = bl(), H = z(D); + tt(H, () => i(L).expired), Z(D), Ce(() => R(D, "title", i(ze))), B(C, D); + }, g = (C) => { + var D = yl(), H = z(D); + tt(H, () => i(L).error), Z(D), Ce(() => R(D, "title", i(ze))), B(C, D); + }; + K(h, (C) => { + i(k) === y.EXPIRED ? C(p) : C(g, !1); + }); + } + Z(u), B(n, u); + }; + K(Sn, (n) => { + (i(ze) || i(k) === y.EXPIRED) && n(yi); + }); + } + var Tn = J(Sn, 2); + { + var wi = (n) => { + var u = El(), h = z(u), p = z(h); + tt(p, () => i(L).footer), Z(h), Z(u), B(n, u); + }; + K(Tn, (n) => { + i(L).footer && (j() !== !0 || i(br)) && n(wi); + }); + } + var Ei = J(Tn, 2); + { + var xi = (n) => { + var u = xl(); + Qt(u, (h) => b(It, h), () => i(It)), B(n, u); + }; + K(Ei, (n) => { + I() && n(xi); + }); + } + Z(ft), Qt(ft, (n) => b(V, n), () => i(V)), Ce( + (n) => { + R(ft, "data-state", i(k)), R(ft, "data-floating", I()), R(ft, "data-overlay", ge()), An = Va(zt, 1, "altcha-checkbox", null, An, n), R(Xe, "id", i(Kr)), Xe.required = a() !== "onsubmit" && (!I() || a() !== "off"), R(Jt, "for", i(Kr)); + }, + [ + () => ({ + "altcha-checkbox-verifying": i(k) === y.VERIFYING + }) + ] + ), Fe("invalid", Xe, sn), Ha(Xe, () => i(At), (n) => b(At, n)), B(e, Cn); + var Ci = So({ + clarify: $t, + configure: bn, + getConfiguration: yn, + getFloatingAnchor: wn, + getPlugin: fi, + getState: En, + hide: St, + repositionFloating: Tt, + reset: Ke, + setFloatingAnchor: xn, + setState: xe, + show: Zt, + verify: Se, + get auto() { + return a(); + }, + set auto(n = void 0) { + a(n), E(); + }, + get blockspam() { + return s(); + }, + set blockspam(n = void 0) { + s(n), E(); + }, + get challengeurl() { + return c(); + }, + set challengeurl(n = void 0) { + c(n), E(); + }, + get challengejson() { + return f(); + }, + set challengejson(n = void 0) { + f(n), E(); + }, + get credentials() { + return d(); + }, + set credentials(n = void 0) { + d(n), E(); + }, + get customfetch() { + return m(); + }, + set customfetch(n = void 0) { + m(n), E(); + }, + get debug() { + return v(); + }, + set debug(n = !1) { + v(n), E(); + }, + get delay() { + return _(); + }, + set delay(n = 0) { + _(n), E(); + }, + get disableautofocus() { + return w(); + }, + set disableautofocus(n = !1) { + w(n), E(); + }, + get refetchonexpire() { + return F(); + }, + set refetchonexpire(n = !0) { + F(n), E(); + }, + get disablerefetchonexpire() { + return M(); + }, + set disablerefetchonexpire(n = !F) { + M(n), E(); + }, + get expire() { + return U(); + }, + set expire(n = void 0) { + U(n), E(); + }, + get floating() { + return I(); + }, + set floating(n = void 0) { + I(n), E(); + }, + get floatinganchor() { + return ee(); + }, + set floatinganchor(n = void 0) { + ee(n), E(); + }, + get floatingoffset() { + return $e(); + }, + set floatingoffset(n = void 0) { + $e(n), E(); + }, + get floatingpersist() { + return X(); + }, + set floatingpersist(n = !1) { + X(n), E(); + }, + get hidefooter() { + return j(); + }, + set hidefooter(n = !1) { + j(n), E(); + }, + get hidelogo() { + return se(); + }, + set hidelogo(n = !1) { + se(n), E(); + }, + get id() { + return He(); + }, + set id(n = void 0) { + He(n), E(); + }, + get language() { + return Ht(); + }, + set language(n = void 0) { + Ht(n), E(); + }, + get name() { + return Ge(); + }, + set name(n = "altcha") { + Ge(n), E(); + }, + get maxnumber() { + return We(); + }, + set maxnumber(n = 1e6) { + We(n), E(); + }, + get mockerror() { + return xt(); + }, + set mockerror(n = !1) { + xt(n), E(); + }, + get obfuscated() { + return Ne(); + }, + set obfuscated(n = void 0) { + Ne(n), E(); + }, + get overlay() { + return ge(); + }, + set overlay(n = void 0) { + ge(n), E(); + }, + get overlaycontent() { + return Ct(); + }, + set overlaycontent(n = void 0) { + Ct(n), E(); + }, + get plugins() { + return Gt(); + }, + set plugins(n = void 0) { + Gt(n), E(); + }, + get sentinel() { + return Ye(); + }, + set sentinel(n = void 0) { + Ye(n), E(); + }, + get spamfilter() { + return ye(); + }, + set spamfilter(n = !1) { + ye(n), E(); + }, + get strings() { + return st(); + }, + set strings(n = void 0) { + st(n), E(); + }, + get test() { + return de(); + }, + set test(n = !1) { + de(n), E(); + }, + get verifyurl() { + return te(); + }, + set verifyurl(n = void 0) { + te(n), E(); + }, + get workers() { + return ut(); + }, + set workers(n = Math.min(16, navigator.hardwareConcurrency || 8)) { + ut(n), E(); + }, + get workerurl() { + return kt(); + }, + set workerurl(n = void 0) { + kt(n), E(); + } + }); + return o(), Ci; +} +Na(["change", "keydown", "click"]); +customElements.define("altcha-widget", Qa( + kl, + { + blockspam: { type: "Boolean" }, + debug: { type: "Boolean" }, + delay: { type: "Number" }, + disableautofocus: { type: "Boolean" }, + disablerefetchonexpire: { type: "Boolean" }, + expire: { type: "Number" }, + floatingoffset: { type: "Number" }, + hidefooter: { type: "Boolean" }, + hidelogo: { type: "Boolean" }, + maxnumber: { type: "Number" }, + mockerror: { type: "Boolean" }, + refetchonexpire: { type: "Boolean" }, + test: { type: "Boolean" }, + workers: { type: "Number" }, + auto: {}, + challengeurl: {}, + challengejson: {}, + credentials: {}, + customfetch: {}, + floating: {}, + floatinganchor: {}, + floatingpersist: {}, + id: {}, + language: {}, + name: {}, + obfuscated: {}, + overlay: {}, + overlaycontent: {}, + plugins: {}, + sentinel: {}, + spamfilter: {}, + strings: {}, + verifyurl: {}, + workerurl: {} + }, + ["default"], + [ + "clarify", + "configure", + "getConfiguration", + "getFloatingAnchor", + "getPlugin", + "getState", + "hide", + "repositionFloating", + "reset", + "setFloatingAnchor", + "setState", + "show", + "verify" + ], + !1 +)); +const Bo = '@keyframes overlay-slidein{to{opacity:1;top:50%}}@keyframes altcha-spinner{to{transform:rotate(360deg)}}.altcha{background:var(--altcha-color-base, transparent);border:var(--altcha-border-width, 1px) solid var(--altcha-color-border, #a0a0a0);border-radius:var(--altcha-border-radius, 3px);color:var(--altcha-color-text, currentColor);display:flex;flex-direction:column;max-width:var(--altcha-max-width, 260px);position:relative}.altcha:focus-within{border-color:var(--altcha-color-border-focus, currentColor)}.altcha[data-floating]{background:var(--altcha-color-base, white);display:none;filter:drop-shadow(3px 3px 6px rgba(0,0,0,.2));left:-100%;position:fixed;top:-100%;width:var(--altcha-max-width, 260px);z-index:999999}.altcha[data-floating=top] .altcha-anchor-arrow{border-bottom-color:transparent;border-top-color:var(--altcha-color-border, #a0a0a0);bottom:-12px;top:auto}.altcha[data-floating=bottom]:focus-within::after{border-bottom-color:var(--altcha-color-border-focus, currentColor)}.altcha[data-floating=top]:focus-within::after{border-top-color:var(--altcha-color-border-focus, currentColor)}.altcha[data-floating]:not([data-state=unverified]){display:block}.altcha-anchor-arrow{border:6px solid transparent;border-bottom-color:var(--altcha-color-border, #a0a0a0);content:"";height:0;left:12px;position:absolute;top:-12px;width:0}.altcha-main{align-items:center;display:flex;gap:.4rem;padding:.7rem;position:relative}.altcha-code-challenge{background:var(--altcha-color-base, white);border:1px solid var(--altcha-color-border-focus, currentColor);border-radius:var(--altcha-border-radius, 3px);filter:drop-shadow(3px 3px 6px rgba(0,0,0,.2));padding:.5rem;position:absolute;top:2.5rem;z-index:9999999}.altcha-code-challenge>form{display:flex;flex-direction:column;gap:.5rem}.altcha-code-challenge-input{border:1px solid currentColor;border-radius:3px;box-sizing:border-box;outline:0;font-size:16px;padding:.35rem;width:220px}.altcha-code-challenge-input:focus{outline:2px solid color-mix(in srgb,var(--altcha-color-active, #1D1DC9) 20%,transparent)}.altcha-code-challenge-input:disabled{opacity:.7}.altcha-code-challenge-image{background-color:#fff;border:1px solid currentColor;border-radius:3px;box-sizing:border-box;object-fit:contain;height:50px;width:220px}.altcha-code-challenge-audio,.altcha-code-challenge-reload{background:color-mix(in srgb,var(--altcha-color-text, currentColor) 10%,transparent);border:0;border-radius:3px;color:var(--altcha-color-text, currentColor);cursor:pointer;display:flex;align-items:center;justify-content:center;padding:.35rem}.altcha-code-challenge-audio:disabled,.altcha-code-challenge-reload:disabled,.altcha-code-challenge-verify:disabled{opacity:.7;pointer-events:none}.altcha-code-challenge-audio>*,.altcha-code-challenge-reload>*{height:20px;width:20px}.altcha-code-challenge-buttons{display:flex;justify-content:space-between}.altcha-code-challenge-buttons-left{display:flex;gap:.25rem}.altcha-code-challenge-verify{align-items:center;background:var(--altcha-color-active, #1D1DC9);border:0;border-radius:3px;color:#fff;cursor:pointer;display:flex;gap:.5rem;font-size:100%;padding:.35rem 1rem}.altcha-code-challenge-arrow{border:6px solid transparent;border-bottom-color:var(--altcha-color-border, currentColor);content:"";height:0;left:.15rem;position:absolute;top:-12px;width:0}.altcha[data-floating=top] .altcha-code-challenge{top:-150px}.altcha[data-floating=top] .altcha-code-challenge-arrow{border-bottom-color:transparent;border-top-color:var(--altcha-color-border, currentColor);bottom:-12px;top:auto}.altcha-label{cursor:pointer;flex-grow:1}.altcha-logo{color:currentColor!important;opacity:.7}.altcha-footer:hover,.altcha-logo:hover{opacity:1}.altcha-error{color:var(--altcha-color-error-text, #f23939);display:flex;font-size:.85rem;gap:.3rem;padding:0 .7rem .7rem}.altcha-footer{align-items:center;background-color:var(--altcha-color-footer-bg, transparent);display:flex;font-size:.75rem;opacity:.7;justify-content:end;padding:.2rem .7rem}.altcha-footer a{color:currentColor}.altcha-checkbox{display:flex;align-items:center;justify-content:center;height:24px;position:relative;width:24px}.altcha-checkbox .altcha-spinner{bottom:0;left:0;position:absolute;right:0;top:0}.altcha-checkbox input{width:18px;height:18px;margin:0}.altcha-checkbox-verifying input{appearance:none;opacity:0;pointer-events:none}.altcha-spinner{animation:altcha-spinner .75s infinite linear;transform-origin:center}.altcha-overlay{--altcha-color-base:#fff;--altcha-color-text:#000;animation:overlay-slidein .5s forwards;display:flex;flex-direction:column;gap:.5rem;left:50%;width:260px;opacity:0;position:fixed;top:45%;transform:translate(-50%,-50%)}.altcha-overlay-backdrop{background:rgba(0,0,0,.5);bottom:0;display:none;left:0;position:fixed;right:0;top:0;z-index:99999999}.altcha-overlay-close-button{align-self:flex-end;background:0 0;border:0;padding:.25rem;cursor:pointer;color:currentColor;font-size:130%;line-height:1;opacity:.7}@media (max-height:450px){.altcha-overlay{top:10%!important;transform:translate(-50%,0)}}'; +function Ho(e, t = "__altcha-css") { + if (!document.getElementById(t)) { + const r = document.createElement("style"); + r.id = t, r.textContent = e, document.head.appendChild(r); + } +} +globalThis.altchaCreateWorker = (e) => e ? new Worker(new URL(e)) : new Ni(); +Ho(Bo); +Ho(Bo); +export { + kl as Altcha +}; diff --git a/website_altcha/static/src/altcha/altcha.esm.js b/website_altcha/static/src/altcha/altcha.esm.js new file mode 100644 index 0000000000..e89d94ffef --- /dev/null +++ b/website_altcha/static/src/altcha/altcha.esm.js @@ -0,0 +1,53 @@ +/* global document, window */ + +import {_t} from "@web/core/l10n/translation"; +import {loadBundle} from "@web/core/assets"; +import {session} from "@web/session"; + +export class Altcha { + /** + * @override + */ + constructor() { + this._publicKey = session.altcha_public_key; + } + /** + * Loads the altcha libraries. + * + * @returns {Promise|Boolean} promise if libs are loading else false if the altcha key is empty. + */ + loadLibs() { + if (this._publicKey) { + this._altchaReady = loadBundle(`web.altcha_libs`); + return this._altchaReady.then(() => + Boolean(document.querySelector(".altcha-widget")) + ); + } + return false; + } + /** + * Returns an object with the token if altcha call succeeds + * If no key is set an object with a message is returned + * If an error occurred an object with the error message is returned + * + * @param {String} action + * @returns {Promise|Object} + */ + async getToken(action) { + if (!this._publicKey) { + return { + message: _t("No altcha site key set."), + }; + } + await this._altchaReady; + try { + return { + token: await window.altcha.execute(this._publicKey, {action: action}), + }; + } catch { + return { + error: _t("The altcha site key is invalid."), + }; + } + } +} diff --git a/website_altcha/static/src/signup/altcha.scss b/website_altcha/static/src/signup/altcha.scss new file mode 100644 index 0000000000..5ddbcfca5d --- /dev/null +++ b/website_altcha/static/src/signup/altcha.scss @@ -0,0 +1,4 @@ +altcha-widget.o_altcha_widget { + width: 100%; + --altcha-max-width: 100%; +} diff --git a/website_altcha/static/src/signup/altcha.xml b/website_altcha/static/src/signup/altcha.xml new file mode 100644 index 0000000000..53bc113c98 --- /dev/null +++ b/website_altcha/static/src/signup/altcha.xml @@ -0,0 +1,19 @@ + + + +
+
+
+
+
+
diff --git a/website_altcha/static/src/signup/signup.esm.js b/website_altcha/static/src/signup/signup.esm.js new file mode 100644 index 0000000000..69f8f62486 --- /dev/null +++ b/website_altcha/static/src/signup/signup.esm.js @@ -0,0 +1,66 @@ +import "@website/snippets/s_website_form/000"; +import {Altcha} from "@website_altcha/altcha/altcha.esm"; +import publicWidget from "@web/legacy/js/public/public_widget"; +import {renderToString} from "@web/core/utils/render"; + +export const AltchaFunctionality = { + init() { + this._super(...arguments); + this._altcha = new Altcha(); + }, + + async willStart() { + this._altcha.loadLibs(); + return this._super(...arguments); + }, + start: function () { + if (this._altcha._publicKey && !this.$el.find(".altcha-widget").length) { + this.$el + .find("div.oe_login_buttons") + .prepend( + '' + ); + } + return this._super(...arguments); + }, +}; + +publicWidget.registry.SignupAltcha = publicWidget.Widget.extend({ + ...AltchaFunctionality, + selector: ".oe_signup_form", + tokenName: "signup", +}); + +publicWidget.registry.ResetPasswordAltcha = publicWidget.Widget.extend({ + ...AltchaFunctionality, + selector: ".oe_reset_password_form", + tokenName: "password_reset", +}); + +publicWidget.registry.s_website_form.include({ + init() { + this._super(...arguments); + this._altcha = new Altcha(); + }, + + async willStart() { + this._altcha.loadLibs(); + return this._super(...arguments); + }, + + /** + * @override + */ + start: function () { + const res = this._super(...arguments); + if (this.$target[0].classList.contains("s_website_form_no_recaptcha")) { + return res; + } + if (this._altcha._publicKey) { + this.$el + .find(".s_website_form_submit") + .before(renderToString("website_altcha.AltchaWidget", {})); + } + return res; + }, +}); From 99086f2a151670d7e3e7849fddf461012537f0ef Mon Sep 17 00:00:00 2001 From: Enric Tobella Date: Tue, 14 Apr 2026 09:27:02 +0200 Subject: [PATCH 2/8] [IMP] website_altcha: From v1 to v2, add tests & improve speed --- website_altcha/README.rst | 70 +- website_altcha/__init__.py | 8 - website_altcha/__manifest__.py | 16 +- website_altcha/controllers/altcha.py | 28 +- website_altcha/models/__init__.py | 2 + website_altcha/models/altcha_key.py | 2 +- website_altcha/models/ir_http.py | 39 +- website_altcha/models/res_config_settings.py | 52 + website_altcha/models/website.py | 41 + website_altcha/readme/CONFIGURE.md | 18 + website_altcha/readme/CONTEXT.md | 11 + website_altcha/readme/CONTRIBUTORS.md | 3 + website_altcha/readme/DESCRIPTION.md | 13 +- website_altcha/security/ir.model.access.csv | 2 + website_altcha/static/description/icon.png | Bin 0 -> 6771 bytes website_altcha/static/description/index.html | 93 +- website_altcha/static/lib/altcha-l10n.js | 786 +- website_altcha/static/lib/altcha.css | 1 + website_altcha/static/lib/altcha.js | 9965 ++++++++++++----- .../static/src/altcha/altcha.esm.js | 30 +- website_altcha/static/src/signup/altcha.xml | 5 +- .../static/src/signup/signup.esm.js | 19 +- website_altcha/tests/__init__.py | 1 + website_altcha/tests/test_altcha.py | 206 + .../views/res_config_settings_views.xml | 65 + 25 files changed, 8239 insertions(+), 3237 deletions(-) create mode 100644 website_altcha/models/res_config_settings.py create mode 100644 website_altcha/models/website.py create mode 100644 website_altcha/readme/CONFIGURE.md create mode 100644 website_altcha/readme/CONTEXT.md create mode 100644 website_altcha/readme/CONTRIBUTORS.md create mode 100644 website_altcha/security/ir.model.access.csv create mode 100644 website_altcha/static/description/icon.png create mode 100644 website_altcha/static/lib/altcha.css create mode 100644 website_altcha/tests/__init__.py create mode 100644 website_altcha/tests/test_altcha.py create mode 100644 website_altcha/views/res_config_settings_views.xml diff --git a/website_altcha/README.rst b/website_altcha/README.rst index 1b8bca2506..1b4f1c201b 100644 --- a/website_altcha/README.rst +++ b/website_altcha/README.rst @@ -1,5 +1,5 @@ ======================== -Website Friendly Captcha +Privacy Friendly Captcha ======================== .. @@ -28,25 +28,61 @@ Website Friendly Captcha |badge1| |badge2| |badge3| |badge4| |badge5| -[ This file is not always required; it should explain **how to configure -the module before using it**; it is aimed at users with administration -privileges. +This module allows to use a Captcha System completly handled by Odoo. -Please be detailed on the path to configuration (eg: do you need to -activate developer mode?), describe step by step configurations and the -use of screenshots is strongly recommended.] - -To configure this module, you need to: - -- Go to *App* > Menu > Menu item -- Activate boolean… > save -- … +It relies on Altcha (https://altcha.org), an OpenSource captcha +alternative. **Table of contents** .. contents:: :local: +Use Cases / Context +=================== + +Currently, Odoo provides 2 options: + +- Google Recaptcha relies on tracking of the user. It implies cookies +- Cloudfare Turnstile relies on signals of the browser so it is less + GDPR problematic. However, it relies on a third party infrastructure. + The decision is made from a probabilistic perspective (likely a human) + +With this new module, everything relies on our own system with no +cookies, no tracking and no network calls. + +The way to solve it is to add a deterministic puzzle to solve. Bots need +to spend more CPU, making it costly at scale. + +Configuration +============= + +Go to Configuration/Website, check "Enable Altcha" under "Privacy". Some +extra parameters will appear with all the ALTCHA information. This +parameters are website dependent. + +- ``altcha_key``: This key is made to create the challenge and review it + later + +Also, the system adds the option to use some extra parameters: + +- ``altcha_secret_key``: Key used to use deterministic mode. Using it + will make it faster from a server perspective. +- ``altcha_algorithm``: Algorithm used, by default ``PBKDF2/SHA-512``, + however, we can use: + + - Fast ones only for testing purposes: ``SHA-256``, ``SHA-384``, + ``SHA-512`` + - Good by default: ``PBKDF2/SHA-256``, ``PBKDF2/SHA-384``, + ``PBKDF2/SHA-512`` + - Memory Hard: ``SCRYPT``. To be implemented + - Memory Hard (it required argon2-cffi): ``ARGON2ID``. To be + implemented + +- ``altcha_timeout``: Number of minutes that we will trust the key, by + default 5 +- ``altcha_cost``: Cost of the challenge. By default, 5000 + Bug Tracker =========== @@ -65,6 +101,14 @@ Authors * Dixmit +Contributors +------------ + +- `Dixmit `__ + + - Enric Tobella + - Luís David Rodríguez + Maintainers ----------- diff --git a/website_altcha/__init__.py b/website_altcha/__init__.py index 61aa1f0e5e..91c5580fed 100644 --- a/website_altcha/__init__.py +++ b/website_altcha/__init__.py @@ -1,10 +1,2 @@ from . import controllers from . import models -import uuid - - -def post_init_hook(env): - """Ensure that the altcha.key parameter exists in the ir_config_parameter table.""" - param_obj = env["ir.config_parameter"].sudo() - if not param_obj.get_param("altcha.key"): - param_obj.set_param("altcha.key", str(uuid.uuid1())) diff --git a/website_altcha/__manifest__.py b/website_altcha/__manifest__.py index 0525fe10b1..2f506e0d84 100644 --- a/website_altcha/__manifest__.py +++ b/website_altcha/__manifest__.py @@ -2,8 +2,9 @@ # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). { - "name": "Website Friendly Captcha", - "summary": """Use Friendly Captcha for verifying users""", + "name": "Privacy Friendly Captcha", + "summary": """Use self hosted privacy friendly captcha for + verifying website users are not bots""", "version": "18.0.1.0.0", "license": "AGPL-3", "author": "Dixmit,Odoo Community Association (OCA)", @@ -20,9 +21,14 @@ "web.altcha_libs": [ "website_altcha/static/lib/altcha.js", "website_altcha/static/lib/altcha-l10n.js", + "website_altcha/static/lib/altcha.css", ], }, - "post_init_hook": "post_init_hook", - "data": [], - "demo": [], + "external_dependencies": { + "python": ["altcha"], + }, + "data": [ + "security/ir.model.access.csv", + "views/res_config_settings_views.xml", + ], } diff --git a/website_altcha/controllers/altcha.py b/website_altcha/controllers/altcha.py index 40734f2999..a0b031bcd8 100644 --- a/website_altcha/controllers/altcha.py +++ b/website_altcha/controllers/altcha.py @@ -1,22 +1,32 @@ import json +import secrets from datetime import timedelta -import altcha.v1 as altcha +import altcha.v2 as altcha from odoo import fields, http from odoo.http import request class AltchaController(http.Controller): - @http.route("/altcha", type="http", auth="public") + @http.route("/altcha", type="http", auth="public", website=True) def generate_altcha_challenge(self): - expires = fields.Datetime.now() + timedelta(minutes=5) - # TODO: Set the time dynamically based on config - options = altcha.ChallengeOptions( - hmac_key=request.env["ir.config_parameter"].sudo().get_param("altcha.key"), - expires=expires, - ) - challenge = altcha.create_challenge(options) + timeout = int(request.website.sudo().altcha_timeout or 5) + cost = int(request.website.sudo().altcha_cost or 1_000) + algorithm = request.website.sudo().altcha_algorithm or "PBKDF2/SHA-512" + expires = fields.Datetime.now() + timedelta(minutes=timeout) + key = request.website.sudo().altcha_key + secret_key = request.website.sudo().altcha_private_key + parameters = { + "algorithm": algorithm, + "cost": cost, + "hmac_secret": key, + "expires_at": expires, + } + if secret_key: + parameters["hmac_key_secret"] = secret_key + parameters["counter"] = secrets.randbelow(cost) + cost + challenge = altcha.create_challenge(**parameters) request.env["altcha.key"].sudo().create( { "key": request.env["ir.http"]._get_altcha_key(challenge.signature), diff --git a/website_altcha/models/__init__.py b/website_altcha/models/__init__.py index bf0ada1e6d..a2fe8fa244 100644 --- a/website_altcha/models/__init__.py +++ b/website_altcha/models/__init__.py @@ -1,2 +1,4 @@ from . import ir_http from . import altcha_key +from . import website +from . import res_config_settings diff --git a/website_altcha/models/altcha_key.py b/website_altcha/models/altcha_key.py index bb3758d536..7f4e1eaf70 100644 --- a/website_altcha/models/altcha_key.py +++ b/website_altcha/models/altcha_key.py @@ -6,7 +6,7 @@ class AltchaKey(models.Model): _name = "altcha.key" - _description = "Altcha Key" # TODO + _description = "Altcha Key" key = fields.Char(required=True) expires_at = fields.Datetime(required=True) diff --git a/website_altcha/models/ir_http.py b/website_altcha/models/ir_http.py index 09950aa373..08763f2056 100644 --- a/website_altcha/models/ir_http.py +++ b/website_altcha/models/ir_http.py @@ -7,7 +7,7 @@ import json import logging -import altcha.v1 as altcha +import altcha.v2 as altcha from odoo import _, api, models from odoo.exceptions import UserError @@ -19,10 +19,6 @@ class IrHttp(models.AbstractModel): _inherit = "ir.http" - def session_info(self): - session_info = super().session_info() - return self._add_altcha_public_key_to_session_info(session_info) - @api.model def get_frontend_session_info(self): frontend_session_info = super().get_frontend_session_info() @@ -31,9 +27,7 @@ def get_frontend_session_info(self): @api.model def _add_altcha_public_key_to_session_info(self, session_info): """Add the Altcha public key to the given session_info object""" - session_info["altcha_public_key"] = bool( - self.env["ir.config_parameter"].sudo().get_param("altcha.key") - ) + session_info["altcha_public_key"] = bool(request.website.sudo().altcha_key) return session_info @api.model @@ -49,20 +43,35 @@ def _verify_request_recaptcha_token(self, action): result = super()._verify_request_recaptcha_token(action) if not result: return result + if not request.website.sudo().altcha_key: + return result altcha_signature = request.params.get("altcha") if not altcha_signature: _logger.warning("Altcha token missing in request") raise UserError(_("Suspicious activity detected by Altcha")) - altcha_request = json.loads(base64.b64decode(altcha_signature)) - is_valid, error = altcha.verify_solution( - altcha_request, - self.env["ir.config_parameter"].sudo().get_param("altcha.key"), - True, + result = altcha.verify_solution( + altcha_signature, + hmac_secret=request.website.sudo().altcha_key, + hmac_key_secret=request.website.sudo().altcha_private_key, ) + is_valid = result.verified if not is_valid: - _logger.warning("Altcha verification failed: %s", error) + error = [] + if result.invalid_signature: + error.append("Invalid Signature") + if result.invalid_solution: + error.append("Invalid Solution") + if result.expired: + error.append("Expired") + if result.error: + error.append(result.error) + _logger.warning( + """Altcha verification failed: %s""", + ", ".join(error), + ) raise UserError(_("Suspicious activity detected by Altcha")) - unique_id = self._get_altcha_key(altcha_request["signature"]) + altcha_request = json.loads(base64.b64decode(altcha_signature)) + unique_id = self._get_altcha_key(altcha_request["challenge"]["signature"]) record = ( self.env["altcha.key"] .sudo() diff --git a/website_altcha/models/res_config_settings.py b/website_altcha/models/res_config_settings.py new file mode 100644 index 0000000000..960e74eac5 --- /dev/null +++ b/website_altcha/models/res_config_settings.py @@ -0,0 +1,52 @@ +# Copyright 2025 Dixmit +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +import uuid + +from odoo import api, fields, models + + +class ResConfigSettings(models.TransientModel): + _inherit = "res.config.settings" + + altcha_enabled = fields.Boolean( + string="Enable Altcha", + help="Enable Altcha functionality on the website.", + compute="_compute_altcha_enabled", + readonly=False, + ) + altcha_key = fields.Char( + related="website_id.altcha_key", + readonly=False, + ) + altcha_private_key = fields.Char( + related="website_id.altcha_private_key", + readonly=False, + ) + altcha_algorithm = fields.Selection( + related="website_id.altcha_algorithm", + readonly=False, + ) + altcha_timeout = fields.Integer( + related="website_id.altcha_timeout", + readonly=False, + ) + altcha_cost = fields.Integer( + related="website_id.altcha_cost", + readonly=False, + ) + + @api.depends("altcha_key") + def _compute_altcha_enabled(self): + for record in self: + record.altcha_enabled = bool(record.altcha_key) + + @api.onchange("altcha_enabled") + def _onchange_altcha_enabled(self): + for record in self: + if not record.altcha_enabled: + record.altcha_key = False + record.altcha_private_key = False + else: + record.altcha_key = str(uuid.uuid4()) + record.altcha_private_key = str(uuid.uuid4()) diff --git a/website_altcha/models/website.py b/website_altcha/models/website.py new file mode 100644 index 0000000000..1d7c5df7dd --- /dev/null +++ b/website_altcha/models/website.py @@ -0,0 +1,41 @@ +# Copyright 2025 Dixmit +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + + +from odoo import fields, models + +try: + import argon2 +except ImportError: + argon2 = None + + +class Website(models.Model): + _inherit = "website" + + altcha_key = fields.Char() + altcha_private_key = fields.Char() + altcha_algorithm = fields.Selection( + selection=lambda self: self._get_available_algorithms(), + default="PBKDF2/SHA-512", + ) + altcha_timeout = fields.Integer( + default=5, + help="Time in minutes before a captcha expires. Default is 5 minutes.", + ) + altcha_cost = fields.Integer( + default=5000, + help="""Cost factor for the hashing algorithm. + For PBKDF2, this is the number of iterations. + Default is 5000 for PBKDF2/SHA-512.""", + ) + + def _get_available_algorithms(self): + return [ + ("SHA256", "SHA-256 (fast, testing only)"), + ("SHA384", "SHA-384 (fast, testing only)"), + ("SHA512", "SHA-512 (fast, testing only)"), + ("PBKDF2/SHA-256", "PBKDF2/SHA-256"), + ("PBKDF2/SHA-384", "PBKDF2/SHA-384"), + ("PBKDF2/SHA-512", "PBKDF2/SHA-512 (default, good)"), + ] diff --git a/website_altcha/readme/CONFIGURE.md b/website_altcha/readme/CONFIGURE.md new file mode 100644 index 0000000000..c7b05f5cce --- /dev/null +++ b/website_altcha/readme/CONFIGURE.md @@ -0,0 +1,18 @@ +Go to Configuration/Website, check "Enable Altcha" under "Privacy". +Some extra parameters will appear with all the ALTCHA information. +This parameters are website dependent. + +- `altcha_key`: This key is made to create the challenge and review it later + +Also, the system adds the option to use some extra parameters: + +- `altcha_secret_key`: Key used to use deterministic mode. + Using it will make it faster from a server perspective. +- `altcha_algorithm`: Algorithm used, by default `PBKDF2/SHA-512`, however, we can use: + - Fast ones only for testing purposes: `SHA-256`, `SHA-384`, `SHA-512` + - Good by default: `PBKDF2/SHA-256`, `PBKDF2/SHA-384`, `PBKDF2/SHA-512` + - Memory Hard: `SCRYPT`. To be implemented + - Memory Hard (it required argon2-cffi): `ARGON2ID`. To be implemented +- `altcha_timeout`: Number of minutes that we will trust the key, by default 5 +- `altcha_cost`: Cost of the challenge. By default, 5000 + diff --git a/website_altcha/readme/CONTEXT.md b/website_altcha/readme/CONTEXT.md new file mode 100644 index 0000000000..5bb3450316 --- /dev/null +++ b/website_altcha/readme/CONTEXT.md @@ -0,0 +1,11 @@ +Currently, Odoo provides 2 options: + +- Google Recaptcha relies on tracking of the user. It implies cookies +- Cloudfare Turnstile relies on signals of the browser so it is less GDPR problematic. + However, it relies on a third party infrastructure. + The decision is made from a probabilistic perspective (likely a human) + +With this new module, everything relies on our own system with no cookies, no tracking and no network calls. + +The way to solve it is to add a deterministic puzzle to solve. +Bots need to spend more CPU, making it costly at scale. diff --git a/website_altcha/readme/CONTRIBUTORS.md b/website_altcha/readme/CONTRIBUTORS.md new file mode 100644 index 0000000000..4e1b11a7b8 --- /dev/null +++ b/website_altcha/readme/CONTRIBUTORS.md @@ -0,0 +1,3 @@ +- [Dixmit](https://www.dixmit.com) + - Enric Tobella + - Luís David Rodríguez \ No newline at end of file diff --git a/website_altcha/readme/DESCRIPTION.md b/website_altcha/readme/DESCRIPTION.md index 86245d1735..5b237a5627 100644 --- a/website_altcha/readme/DESCRIPTION.md +++ b/website_altcha/readme/DESCRIPTION.md @@ -1,12 +1,3 @@ -[ This file is not always required; it should explain **how to configure the module -before using it**; it is aimed at users with administration privileges. +This module allows to use a Captcha System completly handled by Odoo. -Please be detailed on the path to configuration (eg: do you need to activate developer -mode?), describe step by step configurations and the use of screenshots is strongly -recommended.] - -To configure this module, you need to: - -- Go to _App_ > Menu > Menu item -- Activate boolean… > save -- … +It relies on Altcha (https://altcha.org), an OpenSource captcha alternative. diff --git a/website_altcha/security/ir.model.access.csv b/website_altcha/security/ir.model.access.csv new file mode 100644 index 0000000000..c98180b478 --- /dev/null +++ b/website_altcha/security/ir.model.access.csv @@ -0,0 +1,2 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_altcha_key,access_altcha_key,website_altcha.model_altcha_key,base.group_system,1,0,0,0 diff --git a/website_altcha/static/description/icon.png b/website_altcha/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..d8e30bafa521c7207da9030458badd423a6c3ec8 GIT binary patch literal 6771 zcmchcRa6^aw8n7>?$9EoxKp4-11%IOZiN7)K+)pv?(PJaw73SR!Gjg|;9eYx7l)hw zeZBAZVP@8vHEYhy-us;W{k{{Wt}0IecmY5`K_U30@KFEj1&&zz%NFHfz{cLVh$dRan-DT}Uaftv3~pyUnGX9MrZ@#th}Fd-mR4gt*|8aM6I zg1})AwK@rEk!@ojML$B{jN`Qx1kVnlv?x8zYzJdjslU9A&5VdZ4Rc9%IZ^SJOnA;* zZew2S*v+|a!&9r`HD@F?>wzqxg!%-Bh6SRLQlbGAKsfBLOc)CS|6gu&{aiu`hi^cA zeQ$z-(D?ZBl=~?FqRygox1BK9k&aDgx3P^wb5qmPt`scJ{IvpzJ1m%rf(1Z85gy@F zItx!ECJG4XsNu^WFb!#2vA5iJ_2c338yy9QV=4LhImm<*l@HBKnnXB=yO|pTcf4W~gmX+=A z=M2=D6rZ%>&i8e`80K3VvA|wwdfyEUqoCM+V;R48v>=&U z<#A(WQ%^7YV|ZM+WleHqC6pz_$;gMtbBtCBM$p|KMHVi+YGrGE@Npz6LZ>v_vV9q5N-afFM7h+KuRBn-IR~2;%E}=&Ca(ny|yc1y#kzz07WM=={{o z_|eJEq;{dwX-h)48sB@5Q4MCtm@=d|ji?&M#5{I=8O%UMsq-bra|N~@!2q7L!{O%r zdbHT~>sMi6ioMKfSK2Vuq#Zi_)O6ZXvwYdCG>jl9QjsMGxTFhN&lQ{9cWf*OJ@l$9 zWlxyznJXEY8XcS2{YoH^ zFlM_`HDtil$J@ER-Al3Pl?aHMbaP`D8;DXdXRte3QC`a5^Yp6Dk>W*J}>E>{gcAw2{N+MTIwG z`6p@qNYb;)w;I^mie+=f(Ywyvu0>Sh>epeYkPbjJG5CS}hEP^9@+ z*QoE?<6*hZtG4fZUNP&!^NGC7x?zZV}^ZyqeskJsd}GEM=snN z!EID|vIuK59|l|O&<4M9dh%_awDS2w!l!(q$%*Oj|8UZA7-%u~2+;#+XwYZB3o``( zmuw$TI@caHB6#qL{FD2Nlz@~m=r%YOd+LMR!$2XqKl{t3XP!rft=}YowR8a;H$U8l z!C=%W{hq-AhPAHRHT`-yf&toBd*q1CK2%TzBd_7XYD+C{mh8y(tnMM7QNPab7c?AM z!0ZO*ca;;Y-1G^LaJ>0%5Xu#^=6)Q+Ag4*4os=DswP0c`tVSvv@X_{q-E~gLN&@TFfpC9N=O$uf%mp3 zUX(%7A<)e&7Oi5>kj|%}w7kyec9LRQd~;+^SY8Hg&aMs)Mw|3R7JHb6VVOK`^F3vJ z?euRCznxVr6f_O@u>V_-Nc^MhY|KT|-JP9A&Lq&*?Jz+KCbNhpf`%$C zDCl^Ia3szDZ$@wCQqIElo4ASF-ek#5-}k>nwVQaJZ*RR?{3$x|TOv{Jb z)sf9`F%uTnp)MPTj>o1Ipk~|$&;6pVpYmHje)d776u5UZ-F*~tp_DwD!JRiuko z8m;*Ykpcx!RFuG})X>(z6*}{Z^>p!0Z?BPyOPR~KG-E_oAf+rEo{HjixrYLyw6%g( z>VFpYz3H2+IE;=K^Y($TVaC1Om4l->WEp;4?Fl_#iGD+EYvjN1@2Gy(bl?eXDJYIk zNfzCOGqgwtuS=ZO|NIk|nG1DXx3NKEIj`i?rqQ!ET{8MhAqC|R!e2QT|DDW<(#;PrG*ic!x!N_$H3pO4`= z!1Ks-?VkP~(eaFFF50 zw$_$8`H8T%zAYF~`p*@O0?=(n!CKIri?hAN%{rf&l%d;EMzIJsKmsD=srl;iOvE*b`NMgHjkO0sSSF)*xPJ(istMfT;>?=C&=rN(~nq-xZ z&$E+i?|snP%RPELiMTac?29)M286K#rsG-L^=45A^oMk|Cf!${*Cg^)Sa;ZaSBQV^ zSXUNq-;pDPV7qA*f9Z%o$HNa@lEJGU007V$^T2PI|HiG1Ig9c0roZ)W*xgFtVpY>w z=43@ig)?ovp8zCCyy4A#S`h-K)Xh5I)1N=CblHV{4QPMExG}ezUsGLie=;e~jIrsf z-$IY~kT|s%9V&~-rshsg=^jgeoS9SkN`Pdmql=Pq@1jwEhp^6BFozJ|oe95138IYU zeLOK4EkURA(^I12C`WjO2sb&W{$x8X7onC?6%U347ydT%LVhQU>W?-V3r&ehB5DkCEw0 zT>Yx0&oQ+1sQrY}(k}ikt2@_n-JVNV3QrniSxiQgzP=SU zs+{p%iGLZJzmvMv@s2kDNIL8mROi4!{FSFfg~n>!g~E|_XFTECO!k<8qH z>ONwwPNf@b-LD%n8sE{k6`HY45dAPWFNlAHMBv!@b=*kfNe+4}i|8o=D5@^y;*!U* z!Zt#1nglS2tcBhMi+TF0zv7-Kzb#~z=23s~l1J(>l#$E%c+nU_EOd*;u)5l2*!rW} zLzglpq+sBM1hr79h7nQo9xV*o)mhg2Q8as=$WT2HLQ&8u^~~^$!+7a+9Xf1ow@e-V z{r5uWliRc{t7|?wFZZd7kR~#d-r_k`Klrv9>Y%0&*9xCE8U0e1?O@zpZhH5+hPtSxu15!lt2D*GNHTv_~cZZWK7uS2ayILB>CZL+QsE{P94abZ@Nh;m2ot(o&o{5xGiS`KZ}(v`5UQ)A zw0F}{!0&D?Cqf|FLyyz>k#eZ<3=UF0lot!pZ0)7tkCLW=d^hh@XNEd^#@#A zcWwz`al8jL;3kA59`6roabhwu!skJgktCYRsA1xcBA}YiuL1j{O)48J3d}k3444#% zGA-@c6o>-Iax4%qoVg(F8{YNw2%G!~+#TzadQ#)wiD%#&5Yj^D8i?QbIG!R67;E!- zTGyK^DsqfD%vDb{@Z3>m^L+U`m7GCSv$(GAASNbri3Qr$7LnTB`A(NMqXCGNOZZW5eIl88q$8!%u>8u>3 z4c}c_=9^@g3k3M1a4=Z&&reO;4CWra&xt2o+U#pId+bsJhM7d)c&ussftQgXuGe06 z^A(n;UisgcIG;<5=btDl!tm+O16Ay*ZU@;ahK2`eKE5>x#`l%%aj@Iu$YPiI{@8!E zRp2B_7?GAs7tX|b+1k*km+w>kLhCO&^U#p@)5&vnVo~|p4?*fL_p9ytL$Et_&dQq3 ze*O&sp_#4m04$)wYI;1OfxiB1lb!IMHH$<2)ycw7zk@PP(g;kXCSp~^h!a4`yqz|+mH$?Nu$+51sFvr!*1rV5X?9c zaBe1!=`?AeZa9>YTZNiG4$%gz`irN2K_AOK%o1z#U6bUAf5RvOUDCrQI$%}4xmt4g z)R8y*TmAOlwDi5GXX0KJ32P~(jzRWuFD|~(nU>mZh?*tlpZ>Ux%E~)rXFAm<^3~SO zwjAd*`gJbm3FLW&RQ#8&6Z2_;7IJ64Sk+%TB8SFZz=L6KXq1^zlOl9MTtfDd< zyP~3)|6|&o8?(;5wHrqt!)-R(E(JxODXhb=sq)`p&4z08^}ijJ9QJ@qja#V66w>QC z)y9nLcivI9{Qh0{`**6NZ8s$Mq%*6ch#-N*NZ92uLLc_txsB_Y4dcU%&3ehj8WM{``p6ex_0QSH7 z%w4=ZW4B~qX{08tPpD%>23F`5^+3`ds~{3q4raLCzD0Kh6(cF$={2tet;}GH+;n!L zI@WZlRA>_-%A%f$tps!0AXIwH=Oj#tS^2xeCl+VX>(h2q#%VM7n#3!TF9Qosr?=~cofm;XyT?z)kH8PIF4av zfh7PLWi>Z5D=k(VQ2(*VEZ&M6FZzChcmPHh(%ruSB_-uI`(F2-#bZV&FLlL6rw@X@ zGG2ihSDuJD7T7H{Wjk`C1zVUrQj)(zMwkev3&CJ>X{AOO;kF?y?8!u|YqqaByV#iV z*=<{K93J-e(qFJ47vLbzyh$r5VfCBX)(6Kju0Mtkq3PAENYl~LM(|R)M7g^S?cfTL zni_rQ-Llbe504}RFC2mDi|Geml98GrF^h!6ao0jC0W@;E8ADB5UZ+nNLpeK9%~^~S z)A!8~HdAk_$76h-xP*ic5Z zeNBQbfB!Z!R@ert=GJ(-_%=Numz8Bu>QP9awMPqlz2ZT4hRPYP zke&$aAS#^YAf2W3Bn_V@2_`VQ^|XQro<4Gh~@ue)pXpvr`8&mjIC zYbdfny3x|ofJppU3s94NiSIaXi-@IJ-QVY|oD1+UZWI#`tl8b|QPJwbb_qk4pR{!7 zQj_eaxaV5Doax~B+{sD>3-Fqji<2T?jJ7kCJU+PJcXZG2U?In+Jpe<8(<1 z;^Y}g(QtTtGU-+r-pV7turZR~e-odD;+}s>X_Je;WUdIa*U%V1+H2xs8I1;==v2hu zl(#lBN?>DlPc%q%wJ@KW$5BSmW#tSK@sVk}*txBkWuANfv(sd5J}Y?pakJMvv~RmE z&lB!}EOKg>T!+=8R_CG;*rM-M`7hXFazsX+c4;TYCS(iW=lS1RyS?3l0|G*0aEHsPkY-SS>dU=@RIs~+MY5490R^kv z>Pg&J2XR*ghvw^)uioSDkN!Q;iQ8LPAlzJAx_IEnEqTx!AatTXQ6z>0M{MkT9NaMD{=Q_3hp^ZfO zTSndsq+{pMvGBW#8FRTM8=8YmZeh{wXwJTh_ZFA)r1d=juz3A<78a2Xqq`Rp1q3hObkL?=`+ve6+R!BrHENY79!A{e`QBCh`K1H4V8T{6&2*xz%Ww(A6RpSs|e6ASFT0$nB3l+qNCkNO8RET z9&U6a+nnlvg@7om^>}5)J$I~pR^Lr5dqt8TEX=JggfqSEDDqT4$!dPI)YZ!pGJ~@d o^8d0|@_%+@PM=XxP@bQ=vivgZ@?}hrn@K32WK};_OB)CO4}1 -Website Friendly Captcha +Privacy Friendly Captcha -
-

Website Friendly Captcha

+
+

Privacy Friendly Captcha

Beta License: AGPL-3 OCA/website Translate me on Weblate Try me on Runboat

-

[ This file is not always required; it should explain how to configure -the module before using it; it is aimed at users with administration -privileges.

-

Please be detailed on the path to configuration (eg: do you need to -activate developer mode?), describe step by step configurations and the -use of screenshots is strongly recommended.]

-

To configure this module, you need to:

-
    -
  • Go to App > Menu > Menu item
  • -
  • Activate boolean… > save
  • -
  • -
+

This module allows to use a Captcha System completly handled by Odoo.

+

It relies on Altcha (https://altcha.org), an OpenSource captcha +alternative.

Table of contents

+
+

Use Cases / Context

+

Currently, Odoo provides 2 options:

+
    +
  • Google Recaptcha relies on tracking of the user. It implies cookies
  • +
  • Cloudfare Turnstile relies on signals of the browser so it is less +GDPR problematic. However, it relies on a third party infrastructure. +The decision is made from a probabilistic perspective (likely a human)
  • +
+

With this new module, everything relies on our own system with no +cookies, no tracking and no network calls.

+

The way to solve it is to add a deterministic puzzle to solve. Bots need +to spend more CPU, making it costly at scale.

+
+
+

Configuration

+

Go to Configuration/Website, check “Enable Altcha” under “Privacy”. Some +extra parameters will appear with all the ALTCHA information. This +parameters are website dependent.

+
    +
  • altcha_key: This key is made to create the challenge and review it +later
  • +
+

Also, the system adds the option to use some extra parameters:

+
    +
  • altcha_secret_key: Key used to use deterministic mode. Using it +will make it faster from a server perspective.
  • +
  • altcha_algorithm: Algorithm used, by default PBKDF2/SHA-512, +however, we can use:
      +
    • Fast ones only for testing purposes: SHA-256, SHA-384, +SHA-512
    • +
    • Good by default: PBKDF2/SHA-256, PBKDF2/SHA-384, +PBKDF2/SHA-512
    • +
    • Memory Hard: SCRYPT. To be implemented
    • +
    • Memory Hard (it required argon2-cffi): ARGON2ID. To be +implemented
    • +
    +
  • +
  • altcha_timeout: Number of minutes that we will trust the key, by +default 5
  • +
  • altcha_cost: Cost of the challenge. By default, 5000
  • +
+
-

Bug Tracker

+

Bug Tracker

Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed @@ -402,15 +439,25 @@

Bug Tracker

Do not contact contributors directly about support or help with technical issues.

-

Credits

+

Credits

-

Authors

+

Authors

  • Dixmit
+
+

Contributors

+
    +
  • Dixmit
      +
    • Enric Tobella
    • +
    • Luís David Rodríguez
    • +
    +
  • +
+
-

Maintainers

+

Maintainers

This module is maintained by the OCA.

Odoo Community Association diff --git a/website_altcha/static/lib/altcha-l10n.js b/website_altcha/static/lib/altcha-l10n.js index f414c7fe22..b972623a12 100644 --- a/website_altcha/static/lib/altcha-l10n.js +++ b/website_altcha/static/lib/altcha-l10n.js @@ -1,114 +1,49 @@ /* @odoo-module */ -const n = () => { -}; -function b(e, a) { - return e != e ? a == a : e !== a || e !== null && typeof e == "object" || typeof e == "function"; -} -let g = !1; -function v(e) { - var a = g; - try { - return g = !0, e(); - } finally { - g = a; - } -} -function A(e, a, r) { - if (e == null) - return a(void 0), n; - const t = v( - () => e.subscribe( - a, - // @ts-expect-error - r - ) - ); - return t.unsubscribe ? () => t.unsubscribe() : t; -} -const l = []; -function k(e, a = n) { - let r = null; - const t = /* @__PURE__ */ new Set(); - function d(o) { - if (b(e, o) && (e = o, r)) { - const s = !l.length; - for (const i of t) - i[1](), l.push(i, e); - if (s) { - for (let i = 0; i < l.length; i += 2) - l[i][0](l[i + 1]); - l.length = 0; - } - } - } - function c(o) { - d(o( - /** @type {T} */ - e - )); - } - function u(o, s = n) { - const i = [o, s]; - return t.add(i), t.size === 1 && (r = a(d, c) || n), o( - /** @type {T} */ - e - ), () => { - t.delete(i), t.size === 0 && r && (r(), r = null); - }; - } - return { set: d, update: c, subscribe: u }; -} -function h(e) { - let a; - return A(e, (r) => a = r)(), a; -} -globalThis.altchaPlugins = globalThis.altchaPlugins || []; -globalThis.altchaI18n = globalThis.altchaI18n || { - get: (e) => h(globalThis.altchaI18n.store)[e], - set: (e, a) => { - Object.assign(h(globalThis.altchaI18n.store), { - [e]: a - }), globalThis.altchaI18n.store.set(h(globalThis.altchaI18n.store)); - }, - store: k({}) -}; -const p = { +const i18n$Y = { ariaLinkLabel: "زور Altcha.org", enterCode: "أدخل الرمز", enterCodeAria: "أدخل الرمز الذي تسمعه. اضغط على المسافة لتشغيل الصوت.", error: "فشل التحقق. حاول مرة أخرى لاحقاً.", expired: "انتهت صلاحية التحقق. حاول مرة أخرى.", - verificationRequired: "مطلوب التحقق!", footer: 'محمي بواسطة ALTCHA', getAudioChallenge: "احصل على تحدي صوتي", label: "أنا لست روبوتاً", loading: "جارٍ التحميل...", reload: "إعادة تحميل", verify: "تحقق", + verificationRequired: "مطلوب التحقق!", verified: "تم التحقق", verifying: "جارٍ التحقق...", - waitAlert: "جارٍ التحقق... يرجى الانتظار." + waitAlert: "جارٍ التحقق... يرجى الانتظار.", + cancel: "إلغاء", + enterCodeFromImage: "للمتابعة، يرجى إدخال الرمز من الصورة أدناه." }; -globalThis.altchaI18n.set("ar", p); -const C = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("ar", i18n$Y); +} +const i18n$X = { ariaLinkLabel: "Посетете Altcha.org", enterCode: "Въведете код", enterCodeAria: "Въведете кода, който чувате. Натиснете Space за възпроизвеждане на аудио.", error: "Проверката неуспешна. Моля, опитайте по-късно.", expired: "Времето за проверка изтече. Моля, опитайте отново.", - verificationRequired: "Изисква се проверка!", footer: 'Защитено от ALTCHA', getAudioChallenge: "Аудио проверка", label: "Аз не съм робот", loading: "Зареждане...", reload: "Презареди", verify: "Провери", + verificationRequired: "Изисква се проверка!", verified: "Проверено", verifying: "Проверява се...", - waitAlert: "Проверката е в процес... моля изчакайте." + waitAlert: "Проверката е в процес... моля изчакайте.", + cancel: "Отказ", + enterCodeFromImage: "За да продължите, моля, въведете кода от изображението по-долу." }; -globalThis.altchaI18n.set("bg", C); -const y = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("bg", i18n$X); +} +const i18n$W = { ariaLinkLabel: "Наведаць Altcha.org", enterCode: "Увядзіце код", enterCodeAria: "Увядзіце код, які вы чуеце. Націсніце прабел, каб прайграць аўдыё.", @@ -123,10 +58,14 @@ const y = { verificationRequired: "Патрабуецца праверка!", verified: "Праверана", verifying: "Правяраем...", - waitAlert: "Праверка... калі ласка, пачакайце." + waitAlert: "Праверка... калі ласка, пачакайце.", + cancel: "Скасаваць", + enterCodeFromImage: "Каб працягнуць, увядзіце код з малюнка ніжэй." }; -globalThis.altchaI18n.set("be", y); -const L = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("be", i18n$W); +} +const i18n$V = { ariaLinkLabel: "Posjetite Altcha.org", enterCode: "Unesite kod", enterCodeAria: "Unesite kod koji čujete. Pritisnite Space da biste pustili zvuk.", @@ -141,10 +80,14 @@ const L = { verificationRequired: "Verifikacija je obavezna!", verified: "Verifikovano", verifying: "Verifikacija u toku...", - waitAlert: "Verifikacija u toku... molimo vas da sačekate." + waitAlert: "Verifikacija u toku... molimo vas da sačekate.", + cancel: "Odustani", + enterCodeFromImage: "Za nastavak, molimo unesite kod sa slike ispod." }; -globalThis.altchaI18n.set("bs", L); -const m = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("bs", i18n$V); +} +const i18n$U = { ariaLinkLabel: "Visita Altcha.org", enterCode: "Introdueix el codi", enterCodeAria: "Introdueix el codi que escoltes. Prem Espai per reproduir l’àudio.", @@ -159,154 +102,190 @@ const m = { verificationRequired: "Es requereix verificació!", verified: "Verificat", verifying: "Verificant...", - waitAlert: "Verificant... si us plau, espera." + waitAlert: "Verificant... si us plau, espera.", + cancel: "Cancel·la", + enterCodeFromImage: "Per continuar, si us plau, introdueix el codi de la imatge següent." }; -globalThis.altchaI18n.set("ca", m); -const j = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("ca", i18n$U); +} +const i18n$T = { ariaLinkLabel: "Navštivte Altcha.org", enterCode: "Zadejte kód", enterCodeAria: "Zadejte kód, který slyšíte. Stisknutím mezerníku přehrajete zvuk.", error: "Ověření selhalo. Zkuste to prosím později.", expired: "Ověření vypršelo. Zkuste to prosím znovu.", - verificationRequired: "Vyžaduje se ověření!", footer: 'Chráněno pomocí ALTCHA', getAudioChallenge: "Získat audio výzvu", label: "Nejsem robot", loading: "Načítání...", reload: "Znovu načíst", verify: "Ověřit", + verificationRequired: "Vyžaduje se ověření!", verified: "Ověřeno", verifying: "Ověřování...", - waitAlert: "Probíhá ověření... prosím počkejte." + waitAlert: "Probíhá ověření... prosím počkejte.", + cancel: "Zrušit", + enterCodeFromImage: "Pro pokračování zadejte kód z obrázku níže." }; -globalThis.altchaI18n.set("cs", j); -const T = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("cs", i18n$T); +} +const i18n$S = { ariaLinkLabel: "Besøg Altcha.org", enterCode: "Indtast kode", enterCodeAria: "Indtast den kode, du hører. Tryk på mellemrumstasten for at afspille lyd.", error: "Verificering mislykkedes. Prøv venligst igen senere.", expired: "Verificering udløbet. Prøv venligst igen.", - verificationRequired: "Verificering kræves!", footer: 'Beskyttet af ALTCHA', getAudioChallenge: "Hent lydudfordring", label: "Jeg er ikke en robot", loading: "Indlæser...", reload: "Genindlæs", verify: "Verificer", + verificationRequired: "Verificering kræves!", verified: "Verificeret", verifying: "Verificerer...", - waitAlert: "Verificerer... vent venligst." + waitAlert: "Verificerer... vent venligst.", + cancel: "Annuller", + enterCodeFromImage: "For at fortsætte, bedes du indtaste koden fra billedet herunder." }; -globalThis.altchaI18n.set("da", T); -const V = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("da", i18n$S); +} +const i18n$R = { ariaLinkLabel: "Besuche Altcha.org", enterCode: "Code eingeben", enterCodeAria: "Geben Sie den Code ein, den Sie hören. Drücken Sie die Leertaste, um die Audio abzuspielen.", error: "Überprüfung fehlgeschlagen. Bitte versuchen Sie es später erneut.", expired: "Überprüfung abgelaufen. Bitte versuchen Sie es erneut.", - verificationRequired: "Überprüfung erforderlich!", footer: 'Geschützt durch ALTCHA', getAudioChallenge: "Audio-Herausforderung anfordern", label: "Ich bin kein Roboter", loading: "Lade...", reload: "Neu laden", verify: "Überprüfen", + verificationRequired: "Überprüfung erforderlich!", verified: "Überprüft", verifying: "Wird überprüft...", - waitAlert: "Überprüfung läuft... bitte warten." + waitAlert: "Überprüfung läuft... bitte warten.", + cancel: "Abbrechen", + enterCodeFromImage: "Um fortzufahren, geben Sie bitte den Code aus dem Bild unten ein." }; -globalThis.altchaI18n.set("de", V); -const z = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("de", i18n$R); +} +const i18n$Q = { ariaLinkLabel: "Επισκεφθείτε το Altcha.org", enterCode: "Εισαγάγετε κωδικό", enterCodeAria: "Εισαγάγετε τον κωδικό που ακούτε. Πατήστε Space για να παίξετε τον ήχο.", error: "Η επαλήθευση απέτυχε. Δοκιμάστε ξανά αργότερα.", expired: "Η επαλήθευση έληξε. Δοκιμάστε ξανά.", - verificationRequired: "Απαιτείται έλεγχος!", footer: 'Προστατεύεται από το ALTCHA', getAudioChallenge: "Λήψη ηχητικής δοκιμασίας", label: "Δεν είμαι ρομπότ", loading: "Φόρτωση...", reload: "Επαναφόρτωση", verify: "Επαλήθευση", + verificationRequired: "Απαιτείται έλεγχος!", verified: "Επαληθεύτηκε", verifying: "Γίνεται επαλήθευση...", - waitAlert: "Γίνεται επαλήθευση... παρακαλώ περιμένετε." + waitAlert: "Γίνεται επαλήθευση... παρακαλώ περιμένετε.", + cancel: "Ακύρωση", + enterCodeFromImage: "Για να συνεχίσετε, εισάγετε τον κωδικό από την παρακάτω εικόνα." }; -globalThis.altchaI18n.set("el", z); -const w = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("el", i18n$Q); +} +const i18n$P = { ariaLinkLabel: "Visitar Altcha.org", enterCode: "Introduce el código", enterCodeAria: "Introduce el código que escuchas. Pulsa Espacio para reproducir el audio.", error: "Falló la verificación. Por favor intente nuevamente más tarde.", expired: "Verificación expirada. Por favor intente nuevamente.", - verificationRequired: "¡Verificación requerida!", footer: 'Protegido por ALTCHA', getAudioChallenge: "Obtener un desafío de audio", label: "No soy un robot", loading: "Cargando...", reload: "Recargar", verify: "Verificar", + verificationRequired: "¡Verificación requerida!", verified: "Verificado", verifying: "Verificando...", - waitAlert: "Verificando... por favor espere." + waitAlert: "Verificando... por favor espere.", + cancel: "Cancelar", + enterCodeFromImage: "Para continuar, introduzca el código de la imagen de abajo." }; -globalThis.altchaI18n.set("es-es", w); -const I = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("es-es", i18n$P); +} +const i18n$O = { ariaLinkLabel: "Visitar Altcha.org", enterCode: "Ingresa el código", enterCodeAria: "Ingresa el código que escuchas. Presiona Espacio para reproducir el audio.", error: "Falló la verificación. Por favor vuelve a intentarlo más tarde.", expired: "La verificación expiró. Por favor inténtalo de nuevo.", - verificationRequired: "¡Verificación requerida!", footer: 'Protegido por ALTCHA', getAudioChallenge: "Obtener un reto de audio", label: "No soy un robot", loading: "Cargando...", reload: "Volver a cargar", verify: "Verificar", + verificationRequired: "¡Verificación requerida!", verified: "Verificado", verifying: "Verificando...", - waitAlert: "Verificando... por favor espera." + waitAlert: "Verificando... por favor espera.", + cancel: "Cancelar", + enterCodeFromImage: "Para continuar, ingresa el código de la imagen a continuación." }; -globalThis.altchaI18n.set("es-419", I); -const P = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("es-419", i18n$O); +} +const i18n$N = { ariaLinkLabel: "Külasta Altcha.org", enterCode: "Sisesta kood", enterCodeAria: "Sisestage kuuldu kood. Vajutage tühikut, et esitada heli.", error: "Kinnitamine ebaõnnestus. Proovi hiljem uuesti.", expired: "Kinnitamine aegus. Proovi uuesti.", - verificationRequired: "Kontroll on vajalik!", footer: 'Kaitstud ALTCHA poolt', getAudioChallenge: "Hangi heliülesanne", label: "Ma ei ole robot", loading: "Laadimine...", reload: "Laadi uuesti", verify: "Kinnita", + verificationRequired: "Kontroll on vajalik!", verified: "Kinnitatud", verifying: "Kinnitamine...", - waitAlert: "Kinnitamine... palun oota." + waitAlert: "Kinnitamine... palun oota.", + cancel: "Tühista", + enterCodeFromImage: "Jätkamiseks sisestage alloleval pildil olev kood." }; -globalThis.altchaI18n.set("et", P); -const q = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("et", i18n$N); +} +const i18n$M = { ariaLinkLabel: "Bisitatu Altcha.org", enterCode: "Sartu kodea", enterCodeAria: "Sartu entzun duzun kodea. Sakatu Espazioa audioa erreproduzitzeko.", error: "Egiaztatzeak huts egin du. Saiatu berriro geroago.", expired: "Egiaztatzea iraungi da. Saiatu berriro.", - verificationRequired: "Egiaztatzea beharrezkoa da!", footer: 'ALTCHAk babestuta', getAudioChallenge: "Jaso audio-erronka bat", label: "Ez naiz robot bat", loading: "Kargatzen...", reload: "Birkargatu", verify: "Egiaztatu", + verificationRequired: "Egiaztatzea beharrezkoa da!", verified: "Egiaztatuta", verifying: "Egiaztatzen...", - waitAlert: "Egiaztatzen... itxaron mesedez." + waitAlert: "Egiaztatzen... itxaron mesedez.", + cancel: "Utzi", + enterCodeFromImage: "Jarraitzeko, idatzi beheko irudiko kodea." }; -globalThis.altchaI18n.set("eu", q); -const x = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("eu", i18n$M); +} +const i18n$L = { ariaLinkLabel: "بازدید از Altcha.org", enterCode: "کد را وارد کنید", enterCodeAria: "کدی که می‌شنوید را وارد کنید. برای پخش صدا Space را فشار دهید.", @@ -321,10 +300,14 @@ const x = { verificationRequired: "احراز هویت لازم است!", verified: "تایید شد", verifying: "در حال تایید...", - waitAlert: "در حال تایید... لطفا منتظر بمانید." + waitAlert: "در حال تایید... لطفا منتظر بمانید.", + cancel: "لغو کردن", + enterCodeFromImage: "برای ادامه، لطفاً کد تصویر زیر را وارد کنید." }; -globalThis.altchaI18n.set("fa", x); -const R = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("fa", i18n$L); +} +const i18n$K = { ariaLinkLabel: "Besicht Altcha.org", enterCode: "Code aginn", enterCodeAria: "Gitt de Code an deen dir héiert. Dréckt op d'Weltraumtast fir Audio ofzespillen.", @@ -339,118 +322,146 @@ const R = { verificationRequired: "Verifikatioun néideg!", verified: "Verifizéiert", verifying: "Verifizéieren...", - waitAlert: "Verifizéieren... waart wgl." + waitAlert: "Verifizéieren... waart wgl.", + cancel: "Ofbriechen", + enterCodeFromImage: "Fir virun ze fueren, gitt wgl. de Code aus dem Bild hei drënner an." }; -globalThis.altchaI18n.set("lb", R); -const H = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("lb", i18n$K); +} +const i18n$J = { ariaLinkLabel: "Vieraile sivulla Altcha.org", enterCode: "Syötä koodi", enterCodeAria: "Kirjoita kuulemasi koodi. Paina välilyöntiä toistaaksesi äänen.", error: "Varmennus epäonnistui. Yritä myöhemmin uudelleen.", expired: "Varmennus vanhentui. Yritä uudelleen.", - verificationRequired: "Vahvistus vaaditaan!", footer: 'Suojattu ALTCHA:lla', getAudioChallenge: "Hae äänitehtävä", label: "En ole robotti", loading: "Ladataan...", reload: "Lataa uudelleen", verify: "Vahvista", + verificationRequired: "Vahvistus vaaditaan!", verified: "Vahvistettu", verifying: "Vahvistetaan...", - waitAlert: "Vahvistetaan... odota hetki." + waitAlert: "Vahvistetaan... odota hetki.", + cancel: "Peruuta", + enterCodeFromImage: "Jatkaaksesi, syötä alla olevan kuvan koodi." }; -globalThis.altchaI18n.set("fi", H); -const _ = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("fi", i18n$J); +} +const i18n$I = { ariaLinkLabel: "Visitez Altcha.org", enterCode: "Entrez le code", enterCodeAria: "Entrez le code que vous entendez. Appuyez sur la barre d'espace pour écouter l'audio.", error: "Échec de la vérification. Réessayez plus tard.", expired: "La vérification a expiré. Réessayez.", - verificationRequired: "Vérification requise !", footer: 'Protégé par ALTCHA', getAudioChallenge: "Obtenir un défi audio", label: "Pas un robot", loading: "Chargement...", reload: "Recharger", verify: "Vérifier", + verificationRequired: "Vérification requise !", verified: "Vérifié", verifying: "Vérification en cours...", - waitAlert: "Vérification en cours... veuillez patienter." + waitAlert: "Vérification en cours... veuillez patienter.", + cancel: "Annuler", + enterCodeFromImage: "Pour continuer, veuillez entrer le code de l'image ci-dessous." }; -globalThis.altchaI18n.set("fr-ca", _); -const S = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("fr-ca", i18n$I); +} +const i18n$H = { ariaLinkLabel: "Visitez Altcha.org", enterCode: "Entrez le code", enterCodeAria: "Entrez le code que vous entendez. Appuyez sur Espace pour écouter l'audio.", error: "Échec de la vérification. Essayez à nouveau plus tard.", expired: "La vérification a expiré. Essayez à nouveau.", - verificationRequired: "Vérification requise !", footer: 'Protégé par ALTCHA', getAudioChallenge: "Obtenir un défi audio", label: "Pas un robot", loading: "Chargement...", reload: "Recharger", verify: "Vérifier", + verificationRequired: "Vérification requise !", verified: "Vérifié", verifying: "Vérification en cours...", - waitAlert: "Vérification en cours... veuillez patienter." + waitAlert: "Vérification en cours... veuillez patienter.", + cancel: "Annuler", + enterCodeFromImage: "Pour continuer, veuillez entrer le code de l'image ci-dessous." }; -globalThis.altchaI18n.set("fr-fr", S); -const $ = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("fr-fr", i18n$H); +} +const i18n$G = { ariaLinkLabel: "Tabhair cuairt ar Altcha.org", enterCode: "Iontráil cód", enterCodeAria: "Cuir isteach an cód a chloiseann tú. Brúigh Spás chun an fuaime a sheinm.", error: "Theip ar an bhfíorú. Bain triail eile as níos déanaí.", expired: "Tá an fíorú as feidhm. Bain triail eile as.", - verificationRequired: "Fíorú riachtanach!", footer: 'Cosanta ag ALTCHA', getAudioChallenge: "Faigh dúshlán fuaime", label: "Níl mé i mo róbat", loading: "Á luchtú...", reload: "Athluchtaigh", verify: "Fíoraigh", + verificationRequired: "Fíorú riachtanach!", verified: "Fíoraithe", verifying: "Fíorú ar siúl...", - waitAlert: "Fíorú ar siúl... fan go fóill." + waitAlert: "Fíorú ar siúl... fan go fóill.", + cancel: "Cealaigh", + enterCodeFromImage: "Chun dul ar aghaidh, le do thoil cuir isteach an cód ón íomhá thíos." }; -globalThis.altchaI18n.set("ga", $); -const E = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("ga", i18n$G); +} +const i18n$F = { ariaLinkLabel: "Posjetite Altcha.org", enterCode: "Unesite kod", enterCodeAria: "Unesite kod koji čujete. Pritisnite razmaknicu za reprodukciju zvuka.", error: "Provjera nije uspjela. Molimo pokušajte kasnije.", expired: "Provjera je istekla. Molimo pokušajte ponovo.", - verificationRequired: "Potrebna je provjera!", footer: 'Zaštićeno od strane ALTCHA', getAudioChallenge: "Audio provjera", label: "Ja nisam robot", loading: "Učitavanje...", reload: "Ponovno učitaj", verify: "Provjeri", + verificationRequired: "Potrebna je provjera!", verified: "Provjereno", verifying: "Provjeravanje...", - waitAlert: "Provjera je u tijeku... molimo pričekajte." + waitAlert: "Provjera je u tijeku... molimo pričekajte.", + cancel: "Odustani", + enterCodeFromImage: "Za nastavak molimo unesite kod sa slike ispod." }; -globalThis.altchaI18n.set("hr", E); -const B = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("hr", i18n$F); +} +const i18n$E = { ariaLinkLabel: "Látogass el az Altcha.org oldalra", enterCode: "Írja be a kódot", enterCodeAria: "Írja be a hallott kódot. Nyomja meg a Szóköz billentyűt a hang lejátszásához.", error: "A hitelesítés nem sikerült. Próbáld meg később újra.", expired: "A hitelesítés lejárt. Próbáld újra.", - verificationRequired: "Ellenőrzés szükséges!", footer: 'Védve a következő által: ALTCHA', getAudioChallenge: "Hangalapú kihívás kérése", label: "Nem vagyok robot", loading: "Betöltés...", reload: "Újratöltés", verify: "Ellenőrzés", + verificationRequired: "Ellenőrzés szükséges!", verified: "Ellenőrizve", verifying: "Ellenőrzés folyamatban...", - waitAlert: "Ellenőrzés folyamatban... kérlek várj." + waitAlert: "Ellenőrzés folyamatban... kérlek várj.", + cancel: "Mégse", + enterCodeFromImage: "A folytatáshoz, kérjük, adja meg az alábbi kép kódját." }; -globalThis.altchaI18n.set("hu", B); -const N = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("hu", i18n$E); +} +const i18n$D = { ariaLinkLabel: "Heimsækja Altcha.org", enterCode: "Sláðu inn kóða", enterCodeAria: "Sláðu inn kóðann sem þú heyrir. Ýttu á Space til að spila hljóðið.", @@ -465,82 +476,102 @@ const N = { verificationRequired: "Staðfesting er nauðsynleg!", verified: "Staðfest", verifying: "Að staðfesta...", - waitAlert: "Að staðfesta... vinsamlegast bíða." + waitAlert: "Að staðfesta... vinsamlegast bíða.", + cancel: "Hætta við", + enterCodeFromImage: "Til að halda áfram, vinsamlegast sláðu inn kóðann af myndinni hér að neðan." }; -globalThis.altchaI18n.set("is", N); -const D = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("is", i18n$D); +} +const i18n$C = { ariaLinkLabel: "Visita Altcha.org", enterCode: "Inserisci il codice", enterCodeAria: "Inserisci il codice che senti. Premi Spazio per riprodurre l'audio.", error: "Verifica fallita. Riprova più tardi.", expired: "Verifica scaduta. Riprova.", - verificationRequired: "Verifica richiesta!", footer: 'Protetto da ALTCHA', getAudioChallenge: "Ottieni una sfida audio", label: "Non sono un robot", loading: "Caricamento...", reload: "Ricarica", verify: "Verifica", + verificationRequired: "Verifica richiesta!", verified: "Verificato", verifying: "Verifica in corso...", - waitAlert: "Verifica in corso... attendere." + waitAlert: "Verifica in corso... attendere.", + cancel: "Annulla", + enterCodeFromImage: "Per procedere, inserisci il codice dall'immagine sottostante." }; -globalThis.altchaI18n.set("it", D); -const O = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("it", i18n$C); +} +const i18n$B = { ariaLinkLabel: "Apsilankykite Altcha.org", enterCode: "Įveskite kodą", enterCodeAria: "Įveskite girdimą kodą. Paspauskite tarpo klavišą, kad grotumėte garso įrašą.", error: "Patvirtinimas nepavyko. Bandykite vėliau.", expired: "Patvirtinimo laikas baigėsi. Bandykite dar kartą.", - verificationRequired: "Reikalingas patvirtinimas!", footer: 'Apsaugota ALTCHA', getAudioChallenge: "Gauti garso užduotį", label: "Aš nesu robotas", loading: "Įkeliama...", reload: "Įkelti iš naujo", verify: "Patvirtinti", + verificationRequired: "Reikalingas patvirtinimas!", verified: "Patvirtinta", verifying: "Tikrinama...", - waitAlert: "Tikrinama... prašome palaukti." + waitAlert: "Tikrinama... prašome palaukti.", + cancel: "Atšaukti", + enterCodeFromImage: "Norėdami tęsti, įveskite kodą iš paveikslėlio žemiau." }; -globalThis.altchaI18n.set("lt", O); -const K = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("lt", i18n$B); +} +const i18n$A = { ariaLinkLabel: "Apmeklējiet Altcha.org", enterCode: "Ievadiet kodu", enterCodeAria: "Ievadiet dzirdamo kodu. Nospiediet atstarpes taustiņu, lai atskaņotu audio.", error: "Verifikācija neizdevās. Mēģiniet vēlāk vēlreiz.", expired: "Verifikācijas laiks ir beidzies. Mēģiniet vēlreiz.", - verificationRequired: "Nepieciešama verifikācija!", footer: 'Aizsargāts ar ALTCHA', getAudioChallenge: "Saņemt audio izaicinājumu", label: "Es neesmu robots", loading: "Notiek ielāde...", reload: "Pārlādēt", verify: "Verificēt", + verificationRequired: "Nepieciešama verifikācija!", verified: "Verificēts", verifying: "Notiek verifikācija...", - waitAlert: "Notiek verifikācija... lūdzu, uzgaidiet." + waitAlert: "Notiek verifikācija... lūdzu, uzgaidiet.", + cancel: "Atcelt", + enterCodeFromImage: "Lai turpinātu, lūdzu, ievadiet zemāk redzamo attēlu kodu." }; -globalThis.altchaI18n.set("lv", K); -const F = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("lv", i18n$A); +} +const i18n$z = { ariaLinkLabel: "Żur Altcha.org", enterCode: "Idħol il-kodiċi", enterCodeAria: "Idħol il-kodiċi li tisma'. Agħfas Spazju biex tindaqq l-awdjo.", error: "Il-verifika falliet. Erġa’ pprova aktar tard.", expired: "Il-verifika skadiet. Erġa’ pprova.", - verificationRequired: "Verifika meħtieġa!", footer: 'Protett minn ALTCHA', getAudioChallenge: "Ikseb sfida bl-awdjo", label: "M’inix robot", loading: "Qed jitgħabba...", reload: "Ittella’ mill-ġdid", verify: "Ivverifika", + verificationRequired: "Verifika meħtieġa!", verified: "Ivverifikat", verifying: "Verifika għaddejja...", - waitAlert: "Verifika għaddejja... stenna ftit." + waitAlert: "Verifika għaddejja... stenna ftit.", + cancel: "Ikkanċella", + enterCodeFromImage: "Biex tipproċedi, jekk jogħġbok daħħal il-kodiċi mill-immaġni hawn taħt." }; -globalThis.altchaI18n.set("mt", F); -const f = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("mt", i18n$z); +} +const i18n$y = { ariaLinkLabel: "Besøk Altcha.org", enterCode: "Skriv inn kode", enterCodeAria: "Skriv inn koden du hører. Trykk på Space for å spille av lyden.", @@ -555,155 +586,190 @@ const f = { verificationRequired: "Verifisering kreves!", verified: "Verifisert", verifying: "Verifiserer...", - waitAlert: "Verifiserer... vennligst vent." + waitAlert: "Verifiserer... vennligst vent.", + cancel: "Avbryt", + enterCodeFromImage: "For å fortsette, vennligst skriv inn koden fra bildet nedenfor." }; -globalThis.altchaI18n.set("nb", f); -globalThis.altchaI18n.set("no", f); -const M = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("nb", i18n$y); +} +const i18n$x = { ariaLinkLabel: "Bezoek Altcha.org", enterCode: "Voer code in", enterCodeAria: "Voer de code in die je hoort. Druk op Spatie om de audio af te spelen.", error: "Verificatie mislukt. Probeer het later opnieuw.", expired: "Verificatie verlopen. Probeer het opnieuw.", - verificationRequired: "Verificatie vereist!", footer: 'Beschermd door ALTCHA', getAudioChallenge: "Audio-uitdaging ontvangen", label: "Ik ben geen robot", loading: "Laden...", reload: "Herladen", verify: "Verifiëren", + verificationRequired: "Verificatie vereist!", verified: "Geverifieerd", verifying: "Bezig met verifiëren...", - waitAlert: "Bezig met verifiëren... even geduld a.u.b." + waitAlert: "Bezig met verifiëren... even geduld a.u.b.", + cancel: "Annuleren", + enterCodeFromImage: "Om door te gaan, voert u de code uit de onderstaande afbeelding in." }; -globalThis.altchaI18n.set("nl", M); -const Z = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("nl", i18n$x); +} +const i18n$w = { ariaLinkLabel: "Odwiedź Altcha.org", enterCode: "Wprowadź kod", enterCodeAria: "Wpisz kod, który słyszysz. Naciśnij Spację, aby odtworzyć dźwięk.", error: "Weryfikacja nie powiodła się. Spróbuj ponownie później.", expired: "Weryfikacja wygasła. Spróbuj ponownie.", - verificationRequired: "Wymagana weryfikacja!", footer: 'Chronione przez ALTCHA', getAudioChallenge: "Pobierz zadanie dźwiękowe", label: "Nie jestem robotem", loading: "Ładowanie...", reload: "Odśwież", verify: "Zweryfikuj", + verificationRequired: "Wymagana weryfikacja!", verified: "Zweryfikowano", verifying: "Weryfikacja...", - waitAlert: "Trwa weryfikacja... proszę czekać." + waitAlert: "Trwa weryfikacja... proszę czekać.", + cancel: "Anuluj", + enterCodeFromImage: "Aby kontynuować, wprowadź kod z poniższego obrazka." }; -globalThis.altchaI18n.set("pl", Z); -const U = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("pl", i18n$w); +} +const i18n$v = { ariaLinkLabel: "Visitar Altcha.org", enterCode: "Introduza o código", enterCodeAria: "Introduza o código que ouve. Prima Espaço para reproduzir o áudio.", error: "A verificação falhou. Por favor, tente novamente mais tarde.", expired: "Verificação expirada. Por favor, tente novamente.", - verificationRequired: "Verificação necessária!", footer: 'Protegido por ALTCHA', getAudioChallenge: "Obter desafio de áudio", label: "Não sou um robô", loading: "A carregar...", reload: "Recarregar", verify: "Verificar", + verificationRequired: "Verificação necessária!", verified: "Verificado", verifying: "A verificar...", - waitAlert: "A verificar... por favor aguarde." + waitAlert: "A verificar... por favor aguarde.", + cancel: "Cancelar", + enterCodeFromImage: "Para prosseguir, introduza o código da imagem abaixo." }; -globalThis.altchaI18n.set("pt-pt", U); -const G = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("pt-pt", i18n$v); +} +const i18n$u = { ariaLinkLabel: "Visitar Altcha.org", enterCode: "Digite o código", enterCodeAria: "Digite o código que você ouve. Pressione Espaço para reproduzir o áudio.", error: "Falha na verificação. Por favor, tente novamente mais tarde.", expired: "Verificação expirada. Por favor, tente novamente.", - verificationRequired: "Verificação necessária!", footer: 'Protegido por ALTCHA', getAudioChallenge: "Obter desafio de áudio", label: "Eu não sou um robô", loading: "Carregando...", reload: "Recarregar", verify: "Verificar", + verificationRequired: "Verificação necessária!", verified: "Verificado", verifying: "Verificando...", - waitAlert: "Verificando... por favor aguarde." + waitAlert: "Verificando... por favor aguarde.", + cancel: "Cancelar", + enterCodeFromImage: "Para prosseguir, digite o código da imagem abaixo." }; -globalThis.altchaI18n.set("pt-br", G); -const W = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("pt-br", i18n$u); +} +const i18n$t = { ariaLinkLabel: "Vizitează Altcha.org", enterCode: "Introduceți codul", enterCodeAria: "Introduceți codul pe care îl auziți. Apăsați Spațiu pentru a reda audio.", error: "Verificarea a eșuat. Încearcă din nou mai târziu.", expired: "Verificarea a expirat. Încearcă din nou.", - verificationRequired: "Verificare necesară!", footer: 'Protejat de ALTCHA', getAudioChallenge: "Obține o provocare audio", label: "Nu sunt un robot", loading: "Se încarcă...", reload: "Reîncarcă", verify: "Verifică", + verificationRequired: "Verificare necesară!", verified: "Verificat", verifying: "Se verifică...", - waitAlert: "Se verifică... te rugăm să aștepți." + waitAlert: "Se verifică... te rugăm să aștepți.", + cancel: "Anulare", + enterCodeFromImage: "Pentru a continua, vă rugăm să introduceți codul din imaginea de mai jos." }; -globalThis.altchaI18n.set("ro", W); -const J = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("ro", i18n$t); +} +const i18n$s = { ariaLinkLabel: "Перейти на Altcha.org", enterCode: "Введите код", enterCodeAria: "Введите код, который слышите. Нажмите пробел для воспроизведения аудио.", error: "Ошибка верификации. Попробуйте позже.", expired: "Срок действия верификации истек. Попробуйте снова.", - verificationRequired: "Требуется проверка!", footer: 'Защищено ALTCHA', getAudioChallenge: "Получить аудио задачу", label: "Я не робот", loading: "Загрузка...", reload: "Перезагрузить", verify: "Проверить", + verificationRequired: "Требуется проверка!", verified: "Проверено", verifying: "Идет проверка...", - waitAlert: "Идет проверка... Пожалуйста, подождите." + waitAlert: "Идет проверка... Пожалуйста, подождите.", + cancel: "Отмена", + enterCodeFromImage: "Чтобы продолжить, пожалуйста, введите код с изображения ниже." }; -globalThis.altchaI18n.set("ru", J); -const Y = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("ru", i18n$s); +} +const i18n$r = { ariaLinkLabel: "Navštívte Altcha.org", enterCode: "Zadajte kód", enterCodeAria: "Zadajte kód, ktorý počujete. Stlačením medzerníka prehráte zvuk.", error: "Verifikácia zlyhala. Skúste to znova neskôr.", expired: "Verifikácia vypršala. Skúste to znova.", - verificationRequired: "Vyžaduje sa overenie!", footer: 'Chránené ALTCHA', getAudioChallenge: "Získať audio výzvu", label: "Nie som robot", loading: "Načítava sa...", reload: "Obnoviť", verify: "Verifikovať", + verificationRequired: "Vyžaduje sa overenie!", verified: "Verifikované", verifying: "Prebieha verifikácia...", - waitAlert: "Prebieha verifikácia... prosím čakajte." + waitAlert: "Prebieha verifikácia... prosím čakajte.", + cancel: "Zrušiť", + enterCodeFromImage: "Na pokračovanie, prosím, zadajte kód z obrázka nižšie." }; -globalThis.altchaI18n.set("sk", Y); -const Q = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("sk", i18n$r); +} +const i18n$q = { ariaLinkLabel: "Obiščite Altcha.org", enterCode: "Vnesite kodo", enterCodeAria: "Vnesite kodo, ki jo slišite. Pritisnite preslednico za predvajanje zvoka.", error: "Preverjanje ni uspelo. Poskusite znova kasneje.", expired: "Preverjanje je poteklo. Poskusite znova.", - verificationRequired: "Potrebna je preveritev!", footer: 'Zaščiteno z ALTCHA', getAudioChallenge: "Pridobite zvočni izziv", label: "Nisem robot", loading: "Nalagam...", reload: "Ponovno naloži", verify: "Preveri", + verificationRequired: "Potrebna je preveritev!", verified: "Preverjeno", verifying: "Preverjanje...", - waitAlert: "Preverjanje... prosim počakajte." + waitAlert: "Preverjanje... prosim počakajte.", + cancel: "Preklic", + enterCodeFromImage: "Za nadaljevanje, prosimo, vnesite kodo s slike spodaj." }; -globalThis.altchaI18n.set("sl", Q); -const X = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("sl", i18n$q); +} +const i18n$p = { ariaLinkLabel: "Vizitoni Altcha.org", enterCode: "Fut kodin", enterCodeAria: "Fut kodin që dëgjon. Shtypni Hapësirë për të luajtur audio.", @@ -718,10 +784,14 @@ const X = { verificationRequired: "Kërkohet verifikimi!", verified: "I verifikuar", verifying: "Duke verifikuar...", - waitAlert: "Duke verifikuar... ju lutem prisni." + waitAlert: "Duke verifikuar... ju lutem prisni.", + cancel: "Anuloje", + enterCodeFromImage: "Për të vazhduar, ju lutemi fusni kodin nga imazhi më poshtë." }; -globalThis.altchaI18n.set("sq", X); -const ee = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("sq", i18n$p); +} +const i18n$o = { ariaLinkLabel: "Posetite Altcha.org", enterCode: "Unesite kod", enterCodeAria: "Unesite kod koji čujete. Pritisnite Space da biste pustili zvuk.", @@ -736,64 +806,80 @@ const ee = { verificationRequired: "Verifikacija je obavezna!", verified: "Verifikovano", verifying: "Verifikacija u toku...", - waitAlert: "Verifikacija u toku... molimo vas da sačekate." + waitAlert: "Verifikacija u toku... molimo vas da sačekate.", + cancel: "Откажи", + enterCodeFromImage: "Да бисте наставили, унесите код са слике испод." }; -globalThis.altchaI18n.set("sr", ee); -const ae = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("sr", i18n$o); +} +const i18n$n = { ariaLinkLabel: "Besök Altcha.org", enterCode: "Ange kod", enterCodeAria: "Ange koden du hör. Tryck på mellanslag för att spela upp ljudet.", error: "Verifiering misslyckades. Försök igen senare.", expired: "Verifieringen har gått ut. Försök igen.", - verificationRequired: "Verifiering krävs!", footer: 'Skyddad av ALTCHA', getAudioChallenge: "Få ljudutmaning", label: "Jag är inte en robot", loading: "Laddar...", reload: "Ladda om", verify: "Verifiera", + verificationRequired: "Verifiering krävs!", verified: "Verifierad", verifying: "Verifierar...", - waitAlert: "Verifierar... vänligen vänta." + waitAlert: "Verifierar... vänligen vänta.", + cancel: "Avbryt", + enterCodeFromImage: "För att fortsätta, ange koden från bilden nedan." }; -globalThis.altchaI18n.set("sv", ae); -const ie = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("sv", i18n$n); +} +const i18n$m = { ariaLinkLabel: "Altcha.org'yu ziyaret edin", enterCode: "Kodu girin", enterCodeAria: "Duyduğunuz kodu girin. Ses dosyasını oynatmak için Boşluk tuşuna basın.", error: "Doğrulama başarısız oldu. Lütfen daha sonra tekrar deneyin.", expired: "Doğrulama süresi doldu. Lütfen tekrar deneyin.", - verificationRequired: "Doğrulama gerekli!", footer: `ALTCHA tarafından korunuyor ALTCHA`, getAudioChallenge: "Sesli doğrulama al", label: "Ben robot değilim", loading: "Yükleniyor...", reload: "Yeniden yükle", verify: "Doğrula", + verificationRequired: "Doğrulama gerekli!", verified: "Doğrulandı", verifying: "Doğrulama yapılıyor...", - waitAlert: "Doğrulama yapılıyor... lütfen bekleyin." + waitAlert: "Doğrulama yapılıyor... lütfen bekleyin.", + cancel: "İptal", + enterCodeFromImage: "Devam etmek için lütfen aşağıdaki resimdeki kodu girin." }; -globalThis.altchaI18n.set("tr", ie); -const re = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("tr", i18n$m); +} +const i18n$l = { ariaLinkLabel: "Відвідати Altcha.org", enterCode: "Введіть код", enterCodeAria: "Введіть код, який ви чуєте. Натисніть пробіл, щоб відтворити аудіо.", error: "Перевірка не вдалася. Спробуйте пізніше.", expired: "Перевірка прострочена. Спробуйте знову.", - verificationRequired: "Потрібна перевірка!", footer: 'Захищено ALTCHA', getAudioChallenge: "Отримати аудіо-челлендж", label: "Я не робот", loading: "Завантаження...", reload: "Перезавантажити", verify: "Перевірити", + verificationRequired: "Потрібна перевірка!", verified: "Перевірено", verifying: "Перевіряється...", - waitAlert: "Перевірка... будь ласка, зачекайте." + waitAlert: "Перевірка... будь ласка, зачекайте.", + cancel: "Скасувати", + enterCodeFromImage: "Щоб продовжити, введіть код із зображення нижче." }; -globalThis.altchaI18n.set("uk", re); -const te = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("uk", i18n$l); +} +const i18n$k = { ariaLinkLabel: "Besoek Altcha.org", enterCode: "Voer kode in", enterCodeAria: "Voer die kode in wat jy hoor. Druk Spasie om die klank af te speel.", @@ -808,10 +894,14 @@ const te = { verificationRequired: "Verifikasie is vereis!", verified: "Geverifieer", verifying: "Verifieer...", - waitAlert: "Verifieer... wag asseblief." + waitAlert: "Verifieer... wag asseblief.", + cancel: "Kanselleer", + enterCodeFromImage: "Om voort te gaan, voer asseblief die kode vanaf die onderstaande prentjie in." }; -globalThis.altchaI18n.set("af", te); -const oe = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("af", i18n$k); +} +const i18n$j = { ariaLinkLabel: "Altcha.org ይጎብኙ", enterCode: "ኮድ አስገባ", enterCodeAria: "የሚሰማዎትን ኮድ ያስገቡ። ድምጽ ለመጫወት Space ን ይጫኑ።", @@ -826,10 +916,14 @@ const oe = { verificationRequired: "ማረጋገጫ ያስፈልጋል!", verified: "ተረጋግጧል", verifying: "በማረጋገጥ ላይ...", - waitAlert: "በማረጋገጥ ላይ... እባክዎ ይጠብቁ።" + waitAlert: "በማረጋገጥ ላይ... እባክዎ ይጠብቁ።", + cancel: "ይቅር", + enterCodeFromImage: "ለመቀጠል፣ እባክዎን ከታች ካለው ምስል ኮዱን ያስገቡ።" }; -globalThis.altchaI18n.set("am", oe); -const le = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("am", i18n$j); +} +const i18n$i = { ariaLinkLabel: "Tembelea Altcha.org", enterCode: "Weka nambari", enterCodeAria: "Weka nambari unayosikia. Bonyeza Space kucheza sauti.", @@ -844,10 +938,14 @@ const le = { verificationRequired: "Uthibitishaji unahitajika!", verified: "Imethibitishwa", verifying: "Inathibitisha...", - waitAlert: "Inathibitisha... tafadhali subiri." + waitAlert: "Inathibitisha... tafadhali subiri.", + cancel: "Ghairi", + enterCodeFromImage: "Ili kuendelea, tafadhali weka nambari kutoka kwa picha hapa chini." }; -globalThis.altchaI18n.set("sw", le); -const ne = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("sw", i18n$i); +} +const i18n$h = { ariaLinkLabel: "Ṣe abẹwo si Altcha.org", enterCode: "Tẹ koodu sii", enterCodeAria: "Tẹ koodu ti o ngbọ sii. Tẹ Space lati ṣe ohun orin.", @@ -862,118 +960,146 @@ const ne = { verificationRequired: "Ìdájọ́kòwò ni a nílò!", verified: "A ti dájọ́", verifying: "Ó ń ṣàdájọ́...", - waitAlert: "Ó ń ṣàdájọ́... ẹ jọ̀ọ́ ẹ duro." + waitAlert: "Ó ń ṣàdájọ́... ẹ jọ̀ọ́ ẹ duro.", + cancel: "Fagbọsẹ", + enterCodeFromImage: "Lati tẹsiwaju, jọwọ tẹ koodu ti o wa lati aworan isalẹ sii." }; -globalThis.altchaI18n.set("yo", ne); -const de = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("yo", i18n$h); +} +const i18n$g = { ariaLinkLabel: "Altcha.org পরিদর্শন করুন", enterCode: "কোড লিখুন", enterCodeAria: "আপনি যে কোড শুনতে পান তা লিখুন। অডিও প্লে করতে স্পেস বাটন টিপুন।", error: "যাচাইকরণ ব্যর্থ হয়েছে। পরে আবার চেষ্টা করুন।", expired: "যাচাইকরণ সময়সীমা শেষ হয়েছে। আবার চেষ্টা করুন।", - verificationRequired: "যাচাই প্রয়োজন!", footer: 'দ্বারা সুরক্ষিত ALTCHA', getAudioChallenge: "অডিও চ্যালেঞ্জ নিন", label: "আমি রোবট নই", loading: "লোড হচ্ছে...", reload: "পুনরায় লোড করুন", verify: "যাচাই করুন", + verificationRequired: "যাচাই প্রয়োজন!", verified: "যাচাই করা হয়েছে", verifying: "যাচাই করা হচ্ছে...", - waitAlert: "যাচাই করা হচ্ছে... দয়া করে অপেক্ষা করুন।" + waitAlert: "যাচাই করা হচ্ছে... দয়া করে অপেক্ষা করুন।", + cancel: "বাতিল করুন", + enterCodeFromImage: "এগিয়ে যেতে, অনুগ্রহ করে নীচের চিত্র থেকে কোডটি প্রবেশ করান।" }; -globalThis.altchaI18n.set("bn", de); -const se = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("bn", i18n$g); +} +const i18n$f = { ariaLinkLabel: "בקר באתר Altcha.org", enterCode: "הזן קוד", enterCodeAria: "הזן את הקוד שאתה שומע. לחץ על רווח להפעלת השמע.", error: "האימות נכשל. נסה שוב מאוחר יותר.", expired: "תוקף האימות פג. נסה שוב.", - verificationRequired: "נדרש אימות!", footer: 'מוגן על ידי ALTCHA', getAudioChallenge: "קבל אתגר שמע", label: "אני לא רובוט", loading: "טוען...", reload: "טען מחדש", verify: "אמת", + verificationRequired: "נדרש אימות!", verified: "אומת", verifying: "מאמת...", - waitAlert: "מבצע אימות... אנא המתן." + waitAlert: "מבצע אימות... אנא המתן.", + cancel: "ביטול", + enterCodeFromImage: "כדי להמשיך, אנא הזן את הקוד מהתמונה למטה." }; -globalThis.altchaI18n.set("he", se); -const ge = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("he", i18n$f); +} +const i18n$e = { ariaLinkLabel: "Altcha.org पर जाएं", enterCode: "कोड दर्ज करेंं", enterCodeAria: "आप जो कोड सुनते हैं उसे दर्ज करें। ऑडियो चलाने के लिए स्पेस दबाएं।", error: "सत्यापन विफल। कृपया बाद में फिर से प्रयास करें।", expired: "सत्यापन समाप्त हो गया है। कृपया पुनः प्रयास करें।", - verificationRequired: "सत्यापन आवश्यक है!", footer: 'द्वारा संरक्षित ALTCHA', getAudioChallenge: "ऑडियो चुनौती प्राप्त करें", label: "मैं रोबोट नहीं हूँ", loading: "लोड हो रहा है...", reload: "पुनः लोड करें", verify: "सत्यापित करें", + verificationRequired: "सत्यापन आवश्यक है!", verified: "सत्यापित", verifying: "सत्यापित कर रहे हैं...", - waitAlert: "सत्यापित किया जा रहा है... कृपया प्रतीक्षा करें।" + waitAlert: "सत्यापित किया जा रहा है... कृपया प्रतीक्षा करें।", + cancel: "रद्द करें", + enterCodeFromImage: "आगे बढ़ने के लिए, कृपया नीचे दी गई छवि से कोड दर्ज करें।" }; -globalThis.altchaI18n.set("hi", ge); -const he = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("hi", i18n$e); +} +const i18n$d = { ariaLinkLabel: "Kunjungi Altcha.org", enterCode: "Masukkan kode", enterCodeAria: "Masukkan kode yang Anda dengar. Tekan Spasi untuk memutar audio.", error: "Verifikasi gagal. Coba lagi nanti.", expired: "Verifikasi telah kedaluwarsa. Coba lagi.", - verificationRequired: "Verifikasi diperlukan!", footer: 'Dilindungi oleh ALTCHA', getAudioChallenge: "Dapatkan tantangan audio", label: "Saya bukan robot", loading: "Memuat...", reload: "Muat ulang", verify: "Verifikasi", + verificationRequired: "Verifikasi diperlukan!", verified: "Terverifikasi", verifying: "Memverifikasi...", - waitAlert: "Memverifikasi... harap tunggu." + waitAlert: "Memverifikasi... harap tunggu.", + cancel: "Batal", + enterCodeFromImage: "Untuk melanjutkan, silakan masukkan kode dari gambar di bawah ini." }; -globalThis.altchaI18n.set("id", he); -const ce = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("id", i18n$d); +} +const i18n$c = { ariaLinkLabel: "Altcha.orgを訪問", enterCode: "コードを入力", enterCodeAria: "聞こえるコードを入力してください。スペースキーを押して音声を再生します。", error: "認証に失敗しました。後でもう一度試してください。", expired: "認証が期限切れです。再試行してください。", - verificationRequired: "認証が必要です!", footer: '保護されています ALTCHA', getAudioChallenge: "音声チャレンジを取得", label: "私はロボットではありません", loading: "読み込み中...", reload: "再読み込み", verify: "確認", + verificationRequired: "認証が必要です!", verified: "確認済み", verifying: "確認中...", - waitAlert: "確認中...少々お待ちください。" + waitAlert: "確認中...少々お待ちください。", + cancel: "キャンセル", + enterCodeFromImage: "続行するには、以下の画像からコードを入力してください。" }; -globalThis.altchaI18n.set("ja", ce); -const fe = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("ja", i18n$c); +} +const i18n$b = { ariaLinkLabel: "Altcha.org 방문하기", enterCode: "코드 입력", enterCodeAria: "들리는 코드를 입력하세요. 스페이스 바를 눌러 오디오를 재생합니다.", error: "인증 실패. 나중에 다시 시도해주세요.", expired: "인증이 만료되었습니다. 다시 시도해주세요.", - verificationRequired: "인증이 필요합니다!", footer: 'ALTCHA에서 보호됨 ALTCHA', getAudioChallenge: "오디오 챌린지 받기", label: "저는 로봇이 아닙니다", loading: "로딩 중...", reload: "새로 고침", verify: "확인", + verificationRequired: "인증이 필요합니다!", verified: "확인됨", verifying: "확인 중...", - waitAlert: "확인 중... 잠시만 기다려주세요." + waitAlert: "확인 중... 잠시만 기다려주세요.", + cancel: "취소", + enterCodeFromImage: "계속 진행하려면 아래 이미지에서 코드를 입력하세요." }; -globalThis.altchaI18n.set("ko", fe); -const ue = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("ko", i18n$b); +} +const i18n$a = { ariaLinkLabel: "Altcha.org сайтына кіру", enterCode: "Кодты енгізіңіз", enterCodeAria: "Естіген кодыңызды енгізіңіз. Аудионы ойнату үшін Бос орынды басыңыз.", @@ -988,100 +1114,124 @@ const ue = { verificationRequired: "Тексеру талап етіледі!", verified: "Тексерілді", verifying: "Тексеруде...", - waitAlert: "Тексерілуде... күте тұрыңыз." + waitAlert: "Тексерілуде... күте тұрыңыз.", + cancel: "Болдыру", + enterCodeFromImage: "Жалғастыру үшін төмендегі суреттегі кодты енгізіңіз." }; -globalThis.altchaI18n.set("kk", ue); -const be = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("kk", i18n$a); +} +const i18n$9 = { ariaLinkLabel: "Altcha.org भेट द्या", enterCode: "कोड टाकाा", enterCodeAria: "तुम्ही ऐकत असलेला कोड टाका. ऑडिओ प्ले करण्यासाठी स्पेस दाबा.", error: "पुष्टीकरण अयशस्वी झाले. कृपया नंतर पुन्हा प्रयत्न करा.", expired: "पुष्टीकरण कालबाह्य झाले आहे. कृपया पुन्हा प्रयत्न करा.", - verificationRequired: "पडताळणी आवश्यक आहे!", footer: 'द्वारे संरक्षित ALTCHA', getAudioChallenge: "ऑडिओ चॅलेंज मिळवा", label: "मी रोबोट नाही", loading: "लोड होत आहे...", reload: "पुन्हा लोड करा", verify: "पुष्टीकरण करा", + verificationRequired: "पडताळणी आवश्यक आहे!", verified: "पुष्टीकरण झाले", verifying: "पुष्टीकरण करत आहे...", - waitAlert: "पुष्टीकरण करत आहे... कृपया थोडा वेळ थांबा." + waitAlert: "पुष्टीकरण करत आहे... कृपया थोडा वेळ थांबा.", + cancel: "रद्द करा", + enterCodeFromImage: "पुढे जाण्यासाठी, कृपया खालील प्रतिमेतील कोड प्रविष्ट करा." }; -globalThis.altchaI18n.set("mr", be); -const ve = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("mr", i18n$9); +} +const i18n$8 = { ariaLinkLabel: "Altcha.org ஐ பார்வையிடவும்", enterCode: "குறியீட்டை உள்ளிடவும்", enterCodeAria: "நீங்கள் கேட்கும் குறியீட்டை உள்ளிடவும். ஆடியோவை இயக்க Space ஐ அழுத்தவும்.", error: "சரிபார்ப்பு தோல்வி. பிறகு மீண்டும் முயற்சிக்கவும்.", expired: "சரிபார்ப்பு காலாவதியானது. மீண்டும் முயற்சிக்கவும்.", - verificationRequired: "சரிபார்ப்பு தேவை!", footer: 'மூலமாக பாதுகாக்கப்பட்டவை ALTCHA', getAudioChallenge: "ஒலி சவாலை பெறவும்", label: "நான் ரோபோடான அல்ல", loading: "செயலாக்கம்...", reload: "மீண்டும் புதுப்பிக்கவும்", verify: "சரிபார்க்கவும்", + verificationRequired: "சரிபார்ப்பு தேவை!", verified: "சரிபார்க்கப்பட்டது", verifying: "சரிபார்க்கப்படுகிறது...", - waitAlert: "சரிபார்க்கப்படுகிறது... தயவுசெய்து காத்திருக்கவும்." + waitAlert: "சரிபார்க்கப்படுகிறது... தயவுசெய்து காத்திருக்கவும்.", + cancel: "ரத்துசெய்", + enterCodeFromImage: "தொடர, கீழே உள்ள படத்திலிருந்து குறியீட்டை உள்ளிடவும்." }; -globalThis.altchaI18n.set("ta", ve); -const Ae = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("ta", i18n$8); +} +const i18n$7 = { ariaLinkLabel: "Altcha.org సందర్శించండి", enterCode: "కోడ్‌ని నమోదు చేయండి", enterCodeAria: "మీరు విన్న కోడ్‌ని నమోదు చేయండి. ఆడియో ప్లే చేయడానికి స్పేస్‌ను నొక్కండి.", error: "చెకింగ్ విఫలమైంది. దయచేసి మరల ప్రయత్నించండి.", expired: "చెకింగ్ కాలం ముగిసింది. దయచేసి మరల ప్రయత్నించండి.", - verificationRequired: "ధృవీకరణ అవసరం!", footer: 'ఈ సైట్ రక్షించబడింది ALTCHA', getAudioChallenge: "ఆడియో ఛాలెంజ్ పొందండి", label: "నేను రోబోట్ కాదు", loading: "లోడ్ అవుతోంది...", reload: "మళ్ళీ లోడ్ చేయండి", verify: "ధ్రువీకరించు", + verificationRequired: "ధృవీకరణ అవసరం!", verified: "ధ్రువీకరించబడింది", verifying: "ధ్రువీకరణ జరుగుతుంది...", - waitAlert: "ధ్రువీకరణ జరుగుతుంది... దయచేసి వేచి ఉండండి." + waitAlert: "ధ్రువీకరణ జరుగుతుంది... దయచేసి వేచి ఉండండి.", + cancel: "రద్దు చేయండి", + enterCodeFromImage: "కొనసాగడానికి, దయచేసి క్రింది చిత్రంలో ఉన్న కోడ్‌ను నమోదు చేయండి." }; -globalThis.altchaI18n.set("te", Ae); -const ke = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("te", i18n$7); +} +const i18n$6 = { ariaLinkLabel: "เยี่ยมชม Altcha.org", enterCode: "ป้อนรหัส", enterCodeAria: "ป้อนรหัสที่คุณได้ยิน กด Space เพื่อเล่นเสียง", error: "การตรวจสอบล้มเหลว กรุณาลองอีกครั้งภายหลัง", expired: "การตรวจสอบหมดอายุ กรุณาลองใหม่", - verificationRequired: "จำเป็นต้องตรวจสอบ!", footer: 'ป้องกันโดย ALTCHA', getAudioChallenge: "รับการท้าทายเสียง", label: "ฉันไม่ใช่บอท", loading: "กำลังโหลด...", reload: "โหลดใหม่", verify: "ตรวจสอบ", + verificationRequired: "จำเป็นต้องตรวจสอบ!", verified: "ตรวจสอบแล้ว", verifying: "กำลังตรวจสอบ...", - waitAlert: "กำลังตรวจสอบ... กรุณารอ" + waitAlert: "กำลังตรวจสอบ... กรุณารอ", + cancel: "ยกเลิก", + enterCodeFromImage: "เพื่อดำเนินการต่อ โปรดป้อนรหัสจากรูปภาพด้านล่าง" }; -globalThis.altchaI18n.set("th", ke); -const pe = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("th", i18n$6); +} +const i18n$5 = { ariaLinkLabel: "Altcha.org پر جائیں", enterCode: "کوڈ درج کریں", enterCodeAria: "جو کوڈ آپ سنتے ہیں وہ درج کریں۔ آڈیو چلانے کے لیے اسپیس دبائیں۔", error: "توثیق ناکام ہو گئی۔ براہ کرم بعد میں دوبارہ کوشش کریں۔", expired: "توثیق کی مدت ختم ہو گئی ہے۔ براہ کرم دوبارہ کوشش کریں۔", - verificationRequired: "تصدیق ضروری ہے!", footer: 'کے ذریعے محفوظ ALTCHA', getAudioChallenge: "آڈیو چیلنج حاصل کریں", label: "میں روبوٹ نہیں ہوں", loading: "لوڈ ہو رہا ہے...", reload: "دوبارہ لوڈ کریں", verify: "توثیق کریں", + verificationRequired: "تصدیق ضروری ہے!", verified: "توثیق شدہ", verifying: "توثیق ہو رہی ہے...", - waitAlert: "توثیق ہو رہی ہے... براہ کرم انتظار کریں۔" + waitAlert: "توثیق ہو رہی ہے... براہ کرم انتظار کریں۔", + cancel: "منسوخ کریں", + enterCodeFromImage: "اگلے مرحلے پر جانے کے لیے، براہ کرم نیچے دی گئی تصویر سے کوڈ درج کریں۔" }; -globalThis.altchaI18n.set("ur", pe); -const Ce = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("ur", i18n$5); +} +const i18n$4 = { ariaLinkLabel: "Altcha.org saytiga tashrif buyuring", enterCode: "Kodni kiriting", enterCodeAria: "Eshitgan kodingizni kiriting. Audioni ijro etish uchun Bo'sh joy tugmasini bosing.", @@ -1096,60 +1246,98 @@ const Ce = { verificationRequired: "Tekshiruv talab qilinadi!", verified: "Tekshirildi", verifying: "Tekshirilmoqda...", - waitAlert: "Tekshirilmoqda... iltimos kuting." + waitAlert: "Tekshirilmoqda... iltimos kuting.", + cancel: "Bekor qilish", + enterCodeFromImage: "Davom etish uchun, iltimos, quyidagi rasmda ko'rsatilgan kodni kiriting." }; -globalThis.altchaI18n.set("uz", Ce); -const ye = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("uz", i18n$4); +} +const i18n$3 = { ariaLinkLabel: "Truy cập Altcha.org", enterCode: "Nhập mã", enterCodeAria: "Nhập mã bạn nghe được. Nhấn Phím cách để phát âm thanh.", error: "Xác minh thất bại. Vui lòng thử lại sau.", expired: "Xác minh đã hết hạn. Vui lòng thử lại.", - verificationRequired: "Yêu cầu xác minh!", footer: 'Được bảo vệ bởi ALTCHA', getAudioChallenge: "Nhận thử thách âm thanh", label: "Tôi không phải là robot", loading: "Đang tải...", reload: "Tải lại", verify: "Xác minh", + verificationRequired: "Yêu cầu xác minh!", verified: "Đã xác minh", verifying: "Đang xác minh...", - waitAlert: "Đang xác minh... vui lòng chờ." + waitAlert: "Đang xác minh... vui lòng chờ.", + cancel: "Hủy bỏ", + enterCodeFromImage: "Để tiếp tục, vui lòng nhập mã từ hình ảnh bên dưới." }; -globalThis.altchaI18n.set("vi", ye); -const Le = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("vi", i18n$3); +} +const i18n$2 = { ariaLinkLabel: "访问 Altcha.org", enterCode: "输入代码", enterCodeAria: "输入您听到的代码。按空格键播放音频。", error: "验证失败。稍后再试。", expired: "验证已过期。请重试。", - verificationRequired: "需要验证!", footer: '由 ALTCHA 保护', getAudioChallenge: "获取音频挑战", label: "我不是机器人", loading: "加载中...", reload: "重新加载", verify: "验证", + verificationRequired: "需要验证!", verified: "已验证", verifying: "正在验证...", - waitAlert: "正在验证... 请稍等。" + waitAlert: "正在验证... 请稍等。", + cancel: "取消", + enterCodeFromImage: "为继续操作,请输入下图中显示的验证码。" +}; +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("zh-cn", i18n$2); +} +const i18n$1 = { + ariaLinkLabel: "前往 Altcha.org", + cancel: "取消", + enterCode: "輸入代碼", + enterCodeAria: "輸入你聽到嘅代碼。按空格鍵播放音訊。", + enterCodeFromImage: "要繼續,請輸入下面圖片入面嘅代碼。", + error: "驗證失敗。請稍後再試。", + expired: "驗證已過期。請再試一次。", + footer: '由 ALTCHA 提供保護', + getAudioChallenge: "取得音訊驗證", + label: "我唔係機械人", + loading: "載入中...", + reload: "重新載入", + verify: "驗證", + verificationRequired: "需要驗證!", + verified: "已驗證", + verifying: "驗證中...", + waitAlert: "驗證中... 請稍候。" }; -globalThis.altchaI18n.set("zh-cn", Le); -const me = { +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("zh-hk", i18n$1); +} +const i18n = { ariaLinkLabel: "訪問 Altcha.org", enterCode: "輸入代碼", enterCodeAria: "輸入您聽到的代碼。按空格鍵播放音頻。", error: "驗證失敗。稍後再試。", expired: "驗證已過期。請重試。", - verificationRequired: "需要驗證!", footer: '由 ALTCHA 保護', getAudioChallenge: "獲取音頻挑戰", label: "我不是機器人", loading: "載入中...", reload: "重新載入", verify: "驗證", + verificationRequired: "需要驗證!", verified: "已驗證", verifying: "正在驗證...", - waitAlert: "正在驗證... 請稍等。" + waitAlert: "正在驗證... 請稍等。", + cancel: "取消", + enterCodeFromImage: "若要繼續,請輸入下方的圖片驗證碼。" }; -globalThis.altchaI18n.set("zh-tw", me); +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("zh-tw", i18n); +} \ No newline at end of file diff --git a/website_altcha/static/lib/altcha.css b/website_altcha/static/lib/altcha.css new file mode 100644 index 0000000000..975c2e2d9b --- /dev/null +++ b/website_altcha/static/lib/altcha.css @@ -0,0 +1 @@ +:root{--altcha-border-color:var(--altcha-color-neutral);--altcha-border-width:1px;--altcha-border-radius:6px;--altcha-color-base:light-dark(oklch(100% 0.00011 271.152),oklch(20.904% 0.00002 271.152));--altcha-color-base-content:light-dark(oklch(20.904% 0.00002 271.152),oklch(100% 0.00011 271.152));--altcha-color-error:oklch(51.284% 0.20527 28.678);--altcha-color-error-content:oklch(100% 0.00011 271.152);--altcha-color-neutral:light-dark(oklch(83.591% 0.0001 271.152),oklch(46.04% 0.00005 271.152));--altcha-color-neutral-content:light-dark(oklch(46.76% 0.00005 271.152),oklch(100% 0.00011 271.152));--altcha-color-primary:oklch(40.279% 0.2449 268.131);--altcha-color-primary-content:oklch(100% 0.00011 271.152);--altcha-color-success:oklch(55.748% 0.18968 142.511);--altcha-color-success-content:oklch(100% 0.00011 271.152);--altcha-checkbox-border-color:var(--altcha-color-neutral);--altcha-checkbox-border-radius:5px;--altcha-checkbox-border-width:var(--altcha-border-width);--altcha-checkbox-outline:2px solid var(--altcha-checkbox-outline-color);--altcha-checkbox-outline-color:light-dark(color-mix(in srgb,var(--altcha-color-primary) 20%,transparent),color-mix(in srgb,var(--altcha-color-primary) 60%,transparent));--altcha-checkbox-outline-offset:2px;--altcha-checkbox-size:22px;--altcha-checkbox-transition-duration:var(--altcha-transition-duration);--altcha-input-background-color:var(--altcha-color-base);--altcha-input-border-radius:3px;--altcha-input-border-width:1px;--altcha-input-color:var(--altcha-color-base-content);--altcha-max-width:320px;--altcha-padding:0.75rem;--altcha-popover-arrow-size:6px;--altcha-popover-color:var(--altcha-border-color);--altcha-shadow:drop-shadow(3px 3px 6px oklch(0% 0 0/0.2));--altcha-spinner-color:var(--altcha-color-base-content);--altcha-switch-background-color:var(--altcha-color-neutral);--altcha-switch-border-radius:calc(infinity*1px);--altcha-switch-height:var(--altcha-checkbox-size);--altcha-switch-padding:0.25rem;--altcha-switch-width:calc(var(--altcha-checkbox-size)*1.75);--altcha-switch-toggle-border-radius:100%;--altcha-switch-toggle-color:var(--altcha-color-neutral-content);--altcha-switch-toggle-size:calc(var(--altcha-switch-height) - var(--altcha-switch-padding)*2);--altcha-transition-duration:0.6s;--altcha-z-index:99999999;--altcha-z-index-popover:999999999}.altcha{all:revert-layer;display:none;font-family:inherit;font-size:inherit;position:relative}.altcha[data-visible]{display:block}.altcha *,.altcha-popover,.altcha-popover *{all:revert-layer;box-sizing:border-box;font-family:inherit;font-size:inherit;line-height:1.25}.altcha a,.altcha-popover a{color:currentColor;text-decoration:none}.altcha a:hover,.altcha-popover a:hover{color:currentColor}.altcha-main{align-items:start;background-color:var(--altcha-color-base);border:var(--altcha-border-width,1px) solid var(--altcha-border-color);border-radius:var(--altcha-border-radius,0);color:var(--altcha-color-base-content);display:flex;flex-direction:column;gap:.5rem;justify-content:space-between;max-width:var(--altcha-max-width,100%);padding:var(--altcha-padding)}.altcha-main>*{display:flex;width:100%}.altcha-main>:first-child{flex-grow:1}.altcha-checkbox-wrap{align-items:center;display:flex;flex-direction:row;flex-grow:1;gap:.5rem}.altcha-checkbox-wrap>*{display:flex}.altcha-logo{opacity:.7}.altcha-footer{align-items:center;display:flex;flex-grow:1;font-size:.7rem;gap:.5rem;justify-content:flex-end;opacity:.7}.altcha-error{font-size:.85rem}.altcha-button{align-items:center;background:var(--altcha-color-primary);border:var(--altcha-input-border-width) solid var(--altcha-color-primary);border-radius:var(--altcha-input-border-radius);color:var(--altcha-color-primary-content);cursor:pointer;display:flex;font-size:.9rem;gap:.5rem;padding:.35rem}.altcha-button:focus{border-color:var(--altcha-color-primary);outline:var(--altcha-checkbox-outline);outline-offset:var(--altcha-checkbox-outline-offset)}.altcha-button>.altcha-spinner,.altcha-button>svg{height:20px;width:20px}.altcha-button-secondary{background:transparent;border-color:var(--altcha-color-neutral);color:var(--altcha-color-neutral-content)}.altcha-input{background:var(--altcha-input-background-color);border:var(--altcha-input-border-width) solid var(--altcha-color-neutral);border-radius:var(--altcha-input-border-radius);color:var(--altcha-input-color);flex-grow:1;font-size:1rem;min-width:0;padding:.25rem;width:auto}.altcha-input:focus{border-color:var(--altcha-color-primary);outline:var(--altcha-checkbox-outline);outline-offset:var(--altcha-checkbox-outline-offset)}.altcha-spinner{animation:altcha-rotate .6s linear infinite;border:var(--altcha-checkbox-border-width) solid var(--altcha-spinner-color);border-bottom-color:transparent;border-radius:100%;border-right-color:transparent;opacity:.5}.altcha-popover{background-color:var(--altcha-color-base);border:var(--altcha-border-width) solid var(--altcha-border-color);border-radius:var(--altcha-border-radius);color:var(--altcha-color-base-content);filter:var(--altcha-shadow);left:calc(var(--altcha-padding)/2);max-width:calc(var(--altcha-max-width) - var(--altcha-padding));position:absolute;top:calc(var(--altcha-padding) + var(--altcha-checkbox-size) + var(--altcha-popover-arrow-size));z-index:var(--altcha-z-index-popover)}.altcha-popover-arrow{border-bottom-color:transparent;border:var(--altcha-popover-arrow-size) solid transparent;border-bottom:var(--altcha-popover-arrow-size) solid var(--altcha-popover-color);content:"";height:0;left:calc(var(--altcha-checkbox-size)/2);position:absolute;top:calc(var(--altcha-popover-arrow-size)*-2);width:0}.altcha-popover-content{max-height:100dvh;overflow:auto;padding:var(--altcha-padding)}.altcha-popover[data-top=true][data-display=standard]{bottom:calc(100% - var(--altcha-padding) + var(--altcha-popover-arrow-size));top:auto}.altcha-popover[data-top=true][data-display=standard] .altcha-popover-arrow{border-bottom-color:transparent;border-top-color:var(--altcha-popover-color);bottom:calc(var(--altcha-popover-arrow-size)*-2);top:auto}.altcha-popover[data-variant=error]{--altcha-popover-color:var(--altcha-color-error);background-color:var(--altcha-color-error);border-color:var(--altcha-color-error);color:var(--altcha-color-error-content)}.altcha-popover[data-variant=error] .altcha-popover-content{padding:calc(var(--altcha-padding)/1.5) var(--altcha-padding)}.altcha-popover[data-display=overlay]{animation:altcha-overlay-slidein .5s forwards;top:45%;transform:translate(-50%,-50%)}.altcha-popover[data-display=bottomsheet],.altcha-popover[data-display=overlay]{left:50%;position:fixed;width:var(--altcha-max-width);z-index:var(--altcha-z-index)}.altcha-popover[data-display=bottomsheet]{animation:altcha-bottomsheet-slideup .5s forwards;border-bottom:0;border-bottom-left-radius:0;border-bottom-right-radius:0;bottom:-100%;top:auto;transform:translate(-50%)}.altcha-popover[data-display=bottomsheet] .altcha-popover-content{padding-bottom:calc(var(--altcha-padding)*2)}.altcha-popover-backdrop{background:var(--altcha-color-base-content);bottom:0;left:0;opacity:.1;position:fixed;right:0;top:0;transition:opacity .5s;z-index:var(--altcha-z-index)}.altcha-popover-close{color:var(--altcha-color-base-content);cursor:pointer;display:inline-block;font-size:1rem;height:1.25rem;line-height:.95;position:absolute;right:0;text-align:center;text-shadow:0 0 1px var(--altcha-color-base);top:-1.5rem;width:1.25rem;z-index:var(--altcha-z-index)}[dir=rtl] .altcha-popover{left:auto;right:calc(var(--altcha-padding)/2)}[dir=rtl] .altcha-popover-arrow{left:auto;right:calc(var(--altcha-checkbox-size)/2)}[dir=rtl] .altcha-popover-close{left:0;right:auto}.altcha-popover[data-display=bottomsheet] .altcha-footer,.altcha-popover[data-display=overlay] .altcha-footer{align-items:center;gap:.5rem;justify-content:center;padding-top:1rem}.altcha-popover[data-display=bottomsheet] .altcha-footer svg,.altcha-popover[data-display=overlay] .altcha-footer svg{height:18px;vertical-align:middle;width:18px}.altcha-code-challenge>form{display:flex;flex-direction:column;gap:.5rem}.altcha-code-challenge-title{font-weight:600}.altcha-code-challenge-text{font-size:.85rem}.altcha-code-challenge-image{background:#fff;border:var(--altcha-input-border-width) solid var(--altcha-color-neutral);border-radius:var(--altcha-input-border-radius);height:50px;object-fit:contain}.altcha-code-challenge-row{display:flex;gap:.5rem}.altcha-code-challenge-buttons{align-items:center;display:flex;flex-direction:column;gap:.5rem;justify-content:space-between;margin-top:var(--altcha-padding)}.altcha-code-challenge-buttons button{justify-content:center;width:100%}.altcha-checkbox{cursor:pointer;position:relative}.altcha-checkbox,.altcha-checkbox input{height:var(--altcha-checkbox-size);width:var(--altcha-checkbox-size)}.altcha-checkbox input{appearance:none;background:var(--altcha-input-background-color);border:var(--altcha-checkbox-border-width,2px) solid var(--altcha-checkbox-border-color);border-radius:var(--altcha-checkbox-border-radius);left:0;margin:0;outline:none;padding:0;position:absolute;top:0}.altcha-checkbox input:before{background:var(--altcha-color-neutral);border-radius:var(--altcha-checkbox-border-radius);content:"";display:block;height:100%;transform:scale(0);width:100%}.altcha-checkbox input:focus{outline:var(--altcha-checkbox-outline);outline-offset:var(--altcha-checkbox-outline-offset)}.altcha-checkbox input:checked{background-color:var(--altcha-color-success);border-color:var(--altcha-color-success)}.altcha-checkbox input:checked:before{background-color:var(--altcha-color-success);opacity:0;transform:scale(2.2);transition:all var(--altcha-checkbox-transition-duration) ease;transition-delay:.1s}.altcha-checkbox svg{--altcha-radio-svg-size:calc(var(--altcha-checkbox-size)*0.5);--altcha-radio-svg-offset:calc(var(--altcha-checkbox-size)*0.25);fill:none;height:var(--altcha-radio-svg-size);left:var(--altcha-radio-svg-offset);opacity:0;position:absolute;stroke:currentColor;stroke-dasharray:16px;stroke-dashoffset:16px;stroke-linecap:round;stroke-linejoin:round;stroke-width:2;top:var(--altcha-radio-svg-offset);transform:translateZ(0);width:var(--altcha-radio-svg-size)}.altcha-checkbox input:checked+svg{color:var(--altcha-color-success-content);opacity:1;stroke-dashoffset:0;transition:all var(--altcha-checkbox-transition-duration) ease;transition-delay:.1s}.altcha-checkbox-spinner{display:none;height:var(--altcha-checkbox-size);left:0;position:absolute;top:0;width:var(--altcha-checkbox-size)}.altcha-checkbox[data-loading=true] input{appearance:none;opacity:0;pointer-events:none}.altcha-checkbox[data-loading=true] .altcha-checkbox-spinner{display:block}.altcha-checkbox-native{position:relative}.altcha-checkbox-native,.altcha-checkbox-native input{height:var(--altcha-checkbox-size);width:var(--altcha-checkbox-size)}.altcha-checkbox-native input{margin:0}.altcha-checkbox-native input:focus{outline:var(--altcha-checkbox-outline);outline-offset:var(--altcha-checkbox-outline-offset)}.altcha-checkbox-native-spinner{display:none;height:var(--altcha-checkbox-size);left:0;position:absolute;top:0;width:var(--altcha-checkbox-size)}.altcha-checkbox-native[data-loading=true] input{appearance:none;opacity:0;pointer-events:none}.altcha-checkbox-native[data-loading=true] .altcha-checkbox-native-spinner{display:block}.altcha-switch{align-items:center;background-color:var(--altcha-switch-background-color);border-radius:var(--altcha-switch-border-radius);cursor:pointer;display:flex;height:var(--altcha-switch-height);padding:var(--altcha-switch-padding);position:relative;width:var(--altcha-switch-width)}.altcha-switch:focus-within{outline:var(--altcha-checkbox-outline);outline-offset:var(--altcha-checkbox-outline-offset)}.altcha-switch input{appearance:none;height:100%;left:0;opacity:0;position:absolute;top:0;width:100%}.altcha-switch-toggle{align-items:center;background-color:var(--altcha-switch-toggle-color);border-radius:var(--altcha-switch-toggle-border-radius);display:flex;justify-content:center;left:var(--altcha-switch-padding);position:absolute;transition:width .15s ease-out,left .15s ease-out}.altcha-switch-spinner,.altcha-switch-toggle{height:var(--altcha-switch-toggle-size);width:var(--altcha-switch-toggle-size)}.altcha-switch-spinner{display:none}.altcha-switch[data-loading=true]{pointer-events:none}.altcha-switch[data-loading=true] .altcha-switch-spinner{display:block}.altcha-switch[data-loading=true] .altcha-switch-toggle{background-color:transparent;left:calc(50% - var(--altcha-switch-toggle-size)/2)}[data-state=verified] .altcha-switch{--altcha-switch-background-color:var(--altcha-color-success)}[data-state=verified] .altcha-switch-toggle{background-color:var(--altcha-color-success-content)}[data-state=verified] .altcha-switch-toggle,[dir=rtl] .altcha-switch-toggle{left:calc(100% - var(--altcha-switch-height) + var(--altcha-switch-padding))}[dir=rtl][data-state=verified] .altcha-switch-toggle{left:var(--altcha-switch-padding)}.altcha-floating-arrow{border:6px solid transparent;border-bottom:6px solid var(--altcha-border-color);content:"";height:0;left:12px;position:absolute;top:-12px;width:0}.altcha-overlay-backdrop{bottom:0;left:0;position:fixed;right:0;top:0;transition:opacity var(--altcha-transition-duration);z-index:var(--altcha-z-index)}.altcha-overlay-close{color:currentColor;cursor:pointer;display:inline-block;font-size:1rem;height:1rem;line-height:.85;position:absolute;right:0;text-align:center;text-shadow:0 0 1px var(--altcha-color-base);top:-1.5rem;width:1rem;z-index:var(--altcha-z-index)}.altcha[data-display=overlay]{animation:altcha-overlay-slidein var(--altcha-transition-duration) forwards;filter:var(--altcha-shadow);left:50%;opacity:0;position:fixed;top:45%;transform:translate(-50%,-50%);z-index:var(--altcha-z-index)}.altcha[data-display=overlay] .altcha-main{width:var(--altcha-max-width)}.altcha[data-display=floating]{display:none;filter:var(--altcha-shadow);left:var(--altcha-floating-left,-100%);position:fixed;top:var(--altcha-floating-top,-100%);z-index:var(--altcha-z-index)}.altcha[data-display=floating] .altcha-main{width:var(--altcha-max-width)}.altcha[data-display=floating][data-placement=top] .altcha-floating-arrow{border-bottom-color:transparent;border-top-color:var(--altcha-border-color);bottom:-12px;top:auto}.altcha[data-display=floating][data-visible]{display:flex}.altcha[data-display=bar]{bottom:-100%;filter:var(--altcha-shadow);left:0;position:fixed;right:0;transition:bottom var(--altcha-transition-duration),top var(--altcha-transition-duration);z-index:var(--altcha-z-index)}.altcha[data-display=bar] .altcha-main{align-items:center;border-radius:0;border-width:var(--altcha-border-width) 0 0 0;flex-direction:row;max-width:100%!important}.altcha[data-display=bar] .altcha-main>*{width:auto}.altcha[data-display=bar][data-placement=top]{bottom:auto;top:-100%}.altcha[data-display=bar][data-placement=top] .altcha-main{border-width:0 0 var(--altcha-border-width) 0}.altcha[data-display=bar][data-placement=bottom]:not([data-state=unverified]){bottom:0}.altcha[data-display=bar][data-placement=top]:not([data-state=unverified]){top:0}.altcha[data-display=invisible]{display:none}@keyframes altcha-rotate{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}@keyframes altcha-bottomsheet-slideup{to{bottom:0}}@keyframes altcha-overlay-slidein{to{opacity:1;top:50%}} \ No newline at end of file diff --git a/website_altcha/static/lib/altcha.js b/website_altcha/static/lib/altcha.js index 018773fca6..1b70b870b7 100644 --- a/website_altcha/static/lib/altcha.js +++ b/website_altcha/static/lib/altcha.js @@ -1,3106 +1,7441 @@ -/** @odoo-module **/ -const Yn = `(function(){"use strict";const d=new TextEncoder;function p(e){return[...new Uint8Array(e)].map(t=>t.toString(16).padStart(2,"0")).join("")}async function b(e,t,r){if(typeof crypto>"u"||!("subtle"in crypto)||!("digest"in crypto.subtle))throw new Error("Web Crypto is not available. Secure context is required (https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts).");return p(await crypto.subtle.digest(r.toUpperCase(),d.encode(e+t)))}function w(e,t,r="SHA-256",n=1e6,l=0){const o=new AbortController,a=Date.now();return{promise:(async()=>{for(let c=l;c<=n;c+=1){if(o.signal.aborted)return null;if(await b(t,c,r)===e)return{number:c,took:Date.now()-a}}return null})(),controller:o}}function h(e){const t=atob(e),r=new Uint8Array(t.length);for(let n=0;n{for(let i=n;i<=r;i+=1){if(o.signal.aborted||!c||!u)return null;try{const f=await crypto.subtle.decrypt({name:l,iv:g(i)},c,u);if(f)return{clearText:new TextDecoder().decode(f),took:Date.now()-a}}catch{}}return null};let c=null,u=null;try{u=h(e);const i=await crypto.subtle.digest("SHA-256",d.encode(t));c=await crypto.subtle.importKey("raw",i,l,!1,["decrypt"])}catch{return{promise:Promise.reject(),controller:o}}return{promise:s(),controller:o}}let y;onmessage=async e=>{const{type:t,payload:r,start:n,max:l}=e.data;let o=null;if(t==="abort")y?.abort(),y=void 0;else if(t==="work"){if("obfuscated"in r){const{key:a,obfuscated:s}=r||{};o=await m(s,a,l,n)}else{const{algorithm:a,challenge:s,salt:c}=r||{};o=w(s,c,a,l,n)}y=o.controller,o.promise.then(a=>{self.postMessage(a&&{...a,worker:!0})})}}})(); -`, Dn = typeof self < "u" && self.Blob && new Blob(["(self.URL || self.webkitURL).revokeObjectURL(self.location.href);", Yn], { type: "text/javascript;charset=utf-8" }); -function Ni(e) { - let t; - try { - if (t = Dn && (self.URL || self.webkitURL).createObjectURL(Dn), !t) throw ""; - const r = new Worker(t, { - name: e?.name - }); - return r.addEventListener("error", () => { - (self.URL || self.webkitURL).revokeObjectURL(t); - }), r; - } catch { - return new Worker( - "data:text/javascript;charset=utf-8," + encodeURIComponent(Yn), - { - name: e?.name - } - ); +/* @odoo-module */ +const DEV = false; +var is_array = Array.isArray; +var index_of = Array.prototype.indexOf; +var includes = Array.prototype.includes; +var array_from = Array.from; +var object_keys = Object.keys; +var define_property = Object.defineProperty; +var get_descriptor = Object.getOwnPropertyDescriptor; +var get_descriptors = Object.getOwnPropertyDescriptors; +var object_prototype = Object.prototype; +var array_prototype = Array.prototype; +var get_prototype_of = Object.getPrototypeOf; +var is_extensible = Object.isExtensible; +const noop = () => { +}; +function run_all(arr) { + for (var i = 0; i < arr.length; i++) { + arr[i](); } } -const Li = "5"; -typeof window < "u" && ((window.__svelte ??= {}).v ??= /* @__PURE__ */ new Set()).add(Li); -const Pi = 1, Oi = 4, Fi = 8, Mi = 16, Vi = 1, Ui = 2, Mr = "[", Zn = "[!", zn = "]", bt = {}, ae = Symbol(), ji = "http://www.w3.org/1999/xhtml", Nn = !1; -function Jn(e) { - throw new Error("https://svelte.dev/e/lifecycle_outside_component"); +function deferred() { + var resolve; + var reject; + var promise = new Promise((res, rej) => { + resolve = res; + reject = rej; + }); + return { promise, resolve, reject }; +} +const DERIVED = 1 << 1; +const EFFECT = 1 << 2; +const RENDER_EFFECT = 1 << 3; +const MANAGED_EFFECT = 1 << 24; +const BLOCK_EFFECT = 1 << 4; +const BRANCH_EFFECT = 1 << 5; +const ROOT_EFFECT = 1 << 6; +const BOUNDARY_EFFECT = 1 << 7; +const CONNECTED = 1 << 9; +const CLEAN = 1 << 10; +const DIRTY = 1 << 11; +const MAYBE_DIRTY = 1 << 12; +const INERT = 1 << 13; +const DESTROYED = 1 << 14; +const REACTION_RAN = 1 << 15; +const DESTROYING = 1 << 25; +const EFFECT_TRANSPARENT = 1 << 16; +const EAGER_EFFECT = 1 << 17; +const HEAD_EFFECT = 1 << 18; +const EFFECT_PRESERVED = 1 << 19; +const USER_EFFECT = 1 << 20; +const WAS_MARKED = 1 << 16; +const REACTION_IS_UPDATING = 1 << 21; +const ASYNC = 1 << 22; +const ERROR_VALUE = 1 << 23; +const STATE_SYMBOL = /* @__PURE__ */ Symbol("$state"); +const LEGACY_PROPS = /* @__PURE__ */ Symbol("legacy props"); +const LOADING_ATTR_SYMBOL = /* @__PURE__ */ Symbol(""); +const STALE_REACTION = new class StaleReactionError extends Error { + name = "StaleReactionError"; + message = "The reaction that called `getAbortSignal()` was re-run or destroyed"; +}(); +const IS_XHTML = ( + // We gotta write it like this because after downleveling the pure comment may end up in the wrong location + !!globalThis.document?.contentType && /* @__PURE__ */ globalThis.document.contentType.includes("xml") +); +const TEXT_NODE = 3; +const COMMENT_NODE = 8; +function equals(value) { + return value === this.v; +} +function safe_not_equal(a, b) { + return a != a ? b == b : a !== b || a !== null && typeof a === "object" || typeof a === "function"; +} +function safe_equals(value) { + return !safe_not_equal(value, this.v); +} +function lifecycle_outside_component(name) { + { + throw new Error(`https://svelte.dev/e/lifecycle_outside_component`); + } } -var Kn = Array.isArray, qi = Array.prototype.indexOf, Bi = Array.from, or = Object.keys, Mt = Object.defineProperty, rt = Object.getOwnPropertyDescriptor, Hi = Object.getOwnPropertyDescriptors, Gi = Object.prototype, Wi = Array.prototype, Xn = Object.getPrototypeOf, Ln = Object.isExtensible; -const yt = () => { -}; -function Qn(e) { - for (var t = 0; t < e.length; t++) - e[t](); +function async_derived_orphan() { + { + throw new Error(`https://svelte.dev/e/async_derived_orphan`); + } } -function Yi(e, t, r = !1) { - return e === void 0 ? r ? ( - /** @type {() => V} */ - t() - ) : ( - /** @type {V} */ - t - ) : e; +function effect_in_teardown(rune) { + { + throw new Error(`https://svelte.dev/e/effect_in_teardown`); + } +} +function effect_in_unowned_derived() { + { + throw new Error(`https://svelte.dev/e/effect_in_unowned_derived`); + } +} +function effect_orphan(rune) { + { + throw new Error(`https://svelte.dev/e/effect_orphan`); + } +} +function effect_update_depth_exceeded() { + { + throw new Error(`https://svelte.dev/e/effect_update_depth_exceeded`); + } +} +function hydration_failed() { + { + throw new Error(`https://svelte.dev/e/hydration_failed`); + } +} +function state_descriptors_fixed() { + { + throw new Error(`https://svelte.dev/e/state_descriptors_fixed`); + } +} +function state_prototype_fixed() { + { + throw new Error(`https://svelte.dev/e/state_prototype_fixed`); + } } -const me = 2, eo = 4, fr = 8, Vr = 16, De = 32, it = 64, ir = 128, fe = 256, ar = 512, le = 1024, Ie = 2048, at = 4096, wt = 8192, dr = 16384, Zi = 32768, Ur = 65536, zi = 1 << 19, to = 1 << 20, Sr = 1 << 21, Ot = Symbol("$state"), ro = Symbol("legacy props"), Ji = Symbol(""); -function Ki(e) { - throw new Error("https://svelte.dev/e/effect_in_teardown"); +function state_unsafe_mutation() { + { + throw new Error(`https://svelte.dev/e/state_unsafe_mutation`); + } +} +function svelte_boundary_reset_onerror() { + { + throw new Error(`https://svelte.dev/e/svelte_boundary_reset_onerror`); + } } -function Xi() { - throw new Error("https://svelte.dev/e/effect_in_unowned_derived"); +let tracing_mode_flag = false; +const TEMPLATE_FRAGMENT = 1; +const TEMPLATE_USE_IMPORT_NODE = 1 << 1; +const HYDRATION_START = "["; +const HYDRATION_START_ELSE = "[!"; +const HYDRATION_START_FAILED = "[?"; +const HYDRATION_END = "]"; +const HYDRATION_ERROR = {}; +const UNINITIALIZED = /* @__PURE__ */ Symbol(); +const NAMESPACE_HTML = "http://www.w3.org/1999/xhtml"; +const NAMESPACE_SVG = "http://www.w3.org/2000/svg"; +const NAMESPACE_MATHML = "http://www.w3.org/1998/Math/MathML"; +const ATTACHMENT_KEY = "@attach"; +let component_context = null; +function set_component_context(context) { + component_context = context; +} +function push(props, runes = false, fn) { + component_context = { + p: component_context, + i: false, + c: null, + e: null, + s: props, + x: null, + r: ( + /** @type {Effect} */ + active_effect + ), + l: null + }; } -function Qi(e) { - throw new Error("https://svelte.dev/e/effect_orphan"); +function pop(component2) { + var context = ( + /** @type {ComponentContext} */ + component_context + ); + var effects = context.e; + if (effects !== null) { + context.e = null; + for (var fn of effects) { + create_user_effect(fn); + } + } + if (component2 !== void 0) { + context.x = component2; + } + context.i = true; + component_context = context.p; + return component2 ?? /** @type {T} */ + {}; } -function ea() { - throw new Error("https://svelte.dev/e/effect_update_depth_exceeded"); +function is_runes() { + return true; } -function ta() { - throw new Error("https://svelte.dev/e/hydration_failed"); +let micro_tasks = []; +function run_micro_tasks() { + var tasks = micro_tasks; + micro_tasks = []; + run_all(tasks); } -function ra(e) { - throw new Error("https://svelte.dev/e/props_invalid_value"); +function queue_micro_task(fn) { + if (micro_tasks.length === 0 && !is_flushing_sync) { + var tasks = micro_tasks; + queueMicrotask(() => { + if (tasks === micro_tasks) run_micro_tasks(); + }); + } + micro_tasks.push(fn); } -function na() { - throw new Error("https://svelte.dev/e/state_descriptors_fixed"); +function flush_tasks() { + while (micro_tasks.length > 0) { + run_micro_tasks(); + } } -function oa() { - throw new Error("https://svelte.dev/e/state_prototype_fixed"); +function hydration_mismatch(location2) { + { + console.warn(`https://svelte.dev/e/hydration_mismatch`); + } } -function ia() { - throw new Error("https://svelte.dev/e/state_unsafe_mutation"); +function select_multiple_invalid_value() { + { + console.warn(`https://svelte.dev/e/select_multiple_invalid_value`); + } } -function hr(e) { - console.warn("https://svelte.dev/e/hydration_mismatch"); +function svelte_boundary_reset_noop() { + { + console.warn(`https://svelte.dev/e/svelte_boundary_reset_noop`); + } } -let O = !1; -function _t(e) { - O = e; +let hydrating = false; +function set_hydrating(value) { + hydrating = value; } -let P; -function Ue(e) { - if (e === null) - throw hr(), bt; - return P = e; +let hydrate_node; +function set_hydrate_node(node) { + if (node === null) { + hydration_mismatch(); + throw HYDRATION_ERROR; + } + return hydrate_node = node; } -function Et() { - return Ue( - /** @type {TemplateNode} */ - /* @__PURE__ */ Be(P) - ); +function hydrate_next() { + return set_hydrate_node(/* @__PURE__ */ get_next_sibling(hydrate_node)); } -function Z(e) { - if (O) { - if (/* @__PURE__ */ Be(P) !== null) - throw hr(), bt; - P = e; +function reset(node) { + if (!hydrating) return; + if (/* @__PURE__ */ get_next_sibling(hydrate_node) !== null) { + hydration_mismatch(); + throw HYDRATION_ERROR; + } + hydrate_node = node; +} +function next(count = 1) { + if (hydrating) { + var i = count; + var node = hydrate_node; + while (i--) { + node = /** @type {TemplateNode} */ + /* @__PURE__ */ get_next_sibling(node); + } + hydrate_node = node; } } -function aa() { - for (var e = 0, t = P; ; ) { - if (t.nodeType === 8) { - var r = ( +function skip_nodes(remove = true) { + var depth = 0; + var node = hydrate_node; + while (true) { + if (node.nodeType === COMMENT_NODE) { + var data = ( /** @type {Comment} */ - t.data + node.data ); - if (r === zn) { - if (e === 0) return t; - e -= 1; - } else (r === Mr || r === Zn) && (e += 1); + if (data === HYDRATION_END) { + if (depth === 0) return node; + depth -= 1; + } else if (data === HYDRATION_START || data === HYDRATION_START_ELSE || // "[1", "[2", etc. for if blocks + data[0] === "[" && !isNaN(Number(data.slice(1)))) { + depth += 1; + } } - var o = ( + var next2 = ( /** @type {TemplateNode} */ - /* @__PURE__ */ Be(t) + /* @__PURE__ */ get_next_sibling(node) ); - t.remove(), t = o; - } -} -let la = !1; -function Me(e) { - if (typeof e != "object" || e === null || Ot in e) - return e; - const t = Xn(e); - if (t !== Gi && t !== Wi) - return e; - var r = /* @__PURE__ */ new Map(), o = Kn(e), l = /* @__PURE__ */ N(0), a = $, s = (c) => { - var f = $; - Re(a); - var d = c(); - return Re(f), d; + if (remove) node.remove(); + node = next2; + } +} +function read_hydration_instruction(node) { + if (!node || node.nodeType !== COMMENT_NODE) { + hydration_mismatch(); + throw HYDRATION_ERROR; + } + return ( + /** @type {Comment} */ + node.data + ); +} +function proxy(value) { + if (typeof value !== "object" || value === null || STATE_SYMBOL in value) { + return value; + } + const prototype = get_prototype_of(value); + if (prototype !== object_prototype && prototype !== array_prototype) { + return value; + } + var sources = /* @__PURE__ */ new Map(); + var is_proxied_array = is_array(value); + var version = /* @__PURE__ */ state(0); + var parent_version = update_version; + var with_parent = (fn) => { + if (update_version === parent_version) { + return fn(); + } + var reaction = active_reaction; + var version2 = update_version; + set_active_reaction(null); + set_update_version(parent_version); + var result = fn(); + set_active_reaction(reaction); + set_update_version(version2); + return result; }; - return o && r.set("length", /* @__PURE__ */ N( - /** @type {any[]} */ - e.length - )), new Proxy( + if (is_proxied_array) { + sources.set("length", /* @__PURE__ */ state( + /** @type {any[]} */ + value.length + )); + } + return new Proxy( /** @type {any} */ - e, + value, { - defineProperty(c, f, d) { - (!("value" in d) || d.configurable === !1 || d.enumerable === !1 || d.writable === !1) && na(); - var m = r.get(f); - return m === void 0 ? (m = s(() => /* @__PURE__ */ N(d.value)), r.set(f, m)) : b( - m, - s(() => Me(d.value)) - ), !0; + defineProperty(_, prop2, descriptor) { + if (!("value" in descriptor) || descriptor.configurable === false || descriptor.enumerable === false || descriptor.writable === false) { + state_descriptors_fixed(); + } + var s = sources.get(prop2); + if (s === void 0) { + with_parent(() => { + var s2 = /* @__PURE__ */ state(descriptor.value); + sources.set(prop2, s2); + return s2; + }); + } else { + set(s, descriptor.value, true); + } + return true; }, - deleteProperty(c, f) { - var d = r.get(f); - if (d === void 0) - f in c && (r.set( - f, - s(() => /* @__PURE__ */ N(ae)) - ), Ir(l)); - else { - if (o && typeof f == "string") { - var m = ( - /** @type {Source} */ - r.get("length") - ), v = Number(f); - Number.isInteger(v) && v < m.v && b(m, v); + deleteProperty(target, prop2) { + var s = sources.get(prop2); + if (s === void 0) { + if (prop2 in target) { + const s2 = with_parent(() => /* @__PURE__ */ state(UNINITIALIZED)); + sources.set(prop2, s2); + increment(version); } - b(d, ae), Ir(l); + } else { + set(s, UNINITIALIZED); + increment(version); } - return !0; + return true; }, - get(c, f, d) { - if (f === Ot) - return e; - var m = r.get(f), v = f in c; - if (m === void 0 && (!v || rt(c, f)?.writable) && (m = s(() => /* @__PURE__ */ N(Me(v ? c[f] : ae))), r.set(f, m)), m !== void 0) { - var _ = i(m); - return _ === ae ? void 0 : _; - } - return Reflect.get(c, f, d); + get(target, prop2, receiver) { + if (prop2 === STATE_SYMBOL) { + return value; + } + var s = sources.get(prop2); + var exists = prop2 in target; + if (s === void 0 && (!exists || get_descriptor(target, prop2)?.writable)) { + s = with_parent(() => { + var p = proxy(exists ? target[prop2] : UNINITIALIZED); + var s2 = /* @__PURE__ */ state(p); + return s2; + }); + sources.set(prop2, s); + } + if (s !== void 0) { + var v = get(s); + return v === UNINITIALIZED ? void 0 : v; + } + return Reflect.get(target, prop2, receiver); }, - getOwnPropertyDescriptor(c, f) { - var d = Reflect.getOwnPropertyDescriptor(c, f); - if (d && "value" in d) { - var m = r.get(f); - m && (d.value = i(m)); - } else if (d === void 0) { - var v = r.get(f), _ = v?.v; - if (v !== void 0 && _ !== ae) + getOwnPropertyDescriptor(target, prop2) { + var descriptor = Reflect.getOwnPropertyDescriptor(target, prop2); + if (descriptor && "value" in descriptor) { + var s = sources.get(prop2); + if (s) descriptor.value = get(s); + } else if (descriptor === void 0) { + var source2 = sources.get(prop2); + var value2 = source2?.v; + if (source2 !== void 0 && value2 !== UNINITIALIZED) { return { - enumerable: !0, - configurable: !0, - value: _, - writable: !0 + enumerable: true, + configurable: true, + value: value2, + writable: true }; + } } - return d; + return descriptor; }, - has(c, f) { - if (f === Ot) - return !0; - var d = r.get(f), m = d !== void 0 && d.v !== ae || Reflect.has(c, f); - if (d !== void 0 || S !== null && (!m || rt(c, f)?.writable)) { - d === void 0 && (d = s(() => /* @__PURE__ */ N(m ? Me(c[f]) : ae)), r.set(f, d)); - var v = i(d); - if (v === ae) - return !1; - } - return m; + has(target, prop2) { + if (prop2 === STATE_SYMBOL) { + return true; + } + var s = sources.get(prop2); + var has = s !== void 0 && s.v !== UNINITIALIZED || Reflect.has(target, prop2); + if (s !== void 0 || active_effect !== null && (!has || get_descriptor(target, prop2)?.writable)) { + if (s === void 0) { + s = with_parent(() => { + var p = has ? proxy(target[prop2]) : UNINITIALIZED; + var s2 = /* @__PURE__ */ state(p); + return s2; + }); + sources.set(prop2, s); + } + var value2 = get(s); + if (value2 === UNINITIALIZED) { + return false; + } + } + return has; }, - set(c, f, d, m) { - var v = r.get(f), _ = f in c; - if (o && f === "length") - for (var w = d; w < /** @type {Source} */ - v.v; w += 1) { - var F = r.get(w + ""); - F !== void 0 ? b(F, ae) : w in c && (F = s(() => /* @__PURE__ */ N(ae)), r.set(w + "", F)); + set(target, prop2, value2, receiver) { + var s = sources.get(prop2); + var has = prop2 in target; + if (is_proxied_array && prop2 === "length") { + for (var i = value2; i < /** @type {Source} */ + s.v; i += 1) { + var other_s = sources.get(i + ""); + if (other_s !== void 0) { + set(other_s, UNINITIALIZED); + } else if (i in target) { + other_s = with_parent(() => /* @__PURE__ */ state(UNINITIALIZED)); + sources.set(i + "", other_s); + } } - v === void 0 ? (!_ || rt(c, f)?.writable) && (v = s(() => /* @__PURE__ */ N(void 0)), b( - v, - s(() => Me(d)) - ), r.set(f, v)) : (_ = v.v !== ae, b( - v, - s(() => Me(d)) - )); - var M = Reflect.getOwnPropertyDescriptor(c, f); - if (M?.set && M.set.call(m, d), !_) { - if (o && typeof f == "string") { - var U = ( + } + if (s === void 0) { + if (!has || get_descriptor(target, prop2)?.writable) { + s = with_parent(() => /* @__PURE__ */ state(void 0)); + set(s, proxy(value2)); + sources.set(prop2, s); + } + } else { + has = s.v !== UNINITIALIZED; + var p = with_parent(() => proxy(value2)); + set(s, p); + } + var descriptor = Reflect.getOwnPropertyDescriptor(target, prop2); + if (descriptor?.set) { + descriptor.set.call(receiver, value2); + } + if (!has) { + if (is_proxied_array && typeof prop2 === "string") { + var ls = ( /** @type {Source} */ - r.get("length") - ), I = Number(f); - Number.isInteger(I) && I >= U.v && b(U, I + 1); + sources.get("length") + ); + var n = Number(prop2); + if (Number.isInteger(n) && n >= ls.v) { + set(ls, n + 1); + } } - Ir(l); + increment(version); } - return !0; + return true; }, - ownKeys(c) { - i(l); - var f = Reflect.ownKeys(c).filter((v) => { - var _ = r.get(v); - return _ === void 0 || _.v !== ae; + ownKeys(target) { + get(version); + var own_keys = Reflect.ownKeys(target).filter((key3) => { + var source3 = sources.get(key3); + return source3 === void 0 || source3.v !== UNINITIALIZED; }); - for (var [d, m] of r) - m.v !== ae && !(d in c) && f.push(d); - return f; + for (var [key2, source2] of sources) { + if (source2.v !== UNINITIALIZED && !(key2 in target)) { + own_keys.push(key2); + } + } + return own_keys; }, setPrototypeOf() { - oa(); + state_prototype_fixed(); } } ); } -function Ir(e, t = 1) { - b(e, e.v + t); -} -var Pn, no, oo, io; -function Tr() { - if (Pn === void 0) { - Pn = window, no = /Firefox/.test(navigator.userAgent); - var e = Element.prototype, t = Node.prototype, r = Text.prototype; - oo = rt(t, "firstChild").get, io = rt(t, "nextSibling").get, Ln(e) && (e.__click = void 0, e.__className = void 0, e.__attributes = null, e.__style = void 0, e.__e = void 0), Ln(r) && (r.__t = void 0); +function get_proxied_value(value) { + try { + if (value !== null && typeof value === "object" && STATE_SYMBOL in value) { + return value[STATE_SYMBOL]; + } + } catch { } -} -function vr(e = "") { - return document.createTextNode(e); -} -// @__NO_SIDE_EFFECTS__ -function ve(e) { - return oo.call(e); -} -// @__NO_SIDE_EFFECTS__ -function Be(e) { - return io.call(e); -} -function z(e, t) { - if (!O) - return /* @__PURE__ */ ve(e); - var r = ( - /** @type {TemplateNode} */ - /* @__PURE__ */ ve(P) - ); - return r === null && (r = P.appendChild(vr())), Ue(r), r; -} -function Nt(e, t) { - if (!O) { - var r = ( - /** @type {DocumentFragment} */ - /* @__PURE__ */ ve( - /** @type {Node} */ - e - ) - ); - return r instanceof Comment && r.data === "" ? /* @__PURE__ */ Be(r) : r; + return value; +} +function is(a, b) { + return Object.is(get_proxied_value(a), get_proxied_value(b)); +} +var $window; +var $document; +var is_firefox; +var first_child_getter; +var next_sibling_getter; +function init_operations() { + if ($window !== void 0) { + return; } - return P; -} -function J(e, t = 1, r = !1) { - let o = O ? P : e; - for (var l; t--; ) - l = o, o = /** @type {TemplateNode} */ - /* @__PURE__ */ Be(o); - if (!O) - return o; - var a = o?.nodeType; - if (r && a !== 3) { - var s = vr(); - return o === null ? l?.after(s) : o.before(s), Ue(s), s; + $window = window; + $document = document; + is_firefox = /Firefox/.test(navigator.userAgent); + var element_prototype = Element.prototype; + var node_prototype = Node.prototype; + var text_prototype = Text.prototype; + first_child_getter = get_descriptor(node_prototype, "firstChild").get; + next_sibling_getter = get_descriptor(node_prototype, "nextSibling").get; + if (is_extensible(element_prototype)) { + element_prototype.__click = void 0; + element_prototype.__className = void 0; + element_prototype.__attributes = null; + element_prototype.__style = void 0; + element_prototype.__e = void 0; + } + if (is_extensible(text_prototype)) { + text_prototype.__t = void 0; } - return Ue(o), /** @type {TemplateNode} */ - o; -} -function sa(e) { - e.textContent = ""; -} -function ao(e) { - return e === this.v; -} -function lo(e, t) { - return e != e ? t == t : e !== t || e !== null && typeof e == "object" || typeof e == "function"; -} -function jr(e) { - return !lo(e, this.v); } -// @__NO_SIDE_EFFECTS__ -function gr(e) { - var t = me | Ie, r = $ !== null && ($.f & me) !== 0 ? ( - /** @type {Derived} */ - $ - ) : null; - return S === null || r !== null && (r.f & fe) !== 0 ? t |= fe : S.f |= to, { - ctx: ne, - deps: null, - effects: null, - equals: ao, - f: t, - fn: e, - reactions: null, - rv: 0, - v: ( - /** @type {V} */ - null - ), - wv: 0, - parent: r ?? S - }; +function create_text(value = "") { + return document.createTextNode(value); } // @__NO_SIDE_EFFECTS__ -function Lt(e) { - const t = /* @__PURE__ */ gr(e); - return wo(t), t; +function get_first_child(node) { + return ( + /** @type {TemplateNode | null} */ + first_child_getter.call(node) + ); } // @__NO_SIDE_EFFECTS__ -function ua(e) { - const t = /* @__PURE__ */ gr(e); - return t.equals = jr, t; +function get_next_sibling(node) { + return ( + /** @type {TemplateNode | null} */ + next_sibling_getter.call(node) + ); } -function so(e) { - var t = e.effects; - if (t !== null) { - e.effects = null; - for (var r = 0; r < t.length; r += 1) - je( - /** @type {Effect} */ - t[r] - ); +function child(node, is_text) { + if (!hydrating) { + return /* @__PURE__ */ get_first_child(node); } -} -function ca(e) { - for (var t = e.parent; t !== null; ) { - if ((t.f & me) === 0) - return ( - /** @type {Effect} */ - t - ); - t = t.parent; + var child2 = /* @__PURE__ */ get_first_child(hydrate_node); + if (child2 === null) { + child2 = hydrate_node.appendChild(create_text()); + } else if (is_text && child2.nodeType !== TEXT_NODE) { + var text2 = create_text(); + child2?.before(text2); + set_hydrate_node(text2); + return text2; } - return null; -} -function uo(e) { - var t, r = S; - qe(ca(e)); - try { - so(e), t = ko(e); - } finally { - qe(r); + if (is_text) { + merge_text_nodes( + /** @type {Text} */ + child2 + ); } - return t; -} -function co(e) { - var t = uo(e), r = (Ve || (e.f & fe) !== 0) && e.deps !== null ? at : le; - _e(e, r), e.equals(t) || (e.v = t, e.wv = xo()); -} -function fa(e) { - S === null && $ === null && Qi(), $ !== null && ($.f & fe) !== 0 && S === null && Xi(), qt && Ki(); -} -function da(e, t) { - var r = t.last; - r === null ? t.last = t.first = e : (r.next = e, e.prev = r, t.last = e); -} -function lt(e, t, r, o = !0) { - var l = S, a = { - ctx: ne, - deps: null, - nodes_start: null, - nodes_end: null, - f: e | Ie, - first: null, - fn: t, - last: null, - next: null, - parent: l, - prev: null, - teardown: null, - transitions: null, - wv: 0 - }; - if (r) - try { - Wr(a), a.f |= Zi; - } catch (f) { - throw je(a), f; - } - else t !== null && mr(a); - var s = r && a.deps === null && a.first === null && a.nodes_start === null && a.teardown === null && (a.f & (to | ir)) === 0; - if (!s && o && (l !== null && da(a, l), $ !== null && ($.f & me) !== 0)) { - var c = ( - /** @type {Derived} */ - $ + set_hydrate_node(child2); + return child2; +} +function first_child(node, is_text = false) { + if (!hydrating) { + var first = /* @__PURE__ */ get_first_child(node); + if (first instanceof Comment && first.data === "") return /* @__PURE__ */ get_next_sibling(first); + return first; + } + if (is_text) { + if (hydrate_node?.nodeType !== TEXT_NODE) { + var text2 = create_text(); + hydrate_node?.before(text2); + set_hydrate_node(text2); + return text2; + } + merge_text_nodes( + /** @type {Text} */ + hydrate_node ); - (c.effects ??= []).push(a); } - return a; -} -function qr(e) { - const t = lt(fr, null, !1); - return _e(t, le), t.teardown = e, t; -} -function Dr(e) { - fa(); - var t = S !== null && (S.f & De) !== 0 && ne !== null && !ne.m; - if (t) { - var r = ( - /** @type {ComponentContext} */ - ne + return hydrate_node; +} +function sibling(node, count = 1, is_text = false) { + let next_sibling = hydrating ? hydrate_node : node; + var last_sibling; + while (count--) { + last_sibling = next_sibling; + next_sibling = /** @type {TemplateNode} */ + /* @__PURE__ */ get_next_sibling(next_sibling); + } + if (!hydrating) { + return next_sibling; + } + if (is_text) { + if (next_sibling?.nodeType !== TEXT_NODE) { + var text2 = create_text(); + if (next_sibling === null) { + last_sibling?.after(text2); + } else { + next_sibling.before(text2); + } + set_hydrate_node(text2); + return text2; + } + merge_text_nodes( + /** @type {Text} */ + next_sibling ); - (r.e ??= []).push({ - fn: e, - effect: S, - reaction: $ - }); - } else { - var o = Br(e); - return o; } + set_hydrate_node(next_sibling); + return next_sibling; } -function ha(e) { - const t = lt(it, e, !0); - return () => { - je(t); - }; -} -function va(e) { - const t = lt(it, e, !0); - return (r = {}) => new Promise((o) => { - r.outro ? Lr(t, () => { - je(t), o(void 0); - }) : (je(t), o(void 0)); - }); -} -function Br(e) { - return lt(eo, e, !1); -} -function Hr(e) { - return lt(fr, e, !0); +function clear_text_content(node) { + node.textContent = ""; } -function Ce(e, t = [], r = gr) { - const o = t.map(r); - return fo(() => e(...o.map(i))); +function should_defer_append() { + return false; } -function fo(e, t = 0) { - return lt(fr | Vr | t, e, !0); -} -function Nr(e, t = !0) { - return lt(fr | De, e, !0, t); -} -function ho(e) { - var t = e.teardown; - if (t !== null) { - const r = qt, o = $; - Fn(!0), Re(null); - try { - t.call(null); - } finally { - Fn(r), Re(o); - } - } +function create_element(tag, namespace, is2) { + let options = void 0; + return ( + /** @type {T extends keyof HTMLElementTagNameMap ? HTMLElementTagNameMap[T] : Element} */ + document.createElementNS(namespace ?? NAMESPACE_HTML, tag, options) + ); } -function vo(e, t = !1) { - var r = e.first; - for (e.first = e.last = null; r !== null; ) { - var o = r.next; - (r.f & it) !== 0 ? r.parent = null : je(r, t), r = o; +function merge_text_nodes(text2) { + if ( + /** @type {string} */ + text2.nodeValue.length < 65536 + ) { + return; } -} -function ga(e) { - for (var t = e.first; t !== null; ) { - var r = t.next; - (t.f & De) === 0 && je(t), t = r; + let next2 = text2.nextSibling; + while (next2 !== null && next2.nodeType === TEXT_NODE) { + next2.remove(); + text2.nodeValue += /** @type {string} */ + next2.nodeValue; + next2 = text2.nextSibling; } } -function je(e, t = !0) { - var r = !1; - (t || (e.f & zi) !== 0) && e.nodes_start !== null && (go( - e.nodes_start, - /** @type {TemplateNode} */ - e.nodes_end - ), r = !0), vo(e, t && !r), cr(e, 0), _e(e, dr); - var o = e.transitions; - if (o !== null) - for (const a of o) - a.stop(); - ho(e); - var l = e.parent; - l !== null && l.first !== null && po(e), e.next = e.prev = e.teardown = e.ctx = e.deps = e.fn = e.nodes_start = e.nodes_end = null; -} -function go(e, t) { - for (; e !== null; ) { - var r = e === t ? null : ( - /** @type {TemplateNode} */ - /* @__PURE__ */ Be(e) - ); - e.remove(), e = r; +function handle_error(error) { + var effect2 = active_effect; + if (effect2 === null) { + active_reaction.f |= ERROR_VALUE; + return error; } -} -function po(e) { - var t = e.parent, r = e.prev, o = e.next; - r !== null && (r.next = o), o !== null && (o.prev = r), t !== null && (t.first === e && (t.first = o), t.last === e && (t.last = r)); -} -function Lr(e, t) { - var r = []; - mo(e, r, !0), pa(r, () => { - je(e), t && t(); - }); -} -function pa(e, t) { - var r = e.length; - if (r > 0) { - var o = () => --r || t(); - for (var l of e) - l.out(o); - } else - t(); -} -function mo(e, t, r) { - if ((e.f & wt) === 0) { - if (e.f ^= wt, e.transitions !== null) - for (const s of e.transitions) - (s.is_global || r) && t.push(s); - for (var o = e.first; o !== null; ) { - var l = o.next, a = (o.f & Ur) !== 0 || (o.f & De) !== 0; - mo(o, t, a ? r : !1), o = l; - } - } -} -function On(e) { - _o(e, !0); -} -function _o(e, t) { - if ((e.f & wt) !== 0) { - e.f ^= wt, (e.f & le) === 0 && (e.f ^= le), Bt(e) && (_e(e, Ie), mr(e)); - for (var r = e.first; r !== null; ) { - var o = r.next, l = (r.f & Ur) !== 0 || (r.f & De) !== 0; - _o(r, l ? t : !1), r = o; - } - if (e.transitions !== null) - for (const a of e.transitions) - (a.is_global || t) && a.in(); - } -} -const ma = typeof requestIdleCallback > "u" ? (e) => setTimeout(e, 1) : requestIdleCallback; -let Vt = [], Ut = []; -function bo() { - var e = Vt; - Vt = [], Qn(e); -} -function yo() { - var e = Ut; - Ut = [], Qn(e); -} -function Gr(e) { - Vt.length === 0 && queueMicrotask(bo), Vt.push(e); -} -function _a(e) { - Ut.length === 0 && ma(yo), Ut.push(e); -} -function ba() { - Vt.length > 0 && bo(), Ut.length > 0 && yo(); -} -let tr = !1, lr = !1, sr = null, nt = !1, qt = !1; -function Fn(e) { - qt = e; -} -let Ft = []; -let $ = null, ke = !1; -function Re(e) { - $ = e; -} -let S = null; -function qe(e) { - S = e; -} -let Te = null; -function wo(e) { - $ !== null && $.f & Sr && (Te === null ? Te = [e] : Te.push(e)); -} -let re = null, ce = 0, he = null; -function ya(e) { - he = e; -} -let Eo = 1, ur = 0, Ve = !1; -function xo() { - return ++Eo; -} -function Bt(e) { - var t = e.f; - if ((t & Ie) !== 0) - return !0; - if ((t & at) !== 0) { - var r = e.deps, o = (t & fe) !== 0; - if (r !== null) { - var l, a, s = (t & ar) !== 0, c = o && S !== null && !Ve, f = r.length; - if (s || c) { - var d = ( - /** @type {Derived} */ - e - ), m = d.parent; - for (l = 0; l < f; l++) - a = r[l], (s || !a?.reactions?.includes(d)) && (a.reactions ??= []).push(d); - s && (d.f ^= ar), c && m !== null && (m.f & fe) === 0 && (d.f ^= fe); - } - for (l = 0; l < f; l++) - if (a = r[l], Bt( - /** @type {Derived} */ - a - ) && co( - /** @type {Derived} */ - a - ), a.wv > e.wv) - return !0; - } - (!o || S !== null && !Ve) && _e(e, le); + if ((effect2.f & REACTION_RAN) === 0 && (effect2.f & EFFECT) === 0) { + throw error; } - return !1; + invoke_error_boundary(error, effect2); } -function wa(e, t) { - for (var r = t; r !== null; ) { - if ((r.f & ir) !== 0) +function invoke_error_boundary(error, effect2) { + while (effect2 !== null) { + if ((effect2.f & BOUNDARY_EFFECT) !== 0) { + if ((effect2.f & REACTION_RAN) === 0) { + throw error; + } try { - r.fn(e); + effect2.b.error(error); return; - } catch { - r.f ^= ir; + } catch (e) { + error = e; } - r = r.parent; + } + effect2 = effect2.parent; } - throw tr = !1, e; + throw error; } -function Mn(e) { - return (e.f & dr) === 0 && (e.parent === null || (e.parent.f & ir) === 0); +const STATUS_MASK = -7169; +function set_signal_status(signal, status) { + signal.f = signal.f & STATUS_MASK | status; } -function pr(e, t, r, o) { - if (tr) { - if (r === null && (tr = !1), Mn(t)) - throw e; - return; +function update_derived_status(derived2) { + if ((derived2.f & CONNECTED) !== 0 || derived2.deps === null) { + set_signal_status(derived2, CLEAN); + } else { + set_signal_status(derived2, MAYBE_DIRTY); } - if (r !== null && (tr = !0), wa(e, t), Mn(t)) - throw e; } -function Co(e, t, r = !0) { - var o = e.reactions; - if (o !== null) - for (var l = 0; l < o.length; l++) { - var a = o[l]; - Te?.includes(e) || ((a.f & me) !== 0 ? Co( - /** @type {Derived} */ - a, - t, - !1 - ) : t === a && (r ? _e(a, Ie) : (a.f & le) !== 0 && _e(a, at), mr( - /** @type {Effect} */ - a - ))); +function clear_marked(deps) { + if (deps === null) return; + for (const dep of deps) { + if ((dep.f & DERIVED) === 0 || (dep.f & WAS_MARKED) === 0) { + continue; } -} -function ko(e) { - var t = re, r = ce, o = he, l = $, a = Ve, s = Te, c = ne, f = ke, d = e.f; - re = /** @type {null | Value[]} */ - null, ce = 0, he = null, Ve = (d & fe) !== 0 && (ke || !nt || $ === null), $ = (d & (De | it)) === 0 ? e : null, Te = null, Vn(e.ctx), ke = !1, ur++, e.f |= Sr; - try { - var m = ( - /** @type {Function} */ - (0, e.fn)() - ), v = e.deps; - if (re !== null) { - var _; - if (cr(e, ce), v !== null && ce > 0) - for (v.length = ce + re.length, _ = 0; _ < re.length; _++) - v[ce + _] = re[_]; - else - e.deps = v = re; - if (!Ve) - for (_ = ce; _ < v.length; _++) - (v[_].reactions ??= []).push(e); - } else v !== null && ce < v.length && (cr(e, ce), v.length = ce); - if (To() && he !== null && !ke && v !== null && (e.f & (me | at | Ie)) === 0) - for (_ = 0; _ < /** @type {Source[]} */ - he.length; _++) - Co( - he[_], - /** @type {Effect} */ - e - ); - return l !== null && l !== e && (ur++, he !== null && (o === null ? o = he : o.push(.../** @type {Source[]} */ - he))), m; - } finally { - re = t, ce = r, he = o, $ = l, Ve = a, Te = s, Vn(c), ke = f, e.f ^= Sr; + dep.f ^= WAS_MARKED; + clear_marked( + /** @type {Derived} */ + dep.deps + ); } } -function Ea(e, t) { - let r = t.reactions; - if (r !== null) { - var o = qi.call(r, e); - if (o !== -1) { - var l = r.length - 1; - l === 0 ? r = t.reactions = null : (r[o] = r[l], r.pop()); - } +function defer_effect(effect2, dirty_effects, maybe_dirty_effects) { + if ((effect2.f & DIRTY) !== 0) { + dirty_effects.add(effect2); + } else if ((effect2.f & MAYBE_DIRTY) !== 0) { + maybe_dirty_effects.add(effect2); } - r === null && (t.f & me) !== 0 && // Destroying a child effect while updating a parent effect can cause a dependency to appear - // to be unused, when in fact it is used by the currently-updating parent. Checking `new_deps` - // allows us to skip the expensive work of disconnecting and immediately reconnecting it - (re === null || !re.includes(t)) && (_e(t, at), (t.f & (fe | ar)) === 0 && (t.f ^= ar), so( - /** @type {Derived} **/ - t - ), cr( - /** @type {Derived} **/ - t, - 0 - )); -} -function cr(e, t) { - var r = e.deps; - if (r !== null) - for (var o = t; o < r.length; o++) - Ea(e, r[o]); -} -function Wr(e) { - var t = e.f; - if ((t & dr) === 0) { - _e(e, le); - var r = S, o = ne, l = nt; - S = e, nt = !0; - try { - (t & Vr) !== 0 ? ga(e) : vo(e), ho(e); - var a = ko(e); - e.teardown = typeof a == "function" ? a : null, e.wv = Eo; - var s = e.deps, c; - Nn && la && e.f & Ie; - } catch (f) { - pr(f, e, r, o || e.ctx); - } finally { - nt = l, S = r; - } + clear_marked(effect2.deps); + set_signal_status(effect2, CLEAN); +} +function is_capture_event(name) { + return name.endsWith("capture") && name !== "gotpointercapture" && name !== "lostpointercapture"; +} +const DELEGATED_EVENTS = [ + "beforeinput", + "click", + "change", + "dblclick", + "contextmenu", + "focusin", + "focusout", + "input", + "keydown", + "keyup", + "mousedown", + "mousemove", + "mouseout", + "mouseover", + "mouseup", + "pointerdown", + "pointermove", + "pointerout", + "pointerover", + "pointerup", + "touchend", + "touchmove", + "touchstart" +]; +function can_delegate_event(event_name) { + return DELEGATED_EVENTS.includes(event_name); +} +const ATTRIBUTE_ALIASES = { + // no `class: 'className'` because we handle that separately + formnovalidate: "formNoValidate", + ismap: "isMap", + nomodule: "noModule", + playsinline: "playsInline", + readonly: "readOnly", + defaultvalue: "defaultValue", + defaultchecked: "defaultChecked", + srcobject: "srcObject", + novalidate: "noValidate", + allowfullscreen: "allowFullscreen", + disablepictureinpicture: "disablePictureInPicture", + disableremoteplayback: "disableRemotePlayback" +}; +function normalize_attribute(name) { + name = name.toLowerCase(); + return ATTRIBUTE_ALIASES[name] ?? name; +} +const PASSIVE_EVENTS = ["touchstart", "touchmove"]; +function is_passive_event(name) { + return PASSIVE_EVENTS.includes(name); +} +function autofocus(dom, value) { + if (value) { + const body = document.body; + dom.autofocus = true; + queue_micro_task(() => { + if (document.activeElement === body) { + dom.focus(); + } + }); } } -function xa() { - try { - ea(); - } catch (e) { - if (sr !== null) - pr(e, sr, null); - else - throw e; +let listening_to_form_reset = false; +function add_form_reset_listener() { + if (!listening_to_form_reset) { + listening_to_form_reset = true; + document.addEventListener( + "reset", + (evt) => { + Promise.resolve().then(() => { + if (!evt.defaultPrevented) { + for ( + const e of + /**@type {HTMLFormElement} */ + evt.target.elements + ) { + e.__on_r?.(); + } + } + }); + }, + // In the capture phase to guarantee we get noticed of it (no possibility of stopPropagation) + { capture: true } + ); } } -function Ao() { - var e = nt; +function without_reactive_context(fn) { + var previous_reaction = active_reaction; + var previous_effect = active_effect; + set_active_reaction(null); + set_active_effect(null); try { - var t = 0; - for (nt = !0; Ft.length > 0; ) { - t++ > 1e3 && xa(); - var r = Ft, o = r.length; - Ft = []; - for (var l = 0; l < o; l++) { - var a = ka(r[l]); - Ca(a); - } - jt.clear(); - } + return fn(); } finally { - lr = !1, nt = e, sr = null; + set_active_reaction(previous_reaction); + set_active_effect(previous_effect); } } -function Ca(e) { - var t = e.length; - if (t !== 0) - for (var r = 0; r < t; r++) { - var o = e[r]; - if ((o.f & (dr | wt)) === 0) - try { - Bt(o) && (Wr(o), o.deps === null && o.first === null && o.nodes_start === null && (o.teardown === null ? po(o) : o.fn = null)); - } catch (l) { - pr(l, o, null, o.ctx); - } +function listen_to_event_and_reset_event(element, event2, handler, on_reset = handler) { + element.addEventListener(event2, () => without_reactive_context(handler)); + const prev = element.__on_r; + if (prev) { + element.__on_r = () => { + prev(); + on_reset(true); + }; + } else { + element.__on_r = () => on_reset(true); + } + add_form_reset_listener(); +} +const event_symbol = /* @__PURE__ */ Symbol("events"); +const all_registered_events = /* @__PURE__ */ new Set(); +const root_event_handles = /* @__PURE__ */ new Set(); +function create_event(event_name, dom, handler, options = {}) { + function target_handler(event2) { + if (!options.capture) { + handle_event_propagation.call(dom, event2); } -} -function mr(e) { - lr || (lr = !0, queueMicrotask(Ao)); - for (var t = sr = e; t.parent !== null; ) { - t = t.parent; - var r = t.f; - if ((r & (it | De)) !== 0) { - if ((r & le) === 0) return; - t.f ^= le; + if (!event2.cancelBubble) { + return without_reactive_context(() => { + return handler?.call(this, event2); + }); } } - Ft.push(t); -} -function ka(e) { - for (var t = [], r = e; r !== null; ) { - var o = r.f, l = (o & (De | it)) !== 0, a = l && (o & le) !== 0; - if (!a && (o & wt) === 0) { - if ((o & eo) !== 0) - t.push(r); - else if (l) - r.f ^= le; - else - try { - Bt(r) && Wr(r); - } catch (f) { - pr(f, r, null, r.ctx); - } - var s = r.first; - if (s !== null) { - r = s; - continue; - } - } - var c = r.parent; - for (r = r.next; r === null && c !== null; ) - r = c.next, c = c.parent; + if (event_name.startsWith("pointer") || event_name.startsWith("touch") || event_name === "wheel") { + queue_micro_task(() => { + dom.addEventListener(event_name, target_handler, options); + }); + } else { + dom.addEventListener(event_name, target_handler, options); } - return t; -} -function E(e) { - for (var t; ; ) { - if (ba(), Ft.length === 0) - return ( - /** @type {T} */ - t - ); - lr = !0, Ao(); + return target_handler; +} +function event(event_name, dom, handler, capture2, passive) { + var options = { capture: capture2, passive }; + var target_handler = create_event(event_name, dom, handler, options); + if (dom === document.body || // @ts-ignore + dom === window || // @ts-ignore + dom === document || // Firefox has quirky behavior, it can happen that we still get "canplay" events when the element is already removed + dom instanceof HTMLMediaElement) { + teardown(() => { + dom.removeEventListener(event_name, target_handler, options); + }); } } -async function Rr() { - await Promise.resolve(), E(); +function delegated(event_name, element, handler) { + (element[event_symbol] ??= {})[event_name] = handler; } -function i(e) { - var t = e.f, r = (t & me) !== 0; - if ($ !== null && !ke) { - if (!Te?.includes(e)) { - var o = $.deps; - e.rv < ur && (e.rv = ur, re === null && o !== null && o[ce] === e ? ce++ : re === null ? re = [e] : (!Ve || !re.includes(e)) && re.push(e)); - } - } else if (r && /** @type {Derived} */ - e.deps === null && /** @type {Derived} */ - e.effects === null) { - var l = ( - /** @type {Derived} */ - e - ), a = l.parent; - a !== null && (a.f & fe) === 0 && (l.f ^= fe); +function delegate(events) { + for (var i = 0; i < events.length; i++) { + all_registered_events.add(events[i]); } - return r && (l = /** @type {Derived} */ - e, Bt(l) && co(l)), qt && jt.has(e) ? jt.get(e) : e.v; -} -function ot(e) { - var t = ke; - try { - return ke = !0, e(); - } finally { - ke = t; + for (var fn of root_event_handles) { + fn(events); } } -const Aa = -7169; -function _e(e, t) { - e.f = e.f & Aa | t; -} -const jt = /* @__PURE__ */ new Map(); -function Io(e, t) { - var r = { - f: 0, - // TODO ideally we could skip this altogether, but it causes type errors - v: e, - reactions: null, - equals: ao, - rv: 0, - wv: 0 - }; - return r; -} -// @__NO_SIDE_EFFECTS__ -function N(e, t) { - const r = Io(e); - return wo(r), r; -} -// @__NO_SIDE_EFFECTS__ -function Yr(e, t = !1) { - const r = Io(e); - return t || (r.equals = jr), r; -} -function b(e, t, r = !1) { - $ !== null && !ke && To() && ($.f & (me | Vr)) !== 0 && !Te?.includes(e) && ia(); - let o = r ? Me(t) : t; - return Ia(e, o); -} -function Ia(e, t) { - if (!e.equals(t)) { - var r = e.v; - qt ? jt.set(e, t) : jt.set(e, r), e.v = t, (e.f & me) !== 0 && ((e.f & Ie) !== 0 && uo( - /** @type {Derived} */ - e - ), _e(e, (e.f & fe) === 0 ? le : at)), e.wv = xo(), Ro(e, Ie), S !== null && (S.f & le) !== 0 && (S.f & (De | it)) === 0 && (he === null ? ya([e]) : he.push(e)); - } - return t; -} -function Ro(e, t) { - var r = e.reactions; - if (r !== null) - for (var o = r.length, l = 0; l < o; l++) { - var a = r[l], s = a.f; - (s & Ie) === 0 && (_e(a, t), (s & (le | fe)) !== 0 && ((s & me) !== 0 ? Ro( - /** @type {Derived} */ - a, - at - ) : mr( - /** @type {Effect} */ - a - ))); - } -} -let ne = null; -function Vn(e) { - ne = e; -} -function $o(e, t = !1, r) { - var o = ne = { - p: ne, - c: null, - d: !1, - e: null, - m: !1, - s: e, - x: null, - l: null - }; - qr(() => { - o.d = !0; - }); -} -function So(e) { - const t = ne; - if (t !== null) { - e !== void 0 && (t.x = e); - const s = t.e; - if (s !== null) { - var r = S, o = $; - t.e = null; - try { - for (var l = 0; l < s.length; l++) { - var a = s[l]; - qe(a.effect), Re(a.reaction), Br(a.fn); - } - } finally { - qe(r), Re(o); - } - } - ne = t.p, t.m = !0; - } - return e || /** @type {T} */ - {}; -} -function To() { - return !0; -} -const Ra = ["touchstart", "touchmove"]; -function $a(e) { - return Ra.includes(e); -} -function Sa(e, t) { - if (t) { - const r = document.body; - e.autofocus = !0, Gr(() => { - document.activeElement === r && e.focus(); - }); - } -} -let Un = !1; -function Do() { - Un || (Un = !0, document.addEventListener( - "reset", - (e) => { - Promise.resolve().then(() => { - if (!e.defaultPrevented) - for ( - const t of - /**@type {HTMLFormElement} */ - e.target.elements - ) - t.__on_r?.(); - }); - }, - // In the capture phase to guarantee we get noticed of it (no possiblity of stopPropagation) - { capture: !0 } - )); -} -function No(e) { - var t = $, r = S; - Re(null), qe(null); - try { - return e(); - } finally { - Re(t), qe(r); - } -} -function Ta(e, t, r, o = r) { - e.addEventListener(t, () => No(r)); - const l = e.__on_r; - l ? e.__on_r = () => { - l(), o(!0); - } : e.__on_r = () => o(!0), Do(); -} -const Lo = /* @__PURE__ */ new Set(), Pr = /* @__PURE__ */ new Set(); -function Da(e, t, r, o = {}) { - function l(a) { - if (o.capture || Pt.call(t, a), !a.cancelBubble) - return No(() => r?.call(this, a)); - } - return e.startsWith("pointer") || e.startsWith("touch") || e === "wheel" ? Gr(() => { - t.addEventListener(e, l, o); - }) : t.addEventListener(e, l, o), l; -} -function Fe(e, t, r, o, l) { - var a = { capture: o, passive: l }, s = Da(e, t, r, a); - (t === document.body || t === window || t === document) && qr(() => { - t.removeEventListener(e, s, a); - }); -} -function Na(e) { - for (var t = 0; t < e.length; t++) - Lo.add(e[t]); - for (var r of Pr) - r(e); -} -function Pt(e) { - var t = this, r = ( +let last_propagated_event = null; +function handle_event_propagation(event2) { + var handler_element = this; + var owner_document = ( /** @type {Node} */ - t.ownerDocument - ), o = e.type, l = e.composedPath?.() || [], a = ( + handler_element.ownerDocument + ); + var event_name = event2.type; + var path = event2.composedPath?.() || []; + var current_target = ( /** @type {null | Element} */ - l[0] || e.target - ), s = 0, c = e.__root; - if (c) { - var f = l.indexOf(c); - if (f !== -1 && (t === document || t === /** @type {any} */ + path[0] || event2.target + ); + last_propagated_event = event2; + var path_idx = 0; + var handled_at = last_propagated_event === event2 && event2[event_symbol]; + if (handled_at) { + var at_idx = path.indexOf(handled_at); + if (at_idx !== -1 && (handler_element === document || handler_element === /** @type {any} */ window)) { - e.__root = t; + event2[event_symbol] = handler_element; return; } - var d = l.indexOf(t); - if (d === -1) + var handler_idx = path.indexOf(handler_element); + if (handler_idx === -1) { return; - f <= d && (s = f); + } + if (at_idx <= handler_idx) { + path_idx = at_idx; + } } - if (a = /** @type {Element} */ - l[s] || e.target, a !== t) { - Mt(e, "currentTarget", { - configurable: !0, - get() { - return a || r; + current_target = /** @type {Element} */ + path[path_idx] || event2.target; + if (current_target === handler_element) return; + define_property(event2, "currentTarget", { + configurable: true, + get() { + return current_target || owner_document; + } + }); + var previous_reaction = active_reaction; + var previous_effect = active_effect; + set_active_reaction(null); + set_active_effect(null); + try { + var throw_error; + var other_errors = []; + while (current_target !== null) { + var parent_element = current_target.assignedSlot || current_target.parentNode || /** @type {any} */ + current_target.host || null; + try { + var delegated2 = current_target[event_symbol]?.[event_name]; + if (delegated2 != null && (!/** @type {any} */ + current_target.disabled || // DOM could've been updated already by the time this is reached, so we check this as well + // -> the target could not have been disabled because it emits the event in the first place + event2.target === current_target)) { + delegated2.call(current_target, event2); + } + } catch (error) { + if (throw_error) { + other_errors.push(error); + } else { + throw_error = error; + } } - }); - var m = $, v = S; - Re(null), qe(null); - try { - for (var _, w = []; a !== null; ) { - var F = a.assignedSlot || a.parentNode || /** @type {any} */ - a.host || null; - try { - var M = a["__" + o]; - if (M != null && (!/** @type {any} */ - a.disabled || // DOM could've been updated already by the time this is reached, so we check this as well - // -> the target could not have been disabled because it emits the event in the first place - e.target === a)) - if (Kn(M)) { - var [U, ...I] = M; - U.apply(a, [e, ...I]); - } else - M.call(a, e); - } catch (ee) { - _ ? w.push(ee) : _ = ee; - } - if (e.cancelBubble || F === t || F === null) - break; - a = F; + if (event2.cancelBubble || parent_element === handler_element || parent_element === null) { + break; } - if (_) { - for (let ee of w) - queueMicrotask(() => { - throw ee; - }); - throw _; + current_target = parent_element; + } + if (throw_error) { + for (let error of other_errors) { + queueMicrotask(() => { + throw error; + }); } - } finally { - e.__root = t, delete e.currentTarget, Re(m), qe(v); + throw throw_error; } + } finally { + event2[event_symbol] = handler_element; + delete event2.currentTarget; + set_active_reaction(previous_reaction); + set_active_effect(previous_effect); } } -function Zr(e) { - var t = document.createElement("template"); - return t.innerHTML = e, t.content; +const policy = ( + // We gotta write it like this because after downleveling the pure comment may end up in the wrong location + globalThis?.window?.trustedTypes && /* @__PURE__ */ globalThis.window.trustedTypes.createPolicy("svelte-trusted-html", { + /** @param {string} html */ + createHTML: (html2) => { + return html2; + } + }) +); +function create_trusted_html(html2) { + return ( + /** @type {string} */ + policy?.createHTML(html2) ?? html2 + ); +} +function create_fragment_from_html(html2) { + var elem = create_element("template"); + elem.innerHTML = create_trusted_html(html2.replaceAll("", "")); + return elem.content; } -function Ae(e, t) { - var r = ( +function assign_nodes(start, end) { + var effect2 = ( /** @type {Effect} */ - S + active_effect ); - r.nodes_start === null && (r.nodes_start = e, r.nodes_end = t); + if (effect2.nodes === null) { + effect2.nodes = { start, end, a: null, t: null }; + } } // @__NO_SIDE_EFFECTS__ -function be(e, t) { - var r = (t & Vi) !== 0, o = (t & Ui) !== 0, l, a = !e.startsWith(""); +function from_html(content, flags2) { + var is_fragment = (flags2 & TEMPLATE_FRAGMENT) !== 0; + var use_import_node = (flags2 & TEMPLATE_USE_IMPORT_NODE) !== 0; + var node; + var has_start = !content.startsWith(""); return () => { - if (O) - return Ae(P, null), P; - l === void 0 && (l = Zr(a ? e : "" + e), r || (l = /** @type {Node} */ - /* @__PURE__ */ ve(l))); - var s = ( + if (hydrating) { + assign_nodes(hydrate_node, null); + return hydrate_node; + } + if (node === void 0) { + node = create_fragment_from_html(has_start ? content : "" + content); + if (!is_fragment) node = /** @type {TemplateNode} */ + /* @__PURE__ */ get_first_child(node); + } + var clone = ( /** @type {TemplateNode} */ - o || no ? document.importNode(l, !0) : l.cloneNode(!0) + use_import_node || is_firefox ? document.importNode(node, true) : node.cloneNode(true) ); - if (r) { - var c = ( + if (is_fragment) { + var start = ( /** @type {TemplateNode} */ - /* @__PURE__ */ ve(s) - ), f = ( + /* @__PURE__ */ get_first_child(clone) + ); + var end = ( /** @type {TemplateNode} */ - s.lastChild + clone.lastChild ); - Ae(c, f); - } else - Ae(s, s); - return s; + assign_nodes(start, end); + } else { + assign_nodes(clone, clone); + } + return clone; }; } // @__NO_SIDE_EFFECTS__ -function _r(e, t, r = "svg") { - var o = !e.startsWith(""), l = `<${r}>${o ? e : "" + e}`, a; +function from_namespace(content, flags2, ns = "svg") { + var has_start = !content.startsWith(""); + var wrapped = `<${ns}>${has_start ? content : "" + content}`; + var node; return () => { - if (O) - return Ae(P, null), P; - if (!a) { - var s = ( + if (hydrating) { + assign_nodes(hydrate_node, null); + return hydrate_node; + } + if (!node) { + var fragment = ( /** @type {DocumentFragment} */ - Zr(l) - ), c = ( + create_fragment_from_html(wrapped) + ); + var root2 = ( /** @type {Element} */ - /* @__PURE__ */ ve(s) + /* @__PURE__ */ get_first_child(fragment) ); - a = /** @type {Element} */ - /* @__PURE__ */ ve(c); + { + node = /** @type {Element} */ + /* @__PURE__ */ get_first_child(root2); + } } - var f = ( + var clone = ( /** @type {TemplateNode} */ - a.cloneNode(!0) + node.cloneNode(true) ); - return Ae(f, f), f; + { + assign_nodes(clone, clone); + } + return clone; }; } -function Xt() { - if (O) - return Ae(P, null), P; - var e = document.createDocumentFragment(), t = document.createComment(""), r = vr(); - return e.append(t, r), Ae(t, r), e; +// @__NO_SIDE_EFFECTS__ +function from_svg(content, flags2) { + return /* @__PURE__ */ from_namespace(content, flags2, "svg"); +} +function text(value = "") { + if (!hydrating) { + var t = create_text(value + ""); + assign_nodes(t, t); + return t; + } + var node = hydrate_node; + if (node.nodeType !== TEXT_NODE) { + node.before(node = create_text()); + set_hydrate_node(node); + } else { + merge_text_nodes( + /** @type {Text} */ + node + ); + } + assign_nodes(node, node); + return node; } -function B(e, t) { - if (O) { - S.nodes_end = P, Et(); +function comment() { + if (hydrating) { + assign_nodes(hydrate_node, null); + return hydrate_node; + } + var frag = document.createDocumentFragment(); + var start = document.createComment(""); + var anchor = create_text(); + frag.append(start, anchor); + assign_nodes(start, anchor); + return frag; +} +function append(anchor, dom) { + if (hydrating) { + var effect2 = ( + /** @type {Effect & { nodes: EffectNodes }} */ + active_effect + ); + if ((effect2.f & REACTION_RAN) === 0 || effect2.nodes.end === null) { + effect2.nodes.end = hydrate_node; + } + hydrate_next(); + return; + } + if (anchor === null) { return; } - e !== null && e.before( + anchor.before( /** @type {Node} */ - t + dom ); } -function La(e, t) { - var r = t == null ? "" : typeof t == "object" ? t + "" : t; - r !== (e.__t ??= e.nodeValue) && (e.__t = r, e.nodeValue = r + ""); -} -function Po(e, t) { - return Oo(e, t); -} -function Pa(e, t) { - Tr(), t.intro = t.intro ?? !1; - const r = t.target, o = O, l = P; - try { - for (var a = ( - /** @type {TemplateNode} */ - /* @__PURE__ */ ve(r) - ); a && (a.nodeType !== 8 || /** @type {Comment} */ - a.data !== Mr); ) - a = /** @type {TemplateNode} */ - /* @__PURE__ */ Be(a); - if (!a) - throw bt; - _t(!0), Ue( - /** @type {Comment} */ - a - ), Et(); - const s = Oo(e, { ...t, anchor: a }); - if (P === null || P.nodeType !== 8 || /** @type {Comment} */ - P.data !== zn) - throw hr(), bt; - return _t(!1), /** @type {Exports} */ - s; - } catch (s) { - if (s === bt) - return t.recover === !1 && ta(), Tr(), sa(r), _t(!1), Po(e, t); - throw s; - } finally { - _t(o), Ue(l); - } -} -const pt = /* @__PURE__ */ new Map(); -function Oo(e, { target: t, anchor: r, props: o = {}, events: l, context: a, intro: s = !0 }) { - Tr(); - var c = /* @__PURE__ */ new Set(), f = (v) => { - for (var _ = 0; _ < v.length; _++) { - var w = v[_]; - if (!c.has(w)) { - c.add(w); - var F = $a(w); - t.addEventListener(w, Pt, { passive: F }); - var M = pt.get(w); - M === void 0 ? (document.addEventListener(w, Pt, { passive: F }), pt.set(w, 1)) : pt.set(w, M + 1); - } +function createSubscriber(start) { + let subscribers = 0; + let version = source(0); + let stop; + return () => { + if (effect_tracking()) { + get(version); + render_effect(() => { + if (subscribers === 0) { + stop = untrack(() => start(() => increment(version))); + } + subscribers += 1; + return () => { + queue_micro_task(() => { + subscribers -= 1; + if (subscribers === 0) { + stop?.(); + stop = void 0; + increment(version); + } + }); + }; + }); } }; - f(Bi(Lo)), Pr.add(f); - var d = void 0, m = va(() => { - var v = r ?? t.appendChild(vr()); - return Nr(() => { - if (a) { - $o({}); - var _ = ( - /** @type {ComponentContext} */ - ne - ); - _.c = a; - } - l && (o.$$events = l), O && Ae( - /** @type {TemplateNode} */ - v, - null - ), d = e(v, o) || {}, O && (S.nodes_end = P), a && So(); - }), () => { - for (var _ of c) { - t.removeEventListener(_, Pt); - var w = ( - /** @type {number} */ - pt.get(_) - ); - --w === 0 ? (document.removeEventListener(_, Pt), pt.delete(_)) : pt.set(_, w); - } - Pr.delete(f), v !== r && v.parentNode?.removeChild(v); +} +var flags = EFFECT_TRANSPARENT | EFFECT_PRESERVED; +function boundary(node, props, children, transform_error) { + new Boundary(node, props, children, transform_error); +} +class Boundary { + /** @type {Boundary | null} */ + parent; + is_pending = false; + /** + * API-level transformError transform function. Transforms errors before they reach the `failed` snippet. + * Inherited from parent boundary, or defaults to identity. + * @type {(error: unknown) => unknown} + */ + transform_error; + /** @type {TemplateNode} */ + #anchor; + /** @type {TemplateNode | null} */ + #hydrate_open = hydrating ? hydrate_node : null; + /** @type {BoundaryProps} */ + #props; + /** @type {((anchor: Node) => void)} */ + #children; + /** @type {Effect} */ + #effect; + /** @type {Effect | null} */ + #main_effect = null; + /** @type {Effect | null} */ + #pending_effect = null; + /** @type {Effect | null} */ + #failed_effect = null; + /** @type {DocumentFragment | null} */ + #offscreen_fragment = null; + #local_pending_count = 0; + #pending_count = 0; + #pending_count_update_queued = false; + /** @type {Set} */ + #dirty_effects = /* @__PURE__ */ new Set(); + /** @type {Set} */ + #maybe_dirty_effects = /* @__PURE__ */ new Set(); + /** + * A source containing the number of pending async deriveds/expressions. + * Only created if `$effect.pending()` is used inside the boundary, + * otherwise updating the source results in needless `Batch.ensure()` + * calls followed by no-op flushes + * @type {Source | null} + */ + #effect_pending = null; + #effect_pending_subscriber = createSubscriber(() => { + this.#effect_pending = source(this.#local_pending_count); + return () => { + this.#effect_pending = null; }; }); - return Or.set(d, m), d; -} -let Or = /* @__PURE__ */ new WeakMap(); -function Oa(e, t) { - const r = Or.get(e); - return r ? (Or.delete(e), r(t)) : Promise.resolve(); -} -function K(e, t, [r, o] = [0, 0]) { - O && r === 0 && Et(); - var l = e, a = null, s = null, c = ae, f = r > 0 ? Ur : 0, d = !1; - const m = (_, w = !0) => { - d = !0, v(w, _); - }, v = (_, w) => { - if (c === (c = _)) return; - let F = !1; - if (O && o !== -1) { - if (r === 0) { - const U = ( + /** + * @param {TemplateNode} node + * @param {BoundaryProps} props + * @param {((anchor: Node) => void)} children + * @param {((error: unknown) => unknown) | undefined} [transform_error] + */ + constructor(node, props, children, transform_error) { + this.#anchor = node; + this.#props = props; + this.#children = (anchor) => { + var effect2 = ( + /** @type {Effect} */ + active_effect + ); + effect2.b = this; + effect2.f |= BOUNDARY_EFFECT; + children(anchor); + }; + this.parent = /** @type {Effect} */ + active_effect.b; + this.transform_error = transform_error ?? this.parent?.transform_error ?? ((e) => e); + this.#effect = block(() => { + if (hydrating) { + const comment2 = ( /** @type {Comment} */ - l.data + this.#hydrate_open ); - U === Mr ? o = 0 : U === Zn ? o = 1 / 0 : (o = parseInt(U.substring(1)), o !== o && (o = c ? 1 / 0 : -1)); - } - const M = o > r; - !!c === M && (l = aa(), Ue(l), _t(!1), F = !0, o = -1); - } - c ? (a ? On(a) : w && (a = Nr(() => w(l))), s && Lr(s, () => { - s = null; - })) : (s ? On(s) : w && (s = Nr(() => w(l, [r + 1, o]))), a && Lr(a, () => { - a = null; - })), F && _t(!0); - }; - fo(() => { - d = !1, t(m), d || v(null, null); - }, f), O && (l = P); -} -function tt(e, t, r = !1, o = !1, l = !1) { - var a = e, s = ""; - Ce(() => { - var c = ( - /** @type {Effect} */ - S - ); - if (s === (s = t() ?? "")) { - O && Et(); - return; - } - if (c.nodes_start !== null && (go( - c.nodes_start, - /** @type {TemplateNode} */ - c.nodes_end - ), c.nodes_start = c.nodes_end = null), s !== "") { - if (O) { - P.data; - for (var f = Et(), d = f; f !== null && (f.nodeType !== 8 || /** @type {Comment} */ - f.data !== ""); ) - d = f, f = /** @type {TemplateNode} */ - /* @__PURE__ */ Be(f); - if (f === null) - throw hr(), bt; - Ae(P, d), a = Ue(f); - return; - } - var m = s + ""; - r ? m = `${m}` : o && (m = `${m}`); - var v = Zr(m); - if ((r || o) && (v = /** @type {Element} */ - /* @__PURE__ */ ve(v)), Ae( - /** @type {TemplateNode} */ - /* @__PURE__ */ ve(v), - /** @type {TemplateNode} */ - v.lastChild - ), r || o) - for (; /* @__PURE__ */ ve(v); ) - a.before( - /** @type {Node} */ - /* @__PURE__ */ ve(v) - ); - else - a.before(v); - } - }); -} -function Fa(e, t, r, o, l) { - O && Et(); - var a = t.$$slots?.[r], s = !1; - a === !0 && (a = t.children, s = !0), a === void 0 || a(e, s ? () => o : o); -} -const jn = [...` -\r\f \v\uFEFF`]; -function Ma(e, t, r) { - var o = "" + e; - if (r) { - for (var l in r) - if (r[l]) - o = o ? o + " " + l : l; - else if (o.length) - for (var a = l.length, s = 0; (s = o.indexOf(l, s)) >= 0; ) { - var c = s + a; - (s === 0 || jn.includes(o[s - 1])) && (c === o.length || jn.includes(o[c])) ? o = (s === 0 ? "" : o.substring(0, s)) + o.substring(c + 1) : s = c; - } - } - return o === "" ? null : o; -} -function Va(e, t, r, o, l, a) { - var s = e.__className; - if (O || s !== r || s === void 0) { - var c = Ma(r, o, a); - (!O || c !== e.getAttribute("class")) && (c == null ? e.removeAttribute("class") : e.className = c), e.__className = r; - } else if (a && l !== a) - for (var f in a) { - var d = !!a[f]; - (l == null || d !== !!l[f]) && e.classList.toggle(f, d); - } - return a; -} -const Ua = Symbol("is custom element"), ja = Symbol("is html"); -function qn(e) { - if (O) { - var t = !1, r = () => { - if (!t) { - if (t = !0, e.hasAttribute("value")) { - var o = e.value; - R(e, "value", null), e.value = o; - } - if (e.hasAttribute("checked")) { - var l = e.checked; - R(e, "checked", null), e.checked = l; + hydrate_next(); + const server_rendered_pending = comment2.data === HYDRATION_START_ELSE; + const server_rendered_failed = comment2.data.startsWith(HYDRATION_START_FAILED); + if (server_rendered_failed) { + const serialized_error = JSON.parse(comment2.data.slice(HYDRATION_START_FAILED.length)); + this.#hydrate_failed_content(serialized_error); + } else if (server_rendered_pending) { + this.#hydrate_pending_content(); + } else { + this.#hydrate_resolved_content(); } + } else { + this.#render(); } - }; - e.__on_r = r, _a(r), Do(); + }, flags); + if (hydrating) { + this.#anchor = hydrate_node; + } } -} -function qa(e, t) { - var r = Fo(e); - r.value === (r.value = // treat null and undefined the same for the initial value - t ?? void 0) || // @ts-expect-error - // `progress` elements always need their value set when it's `0` - e.value === t && (t !== 0 || e.nodeName !== "PROGRESS") || (e.value = t ?? ""); -} -function R(e, t, r, o) { - var l = Fo(e); - O && (l[t] = e.getAttribute(t), t === "src" || t === "srcset" || t === "href" && e.nodeName === "LINK") || l[t] !== (l[t] = r) && (t === "loading" && (e[Ji] = r), r == null ? e.removeAttribute(t) : typeof r != "string" && Ba(e).includes(t) ? e[t] = r : e.setAttribute(t, r)); -} -function Fo(e) { - return ( - /** @type {Record} **/ - // @ts-expect-error - e.__attributes ??= { - [Ua]: e.nodeName.includes("-"), - [ja]: e.namespaceURI === ji + #hydrate_resolved_content() { + try { + this.#main_effect = branch(() => this.#children(this.#anchor)); + } catch (error) { + this.error(error); } - ); -} -var Bn = /* @__PURE__ */ new Map(); -function Ba(e) { - var t = Bn.get(e.nodeName); - if (t) return t; - Bn.set(e.nodeName, t = []); - for (var r, o = e, l = Element.prototype; l !== o; ) { - r = Hi(o); - for (var a in r) - r[a].set && t.push(a); - o = Xn(o); - } - return t; -} -function Ha(e, t, r = t) { - Ta(e, "change", (o) => { - var l = o ? e.defaultChecked : e.checked; - r(l); - }), // If we are hydrating and the value has since changed, - // then use the update value from the input instead. - (O && e.defaultChecked !== e.checked || // If defaultChecked is set, then checked == defaultChecked - ot(t) == null) && r(e.checked), Hr(() => { - var o = t(); - e.checked = !!o; - }); -} -function Hn(e, t) { - return e === t || e?.[Ot] === t; -} -function Qt(e = {}, t, r, o) { - return Br(() => { - var l, a; - return Hr(() => { - l = a, a = [], ot(() => { - e !== r(...a) && (t(e, ...a), l && Hn(r(...l), e) && t(null, ...l)); - }); - }), () => { - Gr(() => { - a && Hn(r(...a), e) && t(null, ...a); - }); - }; - }), e; -} -function Mo(e) { - ne === null && Jn(), Dr(() => { - const t = ot(e); - if (typeof t == "function") return ( - /** @type {() => void} */ - t - ); - }); -} -function Ga(e) { - ne === null && Jn(), Mo(() => () => ot(e)); -} -function Vo(e, t, r) { - if (e == null) - return t(void 0), yt; - const o = ot( - () => e.subscribe( - t, - // @ts-expect-error - r - ) - ); - return o.unsubscribe ? () => o.unsubscribe() : o; -} -const mt = []; -function Wa(e, t = yt) { - let r = null; - const o = /* @__PURE__ */ new Set(); - function l(c) { - if (lo(e, c) && (e = c, r)) { - const f = !mt.length; - for (const d of o) - d[1](), mt.push(d, e); - if (f) { - for (let d = 0; d < mt.length; d += 2) - mt[d][0](mt[d + 1]); - mt.length = 0; - } - } - } - function a(c) { - l(c( - /** @type {T} */ - e - )); } - function s(c, f = yt) { - const d = [c, f]; - return o.add(d), o.size === 1 && (r = t(l, a) || yt), c( - /** @type {T} */ - e - ), () => { - o.delete(d), o.size === 0 && r && (r(), r = null); - }; + /** + * @param {unknown} error The deserialized error from the server's hydration comment + */ + #hydrate_failed_content(error) { + const failed = this.#props.failed; + if (!failed) return; + this.#failed_effect = branch(() => { + failed( + this.#anchor, + () => error, + () => () => { + } + ); + }); } - return { set: l, update: a, subscribe: s }; -} -function rr(e) { - let t; - return Vo(e, (r) => t = r)(), t; -} -let er = !1, Fr = Symbol(); -function Ya(e, t, r) { - const o = r[t] ??= { - store: null, - source: /* @__PURE__ */ Yr(void 0), - unsubscribe: yt - }; - if (o.store !== e && !(Fr in r)) - if (o.unsubscribe(), o.store = e ?? null, e == null) - o.source.v = void 0, o.unsubscribe = yt; - else { - var l = !0; - o.unsubscribe = Vo(e, (a) => { - l ? o.source.v = a : b(o.source, a); - }), l = !1; - } - return e && Fr in r ? rr(e) : i(o.source); -} -function Za() { - const e = {}; - function t() { - qr(() => { - for (var r in e) - e[r].unsubscribe(); - Mt(e, Fr, { - enumerable: !1, - value: !0 + #hydrate_pending_content() { + const pending = this.#props.pending; + if (!pending) return; + this.is_pending = true; + this.#pending_effect = branch(() => pending(this.#anchor)); + var batch = ( + /** @type {Batch} */ + current_batch + ); + queue_micro_task(() => { + var fragment = this.#offscreen_fragment = document.createDocumentFragment(); + var anchor = create_text(); + fragment.append(anchor); + this.#main_effect = this.#run(() => { + return branch(() => this.#children(anchor)); }); + if (this.#pending_count === 0) { + this.#anchor.before(fragment); + this.#offscreen_fragment = null; + pause_effect( + /** @type {Effect} */ + this.#pending_effect, + () => { + this.#pending_effect = null; + } + ); + this.#resolve(batch); + } }); } - return [e, t]; -} -function za(e) { - var t = er; - try { - return er = !1, [e(), er]; - } finally { - er = t; - } -} -function Gn(e) { - return e.ctx?.d ?? !1; -} -function x(e, t, r, o) { - var l = (r & Pi) !== 0, a = !0, s = (r & Fi) !== 0, c = (r & Mi) !== 0, f = !1, d; - s ? [d, f] = za(() => ( - /** @type {V} */ - e[t] - )) : d = /** @type {V} */ - e[t]; - var m = Ot in e || ro in e, v = s && (rt(e, t)?.set ?? (m && t in e && ((j) => e[t] = j))) || void 0, _ = ( - /** @type {V} */ - o - ), w = !0, F = !1, M = () => (F = !0, w && (w = !1, c ? _ = ot( - /** @type {() => V} */ - o - ) : _ = /** @type {V} */ - o), _); - d === void 0 && o !== void 0 && (v && a && ra(), d = M(), v && v(d)); - var U; - if (U = () => { - var j = ( - /** @type {V} */ - e[t] + #render() { + var batch = ( + /** @type {Batch} */ + current_batch ); - return j === void 0 ? M() : (w = !0, F = !1, j); - }, (r & Oi) === 0) - return U; - if (v) { - var I = e.$$legacy; - return function(j, se) { - return arguments.length > 0 ? ((!se || I || f) && v(se ? U() : j), j) : U(); - }; - } - var ee = !1, $e = /* @__PURE__ */ Yr(d), X = /* @__PURE__ */ gr(() => { - var j = U(), se = i($e); - return ee ? (ee = !1, se) : $e.v = j; - }); - return s && i(X), l || (X.equals = jr), function(j, se) { - if (arguments.length > 0) { - const He = se ? i(X) : s ? Me(j) : j; - if (!X.equals(He)) { - if (ee = !0, b($e, He), F && _ !== void 0 && (_ = He), Gn(X)) - return j; - ot(() => i(X)); + try { + this.is_pending = this.has_pending_snippet(); + this.#pending_count = 0; + this.#local_pending_count = 0; + this.#main_effect = branch(() => { + this.#children(this.#anchor); + }); + if (this.#pending_count > 0) { + var fragment = this.#offscreen_fragment = document.createDocumentFragment(); + move_effect(this.#main_effect, fragment); + const pending = ( + /** @type {(anchor: Node) => void} */ + this.#props.pending + ); + this.#pending_effect = branch(() => pending(this.#anchor)); + } else { + this.#resolve(batch); } - return j; + } catch (error) { + this.error(error); } - return Gn(X) ? X.v : i(X); - }; -} -function Ja(e) { - return new Ka(e); -} -class Ka { - /** @type {any} */ - #t; - /** @type {Record} */ - #e; + } /** - * @param {ComponentConstructorOptions & { - * component: any; - * }} options + * @param {Batch} batch */ - constructor(t) { - var r = /* @__PURE__ */ new Map(), o = (a, s) => { - var c = /* @__PURE__ */ Yr(s); - return r.set(a, c), c; - }; - const l = new Proxy( - { ...t.props || {}, $$events: {} }, - { - get(a, s) { - return i(r.get(s) ?? o(s, Reflect.get(a, s))); - }, - has(a, s) { - return s === ro ? !0 : (i(r.get(s) ?? o(s, Reflect.get(a, s))), Reflect.has(a, s)); - }, - set(a, s, c) { - return b(r.get(s) ?? o(s, c), c), Reflect.set(a, s, c); - } - } - ); - this.#e = (t.hydrate ? Pa : Po)(t.component, { - target: t.target, - anchor: t.anchor, - props: l, - context: t.context, - intro: t.intro ?? !1, - recover: t.recover - }), (!t?.props?.$$host || t.sync === !1) && E(), this.#t = l.$$events; - for (const a of Object.keys(this.#e)) - a === "$set" || a === "$destroy" || a === "$on" || Mt(this, a, { - get() { - return this.#e[a]; - }, - /** @param {any} value */ - set(s) { - this.#e[a] = s; - }, - enumerable: !0 - }); - this.#e.$set = /** @param {Record} next */ - (a) => { - Object.assign(l, a); - }, this.#e.$destroy = () => { - Oa(this.#e); - }; - } - /** @param {Record} props */ - $set(t) { - this.#e.$set(t); + #resolve(batch) { + this.is_pending = false; + for (const e of this.#dirty_effects) { + set_signal_status(e, DIRTY); + batch.schedule(e); + } + for (const e of this.#maybe_dirty_effects) { + set_signal_status(e, MAYBE_DIRTY); + batch.schedule(e); + } + this.#dirty_effects.clear(); + this.#maybe_dirty_effects.clear(); } /** - * @param {string} event - * @param {(...args: any[]) => any} callback - * @returns {any} + * Defer an effect inside a pending boundary until the boundary resolves + * @param {Effect} effect */ - $on(t, r) { - this.#t[t] = this.#t[t] || []; - const o = (...l) => r.call(this, ...l); - return this.#t[t].push(o), () => { - this.#t[t] = this.#t[t].filter( - /** @param {any} fn */ - (l) => l !== o - ); - }; + defer_effect(effect2) { + defer_effect(effect2, this.#dirty_effects, this.#maybe_dirty_effects); } - $destroy() { - this.#e.$destroy(); - } -} -let Uo; -typeof HTMLElement == "function" && (Uo = class extends HTMLElement { - /** The Svelte component constructor */ - $$ctor; - /** Slots */ - $$s; - /** @type {any} The Svelte component instance */ - $$c; - /** Whether or not the custom element is connected */ - $$cn = !1; - /** @type {Record} Component props data */ - $$d = {}; - /** `true` if currently in the process of reflecting component props back to attributes */ - $$r = !1; - /** @type {Record} Props definition (name, reflected, type etc) */ - $$p_d = {}; - /** @type {Record} Event listeners */ - $$l = {}; - /** @type {Map} Event listener unsubscribe functions */ - $$l_u = /* @__PURE__ */ new Map(); - /** @type {any} The managed render effect for reflecting attributes */ - $$me; /** - * @param {*} $$componentCtor - * @param {*} $$slots - * @param {*} use_shadow_dom + * Returns `false` if the effect exists inside a boundary whose pending snippet is shown + * @returns {boolean} */ - constructor(e, t, r) { - super(), this.$$ctor = e, this.$$s = t, r && this.attachShadow({ mode: "open" }); + is_rendered() { + return !this.is_pending && (!this.parent || this.parent.is_rendered()); + } + has_pending_snippet() { + return !!this.#props.pending; } /** - * @param {string} type - * @param {EventListenerOrEventListenerObject} listener - * @param {boolean | AddEventListenerOptions} [options] + * @template T + * @param {() => T} fn */ - addEventListener(e, t, r) { - if (this.$$l[e] = this.$$l[e] || [], this.$$l[e].push(t), this.$$c) { - const o = this.$$c.$on(e, t); - this.$$l_u.set(t, o); + #run(fn) { + var previous_effect = active_effect; + var previous_reaction = active_reaction; + var previous_ctx = component_context; + set_active_effect(this.#effect); + set_active_reaction(this.#effect); + set_component_context(this.#effect.ctx); + try { + Batch.ensure(); + return fn(); + } catch (e) { + handle_error(e); + return null; + } finally { + set_active_effect(previous_effect); + set_active_reaction(previous_reaction); + set_component_context(previous_ctx); } - super.addEventListener(e, t, r); } /** - * @param {string} type - * @param {EventListenerOrEventListenerObject} listener - * @param {boolean | AddEventListenerOptions} [options] + * Updates the pending count associated with the currently visible pending snippet, + * if any, such that we can replace the snippet with content once work is done + * @param {1 | -1} d + * @param {Batch} batch */ - removeEventListener(e, t, r) { - if (super.removeEventListener(e, t, r), this.$$c) { - const o = this.$$l_u.get(t); - o && (o(), this.$$l_u.delete(t)); - } - } - async connectedCallback() { - if (this.$$cn = !0, !this.$$c) { - let e = function(o) { - return (l) => { - const a = document.createElement("slot"); - o !== "default" && (a.name = o), B(l, a); - }; - }; - if (await Promise.resolve(), !this.$$cn || this.$$c) - return; - const t = {}, r = Xa(this); - for (const o of this.$$s) - o in r && (o === "default" && !this.$$d.children ? (this.$$d.children = e(o), t.default = !0) : t[o] = e(o)); - for (const o of this.attributes) { - const l = this.$$g_p(o.name); - l in this.$$d || (this.$$d[l] = nr(l, o.value, this.$$p_d, "toProp")); - } - for (const o in this.$$p_d) - !(o in this.$$d) && this[o] !== void 0 && (this.$$d[o] = this[o], delete this[o]); - this.$$c = Ja({ - component: this.$$ctor, - target: this.shadowRoot || this, - props: { - ...this.$$d, - $$slots: t, - $$host: this - } - }), this.$$me = ha(() => { - Hr(() => { - this.$$r = !0; - for (const o of or(this.$$c)) { - if (!this.$$p_d[o]?.reflect) continue; - this.$$d[o] = this.$$c[o]; - const l = nr( - o, - this.$$d[o], - this.$$p_d, - "toAttribute" - ); - l == null ? this.removeAttribute(this.$$p_d[o].attribute || o) : this.setAttribute(this.$$p_d[o].attribute || o, l); - } - this.$$r = !1; + #update_pending_count(d, batch) { + if (!this.has_pending_snippet()) { + if (this.parent) { + this.parent.#update_pending_count(d, batch); + } + return; + } + this.#pending_count += d; + if (this.#pending_count === 0) { + this.#resolve(batch); + if (this.#pending_effect) { + pause_effect(this.#pending_effect, () => { + this.#pending_effect = null; }); - }); - for (const o in this.$$l) - for (const l of this.$$l[o]) { - const a = this.$$c.$on(o, l); - this.$$l_u.set(l, a); - } - this.$$l = {}; + } + if (this.#offscreen_fragment) { + this.#anchor.before(this.#offscreen_fragment); + this.#offscreen_fragment = null; + } } } - // We don't need this when working within Svelte code, but for compatibility of people using this outside of Svelte - // and setting attributes through setAttribute etc, this is helpful /** - * @param {string} attr - * @param {string} _oldValue - * @param {string} newValue + * Update the source that powers `$effect.pending()` inside this boundary, + * and controls when the current `pending` snippet (if any) is removed. + * Do not call from inside the class + * @param {1 | -1} d + * @param {Batch} batch */ - attributeChangedCallback(e, t, r) { - this.$$r || (e = this.$$g_p(e), this.$$d[e] = nr(e, r, this.$$p_d, "toProp"), this.$$c?.$set({ [e]: this.$$d[e] })); - } - disconnectedCallback() { - this.$$cn = !1, Promise.resolve().then(() => { - !this.$$cn && this.$$c && (this.$$c.$destroy(), this.$$me(), this.$$c = void 0); + update_pending_count(d, batch) { + this.#update_pending_count(d, batch); + this.#local_pending_count += d; + if (!this.#effect_pending || this.#pending_count_update_queued) return; + this.#pending_count_update_queued = true; + queue_micro_task(() => { + this.#pending_count_update_queued = false; + if (this.#effect_pending) { + internal_set(this.#effect_pending, this.#local_pending_count); + } }); } - /** - * @param {string} attribute_name - */ - $$g_p(e) { - return or(this.$$p_d).find( - (t) => this.$$p_d[t].attribute === e || !this.$$p_d[t].attribute && t.toLowerCase() === e - ) || e; - } -}); -function nr(e, t, r, o) { - const l = r[e]?.type; - if (t = l === "Boolean" && typeof t != "boolean" ? t != null : t, !o || !r[e]) - return t; - if (o === "toAttribute") - switch (l) { - case "Object": - case "Array": - return t == null ? null : JSON.stringify(t); - case "Boolean": - return t ? "" : null; - case "Number": - return t ?? null; + get_effect_pending() { + this.#effect_pending_subscriber(); + return get( + /** @type {Source} */ + this.#effect_pending + ); + } + /** @param {unknown} error */ + error(error) { + var onerror = this.#props.onerror; + let failed = this.#props.failed; + if (!onerror && !failed) { + throw error; + } + if (this.#main_effect) { + destroy_effect(this.#main_effect); + this.#main_effect = null; + } + if (this.#pending_effect) { + destroy_effect(this.#pending_effect); + this.#pending_effect = null; + } + if (this.#failed_effect) { + destroy_effect(this.#failed_effect); + this.#failed_effect = null; + } + if (hydrating) { + set_hydrate_node( + /** @type {TemplateNode} */ + this.#hydrate_open + ); + next(); + set_hydrate_node(skip_nodes()); + } + var did_reset = false; + var calling_on_error = false; + const reset2 = () => { + if (did_reset) { + svelte_boundary_reset_noop(); + return; + } + did_reset = true; + if (calling_on_error) { + svelte_boundary_reset_onerror(); + } + if (this.#failed_effect !== null) { + pause_effect(this.#failed_effect, () => { + this.#failed_effect = null; + }); + } + this.#run(() => { + this.#render(); + }); + }; + const handle_error_result = (transformed_error) => { + try { + calling_on_error = true; + onerror?.(transformed_error, reset2); + calling_on_error = false; + } catch (error2) { + invoke_error_boundary(error2, this.#effect && this.#effect.parent); + } + if (failed) { + this.#failed_effect = this.#run(() => { + try { + return branch(() => { + var effect2 = ( + /** @type {Effect} */ + active_effect + ); + effect2.b = this; + effect2.f |= BOUNDARY_EFFECT; + failed( + this.#anchor, + () => transformed_error, + () => reset2 + ); + }); + } catch (error2) { + invoke_error_boundary( + error2, + /** @type {Effect} */ + this.#effect.parent + ); + return null; + } + }); + } + }; + queue_micro_task(() => { + var result; + try { + result = this.transform_error(error); + } catch (e) { + invoke_error_boundary(e, this.#effect && this.#effect.parent); + return; + } + if (result !== null && typeof result === "object" && typeof /** @type {any} */ + result.then === "function") { + result.then( + handle_error_result, + /** @param {unknown} e */ + (e) => invoke_error_boundary(e, this.#effect && this.#effect.parent) + ); + } else { + handle_error_result(result); + } + }); + } +} +function set_text(text2, value) { + var str = value == null ? "" : typeof value === "object" ? `${value}` : value; + if (str !== (text2.__t ??= text2.nodeValue)) { + text2.__t = str; + text2.nodeValue = `${str}`; + } +} +function mount(component2, options) { + return _mount(component2, options); +} +function hydrate(component2, options) { + init_operations(); + options.intro = options.intro ?? false; + const target = options.target; + const was_hydrating = hydrating; + const previous_hydrate_node = hydrate_node; + try { + var anchor = /* @__PURE__ */ get_first_child(target); + while (anchor && (anchor.nodeType !== COMMENT_NODE || /** @type {Comment} */ + anchor.data !== HYDRATION_START)) { + anchor = /* @__PURE__ */ get_next_sibling(anchor); + } + if (!anchor) { + throw HYDRATION_ERROR; + } + set_hydrating(true); + set_hydrate_node( + /** @type {Comment} */ + anchor + ); + const instance = _mount(component2, { ...options, anchor }); + set_hydrating(false); + return ( + /** @type {Exports} */ + instance + ); + } catch (error) { + if (error instanceof Error && error.message.split("\n").some((line) => line.startsWith("https://svelte.dev/e/"))) { + throw error; + } + if (error !== HYDRATION_ERROR) { + console.warn("Failed to hydrate: ", error); + } + if (options.recover === false) { + hydration_failed(); + } + init_operations(); + clear_text_content(target); + set_hydrating(false); + return mount(component2, options); + } finally { + set_hydrating(was_hydrating); + set_hydrate_node(previous_hydrate_node); + } +} +const listeners = /* @__PURE__ */ new Map(); +function _mount(Component, { target, anchor, props = {}, events, context, intro = true, transformError }) { + init_operations(); + var component2 = void 0; + var unmount2 = component_root(() => { + var anchor_node = anchor ?? target.appendChild(create_text()); + boundary( + /** @type {TemplateNode} */ + anchor_node, + { + pending: () => { + } + }, + (anchor_node2) => { + push({}); + var ctx = ( + /** @type {ComponentContext} */ + component_context + ); + if (context) ctx.c = context; + if (events) { + props.$$events = events; + } + if (hydrating) { + assign_nodes( + /** @type {TemplateNode} */ + anchor_node2, + null + ); + } + component2 = Component(anchor_node2, props) || {}; + if (hydrating) { + active_effect.nodes.end = hydrate_node; + if (hydrate_node === null || hydrate_node.nodeType !== COMMENT_NODE || /** @type {Comment} */ + hydrate_node.data !== HYDRATION_END) { + hydration_mismatch(); + throw HYDRATION_ERROR; + } + } + pop(); + }, + transformError + ); + var registered_events = /* @__PURE__ */ new Set(); + var event_handle = (events2) => { + for (var i = 0; i < events2.length; i++) { + var event_name = events2[i]; + if (registered_events.has(event_name)) continue; + registered_events.add(event_name); + var passive = is_passive_event(event_name); + for (const node of [target, document]) { + var counts = listeners.get(node); + if (counts === void 0) { + counts = /* @__PURE__ */ new Map(); + listeners.set(node, counts); + } + var count = counts.get(event_name); + if (count === void 0) { + node.addEventListener(event_name, handle_event_propagation, { passive }); + counts.set(event_name, 1); + } else { + counts.set(event_name, count + 1); + } + } + } + }; + event_handle(array_from(all_registered_events)); + root_event_handles.add(event_handle); + return () => { + for (var event_name of registered_events) { + for (const node of [target, document]) { + var counts = ( + /** @type {Map} */ + listeners.get(node) + ); + var count = ( + /** @type {number} */ + counts.get(event_name) + ); + if (--count == 0) { + node.removeEventListener(event_name, handle_event_propagation); + counts.delete(event_name); + if (counts.size === 0) { + listeners.delete(node); + } + } else { + counts.set(event_name, count); + } + } + } + root_event_handles.delete(event_handle); + if (anchor_node !== anchor) { + anchor_node.parentNode?.removeChild(anchor_node); + } + }; + }); + mounted_components.set(component2, unmount2); + return component2; +} +let mounted_components = /* @__PURE__ */ new WeakMap(); +function unmount(component2, options) { + const fn = mounted_components.get(component2); + if (fn) { + mounted_components.delete(component2); + return fn(options); + } + return Promise.resolve(); +} +// @__NO_SIDE_EFFECTS__ +function derived(fn) { + var flags2 = DERIVED | DIRTY; + var parent_derived = active_reaction !== null && (active_reaction.f & DERIVED) !== 0 ? ( + /** @type {Derived} */ + active_reaction + ) : null; + if (active_effect !== null) { + active_effect.f |= EFFECT_PRESERVED; + } + const signal = { + ctx: component_context, + deps: null, + effects: null, + equals, + f: flags2, + fn, + reactions: null, + rv: 0, + v: ( + /** @type {V} */ + UNINITIALIZED + ), + wv: 0, + parent: parent_derived ?? active_effect, + ac: null + }; + return signal; +} +// @__NO_SIDE_EFFECTS__ +function async_derived(fn, label, location2) { + let parent = ( + /** @type {Effect | null} */ + active_effect + ); + if (parent === null) { + async_derived_orphan(); + } + var promise = ( + /** @type {Promise} */ + /** @type {unknown} */ + void 0 + ); + var signal = source( + /** @type {V} */ + UNINITIALIZED + ); + var should_suspend = !active_reaction; + var deferreds = /* @__PURE__ */ new Map(); + async_effect(() => { + var effect2 = ( + /** @type {Effect} */ + active_effect + ); + var d = deferred(); + promise = d.promise; + try { + Promise.resolve(fn()).then(d.resolve, d.reject).finally(unset_context); + } catch (error) { + d.reject(error); + unset_context(); + } + var batch = ( + /** @type {Batch} */ + current_batch + ); + if (should_suspend) { + if ((effect2.f & REACTION_RAN) !== 0) { + var decrement_pending = increment_pending(); + } + if ( + /** @type {Boundary} */ + parent.b.is_rendered() + ) { + deferreds.get(batch)?.reject(STALE_REACTION); + deferreds.delete(batch); + } else { + for (const d2 of deferreds.values()) { + d2.reject(STALE_REACTION); + } + deferreds.clear(); + } + deferreds.set(batch, d); + } + const handler = (value, error = void 0) => { + if (decrement_pending) { + var skip = error === STALE_REACTION; + decrement_pending(skip); + } + if (error === STALE_REACTION || (effect2.f & DESTROYED) !== 0) { + return; + } + batch.activate(); + if (error) { + signal.f |= ERROR_VALUE; + internal_set(signal, error); + } else { + if ((signal.f & ERROR_VALUE) !== 0) { + signal.f ^= ERROR_VALUE; + } + internal_set(signal, value); + for (const [b, d2] of deferreds) { + deferreds.delete(b); + if (b === batch) break; + d2.reject(STALE_REACTION); + } + } + batch.deactivate(); + }; + d.promise.then(handler, (e) => handler(null, e || "unknown")); + }); + teardown(() => { + for (const d of deferreds.values()) { + d.reject(STALE_REACTION); + } + }); + return new Promise((fulfil) => { + function next2(p) { + function go() { + if (p === promise) { + fulfil(signal); + } else { + next2(promise); + } + } + p.then(go, go); + } + next2(promise); + }); +} +// @__NO_SIDE_EFFECTS__ +function user_derived(fn) { + const d = /* @__PURE__ */ derived(fn); + push_reaction_value(d); + return d; +} +function destroy_derived_effects(derived2) { + var effects = derived2.effects; + if (effects !== null) { + derived2.effects = null; + for (var i = 0; i < effects.length; i += 1) { + destroy_effect( + /** @type {Effect} */ + effects[i] + ); + } + } +} +function get_derived_parent_effect(derived2) { + var parent = derived2.parent; + while (parent !== null) { + if ((parent.f & DERIVED) === 0) { + return (parent.f & DESTROYED) === 0 ? ( + /** @type {Effect} */ + parent + ) : null; + } + parent = parent.parent; + } + return null; +} +function execute_derived(derived2) { + var value; + var prev_active_effect = active_effect; + set_active_effect(get_derived_parent_effect(derived2)); + { + try { + derived2.f &= ~WAS_MARKED; + destroy_derived_effects(derived2); + value = update_reaction(derived2); + } finally { + set_active_effect(prev_active_effect); + } + } + return value; +} +function update_derived(derived2) { + var value = execute_derived(derived2); + if (!derived2.equals(value)) { + derived2.wv = increment_write_version(); + if (!current_batch?.is_fork || derived2.deps === null) { + derived2.v = value; + if (derived2.deps === null) { + set_signal_status(derived2, CLEAN); + return; + } + } + } + if (is_destroying_effect) { + return; + } + if (batch_values !== null) { + if (effect_tracking() || current_batch?.is_fork) { + batch_values.set(derived2, value); + } + } else { + update_derived_status(derived2); + } +} +function freeze_derived_effects(derived2) { + if (derived2.effects === null) return; + for (const e of derived2.effects) { + if (e.teardown || e.ac) { + e.teardown?.(); + e.ac?.abort(STALE_REACTION); + e.teardown = noop; + e.ac = null; + remove_reactions(e, 0); + destroy_effect_children(e); + } + } +} +function unfreeze_derived_effects(derived2) { + if (derived2.effects === null) return; + for (const e of derived2.effects) { + if (e.teardown) { + update_effect(e); + } + } +} +function flatten(blockers, sync, async, fn) { + const d = derived; + var pending = blockers.filter((b) => !b.settled); + if (async.length === 0 && pending.length === 0) { + fn(sync.map(d)); + return; + } + var parent = ( + /** @type {Effect} */ + active_effect + ); + var restore = capture(); + var blocker_promise = pending.length === 1 ? pending[0].promise : pending.length > 1 ? Promise.all(pending.map((b) => b.promise)) : null; + function finish(values) { + restore(); + try { + fn(values); + } catch (error) { + if ((parent.f & DESTROYED) === 0) { + invoke_error_boundary(error, parent); + } + } + unset_context(); + } + if (async.length === 0) { + blocker_promise.then(() => finish(sync.map(d))); + return; + } + var decrement_pending = increment_pending(); + function run() { + Promise.all(async.map((expression) => /* @__PURE__ */ async_derived(expression))).then((result) => finish([...sync.map(d), ...result])).catch((error) => invoke_error_boundary(error, parent)).finally(() => decrement_pending()); + } + if (blocker_promise) { + blocker_promise.then(() => { + restore(); + run(); + unset_context(); + }); + } else { + run(); + } +} +function capture() { + var previous_effect = ( + /** @type {Effect} */ + active_effect + ); + var previous_reaction = active_reaction; + var previous_component_context = component_context; + var previous_batch = ( + /** @type {Batch} */ + current_batch + ); + return function restore(activate_batch = true) { + set_active_effect(previous_effect); + set_active_reaction(previous_reaction); + set_component_context(previous_component_context); + if (activate_batch && (previous_effect.f & DESTROYED) === 0) { + previous_batch?.activate(); + previous_batch?.apply(); + } + }; +} +function unset_context(deactivate_batch = true) { + set_active_effect(null); + set_active_reaction(null); + set_component_context(null); + if (deactivate_batch) current_batch?.deactivate(); +} +function increment_pending() { + var boundary2 = ( + /** @type {Boundary} */ + /** @type {Effect} */ + active_effect.b + ); + var batch = ( + /** @type {Batch} */ + current_batch + ); + var blocking = boundary2.is_rendered(); + boundary2.update_pending_count(1, batch); + batch.increment(blocking); + return (skip = false) => { + boundary2.update_pending_count(-1, batch); + batch.decrement(blocking, skip); + }; +} +class BranchManager { + /** @type {TemplateNode} */ + anchor; + /** @type {Map} */ + #batches = /* @__PURE__ */ new Map(); + /** + * Map of keys to effects that are currently rendered in the DOM. + * These effects are visible and actively part of the document tree. + * Example: + * ``` + * {#if condition} + * foo + * {:else} + * bar + * {/if} + * ``` + * Can result in the entries `true->Effect` and `false->Effect` + * @type {Map} + */ + #onscreen = /* @__PURE__ */ new Map(); + /** + * Similar to #onscreen with respect to the keys, but contains branches that are not yet + * in the DOM, because their insertion is deferred. + * @type {Map} + */ + #offscreen = /* @__PURE__ */ new Map(); + /** + * Keys of effects that are currently outroing + * @type {Set} + */ + #outroing = /* @__PURE__ */ new Set(); + /** + * Whether to pause (i.e. outro) on change, or destroy immediately. + * This is necessary for `` + */ + #transition = true; + /** + * @param {TemplateNode} anchor + * @param {boolean} transition + */ + constructor(anchor, transition = true) { + this.anchor = anchor; + this.#transition = transition; + } + /** + * @param {Batch} batch + */ + #commit = (batch) => { + if (!this.#batches.has(batch)) return; + var key2 = ( + /** @type {Key} */ + this.#batches.get(batch) + ); + var onscreen = this.#onscreen.get(key2); + if (onscreen) { + resume_effect(onscreen); + this.#outroing.delete(key2); + } else { + var offscreen = this.#offscreen.get(key2); + if (offscreen) { + this.#onscreen.set(key2, offscreen.effect); + this.#offscreen.delete(key2); + offscreen.fragment.lastChild.remove(); + this.anchor.before(offscreen.fragment); + onscreen = offscreen.effect; + } + } + for (const [b, k] of this.#batches) { + this.#batches.delete(b); + if (b === batch) { + break; + } + const offscreen2 = this.#offscreen.get(k); + if (offscreen2) { + destroy_effect(offscreen2.effect); + this.#offscreen.delete(k); + } + } + for (const [k, effect2] of this.#onscreen) { + if (k === key2 || this.#outroing.has(k)) continue; + const on_destroy = () => { + const keys = Array.from(this.#batches.values()); + if (keys.includes(k)) { + var fragment = document.createDocumentFragment(); + move_effect(effect2, fragment); + fragment.append(create_text()); + this.#offscreen.set(k, { effect: effect2, fragment }); + } else { + destroy_effect(effect2); + } + this.#outroing.delete(k); + this.#onscreen.delete(k); + }; + if (this.#transition || !onscreen) { + this.#outroing.add(k); + pause_effect(effect2, on_destroy, false); + } else { + on_destroy(); + } + } + }; + /** + * @param {Batch} batch + */ + #discard = (batch) => { + this.#batches.delete(batch); + const keys = Array.from(this.#batches.values()); + for (const [k, branch2] of this.#offscreen) { + if (!keys.includes(k)) { + destroy_effect(branch2.effect); + this.#offscreen.delete(k); + } + } + }; + /** + * + * @param {any} key + * @param {null | ((target: TemplateNode) => void)} fn + */ + ensure(key2, fn) { + var batch = ( + /** @type {Batch} */ + current_batch + ); + var defer = should_defer_append(); + if (fn && !this.#onscreen.has(key2) && !this.#offscreen.has(key2)) { + if (defer) { + var fragment = document.createDocumentFragment(); + var target = create_text(); + fragment.append(target); + this.#offscreen.set(key2, { + effect: branch(() => fn(target)), + fragment + }); + } else { + this.#onscreen.set( + key2, + branch(() => fn(this.anchor)) + ); + } + } + this.#batches.set(batch, key2); + if (defer) { + for (const [k, effect2] of this.#onscreen) { + if (k === key2) { + batch.unskip_effect(effect2); + } else { + batch.skip_effect(effect2); + } + } + for (const [k, branch2] of this.#offscreen) { + if (k === key2) { + batch.unskip_effect(branch2.effect); + } else { + batch.skip_effect(branch2.effect); + } + } + batch.oncommit(this.#commit); + batch.ondiscard(this.#discard); + } else { + if (hydrating) { + this.anchor = hydrate_node; + } + this.#commit(batch); + } + } +} +function if_block(node, fn, elseif = false) { + var marker; + if (hydrating) { + marker = hydrate_node; + hydrate_next(); + } + var branches = new BranchManager(node); + var flags2 = elseif ? EFFECT_TRANSPARENT : 0; + function update_branch(key2, fn2) { + if (hydrating) { + var data = read_hydration_instruction( + /** @type {TemplateNode} */ + marker + ); + if (key2 !== parseInt(data.substring(1))) { + var anchor = skip_nodes(); + set_hydrate_node(anchor); + branches.anchor = anchor; + set_hydrating(false); + branches.ensure(key2, fn2); + set_hydrating(true); + return; + } + } + branches.ensure(key2, fn2); + } + block(() => { + var has_branch = false; + fn((fn2, key2 = 0) => { + has_branch = true; + update_branch(key2, fn2); + }); + if (!has_branch) { + update_branch(-1, null); + } + }, flags2); +} +const NAN = /* @__PURE__ */ Symbol("NaN"); +function key(node, get_key, render_fn) { + if (hydrating) { + hydrate_next(); + } + var branches = new BranchManager(node); + block(() => { + var key2 = get_key(); + if (key2 !== key2) { + key2 = /** @type {any} */ + NAN; + } + branches.ensure(key2, render_fn); + }); +} +function html(node, get_value, is_controlled = false, svg = false, mathml = false, skip_warning = false) { + var anchor = node; + var value = ""; + if (is_controlled) { + var parent_node = ( + /** @type {Element} */ + node + ); + if (hydrating) { + anchor = set_hydrate_node(/* @__PURE__ */ get_first_child(parent_node)); + } + } + template_effect(() => { + var effect2 = ( + /** @type {Effect} */ + active_effect + ); + if (value === (value = get_value() ?? "")) { + if (hydrating) hydrate_next(); + return; + } + if (is_controlled && !hydrating) { + effect2.nodes = null; + parent_node.innerHTML = /** @type {string} */ + value; + if (value !== "") { + assign_nodes( + /** @type {TemplateNode} */ + /* @__PURE__ */ get_first_child(parent_node), + /** @type {TemplateNode} */ + parent_node.lastChild + ); + } + return; + } + if (effect2.nodes !== null) { + remove_effect_dom( + effect2.nodes.start, + /** @type {TemplateNode} */ + effect2.nodes.end + ); + effect2.nodes = null; + } + if (value === "") return; + if (hydrating) { + hydrate_node.data; + var next2 = hydrate_next(); + var last = next2; + while (next2 !== null && (next2.nodeType !== COMMENT_NODE || /** @type {Comment} */ + next2.data !== "")) { + last = next2; + next2 = /* @__PURE__ */ get_next_sibling(next2); + } + if (next2 === null) { + hydration_mismatch(); + throw HYDRATION_ERROR; + } + assign_nodes(hydrate_node, last); + anchor = set_hydrate_node(next2); + return; + } + var ns = svg ? NAMESPACE_SVG : mathml ? NAMESPACE_MATHML : void 0; + var wrapper = ( + /** @type {HTMLTemplateElement | SVGElement | MathMLElement} */ + create_element(svg ? "svg" : mathml ? "math" : "template", ns) + ); + wrapper.innerHTML = /** @type {any} */ + value; + var node2 = svg || mathml ? wrapper : ( + /** @type {HTMLTemplateElement} */ + wrapper.content + ); + assign_nodes( + /** @type {TemplateNode} */ + /* @__PURE__ */ get_first_child(node2), + /** @type {TemplateNode} */ + node2.lastChild + ); + if (svg || mathml) { + while (/* @__PURE__ */ get_first_child(node2)) { + anchor.before( + /** @type {TemplateNode} */ + /* @__PURE__ */ get_first_child(node2) + ); + } + } else { + anchor.before(node2); + } + }); +} +function snippet(node, get_snippet, ...args) { + var branches = new BranchManager(node); + block(() => { + const snippet2 = get_snippet() ?? null; + branches.ensure(snippet2, snippet2 && ((anchor) => snippet2(anchor, ...args))); + }, EFFECT_TRANSPARENT); +} +function component(node, get_component, render_fn) { + var hydration_start_node; + if (hydrating) { + hydration_start_node = hydrate_node; + hydrate_next(); + } + var branches = new BranchManager(node); + block(() => { + var component2 = get_component() ?? null; + if (hydrating) { + var data = read_hydration_instruction( + /** @type {TemplateNode} */ + hydration_start_node + ); + var server_had_component = data === HYDRATION_START; + var client_has_component = component2 !== null; + if (server_had_component !== client_has_component) { + var anchor = skip_nodes(); + set_hydrate_node(anchor); + branches.anchor = anchor; + set_hydrating(false); + branches.ensure(component2, component2 && ((target) => render_fn(target, component2))); + set_hydrating(true); + return; + } + } + branches.ensure(component2, component2 && ((target) => render_fn(target, component2))); + }, EFFECT_TRANSPARENT); +} +function attach(node, get_fn) { + var fn = void 0; + var e; + managed(() => { + if (fn !== (fn = get_fn())) { + if (e) { + destroy_effect(e); + e = null; + } + if (fn) { + e = branch(() => { + effect(() => ( + /** @type {(node: Element) => void} */ + fn(node) + )); + }); + } + } + }); +} +function r(e) { + var t, f, n = ""; + if ("string" == typeof e || "number" == typeof e) n += e; + else if ("object" == typeof e) if (Array.isArray(e)) { + var o = e.length; + for (t = 0; t < o; t++) e[t] && (f = r(e[t])) && (n && (n += " "), n += f); + } else for (f in e) e[f] && (n && (n += " "), n += f); + return n; +} +function clsx$1() { + for (var e, t, f = 0, n = "", o = arguments.length; f < o; f++) (e = arguments[f]) && (t = r(e)) && (n && (n += " "), n += t); + return n; +} +function clsx(value) { + if (typeof value === "object") { + return clsx$1(value); + } else { + return value ?? ""; + } +} +const whitespace = [..." \n\r\f \v\uFEFF"]; +function to_class(value, hash, directives) { + var classname = value == null ? "" : "" + value; + if (directives) { + for (var key2 of Object.keys(directives)) { + if (directives[key2]) { + classname = classname ? classname + " " + key2 : key2; + } else if (classname.length) { + var len = key2.length; + var a = 0; + while ((a = classname.indexOf(key2, a)) >= 0) { + var b = a + len; + if ((a === 0 || whitespace.includes(classname[a - 1])) && (b === classname.length || whitespace.includes(classname[b]))) { + classname = (a === 0 ? "" : classname.substring(0, a)) + classname.substring(b + 1); + } else { + a = b; + } + } + } + } + } + return classname === "" ? null : classname; +} +function append_styles(styles, important = false) { + var separator = important ? " !important;" : ";"; + var css2 = ""; + for (var key2 of Object.keys(styles)) { + var value = styles[key2]; + if (value != null && value !== "") { + css2 += " " + key2 + ": " + value + separator; + } + } + return css2; +} +function to_css_name(name) { + if (name[0] !== "-" || name[1] !== "-") { + return name.toLowerCase(); + } + return name; +} +function to_style(value, styles) { + if (styles) { + var new_style = ""; + var normal_styles; + var important_styles; + if (Array.isArray(styles)) { + normal_styles = styles[0]; + important_styles = styles[1]; + } else { + normal_styles = styles; + } + if (value) { + value = String(value).replaceAll(/\s*\/\*.*?\*\/\s*/g, "").trim(); + var in_str = false; + var in_apo = 0; + var in_comment = false; + var reserved_names = []; + if (normal_styles) { + reserved_names.push(...Object.keys(normal_styles).map(to_css_name)); + } + if (important_styles) { + reserved_names.push(...Object.keys(important_styles).map(to_css_name)); + } + var start_index = 0; + var name_index = -1; + const len = value.length; + for (var i = 0; i < len; i++) { + var c = value[i]; + if (in_comment) { + if (c === "/" && value[i - 1] === "*") { + in_comment = false; + } + } else if (in_str) { + if (in_str === c) { + in_str = false; + } + } else if (c === "/" && value[i + 1] === "*") { + in_comment = true; + } else if (c === '"' || c === "'") { + in_str = c; + } else if (c === "(") { + in_apo++; + } else if (c === ")") { + in_apo--; + } + if (!in_comment && in_str === false && in_apo === 0) { + if (c === ":" && name_index === -1) { + name_index = i; + } else if (c === ";" || i === len - 1) { + if (name_index !== -1) { + var name = to_css_name(value.substring(start_index, name_index).trim()); + if (!reserved_names.includes(name)) { + if (c !== ";") { + i++; + } + var property = value.substring(start_index, i).trim(); + new_style += " " + property + ";"; + } + } + start_index = i + 1; + name_index = -1; + } + } + } + } + if (normal_styles) { + new_style += append_styles(normal_styles); + } + if (important_styles) { + new_style += append_styles(important_styles, true); + } + new_style = new_style.trim(); + return new_style === "" ? null : new_style; + } + return value == null ? null : String(value); +} +function set_class(dom, is_html, value, hash, prev_classes, next_classes) { + var prev = dom.__className; + if (hydrating || prev !== value || prev === void 0) { + var next_class_name = to_class(value, hash, next_classes); + if (!hydrating || next_class_name !== dom.getAttribute("class")) { + if (next_class_name == null) { + dom.removeAttribute("class"); + } else if (is_html) { + dom.className = next_class_name; + } else { + dom.setAttribute("class", next_class_name); + } + } + dom.__className = value; + } else if (next_classes && prev_classes !== next_classes) { + for (var key2 in next_classes) { + var is_present = !!next_classes[key2]; + if (prev_classes == null || is_present !== !!prev_classes[key2]) { + dom.classList.toggle(key2, is_present); + } + } + } + return next_classes; +} +function update_styles(dom, prev = {}, next2, priority) { + for (var key2 in next2) { + var value = next2[key2]; + if (prev[key2] !== value) { + if (next2[key2] == null) { + dom.style.removeProperty(key2); + } else { + dom.style.setProperty(key2, value, priority); + } + } + } +} +function set_style(dom, value, prev_styles, next_styles) { + var prev = dom.__style; + if (hydrating || prev !== value) { + var next_style_attr = to_style(value, next_styles); + if (!hydrating || next_style_attr !== dom.getAttribute("style")) { + if (next_style_attr == null) { + dom.removeAttribute("style"); + } else { + dom.style.cssText = next_style_attr; + } + } + dom.__style = value; + } else if (next_styles) { + if (Array.isArray(next_styles)) { + update_styles(dom, prev_styles?.[0], next_styles[0]); + update_styles(dom, prev_styles?.[1], next_styles[1], "important"); + } else { + update_styles(dom, prev_styles, next_styles); + } + } + return next_styles; +} +function select_option(select, value, mounting = false) { + if (select.multiple) { + if (value == void 0) { + return; + } + if (!is_array(value)) { + return select_multiple_invalid_value(); + } + for (var option of select.options) { + option.selected = value.includes(get_option_value(option)); + } + return; + } + for (option of select.options) { + var option_value = get_option_value(option); + if (is(option_value, value)) { + option.selected = true; + return; + } + } + if (!mounting || value !== void 0) { + select.selectedIndex = -1; + } +} +function init_select(select) { + var observer = new MutationObserver(() => { + select_option(select, select.__value); + }); + observer.observe(select, { + // Listen to option element changes + childList: true, + subtree: true, + // because of + // Listen to option element value attribute changes + // (doesn't get notified of select value changes, + // because that property is not reflected as an attribute) + attributes: true, + attributeFilter: ["value"] + }); + teardown(() => { + observer.disconnect(); + }); +} +function get_option_value(option) { + if ("__value" in option) { + return option.__value; + } else { + return option.value; + } +} +const CLASS = /* @__PURE__ */ Symbol("class"); +const STYLE = /* @__PURE__ */ Symbol("style"); +const IS_CUSTOM_ELEMENT = /* @__PURE__ */ Symbol("is custom element"); +const IS_HTML = /* @__PURE__ */ Symbol("is html"); +const LINK_TAG = IS_XHTML ? "link" : "LINK"; +const INPUT_TAG = IS_XHTML ? "input" : "INPUT"; +const OPTION_TAG = IS_XHTML ? "option" : "OPTION"; +const SELECT_TAG = IS_XHTML ? "select" : "SELECT"; +const PROGRESS_TAG = IS_XHTML ? "progress" : "PROGRESS"; +function remove_input_defaults(input) { + if (!hydrating) return; + var already_removed = false; + var remove_defaults = () => { + if (already_removed) return; + already_removed = true; + if (input.hasAttribute("value")) { + var value = input.value; + set_attribute(input, "value", null); + input.value = value; + } + if (input.hasAttribute("checked")) { + var checked = input.checked; + set_attribute(input, "checked", null); + input.checked = checked; + } + }; + input.__on_r = remove_defaults; + queue_micro_task(remove_defaults); + add_form_reset_listener(); +} +function set_value(element, value) { + var attributes = get_attributes(element); + if (attributes.value === (attributes.value = // treat null and undefined the same for the initial value + value ?? void 0) || // @ts-expect-error + // `progress` elements always need their value set when it's `0` + element.value === value && (value !== 0 || element.nodeName !== PROGRESS_TAG)) { + return; + } + element.value = value ?? ""; +} +function set_selected(element, selected) { + if (selected) { + if (!element.hasAttribute("selected")) { + element.setAttribute("selected", ""); + } + } else { + element.removeAttribute("selected"); + } +} +function set_attribute(element, attribute, value, skip_warning) { + var attributes = get_attributes(element); + if (hydrating) { + attributes[attribute] = element.getAttribute(attribute); + if (attribute === "src" || attribute === "srcset" || attribute === "href" && element.nodeName === LINK_TAG) { + return; + } + } + if (attributes[attribute] === (attributes[attribute] = value)) return; + if (attribute === "loading") { + element[LOADING_ATTR_SYMBOL] = value; + } + if (value == null) { + element.removeAttribute(attribute); + } else if (typeof value !== "string" && get_setters(element).includes(attribute)) { + element[attribute] = value; + } else { + element.setAttribute(attribute, value); + } +} +function set_attributes(element, prev, next2, css_hash, should_remove_defaults = false, skip_warning = false) { + if (hydrating && should_remove_defaults && element.nodeName === INPUT_TAG) { + var input = ( + /** @type {HTMLInputElement} */ + element + ); + var attribute = input.type === "checkbox" ? "defaultChecked" : "defaultValue"; + if (!(attribute in next2)) { + remove_input_defaults(input); + } + } + var attributes = get_attributes(element); + var is_custom_element = attributes[IS_CUSTOM_ELEMENT]; + var preserve_attribute_case = !attributes[IS_HTML]; + let is_hydrating_custom_element = hydrating && is_custom_element; + if (is_hydrating_custom_element) { + set_hydrating(false); + } + var current = prev || {}; + var is_option_element = element.nodeName === OPTION_TAG; + for (var key2 in prev) { + if (!(key2 in next2)) { + next2[key2] = null; + } + } + if (next2.class) { + next2.class = clsx(next2.class); + } else if (next2[CLASS]) { + next2.class = null; + } + if (next2[STYLE]) { + next2.style ??= null; + } + var setters = get_setters(element); + for (const key3 in next2) { + let value = next2[key3]; + if (is_option_element && key3 === "value" && value == null) { + element.value = element.__value = ""; + current[key3] = value; + continue; + } + if (key3 === "class") { + var is_html = element.namespaceURI === "http://www.w3.org/1999/xhtml"; + set_class(element, is_html, value, css_hash, prev?.[CLASS], next2[CLASS]); + current[key3] = value; + current[CLASS] = next2[CLASS]; + continue; + } + if (key3 === "style") { + set_style(element, value, prev?.[STYLE], next2[STYLE]); + current[key3] = value; + current[STYLE] = next2[STYLE]; + continue; + } + var prev_value = current[key3]; + if (value === prev_value && !(value === void 0 && element.hasAttribute(key3))) { + continue; + } + current[key3] = value; + var prefix = key3[0] + key3[1]; + if (prefix === "$$") continue; + if (prefix === "on") { + const opts = {}; + const event_handle_key = "$$" + key3; + let event_name = key3.slice(2); + var is_delegated = can_delegate_event(event_name); + if (is_capture_event(event_name)) { + event_name = event_name.slice(0, -7); + opts.capture = true; + } + if (!is_delegated && prev_value) { + if (value != null) continue; + element.removeEventListener(event_name, current[event_handle_key], opts); + current[event_handle_key] = null; + } + if (is_delegated) { + delegated(event_name, element, value); + delegate([event_name]); + } else if (value != null) { + let handle2 = function(evt) { + current[key3].call(this, evt); + }; + var handle = handle2; + current[event_handle_key] = create_event(event_name, element, handle2, opts); + } + } else if (key3 === "style") { + set_attribute(element, key3, value); + } else if (key3 === "autofocus") { + autofocus( + /** @type {HTMLElement} */ + element, + Boolean(value) + ); + } else if (!is_custom_element && (key3 === "__value" || key3 === "value" && value != null)) { + element.value = element.__value = value; + } else if (key3 === "selected" && is_option_element) { + set_selected( + /** @type {HTMLOptionElement} */ + element, + value + ); + } else { + var name = key3; + if (!preserve_attribute_case) { + name = normalize_attribute(name); + } + var is_default = name === "defaultValue" || name === "defaultChecked"; + if (value == null && !is_custom_element && !is_default) { + attributes[key3] = null; + if (name === "value" || name === "checked") { + let input2 = ( + /** @type {HTMLInputElement} */ + element + ); + const use_default = prev === void 0; + if (name === "value") { + let previous = input2.defaultValue; + input2.removeAttribute(name); + input2.defaultValue = previous; + input2.value = input2.__value = use_default ? previous : null; + } else { + let previous = input2.defaultChecked; + input2.removeAttribute(name); + input2.defaultChecked = previous; + input2.checked = use_default ? previous : false; + } + } else { + element.removeAttribute(key3); + } + } else if (is_default || setters.includes(name) && (is_custom_element || typeof value !== "string")) { + element[name] = value; + if (name in attributes) attributes[name] = UNINITIALIZED; + } else if (typeof value !== "function") { + set_attribute(element, name, value); + } + } + } + if (is_hydrating_custom_element) { + set_hydrating(true); + } + return current; +} +function attribute_effect(element, fn, sync = [], async = [], blockers = [], css_hash, should_remove_defaults = false, skip_warning = false) { + flatten(blockers, sync, async, (values) => { + var prev = void 0; + var effects = {}; + var is_select = element.nodeName === SELECT_TAG; + var inited = false; + managed(() => { + var next2 = fn(...values.map(get)); + var current = set_attributes( + element, + prev, + next2, + css_hash, + should_remove_defaults, + skip_warning + ); + if (inited && is_select && "value" in next2) { + select_option( + /** @type {HTMLSelectElement} */ + element, + next2.value + ); + } + for (let symbol of Object.getOwnPropertySymbols(effects)) { + if (!next2[symbol]) destroy_effect(effects[symbol]); + } + for (let symbol of Object.getOwnPropertySymbols(next2)) { + var n = next2[symbol]; + if (symbol.description === ATTACHMENT_KEY && (!prev || n !== prev[symbol])) { + if (effects[symbol]) destroy_effect(effects[symbol]); + effects[symbol] = branch(() => attach(element, () => n)); + } + current[symbol] = n; + } + prev = current; + }); + if (is_select) { + var select = ( + /** @type {HTMLSelectElement} */ + element + ); + effect(() => { + select_option( + select, + /** @type {Record} */ + prev.value, + true + ); + init_select(select); + }); + } + inited = true; + }); +} +function get_attributes(element) { + return ( + /** @type {Record} **/ + // @ts-expect-error + element.__attributes ??= { + [IS_CUSTOM_ELEMENT]: element.nodeName.includes("-"), + [IS_HTML]: element.namespaceURI === NAMESPACE_HTML + } + ); +} +var setters_cache = /* @__PURE__ */ new Map(); +function get_setters(element) { + var cache_key = element.getAttribute("is") || element.nodeName; + var setters = setters_cache.get(cache_key); + if (setters) return setters; + setters_cache.set(cache_key, setters = []); + var descriptors; + var proto = element; + var element_proto = Element.prototype; + while (element_proto !== proto) { + descriptors = get_descriptors(proto); + for (var key2 in descriptors) { + if (descriptors[key2].set) { + setters.push(key2); + } + } + proto = get_prototype_of(proto); + } + return setters; +} +function bind_value(input, get2, set2 = get2) { + var batches2 = /* @__PURE__ */ new WeakSet(); + listen_to_event_and_reset_event(input, "input", async (is_reset) => { + var value = is_reset ? input.defaultValue : input.value; + value = is_numberlike_input(input) ? to_number(value) : value; + set2(value); + if (current_batch !== null) { + batches2.add(current_batch); + } + await tick(); + if (value !== (value = get2())) { + var start = input.selectionStart; + var end = input.selectionEnd; + var length = input.value.length; + input.value = value ?? ""; + if (end !== null) { + var new_length = input.value.length; + if (start === end && end === length && new_length > length) { + input.selectionStart = new_length; + input.selectionEnd = new_length; + } else { + input.selectionStart = start; + input.selectionEnd = Math.min(end, new_length); + } + } + } + }); + if ( + // If we are hydrating and the value has since changed, + // then use the updated value from the input instead. + hydrating && input.defaultValue !== input.value || // If defaultValue is set, then value == defaultValue + // TODO Svelte 6: remove input.value check and set to empty string? + untrack(get2) == null && input.value + ) { + set2(is_numberlike_input(input) ? to_number(input.value) : input.value); + if (current_batch !== null) { + batches2.add(current_batch); + } + } + render_effect(() => { + var value = get2(); + if (input === document.activeElement) { + var batch = ( + /** @type {Batch} */ + current_batch + ); + if (batches2.has(batch)) { + return; + } + } + if (is_numberlike_input(input) && value === to_number(input.value)) { + return; + } + if (input.type === "date" && !value && !input.value) { + return; + } + if (value !== input.value) { + input.value = value ?? ""; + } + }); +} +function is_numberlike_input(input) { + var type = input.type; + return type === "number" || type === "range"; +} +function to_number(value) { + return value === "" ? null : +value; +} +function is_bound_this(bound_value, element_or_component) { + return bound_value === element_or_component || bound_value?.[STATE_SYMBOL] === element_or_component; +} +function bind_this(element_or_component = {}, update, get_value, get_parts) { + var component_effect = ( + /** @type {ComponentContext} */ + component_context.r + ); + var parent = ( + /** @type {Effect} */ + active_effect + ); + effect(() => { + var old_parts; + var parts; + render_effect(() => { + old_parts = parts; + parts = []; + untrack(() => { + if (element_or_component !== get_value(...parts)) { + update(element_or_component, ...parts); + if (old_parts && is_bound_this(get_value(...old_parts), element_or_component)) { + update(null, ...old_parts); + } + } + }); + }); + return () => { + let p = parent; + while (p !== component_effect && p.parent !== null && p.parent.f & DESTROYING) { + p = p.parent; + } + const teardown2 = () => { + if (parts && is_bound_this(get_value(...parts), element_or_component)) { + update(null, ...parts); + } + }; + const original_teardown = p.teardown; + p.teardown = () => { + teardown2(); + original_teardown?.(); + }; + }; + }); + return element_or_component; +} +const rest_props_handler = { + get(target, key2) { + if (target.exclude.includes(key2)) return; + return target.props[key2]; + }, + set(target, key2) { + return false; + }, + getOwnPropertyDescriptor(target, key2) { + if (target.exclude.includes(key2)) return; + if (key2 in target.props) { + return { + enumerable: true, + configurable: true, + value: target.props[key2] + }; + } + }, + has(target, key2) { + if (target.exclude.includes(key2)) return false; + return key2 in target.props; + }, + ownKeys(target) { + return Reflect.ownKeys(target.props).filter((key2) => !target.exclude.includes(key2)); + } +}; +// @__NO_SIDE_EFFECTS__ +function rest_props(props, exclude, name) { + return new Proxy( + { props, exclude }, + rest_props_handler + ); +} +function prop(props, key2, flags2, fallback) { + var fallback_value = ( + /** @type {V} */ + fallback + ); + var fallback_dirty = true; + var get_fallback = () => { + if (fallback_dirty) { + fallback_dirty = false; + fallback_value = /** @type {V} */ + fallback; + } + return fallback_value; + }; + var initial_value; + { + initial_value = /** @type {V} */ + props[key2]; + } + if (initial_value === void 0 && fallback !== void 0) { + initial_value = get_fallback(); + } + var getter; + { + getter = () => { + var value = ( + /** @type {V} */ + props[key2] + ); + if (value === void 0) return get_fallback(); + fallback_dirty = true; + return value; + }; + } + var overridden = false; + var d = /* @__PURE__ */ derived(() => { + overridden = false; + return getter(); + }); + var parent_effect = ( + /** @type {Effect} */ + active_effect + ); + return ( + /** @type {() => V} */ + (function(value, mutation) { + if (arguments.length > 0) { + const new_value = mutation ? get(d) : value; + set(d, new_value); + overridden = true; + if (fallback_value !== void 0) { + fallback_value = new_value; + } + return value; + } + if (is_destroying_effect && overridden || (parent_effect.f & DESTROYED) !== 0) { + return d.v; + } + return get(d); + }) + ); +} +function createClassComponent(options) { + return new Svelte4Component(options); +} +class Svelte4Component { + /** @type {any} */ + #events; + /** @type {Record} */ + #instance; + /** + * @param {ComponentConstructorOptions & { + * component: any; + * }} options + */ + constructor(options) { + var sources = /* @__PURE__ */ new Map(); + var add_source = (key2, value) => { + var s = /* @__PURE__ */ mutable_source(value, false, false); + sources.set(key2, s); + return s; + }; + const props = new Proxy( + { ...options.props || {}, $$events: {} }, + { + get(target, prop2) { + return get(sources.get(prop2) ?? add_source(prop2, Reflect.get(target, prop2))); + }, + has(target, prop2) { + if (prop2 === LEGACY_PROPS) return true; + get(sources.get(prop2) ?? add_source(prop2, Reflect.get(target, prop2))); + return Reflect.has(target, prop2); + }, + set(target, prop2, value) { + set(sources.get(prop2) ?? add_source(prop2, value), value); + return Reflect.set(target, prop2, value); + } + } + ); + this.#instance = (options.hydrate ? hydrate : mount)(options.component, { + target: options.target, + anchor: options.anchor, + props, + context: options.context, + intro: options.intro ?? false, + recover: options.recover, + transformError: options.transformError + }); + if (!options?.props?.$$host || options.sync === false) { + flushSync(); + } + this.#events = props.$$events; + for (const key2 of Object.keys(this.#instance)) { + if (key2 === "$set" || key2 === "$destroy" || key2 === "$on") continue; + define_property(this, key2, { + get() { + return this.#instance[key2]; + }, + /** @param {any} value */ + set(value) { + this.#instance[key2] = value; + }, + enumerable: true + }); + } + this.#instance.$set = /** @param {Record} next */ + (next2) => { + Object.assign(props, next2); + }; + this.#instance.$destroy = () => { + unmount(this.#instance); + }; + } + /** @param {Record} props */ + $set(props) { + this.#instance.$set(props); + } + /** + * @param {string} event + * @param {(...args: any[]) => any} callback + * @returns {any} + */ + $on(event2, callback) { + this.#events[event2] = this.#events[event2] || []; + const cb = (...args) => callback.call(this, ...args); + this.#events[event2].push(cb); + return () => { + this.#events[event2] = this.#events[event2].filter( + /** @param {any} fn */ + (fn) => fn !== cb + ); + }; + } + $destroy() { + this.#instance.$destroy(); + } +} +let SvelteElement = class { +}; +if (typeof HTMLElement === "function") { + SvelteElement = class extends HTMLElement { + /** The Svelte component constructor */ + $$ctor; + /** Slots */ + $$s; + /** @type {any} The Svelte component instance */ + $$c; + /** Whether or not the custom element is connected */ + $$cn = false; + /** @type {Record} Component props data */ + $$d = {}; + /** `true` if currently in the process of reflecting component props back to attributes */ + $$r = false; + /** @type {Record} Props definition (name, reflected, type etc) */ + $$p_d = {}; + /** @type {Record} Event listeners */ + $$l = {}; + /** @type {Map} Event listener unsubscribe functions */ + $$l_u = /* @__PURE__ */ new Map(); + /** @type {any} The managed render effect for reflecting attributes */ + $$me; + /** @type {ShadowRoot | null} The ShadowRoot of the custom element */ + $$shadowRoot = null; + /** + * @param {*} $$componentCtor + * @param {*} $$slots + * @param {ShadowRootInit | undefined} shadow_root_init + */ + constructor($$componentCtor, $$slots, shadow_root_init) { + super(); + this.$$ctor = $$componentCtor; + this.$$s = $$slots; + if (shadow_root_init) { + this.$$shadowRoot = this.attachShadow(shadow_root_init); + } + } + /** + * @param {string} type + * @param {EventListenerOrEventListenerObject} listener + * @param {boolean | AddEventListenerOptions} [options] + */ + addEventListener(type, listener, options) { + this.$$l[type] = this.$$l[type] || []; + this.$$l[type].push(listener); + if (this.$$c) { + const unsub = this.$$c.$on(type, listener); + this.$$l_u.set(listener, unsub); + } + super.addEventListener(type, listener, options); + } + /** + * @param {string} type + * @param {EventListenerOrEventListenerObject} listener + * @param {boolean | AddEventListenerOptions} [options] + */ + removeEventListener(type, listener, options) { + super.removeEventListener(type, listener, options); + if (this.$$c) { + const unsub = this.$$l_u.get(listener); + if (unsub) { + unsub(); + this.$$l_u.delete(listener); + } + } + } + async connectedCallback() { + this.$$cn = true; + if (!this.$$c) { + let create_slot2 = function(name) { + return (anchor) => { + const slot = create_element("slot"); + if (name !== "default") slot.name = name; + append(anchor, slot); + }; + }; + var create_slot = create_slot2; + await Promise.resolve(); + if (!this.$$cn || this.$$c) { + return; + } + const $$slots = {}; + const existing_slots = get_custom_elements_slots(this); + for (const name of this.$$s) { + if (name in existing_slots) { + if (name === "default" && !this.$$d.children) { + this.$$d.children = create_slot2(name); + $$slots.default = true; + } else { + $$slots[name] = create_slot2(name); + } + } + } + for (const attribute of this.attributes) { + const name = this.$$g_p(attribute.name); + if (!(name in this.$$d)) { + this.$$d[name] = get_custom_element_value(name, attribute.value, this.$$p_d, "toProp"); + } + } + for (const key2 in this.$$p_d) { + if (!(key2 in this.$$d) && this[key2] !== void 0) { + this.$$d[key2] = this[key2]; + delete this[key2]; + } + } + this.$$c = createClassComponent({ + component: this.$$ctor, + target: this.$$shadowRoot || this, + props: { + ...this.$$d, + $$slots, + $$host: this + } + }); + this.$$me = effect_root(() => { + render_effect(() => { + this.$$r = true; + for (const key2 of object_keys(this.$$c)) { + if (!this.$$p_d[key2]?.reflect) continue; + this.$$d[key2] = this.$$c[key2]; + const attribute_value = get_custom_element_value( + key2, + this.$$d[key2], + this.$$p_d, + "toAttribute" + ); + if (attribute_value == null) { + this.removeAttribute(this.$$p_d[key2].attribute || key2); + } else { + this.setAttribute(this.$$p_d[key2].attribute || key2, attribute_value); + } + } + this.$$r = false; + }); + }); + for (const type in this.$$l) { + for (const listener of this.$$l[type]) { + const unsub = this.$$c.$on(type, listener); + this.$$l_u.set(listener, unsub); + } + } + this.$$l = {}; + } + } + // We don't need this when working within Svelte code, but for compatibility of people using this outside of Svelte + // and setting attributes through setAttribute etc, this is helpful + /** + * @param {string} attr + * @param {string} _oldValue + * @param {string} newValue + */ + attributeChangedCallback(attr, _oldValue, newValue) { + if (this.$$r) return; + attr = this.$$g_p(attr); + this.$$d[attr] = get_custom_element_value(attr, newValue, this.$$p_d, "toProp"); + this.$$c?.$set({ [attr]: this.$$d[attr] }); + } + disconnectedCallback() { + this.$$cn = false; + Promise.resolve().then(() => { + if (!this.$$cn && this.$$c) { + this.$$c.$destroy(); + this.$$me(); + this.$$c = void 0; + } + }); + } + /** + * @param {string} attribute_name + */ + $$g_p(attribute_name) { + return object_keys(this.$$p_d).find( + (key2) => this.$$p_d[key2].attribute === attribute_name || !this.$$p_d[key2].attribute && key2.toLowerCase() === attribute_name + ) || attribute_name; + } + }; +} +function get_custom_element_value(prop2, value, props_definition, transform) { + const type = props_definition[prop2]?.type; + value = type === "Boolean" && typeof value !== "boolean" ? value != null : value; + if (!transform || !props_definition[prop2]) { + return value; + } else if (transform === "toAttribute") { + switch (type) { + case "Object": + case "Array": + return value == null ? null : JSON.stringify(value); + case "Boolean": + return value ? "" : null; + case "Number": + return value == null ? null : value; + default: + return value; + } + } else { + switch (type) { + case "Object": + case "Array": + return value && JSON.parse(value); + case "Boolean": + return value; + // conversion already handled above + case "Number": + return value != null ? +value : value; default: - return t; + return value; + } + } +} +function get_custom_elements_slots(element) { + const result = {}; + element.childNodes.forEach((node) => { + result[ + /** @type {Element} node */ + node.slot || "default" + ] = true; + }); + return result; +} +function create_custom_element(Component, props_definition, slots, exports$1, shadow_root_init, extend) { + let Class = class extends SvelteElement { + constructor() { + super(Component, slots, shadow_root_init); + this.$$p_d = props_definition; + } + static get observedAttributes() { + return object_keys(props_definition).map( + (key2) => (props_definition[key2].attribute || key2).toLowerCase() + ); + } + }; + object_keys(props_definition).forEach((prop2) => { + define_property(Class.prototype, prop2, { + get() { + return this.$$c && prop2 in this.$$c ? this.$$c[prop2] : this.$$d[prop2]; + }, + set(value) { + value = get_custom_element_value(prop2, value, props_definition); + this.$$d[prop2] = value; + var component2 = this.$$c; + if (component2) { + var setter = get_descriptor(component2, prop2)?.get; + if (setter) { + component2[prop2] = value; + } else { + component2.$set({ [prop2]: value }); + } + } + } + }); + }); + exports$1.forEach((property) => { + define_property(Class.prototype, property, { + get() { + return this.$$c?.[property]; + } + }); + }); + Component.element = /** @type {any} */ + Class; + return Class; +} +function onMount(fn) { + if (component_context === null) { + lifecycle_outside_component(); + } + { + user_effect(() => { + const cleanup = untrack(fn); + if (typeof cleanup === "function") return ( + /** @type {() => void} */ + cleanup + ); + }); + } +} +function subscribe_to_store(store2, run, invalidate) { + if (store2 == null) { + run(void 0); + return noop; + } + const unsub = untrack( + () => store2.subscribe( + run, + // @ts-expect-error + invalidate + ) + ); + return unsub.unsubscribe ? () => unsub.unsubscribe() : unsub; +} +const subscriber_queue = []; +function writable(value, start = noop) { + let stop = null; + const subscribers = /* @__PURE__ */ new Set(); + function set2(new_value) { + if (safe_not_equal(value, new_value)) { + value = new_value; + if (stop) { + const run_queue = !subscriber_queue.length; + for (const subscriber of subscribers) { + subscriber[1](); + subscriber_queue.push(subscriber, value); + } + if (run_queue) { + for (let i = 0; i < subscriber_queue.length; i += 2) { + subscriber_queue[i][0](subscriber_queue[i + 1]); + } + subscriber_queue.length = 0; + } + } + } + } + function update(fn) { + set2(fn( + /** @type {T} */ + value + )); + } + function subscribe(run, invalidate = noop) { + const subscriber = [run, invalidate]; + subscribers.add(subscriber); + if (subscribers.size === 1) { + stop = start(set2, update) || noop; + } + run( + /** @type {T} */ + value + ); + return () => { + subscribers.delete(subscriber); + if (subscribers.size === 0 && stop) { + stop(); + stop = null; + } + }; + } + return { set: set2, update, subscribe }; +} +function get$1(store2) { + let value; + subscribe_to_store(store2, (_) => value = _)(); + return value; +} +let IS_UNMOUNTED = /* @__PURE__ */ Symbol(); +function store_get(store2, store_name, stores) { + const entry = stores[store_name] ??= { + store: null, + source: /* @__PURE__ */ mutable_source(void 0), + unsubscribe: noop + }; + if (entry.store !== store2 && !(IS_UNMOUNTED in stores)) { + entry.unsubscribe(); + entry.store = store2 ?? null; + if (store2 == null) { + entry.source.v = void 0; + entry.unsubscribe = noop; + } else { + var is_synchronous_callback = true; + entry.unsubscribe = subscribe_to_store(store2, (v) => { + if (is_synchronous_callback) { + entry.source.v = v; + } else { + set(entry.source, v); + } + }); + is_synchronous_callback = false; + } + } + if (store2 && IS_UNMOUNTED in stores) { + return get$1(store2); + } + return get(entry.source); +} +function setup_stores() { + const stores = {}; + function cleanup() { + teardown(() => { + for (var store_name in stores) { + const ref = stores[store_name]; + ref.unsubscribe(); + } + define_property(stores, IS_UNMOUNTED, { + enumerable: false, + value: true + }); + }); + } + return [stores, cleanup]; +} +const batches = /* @__PURE__ */ new Set(); +let current_batch = null; +let batch_values = null; +let last_scheduled_effect = null; +let is_flushing_sync = false; +let is_processing = false; +let collected_effects = null; +let legacy_updates = null; +var flush_count = 0; +let uid = 1; +class Batch { + // for debugging. TODO remove once async is stable + id = uid++; + /** + * The current values of any sources that are updated in this batch + * They keys of this map are identical to `this.#previous` + * @type {Map} + */ + current = /* @__PURE__ */ new Map(); + /** + * The values of any sources that are updated in this batch _before_ those updates took place. + * They keys of this map are identical to `this.#current` + * @type {Map} + */ + previous = /* @__PURE__ */ new Map(); + /** + * When the batch is committed (and the DOM is updated), we need to remove old branches + * and append new ones by calling the functions added inside (if/each/key/etc) blocks + * @type {Set<(batch: Batch) => void>} + */ + #commit_callbacks = /* @__PURE__ */ new Set(); + /** + * If a fork is discarded, we need to destroy any effects that are no longer needed + * @type {Set<(batch: Batch) => void>} + */ + #discard_callbacks = /* @__PURE__ */ new Set(); + /** + * The number of async effects that are currently in flight + */ + #pending = 0; + /** + * The number of async effects that are currently in flight, _not_ inside a pending boundary + */ + #blocking_pending = 0; + /** + * A deferred that resolves when the batch is committed, used with `settled()` + * TODO replace with Promise.withResolvers once supported widely enough + * @type {{ promise: Promise, resolve: (value?: any) => void, reject: (reason: unknown) => void } | null} + */ + #deferred = null; + /** + * The root effects that need to be flushed + * @type {Effect[]} + */ + #roots = []; + /** + * Deferred effects (which run after async work has completed) that are DIRTY + * @type {Set} + */ + #dirty_effects = /* @__PURE__ */ new Set(); + /** + * Deferred effects that are MAYBE_DIRTY + * @type {Set} + */ + #maybe_dirty_effects = /* @__PURE__ */ new Set(); + /** + * A map of branches that still exist, but will be destroyed when this batch + * is committed — we skip over these during `process`. + * The value contains child effects that were dirty/maybe_dirty before being reset, + * so they can be rescheduled if the branch survives. + * @type {Map} + */ + #skipped_branches = /* @__PURE__ */ new Map(); + is_fork = false; + #decrement_queued = false; + #is_deferred() { + return this.is_fork || this.#blocking_pending > 0; + } + /** + * Add an effect to the #skipped_branches map and reset its children + * @param {Effect} effect + */ + skip_effect(effect2) { + if (!this.#skipped_branches.has(effect2)) { + this.#skipped_branches.set(effect2, { d: [], m: [] }); + } + } + /** + * Remove an effect from the #skipped_branches map and reschedule + * any tracked dirty/maybe_dirty child effects + * @param {Effect} effect + */ + unskip_effect(effect2) { + var tracked = this.#skipped_branches.get(effect2); + if (tracked) { + this.#skipped_branches.delete(effect2); + for (var e of tracked.d) { + set_signal_status(e, DIRTY); + this.schedule(e); + } + for (e of tracked.m) { + set_signal_status(e, MAYBE_DIRTY); + this.schedule(e); + } + } + } + #process() { + if (flush_count++ > 1e3) { + infinite_loop_guard(); + } + const roots = this.#roots; + this.#roots = []; + this.apply(); + var effects = collected_effects = []; + var render_effects = []; + var updates = legacy_updates = []; + for (const root2 of roots) { + this.#traverse(root2, effects, render_effects); + } + current_batch = null; + if (updates.length > 0) { + var batch = Batch.ensure(); + for (const e of updates) { + batch.schedule(e); + } + } + collected_effects = null; + legacy_updates = null; + if (this.#is_deferred()) { + this.#defer_effects(render_effects); + this.#defer_effects(effects); + for (const [e, t] of this.#skipped_branches) { + reset_branch(e, t); + } + } else { + this.#dirty_effects.clear(); + this.#maybe_dirty_effects.clear(); + for (const fn of this.#commit_callbacks) fn(this); + this.#commit_callbacks.clear(); + flush_queued_effects(render_effects); + flush_queued_effects(effects); + if (this.#pending === 0) { + this.#commit(); + } + this.#deferred?.resolve(); + } + var next_batch = ( + /** @type {Batch | null} */ + /** @type {unknown} */ + current_batch + ); + if (this.#roots.length > 0) { + const batch2 = next_batch ??= this; + batch2.#roots.push(...this.#roots.filter((r2) => !batch2.#roots.includes(r2))); + } + if (next_batch !== null) { + batches.add(next_batch); + next_batch.#process(); + } + } + /** + * Traverse the effect tree, executing effects or stashing + * them for later execution as appropriate + * @param {Effect} root + * @param {Effect[]} effects + * @param {Effect[]} render_effects + */ + #traverse(root2, effects, render_effects) { + root2.f ^= CLEAN; + var effect2 = root2.first; + while (effect2 !== null) { + var flags2 = effect2.f; + var is_branch = (flags2 & (BRANCH_EFFECT | ROOT_EFFECT)) !== 0; + var is_skippable_branch = is_branch && (flags2 & CLEAN) !== 0; + var skip = is_skippable_branch || (flags2 & INERT) !== 0 || this.#skipped_branches.has(effect2); + if (!skip && effect2.fn !== null) { + if (is_branch) { + effect2.f ^= CLEAN; + } else if ((flags2 & EFFECT) !== 0) { + effects.push(effect2); + } else if (is_dirty(effect2)) { + if ((flags2 & BLOCK_EFFECT) !== 0) this.#maybe_dirty_effects.add(effect2); + update_effect(effect2); + } + var child2 = effect2.first; + if (child2 !== null) { + effect2 = child2; + continue; + } + } + while (effect2 !== null) { + var next2 = effect2.next; + if (next2 !== null) { + effect2 = next2; + break; + } + effect2 = effect2.parent; + } + } + } + /** + * @param {Effect[]} effects + */ + #defer_effects(effects) { + for (var i = 0; i < effects.length; i += 1) { + defer_effect(effects[i], this.#dirty_effects, this.#maybe_dirty_effects); + } + } + /** + * Associate a change to a given source with the current + * batch, noting its previous and current values + * @param {Source} source + * @param {any} value + */ + capture(source2, value) { + if (value !== UNINITIALIZED && !this.previous.has(source2)) { + this.previous.set(source2, value); + } + if ((source2.f & ERROR_VALUE) === 0) { + this.current.set(source2, source2.v); + batch_values?.set(source2, source2.v); + } + } + activate() { + current_batch = this; + } + deactivate() { + current_batch = null; + batch_values = null; + } + flush() { + try { + is_processing = true; + current_batch = this; + if (!this.#is_deferred()) { + for (const e of this.#dirty_effects) { + this.#maybe_dirty_effects.delete(e); + set_signal_status(e, DIRTY); + this.schedule(e); + } + for (const e of this.#maybe_dirty_effects) { + set_signal_status(e, MAYBE_DIRTY); + this.schedule(e); + } + } + this.#process(); + } finally { + flush_count = 0; + last_scheduled_effect = null; + collected_effects = null; + legacy_updates = null; + is_processing = false; + current_batch = null; + batch_values = null; + old_values.clear(); + } + } + discard() { + for (const fn of this.#discard_callbacks) fn(this); + this.#discard_callbacks.clear(); + } + #commit() { + if (batches.size > 1) { + this.previous.clear(); + var previous_batch = current_batch; + var previous_batch_values = batch_values; + var is_earlier = true; + for (const batch of batches) { + if (batch === this) { + is_earlier = false; + continue; + } + const sources = []; + for (const [source2, value] of this.current) { + if (batch.current.has(source2)) { + if (is_earlier && value !== batch.current.get(source2)) { + batch.current.set(source2, value); + } else { + continue; + } + } + sources.push(source2); + } + if (sources.length === 0) { + continue; + } + const others = [...batch.current.keys()].filter((s) => !this.current.has(s)); + if (others.length > 0) { + batch.activate(); + const marked = /* @__PURE__ */ new Set(); + const checked = /* @__PURE__ */ new Map(); + for (const source2 of sources) { + mark_effects(source2, others, marked, checked); + } + if (batch.#roots.length > 0) { + batch.apply(); + for (const root2 of batch.#roots) { + batch.#traverse(root2, [], []); + } + } + batch.deactivate(); + } + } + current_batch = previous_batch; + batch_values = previous_batch_values; + } + this.#skipped_branches.clear(); + batches.delete(this); + } + /** + * + * @param {boolean} blocking + */ + increment(blocking) { + this.#pending += 1; + if (blocking) this.#blocking_pending += 1; + } + /** + * @param {boolean} blocking + * @param {boolean} skip - whether to skip updates (because this is triggered by a stale reaction) + */ + decrement(blocking, skip) { + this.#pending -= 1; + if (blocking) this.#blocking_pending -= 1; + if (this.#decrement_queued || skip) return; + this.#decrement_queued = true; + queue_micro_task(() => { + this.#decrement_queued = false; + this.flush(); + }); + } + /** @param {(batch: Batch) => void} fn */ + oncommit(fn) { + this.#commit_callbacks.add(fn); + } + /** @param {(batch: Batch) => void} fn */ + ondiscard(fn) { + this.#discard_callbacks.add(fn); + } + settled() { + return (this.#deferred ??= deferred()).promise; + } + static ensure() { + if (current_batch === null) { + const batch = current_batch = new Batch(); + if (!is_processing) { + batches.add(current_batch); + if (!is_flushing_sync) { + queue_micro_task(() => { + if (current_batch !== batch) { + return; + } + batch.flush(); + }); + } + } + } + return current_batch; + } + apply() { + return; + } + /** + * + * @param {Effect} effect + */ + schedule(effect2) { + last_scheduled_effect = effect2; + if (effect2.b?.is_pending && (effect2.f & (EFFECT | RENDER_EFFECT | MANAGED_EFFECT)) !== 0 && (effect2.f & REACTION_RAN) === 0) { + effect2.b.defer_effect(effect2); + return; + } + var e = effect2; + while (e.parent !== null) { + e = e.parent; + var flags2 = e.f; + if (collected_effects !== null && e === active_effect) { + if ((active_reaction === null || (active_reaction.f & DERIVED) === 0) && true) { + return; + } + } + if ((flags2 & (ROOT_EFFECT | BRANCH_EFFECT)) !== 0) { + if ((flags2 & CLEAN) === 0) { + return; + } + e.f ^= CLEAN; + } + } + this.#roots.push(e); + } +} +function flushSync(fn) { + var was_flushing_sync = is_flushing_sync; + is_flushing_sync = true; + try { + var result; + if (fn) ; + while (true) { + flush_tasks(); + if (current_batch === null) { + return ( + /** @type {T} */ + result + ); + } + current_batch.flush(); + } + } finally { + is_flushing_sync = was_flushing_sync; + } +} +function infinite_loop_guard() { + try { + effect_update_depth_exceeded(); + } catch (error) { + invoke_error_boundary(error, last_scheduled_effect); + } +} +let eager_block_effects = null; +function flush_queued_effects(effects) { + var length = effects.length; + if (length === 0) return; + var i = 0; + while (i < length) { + var effect2 = effects[i++]; + if ((effect2.f & (DESTROYED | INERT)) === 0 && is_dirty(effect2)) { + eager_block_effects = /* @__PURE__ */ new Set(); + update_effect(effect2); + if (effect2.deps === null && effect2.first === null && effect2.nodes === null && effect2.teardown === null && effect2.ac === null) { + unlink_effect(effect2); + } + if (eager_block_effects?.size > 0) { + old_values.clear(); + for (const e of eager_block_effects) { + if ((e.f & (DESTROYED | INERT)) !== 0) continue; + const ordered_effects = [e]; + let ancestor = e.parent; + while (ancestor !== null) { + if (eager_block_effects.has(ancestor)) { + eager_block_effects.delete(ancestor); + ordered_effects.push(ancestor); + } + ancestor = ancestor.parent; + } + for (let j = ordered_effects.length - 1; j >= 0; j--) { + const e2 = ordered_effects[j]; + if ((e2.f & (DESTROYED | INERT)) !== 0) continue; + update_effect(e2); + } + } + eager_block_effects.clear(); + } + } + } + eager_block_effects = null; +} +function mark_effects(value, sources, marked, checked) { + if (marked.has(value)) return; + marked.add(value); + if (value.reactions !== null) { + for (const reaction of value.reactions) { + const flags2 = reaction.f; + if ((flags2 & DERIVED) !== 0) { + mark_effects( + /** @type {Derived} */ + reaction, + sources, + marked, + checked + ); + } else if ((flags2 & (ASYNC | BLOCK_EFFECT)) !== 0 && (flags2 & DIRTY) === 0 && depends_on(reaction, sources, checked)) { + set_signal_status(reaction, DIRTY); + schedule_effect( + /** @type {Effect} */ + reaction + ); + } + } + } +} +function depends_on(reaction, sources, checked) { + const depends = checked.get(reaction); + if (depends !== void 0) return depends; + if (reaction.deps !== null) { + for (const dep of reaction.deps) { + if (includes.call(sources, dep)) { + return true; + } + if ((dep.f & DERIVED) !== 0 && depends_on( + /** @type {Derived} */ + dep, + sources, + checked + )) { + checked.set( + /** @type {Derived} */ + dep, + true + ); + return true; + } + } + } + checked.set(reaction, false); + return false; +} +function schedule_effect(effect2) { + current_batch.schedule(effect2); +} +function reset_branch(effect2, tracked) { + if ((effect2.f & BRANCH_EFFECT) !== 0 && (effect2.f & CLEAN) !== 0) { + return; + } + if ((effect2.f & DIRTY) !== 0) { + tracked.d.push(effect2); + } else if ((effect2.f & MAYBE_DIRTY) !== 0) { + tracked.m.push(effect2); + } + set_signal_status(effect2, CLEAN); + var e = effect2.first; + while (e !== null) { + reset_branch(e, tracked); + e = e.next; + } +} +let eager_effects = /* @__PURE__ */ new Set(); +const old_values = /* @__PURE__ */ new Map(); +let eager_effects_deferred = false; +function source(v, stack) { + var signal = { + f: 0, + // TODO ideally we could skip this altogether, but it causes type errors + v, + reactions: null, + equals, + rv: 0, + wv: 0 + }; + return signal; +} +// @__NO_SIDE_EFFECTS__ +function state(v, stack) { + const s = source(v); + push_reaction_value(s); + return s; +} +// @__NO_SIDE_EFFECTS__ +function mutable_source(initial_value, immutable = false, trackable = true) { + const s = source(initial_value); + if (!immutable) { + s.equals = safe_equals; + } + return s; +} +function set(source2, value, should_proxy = false) { + if (active_reaction !== null && // since we are untracking the function inside `$inspect.with` we need to add this check + // to ensure we error if state is set inside an inspect effect + (!untracking || (active_reaction.f & EAGER_EFFECT) !== 0) && is_runes() && (active_reaction.f & (DERIVED | BLOCK_EFFECT | ASYNC | EAGER_EFFECT)) !== 0 && (current_sources === null || !includes.call(current_sources, source2))) { + state_unsafe_mutation(); + } + let new_value = should_proxy ? proxy(value) : value; + return internal_set(source2, new_value, legacy_updates); +} +function internal_set(source2, value, updated_during_traversal = null) { + if (!source2.equals(value)) { + var old_value = source2.v; + if (is_destroying_effect) { + old_values.set(source2, value); + } else { + old_values.set(source2, old_value); + } + source2.v = value; + var batch = Batch.ensure(); + batch.capture(source2, old_value); + if ((source2.f & DERIVED) !== 0) { + const derived2 = ( + /** @type {Derived} */ + source2 + ); + if ((source2.f & DIRTY) !== 0) { + execute_derived(derived2); + } + update_derived_status(derived2); + } + source2.wv = increment_write_version(); + mark_reactions(source2, DIRTY, updated_during_traversal); + if (active_effect !== null && (active_effect.f & CLEAN) !== 0 && (active_effect.f & (BRANCH_EFFECT | ROOT_EFFECT)) === 0) { + if (untracked_writes === null) { + set_untracked_writes([source2]); + } else { + untracked_writes.push(source2); + } + } + if (!batch.is_fork && eager_effects.size > 0 && !eager_effects_deferred) { + flush_eager_effects(); + } + } + return value; +} +function flush_eager_effects() { + eager_effects_deferred = false; + for (const effect2 of eager_effects) { + if ((effect2.f & CLEAN) !== 0) { + set_signal_status(effect2, MAYBE_DIRTY); + } + if (is_dirty(effect2)) { + update_effect(effect2); + } + } + eager_effects.clear(); +} +function increment(source2) { + set(source2, source2.v + 1); +} +function mark_reactions(signal, status, updated_during_traversal) { + var reactions = signal.reactions; + if (reactions === null) return; + var length = reactions.length; + for (var i = 0; i < length; i++) { + var reaction = reactions[i]; + var flags2 = reaction.f; + var not_dirty = (flags2 & DIRTY) === 0; + if (not_dirty) { + set_signal_status(reaction, status); + } + if ((flags2 & DERIVED) !== 0) { + var derived2 = ( + /** @type {Derived} */ + reaction + ); + batch_values?.delete(derived2); + if ((flags2 & WAS_MARKED) === 0) { + if (flags2 & CONNECTED) { + reaction.f |= WAS_MARKED; + } + mark_reactions(derived2, MAYBE_DIRTY, updated_during_traversal); + } + } else if (not_dirty) { + var effect2 = ( + /** @type {Effect} */ + reaction + ); + if ((flags2 & BLOCK_EFFECT) !== 0 && eager_block_effects !== null) { + eager_block_effects.add(effect2); + } + if (updated_during_traversal !== null) { + updated_during_traversal.push(effect2); + } else { + schedule_effect(effect2); + } + } + } +} +let is_updating_effect = false; +let is_destroying_effect = false; +function set_is_destroying_effect(value) { + is_destroying_effect = value; +} +let active_reaction = null; +let untracking = false; +function set_active_reaction(reaction) { + active_reaction = reaction; +} +let active_effect = null; +function set_active_effect(effect2) { + active_effect = effect2; +} +let current_sources = null; +function push_reaction_value(value) { + if (active_reaction !== null && true) { + if (current_sources === null) { + current_sources = [value]; + } else { + current_sources.push(value); + } + } +} +let new_deps = null; +let skipped_deps = 0; +let untracked_writes = null; +function set_untracked_writes(value) { + untracked_writes = value; +} +let write_version = 1; +let read_version = 0; +let update_version = read_version; +function set_update_version(value) { + update_version = value; +} +function increment_write_version() { + return ++write_version; +} +function is_dirty(reaction) { + var flags2 = reaction.f; + if ((flags2 & DIRTY) !== 0) { + return true; + } + if (flags2 & DERIVED) { + reaction.f &= ~WAS_MARKED; + } + if ((flags2 & MAYBE_DIRTY) !== 0) { + var dependencies = ( + /** @type {Value[]} */ + reaction.deps + ); + var length = dependencies.length; + for (var i = 0; i < length; i++) { + var dependency = dependencies[i]; + if (is_dirty( + /** @type {Derived} */ + dependency + )) { + update_derived( + /** @type {Derived} */ + dependency + ); + } + if (dependency.wv > reaction.wv) { + return true; + } + } + if ((flags2 & CONNECTED) !== 0 && // During time traveling we don't want to reset the status so that + // traversal of the graph in the other batches still happens + batch_values === null) { + set_signal_status(reaction, CLEAN); + } + } + return false; +} +function schedule_possible_effect_self_invalidation(signal, effect2, root2 = true) { + var reactions = signal.reactions; + if (reactions === null) return; + if (current_sources !== null && includes.call(current_sources, signal)) { + return; + } + for (var i = 0; i < reactions.length; i++) { + var reaction = reactions[i]; + if ((reaction.f & DERIVED) !== 0) { + schedule_possible_effect_self_invalidation( + /** @type {Derived} */ + reaction, + effect2, + false + ); + } else if (effect2 === reaction) { + if (root2) { + set_signal_status(reaction, DIRTY); + } else if ((reaction.f & CLEAN) !== 0) { + set_signal_status(reaction, MAYBE_DIRTY); + } + schedule_effect( + /** @type {Effect} */ + reaction + ); + } + } +} +function update_reaction(reaction) { + var previous_deps = new_deps; + var previous_skipped_deps = skipped_deps; + var previous_untracked_writes = untracked_writes; + var previous_reaction = active_reaction; + var previous_sources = current_sources; + var previous_component_context = component_context; + var previous_untracking = untracking; + var previous_update_version = update_version; + var flags2 = reaction.f; + new_deps = /** @type {null | Value[]} */ + null; + skipped_deps = 0; + untracked_writes = null; + active_reaction = (flags2 & (BRANCH_EFFECT | ROOT_EFFECT)) === 0 ? reaction : null; + current_sources = null; + set_component_context(reaction.ctx); + untracking = false; + update_version = ++read_version; + if (reaction.ac !== null) { + without_reactive_context(() => { + reaction.ac.abort(STALE_REACTION); + }); + reaction.ac = null; + } + try { + reaction.f |= REACTION_IS_UPDATING; + var fn = ( + /** @type {Function} */ + reaction.fn + ); + var result = fn(); + reaction.f |= REACTION_RAN; + var deps = reaction.deps; + var is_fork = current_batch?.is_fork; + if (new_deps !== null) { + var i; + if (!is_fork) { + remove_reactions(reaction, skipped_deps); + } + if (deps !== null && skipped_deps > 0) { + deps.length = skipped_deps + new_deps.length; + for (i = 0; i < new_deps.length; i++) { + deps[skipped_deps + i] = new_deps[i]; + } + } else { + reaction.deps = deps = new_deps; + } + if (effect_tracking() && (reaction.f & CONNECTED) !== 0) { + for (i = skipped_deps; i < deps.length; i++) { + (deps[i].reactions ??= []).push(reaction); + } + } + } else if (!is_fork && deps !== null && skipped_deps < deps.length) { + remove_reactions(reaction, skipped_deps); + deps.length = skipped_deps; + } + if (is_runes() && untracked_writes !== null && !untracking && deps !== null && (reaction.f & (DERIVED | MAYBE_DIRTY | DIRTY)) === 0) { + for (i = 0; i < /** @type {Source[]} */ + untracked_writes.length; i++) { + schedule_possible_effect_self_invalidation( + untracked_writes[i], + /** @type {Effect} */ + reaction + ); + } + } + if (previous_reaction !== null && previous_reaction !== reaction) { + read_version++; + if (previous_reaction.deps !== null) { + for (let i2 = 0; i2 < previous_skipped_deps; i2 += 1) { + previous_reaction.deps[i2].rv = read_version; + } + } + if (previous_deps !== null) { + for (const dep of previous_deps) { + dep.rv = read_version; + } + } + if (untracked_writes !== null) { + if (previous_untracked_writes === null) { + previous_untracked_writes = untracked_writes; + } else { + previous_untracked_writes.push(.../** @type {Source[]} */ + untracked_writes); + } + } + } + if ((reaction.f & ERROR_VALUE) !== 0) { + reaction.f ^= ERROR_VALUE; + } + return result; + } catch (error) { + return handle_error(error); + } finally { + reaction.f ^= REACTION_IS_UPDATING; + new_deps = previous_deps; + skipped_deps = previous_skipped_deps; + untracked_writes = previous_untracked_writes; + active_reaction = previous_reaction; + current_sources = previous_sources; + set_component_context(previous_component_context); + untracking = previous_untracking; + update_version = previous_update_version; + } +} +function remove_reaction(signal, dependency) { + let reactions = dependency.reactions; + if (reactions !== null) { + var index = index_of.call(reactions, signal); + if (index !== -1) { + var new_length = reactions.length - 1; + if (new_length === 0) { + reactions = dependency.reactions = null; + } else { + reactions[index] = reactions[new_length]; + reactions.pop(); + } + } + } + if (reactions === null && (dependency.f & DERIVED) !== 0 && // Destroying a child effect while updating a parent effect can cause a dependency to appear + // to be unused, when in fact it is used by the currently-updating parent. Checking `new_deps` + // allows us to skip the expensive work of disconnecting and immediately reconnecting it + (new_deps === null || !includes.call(new_deps, dependency))) { + var derived2 = ( + /** @type {Derived} */ + dependency + ); + if ((derived2.f & CONNECTED) !== 0) { + derived2.f ^= CONNECTED; + derived2.f &= ~WAS_MARKED; + } + update_derived_status(derived2); + freeze_derived_effects(derived2); + remove_reactions(derived2, 0); + } +} +function remove_reactions(signal, start_index) { + var dependencies = signal.deps; + if (dependencies === null) return; + for (var i = start_index; i < dependencies.length; i++) { + remove_reaction(signal, dependencies[i]); + } +} +function update_effect(effect2) { + var flags2 = effect2.f; + if ((flags2 & DESTROYED) !== 0) { + return; + } + set_signal_status(effect2, CLEAN); + var previous_effect = active_effect; + var was_updating_effect = is_updating_effect; + active_effect = effect2; + is_updating_effect = true; + try { + if ((flags2 & (BLOCK_EFFECT | MANAGED_EFFECT)) !== 0) { + destroy_block_effect_children(effect2); + } else { + destroy_effect_children(effect2); + } + execute_effect_teardown(effect2); + var teardown2 = update_reaction(effect2); + effect2.teardown = typeof teardown2 === "function" ? teardown2 : null; + effect2.wv = write_version; + var dep; + if (DEV && tracing_mode_flag && (effect2.f & DIRTY) !== 0 && effect2.deps !== null) ; + } finally { + is_updating_effect = was_updating_effect; + active_effect = previous_effect; + } +} +async function tick() { + await Promise.resolve(); + flushSync(); +} +function get(signal) { + var flags2 = signal.f; + var is_derived = (flags2 & DERIVED) !== 0; + if (active_reaction !== null && !untracking) { + var destroyed = active_effect !== null && (active_effect.f & DESTROYED) !== 0; + if (!destroyed && (current_sources === null || !includes.call(current_sources, signal))) { + var deps = active_reaction.deps; + if ((active_reaction.f & REACTION_IS_UPDATING) !== 0) { + if (signal.rv < read_version) { + signal.rv = read_version; + if (new_deps === null && deps !== null && deps[skipped_deps] === signal) { + skipped_deps++; + } else if (new_deps === null) { + new_deps = [signal]; + } else { + new_deps.push(signal); + } + } + } else { + (active_reaction.deps ??= []).push(signal); + var reactions = signal.reactions; + if (reactions === null) { + signal.reactions = [active_reaction]; + } else if (!includes.call(reactions, active_reaction)) { + reactions.push(active_reaction); + } + } + } + } + if (is_destroying_effect && old_values.has(signal)) { + return old_values.get(signal); + } + if (is_derived) { + var derived2 = ( + /** @type {Derived} */ + signal + ); + if (is_destroying_effect) { + var value = derived2.v; + if ((derived2.f & CLEAN) === 0 && derived2.reactions !== null || depends_on_old_values(derived2)) { + value = execute_derived(derived2); + } + old_values.set(derived2, value); + return value; + } + var should_connect = (derived2.f & CONNECTED) === 0 && !untracking && active_reaction !== null && (is_updating_effect || (active_reaction.f & CONNECTED) !== 0); + var is_new = (derived2.f & REACTION_RAN) === 0; + if (is_dirty(derived2)) { + if (should_connect) { + derived2.f |= CONNECTED; + } + update_derived(derived2); + } + if (should_connect && !is_new) { + unfreeze_derived_effects(derived2); + reconnect(derived2); + } + } + if (batch_values?.has(signal)) { + return batch_values.get(signal); + } + if ((signal.f & ERROR_VALUE) !== 0) { + throw signal.v; + } + return signal.v; +} +function reconnect(derived2) { + derived2.f |= CONNECTED; + if (derived2.deps === null) return; + for (const dep of derived2.deps) { + (dep.reactions ??= []).push(derived2); + if ((dep.f & DERIVED) !== 0 && (dep.f & CONNECTED) === 0) { + unfreeze_derived_effects( + /** @type {Derived} */ + dep + ); + reconnect( + /** @type {Derived} */ + dep + ); + } + } +} +function depends_on_old_values(derived2) { + if (derived2.v === UNINITIALIZED) return true; + if (derived2.deps === null) return false; + for (const dep of derived2.deps) { + if (old_values.has(dep)) { + return true; + } + if ((dep.f & DERIVED) !== 0 && depends_on_old_values( + /** @type {Derived} */ + dep + )) { + return true; + } + } + return false; +} +function untrack(fn) { + var previous_untracking = untracking; + try { + untracking = true; + return fn(); + } finally { + untracking = previous_untracking; + } +} +function validate_effect(rune) { + if (active_effect === null) { + if (active_reaction === null) { + effect_orphan(); + } + effect_in_unowned_derived(); + } + if (is_destroying_effect) { + effect_in_teardown(); + } +} +function push_effect(effect2, parent_effect) { + var parent_last = parent_effect.last; + if (parent_last === null) { + parent_effect.last = parent_effect.first = effect2; + } else { + parent_last.next = effect2; + effect2.prev = parent_last; + parent_effect.last = effect2; + } +} +function create_effect(type, fn) { + var parent = active_effect; + if (parent !== null && (parent.f & INERT) !== 0) { + type |= INERT; + } + var effect2 = { + ctx: component_context, + deps: null, + nodes: null, + f: type | DIRTY | CONNECTED, + first: null, + fn, + last: null, + next: null, + parent, + b: parent && parent.b, + prev: null, + teardown: null, + wv: 0, + ac: null + }; + var e = effect2; + if ((type & EFFECT) !== 0) { + if (collected_effects !== null) { + collected_effects.push(effect2); + } else { + Batch.ensure().schedule(effect2); + } + } else if (fn !== null) { + try { + update_effect(effect2); + } catch (e2) { + destroy_effect(effect2); + throw e2; + } + if (e.deps === null && e.teardown === null && e.nodes === null && e.first === e.last && // either `null`, or a singular child + (e.f & EFFECT_PRESERVED) === 0) { + e = e.first; + if ((type & BLOCK_EFFECT) !== 0 && (type & EFFECT_TRANSPARENT) !== 0 && e !== null) { + e.f |= EFFECT_TRANSPARENT; + } + } + } + if (e !== null) { + e.parent = parent; + if (parent !== null) { + push_effect(e, parent); + } + if (active_reaction !== null && (active_reaction.f & DERIVED) !== 0 && (type & ROOT_EFFECT) === 0) { + var derived2 = ( + /** @type {Derived} */ + active_reaction + ); + (derived2.effects ??= []).push(e); + } + } + return effect2; +} +function effect_tracking() { + return active_reaction !== null && !untracking; +} +function teardown(fn) { + const effect2 = create_effect(RENDER_EFFECT, null); + set_signal_status(effect2, CLEAN); + effect2.teardown = fn; + return effect2; +} +function user_effect(fn) { + validate_effect(); + var flags2 = ( + /** @type {Effect} */ + active_effect.f + ); + var defer = !active_reaction && (flags2 & BRANCH_EFFECT) !== 0 && (flags2 & REACTION_RAN) === 0; + if (defer) { + var context = ( + /** @type {ComponentContext} */ + component_context + ); + (context.e ??= []).push(fn); + } else { + return create_user_effect(fn); + } +} +function create_user_effect(fn) { + return create_effect(EFFECT | USER_EFFECT, fn); +} +function effect_root(fn) { + Batch.ensure(); + const effect2 = create_effect(ROOT_EFFECT | EFFECT_PRESERVED, fn); + return () => { + destroy_effect(effect2); + }; +} +function component_root(fn) { + Batch.ensure(); + const effect2 = create_effect(ROOT_EFFECT | EFFECT_PRESERVED, fn); + return (options = {}) => { + return new Promise((fulfil) => { + if (options.outro) { + pause_effect(effect2, () => { + destroy_effect(effect2); + fulfil(void 0); + }); + } else { + destroy_effect(effect2); + fulfil(void 0); + } + }); + }; +} +function effect(fn) { + return create_effect(EFFECT, fn); +} +function async_effect(fn) { + return create_effect(ASYNC | EFFECT_PRESERVED, fn); +} +function render_effect(fn, flags2 = 0) { + return create_effect(RENDER_EFFECT | flags2, fn); +} +function template_effect(fn, sync = [], async = [], blockers = []) { + flatten(blockers, sync, async, (values) => { + create_effect(RENDER_EFFECT, () => fn(...values.map(get))); + }); +} +function block(fn, flags2 = 0) { + var effect2 = create_effect(BLOCK_EFFECT | flags2, fn); + return effect2; +} +function managed(fn, flags2 = 0) { + var effect2 = create_effect(MANAGED_EFFECT | flags2, fn); + return effect2; +} +function branch(fn) { + return create_effect(BRANCH_EFFECT | EFFECT_PRESERVED, fn); +} +function execute_effect_teardown(effect2) { + var teardown2 = effect2.teardown; + if (teardown2 !== null) { + const previously_destroying_effect = is_destroying_effect; + const previous_reaction = active_reaction; + set_is_destroying_effect(true); + set_active_reaction(null); + try { + teardown2.call(null); + } finally { + set_is_destroying_effect(previously_destroying_effect); + set_active_reaction(previous_reaction); + } + } +} +function destroy_effect_children(signal, remove_dom = false) { + var effect2 = signal.first; + signal.first = signal.last = null; + while (effect2 !== null) { + const controller = effect2.ac; + if (controller !== null) { + without_reactive_context(() => { + controller.abort(STALE_REACTION); + }); + } + var next2 = effect2.next; + if ((effect2.f & ROOT_EFFECT) !== 0) { + effect2.parent = null; + } else { + destroy_effect(effect2, remove_dom); + } + effect2 = next2; + } +} +function destroy_block_effect_children(signal) { + var effect2 = signal.first; + while (effect2 !== null) { + var next2 = effect2.next; + if ((effect2.f & BRANCH_EFFECT) === 0) { + destroy_effect(effect2); + } + effect2 = next2; + } +} +function destroy_effect(effect2, remove_dom = true) { + var removed = false; + if ((remove_dom || (effect2.f & HEAD_EFFECT) !== 0) && effect2.nodes !== null && effect2.nodes.end !== null) { + remove_effect_dom( + effect2.nodes.start, + /** @type {TemplateNode} */ + effect2.nodes.end + ); + removed = true; + } + set_signal_status(effect2, DESTROYING); + destroy_effect_children(effect2, remove_dom && !removed); + remove_reactions(effect2, 0); + var transitions = effect2.nodes && effect2.nodes.t; + if (transitions !== null) { + for (const transition of transitions) { + transition.stop(); + } + } + execute_effect_teardown(effect2); + effect2.f ^= DESTROYING; + effect2.f |= DESTROYED; + var parent = effect2.parent; + if (parent !== null && parent.first !== null) { + unlink_effect(effect2); + } + effect2.next = effect2.prev = effect2.teardown = effect2.ctx = effect2.deps = effect2.fn = effect2.nodes = effect2.ac = null; +} +function remove_effect_dom(node, end) { + while (node !== null) { + var next2 = node === end ? null : /* @__PURE__ */ get_next_sibling(node); + node.remove(); + node = next2; + } +} +function unlink_effect(effect2) { + var parent = effect2.parent; + var prev = effect2.prev; + var next2 = effect2.next; + if (prev !== null) prev.next = next2; + if (next2 !== null) next2.prev = prev; + if (parent !== null) { + if (parent.first === effect2) parent.first = next2; + if (parent.last === effect2) parent.last = prev; + } +} +function pause_effect(effect2, callback, destroy = true) { + var transitions = []; + pause_children(effect2, transitions, true); + var fn = () => { + if (destroy) destroy_effect(effect2); + if (callback) callback(); + }; + var remaining = transitions.length; + if (remaining > 0) { + var check = () => --remaining || fn(); + for (var transition of transitions) { + transition.out(check); + } + } else { + fn(); + } +} +function pause_children(effect2, transitions, local) { + if ((effect2.f & INERT) !== 0) return; + effect2.f ^= INERT; + var t = effect2.nodes && effect2.nodes.t; + if (t !== null) { + for (const transition of t) { + if (transition.is_global || local) { + transitions.push(transition); + } + } + } + var child2 = effect2.first; + while (child2 !== null) { + var sibling2 = child2.next; + var transparent = (child2.f & EFFECT_TRANSPARENT) !== 0 || // If this is a branch effect without a block effect parent, + // it means the parent block effect was pruned. In that case, + // transparency information was transferred to the branch effect. + (child2.f & BRANCH_EFFECT) !== 0 && (effect2.f & BLOCK_EFFECT) !== 0; + pause_children(child2, transitions, transparent ? local : false); + child2 = sibling2; + } +} +function resume_effect(effect2) { + resume_children(effect2, true); +} +function resume_children(effect2, local) { + if ((effect2.f & INERT) === 0) return; + effect2.f ^= INERT; + if ((effect2.f & CLEAN) === 0) { + set_signal_status(effect2, DIRTY); + Batch.ensure().schedule(effect2); + } + var child2 = effect2.first; + while (child2 !== null) { + var sibling2 = child2.next; + var transparent = (child2.f & EFFECT_TRANSPARENT) !== 0 || (child2.f & BRANCH_EFFECT) !== 0; + resume_children(child2, transparent ? local : false); + child2 = sibling2; + } + var t = effect2.nodes && effect2.nodes.t; + if (t !== null) { + for (const transition of t) { + if (transition.is_global || local) { + transition.in(); + } + } + } +} +function move_effect(effect2, fragment) { + if (!effect2.nodes) return; + var node = effect2.nodes.start; + var end = effect2.nodes.end; + while (node !== null) { + var next2 = node === end ? null : /* @__PURE__ */ get_next_sibling(node); + fragment.append(node); + node = next2; + } +} +function store(defaultValue) { + const scope = { + get: (name) => { + return get$1(scope.store)[name]; + }, + set: (name, value) => { + if (typeof name === "string") { + Object.assign(get$1(scope.store), { + [name]: value + }); + } else { + Object.assign(get$1(scope.store), name); + } + scope.store.set(get$1(scope.store)); + }, + store: writable(defaultValue) + }; + return scope; +} +globalThis.$altcha = globalThis.$altcha || { + algorithms: /* @__PURE__ */ new Map(), + defaults: store({}), + i18n: store({}), + instances: /* @__PURE__ */ new Set(), + plugins: /* @__PURE__ */ new Set() +}; +const i18n = { + ariaLinkLabel: "Visit Altcha.org", + cancel: "Cancel", + enterCode: "Enter code", + enterCodeAria: "Enter code you hear. Press Space to play audio.", + enterCodeFromImage: "To proceed, please enter the code from the image below.", + error: "Verification failed. Try again later.", + expired: "Verification expired. Try again.", + footer: 'Protected by ALTCHA', + getAudioChallenge: "Get an audio challenge", + label: "I'm not a robot", + loading: "Loading...", + reload: "Reload", + verify: "Verify", + verificationRequired: "Verification required!", + verified: "Verified", + verifying: "Verifying...", + waitAlert: "Verifying... please wait." +}; +if ("$altcha" in globalThis) { + globalThis.$altcha.i18n.set("en", i18n); +} +const PUBLIC_VERSION = "5"; +if (typeof window !== "undefined") { + ((window.__svelte ??= {}).v ??= /* @__PURE__ */ new Set()).add(PUBLIC_VERSION); +} +var root$7 = /* @__PURE__ */ from_html(``); +function Checkbox($$anchor, $$props) { + push($$props, true); + let loading = prop($$props, "loading"), rest = /* @__PURE__ */ rest_props($$props, ["$$slots", "$$events", "$$legacy", "$$host", "loading"]); + var $$exports = { + get loading() { + return loading(); + }, + set loading($$value) { + loading($$value); + flushSync(); + } + }; + var label = root$7(); + var input = child(label); + attribute_effect(input, () => ({ type: "checkbox", ...rest }), void 0, void 0, void 0, void 0, true); + next(4); + reset(label); + template_effect(() => set_attribute(label, "data-loading", loading())); + append($$anchor, label); + return pop($$exports); +} +create_custom_element(Checkbox, { loading: {} }, [], [], { mode: "open" }); +var root$6 = /* @__PURE__ */ from_html(`
`); +function CheckboxNative($$anchor, $$props) { + push($$props, true); + let loading = prop($$props, "loading"), rest = /* @__PURE__ */ rest_props($$props, ["$$slots", "$$events", "$$legacy", "$$host", "loading"]); + var $$exports = { + get loading() { + return loading(); + }, + set loading($$value) { + loading($$value); + flushSync(); + } + }; + var div = root$6(); + var input = child(div); + attribute_effect(input, () => ({ type: "checkbox", ...rest }), void 0, void 0, void 0, void 0, true); + next(2); + reset(div); + template_effect(() => set_attribute(div, "data-loading", loading())); + append($$anchor, div); + return pop($$exports); +} +create_custom_element(CheckboxNative, { loading: {} }, [], [], { mode: "open" }); +var root$5 = /* @__PURE__ */ from_html(`
`); +function Logo($$anchor, $$props) { + push($$props, true); + let strings = prop($$props, "strings"); + const website = "https://altcha.org"; + var $$exports = { + get strings() { + return strings(); + }, + set strings($$value) { + strings($$value); + flushSync(); + } + }; + var div = root$5(); + var a = child(div); + set_attribute(a, "href", website); + reset(div); + template_effect(() => set_attribute(a, "aria-label", strings().ariaLinkLabel)); + append($$anchor, div); + return pop($$exports); +} +create_custom_element(Logo, { strings: {} }, [], [], { mode: "open" }); +var root$4 = /* @__PURE__ */ from_html(``); +function Footer($$anchor, $$props) { + push($$props, true); + let logo = prop($$props, "logo"), strings = prop($$props, "strings"); + var $$exports = { + get logo() { + return logo(); + }, + set logo($$value) { + logo($$value); + flushSync(); + }, + get strings() { + return strings(); + }, + set strings($$value) { + strings($$value); + flushSync(); + } + }; + var div = root$4(); + var div_1 = child(div); + html(div_1, () => strings().footer, true); + reset(div_1); + var node = sibling(div_1, 2); + { + var consequent = ($$anchor2) => { + Logo($$anchor2, { + get strings() { + return strings(); + } + }); + }; + if_block(node, ($$render) => { + if (logo()) $$render(consequent); + }); + } + reset(div); + append($$anchor, div); + return pop($$exports); +} +create_custom_element(Footer, { logo: {}, strings: {} }, [], [], { mode: "open" }); +var root$3 = /* @__PURE__ */ from_html(``); +function Switch($$anchor, $$props) { + push($$props, true); + let loading = prop($$props, "loading"), rest = /* @__PURE__ */ rest_props($$props, ["$$slots", "$$events", "$$legacy", "$$host", "loading"]); + var $$exports = { + get loading() { + return loading(); + }, + set loading($$value) { + loading($$value); + flushSync(); + } + }; + var label = root$3(); + var input = child(label); + attribute_effect(input, () => ({ type: "checkbox", ...rest }), void 0, void 0, void 0, void 0, true); + next(2); + reset(label); + template_effect(() => set_attribute(label, "data-loading", loading())); + append($$anchor, label); + return pop($$exports); +} +create_custom_element(Switch, { loading: {} }, [], [], { mode: "open" }); +var AudioState = /* @__PURE__ */ ((AudioState2) => { + AudioState2["ERROR"] = "error"; + AudioState2["LOADING"] = "loading"; + AudioState2["PLAYING"] = "playing"; + AudioState2["PAUSED"] = "paused"; + AudioState2["READY"] = "ready"; + return AudioState2; +})(AudioState || {}); +var State = /* @__PURE__ */ ((State2) => { + State2["CODE"] = "code"; + State2["ERROR"] = "error"; + State2["VERIFIED"] = "verified"; + State2["VERIFYING"] = "verifying"; + State2["UNVERIFIED"] = "unverified"; + State2["EXPIRED"] = "expired"; + return State2; +})(State || {}); +var root_1$2 = /* @__PURE__ */ from_html(`
`); +var root_3$2 = /* @__PURE__ */ from_html(`
`); +var root_4 = /* @__PURE__ */ from_svg(``); +var root_5 = /* @__PURE__ */ from_svg(``); +var root_6 = /* @__PURE__ */ from_svg(``); +var root_2$2 = /* @__PURE__ */ from_html(``); +var root_7 = /* @__PURE__ */ from_html(``); +var root$2 = /* @__PURE__ */ from_html(`
`); +function Code($$anchor, $$props) { + push($$props, true); + let audioUrl = prop($$props, "audioUrl"), codeChallenge = prop($$props, "codeChallenge"), config = prop($$props, "config"), imageUrl = prop($$props, "imageUrl"), onCancel = prop($$props, "onCancel"), onReload = prop($$props, "onReload"), onSubmit = prop($$props, "onSubmit"), strings = prop($$props, "strings"); + let audioState = /* @__PURE__ */ state(void 0); + let elAudio = /* @__PURE__ */ state(void 0); + let elInput = /* @__PURE__ */ state(void 0); + let loading = /* @__PURE__ */ state(false); + let code = /* @__PURE__ */ state(""); + let playAudio = /* @__PURE__ */ state(false); + onMount(() => { + if (!config().disableAutoFocus) { + tick().then(() => { + get(elInput)?.focus(); + }); + } + return () => { + if (get(elAudio)) { + get(elAudio).pause(); + set(elAudio, void 0); + } + }; + }); + function onAudioEnded() { + set(audioState, AudioState.PAUSED, true); + } + function onAudioError(ev) { + set(audioState, AudioState.ERROR, true); + } + function onAudioCanPlay() { + set(audioState, AudioState.READY, true); + } + function onAudioLoadStart() { + set(audioState, AudioState.LOADING, true); + } + function onAudioPlaying() { + set(audioState, AudioState.PLAYING, true); + } + function onAudioPause() { + set(audioState, AudioState.PAUSED, true); + } + function onInputKeyDown(ev) { + if (ev.code === "Space") { + ev.preventDefault(); + ev.stopPropagation(); + onPlayAudio(); + } else if (ev.code === "Escape") { + ev.preventDefault(); + ev.stopPropagation(); + onCancel()?.(); + } + } + function onSubmitCapture(ev) { + ev.preventDefault(); + ev.stopPropagation(); + onSubmit()?.(get(code)); + } + function onPlayAudio() { + if (get(elAudio)) { + if (get(audioState) === AudioState.LOADING) ; + else if (!get(elAudio).paused) { + get(elAudio).pause(); + } else { + if (audioUrl() && get(elAudio).src !== audioUrl()) { + get(elAudio).src = audioUrl(); + } + get(elAudio).currentTime = 0; + get(elAudio).play(); + } + } else { + set(playAudio, true); + requestAnimationFrame(() => { + if (get(elAudio) && audioUrl()) { + get(elAudio).src = audioUrl(); + get(elAudio).play(); + } + }); + } + } + var $$exports = { + get audioUrl() { + return audioUrl(); + }, + set audioUrl($$value) { + audioUrl($$value); + flushSync(); + }, + get codeChallenge() { + return codeChallenge(); + }, + set codeChallenge($$value) { + codeChallenge($$value); + flushSync(); + }, + get config() { + return config(); + }, + set config($$value) { + config($$value); + flushSync(); + }, + get imageUrl() { + return imageUrl(); + }, + set imageUrl($$value) { + imageUrl($$value); + flushSync(); + }, + get onCancel() { + return onCancel(); + }, + set onCancel($$value) { + onCancel($$value); + flushSync(); + }, + get onReload() { + return onReload(); + }, + set onReload($$value) { + onReload($$value); + flushSync(); + }, + get onSubmit() { + return onSubmit(); + }, + set onSubmit($$value) { + onSubmit($$value); + flushSync(); + }, + get strings() { + return strings(); + }, + set strings($$value) { + strings($$value); + flushSync(); + } + }; + var div = root$2(); + var form = child(div); + var node = child(form); + { + var consequent = ($$anchor2) => { + var div_1 = root_1$2(); + var text2 = child(div_1, true); + reset(div_1); + template_effect(() => set_text(text2, strings().verificationRequired)); + append($$anchor2, div_1); + }; + if_block(node, ($$render) => { + if (config().codeChallengeDisplay !== "standard") $$render(consequent); + }); + } + var div_2 = sibling(node, 2); + var text_1 = child(div_2, true); + reset(div_2); + var img = sibling(div_2, 2); + var div_3 = sibling(img, 2); + var input = child(div_3); + remove_input_defaults(input); + input.disabled = get(loading); + bind_this(input, ($$value) => set(elInput, $$value), () => get(elInput)); + var node_1 = sibling(input, 2); + { + var consequent_4 = ($$anchor2) => { + var button = root_2$2(); + var node_2 = child(button); + { + var consequent_1 = ($$anchor3) => { + var div_4 = root_3$2(); + append($$anchor3, div_4); + }; + var consequent_2 = ($$anchor3) => { + var svg = root_4(); + append($$anchor3, svg); + }; + var consequent_3 = ($$anchor3) => { + var svg_1 = root_5(); + append($$anchor3, svg_1); + }; + var alternate = ($$anchor3) => { + var svg_2 = root_6(); + append($$anchor3, svg_2); + }; + if_block(node_2, ($$render) => { + if (get(audioState) === AudioState.LOADING) $$render(consequent_1); + else if (get(audioState) === AudioState.ERROR) $$render(consequent_2, 1); + else if (get(audioState) === AudioState.PLAYING) $$render(consequent_3, 2); + else $$render(alternate, -1); + }); + } + reset(button); + template_effect(() => { + set_attribute(button, "title", strings().getAudioChallenge); + button.disabled = get(audioState) === AudioState.LOADING || get(audioState) === AudioState.ERROR; + set_attribute(button, "aria-label", get(audioState) === AudioState.LOADING ? strings().loading : strings().getAudioChallenge); + }); + delegated("click", button, () => onPlayAudio()); + append($$anchor2, button); + }; + if_block(node_1, ($$render) => { + if (codeChallenge().audio) $$render(consequent_4); + }); + } + var button_1 = sibling(node_1, 2); + reset(div_3); + var div_5 = sibling(div_3, 2); + var button_2 = child(div_5); + var text_2 = child(button_2, true); + reset(button_2); + var button_3 = sibling(button_2, 2); + var text_3 = child(button_3, true); + reset(button_3); + reset(div_5); + reset(form); + var node_3 = sibling(form, 2); + { + var consequent_5 = ($$anchor2) => { + var audio = root_7(); + bind_this(audio, ($$value) => set(elAudio, $$value), () => get(elAudio)); + event("error", audio, onAudioError); + event("loadstart", audio, onAudioLoadStart); + event("canplay", audio, onAudioCanPlay); + event("pause", audio, onAudioPause); + event("playing", audio, onAudioPlaying); + event("ended", audio, onAudioEnded); + append($$anchor2, audio); + }; + if_block(node_3, ($$render) => { + if (get(playAudio)) $$render(consequent_5); + }); + } + reset(div); + template_effect(() => { + set_text(text_1, strings().enterCodeFromImage); + set_attribute(img, "src", imageUrl()); + set_attribute(input, "minlength", codeChallenge().length || 1); + set_attribute(input, "maxlength", codeChallenge().length); + set_attribute(input, "placeholder", strings().enterCode); + set_attribute(input, "aria-label", get(audioState) === AudioState.LOADING ? strings().loading : get(audioState) === AudioState.PLAYING ? "" : strings().enterCodeAria); + set_attribute(input, "aria-live", get(audioState) ? "assertive" : "polite"); + set_attribute(input, "aria-busy", get(audioState) === AudioState.LOADING); + set_attribute(button_1, "title", strings().reload); + set_attribute(button_1, "aria-label", strings().reload); + set_attribute(button_2, "aria-label", strings().verify); + set_text(text_2, strings().verify); + set_attribute(button_3, "aria-label", strings().cancel); + set_text(text_3, strings().cancel); + }); + event("submit", form, onSubmitCapture, true); + delegated("keydown", input, onInputKeyDown); + bind_value(input, () => get(code), ($$value) => set(code, $$value)); + delegated("click", button_1, () => onReload()?.()); + delegated("click", button_3, () => onCancel()?.()); + append($$anchor, div); + return pop($$exports); +} +delegate(["keydown", "click"]); +create_custom_element( + Code, + { + audioUrl: {}, + codeChallenge: {}, + config: {}, + imageUrl: {}, + onCancel: {}, + onReload: {}, + onSubmit: {}, + strings: {} + }, + [], + [], + { mode: "open" } +); +var root_1$1 = /* @__PURE__ */ from_html(`
`); +var root_2$1 = /* @__PURE__ */ from_html(`
`); +var root_3$1 = /* @__PURE__ */ from_html(`
×
`); +var root$1 = /* @__PURE__ */ from_html(`
`, 1); +function Popover($$anchor, $$props) { + push($$props, true); + let anchor = prop($$props, "anchor"), children = prop($$props, "children"), display = prop($$props, "display", 7, "standard"), backdrop = prop($$props, "backdrop", 7, false), onClickOutside = prop($$props, "onClickOutside"), onClickOutsideDelay = prop($$props, "onClickOutsideDelay", 7, 600), onClose = prop($$props, "onClose"), placement = prop($$props, "placement", 7, "auto"), variant = prop($$props, "variant", 7, "neutral"), rest = /* @__PURE__ */ rest_props($$props, [ + "$$slots", + "$$events", + "$$legacy", + "$$host", + "anchor", + "children", + "display", + "backdrop", + "onClickOutside", + "onClickOutsideDelay", + "onClose", + "placement", + "variant" + ]); + let el = /* @__PURE__ */ state(void 0); + let elBackdrop = /* @__PURE__ */ state(void 0); + let top = /* @__PURE__ */ state(false); + let mountedAt = /* @__PURE__ */ state(0); + user_effect(() => { + if (placement() !== "auto") { + set(top, placement() === "top"); + } + }); + onMount(() => { + const moveToBody = display() === "bottomsheet" || display() === "overlay"; + if (moveToBody) { + get(elBackdrop) && document.body.append(get(elBackdrop)); + get(el) && document.body.append(get(el)); + } + reposition(); + tick().then(() => { + set(mountedAt, Date.now(), true); + }); + return () => { + if (moveToBody) { + get(elBackdrop) && document.body.removeChild(get(elBackdrop)); + get(el) && document.body.removeChild(get(el)); + } + }; + }); + function onCloseClick() { + onClose()?.(); + } + function onWindowClick(ev) { + const target = ev.target; + if (!get(el)?.contains(target) && get(mountedAt) && get(mountedAt) + onClickOutsideDelay() < Date.now()) { + onClickOutside()?.(); + } + } + function onWindowResize() { + reposition(); + } + function onWindowScroll() { + reposition(); + } + function reposition() { + if (anchor() && placement() === "auto" && get(el)) { + const boundary2 = anchor().getBoundingClientRect(); + const bottomGap = document.documentElement.clientHeight - (boundary2.top + boundary2.height); + const newTop = bottomGap < get(el).clientHeight; + if (get(top) !== newTop) { + set(top, newTop); + } + } + } + var $$exports = { + get anchor() { + return anchor(); + }, + set anchor($$value) { + anchor($$value); + flushSync(); + }, + get children() { + return children(); + }, + set children($$value) { + children($$value); + flushSync(); + }, + get display() { + return display(); + }, + set display($$value = "standard") { + display($$value); + flushSync(); + }, + get backdrop() { + return backdrop(); + }, + set backdrop($$value = false) { + backdrop($$value); + flushSync(); + }, + get onClickOutside() { + return onClickOutside(); + }, + set onClickOutside($$value) { + onClickOutside($$value); + flushSync(); + }, + get onClickOutsideDelay() { + return onClickOutsideDelay(); + }, + set onClickOutsideDelay($$value = 600) { + onClickOutsideDelay($$value); + flushSync(); + }, + get onClose() { + return onClose(); + }, + set onClose($$value) { + onClose($$value); + flushSync(); + }, + get placement() { + return placement(); + }, + set placement($$value = "auto") { + placement($$value); + flushSync(); + }, + get variant() { + return variant(); + }, + set variant($$value = "neutral") { + variant($$value); + flushSync(); + } + }; + var fragment = root$1(); + event("click", $window, onWindowClick); + event("resize", $window, onWindowResize); + event("scroll", $window, onWindowScroll); + var node = first_child(fragment); + { + var consequent = ($$anchor2) => { + var div = root_1$1(); + bind_this(div, ($$value) => set(elBackdrop, $$value), () => get(elBackdrop)); + append($$anchor2, div); + }; + if_block(node, ($$render) => { + if (backdrop()) $$render(consequent); + }); + } + var div_1 = sibling(node, 2); + attribute_effect(div_1, () => ({ + ...rest, + class: `altcha-popover ${($$props.class || "") ?? ""}`, + "data-popover": true, + "data-variant": variant(), + "data-top": get(top), + "data-display": display() + })); + var node_1 = child(div_1); + { + var consequent_1 = ($$anchor2) => { + var div_2 = root_2$1(); + append($$anchor2, div_2); + }; + if_block(node_1, ($$render) => { + if (display() === "standard") $$render(consequent_1); + }); + } + var node_2 = sibling(node_1, 2); + { + var consequent_2 = ($$anchor2) => { + var div_3 = root_3$1(); + delegated("click", div_3, onCloseClick); + append($$anchor2, div_3); + }; + if_block(node_2, ($$render) => { + if (display() !== "standard") $$render(consequent_2); + }); + } + var div_4 = sibling(node_2, 2); + var node_3 = child(div_4); + snippet(node_3, () => children() ?? noop); + reset(div_4); + reset(div_1); + bind_this(div_1, ($$value) => set(el, $$value), () => get(el)); + append($$anchor, fragment); + return pop($$exports); +} +delegate(["click"]); +create_custom_element( + Popover, + { + anchor: {}, + children: {}, + display: {}, + backdrop: {}, + onClickOutside: {}, + onClickOutsideDelay: {}, + onClose: {}, + placement: {}, + variant: {} + }, + [], + [], + { mode: "open" } +); +function bufferToHex(buffer) { + return Array.from(new Uint8Array(buffer)).map((b) => b.toString(16).padStart(2, "0")).join(""); +} +function injectCss(css2, id = "altcha-css") { + if (typeof document !== "undefined" && document && !document.getElementById(id)) { + const style = document.createElement("style"); + style.id = id; + style.textContent = css2; + document.head.appendChild(style); + } +} +async function solveChallengeWorkers(options) { + const { + challenge, + concurrency = navigator.hardwareConcurrency, + controller = new AbortController(), + createWorker, + onOutOfMemory = (c) => c > 1 ? Math.floor(c / 2) : 0, + counterMode, + timeout = 9e4 + } = options; + const workersConcurrency = Math.min(16, Math.max(1, concurrency)); + const workersInstances = []; + const terminate = () => { + for (const worker of workersInstances) { + worker.terminate(); + } + }; + for (let i = 0; i < workersConcurrency; i++) { + workersInstances.push(await createWorker(challenge.parameters.algorithm)); + } + let solution = null; + try { + solution = await Promise.race( + workersInstances.map((worker, i) => { + controller.signal.addEventListener("abort", () => { + worker.postMessage({ type: "abort" }); + }); + return new Promise((resolve, reject) => { + worker.addEventListener("error", (err) => { + reject(err); + }); + worker.addEventListener("message", (message) => { + if (message.data) { + for (const w of workersInstances) { + if (w !== worker) { + w.postMessage({ type: "abort" }); + } + } + if (message.data.error) { + return reject(new Error(message.data.error)); + } + } + resolve(message.data); + }); + worker.postMessage({ + challenge, + counterMode, + counterStart: i, + counterStep: workersConcurrency, + timeout, + type: "work" + }); + }); + }) + ); + } catch (err) { + const isOOM = err instanceof Error && !!err?.message?.includes("Out of memory"); + if (isOOM) { + if (onOutOfMemory) { + terminate(); + const retryConcurrency = onOutOfMemory(workersConcurrency); + if (retryConcurrency) { + return solveChallengeWorkers({ + ...options, + challenge, + controller, + concurrency: retryConcurrency, + createWorker + }); + } + } } - else - switch (l) { - case "Object": - case "Array": - return t && JSON.parse(t); - case "Boolean": - return t; - // conversion already handled above - case "Number": - return t != null ? +t : t; - default: - return t; + throw err; + } finally { + terminate(); + } + if (controller.signal.aborted) { + return null; + } + return solution || null; +} +class Collector { + TAG_CODES = { + INPUT: 1, + TEXTAREA: 2, + SELECT: 3, + BUTTON: 4, + A: 5, + DETAILS: 6, + SUMMARY: 7, + IFRAME: 8, + VIDEO: 9, + AUDIO: 10 + }; + maxSamples; + sampleInterval; + target; + focusStartTime = 0; + focusInteraction = 0; + focusInteractionTimer = null; + lastPointerSample = 0; + lastTouchSample = 0; + lastScrollSample = 0; + pendingPointer = null; + pendingTouch = null; + focus = []; + pointer = []; + scroll = []; + touch = []; + constructor(options = {}) { + const { maxSamples = 60, sampleInterval = 50, target = window } = options; + this.maxSamples = maxSamples; + this.sampleInterval = sampleInterval; + this.target = target; + this.attach(); + } + destroy() { + const o = { capture: true }; + this.target.removeEventListener("focusin", this.onFocus, o); + this.target.removeEventListener("keydown", this.onInteraction, o); + this.target.removeEventListener("pointerdown", this.onInteraction, o); + this.target.removeEventListener("pointermove", this.onPointer, o); + this.target.removeEventListener("scroll", this.onScroll, o); + this.target.removeEventListener("touchmove", this.onTouchMove, o); + } + export() { + return { + focus: this.focus, + maxTouchPoints: navigator.maxTouchPoints || 0, + pointer: this.pointer, + scroll: this.scroll, + time: Date.now(), + touch: this.touch + }; + } + attach() { + const o = { passive: true, capture: true }; + this.target.addEventListener("focusin", this.onFocus, o); + this.target.addEventListener("keydown", this.onInteraction, o); + this.target.addEventListener("pointerdown", this.onInteraction, o); + this.target.addEventListener("pointermove", this.onPointer, o); + this.target.addEventListener("scroll", this.onScroll, o); + this.target.addEventListener("touchmove", this.onTouchMove, o); + } + evict(buffer) { + if (buffer.length > this.maxSamples) { + buffer.splice(0, buffer.length - this.maxSamples); } -} -function Xa(e) { - const t = {}; - return e.childNodes.forEach((r) => { - t[ - /** @type {Element} node */ - r.slot || "default" - ] = !0; - }), t; -} -function Qa(e, t, r, o, l, a) { - let s = class extends Uo { - constructor() { - super(e, r, l), this.$$p_d = t; + } + onFocus = (e) => { + if (this.focusInteraction === 2) { + return; } - static get observedAttributes() { - return or(t).map( - (c) => (t[c].attribute || c).toLowerCase() - ); + const el = e.target; + if (!(el instanceof Element)) { + return; } + const now = performance.now(); + if (this.focusStartTime === 0) { + this.focusStartTime = now; + } + this.focus.push([ + Math.round(now - this.focusStartTime), + el.tabIndex, + this.TAG_CODES[el.tagName] ?? 0, + this.focusInteraction ? 1 : 0 + ]); + this.evict(this.focus); }; - return or(t).forEach((c) => { - Mt(s.prototype, c, { - get() { - return this.$$c && c in this.$$c ? this.$$c[c] : this.$$d[c]; - }, - set(f) { - f = nr(c, f, t), this.$$d[c] = f; - var d = this.$$c; - if (d) { - var m = rt(d, c)?.get; - m ? d[c] = f : d.$set({ [c]: f }); - } - } - }); - }), o.forEach((c) => { - Mt(s.prototype, c, { - get() { - return this.$$c?.[c]; - } - }); - }), e.element = /** @type {any} */ - s, s; -} -const jo = new TextEncoder(); -function el(e) { - return [...new Uint8Array(e)].map((t) => t.toString(16).padStart(2, "0")).join(""); -} -async function tl(e, t = "SHA-256", r = 1e5) { - const o = Date.now().toString(16); - e || (e = Math.round(Math.random() * r)); - const l = await qo(o, e, t); - return { - algorithm: t, - challenge: l, - salt: o, - signature: "" + onInteraction = (e) => { + this.focusInteraction = "keyCode" in e ? 1 : 2; + if (this.focusInteractionTimer) { + clearTimeout(this.focusInteractionTimer); + } + this.focusInteractionTimer = setTimeout(() => { + this.focusInteraction = 0; + }, 100); }; -} -async function qo(e, t, r) { - if (typeof crypto > "u" || !("subtle" in crypto) || !("digest" in crypto.subtle)) - throw new Error("Web Crypto is not available. Secure context is required (https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts)."); - return el( - await crypto.subtle.digest( - r.toUpperCase(), - jo.encode(e + t) - ) - ); -} -function rl(e, t, r = "SHA-256", o = 1e6, l = 0) { - const a = new AbortController(), s = Date.now(); - return { - promise: (async () => { - for (let f = l; f <= o; f += 1) { - if (a.signal.aborted) - return null; - if (await qo(t, f, r) === e) - return { - number: f, - took: Date.now() - s - }; - } - return null; - })(), - controller: a + onPointer = (e) => { + if (e.pointerType === "touch") { + return; + } + const now = e.timeStamp || performance.now(); + this.pendingPointer = [Math.round(e.clientX), Math.round(e.clientY), Math.round(now)]; + if (now - this.lastPointerSample >= this.sampleInterval) { + this.pointer.push(this.pendingPointer); + this.lastPointerSample = now; + this.pendingPointer = null; + this.evict(this.pointer); + } + }; + onScroll = () => { + const now = performance.now(); + if (now - this.lastScrollSample < this.sampleInterval) { + return; + } + this.scroll.push([Math.round(window.scrollY), Math.round(now)]); + this.lastScrollSample = now; + this.evict(this.scroll); + }; + onTouchMove = (e) => { + const now = e.timeStamp || performance.now(); + const t = e.touches[0]; + if (!t) { + return; + } + this.pendingTouch = [ + Math.round(t.clientX), + Math.round(t.clientY), + Math.round(now), + Math.round(t.force * 1e3) / 1e3, + Math.round(t.radiusX || 0), + Math.round(t.radiusY || 0) + ]; + if (now - this.lastTouchSample >= this.sampleInterval) { + this.touch.push(this.pendingTouch); + this.lastTouchSample = now; + this.pendingTouch = null; + this.evict(this.touch); + } }; } -function Wn() { - try { - return Intl.DateTimeFormat().resolvedOptions().timeZone; - } catch { +var root_1 = /* @__PURE__ */ from_html(`
`); +var root_3 = /* @__PURE__ */ from_html(`
`); +var root_2 = /* @__PURE__ */ from_html(`
×
`, 1); +var root_10 = /* @__PURE__ */ from_html(`
`); +var root_11 = /* @__PURE__ */ from_html(``); +var root_14 = /* @__PURE__ */ from_html(`
Secure context (HTTPS) required.
`); +var root_15 = /* @__PURE__ */ from_html(`
`); +var root_16 = /* @__PURE__ */ from_html(`
`); +var root_19 = /* @__PURE__ */ from_html(` `, 1); +var root = /* @__PURE__ */ from_html(`
`, 1); +function Widget($$anchor, $$props) { + push($$props, true); + const $altchaDefaults = () => store_get(altchaDefaults, "$altchaDefaults", $$stores); + const $altchaI18nStore = () => store_get(altchaI18nStore, "$altchaI18nStore", $$stores); + const [$$stores, $$cleanup] = setup_stores(); + const fieldsSelector = 'input[type="text"]:not([data-no-spamfilter]), textarea:not([data-no-spamfilter])'; + const submitButtonSelector = 'input[type="submit"], button[type="submit"], button:not([type="button"]):not([type="reset"])'; + const rtlLanguages = ["ar", "fa", "he", "ur"]; + const { isSecureContext } = globalThis; + const { store: altchaDefaults } = globalThis.$altcha.defaults; + const hardwareConcurrency = navigator.hardwareConcurrency || 2; + const deviceMemory = navigator.deviceMemory || 0; + const defaultWorkers = deviceMemory && deviceMemory <= 4 ? Math.min(4, hardwareConcurrency) : hardwareConcurrency; + const altchaI18nStore = globalThis.$altcha.i18n.store; + const instance = $$props.$$host; + const dispatch = (event2, detail) => { + tick().then(() => { + instance?.dispatchEvent(new CustomEvent(event2, { detail })); + }); + }; + let hisCollector = null; + let baseUrl = /* @__PURE__ */ state(proxy(new URL(location.origin))); + let checked = /* @__PURE__ */ state(false); + let codeChallenge = /* @__PURE__ */ state(null); + let currentController = /* @__PURE__ */ state(null); + let currentState = /* @__PURE__ */ state(proxy(State.UNVERIFIED)); + let elAnchorArrow = /* @__PURE__ */ state(void 0); + let elFloatingAnchor = /* @__PURE__ */ state(void 0); + let elForm = /* @__PURE__ */ state(null); + let elRoot = /* @__PURE__ */ state(void 0); + let elSubmitter = /* @__PURE__ */ state(null); + let error = /* @__PURE__ */ state(null); + let expirationTimeout = /* @__PURE__ */ state(null); + let payload = /* @__PURE__ */ state(null); + let plugins = /* @__PURE__ */ state(proxy([])); + let userConfig = /* @__PURE__ */ state(proxy({})); + let visible = /* @__PURE__ */ state(true); + const config = /* @__PURE__ */ user_derived(() => ({ + fetch: (input, init) => fetch(input, init), + audioChallengeLanguage: "", + auto: "off", + barPlacement: "bottom", + challenge: "", + codeChallenge: null, + codeChallengeDisplay: "standard", + credentials: null, + debug: false, + disableAutoFocus: false, + display: "standard", + floatingAnchor: "", + floatingOffset: 8, + floatingPersist: false, + floatingPlacement: "auto", + hideFooter: false, + hideLogo: false, + humanInteractionSignature: true, + language: "", + mockError: false, + minDuration: 500, + overlayContent: "", + name: "altcha", + popoverPlacement: "auto", + retryOnOutOfMemoryError: true, + setCookie: null, + serverVerificationFields: false, + serverVerificationTimeZone: false, + test: false, + timeout: 9e4, + type: "checkbox", + validationMessage: "", + verifyFunction: null, + verifyUrl: "", + workers: defaultWorkers, + ...$altchaDefaults(), + ...get(userConfig) + })); + const checkboxId = /* @__PURE__ */ user_derived(() => `altcha-checkbox-${$$props.id || Math.floor(Math.random() * 1e12).toString(16)}`); + const CheckboxComponent = /* @__PURE__ */ user_derived(() => getCheckboxComponent(get(config).type)); + const auto = /* @__PURE__ */ user_derived(() => get(config).auto); + const loading = /* @__PURE__ */ user_derived(() => get(currentState) === State.VERIFYING); + const showFooter = /* @__PURE__ */ user_derived(() => !get(config).hideFooter); + const showLogo = /* @__PURE__ */ user_derived(() => !get(config).hideLogo && get(config).display !== "bar"); + const locale = /* @__PURE__ */ user_derived(() => getI18nStrings($altchaI18nStore(), [ + get(config).language, + document.documentElement.lang, + ...navigator.languages + ])); + const dir = /* @__PURE__ */ user_derived(() => rtlLanguages.includes(get(locale).language) ? "rtl" : void 0); + const strings = /* @__PURE__ */ user_derived(() => ({ ...get(locale).strings })); + const codeChallengeAudioUrl = /* @__PURE__ */ user_derived(() => get(codeChallenge)?.audio?.match(/^(https?:)?\//) ? getUrl(get(codeChallenge).audio, get(baseUrl), { + language: get(config).audioChallengeLanguage || get(locale).language + }).toString() : get(codeChallenge)?.audio); + const codeChallengeImageUrl = /* @__PURE__ */ user_derived(() => get(codeChallenge)?.image?.match(/^(https?:)?\//) ? getUrl(get(codeChallenge).image, get(baseUrl)) : get(codeChallenge)?.image); + user_effect(() => { + configure({ + auto: $$props.auto, + challenge: $$props.challenge, + display: $$props.display, + language: $$props.language, + name: $$props.name, + type: $$props.type, + workers: $$props.workers + }); + }); + user_effect(() => { + if ($$props.configuration) { + try { + configure(JSON.parse($$props.configuration)); + } catch { + log("unable to parse the `configuration` attribute (JSON expected)"); + } + } + }); + user_effect(() => { + setDisplay(get(config).display); + }); + user_effect(() => { + if (get(checked) && get(currentState) === State.VERIFYING) { + set(checked, false); + } + }); + user_effect(() => { + if (!get(checked) && get(currentState) === State.VERIFIED) { + set(checked, true); + } + }); + user_effect(() => { + if (!get(checked)) { + const checkbox = getCheckboxElement(); + if (checkbox && checkbox.checked) { + checkbox.checked = false; + } + } + }); + user_effect(() => { + if (get(currentState) === State.VERIFIED) { + getCheckboxElement()?.setCustomValidity(""); + } + }); + user_effect(() => { + if (get(auto) === "onload") { + const tm = setTimeout( + () => { + verify(); + }, + 1 + ); + return () => { + if (tm) { + clearTimeout(tm); + } + }; + } + }); + user_effect(() => { + if (get(error)) { + log("error:", get(error)); + } + }); + user_effect(() => { + if (get(payload) && get(config).setCookie) { + setCookie(get(payload), get(config).setCookie); + } + }); + onMount(() => { + log("mounted", "3.0.2"); + if (instance) { + globalThis.$altcha.instances.add(instance); + } + set(elForm, get(elRoot)?.closest("form"), true); + get(elForm)?.addEventListener("reset", onFormReset); + get(elForm)?.addEventListener("submit", onFormSubmit, { capture: true }); + get(elForm)?.addEventListener("focusin", onFormFocusIn); + activatePlugins(); + if (get(config).humanInteractionSignature) { + log("human interaction signature enabled"); + hisCollector = new Collector(); + } + dispatch("load"); + if (!isSecureContext) { + log("secure context (HTTPS) required"); + } + return () => { + destroyPlugins(); + if (instance) { + globalThis.$altcha.instances.delete(instance); + } + if (get(expirationTimeout)) { + clearTimeout(get(expirationTimeout)); + } + get(elForm)?.removeEventListener("reset", onFormReset); + get(elForm)?.removeEventListener("submit", onFormSubmit, { capture: true }); + get(elForm)?.removeEventListener("focusin", onFormFocusIn); + hisCollector?.destroy(); + }; + }); + function activatePlugins() { + set(plugins, [...globalThis.$altcha.plugins].map((PluginCls) => new PluginCls(instance)), true); + log("activating plugins", get(plugins).map((plugin) => plugin.constructor.name)); + for (const plugin of get(plugins)) { + plugin.activate(); + } } -} -function nl(e) { - const t = atob(e), r = new Uint8Array(t.length); - for (let o = 0; o < t.length; o++) - r[o] = t.charCodeAt(o); - return r; -} -function ol(e, t = 12) { - const r = new Uint8Array(t); - for (let o = 0; o < t; o++) - r[o] = e % 256, e = Math.floor(e / 256); - return r; -} -async function il(e, t = "", r = 1e6, o = 0) { - const l = "AES-GCM", a = new AbortController(), s = Date.now(), c = async () => { - for (let m = o; m <= r; m += 1) { - if (a.signal.aborted || !f || !d) - return null; + async function callHook(hook, ...args) { + let result = void 0; + for (const plugin of get(plugins)) { + result = await plugin[hook].call(plugin, ...args); + } + return result; + } + function destroyPlugins() { + for (const plugin of get(plugins)) { + plugin.destroy(); + } + } + function createChallengeFromV1(challenge) { + const [_, queryParams] = challenge.salt.split("?"); + const data = {}; + if (queryParams) { try { - const v = await crypto.subtle.decrypt( - { - name: l, - iv: ol(m) - }, - f, - d - ); - if (v) - return { - clearText: new TextDecoder().decode(v), - took: Date.now() - s - }; + Object.assign(data, Object.fromEntries(new URLSearchParams(queryParams).entries())); } catch { } } - return null; - }; - let f = null, d = null; - try { - d = nl(e); - const m = await crypto.subtle.digest( - "SHA-256", - jo.encode(t) - ); - f = await crypto.subtle.importKey( - "raw", - m, - l, - !1, - ["decrypt"] - ); - } catch { + const result = { + codeChallenge: challenge.codeChallenge, + parameters: { + algorithm: challenge.algorithm, + cost: 1, + data, + expiresAt: data?.expires ? parseInt(data.expires, 10) : void 0, + keyLength: challenge.algorithm === "SHA-512" ? 64 : challenge.algorithm === "SHA-384" ? 48 : 32, + nonce: bufferToHex(new TextEncoder().encode(challenge.salt)), + keyPrefix: challenge.challenge, + salt: "" + }, + signature: challenge.signature + }; + Object.defineProperties(result, { + _originalSalt: { enumerable: false, value: challenge.salt, writable: false }, + _version: { enumerable: false, value: 1, writable: false } + }); + return result; + } + function createPayloadV1(challenge, solution) { return { - promise: Promise.reject(), - controller: a + algorithm: challenge.parameters.algorithm, + challenge: challenge.parameters.keyPrefix, + number: solution.counter, + salt: "_originalSalt" in challenge ? challenge._originalSalt : challenge.parameters.nonce, + signature: challenge.signature, + took: solution.time || 0 }; } - return { - promise: c(), - controller: a - }; -} -var y = /* @__PURE__ */ ((e) => (e.CODE = "code", e.ERROR = "error", e.VERIFIED = "verified", e.VERIFYING = "verifying", e.UNVERIFIED = "unverified", e.EXPIRED = "expired", e))(y || {}), Q = /* @__PURE__ */ ((e) => (e.ERROR = "error", e.LOADING = "loading", e.PLAYING = "playing", e.PAUSED = "paused", e.READY = "ready", e))(Q || {}); -globalThis.altchaPlugins = globalThis.altchaPlugins || []; -globalThis.altchaI18n = globalThis.altchaI18n || { - get: (e) => rr(globalThis.altchaI18n.store)[e], - set: (e, t) => { - Object.assign(rr(globalThis.altchaI18n.store), { - [e]: t - }), globalThis.altchaI18n.store.set(rr(globalThis.altchaI18n.store)); - }, - store: Wa({}) -}; -const al = { - ariaLinkLabel: "Visit Altcha.org", - enterCode: "Enter code", - enterCodeAria: "Enter code you hear. Press Space to play audio.", - error: "Verification failed. Try again later.", - expired: "Verification expired. Try again.", - footer: 'Protected by ALTCHA', - getAudioChallenge: "Get an audio challenge", - label: "I'm not a robot", - loading: "Loading...", - reload: "Reload", - verify: "Verify", - verificationRequired: "Verification required!", - verified: "Verified", - verifying: "Verifying...", - waitAlert: "Verifying... please wait." -}; -globalThis.altchaI18n.set("en", al); -const $r = (e, t) => { - let r = /* @__PURE__ */ ua(() => Yi(t?.(), 24)); - var o = cl(); - Ce(() => { - R(o, "width", i(r)), R(o, "height", i(r)); - }), B(e, o); -}; -function ll(e, t) { - e.code === "Space" && (e.preventDefault(), e.stopImmediatePropagation(), t()); -} -function sl(e, t) { - e.preventDefault(), t(); -} -function ul(e, t, r, o, l, a, s, c) { - [ - y.UNVERIFIED, - y.ERROR, - y.EXPIRED, - y.CODE - ].includes(i(t)) ? r() !== !1 && i(o)?.reportValidity() === !1 ? b(l, !1) : a() ? s() : c() : b(l, !0); -} -var cl = /* @__PURE__ */ _r(''), fl = /* @__PURE__ */ be(''), dl = /* @__PURE__ */ be('
'), hl = /* @__PURE__ */ _r(''), vl = /* @__PURE__ */ _r(''), gl = /* @__PURE__ */ _r(''), pl = /* @__PURE__ */ be(''), ml = /* @__PURE__ */ be(""), _l = /* @__PURE__ */ be(''), bl = /* @__PURE__ */ be("
"), yl = /* @__PURE__ */ be("
"), wl = /* @__PURE__ */ be('
'), El = /* @__PURE__ */ be(''), xl = /* @__PURE__ */ be('
'), Cl = /* @__PURE__ */ be('
', 1); -function kl(e, t) { - $o(t, !0); - const [r, o] = Za(), l = () => Ya(Wo, "$altchaI18nStore", r); - let a = x(t, "auto", 7, void 0), s = x(t, "blockspam", 7, void 0), c = x(t, "challengeurl", 7, void 0), f = x(t, "challengejson", 7, void 0), d = x(t, "credentials", 7, void 0), m = x(t, "customfetch", 7, void 0), v = x(t, "debug", 7, !1), _ = x(t, "delay", 7, 0), w = x(t, "disableautofocus", 7, !1), F = x(t, "refetchonexpire", 7, !0), M = x(t, "disablerefetchonexpire", 23, () => !F()), U = x(t, "expire", 7, void 0), I = x(t, "floating", 7, void 0), ee = x(t, "floatinganchor", 7, void 0), $e = x(t, "floatingoffset", 7, void 0), X = x(t, "floatingpersist", 7, !1), j = x(t, "hidefooter", 7, !1), se = x(t, "hidelogo", 7, !1), He = x(t, "id", 7, void 0), Ht = x(t, "language", 7, void 0), Ge = x(t, "name", 7, "altcha"), We = x(t, "maxnumber", 7, 1e6), xt = x(t, "mockerror", 7, !1), Ne = x(t, "obfuscated", 7, void 0), ge = x(t, "overlay", 7, void 0), Ct = x(t, "overlaycontent", 7, void 0), Gt = x(t, "plugins", 7, void 0), Ye = x(t, "sentinel", 7, void 0), ye = x(t, "spamfilter", 7, !1), st = x(t, "strings", 7, void 0), de = x(t, "test", 7, !1), te = x(t, "verifyurl", 7, void 0), ut = x(t, "workers", 23, () => Math.min(16, navigator.hardwareConcurrency || 8)), kt = x(t, "workerurl", 7, void 0); - const { altchaI18n: Go } = globalThis, Wo = Go.store, zr = ["SHA-256", "SHA-384", "SHA-512"], Yo = "https://altcha.org/", Le = (n, u) => { - t.$$host.dispatchEvent(new CustomEvent(n, { detail: u })); - }, Jr = document.documentElement.lang?.split("-")?.[0], br = /* @__PURE__ */ Lt(() => c() && new URL(c(), location.origin).host.endsWith(".altcha.org") && !!c()?.includes("apiKey=ckey_")), Wt = /* @__PURE__ */ Lt(() => f() ? fn(f()) : void 0), Zo = /* @__PURE__ */ Lt(() => st() ? fn(st()) : {}), L = /* @__PURE__ */ Lt(() => ({ - ...Qr(l()), - ...i(Zo) - })), Kr = /* @__PURE__ */ Lt(() => `${He() || Ge()}_checkbox_${Math.round(Math.random() * 1e8)}`); - let Ze = /* @__PURE__ */ N(null), At = /* @__PURE__ */ N(!1), G = /* @__PURE__ */ N(null), k = /* @__PURE__ */ N(Me(y.UNVERIFIED)), V = /* @__PURE__ */ N(void 0), It = /* @__PURE__ */ N(null), Pe = /* @__PURE__ */ N(null), ue = /* @__PURE__ */ N(null), yr = /* @__PURE__ */ N(null), ct = /* @__PURE__ */ N(null), T = /* @__PURE__ */ N(null), Rt = /* @__PURE__ */ N(null), ze = /* @__PURE__ */ N(null), we = null, W = /* @__PURE__ */ N(null), Je = /* @__PURE__ */ N(!1), Oe = [], wr = /* @__PURE__ */ N(!1), Ee = /* @__PURE__ */ N(null); - Dr(() => { - li(i(ze)); - }), Dr(() => { - si(i(k)); - }), Ga(() => { - zo(), b(Rt, null), i(T) && (i(T).removeEventListener("submit", an), i(T).removeEventListener("reset", ln), i(T).removeEventListener("focusin", on), b(T, null)), we && (clearTimeout(we), we = null), document.removeEventListener("click", rn), document.removeEventListener("scroll", nn), window.removeEventListener("resize", cn); - }), Mo(() => { - A("mounted", "2.2.4"), A("workers", ut()), Qo(), A("plugins", Oe.length ? Oe.map((n) => n.constructor.pluginName).join(", ") : "none"), de() && A("using test mode"), U() && xr(U()), a() !== void 0 && A("auto", a()), I() !== void 0 && gn(I()), b(T, i(V)?.closest("form"), !0), i(T) && (i(T).addEventListener("submit", an, { capture: !0 }), i(T).addEventListener("reset", ln), (a() === "onfocus" || X() === "focus") && i(T).addEventListener("focusin", on)), ge() && pn(!0), a() === "onload" && (Ne() ? $t() : Se()), i(br) && (j() || se()) && A("Attributes hidefooter and hidelogo ignored because usage with free API Keys requires attribution."), requestAnimationFrame(() => { - Le("load"); - }); - }); - function Yt(n, u) { - return btoa(JSON.stringify({ - algorithm: n.algorithm, - challenge: n.challenge, - number: u.number, - salt: n.salt, - signature: n.signature, - test: de() ? !0 : void 0, - took: u.took - })); - } - function zo() { - for (const n of Oe) - n.destroy(); - } - function Xr() { - c() && !M() && i(k) === y.VERIFIED ? Se() : Ke(y.EXPIRED, i(L).expired); - } - async function Jo() { - if (xt()) - throw A("mocking error"), new Error("Mocked error."); - if (i(Wt)) - return A("using provided json data"), dn(i(Wt).salt), i(Wt); - if (de()) - return A("generating test challenge", { test: de() }), tl(typeof de() != "boolean" ? +de() : void 0); - { - if (!c() && i(T)) { - const g = i(T).getAttribute("action"); - g?.includes("/form/") && c(g + "/altcha"); - } - if (!c()) - throw new Error("Attribute challengeurl not set."); - A("fetching challenge from", c()); - const n = { - credentials: typeof d() == "boolean" ? "include" : d(), - headers: ye() !== !1 ? { "x-altcha-spam-filter": "1" } : {} - }, u = await Er()(c(), n); - if (!u || !(u instanceof Response)) - throw new Error("Custom fetch function did not return a response."); - if (u.status !== 200) - throw new Error(`Server responded with ${u.status}.`); - const h = u.headers.get("X-Altcha-Config"), p = await u.json(); - if (dn(p.salt), h) + async function delay(ms) { + await new Promise((resolve) => setTimeout(resolve, ms)); + } + async function fetchChallenge(source2 = get(config).challenge, requestOptions) { + const hook = await callHook("onFetchChallenge", source2); + let challenge = null; + if (hook !== void 0) { + return hook; + } + if (typeof source2 === "string") { + if (source2.match(/^(https?:)?\//)) { + log("fetching challenge from", requestOptions?.method || "GET", source2); + set(baseUrl, new URL(source2, location.origin), true); + const resp = await get(config).fetch(source2, { + credentials: get(config).credentials || void 0, + ...requestOptions + }); + await validateResponse(resp); + const configHeader = resp.headers.get("x-altcha-config"); + if (configHeader) { + processConfigHeader(configHeader); + } + const json = await resp.json(); + if (json && "his" in json && json.his) { + log("requested HIS"); + if (!hisCollector) { + throw new Error("Server requested HIS data but collector is disabled."); + } + return fetchChallenge(getUrl(json.his.url, get(baseUrl)), { + body: JSON.stringify({ his: hisCollector.export() }), + headers: { "content-type": "application/json" }, + method: "POST" + }); + } + if (json && "hisResult" in json && json.hisResult) { + log("HIS result", json.hisResult); + } + challenge = json; + } else { + log("parsing JSON challenge"); try { - const g = JSON.parse(h); - g && typeof g == "object" && (g.verifyurl && !g.verifyurl.startsWith("fn:") && (g.verifyurl = tn(g.verifyurl)), bn(g)); - } catch (g) { - A("unable to configure from X-Altcha-Config", g); - } - return p; - } - } - function Ko(n) { - const u = i(T)?.querySelector(typeof n == "string" ? `input[name="${n}"]` : 'input[type="email"]:not([data-no-spamfilter])'); - return u?.value?.slice(u.value.indexOf("@")) || void 0; - } - function Er() { - let n = fetch; - if (m()) - if (A("using customfetch"), typeof m() == "string") { - if (n = globalThis[m()] || null, !n) - throw new Error(`Custom fetch function not found: ${m()}`); - } else - n = m(); - return n; - } - function Qr(n, u = [ - Ht() || "", - document.documentElement.lang || "", - ...navigator.languages - ]) { - const h = Object.keys(n).map((g) => g.toLowerCase()), p = u.reduce( - (g, C) => (C = C.toLowerCase(), g || (n[C] ? C : null) || h.find((D) => C.split("-")[0] === D.split("-")[0]) || null), + challenge = JSON.parse(source2); + } catch { + throw new Error(`Unable to parse JSON challenge.`); + } + } + } else if (source2 && typeof source2 === "object") { + try { + challenge = JSON.parse(JSON.stringify(source2)); + } catch { + throw new Error(`Unable to parse JSON challenge.`); + } + } + if (isChallengeV1(challenge)) { + challenge = createChallengeFromV1(challenge); + } + if (!isChallengeValid(challenge)) { + throw new Error(`Challenge validation failed.`); + } + return challenge; + } + function isChallengeV1(challenge) { + return typeof challenge === "object" && "challenge" in challenge; + } + function isChallengeValid(challenge) { + return !!challenge && typeof challenge === "object" && "parameters" in challenge && !!challenge.parameters && typeof challenge.parameters === "object" && "algorithm" in challenge.parameters && "nonce" in challenge.parameters && "salt" in challenge.parameters && "keyPrefix" in challenge.parameters; + } + function getCheckboxElement() { + return document.getElementById(get(checkboxId)); + } + function getCheckboxComponent(type) { + switch (type) { + case "checkbox": + return Checkbox; + case "switch": + return Switch; + case "native": + default: + return CheckboxNative; + } + } + function getI18nStrings(i18n2, languages) { + const codes = Object.keys(i18n2).map((code) => code.toLowerCase()); + let language = languages.reduce( + (acc, lang) => { + lang = lang.toLowerCase(); + return acc || (i18n2[lang] ? lang : null) || codes.find((code) => lang.split("-")[0] === code.split("-")[0]) || null; + }, null ); - return n[p || "en"]; - } - function Xo() { - return ye() === "ipAddress" ? { - blockedCountries: void 0, - classifier: void 0, - disableRules: void 0, - email: !1, - expectedCountries: void 0, - expectedLanguages: void 0, - fields: !1, - ipAddress: void 0, - text: void 0, - timeZone: void 0 - } : typeof ye() == "object" ? ye() : { - blockedCountries: void 0, - classifier: void 0, - disableRules: void 0, - email: void 0, - expectedCountries: void 0, - expectedLanguages: void 0, - fields: void 0, - ipAddress: void 0, - text: void 0, - timeZone: void 0 - }; + if (!i18n2[language || ""]) { + language = "en"; + } + return { language, strings: i18n2[language] }; } - function en(n) { - return [ - ...i(T)?.querySelectorAll(n?.length ? n.map((h) => `input[name="${h}"]`).join(", ") : 'input[type="text"]:not([data-no-spamfilter]), textarea:not([data-no-spamfilter])') || [] - ].reduce( - (h, p) => { - const g = p.name, C = p.value; - return g && C && (h[g] = /\n/.test(C) ? C.replace(new RegExp("(? { + const name = el.name; + const value = el.value; + if (name && value) { + acc[name] = /\n/.test(value) ? value.replace(new RegExp("(? u instanceof Error)) && console[n[0] instanceof Error ? "error" : "log"]("ALTCHA", `[name=${Ge()}]`, ...n); - } - function ei() { - b(W, Q.PAUSED, !0); - } - function ti(n) { - b(W, Q.ERROR, !0); - } - function ri() { - b(W, Q.READY, !0); - } - function ni() { - b(W, Q.LOADING, !0); - } - function oi() { - b(W, Q.PLAYING, !0); - } - function ii() { - b(W, Q.PAUSED, !0); - } - function ai(n) { - if (n.preventDefault(), n.stopPropagation(), i(G)) { - const u = new FormData(n.target), h = String(u.get("code")); - if (te()?.startsWith("fn:")) { - const p = te().replace(/^fn:/, ""); - if (A(`calling ${p} function instead of verifyurl`), !(p in globalThis)) - throw new Error(`Global function "${p}" is undefined.`); - return globalThis[p]({ - challenge: i(G).challenge, - code: h, - solution: i(G).solution - }); + function getTimeZone() { + try { + return Intl.DateTimeFormat().resolvedOptions().timeZone; + } catch { + } + return void 0; + } + function getUrl(uri, baseUrl2, params) { + const result = new URL(uri, baseUrl2); + if (!result.search) { + result.search = baseUrl2.search; + } + if (params) { + for (const key2 in params) { + if (params[key2] !== void 0 && params[key2] !== null) { + result.searchParams.set(key2, params[key2]); + } } - b(Je, !0), hn(Yt(i(G).challenge, i(G).solution), h).then(({ reason: p, verified: g }) => { - g ? (b(G, null), xe(y.VERIFIED), A("verified"), Rr().then(() => { - i(yr)?.focus(), Le("verified", { payload: i(Ee) }), a() === "onsubmit" ? vn(i(Rt)) : ge() && St(); - })) : (Ke(), b(ze, p || "Verification failed", !0)); - }).catch((p) => { - b(G, null), xe(y.ERROR, p), A("sentinel verification failed:", p); - }).finally(() => { - b(Je, !1); - }); } + return result.toString(); } - function rn(n) { - const u = n.target; - I() && u && !i(V).contains(u) && (i(k) === y.VERIFIED && X() === !1 || i(k) === y.VERIFIED && X() === "focus" && !i(T)?.matches(":focus-within") || a() === "off" && i(k) === y.UNVERIFIED) && St(); - } - function nn() { - I() && i(k) !== y.UNVERIFIED && Tt(); - } - function li(n) { - for (const u of Oe) - typeof u.onErrorChange == "function" && u.onErrorChange(i(ze)); - } - function on(n) { - i(k) === y.UNVERIFIED ? Se() : I() && X() === "focus" && i(k) === y.VERIFIED && Zt(); - } - function an(n) { - n.target?.hasAttribute("data-code-challenge-form") || (b(Rt, n.submitter, !0), i(T) && a() === "onsubmit" ? (i(Rt)?.blur(), i(k) === y.UNVERIFIED ? (n.preventDefault(), n.stopPropagation(), Se().then(() => { - vn(i(Rt)); - })) : i(k) !== y.VERIFIED && (n.preventDefault(), n.stopPropagation(), i(k) === y.VERIFYING && sn())) : i(T) && I() && a() === "off" && i(k) === y.UNVERIFIED && (n.preventDefault(), n.stopPropagation(), Zt())); - } - function ln() { - Ke(); - } - function sn() { - i(k) === y.VERIFYING && i(L).waitAlert && alert(i(L).waitAlert); - } - function un() { - i(Pe) ? i(Pe).paused ? (i(Pe).currentTime = 0, i(Pe).play()) : i(Pe).pause() : (b(wr, !0), requestAnimationFrame(() => { - i(Pe)?.play(); - })); - } - function si(n) { - for (const u of Oe) - typeof u.onStateChange == "function" && u.onStateChange(i(k)); - I() && i(k) !== y.UNVERIFIED && requestAnimationFrame(() => { - Tt(); - }), b(At, i(k) === y.VERIFIED), ge() && i(ue) && (i(k) !== y.UNVERIFIED ? Zt() : St()); - } - function cn() { - I() && Tt(); - } - function fn(n) { - return JSON.parse(n); - } - function dn(n) { - const u = new URLSearchParams(n.split("?")?.[1]), h = u.get("expires") || u.get("expire"); - if (h) { - const p = new Date(+h * 1e3), g = isNaN(p.getTime()) ? 0 : p.getTime() - Date.now(); - g > 0 && xr(g); - } else we && (clearTimeout(we), we = null); - } - async function ui(n) { - if (!te()) - throw new Error("Attribute verifyurl not set."); - A("requesting server verification from", te()); - const u = { payload: n }; - if (ye() !== !1) { - const { - blockedCountries: g, - classifier: C, - disableRules: D, - email: H, - expectedLanguages: q, - expectedCountries: oe, - fields: ie, - ipAddress: Qe, - text: dt, - timeZone: et - } = Xo(); - u.blockedCountries = g, u.classifier = C, u.disableRules = D, u.email = H === !1 ? void 0 : Ko(H), u.expectedCountries = oe, u.expectedLanguages = q || (Jr ? [Jr] : void 0), u.fields = ie === !1 ? void 0 : en(ie), u.ipAddress = Qe === !1 ? void 0 : Qe || "auto", u.text = dt, u.timeZone = et === !1 ? void 0 : et || Wn(); - } - const h = await Er()(te(), { - body: JSON.stringify(u), - headers: { "content-type": "application/json" }, - method: "POST" - }); - if (!h || !(h instanceof Response)) - throw new Error("Custom fetch function did not return a response."); - if (h.status !== 200) - throw new Error(`Server responded with ${h.status}.`); - const p = await h.json(); - if (p?.payload && b(Ee, p.payload, !0), Le("serververification", p), s() && p.classification === "BAD") - throw new Error("SpamFilter returned negative classification."); - } - async function hn(n, u) { - if (!te()) - throw new Error("Attribute verifyurl not set."); - A("requesting sentinel verification from", te()); - const h = { code: u, payload: n }; - Ye() && (h.fields = Ye().fields ? en() : void 0, h.timeZone = Ye().timeZone ? Wn() : void 0); - const p = await Er()(te(), { - body: JSON.stringify(h), - headers: { "content-type": "application/json" }, - method: "POST" - }); - if (!p || !(p instanceof Response)) - throw new Error("Fetch function did not return a response."); - if (p.status !== 200) - throw new Error(`Server responded with ${p.status}.`); - const g = await p.json(); - return g?.payload && b(Ee, g.payload, !0), Le("sentinelverification", g), g; - } - function vn(n) { - i(T) && "requestSubmit" in i(T) ? i(T).requestSubmit(n) : i(T)?.reportValidity() && (n ? n.click() : i(T).submit()); - } - function xr(n) { - A("expire", n), we && (clearTimeout(we), we = null), n < 1 ? Xr() : we = setTimeout(Xr, n); - } - function gn(n) { - A("floating", n), I() !== n && (i(V).style.left = "", i(V).style.top = ""), I(n === !0 || n === "" ? "auto" : n === !1 || n === "false" ? void 0 : I()), I() ? (a() || a("onsubmit"), document.addEventListener("scroll", nn), document.addEventListener("click", rn), window.addEventListener("resize", cn)) : a() === "onsubmit" && a(void 0); - } - function pn(n) { - if (A("overlay", n), ge(n), n) { - if (a() || a("onsubmit"), i(ue) && i(V).parentElement && i(ue).replaceWith(i(V).parentElement), i(V)?.parentElement?.parentElement) { - b(ue, document.createElement("div"), !0), i(V).parentElement.parentElement.appendChild(i(ue)); - const u = document.createElement("div"), h = document.createElement("button"); - h.type = "button", h.innerHTML = "×", h.addEventListener("click", (p) => { - p.preventDefault(), Ke(); - }), i(ue).classList.add("altcha-overlay-backdrop"), h.classList.add("altcha-overlay-close-button"), u.classList.add("altcha-overlay"), i(ue).append(u), u.append(h), Ct() && u.append(...document.querySelectorAll(Ct())), u.append(i(V).parentElement); - } - } else i(ue) && i(V).parentElement && (i(ue).replaceWith(i(V).parentElement), i(V).style.display = "block"); - } - function mn(n) { - if (!n.algorithm) - throw new Error("Invalid challenge. Property algorithm is missing."); - if (n.signature === void 0) - throw new Error("Invalid challenge. Property signature is missing."); - if (!zr.includes(n.algorithm.toUpperCase())) - throw new Error(`Unknown algorithm value. Allowed values: ${zr.join(", ")}`); - if (!n.challenge || n.challenge.length < 40) - throw new Error("Challenge is too short. Min. 40 chars."); - if (!n.salt || n.salt.length < 10) - throw new Error("Salt is too short. Min. 10 chars."); - } - async function _n(n) { - let u = null, h = null; - if ("Worker" in window) { - try { - u = ci(n, n.maxNumber || n.maxnumber || We()), b(Ze, u.controller, !0), h = await u.promise; - } catch (p) { - A(p); - } finally { - b(Ze, null); + function onCheckboxChange(ev) { + if (!get(checked) && ev.currentTarget.checked) { + ev.preventDefault(); + ev.currentTarget.checked = false; + if (get(currentState) !== State.VERIFYING) { + verify(); } - if (h === null || h?.number !== void 0 || "obfuscated" in n) - return { data: n, solution: h }; + } else if (!ev.currentTarget.checked) { + ev.preventDefault(); + reset$1(); } - if ("obfuscated" in n) { - const p = await il(n.obfuscated, n.key, n.maxNumber || n.maxnumber); - return { data: n, solution: await p.promise }; + } + function onCheckboxInvalid(ev) { + if (get(currentState) === State.VERIFYING) { + ev.currentTarget.setCustomValidity(get(strings).waitAlert); + } else if (get(config).validationMessage) { + ev.currentTarget.setCustomValidity(get(config).validationMessage); } - u = rl(n.challenge, n.salt, n.algorithm, n.maxNumber || n.maxnumber || We()), b(Ze, u.controller, !0); - try { - h = await u.promise; - } catch (p) { - A(p); - } finally { - b(Ze, null); - } - return { data: n, solution: h }; - } - function ci(n, u = typeof de() == "number" ? de() : n.maxNumber || n.maxnumber || We(), h = Math.ceil(ut())) { - const p = new AbortController(), g = []; - h = Math.min(16, u, Math.max(1, h)); - for (let H = 0; H < h; H++) - g.push(altchaCreateWorker(kt())); - const C = Math.ceil(u / h); - return { promise: (async () => { - const H = await Promise.all(g.map((q, oe) => { - const ie = oe * C; - return p.signal.addEventListener("abort", () => { - q.postMessage({ type: "abort" }); - }), new Promise((Qe) => { - q.addEventListener("message", (dt) => { - if (dt.data) - for (const et of g) - et !== q && et.postMessage({ type: "abort" }); - Qe(dt.data); - }), q.postMessage({ - payload: n, - max: ie + C, - start: ie, - type: "work" + } + function onCloseClick() { + if (get(currentController)) { + get(currentController).abort(); + } + setDisplay(get(config).display); + reset$1(); + } + function onDocumentScroll() { + updateUI(); + } + function onDocumentClick(ev) { + const target = ev.target; + if (get(config).display === "floating" && target && !instance?.contains(target) && !target.hasAttribute("data-backdrop") && !target.closest("[data-popover]") && get(currentState) !== State.VERIFIED && !get(config).floatingPersist) { + hide(); + } + } + function onFormFocusIn(ev) { + if (get(auto) === "onfocus" && get(currentState) === State.UNVERIFIED) { + verify(); + } + } + function onFormReset() { + if (get(currentController)) { + get(currentController).abort(); + } + setDisplay(get(config).display); + reset$1(); + } + function onFormSubmit(ev) { + set(elSubmitter, ev.submitter, true); + if (get(auto) === "onsubmit" && get(currentState) === State.UNVERIFIED) { + ev.preventDefault(); + ev.stopPropagation(); + show(); + verify().then((result) => { + if (result && !get(codeChallenge)) { + tick().then(() => { + requestSubmit(get(elSubmitter)); }); + } + }); + } + } + function onWindowPageshow() { + reset$1(); + } + function onWindowResize() { + updateUI(); + } + function processConfigHeader(jsonConfig) { + try { + const json = JSON.parse(jsonConfig); + if (json && typeof json === "object") { + configure({ + // Backward compatibility mappings + serverVerificationFields: json?.sentinel?.fields, + serverVerificationTimeZone: json?.sentinel?.timeZone, + verifyUrl: json.verifyurl, + ...json }); - })); - for (const q of g) - q.terminate(); - return H.find((q) => !!q) || null; - })(), controller: p }; - } - async function $t() { - if (!Ne()) { - xe(y.ERROR); - return; + } + } catch (err) { + log("unable to configure from x-altcha-config header", err); } - const n = Oe.find((u) => u.constructor.pluginName === "obfuscation"); - if (!n || !("clarify" in n)) { - xe(y.ERROR), A("Plugin `obfuscation` not found. Import `altcha/plugins/obfuscation` to load it."); + } + function repositionFloating(viewportOffset = 20) { + if (!get(elRoot)) { return; } - if ("clarify" in n && typeof n.clarify == "function") - return n.clarify(); + const floatingPlacement = get(config).floatingPlacement; + if (!get(elFloatingAnchor)) { + set( + elFloatingAnchor, + (get(config).floatingAnchor instanceof HTMLElement ? get(config).floatingAnchor : get(config).floatingAnchor ? document.querySelector(get(config).floatingAnchor) : get(elForm)?.querySelector(submitButtonSelector)) || get(elForm), + true + ); + if (!get(elFloatingAnchor)) { + log("unable to find floating anchor element"); + return; + } + } + const offsetY = parseInt(get(config).floatingOffset, 10) || 12; + const anchorBoundry = get(elFloatingAnchor).getBoundingClientRect(); + const elBoundary = get(elRoot).getBoundingClientRect(); + const docHeight = document.documentElement.clientHeight; + const docWidth = document.documentElement.clientWidth; + const showOnTop = !floatingPlacement || floatingPlacement === "auto" ? anchorBoundry.bottom + elBoundary.height + offsetY + viewportOffset > docHeight : floatingPlacement === "top"; + const left = Math.max(viewportOffset, Math.min(docWidth - viewportOffset - elBoundary.width, anchorBoundry.left + anchorBoundry.width / 2 - elBoundary.width / 2)); + get(elRoot).style.setProperty("--altcha-floating-left", `${left}px`); + get(elRoot).style.setProperty("--altcha-floating-top", showOnTop ? `${anchorBoundry.top - (elBoundary.height + offsetY)}px` : `${anchorBoundry.bottom + offsetY}px`); + get(elRoot).setAttribute("data-floating-position", showOnTop ? "top" : "bottom"); + if (get(elAnchorArrow)) { + const anchorArrowBoundry = get(elAnchorArrow).getBoundingClientRect(); + get(elAnchorArrow).style.left = anchorBoundry.left - left + anchorBoundry.width / 2 - anchorArrowBoundry.width / 2 + "px"; + } } - function bn(n) { - n.obfuscated !== void 0 && Ne(n.obfuscated), n.auto !== void 0 && (a(n.auto), a() === "onload" && (Ne() ? $t() : Se())), n.blockspam !== void 0 && s(!!n.blockspam), n.customfetch !== void 0 && m(n.customfetch), n.floatinganchor !== void 0 && ee(n.floatinganchor), n.delay !== void 0 && _(n.delay), n.floatingoffset !== void 0 && $e(n.floatingoffset), n.floating !== void 0 && gn(n.floating), n.expire !== void 0 && (xr(n.expire), U(n.expire)), n.challenge && (f(typeof n.challenge == "string" ? n.challenge : JSON.stringify(n.challenge)), mn(i(Wt))), n.challengeurl !== void 0 && c(n.challengeurl), n.debug !== void 0 && v(!!n.debug), n.hidefooter !== void 0 && j(!!n.hidefooter), n.hidelogo !== void 0 && se(!!n.hidelogo), n.language !== void 0 && st(Qr(l(), [n.language])), n.maxnumber !== void 0 && We(+n.maxnumber), n.mockerror !== void 0 && xt(!!n.mockerror), n.name !== void 0 && Ge(n.name), n.overlaycontent !== void 0 && Ct(n.overlaycontent), n.overlay !== void 0 && pn(n.overlay), n.refetchonexpire !== void 0 && M(!n.refetchonexpire), n.disablerefetchonexpire !== void 0 && M(!n.disablerefetchonexpire), n.sentinel !== void 0 && typeof n.sentinel == "object" && Ye(n.sentinel), n.spamfilter !== void 0 && ye(typeof n.spamfilter == "object" ? n.spamfilter : !!n.spamfilter), n.strings && st(typeof n.strings == "string" ? n.strings : JSON.stringify(n.strings)), n.test !== void 0 && de(typeof n.test == "number" ? n.test : !!n.test), n.verifyurl !== void 0 && te(n.verifyurl), n.workers !== void 0 && ut(+n.workers), n.workerurl !== void 0 && kt(n.workerurl); + async function requestServerVerification(verificationPayload, code) { + const hook = await callHook("onRequestServerVerification", verificationPayload, code); + if (hook !== void 0) { + return hook; + } + log("requesting server verification from", get(config).verifyUrl); + if (!get(config).verifyUrl) { + throw new Error(`Parameter verifyUrl must be set for server verification.`); + } + const resp = await get(config).fetch(getUrl(get(config).verifyUrl, get(baseUrl)), { + body: JSON.stringify({ + code, + fields: get(config).serverVerificationFields ? getTextFields() : void 0, + payload: verificationPayload, + timeZone: get(config).serverVerificationTimeZone ? getTimeZone() : void 0 + }), + credentials: get(config).credentials || void 0, + headers: { "Content-Type": "application/json" }, + method: "POST" + }); + await validateResponse(resp); + const json = await resp.json(); + if (json && typeof json === "object" && "payload" in json && !!json.payload) { + dispatch("serververification", json); + } + return json; } - function yn() { - return { - auto: a(), - blockspam: s(), - challengeurl: c(), - debug: v(), - delay: _(), - disableautofocus: w(), - disablerefetchonexpire: M(), - expire: U(), - floating: I(), - floatinganchor: ee(), - floatingoffset: $e(), - hidefooter: j(), - hidelogo: se(), - name: Ge(), - maxnumber: We(), - mockerror: xt(), - obfuscated: Ne(), - overlay: ge(), - refetchonexpire: !M(), - spamfilter: ye(), - strings: i(L), - test: de(), - verifyurl: te(), - workers: ut(), - workerurl: kt() + function requestSubmit(submitter) { + if (get(elForm) && "requestSubmit" in get(elForm)) { + get(elForm).requestSubmit(submitter); + } else if (get(elForm)?.reportValidity()) { + if (submitter) { + submitter.click(); + } else { + get(elForm).submit(); + } + } + } + function setCookie(value, options = {}) { + const { + domain, + name = get(config).name, + maxAge, + path, + sameSite, + secure + } = options; + let cookie = `${encodeURIComponent(name)}=${encodeURIComponent(value)}`; + if (domain) cookie += `; Domain=${domain}`; + if (maxAge != null) cookie += `; Max-Age=${maxAge}`; + if (path) cookie += `; Path=${path}`; + if (sameSite) cookie += `; SameSite=${sameSite}`; + if (secure) cookie += `; Secure`; + document.cookie = cookie; + } + function setDisplay(value) { + switch (value) { + case "bar": + case "floating": + case "overlay": + hide(); + if (!get(auto) || get(auto) === "off") { + get(userConfig).auto = "onsubmit"; + } + break; + case "standard": + show(); + } + } + function setChallengeExpiration(expiresAt) { + if (get(expirationTimeout)) { + clearTimeout(get(expirationTimeout)); + } + const onExpired = () => { + if (get(currentState) !== State.UNVERIFIED) { + set(checked, false); + setState(State.EXPIRED); + } else { + reset$1(); + } + dispatch("expired"); }; + const duration = expiresAt * 1e3 - Date.now(); + if (duration >= 1) { + set(expirationTimeout, setTimeout(onExpired, duration), true); + } else { + onExpired(); + } + } + async function validateResponse(resp) { + if (resp.status >= 400) { + if (resp.headers.get("content-type")?.includes("/json")) { + let json; + try { + json = await resp.json(); + } catch { + } + if (json && "error" in json) { + throw new Error(`Server responded with ${resp.status} - ${json.error}`); + } + } + throw new Error(`Server responded with ${resp.status}.`); + } + const contentType = resp.headers.get("content-type"); + if (!contentType || !contentType.includes("/json")) { + throw new Error(`Server responded with invalid content-type. Expected application/json, received ${contentType}.`); + } } - function wn() { - return i(ct); + async function verifyServer(code) { + if (!get(payload)) { + setState(State.ERROR, "Cannot verify code challenge without PoW payload."); + return; + } + setState(State.VERIFYING); + let result = null; + if (get(config).verifyUrl) { + result = await requestServerVerification(get(payload), code); + } else if (get(config).verifyFunction) { + result = await get(config).verifyFunction(get(payload), code); + } else { + setState(State.ERROR, "Parameter verifyUrl is required for code challenge verification."); + return; + } + if (result?.payload) { + set(payload, result.payload, true); + log("server payload", get(payload)); + } + if (result?.verified === true) { + log("verified"); + setState(State.VERIFIED); + dispatch("verified", { payload: get(payload) }); + if (get(auto) === "onsubmit") { + tick().then(() => { + requestSubmit(get(elSubmitter)); + }); + } + } else { + setState(State.ERROR, result?.reason || "Verification failed."); + } + if (!get(config).disableAutoFocus) { + getCheckboxElement()?.focus(); + } + } + function configure(newConfig) { + Object.assign(get(userConfig), { + ...Object.fromEntries(Object.entries(newConfig).filter(([_, value]) => value !== void 0)) + }); } - function fi(n) { - return Oe.find((u) => u.constructor.pluginName === n); + function getConfiguration() { + return { ...get(config) }; } - function En() { - return i(k); + function getState() { + return get(currentState); } - function St() { - i(V).style.display = "none", ge() && i(ue) && (i(ue).style.display = "none"); + function hide() { + set(visible, false); } - function Tt(n = 20) { - if (i(V)) - if (i(ct) || b(ct, (ee() ? document.querySelector(ee()) : i(T)?.querySelector('input[type="submit"], button[type="submit"], button:not([type="button"]):not([type="reset"])')) || i(T), !0), i(ct)) { - const u = parseInt($e(), 10) || 12, h = i(ct).getBoundingClientRect(), p = i(V).getBoundingClientRect(), g = document.documentElement.clientHeight, C = document.documentElement.clientWidth, D = I() === "auto" ? h.bottom + p.height + u + n > g : I() === "top", H = Math.max(n, Math.min(C - n - p.width, h.left + h.width / 2 - p.width / 2)); - if (D ? i(V).style.top = `${h.top - (p.height + u)}px` : i(V).style.top = `${h.bottom + u}px`, i(V).style.left = `${H}px`, i(V).setAttribute("data-floating", D ? "top" : "bottom"), i(It)) { - const q = i(It).getBoundingClientRect(); - i(It).style.left = h.left - H + h.width / 2 - q.width / 2 + "px"; - } - } else - A("unable to find floating anchor element"); + function log(...args) { + if (get(config).debug || args.some((a) => a instanceof Error)) { + console[args[0] instanceof Error ? "error" : "log"]("ALTCHA", `[name=${get(config).name}]`, ...args); + } } - function Ke(n = y.UNVERIFIED, u = null) { - i(Ze) && (i(Ze).abort(), b(Ze, null)), b(At, !1), b(Ee, null), b(G, null), b(wr, !1), b(W, null), xe(n, u); + function reset$1(newState = State.UNVERIFIED, err = null) { + set(checked, false); + set(error, err, true); + set(payload, null); + if (get(expirationTimeout)) { + clearTimeout(get(expirationTimeout)); + set(expirationTimeout, null); + } + setState(newState); } - function xn(n) { - b(ct, n, !0); + function setState(newState, err = null) { + set(currentState, newState, true); + set(error, err, true); + dispatch("statechange", { payload: get(payload), state: get(currentState) }); } - function xe(n, u = null) { - b(k, n, !0), b(ze, u, !0), Le("statechange", { - payload: i(Ee), - state: i(k) + function show() { + set(visible, true); + tick().then(() => { + updateUI(); }); } - function Zt() { - i(V).style.display = "block", I() && Tt(), ge() && i(ue) && (i(ue).style.display = "flex"); - } - async function Se() { - return Ke(y.VERIFYING), await new Promise((n) => setTimeout(n, _() || 0)), Jo().then((n) => (mn(n), A("challenge", n), _n(n))).then(({ data: n, solution: u }) => { - if (A("solution", u), !u || n && "challenge" in n && !("clearText" in u)) { - if (u?.number !== void 0 && "challenge" in n) - if (te() && "codeChallenge" in n) - ["INPUT", "BUTTON", "SELECT", "TEXTAREA"].includes(document.activeElement?.tagName || "") && w() === !1 && document.activeElement.blur(), b(G, { challenge: n, solution: u }, !0); - else { - if (te() && Ye() !== void 0) - return hn(Yt(n, u)); - if (te()) - return ui(Yt(n, u)); - b(Ee, Yt(n, u), !0), A("payload", i(Ee)); + function updateUI() { + switch (get(config).display) { + case "floating": + return repositionFloating(); + } + } + async function verify(options = {}) { + const { + concurrency = Math.max(1, get(config).workers), + controller = new AbortController(), + minDuration = get(config).minDuration + } = options; + const start = performance.now(); + let challenge = null; + let solution = null; + let isChallengeV12 = false; + const hook = await callHook("onVerify", options); + if (hook !== void 0) { + return hook; + } + set(currentController, controller, true); + reset$1(State.VERIFYING); + try { + if (!isSecureContext) { + throw new Error("Secure context (HTTPS) required."); + } + if (get(config).mockError) { + throw new Error("Mock error."); + } + if (get(config).test) { + log("running test mode with null challenge"); + await delay(Math.max(0, minDuration - (performance.now() - start))); + set(payload, btoa(JSON.stringify({ challenge: null, solution: null, test: true })), true); + log("verified"); + setState(State.VERIFIED); + dispatch("vefified", { payload: get(payload) }); + return { payload: get(payload) }; + } + challenge = await fetchChallenge(); + if (!challenge) { + throw new Error("Failed to fetch challenge."); + } + log("challenge", challenge); + if ("configuration" in challenge) { + log("re-configuring from challenge", challenge.configuration); + configure(challenge.configuration); + } + if (challenge.parameters.expiresAt) { + setChallengeExpiration(challenge.parameters.expiresAt); + } + isChallengeV12 = "_version" in challenge && challenge._version === 1; + const createWorker = globalThis.$altcha.algorithms.get(challenge.parameters.algorithm); + if (!createWorker) { + throw new Error(`Unsupported algorithm ${challenge.parameters.algorithm}.`); + } + solution = await solveChallengeWorkers({ + challenge, + concurrency, + controller, + createWorker, + counterMode: isChallengeV12 ? "string" : "uint32", + onOutOfMemory: (c) => { + log("out of memory error received"); + dispatch("outofmemory"); + if (get(config).retryOnOutOfMemoryError && c > 1) { + const retryConcurrency = Math.floor(c / 2); + log(`retrying with ${retryConcurrency} workers...`); + return retryConcurrency; } - else if (i(k) !== y.EXPIRED) - throw A("Unable to find a solution. Ensure that the 'maxnumber' attribute is greater than the randomly generated number."), new Error("Unexpected result returned."); - } - }).then(() => { - i(G) ? (xe(y.CODE), Rr().then(() => { - Le("code", { codeChallenge: i(G) }); - })) : i(Ee) && (xe(y.VERIFIED), A("verified"), Rr().then(() => { - Le("verified", { payload: i(Ee) }), ge() && St(); - })); - }).catch((n) => { - A(n), xe(y.ERROR, n.message); - }); + }, + timeout: get(config).timeout + }); + if (get(currentController)?.signal.aborted) { + reset$1(); + return null; + } + if (!solution) { + throw new Error("Failed to find solution."); + } + log("solution", solution); + await delay(Math.max(0, minDuration - (performance.now() - start))); + set(codeChallenge, challenge.codeChallenge || get(config).codeChallenge || null, true); + if (isChallengeV12) { + set(payload, btoa(JSON.stringify(createPayloadV1(challenge, solution))), true); + } else { + set( + payload, + btoa(JSON.stringify({ + challenge: { + parameters: challenge.parameters, + signature: challenge.signature + }, + solution + })), + true + ); + } + if (get(codeChallenge)) { + log("requesting code verification"); + setState(State.CODE); + dispatch("codechallenge", { codeChallenge: get(codeChallenge) }); + } else if (get(config).verifyUrl) { + await verifyServer(); + } else { + log("verified"); + setState(State.VERIFIED); + dispatch("vefified", { payload: get(payload) }); + } + } catch (err) { + log("verification failed", err); + setState(State.ERROR, String(err)); + return null; + } finally { + set(currentController, null); + } + return { challenge, payload: get(payload), solution }; } - var Cn = Cl(), kn = Nt(Cn); - Fa(kn, t, "default", {}); - var ft = J(kn, 2), Cr = z(ft), zt = z(Cr); - let An; - var In = z(zt); + var $$exports = { + configure, + getConfiguration, + getState, + hide, + log, + reset: reset$1, + setState, + show, + updateUI, + verify + }; + var fragment = root(); + event("scroll", $document, onDocumentScroll); + event("click", $document, onDocumentClick); + event("pageshow", $window, onWindowPageshow); + event("resize", $window, onWindowResize); + var node = first_child(fragment); { - var di = (n) => { - $r(n); + var consequent = ($$anchor2) => { + var div = root_1(); + append($$anchor2, div); }; - K(In, (n) => { - i(k) === y.VERIFYING && n(di); + if_block(node, ($$render) => { + if (get(config).display === "overlay" && get(visible)) $$render(consequent); }); } - var Xe = J(In, 2); - qn(Xe), Xe.__change = [ - ul, - k, - ye, - T, - At, - Ne, - $t, - Se - ], Qt(Xe, (n) => b(yr, n), () => i(yr)), Z(zt); - var Jt = J(zt, 2), hi = z(Jt); + var div_1 = sibling(node, 2); + var node_1 = child(div_1); { - var vi = (n) => { - var u = Xt(), h = Nt(u); - tt(h, () => i(L).verified), B(n, u); - }, gi = (n, u) => { + var consequent_2 = ($$anchor2) => { + var fragment_1 = root_2(); + var div_2 = first_child(fragment_1); + var node_2 = sibling(div_2, 2); { - var h = (g) => { - var C = Xt(), D = Nt(C); - tt(D, () => i(L).verifying), B(g, C); - }, p = (g, C) => { - { - var D = (q) => { - var oe = Xt(), ie = Nt(oe); - tt(ie, () => i(L).verificationRequired), B(q, oe); - }, H = (q) => { - var oe = Xt(), ie = Nt(oe); - tt(ie, () => i(L).label), B(q, oe); - }; - K( - g, - (q) => { - i(k) === y.CODE ? q(D) : q(H, !1); - }, - C - ); - } + var consequent_1 = ($$anchor3) => { + var div_3 = root_3(); + html(div_3, () => document.querySelector(get(config).overlayContent)?.innerHTML, true); + reset(div_3); + append($$anchor3, div_3); }; - K( - n, - (g) => { - i(k) === y.VERIFYING ? g(h) : g(p, !1); - }, - u - ); + if_block(node_2, ($$render) => { + if (get(config).overlayContent) $$render(consequent_1); + }); } + delegated("click", div_2, onCloseClick); + append($$anchor2, fragment_1); }; - K(hi, (n) => { - i(k) === y.VERIFIED ? n(vi) : n(gi, !1); + if_block(node_1, ($$render) => { + if (get(config).display === "overlay" && get(visible)) $$render(consequent_2); + }); + } + var div_4 = sibling(node_1, 2); + var div_5 = child(div_4); + var div_6 = child(div_5); + var node_3 = child(div_6); + { + let $0 = /* @__PURE__ */ user_derived(() => get(config).display === "standard" && get(auto) !== "onsubmit" || get(currentState) === State.VERIFYING); + component(node_3, () => get(CheckboxComponent), ($$anchor2, CheckboxComponent_1) => { + CheckboxComponent_1($$anchor2, { + get id() { + return get(checkboxId); + }, + name: "", + get required() { + return get($0); + }, + get loading() { + return get(loading); + }, + get checked() { + return get(checked); + }, + onchange: onCheckboxChange, + oninvalid: onCheckboxInvalid + }); }); } - Z(Jt); - var Rn = J(Jt, 2); + var label = sibling(node_3, 2); + var node_4 = child(label); { - var pi = (n) => { - var u = fl(); - qn(u), Ce(() => { - R(u, "name", Ge()), qa(u, i(Ee)); - }), B(n, u); + var consequent_3 = ($$anchor2) => { + var text$1 = text(); + template_effect(() => set_text(text$1, get(strings).verificationRequired)); + append($$anchor2, text$1); + }; + var consequent_4 = ($$anchor2) => { + var text_1 = text(); + template_effect(() => set_text(text_1, get(strings).verifying)); + append($$anchor2, text_1); + }; + var consequent_5 = ($$anchor2) => { + var text_2 = text(); + template_effect(() => set_text(text_2, get(strings).verified)); + append($$anchor2, text_2); + }; + var alternate = ($$anchor2) => { + var text_3 = text(); + template_effect(() => set_text(text_3, get(strings).label)); + append($$anchor2, text_3); }; - K(Rn, (n) => { - i(k) === y.VERIFIED && n(pi); + if_block(node_4, ($$render) => { + if (get(currentState) === State.CODE && get(codeChallenge)) $$render(consequent_3); + else if (get(currentState) === State.VERIFYING) $$render(consequent_4, 1); + else if (get(currentState) === State.VERIFIED) $$render(consequent_5, 2); + else $$render(alternate, -1); }); } - var $n = J(Rn, 2); + reset(label); + reset(div_6); + var node_5 = sibling(div_6, 2); { - var mi = (n) => { - var u = dl(), h = z(u); - R(h, "href", Yo), Z(u), Ce(() => R(h, "aria-label", i(L).ariaLinkLabel)), B(n, u); + var consequent_6 = ($$anchor2) => { + Logo($$anchor2, { + get strings() { + return get(strings); + } + }); }; - K($n, (n) => { - (se() !== !0 || i(br)) && n(mi); + if_block(node_5, ($$render) => { + if (get(showLogo)) $$render(consequent_6); }); } - var _i = J($n, 2); + reset(div_5); + var node_6 = sibling(div_5, 2); { - var bi = (n) => { - var u = _l(), h = J(z(u), 2), p = z(h), g = J(p, 2); - Sa(g, !w()), g.__keydown = [ - ll, - un - ]; - var C = J(g, 2), D = z(C), H = z(D); + var consequent_7 = ($$anchor2) => { { - var q = (pe) => { - var Y = pl(); - Y.__click = un; - var Kt = z(Y); - { - var Dt = (ht) => { - $r(ht, () => 20); - }, Ii = (ht, Ri) => { - { - var $i = (vt) => { - var kr = hl(); - B(vt, kr); - }, Si = (vt, kr) => { - { - var Ti = (gt) => { - var Ar = vl(); - B(gt, Ar); - }, Di = (gt) => { - var Ar = gl(); - B(gt, Ar); - }; - K( - vt, - (gt) => { - i(W) === Q.PLAYING ? gt(Ti) : gt(Di, !1); - }, - kr - ); - } - }; - K( - ht, - (vt) => { - i(W) === Q.ERROR ? vt($i) : vt(Si, !1); - }, - Ri - ); - } - }; - K(Kt, (ht) => { - i(W) === Q.LOADING ? ht(Dt) : ht(Ii, !1); - }); + let $0 = /* @__PURE__ */ user_derived(() => get(config).display === "bar" && get(showLogo)); + Footer($$anchor2, { + get logo() { + return get($0); + }, + get strings() { + return get(strings); } - Z(Y), Ce(() => { - R(Y, "title", i(L).getAudioChallenge), Y.disabled = i(W) === Q.LOADING || i(W) === Q.ERROR || i(Je), R(Y, "aria-label", i(W) === Q.LOADING ? i(L).loading : i(L).getAudioChallenge); - }), B(pe, Y); - }; - K(H, (pe) => { - i(G).challenge.codeChallenge.audio && pe(q); - }); - } - var oe = J(H, 2); - oe.__click = [sl, Se], Z(D); - var ie = J(D, 2), Qe = z(ie); - { - var dt = (pe) => { - $r(pe, () => 16); - }; - K(Qe, (pe) => { - i(Je) && pe(dt); - }); - } - var et = J(Qe); - Z(ie), Z(C); - var ki = J(C, 2); - { - var Ai = (pe) => { - var Y = ml(), Kt = z(Y); - Z(Y), Qt(Y, (Dt) => b(Pe, Dt), () => i(Pe)), Ce((Dt) => R(Kt, "src", Dt), [ - () => tn(i(G).challenge.codeChallenge.audio, { language: Ht() }) - ]), Fe("loadstart", Y, ni), Fe("canplay", Y, ri), Fe("pause", Y, ii), Fe("playing", Y, oi), Fe("ended", Y, ei), Fe("error", Kt, ti), B(pe, Y); - }; - K(ki, (pe) => { - i(G).challenge.codeChallenge.audio && i(wr) && pe(Ai); }); } - Z(h), Z(u), Ce(() => { - R(u, "aria-label", i(L).verificationRequired), R(p, "src", i(G).challenge.codeChallenge.image), R(g, "minlength", i(G).challenge.codeChallenge.length || 1), R(g, "maxlength", i(G).challenge.codeChallenge.length), R(g, "placeholder", i(L).enterCode), R(g, "aria-label", i(W) === Q.LOADING ? i(L).loading : i(W) === Q.PLAYING ? "" : i(L).enterCodeAria), R(g, "aria-live", i(W) ? "assertive" : "polite"), R(g, "aria-busy", i(W) === Q.LOADING), g.disabled = i(Je), R(oe, "aria-label", i(L).reload), R(oe, "title", i(L).reload), oe.disabled = i(Je), ie.disabled = i(Je), R(ie, "aria-label", i(L).verify), La(et, ` ${i(L).verify ?? ""}`); - }), Fe("submit", h, ai, !0), B(n, u); }; - K(_i, (n) => { - i(G)?.challenge.codeChallenge && n(bi); + if_block(node_6, ($$render) => { + if (get(showFooter)) $$render(consequent_7); }); } - Z(Cr); - var Sn = J(Cr, 2); + var node_7 = sibling(node_6, 2); { - var yi = (n) => { - var u = wl(), h = J(z(u), 2); - { - var p = (C) => { - var D = bl(), H = z(D); - tt(H, () => i(L).expired), Z(D), Ce(() => R(D, "title", i(ze))), B(C, D); - }, g = (C) => { - var D = yl(), H = z(D); - tt(H, () => i(L).error), Z(D), Ce(() => R(D, "title", i(ze))), B(C, D); - }; - K(h, (C) => { - i(k) === y.EXPIRED ? C(p) : C(g, !1); - }); - } - Z(u), B(n, u); + var consequent_8 = ($$anchor2) => { + var div_7 = root_10(); + bind_this(div_7, ($$value) => set(elAnchorArrow, $$value), () => get(elAnchorArrow)); + append($$anchor2, div_7); }; - K(Sn, (n) => { - (i(ze) || i(k) === y.EXPIRED) && n(yi); + if_block(node_7, ($$render) => { + if (get(config).display === "floating") $$render(consequent_8); }); } - var Tn = J(Sn, 2); + var node_8 = sibling(node_7, 2); { - var wi = (n) => { - var u = El(), h = z(u), p = z(h); - tt(p, () => i(L).footer), Z(h), Z(u), B(n, u); + var consequent_9 = ($$anchor2) => { + var input_1 = root_11(); + remove_input_defaults(input_1); + template_effect(() => { + set_attribute(input_1, "name", get(config).name); + set_value(input_1, get(payload)); + }); + append($$anchor2, input_1); }; - K(Tn, (n) => { - i(L).footer && (j() !== !0 || i(br)) && n(wi); + if_block(node_8, ($$render) => { + if (!get(config).setCookie) $$render(consequent_9); }); } - var Ei = J(Tn, 2); + reset(div_4); + var node_9 = sibling(div_4, 2); { - var xi = (n) => { - var u = xl(); - Qt(u, (h) => b(It, h), () => i(It)), B(n, u); + var consequent_12 = ($$anchor2) => { + Popover($$anchor2, { + get anchor() { + return get(elRoot); + }, + onClickOutside: () => { + if (isSecureContext) { + reset$1(); + } + }, + get placement() { + return get(config).popoverPlacement; + }, + role: "alert", + variant: "error", + get dir() { + return get(dir); + }, + children: ($$anchor3, $$slotProps) => { + var fragment_9 = comment(); + var node_10 = first_child(fragment_9); + { + var consequent_10 = ($$anchor4) => { + var div_8 = root_14(); + append($$anchor4, div_8); + }; + var consequent_11 = ($$anchor4) => { + var div_9 = root_15(); + var text_4 = child(div_9, true); + reset(div_9); + template_effect(() => set_text(text_4, get(strings).expired)); + append($$anchor4, div_9); + }; + var alternate_1 = ($$anchor4) => { + var div_10 = root_16(); + var text_5 = child(div_10, true); + reset(div_10); + template_effect(() => { + set_attribute(div_10, "title", get(error)); + set_text(text_5, get(strings).error); + }); + append($$anchor4, div_10); + }; + if_block(node_10, ($$render) => { + if (!get(error) && !isSecureContext) $$render(consequent_10); + else if (!get(error) && get(currentState) === State.EXPIRED) $$render(consequent_11, 1); + else $$render(alternate_1, -1); + }); + } + append($$anchor3, fragment_9); + }, + $$slots: { default: true } + }); + }; + var consequent_14 = ($$anchor2) => { + var fragment_10 = comment(); + var node_11 = first_child(fragment_10); + key(node_11, () => get(codeChallenge), ($$anchor3) => { + { + let $0 = /* @__PURE__ */ user_derived(() => get(config).codeChallengeDisplay !== "standard"); + Popover($$anchor3, { + get anchor() { + return get(elRoot); + }, + get backdrop() { + return get($0); + }, + get display() { + return get(config).codeChallengeDisplay; + }, + onClose: () => { + reset$1(); + }, + get placement() { + return get(config).popoverPlacement; + }, + role: "dialog", + get "aria-label"() { + return get(strings).verificationRequired; + }, + get dir() { + return get(dir); + }, + children: ($$anchor4, $$slotProps) => { + var fragment_12 = root_19(); + var node_12 = first_child(fragment_12); + Code(node_12, { + get audioUrl() { + return get(codeChallengeAudioUrl); + }, + get imageUrl() { + return get(codeChallengeImageUrl); + }, + onCancel: () => reset$1(), + onReload: () => verify(), + onSubmit: (code) => verifyServer(code), + get codeChallenge() { + return get(codeChallenge); + }, + get config() { + return get(config); + }, + get strings() { + return get(strings); + } + }); + var node_13 = sibling(node_12, 2); + { + var consequent_13 = ($$anchor5) => { + Footer($$anchor5, { + get logo() { + return get(showLogo); + }, + get strings() { + return get(strings); + } + }); + }; + if_block(node_13, ($$render) => { + if (get(showFooter) && get(config).codeChallengeDisplay !== "standard") $$render(consequent_13); + }); + } + append($$anchor4, fragment_12); + }, + $$slots: { default: true } + }); + } + }); + append($$anchor2, fragment_10); }; - K(Ei, (n) => { - I() && n(xi); + if_block(node_9, ($$render) => { + if (get(error) || get(currentState) === State.EXPIRED || !isSecureContext) $$render(consequent_12); + else if (get(codeChallenge) && get(currentState) === State.CODE) $$render(consequent_14, 1); }); } - Z(ft), Qt(ft, (n) => b(V, n), () => i(V)), Ce( - (n) => { - R(ft, "data-state", i(k)), R(ft, "data-floating", I()), R(ft, "data-overlay", ge()), An = Va(zt, 1, "altcha-checkbox", null, An, n), R(Xe, "id", i(Kr)), Xe.required = a() !== "onsubmit" && (!I() || a() !== "off"), R(Jt, "for", i(Kr)); - }, - [ - () => ({ - "altcha-checkbox-verifying": i(k) === y.VERIFYING - }) - ] - ), Fe("invalid", Xe, sn), Ha(Xe, () => i(At), (n) => b(At, n)), B(e, Cn); - var Ci = So({ - clarify: $t, - configure: bn, - getConfiguration: yn, - getFloatingAnchor: wn, - getPlugin: fi, - getState: En, - hide: St, - repositionFloating: Tt, - reset: Ke, - setFloatingAnchor: xn, - setState: xe, - show: Zt, - verify: Se, - get auto() { - return a(); - }, - set auto(n = void 0) { - a(n), E(); - }, - get blockspam() { - return s(); - }, - set blockspam(n = void 0) { - s(n), E(); - }, - get challengeurl() { - return c(); - }, - set challengeurl(n = void 0) { - c(n), E(); - }, - get challengejson() { - return f(); - }, - set challengejson(n = void 0) { - f(n), E(); - }, - get credentials() { - return d(); - }, - set credentials(n = void 0) { - d(n), E(); - }, - get customfetch() { - return m(); - }, - set customfetch(n = void 0) { - m(n), E(); - }, - get debug() { - return v(); - }, - set debug(n = !1) { - v(n), E(); - }, - get delay() { - return _(); - }, - set delay(n = 0) { - _(n), E(); - }, - get disableautofocus() { - return w(); - }, - set disableautofocus(n = !1) { - w(n), E(); - }, - get refetchonexpire() { - return F(); - }, - set refetchonexpire(n = !0) { - F(n), E(); - }, - get disablerefetchonexpire() { - return M(); - }, - set disablerefetchonexpire(n = !F) { - M(n), E(); - }, - get expire() { - return U(); - }, - set expire(n = void 0) { - U(n), E(); - }, - get floating() { - return I(); - }, - set floating(n = void 0) { - I(n), E(); - }, - get floatinganchor() { - return ee(); - }, - set floatinganchor(n = void 0) { - ee(n), E(); - }, - get floatingoffset() { - return $e(); - }, - set floatingoffset(n = void 0) { - $e(n), E(); - }, - get floatingpersist() { - return X(); - }, - set floatingpersist(n = !1) { - X(n), E(); - }, - get hidefooter() { - return j(); - }, - set hidefooter(n = !1) { - j(n), E(); - }, - get hidelogo() { - return se(); - }, - set hidelogo(n = !1) { - se(n), E(); - }, - get id() { - return He(); - }, - set id(n = void 0) { - He(n), E(); - }, - get language() { - return Ht(); - }, - set language(n = void 0) { - Ht(n), E(); - }, - get name() { - return Ge(); - }, - set name(n = "altcha") { - Ge(n), E(); - }, - get maxnumber() { - return We(); - }, - set maxnumber(n = 1e6) { - We(n), E(); + reset(div_1); + bind_this(div_1, ($$value) => set(elRoot, $$value), () => get(elRoot)); + template_effect( + ($0) => { + set_attribute(div_1, "data-state", get(currentState)); + set_attribute(div_1, "data-display", get(config).display || void 0); + set_attribute(div_1, "data-placement", $0); + set_attribute(div_1, "data-visible", get(visible) || void 0); + set_attribute(div_1, "dir", get(dir)); + set_attribute(label, "for", get(checkboxId)); + div_1.dir = div_1.dir; }, - get mockerror() { - return xt(); - }, - set mockerror(n = !1) { - xt(n), E(); - }, - get obfuscated() { - return Ne(); - }, - set obfuscated(n = void 0) { - Ne(n), E(); - }, - get overlay() { - return ge(); - }, - set overlay(n = void 0) { - ge(n), E(); - }, - get overlaycontent() { - return Ct(); - }, - set overlaycontent(n = void 0) { - Ct(n), E(); - }, - get plugins() { - return Gt(); - }, - set plugins(n = void 0) { - Gt(n), E(); - }, - get sentinel() { - return Ye(); - }, - set sentinel(n = void 0) { - Ye(n), E(); - }, - get spamfilter() { - return ye(); - }, - set spamfilter(n = !1) { - ye(n), E(); - }, - get strings() { - return st(); - }, - set strings(n = void 0) { - st(n), E(); - }, - get test() { - return de(); - }, - set test(n = !1) { - de(n), E(); - }, - get verifyurl() { - return te(); - }, - set verifyurl(n = void 0) { - te(n), E(); - }, - get workers() { - return ut(); - }, - set workers(n = Math.min(16, navigator.hardwareConcurrency || 8)) { - ut(n), E(); - }, - get workerurl() { - return kt(); - }, - set workerurl(n = void 0) { - kt(n), E(); - } - }); - return o(), Ci; -} -Na(["change", "keydown", "click"]); -customElements.define("altcha-widget", Qa( - kl, + [() => getPlacement(get(config).display)] + ); + append($$anchor, fragment); + var $$pop = pop($$exports); + $$cleanup(); + return $$pop; +} +delegate(["click"]); +if (typeof window !== "undefined" && window.customElements) customElements.define("altcha-widget", create_custom_element( + Widget, { - blockspam: { type: "Boolean" }, - debug: { type: "Boolean" }, - delay: { type: "Number" }, - disableautofocus: { type: "Boolean" }, - disablerefetchonexpire: { type: "Boolean" }, - expire: { type: "Number" }, - floatingoffset: { type: "Number" }, - hidefooter: { type: "Boolean" }, - hidelogo: { type: "Boolean" }, - maxnumber: { type: "Number" }, - mockerror: { type: "Boolean" }, - refetchonexpire: { type: "Boolean" }, - test: { type: "Boolean" }, - workers: { type: "Number" }, - auto: {}, - challengeurl: {}, - challengejson: {}, - credentials: {}, - customfetch: {}, - floating: {}, - floatinganchor: {}, - floatingpersist: {}, - id: {}, - language: {}, - name: {}, - obfuscated: {}, - overlay: {}, - overlaycontent: {}, - plugins: {}, - sentinel: {}, - spamfilter: {}, - strings: {}, - verifyurl: {}, - workerurl: {} + auto: { type: "String" }, + challenge: { type: "String" }, + configuration: { type: "String" }, + display: { type: "String" }, + language: { type: "String" }, + name: { type: "String" }, + theme: { type: "String" }, + type: { type: "String" }, + workers: { type: "Number" } }, - ["default"], + [], [ - "clarify", "configure", "getConfiguration", - "getFloatingAnchor", - "getPlugin", "getState", "hide", - "repositionFloating", + "log", "reset", - "setFloatingAnchor", "setState", "show", + "updateUI", "verify" - ], - !1 + ] )); -const Bo = '@keyframes overlay-slidein{to{opacity:1;top:50%}}@keyframes altcha-spinner{to{transform:rotate(360deg)}}.altcha{background:var(--altcha-color-base, transparent);border:var(--altcha-border-width, 1px) solid var(--altcha-color-border, #a0a0a0);border-radius:var(--altcha-border-radius, 3px);color:var(--altcha-color-text, currentColor);display:flex;flex-direction:column;max-width:var(--altcha-max-width, 260px);position:relative}.altcha:focus-within{border-color:var(--altcha-color-border-focus, currentColor)}.altcha[data-floating]{background:var(--altcha-color-base, white);display:none;filter:drop-shadow(3px 3px 6px rgba(0,0,0,.2));left:-100%;position:fixed;top:-100%;width:var(--altcha-max-width, 260px);z-index:999999}.altcha[data-floating=top] .altcha-anchor-arrow{border-bottom-color:transparent;border-top-color:var(--altcha-color-border, #a0a0a0);bottom:-12px;top:auto}.altcha[data-floating=bottom]:focus-within::after{border-bottom-color:var(--altcha-color-border-focus, currentColor)}.altcha[data-floating=top]:focus-within::after{border-top-color:var(--altcha-color-border-focus, currentColor)}.altcha[data-floating]:not([data-state=unverified]){display:block}.altcha-anchor-arrow{border:6px solid transparent;border-bottom-color:var(--altcha-color-border, #a0a0a0);content:"";height:0;left:12px;position:absolute;top:-12px;width:0}.altcha-main{align-items:center;display:flex;gap:.4rem;padding:.7rem;position:relative}.altcha-code-challenge{background:var(--altcha-color-base, white);border:1px solid var(--altcha-color-border-focus, currentColor);border-radius:var(--altcha-border-radius, 3px);filter:drop-shadow(3px 3px 6px rgba(0,0,0,.2));padding:.5rem;position:absolute;top:2.5rem;z-index:9999999}.altcha-code-challenge>form{display:flex;flex-direction:column;gap:.5rem}.altcha-code-challenge-input{border:1px solid currentColor;border-radius:3px;box-sizing:border-box;outline:0;font-size:16px;padding:.35rem;width:220px}.altcha-code-challenge-input:focus{outline:2px solid color-mix(in srgb,var(--altcha-color-active, #1D1DC9) 20%,transparent)}.altcha-code-challenge-input:disabled{opacity:.7}.altcha-code-challenge-image{background-color:#fff;border:1px solid currentColor;border-radius:3px;box-sizing:border-box;object-fit:contain;height:50px;width:220px}.altcha-code-challenge-audio,.altcha-code-challenge-reload{background:color-mix(in srgb,var(--altcha-color-text, currentColor) 10%,transparent);border:0;border-radius:3px;color:var(--altcha-color-text, currentColor);cursor:pointer;display:flex;align-items:center;justify-content:center;padding:.35rem}.altcha-code-challenge-audio:disabled,.altcha-code-challenge-reload:disabled,.altcha-code-challenge-verify:disabled{opacity:.7;pointer-events:none}.altcha-code-challenge-audio>*,.altcha-code-challenge-reload>*{height:20px;width:20px}.altcha-code-challenge-buttons{display:flex;justify-content:space-between}.altcha-code-challenge-buttons-left{display:flex;gap:.25rem}.altcha-code-challenge-verify{align-items:center;background:var(--altcha-color-active, #1D1DC9);border:0;border-radius:3px;color:#fff;cursor:pointer;display:flex;gap:.5rem;font-size:100%;padding:.35rem 1rem}.altcha-code-challenge-arrow{border:6px solid transparent;border-bottom-color:var(--altcha-color-border, currentColor);content:"";height:0;left:.15rem;position:absolute;top:-12px;width:0}.altcha[data-floating=top] .altcha-code-challenge{top:-150px}.altcha[data-floating=top] .altcha-code-challenge-arrow{border-bottom-color:transparent;border-top-color:var(--altcha-color-border, currentColor);bottom:-12px;top:auto}.altcha-label{cursor:pointer;flex-grow:1}.altcha-logo{color:currentColor!important;opacity:.7}.altcha-footer:hover,.altcha-logo:hover{opacity:1}.altcha-error{color:var(--altcha-color-error-text, #f23939);display:flex;font-size:.85rem;gap:.3rem;padding:0 .7rem .7rem}.altcha-footer{align-items:center;background-color:var(--altcha-color-footer-bg, transparent);display:flex;font-size:.75rem;opacity:.7;justify-content:end;padding:.2rem .7rem}.altcha-footer a{color:currentColor}.altcha-checkbox{display:flex;align-items:center;justify-content:center;height:24px;position:relative;width:24px}.altcha-checkbox .altcha-spinner{bottom:0;left:0;position:absolute;right:0;top:0}.altcha-checkbox input{width:18px;height:18px;margin:0}.altcha-checkbox-verifying input{appearance:none;opacity:0;pointer-events:none}.altcha-spinner{animation:altcha-spinner .75s infinite linear;transform-origin:center}.altcha-overlay{--altcha-color-base:#fff;--altcha-color-text:#000;animation:overlay-slidein .5s forwards;display:flex;flex-direction:column;gap:.5rem;left:50%;width:260px;opacity:0;position:fixed;top:45%;transform:translate(-50%,-50%)}.altcha-overlay-backdrop{background:rgba(0,0,0,.5);bottom:0;display:none;left:0;position:fixed;right:0;top:0;z-index:99999999}.altcha-overlay-close-button{align-self:flex-end;background:0 0;border:0;padding:.25rem;cursor:pointer;color:currentColor;font-size:130%;line-height:1;opacity:.7}@media (max-height:450px){.altcha-overlay{top:10%!important;transform:translate(-50%,0)}}'; -function Ho(e, t = "__altcha-css") { - if (!document.getElementById(t)) { - const r = document.createElement("style"); - r.id = t, r.textContent = e, document.head.appendChild(r); - } -} -globalThis.altchaCreateWorker = (e) => e ? new Worker(new URL(e)) : new Ni(); -Ho(Bo); -Ho(Bo); -export { - kl as Altcha -}; +const jsContent$1 = `(function() { + "use strict"; + function bufferStartsWith(buffer, prefix) { + if (prefix.length > buffer.length) { + return false; + } + for (let i = 0; i < prefix.length; i++) { + if (buffer[i] !== prefix[i]) { + return false; + } + } + return true; + } + function bufferToHex(buffer) { + return Array.from(new Uint8Array(buffer)).map((b) => b.toString(16).padStart(2, "0")).join(""); + } + function concatBuffers(a, b) { + const out = new Uint8Array(a.length + b.length); + out.set(a, 0); + out.set(b, a.length); + return out; + } + function hexToBuffer(hex) { + if (hex.length % 2 !== 0) { + throw new Error(\`Hex string must have an even length. Got: \${hex}\`); + } + const buffer = new ArrayBuffer(hex.length / 2); + const view = new DataView(buffer); + for (let i = 0; i < hex.length; i += 2) { + const byteString = hex.substring(i, i + 2); + const byteValue = parseInt(byteString, 16); + view.setUint8(i / 2, byteValue); + } + return new Uint8Array(buffer); + } + async function delay(ms) { + await new Promise((resolve) => setTimeout(resolve, ms)); + } + function timeDuration(start) { + return Math.floor((performance.now() - start) * 10) / 10; + } + class PasswordBuffer { + constructor(nonce, mode = "uint32") { + this.nonce = nonce; + this.mode = mode; + this.buffer = new Uint8Array(this.nonce.length + this.COUNTER_BYTES); + this.buffer.set(this.nonce, 0); + this.dataView = new DataView(this.buffer.buffer); + } + COUNTER_BYTES = 4; + buffer; + dataView; + encoder = new TextEncoder(); + /** + * Appends the counter to the nonce buffer. + * In 'string' mode, encodes the counter as a UTF-8 string. + * In 'uint32' mode, writes the counter as a big-endian 32-bit integer. + */ + setCounter(n) { + if (this.mode === "string") { + return concatBuffers(this.nonce, this.encoder.encode(n.toString())); + } + this.dataView.setUint32(this.nonce.length, n, false); + return this.buffer; + } + } + async function solveChallenge(options) { + const { + challenge, + controller, + counterMode = "uint32", + counterStart = 0, + counterStep = 1, + deriveKey: deriveKey2, + timeout = 9e4 + } = options; + const { nonce, keyPrefix, salt } = challenge.parameters; + const nonceBuf = hexToBuffer(nonce); + const saltBuf = hexToBuffer(salt); + const keyPrefixBuf = keyPrefix.length % 2 === 0 ? hexToBuffer(keyPrefix) : null; + const password = new PasswordBuffer(nonceBuf, counterMode); + const start = performance.now(); + let counter = counterStart; + let iterations = 0; + let derivedKeyHex = ""; + let lastYield = start; + while (true) { + if (controller?.signal.aborted || timeout && iterations % 10 === 0 && performance.now() - start > timeout) { + return null; + } + const { derivedKey } = await deriveKey2( + challenge.parameters, + saltBuf, + password.setCounter(counter) + ); + if (iterations % 10 === 0 && performance.now() - lastYield > 200) { + await delay(0); + lastYield = performance.now(); + } + if (keyPrefixBuf ? bufferStartsWith(derivedKey, keyPrefixBuf) : bufferToHex(derivedKey).startsWith(keyPrefix)) { + derivedKeyHex = bufferToHex(derivedKey); + break; + } + counter = counter + counterStep; + iterations = iterations + 1; + } + return { + counter, + derivedKey: derivedKeyHex, + time: timeDuration(start) + }; + } + function handler(options) { + const { deriveKey: deriveKey2 } = options; + let controller = void 0; + self.onmessage = async (message) => { + const { challenge, counterMode, counterStart, counterStep, timeout, type } = message.data; + if (type === "abort") { + controller?.abort(); + } else if (type === "work") { + controller = new AbortController(); + let solution; + try { + solution = await solveChallenge({ + challenge, + controller, + counterStart, + counterStep, + deriveKey: deriveKey2, + counterMode, + timeout + }); + } catch (err) { + return self.postMessage({ error: err }); + } + self.postMessage(solution); + } + }; + } + function getDigest(algorithm) { + switch (algorithm) { + case "PBKDF2/SHA-512": + return "SHA-512"; + case "PBKDF2/SHA-384": + return "SHA-384"; + case "PBKDF2/SHA-256": + default: + return "SHA-256"; + } + } + async function deriveKey(parameters, salt, password) { + const { algorithm, cost, keyLength = 32 } = parameters; + const passwordKey = await crypto.subtle.importKey( + "raw", + password, + { name: "PBKDF2" }, + false, + ["deriveKey"] + ); + const derivedKey = await crypto.subtle.deriveKey( + { + name: "PBKDF2", + salt, + iterations: cost, + hash: getDigest(algorithm) + }, + passwordKey, + { name: "AES-GCM", length: keyLength * 8 }, + true, + ["encrypt"] + ); + return { + derivedKey: new Uint8Array(await crypto.subtle.exportKey("raw", derivedKey)) + }; + } + handler({ + deriveKey + }); +})(); +`; +const blob$1 = typeof self !== "undefined" && self.Blob && new Blob(["(self.URL || self.webkitURL).revokeObjectURL(self.location.href);", jsContent$1], { type: "text/javascript;charset=utf-8" }); +function WorkerWrapper$1(options) { + let objURL; + try { + objURL = blob$1 && (self.URL || self.webkitURL).createObjectURL(blob$1); + if (!objURL) throw ""; + const worker = new Worker(objURL, { + name: options?.name + }); + worker.addEventListener("error", () => { + (self.URL || self.webkitURL).revokeObjectURL(objURL); + }); + return worker; + } catch (e) { + return new Worker( + "data:text/javascript;charset=utf-8," + encodeURIComponent(jsContent$1), + { + name: options?.name + } + ); + } +} +const jsContent = `(function() { + "use strict"; + function bufferStartsWith(buffer, prefix) { + if (prefix.length > buffer.length) { + return false; + } + for (let i = 0; i < prefix.length; i++) { + if (buffer[i] !== prefix[i]) { + return false; + } + } + return true; + } + function bufferToHex(buffer) { + return Array.from(new Uint8Array(buffer)).map((b) => b.toString(16).padStart(2, "0")).join(""); + } + function concatBuffers(a, b) { + const out = new Uint8Array(a.length + b.length); + out.set(a, 0); + out.set(b, a.length); + return out; + } + function hexToBuffer(hex) { + if (hex.length % 2 !== 0) { + throw new Error(\`Hex string must have an even length. Got: \${hex}\`); + } + const buffer = new ArrayBuffer(hex.length / 2); + const view = new DataView(buffer); + for (let i = 0; i < hex.length; i += 2) { + const byteString = hex.substring(i, i + 2); + const byteValue = parseInt(byteString, 16); + view.setUint8(i / 2, byteValue); + } + return new Uint8Array(buffer); + } + async function delay(ms) { + await new Promise((resolve) => setTimeout(resolve, ms)); + } + function timeDuration(start) { + return Math.floor((performance.now() - start) * 10) / 10; + } + class PasswordBuffer { + constructor(nonce, mode = "uint32") { + this.nonce = nonce; + this.mode = mode; + this.buffer = new Uint8Array(this.nonce.length + this.COUNTER_BYTES); + this.buffer.set(this.nonce, 0); + this.dataView = new DataView(this.buffer.buffer); + } + COUNTER_BYTES = 4; + buffer; + dataView; + encoder = new TextEncoder(); + /** + * Appends the counter to the nonce buffer. + * In 'string' mode, encodes the counter as a UTF-8 string. + * In 'uint32' mode, writes the counter as a big-endian 32-bit integer. + */ + setCounter(n) { + if (this.mode === "string") { + return concatBuffers(this.nonce, this.encoder.encode(n.toString())); + } + this.dataView.setUint32(this.nonce.length, n, false); + return this.buffer; + } + } + async function solveChallenge(options) { + const { + challenge, + controller, + counterMode = "uint32", + counterStart = 0, + counterStep = 1, + deriveKey: deriveKey2, + timeout = 9e4 + } = options; + const { nonce, keyPrefix, salt } = challenge.parameters; + const nonceBuf = hexToBuffer(nonce); + const saltBuf = hexToBuffer(salt); + const keyPrefixBuf = keyPrefix.length % 2 === 0 ? hexToBuffer(keyPrefix) : null; + const password = new PasswordBuffer(nonceBuf, counterMode); + const start = performance.now(); + let counter = counterStart; + let iterations = 0; + let derivedKeyHex = ""; + let lastYield = start; + while (true) { + if (controller?.signal.aborted || timeout && iterations % 10 === 0 && performance.now() - start > timeout) { + return null; + } + const { derivedKey } = await deriveKey2( + challenge.parameters, + saltBuf, + password.setCounter(counter) + ); + if (iterations % 10 === 0 && performance.now() - lastYield > 200) { + await delay(0); + lastYield = performance.now(); + } + if (keyPrefixBuf ? bufferStartsWith(derivedKey, keyPrefixBuf) : bufferToHex(derivedKey).startsWith(keyPrefix)) { + derivedKeyHex = bufferToHex(derivedKey); + break; + } + counter = counter + counterStep; + iterations = iterations + 1; + } + return { + counter, + derivedKey: derivedKeyHex, + time: timeDuration(start) + }; + } + function handler(options) { + const { deriveKey: deriveKey2 } = options; + let controller = void 0; + self.onmessage = async (message) => { + const { challenge, counterMode, counterStart, counterStep, timeout, type } = message.data; + if (type === "abort") { + controller?.abort(); + } else if (type === "work") { + controller = new AbortController(); + let solution; + try { + solution = await solveChallenge({ + challenge, + controller, + counterStart, + counterStep, + deriveKey: deriveKey2, + counterMode, + timeout + }); + } catch (err) { + return self.postMessage({ error: err }); + } + self.postMessage(solution); + } + }; + } + async function deriveKey(parameters, salt, password) { + const { algorithm, keyLength = 32 } = parameters; + const iterations = Math.max(1, parameters.cost); + let data = void 0; + let derivedKey = void 0; + for (let i = 0; i < iterations; i++) { + if (i === 0) { + data = concatBuffers(salt, password); + } else { + data = derivedKey; + } + derivedKey = new Uint8Array( + (await crypto.subtle.digest(algorithm, data)).slice(0, keyLength) + ); + } + return { + parameters: {}, + derivedKey + }; + } + handler({ + deriveKey + }); +})(); +`; +const blob = typeof self !== "undefined" && self.Blob && new Blob(["(self.URL || self.webkitURL).revokeObjectURL(self.location.href);", jsContent], { type: "text/javascript;charset=utf-8" }); +function WorkerWrapper(options) { + let objURL; + try { + objURL = blob && (self.URL || self.webkitURL).createObjectURL(blob); + if (!objURL) throw ""; + const worker = new Worker(objURL, { + name: options?.name + }); + worker.addEventListener("error", () => { + (self.URL || self.webkitURL).revokeObjectURL(objURL); + }); + return worker; + } catch (e) { + return new Worker( + "data:text/javascript;charset=utf-8," + encodeURIComponent(jsContent), + { + name: options?.name + } + ); + } +} +const css = ':root {\n --altcha-border-color: var(--altcha-color-neutral);\n --altcha-border-width: 1px;\n --altcha-border-radius: 6px;\n --altcha-color-base: light-dark(oklch(100% 0.00011 271.152), oklch(20.904% 0.00002 271.152));\n --altcha-color-base-content: light-dark(\n oklch(20.904% 0.00002 271.152),\n oklch(100% 0.00011 271.152)\n );\n --altcha-color-error: oklch(51.284% 0.20527 28.678);\n --altcha-color-error-content: oklch(100% 0.00011 271.152);\n --altcha-color-neutral: light-dark(oklch(83.591% 0.0001 271.152), oklch(46.04% 0.00005 271.152));\n --altcha-color-neutral-content: light-dark(\n oklch(46.76% 0.00005 271.152),\n oklch(100% 0.00011 271.152)\n );\n --altcha-color-primary: oklch(40.279% 0.2449 268.131);\n --altcha-color-primary-content: oklch(100% 0.00011 271.152);\n --altcha-color-success: oklch(55.748% 0.18968 142.511);\n --altcha-color-success-content: oklch(100% 0.00011 271.152);\n --altcha-checkbox-border-color: var(--altcha-color-neutral);\n --altcha-checkbox-border-radius: 5px;\n --altcha-checkbox-border-width: var(--altcha-border-width);\n --altcha-checkbox-outline: 2px solid var(--altcha-checkbox-outline-color);\n --altcha-checkbox-outline-color: light-dark(\n color-mix(in srgb, var(--altcha-color-primary) 20%, transparent),\n color-mix(in srgb, var(--altcha-color-primary) 60%, transparent)\n );\n --altcha-checkbox-outline-offset: 2px;\n --altcha-checkbox-size: 22px;\n --altcha-checkbox-transition-duration: var(--altcha-transition-duration);\n --altcha-input-background-color: var(--altcha-color-base);\n --altcha-input-border-radius: 3px;\n --altcha-input-border-width: 1px;\n --altcha-input-color: var(--altcha-color-base-content);\n --altcha-max-width: 320px;\n --altcha-padding: 0.75rem;\n --altcha-popover-arrow-size: 6px;\n --altcha-popover-color: var(--altcha-border-color);\n --altcha-shadow: drop-shadow(3px 3px 6px oklch(0% 0 0 / 0.2));\n --altcha-spinner-color: var(--altcha-color-base-content);\n --altcha-switch-background-color: var(--altcha-color-neutral);\n --altcha-switch-border-radius: calc(infinity * 1px);\n --altcha-switch-height: var(--altcha-checkbox-size);\n --altcha-switch-padding: 0.25rem;\n --altcha-switch-width: calc(var(--altcha-checkbox-size) * 1.75);\n --altcha-switch-toggle-border-radius: 100%;\n --altcha-switch-toggle-color: var(--altcha-color-neutral-content);\n --altcha-switch-toggle-size: calc(\n var(--altcha-switch-height) - calc(var(--altcha-switch-padding) * 2)\n );\n --altcha-transition-duration: 0.6s;\n --altcha-z-index: 99999999;\n --altcha-z-index-popover: 999999999;\n}\n\n.altcha {\n all: revert-layer;\n display: none;\n font-family: inherit;\n font-size: inherit;\n position: relative;\n}\n.altcha[data-visible] {\n display: block;\n}\n.altcha-popover, .altcha-popover * {\n all: revert-layer;\n box-sizing: border-box;\n font-family: inherit;\n font-size: inherit;\n line-height: 1.25;\n}\n.altcha * {\n all: revert-layer;\n box-sizing: border-box;\n font-family: inherit;\n font-size: inherit;\n line-height: 1.25;\n}\n.altcha a, .altcha-popover a {\n color: currentColor;\n text-decoration: none;\n}\n.altcha a:hover, .altcha-popover a:hover {\n color: currentColor;\n}\n.altcha-main {\n align-items: start;\n background-color: var(--altcha-color-base);\n border: var(--altcha-border-width, 1px) solid var(--altcha-border-color);\n border-radius: var(--altcha-border-radius, 0);\n color: var(--altcha-color-base-content);\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n justify-content: space-between;\n padding: var(--altcha-padding);\n max-width: var(--altcha-max-width, 100%);\n}\n.altcha-main > * {\n display: flex;\n width: 100%;\n}\n.altcha-main > *:first-child {\n flex-grow: 1;\n}\n.altcha-checkbox-wrap {\n align-items: center;\n display: flex;\n flex-direction: row;\n flex-grow: 1;\n gap: 0.5rem;\n}\n.altcha-checkbox-wrap > * {\n display: flex;\n}\n.altcha-logo {\n opacity: 0.7;\n}\n.altcha-footer {\n align-items: center;\n display: flex;\n flex-grow: 1;\n gap: 0.5rem;\n justify-content: flex-end;\n font-size: 0.7rem;\n opacity: 0.7;\n}\n.altcha-error {\n font-size: 0.85rem;\n}\n.altcha-button {\n align-items: center;\n background: var(--altcha-color-primary);\n border: var(--altcha-input-border-width) solid var(--altcha-color-primary);\n border-radius: var(--altcha-input-border-radius);\n color: var(--altcha-color-primary-content);\n cursor: pointer;\n display: flex;\n font-size: 0.9rem;\n gap: 0.5rem;\n padding: 0.35rem;\n}\n.altcha-button:focus {\n border-color: var(--altcha-color-primary);\n outline: var(--altcha-checkbox-outline);\n outline-offset: var(--altcha-checkbox-outline-offset);\n}\n.altcha-button > .altcha-spinner, .altcha-button > svg {\n height: 20px;\n width: 20px;\n}\n.altcha-button-secondary {\n background: transparent;\n border-color: var(--altcha-color-neutral);\n color: var(--altcha-color-neutral-content);\n}\n.altcha-input {\n background: var(--altcha-input-background-color);\n border: var(--altcha-input-border-width) solid var(--altcha-color-neutral);\n border-radius: var(--altcha-input-border-radius);\n color: var(--altcha-input-color);\n flex-grow: 1;\n font-size: 1rem;\n min-width: 0;\n padding: 0.25rem;\n width: auto;\n}\n.altcha-input:focus {\n border-color: var(--altcha-color-primary);\n outline: var(--altcha-checkbox-outline);\n outline-offset: var(--altcha-checkbox-outline-offset);\n}\n.altcha-spinner {\n animation: altcha-rotate 0.6s linear infinite;\n border-radius: 100%;\n border: var(--altcha-checkbox-border-width) solid var(--altcha-spinner-color);\n border-bottom-color: transparent;\n border-right-color: transparent;\n opacity: 0.5;\n}\n.altcha-popover {\n background-color: var(--altcha-color-base);\n border: var(--altcha-border-width) solid var(--altcha-border-color);\n border-radius: var(--altcha-border-radius);\n color: var(--altcha-color-base-content);\n filter: var(--altcha-shadow);\n position: absolute;\n left: calc(var(--altcha-padding) / 2);\n max-width: calc(var(--altcha-max-width) - var(--altcha-padding));\n top: calc(var(--altcha-padding) + var(--altcha-checkbox-size) + var(--altcha-popover-arrow-size));\n z-index: var(--altcha-z-index-popover);\n}\n.altcha-popover-arrow {\n border: var(--altcha-popover-arrow-size) solid transparent;\n border-bottom-color: var(--altcha-popover-color);\n content: "";\n height: 0;\n left: calc(var(--altcha-checkbox-size) / 2);\n position: absolute;\n top: calc(var(--altcha-popover-arrow-size) * -2);\n width: 0;\n}\n.altcha-popover-content {\n max-height: 100dvh;\n overflow: auto;\n padding: var(--altcha-padding);\n}\n.altcha-popover[data-top=true][data-display=standard] {\n bottom: calc(100% - (var(--altcha-padding) - var(--altcha-popover-arrow-size)));\n top: auto;\n}\n.altcha-popover[data-top=true][data-display=standard] .altcha-popover-arrow {\n border-bottom-color: transparent;\n border-top-color: var(--altcha-popover-color);\n bottom: calc(var(--altcha-popover-arrow-size) * -2);\n top: auto;\n}\n.altcha-popover[data-variant=error] {\n --altcha-popover-color: var(--altcha-color-error);\n background-color: var(--altcha-color-error);\n border-color: var(--altcha-color-error);\n color: var(--altcha-color-error-content);\n}\n.altcha-popover[data-variant=error] .altcha-popover-content {\n padding: calc(var(--altcha-padding) / 1.5) var(--altcha-padding);\n}\n.altcha-popover[data-display=overlay] {\n animation: altcha-overlay-slidein 0.5s forwards;\n left: 50%;\n position: fixed;\n top: 45%;\n transform: translate(-50%, -50%);\n width: var(--altcha-max-width);\n z-index: var(--altcha-z-index);\n}\n.altcha-popover[data-display=bottomsheet] {\n animation: altcha-bottomsheet-slideup 0.5s forwards;\n border-bottom-left-radius: 0;\n border-bottom-right-radius: 0;\n border-bottom: 0;\n bottom: -100%;\n left: 50%;\n position: fixed;\n top: auto;\n transform: translate(-50%, 0);\n width: var(--altcha-max-width);\n z-index: var(--altcha-z-index);\n}\n.altcha-popover[data-display=bottomsheet] .altcha-popover-content {\n padding-bottom: calc(var(--altcha-padding) * 2);\n}\n.altcha-popover-backdrop {\n background: var(--altcha-color-base-content);\n bottom: 0;\n left: 0;\n opacity: 0.1;\n position: fixed;\n right: 0;\n top: 0;\n transition: opacity 0.5s;\n z-index: var(--altcha-z-index);\n}\n.altcha-popover-close {\n color: var(--altcha-color-base-content);\n cursor: pointer;\n display: inline-block;\n font-size: 1rem;\n height: 1.25rem;\n line-height: 0.95;\n position: absolute;\n right: 0;\n text-align: center;\n text-shadow: 0 0 1px var(--altcha-color-base);\n top: -1.5rem;\n width: 1.25rem;\n z-index: var(--altcha-z-index);\n}\n[dir=rtl] .altcha-popover {\n left: auto;\n right: calc(var(--altcha-padding) / 2);\n}\n[dir=rtl] .altcha-popover-arrow {\n left: auto;\n right: calc(var(--altcha-checkbox-size) / 2);\n}\n[dir=rtl] .altcha-popover-close {\n left: 0;\n right: auto;\n}\n.altcha-popover[data-display=bottomsheet] .altcha-footer, .altcha-popover[data-display=overlay] .altcha-footer {\n align-items: center;\n justify-content: center;\n padding-top: 1rem;\n gap: 0.5rem;\n}\n.altcha-popover[data-display=bottomsheet] .altcha-footer svg, .altcha-popover[data-display=overlay] .altcha-footer svg {\n height: 18px;\n width: 18px;\n vertical-align: middle;\n}\n.altcha-code-challenge > form {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n}\n.altcha-code-challenge-title {\n font-weight: 600;\n}\n.altcha-code-challenge-text {\n font-size: 0.85rem;\n}\n.altcha-code-challenge-image {\n background: white;\n border: var(--altcha-input-border-width) solid var(--altcha-color-neutral);\n border-radius: var(--altcha-input-border-radius);\n object-fit: contain;\n height: 50px;\n}\n.altcha-code-challenge-row {\n display: flex;\n gap: 0.5rem;\n}\n.altcha-code-challenge-buttons {\n align-items: center;\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n margin-top: var(--altcha-padding);\n justify-content: space-between;\n}\n.altcha-code-challenge-buttons button {\n justify-content: center;\n width: 100%;\n}\n.altcha-checkbox {\n cursor: pointer;\n height: var(--altcha-checkbox-size);\n position: relative;\n width: var(--altcha-checkbox-size);\n}\n.altcha-checkbox input {\n appearance: none;\n background: var(--altcha-input-background-color);\n border: var(--altcha-checkbox-border-width, 2px) solid var(--altcha-checkbox-border-color);\n border-radius: var(--altcha-checkbox-border-radius);\n height: var(--altcha-checkbox-size);\n left: 0;\n margin: 0;\n outline: none;\n padding: 0;\n position: absolute;\n top: 0;\n width: var(--altcha-checkbox-size);\n}\n.altcha-checkbox input:before {\n border-radius: var(--altcha-checkbox-border-radius);\n content: "";\n width: 100%;\n height: 100%;\n background: var(--altcha-color-neutral);\n display: block;\n transform: scale(0);\n}\n.altcha-checkbox input:focus {\n outline: var(--altcha-checkbox-outline);\n outline-offset: var(--altcha-checkbox-outline-offset);\n}\n.altcha-checkbox input:checked {\n background-color: var(--altcha-color-success);\n border-color: var(--altcha-color-success);\n}\n.altcha-checkbox input:checked::before {\n background-color: var(--altcha-color-success);\n opacity: 0;\n transform: scale(2.2);\n transition: all var(--altcha-checkbox-transition-duration) ease;\n transition-delay: 0.1s;\n}\n.altcha-checkbox svg {\n --altcha-radio-svg-size: calc(var(--altcha-checkbox-size) * 0.5);\n --altcha-radio-svg-offset: calc(var(--altcha-checkbox-size) * 0.25);\n fill: none;\n left: var(--altcha-radio-svg-offset);\n height: var(--altcha-radio-svg-size);\n opacity: 0;\n position: absolute;\n stroke: currentColor;\n stroke-width: 2;\n stroke-linecap: round;\n stroke-linejoin: round;\n stroke-dasharray: 16px;\n stroke-dashoffset: 16px;\n top: var(--altcha-radio-svg-offset);\n transform: translate3d(0, 0, 0);\n width: var(--altcha-radio-svg-size);\n}\n.altcha-checkbox input:checked + svg {\n color: var(--altcha-color-success-content);\n opacity: 1;\n stroke-dashoffset: 0;\n transition: all var(--altcha-checkbox-transition-duration) ease;\n transition-delay: 0.1s;\n}\n.altcha-checkbox-spinner {\n display: none;\n left: 0;\n height: var(--altcha-checkbox-size);\n position: absolute;\n top: 0;\n width: var(--altcha-checkbox-size);\n}\n.altcha-checkbox[data-loading=true] input {\n appearance: none;\n opacity: 0;\n pointer-events: none;\n}\n.altcha-checkbox[data-loading=true] .altcha-checkbox-spinner {\n display: block;\n}\n.altcha-checkbox-native {\n height: var(--altcha-checkbox-size);\n position: relative;\n width: var(--altcha-checkbox-size);\n}\n.altcha-checkbox-native input {\n height: var(--altcha-checkbox-size);\n margin: 0;\n width: var(--altcha-checkbox-size);\n}\n.altcha-checkbox-native input:focus {\n outline: var(--altcha-checkbox-outline);\n outline-offset: var(--altcha-checkbox-outline-offset);\n}\n.altcha-checkbox-native-spinner {\n display: none;\n left: 0;\n height: var(--altcha-checkbox-size);\n position: absolute;\n top: 0;\n width: var(--altcha-checkbox-size);\n}\n.altcha-checkbox-native[data-loading=true] input {\n appearance: none;\n opacity: 0;\n pointer-events: none;\n}\n.altcha-checkbox-native[data-loading=true] .altcha-checkbox-native-spinner {\n display: block;\n}\n.altcha-switch {\n align-items: center;\n border-radius: var(--altcha-switch-border-radius);\n background-color: var(--altcha-switch-background-color);\n cursor: pointer;\n display: flex;\n height: var(--altcha-switch-height);\n padding: var(--altcha-switch-padding);\n position: relative;\n width: var(--altcha-switch-width);\n}\n.altcha-switch:focus-within {\n outline: var(--altcha-checkbox-outline);\n outline-offset: var(--altcha-checkbox-outline-offset);\n}\n.altcha-switch input {\n appearance: none;\n height: 100%;\n left: 0;\n opacity: 0;\n position: absolute;\n top: 0;\n width: 100%;\n}\n.altcha-switch-toggle {\n align-items: center;\n background-color: var(--altcha-switch-toggle-color);\n border-radius: var(--altcha-switch-toggle-border-radius);\n display: flex;\n height: var(--altcha-switch-toggle-size);\n justify-content: center;\n left: var(--altcha-switch-padding);\n position: absolute;\n transition: width 150ms ease-out, left 150ms ease-out;\n width: var(--altcha-switch-toggle-size);\n}\n.altcha-switch-spinner {\n display: none;\n height: var(--altcha-switch-toggle-size);\n width: var(--altcha-switch-toggle-size);\n}\n.altcha-switch[data-loading=true] {\n pointer-events: none;\n}\n.altcha-switch[data-loading=true] .altcha-switch-spinner {\n display: block;\n}\n.altcha-switch[data-loading=true] .altcha-switch-toggle {\n background-color: transparent;\n left: calc(50% - var(--altcha-switch-toggle-size) / 2);\n}\n[data-state=verified] .altcha-switch {\n --altcha-switch-background-color: var(--altcha-color-success);\n}\n[data-state=verified] .altcha-switch-toggle {\n background-color: var(--altcha-color-success-content);\n left: calc(100% - var(--altcha-switch-height) + var(--altcha-switch-padding));\n}\n[dir=rtl] .altcha-switch-toggle {\n left: calc(100% - var(--altcha-switch-height) + var(--altcha-switch-padding));\n}\n[dir=rtl][data-state=verified] .altcha-switch-toggle {\n left: var(--altcha-switch-padding);\n}\n.altcha-floating-arrow {\n border: 6px solid transparent;\n border-bottom-color: var(--altcha-border-color);\n content: "";\n height: 0;\n left: 12px;\n position: absolute;\n top: -12px;\n width: 0;\n}\n.altcha-overlay-backdrop {\n bottom: 0;\n left: 0;\n position: fixed;\n right: 0;\n top: 0;\n transition: opacity var(--altcha-transition-duration);\n z-index: var(--altcha-z-index);\n}\n.altcha-overlay-close {\n display: inline-block;\n color: currentColor;\n cursor: pointer;\n font-size: 1rem;\n height: 1rem;\n line-height: 0.85;\n position: absolute;\n right: 0;\n text-align: center;\n text-shadow: 0 0 1px var(--altcha-color-base);\n top: -1.5rem;\n width: 1rem;\n z-index: var(--altcha-z-index);\n}\n.altcha[data-display=overlay] {\n animation: altcha-overlay-slidein var(--altcha-transition-duration) forwards;\n filter: var(--altcha-shadow);\n left: 50%;\n opacity: 0;\n position: fixed;\n top: 45%;\n transform: translate(-50%, -50%);\n z-index: var(--altcha-z-index);\n}\n.altcha[data-display=overlay] .altcha-main {\n width: var(--altcha-max-width);\n}\n.altcha[data-display=floating] {\n display: none;\n filter: var(--altcha-shadow);\n left: var(--altcha-floating-left, -100%);\n position: fixed;\n top: var(--altcha-floating-top, -100%);\n z-index: var(--altcha-z-index);\n}\n.altcha[data-display=floating] .altcha-main {\n width: var(--altcha-max-width);\n}\n.altcha[data-display=floating][data-placement=top] .altcha-floating-arrow {\n border-bottom-color: transparent;\n border-top-color: var(--altcha-border-color);\n bottom: -12px;\n top: auto;\n}\n.altcha[data-display=floating][data-visible] {\n display: flex;\n}\n.altcha[data-display=bar] {\n bottom: -100%;\n filter: var(--altcha-shadow);\n left: 0;\n position: fixed;\n right: 0;\n transition: bottom var(--altcha-transition-duration), top var(--altcha-transition-duration);\n z-index: var(--altcha-z-index);\n}\n.altcha[data-display=bar] .altcha-main {\n align-items: center;\n border-radius: 0;\n border-width: var(--altcha-border-width) 0 0 0;\n flex-direction: row;\n max-width: 100% !important;\n}\n.altcha[data-display=bar] .altcha-main > * {\n width: auto;\n}\n.altcha[data-display=bar][data-placement=top] {\n bottom: auto;\n top: -100%;\n}\n.altcha[data-display=bar][data-placement=top] .altcha-main {\n border-width: 0 0 var(--altcha-border-width) 0;\n}\n.altcha[data-display=bar][data-placement=bottom]:not([data-state=unverified]) {\n bottom: 0;\n}\n.altcha[data-display=bar][data-placement=top]:not([data-state=unverified]) {\n top: 0;\n}\n.altcha[data-display=invisible] {\n display: none;\n}\n\n@keyframes altcha-rotate {\n 0% {\n transform: rotate(0deg);\n }\n 100% {\n transform: rotate(360deg);\n }\n}\n@keyframes altcha-bottomsheet-slideup {\n 100% {\n bottom: 0;\n }\n}\n@keyframes altcha-overlay-slidein {\n 100% {\n opacity: 1;\n top: 50%;\n }\n}'; +injectCss(css); +$altcha.algorithms.set("SHA-256", () => new WorkerWrapper()); +$altcha.algorithms.set("SHA-384", () => new WorkerWrapper()); +$altcha.algorithms.set("SHA-512", () => new WorkerWrapper()); +$altcha.algorithms.set("PBKDF2/SHA-256", () => new WorkerWrapper$1()); +$altcha.algorithms.set("PBKDF2/SHA-384", () => new WorkerWrapper$1()); +$altcha.algorithms.set("PBKDF2/SHA-512", () => new WorkerWrapper$1()); diff --git a/website_altcha/static/src/altcha/altcha.esm.js b/website_altcha/static/src/altcha/altcha.esm.js index e89d94ffef..4f18e82e33 100644 --- a/website_altcha/static/src/altcha/altcha.esm.js +++ b/website_altcha/static/src/altcha/altcha.esm.js @@ -1,6 +1,5 @@ -/* global document, window */ +/* global document */ -import {_t} from "@web/core/l10n/translation"; import {loadBundle} from "@web/core/assets"; import {session} from "@web/session"; @@ -20,34 +19,9 @@ export class Altcha { if (this._publicKey) { this._altchaReady = loadBundle(`web.altcha_libs`); return this._altchaReady.then(() => - Boolean(document.querySelector(".altcha-widget")) + Boolean(document.querySelector(".o_altcha_widget")) ); } return false; } - /** - * Returns an object with the token if altcha call succeeds - * If no key is set an object with a message is returned - * If an error occurred an object with the error message is returned - * - * @param {String} action - * @returns {Promise|Object} - */ - async getToken(action) { - if (!this._publicKey) { - return { - message: _t("No altcha site key set."), - }; - } - await this._altchaReady; - try { - return { - token: await window.altcha.execute(this._publicKey, {action: action}), - }; - } catch { - return { - error: _t("The altcha site key is invalid."), - }; - } - } } diff --git a/website_altcha/static/src/signup/altcha.xml b/website_altcha/static/src/signup/altcha.xml index 53bc113c98..bd94d2d3e0 100644 --- a/website_altcha/static/src/signup/altcha.xml +++ b/website_altcha/static/src/signup/altcha.xml @@ -8,10 +8,7 @@ style="width: 200px;" />
- +
diff --git a/website_altcha/static/src/signup/signup.esm.js b/website_altcha/static/src/signup/signup.esm.js index 69f8f62486..fb5de1032d 100644 --- a/website_altcha/static/src/signup/signup.esm.js +++ b/website_altcha/static/src/signup/signup.esm.js @@ -14,12 +14,10 @@ export const AltchaFunctionality = { return this._super(...arguments); }, start: function () { - if (this._altcha._publicKey && !this.$el.find(".altcha-widget").length) { + if (this._altcha._publicKey && !this.$el.find(".o_altcha_widget").length) { this.$el .find("div.oe_login_buttons") - .prepend( - '' - ); + .prepend(renderToString("website_altcha.AltchaWidget", {})); } return this._super(...arguments); }, @@ -28,13 +26,11 @@ export const AltchaFunctionality = { publicWidget.registry.SignupAltcha = publicWidget.Widget.extend({ ...AltchaFunctionality, selector: ".oe_signup_form", - tokenName: "signup", }); publicWidget.registry.ResetPasswordAltcha = publicWidget.Widget.extend({ ...AltchaFunctionality, selector: ".oe_reset_password_form", - tokenName: "password_reset", }); publicWidget.registry.s_website_form.include({ @@ -64,3 +60,14 @@ publicWidget.registry.s_website_form.include({ return res; }, }); +publicWidget.registry.EditModeWebsiteForm.include({ + start: function () { + const res = this._super(...arguments); + if (this.editableMode) { + // We should delete the altcha widget in edit mode + this.$el.find(".o_altcha_widget").remove(); + this.$el.find(".o_altcha_widget_container").remove(); + } + return res; + }, +}); diff --git a/website_altcha/tests/__init__.py b/website_altcha/tests/__init__.py new file mode 100644 index 0000000000..65d22d8cf1 --- /dev/null +++ b/website_altcha/tests/__init__.py @@ -0,0 +1 @@ +from . import test_altcha diff --git a/website_altcha/tests/test_altcha.py b/website_altcha/tests/test_altcha.py new file mode 100644 index 0000000000..462f16638b --- /dev/null +++ b/website_altcha/tests/test_altcha.py @@ -0,0 +1,206 @@ +# Copyright 2026 Dixmit +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from unittest import mock + +from altcha.v2 import Challenge, Payload, solve_challenge +from freezegun import freeze_time +from requests.exceptions import HTTPError + +from odoo.exceptions import UserError +from odoo.tests import Form, HttpCase +from odoo.tools import mute_logger + +from odoo.addons.website.tools import MockRequest + + +class TestAltchaCreation(HttpCase): + @classmethod + def setUpClass(cls): + result = super().setUpClass() + cls.website = cls.env["website"].get_current_website() + cls.website.altcha_key = "test_key" + cls.website.altcha_private_key = "test_secret_key" + cls.website.altcha_cost = 128 + # Forcing a small power of 2 cost for allowing scrypt to work + # and make everything faster + return result + + def test_generate_altcha_challenge(self): + response = self.url_open("/altcha") + self.assertEqual(response.status_code, 200, "Expected status code 200") + challenge = Challenge.from_dict(response.json()) + with MockRequest(self.env, website=self.website): + self.assertTrue( + self.env["altcha.key"] + .sudo() + .search( + [ + ( + "key", + "=", + self.env["ir.http"]._get_altcha_key(challenge.signature), + ) + ] + ) + ) + + def generate_and_solve_challenge(self, website=None): + with mock.patch.object( + type(self.env["website"]), + "get_current_website", + return_value=website or self.website, + ): + response = self.url_open("/altcha") + response.raise_for_status() + challenge = Challenge.from_dict(response.json()) + return Payload(challenge, solve_challenge(challenge)) + + def solve_altcha_challenge_ok(self, website=None): + payload = self.generate_and_solve_challenge(website) + with MockRequest(self.env, website=website or self.website) as request: + request.params["altcha"] = payload.to_base64() + self.env["ir.http"]._verify_request_recaptcha_token("TEST") + self.assertTrue( + self.env["altcha.key"] + .sudo() + .search( + [ + ( + "key", + "=", + self.env["ir.http"]._get_altcha_key( + payload.challenge.signature + ), + ) + ] + ) + .used + ) + + def test_generate_altcha_all_algorithms(self): + for algorithm, _description in self.env["website"]._get_available_algorithms(): + with self.subTest(algorithm=algorithm): + self.website.write({"altcha_algorithm": algorithm}) + self.solve_altcha_challenge_ok() + + @mute_logger("odoo.addons.website_altcha.models.ir_http") + def test_solve_altcha_challenge_failure_01(self): + """Fails because Altcha is not passed""" + with MockRequest(self.env, website=self.website) as request: + request.params["altcha"] = False + with self.assertRaises(UserError): + self.env["ir.http"]._verify_request_recaptcha_token("TEST") + + @mute_logger("odoo.addons.website_altcha.models.ir_http") + def test_solve_altcha_challenge_failure_02(self): + """Signature fails for wrong signature""" + payload = self.generate_and_solve_challenge() + payload.challenge.signature = "invalid_signature" + with MockRequest(self.env, website=self.website) as request: + request.params["altcha"] = payload.to_base64() + with self.assertRaises(UserError): + self.env["ir.http"]._verify_request_recaptcha_token("TEST") + + @mute_logger("odoo.addons.website_altcha.models.ir_http") + def test_solve_altcha_challenge_failure_03(self): + """Signature fails with wrong payload""" + with MockRequest(self.env, website=self.website) as request: + request.params["altcha"] = "Not a valid ALTCHA Base64" + with self.assertRaises(UserError): + self.env["ir.http"]._verify_request_recaptcha_token("TEST") + + @mute_logger("odoo.addons.website_altcha.models.ir_http") + def test_solve_altcha_challenge_failure_04(self): + """Signature fails with wrong solution""" + payload = self.generate_and_solve_challenge() + payload.solution.derived_key += "01" + with MockRequest(self.env, website=self.website) as request: + request.params["altcha"] = payload.to_base64() + with self.assertRaises(UserError): + self.env["ir.http"]._verify_request_recaptcha_token("TEST") + + @mute_logger("odoo.addons.website_altcha.models.ir_http") + def test_solve_altcha_challenge_failure_05(self): + """Signature fails when expired""" + with freeze_time("2026-01-01 00:00:00"): + payload = self.generate_and_solve_challenge() + with MockRequest(self.env, website=self.website) as request: + request.params["altcha"] = payload.to_base64() + with self.assertRaises(UserError): + self.env["ir.http"]._verify_request_recaptcha_token("TEST") + + @mute_logger("odoo.addons.website_altcha.models.ir_http") + def test_solve_altcha_challenge_failure_06(self): + """Signature fails when reused""" + payload = self.generate_and_solve_challenge() + with MockRequest(self.env, website=self.website) as request: + request.params["altcha"] = payload.to_base64() + self.env["ir.http"]._verify_request_recaptcha_token("TEST") + with self.assertRaises(UserError): + self.env["ir.http"]._verify_request_recaptcha_token("TEST") + + def test_autovacuum(self): + with freeze_time("2026-01-01 00:00:00"): + payload = self.generate_and_solve_challenge() + with MockRequest(self.env, website=self.website): + key = ( + self.env["altcha.key"] + .sudo() + .search( + [ + ( + "key", + "=", + self.env["ir.http"]._get_altcha_key( + payload.challenge.signature + ), + ) + ] + ) + ) + self.assertTrue(key) + self.env["altcha.key"].sudo()._autovacuum_expired_keys() + self.assertFalse(key.exists()) + + def test_no_altcha_key_different_website(self): + """Test that a challenge from another website is not valid""" + # Create a second website without altcha keys + website = self.env["website"].create( + { + "name": "Test Website 2", + "domain": "test2", + "altcha_cost": 128, + } + ) + self.solve_altcha_challenge_ok() + with self.assertRaises(HTTPError), mute_logger("odoo.http"): + # The challenge should fail for website2 which has no altcha key configured + self.solve_altcha_challenge_ok(website=website) + + def test_altcha_configure_new_website(self): + website = self.env["website"].create( + { + "name": "Test Website 2", + "domain": "test2", + "altcha_cost": 128, + } + ) + self.solve_altcha_challenge_ok() + self.assertFalse(website.altcha_key, "Expected no altcha key for website 2") + self.assertFalse( + website.altcha_private_key, "Expected no altcha key for website 2" + ) + with Form(self.env["res.config.settings"]) as f: + f.website_id = website + self.assertFalse(f.altcha_enabled) + f.altcha_enabled = True + self.assertTrue( + website.altcha_key, "Expected altcha key to be generated for website 2" + ) + self.assertTrue( + website.altcha_private_key, + "Expected altcha private key to be generated for website 2", + ) + website.flush_recordset() + self.solve_altcha_challenge_ok(website=website) diff --git a/website_altcha/views/res_config_settings_views.xml b/website_altcha/views/res_config_settings_views.xml new file mode 100644 index 0000000000..cb215a4017 --- /dev/null +++ b/website_altcha/views/res_config_settings_views.xml @@ -0,0 +1,65 @@ + + + + + res.config.settings.view.form.inherit.cookiefirst + + res.config.settings + + + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
From 289aa2f7dcca4dfb51c7a666407aa1c1aa361afa Mon Sep 17 00:00:00 2001 From: oca-ci Date: Sun, 31 May 2026 04:41:05 +0000 Subject: [PATCH 3/8] [UPD] Update website_altcha.pot --- website_altcha/i18n/website_altcha.pot | 171 +++++++++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 website_altcha/i18n/website_altcha.pot diff --git a/website_altcha/i18n/website_altcha.pot b/website_altcha/i18n/website_altcha.pot new file mode 100644 index 0000000000..5ffdfad4f3 --- /dev/null +++ b/website_altcha/i18n/website_altcha.pot @@ -0,0 +1,171 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * website_altcha +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 18.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: website_altcha +#: model_terms:ir.ui.view,arch_db:website_altcha.res_config_settings_view_form +msgid "Add Altcha functionality" +msgstr "" + +#. module: website_altcha +#: model_terms:ir.ui.view,arch_db:website_altcha.res_config_settings_view_form +msgid "Algorithm" +msgstr "" + +#. module: website_altcha +#: model:ir.model.fields,field_description:website_altcha.field_res_config_settings__altcha_algorithm +#: model:ir.model.fields,field_description:website_altcha.field_website__altcha_algorithm +msgid "Altcha Algorithm" +msgstr "" + +#. module: website_altcha +#: model:ir.model.fields,field_description:website_altcha.field_res_config_settings__altcha_cost +#: model:ir.model.fields,field_description:website_altcha.field_website__altcha_cost +msgid "Altcha Cost" +msgstr "" + +#. module: website_altcha +#: model:ir.model,name:website_altcha.model_altcha_key +#: model:ir.model.fields,field_description:website_altcha.field_res_config_settings__altcha_key +#: model:ir.model.fields,field_description:website_altcha.field_website__altcha_key +msgid "Altcha Key" +msgstr "" + +#. module: website_altcha +#: model:ir.model.fields,field_description:website_altcha.field_res_config_settings__altcha_private_key +#: model:ir.model.fields,field_description:website_altcha.field_website__altcha_private_key +msgid "Altcha Private Key" +msgstr "" + +#. module: website_altcha +#: model:ir.model.fields,field_description:website_altcha.field_res_config_settings__altcha_timeout +#: model:ir.model.fields,field_description:website_altcha.field_website__altcha_timeout +msgid "Altcha Timeout" +msgstr "" + +#. module: website_altcha +#: model:ir.model,name:website_altcha.model_res_config_settings +msgid "Config Settings" +msgstr "" + +#. module: website_altcha +#: model_terms:ir.ui.view,arch_db:website_altcha.res_config_settings_view_form +msgid "Cost" +msgstr "" + +#. module: website_altcha +#: model:ir.model.fields,help:website_altcha.field_res_config_settings__altcha_cost +#: model:ir.model.fields,help:website_altcha.field_website__altcha_cost +msgid "" +"Cost factor for the hashing algorithm.\n" +" For PBKDF2, this is the number of iterations.\n" +" Default is 5000 for PBKDF2/SHA-512." +msgstr "" + +#. module: website_altcha +#: model:ir.model.fields,field_description:website_altcha.field_altcha_key__create_uid +msgid "Created by" +msgstr "" + +#. module: website_altcha +#: model:ir.model.fields,field_description:website_altcha.field_altcha_key__create_date +msgid "Created on" +msgstr "" + +#. module: website_altcha +#: model:ir.model.fields,field_description:website_altcha.field_altcha_key__display_name +msgid "Display Name" +msgstr "" + +#. module: website_altcha +#: model:ir.model.fields,field_description:website_altcha.field_res_config_settings__altcha_enabled +msgid "Enable Altcha" +msgstr "" + +#. module: website_altcha +#: model:ir.model.fields,help:website_altcha.field_res_config_settings__altcha_enabled +msgid "Enable Altcha functionality on the website." +msgstr "" + +#. module: website_altcha +#: model:ir.model.fields,field_description:website_altcha.field_altcha_key__expires_at +msgid "Expires At" +msgstr "" + +#. module: website_altcha +#: model_terms:ir.ui.view,arch_db:website_altcha.res_config_settings_view_form +msgid "HMAC key secret" +msgstr "" + +#. module: website_altcha +#: model_terms:ir.ui.view,arch_db:website_altcha.res_config_settings_view_form +msgid "HMAC secret" +msgstr "" + +#. module: website_altcha +#: model:ir.model,name:website_altcha.model_ir_http +msgid "HTTP Routing" +msgstr "" + +#. module: website_altcha +#: model:ir.model.fields,field_description:website_altcha.field_altcha_key__id +msgid "ID" +msgstr "" + +#. module: website_altcha +#: model:ir.model.fields,field_description:website_altcha.field_altcha_key__key +msgid "Key" +msgstr "" + +#. module: website_altcha +#: model:ir.model.fields,field_description:website_altcha.field_altcha_key__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: website_altcha +#: model:ir.model.fields,field_description:website_altcha.field_altcha_key__write_date +msgid "Last Updated on" +msgstr "" + +#. module: website_altcha +#. odoo-python +#: code:addons/website_altcha/models/ir_http.py:0 +msgid "Suspicious activity detected by Altcha" +msgstr "" + +#. module: website_altcha +#: model:ir.model.constraint,message:website_altcha.constraint_altcha_key_key_uniq +msgid "The Altcha key must be unique." +msgstr "" + +#. module: website_altcha +#: model:ir.model.fields,help:website_altcha.field_res_config_settings__altcha_timeout +#: model:ir.model.fields,help:website_altcha.field_website__altcha_timeout +msgid "Time in minutes before a captcha expires. Default is 5 minutes." +msgstr "" + +#. module: website_altcha +#: model_terms:ir.ui.view,arch_db:website_altcha.res_config_settings_view_form +msgid "Timeout" +msgstr "" + +#. module: website_altcha +#: model:ir.model.fields,field_description:website_altcha.field_altcha_key__used +msgid "Used" +msgstr "" + +#. module: website_altcha +#: model:ir.model,name:website_altcha.model_website +msgid "Website" +msgstr "" From 8fb5cda9e028cd2f12264ec150ac33cc35f5e58d Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Sun, 31 May 2026 04:45:21 +0000 Subject: [PATCH 4/8] [BOT] post-merge updates --- website_altcha/README.rst | 8 ++++-- website_altcha/static/description/index.html | 30 ++++++++++++-------- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/website_altcha/README.rst b/website_altcha/README.rst index 1b4f1c201b..e5d69cca7e 100644 --- a/website_altcha/README.rst +++ b/website_altcha/README.rst @@ -1,3 +1,7 @@ +.. image:: https://odoo-community.org/readme-banner-image + :target: https://odoo-community.org/get-involved?utm_source=readme + :alt: Odoo Community Association + ======================== Privacy Friendly Captcha ======================== @@ -7,13 +11,13 @@ Privacy Friendly Captcha !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:ad4756a7f15fb03bdbfe14d8f738109df9bc20d0af3d9c500b00fa14eb8aa46b + !! source digest: sha256:72f381043be58f2d2154c68ba7152e620c995760d9ce8280c5d49e161adbf924 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png :target: https://odoo-community.org/page/development-status :alt: Beta -.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png +.. |badge2| image:: https://img.shields.io/badge/license-AGPL--3-blue.png :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fwebsite-lightgray.png?logo=github diff --git a/website_altcha/static/description/index.html b/website_altcha/static/description/index.html index 2642fd6ff7..961c70b429 100644 --- a/website_altcha/static/description/index.html +++ b/website_altcha/static/description/index.html @@ -3,7 +3,7 @@ -Privacy Friendly Captcha +README.rst -
-

Privacy Friendly Captcha

+
+ + +Odoo Community Association + +
+

Privacy Friendly Captcha

-

Beta License: AGPL-3 OCA/website Translate me on Weblate Try me on Runboat

+

Beta License: AGPL-3 OCA/website Translate me on Weblate Try me on Runboat

This module allows to use a Captcha System completly handled by Odoo.

It relies on Altcha (https://altcha.org), an OpenSource captcha alternative.

@@ -388,7 +393,7 @@

Privacy Friendly Captcha

-

Use Cases / Context

+

Use Cases / Context

Currently, Odoo provides 2 options:

  • Google Recaptcha relies on tracking of the user. It implies cookies
  • @@ -402,7 +407,7 @@

    Use Cases / Context

    to spend more CPU, making it costly at scale.

-

Configuration

+

Configuration

Go to Configuration/Website, check “Enable Altcha” under “Privacy”. Some extra parameters will appear with all the ALTCHA information. This parameters are website dependent.

@@ -431,7 +436,7 @@

Configuration

-

Bug Tracker

+

Bug Tracker

Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed @@ -439,15 +444,15 @@

Bug Tracker

Do not contact contributors directly about support or help with technical issues.

-

Credits

+

Credits

-

Authors

+

Authors

  • Dixmit
-

Contributors

+

Contributors

-

Maintainers

+

Maintainers

This module is maintained by the OCA.

Odoo Community Association @@ -470,5 +475,6 @@

Maintainers

+
From ca49fe5300efc5189f70b9157f902872650cd718 Mon Sep 17 00:00:00 2001 From: mymage Date: Wed, 3 Jun 2026 06:29:15 +0000 Subject: [PATCH 5/8] Added translation using Weblate (Italian) --- website_altcha/i18n/it.po | 172 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 website_altcha/i18n/it.po diff --git a/website_altcha/i18n/it.po b/website_altcha/i18n/it.po new file mode 100644 index 0000000000..736331e543 --- /dev/null +++ b/website_altcha/i18n/it.po @@ -0,0 +1,172 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * website_altcha +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 18.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +#. module: website_altcha +#: model_terms:ir.ui.view,arch_db:website_altcha.res_config_settings_view_form +msgid "Add Altcha functionality" +msgstr "" + +#. module: website_altcha +#: model_terms:ir.ui.view,arch_db:website_altcha.res_config_settings_view_form +msgid "Algorithm" +msgstr "" + +#. module: website_altcha +#: model:ir.model.fields,field_description:website_altcha.field_res_config_settings__altcha_algorithm +#: model:ir.model.fields,field_description:website_altcha.field_website__altcha_algorithm +msgid "Altcha Algorithm" +msgstr "" + +#. module: website_altcha +#: model:ir.model.fields,field_description:website_altcha.field_res_config_settings__altcha_cost +#: model:ir.model.fields,field_description:website_altcha.field_website__altcha_cost +msgid "Altcha Cost" +msgstr "" + +#. module: website_altcha +#: model:ir.model,name:website_altcha.model_altcha_key +#: model:ir.model.fields,field_description:website_altcha.field_res_config_settings__altcha_key +#: model:ir.model.fields,field_description:website_altcha.field_website__altcha_key +msgid "Altcha Key" +msgstr "" + +#. module: website_altcha +#: model:ir.model.fields,field_description:website_altcha.field_res_config_settings__altcha_private_key +#: model:ir.model.fields,field_description:website_altcha.field_website__altcha_private_key +msgid "Altcha Private Key" +msgstr "" + +#. module: website_altcha +#: model:ir.model.fields,field_description:website_altcha.field_res_config_settings__altcha_timeout +#: model:ir.model.fields,field_description:website_altcha.field_website__altcha_timeout +msgid "Altcha Timeout" +msgstr "" + +#. module: website_altcha +#: model:ir.model,name:website_altcha.model_res_config_settings +msgid "Config Settings" +msgstr "" + +#. module: website_altcha +#: model_terms:ir.ui.view,arch_db:website_altcha.res_config_settings_view_form +msgid "Cost" +msgstr "" + +#. module: website_altcha +#: model:ir.model.fields,help:website_altcha.field_res_config_settings__altcha_cost +#: model:ir.model.fields,help:website_altcha.field_website__altcha_cost +msgid "" +"Cost factor for the hashing algorithm.\n" +" For PBKDF2, this is the number of iterations.\n" +" Default is 5000 for PBKDF2/SHA-512." +msgstr "" + +#. module: website_altcha +#: model:ir.model.fields,field_description:website_altcha.field_altcha_key__create_uid +msgid "Created by" +msgstr "" + +#. module: website_altcha +#: model:ir.model.fields,field_description:website_altcha.field_altcha_key__create_date +msgid "Created on" +msgstr "" + +#. module: website_altcha +#: model:ir.model.fields,field_description:website_altcha.field_altcha_key__display_name +msgid "Display Name" +msgstr "" + +#. module: website_altcha +#: model:ir.model.fields,field_description:website_altcha.field_res_config_settings__altcha_enabled +msgid "Enable Altcha" +msgstr "" + +#. module: website_altcha +#: model:ir.model.fields,help:website_altcha.field_res_config_settings__altcha_enabled +msgid "Enable Altcha functionality on the website." +msgstr "" + +#. module: website_altcha +#: model:ir.model.fields,field_description:website_altcha.field_altcha_key__expires_at +msgid "Expires At" +msgstr "" + +#. module: website_altcha +#: model_terms:ir.ui.view,arch_db:website_altcha.res_config_settings_view_form +msgid "HMAC key secret" +msgstr "" + +#. module: website_altcha +#: model_terms:ir.ui.view,arch_db:website_altcha.res_config_settings_view_form +msgid "HMAC secret" +msgstr "" + +#. module: website_altcha +#: model:ir.model,name:website_altcha.model_ir_http +msgid "HTTP Routing" +msgstr "" + +#. module: website_altcha +#: model:ir.model.fields,field_description:website_altcha.field_altcha_key__id +msgid "ID" +msgstr "" + +#. module: website_altcha +#: model:ir.model.fields,field_description:website_altcha.field_altcha_key__key +msgid "Key" +msgstr "" + +#. module: website_altcha +#: model:ir.model.fields,field_description:website_altcha.field_altcha_key__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: website_altcha +#: model:ir.model.fields,field_description:website_altcha.field_altcha_key__write_date +msgid "Last Updated on" +msgstr "" + +#. module: website_altcha +#. odoo-python +#: code:addons/website_altcha/models/ir_http.py:0 +msgid "Suspicious activity detected by Altcha" +msgstr "" + +#. module: website_altcha +#: model:ir.model.constraint,message:website_altcha.constraint_altcha_key_key_uniq +msgid "The Altcha key must be unique." +msgstr "" + +#. module: website_altcha +#: model:ir.model.fields,help:website_altcha.field_res_config_settings__altcha_timeout +#: model:ir.model.fields,help:website_altcha.field_website__altcha_timeout +msgid "Time in minutes before a captcha expires. Default is 5 minutes." +msgstr "" + +#. module: website_altcha +#: model_terms:ir.ui.view,arch_db:website_altcha.res_config_settings_view_form +msgid "Timeout" +msgstr "" + +#. module: website_altcha +#: model:ir.model.fields,field_description:website_altcha.field_altcha_key__used +msgid "Used" +msgstr "" + +#. module: website_altcha +#: model:ir.model,name:website_altcha.model_website +msgid "Website" +msgstr "" From 0f603051ac59e3108c44284ae6bc310b0320bcd0 Mon Sep 17 00:00:00 2001 From: mymage Date: Wed, 3 Jun 2026 07:01:15 +0000 Subject: [PATCH 6/8] Translated using Weblate (Italian) Currently translated at 100.0% (29 of 29 strings) Translation: website-18.0/website-18.0-website_altcha Translate-URL: https://translation.odoo-community.org/projects/website-18-0/website-18-0-website_altcha/it/ --- website_altcha/i18n/it.po | 62 +++++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 28 deletions(-) diff --git a/website_altcha/i18n/it.po b/website_altcha/i18n/it.po index 736331e543..4f917f8381 100644 --- a/website_altcha/i18n/it.po +++ b/website_altcha/i18n/it.po @@ -6,64 +6,66 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 18.0\n" "Report-Msgid-Bugs-To: \n" -"Last-Translator: Automatically generated\n" +"PO-Revision-Date: 2026-06-03 09:46+0000\n" +"Last-Translator: mymage \n" "Language-Team: none\n" "Language: it\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: \n" "Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 5.15.2\n" #. module: website_altcha #: model_terms:ir.ui.view,arch_db:website_altcha.res_config_settings_view_form msgid "Add Altcha functionality" -msgstr "" +msgstr "Aggiungi funzionalità Altcha" #. module: website_altcha #: model_terms:ir.ui.view,arch_db:website_altcha.res_config_settings_view_form msgid "Algorithm" -msgstr "" +msgstr "Algoritmo" #. module: website_altcha #: model:ir.model.fields,field_description:website_altcha.field_res_config_settings__altcha_algorithm #: model:ir.model.fields,field_description:website_altcha.field_website__altcha_algorithm msgid "Altcha Algorithm" -msgstr "" +msgstr "Algoritmo Altcha" #. module: website_altcha #: model:ir.model.fields,field_description:website_altcha.field_res_config_settings__altcha_cost #: model:ir.model.fields,field_description:website_altcha.field_website__altcha_cost msgid "Altcha Cost" -msgstr "" +msgstr "Costo Altcha" #. module: website_altcha #: model:ir.model,name:website_altcha.model_altcha_key #: model:ir.model.fields,field_description:website_altcha.field_res_config_settings__altcha_key #: model:ir.model.fields,field_description:website_altcha.field_website__altcha_key msgid "Altcha Key" -msgstr "" +msgstr "Chiave Altcha" #. module: website_altcha #: model:ir.model.fields,field_description:website_altcha.field_res_config_settings__altcha_private_key #: model:ir.model.fields,field_description:website_altcha.field_website__altcha_private_key msgid "Altcha Private Key" -msgstr "" +msgstr "Chiave privata Altcha" #. module: website_altcha #: model:ir.model.fields,field_description:website_altcha.field_res_config_settings__altcha_timeout #: model:ir.model.fields,field_description:website_altcha.field_website__altcha_timeout msgid "Altcha Timeout" -msgstr "" +msgstr "Timeout Altcha" #. module: website_altcha #: model:ir.model,name:website_altcha.model_res_config_settings msgid "Config Settings" -msgstr "" +msgstr "Impostazioni configurazione" #. module: website_altcha #: model_terms:ir.ui.view,arch_db:website_altcha.res_config_settings_view_form msgid "Cost" -msgstr "" +msgstr "Costo" #. module: website_altcha #: model:ir.model.fields,help:website_altcha.field_res_config_settings__altcha_cost @@ -73,100 +75,104 @@ msgid "" " For PBKDF2, this is the number of iterations.\n" " Default is 5000 for PBKDF2/SHA-512." msgstr "" +"Fattore di costo per l'algoritmo di hashing.\n" +" Per PBKDF2, questo rappresenta il numero di iterazioni.\n" +" Il valore predefinito è 5000 per PBKDF2/SHA-512." #. module: website_altcha #: model:ir.model.fields,field_description:website_altcha.field_altcha_key__create_uid msgid "Created by" -msgstr "" +msgstr "Creato da" #. module: website_altcha #: model:ir.model.fields,field_description:website_altcha.field_altcha_key__create_date msgid "Created on" -msgstr "" +msgstr "Creato il" #. module: website_altcha #: model:ir.model.fields,field_description:website_altcha.field_altcha_key__display_name msgid "Display Name" -msgstr "" +msgstr "Nome visualizzato" #. module: website_altcha #: model:ir.model.fields,field_description:website_altcha.field_res_config_settings__altcha_enabled msgid "Enable Altcha" -msgstr "" +msgstr "Abilita Altcha" #. module: website_altcha #: model:ir.model.fields,help:website_altcha.field_res_config_settings__altcha_enabled msgid "Enable Altcha functionality on the website." -msgstr "" +msgstr "Abilita la funzionalità Altcha sul sito web." #. module: website_altcha #: model:ir.model.fields,field_description:website_altcha.field_altcha_key__expires_at msgid "Expires At" -msgstr "" +msgstr "Scade alle" #. module: website_altcha #: model_terms:ir.ui.view,arch_db:website_altcha.res_config_settings_view_form msgid "HMAC key secret" -msgstr "" +msgstr "Segreto chiave HMAC" #. module: website_altcha #: model_terms:ir.ui.view,arch_db:website_altcha.res_config_settings_view_form msgid "HMAC secret" -msgstr "" +msgstr "Segreto HMAC" #. module: website_altcha #: model:ir.model,name:website_altcha.model_ir_http msgid "HTTP Routing" -msgstr "" +msgstr "Instradamento HTTP" #. module: website_altcha #: model:ir.model.fields,field_description:website_altcha.field_altcha_key__id msgid "ID" -msgstr "" +msgstr "ID" #. module: website_altcha #: model:ir.model.fields,field_description:website_altcha.field_altcha_key__key msgid "Key" -msgstr "" +msgstr "Chiave" #. module: website_altcha #: model:ir.model.fields,field_description:website_altcha.field_altcha_key__write_uid msgid "Last Updated by" -msgstr "" +msgstr "Ultimo aggiornamento di" #. module: website_altcha #: model:ir.model.fields,field_description:website_altcha.field_altcha_key__write_date msgid "Last Updated on" -msgstr "" +msgstr "Ultimo aggiornamento il" #. module: website_altcha #. odoo-python #: code:addons/website_altcha/models/ir_http.py:0 msgid "Suspicious activity detected by Altcha" -msgstr "" +msgstr "Attività sospetta rilevata da Altcha" #. module: website_altcha #: model:ir.model.constraint,message:website_altcha.constraint_altcha_key_key_uniq msgid "The Altcha key must be unique." -msgstr "" +msgstr "La chiave Altcha deve essere univoca." #. module: website_altcha #: model:ir.model.fields,help:website_altcha.field_res_config_settings__altcha_timeout #: model:ir.model.fields,help:website_altcha.field_website__altcha_timeout msgid "Time in minutes before a captcha expires. Default is 5 minutes." msgstr "" +"Tempo in minuti prima della scadenza di un captcha. Predefinito 5 minuti." #. module: website_altcha #: model_terms:ir.ui.view,arch_db:website_altcha.res_config_settings_view_form msgid "Timeout" -msgstr "" +msgstr "Timeout" #. module: website_altcha #: model:ir.model.fields,field_description:website_altcha.field_altcha_key__used msgid "Used" -msgstr "" +msgstr "Usata" #. module: website_altcha #: model:ir.model,name:website_altcha.model_website msgid "Website" -msgstr "" +msgstr "Sito web" From 10034491af92f8dab2950e8f6b596470d3b4df97 Mon Sep 17 00:00:00 2001 From: Holger Brunn Date: Fri, 5 Jun 2026 06:40:27 +0200 Subject: [PATCH 7/8] [IMP] website_altcha: pre-commit auto fixes --- requirements.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 requirements.txt diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000000..5d36fde523 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +# generated from manifests external_dependencies +altcha From ee7ab3eea22ce1a40728d482e54320ee065840bd Mon Sep 17 00:00:00 2001 From: Holger Brunn Date: Fri, 5 Jun 2026 06:40:27 +0200 Subject: [PATCH 8/8] [MIG] website_altcha: Migration to 17.0 --- website_altcha/README.rst | 16 ++++------ website_altcha/__manifest__.py | 2 +- website_altcha/models/altcha_key.py | 6 +++- website_altcha/static/description/index.html | 32 ++++++++----------- .../static/src/altcha/altcha.esm.js | 2 +- .../static/src/signup/signup.esm.js | 1 + 6 files changed, 27 insertions(+), 32 deletions(-) diff --git a/website_altcha/README.rst b/website_altcha/README.rst index e5d69cca7e..ec947d3484 100644 --- a/website_altcha/README.rst +++ b/website_altcha/README.rst @@ -1,7 +1,3 @@ -.. image:: https://odoo-community.org/readme-banner-image - :target: https://odoo-community.org/get-involved?utm_source=readme - :alt: Odoo Community Association - ======================== Privacy Friendly Captcha ======================== @@ -17,17 +13,17 @@ Privacy Friendly Captcha .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png :target: https://odoo-community.org/page/development-status :alt: Beta -.. |badge2| image:: https://img.shields.io/badge/license-AGPL--3-blue.png +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fwebsite-lightgray.png?logo=github - :target: https://github.com/OCA/website/tree/18.0/website_altcha + :target: https://github.com/OCA/website/tree/17.0/website_altcha :alt: OCA/website .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/website-18-0/website-18-0-website_altcha + :target: https://translation.odoo-community.org/projects/website-17-0/website-17-0-website_altcha :alt: Translate me on Weblate .. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png - :target: https://runboat.odoo-community.org/builds?repo=OCA/website&target_branch=18.0 + :target: https://runboat.odoo-community.org/builds?repo=OCA/website&target_branch=17.0 :alt: Try me on Runboat |badge1| |badge2| |badge3| |badge4| |badge5| @@ -93,7 +89,7 @@ Bug Tracker Bugs are tracked on `GitHub Issues `_. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed -`feedback `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -126,6 +122,6 @@ OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use. -This module is part of the `OCA/website `_ project on GitHub. +This module is part of the `OCA/website `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/website_altcha/__manifest__.py b/website_altcha/__manifest__.py index 2f506e0d84..490bde2689 100644 --- a/website_altcha/__manifest__.py +++ b/website_altcha/__manifest__.py @@ -5,7 +5,7 @@ "name": "Privacy Friendly Captcha", "summary": """Use self hosted privacy friendly captcha for verifying website users are not bots""", - "version": "18.0.1.0.0", + "version": "17.0.1.0.0", "license": "AGPL-3", "author": "Dixmit,Odoo Community Association (OCA)", "website": "https://github.com/OCA/website", diff --git a/website_altcha/models/altcha_key.py b/website_altcha/models/altcha_key.py index 7f4e1eaf70..dd7551f2ee 100644 --- a/website_altcha/models/altcha_key.py +++ b/website_altcha/models/altcha_key.py @@ -13,7 +13,11 @@ class AltchaKey(models.Model): used = fields.Boolean(default=False) _sql_constraints = [ - ("key_uniq", "unique(key)", "The Altcha key must be unique."), + ( + "key_unique", + "unique(key)", + "The Altcha key must be unique.", + ) ] @api.autovacuum diff --git a/website_altcha/static/description/index.html b/website_altcha/static/description/index.html index 961c70b429..0ce4fcc181 100644 --- a/website_altcha/static/description/index.html +++ b/website_altcha/static/description/index.html @@ -3,7 +3,7 @@ -README.rst +Privacy Friendly Captcha -
+
+

Privacy Friendly Captcha

- - -Odoo Community Association - -
-

Privacy Friendly Captcha

-

Beta License: AGPL-3 OCA/website Translate me on Weblate Try me on Runboat

+

Beta License: AGPL-3 OCA/website Translate me on Weblate Try me on Runboat

This module allows to use a Captcha System completly handled by Odoo.

It relies on Altcha (https://altcha.org), an OpenSource captcha alternative.

@@ -393,7 +388,7 @@

Privacy Friendly Captcha

-

Use Cases / Context

+

Use Cases / Context

Currently, Odoo provides 2 options:

  • Google Recaptcha relies on tracking of the user. It implies cookies
  • @@ -407,7 +402,7 @@

    Use Cases / Context

    to spend more CPU, making it costly at scale.

-

Configuration

+

Configuration

Go to Configuration/Website, check “Enable Altcha” under “Privacy”. Some extra parameters will appear with all the ALTCHA information. This parameters are website dependent.

@@ -436,23 +431,23 @@

Configuration

-

Bug Tracker

+

Bug Tracker

Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed -feedback.

+feedback.

Do not contact contributors directly about support or help with technical issues.

-

Credits

+

Credits

-

Authors

+

Authors

  • Dixmit
-

Contributors

+

Contributors

-

Maintainers

+

Maintainers

This module is maintained by the OCA.

Odoo Community Association @@ -470,11 +465,10 @@

Maintainers

OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use.

-

This module is part of the OCA/website project on GitHub.

+

This module is part of the OCA/website project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

-
diff --git a/website_altcha/static/src/altcha/altcha.esm.js b/website_altcha/static/src/altcha/altcha.esm.js index 4f18e82e33..d6c013d15c 100644 --- a/website_altcha/static/src/altcha/altcha.esm.js +++ b/website_altcha/static/src/altcha/altcha.esm.js @@ -1,4 +1,4 @@ -/* global document */ +/** @odoo-module **/ import {loadBundle} from "@web/core/assets"; import {session} from "@web/session"; diff --git a/website_altcha/static/src/signup/signup.esm.js b/website_altcha/static/src/signup/signup.esm.js index fb5de1032d..13f6e7918d 100644 --- a/website_altcha/static/src/signup/signup.esm.js +++ b/website_altcha/static/src/signup/signup.esm.js @@ -1,3 +1,4 @@ +/** @odoo-module **/ import "@website/snippets/s_website_form/000"; import {Altcha} from "@website_altcha/altcha/altcha.esm"; import publicWidget from "@web/legacy/js/public/public_widget";