SPDXVersion: SPDX-2.1 DataLicense: CC0-1.0 SPDXID: SPDXRef-DOCUMENT DocumentName: project DocumentNamespace: http://spdx.org/spdxdocs/spdx-v2.1-b97979e8-4c62-49e5-89d3-075bb1911b18 Creator: Person: Anonymous () Creator: Organization: Anonymous () Creator: Tool: reuse-6.1.0 Created: 2026-09-17T08:25:01Z CreatorComment: This document was created automatically using available reuse information consistent with REUSE. Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-1daf80d8bdc043cc22a51a87c714a52c Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-bdf5dcefefc032ab534ee2bd721778f8 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-5a768749c987f3a0bfe90cbabe5e6d10 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-e74783a634bc129947e4f1d0296559c9 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-3f844fe1cbf43f1ebe1e4e171e4fa820 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-aa7007ad3b009f4874270656bc4140a3 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-d270ae9a8ccca017fa90c22335830c2f Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-ef8f9b646ff2fd2a43135641f279a02c Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-38196f432e2c405f84536055c47df77d Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-7bcc80fe829702ee00868452de46d76f Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-bf33c3cc60199bb0dfe80765a2614d28 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-680cfe29c51065e3c584e1f0c8f79d67 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-b4cf03c13abd16fb35c238bc5882bdd0 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-e955c6febed0e6afa1db99ef7add3519 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-08f8215acdd2dba3cbecaae70a1680b8 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-c312b7368d5840cf8e3a83e4b868295c Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-5af366f8c3dad5f5c107063328b34c32 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-2991968d30b84c227c20fb4a1d292042 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-524aac921eefe8714f04b72d504769ab Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-27372a9708522ba402fa034a9412b04d Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-818d1103f3f350e23f0ac33631e4dc8b Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-fda18d4cd969339d3f64d30aeee3a16a Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-aa2a2668c94160d649b7afa4b70bd5be Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-4c9623393b765675cf9a29bf6362a69b Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-9ff7f2ce27d7e024872ac461211f5205 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-644040c6f3599f02cd33438659204571 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-d79860184909a5325dfe837c71b4f09f Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-492b9faa334fb8f1b7aa86b2e9de3918 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-049975838d8eb869d6df6f0962383465 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-90c3df5a9117a84096045b6226c7f472 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-87a2d84c5ffce18b4ae1fe166548609a Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-b98eb2c95cde57ee1bf4aa29ccc613f6 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-6821aa2ad09f86a9d57b9239c2e3f3fc Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-09d150f12366f5b4f793fd8ea43a226a Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-753c533bb8beeb598ea7a21ad3e6da35 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-31079b308933f0a8ee20a04eb993bae0 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-bade0ef48e9599daae9c80276d99ee89 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-2f34a19d4de7cea1a8154fa4bef6ff6e Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-fae8d67017da3161d53e25e1613d7eda Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-b30512da218040016c5966c0627ce35e Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-74e163e868e23d96285ffd6e3ee9c1af Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-e6c4967db4f5cf454200f2e86c56d423 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-2cdf62ad53cc857963ad2dedb51add9c Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-4a6f1fb3c5e49c2d700b47434ea787a7 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-454f29521fdc5c68cd55e71dd7468e7d Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-7befb881b3dd2992abdf5a0158ea36cc Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-e38ccb8364a1ae184cc5b54b1c2d4a87 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-c35557076f2074bc28d24c113e990424 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-eb5119f1f301e738497e88c78242c173 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-7a1c15dce9d1140ff36d0547531ff635 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-cc7b470009d0bba6e788d4a75ce6ce83 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-2ad54649fa4c574a66e5542422283fd0 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-9393601c7ed7ddd21047bab27d26de50 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-deecb78b6c5d7dd0c3d118cfb3b18c96 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-7c475b157bd8ae57222604e84e14f8a4 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-f1e41b9bbf9a206fc83e7308b05f1bac Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-76f0ff047b1ce33b8783bdd8f5090383 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-e607ec53c2225d81ac94f45ea0bcf40f Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-ae9beb11b53a4bcc10a70727c234a679 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-56f6998d264e587451f9b8f3d8a8f1d7 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-b83fcb3dd7359cf2da914ced5397bb1f Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-408efb8f95c5c2edef71a5a26acdc50a Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-fbc12a69c4bf39490771f0042099810e Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-fe98b0c89271de1d249456af0c12b5c8 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-15cc9b9bc14ef1ee95a456236204144c Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-2f2c2b078edc264aa680692550fd71f3 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-c30cda570056b450f91cf930efb3b085 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-ddbfb64852ab4c9d47ba985c18f1d734 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-405011458d91c5206db9bb83d5a5a0c4 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-3952496b431fc6cc2d37cd5a592c75f9 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-447d86d379378f6e55a546caede414ed Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-5df1a2de4e933b5c6c1f48f970833a5d Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-57332f12203aaf4c94503688f3cf25b2 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-568cac80f334aed608104995fca3293e Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-db9866c7e9c485c74e0b846bda28a653 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-86591f766080265f7ae84460172a8d84 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-f793ac2abdaf3aa5d88d9ef1fbd3020c Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-74037ff4b6dd5fdae0222050eab3eed0 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-2d9ebffa4255426a97f1c61a982e1bae Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-fa37093b15cb2359688e9eeff089ab0c Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-2c09932e1343ac4375748f9615a5f5c6 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-ab7010bafba1f2d31b822c3496de875a Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-fe4bdb4d05dfcf885527adf015587869 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-7028c0d0d706d2229528c9ffb2c756e8 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-cb8c81eda6e6b0c922c034f3079636f8 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-3244a5d087c6a3882073bc76ab886f61 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-906955478cd1d4c184ea3fa58d040282 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-c1a7ec1a329c02d2b88cac11be18ed0c Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-674dc417a19bcb60db8021bbc96b1f1b Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-59178e1ee6ae27d82da9bcae38bde689 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-d60a9d6384dd4c8ce6275bca325f1124 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-1472e8a602db221d1efab7cdf6c26ad2 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-57420942d9178a1ebb768d62208b6689 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-43dc5a2b2851e7709a311c1030c87c52 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-0dc7102cf6f4e3ba570382847984b906 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-3a4e53758db6e14c7e97dc7df5963318 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-74f29a3ac5baeca706126efd978e619b Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-c4266a30e3195ae5a1a43d74ffabd332 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-d5dbccccff449281b90fe66cf6293c8d Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-57ad52a7b6532012566d67ea55d782b5 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-6b0779e6ec4cc50ea356af5095353407 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-16ff89fed3ff421eac69ead3cec6c68d Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-ceb532f63f372ffd594d27f2c6174491 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-a71791ca704501106a5f06ad22d8bce6 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-24f5593fa910cb538aee30de142ccbe3 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-25329054a5f69d2e4e080bcc962768b6 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-13d269cd1cdcec5812b80933b195c3b1 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-33db4c52581d423f4e3b2aa70f2feee2 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-6ff3b01c33e4deb182f6c3e0b33ea7ff Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-fd17636703d2e51641dd53b7bd35fde3 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-96f6d1125ee842e0acf849df6767e19f Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-91182c83d770e0a8d39b5b8b4b03707c Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-e4a899b5c74dbc7e3aee2ef8862b9db3 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-b6b35b5b092f9f7b6c14697cf9cd02bc Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-df6b29426d87770a579db37f0240630d Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-9beaa11529aafdb0a65c1e5cddf908b6 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-6c4af68f699e9196d28dfadfd62a2bae Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-79c3fd31342f9bb6791e31b5ad7ab9ac Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-b48b06651a7fe437892c2ba1bd47cbd0 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-a3f982c3610fbf5660b4de8bb369ad3d Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-75fc3f52e756de0f7ed61bd9596f12d0 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-683c864ec0ab02588d32cbc2f71c55cf Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-3557dfecfd731659faf8f92a7470a019 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-29cd99f144e256e2d89b5b3d4698439c Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-3a8500df25b7410669fdd94db210d12b Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-206738cfe7ea6d5e0ed1674bbbcd957a Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-dfe914b11340a393f6332442f56dcbf7 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-c66e95e44ae1e3ff0faeb1ee08030a3e Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-b4e7e38b2155551e8254b0f99a1f3e5d Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-ecf423d9c38ca4dc30e4faa5df265456 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-b0d47237e7e8078275828b35bffa8d57 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-e647d99832786aa55a7cf108172391e8 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-53ee6e6ea78a76cb537e3b845ce44bab Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-425e39356f774c5e217c1d94de641e19 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-b11323d61e7df0e7658d0bd9903d1e97 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-53647e1138ae765894e96869068ce68d Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-8e1a3b0f9ae92b28a646a637ea770ec8 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-5e35652f8a5fb598c7fef61f999272bd Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-e2b4c215fa755624374ae7b068f5bbd5 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-e28c8b339669b84595a4b3a1cd8d1f05 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-31d93d370d2a1aa9c7d227070e94ed3b Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-da07118445c055b5f9154745a00f81ff Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-0637f076bb9983e3b950363ac15a100c Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-2395f00f19e2f6fe4602a1795810151c Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-7df8feaf9d37a215ab5dcabd68d69258 FileName: ./.github/workflows/ci.yml SPDXID: SPDXRef-1daf80d8bdc043cc22a51a87c714a52c FileChecksum: SHA1: c8f8e7ee65f3862631c2f8ecde62567f1815a4fc LicenseConcluded: NOASSERTION LicenseInfoInFile: AGPL-3.0-or-later LicenseInfoInFile: CC0-1.0 FileCopyrightText: SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors SPDX-FileCopyrightText: none FileName: ./.github/workflows/reuse.yml SPDXID: SPDXRef-bdf5dcefefc032ab534ee2bd721778f8 FileChecksum: SHA1: e161cf9fec66ea92c3a4a5b3c2732287d5d5a30d LicenseConcluded: NOASSERTION LicenseInfoInFile: CC0-1.0 LicenseInfoInFile: CC0-1.0 FileCopyrightText: SPDX-FileCopyrightText: 2022 Free Software Foundation Europe e.V. SPDX-FileCopyrightText: none FileName: ./.gitignore SPDXID: SPDXRef-5a768749c987f3a0bfe90cbabe5e6d10 FileChecksum: SHA1: 65cd84d158664bc8afbd7722a54447f9149d70cc LicenseConcluded: NOASSERTION LicenseInfoInFile: AGPL-3.0-or-later LicenseInfoInFile: CC0-1.0 FileCopyrightText: SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors SPDX-FileCopyrightText: none FileName: ./.tx/config SPDXID: SPDXRef-e74783a634bc129947e4f1d0296559c9 FileChecksum: SHA1: 8fb35b84b6962f8b98fdb429a0652733223b11df LicenseConcluded: NOASSERTION LicenseInfoInFile: AGPL-3.0-or-later LicenseInfoInFile: CC0-1.0 FileCopyrightText: SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors SPDX-FileCopyrightText: none FileName: ./AGENTS.md SPDXID: SPDXRef-3f844fe1cbf43f1ebe1e4e171e4fa820 FileChecksum: SHA1: aab9cf1ee395218cb57d1261d86ae9b76166d8ff LicenseConcluded: NOASSERTION LicenseInfoInFile: AGPL-3.0-or-later FileCopyrightText: SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors FileName: ./CLAUDE.md SPDXID: SPDXRef-aa7007ad3b009f4874270656bc4140a3 FileChecksum: SHA1: c140473a3a5fbe89301c99d9d0d1b76c5971f2c3 LicenseConcluded: NOASSERTION LicenseInfoInFile: AGPL-3.0-or-later FileCopyrightText: SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors FileName: ./README.md SPDXID: SPDXRef-d270ae9a8ccca017fa90c22335830c2f FileChecksum: SHA1: 3b369688c741f70c414eda7caea88cb8e5c5cc49 LicenseConcluded: NOASSERTION LicenseInfoInFile: AGPL-3.0-or-later FileCopyrightText: SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors FileName: ./appinfo/info.xml SPDXID: SPDXRef-ef8f9b646ff2fd2a43135641f279a02c FileChecksum: SHA1: ec857d52ac0bab859b0f12a0e5d13cbf9155965f LicenseConcluded: NOASSERTION LicenseInfoInFile: AGPL-3.0-or-later FileCopyrightText: SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors FileName: ./appinfo/routes.php SPDXID: SPDXRef-38196f432e2c405f84536055c47df77d FileChecksum: SHA1: ca76a40bfcf0fbcacf3061d95b0f539a5ae628f2 LicenseConcluded: NOASSERTION LicenseInfoInFile: AGPL-3.0-or-later FileCopyrightText: SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors FileName: ./composer.json SPDXID: SPDXRef-7bcc80fe829702ee00868452de46d76f FileChecksum: SHA1: a9e33f7032b3d4c8387df66c36f391ff64bee6f0 LicenseConcluded: NOASSERTION LicenseInfoInFile: CC0-1.0 FileCopyrightText: SPDX-FileCopyrightText: none FileName: ./composer.lock SPDXID: SPDXRef-bf33c3cc60199bb0dfe80765a2614d28 FileChecksum: SHA1: 2ed32029a567db93ee78b997426d4bf68dfe6842 LicenseConcluded: NOASSERTION LicenseInfoInFile: CC0-1.0 FileCopyrightText: SPDX-FileCopyrightText: none FileName: ./css/ApplyDialog-BTEIodbs.chunk.css SPDXID: SPDXRef-680cfe29c51065e3c584e1f0c8f79d67 FileChecksum: SHA1: a6a95c010142db72f4c0934748bd49c09ddb9d8d LicenseConcluded: NOASSERTION LicenseInfoInFile: AGPL-3.0-or-later FileCopyrightText: SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors FileName: ./css/ApplyDialog-BmzRWDb5.chunk.css SPDXID: SPDXRef-b4cf03c13abd16fb35c238bc5882bdd0 FileChecksum: SHA1: 835ff3d52a2e7026b67d2dd73761d5726a59b99b LicenseConcluded: NOASSERTION LicenseInfoInFile: AGPL-3.0-or-later FileCopyrightText: SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors FileName: ./css/ApplyDialog-BrNLYA73.chunk.css SPDXID: SPDXRef-e955c6febed0e6afa1db99ef7add3519 FileChecksum: SHA1: 50907a68411882f1e72838edb916d2df08283b21 LicenseConcluded: NOASSERTION LicenseInfoInFile: AGPL-3.0-or-later FileCopyrightText: SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors FileName: ./css/ApplyDialog-DKmKjGq2.chunk.css SPDXID: SPDXRef-08f8215acdd2dba3cbecaae70a1680b8 FileChecksum: SHA1: da8f7d707770096c204ff9a34bc15f3da63ebd68 LicenseConcluded: NOASSERTION LicenseInfoInFile: AGPL-3.0-or-later FileCopyrightText: SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors FileName: ./css/ApplyDialog-DeyeTbZM.chunk.css SPDXID: SPDXRef-c312b7368d5840cf8e3a83e4b868295c FileChecksum: SHA1: 3da2b693015982a19c1dadb8effd87232dc375b4 LicenseConcluded: NOASSERTION LicenseInfoInFile: AGPL-3.0-or-later FileCopyrightText: SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors FileName: ./css/ConfettiOverlay-CDk1RBSL.chunk.css SPDXID: SPDXRef-5af366f8c3dad5f5c107063328b34c32 FileChecksum: SHA1: 8acb1572a2515d1a6162b65c51a21938538f75f3 LicenseConcluded: NOASSERTION LicenseInfoInFile: AGPL-3.0-or-later FileCopyrightText: SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors FileName: ./css/ConfettiOverlay-CVYfl_Cc.chunk.css SPDXID: SPDXRef-2991968d30b84c227c20fb4a1d292042 FileChecksum: SHA1: 00313ee6258d034ff6078baf7a1c217141894f3e LicenseConcluded: NOASSERTION LicenseInfoInFile: AGPL-3.0-or-later FileCopyrightText: SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors FileName: ./css/ConfettiOverlay-CmCzv9eO.chunk.css SPDXID: SPDXRef-524aac921eefe8714f04b72d504769ab FileChecksum: SHA1: 3cac644c52a3ec4946a858879a4541d0a5a9f5ec LicenseConcluded: NOASSERTION LicenseInfoInFile: AGPL-3.0-or-later FileCopyrightText: SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors FileName: ./css/ConfettiOverlay-D8lAWf67.chunk.css SPDXID: SPDXRef-27372a9708522ba402fa034a9412b04d FileChecksum: SHA1: d9d76fda957a1c5ccde94b172f53d69cd1a3c731 LicenseConcluded: NOASSERTION LicenseInfoInFile: AGPL-3.0-or-later FileCopyrightText: SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors FileName: ./css/ConfettiOverlay-tFIL-KOZ.chunk.css SPDXID: SPDXRef-818d1103f3f350e23f0ac33631e4dc8b FileChecksum: SHA1: c1ed31b120b61fa5bae4268277aff74d695dbc47 LicenseConcluded: NOASSERTION LicenseInfoInFile: AGPL-3.0-or-later FileCopyrightText: SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors FileName: ./css/SettingsDialog---6QYi7E.chunk.css SPDXID: SPDXRef-fda18d4cd969339d3f64d30aeee3a16a FileChecksum: SHA1: fc39091e32f14bae0fb5131a9a4b2ee1478fc176 LicenseConcluded: NOASSERTION LicenseInfoInFile: AGPL-3.0-or-later LicenseInfoInFile: AGPL-3.0-or-later FileCopyrightText: SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors FileName: ./css/SettingsDialog-Bu4OLAR7.chunk.css SPDXID: SPDXRef-aa2a2668c94160d649b7afa4b70bd5be FileChecksum: SHA1: 45898de84c6a2196012d3df9c60b2d1d1203c969 LicenseConcluded: NOASSERTION LicenseInfoInFile: AGPL-3.0-or-later LicenseInfoInFile: AGPL-3.0-or-later FileCopyrightText: SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors FileName: ./css/SettingsDialog-C9c9RcxI.chunk.css SPDXID: SPDXRef-4c9623393b765675cf9a29bf6362a69b FileChecksum: SHA1: d306681e1d64eb74687c613979ea1f42c5126894 LicenseConcluded: NOASSERTION LicenseInfoInFile: AGPL-3.0-or-later LicenseInfoInFile: AGPL-3.0-or-later FileCopyrightText: SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors FileName: ./css/SettingsDialog-CZYAHKo1.chunk.css SPDXID: SPDXRef-9ff7f2ce27d7e024872ac461211f5205 FileChecksum: SHA1: bc9ac28fccdad951f4137e400790d9dba5458db0 LicenseConcluded: NOASSERTION LicenseInfoInFile: AGPL-3.0-or-later LicenseInfoInFile: AGPL-3.0-or-later FileCopyrightText: SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors FileName: ./css/SettingsDialog-Dz-qR0wv.chunk.css SPDXID: SPDXRef-644040c6f3599f02cd33438659204571 FileChecksum: SHA1: e9024b3430bcaa80eb7b4badb1c6de439bd4d732 LicenseConcluded: NOASSERTION LicenseInfoInFile: AGPL-3.0-or-later LicenseInfoInFile: AGPL-3.0-or-later FileCopyrightText: SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors FileName: ./css/SnippetDialog--RC3unyw.chunk.css SPDXID: SPDXRef-d79860184909a5325dfe837c71b4f09f FileChecksum: SHA1: fc2e9f3192a73ae06b7c3e4c085c1e83cf601742 LicenseConcluded: NOASSERTION LicenseInfoInFile: AGPL-3.0-or-later FileCopyrightText: SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors FileName: ./css/SnippetDialog-BytWXlNP.chunk.css SPDXID: SPDXRef-492b9faa334fb8f1b7aa86b2e9de3918 FileChecksum: SHA1: 96710b699e7d7d1e6f15dbe38f0b1588c565a32b LicenseConcluded: NOASSERTION LicenseInfoInFile: AGPL-3.0-or-later FileCopyrightText: SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors FileName: ./css/SnippetDialog-CFp416vY.chunk.css SPDXID: SPDXRef-049975838d8eb869d6df6f0962383465 FileChecksum: SHA1: 313e6f32b91edcff92951aabbecb3324e5476d96 LicenseConcluded: NOASSERTION LicenseInfoInFile: AGPL-3.0-or-later FileCopyrightText: SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors FileName: ./css/SnippetDialog-Cdcf9Hzc.chunk.css SPDXID: SPDXRef-90c3df5a9117a84096045b6226c7f472 FileChecksum: SHA1: e1abe4cbe9538333d00d3529d3f2fbb8959141d8 LicenseConcluded: NOASSERTION LicenseInfoInFile: AGPL-3.0-or-later FileCopyrightText: SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors FileName: ./css/SnippetDialog-Ce5mMUB_.chunk.css SPDXID: SPDXRef-87a2d84c5ffce18b4ae1fe166548609a FileChecksum: SHA1: 02b5a049af0ef797dc61d2b92aea9e233ab3a433 LicenseConcluded: NOASSERTION LicenseInfoInFile: AGPL-3.0-or-later FileCopyrightText: SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors FileName: ./css/dbdoctor-main.css SPDXID: SPDXRef-b98eb2c95cde57ee1bf4aa29ccc613f6 FileChecksum: SHA1: acfa4f5b3b0adc51979f7e996b30a012c1d31833 LicenseConcluded: NOASSERTION LicenseInfoInFile: AGPL-3.0-or-later FileCopyrightText: SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors FileName: ./css/main-BR5kosLV.chunk.css SPDXID: SPDXRef-6821aa2ad09f86a9d57b9239c2e3f3fc FileChecksum: SHA1: 089c70d28095506146eee23ff5f4845e5676d0ea LicenseConcluded: NOASSERTION LicenseInfoInFile: AGPL-3.0-or-later LicenseInfoInFile: AGPL-3.0-or-later FileCopyrightText: SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors FileName: ./css/main-CLSUCLHM.chunk.css SPDXID: SPDXRef-09d150f12366f5b4f793fd8ea43a226a FileChecksum: SHA1: 047cc53b1fa8b8b52a1699c1ff0cf2b74663821d LicenseConcluded: NOASSERTION LicenseInfoInFile: AGPL-3.0-or-later LicenseInfoInFile: AGPL-3.0-or-later FileCopyrightText: SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors FileName: ./css/main-CPy_sJxq.chunk.css SPDXID: SPDXRef-753c533bb8beeb598ea7a21ad3e6da35 FileChecksum: SHA1: 37f93e4a7d5c92a0c30c1e47bb0824870fa3b073 LicenseConcluded: NOASSERTION LicenseInfoInFile: AGPL-3.0-or-later LicenseInfoInFile: AGPL-3.0-or-later FileCopyrightText: SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors FileName: ./css/main-cG-ZVS9Q.chunk.css SPDXID: SPDXRef-31079b308933f0a8ee20a04eb993bae0 FileChecksum: SHA1: 4452e8404509e4359d3d82a331f5a1c710e0c2cf LicenseConcluded: NOASSERTION LicenseInfoInFile: AGPL-3.0-or-later LicenseInfoInFile: AGPL-3.0-or-later FileCopyrightText: SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors FileName: ./css/main-oBhRdWF9.chunk.css SPDXID: SPDXRef-bade0ef48e9599daae9c80276d99ee89 FileChecksum: SHA1: 9eb8152a44c727738c118b49da5279c43263d64f LicenseConcluded: NOASSERTION LicenseInfoInFile: AGPL-3.0-or-later LicenseInfoInFile: AGPL-3.0-or-later FileCopyrightText: SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors FileName: ./eslint.config.mjs SPDXID: SPDXRef-2f34a19d4de7cea1a8154fa4bef6ff6e FileChecksum: SHA1: 130abcf815a6fd74586ee75750e91bc79987cfad LicenseConcluded: NOASSERTION LicenseInfoInFile: CC0-1.0 FileCopyrightText: SPDX-FileCopyrightText: none FileName: ./img/app-color.svg SPDXID: SPDXRef-fae8d67017da3161d53e25e1613d7eda FileChecksum: SHA1: aa850d7036205dbb1495a42f57919b20f124eb4a LicenseConcluded: NOASSERTION LicenseInfoInFile: AGPL-3.0-or-later LicenseInfoInFile: AGPL-3.0-or-later FileCopyrightText: SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors FileName: ./img/app.svg SPDXID: SPDXRef-b30512da218040016c5966c0627ce35e FileChecksum: SHA1: 4c2ac5384e6cb8ba8168bb821d8dc8b12d2867f6 LicenseConcluded: NOASSERTION LicenseInfoInFile: AGPL-3.0-or-later LicenseInfoInFile: AGPL-3.0-or-later FileCopyrightText: SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors FileName: ./js/ApplyDialog-BNYMYN-v.chunk.mjs SPDXID: SPDXRef-74e163e868e23d96285ffd6e3ee9c1af FileChecksum: SHA1: 0195273beaccab1f9e9834ff72bea79209476c0c LicenseConcluded: NOASSERTION LicenseInfoInFile: AGPL-3.0-or-later LicenseInfoInFile: AGPL-3.0-or-later FileCopyrightText: SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors FileName: ./js/ApplyDialog-BNYMYN-v.chunk.mjs.map SPDXID: SPDXRef-e6c4967db4f5cf454200f2e86c56d423 FileChecksum: SHA1: 9bf73f17bc0e9bd72eb3c14e1379feeec5f1d25a LicenseConcluded: NOASSERTION LicenseInfoInFile: AGPL-3.0-or-later FileCopyrightText: SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors\r\n - SPDX-License-Identifier: AGPL-3.0-or-later\r\n-->\r\n\r\n\r\n\r\n\r\n\r\n"],"names":["props","__props","emit","__emit","busy","ref","result","watch","next","onApply","r","onUpdateOpen","v","_createBlock","_unref","NcDialog","t","_createVNode","NcButton","_createTextVNode","_toDisplayString","NcLoadingIcon","IconFlash","_createElementVNode","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","_hoisted_5","_hoisted_6","_hoisted_7","_hoisted_8","_hoisted_9","_hoisted_10","_createElementBlock","_hoisted_11","_hoisted_12","_normalizeClass","_hoisted_13","_openBlock"],"mappings":"usBA2EA,MAAMA,EAAQC,EAKRC,EAAOC,EAUPC,EAAOC,EAAI,EAAK,EAChBC,EAASD,EAAmG,IAAI,EAGtHE,EAAM,IAAMP,EAAM,KAAOQ,GAAS,CAC7BA,IACHJ,EAAK,MAAQ,GACbE,EAAO,MAAQ,KAEjB,CAAC,EAED,SAASG,GAAgB,CACxBL,EAAK,MAAQ,GACbF,EAAK,QAASF,EAAM,KAAOU,GAAM,CAChCN,EAAK,MAAQ,GACbE,EAAO,MAAQI,CAChB,CAAC,CACF,CAEA,SAASC,EAAaC,EAAkB,CACvCV,EAAK,cAAeU,CAAC,CACtB,cAzGQX,EAAA,UADPY,EAyDWC,EAAAC,CAAA,EAAA,OAvDT,KAAMD,EAAAE,CAAA,EAAC,WAAA,wBAAA,EACP,KAAMf,EAAA,KACP,KAAK,SACJ,gBAAaU,CAAA,GAoCH,UACV,IAEW,CAFXM,EAEWH,EAAAI,CAAA,EAAA,CAFD,QAAQ,WAAY,uBAAOP,EAAY,EAAA,EAAA,aAChD,IAAwE,CAArEQ,EAAAC,EAAAd,EAAA,OAAQ,QAAUQ,EAAAE,CAAA,sBAAyBF,EAAAE,CAAA,EAAC,WAAA,QAAA,CAAA,EAAA,CAAA,CAAA,SAGxCV,EAAA,OAAQ,sBADhBO,EAUWC,EAAAI,CAAA,EAAA,OARV,QAAQ,UACP,SAAUd,EAAA,MACV,QAAOK,CAAA,GACG,OACV,IAAwC,CAAnBL,EAAA,WAArBS,EAAwCC,EAAAO,CAAA,EAAA,OAAZ,KAAM,EAAA,SAClCR,EAA+BS,EAAA,OAAZ,KAAM,EAAA,gBACf,IACX,CADWH,EAAA,IACXC,EAAGhB,EAAA,MAAOU,EAAAE,CAAA,0BAA6BF,EAAAE,CAAA,EAAC,WAAA,OAAA,CAAA,EAAA,CAAA,CAAA,qCAhD1C,IAiCM,CAjCNO,EAiCM,MAjCNC,EAiCM,CAhCLD,EAGI,IAHJE,EAGI,CAFHF,EAAgC,SAAA,KAAAH,EAArBnB,EAAA,KAAK,IAAI,EAAA,CAAA,EACpBsB,EAA+D,OAA/DG,EAA+DN,EAAvBnB,EAAA,KAAK,QAAQ,EAAA,CAAA,CAAA,GAGtDsB,EASM,MATNI,EASM,CARLJ,EAGM,MAHNK,EAGM,CAFLL,EAAwE,OAAxEM,EAAwET,EAAnCN,EAAAE,CAAA,EAAC,WAAA,UAAA,CAAA,EAAA,CAAA,EACtCO,EAAkE,OAAlEO,EAAkEV,EAA9BnB,OAAK,OAAO,QAAQ,EAAA,CAAA,CAAA,GAEzDsB,EAGM,MAHNQ,EAGM,CAFLR,EAAyE,OAAzES,EAAyEZ,EAApCN,EAAAE,CAAA,EAAC,WAAA,WAAA,CAAA,EAAA,CAAA,EACtCO,EAAqG,OAArGU,EAAqGb,EAAtCnB,OAAK,OAAO,gBAAgB,EAAA,CAAA,CAAA,KAIpFA,EAAA,KAAK,OAAO,UAArBiC,EAEI,IAFJC,EAAsD,QAChDlC,EAAA,KAAK,MAAM,IAAI,EAAA,CAAA,YAGrBsB,EAEI,IAFJa,EAEIhB,EADAN,EAAAE,CAAA,EAAC,WAAA,sLAAA,CAAA,EAAA,CAAA,EAGMV,EAAA,WAAX4B,EAOM,MAAA,OAPa,MAAKG,EAAA,CAAC,uBAAsB,CAAA,8BAAA,CAA2C/B,EAAA,MAAO,QAAO,CAAA,CAAA,GAC9FA,EAAA,MAAO,aAAhB4B,EAEI,IAAAI,EAFqB,MACtBlB,EAAGN,EAAAE,CAAA,EAAC,WAAA,+CAAA,CAAA,IAAoEV,EAAA,MAAO,UAAQ,IAAA,IAAcA,EAAA,MAAO,UAAQ,IAAA,CAAA,EAAA,CAAA,IAEvHiC,IAAAL,EAEI,MAFM,MACPd,EAAGd,QAAO,OAASQ,EAAAE,CAAA,EAAC,WAAA,eAAA,CAAA,EAAA,CAAA,EAAA" FileName: ./js/Check-CG5Fo80g.chunk.mjs SPDXID: SPDXRef-2cdf62ad53cc857963ad2dedb51add9c FileChecksum: SHA1: b69f7f8d77bb9808c3aed7db15619b31eb89bfa6 LicenseConcluded: NOASSERTION LicenseInfoInFile: AGPL-3.0-or-later LicenseInfoInFile: MIT FileCopyrightText: SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors SPDX-FileCopyrightText: Rob Cresswell FileName: ./js/Check-CG5Fo80g.chunk.mjs.map SPDXID: SPDXRef-4a6f1fb3c5e49c2d700b47434ea787a7 FileChecksum: SHA1: b20b67f488cd64d783eee6045ad11af8a0578968 LicenseConcluded: NOASSERTION LicenseInfoInFile: AGPL-3.0-or-later FileCopyrightText: SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors FileName: ./js/ConfettiOverlay-Lcj26EH6.chunk.mjs SPDXID: SPDXRef-454f29521fdc5c68cd55e71dd7468e7d FileChecksum: SHA1: 43b5b85e8095c9786ecfc58c19a5a9087b87059b LicenseConcluded: NOASSERTION LicenseInfoInFile: AGPL-3.0-or-later LicenseInfoInFile: AGPL-3.0-or-later FileCopyrightText: SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors FileName: ./js/ConfettiOverlay-Lcj26EH6.chunk.mjs.map SPDXID: SPDXRef-7befb881b3dd2992abdf5a0158ea36cc FileChecksum: SHA1: b4cff8708ed3712a9490f2b76eeccfda4b09268b LicenseConcluded: NOASSERTION LicenseInfoInFile: AGPL-3.0-or-later FileCopyrightText: SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors\r\n - SPDX-License-Identifier: AGPL-3.0-or-later\r\n-->\r\n\r\n\r\n\r\n\r\n\r\n"],"names":["props","__props","emit","__emit","visible","ref","timer","PALETTE","pieces","computed","out","i","x","delay","duration","rot","sway","color","watch","next","_openBlock","_createElementBlock","_hoisted_1","_Fragment","_renderList","p","_normalizeStyle"],"mappings":"kQAiBA,MAAMA,EAAQC,EACRC,EAAOC,EAIPC,EAAUC,EAAI,EAAK,EACzB,IAAIC,EAAuB,KAI3B,MAAMC,EAAU,CAAC,UAAW,UAAW,UAAW,UAAW,UAAW,SAAS,EAC3EC,EAASC,EAAkB,IAAM,CACtC,MAAMC,EAAe,CAAA,EAErB,QAASC,EAAI,EAAGA,EAAI,GAAOA,IAAK,CAC/B,MAAMC,EAAI,KAAK,OAAA,EAAW,IACpBC,EAAQ,KAAK,OAAA,EAAW,GACxBC,EAAW,IAAM,KAAK,OAAA,EAAW,IACjCC,EAAM,KAAK,OAAA,EAAW,IACtBC,GAAQ,KAAK,OAAA,EAAW,IAAO,GAC/BC,EAAQV,EAAQI,EAAIJ,EAAQ,MAAM,EACxCG,EAAI,KAAK,CACR,MAAO,CACN,eAAgBE,EAAI,IACpB,mBAAoBC,EAAQ,IAC5B,sBAAuBC,EAAW,IAClC,iBAAkBC,EAAM,MACxB,kBAAmBC,EAAO,KAC1B,WAAYC,CAAA,CACb,CACA,CACF,CACA,OAAOP,CACR,CAAC,EAKD,OAAAQ,EAAM,IAAMlB,EAAM,QAAUmB,GAAS,CACpC,GAAKA,EAML,IAHe,OAAO,OAAW,KAC7B,OAAO,YACP,OAAO,WAAW,kCAAkC,EAAE,QAC9C,CACXjB,EAAK,MAAM,EACX,MACD,CACAE,EAAQ,MAAQ,GACZE,IAAU,MAAQ,aAAaA,CAAK,EACxCA,EAAQ,OAAO,WAAW,IAAM,CAC/BF,EAAQ,MAAQ,GAChBF,EAAK,MAAM,CACZ,EAAG,IAAI,EACR,EAAG,CAAE,UAAW,GAAM,SAnEVE,EAAA,OAAXgB,EAAA,EAAAC,EAMM,MANNC,EAMM,EALLF,EAAA,EAAA,EAAAC,EAIoBE,EAAA,KAAAC,EAHFhB,EAAA,MAAM,CAAfiB,EAAGd,SADZU,EAIoB,OAAA,CAFlB,IAAKV,EACN,MAAM,kBACL,MAAKe,EAAED,EAAE,KAAK,CAAA" FileName: ./js/SettingsDialog-K1mA7hFS.chunk.mjs SPDXID: SPDXRef-e38ccb8364a1ae184cc5b54b1c2d4a87 FileChecksum: SHA1: 454373188d9af916e0157590e1ab8d0632fe8ade LicenseConcluded: NOASSERTION LicenseInfoInFile: AGPL-3.0-or-later LicenseInfoInFile: AGPL-3.0-or-later LicenseInfoInFile: MIT FileCopyrightText: SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors SPDX-FileCopyrightText: Jeff Sagal SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors SPDX-FileCopyrightText: Rob Cresswell SPDX-FileCopyrightText: atomiks FileName: ./js/SettingsDialog-K1mA7hFS.chunk.mjs.map SPDXID: SPDXRef-c35557076f2074bc28d24c113e990424 FileChecksum: SHA1: a4474ef126accc84fd483402008fc521d966f264 LicenseConcluded: NOASSERTION LicenseInfoInFile: AGPL-3.0-or-later FileCopyrightText: SPDX-FileCopyrightText: 2020, 1040, 2026, 2026 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\nfunction findRanges(text, search) {\n const ranges = [];\n let currentIndex = 0;\n let index = text.toLowerCase().indexOf(search.toLowerCase(), currentIndex);\n let i = 0;\n while (index > -1 && i++ < text.length) {\n currentIndex = index + search.length;\n ranges.push({ start: index, end: currentIndex });\n index = text.toLowerCase().indexOf(search.toLowerCase(), currentIndex);\n }\n return ranges;\n}\nconst _sfc_main = defineComponent({\n name: \"NcHighlight\",\n props: {\n /**\n * The string to display\n */\n text: {\n type: String,\n default: \"\"\n },\n /**\n * The string to match and highlight\n */\n search: {\n type: String,\n default: \"\"\n },\n /**\n * The ranges to highlight, takes precedence over the search prop.\n */\n highlight: {\n type: Array,\n default: () => []\n }\n },\n computed: {\n /**\n * The indice ranges which should be highlighted.\n * If an array with ranges is provided, we use it. Otherwise\n * we calculate it based on the provided substring to highlight.\n *\n * @return The array of ranges to highlight\n */\n ranges() {\n let ranges = [];\n if (!this.search && this.highlight.length === 0) {\n return ranges;\n }\n if (this.highlight.length > 0) {\n ranges = this.highlight;\n } else {\n ranges = findRanges(this.text, this.search);\n }\n ranges.forEach((range, i) => {\n if (range.end < range.start) {\n ranges[i] = {\n start: range.end,\n end: range.start\n };\n }\n });\n ranges = ranges.reduce((validRanges, range) => {\n if (range.start < this.text.length && range.end > 0) {\n validRanges.push({\n start: range.start < 0 ? 0 : range.start,\n end: range.end > this.text.length ? this.text.length : range.end\n });\n }\n return validRanges;\n }, []);\n ranges.sort((a, b) => {\n return a.start - b.start;\n });\n ranges = ranges.reduce((mergedRanges, range) => {\n if (!mergedRanges.length) {\n mergedRanges.push(range);\n } else {\n const idx = mergedRanges.length - 1;\n if (mergedRanges[idx].end >= range.start) {\n mergedRanges[idx] = {\n start: mergedRanges[idx].start,\n end: Math.max(mergedRanges[idx].end, range.end)\n };\n } else {\n mergedRanges.push(range);\n }\n }\n return mergedRanges;\n }, []);\n return ranges;\n },\n /**\n * Calculate the different chunks to show based on the ranges to highlight.\n */\n chunks() {\n if (this.ranges.length === 0) {\n return [{\n start: 0,\n end: this.text.length,\n highlight: false,\n text: this.text\n }];\n }\n const chunks = [];\n let currentIndex = 0;\n let currentRange = 0;\n while (currentIndex < this.text.length) {\n const range = this.ranges[currentRange];\n if (range.start === currentIndex) {\n chunks.push({\n ...range,\n highlight: true,\n text: this.text.slice(range.start, range.end)\n });\n currentRange++;\n currentIndex = range.end;\n if (currentRange >= this.ranges.length && currentIndex < this.text.length) {\n chunks.push({\n start: currentIndex,\n end: this.text.length,\n highlight: false,\n text: this.text.slice(currentIndex)\n });\n currentIndex = this.text.length;\n }\n continue;\n }\n chunks.push({\n start: currentIndex,\n end: range.start,\n highlight: false,\n text: this.text.slice(currentIndex, range.start)\n });\n currentIndex = range.start;\n }\n return chunks;\n }\n },\n /**\n * The render function to display the component\n */\n render() {\n if (!this.ranges.length) {\n return h(\"span\", {}, this.text);\n }\n return h(\"span\", {}, this.chunks.map((chunk) => {\n return chunk.highlight ? h(\"strong\", {}, chunk.text) : chunk.text;\n }));\n }\n});\nexport {\n _sfc_main as _,\n findRanges as f\n};\n//# sourceMappingURL=NcHighlight.vue_vue_type_script_lang-DnWQDM_2.mjs.map\n","import '../assets/NcEllipsisedOption-CPWbbgBy.css';\nimport { _ as _sfc_main$1, f as findRanges } from \"./NcHighlight.vue_vue_type_script_lang-DnWQDM_2.mjs\";\nimport { resolveComponent, openBlock, createElementBlock, createVNode, createBlock, createCommentVNode } from \"vue\";\nimport { _ as _export_sfc } from \"./_plugin-vue_export-helper-1tPrXgE0.mjs\";\nconst _sfc_main = {\n name: \"NcEllipsisedOption\",\n components: {\n NcHighlight: _sfc_main$1\n },\n props: {\n /**\n * The text to be display in one line. If it is longer than 10 characters, it is be truncated with ellipsis in the end but keeping up to 10 last characters to fit the parent container.\n */\n name: {\n type: String,\n default: \"\"\n },\n /**\n * The search value to highlight in the text\n */\n search: {\n type: String,\n default: \"\"\n }\n },\n computed: {\n needsTruncate() {\n return this.name && this.name.length >= 10;\n },\n /**\n * Index at which to split the name if it is longer than 10 characters.\n *\n * @return {number} The position at which to split\n */\n split() {\n return this.name.length - Math.min(Math.floor(this.name.length / 2), 10);\n },\n part1() {\n if (this.needsTruncate) {\n return this.name.slice(0, this.split);\n }\n return this.name;\n },\n part2() {\n if (this.needsTruncate) {\n return this.name.slice(this.split);\n }\n return \"\";\n },\n /**\n * The ranges to highlight. Since we split the string for ellipsising,\n * the Highlight component cannot figure this out itself and needs the ranges provided.\n *\n * @return {Array} The array with the ranges to highlight\n */\n highlight1() {\n if (!this.search) {\n return [];\n }\n return findRanges(this.name, this.search);\n },\n /**\n * We shift the ranges for the second part by the position of the split.\n * Ranges out of the string length are discarded by the Highlight component,\n * so we don't need to take care of this here.\n *\n * @return {Array} The array with the ranges to highlight\n */\n highlight2() {\n return this.highlight1.map((range) => {\n return {\n start: range.start - this.split,\n end: range.end - this.split\n };\n });\n }\n }\n};\nconst _hoisted_1 = [\"title\"];\nfunction _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {\n const _component_NcHighlight = resolveComponent(\"NcHighlight\");\n return openBlock(), createElementBlock(\"span\", {\n dir: \"auto\",\n class: \"name-parts\",\n title: $props.name\n }, [\n createVNode(_component_NcHighlight, {\n class: \"name-parts__first\",\n text: $options.part1,\n search: $props.search,\n highlight: $options.highlight1\n }, null, 8, [\"text\", \"search\", \"highlight\"]),\n $options.part2 ? (openBlock(), createBlock(_component_NcHighlight, {\n key: 0,\n class: \"name-parts__last\",\n text: $options.part2,\n search: $props.search,\n highlight: $options.highlight2\n }, null, 8, [\"text\", \"search\", \"highlight\"])) : createCommentVNode(\"\", true)\n ], 8, _hoisted_1);\n}\nconst NcEllipsisedOption = /* @__PURE__ */ _export_sfc(_sfc_main, [[\"render\", _sfc_render], [\"__scopeId\", \"data-v-a612f185\"]]);\nexport {\n NcEllipsisedOption as N\n};\n//# sourceMappingURL=NcEllipsisedOption-D6Amb91K.mjs.map\n","import '../assets/NcSelect-CvDEQAjD.css';\nimport { autoUpdate, computePosition, offset, flip, shift, limitShift } from \"@floating-ui/dom\";\nimport { VueSelect } from \"@nextcloud/vue-select\";\nimport { resolveComponent, openBlock, createBlock, mergeProps, createSlots, withCtx, createTextVNode, toDisplayString, createCommentVNode, renderSlot, normalizeProps, guardReactiveProps, createVNode, createElementVNode, toHandlers, renderList, warn, h } from \"vue\";\nimport { C as ChevronDown } from \"./ChevronDown-C6gc637b.mjs\";\nimport { I as IconClose } from \"./Close-CuhcJnX2.mjs\";\nimport { N as NcEllipsisedOption } from \"./NcEllipsisedOption-D6Amb91K.mjs\";\nimport { N as NcLoadingIcon } from \"./NcLoadingIcon-BOVpFVQz.mjs\";\nimport { r as register, g as t17, a as t } from \"./_l10n-wdIzZwir.mjs\";\nimport { c as createElementId } from \"./createElementId-DhjFt1I9.mjs\";\nimport { a as isLegacy } from \"./legacy-BoqDmOCa.mjs\";\nimport { _ as _export_sfc } from \"./_plugin-vue_export-helper-1tPrXgE0.mjs\";\nregister(t17);\nconst _sfc_main = {\n name: \"NcSelect\",\n components: {\n ChevronDown,\n NcEllipsisedOption,\n NcLoadingIcon,\n VueSelect\n },\n props: {\n // Add VueSelect props to $props\n ...VueSelect.props,\n ...VueSelect.mixins.reduce((allProps, mixin) => ({ ...allProps, ...mixin.props }), {}),\n /**\n * `aria-label` for the clear input button\n */\n ariaLabelClearSelected: {\n type: String,\n default: t(\"Clear selected\")\n },\n /**\n * `aria-label` for the search input\n *\n * A descriptive `inputLabel` is preferred as this is not visible.\n */\n ariaLabelCombobox: {\n type: String,\n default: null\n },\n /**\n * `aria-label` for the listbox element\n */\n ariaLabelListbox: {\n type: String,\n default: t(\"Options\")\n },\n /**\n * Allows to customize the `aria-label` for the deselect-option button\n * The default is \"Deselect \" + optionLabel\n *\n * @type {(optionLabel: string) => string}\n */\n ariaLabelDeselectOption: {\n type: Function,\n default: (optionLabel) => t(\"Deselect {option}\", { option: optionLabel })\n },\n /**\n * Append the dropdown element to the end of the body\n * and size/position it dynamically.\n *\n * @see https://vue-select.org/api/props.html#appendtobody\n */\n appendToBody: {\n type: Boolean,\n default: true\n },\n /**\n * When `appendToBody` is true, this function is responsible for\n * positioning the drop down list.\n *\n * If a function is returned from `calculatePosition`, it will\n * be called when the drop down list is removed from the DOM.\n * This allows for any garbage collection you may need to do.\n *\n * @see https://vue-select.org/api/props.html#calculateposition\n */\n calculatePosition: {\n type: Function,\n default: null\n },\n /**\n * Keep the dropdown open after selecting an option.\n *\n * @default false\n * @since 8.25.0\n */\n keepOpen: {\n type: Boolean,\n default: false\n },\n /**\n * Replace default vue-select components\n *\n * @see https://vue-select.org/api/props.html#components\n */\n components: {\n type: Object,\n default: () => ({\n Deselect: {\n render: () => h(IconClose, {\n size: 20,\n fillColor: \"var(--vs-controls-color)\",\n style: [\n { cursor: \"pointer\" }\n ]\n })\n }\n })\n },\n /**\n * Sets the maximum number of options to display in the dropdown list\n */\n limit: {\n type: Number,\n default: null\n },\n /**\n * Disable the component\n *\n * @see https://vue-select.org/api/props.html#disabled\n */\n disabled: {\n type: Boolean,\n default: false\n },\n /**\n * Determines whether the dropdown should be open.\n * Receives the component instance as the only argument.\n *\n * @see https://vue-select.org/api/props.html#dropdownshouldopen\n */\n dropdownShouldOpen: {\n type: Function,\n default: ({ noDrop, open }) => {\n return noDrop ? false : open;\n }\n },\n /**\n * Callback to determine if the provided option should\n * match the current search text. Used to determine\n * if the option should be displayed.\n *\n * Defaults to the internal vue-select function documented at the link\n * below\n *\n * @see https://vue-select.org/api/props.html#filterby\n */\n filterBy: {\n type: Function,\n default: null\n },\n /**\n * Class for the `input`\n *\n * Necessary for use in NcActionInput\n */\n inputClass: {\n type: [String, Object],\n default: null\n },\n /**\n * Input element id\n */\n inputId: {\n type: String,\n default: () => createElementId()\n },\n /**\n * Visible label for the input element\n */\n inputLabel: {\n type: String,\n default: null\n },\n /**\n * Pass true if you are using an external label\n */\n labelOutside: {\n type: Boolean,\n default: false\n },\n /**\n * Display a visible border around dropdown options\n * which have keyboard focus\n */\n keyboardFocusBorder: {\n type: Boolean,\n default: true\n },\n /**\n * Key of the displayed label for object options\n *\n * Defaults to the internal vue-select string documented at the link\n * below\n *\n * @see https://vue-select.org/api/props.html#label\n */\n label: {\n type: String,\n default: null\n },\n /**\n * Show the loading icon\n *\n * @see https://vue-select.org/api/props.html#loading\n */\n loading: {\n type: Boolean,\n default: false\n },\n /**\n * Allow selection of multiple options\n *\n * @see https://vue-select.org/api/props.html#multiple\n */\n multiple: {\n type: Boolean,\n default: false\n },\n /**\n * Disable automatic wrapping when selected options overflow the width\n */\n noWrap: {\n type: Boolean,\n default: false\n },\n /**\n * Array of options\n *\n * @type {Array>}\n *\n * @see https://vue-select.org/api/props.html#options\n */\n options: {\n type: Array,\n default: () => []\n },\n /**\n * Placeholder text\n *\n * @see https://vue-select.org/api/props.html#placeholder\n */\n placeholder: {\n type: String,\n default: \"\"\n },\n /**\n * Customized component's response to keydown events while the search input has focus\n *\n * @see https://vue-select.org/guide/keydown.html#mapkeydown\n */\n mapKeydown: {\n type: Function,\n /**\n * Patched Vue-Select keydown events handlers map to stop Escape propagation in open select\n *\n * @param {Record void>} map - Mapped keyCode to handlers { : }\n * @param {import('vue').ComponentPublicInstance} vm - VueSelect instance\n * @return {Record void>} patched keydown event handlers\n */\n default(map, vm) {\n return {\n ...map,\n /**\n * Patched Escape handler to stop propagation from open select\n *\n * @param {KeyboardEvent} event - default keydown event handler\n */\n 27: (event) => {\n if (vm.open) {\n event.stopPropagation();\n }\n map[27](event);\n }\n };\n }\n },\n /**\n * A unique identifier used to generate IDs and DOM attributes. Must be unique for every instance of the component.\n *\n * @see https://vue-select.org/api/props.html#uid\n */\n uid: {\n type: String,\n default: () => createElementId()\n },\n /**\n * When `appendToBody` is true, this sets the placement of the dropdown\n *\n * @type {'bottom' | 'top'}\n */\n placement: {\n type: String,\n default: \"bottom\"\n },\n /**\n * If false, the focused dropdown option will not be reset when filtered\n * options change\n */\n resetFocusOnOptionsChange: {\n type: Boolean,\n default: true\n },\n /**\n * Currently selected value\n *\n * The `v-model` directive may be used for two-way data binding\n *\n * @type {string | number | Record | Array}\n *\n * @see https://vue-select.org/api/props.html#value\n */\n modelValue: {\n type: [String, Number, Object, Array],\n default: null\n },\n /**\n * Enable if a value is required for native form validation\n */\n required: {\n type: Boolean,\n default: false\n },\n /**\n * Any available prop\n *\n * @see https://vue-select.org/api/props.html\n */\n // Not an actual prop but needed to show in vue-styleguidist docs\n // eslint-disable-next-line\n \" \": {}\n },\n emits: [\n /**\n * All events from https://vue-select.org/api/events.html\n */\n // Not an actual event but needed to show in vue-styleguidist docs\n \" \",\n \"update:modelValue\"\n ],\n setup() {\n const clickableArea = Number.parseInt(window.getComputedStyle(document.body).getPropertyValue(\"--default-clickable-area\"));\n const gridBaseLine = Number.parseInt(window.getComputedStyle(document.body).getPropertyValue(\"--default-grid-baseline\"));\n const avatarSize = clickableArea - 2 * gridBaseLine;\n return {\n avatarSize,\n isLegacy\n };\n },\n data() {\n return {\n search: \"\"\n };\n },\n computed: {\n inputRequired() {\n if (!this.required) {\n return null;\n }\n return this.modelValue === null || Array.isArray(this.modelValue) && this.modelValue.length === 0;\n },\n localCalculatePosition() {\n if (this.calculatePosition !== null) {\n return this.calculatePosition;\n }\n return (dropdownMenu, component, { width }) => {\n dropdownMenu.style.width = width;\n const addClass = {\n name: \"addClass\",\n fn() {\n dropdownMenu.classList.add(\"vs__dropdown-menu--floating\");\n return {};\n }\n };\n const togglePlacementClass = {\n name: \"togglePlacementClass\",\n fn({ placement }) {\n component.$el.classList.toggle(\n \"select--drop-up\",\n placement === \"top\"\n );\n dropdownMenu.classList.toggle(\n \"vs__dropdown-menu--floating-placement-top\",\n placement === \"top\"\n );\n return {};\n }\n };\n const updatePosition = () => {\n computePosition(component.$refs.toggle, dropdownMenu, {\n placement: this.placement,\n middleware: [\n offset(-1),\n addClass,\n togglePlacementClass,\n // Match popperjs default collision prevention behavior by appending the following middleware in order\n flip(),\n shift({ limiter: limitShift() })\n ]\n }).then(({ x, y }) => {\n Object.assign(dropdownMenu.style, {\n left: `${x}px`,\n top: `${y}px`,\n width: `${component.$refs.toggle.getBoundingClientRect().width}px`\n });\n });\n };\n const cleanup = autoUpdate(\n component.$refs.toggle,\n dropdownMenu,\n updatePosition\n );\n return cleanup;\n };\n },\n localFilterBy() {\n return this.filterBy ?? VueSelect.props.filterBy.default;\n },\n localLabel() {\n return this.label ?? VueSelect.props.label.default;\n },\n propsToForward() {\n const vueSelectKeys = [\n ...Object.keys(VueSelect.props),\n ...VueSelect.mixins.flatMap((mixin) => Object.keys(mixin.props ?? {}))\n ];\n const initialPropsToForward = Object.fromEntries(Object.entries(this.$props).filter(([key, _value]) => vueSelectKeys.includes(key)));\n const propsToForward = {\n ...initialPropsToForward,\n // Custom overrides of vue-select props\n calculatePosition: this.localCalculatePosition,\n closeOnSelect: !this.keepOpen,\n filterBy: this.localFilterBy,\n label: this.localLabel\n };\n return propsToForward;\n }\n },\n mounted() {\n if (!this.labelOutside && !this.inputLabel && !this.ariaLabelCombobox) {\n warn(\"[NcSelect] An `inputLabel` or `ariaLabelCombobox` should be set. If an external label is used, `labelOutside` should be set to `true`.\");\n }\n if (this.inputLabel && this.ariaLabelCombobox) {\n warn(\"[NcSelect] Only one of `inputLabel` or `ariaLabelCombobox` should to be set.\");\n }\n },\n methods: {\n t\n }\n};\nconst _hoisted_1 = [\"for\"];\nconst _hoisted_2 = [\"required\"];\nfunction _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {\n const _component_ChevronDown = resolveComponent(\"ChevronDown\");\n const _component_NcEllipsisedOption = resolveComponent(\"NcEllipsisedOption\");\n const _component_NcLoadingIcon = resolveComponent(\"NcLoadingIcon\");\n const _component_VueSelect = resolveComponent(\"VueSelect\");\n return openBlock(), createBlock(_component_VueSelect, mergeProps({\n class: [\"select\", {\n \"select--legacy\": $setup.isLegacy,\n \"select--no-wrap\": $props.noWrap\n }]\n }, $options.propsToForward, {\n onSearch: _cache[0] || (_cache[0] = ($event) => $data.search = $event),\n \"onUpdate:modelValue\": _cache[1] || (_cache[1] = ($event) => _ctx.$emit(\"update:modelValue\", $event))\n }), createSlots({\n search: withCtx(({ attributes, events }) => [\n createElementVNode(\"input\", mergeProps({\n class: [\"vs__search\", [$props.inputClass]]\n }, attributes, {\n required: $options.inputRequired,\n dir: \"auto\"\n }, toHandlers(events, true)), null, 16, _hoisted_2)\n ]),\n \"open-indicator\": withCtx(({ attributes }) => [\n createVNode(_component_ChevronDown, mergeProps(attributes, {\n fillColor: \"var(--vs-controls-color)\",\n style: {\n cursor: !$props.disabled ? \"pointer\" : null\n },\n size: 26\n }), null, 16, [\"style\"])\n ]),\n option: withCtx((option) => [\n renderSlot(_ctx.$slots, \"option\", normalizeProps(guardReactiveProps(option)), () => [\n createVNode(_component_NcEllipsisedOption, {\n name: String(option[$options.localLabel]),\n search: $data.search\n }, null, 8, [\"name\", \"search\"])\n ])\n ]),\n \"selected-option\": withCtx((selectedOption) => [\n renderSlot(_ctx.$slots, \"selected-option\", normalizeProps(guardReactiveProps(selectedOption)), () => [\n createVNode(_component_NcEllipsisedOption, {\n name: String(selectedOption[$options.localLabel]),\n search: $data.search\n }, null, 8, [\"name\", \"search\"])\n ])\n ]),\n spinner: withCtx((spinner) => [\n spinner.loading ? (openBlock(), createBlock(_component_NcLoadingIcon, { key: 0 })) : createCommentVNode(\"\", true)\n ]),\n \"no-options\": withCtx(() => [\n createTextVNode(toDisplayString($options.t(\"No results\")), 1)\n ]),\n _: 2\n }, [\n !$props.labelOutside && $props.inputLabel ? {\n name: \"header\",\n fn: withCtx(() => [\n createElementVNode(\"label\", {\n for: $props.inputId,\n class: \"select__label\"\n }, toDisplayString($props.inputLabel), 9, _hoisted_1)\n ]),\n key: \"0\"\n } : void 0,\n renderList(_ctx.$slots, (_, name) => {\n return {\n name,\n fn: withCtx((data) => [\n renderSlot(_ctx.$slots, name, normalizeProps(guardReactiveProps(data)))\n ])\n };\n })\n ]), [\"class\"]);\n}\nconst NcSelect = /* @__PURE__ */ _export_sfc(_sfc_main, [[\"render\", _sfc_render]]);\nexport {\n NcSelect as N\n};\n//# sourceMappingURL=NcSelect--kERLlBK.mjs.map\n","\n\n","/**\r\n * SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors\r\n * SPDX-License-Identifier: AGPL-3.0-or-later\r\n */\r\n\r\nimport type { AuditRow, Settings } from '../api/types'\r\n\r\nimport { defineStore } from 'pinia'\r\nimport { ref } from 'vue'\r\nimport * as api from '../api/client'\r\nimport logger from '../utils/logger'\r\n\r\nexport const useSettingsStore = defineStore('dbdoctor/settings', () => {\r\n\tconst settings = ref(null)\r\n\tconst audit = ref([])\r\n\tconst loading = ref(false)\r\n\tconst error = ref(null)\r\n\r\n\tasync function load(): Promise {\r\n\t\tloading.value = true\r\n\t\ttry {\r\n\t\t\tsettings.value = await api.getSettings()\r\n\t\t\taudit.value = await api.getAudit(50)\r\n\t\t\terror.value = null\r\n\t\t} catch (e) {\r\n\t\t\terror.value = (e as Error).message ?? 'Could not load settings.'\r\n\t\t\tlogger.error('settings load failed', e)\r\n\t\t} finally {\r\n\t\t\tloading.value = false\r\n\t\t}\r\n\t}\r\n\r\n\tasync function update(patch: Parameters[0]): Promise {\r\n\t\tsettings.value = await api.updateSettings(patch)\r\n\t}\r\n\r\n\tasync function refreshAudit(): Promise {\r\n\t\taudit.value = await api.getAudit(50)\r\n\t}\r\n\r\n\treturn { settings, audit, loading, error, load, update, refreshAudit }\r\n})\r\n","\r\n\r\n\r\n\r\n\r\n\r\n"],"names":["hasWindow","getNodeName","node","isNode","getWindow","_node$ownerDocument","getDocumentElement","_ref","value","isElement","isHTMLElement","isShadowRoot","isOverflowElement","element","overflow","overflowX","overflowY","display","getComputedStyle","isTableElement","isTopLayer","willChangeRe","containRe","isNotNone","isWeb SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors FileName: ./js/SnippetDialog-DwcDACSN.chunk.mjs SPDXID: SPDXRef-eb5119f1f301e738497e88c78242c173 FileChecksum: SHA1: ae0763a33ddf282ababe588a9c30b12a51ccf87f LicenseConcluded: NOASSERTION LicenseInfoInFile: AGPL-3.0-or-later LicenseInfoInFile: AGPL-3.0-or-later LicenseInfoInFile: MIT FileCopyrightText: SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors SPDX-FileCopyrightText: Rob Cresswell FileName: ./js/SnippetDialog-DwcDACSN.chunk.mjs.map SPDXID: SPDXRef-7a1c15dce9d1140ff36d0547531ff635 FileChecksum: SHA1: dd8d74a1bba034a44281f262d1e290337ca6d69e LicenseConcluded: NOASSERTION LicenseInfoInFile: AGPL-3.0-or-later FileCopyrightText: SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors\r\n - SPDX-License-Identifier: AGPL-3.0-or-later\r\n-->\r\n\r\n\r\n\r\n\r\n\r\n"],"names":["_sfc_main","_hoisted_3","_createElementBlock","_mergeProps","_ctx","$props","_cache","$event","_createElementVNode","_openBlock","props","__props","copied","ref","snippet","computed","a","copy","showError","t","_createBlock","_unref","NcDialog","v","$emit","_createVNode","NcButton","_hoisted_1","_hoisted_2","_toDisplayString","IconCheck","IconContentCopy","_createTextVNode","_hoisted_4"],"mappings":"iNAoBA,MAAKA,EAAU,CACb,KAAM,kBACN,MAAO,CAAC,OAAO,EACf,MAAO,CACL,MAAO,CACL,KAAM,QAER,UAAW,CACT,KAAM,OACN,QAAS,gBAEX,KAAM,CACJ,KAAM,OACN,QAAS,EACX,CACF,CACF,6DAxBYC,EAAA,CAAA,EAAE,4HAA4H,+CAXxIC,EAeO,OAfPC,EAAcC,EAAA,OAAM,CACb,cAAaC,EAAA,MAAK,KAAA,OAClB,aAAYA,EAAA,MACb,MAAM,yCACN,KAAK,MACJ,QAAKC,EAAA,CAAA,IAAAA,EAAA,CAAA,EAAAC,GAAEH,EAAA,MAAK,QAAUG,CAAM,WACjCL,EAQM,MAAA,CARA,KAAMG,EAAA,UACP,MAAM,4BACL,MAAOA,EAAA,KACP,OAAQA,EAAA,KACT,QAAQ,cACXG,EAEO,OAFPP,EAEO,CADQI,EAAA,OAAbI,EAAA,EAAAP,EAAuC,YAAhBG,EAAA,KAAK,EAAA,CAAA,4RCqCpC,MAAMK,EAAQC,EAORC,EAASC,EAAI,EAAK,EAElBC,EAAUC,EAAiB,IAAM,CACtC,MAAMC,EAAIN,EAAM,KAAK,MACrB,OAAKM,EAIDA,EAAE,aAAe,kBACb,KAAKA,EAAE,UAAU;AAAA,EAAKA,EAAE,SAAS,MAAMA,EAAE,gBAAgB,GAE1D,KAAKA,EAAE,UAAU;AAAA;AAAA,EAAeA,EAAE,SAAS,MAAMA,EAAE,gBAAgB,GAPzD,EAQlB,CAAC,EAED,eAAeC,GAAsB,CACpC,GAAI,CACH,MAAM,UAAU,UAAU,UAAUH,EAAQ,KAAK,EACjDF,EAAO,MAAQ,GACf,WAAW,IAAM,CAAEA,EAAO,MAAQ,EAAM,EAAG,IAAI,CAChD,MAAQ,CACPM,EAAUC,EAAE,WAAY,gEAAgE,CAAC,CAC1F,CACD,cAzEQR,EAAA,UADPS,EA+BWC,EAAAC,CAAA,EAAA,OA7BT,KAAMD,EAAAF,CAAA,EAAC,WAAA,uBAAA,EACP,KAAMR,EAAA,KACP,KAAK,SACJ,gBAAWL,EAAA,CAAA,IAAAA,EAAA,CAAA,EAAGiB,GAAMC,EAAAA,oBAAqBD,CAAC,EAAA,GAqBhC,UACV,IAEW,CAFXE,EAEWJ,EAAAK,CAAA,EAAA,CAFD,QAAQ,WAAY,uBAAOF,EAAAA,MAAK,cAAA,EAAA,EAAA,aACzC,IAA4B,KAAzBH,EAAAF,CAAA,EAAC,WAAA,OAAA,CAAA,EAAA,CAAA,CAAA,qBAtBN,IAkBM,CAlBNX,EAkBM,MAlBNmB,EAkBM,CAjBLnB,EAEI,IAFJoB,EAEIC,EADAR,EAAAF,CAAA,+FAAmGR,EAAA,KAAK,OAAO,YAAU,GAAA,CAAA,EAAA,CAAA,EAG7HH,EAAkE,MAAlEP,EAAkE,CAAhCO,EAA0B,cAAjBM,EAAA,KAAO,EAAA,CAAA,CAAA,GAElDW,EAMWJ,EAAAK,CAAA,EAAA,CAND,QAAQ,UAAW,QAAOT,CAAA,GACxB,OACV,IAAsC,CAArBL,EAAA,WAAjBQ,EAAsCU,EAAA,OAAZ,KAAM,EAAA,SAChCV,EAAqCW,EAAA,OAAZ,KAAM,EAAA,gBACrB,IACX,CADWC,EAAA,IACXH,EAAGjB,EAAA,MAASS,EAAAF,CAAA,wBAA2BE,EAAAF,CAAA,EAAC,WAAA,mBAAA,CAAA,EAAA,CAAA,CAAA,SAGhCR,EAAA,KAAK,OAAO,UAArBT,EAEI,IAFJ+B,EAAwD,QAClDtB,EAAA,KAAK,MAAM,IAAI,EAAA,CAAA","x_google_ignoreList":[0] FileName: ./js/dbdoctor-main.mjs SPDXID: SPDXRef-cc7b470009d0bba6e788d4a75ce6ce83 FileChecksum: SHA1: 7b099314b7fe850933b63471d5068ed50077bd79 LicenseConcluded: NOASSERTION LicenseInfoInFile: AGPL-3.0-or-later LicenseInfoInFile: AGPL-3.0-or-later LicenseInfoInFile: Apache-2.0 LicenseInfoInFile: GPL-3.0-or-later LicenseInfoInFile: ISC LicenseInfoInFile: MIT LicenseInfoInFile: MPL-2.0 FileCopyrightText: SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors SPDX-FileCopyrightText: @nextcloud/dialogs developers SPDX-FileCopyrightText: Anthony Fu SPDX-FileCopyrightText: David Clark SPDX-FileCopyrightText: David Myers SPDX-FileCopyrightText: Dr.-Ing. Mario Heiderich, Cure53 (https://cure53.de/) SPDX-FileCopyrightText: Eduardo San Martin Morote SPDX-FileCopyrightText: Evan You SPDX-FileCopyrightText: GitHub Inc. SPDX-FileCopyrightText: Guillaume Chau SPDX-FileCopyrightText: Matt Zabriskie SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors SPDX-FileCopyrightText: Rob Cresswell SPDX-FileCopyrightText: Varun A P SPDX-FileCopyrightText: atomiks SPDX-FileCopyrightText: debounce developers SPDX-FileCopyrightText: escape-html developers FileName: ./js/dbdoctor-main.mjs.map SPDXID: SPDXRef-2ad54649fa4c574a66e5542422283fd0 FileChecksum: SHA1: c24aa65a19e87387ab454caab1292d0ed6928900 LicenseConcluded: NOASSERTION LicenseInfoInFile: AGPL-3.0-or-later FileCopyrightText: Copyright (C) 2012-2013, 2015, 2015, 2019, 2022, 2019, 2018-present, 2018-present TJ Holowaychuk\n * Copyright(c) Andreas Lubbe\n * Copyright(c) Tiancheng \"Timothy\" Gu\n * MIT Licensed\n */\n\n'use strict';\n\n/**\n * Module variables.\n * @private\n */\n\nvar matchHtmlRegExp = /[\"'&<>]/;\n\n/**\n * Module exports.\n * @public\n */\n\nmodule.exports = escapeHtml;\n\n/**\n * Escape special characters in the given string of html.\n *\n * @param {string} string The string to escape for inserting into HTML\n * @return {string}\n * @public\n */\n\nfunction escapeHtml(string) {\n var str = '' + string;\n var match = matchHtmlRegExp.exec(str);\n\n if (!match) {\n return str;\n }\n\n var escape;\n var html = '';\n var index = 0;\n var lastIndex = 0;\n\n for (index = match.index; index < str.length; index++) {\n switch (str.charCodeAt(index)) {\n case 34: // \"\n escape = '"';\n break;\n case 38: // &\n escape = '&';\n break;\n case 39: // '\n escape = ''';\n break;\n case 60: // <\n escape = '<';\n break;\n case 62: // >\n escape = '>';\n break;\n default:\n continue;\n }\n\n if (lastIndex !== index) {\n html += str.substring(lastIndex, index);\n }\n\n lastIndex = index + 1;\n html += escape;\n }\n\n return lastIndex !== index\n ? html + str.substring(lastIndex, index)\n : html;\n}\n","import { generateFilePath } from \"@nextcloud/router\";\nimport DOMPurify from \"dompurify\";\nimport escapeHTML from \"escape-html\";\n/*!\n * SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: GPL-3.0-or-later\n */\nfunction getLocale() {\n return globalThis._nc_l10n_locale;\n}\nfunction getCanonicalLocale() {\n return getLocale().replaceAll(/_/g, \"-\");\n}\nfunction setLocale(locale) {\n globalThis._nc_l10n_locale = locale;\n if (typeof document !== \"undefined\") {\n document.documentElement.dataset.locale = locale;\n }\n}\nfunction getLanguage() {\n return globalThis._nc_l10n_language;\n}\nfunction setLanguage(lang) {\n globalThis._nc_l10n_language = lang;\n if (typeof document !== \"undefined\") {\n document.documentElement.lang = lang;\n }\n}\nfunction isRTL(language) {\n const languageCode = language || getLanguage();\n const rtlLanguages = [\n \"ae\",\n // Avestan\n \"ar\",\n // 'العربية', Arabic\n \"arc\",\n // Aramaic\n \"arz\",\n // 'مصرى', Egyptian\n \"bcc\",\n // 'بلوچی مکرانی', Southern Balochi\n \"bqi\",\n // 'بختياري', Bakthiari\n \"ckb\",\n // 'Soranî / کوردی', Sorani\n \"dv\",\n // Dhivehi\n \"fa\",\n // 'فارسی', Persian\n \"glk\",\n // 'گیلکی', Gilaki\n \"ha\",\n // 'هَوُسَ', Hausa\n \"he\",\n // 'עברית', Hebrew\n \"khw\",\n // 'کھوار', Khowar\n \"ks\",\n // 'कॉशुर / کٲشُر', Kashmiri\n \"ku\",\n // 'Kurdî / كوردی', Kurdish\n \"mzn\",\n // 'مازِرونی', Mazanderani\n \"nqo\",\n // 'ߒߞߏ', N’Ko\n \"pnb\",\n // 'پنجابی', Western Punjabi\n \"ps\",\n // 'پښتو', Pashto,\n \"sd\",\n // 'سنڌي', Sindhi\n \"ug\",\n // 'Uyghurche / ئۇيغۇرچە', Uyghur\n \"ur\",\n // 'اردو', Urdu\n \"ur-PK\",\n // 'اردو', Urdu (nextcloud BCP47 variant)\n \"uz-AF\",\n // 'اوزبیکی', Uzbek Afghan\n \"yi\"\n // 'ייִדיש', Yiddish\n ];\n return rtlLanguages.includes(languageCode);\n}\nglobalThis._nc_l10n_locale ??= typeof document !== \"undefined\" && document.documentElement.dataset.locale || Intl.DateTimeFormat().resolvedOptions().locale.replaceAll(/-/g, \"_\");\nglobalThis._nc_l10n_language ??= typeof document !== \"undefined\" && document.documentElement.lang || (globalThis.navigator?.language ?? \"en\");\n/*!\n * SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: GPL-3.0-or-later\n */\nfunction hasAppTranslations(appId) {\n return appId in globalThis._oc_l10n_registry_translations && appId in globalThis._oc_l10n_registry_plural_functions;\n}\nfunction registerAppTranslations(appId, translations, pluralFunction) {\n if (appId === \"__proto__\" || appId === \"constructor\" || appId === \"prototype\") {\n throw new Error(\"Invalid appId\");\n }\n globalThis._oc_l10n_registry_translations[appId] = {\n ...globalThis._oc_l10n_registry_translations[appId] || {},\n ...translations\n };\n globalThis._oc_l10n_registry_plural_functions[appId] = pluralFunction;\n}\nfunction unregisterAppTranslations(appId) {\n delete globalThis._oc_l10n_registry_translations[appId];\n delete globalThis._oc_l10n_registry_plural_functions[appId];\n}\nfunction getAppTranslations(appId) {\n return {\n translations: globalThis._oc_l10n_registry_translations[appId] ?? {},\n pluralFunction: globalThis._oc_l10n_registry_plural_functions[appId] ?? ((number) => number)\n };\n}\nglobalThis._oc_l10n_registry_translations ??= {};\nglobalThis._oc_l10n_registry_plural_functions ??= {};\n/*!\n * SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: GPL-3.0-or-later\n */\nfunction translate(app, text, placeholdersOrNumber, optionsOrNumber, options) {\n const vars = typeof placeholdersOrNumber === \"object\" ? placeholdersOrNumber : void 0;\n const number = typeof optionsOrNumber === \"number\" ? optionsOrNumber : typeof placeholdersOrNumber === \"number\" ? placeholdersOrNumber : void 0;\n const allOptions = {\n // defaults\n escape: true,\n sanitize: true,\n // overwrite with user config\n ...typeof options === \"object\" ? options : typeof optionsOrNumber === \"object\" ? optionsOrNumber : {}\n };\n const identity = (value) => value;\n const optSanitize = (allOptions.sanitize ? DOMPurify.sanitize : identity) || identity;\n const optEscape = allOptions.escape ? escapeHTML : identity;\n const isValidReplacement = (value) => typeof value === \"string\" || typeof value === \"number\";\n const _build = (text2, vars2, number2) => {\n return text2.replace(/%n/g, \"\" + number2).replace(/{([^{}]*)}/g, (match, key) => {\n if (vars2 === void 0 || !(key in vars2)) {\n return optEscape(match);\n }\n const replacement = vars2[key];\n if (isValidReplacement(replacement)) {\n return optEscape(`${replacement}`);\n } else if (typeof replacement === \"object\" && isValidReplacement(replacement.value)) {\n const escape = replacement.escape !== false ? escapeHTML : identity;\n return escape(`${replacement.value}`);\n } else {\n return optEscape(match);\n }\n });\n };\n const bundle = options?.bundle ?? getAppTranslations(app);\n let translation = bundle.translations[text] || text;\n translation = Array.isArray(translation) ? translation[0] : translation;\n if (typeof vars === \"object\" || number !== void 0) {\n return optSanitize(_build(\n translation,\n vars,\n number\n ));\n } else {\n return optSanitize(translation);\n }\n}\nfunction translatePlural(app, textSingular, textPlural, number, vars, options) {\n const identifier = \"_\" + textSingular + \"_::_\" + textPlural + \"_\";\n const bundle = options?.bundle ?? getAppTranslations(app);\n const value = bundle.translations[identifier];\n if (typeof value !== \"undefined\") {\n const translation = value;\n if (Array.isArray(translation)) {\n const plural = bundle.pluralFunction(number);\n return translate(app, translation[plural], vars, number, options);\n }\n }\n if (number === 1) {\n return translate(app, textSingular, vars, number, options);\n } else {\n return translate(app, textPlural, vars, number, options);\n }\n}\nasync function loadTranslations(appName, callback) {\n if (hasAppTranslations(appName) || getLanguage() === \"en\") {\n const bundle = getAppTranslations(appName);\n callback?.(bundle);\n return bundle;\n }\n let response;\n try {\n const url = generateFilePath(appName, \"l10n\", getLanguage() + \".json\");\n response = await fetch(url);\n } catch (error) {\n throw new Error(\"Network error\", { cause: error });\n }\n if (response.ok) {\n try {\n const bundle = await response.json();\n if (typeof bundle.translations === \"object\") {\n register(appName, bundle.translations);\n callback?.(bundle);\n return bundle;\n }\n } catch {\n }\n throw new Error(\"Invalid content of translation bundle\");\n } else {\n throw new Error(response.statusText);\n }\n}\nfunction register(appName, bundle) {\n registerAppTranslations(appName, bundle, getPlural);\n}\nfunction unregister(appName) {\n return unregisterAppTranslations(appName);\n}\nfunction getPlural(number, language = getLanguage()) {\n if (language === \"pt-BR\") {\n language = \"xbr\";\n }\n if (language.length > 3) {\n language = language.substring(0, language.lastIndexOf(\"-\"));\n }\n switch (language) {\n case \"az\":\n case \"bo\":\n case \"dz\":\n case \"id\":\n case \"ja\":\n case \"jv\":\n case \"ka\":\n case \"km\":\n case \"kn\":\n case \"ko\":\n case \"ms\":\n case \"th\":\n case \"tr\":\n case \"vi\":\n case \"zh\":\n return 0;\n case \"af\":\n case \"bn\":\n case \"bg\":\n case \"ca\":\n case \"da\":\n case \"de\":\n case \"el\":\n case \"en\":\n case \"eo\":\n case \"es\":\n case \"et\":\n case \"eu\":\n case \"fa\":\n case \"fi\":\n case \"fo\":\n case \"fur\":\n case \"fy\":\n case \"gl\":\n case \"gu\":\n case \"ha\":\n case \"he\":\n case \"hu\":\n case \"is\":\n case \"it\":\n case \"ku\":\n case \"lb\":\n case \"ml\":\n case \"mn\":\n case \"mr\":\n case \"nah\":\n case \"nb\":\n case \"ne\":\n case \"nl\":\n case \"nn\":\n case \"no\":\n case \"oc\":\n case \"om\":\n case \"or\":\n case \"pa\":\n case \"pap\":\n case \"ps\":\n case \"pt\":\n case \"so\":\n case \"sq\":\n case \"sv\":\n case \"sw\":\n case \"ta\":\n case \"te\":\n case \"tk\":\n case \"ur\":\n case \"zu\":\n return number === 1 ? 0 : 1;\n case \"am\":\n case \"bh\":\n case \"fil\":\n case \"fr\":\n case \"gun\":\n case \"hi\":\n case \"hy\":\n case \"ln\":\n case \"mg\":\n case \"nso\":\n case \"xbr\":\n case \"ti\":\n case \"wa\":\n return number === 0 || number === 1 ? 0 : 1;\n case \"be\":\n case \"bs\":\n case \"hr\":\n case \"ru\":\n case \"sh\":\n case \"sr\":\n case \"uk\":\n return number % 10 === 1 && number % 100 !== 11 ? 0 : number % 10 >= 2 && number % 10 <= 4 && (number % 100 < 10 || number % 100 >= 20) ? 1 : 2;\n case \"cs\":\n case \"sk\":\n return number === 1 ? 0 : number >= 2 && number <= 4 ? 1 : 2;\n case \"ga\":\n return number === 1 ? 0 : number === 2 ? 1 : 2;\n case \"lt\":\n return number % 10 === 1 && number % 100 !== 11 ? 0 : number % 10 >= 2 && (number % 100 < 10 || number % 100 >= 20) ? 1 : 2;\n case \"sl\":\n return number % 100 === 1 ? 0 : number % 100 === 2 ? 1 : number % 100 === 3 || number % 100 === 4 ? 2 : 3;\n case \"mk\":\n return number % 10 === 1 ? 0 : 1;\n case \"mt\":\n return number === 1 ? 0 : number === 0 || number % 100 > 1 && number % 100 < 11 ? 1 : number % 100 > 10 && number % 100 < 20 ? 2 : 3;\n case \"lv\":\n return number === 0 ? 0 : number % 10 === 1 && number % 100 !== 11 ? 1 : 2;\n case \"pl\":\n return number === 1 ? 0 : number % 10 >= 2 && number % 10 <= 4 && (number % 100 < 12 || number % 100 > 14) ? 1 : 2;\n case \"cy\":\n return number === 1 ? 0 : number === 2 ? 1 : number === 8 || number === 11 ? 2 : 3;\n case \"ro\":\n return number === 1 ? 0 : number === 0 || number % 100 > 0 && number % 100 < 20 ? 1 : 2;\n case \"ar\":\n return number === 0 ? 0 : number === 1 ? 1 : number === 2 ? 2 : number % 100 >= 3 && number % 100 <= 10 ? 3 : number % 100 >= 11 && number % 100 <= 99 ? 4 : 5;\n default:\n return 0;\n }\n}\nexport {\n getLanguage as a,\n getLocale as b,\n setLanguage as c,\n translatePlural as d,\n getPlural as e,\n getCanonicalLocale as g,\n isRTL as i,\n loadTranslations as l,\n register as r,\n setLocale as s,\n translate as t,\n unregister as u\n};\n//# sourceMappingURL=translation-DoG5ZELJ.mjs.map\n","const global = globalThis || void 0 || self;\n\nexport { global as default, global };\n//# sourceMappingURL=index.js.map\n","/**\n* @vue/shared v3.5.40\n* (c) Yuxi (Evan) You and Vue contributors\n* @license MIT\n**/\n// @__NO_SIDE_EFFECTS__\nfunction makeMap(str) {\n const map = /* @__PURE__ */ Object.create(null);\n for (const key of str.split(\",\")) map[key] = 1;\n return (val) => val in map;\n}\n\nconst EMPTY_OBJ = !!(process.env.NODE_ENV !== \"production\") ? Object.freeze({}) : {};\nconst EMPTY_ARR = !!(process.env.NODE_ENV !== \"production\") ? Object.freeze([]) : [];\nconst NOOP = () => {\n};\nconst NO = () => false;\nconst isOn = (key) => key.charCodeAt(0) === 111 && key.charCodeAt(1) === 110 && // uppercase letter\n(key.charCodeAt(2) > 122 || key.charCodeAt(2) < 97);\nconst isModelListener = (key) => key.startsWith(\"onUpdate:\");\nconst extend = Object.assign;\nconst remove = (arr, el) => {\n const i = arr.indexOf(el);\n if (i > -1) {\n arr.splice(i, 1);\n }\n};\nconst hasOwnProperty = Object.prototype.hasOwnProperty;\nconst hasOwn = (val, key) => hasOwnProperty.call(val, key);\nconst isArray = Array.isArray;\nconst isMap = (val) => toTypeString(val) === \"[object Map]\";\nconst isSet = (val) => toTypeString(val) === \"[object Set]\";\nconst isDate = (val) => toTypeString(val) === \"[object Date]\";\nconst isRegExp = (val) => toTypeString(val) === \"[object RegExp]\";\nconst isFunction = (val) => typeof val === \"function\";\nconst isString = (val) => typeof val === \"string\";\nconst isSymbol = (val) => typeof val === \"symbol\";\nconst isObject = (val) => val !== null && typeof val === \"object\";\nconst isPromise = (val) => {\n return (isObject(val) || isFunction(val)) && isFunction(val.then) && isFunction(val.catch);\n};\nconst objectToString = Object.prototype.toString;\nconst toTypeString = (value) => objectToString.call(value);\nconst toRawType = (value) => {\n return toTypeString(value).slice(8, -1);\n};\nconst isPlainObject = (val) => toTypeString(val) === \"[object Object]\";\nconst isIntegerKey = (key) => isString(key) && key !== \"NaN\" && key[0] !== \"-\" && \"\" + parseInt(key, 10) === key;\nconst isReservedProp = /* @__PURE__ */ makeMap(\n // the leading comma is intentional so empty string \"\" is also included\n \",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted\"\n);\nconst isBuiltInDirective = /* @__PURE__ */ makeMap(\n \"bind,cloak,else-if,else,for,html,if,model,on,once,pre,show,slot,text,memo\"\n);\nconst cacheStringFunction = (fn) => {\n const cache = /* @__PURE__ */ Object.create(null);\n return ((str) => {\n const hit = cache[str];\n return hit || (cache[str] = fn(str));\n });\n};\nconst camelizeRE = /-\\w/g;\nconst camelize = cacheStringFunction(\n (str) => {\n return str.replace(camelizeRE, (c) => c.slice(1).toUpperCase());\n }\n);\nconst hyphenateRE = /\\B([A-Z])/g;\nconst hyphenate = cacheStringFunction(\n (str) => str.replace(hyphenateRE, \"-$1\").toLowerCase()\n);\nconst capitalize = cacheStringFunction((str) => {\n return str.charAt(0).toUpperCase() + str.slice(1);\n});\nconst toHandlerKey = cacheStringFunction(\n (str) => {\n const s = str ? `on${capitalize(str)}` : ``;\n return s;\n }\n);\nconst hasChanged = (value, oldValue) => !Object.is(value, oldValue);\nconst invokeArrayFns = (fns, ...arg) => {\n for (let i = 0; i < fns.length; i++) {\n fns[i](...arg);\n }\n};\nconst def = (obj, key, value, writable = false) => {\n Object.defineProperty(obj, key, {\n configurable: true,\n enumerable: false,\n writable,\n value\n });\n};\nconst looseToNumber = (val) => {\n const n = parseFloat(val);\n return isNaN(n) ? val : n;\n};\nconst toNumber = (val) => {\n const n = isString(val) ? Number(val) : NaN;\n return isNaN(n) ? val : n;\n};\nlet _globalThis;\nconst getGlobalThis = () => {\n return _globalThis || (_globalThis = typeof globalThis !== \"undefined\" ? globalThis : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : typeof global !== \"undefined\" ? global : {});\n};\nconst identRE = /^[_$a-zA-Z\\xA0-\\uFFFF][_$a-zA-Z0-9\\xA0-\\uFFFF]*$/;\nfunction genPropsAccessExp(name) {\n return identRE.test(name) ? `__props.${name}` : `__props[${JSON.stringify(name)}]`;\n}\nfunction genCacheKey(source, options) {\n return source + JSON.stringify(\n options,\n (_, val) => typeof val === \"function\" ? val.toString() : val\n );\n}\n\nconst PatchFlags = {\n \"TEXT\": 1,\n \"1\": \"TEXT\",\n \"CLASS\": 2,\n \"2\": \"CLASS\",\n \"STYLE\": 4,\n \"4\": \"STYLE\",\n \"PROPS\": 8,\n \"8\": \"PROPS\",\n \"FULL_PROPS\": 16,\n \"16\": \"FULL_PROPS\",\n \"NEED_HYDRATION\": 32,\n \"32\": \"NEED_HYDRATION\",\n \"STABLE_FRAGMENT\": 64,\n \"64\": \"STABLE_FRAGMENT\",\n \"KEYED_FRAGMENT\": 128,\n \"128\": \"KEYED_FRAGMENT\",\n \"UNKEYED_FRAGMENT\": 256,\n \"256\": \"UNKEYED_FRAGMENT\",\n \"NEED_PATCH\": 512,\n \"512\": \"NEED_PATCH\",\n \"DYNAMIC_SLOTS\": 1024,\n \"1024\": \"DYNAMIC_SLOTS\",\n \"DEV_ROOT_FRAGMENT\": 2048,\n \"2048\": \"DEV_ROOT_FRAGMENT\",\n \"CACHED\": -1,\n \"-1\": \"CACHED\",\n \"BAIL\": -2,\n \"-2\": \"BAIL\"\n};\nconst PatchFlagNames = {\n [1]: `TEXT`,\n [2]: `CLASS`,\n [4]: `STYLE`,\n [8]: `PROPS`,\n [16]: `FULL_PROPS`,\n [32]: `NEED_HYDRATION`,\n [64]: `STABLE_FRAGMENT`,\n [128]: `KEYED_FRAGMENT`,\n [256]: `UNKEYED_FRAGMENT`,\n [512]: `NEED_PATCH`,\n [1024]: `DYNAMIC_SLOTS`,\n [2048]: `DEV_ROOT_FRAGMENT`,\n [-1]: `CACHED`,\n [-2]: `BAIL`\n};\n\nconst ShapeFlags = {\n \"ELEMENT\": 1,\n \"1\": \"ELEMENT\",\n \"FUNCTIONAL_COMPONENT\": 2,\n \"2\": \"FUNCTIONAL_COMPONENT\",\n \"STATEFUL_COMPONENT\": 4,\n \"4\": \"STATEFUL_COMPONENT\",\n \"TEXT_CHILDREN\": 8,\n \"8\": \"TEXT_CHILDREN\",\n \"ARRAY_CHILDREN\": 16,\n \"16\": \"ARRAY_CHILDREN\",\n \"SLOTS_CHILDREN\": 32,\n \"32\": \"SLOTS_CHILDREN\",\n \"TELEPORT\": 64,\n \"64\": \"TELEPORT\",\n \"SUSPENSE\": 128,\n \"128\": \"SUSPENSE\",\n \"COMPONENT_SHOULD_KEEP_ALIVE\": 256,\n \"256\": \"COMPONENT_SHOULD_KEEP_ALIVE\",\n \"COMPONENT_KEPT_ALIVE\": 512,\n \"512\": \"COMPONENT_KEPT_ALIVE\",\n \"COMPONENT\": 6,\n \"6\": \"COMPONENT\"\n};\n\nconst SlotFlags = {\n \"STABLE\": 1,\n \"1\": \"STABLE\",\n \"DYNAMIC\": 2,\n \"2\": \"DYNAMIC\",\n \"FORWARDED\": 3,\n \"3\": \"FORWARDED\"\n};\nconst slotFlagsText = {\n [1]: \"STABLE\",\n [2]: \"DYNAMIC\",\n [3]: \"FORWARDED\"\n};\n\nconst GLOBALS_ALLOWED = \"Infinity,undefined,NaN,isFinite,isNaN,parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,BigInt,console,Error,Symbol\";\nconst isGloballyAllowed = /* @__PURE__ */ makeMap(GLOBALS_ALLOWED);\nconst isGloballyWhitelisted = isGloballyAllowed;\n\nconst range = 2;\nfunction generateCodeFrame(source, start = 0, end = source.length) {\n start = Math.max(0, Math.min(start, source.length));\n end = Math.max(0, Math.min(end, source.length));\n if (start > end) return \"\";\n let lines = source.split(/(\\r?\\n)/);\n const newlineSequences = lines.filter((_, idx) => idx % 2 === 1);\n lines = lines.filter((_, idx) => idx % 2 === 0);\n let count = 0;\n const res = [];\n for (let i = 0; i < lines.length; i++) {\n count += lines[i].length + (newlineSequences[i] && newlineSequences[i].length || 0);\n if (count >= start) {\n for (let j = i - range; j <= i + range || end > count; j++) {\n if (j < 0 || j >= lines.length) continue;\n const line = j + 1;\n res.push(\n `${line}${\" \".repeat(Math.max(3 - String(line).length, 0))}| ${lines[j]}`\n );\n const lineLength = lines[j].length;\n const newLineSeqLength = newlineSequences[j] && newlineSequences[j].length || 0;\n if (j === i) {\n const pad = start - (count - (lineLength + newLineSeqLength));\n const length = Math.max(\n 1,\n end > count ? lineLength - pad : end - start\n );\n res.push(` | ` + \" \".repeat(pad) + \"^\".repeat(length));\n } else if (j > i) {\n if (end > count) {\n const length = Math.max(Math.min(end - count, lineLength), 1);\n res.push(` | ` + \"^\".repeat(length));\n }\n count += lineLength + newLineSeqLength;\n }\n }\n break;\n }\n }\n return res.join(\"\\n\");\n}\n\nfunction normalizeStyle(value) {\n if (isArray(value)) {\n const res = {};\n for (let i = 0; i < value.length; i++) {\n const item = value[i];\n const normalized = isString(item) ? parseStringStyle(item) : normalizeStyle(item);\n if (normalized) {\n for (const key in normalized) {\n res[key] = normalized[key];\n }\n }\n }\n return res;\n } else if (isString(value) || isObject(value)) {\n return value;\n }\n}\nconst listDelimiterRE = /;(?![^(]*\\))/g;\nconst propertyDelimiterRE = /:([^]+)/;\nconst styleCommentRE = /\\/\\*[^]*?\\*\\//g;\nfunction parseStringStyle(cssText) {\n const ret = {};\n cssText.replace(styleCommentRE, \"\").split(listDelimiterRE).forEach((item) => {\n if (item) {\n const tmp = item.split(propertyDelimiterRE);\n tmp.length > 1 && (ret[tmp[0].trim()] = tmp[1].trim());\n }\n });\n return ret;\n}\nfunction stringifyStyle(styles) {\n if (!styles) return \"\";\n if (isString(styles)) return styles;\n let ret = \"\";\n for (const key in styles) {\n const value = styles[key];\n if (isString(value) || typeof value === \"number\") {\n const normalizedKey = key.startsWith(`--`) ? key : hyphenate(key);\n ret += `${normalizedKey}:${value};`;\n }\n }\n return ret;\n}\nfunction normalizeClass(value) {\n let res = \"\";\n if (isString(value)) {\n res = value;\n } else if (isArray(value)) {\n for (let i = 0; i < value.length; i++) {\n const normalized = normalizeClass(value[i]);\n if (normalized) {\n res += normalized + \" \";\n }\n }\n } else if (isObject(value)) {\n for (const name in value) {\n if (value[name]) {\n res += name + \" \";\n }\n }\n }\n return res.trim();\n}\nfunction normalizeProps(props) {\n if (!props) return null;\n let { class: klass, style } = props;\n if (klass && !isString(klass)) {\n props.class = normalizeClass(klass);\n }\n if (style) {\n props.style = normalizeStyle(style);\n }\n return props;\n}\n\nconst HTML_TAGS = \"html,body,base,head,link,meta,style,title,address,article,aside,footer,header,hgroup,h1,h2,h3,h4,h5,h6,nav,section,div,dd,dl,dt,figcaption,figure,picture,hr,img,li,main,ol,p,pre,ul,a,b,abbr,bdi,bdo,br,cite,code,data,dfn,em,i,kbd,mark,q,rp,rt,ruby,s,samp,small,span,strong,sub,sup,time,u,var,wbr,area,audio,map,track,video,embed,object,param,source,canvas,script,noscript,del,ins,caption,col,colgroup,table,thead,tbody,td,th,tr,button,datalist,fieldset,form,input,label,legend,meter,optgroup,option,output,progress,select,textarea,details,dialog,menu,summary,template,blockquote,iframe,tfoot\";\nconst SVG_TAGS = \"svg,animate,animateMotion,animateTransform,circle,clipPath,color-profile,defs,desc,discard,ellipse,feBlend,feColorMatrix,feComponentTransfer,feComposite,feConvolveMatrix,feDiffuseLighting,feDisplacementMap,feDistantLight,feDropShadow,feFlood,feFuncA,feFuncB,feFuncG,feFuncR,feGaussianBlur,feImage,feMerge,feMergeNode,feMorphology,feOffset,fePointLight,feSpecularLighting,feSpotLight,feTile,feTurbulence,filter,foreignObject,g,hatch,hatchpath,image,line,linearGradient,marker,mask,mesh,meshgradient,meshpatch,meshrow,metadata,mpath,path,pattern,polygon,polyline,radialGradient,rect,set,solidcolor,stop,switch,symbol,text,textPath,title,tspan,unknown,use,view\";\nconst MATH_TAGS = \"annotation,annotation-xml,maction,maligngroup,malignmark,math,menclose,merror,mfenced,mfrac,mfraction,mglyph,mi,mlabeledtr,mlongdiv,mmultiscripts,mn,mo,mover,mpadded,mphantom,mprescripts,mroot,mrow,ms,mscarries,mscarry,msgroup,msline,mspace,msqrt,msrow,mstack,mstyle,msub,msubsup,msup,mtable,mtd,mtext,mtr,munder,munderover,none,semantics\";\nconst VOID_TAGS = \"area,base,br,col,embed,hr,img,input,link,meta,param,source,track,wbr\";\nconst isHTMLTag = /* @__PURE__ */ makeMap(HTML_TAGS);\nconst isSVGTag = /* @__PURE__ */ makeMap(SVG_TAGS);\nconst isMathMLTag = /* @__PURE__ */ makeMap(MATH_TAGS);\nconst isVoidTag = /* @__PURE__ */ makeMap(VOID_TAGS);\n\nconst specialBooleanAttrs = `itemscope,allowfullscreen,formnovalidate,ismap,nomodule,novalidate,readonly`;\nconst isSpecialBooleanAttr = /* @__PURE__ */ makeMap(specialBooleanAttrs);\nconst isBooleanAttr = /* @__PURE__ */ makeMap(\n specialBooleanAttrs + `,async,autofocus,autoplay,controls,default,defer,disabled,hidden,inert,loop,open,required,reversed,scoped,seamless,checked,muted,multiple,selected`\n);\nfunction includeBooleanAttr(value) {\n return !!value || value === \"\";\n}\nconst unsafeAttrCharRE = /[>/=\"'\\u0009\\u000a\\u000c\\u0020]/;\nconst attrValidationCache = {};\nfunction isSSRSafeAttrName(name) {\n if (attrValidationCache.hasOwnProperty(name)) {\n return attrValidationCache[name];\n }\n const isUnsafe = unsafeAttrCharRE.test(name);\n if (isUnsafe) {\n console.error(`unsafe attribute name: ${name}`);\n }\n return attrValidationCache[name] = !isUnsafe;\n}\nconst propsToAttrMap = {\n acceptCharset: \"accept-charset\",\n className: \"class\",\n htmlFor: \"for\",\n httpEquiv: \"http-equiv\"\n};\nconst isKnownHtmlAttr = /* @__PURE__ */ makeMap(\n `accept,accept-charset,accesskey,action,align,allow,alt,async,autocapitalize,autocomplete,autofocus,autoplay,background,bgcolor,border,buffered,capture,challenge,charset,checked,cite,class,code,codebase,color,cols,colspan,content,contenteditable,contextmenu,controls,coords,crossorigin,csp,data,datetime,decoding,default,defer,dir,dirname,disabled,download,draggable,dropzone,enctype,enterkeyhint,for,form,formaction,formenctype,formmethod,formnovalidate,formtarget,headers,height,hidden,high,href,hreflang,http-equiv,icon,id,importance,inert,integrity,ismap,itemprop,keytype,kind,label,lang,language,loading,list,loop,low,manifest,max,maxlength,minlength,media,min,multiple,muted,name,novalidate,open,optimum,pattern,ping,placeholder,poster,preload,radiogroup,readonly,referrerpolicy,rel,required,reversed,rows,rowspan,sandbox,scope,scoped,selected,shape,size,sizes,slot,span,spellcheck,src,srcdoc,srclang,srcset,start,step,style,summary,tabindex,target,title,translate,type,usemap,value,width,wrap`\n);\nconst isKnownSvgAttr = /* @__PURE__ */ makeMap(\n `xmlns,accent-height,accumulate,additive,alignment-baseline,alphabetic,amplitude,arabic-form,ascent,attributeName,attributeType,azimuth,baseFrequency,baseline-shift,baseProfile,bbox,begin,bias,by,calcMode,cap-height,class,clip,clipPathUnits,clip-path,clip-rule,color,color-interpolation,color-interpolation-filters,color-profile,color-rendering,contentScriptType,contentStyleType,crossorigin,cursor,cx,cy,d,decelerate,descent,diffuseConstant,direction,display,divisor,dominant-baseline,dur,dx,dy,edgeMode,elevation,enable-background,end,exponent,fill,fill-opacity,fill-rule,filter,filterRes,filterUnits,flood-color,flood-opacity,font-family,font-size,font-size-adjust,font-stretch,font-style,font-variant,font-weight,format,from,fr,fx,fy,g1,g2,glyph-name,glyph-orientation-horizontal,glyph-orientation-vertical,glyphRef,gradientTransform,gradientUnits,hanging,height,href,hreflang,horiz-adv-x,horiz-origin-x,id,ideographic,image-rendering,in,in2,intercept,k,k1,k2,k3,k4,kernelMatrix,kernelUnitLength,kerning,keyPoints,keySplines,keyTimes,lang,lengthAdjust,letter-spacing,lighting-color,limitingConeAngle,local,marker-end,marker-mid,marker-start,markerHeight,markerUnits,markerWidth,mask,maskContentUnits,maskUnits,mathematical,max,media,method,min,mode,name,numOctaves,offset,opacity,operator,order,orient,orientation,origin,overflow,overline-position,overline-thickness,panose-1,paint-order,path,pathLength,patternContentUnits,patternTransform,patternUnits,ping,pointer-events,points,pointsAtX,pointsAtY,pointsAtZ,preserveAlpha,preserveAspectRatio,primitiveUnits,r,radius,referrerPolicy,refX,refY,rel,rendering-intent,repeatCount,repeatDur,requiredExtensions,requiredFeatures,restart,result,rotate,rx,ry,scale,seed,shape-rendering,slope,spacing,specularConstant,specularExponent,speed,spreadMethod,startOffset,stdDeviation,stemh,stemv,stitchTiles,stop-color,stop-opacity,strikethrough-position,strikethrough-thickness,string,stroke,stroke-dasharray,stroke-dashoffset,stroke-linecap,stroke-linejoin,stroke-miterlimit,stroke-opacity,stroke-width,style,surfaceScale,systemLanguage,tabindex,tableValues,target,targetX,targetY,text-anchor,text-decoration,text-rendering,textLength,to,transform,transform-origin,type,u1,u2,underline-position,underline-thickness,unicode,unicode-bidi,unicode-range,units-per-em,v-alphabetic,v-hanging,v-ideographic,v-mathematical,values,vector-effect,version,vert-adv-y,vert-origin-x,vert-origin-y,viewBox,viewTarget,visibility,width,widths,word-spacing,writing-mode,x,x-height,x1,x2,xChannelSelector,xlink:actuate,xlink:arcrole,xlink:href,xlink:role,xlink:show,xlink:title,xlink:type,xmlns:xlink,xml:base,xml:lang,xml:space,y,y1,y2,yChannelSelector,z,zoomAndPan`\n);\nconst isKnownMathMLAttr = /* @__PURE__ */ makeMap(\n `accent,accentunder,actiontype,align,alignmentscope,altimg,altimg-height,altimg-valign,altimg-width,alttext,bevelled,close,columnsalign,columnlines,columnspan,denomalign,depth,dir,display,displaystyle,encoding,equalcolumns,equalrows,fence,fontstyle,fontweight,form,frame,framespacing,groupalign,height,href,id,indentalign,indentalignfirst,indentalignlast,indentshift,indentshiftfirst,indentshiftlast,indextype,justify,largetop,largeop,lquote,lspace,mathbackground,mathcolor,mathsize,mathvariant,maxsize,minlabelspacing,mode,other,overflow,position,rowalign,rowlines,rowspan,rquote,rspace,scriptlevel,scriptminsize,scriptsizemultiplier,selection,separator,separators,shift,side,src,stackalign,stretchy,subscriptshift,superscriptshift,symmetric,voffset,width,widths,xlink:href,xlink:show,xlink:type,xmlns`\n);\nfunction isRenderableAttrValue(value) {\n if (value == null) {\n return false;\n }\n const type = typeof value;\n return type === \"string\" || type === \"number\" || type === \"boolean\";\n}\n\nconst escapeRE = /[\"'&<>]/;\nfunction escapeHtml(string) {\n const str = \"\" + string;\n const match = escapeRE.exec(str);\n if (!match) {\n return str;\n }\n let html = \"\";\n let escaped;\n let index;\n let lastIndex = 0;\n for (index = match.index; index < str.length; index++) {\n switch (str.charCodeAt(index)) {\n case 34:\n escaped = \""\";\n break;\n case 38:\n escaped = \"&\";\n break;\n case 39:\n escaped = \"'\";\n break;\n case 60:\n escaped = \"<\";\n break;\n case 62:\n escaped = \">\";\n break;\n default:\n continue;\n }\n if (lastIndex !== index) {\n html += str.slice(lastIndex, index);\n }\n lastIndex = index + 1;\n html += escaped;\n }\n return lastIndex !== index ? html + str.slice(lastIndex, index) : html;\n}\nconst commentStripRE = /^(?:-?>)+||--!>|?@[\\\\\\]^`{|}~]/g;\nfunction getEscapedCssVarName(key, doubleEscape) {\n return key.replace(\n cssVarNameEscapeSymbolsRE,\n (s) => doubleEscape ? s === '\"' ? '\\\\\\\\\\\\\"' : `\\\\\\\\${s}` : `\\\\${s}`\n );\n}\n\nfunction looseCompareArrays(a, b) {\n if (a.length !== b.length) return false;\n let equal = true;\n for (let i = 0; equal && i < a.length; i++) {\n equal = looseEqual(a[i], b[i]);\n }\n return equal;\n}\nfunction looseEqual(a, b) {\n if (a === b) return true;\n let aValidType = isDate(a);\n let bValidType = isDate(b);\n if (aValidType || bValidType) {\n return aValidType && bValidType ? a.getTime() === b.getTime() : false;\n }\n aValidType = isSymbol(a);\n bValidType = isSymbol(b);\n if (aValidType || bValidType) {\n return a === b;\n }\n aValidType = isArray(a);\n bValidType = isArray(b);\n if (aValidType || bValidType) {\n return aValidType && bValidType ? looseCompareArrays(a, b) : false;\n }\n aValidType = isObject(a);\n bValidType = isObject(b);\n if (aValidType || bValidType) {\n if (!aValidType || !bValidType) {\n return false;\n }\n const aKeysCount = Object.keys(a).length;\n const bKeysCount = Object.keys(b).length;\n if (aKeysCount !== bKeysCount) {\n return false;\n }\n for (const key in a) {\n const aHasKey = a.hasOwnProperty(key);\n const bHasKey = b.hasOwnProperty(key);\n if (aHasKey && !bHasKey || !aHasKey && bHasKey || !looseEqual(a[key], b[key])) {\n return false;\n }\n }\n }\n return String(a) === String(b);\n}\nfunction looseIndexOf(arr, val) {\n return arr.findIndex((item) => looseEqual(item, val));\n}\n\nconst isRef = (val) => {\n return !!(val && val[\"__v_isRef\"] === true);\n};\nconst toDisplayString = (val) => {\n return isString(val) ? val : val == null ? \"\" : isArray(val) || isObject(val) && (val.toString === objectToString || !isFunction(val.toString)) ? isRef(val) ? toDisplayString(val.value) : JSON.stringify(val, replacer, 2) : String(val);\n};\nconst replacer = (_key, val) => {\n if (isRef(val)) {\n return replacer(_key, val.value);\n } else if (isMap(val)) {\n return {\n [`Map(${val.size})`]: [...val.entries()].reduce(\n (entries, [key, val2], i) => {\n entries[stringifySymbol(key, i) + \" =>\"] = val2;\n return entries;\n },\n {}\n )\n };\n } else if (isSet(val)) {\n return {\n [`Set(${val.size})`]: [...val.values()].map((v) => stringifySymbol(v))\n };\n } else if (isSymbol(val)) {\n return stringifySymbol(val);\n } else if (isObject(val) && !isArray(val) && !isPlainObject(val)) {\n return String(val);\n }\n return val;\n};\nconst stringifySymbol = (v, i = \"\") => {\n var _a;\n return (\n // Symbol.description in es2019+ so we need to cast here to pass\n // the lib: es2016 check\n isSymbol(v) ? `Symbol(${(_a = v.description) != null ? _a : i})` : v\n );\n};\n\nfunction normalizeCssVarValue(value) {\n if (value == null) {\n return \"initial\";\n }\n if (typeof value === \"string\") {\n return value === \"\" ? \" \" : value;\n }\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n if (!!(process.env.NODE_ENV !== \"production\")) {\n console.warn(\n \"[Vue warn] Invalid value used for CSS binding. Expected a string or a finite number but received:\",\n value\n );\n }\n }\n return String(value);\n}\n\nexport { EMPTY_ARR, EMPTY_OBJ, NO, NOOP, PatchFlagNames, PatchFlags, ShapeFlags, SlotFlags, camelize, capitalize, cssVarNameEscapeSymbolsRE, def, escapeHtml, escapeHtmlComment, extend, genCacheKey, genPropsAccessExp, generateCodeFrame, getEscapedCssVarName, getGlobalThis, hasChanged, hasOwn, hyphenate, includeBooleanAttr, invokeArrayFns, isArray, isBooleanAttr, isBuiltInDirective, isDate, isFunction, isGloballyAllowed, isGloballyWhitelisted, isHTMLTag, isIntegerKey, isKnownHtmlAttr, isKnownMathMLAttr, isKnownSvgAttr, isMap, isMathMLTag, isModelListener, isObject, isOn, isPlainObject, isPromise, isRegExp, isRenderableAttrValue, isReservedProp, isSSRSafeAttrName, isSVGTag, isSet, isSpecialBooleanAttr, isString, isSymbol, isVoidTag, looseEqual, looseIndexOf, looseToNumber, makeMap, normalizeClass, normalizeCssVarValue, normalizeProps, normalizeStyle, objectToString, parseStringStyle, propsToAttrMap, remove, slotFlagsText, stringifyStyle, toDisplayString, toHandlerKey, toNumber, toRawType, toTypeString };\n","/**\n* @vue/reactivity v3.5.40\n* (c) Yuxi (Evan) You and Vue contributors\n* @license MIT\n**/\nimport { extend, hasChanged, isArray, isIntegerKey, isSymbol, isMap, hasOwn, isObject, makeMap, capitalize, toRawType, def, isFunction, EMPTY_OBJ, isSet, isPlainObject, remove, NOOP } from '@vue/shared';\n\nfunction warn(msg, ...args) {\n console.warn(`[Vue warn] ${msg}`, ...args);\n}\n\nlet activeEffectScope;\nclass EffectScope {\n // TODO isolatedDeclarations \"__v_skip\"\n constructor(detached = false) {\n this.detached = detached;\n /**\n * @internal\n */\n this._active = true;\n /**\n * @internal track `on` calls, allow `on` call multiple times\n */\n this._on = 0;\n /**\n * @internal\n */\n this.effects = [];\n /**\n * @internal\n */\n this.cleanups = [];\n this._isPaused = false;\n this._warnOnRun = true;\n this.__v_skip = true;\n if (!detached && activeEffectScope) {\n if (activeEffectScope.active) {\n this.parent = activeEffectScope;\n this.index = (activeEffectScope.scopes || (activeEffectScope.scopes = [])).push(\n this\n ) - 1;\n } else {\n this._active = false;\n this._warnOnRun = false;\n }\n }\n }\n get active() {\n return this._active;\n }\n pause() {\n if (this._active) {\n this._isPaused = true;\n let i, l;\n if (this.scopes) {\n const scopes = this.scopes.slice();\n for (i = 0, l = scopes.length; i < l; i++) {\n scopes[i].pause();\n }\n }\n for (i = 0, l = this.effects.length; i < l; i++) {\n this.effects[i].pause();\n }\n }\n }\n /**\n * Resumes the effect scope, including all child scopes and effects.\n */\n resume() {\n if (this._active) {\n if (this._isPaused) {\n this._isPaused = false;\n let i, l;\n if (this.scopes) {\n const scopes = this.scopes.slice();\n for (i = 0, l = scopes.length; i < l; i++) {\n scopes[i].resume();\n }\n }\n const effects = this.effects.slice();\n for (i = 0, l = effects.length; i < l; i++) {\n effects[i].resume();\n }\n }\n }\n }\n run(fn) {\n if (this._active) {\n const currentEffectScope = activeEffectScope;\n try {\n activeEffectScope = this;\n return fn();\n } finally {\n activeEffectScope = currentEffectScope;\n }\n } else if (!!(process.env.NODE_ENV !== \"production\") && this._warnOnRun) {\n warn(`cannot run an inactive effect scope.`);\n }\n }\n /**\n * This should only be called on non-detached scopes\n * @internal\n */\n on() {\n if (++this._on === 1) {\n this.prevScope = activeEffectScope;\n activeEffectScope = this;\n }\n }\n /**\n * This should only be called on non-detached scopes\n * @internal\n */\n off() {\n if (this._on > 0 && --this._on === 0) {\n if (activeEffectScope === this) {\n activeEffectScope = this.prevScope;\n } else {\n let current = activeEffectScope;\n while (current) {\n if (current.prevScope === this) {\n current.prevScope = this.prevScope;\n break;\n }\n current = current.prevScope;\n }\n }\n this.prevScope = void 0;\n }\n }\n stop(fromParent) {\n if (this._active) {\n this._active = false;\n let i, l;\n for (i = 0, l = this.effects.length; i < l; i++) {\n this.effects[i].stop();\n }\n this.effects.length = 0;\n for (i = 0, l = this.cleanups.length; i < l; i++) {\n this.cleanups[i]();\n }\n this.cleanups.length = 0;\n if (this.scopes) {\n const scopes = this.scopes.slice();\n for (i = 0, l = scopes.length; i < l; i++) {\n scopes[i].stop(true);\n }\n this.scopes.length = 0;\n }\n if (!this.detached && this.parent && !fromParent) {\n const last = this.parent.scopes.pop();\n if (last && last !== this) {\n this.parent.scopes[this.index] = last;\n last.index = this.index;\n }\n }\n this.parent = void 0;\n }\n }\n}\nfunction effectScope(detached) {\n return new EffectScope(detached);\n}\nfunction getCurrentScope() {\n return activeEffectScope;\n}\nfunction onScopeDispose(fn, failSilently = false) {\n if (activeEffectScope) {\n activeEffectScope.cleanups.push(fn);\n } else if (!!(process.env.NODE_ENV !== \"production\") && !failSilently) {\n warn(\n `onScopeDispose() is called when there is no active effect scope to be associated with.`\n );\n }\n}\n\nlet activeSub;\nconst EffectFlags = {\n \"ACTIVE\": 1,\n \"1\": \"ACTIVE\",\n \"RUNNING\": 2,\n \"2\": \"RUNNING\",\n \"TRACKING\": 4,\n \"4\": \"TRACKING\",\n \"NOTIFIED\": 8,\n \"8\": \"NOTIFIED\",\n \"DIRTY\": 16,\n \"16\": \"DIRTY\",\n \"ALLOW_RECURSE\": 32,\n \"32\": \"ALLOW_RECURSE\",\n \"PAUSED\": 64,\n \"64\": \"PAUSED\",\n \"EVALUATED\": 128,\n \"128\": \"EVALUATED\"\n};\nconst pausedQueueEffects = /* @__PURE__ */ new WeakSet();\nclass ReactiveEffect {\n constructor(fn) {\n this.fn = fn;\n /**\n * @internal\n */\n this.deps = void 0;\n /**\n * @internal\n */\n this.depsTail = void 0;\n /**\n * @internal\n */\n this.flags = 1 | 4;\n /**\n * @internal\n */\n this.next = void 0;\n /**\n * @internal\n */\n this.cleanup = void 0;\n this.scheduler = void 0;\n if (activeEffectScope) {\n if (activeEffectScope.active) {\n activeEffectScope.effects.push(this);\n } else {\n this.flags &= -2;\n }\n }\n }\n pause() {\n this.flags |= 64;\n }\n resume() {\n if (this.flags & 64) {\n this.flags &= -65;\n if (pausedQueueEffects.has(this)) {\n pausedQueueEffects.delete(this);\n this.trigger();\n }\n }\n }\n /**\n * @internal\n */\n notify() {\n if (this.flags & 2 && !(this.flags & 32)) {\n return;\n }\n if (!(this.flags & 8)) {\n batch(this);\n }\n }\n run() {\n if (!(this.flags & 1)) {\n return this.fn();\n }\n this.flags |= 2;\n cleanupEffect(this);\n prepareDeps(this);\n const prevEffect = activeSub;\n const prevShouldTrack = shouldTrack;\n activeSub = this;\n shouldTrack = true;\n try {\n return this.fn();\n } finally {\n if (!!(process.env.NODE_ENV !== \"production\") && activeSub !== this) {\n warn(\n \"Active effect was not restored correctly - this is likely a Vue internal bug.\"\n );\n }\n cleanupDeps(this);\n activeSub = prevEffect;\n shouldTrack = prevShouldTrack;\n this.flags &= -3;\n }\n }\n stop() {\n if (this.flags & 1) {\n for (let link = this.deps; link; link = link.nextDep) {\n removeSub(link);\n }\n this.deps = this.depsTail = void 0;\n cleanupEffect(this);\n this.onStop && this.onStop();\n this.flags &= -2;\n }\n }\n trigger() {\n if (this.flags & 64) {\n pausedQueueEffects.add(this);\n } else if ( SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\nasync function openConflictPicker(dirname, conflicts, content, options) {\n const ConflictPicker = defineAsyncComponent(() => import(\"./ConflictPicker.mjs\"));\n const incoming = [];\n const existing = [];\n for (const node of content) {\n if (isConflictingNode(node)) {\n existing.push(node);\n incoming.push(conflicts[indexOf(node)]);\n }\n }\n if (conflicts.length === 0 || content.length === 0) {\n throw new Error(\"ConflictPicker: files and conflicts must not be empty\");\n }\n if (conflicts.length !== content.length) {\n throw new Error(\"ConflictPicker: files and conflicts must have the same length. Make sure you filter out non conflicting files from the conflicts array.\");\n }\n return await spawnDialog(ConflictPicker, {\n dirname,\n existing,\n incoming,\n isOverwriting: options?.overwriting === true,\n recursiveUpload: options?.recursive === true\n }, {\n container: options?.container\n });\n function isConflictingNode(node) {\n return conflicts.some((entry) => nodeIsConflict(node, entry));\n }\n function indexOf(node) {\n return conflicts.findIndex((entry) => nodeIsConflict(node, entry));\n }\n function nodeIsConflict(node, conflict) {\n if (\"basename\" in conflict) {\n return conflict.basename === node.basename;\n }\n return conflict.name === node.basename;\n }\n}\nconst IconMove = '';\nconst IconCopy = '';\nconst gtBuilder = getGettextBuilder().detectLanguage();\nfor (const data of [{ \"language\": \"ar\", \"translations\": [{ \"msgid\": '\"{name}\" is an invalid folder name.', \"msgstr\": ['\"{name}\" لا يصلح كاسم مجلد.'] }, { \"msgid\": '\"{name}\" is not an allowed folder name', \"msgstr\": ['\"{name}\" غير مسموح به كاسم مجلد'] }, { \"msgid\": '\"/\" is not allowed inside a folder name.', \"msgstr\": ['\"/\" غير مسموح به داخل اسم مجلد.'] }, { \"msgid\": \"All files\", \"msgstr\": [\"كل الملفات\"] }, { \"msgid\": \"Choose\", \"msgstr\": [\"إختَر\"] }, { \"msgid\": \"Choose {file}\", \"msgstr\": [\"إختر {file}\"] }, { \"msgid\": \"Choose %n file\", \"msgid_plural\": \"Choose %n files\", \"msgstr\": [\"إختَر %n ملف\", \"إختَر %n ملف\", \"إختَر %n ملف\", \"إختَر %n ملفات\", \"إختَر %n ملف\", \"إختر %n ملف\"] }, { \"msgid\": \"Copy\", \"msgstr\": [\"نسخ\"] }, { \"msgid\": \"Copy to {target}\", \"msgstr\": [\"نسخ إلى {target}\"] }, { \"msgid\": \"Could not create the new folder\", \"msgstr\": [\"تعذّر إنشاء المجلد الجديد\"] }, { \"msgid\": \"Could not load files settings\", \"msgstr\": [\"يتعذّر تحميل إعدادات الملفات\"] }, { \"msgid\": \"Could not load files views\", \"msgstr\": [\"تعذر تحميل عرض الملفات\"] }, { \"msgid\": \"Create directory\", \"msgstr\": [\"إنشاء مجلد\"] }, { \"msgid\": \"Current view selector\", \"msgstr\": [\"محدد العرض الحالي\"] }, { \"msgid\": \"Favorites\", \"msgstr\": [\"المفضلة\"] }, { \"msgid\": \"Files and folders you mark as favorite will show up here.\", \"msgstr\": [\"الملفات والمجلدات التي تحددها كمفضلة ستظهر هنا.\"] }, { \"msgid\": \"Files and folders you recently modified will show up here.\", \"msgstr\": [\"الملفات و المجلدات التي قمت مؤخراً بتعديلها سوف تظهر هنا.\"] }, { \"msgid\": \"Filter file list\", \"msgstr\": [\"تصفية قائمة الملفات\"] }, { \"msgid\": \"Folder name cannot be empty.\", \"msgstr\": [\"اسم المجلد لا يمكن أن يكون فارغاً.\"] }, { \"msgid\": \"Home\", \"msgstr\": [\"البداية\"] }, { \"msgid\": \"Modified\", \"msgstr\": [\"التعديل\"] }, { \"msgid\": \"Move\", \"msgstr\": [\"نقل\"] }, { \"msgid\": \"Move to {target}\", \"msgstr\": [\"نقل إلى {target}\"] }, { \"msgid\": \"Name\", \"msgstr\": [\"الاسم\"] }, { \"msgid\": \"New\", \"msgstr\": [\"جديد\"] }, { \"msgid\": \"New folder\", \"msgstr\": [\"مجلد جديد\"] }, { \"msgid\": \"New folder name\", \"msgstr\": [\"اسم المجلد الجديد\"] }, { \"msgid\": \"No files in here\", \"msgstr\": [\"لا توجد ملفات هنا\"] }, { \"msgid\": \"No files matching your filter were found.\", \"msgstr\": [\"لا توجد ملفات تتطابق مع عامل التصفية الذي وضعته\"] }, { \"msgid\": \"No matching files\", \"msgstr\": [\"لا توجد ملفات مطابقة\"] }, { \"msgid\": \"Recent\", \"msgstr\": [\"الحالي\"] }, { \"msgid\": \"Select all entries\", \"msgstr\": [\"حدد جميع الإدخالات\"] }, { \"msgid\": \"Select entry\", \"msgstr\": [\"إختَر المدخل\"] }, { \"msgid\": \"Select the row for {nodename}\", \"msgstr\": [\"إختر سطر الـ {nodename}\"] }, { \"msgid\": \"Size\", \"msgstr\": [\"الحجم\"] }, { \"msgid\": \"Undo\", \"msgstr\": [\"تراجع\"] }, { \"msgid\": \"Upload some content or sync with your devices!\", \"msgstr\": [\"قم برفع بعض المحتوى أو المزامنة مع أجهزتك!\"] }] }, { \"language\": \"ast\", \"translations\": [{ \"msgid\": '\"{name}\" is an invalid folder name.', \"msgstr\": [\"«{name}» ye un nome de carpeta inválidu.\"] }, { \"msgid\": '\"{name}\" is not an allowed folder name', \"msgstr\": [\"«{name}» ye un nome de carpeta inválidu\"] }, { \"msgid\": '\"/\" is not allowed inside a folder name.', \"msgstr\": [\"Nun se permite'l caráuter «/» dientro'l nome de les carpetes.\"] }, { \"msgid\": \"All files\", \"msgstr\": [\"Tolos ficheros\"] }, { \"msgid\": \"Choose\", \"msgstr\": [\"Escoyer\"] }, { \"msgid\": \"Choose {file}\", \"msgstr\": [\"Escoyer «{ficheru}»\"] }, { \"msgid\": \"Choose %n file\", \"msgid_plural\": \"Choose %n files\", \"msgstr\": [\"Escoyer %n ficheru\", \"Escoyer %n ficheros\"] }, { \"msgid\": \"Copy\", \"msgstr\": [\"Copiar\"] }, { \"msgid\": \"Copy to {target}\", \"msgstr\": [\"Copiar en: {target}\"] }, { \"msgid\": \"Could not create the new folder\", \"msgstr\": [\"Nun se pudo crear la carpeta\"] }, { \"msgid\": \"Could not load files settings\", \"msgstr\": [\"Nun se pudo cargar la configuración de los ficheros\"] }, { \"msgid\": \"Could not load files views\", \"msgstr\": [\"Nun se pudieron cargar les vistes de los ficheros\"] }, { \"msgid\": \"Create directory\", \"msgstr\": [\"Crear un direutoriu\"] }, { \"msgid\": \"Current view selector\", \"msgstr\": [\"Selector de la vista actual\"] }, { \"msgid\": \"Favorites\", \"msgstr\": [\"Favoritos\"] }, { \"msgid\": \"Files and folders you mark as favorite will show up here.\", \"msgstr\": [\"Equí apaecen los ficheros y les carpetes que metas en Favoritos.\"] }, { \"msgid\": \"Files and folders you recently modified will show up here.\", \"msgstr\": [\"Equí apaecen los fichero y les carpetes que modificares apocayá.\"] }, { \"msgid\": \"Filter file list\", \"msgstr\": [\"Peñerar la llista de ficheros\"] }, { \"msgid\": \"Folder name cannot be empty.\", \"msgstr\": [\"El nome de la carpeta nun pue tar baleru.\"] }, { \"msgid\": \"Home\", \"msgstr\": [\"Aniciu\"] }, { \"msgid\": \"Modified\", \"msgstr\": [\"Modificóse\"] }, { \"msgid\": \"Move\", \"msgstr\": [\"Mover\"] }, { \"msgid\": \"Move to {target}\", \"msgstr\": [\"Mover a {target}\"] }, { \"msgid\": \"Name\", \"msgstr\": [\"Nome\"] }, { \"msgid\": \"New\", \"msgstr\": [\"Nuevu\"] }, { \"msgid\": \"New folder\", \"msgstr\": [\"Carpeta nueva\"] }, { \"msgid\": \"New folder name\", \"msgstr\": [\"Nome de carpeta nuevu\"] }, { \"msgid\": \"No files in here\", \"msgstr\": [\"Equí nun hai nengún ficheru\"] }, { \"msgid\": \"No files matching your filter were found.\", \"msgstr\": [\"Nun s'atopó nengún ficheru que concasare cola peñera.\"] }, { \"msgid\": \"No matching files\", \"msgstr\": [\"Nun hai nengún ficheru que concase\"] }, { \"msgid\": \"Recent\", \"msgstr\": [\"De recién\"] }, { \"msgid\": \"Select all entries\", \"msgstr\": [\"Seleicionar toles entraes\"] }, { \"msgid\": \"Select entry\", \"msgstr\": [\"Seleicionar la entrada\"] }, { \"msgid\": \"Select the row for {nodename}\", \"msgstr\": [\"Seleicionar la filera de: {nodename}\"] }, { \"msgid\": \"Size\", \"msgstr\": [\"Tamañu\"] }, { \"msgid\": \"Undo\", \"msgstr\": [\"Desfacer\"] }, { \"msgid\": \"Upload some content or sync with your devices!\", \"msgstr\": [\"¡Xubi dalgún elementu o sincroniza colos tos preseos!\"] }] }, { \"language\": \"ca\", \"translations\": [{ \"msgid\": '\"{char}\" is not allowed inside a name.', \"msgstr\": [`No és permès d'usar el caràcter \"{char}\" en un nom.`] }, { \"msgid\": '\"{extension}\" is not an allowed name.', \"msgstr\": ['\"{extension}\" no és un nom permès.'] }, { \"msgid\": '\"{name}\" is an invalid folder name.', \"msgstr\": ['\"{name}\" no és vàlid com a nom de carpeta.'] }, { \"msgid\": '\"{name}\" is not an allowed folder name', \"msgstr\": ['\"{name}\" no és vàlid com a nom de carpeta'] }, { \"msgid\": '\"{segment}\" is a reserved name and not allowed.', \"msgstr\": ['\"{segment}\" és un mot reservat i no està permès com a nom.'] }, { \"msgid\": '\"/\" is not allowed inside a folder name.', \"msgstr\": [`\"/\" no està permès en el nom d'una carpeta.`] }, { \"msgid\": \"%n file conflict\", \"msgid_plural\": \"%n files conflict\", \"msgstr\": [\"%n conflicte de fitxers\", \"%n conflictes de fitxers\"] }, { \"msgid\": \"%n file conflict in {dirname}\", \"msgid_plural\": \"%n file conflicts in {dirname}\", \"msgstr\": [\"%n onflicte de fitxers a {dirname}\", \"%n conflictes de fitxers a {dirname}\"] }, { \"msgid\": \"All files\", \"msgstr\": [\"Tots els fitxers\"] }, { \"msgid\": \"Cancel\", \"msgstr\": [\"Cancel·lar\"] }, { \"msgid\": \"Cancel the entire operation\", \"msgstr\": [\"Cancel·lar tota l'operació\"] }, { \"msgid\": \"Choose\", \"msgstr\": [\"Tria\"] }, { \"msgid\": \"Choose {file}\", \"msgstr\": [\"Tria {file}\"] }, { \"msgid\": \"Choose %n file\", \"msgid_plural\": \"Choose %n files\", \"msgstr\": [\"Tria %n fitxer\", \"Tria %n fitxers\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"Confirma\"] }, { \"msgid\": \"Continue\", \"msgstr\": [\"Continuar\"] }, { \"msgid\": \"Copy\", \"msgstr\": [\"Copia\"] }, { \"msgid\": \"Copy to {target}\", \"msgstr\": [\"Copia a {target}\"] }, { \"msgid\": \"Could not create the new folder\", \"msgstr\": [\"No s'ha pogut crear la carpeta nova\"] }, { \"msgid\": \"Could not load files settings\", \"msgstr\": [\"No es poden carregar fitxers de configuració\"] }, { \"msgid\": \"Could not load files views\", \"msgstr\": [\"No es poden carregar fitxers de vistes\"] }, { \"msgid\": \"Create directory\", \"msgstr\": [\"Crea un directori\"] }, { \"msgid\": \"Current view selector\", \"msgstr\": [\"Selector de visualització actual\"] }, { \"msgid\": \"Enter your name\", \"msgstr\": [\"Escriviu el vostre nom\"] }, { \"msgid\": \"Existing version\", \"msgstr\": [\"Versió existent\"] }, { \"msgid\": \"Failed to set nickname.\", \"msgstr\": [\"No s'ha pogut desar el sobrenom.\"] }, { \"msgid\": \"Favorites\", \"msgstr\": [\"Preferits\"] }, { \"msgid\": \"Files and folders you mark as favorite will show up here.\", \"msgstr\": [\"Els fitxers i les carpetes que marqueu com a favorits es mostraran aquí.\"] }, { \"msgid\": \"Files and folders you recently modified will show up here.\", \"msgstr\": [\"Els fitxers i les carpetes recentment modificats es mostraran aquí.\"] }, { \"msgid\": \"Filter file list\", \"msgstr\": [\"Filtrar llistat de fitxers\"] }, { \"msgid\": \"Folder name cannot be empty.\", \"msgstr\": [\"El nom de la carpeta no pot estar buit.\"] }, { \"msgid\": \"Guest identification\", \"msgstr\": [\"Identificació com a convidat\"] }, { \"msgid\": \"Home\", \"msgstr\": [\"Inici\"] }, { \"msgid\": \"If you select both versions, the incoming file will have a number added to its name.\", \"msgstr\": [\"Si seleccioneu les dues versions, el fitxer entrant tindrà un número afegit al seu nom.\"] }, { \"msgid\": \"Invalid name.\", \"msgstr\": [\"Nom no vàlid.\"] }, { \"msgid\": \"Last modified date unknown\", \"msgstr\": [\"Data de l'última modificació desconeguda\"] }, { \"msgid\": \"Modified\", \"msgstr\": [\"Data de modificació\"] }, { \"msgid\": \"Move\", \"msgstr\": [\"Desplaça\"] }, { \"msgid\": \"Move to {target}\", \"msgstr\": [\"Desplaça a {target}\"] }, { \"msgid\": \"Name\", \"msgstr\": [\"Nom\"] }, { \"msgid\": \"Names may be at most 64 characters long.\", \"msgstr\": [\"Els noms poden tenir com a màxim 64 caràcters.\"] }, { \"msgid\": \"Names must not be empty.\", \"msgstr\": [\"Els noms no poden ser buits.\"] }, { \"msgid\": 'Names must not end with \"{extension}\".', \"msgstr\": [`Els noms no poden acabar amb l'extensió \"{extension}\".`] }, { \"msgid\": \"Names must not start with a dot.\", \"msgstr\": [\"Els noms no poden començar amb un punt.\"] }, { \"msgid\": \"New\", \"msgstr\": [\"Crea\"] }, { \"msgid\": \"New folder\", \"msgstr\": [\"Carpeta nova\"] }, { \"msgid\": \"New folder name\", \"msgstr\": [\"Nom de la carpeta nova\"] }, { \"msgid\": \"New version\", \"msgstr\": [\"Nova versió\"] }, { \"msgid\": \"No files in here\", \"msgstr\": [\"No hi ha cap fitxer\"] }, { \"msgid\": \"No files matching your filter were found.\", \"msgstr\": [\"No s'ha trobat cap fitxer que coincideixi amb el filtre.\"] }, { \"msgid\": \"No matching files\", \"msgstr\": [\"No hi ha cap fitxer que coincideixi\"] }, { \"msgid\": \"Please enter a name with at least 2 characters.\", \"msgstr\": [\"Si us plau, escriu un nom amb 2 caràcters com a mínim.\"] }, { \"msgid\": \"Recent\", \"msgstr\": [\"Recents\"] }, { \"msgid\": \"Select all checkboxes\", \"msgstr\": [\"Selecciona totes les caselles de selecció\"] }, { \"msgid\": \"Select all entries\", \"msgstr\": [\"Selecciona totes les entrades\"] }, { \"msgid\": \"Select all existing files\", \"msgstr\": [\"Selecciona tots els fitxers existents\"] }, { \"msgid\": \"Select all new files\", \"msgstr\": [\"Selecciona tots els fitxers nous\"] }, { \"msgid\": \"Select entry\", \"msgstr\": [\"Selecciona l'entrada\"] }, { \"msgid\": \"Select the row for {nodename}\", \"msgstr\": [\"Selecciona la fila per a {nodename}\"] }, { \"msgid\": \"Size\", \"msgstr\": [\"Mida\"] }, { \"msgid\": \"Skip %n file\", \"msgid_plural\": \"Skip %n files\", \"msgstr\": [\"Omet %n fitxer\", \"Omet %n fitxers\"] }, { \"msgid\": \"Skip this file\", \"msgstr\": [\"Omet aquest fitxer\"] }, { \"msgid\": \"Submit name\", \"msgstr\": [\"Entreu el nom\"] }, { \"msgid\": \"Undo\", \"msgstr\": [\"Desfés\"] }, { \"msgid\": \"Upload some content or sync with your devices!\", \"msgstr\": [\"Pugeu contingut o sincronitzeu-lo amb els vostres dispositius!\"] }, { \"msgid\": \"When an incoming folder is selected, any conflicting files within it will also be overwritten.\", \"msgstr\": [\"Quan es selecciona una carpeta entrant, també se sobreescriuran els fitxers que hi entrin en conflicte.\"] }, { \"msgid\": \"When an incoming folder is selected, the content is written into the existing folder and a recursive conflict resolution is performed.\", \"msgstr\": [\"Quan es selecciona una carpeta entrant, el contingut s'escriu a la carpeta existent i es realitza una resolució recursiva de conflictes.\"] }, { \"msgid\": \"Which files do you want to keep?\", \"msgstr\": [\"Quins fitxers voleu conservar?\"] }, { \"msgid\": \"You are currently identified as {nickname}.\", \"msgstr\": [\"Actualment se us mostra com a {nickname}.\"] }, { \"msgid\": \"You are currently not identified.\", \"msgstr\": [\"Actualment no esteu identificat.\"] }, { \"msgid\": \"You cannot leave the name empty.\", \"msgstr\": [\"No podeu deixar el nom buit.\"] }, { \"msgid\": \"You need to choose at least one conflict solution\", \"msgstr\": [\"Heu de triar com a mínim una solució de conflicte\"] }, { \"msgid\": \"You need to select at least one version of each file to continue.\", \"msgstr\": [\"Heu de seleccionar com a mínim una versió de cada fitxer per continuar.\"] }] }, { \"language\": \"cs_CZ\", \"translations\": [{ \"msgid\": '\"{char}\" is not allowed inside a folder name.', \"msgstr\": [\"znak „{char}“ není možné použít uvnitř názvu složky.\"] }, { \"msgid\": '\"{char}\" is not allowed inside a name.', \"msgstr\": [\"„{char}“ není možné použít uvnitř názvu.\"] }, { \"msgid\": '\"{extension}\" is not an allowed name.', \"msgstr\": [\"„{extension}“ není možné použít jako název.\"] }, { \"msgid\": '\"{segment}\" is a reserved name and not allowed for folder names.', \"msgstr\": [\"„{segment}“ je vyhrazeným názvem a není možné ho používat pro názvy složek.\"] }, { \"msgid\": '\"{segment}\" is a reserved name and not allowed.', \"msgstr\": [\"„{segment}“ je vyhrazeným názvem a není možné ho použít.\"] }, { \"msgid\": \"%n file conflict\", \"msgid_plural\": \"%n files conflict\", \"msgstr\": [\"%n kolize souboru\", \"%n kolize souborů\", \"%n kolizí souborů\", \"%n kolize souborů\"] }, { \"msgid\": \"%n file conflict in {dirname}\", \"msgid_plural\": \"%n file conflicts in {dirname}\", \"msgstr\": [\"%n kolize souborů v {dirname}\", \"%n kolize souborů v {dirname}\", \"%n kolizí souborů v {dirname}\", \"%n kolize souborů v {dirname}\"] }, { \"msgid\": \"All files\", \"msgstr\": [\"Veškeré soubory\"] }, { \"msgid\": \"Cancel\", \"msgstr\": [\"Storno\"] }, { \"msgid\": \"Cancel the entire operation\", \"msgstr\": [\"Zrušit celou operaci\"] }, { \"msgid\": \"Choose\", \"msgstr\": [\"Zvolit\"] }, { \"msgid\": \"Choose {file}\", \"msgstr\": [\"Zvolit {file}\"] }, { \"msgid\": \"Choose %n file\", \"msgid_plural\": \"Choose %n files\", \"msgstr\": [\"Zvolte %n soubor\", \"Zvolte %n soubory\", \"Zvolte %n souborů\", \"Zvolte %n soubory\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"Potvrdit\"] }, { \"msgid\": \"Continue\", \"msgstr\": [\"Pokračovat\"] }, { \"msgid\": \"Copy\", \"msgstr\": [\"Zkopírovat\"] }, { \"msgid\": \"Copy to {target}\", \"msgstr\": [\"Zkopírovat do {target}\"] }, { \"msgid\": \"Could not create the new folder\", \"msgstr\": [\"Novou složku se nepodařilo vytvořit\"] }, { \"msgid\": \"Could not load files settings\", \"msgstr\": [\"Nepodařilo se načíst nastavení pro soubory\"] }, { \"msgid\": \"Could not load files views\", \"msgstr\": [\"Nepodařilo se načíst pohledy souborů\"] }, { \"msgid\": \"Create directory\", \"msgstr\": [\"Vytvořit složku\"] }, { \"msgid\": \"Current view selector\", \"msgstr\": [\"Výběr stávajícího zobrazení\"] }, { \"msgid\": \"Enter your name\", \"msgstr\": [\"Zadejte své jméno\"] }, { \"msgid\": \"Existing version\", \"msgstr\": [\"Existující verze\"] }, { \"msgid\": \"Failed to set nickname.\", \"msgstr\": [\"Nepodařilo se nastavit přezdívku.\"] }, { \"msgid\": \"Favorites\", \"msgstr\": [\"Oblíbené\"] }, { \"msgid\": \"Files and folders you mark as favorite will show up here.\", \"msgstr\": [\"Zde se zobrazí soubory a složky, které označíte jako oblíbené.\"] }, { \"msgid\": \"Files and folders you recently modified will show up here.\", \"msgstr\": [\"Zde se zobrazí soubory a složky, které jste nedávno pozměnili.\"] }, { \"msgid\": \"Filter file list\", \"msgstr\": [\"Filtrovat seznam souborů\"] }, { \"msgid\": 'Folder names must not end with \"{extension}\".', \"msgstr\": [\"Názvy složek nemohou končit na „{extension}“.\"] }, { \"msgid\": \"Guest identification\", \"msgstr\": [\"Identifikace hosta\"] }, { \"msgid\": \"Home\", \"msgstr\": [\"Domů\"] }, { \"msgid\": \"If you select both versions, the incoming file will have a number added to its name.\", \"msgstr\": [\"Pokud vyberete obě verze, pak k názvu příchozího souboru bude přidáno číslo.\"] }, { \"msgid\": \"Invalid folder name.\", \"msgstr\": [\"Neplatný název složky.\"] }, { \"msgid\": \"Invalid name.\", \"msgstr\": [\"Neplatný název.\"] }, { \"msgid\": \"Last modified date unknown\", \"msgstr\": [\"Datum poslední změny neznámé\"] }, { \"msgid\": \"Modified\", \"msgstr\": [\"Změněno\"] }, { \"msgid\": \"Move\", \"msgstr\": [\"Přesounout\"] }, { \"msgid\": \"Move to {target}\", \"msgstr\": [\"Přesunout do {target}\"] }, { \"msgid\": \"Name\", \"msgstr\": [\"Název\"] }, { \"msgid\": \"Names may be at most 64 characters long.\", \"msgstr\": [\"Je třeba, aby délka jmen nepřesahovala 64 znaků.\"] }, { \"msgid\": \"Names must not be empty.\", \"msgstr\": [\"Názvy je třeba vyplnit.\"] }, { \"msgid\": 'Names must not end with \"{extension}\".', \"msgstr\": [\"Názvy nemohou končit na „{extension}“.\"] }, { \"msgid\": \"Names must not start with a dot.\", \"msgstr\": [\"Názvy nemohou začínat tečkou.\"] }, { \"msgid\": \"New\", \"msgstr\": [\"Nové\"] }, { \"msgid\": \"New folder\", \"msgstr\": [\"Nová složka\"] }, { \"msgid\": \"New folder name\", \"msgstr\": [\"Název pro novou složku\"] }, { \"msgid\": \"New version\", \"msgstr\": [\"Nová verze\"] }, { \"msgid\": \"No files in here\", \"msgstr\": [\"Nejsou zde žádné soubory\"] }, { \"msgid\": \"No files matching your filter were found.\", \"msgstr\": [\"Nenalezeny žádné soubory odpovídající vašemu filtru\"] }, { \"msgid\": \"No matching files\", \"msgstr\": [\"Žádné odpovídající soubory\"] }, { \"msgid\": \"Please enter a name with at least 2 characters.\", \"msgstr\": [\"Zadejte jméno dlouhé alespoň 2 znaky.\"] }, { \"msgid\": \"Recent\", \"msgstr\": [\"Nedávné\"] }, { \"msgid\": \"Select all checkboxes\", \"msgstr\": [\"Vybrat všechny zaškrtávací kolonky\"] }, { \"msgid\": \"Select all entries\", \"msgstr\": [\"Vybrat všechny položky\"] }, { \"msgid\": \"Select all existing files\", \"msgstr\": [\"Vybrat všechny existující soubory\"] }, { \"msgid\": \"Select all new files\", \"msgstr\": [\"Vybrat všechny nové soubory\"] }, { \"msgid\": \"Select entry\", \"msgstr\": [\"Vybrat položku\"] }, { \"msgid\": \"Select the row for {nodename}\", \"msgstr\": [\"Vybrat řádek pro {nodename}\"] }, { \"msgid\": \"Size\", \"msgstr\": [\"Velikost\"] }, { \"msgid\": \"Skip %n file\", \"msgid_plural\": \"Skip %n files\", \"msgstr\": [\"Přeskočit %n soubor\", \"Přeskočit %n soubory\", \"Přeskočit %n souborů\", \"Přeskočit %n soubory\"] }, { \"msgid\": \"Skip this file\", \"msgstr\": [\"Přeskočit tento soubor\"] }, { \"msgid\": \"Submit name\", \"msgstr\": [\"Odeslat jméno\"] }, { \"msgid\": \"Undo\", \"msgstr\": [\"Zpět\"] }, { \"msgid\": \"Upload some content or sync with your devices!\", \"msgstr\": [\"Nahrajte sem nějaký obsah nebo proveďte synchronizaci se svými zařízeními!\"] }, { \"msgid\": \"When an incoming folder is selected, any conflicting files within it will also be overwritten.\", \"msgstr\": [\"Pokud je vybrána příchozí složka, budou v ní také přepsány jakékoli kolidující soubory.\"] }, { \"msgid\": \"When an incoming folder is selected, any files within it will also be overwritten.\", \"msgstr\": [\"Když je vybrána příchozí složka, jakékoli soubory v ní budou také přepsány.\"] }, { \"msgid\": \"When an incoming folder is selected, the content is written into the existing folder and a recursive conflict resolution is performed.\", \"msgstr\": [\"Pokud je vybrána příchozí složka, je obsah zapsán do existující složky a je provedeno rekurzivní vyřešení kolizí.\"] }, { \"msgid\": \"Which files do you want to keep?\", \"msgstr\": [\"Které soubory chcete ponechat?\"] }, { \"msgid\": \"You are currently identified as {nickname}.\", \"msgstr\": [\"V tuto chvíli jste identifikováni jako {nickname}.\"] }, { \"msgid\": \"You are currently not identified.\", \"msgstr\": [\"V tuto chvíli nejste identifikovaní.\"] }, { \"msgid\": \"You cannot leave the name empty.\", \"msgstr\": [\"Jméno nelze ponechat nevyplněné.\"] }, { \"msgid\": \"You need to choose at least one conflict solution\", \"msgstr\": [\"Je třeba zvolit alespoň jedno z řešení kolize\"] }, { \"msgid\": \"You need to select at least one version of each file to continue.\", \"msgstr\": [\"Aby bylo možné pokračovat, je třeba vybrat alespoň jednu verzi od každého souboru.\"] }] }, { \"language\": \"da\", \"translations\": [{ \"msgid\": '\"{char}\" is not allowed inside a name.', \"msgstr\": ['\"{char}\" er ikke tilladt i et navn.'] }, { \"msgid\": '\"{extension}\" is not an allowed name.', \"msgstr\": ['\"{extension}\" er ikke tilladt i et navn.'] }, { \"msgid\": '\"{name}\" is an invalid folder name.', \"msgstr\": ['\"{name}\" er et ugyldigt mappenavn.'] }, { \"msgid\": '\"{name}\" is not an allowed folder name', \"msgstr\": ['\"{name}\" er ikke et tilladt mappenavn'] }, { \"msgid\": '\"{segment}\" is a reserved name and not allowed.', \"msgstr\": ['\"{segment}\" er et reserveret navn og er derfor ikke tilladt.'] }, { \"msgid\": '\"/\" is not allowed inside a folder name.', \"msgstr\": ['\"/\" er ikke tilladt i et mappenavn.'] }, { \"msgid\": \"%n file conflict\", \"msgid_plural\": \"%n files conflict\", \"msgstr\": [\"%n filkonflikt\", \"%n filer konflikter\"] }, { \"msgid\": \"%n file conflict in {dirname}\", \"msgid_plural\": \"%n file conflicts in {dirname}\", \"msgstr\": [\"%n filkonflikt i {dirname}\", \"%n filkonflikter i {dirname}\"] }, { \"msgid\": \"All files\", \"msgstr\": [\"Alle filer\"] }, { \"msgid\": \"Cancel\", \"msgstr\": [\"Fortryd\"] }, { \"msgid\": \"Cancel the entire operation\", \"msgstr\": [\"Annullér hele operationen\"] }, { \"msgid\": \"Choose\", \"msgstr\": [\"Vælg\"] }, { \"msgid\": \"Choose {file}\", \"msgstr\": [\"Vælg {file}\"] }, { \"msgid\": \"Choose %n file\", \"msgid_plural\": \"Choose %n files\", \"msgstr\": [\"Vælg %n fil\", \"Vælg %n filer\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"Bekræft\"] }, { \"msgid\": \"Continue\", \"msgstr\": [\"Fortsæt\"] }, { \"msgid\": \"Copy\", \"msgstr\": [\"Kopier\"] }, { \"msgid\": \"Copy to {target}\", \"msgstr\": [\"Kopier til {target}\"] }, { \"msgid\": \"Could not create the new folder\", \"msgstr\": [\"Kunne ikke oprette den nye mappe\"] }, { \"msgid\": \"Could not load files settings\", \"msgstr\": [\"Filindstillingerne kunne ikke indlæses\"] }, { \"msgid\": \"Could not load files views\", \"msgstr\": [\"Kunne ikke indlæse filvisninger\"] }, { \"msgid\": \"Create directory\", \"msgstr\": [\"Opret mappe\"] }, { \"msgid\": \"Current view selector\", \"msgstr\": [\"Aktuel visningsvælger\"] }, { \"msgid\": \"Enter your name\", \"msgstr\": [\"Indtast dit navn\"] }, { \"msgid\": \"Existing version\", \"msgstr\": [\"Eksisterende version\"] }, { \"msgid\": \"Failed to set nickname.\", \"msgstr\": [\"Forsøg på at gemme kaldenavn mislykkedes.\"] }, { \"msgid\": \"Favorites\", \"msgstr\": [\"Favoritter\"] }, { \"msgid\": \"Files and folders you mark as favorite will show up here.\", \"msgstr\": [\"Filer og mapper, du markerer som foretrukne, vises her.\"] }, { \"msgid\": \"Files and folders you recently modified will show up here.\", \"msgstr\": [\"Filer og mapper, du for nylig har ændret, vises her.\"] }, { \"msgid\": \"Filter file list\", \"msgstr\": [\"Filtrer fil liste\"] }, { \"msgid\": \"Folder name cannot be empty.\", \"msgstr\": [\"Mappenavnet må ikke være tomt.\"] }, { \"msgid\": \"Guest identification\", \"msgstr\": [\"Gæsteidentifikation\"] }, { \"msgid\": \"Home\", \"msgstr\": [\"Hjem\"] }, { \"msgid\": \"If you select both versions, the incoming file will have a number added to its name.\", \"msgstr\": [\"Hvis du vælger begge versioner, vil den indkommende fil have et nummer tilføjet til sit navn.\"] }, { \"msgid\": \"Invalid name.\", \"msgstr\": [\"Ugyldigt navn.\"] }, { \"msgid\": \"Last modified date unknown\", \"msgstr\": [\"Senest ændret dato ukendt\"] }, { \"msgid\": \"Modified\", \"msgstr\": [\"Ændret\"] }, { \"msgid\": \"Move\", \"msgstr\": [\"Flyt\"] }, { \"msgid\": \"Move to {target}\", \"msgstr\": [\"Flyt til {target}\"] }, { \"msgid\": \"Name\", \"msgstr\": [\"Navn\"] }, { \"msgid\": \"Names may be at most 64 characters long.\", \"msgstr\": [\"Navne kan højst være 64 tegn lange.\"] }, { \"msgid\": \"Names must not be empty.\", \"msgstr\": [\"Navne kan ikke være tomt.\"] }, { \"msgid\": 'Names must not end with \"{extension}\".', \"msgstr\": ['Navne må ikke ende på \"{extension}\".'] }, { \"msgid\": \"Names must not start with a dot.\", \"msgstr\": [\"Navne skal starte med et punktum.\"] }, { \"msgid\": \"New\", \"msgstr\": [\"Ny\"] }, { \"msgid\": \"New folder\", \"msgstr\": [\"Ny mappe\"] }, { \"msgid\": \"New folder name\", \"msgstr\": [\"Ny mappe navn\"] }, { \"msgid\": \"New version\", \"msgstr\": [\"Ny version\"] }, { \"msgid\": \"No files in here\", \"msgstr\": [\"Ingen filer here\"] }, { \"msgid\": \"No files matching your filter were found.\", \"msgstr\": [\"Der blev ikke fundet nogen filer, der matcher dit filter.\"] }, { \"msgid\": \"No matching files\", \"msgstr\": [\"Ingen matchende filer\"] }, { \"msgid\": \"Please enter a name with at least 2 characters.\", \"msgstr\": [\"Indtast et navn med mindst 2 tegn.\"] }, { \"msgid\": \"Recent\", \"msgstr\": [\"Seneste\"] }, { \"msgid\": \"Select all checkboxes\", \"msgstr\": [\"Markér alle afkrydsningsfelter\"] }, { \"msgid\": \"Select all entries\", \"msgstr\": [\"Vælg alle poster\"] }, { \"msgid\": \"Select all existing files\", \"msgstr\": [\"Vælg alle eksisterende filer\"] }, { \"msgid\": \"Select all new files\", \"msgstr\": [\"Vælg alle nye filer\"] }, { \"msgid\": \"Select entry\", \"msgstr\": [\"Vælg post\"] }, { \"msgid\": \"Select the row for {nodename}\", \"msgstr\": [\"Vælg rækken for {nodenavn}\"] }, { \"msgid\": \"Size\", \"msgstr\": [\"Størelse\"] }, { \"msgid\": \"Skip %n file\", \"msgid_plural\": \"Skip %n files\", \"msgstr\": [\"Spring %n fil over\", \"Spring %n filer over\"] }, { \"msgid\": \"Skip this file\", \"msgstr\": [\"Spring denne fil over\"] }, { \"msgid\": \"Submit name\", \"msgstr\": [\"Indsend navn\"] }, { \"msgid\": \"Undo\", \"msgstr\": [\"Fortryd\"] }, { \"msgid\": \"Upload some content or sync with your devices!\", \"msgstr\": [\"Upload noget indhold eller synkroniser med dine enheder!\"] }, { \"msgid\": \"When an incoming folder is selected, any conflicting files within it will also be overwritten.\", \"msgstr\": [\"Når en indkommende mappe er valgt, vil eventuelle modstridende filer i det også blive overskrevet.\"] }, { \"msgid\": \"When an incoming folder is selected, the content is written into the existing folder and a recursive conflict resolution is performed.\", \"msgstr\": [\"Når en indkommende mappe er valgt, er indholdet skrevet ind i den eksisterende mappe og en rekursiv konfliktløsning udføres.\"] }, { \"msgid\": \"Which files do you want to keep?\", \"msgstr\": [\"Hvilke filer vil du have?\"] }, { \"msgid\": \"You are currently identified as {nickname}.\", \"msgstr\": [\"Du er i øjeblikket identificeret som {nickname}.\"] }, { \"msgid\": \"You are currently not identified.\", \"msgstr\": [\"Du er ikke identificeret.\"] }, { \"msgid\": \"You cannot leave the name empty.\", \"msgstr\": [\"Du kan ikke efterlade navnet tomt.\"] }, { \"msgid\": \"You need to choose at least one conflict solution\", \"msgstr\": [\"Du skal vælge mindst én konfliktløsning\"] }, { \"msgid\": \"You need to select at least one version of each file to continue.\", \"msgstr\": [\"Du skal vælge mindst én version af hver fil for at fortsætte.\"] }] }, { \"language\": \"de\", \"translations\": [{ \"msgid\": '\"{char}\" is not allowed inside a folder name.', \"msgstr\": ['\"{char}\" ist innerhalb eines Ordnernamens nicht zulässig.'] }, { \"msgid\": '\"{char}\" is not allowed inside a name.', \"msgstr\": ['\"{char}\" ist innerhalb eines Namens nicht zulässig.'] }, { \"msgid\": '\"{extension}\" is not an allowed name.', \"msgstr\": ['\"{extension}\" ist kein zulässiger Name.'] }, { \"msgid\": '\"{segment}\" is a reserved name and not allowed for folder names.', \"msgstr\": ['\"{segment}\" ist ein reservierter Name und nicht zulässig für Ordnernamen.'] }, { \"msgid\": '\"{segment}\" is a reserved name and not allowed.', \"msgstr\": ['\"{segment}\" ist ein reservierter Name und nicht zulässig.'] }, { \"msgid\": \"%n file conflict\", \"msgid_plural\": \"%n files conflict\", \"msgstr\": [\"%n Dateikonflikt\", \"%n Dateikonflikte\"] }, { \"msgid\": \"%n file conflict in {dirname}\", \"msgid_plural\": \"%n file conflicts in {dirname}\", \"msgstr\": [\"%n Dateikonflikt in {dirname}\", \"%n Dateikonflikte in {dirname}\"] }, { \"msgid\": \"All files\", \"msgstr\": [\"Alle Dateien\"] }, { \"msgid\": \"Cancel\", \"msgstr\": [\"Abbrechen\"] }, { \"msgid\": \"Cancel the entire operation\", \"msgstr\": [\"Den gesamten Vorgang abbrechen\"] }, { \"msgid\": \"Choose\", \"msgstr\": [\"Auswählen\"] }, { \"msgid\": \"Choose {file}\", \"msgstr\": [\"{file} auswählen\"] }, { \"msgid\": \"Choose %n file\", \"msgid_plural\": \"Choose %n files\", \"msgstr\": [\"%n Datei auswählen\", \"%n Dateien auswählen\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"Bestätigen\"] }, { \"msgid\": \"Continue\", \"msgstr\": [\"Fortsetzen\"] }, { \"msgid\": \"Copy\", \"msgstr\": [\"Kopieren\"] }, { \"msgid\": \"Copy to {target}\", \"msgstr\": [\"Nach {target} kopieren\"] }, { \"msgid\": \"Could not create the new folder\", \"msgstr\": [\"Der neue Ordner konnte nicht erstellt werden\"] }, { \"msgid\": \"Could not load files settings\", \"msgstr\": [\"Dateieinstellungen konnten nicht geladen werden\"] }, { \"msgid\": \"Could not load files views\", \"msgstr\": [\"Dateiansichten konnten nicht geladen werden\"] }, { \"msgid\": \"Create directory\", \"msgstr\": [\"Verzeichnis erstellen\"] }, { \"msgid\": \"Current view selector\", \"msgstr\": [\"Aktuelle Ansichtsauswahl\"] }, { \"msgid\": \"Enter your name\", \"msgstr\": [\"Gib deinen Namen ein\"] }, { \"msgid\": \"Existing version\", \"msgstr\": [\"Vorhandene Version\"] }, { \"msgid\": \"Failed to set nickname.\", \"msgstr\": [\"Spitzname konnte nicht gespeichert werden.\"] }, { \"msgid\": \"Favorites\", \"msgstr\": [\"Favoriten\"] }, { \"msgid\": \"Files and folders you mark as favorite will show up here.\", \"msgstr\": [\"Dateien und Ordner, die du als Favorit markierst, werden hier angezeigt.\"] }, { \"msgid\": \"Files and folders you recently modified will show up here.\", \"msgstr\": [\"Dateien und Ordner, die du kürzlich geändert hast, werden hier angezeigt.\"] }, { \"msgid\": \"Filter file list\", \"msgstr\": [\"Dateiliste filtern\"] }, { \"msgid\": 'Folder names must not end with \"{extension}\".', \"msgstr\": ['Ordnernamen dürfen nicht mit \"{extension}\" enden.'] }, { \"msgid\": \"Guest identification\", \"msgstr\": [\"Gast-Identifikation\"] }, { \"msgid\": \"Home\", \"msgstr\": [\"Home\"] }, { \"msgid\": \"If you select both versions, the incoming file will have a number added to its name.\", \"msgstr\": [\"Wenn beide Versionen ausgewählt werden, wird dem Namen der eingehenden Datei eine Nummer hinzugefügt.\"] }, { \"msgid\": \"Invalid folder name.\", \"msgstr\": [\"Ungültiger Ordnername.\"] }, { \"msgid\": \"Invalid name.\", \"msgstr\": [\"Ungültiger Name.\"] }, { \"msgid\": \"Last modified date unknown\", \"msgstr\": [\"Datum der letzten Änderung unbekannt\"] }, { \"msgid\": \"Modified\", \"msgstr\": [\"Geändert\"] }, { \"msgid\": \"Move\", \"msgstr\": [\"Verschieben\"] }, { \"msgid\": \"Move to {target}\", \"msgstr\": [\"Nach {target} verschieben\"] }, { \"msgid\": \"Name\", \"msgstr\": [\"Name\"] }, { \"msgid\": \"Names may be at most 64 characters long.\", \"msgstr\": [\"Namen dürfen maximal 64 Zeichen lang sein.\"] }, { \"msgid\": \"Names must not be empty.\", \"msgstr\": [\"Namen dürfen nicht leer sein.\"] }, { \"msgid\": 'Names must not end with \"{extension}\".', \"msgstr\": ['Namen dürfen nicht mit \"{extension}\" enden.'] }, { \"msgid\": \"Names must not start with a dot.\", \"msgstr\": [\"Namen dürfen nicht mit einem Punkt beginnen.\"] }, { \"msgid\": \"New\", \"msgstr\": [\"Neu\"] }, { \"msgid\": \"New folder\", \"msgstr\": [\"Neuer Ordner\"] }, { \"msgid\": \"New folder name\", \"msgstr\": [\"Neuer Ordnername\"] }, { \"msgid\": \"New version\", \"msgstr\": [\"Neue Version\"] }, { \"msgid\": \"No files in here\", \"msgstr\": [\"Hier sind keine Dateien\"] }, { \"msgid\": \"No files matching your filter were found.\", \"msgstr\": [\"Es wurden keine Dateien gefunden, die deinem Filter entsprechen.\"] }, { \"msgid\": \"No matching files\", \"msgstr\": [\"Keine passenden Dateien\"] }, { \"msgid\": \"Please enter a name with at least 2 characters.\", \"msgstr\": [\"Bitte einen Namen mit mindestens zwei Zeichen eingeben.\"] }, { \"msgid\": \"Recent\", \"msgstr\": [\"Neueste\"] }, { \"msgid\": \"Select all checkboxes\", \"msgstr\": [\"Alle Kontrollkästchen aktivieren\"] }, { \"msgid\": \"Select all entries\", \"msgstr\": [\"Alle Einträge auswählen\"] }, { \"msgid\": \"Select all existing files\", \"msgstr\": [\"Alle vorhandenen Dateien auswählen\"] }, { \"msgid\": \"Select all new files\", \"msgstr\": [\"Alle neuen Dateien auswählen\"] }, { \"msgid\": \"Select entry\", \"msgstr\": [\"Eintrag auswählen\"] }, { \"msgid\": \"Select the row for {nodename}\", \"msgstr\": [\"Die Zeile für {nodename} auswählen.\"] }, { \"msgid\": \"Size\", \"msgstr\": [\"Größe\"] }, { \"msgid\": \"Skip %n file\", \"msgid_plural\": \"Skip %n files\", \"msgstr\": [\"%n Datei überspringen\", \"%n Dateien überspringen\"] }, { \"msgid\": \"Skip this file\", \"msgstr\": [\"Diese Datei überspringen\"] }, { \"msgid\": \"Submit name\", \"msgstr\": [\"Namen senden\"] }, { \"msgid\": \"Undo\", \"msgstr\": [\"Rückgängig machen\"] }, { \"msgid\": \"Upload some content or sync with your devices!\", \"msgstr\": [\"Lade Inhalte hoch oder synchronisiere diese mit deinen Geräten!\"] }, { \"msgid\": \"When an incoming folder is selected, any conflicting files within it will also be overwritten.\", \"msgstr\": [\"Wenn ein eingehender Ordner ausgewählt wird, werden auch alle darin enthaltenen Dateien mit Konflikten überschrieben.\"] }, { \"msgid\": \"When an incoming folder is selected, any files within it will also be overwritten.\", \"msgstr\": [\"Wenn ein eingehender Ordner ausgewählt wird, werden auch alle darin enthaltenen Dateien überschrieben.\"] }, { \"msgid\": \"When an incoming folder is selected, the content is written into the existing folder and a recursive conflict resolution is performed.\", \"msgstr\": [\"Bei Auswahl eines eingehenden Ordners wird der Inhalt in den vorhandenen Ordner geschrieben und eine rekursive Konfliktlösung durchgeführt.\"] }, { \"msgid\": \"Which files do you want to keep?\", \"msgstr\": [\"Welche Dateien sollen behalten werden?\"] }, { \"msgid\": \"You are currently identified as {nickname}.\", \"msgstr\": [\"Du bist derzeit als {nickname} identifiziert.\"] }, { \"msgid\": \"You are currently not identified.\", \"msgstr\": [\"Du bist momentan nicht identifiziert.\"] }, { \"msgid\": \"You cannot leave the name empty.\", \"msgstr\": [\"Du kannst den Namen nicht leer lassen.\"] }, { \"msgid\": \"You need to choose at least one conflict solution\", \"msgstr\": [\"Es muss mindestens eine Konfliktlösung gewählt werden\"] }, { \"msgid\": \"You need to select at least one version of each file to continue.\", \"msgstr\": [\"Es muss mindestens eine Version jeder Datei ausgewählt werden, um fortzufahren.\"] }] }, { \"language\": \"de_DE\", \"translations\": [{ \"msgid\": '\"{char}\" is not allowed inside a folder name.', \"msgstr\": ['\"{char}\" ist innerhalb eines Ordnernamens nicht zulässig.'] }, { \"msgid\": '\"{char}\" is not allowed inside a name.', \"msgstr\": ['\"{char}\" ist innerhalb eines Namens nicht zulässig.'] }, { \"msgid\": '\"{extension}\" is not an allowed name.', \"msgstr\": ['\"{extension}\" ist kein zulässiger Name.'] }, { \"msgid\": '\"{segment}\" is a reserved name and not allowed for folder names.', \"msgstr\": ['\"{segment}\" ist ein reservierter Name und nicht zulässig für Ordnernamen.'] }, { \"msgid\": '\"{segment}\" is a reserved name and not allowed.', \"msgstr\": ['\"{segment}\" ist ein reservierter Name und nicht zulässig.'] }, { \"msgid\": \"%n file conflict\", \"msgid_plural\": \"%n files conflict\", \"msgstr\": [\"%n Dateikonflikt\", \"%n Dateikonflikte\"] }, { \"msgid\": \"%n file conflict in {dirname}\", \"msgid_plural\": \"%n file conflicts in {dirname}\", \"msgstr\": [\"%n Dateikonflikt in {dirname}\", \"%n Dateikonflikte in {dirname}\"] }, { \"msgid\": \"All files\", \"msgstr\": [\"Alle Dateien\"] }, { \"msgid\": \"Cancel\", \"msgstr\": [\"Abbrechen\"] }, { \"msgid\": \"Cancel the entire operation\", \"msgstr\": [\"Den gesamten Vorgang abbrechen\"] }, { \"msgid\": \"Choose\", \"msgstr\": [\"Auswählen\"] }, { \"msgid\": \"Choose {file}\", \"msgstr\": [\"{file} auswählen\"] }, { \"msgid\": \"Choose %n file\", \"msgid_plural\": \"Choose %n files\", \"msgstr\": [\"%n Datei auswählen\", \"%n Dateien auswählen\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"Bestätigen\"] }, { \"msgid\": \"Continue\", \"msgstr\": [\"Fortsetzen\"] }, { \"msgid\": \"Copy\", \"msgstr\": [\"Kopieren\"] }, { \"msgid\": \"Copy to {target}\", \"msgstr\": [\"Nach {target} kopieren\"] }, { \"msgid\": \"Could not create the new folder\", \"msgstr\": [\"Der neue Ordner konnte nicht erstellt werden\"] }, { \"msgid\": \"Could not load files settings\", \"msgstr\": [\"Dateieinstellungen konnten nicht geladen werden\"] }, { \"msgid\": \"Could not load files views\", \"msgstr\": [\"Dateiansichten konnten nicht geladen werden\"] }, { \"msgid\": \"Create directory\", \"msgstr\": [\"Verzeichnis erstellen\"] }, { \"msgid\": \"Current view selector\", \"msgstr\": [\"Aktuelle Ansichtsauswahl\"] }, { \"msgid\": \"Enter your name\", \"msgstr\": [\"Geben Sie Ihren Namen ein\"] }, { \"msgid\": \"Existing version\", \"msgstr\": [\"Vorhandene Version\"] }, { \"msgid\": \"Failed to set nickname.\", \"msgstr\": [\"Spitzname konnte nicht gespeichert werden.\"] }, { \"msgid\": \"Favorites\", \"msgstr\": [\"Favoriten\"] }, { \"msgid\": \"Files and folders you mark as favorite will show up here.\", \"msgstr\": [\"Dateien und Ordner, die Sie als Favorit markieren, werden hier angezeigt.\"] }, { \"msgid\": \"Files and folders you recently modified will show up here.\", \"msgstr\": [\"Dateien und Ordner, die Sie kürzlich geändert haben, werden hier angezeigt.\"] }, { \"msgid\": \"Filter file list\", \"msgstr\": [\"Dateiliste filtern\"] }, { \"msgid\": 'Folder names must not end with \"{extension}\".', \"msgstr\": ['Ordnernamen dürfen nicht mit \"{extension}\" enden.'] }, { \"msgid\": \"Guest identification\", \"msgstr\": [\"Gast-Identifikation\"] }, { \"msgid\": \"Home\", \"msgstr\": [\"Home\"] }, { \"msgid\": \"If you select both versions, the incoming file will have a number added to its name.\", \"msgstr\": [\"Wenn beide Versionen ausgewählt werden, wird dem Namen der eingehenden Datei eine Nummer hinzugefügt.\"] }, { \"msgid\": \"Invalid folder name.\", \"msgstr\": [\"Ungültiger Ordnername.\"] }, { \"msgid\": \"Invalid name.\", \"msgstr\": [\"Ungültiger Name.\"] }, { \"msgid\": \"Last modified date unknown\", \"msgstr\": [\"Datum der letzten Änderung unbekannt\"] }, { \"msgid\": \"Modified\", \"msgstr\": [\"Geändert\"] }, { \"msgid\": \"Move\", \"msgstr\": [\"Verschieben\"] }, { \"msgid\": \"Move to {target}\", \"msgstr\": [\"Nach {target} verschieben\"] }, { \"msgid\": \"Name\", \"msgstr\": [\"Name\"] }, { \"msgid\": \"Names may be at most 64 characters long.\", \"msgstr\": [\"Namen dürfen maximal 64 Zeichen lang sein.\"] }, { \"msgid\": \"Names must not be empty.\", \"msgstr\": [\"Namen dürfen nicht leer sein.\"] }, { \"msgid\": 'Names must not end with \"{extension}\".', \"msgstr\": ['Namen dürfen nicht mit \"{extension}\" enden.'] }, { \"msgid\": \"Names must not start with a dot.\", \"msgstr\": [\"Namen dürfen nicht mit einem Punkt beginnen.\"] }, { \"msgid\": \"New\", \"msgstr\": [\"Neu\"] }, { \"msgid\": \"New folder\", \"msgstr\": [\"Neuer Ordner\"] }, { \"msgid\": \"New folder name\", \"msgstr\": [\"Neuer Ordnername\"] }, { \"msgid\": \"New version\", \"msgstr\": [\"Neue Version\"] }, { \"msgid\": \"No files in here\", \"msgstr\": [\"Hier sind keine Dateien\"] }, { \"msgid\": \"No files matching your filter were found.\", \"msgstr\": [\"Es wurden keine Dateien gefunden, die Ihrem Filter entsprechen.\"] }, { \"msgid\": \"No matching files\", \"msgstr\": [\"Keine passenden Dateien\"] }, { \"msgid\": \"Please enter a name with at least 2 characters.\", \"msgstr\": [\"Bitte einen Namen mit mindestens zwei Zeichen eingeben.\"] }, { \"msgid\": \"Recent\", \"msgstr\": [\"Neueste\"] }, { \"msgid\": \"Select all checkboxes\", \"msgstr\": [\"Alle Kontrollkästchen aktivieren\"] }, { \"msgid\": \"Select all entries\", \"msgstr\": [\"Alle Einträge auswählen\"] }, { \"msgid\": \"Select all existing files\", \"msgstr\": [\"Alle vorhandenen Dateien auswählen\"] }, { \"msgid\": \"Select all new files\", \"msgstr\": [\"All SPDX-FileCopyrightText: 2022-2024, 2022-2024, 2020-2024, 1040, 2022, 2020, 2025, 2026, 2022, 2020 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: GPL-3.0-or-later\n */\nimport { isAxiosError } from 'axios';\nconst RETRY_DELAY_KEY = '_nextcloudMaintenanceModeRetryDelay';\n/**\n * Handles Nextcloud maintenance mode errors in Axios requests.\n *\n * @param axios - The current Axios instance\n */\nexport function onMaintenanceModeError(axios) {\n return async (error) => {\n if (!isAxiosError(error)) {\n throw error;\n }\n const { config, response, request } = error;\n const responseURL = request?.responseURL;\n const status = response?.status;\n const headers = response?.headers;\n let retryDelay = config?.[RETRY_DELAY_KEY] ?? 1;\n /**\n * Retry requests if they failed due to maintenance mode\n *\n * The delay is exponential. It starts at 2s and then doubles\n * until a final retry after 32s. This results in roughly 1m of\n * retries until we give up and throw the axios error towards\n * the caller.\n */\n if (status === 503\n && headers?.['x-nextcloud-maintenance-mode'] === '1'\n && config?.retryIfMaintenanceMode) {\n retryDelay *= 2;\n if (retryDelay > 32) {\n console.error('Retry delay exceeded one minute, giving up.', { responseURL });\n throw error;\n }\n console.warn(`Request to ${responseURL} failed because of maintenance mode. Retrying in ${retryDelay}s`);\n await new Promise((resolve) => {\n setTimeout(resolve, retryDelay * 1000);\n });\n return axios({\n ...config,\n [RETRY_DELAY_KEY]: retryDelay,\n });\n }\n throw error;\n };\n}\n","/**\n * SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: GPL-3.0-or-later\n */\nimport { isAxiosError } from 'axios';\n/**\n * Axios response interceptor onError callback.\n * This interceptor checks if the response failed because of a expired user session\n * and if enabled it will cause a redirect to the login.\n *\n * @param error - The response error\n */\nexport async function onNotLoggedInError(error) {\n if (isAxiosError(error)) {\n const { config, response, request } = error;\n const responseURL = request?.responseURL;\n const status = response?.status;\n if (status === 401\n && response?.data?.message === 'Current user is not logged in'\n && config?.reloadExpiredSession\n && globalThis.location?.reload) {\n console.error(`Request to ${responseURL} failed because the user session expired. Reloading the page …`);\n if (globalThis.OC?.reload) {\n globalThis.OC.reload();\n }\n else {\n globalThis.location.reload();\n }\n }\n }\n throw error;\n}\n","/**\n * SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: GPL-3.0-or-later\n */\nimport { getCancelableClient } from \"./client.js\";\nimport { onCsrfTokenError } from \"./interceptors/csrf-token.js\";\nimport { onMaintenanceModeError } from \"./interceptors/maintenance-mode.js\";\nimport { onNotLoggedInError } from \"./interceptors/not-logged-in.js\";\nconst cancelableClient = getCancelableClient();\ncancelableClient.interceptors.response.use((r) => r, onCsrfTokenError(cancelableClient));\ncancelableClient.interceptors.response.use((r) => r, onMaintenanceModeError(cancelableClient));\ncancelableClient.interceptors.response.use((r) => r, onNotLoggedInError);\nexport { isAxiosError, isCancel } from 'axios';\nexport default cancelableClient;\n","import { loadState } from \"@nextcloud/initial-state\";\nfunction getCapabilities() {\n try {\n return loadState(\"core\", \"capabilities\");\n } catch (error) {\n console.debug(\"Could not find capabilities initial state fall back to _oc_capabilities\");\n if (!(\"_oc_capabilities\" in window)) {\n return {};\n }\n return window[\"_oc_capabilities\"];\n }\n}\nexport {\n getCapabilities\n};\n//# sourceMappingURL=index.mjs.map\n","export default function debounce(function_, wait = 100, options = {}) {\n\tif (typeof function_ !== 'function') {\n\t\tthrow new TypeError(`Expected the first parameter to be a function, got \\`${typeof function_}\\`.`);\n\t}\n\n\tif (wait < 0) {\n\t\tthrow new RangeError('`wait` must not be negative.');\n\t}\n\n\tif (typeof options === 'boolean') {\n\t\tthrow new TypeError('The `options` parameter must be an object, not a boolean. Use `{immediate: true}` instead.');\n\t}\n\n\tconst {immediate} = options;\n\n\tlet storedContext;\n\tlet storedArguments;\n\tlet timeoutId;\n\tlet timestamp;\n\tlet result;\n\n\tfunction run() {\n\t\tconst callContext = storedContext;\n\t\tconst callArguments = storedArguments;\n\t\tstoredContext = undefined;\n\t\tstoredArguments = undefined;\n\t\tresult = function_.apply(callContext, callArguments);\n\t\treturn result;\n\t}\n\n\tfunction later() {\n\t\tconst last = Date.now() - timestamp;\n\n\t\tif (last < wait && last >= 0) {\n\t\t\ttimeoutId = setTimeout(later, wait - last);\n\t\t} else {\n\t\t\ttimeoutId = undefined;\n\n\t\t\tif (!immediate) {\n\t\t\t\tresult = run();\n\t\t\t}\n\t\t}\n\t}\n\n\tconst debounced = function (...arguments_) {\n\t\tif (\n\t\t\tstoredContext\n\t\t\t&& this !== storedContext\n\t\t\t&& Object.getPrototypeOf(this) === Object.getPrototypeOf(storedContext)\n\t\t) {\n\t\t\tthrow new Error('Debounced method called with different contexts of the same prototype.');\n\t\t}\n\n\t\tstoredContext = this; // eslint-disable-line unicorn/no-this-assignment\n\t\tstoredArguments = arguments_;\n\t\ttimestamp = Date.now();\n\n\t\tconst callNow = immediate && !timeoutId;\n\n\t\tif (!timeoutId) {\n\t\t\ttimeoutId = setTimeout(later, wait);\n\t\t}\n\n\t\tif (callNow) {\n\t\t\tresult = run();\n\t\t\treturn result;\n\t\t}\n\n\t\treturn undefined;\n\t};\n\n\tObject.defineProperty(debounced, 'isPending', {\n\t\tget() {\n\t\t\treturn timeoutId !== undefined;\n\t\t},\n\t});\n\n\tdebounced.clear = () => {\n\t\tif (!timeoutId) {\n\t\t\treturn;\n\t\t}\n\n\t\tclearTimeout(timeoutId);\n\t\ttimeoutId = undefined;\n\t\tstoredContext = undefined;\n\t\tstoredArguments = undefined;\n\t};\n\n\tdebounced.flush = () => {\n\t\tif (!timeoutId) {\n\t\t\treturn;\n\t\t}\n\n\t\tdebounced.trigger();\n\t};\n\n\tdebounced.trigger = () => {\n\t\tresult = run();\n\n\t\tdebounced.clear();\n\t};\n\n\treturn debounced;\n}\n","import '../assets/NcInputField-DpyFJ1xw.css';\nimport { defineComponent, useModel, useAttrs, useTemplateRef, computed, warn, openBlock, createElementBlock, normalizeClass, unref, createElementVNode, mergeProps, toDisplayString, createCommentVNode, withDirectives, renderSlot, vShow, createBlock, withCtx, createTextVNode, mergeModels } from \"vue\";\nimport { d as mdiCheck, j as mdiAlertCircleOutline } from \"./mdi-CpchYUUV.mjs\";\nimport { N as NcButton } from \"./NcButton-jvoYS2my.mjs\";\nimport { N as NcIconSvgWrapper } from \"./NcIconSvgWrapper-g8ubWhoz.mjs\";\nimport { c as createElementId } from \"./createElementId-DhjFt1I9.mjs\";\nimport { a as isLegacy } from \"./legacy-BoqDmOCa.mjs\";\nimport { _ as _export_sfc } from \"./_plugin-vue_export-helper-1tPrXgE0.mjs\";\nconst _hoisted_1 = { class: \"input-field__main-wrapper\" };\nconst _hoisted_2 = [\"id\", \"aria-describedby\", \"disabled\", \"placeholder\", \"type\", \"value\"];\nconst _hoisted_3 = [\"for\"];\nconst _hoisted_4 = { class: \"input-field__icon input-field__icon--leading\" };\nconst _hoisted_5 = {\n key: 2,\n class: \"input-field__icon input-field__icon--trailing\"\n};\nconst _hoisted_6 = [\"id\"];\nconst _sfc_main = /* @__PURE__ */ defineComponent({\n ...{\n inheritAttrs: false\n },\n __name: \"NcInputField\",\n props: /* @__PURE__ */ mergeModels({\n class: { default: \"\" },\n inputClass: { default: \"\" },\n id: { default: () => createElementId() },\n label: { default: void 0 },\n labelOutside: { type: Boolean },\n type: { default: \"text\" },\n placeholder: { default: void 0 },\n showTrailingButton: { type: Boolean },\n trailingButtonLabel: { default: void 0 },\n success: { type: Boolean },\n error: { type: Boolean },\n helperText: { default: \"\" },\n disabled: { type: Boolean },\n pill: { type: Boolean }\n }, {\n \"modelValue\": { required: true },\n \"modelModifiers\": {}\n }),\n emits: /* @__PURE__ */ mergeModels([\"trailingButtonClick\"], [\"update:modelValue\"]),\n setup(__props, { expose: __expose, emit: __emit }) {\n const modelValue = useModel(__props, \"modelValue\");\n const props = __props;\n const emit = __emit;\n __expose({\n focus,\n select\n });\n const attrs = useAttrs();\n const inputElement = useTemplateRef(\"input\");\n const hasTrailingIcon = computed(() => props.showTrailingButton || props.success);\n const internalPlaceholder = computed(() => {\n if (props.placeholder) {\n return props.placeholder;\n }\n if (props.label) {\n return isLegacy ? props.label : \"\";\n }\n return void 0;\n });\n const isValidLabel = computed(() => {\n const isValidLabel2 = props.label || props.labelOutside;\n if (!isValidLabel2) {\n warn(\"You need to add a label to the NcInputField component. Either use the prop label or use an external one, as per the example in the documentation.\");\n }\n return isValidLabel2;\n });\n const ariaDescribedby = computed(() => {\n const ariaDescribedby2 = [];\n if (props.helperText) {\n ariaDescribedby2.push(`${props.id}-helper-text`);\n }\n if (attrs[\"aria-describedby\"]) {\n ariaDescribedby2.push(String(attrs[\"aria-describedby\"]));\n }\n return ariaDescribedby2.join(\" \") || void 0;\n });\n function focus(options) {\n inputElement.value.focus(options);\n }\n function select() {\n inputElement.value.select();\n }\n function handleInput(event) {\n const target = event.target;\n modelValue.value = props.type === \"number\" && typeof modelValue.value === \"number\" ? parseFloat(target.value) : target.value;\n }\n return (_ctx, _cache) => {\n return openBlock(), createElementBlock(\"div\", {\n class: normalizeClass([\"input-field\", [{\n \"input-field--disabled\": __props.disabled,\n \"input-field--error\": __props.error,\n \"input-field--label-outside\": __props.labelOutside || !isValidLabel.value,\n \"input-field--leading-icon\": !!_ctx.$slots.icon,\n \"input-field--trailing-icon\": hasTrailingIcon.value,\n \"input-field--pill\": __props.pill,\n \"input-field--success\": __props.success,\n \"input-field--legacy\": unref(isLegacy)\n }, _ctx.$props.class]])\n }, [\n createElementVNode(\"div\", _hoisted_1, [\n createElementVNode(\"input\", mergeProps(_ctx.$attrs, {\n id: __props.id,\n ref: \"input\",\n \"aria-describedby\": ariaDescribedby.value,\n \"aria-live\": \"polite\",\n class: [\"input-field__input\", __props.inputClass],\n disabled: __props.disabled,\n placeholder: internalPlaceholder.value,\n type: __props.type,\n value: modelValue.value.toString(),\n onInput: handleInput\n }), null, 16, _hoisted_2),\n !__props.labelOutside && isValidLabel.value ? (openBlock(), createElementBlock(\"label\", {\n key: 0,\n class: \"input-field__label\",\n for: __props.id\n }, toDisplayString(__props.label), 9, _hoisted_3)) : createCommentVNode(\"\", true),\n withDirectives(createElementVNode(\"div\", _hoisted_4, [\n renderSlot(_ctx.$slots, \"icon\", {}, void 0, true)\n ], 512), [\n [vShow, !!_ctx.$slots.icon]\n ]),\n __props.showTrailingButton ? (openBlock(), createBlock(NcButton, {\n key: 1,\n class: \"input-field__trailing-button\",\n \"aria-label\": __props.trailingButtonLabel,\n disabled: __props.disabled,\n variant: \"tertiary-no-background\",\n onClick: _cache[0] || (_cache[0] = ($event) => emit(\"trailingButtonClick\", $event))\n }, {\n icon: withCtx(() => [\n renderSlot(_ctx.$slots, \"trailing-button-icon\", {}, void 0, true)\n ]),\n _: 3\n }, 8, [\"aria-label\", \"disabled\"])) : __props.success || __props.error ? (openBlock(), createElementBlock(\"div\", _hoisted_5, [\n __props.success ? (openBlock(), createBlock(NcIconSvgWrapper, {\n key: 0,\n path: unref(mdiCheck)\n }, null, 8, [\"path\"])) : (openBlock(), createBlock(NcIconSvgWrapper, {\n key: 1,\n path: unref(mdiAlertCircleOutline)\n }, null, 8, [\"path\"]))\n ])) : createCommentVNode(\"\", true)\n ]),\n __props.helperText ? (openBlock(), createElementBlock(\"p\", {\n key: 0,\n id: `${__props.id}-helper-text`,\n class: \"input-field__helper-text-message\"\n }, [\n __props.success ? (openBlock(), createBlock(NcIconSvgWrapper, {\n key: 0,\n class: \"input-field__helper-text-message__icon\",\n path: unref(mdiCheck),\n inline: \"\"\n }, null, 8, [\"path\"])) : __props.error ? (openBlock(), createBlock(NcIconSvgWrapper, {\n key: 1,\n class: \"input-field__helper-text-message__icon\",\n path: unref(mdiAlertCircleOutline),\n inline: \"\"\n }, null, 8, [\"path\"])) : createCommentVNode(\"\", true),\n createTextVNode(\" \" + toDisplayString(__props.helperText), 1)\n ], 8, _hoisted_6)) : createCommentVNode(\"\", true)\n ], 2);\n };\n }\n});\nconst NcInputField = /* @__PURE__ */ _export_sfc(_sfc_main, [[\"__scopeId\", \"data-v-8e16cbb5\"]]);\nexport {\n NcInputField as N\n};\n//# sourceMappingURL=NcInputField-5Sg6EUP6.mjs.map\n","import '../assets/NcPasswordField-BN4HFgU5.css';\nimport { defineComponent, useModel, useTemplateRef, ref, computed, watch, openBlock, createBlock, mergeProps, unref, createSlots, withCtx, createVNode, renderSlot, mergeModels } from \"vue\";\nimport { q as mdiEyeOff, r as mdiEye } from \"./mdi-CpchYUUV.mjs\";\nimport axios from \"@nextcloud/axios\";\nimport { getCapabilities } from \"@nextcloud/capabilities\";\nimport { generateOcsUrl } from \"@nextcloud/router\";\nimport debounce from \"debounce\";\nimport { N as NcIconSvgWrapper } from \"./NcIconSvgWrapper-g8ubWhoz.mjs\";\nimport { N as NcInputField } from \"./NcInputField-5Sg6EUP6.mjs\";\nimport { r as register, n as t29, a as t } from \"./_l10n-wdIzZwir.mjs\";\nimport { l as logger } from \"./logger-D3RVzcfQ.mjs\";\nimport { _ as _export_sfc } from \"./_plugin-vue_export-helper-1tPrXgE0.mjs\";\nregister(t29);\nconst _sfc_main = /* @__PURE__ */ defineComponent({\n __name: \"NcPasswordField\",\n props: /* @__PURE__ */ mergeModels({\n class: {},\n inputClass: { default: \"\" },\n id: {},\n label: {},\n labelOutside: { type: Boolean },\n placeholder: {},\n showTrailingButton: { type: Boolean, default: true },\n success: { type: Boolean },\n error: { type: Boolean },\n helperText: {},\n disabled: { type: Boolean },\n pill: { type: Boolean },\n checkPasswordStrength: { type: Boolean },\n minlength: { default: void 0 },\n asText: { type: Boolean }\n }, {\n \"modelValue\": { default: \"\" },\n \"modelModifiers\": {},\n \"visible\": { type: Boolean, ...{ default: false } },\n \"visibleModifiers\": {}\n }),\n emits: /* @__PURE__ */ mergeModels([\"valid\", \"invalid\"], [\"update:modelValue\", \"update:visible\"]),\n setup(__props, { expose: __expose, emit: __emit }) {\n const modelValue = useModel(__props, \"modelValue\");\n const visible = useModel(__props, \"visible\");\n const props = __props;\n const emit = __emit;\n __expose({\n focus,\n select\n });\n const { password_policy: passwordPolicy } = getCapabilities();\n const inputFieldInstance = useTemplateRef(\"inputField\");\n const internalHelpMessage = ref(\"\");\n const isValid = ref();\n const propsToForward = computed(() => {\n const all = { ...props };\n delete all.checkPasswordStrength;\n delete all.minlength;\n delete all.asText;\n delete all.error;\n delete all.helperText;\n delete all.inputClass;\n delete all.success;\n return all;\n });\n const minLengthWithPolicy = computed(() => {\n return props.minlength ?? (props.checkPasswordStrength ? passwordPolicy?.minLength : void 0) ?? void 0;\n });\n watch(modelValue, () => {\n isValid.value = void 0;\n internalHelpMessage.value = \"\";\n });\n watch(modelValue, debounce(checkPassword, 500));\n async function checkPassword() {\n if (!props.checkPasswordStrength || !modelValue.value) {\n return;\n }\n try {\n const { data } = await axios.post(generateOcsUrl(\"apps/password_policy/api/v1/validate\"), { password: modelValue.value });\n isValid.value = data.ocs.data.passed;\n if (data.ocs.data.passed) {\n internalHelpMessage.value = t(\"Password is secure\");\n emit(\"valid\");\n return;\n }\n internalHelpMessage.value = data.ocs.data.reason;\n emit(\"invalid\");\n } catch (error) {\n logger.error(\"Password policy returned an error\", { error });\n }\n }\n function toggleVisibility() {\n visible.value = !visible.value;\n }\n function focus(options) {\n inputFieldInstance.value.focus(options);\n }\n function select() {\n inputFieldInstance.value.select();\n }\n return (_ctx, _cache) => {\n return openBlock(), createBlock(NcInputField, mergeProps(propsToForward.value, {\n ref: \"inputField\",\n modelValue: modelValue.value,\n \"onUpdate:modelValue\": _cache[0] || (_cache[0] = ($event) => modelValue.value = $event),\n error: __props.error || isValid.value === false,\n helperText: __props.helperText || internalHelpMessage.value,\n inputClass: [__props.inputClass, { \"password-field__input--secure-text\": !visible.value && __props.asText }],\n minlength: minLengthWithPolicy.value,\n success: __props.success || isValid.value === true,\n trailingButtonLabel: visible.value ? unref(t)(\"Hide password\") : unref(t)(\"Show password\"),\n type: visible.value || __props.asText ? \"text\" : \"password\",\n onTrailingButtonClick: toggleVisibility\n }), createSlots({\n \"trailing-button-icon\": withCtx(() => [\n createVNode(NcIconSvgWrapper, {\n path: visible.value ? unref(mdiEyeOff) : unref(mdiEye)\n }, null, 8, [\"path\"])\n ]),\n _: 2\n }, [\n !!_ctx.$slots.icon ? {\n name: \"icon\",\n fn: withCtx(() => [\n renderSlot(_ctx.$slots, \"icon\", {}, void 0, true)\n ]),\n key: \"0\"\n } : void 0\n ]), [\"modelValue\", \"error\", \"helperText\", \"inputClass\", \"minlength\", \"success\", \"trailingButtonLabel\", \"type\"]);\n };\n }\n});\nconst NcPasswordField = /* @__PURE__ */ _export_sfc(_sfc_main, [[\"__scopeId\", \"data-v-cb828737\"]]);\nexport {\n NcPasswordField as N\n};\n//# sourceMappingURL=NcPasswordField-BFyzHTOO.mjs.map\n","import { getCurrentUser } from \"@nextcloud/auth\";\nimport axios, { isAxiosError } from \"@nextcloud/axios\";\nimport { generateUrl } from \"@nextcloud/router\";\nimport { spawnDialog } from \"@nextcloud/vue/functions/dialog\";\nimport { defineComponent, onMounted, useTemplateRef, ref, computed, nextTick, openBlock, createBlock, unref, withCtx, createElementVNode, toDisplayString, createVNode } from \"vue\";\nimport NcDialog from \"@nextcloud/vue/components/NcDialog\";\nimport NcPasswordField from \"@nextcloud/vue/components/NcPasswordField\";\nimport { getLoggerBuilder } from \"@nextcloud/logger\";\nimport { getGettextBuilder } from \"@nextcloud/l10n/gettext\";\n/*!\n * SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: MIT\n */\nvar PwdConfirmationMode = /* @__PURE__ */ ((PwdConfirmationMode2) => {\n PwdConfirmationMode2[\"Lax\"] = \"lax\";\n PwdConfirmationMode2[\"Strict\"] = \"strict\";\n return PwdConfirmationMode2;\n})(PwdConfirmationMode || {});\n/*!\n * SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: MIT\n */\nconst PAGE_LOAD_TIME = Date.now();\nfunction isPasswordConfirmationRequired(mode) {\n if (!window.backendAllowsPasswordConfirmation) {\n return false;\n }\n if (mode === PwdConfirmationMode.Strict) {\n return true;\n }\n const serverTimeDiff = PAGE_LOAD_TIME - window.nc_pageLoad * 1e3;\n const timeSinceLogin = Date.now() - (serverTimeDiff + window.nc_lastLogin * 1e3);\n return timeSinceLogin > 30 * 60 * 1e3;\n}\n/*!\n * SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: CC0-1.0\n */\nconst logger = getLoggerBuilder().setApp(\"@nextcloud/password-confirmation\").detectLogLevel().build();\n/*!\n * SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: MIT\n */\nconst [NC_MAJOR_VERSION] = window._oc_config?.version.split(\".\").map(Number) ?? [];\nfunction isConfirmationError(error) {\n if (!isAxiosError(error) || !error.response) {\n return false;\n }\n const hasConfirmationHeader = error.response.headers?.[\"x-nextcloud-password-confirmation\"] === \"true\";\n if (NC_MAJOR_VERSION < 32) {\n logger.debug(\"Handle legacy confirmation error based on status code\", { status: error.response.status });\n return error.response.status === 403;\n }\n logger.debug(\"Handle modern confirmation error based on header\", { hasConfirmationHeader });\n return hasConfirmationHeader;\n}\n/*!\n * SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: MIT\n */\nconst gtBuilder = getGettextBuilder().detectLanguage();\n[{ \"locale\": \"ar\", \"translations\": [{ \"msgid\": \"Checking password …\", \"msgstr\": [\"يتم التحقق من كلمة المرور...\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"تأكيد\"] }, { \"msgid\": \"Confirm your password\", \"msgstr\": [\"تأكيد كلمة المرور\"] }, { \"msgid\": \"Password\", \"msgstr\": [\"كلمة المرور\"] }, { \"msgid\": \"Please enter your password\", \"msgstr\": [\"يرجى إدخال كلمة المرور الخاصة بك\"] }, { \"msgid\": \"This action needs authentication\", \"msgstr\": [\"هذا الإجراء يتطلب التحقق من الهوية\"] }, { \"msgid\": \"Wrong password\", \"msgstr\": [\"كلمة المرور غير صحيحة\"] }] }, { \"locale\": \"ast\", \"translations\": [{ \"msgid\": \"Checking password …\", \"msgstr\": [\"Comprobando la contraseña…\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"Confirmación\"] }, { \"msgid\": \"Confirm your password\", \"msgstr\": [\"Confirma la contraseña\"] }, { \"msgid\": \"Password\", \"msgstr\": [\"Contraseña\"] }, { \"msgid\": \"Please enter your password\", \"msgstr\": [\"Introduz la contraseña\"] }, { \"msgid\": \"This action needs authentication\", \"msgstr\": [\"Esta aición precisa l'autenticación\"] }, { \"msgid\": \"Wrong password\", \"msgstr\": [\"La contraseña ye incorreuta\"] }] }, { \"locale\": \"az\", \"translations\": [{ \"msgid\": \"Confirm\", \"msgstr\": [\"Təsdiq edin\"] }, { \"msgid\": \"Confirm your password\", \"msgstr\": [\"Parolunuzu təsdiq edin\"] }, { \"msgid\": \"Password\", \"msgstr\": [\"Parol\"] }, { \"msgid\": \"Password confirmation dialog already mounted\", \"msgstr\": [\"Parolun təsdiqi dialoqu artıq quraşdırılıb\"] }, { \"msgid\": \"This action needs authentication\", \"msgstr\": [\"Bu əməliyyat autentifikasiya tələb edir\"] }, { \"msgid\": \"Wrong password\", \"msgstr\": [\"Səhv parol\"] }] }, { \"locale\": \"be\", \"translations\": [{ \"msgid\": \"Checking password …\", \"msgstr\": [\"Праверка пароля…\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"Пацвердзіць\"] }, { \"msgid\": \"Confirm your password\", \"msgstr\": [\"Пацвердзіць пароль\"] }, { \"msgid\": \"Password\", \"msgstr\": [\"Пароль\"] }, { \"msgid\": \"Please enter your password\", \"msgstr\": [\"Калі ласка, увядзіце ваш пароль\"] }, { \"msgid\": \"This action needs authentication\", \"msgstr\": [\"Гэта дзеянне патрабуе аўтэнтыфікацыі\"] }, { \"msgid\": \"Wrong password\", \"msgstr\": [\"Памылковы пароль\"] }] }, { \"locale\": \"ca\", \"translations\": [{ \"msgid\": \"Checking password …\", \"msgstr\": [\"S'està comprovant la contrasenya …\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"Confirma\"] }, { \"msgid\": \"Confirm your password\", \"msgstr\": [\"Confirmeu la vostra contrasenya\"] }, { \"msgid\": \"Password\", \"msgstr\": [\"Contrasenya\"] }, { \"msgid\": \"Please enter your password\", \"msgstr\": [\"Introduïu la vostra contrasenya\"] }, { \"msgid\": \"This action needs authentication\", \"msgstr\": [\"Aquesta acció necessita autenticació\"] }, { \"msgid\": \"Wrong password\", \"msgstr\": [\"Contrasenya incorrecta\"] }] }, { \"locale\": \"cs_CZ\", \"translations\": [{ \"msgid\": \"Authentication required\", \"msgstr\": [\"Vyžadováno ověření se\"] }, { \"msgid\": \"Checking password …\", \"msgstr\": [\"Ověřování hesla…\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"Potvrdit\"] }, { \"msgid\": \"Password\", \"msgstr\": [\"Heslo\"] }, { \"msgid\": \"Please enter your password\", \"msgstr\": [\"Zadejte heslo\"] }, { \"msgid\": \"This action needs authentication, please confirm it by entering your password.\", \"msgstr\": [\"Tato akce vyžaduje ověření se – potvrďte ji zadáním svého hesla.\"] }, { \"msgid\": \"Wrong password\", \"msgstr\": [\"Nesprávné heslo\"] }] }, { \"locale\": \"da\", \"translations\": [{ \"msgid\": \"Authentication required\", \"msgstr\": [\"Bekræft din identitet\"] }, { \"msgid\": \"Checking password …\", \"msgstr\": [\"Kontrollerer adgangskode …\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"Bekræft\"] }, { \"msgid\": \"Password\", \"msgstr\": [\"Adgangskode\"] }, { \"msgid\": \"Please enter your password\", \"msgstr\": [\"Indtast venligst dit kodeord\"] }, { \"msgid\": \"This action needs authentication, please confirm it by entering your password.\", \"msgstr\": [\"Denne handling kræver godkendelse. Indtast din adgangskode for at bekræfte.\"] }, { \"msgid\": \"Wrong password\", \"msgstr\": [\"forkert Adgangskode\"] }] }, { \"locale\": \"de\", \"translations\": [{ \"msgid\": \"Authentication required\", \"msgstr\": [\"Authentifizierung erforderlich\"] }, { \"msgid\": \"Checking password …\", \"msgstr\": [\"Passwort prüfen  …\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"Bestätigen\"] }, { \"msgid\": \"Password\", \"msgstr\": [\"Passwort\"] }, { \"msgid\": \"Please enter your password\", \"msgstr\": [\"Bitte gib dein Passwort ein\"] }, { \"msgid\": \"This action needs authentication, please confirm it by entering your password.\", \"msgstr\": [\"Für diese Aktion ist eine Authentifizierung erforderlich. Bitte bestätige diese durch Eingabe deines Passworts.\"] }, { \"msgid\": \"Wrong password\", \"msgstr\": [\"Falsches Passwort\"] }] }, { \"locale\": \"de_DE\", \"translations\": [{ \"msgid\": \"Authentication required\", \"msgstr\": [\"Authentifizierung erforderlich\"] }, { \"msgid\": \"Checking password …\", \"msgstr\": [\"Passwort prüfen …\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"Bestätigen\"] }, { \"msgid\": \"Password\", \"msgstr\": [\"Passwort\"] }, { \"msgid\": \"Please enter your password\", \"msgstr\": [\"Bitte geben Sie Ihr Passwort ein\"] }, { \"msgid\": \"This action needs authentication, please confirm it by entering your password.\", \"msgstr\": [\"Für diese Aktion ist eine Authentifizierung erforderlich. Bitte bestätigen Sie diese durch Eingabe Ihres Passworts.\"] }, { \"msgid\": \"Wrong password\", \"msgstr\": [\"Falsches Passwort\"] }] }, { \"locale\": \"el\", \"translations\": [{ \"msgid\": \"Authentication required\", \"msgstr\": [\"Απαιτείται πιστοποίηση\"] }, { \"msgid\": \"Checking password …\", \"msgstr\": [\"Έλεγχος κωδικού πρόσβασης …\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"Επιβεβαίωση\"] }, { \"msgid\": \"Password\", \"msgstr\": [\"Συνθηματικό\"] }, { \"msgid\": \"Please enter your password\", \"msgstr\": [\"Παρακαλώ εισάγετε το συνθηματικό σας\"] }, { \"msgid\": \"This action needs authentication, please confirm it by entering your password.\", \"msgstr\": [\"Αυτή η ενέργεια απαιτεί πιστοποίηση. Επιβεβαιώστε την εισάγοντας τον κωδικό πρόσβασής σας.\"] }, { \"msgid\": \"Wrong password\", \"msgstr\": [\"Λάθος συνθηματικό\"] }] }, { \"locale\": \"en_GB\", \"translations\": [{ \"msgid\": \"Authentication required\", \"msgstr\": [\"Authentication required\"] }, { \"msgid\": \"Checking password …\", \"msgstr\": [\"Checking password …\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"Confirm\"] }, { \"msgid\": \"Password\", \"msgstr\": [\"Password\"] }, { \"msgid\": \"Please enter your password\", \"msgstr\": [\"Please enter your password\"] }, { \"msgid\": \"This action needs authentication, please confirm it by entering your password.\", \"msgstr\": [\"This action needs authentication, please confirm it by entering your password.\"] }, { \"msgid\": \"Wrong password\", \"msgstr\": [\"Wrong password\"] }] }, { \"locale\": \"es\", \"translations\": [{ \"msgid\": \"Authentication required\", \"msgstr\": [\"Se requiere autenticación\"] }, { \"msgid\": \"Checking password …\", \"msgstr\": [\"Verificando contraseña …\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"Confirmar\"] }, { \"msgid\": \"Password\", \"msgstr\": [\"Contraseña\"] }, { \"msgid\": \"Please enter your password\", \"msgstr\": [\"Por favor, Introduzca su contraseña\"] }, { \"msgid\": \"This action needs authentication, please confirm it by entering your password.\", \"msgstr\": [\"Esta acción requiere autenticación, por favor, confírmela ingresado su contraseña.\"] }, { \"msgid\": \"Wrong password\", \"msgstr\": [\"Contraseña errónea\"] }] }, { \"locale\": \"es_AR\", \"translations\": [{ \"msgid\": \"Checking password …\", \"msgstr\": [\"Verificando contraseña …\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"Confirmar\"] }, { \"msgid\": \"Confirm your password\", \"msgstr\": [\"Confirme su contraseña\"] }, { \"msgid\": \"Password\", \"msgstr\": [\"Contraseña\"] }, { \"msgid\": \"Please enter your password\", \"msgstr\": [\"Por favor, introduzca su contraseña\"] }, { \"msgid\": \"This action needs authentication\", \"msgstr\": [\"Esta acción necesita autenticación\"] }, { \"msgid\": \"Wrong password\", \"msgstr\": [\"Contraseña incorrecta\"] }] }, { \"locale\": \"es_CO\", \"translations\": [{ \"msgid\": \"Authentication required\", \"msgstr\": [\"Autenticación requerida\"] }, { \"msgid\": \"Checking password …\", \"msgstr\": [\"Verificando contraseña …\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"Confirmar\"] }, { \"msgid\": \"Password\", \"msgstr\": [\"Contraseña\"] }, { \"msgid\": \"Please enter your password\", \"msgstr\": [\"Por favor introduzca su contraseña\"] }, { \"msgid\": \"This action needs authentication, please confirm it by entering your password.\", \"msgstr\": [\"Esta acción necesita autentificación, por favor confírmela introduciendo su contraseña.\"] }, { \"msgid\": \"Wrong password\", \"msgstr\": [\"Contraseña incorrecta\"] }] }, { \"locale\": \"es_MX\", \"translations\": [{ \"msgid\": \"Checking password …\", \"msgstr\": [\"Verificando contraseña …\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"Confirmar\"] }, { \"msgid\": \"Confirm your password\", \"msgstr\": [\"Confirme su contraseña\"] }, { \"msgid\": \"Password\", \"msgstr\": [\"Contraseña\"] }, { \"msgid\": \"Please enter your password\", \"msgstr\": [\"Por favor introduzca su contraseña\"] }, { \"msgid\": \"This action needs authentication\", \"msgstr\": [\"Esta acción necesita autenticación\"] }, { \"msgid\": \"Wrong password\", \"msgstr\": [\"Contraseña incorrecta\"] }] }, { \"locale\": \"et_EE\", \"translations\": [{ \"msgid\": \"Authentication required\", \"msgstr\": [\"Autentimine on vajalik\"] }, { \"msgid\": \"Checking password …\", \"msgstr\": [\"Kontrollin salasõna…\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"Kinnita\"] }, { \"msgid\": \"Password\", \"msgstr\": [\"Salasõna\"] }, { \"msgid\": \"Please enter your password\", \"msgstr\": [\"Palun sisesta oma salasõna\"] }, { \"msgid\": \"This action needs authentication, please confirm it by entering your password.\", \"msgstr\": [\"See tegevus eeldab autentimist, palun tee seda sisestades oma salasõna.\"] }, { \"msgid\": \"Wrong password\", \"msgstr\": [\"Vale salasõna\"] }] }, { \"locale\": \"fa\", \"translations\": [{ \"msgid\": \"Authentication required\", \"msgstr\": [\"احراز هویت مورد نیاز است\"] }, { \"msgid\": \"Checking password …\", \"msgstr\": [\"در حال بررسی رمز عبور...\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"تأیید\"] }, { \"msgid\": \"Password\", \"msgstr\": [\"رمز عبور\"] }, { \"msgid\": \"Please enter your password\", \"msgstr\": [\"لطفاً رمز عبور خود را وارد کنید\"] }, { \"msgid\": \"This action needs authentication, please confirm it by entering your password.\", \"msgstr\": [\"این عمل نیاز به احراز هویت دارد، لطفاً با وارد کردن رمز عبور خود آن را تأیید کنید.\"] }, { \"msgid\": \"Wrong password\", \"msgstr\": [\"رمز عبور اشتباه است\"] }] }, { \"locale\": \"fi_FI\", \"translations\": [{ \"msgid\": \"Authentication required\", \"msgstr\": [\"Tunnistautuminen vaaditaan\"] }, { \"msgid\": \"Checking password …\", \"msgstr\": [\"Tarkistetaan salasanaa …\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"Vahvista\"] }, { \"msgid\": \"Password\", \"msgstr\": [\"Salasana\"] }, { \"msgid\": \"Please enter your password\", \"msgstr\": [\"Kirjoita salasanasi\"] }, { \"msgid\": \"This action needs authentication, please confirm it by entering your password.\", \"msgstr\": [\"Tämä toimenpide vaatii tunnistautumisen. Vahvista kirjoittamalla salasanasi.\"] }, { \"msgid\": \"Wrong password\", \"msgstr\": [\"Väärä salasana\"] }] }, { \"locale\": \"fr\", \"translations\": [{ \"msgid\": \"Authentication required\", \"msgstr\": [\"Authentification requise\"] }, { \"msgid\": \"Checking password …\", \"msgstr\": [\"Vérification du mot de passe ...\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"Confirmer\"] }, { \"msgid\": \"Password\", \"msgstr\": [\"Mot de passe\"] }, { \"msgid\": \"Please enter your password\", \"msgstr\": [\"Veuillez saisir votre mot de passe\"] }, { \"msgid\": \"This action needs authentication, please confirm it by entering your password.\", \"msgstr\": [\"Cette action nécessite une authentification, veuillez confirmer en saisissant votre mot de passe.\"] }, { \"msgid\": \"Wrong password\", \"msgstr\": [\"Mot de passe incorrect\"] }] }, { \"locale\": \"ga\", \"translations\": [{ \"msgid\": \"Authentication required\", \"msgstr\": [\"Fíordheimhniú ag teastáil\"] }, { \"msgid\": \"Checking password …\", \"msgstr\": [\"Ag seiceáil an focal faire …\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"Deimhnigh\"] }, { \"msgid\": \"Password\", \"msgstr\": [\"Pasfhocal\"] }, { \"msgid\": \"Please enter your password\", \"msgstr\": [\"Cuir isteach do phasfhocal\"] }, { \"msgid\": \"This action needs authentication, please confirm it by entering your password.\", \"msgstr\": [\"Teastaíonn fíordheimhniú don ghníomh seo, deimhnigh é trí do phasfhocal a iontráil.\"] }, { \"msgid\": \"Wrong password\", \"msgstr\": [\"Pasfhocal mícheart\"] }] }, { \"locale\": \"gl\", \"translations\": [{ \"msgid\": \"Authentication required\", \"msgstr\": [\"É necesaria a autenticación\"] }, { \"msgid\": \"Checking password …\", \"msgstr\": [\"Comprobando o contrasinal…\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"Confirmar\"] }, { \"msgid\": \"Password\", \"msgstr\": [\"Contrasinal\"] }, { \"msgid\": \"Please enter your password\", \"msgstr\": [\"Introduza o seu contrasinal\"] }, { \"msgid\": \"This action needs authentication, please confirm it by entering your password.\", \"msgstr\": [\"Esta acción precisa de autenticación, confírmea introducindo o seu contrasinal.\"] }, { \"msgid\": \"Wrong password\", \"msgstr\": [\"Contrasinal incorrecto\"] }] }, { \"locale\": \"hr\", \"translations\": [{ \"msgid\": \"Authentication required\", \"msgstr\": [\"Potrebna je autentifikacija\"] }, { \"msgid\": \"Checking password …\", \"msgstr\": [\"Provjera lozinke …\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"Potvrdi\"] }, { \"msgid\": \"Password\", \"msgstr\": [\"Lozinka\"] }, { \"msgid\": \"Please enter your password\", \"msgstr\": [\"Molimo unesite vašu lozinku\"] }, { \"msgid\": \"This action needs authentication, please confirm it by entering your password.\", \"msgstr\": [\"Ova radnja zahtijeva autentifikaciju, potvrdite je unosom svoje lozinke.\"] }, { \"msgid\": \"Wrong password\", \"msgstr\": [\"Pogrešna lozinka\"] }] }, { \"locale\": \"hu_HU\", \"translations\": [{ \"msgid\": \"Authentication required\", \"msgstr\": [\"Azonosítás szükséges\"] }, { \"msgid\": \"Checking password …\", \"msgstr\": [\"Jelszó ellenőrzése ...\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"Jóváhagyás\"] }, { \"msgid\": \"Password\", \"msgstr\": [\"Jelszó\"] }, { \"msgid\": \"Please enter your password\", \"msgstr\": [\"Adja meg a jelszavát\"] }, { \"msgid\": \"This action needs authentication, please confirm it by entering your password.\", \"msgstr\": [\"Ehhez a tevékenységhez azonosítás szükséges. Kérlek hagyd jóvá a jelszavad megadásával.\"] }, { \"msgid\": \"Wrong password\", \"msgstr\": [\"Hibás jelszó\"] }] }, { \"locale\": \"id\", \"translations\": [{ \"msgid\": \"Authentication required\", \"msgstr\": [\"Autentikasi diperlukan\"] }, { \"msgid\": \"Checking password …\", \"msgstr\": [\"Memeriksa kata sandi ...\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"Konfirmasi\"] }, { \"msgid\": \"Password\", \"msgstr\": [\"Kata sandi\"] }, { \"msgid\": \"Please enter your password\", \"msgstr\": [\"Silahkan masukan kata sandi Anda\"] }, { \"msgid\": \"This action needs authentication, please confirm it by entering your password.\", \"msgstr\": [\"Aksi ini memerlukan autentikasi, silahkan konfirmasi dengan memasukan kata sandi Anda.\"] }, { \"msgid\": \"Wrong password\", \"msgstr\": [\"Kata sandi salah\"] }] }, { \"locale\": \"is\", \"translations\": [{ \"msgid\": \"Checking password …\", \"msgstr\": [\"Athuga lykilorð …\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"Staðfesta\"] }, { \"msgid\": \"Confirm your password\", \"msgstr\": [\"Staðfestu lykilorðið þitt\"] }, { \"msgid\": \"Password\", \"msgstr\": [\"Lykilorð\"] }, { \"msgid\": \"Please enter your password\", \"msgstr\": [\"Settu inn lykilorðið þitt\"] }, { \"msgid\": \"This action needs authentication\", \"msgstr\": [\"Þessi aðgerð krefst auðkenningar\"] }, { \"msgid\": \"Wrong password\", \"msgstr\": [\"Rangt lykilorð\"] }] }, { \"locale\": \"it\", \"translations\": [{ \"msgid\": \"Authentication required\", \"msgstr\": [\"Autenticazione richiesta\"] }, { \"msgid\": \"Checking password …\", \"msgstr\": [\"Controllo della password…\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"Conferma\"] }, { \"msgid\": \"Password\", \"msgstr\": [\"Password\"] }, { \"msgid\": \"Please enter your password\", \"msgstr\": [\"Digita la tua password\"] }, { \"msgid\": \"This action needs authentication, please confirm it by entering your password.\", \"msgstr\": [\"Questa azione richiede l'autenticazione, confermala digitando la tua password.\"] }, { \"msgid\": \"Wrong password\", \"msgstr\": [\"Password errata\"] }] }, { \"locale\": \"ja_JP\", \"translations\": [{ \"msgid\": \"Authentication required\", \"msgstr\": [\"認証が必要です\"] }, { \"msgid\": \"Checking password …\", \"msgstr\": [\"パスワードの確認 …\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"確認\"] }, { \"msgid\": \"Password\", \"msgstr\": [\"パスワード\"] }, { \"msgid\": \"Please enter your password\", \"msgstr\": [\"パスワードを入力してください\"] }, { \"msgid\": \"This action needs authentication, please confirm it by entering your password.\", \"msgstr\": [\"この操作には認証が必要です。パスワードを入力してください。\"] }, { \"msgid\": \"Wrong password\", \"msgstr\": [\"間違ったパスワード\"] }] }, { \"locale\": \"kab\", \"translations\": [{ \"msgid\": \"Authentication required\", \"msgstr\": [\"Asesteb yettwasra\"] }, { \"msgid\": \"Checking password …\", \"msgstr\": [\"Asenqed n wawal n uɛeddi …\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"Sentem\"] }, { \"msgid\": \"Password\", \"msgstr\": [\"Awal n uɛeddi\"] }, { \"msgid\": \"Please enter your password\", \"msgstr\": [\"Txil, sekcem-d awal-ik·im n uɛeddi\"] }, { \"msgid\": \"This action needs authentication, please confirm it by entering your password.\", \"msgstr\": [\"Tigawt-a tesra asesteb, ttxil-k·m, wekked-itt-id s usekcem n wawal-inek·inem n uɛeddi.\"] }, { \"msgid\": \"Wrong password\", \"msgstr\": [\"Awal n uɛeddi d arameɣtu\"] }] }, { \"locale\": \"ko\", \"translations\": [{ \"msgid\": \"Authentication required\", \"msgstr\": [\"인증 필요 \"] }, { \"msgid\": \"Checking password …\", \"msgstr\": [\"비밀번호 확인 중 ...\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"확인\"] }, { \"msgid\": \"Password\", \"msgstr\": [\"비밀번호\"] }, { \"msgid\": \"Please enter your password\", \"msgstr\": [\"비밀번호를 입력하세요\"] }, { \"msgid\": \"This action needs authentication, please confirm it by entering your password.\", \"msgstr\": [\"이 작업은 인증이 필요합니다. 비밀번호를 입력하여 확인하십시오. \"] }, { \"msgid\": \"Wrong password\", \"msgstr\": [\"잘못된 비밀번호\"] }] }, { \"locale\": \"lv\", \"translations\": [{ \"msgid\": \"Authentication required\", \"msgstr\": [\"Nepieciešama autentificēšanās\"] }, { \"msgid\": \"Checking password …\", \"msgstr\": [\"Pārbauda paroli...\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"Apstiprināt\"] }, { \"msgid\": \"Password\", \"msgstr\": [\"Parole\"] }, { \"msgid\": \"Please enter your password\", \"msgstr\": [\"Lūgums ievadīt savu paroli\"] }, { \"msgid\": \"This action needs authentication, please confirm it by entering your password.\", \"msgstr\": [\"Šai darbībai ir nepieciešama autentificēšanās. Lūgums to apstiprināt ar savas paroles ievadīšanu.\"] }, { \"msgid\": \"Wrong password\", \"msgstr\": [\"Nepareiza parole\"] }] }, { \"locale\": \"mk\", \"translations\": [{ \"msgid\": \"Authentication required\", \"msgstr\": [\"Потребна е автентификација\"] }, { \"msgid\": \"Checking password …\", \"msgstr\": [\"Проверка на лозинка …\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"Потврди\"] }, { \"msgid\": \"Password\", \"msgstr\": [\"Лозинка\"] }, { \"msgid\": \"Please enter your password\", \"msgstr\": [\"Внесете ја вашата лозинка\"] }, { \"msgid\": \"This action needs authentication, please confirm it by entering your password.\", \"msgstr\": [\"Оваа акција бара автентикација, потврдете ја со внесување на вашата лозинка.\"] }, { \"msgid\": \"Wrong password\", \"msgstr\": [\"Погрешна лозинка\"] }] }, { \"locale\": \"ms_MY\", \"translations\": [{ \"msgid\": \"Authentication required\", \"msgstr\": [\"Pengesahan diperlukan\"] }, { \"msgid\": \"Checking password …\", \"msgstr\": [\"Menyemak kata laluan …\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"Mengesahkan\"] }, { \"msgid\": \"Password\", \"msgstr\": [\"Kata laluan\"] }, { \"msgid\": \"Please enter your password\", \"msgstr\": [\"Sila masukkan kata laluan anda\"] }, { \"msgid\": \"This action needs authentication, please confirm it by entering your password.\", \"msgstr\": [\"Tindakan ini memerlukan pengesahan, sila sahkan dengan memasukkan kata laluan anda.\"] }, { \"msgid\": \"Wrong password\", \"msgstr\": [\"Kata laluan salah\"] }] }, { \"locale\": \"nb_NO\", \"translations\": [{ \"msgid\": \"Checking password …\", \"msgstr\": [\"Sjekker passord …\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"Bekreft\"] }, { \"msgid\": \"Confirm your password\", \"msgstr\": [\"Bekreft passordet ditt\"] }, { \"msgid\": \"Password\", \"msgstr\": [\"Passord\"] }, { \"msgid\": \"Please enter your password\", \"msgstr\": [\"Vennligst skriv inn passordet ditt\"] }, { \"msgid\": \"This action needs authentication\", \"msgstr\": [\"Denne handlingen krever autentisering\"] }, { \"msgid\": \"Wrong password\", \"msgstr\": [\"Feil passord\"] }] }, { \"locale\": \"nl\", \"translations\": [{ \"msgid\": \"Authentication required\", \"msgstr\": [\"Authenticatie vereist\"] }, { \"msgid\": \"Checking password …\", \"msgstr\": [\"Wachtwoord controleren…\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"Bevestigen\"] }, { \"msgid\": \"Password\", \"msgstr\": [\"Wachtwoord\"] }, { \"msgid\": \"Please enter your password\", \"msgstr\": [\"Voer je wachtwoord in\"] }, { \"msgid\": \"This action needs authentication, please confirm it by entering your password.\", \"msgstr\": [\"Deze actie vereist authenticatie, voer je wachtwoord in.\"] }, { \"msgid\": \"Wrong password\", \"msgstr\": [\"Incorrect wachtwoord\"] }] }, { \"locale\": \"pl\", \"translations\": [{ \"msgid\": \"Checking password …\", \"msgstr\": [\"Sprawdzanie hasła…\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"Potwierdź\"] }, { \"msgid\": \"Confirm your password\", \"msgstr\": [\"Potwierdź swoje hasło\"] }, { \"msgid\": \"Password\", \"msgstr\": [\"Hasło\"] }, { \"msgid\": \"Please enter your password\", \"msgstr\": [\"Wprowadź swoje hasło\"] }, { \"msgid\": \"This action needs authentication\", \"msgstr\": [\"Wykonanie tej czynności wymaga autoryzacji\"] }, { \"msgid\": \"Wrong password\", \"msgstr\": [\"Nieprawidłowe hasło\"] }] }, { \"locale\": \"pt_BR\", \"translations\": [{ \"msgid\": \"Authentication required\", \"msgstr\": [\"Autenticação necessária\"] }, { \"msgid\": \"Checking password …\", \"msgstr\": [\"Verificando a senha …\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"Confirmar\"] }, { \"msgid\": \"Password\", \"msgstr\": [\"Senha\"] }, { \"msgid\": \"Please enter your password\", \"msgstr\": [\"Por favor, insira sua senha\"] }, { \"msgid\": \"This action needs authentication, please confirm it by entering your password.\", \"msgstr\": [\"Esta ação precisa de autenticação. Por favor, confirme-a digitando sua senha.\"] }, { \"msgid\": \"Wrong password\", \"msgstr\": [\"Senha incorreta\"] }] }, { \"locale\": \"pt_PT\", \"translations\": [{ \"msgid\": \"Authentication required\", \"msgstr\": [\"Autenticação necessária\"] }, { \"msgid\": \"Checking password …\", \"msgstr\": [\"A verificar palavra-passe…\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"Confirmar\"] }, { \"msgid\": \"Password\", \"msgstr\": [\"Palavra-passe\"] }, { \"msgid\": \"Please enter your password\", \"msgstr\": [\"Introduza a sua palavra-passe, por favor\"] }, { \"msgid\": \"This action needs authentication, please confirm it by entering your password.\", \"msgstr\": [\"Esta ação requer autenticação; confirme-a introduzindo a sua palavra-passe.\"] }, { \"msgid\": \"Wrong password\", \"msgstr\": [\"Palavra-passe incorreta\"] }] }, { \"locale\": \"ro\", \"translations\": [{ \"msgid\": \"Checking password …\", \"msgstr\": [\"Se verifică parola ...\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"Confirmare\"] }, { \"msgid\": \"Confirm your password\", \"msgstr\": [\"Confirmare parolă\"] }, { \"msgid\": \"Password\", \"msgstr\": [\"Parolă\"] }, { \"msgid\": \"Please enter your password\", \"msgstr\": [\"Vă rugăm să introduceți parola\"] }, { \"msgid\": \"This action needs authentication\", \"msgstr\": [\"Această acțiune necesită autentificare\"] }, { \"msgid\": \"Wrong password\", \"msgstr\": [\"Parolă incorectă\"] }] }, { \"locale\": \"ru\", \"translations\": [{ \"msgid\": \"Authentication required\", \"msgstr\": [\"Требуется аутентификация\"] }, { \"msgid\": \"Checking password …\", \"msgstr\": [\"Проверка пароля …\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"Подтвердить\"] }, { \"msgid\": \"Password\", \"msgstr\": [\"Пароль\"] }, { \"msgid\": \"Please enter your password\", \"msgstr\": [\"Пожалуйста, введите свой пароль\"] }, { \"msgid\": \"This action needs authentication, please confirm it by entering your password.\", \"msgstr\": [\"Это действие требует аутентификации, пожалуйста подтвердите его вводом вашего пароля.\"] }, { \"msgid\": \"Wrong password\", \"msgstr\": [\"Неправильный пароль\"] }] }, { \"locale\": \"sk_SK\", \"translations\": [{ \"msgid\": \"Authentication required\", \"msgstr\": [\"Vyžaduje sa autentifikácia\"] }, { \"msgid\": \"Checking password …\", \"msgstr\": [\"Kontrola hesla…\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"Potvrdiť\"] }, { \"msgid\": \"Password\", \"msgstr\": [\"Heslo\"] }, { \"msgid\": \"Please enter your password\", \"msgstr\": [\"Zadajte prosím svoje heslo\"] }, { \"msgid\": \"This action needs authentication, please confirm it by entering your password.\", \"msgstr\": [\"Táto akcia vyžaduje overenie, prosím potvrďte ju zadaním vášho hesla.\"] }, { \"msgid\": \"Wrong password\", \"msgstr\": [\"Nesprávne heslo\"] }] }, { \"locale\": \"sl\", \"translations\": [{ \"msgid\": \"Authentication required\", \"msgstr\": [\"Zahtevana avtentikacija\"] }, { \"msgid\": \"Checking password …\", \"msgstr\": [\"Poteka preverjanje gesla ...\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"Potrdi\"] }, { \"msgid\": \"Password\", \"msgstr\": [\"Geslo\"] }, { \"msgid\": \"Please enter your password\", \"msgstr\": [\"Vpisati je treba geslo\"] }, { \"msgid\": \"This action needs authentication, please confirm it by entering your password.\", \"msgstr\": [\"To dejanje zahteva preverjanje pristnosti, potrdite ga z vnosom gesla.\"] }, { \"msgid\": \"Wrong password\", \"msgstr\": [\"Napačno geslo\"] }] }, { \"locale\": \"sr\", \"translations\": [{ \"msgid\": \"Authentication required\", \"msgstr\": [\"Потребна је потврда идентитета\"] }, { \"msgid\": \"Checking password …\", \"msgstr\": [\"Проверава се лозинка…\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"Потврда\"] }, { \"msgid\": \"Password\", \"msgstr\": [\"Лозинка\"] }, { \"msgid\": \"Please enter your password\", \"msgstr\": [\"Молимо вас да унесете своју лозинку\"] }, { \"msgid\": \"This action needs authentication, please confirm it by entering your password.\", \"msgstr\": [\"За ову акцију је потребна провера идентитета, молимо вас да га потврдите уносом своје лозинке.\"] }, { \"msgid\": \"Wrong password\", \"msgstr\": [\"Погрешна лозинка\"] }] }, { \"locale\": \"sv\", \"translations\": [{ \"msgid\": \"Authentication required\", \"msgstr\": [\"Autentisering krävs\"] }, { \"msgid\": \"Checking password …\", \"msgstr\": [\"Kontrollerar lösenord …\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"Bekräfta\"] }, { \"msgid\": \"Password\", \"msgstr\": [\"Lösenord\"] }, { \"msgid\": \"Please enter your password\", \"msgstr\": [\"Ange ditt lösenord\"] }, { \"msgid\": \"This action needs authentication, please confirm it by entering your password.\", \"msgstr\": [\"Den här åtgärden kräver autentisering, bekräfta genom att ange ditt lösenord.\"] }, { \"msgid\": \"Wrong password\", \"msgstr\": [\"Fel lösenord\"] }] }, { \"locale\": \"tr\", \"translations\": [{ \"msgid\": \"Authentication required\", \"msgstr\": [\"Kimlik doğrulaması gerekli\"] }, { \"msgid\": \"Checking password …\", \"msgstr\": [\"Parola denetleniyor…\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"Parola onayı\"] }, { \"msgid\": \"Password\", \"msgstr\": [\"Parola\"] }, { \"msgid\": \"Please enter your password\", \"msgstr\": [\"Lütfen parolanızı yazın\"] }, { \"msgid\": \"This action needs authentication, please confirm it by entering your password.\", \"msgstr\": [\"Bu işlemi yapmak için kimliğinizi doğrulamalısınız. Lütfen parolanızı yazın.\"] }, { \"msgid\": \"Wrong password\", \"msgstr\": [\"Parola geçersiz\"] }] }, { \"locale\": \"uk\", \"translations\": [{ \"msgid\": \"Authentication required\", \"msgstr\": [\"Потрібна авторизація\"] }, { \"msgid\": \"Checking password …\", \"msgstr\": [\"Перевірка паролю ...\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"Підтвердити\"] }, { \"msgid\": \"Password\", \"msgstr\": [\"Пароль\"] }, { \"msgid\": \"Please enter your password\", \"msgstr\": [\"Зазначте ваш пароль\"] }, { \"msgid\": \"This action needs authentication, please confirm it by entering your password.\", \"msgstr\": [\"Ця дія вимагає авторизацію, зазначте ваш пароль.\"] }, { \"msgid\": \"Wrong password\", \"msgstr\": [\"Помилковий пароль\"] }] }, { \"locale\": \"ur_PK\", \"translations\": [{ \"msgid\": \"Authentication required\", \"msgstr\": [\"تصدیق درکار ہے\"] }, { \"msgid\": \"Checking password …\", \"msgstr\": [\"پاس ورڈ چیک ہو رہا ہے …\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"تصدیق کریں\"] }, { \"msgid\": \"Password\", \"msgstr\": [\"پاس ورڈ\"] }, { \"msgid\": \"Please enter your password\", \"msgstr\": [\"براہ کرم اپنا پاس ورڈ درج کریں\"] }, { \"msgid\": \"This action needs authentication, please confirm it by entering your password.\", \"msgstr\": [\"اس عمل کو تصدیق کی ضرورت ہے، براہ کرم پاس ورڈ درج کرکے اس کی تصدیق کریں۔\"] }, { \"msgid\": \"Wrong password\", \"msgstr\": [\"نادرست پاس ورڈ\"] }] }, { \"locale\": \"uz\", \"translations\": [{ \"msgid\": \"Authentication required\", \"msgstr\": [\"Autentifikatsiya talab qilinadi\"] }, { \"msgid\": \"Checking password …\", \"msgstr\": [\"Parol tekshirilmoqda…\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"Tasdiqlang\"] }, { \"msgid\": \"Password\", \"msgstr\": [\"Parol\"] }, { \"msgid\": \"Please enter your password\", \"msgstr\": [\"Iltimos, parolingizni kiriting\"] }, { \"msgid\": \"This action needs authentication, please confirm it by entering your password.\", \"msgstr\": [\"Ushbu amaliyot autentifikatsiya talab etadi, parolingizni kiritish orqali buni tasdiqlang.\"] }, { \"msgid\": \"Wrong password\", \"msgstr\": [\"Parol noto'g'ri \"] }] }, { \"locale\": \"vi\", \"translations\": [{ \"msgid\": \"Authentication required\", \"msgstr\": [\"Yêu cầu xác thực\"] }, { \"msgid\": \"Checking password …\", \"msgstr\": [\"Đang kiểm tra mật khẩu ...\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"Chấp nhận\"] }, { \"msgid\": \"Password\", \"msgstr\": [\"Mật khẩu\"] }, { \"msgid\": \"Please enter your password\", \"msgstr\": [\"Vui lòng nhập mật khẩu của bạn\"] }, { \"msgid\": \"This action needs authentication, please confirm it by entering your password.\", \"msgstr\": [\"Thao tác này cần xác thực, vui lòng xác nhận bằng cách nhập mật khẩu của bạn.\"] }, { \"msgid\": \"Wrong password\", \"msgstr\": [\"Mật khẩu sai\"] }] }, { \"locale\": \"zh_CN\", \"translations\": [{ \"msgid\": \"Authentication required\", \"msgstr\": [\"需要身份验证\"] }, { \"msgid\": \"Checking password …\", \"msgstr\": [\"正在检查密码 …\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"确认\"] }, { \"msgid\": \"Password\", \"msgstr\": [\"密码\"] }, { \"msgid\": \"Please enter your password\", \"msgstr\": [\"请输入您的密码\"] }, { \"msgid\": \"This action needs authentication, please confirm it by entering your password.\", \"msgstr\": [\"此操作需要身份验证,请输入密码进行确认。\"] }, { \"msgid\": \"Wrong password\", \"msgstr\": [\"密码错误\"] }] }, { \"locale\": \"zh_HK\", \"translations\": [{ \"msgid\": \"Authentication required\", \"msgstr\": [\"需要驗證\"] }, { \"msgid\": \"Checking password …\", \"msgstr\": [\"正在檢查密碼 …\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"確認\"] }, { \"msgid\": \"Password\", \"msgstr\": [\"密碼\"] }, { \"msgid\": \"Please enter your password\", \"msgstr\": [\"請輸入您的密碼\"] }, { \"msgid\": \"This action needs authentication, please confirm it by entering your password.\", \"msgstr\": [\"此操作需要身份驗證,請輸入您的密碼以進行確認。\"] }, { \"msgid\": \"Wrong password\", \"msgstr\": [\"密碼錯誤\"] }] }, { \"locale\": \"zh_TW\", \"translations\": [{ \"msgid\": \"Checking password …\", \"msgstr\": [\"正在檢查密碼……\"] }, { \"msgid\": \"Confirm\", \"msgstr\": [\"確認\"] }, { \"msgid\": \"Confirm your password\", \"msgstr\": [\"確認您的密碼\"] }, { \"msgid\": \"Password\", \"msgstr\": [\"密碼\"] }, { \"msgid\": \"Please enter your password\", \"msgstr\": [\"請輸入您的密碼\"] }, { \"msgid\": \"This action needs authentication\", \"msgstr\": [\"此動作需要驗證\"] }, { \"msgid\": \"Wrong password\", \"msgstr\": [\"密碼錯誤\"] }] }].map(({ locale, translations }) => gtBuilder.addTranslation(locale, {\n headers: {},\n translations: {\n \"\": Object.fromEntries(translations.map((t2) => [t2.msgid, t2]))\n }\n}));\nconst gt = gtBuilder.build();\ngt.ngettext.bind(gt);\nconst t = gt.gettext.bind(gt);\nconst _sfc_main = /* @__PURE__ */ defineComponent({\n __name: \"PasswordDialog\",\n props: {\n validate: { type: Function }\n },\n emits: [\"close\"],\n setup(__props, { emit: __emit }) {\n const props = __props;\n const emit = __emit;\n onMounted(focusPasswordField);\n const passwordInput = useTemplateRef(\"field\");\n const password = ref(\"\");\n const loading = ref(false);\n const hasError = ref(false);\n const buttons = [{\n label: t(\"Confirm\"),\n type: \"submit\",\n variant: \"primary\",\n callback\n }];\n const helperText = computed(() => {\n if (hasError.value) {\n return t(\"Wrong password\");\n }\n if (loading.value) {\n return t(\"Checking password …\");\n }\n if (password.value === \"\") {\n return t(\"Please enter your password\");\n }\n return \"\";\n });\n async function callback() {\n hasError.value = false;\n loading.value = true;\n if (password.value === \"\") {\n hasError.value = true;\n return false;\n }\n try {\n await props.validate(password.value);\n emit(\"close\", true);\n } catch (error) {\n if (isConfirmationError(error)) {\n hasError.value = true;\n logger.error(\"Exception during password confirmation\", { error });\n selectPasswordField();\n return false;\n }\n hasError.value = true;\n emit(\"close\", false);\n } finally {\n loading.value = false;\n }\n return true;\n }\n function focusPasswordField() {\n nextTick(() => {\n passwordInput.value.focus();\n });\n }\n function selectPasswordField() {\n nextTick(() => {\n passwordInput.value.select();\n });\n }\n return (_ctx, _cache) => {\n return openBlock(), createBlock(unref(NcDialog), {\n isForm: \"\",\n buttons,\n name: unref(t)(\"Authentication required\"),\n contentClasses: _ctx.$style.passwordDialog,\n \"onUpdate:open\": _cache[1] || (_cache[1] = ($event) => emit(\"close\", false))\n }, {\n default: withCtx(() => [\n createElementVNode(\"p\", null, toDisplayString(unref(t)(\"This action needs authentication, please confirm it by entering your password.\")), 1),\n createVNode(unref(NcPasswordField), {\n ref: \"field\",\n modelValue: password.value,\n \"onUpdate:modelValue\": _cache[0] || (_cache[0] = ($event) => password.value = $event),\n label: unref(t)(\"Password\"),\n helperText: helperText.value,\n checkPasswordStrength: false,\n error: hasError.value !== false,\n required: \"\"\n }, null, 8, [\"modelValue\", \"label\", \"helperText\", \"error\"])\n ]),\n _: 1\n }, 8, [\"name\", \"contentClasses\"]);\n };\n }\n});\nconst passwordDialog = \"_passwordDialog_joix2_2\";\nconst style0 = {\n passwordDialog\n};\nconst _export_sfc = (sfc, props) => {\n const target = sfc.__vccOpts || sfc;\n for (const [key, val] of props) {\n target[key] = val;\n }\n return target;\n};\nconst cssModules = {\n \"$style\": style0\n};\nconst PasswordDialogVue = /* @__PURE__ */ _export_sfc(_sfc_main, [[\"__cssModules\", cssModules]]);\n/*!\n * SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: MIT\n */\nlet INTERCEPTOR_INITIALIZED = false;\nasync function confirmPassword() {\n if (!isPasswordConfirmationRequired(PwdConfirmationMode.Lax)) {\n return Promise.resolve();\n }\n await promptPassword(async (password) => {\n await _confirmPassword(password);\n });\n}\nasync function _confirmPassword(password) {\n logger.debug(\"Confirming password\");\n const url = generateUrl(\"/login/confirm\");\n const { data } = await axios.post(url, { password });\n window.nc_lastLogin = data.lastLogin;\n logger.debug(\"Password confirmed\");\n}\nlet _passwordDialog;\nlet _dialogCallback;\nasync function promptPassword(validate) {\n _dialogCallback = validate;\n if (!_passwordDialog) {\n _passwordDialog = spawnDialog(PasswordDialogVue, {\n validate(password) {\n return _dialogCallback(password);\n }\n });\n }\n const result = await _passwordDialog;\n _passwordDialog = void 0;\n if (!result) {\n throw new Error(\"Dialog closed\");\n }\n}\nfunction addPasswordConfirmationInterceptors(axios2) {\n if (INTERCEPTOR_INITIALIZED) {\n return;\n }\n INTERCEPTOR_INITIALIZED = true;\n let validatePromise;\n axios2.interceptors.request.use(async (config) => {\n if (config.confirmPassword === void 0) {\n return config;\n }\n if (!isPasswordConfirmationRequired(config.confirmPassword)) {\n return config;\n }\n const { promise, resolve, reject } = Promise.withResolvers();\n promptPassword(async (password) => {\n switch (config.confirmPassword) {\n case PwdConfirmationMode.Lax:\n await _confirmPassword(password);\n resolve(config);\n break;\n case PwdConfirmationMode.Strict:\n validatePromise = Promise.withResolvers();\n config.auth = {\n username: getCurrentUser()?.uid ?? \"\",\n password\n };\n logger.debug(\"Adding auth info to the request\", { config });\n resolve(config);\n return validatePromise.promise;\n }\n }).catch(reject);\n return promise;\n });\n axios2.interceptors.response.use(\n (response) => {\n if (response.config.confirmPassword !== PwdConfirmationMode.Strict) {\n return response;\n }\n if (validatePromise === void 0) {\n logger.debug(\"Password confirmation not required\", { response });\n return response;\n }\n logger.debug(\"Password confirmation succeeded\", { response });\n window.nc_lastLogin = Date.now() / 1e3;\n validatePromise.resolve();\n return response;\n },\n (error) => {\n if (error.config?.confirmPassword !== PwdConfirmationMode.Strict) {\n throw error;\n }\n if (validatePromise === void 0) {\n logger.debug(\"Password confirmation not required\", { error });\n throw error;\n }\n logger.debug(\"Password confirmation failed\", { error });\n validatePromise.reject(error);\n if (isConfirmationError(error)) {\n logger.debug(\"Triggering new request\", { error });\n return axios2.request(error.config);\n }\n throw error;\n }\n );\n}\nexport {\n PwdConfirmationMode,\n addPasswordConfirmationInterceptors,\n confirmPassword,\n isPasswordConfirmationRequired\n};\n//# sourceMappingURL=index.mjs.map\n","import { defineComponent, useModel, useTemplateRef, computed, openBlock, createBlock, unref, mergeProps, createSlots, withCtx, renderSlot, mergeModels } from \"vue\";\nimport { m as mdiArrowRight, a as mdiUndo, b as mdiClose } from \"./mdi-CpchYUUV.mjs\";\nimport { r as register, b as t51, c as t18, a as t } from \"./_l10n-wdIzZwir.mjs\";\nimport { N as NcIconSvgWrapper } from \"./NcIconSvgWrapper-g8ubWhoz.mjs\";\nimp SPDX-FileCopyrightText: 2023, 2019 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\nconst logger = getLoggerBuilder().setApp(\"@nextcloud/dialogs\").detectLogLevel().build();\nvar FilePickerType = /* @__PURE__ */ ((FilePickerType2) => {\n FilePickerType2[FilePickerType2[\"Choose\"] = 1] = \"Choose\";\n FilePickerType2[FilePickerType2[\"Move\"] = 2] = \"Move\";\n FilePickerType2[FilePickerType2[\"Copy\"] = 3] = \"Copy\";\n FilePickerType2[FilePickerType2[\"CopyMove\"] = 4] = \"CopyMove\";\n FilePickerType2[FilePickerType2[\"Custom\"] = 5] = \"Custom\";\n return FilePickerType2;\n})(FilePickerType || {});\nclass FilePickerClosed extends Error {\n}\nclass FilePicker {\n title;\n multiSelect;\n mimeTypeFilter;\n directoriesAllowed;\n noMenu;\n buttons;\n path;\n filter;\n canPick;\n container;\n disabledNavigation;\n constructor(title, multiSelect, mimeTypeFilter, directoriesAllowed, noMenu, buttons, path, filter, canPick, container, disabledNavigation = false) {\n this.title = title;\n this.multiSelect = multiSelect;\n this.mimeTypeFilter = mimeTypeFilter;\n this.directoriesAllowed = directoriesAllowed;\n this.noMenu = noMenu;\n this.path = path;\n this.filter = filter;\n this.canPick = canPick;\n this.buttons = buttons;\n this.container = container;\n this.disabledNavigation = disabledNavigation;\n }\n /**\n * Pick files using the FilePicker.\n *\n * @return Promise with array of picked files or rejected promise on close without picking\n */\n async pickNodes() {\n const { default: FilePickerVue } = await import(\"./FilePicker.mjs\");\n const nodes = await spawnDialog(FilePickerVue, {\n allowPickDirectory: this.directoriesAllowed,\n noMenu: this.noMenu,\n buttons: this.buttons,\n name: this.title,\n path: this.path,\n mimetypeFilter: this.mimeTypeFilter,\n multiselect: this.multiSelect,\n filterFn: this.filter,\n canPickFn: this.canPick,\n disabledNavigation: this.disabledNavigation\n }, {\n container: this.container\n });\n if (!Array.isArray(nodes) || nodes.length === 0) {\n throw new FilePickerClosed(\"FilePicker: No nodes selected\");\n }\n return nodes;\n }\n /**\n * Pick files using the FilePicker\n *\n * @return Promise with array of paths of picked files or rejected promise on close without picking\n */\n async pick() {\n const nodes = await this.pickNodes();\n if (this.multiSelect) {\n return nodes.map((node) => node.path);\n }\n const path = nodes[0]?.path ?? \"/\";\n return path;\n }\n}\nclass FilePickerBuilder {\n title;\n multiSelect = false;\n mimeTypeFilter = [];\n directoriesAllowed = false;\n noMenu = false;\n path;\n filter;\n canPick;\n buttons = [];\n container;\n disabledNavigation = false;\n /**\n * Construct a new FilePicker\n *\n * @param title Title of the FilePicker\n */\n constructor(title) {\n this.title = title;\n }\n /**\n * Set the container where the FilePicker will be mounted\n * By default 'body' is used\n *\n * @param container The dialog container\n */\n setContainer(container) {\n this.container = container;\n return this;\n }\n /**\n * Enable or disable picking multiple files\n *\n * @param ms True to enable picking multiple files, false otherwise\n */\n setMultiSelect(ms) {\n this.multiSelect = ms;\n return this;\n }\n /**\n * Add allowed MIME type\n *\n * @param filter MIME type to allow\n */\n addMimeTypeFilter(filter) {\n this.mimeTypeFilter.push(filter);\n return this;\n }\n /**\n * Set allowed MIME types\n *\n * @param filter Array of allowed MIME types\n */\n setMimeTypeFilter(filter) {\n this.mimeTypeFilter = filter;\n return this;\n }\n /**\n * Add a button to the FilePicker\n * Note: This overrides any previous `setButtonFactory` call\n *\n * @param button The button\n */\n addButton(button) {\n if (typeof this.buttons === \"function\") {\n logger.warn(\"FilePicker buttons were set to factory, now overwritten with button object.\");\n this.buttons = [];\n }\n this.buttons.push(button);\n return this;\n }\n /**\n * Set the button factory which is used to generate buttons from current view, path and selected nodes\n * Note: This overrides any previous `addButton` call\n *\n * @param factory The button factory\n */\n setButtonFactory(factory) {\n this.buttons = factory;\n return this;\n }\n /**\n * Set FilePicker type based on legacy file picker types\n *\n * @param type The legacy filepicker type to emulate\n * @deprecated Use `addButton` or `setButtonFactory` instead as with setType you do not know which button was pressed\n */\n setType(type) {\n this.buttons = (nodes, path) => {\n const buttons = [];\n const node = nodes[0];\n const target = node?.displayname || basename(path);\n if (type === 1) {\n let label = t(\"Choose\");\n if (nodes.length === 1) {\n label = t(\"Choose {file}\", { file: target });\n } else if (this.multiSelect) {\n label = n(\"Choose %n file\", \"Choose %n files\", nodes.length);\n }\n buttons.push({\n callback: () => {\n },\n label,\n variant: \"primary\"\n });\n }\n if (type === 4 || type === 3) {\n buttons.push({\n callback: () => {\n },\n label: target ? t(\"Copy to {target}\", { target }) : t(\"Copy\"),\n icon: IconCopy,\n variant: type === 3 ? \"primary\" : \"secondary\"\n });\n }\n if (type === 4 || type === 2) {\n buttons.push({\n callback: () => {\n },\n label: target ? t(\"Move to {target}\", { target }) : t(\"Move\"),\n icon: IconMove,\n variant: \"primary\"\n // move is always primary - also on copy-move\n });\n }\n return buttons;\n };\n return this;\n }\n /**\n * Allow to pick directories besides files\n *\n * @param allow True to allow picking directories\n */\n allowDirectories(allow = true) {\n this.directoriesAllowed = allow;\n return this;\n }\n /**\n * Allow to create New folders\n *\n * @param noMenu True to hide menu\n */\n setNoMenu(noMenu = true) {\n this.noMenu = noMenu;\n return this;\n }\n /**\n * Set starting path of the FilePicker\n *\n * @param path Path to start from picking\n */\n startAt(path) {\n this.path = path;\n return this;\n }\n /**\n * Add filter function to filter file list of FilePicker\n *\n * @param filter Filter function to apply\n */\n setFilter(filter) {\n this.filter = filter;\n return this;\n }\n /**\n * Add function to allow or not picking a node\n *\n * @param canPick Function to decide if a node can be picked\n */\n setCanPick(canPick) {\n this.canPick = canPick;\n return this;\n }\n /**\n * Disable navigation (view selection)\n */\n disableNavigation() {\n this.disabledNavigation = true;\n return this;\n }\n /**\n * Construct the configured FilePicker\n */\n build() {\n return new FilePicker(\n this.title,\n this.multiSelect,\n this.mimeTypeFilter,\n this.directoriesAllowed,\n this.noMenu,\n this.buttons,\n this.path,\n this.filter,\n this.canPick,\n this.container,\n this.disabledNavigation\n );\n }\n}\nfunction getFilePickerBuilder(title) {\n return new FilePickerBuilder(title);\n}\nasync function showGuestUserPrompt(props) {\n const name = await spawnDialog(\n defineAsyncComponent(() => import(\"./PublicAuthPrompt.mjs\")),\n props\n );\n return name;\n}\nconst LoaderSvg = '\\n\t\\n\t\\n\\n';\nvar ToastType = /* @__PURE__ */ ((ToastType2) => {\n ToastType2[\"ERROR\"] = \"toast-error\";\n ToastType2[\"WARNING\"] = \"toast-warning\";\n ToastType2[\"INFO\"] = \"toast-info\";\n ToastType2[\"SUCCESS\"] = \"toast-success\";\n ToastType2[\"UNDO\"] = \"toast-undo\";\n ToastType2[\"LOADING\"] = \"toast-loading\";\n return ToastType2;\n})(ToastType || {});\nconst TOAST_ARIA_LIVE_OFF = \"off\";\nconst TOAST_ARIA_LIVE_POLITE = \"polite\";\nconst TOAST_ARIA_LIVE_ASSERTIVE = \"assertive\";\nvar ToastAriaLive = /* @__PURE__ */ ((ToastAriaLive2) => {\n ToastAriaLive2[ToastAriaLive2[\"OFF\"] = TOAST_ARIA_LIVE_OFF] = \"OFF\";\n ToastAriaLive2[ToastAriaLive2[\"POLITE\"] = TOAST_ARIA_LIVE_POLITE] = \"POLITE\";\n ToastAriaLive2[ToastAriaLive2[\"ASSERTIVE\"] = TOAST_ARIA_LIVE_ASSERTIVE] = \"ASSERTIVE\";\n return ToastAriaLive2;\n})(ToastAriaLive || {});\nconst TOAST_UNDO_TIMEOUT = 1e4;\nconst TOAST_DEFAULT_TIMEOUT = 7e3;\nconst TOAST_PERMANENT_TIMEOUT = -1;\nfunction showMessage(data, options) {\n options = {\n timeout: TOAST_DEFAULT_TIMEOUT,\n isHTML: false,\n type: void 0,\n // An undefined selector defaults to the body element\n selector: void 0,\n onRemove: () => {\n },\n onClick: void 0,\n close: true,\n ...options\n };\n if (typeof data === \"string\" && !options.isHTML) {\n const element = document.createElement(\"div\");\n element.innerHTML = data;\n data = element.innerText;\n }\n let classes = options.type ?? \"\";\n if (typeof options.onClick === \"function\") {\n classes += \" toast-with-click \";\n }\n const isNode = data instanceof Node;\n let ariaLive = ToastAriaLive.POLITE;\n if (options.ariaLive) {\n ariaLive = options.ariaLive;\n } else if (options.type === \"toast-error\" || options.type === \"toast-undo\") {\n ariaLive = ToastAriaLive.ASSERTIVE;\n }\n const toast = Toastify({\n [!isNode ? \"text\" : \"node\"]: data,\n duration: options.timeout,\n callback: options.onRemove,\n onClick: options.onClick,\n close: options.close,\n gravity: \"top\",\n selector: options.selector,\n position: \"right\",\n backgroundColor: \"\",\n className: \"dialogs \" + classes,\n escapeMarkup: !options.isHTML,\n ariaLive\n });\n toast.showToast();\n return toast;\n}\nfunction showError(text, options) {\n return showMessage(text, {\n ...options,\n type: \"toast-error\"\n /* ERROR */\n });\n}\nfunction showWarning(text, options) {\n return showMessage(text, {\n ...options,\n type: \"toast-warning\"\n /* WARNING */\n });\n}\nfunction showInfo(text, options) {\n return showMessage(text, {\n ...options,\n type: \"toast-info\"\n /* INFO */\n });\n}\nfunction showSuccess(text, options) {\n return showMessage(text, {\n ...options,\n type: \"toast-success\"\n /* SUCCESS */\n });\n}\nfunction showLoading(text, options) {\n const loader = document.createElement(\"span\");\n loader.innerHTML = LoaderSvg;\n loader.classList.add(\"toast-loader\");\n const loaderContent = document.createElement(\"span\");\n loaderContent.classList.add(\"toast-loader-container\");\n loaderContent.innerText = text;\n loaderContent.appendChild(loader);\n return showMessage(loaderContent, {\n ...options,\n close: false,\n timeout: TOAST_PERMANENT_TIMEOUT,\n type: \"toast-loading\"\n /* LOADING */\n });\n}\nfunction showUndo(text, onUndo, options) {\n if (!(onUndo instanceof Function)) {\n throw new Error(\"Please provide a valid onUndo method\");\n }\n options = Object.assign(options || {}, {\n // force 10 seconds of timeout\n timeout: TOAST_UNDO_TIMEOUT\n });\n const undoContent = document.createElement(\"span\");\n const undoButton = document.createElement(\"button\");\n undoContent.classList.add(\"toast-undo-container\");\n undoButton.classList.add(\"toast-undo-button\");\n undoButton.innerText = t(\"Undo\");\n undoContent.innerText = text;\n undoContent.appendChild(undoButton);\n const toast = showMessage(undoContent, {\n ...options,\n type: \"toast-undo\"\n /* UNDO */\n });\n undoButton.addEventListener(\"click\", function(event) {\n event.stopPropagation();\n onUndo(event);\n if (toast?.hideToast instanceof Function) {\n toast.hideToast();\n }\n });\n return toast;\n}\nconst _hoisted_1 = [\"textContent\"];\nconst _hoisted_2 = [\"innerHTML\"];\nconst _sfc_main = /* @__PURE__ */ defineComponent({\n __name: \"GenericDialog\",\n props: {\n name: {},\n text: {},\n html: {},\n buttons: {},\n severity: {}\n },\n emits: [\"close\"],\n setup(__props, { emit: __emit }) {\n const props = __props;\n const emit = __emit;\n const dialogButtons = computed(() => props.buttons?.map((button) => ({\n ...button,\n callback() {\n button.callback();\n emit(\"close\", true);\n }\n })));\n const handleUnload = () => `${props.name}: ${props.text}`;\n onMounted(() => window.addEventListener(\"unload\", handleUnload));\n onUnmounted(() => window.removeEventListener(\"unload\", handleUnload));\n return (_ctx, _cache) => {\n return openBlock(), createBlock(unref(NcDialog), {\n dialogClasses: \"nc-generic-dialog\",\n buttons: dialogButtons.value,\n name: __props.name,\n message: __props.text,\n \"onUpdate:open\": _cache[0] || (_cache[0] = ($event) => _ctx.$emit(\"close\", false))\n }, {\n default: withCtx(() => [\n __props.severity ? (openBlock(), createBlock(unref(NcNoteCard), {\n key: 0,\n type: __props.severity\n }, {\n default: withCtx(() => [\n createElementVNode(\"p\", {\n textContent: toDisplayString(__props.text)\n }, null, 8, _hoisted_1)\n ]),\n _: 1\n }, 8, [\"type\"])) : createCommentVNode(\"\", true),\n __props.html ? (openBlock(), createElementBlock(\"div\", {\n key: 1,\n innerHTML: __props.html\n }, null, 8, _hoisted_2)) : createCommentVNode(\"\", true)\n ]),\n _: 1\n }, 8, [\"buttons\", \"name\", \"message\"]);\n };\n }\n});\nclass Dialog {\n #name;\n #text;\n #buttons;\n #severity;\n constructor(name, text, buttons = [], severity) {\n this.#name = name;\n this.#text = text;\n this.#buttons = buttons;\n this.#severity = severity;\n }\n /**\n * Spawn and show the dialog - if already open the previous instance will be destroyed\n *\n * @return Promise that resolves when the dialog is answered successfully and rejects on close\n */\n async show() {\n const result = await spawnDialog(\n _sfc_main,\n {\n buttons: this.#buttons,\n name: this.#name,\n text: this.#text,\n severity: this.#severity\n }\n );\n if (!result) {\n throw new Error(\"Dialog closed\");\n }\n }\n}\nclass DialogBuilder {\n #severity;\n #text;\n #name;\n #buttons;\n constructor(name) {\n this.#severity = void 0;\n this.#text = \"\";\n this.#name = name ?? \"\";\n this.#buttons = [];\n }\n /**\n * Set dialog name\n *\n * @param name The name or headline of the dialog\n */\n setName(name) {\n this.#name = name;\n return this;\n }\n /**\n * Set the dialog text\n *\n * @param text Main text of the dialog\n */\n setText(text) {\n this.#text = text;\n return this;\n }\n /**\n * Set the severity of the dialog\n *\n * @param severity Severity of the dialog\n */\n setSeverity(severity) {\n this.#severity = severity;\n return this;\n }\n /**\n * Set buttons from array\n *\n * @param buttons Either an array of dialog buttons\n */\n setButtons(buttons) {\n if (this.#buttons.length > 0) {\n logger.warn(\"[@nextcloud/dialogs] Dialog buttons are already set - this overrides previous buttons.\");\n }\n this.#buttons = buttons;\n return this;\n }\n /**\n * Add a single button\n *\n * @param button Button to add\n */\n addButton(button) {\n this.#buttons.push(button);\n return this;\n }\n build() {\n return new Dialog(this.#name, this.#text, this.#buttons, this.#severity);\n }\n}\nfunction getDialogBuilder(name) {\n return new DialogBuilder(name);\n}\nasync function showConfirmation(options) {\n options = {\n labelConfirm: t(\"Confirm\"),\n ...options\n };\n const { promise, resolve } = Promise.withResolvers();\n const buttons = [{\n label: options.labelConfirm,\n variant: \"primary\",\n callback() {\n resolve(true);\n }\n }];\n if (options.labelReject) {\n buttons.unshift({\n label: options.labelReject,\n callback() {\n resolve(false);\n }\n });\n }\n const dialog = new Dialog(\n options.name,\n options.text,\n buttons,\n options.severity\n );\n await dialog.show();\n return promise;\n}\nexport {\n Dialog as D,\n FilePicker as F,\n TOAST_ARIA_LIVE_ASSERTIVE as T,\n DialogBuilder as a,\n FilePickerBuilder as b,\n FilePickerClosed as c,\n FilePickerType as d,\n TOAST_ARIA_LIVE_OFF as e,\n TOAST_ARIA_LIVE_POLITE as f,\n TOAST_DEFAULT_TIMEOUT as g,\n TOAST_PERMANENT_TIMEOUT as h,\n TOAST_UNDO_TIMEOUT as i,\n ToastAriaLive as j,\n ToastType as k,\n logger as l,\n getDialogBuilder as m,\n n,\n getFilePickerBuilder as o,\n openConflictPicker as p,\n showConfirmation as q,\n showGuestUserPrompt as r,\n showError as s,\n t,\n showInfo as u,\n showLoading as v,\n showMessage as w,\n showSuccess as x,\n showUndo as y,\n showWarning as z\n};\n//# sourceMappingURL=index.mjs.map\n","/**\n * SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: GPL-3.0-or-later\n */\n/**\n * @param app app ID, e.g. \"mail\"\n * @param key name of the property\n * @param fallback optional parameter to use as default value\n * @throws if the key can't be found\n */\nexport function loadState(app, key, fallback) {\n const selector = `#initial-state-${app}-${key}`;\n if (window._nc_initial_state?.has(selector)) {\n return window._nc_initial_state.get(selector);\n }\n else if (!window._nc_initial_state) {\n window._nc_initial_state = new Map();\n }\n const elem = document.querySelector(selector);\n if (elem === null) {\n if (fallback !== undefined) {\n return fallback;\n }\n throw new Error(`Could not find initial state ${key} of ${app}`);\n }\n try {\n const parsedValue = JSON.parse(atob(elem.value));\n window._nc_initial_state.set(selector, parsedValue);\n return parsedValue;\n }\n catch (error) {\n console.error('[@nextcloud/initial-state] Could not parse initial state', { key, app, error });\n if (fallback !== undefined) {\n return fallback;\n }\n throw new Error(`Could not parse initial state ${key} of ${app}`, { cause: error });\n }\n}\n","'use strict';\n\n/**\n * Create a bound version of a function with a specified `this` context\n *\n * @param {Function} fn - The function to bind\n * @param {*} thisArg - The value to be passed as the `this` parameter\n * @returns {Function} A new function that will call the original function with the specified `this` context\n */\nexport default function bind(fn, thisArg) {\n return function wrap() {\n return fn.apply(thisArg, arguments);\n };\n}\n","'use strict';\n\nimport bind from './helpers/bind.js';\n\n// utils is a library of generic helper functions non-specific to axios\n\nconst { toString } = Object.prototype;\nconst { getPrototypeOf } = Object;\nconst { iterator, toStringTag } = Symbol;\n\n/* Creating a function that will check if an object has a property. */\nconst hasOwnProperty = (\n ({ hasOwnProperty }) =>\n (obj, prop) =>\n hasOwnProperty.call(obj, prop)\n)(Object.prototype);\n\n/**\n * Walk the prototype chain (excluding the shared Object.prototype) looking for\n * an own `prop`. This distinguishes genuine own/inherited members — including\n * class accessors and template prototypes — from members injected via\n * Object.prototype pollution (e.g. `Object.prototype.username = '...'`), which\n * live on Object.prototype itself and are therefore never matched.\n *\n * @param {*} thing The value whose chain to inspect\n * @param {string|symbol} prop The property key to look for\n *\n * @returns {boolean} True when `prop` is owned below Object.prototype\n */\nconst hasOwnInPrototypeChain = (thing, prop) => {\n let obj = thing;\n const seen = [];\n\n while (obj != null && obj !== Object.prototype) {\n if (seen.indexOf(obj) !== -1) {\n return false;\n }\n seen.push(obj);\n\n if (hasOwnProperty(obj, prop)) {\n return true;\n }\n obj = getPrototypeOf(obj);\n }\n return false;\n};\n\n/**\n * Read `obj[prop]` only when it is safe from Object.prototype pollution. Own\n * properties and members inherited from a non-Object.prototype source (a class\n * instance or template object) are honored; a value reachable only through a\n * polluted Object.prototype is ignored and `undefined` is returned.\n *\n * @param {*} obj The source object\n * @param {string|symbol} prop The property key to read\n *\n * @returns {*} The resolved value, or undefined when unsafe/absent\n */\nconst getSafeProp = (obj, prop) =>\n obj != null && hasOwnInPrototypeChain(obj, prop) ? obj[prop] : undefined;\n\nconst kindOf = ((cache) => (thing) => {\n const str = toString.call(thing);\n return cache[str] || (cache[str] = str.slice(8, -1).toLowerCase());\n})(Object.create(null));\n\nconst kindOfTest = (type) => {\n type = type.toLowerCase();\n return (thing) => kindOf(thing) === type;\n};\n\nconst typeOfTest = (type) => (thing) => typeof thing === type;\n\n/**\n * Determine if a value is a non-null object\n *\n * @param {Object} val The value to test\n *\n * @returns {boolean} True if value is an Array, otherwise false\n */\nconst { isArray } = Array;\n\n/**\n * Determine if a value is undefined\n *\n * @param {*} val The value to test\n *\n * @returns {boolean} True if the value is undefined, otherwise false\n */\nconst isUndefined = typeOfTest('undefined');\n\n/**\n * Determine if a value is a Buffer\n *\n * @param {*} val The value to test\n *\n * @returns {boolean} True if value is a Buffer, otherwise false\n */\nfunction isBuffer(val) {\n return (\n val !== null &&\n !isUndefined(val) &&\n val.constructor !== null &&\n !isUndefined(val.constructor) &&\n isFunction(val.constructor.isBuffer) &&\n val.constructor.isBuffer(val)\n );\n}\n\n/**\n * Determine if a value is an ArrayBuffer\n *\n * @param {*} val The value to test\n *\n * @returns {boolean} True if value is an ArrayBuffer, otherwise false\n */\nconst isArrayBuffer = kindOfTest('ArrayBuffer');\n\n/**\n * Determine if a value is a view on an ArrayBuffer\n *\n * @param {*} val The value to test\n *\n * @returns {boolean} True if value is a view on an ArrayBuffer, otherwise false\n */\nfunction isArrayBufferView(val) {\n let result;\n if (typeof ArrayBuffer !== 'undefined' && ArrayBuffer.isView) {\n result = ArrayBuffer.isView(val);\n } else {\n result = val && val.buffer && isArrayBuffer(val.buffer);\n }\n return result;\n}\n\n/**\n * Determine if a value is a String\n *\n * @param {*} val The value to test\n *\n * @returns {boolean} True if value is a String, otherwise false\n */\nconst isString = typeOfTest('string');\n\n/**\n * Determine if a value is a Function\n *\n * @param {*} val The value to test\n * @returns {boolean} True if value is a Function, otherwise false\n */\nconst isFunction = typeOfTest('function');\n\n/**\n * Determine if a value is a Number\n *\n * @param {*} val The value to test\n *\n * @returns {boolean} True if value is a Number, otherwise false\n */\nconst isNumber = typeOfTest('number');\n\n/**\n * Determine if a value is an Object\n *\n * @param {*} thing The value to test\n *\n * @returns {boolean} True if value is an Object, otherwise false\n */\nconst isObject = (thing) => thing !== null && typeof thing === 'object';\n\n/**\n * Determine if a value is a Boolean\n *\n * @param {*} thing The value to test\n * @returns {boolean} True if value is a Boolean, otherwise false\n */\nconst isBoolean = (thing) => thing === true || thing === false;\n\n/**\n * Determine if a value is a plain Object\n *\n * @param {*} val The value to test\n *\n * @returns {boolean} True if value is a plain Object, otherwise false\n */\nconst isPlainObject = (val) => {\n if (!isObject(val)) {\n return false;\n }\n\n const prototype = getPrototypeOf(val);\n return (\n (prototype === null ||\n prototype === Object.prototype ||\n getPrototypeOf(prototype) === null) &&\n // Treat any genuine (non-Object.prototype-polluted) Symbol.toStringTag or\n // Symbol.iterator as evidence the value is a tagged/iterable type rather\n // than a plain object, while ignoring keys injected onto Object.prototype.\n !hasOwnInPrototypeChain(val, toStringTag) &&\n !hasOwnInPrototypeChain(val, iterator)\n );\n};\n\n/**\n * Determine if a value is an empty object (safely handles Buffers)\n *\n * @param {*} val The value to test\n *\n * @returns {boolean} True if value is an empty object, otherwise false\n */\nconst isEmptyObject = (val) => {\n // Early return for non-objects or Buffers to prevent RangeError\n if (!isObject(val) || isBuffer(val)) {\n return false;\n }\n\n try {\n return Object.keys(val).length === 0 && Object.getPrototypeOf(val) === Object.prototype;\n } catch (e) {\n // Fallback for any other objects that might cause RangeError with Object.keys()\n return false;\n }\n};\n\n/**\n * Determine if a value is a Date\n *\n * @param {*} val The value to test\n *\n * @returns {boolean} True if value is a Date, otherwise false\n */\nconst isDate = kindOfTest('Date');\n\n/**\n * Determine if a value is a File\n *\n * @param {*} val The value to test\n *\n * @returns {boolean} True if value is a File, otherwise false\n */\nconst isFile = kindOfTest('File');\n\n/**\n * Determine if a value is a React Native Blob\n * React Native \"blob\": an object with a `uri` attribute. Optionally, it can\n * also have a `name` and `type` attribute to specify filename and content type\n *\n * @see https://github.com/facebook/react-native/blob/26684cf3adf4094eb6c405d345a75bf8c7c0bf88/Libraries/Network/FormData.js#L68-L71\n *\n * @param {*} value The value to test\n *\n * @returns {boolean} True if value is a React Native Blob, otherwise false\n */\nconst isReactNativeBlob = (value) => {\n return !!(value && typeof value.uri !== 'undefined');\n};\n\n/**\n * Determine if environment is React Native\n * ReactNative `FormData` has a non-standard `getParts()` method\n *\n * @param {*} formData The formData to test\n *\n * @returns {boolean} True if environment is React Native, otherwise false\n */\nconst isReactNative = (formData) => formData && typeof formData.getParts !== 'undefined';\n\n/**\n * Determine if a value is a Blob\n *\n * @param {*} val The value to test\n *\n * @returns {boolean} True if value is a Blob, otherwise false\n */\nconst isBlob = kindOfTest('Blob');\n\n/**\n * Determine if a value is a FileList\n *\n * @param {*} val The value to test\n *\n * @returns {boolean} True if value is a FileList, otherwise false\n */\nconst isFileList = kindOfTest('FileList');\n\n/**\n * Determine if a value is a Stream\n *\n * @param {*} val The value to test\n *\n * @returns {boolean} True if value is a Stream, otherwise false\n */\nconst isStream = (val) => isObject(val) && isFunction(val.pipe);\n\n/**\n * Determine if a value is a FormData\n *\n * @param {*} thing The value to test\n *\n * @returns {boolean} True if value is an FormData, otherwise false\n */\nfunction getGlobal() {\n if (typeof globalThis !== 'undefined') return globalThis;\n if (typeof self !== 'undefined') return self;\n if (typeof window !== 'undefined') return window;\n if (typeof global !== 'undefined') return global;\n return {};\n}\n\nconst G = getGlobal();\nconst FormDataCtor = typeof G.FormData !== 'undefined' ? G.FormData : undefined;\n\nconst isFormData = (thing) => {\n if (!thing) return false;\n if (FormDataCtor && thing instanceof FormDataCtor) return true;\n // Reject plain objects inheriting directly from Object.prototype so prototype-pollution gadgets can't spoof FormData.\n const proto = getPrototypeOf(thing);\n if (!proto || proto === Object.prototype) return false;\n if (!isFunction(thing.append)) return false;\n const kind = kindOf(thing);\n return (\n kind === 'formdata' ||\n // detect form-data instance\n (kind === 'object' && isFunction(thing.toString) && thing.toString() === '[object FormData]')\n );\n};\n\n/**\n * Determine if a value is a URLSearchParams object\n *\n * @param {*} val The value to test\n *\n * @returns {boolean} True if value is a URLSearchParams object, otherwise false\n */\nconst isURLSearchParams = kindOfTest('URLSearchParams');\n\nconst [isReadableStream, isRequest, isResponse, isHeaders] = [\n 'ReadableStream',\n 'Request',\n 'Response',\n 'Headers',\n].map(kindOfTest);\n\n/**\n * Trim excess whitespace off the beginning and end of a string\n *\n * @param {String} str The String to trim\n *\n * @returns {String} The String freed of excess whitespace\n */\nconst trim = (str) => {\n return str.trim ? str.trim() : str.replace(/^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g, '');\n};\n/**\n * Iterate over an Array or an Object invoking a function for each item.\n *\n * If `obj` is an Array callback will be called passing\n * the value, index, and complete array for each item.\n *\n * If 'obj' is an Object callback will be called passing\n * the value, key, and complete object for each property.\n *\n * @param {Object|Array} obj The object to iterate\n * @param {Function} fn The callback to invoke for each item\n *\n * @param {Object} [options]\n * @param {Boolean} [options.allOwnKeys = false]\n * @returns {any}\n */\nfunction forEach(obj, fn, { allOwnKeys = false } = {}) {\n // Don't bother if no value provided\n if (obj === null || typeof obj === 'undefined') {\n return;\n }\n\n let i;\n let l;\n\n // Force an array if not already something iterable\n if (typeof obj !== 'object') {\n /*eslint no-param-reassign:0*/\n obj = [obj];\n }\n\n if (isArray(obj)) {\n // Iterate over array values\n for (i = 0, l = obj.length; i < l; i++) {\n fn.call(null, obj[i], i, obj);\n }\n } else {\n // Buffer check\n if (isBuffer(obj)) {\n return;\n }\n\n // Iterate over object keys\n const keys = allOwnKeys ? Object.getOwnPropertyNames(obj) : Object.keys(obj);\n const len = keys.length;\n let key;\n\n for (i = 0; i < len; i++) {\n key = keys[i];\n fn.call(null, obj[key], key, obj);\n }\n }\n}\n\n/**\n * Finds a key in an object, case-insensitive, returning the actual key name.\n * Returns null if the object is a Buffer or if no match is found.\n *\n * @param {Object} obj - The object to search.\n * @param {string} key - The key to find (case-insensitive).\n * @returns {?string} The actual key name if found, otherwise null.\n */\nfunction findKey(obj, key) {\n if (isBuffer(obj)) {\n return null;\n }\n\n key = key.toLowerCase();\n const keys = Object.keys(obj);\n let i = keys.length;\n let _key;\n while (i-- > 0) {\n _key = keys[i];\n if (key === _key.toLowerCase()) {\n return _key;\n }\n }\n return null;\n}\n\nconst _global = (() => {\n /*eslint no-undef:0*/\n if (typeof globalThis !== 'undefined') return globalThis;\n return typeof self !== 'undefined' ? self : typeof window !== 'undefined' ? window : global;\n})();\n\nconst isContextDefined = (context) => !isUndefined(context) && context !== _global;\n\n/**\n * Accepts varargs expecting each argument to be an object, then\n * immutably merges the properties of each object and returns result.\n *\n * When multiple objects contain the same key the later object in\n * the arguments list will take precedence.\n *\n * Example:\n *\n * ```js\n * const result = merge({foo: 123}, {foo: 456});\n * console.log(result.foo); // outputs 456\n * ```\n *\n * @param {Object} obj1 Object to merge\n *\n * @returns {Object} Result of all merge properties\n */\nfunction merge(...objs) {\n const { caseless, skipUndefined } = (isContextDefined(this) && this) || {};\n const result = {};\n const assignValue = (val, key) => {\n // Skip dangerous property names to prevent prototype pollution\n if (key === '__proto__' || key === 'constructor' || key === 'prototype') {\n return;\n }\n\n // findKey lowercases the key, so caseless lookup only applies to strings —\n // symbol keys are identity-matched.\n const targetKey = (caseless && typeof key === 'string' && findKey(result, key)) || key;\n // Read via own-prop only — a bare `result[targetKey]` walks the prototype\n // chain, so a polluted Object.prototype value could surface here and get\n // copied into the merged result.\n const existing = hasOwnProperty(result, targetKey) ? result[targetKey] : undefined;\n if (isPlainObject(existing) && isPlainObject(val)) {\n result[targetKey] = merge(existing, val);\n } else if (isPlainObject(val)) {\n result[targetKey] = merge({}, val);\n } else if (isArray(val)) {\n result[targetKey] = val.slice();\n } else if (!skipUndefined || !isUndefined(val)) {\n result[targetKey] = val;\n }\n };\n\n for (let i = 0, l = objs.length; i < l; i++) {\n const source = objs[i];\n if (!source || isBuffer(source)) {\n continue;\n }\n\n forEach(source, assignValue);\n\n if (typeof source !== 'object' || isArray(source)) {\n continue;\n }\n\n const symbols = Object.getOwnPropertySymbols(source);\n for (let j = 0; j < symbols.length; j++) {\n const symbol = symbols[j];\n if (propertyIsEnumerable.call(source, symbol)) {\n assignValue(source[symbol], symbol);\n }\n }\n }\n return result;\n}\n\n/**\n * Extends object a by mutably adding to it the properties of object b.\n *\n * @param {Object} a The object to be extended\n * @param {Object} b The object to copy properties from\n * @param {Object} thisArg The object to bind function to\n *\n * @param {Object} [options]\n * @param {Boolean} [options.allOwnKeys]\n * @returns {Object} The resulting value of object a\n */\nconst extend = (a, b, thisArg, { allOwnKeys } = {}) => {\n forEach(\n b,\n (val, key) => {\n if (thisArg && isFunction(val)) {\n Object.defineProperty(a, key, {\n // Null-proto descriptor so a polluted Object.prototype.get cannot\n // hijack defineProperty's accessor-vs-data resolution.\n __proto__: null,\n value: bind(val, thisArg),\n writable: true,\n enumerable: true,\n configurable: true,\n });\n } else {\n Object.defineProperty(a, key, {\n __proto__: null,\n value: val,\n writable: true,\n enumerable: true,\n configurable: true,\n });\n }\n },\n { allOwnKeys }\n );\n return a;\n};\n\n/**\n * Remove byte order marker. This catches EF BB BF (the UTF-8 BOM)\n *\n * @param {string} content with BOM\n *\n * @returns {string} content value without BOM\n */\nconst stripBOM = (content) => {\n if (content.charCodeAt(0) === 0xfeff) {\n content = content.slice(1);\n }\n return content;\n};\n\n/**\n * Inherit the prototype methods from one constructor into another\n * @param {function} constructor\n * @param {function} superConstructor\n * @param {object} [props]\n * @param {object} [descriptors]\n *\n * @returns {void}\n */\nconst inherits = (constructor, superConstructor, props, descriptors) => {\n constructor.prototype = Object.create(superConstructor.prototype, descriptors);\n Object.defineProperty(constructor.prototype, 'constructor', {\n __proto__: null,\n value: constructor,\n writable: true,\n enumerable: false,\n configurable: true,\n });\n Object.defineProperty(constructor, 'super', {\n __proto__: null,\n value: superConstructor.prototype,\n });\n props && Object.assign(constructor.prototype, props);\n};\n\n/**\n * Resolve object with deep prototype chain to a flat object\n * @param {Object} sourceObj source object\n * @param {Object} [destObj]\n * @param {Function|Boolean} [filter]\n * @param {Function} [propFilter]\n *\n * @returns {Object}\n */\nconst toFlatObject = (sourceObj, destObj, filter, propFilter) => {\n let props;\n let i;\n let prop;\n const merged = {};\n\n destObj = destObj || {};\n // eslint-disable-next-line no-eq-null,eqeqeq\n if (sourceObj == null) return destObj;\n\n do {\n props = Object.getOwnPropertyNames(sourceObj);\n i = props.length;\n while (i-- > 0) {\n prop = props[i];\n if ((!propFilter || propFilter(prop, sourceObj, destObj)) && !merged[prop]) {\n destObj[prop] = sourceObj[prop];\n merged[prop] = true;\n }\n }\n sourceObj = filter !== false && getPrototypeOf(sourceObj);\n } while (sourceObj && (!filter || filter(sourceObj, destObj)) && sourceObj !== Object.prototype);\n\n return destObj;\n};\n\n/**\n * Determines whether a string ends with the characters of a specified string\n *\n * @param {String} str\n * @param {String} searchString\n * @param {Number} [position= 0]\n *\n * @returns {boolean}\n */\nconst endsWith = (str, searchString, position) => {\n str = String(str);\n if (position === undefined || position > str.length) {\n position = str.length;\n }\n position -= searchString.length;\n const lastIndex = str.indexOf(searchString, position);\n return lastIndex !== -1 && lastIndex === position;\n};\n\n/**\n * Returns new array from array like object or null if failed\n *\n * @param {*} [thing]\n *\n * @returns {?Array}\n */\nconst toArray = (thing) => {\n if (!thing) return null;\n if (isArray(thing)) return thing;\n let i = thing.length;\n if (!isNumber(i)) return null;\n const arr = new Array(i);\n while (i-- > 0) {\n arr[i] = thing[i];\n }\n return arr;\n};\n\n/**\n * Checking if the Uint8Array exists and if it does, it returns a function that checks if the\n * thing passed in is an instance of Uint8Array\n *\n * @param {TypedArray}\n *\n * @returns {Array}\n */\n// eslint-disable-next-line func-names\nconst isTypedArray = ((TypedArray) => {\n // eslint-disable-next-line func-names\n return (thing) => {\n return TypedArray && thing instanceof TypedArray;\n };\n})(typeof Uint8Array !== 'undefined' && getPrototypeOf(Uint8Array));\n\n/**\n * For each entry in the object, call the function with the key and value.\n *\n * @param {Object} obj - The object to iterate over.\n * @param {Function} fn - The function to call for each entry.\n *\n * @returns {void}\n */\nconst forEachEntry = (obj, fn) => {\n const generator = obj && obj[iterator];\n\n const _iterator = generator.call(obj);\n\n let result;\n\n while ((result = _iterator.next()) && !result.done) {\n const pair = result.value;\n fn.call(obj, pair[0], pair[1]);\n }\n};\n\n/**\n * It takes a regular expression and a string, and returns an array of all the matches\n *\n * @param {string} regExp - The regular expression to match against.\n * @param {string} str - The string to search.\n *\n * @returns {Array}\n */\nconst matchAll = (regExp, str) => {\n let matches;\n const arr = [];\n\n while ((matches = regExp.exec(str)) !== null) {\n arr.push(matches);\n }\n\n return arr;\n};\n\n/* Checking if the kindOfTest function returns true when passed an HTMLFormElement. */\nconst isHTMLForm = kindOfTest('HTMLFormElement');\n\nconst toCamelCase = (str) => {\n return str.toLowerCase().replace(/[-_\\s]([a-z\\d])(\\w*)/g, function replacer(m, p1, p2) {\n return p1.toUpperCase() + p2;\n });\n};\n\nconst { propertyIsEnumerable } = Object.prototype;\n\n/**\n * Determine if a value is a RegExp object\n *\n * @param {*} val The value to test\n *\n * @returns {boolean} True if value is a RegExp object, otherwise false\n */\nconst isRegExp = kindOfTest('RegExp');\n\nconst reduceDescriptors = (obj, reducer) => {\n const descriptors = Object.getOwnPropertyDescriptors(obj);\n const reducedDescriptors = {};\n\n forEach(descriptors, (descriptor, name) => {\n let ret;\n if ((ret = reducer(descriptor, name, obj)) !== false) {\n reducedDescriptors[name] = ret || descriptor;\n }\n });\n\n Object.defineProperties(obj, reducedDescriptors);\n};\n\n/**\n * Makes all methods read-only\n * @param {Object} obj\n */\n\nconst freezeMethods = (obj) => {\n reduceDescriptors(obj, (descriptor, name) => {\n // skip restricted props in strict mode\n if (isFunction(obj) && ['arguments', 'caller', 'callee'].includes(name)) {\n return false;\n }\n\n const value = obj[name];\n\n if (!isFunction(value)) return;\n\n descriptor.enumerable = false;\n\n if ('writable' in descriptor) {\n descriptor.writable = false;\n return;\n }\n\n if (!descriptor.set) {\n descriptor.set = () => {\n throw Error(\"Can not rewrite read-only method '\" + name + \"'\");\n };\n }\n });\n};\n\n/**\n * Converts an array or a delimited string into an object set with values as keys and true as values.\n * Useful for fast membership checks.\n *\n * @param {Array|string} arrayOrString - The array or string to convert.\n * @param {string} delimiter - The delimiter to use if input is a string.\n * @returns {Object} An object with keys from the array or string, values set to true.\n */\nconst toObjectSet = (arrayOrString, delimiter) => {\n const obj = {};\n\n const define = (arr) => {\n arr.forEach((value) => {\n obj[value] = true;\n });\n };\n\n isArray(arrayOrString) ? define(arrayOrString) : define(String(arrayOrString).split(delimiter));\n\n return obj;\n};\n\nconst noop = () => {};\n\nconst toFiniteNumber = (value, defaultValue) => {\n return value != null && Number.isFinite((value = +value)) ? value : defaultValue;\n};\n\n/**\n * If the thing is a FormData object, return true, otherwise return false.\n *\n * @param {unknown} thing - The thing to check.\n *\n * @returns {boolean}\n */\nfunction isSpecCompliantForm(thing) {\n return !!(\n thing &&\n isFunction(thing.append) &&\n thing[toStringTag] === 'FormData' &&\n thing[iterator]\n );\n}\n\n/**\n * Recursively converts an object to a JSON-compatible object, handling circular references and Buffers.\n *\n * @param {Object} ob SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\nfunction getSameNodeParent(instance) {\n if (!instance.parent) {\n return null;\n }\n if (\"vapor\" in instance || \"vapor\" in instance.parent) {\n warn(\"Vapor instances are not supported in useScopeIdAttrs :(\");\n return null;\n }\n if (instance.parent.subTree !== instance.vnode) {\n return null;\n }\n return instance.parent;\n}\nfunction getSameNodeAncestors(instance) {\n const ancestors = [instance];\n let parent = getSameNodeParent(instance);\n while (parent) {\n ancestors.push(parent);\n parent = getSameNodeParent(parent);\n }\n return ancestors;\n}\nfunction useScopeIdAttrs() {\n const instance = getCurrentInstance();\n if (!instance) {\n throw new Error(\"useScopeId must be called within a setup context\");\n }\n const sameNodeAncestors = getSameNodeAncestors(instance);\n const scopeIds = sameNodeAncestors.map((instance2) => instance2.vnode.scopeId).filter(Boolean);\n const scopeIdAttrs = Object.fromEntries(scopeIds.map((scopeId) => [scopeId, \"\"]));\n return scopeIdAttrs;\n}\nregister(t19, t36);\nconst _hoisted_1 = [\"aria-labelledby\", \"aria-describedby\"];\nconst _hoisted_2 = [\"data-theme-light\", \"data-theme-dark\"];\nconst _hoisted_3 = [\"id\"];\nconst _hoisted_4 = { class: \"icons-menu\" };\nconst _hoisted_5 = [\"title\"];\nconst _hoisted_6 = [\"id\"];\nconst _hoisted_7 = { class: \"modal-container__content\" };\nconst _sfc_main = /* @__PURE__ */ defineComponent({\n ...{ inheritAttrs: false },\n __name: \"NcModal\",\n props: /* @__PURE__ */ mergeModels({\n name: { default: \"\" },\n hasPrevious: { type: Boolean },\n hasNext: { type: Boolean },\n outTransition: { type: Boolean },\n enableSlideshow: { type: Boolean },\n slideshowDelay: { default: 5e3 },\n slideshowPaused: { type: Boolean },\n disableSwipe: { type: Boolean },\n spreadNavigation: { type: Boolean },\n size: { default: \"normal\" },\n noClose: { type: Boolean },\n closeOnClickOutside: { type: Boolean },\n dark: { type: Boolean },\n lightBackdrop: { type: Boolean },\n container: { default: \"body\" },\n closeButtonOutside: { type: Boolean },\n additionalTrapElements: { default: () => [] },\n inlineActions: { default: 0 },\n labelId: { default: \"\" },\n setReturnFocus: { default: void 0 }\n }, {\n \"show\": { type: Boolean, ...{ default: true } },\n \"showModifiers\": {}\n }),\n emits: /* @__PURE__ */ mergeModels([\"next\", \"previous\", \"close\", \"update:show\"], [\"update:show\"]),\n setup(__props, { emit: __emit }) {\n useCssVars((_ctx) => ({\n \"v046d2bb2\": numHeaderActions.value,\n \"v71f7c020\": cssSlideshowDelay.value\n }));\n const showModal = useModel(__props, \"show\");\n const props = __props;\n const emit = __emit;\n const scopeIdAttrs = useScopeIdAttrs();\n const modalId = createElementId();\n const maskElement = useTemplateRef(\"mask\");\n let focusTrap;\n onUnmounted(() => clearFocusTrap());\n watch(() => props.additionalTrapElements, (elements) => {\n if (focusTrap) {\n focusTrap.updateContainerElements([maskElement.value, ...elements]);\n }\n });\n const {\n isActive: isPlaying,\n pause: stopSlideshow,\n resume: startSlideshow\n } = useIntervalFn(nextSlide, toRef(() => props.slideshowDelay), { immediate: false });\n const animationKey = ref(0);\n const runSlideshow = ref(false);\n watchEffect(() => {\n if (runSlideshow.value && !props.slideshowPaused) {\n startSlideshow();\n } else SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: GPL-3.0-or-later\n */\nfunction generateAvatarUrl(user, options) {\n const size = (options?.size || 64) <= 64 ? 64 : 512;\n const guestUrl = options?.isGuestUser ? \"/guest\" : \"\";\n const themeUrl = options?.isDarkTheme ? \"/dark\" : \"\";\n return generateUrl(`/avatar${guestUrl}/{user}/{size}${themeUrl}`, {\n user,\n size\n });\n}\nexport {\n generateAvatarUrl,\n generateFilePath,\n generateOcsUrl,\n generateRemoteUrl,\n generateUrl,\n getAppRootUrl,\n getBaseUrl,\n getRootUrl,\n imagePath,\n linkTo\n};\n//# sourceMappingURL=index.mjs.map\n","/*! @license DOMPurify 3.4.12 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.4.12/LICENSE */\n\nfunction _arrayLikeToArray(r, a) {\n (null == a || a > r.length) && (a = r.length);\n for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];\n return n;\n}\nfunction _arrayWithHoles(r) {\n if (Array.isArray(r)) return r;\n}\nfunction _iterableToArrayLimit(r, l) {\n var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"];\n if (null != t) {\n var e,\n n,\n i,\n u,\n a = [],\n f = true,\n o = false;\n try {\n if (i = (t = t.call(r)).next, 0 === l) ; else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0);\n } catch (r) {\n o = true, n = r;\n } finally {\n try {\n if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return;\n } finally {\n if (o) throw n;\n }\n }\n return a;\n }\n}\nfunction _nonIterableRest() {\n throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\");\n}\nfunction _slicedToArray(r, e) {\n return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest();\n}\nfunction _unsupportedIterableToArray(r, a) {\n if (r) {\n if (\"string\" == typeof r) return _arrayLikeToArray(r, a);\n var t = {}.toString.call(r).slice(8, -1);\n return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0;\n }\n}\n\nconst entries = Object.entries,\n setPrototypeOf = Object.setPrototypeOf,\n isFrozen = Object.isFrozen,\n getPrototypeOf = Object.getPrototypeOf,\n getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\nlet freeze = Object.freeze,\n seal = Object.seal,\n create = Object.create; // eslint-disable-line import/no-mutable-exports\nlet _ref = typeof Reflect !== 'undefined' && Reflect,\n apply = _ref.apply,\n construct = _ref.construct;\nif (!freeze) {\n freeze = function freeze(x) {\n return x;\n };\n}\nif (!seal) {\n seal = function seal(x) {\n return x;\n };\n}\nif (!apply) {\n apply = function apply(func, thisArg) {\n for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {\n args[_key - 2] = arguments[_key];\n }\n return func.apply(thisArg, args);\n };\n}\nif (!construct) {\n construct = function construct(Func) {\n for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {\n args[_key2 - 1] = arguments[_key2];\n }\n return new Func(...args);\n };\n}\nconst arrayForEach = unapply(Array.prototype.forEach);\nconst arrayLastIndexOf = unapply(Array.prototype.lastIndexOf);\nconst arrayPop = unapply(Array.prototype.pop);\nconst arrayPush = unapply(Array.prototype.push);\nconst arraySplice = unapply(Array.prototype.splice);\nconst arrayIsArray = Array.isArray;\nconst stringToLowerCase = unapply(String.prototype.toLowerCase);\nconst stringToString = unapply(String.prototype.toString);\nconst stringMatch = unapply(String.prototype.match);\nconst stringReplace = unapply(String.prototype.replace);\nconst stringIndexOf = unapply(String.prototype.indexOf);\nconst stringTrim = unapply(String.prototype.trim);\nconst numberToString = unapply(Number.prototype.toString);\nconst booleanToString = unapply(Boolean.prototype.toString);\nconst bigintToString = typeof BigInt === 'undefined' ? null : unapply(BigInt.prototype.toString);\nconst symbolToString = typeof Symbol === 'undefined' ? null : unapply(Symbol.prototype.toString);\nconst objectHasOwnProperty = unapply(Object.prototype.hasOwnProperty);\nconst objectToString = unapply(Object.prototype.toString);\nconst regExpTest = unapply(RegExp.prototype.test);\nconst typeErrorCreate = unconstruct(TypeError);\n/**\n * Creates a new function that calls the given function with a specified thisArg and arguments.\n *\n * @param func - The function to be wrapped and called.\n * @returns A new function that calls the given function with a specified thisArg and arguments.\n */\nfunction unapply(func) {\n return function (thisArg) {\n if (thisArg instanceof RegExp) {\n thisArg.lastIndex = 0;\n }\n for (var _len3 = arguments.length, args = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {\n args[_key3 - 1] = arguments[_key3];\n }\n return apply(func, thisArg, args);\n };\n}\n/**\n * Creates a new function that constructs an instance of the given constructor function with the provided arguments.\n *\n * @param func - The constructor function to be wrapped and called.\n * @returns A new function that constructs an instance of the given constructor function with the provided arguments.\n */\nfunction unconstruct(Func) {\n return function () {\n for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {\n args[_key4] = arguments[_key4];\n }\n return construct(Func, args);\n };\n}\n/**\n * Add properties to a lookup table\n *\n * @param set - The set to which elements will be added.\n * @param array - The array containing elements to be added to the set.\n * @param transformCaseFunc - An optional function to transform the case of each element before adding to the set.\n * @returns The modified set with added elements.\n */\nfunction addToSet(set, array) {\n let transformCaseFunc = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : stringToLowerCase;\n if (setPrototypeOf) {\n // Make 'in' and truthy checks like Boolean(set.constructor)\n // independent of any properties defined on Object.prototype.\n // Prevent prototype setters from intercepting set as a this value.\n setPrototypeOf(set, null);\n }\n if (!arrayIsArray(array)) {\n return set;\n }\n let l = array.length;\n while (l--) {\n let element = array[l];\n if (typeof element === 'string') {\n const lcElement = transformCaseFunc(element);\n if (lcElement !== element) {\n // Config presets (e.g. tags.js, attrs.js) are immutable.\n if (!isFrozen(array)) {\n array[l] = lcElement;\n }\n element = lcElement;\n }\n }\n set[element] = true;\n }\n return set;\n}\n/**\n * Clean up an array to harden against CSPP\n *\n * @param array - The array to be cleaned.\n * @returns The cleaned version of the array\n */\nfunction cleanArray(array) {\n for (let index = 0; index < array.length; index++) {\n const isPropertyExist = objectHasOwnProperty(array, index);\n if (!isPropertyExist) {\n array[index] = null;\n }\n }\n return array;\n}\n/**\n * Shallow clone an object\n *\n * @param object - The object to be cloned.\n * @returns A new object that copies the original.\n */\nfunction clone(object) {\n const newObject = create(null);\n for (const _ref2 of entries(object)) {\n var _ref3 = _slicedToArray(_ref2, 2);\n const property = _ref3[0];\n const value = _ref3[1];\n const isPropertyExist = objectHasOwnProperty(object, property);\n if (isPropertyExist) {\n if (arrayIsArray(value)) {\n newObject[property] = cleanArray(value);\n } else if (value && typeof value === 'object' && value.constructor === Object) {\n newObject[property] = clone(value);\n } else {\n newObject[property] = value;\n }\n }\n }\n return newObject;\n}\n/**\n * Convert non-node values into strings without depending on direct property access.\n *\n * @param value - The value to stringify.\n * @returns A string representation of the provided value.\n */\nfunction stringifyValue(value) {\n switch (typeof value) {\n case 'string':\n {\n return value;\n }\n case 'number':\n {\n return numberToString(value);\n }\n case 'boolean':\n {\n return booleanToString(value);\n }\n case 'bigint':\n {\n return bigintToString ? bigintToString(value) : '0';\n }\n case 'symbol':\n {\n return symbolToString ? symbolToString(value) : 'Symbol()';\n }\n case 'undefined':\n {\n return objectToString(value);\n }\n case 'function':\n case 'object':\n {\n if (value === null) {\n return objectToString(value);\n }\n const valueAsRecord = value;\n const valueToString = lookupGetter(valueAsRecord, 'toString');\n if (typeof valueToString === 'function') {\n const stringified = valueToString(valueAsRecord);\n return typeof stringified === 'string' ? stringified : objectToString(stringified);\n }\n return objectToString(value);\n }\n default:\n {\n return objectToString(value);\n }\n }\n}\n/**\n * This method automatically checks if the prop is function or getter and behaves accordingly.\n *\n * @param object - The object to look up the getter function in its prototype chain.\n * @param prop - The property name for which to find the getter function.\n * @returns The getter function found in the prototype chain or a fallback function.\n */\nfunction lookupGetter(object, prop) {\n while (object !== null) {\n const desc = getOwnPropertyDescriptor(object, prop);\n if (desc) {\n if (desc.get) {\n return unapply(desc.get);\n }\n if (typeof desc.value === 'function') {\n return unapply(desc.value);\n }\n }\n object = getPrototypeOf(object);\n }\n function fallbackValue() {\n return null;\n }\n return fallbackValue;\n}\nfunction isRegex(value) {\n try {\n regExpTest(value, '');\n return true;\n } catch (_unused) {\n return false;\n }\n}\n\nconst html$1 = freeze(['a', 'abbr', 'acronym', 'address', 'area', 'article', 'aside', 'audio', 'b', 'bdi', 'bdo', 'big', 'blink', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'content', 'data', 'datalist', 'dd', 'decorator', 'del', 'details', 'dfn', 'dialog', 'dir', 'div', 'dl', 'dt', 'element', 'em', 'fieldset', 'figcaption', 'figure', 'font', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'i', 'img', 'input', 'ins', 'kbd', 'label', 'legend', 'li', 'main', 'map', 'mark', 'marquee', 'menu', 'menuitem', 'meter', 'nav', 'nobr', 'ol', 'optgroup', 'option', 'output', 'p', 'picture', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'search', 'section', 'select', 'shadow', 'slot', 'small', 'source', 'spacer', 'span', 'strike', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'time', 'tr', 'track', 'tt', 'u', 'ul', 'var', 'video', 'wbr']);\nconst svg$1 = freeze(['svg', 'a', 'altglyph', 'altglyphdef', 'altglyphitem', 'animatecolor', 'animatemotion', 'animatetransform', 'circle', 'clippath', 'defs', 'desc', 'ellipse', 'enterkeyhint', 'exportparts', 'filter', 'font', 'g', 'glyph', 'glyphref', 'hkern', 'image', 'inputmode', 'line', 'lineargradient', 'marker', 'mask', 'metadata', 'mpath', 'part', 'path', 'pattern', 'polygon', 'polyline', 'radialgradient', 'rect', 'stop', 'style', 'switch', 'symbol', 'text', 'textpath', 'title', 'tref', 'tspan', 'view', 'vkern']);\nconst svgFilters = freeze(['feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight', 'feDropShadow', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur', 'feImage', 'feMerge', 'feMergeNode', 'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence']);\n// List of SVG elements that are disallowed by default.\n// We still need to know them so that we can do namespace\n// checks properly in case one wants to add them to\n// allow-list.\nconst svgDisallowed = freeze(['animate', 'color-profile', 'cursor', 'discard', 'font-face', 'font-face-format', 'font-face-name', 'font-face-src', 'font-face-uri', 'foreignobject', 'hatch', 'hatchpath', 'mesh', 'meshgradient', 'meshpatch', 'meshrow', 'missing-glyph', 'script', 'set', 'solidcolor', 'unknown', 'use']);\nconst mathMl$1 = freeze(['math', 'menclose', 'merror', 'mfenced', 'mfrac', 'mglyph', 'mi', 'mlabeledtr', 'mmultiscripts', 'mn', 'mo', 'mover', 'mpadded', 'mphantom', 'mroot', 'mrow', 'ms', 'mspace', 'msqrt', 'mstyle', 'msub', 'msup', 'msubsup', 'mtable', 'mtd', 'mtext', 'mtr', 'munder', 'munderover', 'mprescripts']);\n// Similarly to SVG, we want to know all MathML elements,\n// even those that we disallow by default.\nconst mathMlDisallowed = freeze(['maction', 'maligngroup', 'malignmark', 'mlongdiv', 'mscarries', 'mscarry', 'msgroup', 'mstack', 'msline', 'msrow', 'semantics', 'annotation', 'annotation-xml', 'mprescripts', 'none']);\nconst text = freeze(['#text']);\n\nconst html = freeze(['accept', 'action', 'align', 'alt', 'autocapitalize', 'autocomplete', 'autopictureinpicture', 'autoplay', 'background', 'bgcolor', 'border', 'capture', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', 'command', 'commandfor', 'controls', 'controlslist', 'coords', 'crossorigin', 'datetime', 'decoding', 'default', 'dir', 'disabled', 'disablepictureinpicture', 'disableremoteplayback', 'download', 'draggable', 'enctype', 'enterkeyhint', 'exportparts', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', 'inert', 'inputmode', 'integrity', 'ismap', 'kind', 'label', 'lang', 'list', 'loading', 'loop', 'low', 'max', 'maxlength', 'media', 'method', 'min', 'minlength', 'multiple', 'muted', 'name', 'nonce', 'noshade', 'novalidate', 'nowrap', 'open', 'optimum', 'part', 'pattern', 'placeholder', 'playsinline', 'popover', 'popovertarget', 'popovertargetaction', 'poster', 'preload', 'pubdate', 'radiogroup', 'readonly', 'rel', 'required', 'rev', 'reversed', 'role', 'rows', 'rowspan', 'spellcheck', 'scope', 'selected', 'shape', 'size', 'sizes', 'slot', 'span', 'srclang', 'start', 'src', 'srcset', 'step', 'style', 'summary', 'tabindex', 'title', 'translate', 'type', 'usemap', 'valign', 'value', 'width', 'wrap', 'xmlns']);\nconst svg = freeze(['accent-height', 'accumulate', 'additive', 'alignment-baseline', 'amplitude', 'ascent', 'attributename', 'attributetype', 'azimuth', 'basefrequency', 'baseline-shift', 'begin', 'bias', 'by', 'class', 'clip', 'clippathunits', 'clip-path', 'clip-rule', 'color', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'cx', 'cy', 'd', 'dx', 'dy', 'diffuseconstant', 'direction', 'display', 'divisor', 'dominant-baseline', 'dur', 'edgemode', 'elevation', 'end', 'exponent', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'filterunits', 'flood-color', 'flood-opacity', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'fx', 'fy', 'g1', 'g2', 'glyph-name', 'glyphref', 'gradientunits', 'gradienttransform', 'height', 'href', 'id', 'image-rendering', 'in', 'in2', 'intercept', 'k', 'k1', 'k2', 'k3', 'k4', 'kerning', 'keypoints', 'keysplines', 'keytimes', 'lang', 'lengthadjust', 'letter-spacing', 'kernelmatrix', 'kernelunitlength', 'lighting-color', 'local', 'marker-end', 'marker-mid', 'marker-start', 'markerheight', 'markerunits', 'markerwidth', 'maskcontentunits', 'maskunits', 'max', 'mask', 'mask-type', 'media', 'method', 'mode', 'min', 'name', 'numoctaves', 'offset', 'operator', 'opacity', 'order', 'orient', 'orientation', 'origin', 'overflow', 'paint-order', 'path', 'pathlength', 'patterncontentunits', 'patterntransform', 'patternunits', 'points', 'preservealpha', 'preserveaspectratio', 'primitiveunits', 'r', 'rx', 'ry', 'radius', 'refx', 'refy', 'repeatcount', 'repeatdur', 'restart', 'result', 'rotate', 'scale', 'seed', 'shape-rendering', 'slope', 'specularconstant', 'specularexponent', 'spreadmethod', 'startoffset', 'stddeviation', 'stitchtiles', 'stop-color', 'stop-opacity', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke', 'stroke-width', 'style', 'surfacescale', 'systemlanguage', 'tabindex', 'tablevalues', 'targetx', 'targety', 'transform', 'transform-origin', 'text-anchor', 'text-decoration', 'text-orientation', 'text-rendering', 'textlength', 'type', 'u1', 'u2', 'unicode', 'values', 'viewbox', 'visibility', 'version', 'vert-adv-y', 'vert-origin-x', 'vert-origin-y', 'width', 'word-spacing', 'wrap', 'writing-mode', 'xchannelselector', 'ychannelselector', 'x', 'x1', 'x2', 'xmlns', 'y', 'y1', 'y2', 'z', 'zoomandpan']);\nconst mathMl = freeze(['accent', 'accentunder', 'align', 'bevelled', 'close', 'columnalign', 'columnlines', 'columnspacing', 'columnspan', 'denomalign', 'depth', 'dir', 'display', 'displaystyle', 'encoding', 'fence', 'frame', 'height', 'href', 'id', 'largeop', 'length', 'linethickness', 'lquote', 'lspace', 'mathbackground', 'mathcolor', 'mathsize', 'mathvariant', 'maxsize', 'minsize', 'movablelimits', 'notation', 'numalign', 'open', 'rowalign', 'rowlines', 'rowspacing', 'rowspan', 'rspace', 'rquote', 'scriptlevel', 'scriptminsize', 'scriptsizemultiplier', 'selection', 'separator', 'separators', 'stretchy', 'subscriptshift', 'supscriptshift', 'symmetric', 'voffset', 'width', 'xmlns']);\nconst xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);\n\nconst MUSTACHE_EXPR = seal(/{{[\\w\\W]*|^[\\w\\W]*}}/g);\nconst ERB_EXPR = seal(/<%[\\w\\W]*|^[\\w\\W]*%>/g);\nconst TMPLIT_EXPR = seal(/\\${[\\w\\W]*/g);\nconst DATA_ATTR = seal(/^data-[\\-\\w.\\u00B7-\\uFFFF]+$/); // eslint-disable-line no-useless-escape\nconst ARIA_ATTR = seal(/^aria-[\\-\\w]+$/); // eslint-disable-line no-useless-escape\nconst IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.\\-]+(?:[^a-z+.\\-:]|$))/i // eslint-disable-line no-useless-escape\n);\nconst IS_SCRIPT_OR_DATA = seal(/^(?:\\w+script|data):/i);\nconst ATTR_WHITESPACE = seal(/[\\u0000-\\u0020\\u00A0\\u1680\\u180E\\u2000-\\u2029\\u205F\\u3000]/g // eslint-disable-line no-control-regex\n);\nconst DOCTYPE_NAME = seal(/^html$/i);\nconst CUSTOM_ELEMENT = seal(/^[a-z][.\\w]*(-[.\\w]+)+$/i);\n// Markup-significant character probes used by _sanitizeElements.\n// Shared module-level instances are safe despite the sticky /g flags:\n// unapply() resets lastIndex for RegExp receivers before every call.\nconst ELEMENT_MARKUP_PROBE = seal(/<[/\\w!]/g);\nconst COMMENT_MARKUP_PROBE = seal(/<[/\\w]/g);\nconst FALLBACK_TAG_CLOSE = seal(/<\\/no(script|embed|frames)/i);\nconst SELF_CLOSING_TAG = seal(/\\/>/i);\n\n// https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType\nconst NODE_TYPE = {\n element: 1,\n attribute: 2,\n text: 3,\n cdataSection: 4,\n entityReference: 5,\n // Deprecated\n entityNode: 6,\n // Deprecated\n processingInstruction: 7,\n comment: 8,\n document: 9,\n documentType: 10,\n documentFragment: 11,\n notation: 12 // Deprecated\n};\nconst getGlobal = function getGlobal() {\n return typeof window === 'undefined' ? null : window;\n};\n/**\n * Creates a no-op policy for internal use only.\n * Don't export this function outside this module!\n * @param trustedTypes The policy factory.\n * @param purifyHostElement The Script element used to load DOMPurify (to determine policy name suffix).\n * @return The policy created (or null, if Trusted Types\n * are not supported or creating the policy failed).\n */\nconst _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedTypes, purifyHostElement) {\n if (typeof trustedTypes !== 'object' || typeof trustedTypes.createPolicy !== 'function') {\n return null;\n }\n // Allow the callers to control the unique policy name\n // by adding a data-tt-policy-suffix to the script element with the DOMPurify.\n // Policy creation with duplicate names throws in Trusted Types.\n let suffix = null;\n const ATTR_NAME = 'data-tt-policy-suffix';\n if (purifyHostElement && purifyHostElement.hasAttribute(ATTR_NAME)) {\n suffix = purifyHostElement.getAttribute(ATTR_NAME);\n }\n const policyName = 'dompurify' + (suffix ? '#' + suffix : '');\n try {\n return trustedTypes.createPolicy(policyName, {\n createHTML(html) {\n return html;\n },\n createScriptURL(scriptUrl) {\n return scriptUrl;\n }\n });\n } catch (_) {\n // Policy creation failed (most likely another DOMPurify script has\n // already run). Skip creating the policy, as this will only cause errors\n // if TT are enforced.\n console.warn('TrustedTypes policy ' + policyName + ' could not be created.');\n return null;\n }\n};\nconst _createHooksMap = function _createHooksMap() {\n return {\n afterSanitizeAttributes: [],\n afterSanitizeElements: [],\n afterSanitizeShadowDOM: [],\n beforeSanitizeAttributes: [],\n beforeSanitizeElements: [],\n beforeSanitizeShadowDOM: [],\n uponSanitizeAttribute: [],\n uponSanitizeElement: [],\n uponSanitizeShadowNode: []\n };\n};\n/**\n * Resolve a set-valued configuration option: a fresh set built from\n * cfg[key] when it is an own array property (seeded with a clone of\n * options.base when given, case-normalized via options.transform),\n * the fallback set otherwise.\n *\n * @param cfg the cloned, prototype-free configuration object\n * @param key the configuration property to read\n * @param fallback the set to use when the option is absent or not an array\n * @param options transform and optional base set to merge into\n * @returns the resolved set\n */\nconst _resolveSetOption = function _resolveSetOption(cfg, key, fallback, options) {\n return objectHasOwnProperty(cfg, key) && arrayIsArray(cfg[key]) ? addToSet(options.base ? clone(options.base) : {}, cfg[key], options.transform) : fallback;\n};\nfunction createDOMPurify() {\n let window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();\n const DOMPurify = root => createDOMPurify(root);\n DOMPurify.version = '3.4.12';\n DOMPurify.removed = [];\n if (!window || !window.document || window.document.nodeType !== NODE_TYPE.document || !window.Element) {\n // Not running in a browser, provide a factory function\n // so that you can pass your own Window\n DOMPurify.isSupported = false;\n return DOMPurify;\n }\n let document = window.document;\n const originalDocument = document;\n const currentScript = originalDocument.currentScript;\n window.DocumentFragment;\n const HTMLTemplateElement = window.HTMLTemplateElement,\n Node = window.Node,\n Element = window.Element,\n NodeFilter = window.NodeFilter,\n _window$NamedNodeMap = window.NamedNodeMap;\n _window$NamedNodeMap === void 0 ? window.NamedNodeMap || window.MozNamedAttrMap : _window$NamedNodeMap;\n window.HTMLFormElement;\n const DOMParser = window.DOMParser,\n trustedTypes = window.trustedTypes;\n const ElementPrototype = Element.prototype;\n const cloneNode = lookupGetter(ElementPrototype, 'cloneNode');\n const remove = lookupGetter(ElementPrototype, 'remove');\n const getNextSibling = lookupGetter(ElementPrototype, 'nextSibling');\n const getChildNodes = lookupGetter(ElementPrototype, 'childNodes');\n const getParentNode = lookupGetter(ElementPrototype, 'parentNode');\n const getShadowRoot = lookupGetter(ElementPrototype, 'shadowRoot');\n const getAttributes = lookupGetter(ElementPrototype, 'attributes');\n const getNodeType = Node && Node.prototype ? lookupGetter(Node.prototype, 'nodeType') : null;\n const getNodeName = Node && Node.prototype ? lookupGetter(Node.prototype, 'nodeName') : null;\n // As per issue #47, the web-components registry is inherited by a\n // new document created via createHTMLDocument. As per the spec\n // (http://w3c.github.io/webcomponents/spec/custom/#creating-and-passing-registries)\n // a new empty registry is used when creating a template contents owner\n // document, so we use that as our parent document to ensure nothing\n // is inherited.\n if (typeof HTMLTemplateElement === 'function') {\n const template = document.createElement('template');\n if (template.content && template.content.ownerDocument) {\n document = template.content.ownerDocument;\n }\n }\n let trustedTypesPolicy;\n let emptyHTML = '';\n // The instance's own internal Trusted Types policy. Unlike a caller-supplied\n // `TRUSTED_TYPES_POLICY`, this is created at most once — Trusted Types throws\n // on duplicate policy names — and is the only policy allowed to persist\n // across configurations and survive `clearConfig()`.\n let defaultTrustedTypesPolicy;\n let defaultTrustedTypesPolicyResolved = false;\n // Tracks whether we are already inside a call to the configured Trusted Types\n // policy (`createHTML` or `createScriptURL`). If a supplied policy callback\n // itself calls `DOMPurify.sanitize` (the cause of #1422), `sanitize` would\n // re-enter the policy and recurse until the stack overflows. We detect that\n // re-entry and throw a clear, actionable error instead. The guard is shared\n // across both callbacks, because either one re-entering `sanitize` triggers\n // the same unbounded recursion.\n let IN_TRUSTED_TYPES_POLICY = 0;\n const _assertNotInTrustedTypesPolicy = function _assertNotInTrustedTypesPolicy() {\n if (IN_TRUSTED_TYPES_POLICY > 0) {\n throw typeErrorCreate('A configured TRUSTED_TYPES_POLICY callback (createHTML or ' + 'createScriptURL) must not call DOMPurify.sanitize, as that causes ' + 'infinite recursion. Do not pass a policy whose callbacks wrap ' + 'DOMPurify as TRUSTED_TYPES_POLICY; see the \"DOMPurify and Trusted ' + 'Types\" section of the README.');\n }\n };\n const _createTrustedHTML = function _createTrustedHTML(html) {\n _assertNotInTrustedTypesPolicy();\n IN_TRUSTED_TYPES_POLICY++;\n try {\n return trustedTypesPolicy.createHTML(html);\n } finally {\n IN_TRUSTED_TYPES_POLICY--;\n }\n };\n const _createTrustedScriptURL = function _createTrustedScriptURL(scriptUrl) {\n _assertNotInTrustedTypesPolicy();\n IN_TRUSTED_TYPES_POLICY++;\n try {\n return trustedTypesPolicy.createScriptURL(scriptUrl);\n } finally {\n IN_TRUSTED_TYPES_POLICY--;\n }\n };\n // Lazily resolve (and cache) the instance's internal default policy.\n // Resolution is attempted at most once: a successful `createPolicy` cannot be\n // repeated (Trusted Types throws on duplicate names), and a failed or\n // unsupported attempt must not be retried on every parse.\n const _getDefaultTrustedTypesPolicy = function _getDefaultTrustedTypesPolicy() {\n if (!defaultTrustedTypesPolicyResolved) {\n defaultTrustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, currentScript);\n defaultTrustedTypesPolicyResolved = true;\n }\n return defaultTrustedTypesPolicy;\n };\n const _document = document,\n implementation = _document.implementation,\n createNodeIterator = _document.createNodeIterator,\n createDocumentFragment = _document.createDocumentFragment,\n getElementsByTagName = _document.getElementsByTagName;\n const importNode = originalDocument.importNode;\n let hooks = _createHooksMap();\n /**\n * Expose whether this browser supports running the full DOMPurify.\n */\n DOMPurify.isSupported = typeof entries === 'function' && typeof getParentNode === 'function' && implementation && implementation.createHTMLDocument !== undefined;\n const MUSTACHE_EXPR$1 = MUSTACHE_EXPR,\n ERB_EXPR$1 = ERB_EXPR,\n TMPLIT_EXPR$1 = TMPLIT_EXPR,\n DATA_ATTR$1 = DATA_ATTR,\n ARIA_ATTR$1 = ARIA_ATTR,\n IS_SCRIPT_OR_DATA$1 = IS_SCRIPT_OR_DATA,\n ATTR_WHITESPACE$1 = ATTR_WHITESPACE,\n CUSTOM_ELEMENT$1 = CUSTOM_ELEMENT;\n let IS_ALLOWED_URI$1 = IS_ALLOWED_URI;\n /**\n * We consider the elements and attributes below to be safe. Ideally\n * don't add any new ones but feel free to remove unwanted ones.\n */\n /* allowed element names */\n let ALLOWED_TAGS = null;\n const DEFAULT_ALLOWED_TAGS = addToSet({}, [...html$1, ...svg$1, ...svgFilters, ...mathMl$1, ...text]);\n /* Allowed attribute names */\n let ALLOWED_ATTR = null;\n const DEFAULT_ALLOWED_ATTR = addToSet({}, [...html, ...svg, ...mathMl, ...xml]);\n /*\n * Configure how DOMPurify should handle custom elements and their attributes as well as customized built-in elements.\n * @property {RegExp|Function|null} tagNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any custom elements)\n * @property {RegExp|Function|null} attributeNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any attributes not on the allow list)\n * @property {boolean} allowCustomizedBuiltInElements allow custom elements derived from built-ins if they pass CUSTOM_ELEMENT_HANDLING.tagNameCheck. Default: `false`.\n */\n let CUSTOM_ELEMENT_HANDLING = Object.seal(create(null, {\n tagNameCheck: {\n writable: true,\n configurable: false,\n enumerable: true,\n value: null\n },\n attributeNameCheck: {\n writable: true,\n configurable: false,\n enumerable: true,\n value: null\n },\n allowCustomizedBuiltInElements: {\n writable: true,\n configurable: false,\n enumerable: true,\n value: false\n }\n }));\n /* Explicitly forbidden tags (overrides ALLOWED_TAGS/ADD_TAGS) */\n let FORBID_TAGS = null;\n /* Explicitly forbidden attributes (overrides ALLOWED_ATTR/ADD_ATTR) */\n let FORBID_ATTR = null;\n /* Config object to store ADD_TAGS/ADD_ATTR functions (when used as functions) */\n const EXTRA_ELEMENT_HANDLING = Object.seal(create(null, {\n tagCheck: {\n writable: true,\n configurable: false,\n enumerable: true,\n value: null\n },\n attributeCheck: {\n writable: true,\n configurable: false,\n enumerable: true,\n value: null\n }\n }));\n /* Decide if ARIA attributes are okay */\n let ALLOW_ARIA_ATTR = true;\n /* Decide if custom data attributes are okay */\n let ALLOW_DATA_ATTR = true;\n /* Decide if unknown protocols are okay */\n let ALLOW_UNKNOWN_PROTOCOLS = false;\n /* Decide if self-closing tags in attributes are allowed.\n * Usually removed due to a mXSS issue in jQuery 3.0 */\n let ALLOW_SELF_CLOSE_IN_ATTR = true;\n /* Output should be safe for common template engines.\n * This means, DOMPurify removes data attributes, mustaches and ERB\n */\n let SAFE_FOR_TEMPLATES = false;\n /* Output should be safe even for XML used within HTML and alike.\n * This means, DOMPurify removes comments when containing risky content.\n */\n let SAFE_FOR_XML = true;\n /* Decide if document with ... should be returned */\n let WHOLE_DOCUMENT = false;\n /* Track whether config is already set on this instance of DOMPurify. */\n let SET_CONFIG = false; SPDX-FileCopyrightText: 2025, 2022-2024 Nextcloud GmbH and Nextcloud contributors\n */\nimport { getRequestToken, onRequestTokenUpdate } from '@nextcloud/auth';\nimport Axios from 'axios';\n/**\n * Get an Axios instance with default Nextcloud headers and CSRF token handling.\n */\nexport function getCancelableClient() {\n const client = Axios.create({\n headers: {\n requesttoken: getRequestToken() ?? '',\n 'X-Requested-With': 'XMLHttpRequest',\n },\n });\n onRequestTokenUpdate((token) => {\n client.defaults.headers.requesttoken = token;\n });\n return Object.assign(client, {\n CancelToken: Axios.CancelToken,\n isCancel: Axios.isCancel,\n });\n}\n","/**\n * SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: GPL-3.0-or-later\n */\nimport { fetchRequestToken } from '@nextcloud/auth';\nimport { isAxiosError } from 'axios';\nconst RETRY_KEY = '_nextcloudCsrfTokenReloaded';\n/**\n * Handle CSRF token errors in Axios requests.\n *\n * @param axios - The axios instance the interceptor is attached to\n */\nexport function onCsrfTokenError(axios) {\n return async (error) => {\n if (!isAxiosError(error)) {\n throw error;\n }\n const { config, response, request } = error;\n const responseURL = request?.responseURL;\n if (config\n && !(RETRY_KEY in config)\n && response?.status === 412\n && response?.data?.message === 'CSRF check failed') {\n console.warn(`Request to ${responseURL} failed because of a CSRF mismatch. Fetching a new token.`);\n const token = await fetchRequestToken();\n axios.defaults.headers.requesttoken = token;\n return axios({\n SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors SPDX-FileCopyrightText: 2026, 1000, 2026, 2026, 1000, 2026, 2026, 2026, 2026 Nextcloud GmbH and Nextcloud contributors\r\n - SPDX-License-Identifier: AGPL-3.0-or-later\r\n-->\r\n\r\n\r\n\r\n\r\n\r\n","\r\n\r\n\r\n\r\n\r\n\r\n","/**\r\n * SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors\r\n * SPDX-License-Identifier: AGPL-3.0-or-later\r\n */\r\n\r\nexport type Grade = 'A' | 'B' | 'C' | 'D' | 'F'\r\n\r\nexport type MascotState = 'happy' | 'idle' | 'concerned' | 'checking'\r\n\r\n/**\r\n * Derive a grade letter from a numeric 0-100 score. Mirrors the\r\n * server-side {@see \\OCA\\DBDoctor\\Service\\Score::gradeFor} so\r\n * client-side fallbacks and server responses agree.\r\n *\r\n * @param score\r\n */\r\nexport function gradeFor(score: number): Grade {\r\n\tif (score >= 90) { return 'A' }\r\n\tif (score >= 80) { return 'B' }\r\n\tif (score >= 70) { return 'C' }\r\n\tif (score >= 60) { return 'D' }\r\n\treturn 'F'\r\n}\r\n\r\n/**\r\n * The CSS custom-property used to colour the score / heartbeat for\r\n * a given grade. Indirection through CSS variables keeps the\r\n * grade colours editable in tokens.scss.\r\n *\r\n * @param grade\r\n */\r\nexport function colorVarFor(grade: Grade): string {\r\n\treturn {\r\n\t\tA: 'var(--dbd-grade-a)',\r\n\t\tB: 'var(--dbd-grade-b)',\r\n\t\tC: 'var(--dbd-grade-c)',\r\n\t\tD: 'var(--dbd-grade-d)',\r\n\t\tF: 'var(--dbd-grade-f)',\r\n\t}[grade]\r\n}\r\n\r\n/**\r\n * Readable variant of the grade colour. The raw palette is tuned for\r\n * accents (tints, strokes, dots); as actual text on card surfaces it\r\n * can fall below AA — most visibly the dark-red F on a dark theme.\r\n * These variants are blended with the theme's main text colour in\r\n * tokens.scss so they stay legible on both light and dark surfaces.\r\n *\r\n * @param grade\r\n */\r\nexport function readableColorVarFor(grade: Grade): string {\r\n\treturn {\r\n\t\tA: 'var(--dbd-grade-a-readable)',\r\n\t\tB: 'var(--dbd-grade-b-readable)',\r\n\t\tC: 'var(--dbd-grade-c-readable)',\r\n\t\tD: 'var(--dbd-grade-d-readable)',\r\n\t\tF: 'var(--dbd-grade-f-readable)',\r\n\t}[grade]\r\n}\r\n\r\n/**\r\n * Beats per minute used by the Heartbeat component. The worse the\r\n * grade, the faster (and more alarming) the heartbeat — a soft visual\r\n * metaphor that doesn't fight the data.\r\n *\r\n * @param grade\r\n */\r\nexport function bpmFor(grade: Grade): number {\r\n\treturn { A: 60, B: 75, C: 90, D: 110, F: 130 }[grade]\r\n}\r\n\r\n/**\r\n * Beats per minute as a function of *live database latency*. Used\r\n * by the Heartbeat when a smoothed latency reading is available — a\r\n * snappy database makes the mascot's heart slow + calm, a struggling\r\n * one makes it race.\r\n *\r\n * Curve:\r\n * - 0 ms → 50 BPM (resting calm)\r\n * - 1 ms → 60 BPM\r\n * - 10 ms → 80 BPM (alert)\r\n * - 100 ms → 110 BPM (stressed)\r\n * - ms → 140 BPM (alarmed)\r\n *\r\n * The shape is `50 + 30 * log10(ms + 1)` clamped to [50, 160]. log10\r\n * keeps the response sane across the multi-decade range we care about\r\n * (sub-millisecond local DBs through hundreds-of-ms remote).\r\n *\r\n * @param latencyMs\r\n */\r\nexport function bpmForLatency(latencyMs: number): number {\r\n\tif (!Number.isFinite(latencyMs) || latencyMs < 0) { return 60 }\r\n\tconst bpm = 50 + 30 * Math.log10(latencyMs + 1)\r\n\treturn Math.max(50, Math.min(160, bpm))\r\n}\r\n\r\n/**\r\n * Mascot expression for a given grade + running state. When a check\r\n * is running we always show the \"checking\" mascot so the user gets\r\n * immediate feedback that something's happening.\r\n *\r\n * @param grade\r\n * @param running\r\n */\r\nexport function mascotFor(grade: Grade | null, running: boolean): MascotState {\r\n\tif (running) { return 'checking' }\r\n\tif (grade === null) { return 'idle' }\r\n\tif (grade === 'A' || grade === 'B') { return 'happy' }\r\n\tif (grade === 'F') { return 'concerned' }\r\n\treturn 'idle'\r\n}\r\n","\r\n\r\n\r\n\r\n\r\n\r\n","/**\r\n * SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors\r\n * SPDX-License-Identifier: AGPL-3.0-or-later\r\n */\r\n\r\nimport type { RunResult, SeriesPoint } from '../api/types'\r\n\r\nimport { defineStore } from 'pinia'\r\nimport { computed, ref } from 'vue'\r\nimport * as api from '../api/client'\r\nimport logger from '../utils/logger'\r\n\r\n/**\r\n * Store for the dashboard's main check data.\r\n *\r\n * Holds the most-recent RunResult, a per-rule history series cache\r\n * (lazily filled when a card expands), and a \"celebrate\" flag the\r\n * confetti overlay listens to. We deliberately keep this store\r\n * narrow — settings live in their own store.\r\n */\r\nexport const useChecksStore = defineStore('dbdoctor/checks', () => {\r\n\tconst latest = ref(null)\r\n\tconst running = ref(false)\r\n\tconst error = ref(null)\r\n\tconst ruleSeries = ref>({})\r\n\t// Toggled true for one frame after a fresh A grade is achieved\r\n\t// so ConfettiOverlay can mount and immediately consume it.\r\n\tconst celebrate = ref(false)\r\n\r\n\tconst grade = computed(() => latest.value?.grade ?? null)\r\n\r\n\tasync function fetchLatest(): Promise {\r\n\t\ttry {\r\n\t\t\tlatest.value = await api.getLatest()\r\n\t\t\terror.value = null\r\n\t\t} catch (e) {\r\n\t\t\terror.value = (e as Error).message ?? 'Could not load latest run.'\r\n\t\t\tlogger.error('fetchLatest failed', e)\r\n\t\t}\r\n\t}\r\n\r\n\tasync function runNow(): Promise {\r\n\t\tif (running.value) { return }\r\n\t\trunning.value = true\r\n\t\terror.value = null\r\n\t\tconst previousGrade = latest.value?.grade ?? null\r\n\t\ttry {\r\n\t\t\tconst next = await api.runCheck()\r\n\t\t\tlatest.value = next\r\n\t\t\t// Celebrate when the user just earned an A — but not\r\n\t\t\t// every load on a server that's already at A.\r\n\t\t\tif (next.grade === 'A' && previousGrade !== 'A') {\r\n\t\t\t\tcelebrate.value = true\r\n\t\t\t}\r\n\t\t} catch (e) {\r\n\t\t\terror.value = (e as Error).message ?? 'Check run failed.'\r\n\t\t\tlogger.error('runNow failed', e)\r\n\t\t} finally {\r\n\t\t\trunning.value = false\r\n\t\t}\r\n\t}\r\n\r\n\tfunction consumeCelebrate(): void {\r\n\t\tcelebrate.value = false\r\n\t}\r\n\r\n\tasync function loadSeries(ruleId: string, days: number = 30): Promise {\r\n\t\ttry {\r\n\t\t\truleSeries.value = {\r\n\t\t\t\t...ruleSeries.value,\r\n\t\t\t\t[ruleId]: await api.getHistory(ruleId, days),\r\n\t\t\t}\r\n\t\t} catch (e) {\r\n\t\t\tlogger.warn(`history load failed for ${ruleId}`, e)\r\n\t\t}\r\n\t}\r\n\r\n\tasync function applyAndRefresh(\r\n\t\truleId: string,\r\n\t\tvariable: string,\r\n\t\tvalue: string,\r\n\t): Promise<{ success: boolean, oldValue: string | null, newValue: string | null, error?: string }> {\r\n\t\tconst result = await api.applyChange(ruleId, variable, value)\r\n\t\tif (result.success) {\r\n\t\t\t// Re-run so the score reflects the change. We don't await\r\n\t\t\t// this aggressively — the dialog has already shown the\r\n\t\t\t// outcome by the time this resolves.\r\n\t\t\tvoid runNow()\r\n\t\t}\r\n\t\treturn result\r\n\t}\r\n\r\n\treturn {\r\n\t\t// state\r\n\t\tlatest,\r\n\t\trunning,\r\n\t\terror,\r\n\t\truleSeries,\r\n\t\tcelebrate,\r\n\t\t// derived\r\n\t\tgrade,\r\n\t\t// actions\r\n\t\tfetchLatest,\r\n\t\trunNow,\r\n\t\tloadSeries,\r\n\t\tapplyAndRefresh,\r\n\t\tconsumeCelebrate,\r\n\t}\r\n})\r\n","\r\n\r\n\r\n\r\n\r\n\r\n","\r\n\r\n\r\n\r\n\r\n\r\n","import { createApp } from \"vue\";\nfunction spawnDialog(dialog, props = {}, options = {}) {\n let { container } = options;\n if (\"container\" in props && typeof props.container === \"string\") {\n container ??= props.container;\n }\n const resolvedContainer = typeof container === \"string\" && document.querySelector(container) || document.body;\n const element = resolvedContainer.appendChild(document.createElement(\"div\"));\n return new Promise((resolve, reject) => {\n const app = createApp(dialog, {\n ...props,\n // If dialog has no `container` prop passing a falsy value does nothing\n // Otherwise it is expected that `null` disables teleport and mounts dialog in place like NcDialog/NcModal\n container: null,\n onClose(...rest) {\n const payload = rest.length > 1 ? rest : rest[0];\n app.unmount();\n element.remove();\n resolve(payload);\n },\n \"onVue:unmounted\": () => {\n app.unmount();\n element.remove();\n reject(new Error(\"Dialog was unmounted without close event\"));\n }\n });\n app.mount(element);\n });\n}\nexport {\n spawnDialog\n};\n//# sourceMappingURL=index.mjs.map\n","import { a as getLanguage, e as getPlural, t as translate, d as translatePlural } from \"./chunks/translation-DoG5ZELJ.mjs\";\n/*!\n * SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: GPL-3.0-or-later\n */\nclass GettextWrapper {\n bundle;\n constructor(pluralFunction) {\n this.bundle = {\n pluralFunction,\n translations: {}\n };\n }\n /**\n * Append new translations to the wrapper.\n *\n * This is useful if translations should be added on demand,\n * e.g. depending on component usage.\n *\n * @param bundle - The new translation bundle to append\n */\n addTranslations(bundle) {\n const dict = Object.values(bundle.translations[\"\"] ?? {}).map(({ msgid, msgid_plural: msgidPlural, msgstr }) => {\n if (msgidPlural !== void 0) {\n return [`_${msgid}_::_${msgidPlural}_`, msgstr];\n }\n return [msgid, msgstr[0]];\n });\n this.bundle.translations = {\n ...this.bundle.translations,\n ...Object.fromEntries(dict)\n };\n }\n /**\n * Get translated string (singular form), optionally with placeholders\n *\n * @param original original string to translate\n * @param placeholders map of placeholder key to value\n */\n gettext(original, placeholders = {}) {\n return translate(\"\", original, placeholders, void 0, { bundle: this.bundle });\n }\n /**\n * Get translated string with plural forms\n *\n * @param singular Singular text form\n * @param plural Plural text form to be used if `count` requires it\n * @param count The number to insert into the text\n * @param placeholders optional map of placeholder key to value\n */\n ngettext(singular, plural, count, placeholders = {}) {\n return translatePlural(\"\", singular, plural, count, placeholders, { bundle: this.bundle });\n }\n}\nclass GettextBuilder {\n debug = false;\n language = \"en\";\n translations = {};\n setLanguage(language) {\n this.language = language;\n return this;\n }\n /**\n * Try to detect locale from context with `en` as fallback value\n * This only works within a Nextcloud page context.\n *\n * @deprecated use `detectLanguage` instead.\n */\n detectLocale() {\n return this.detectLanguage();\n }\n /**\n * Try to detect locale from context with `en` as fallback value.\n * This only works within a Nextcloud page context.\n */\n detectLanguage() {\n return this.setLanguage(getLanguage().replace(\"-\", \"_\"));\n }\n /**\n * Register a new translation bundle for a specified language.\n *\n * Please note that existing translations for that language will be overwritten.\n *\n * @param language - Language this is the translation for\n * @param data - The translation bundle\n */\n addTranslation(language, data) {\n this.translations[language] = data;\n return this;\n }\n enableDebugMode() {\n this.debug = true;\n return this;\n }\n build() {\n if (this.debug) {\n console.debug(`Creating gettext instance for language ${this.language}`);\n }\n const wrapper = new GettextWrapper((n) => getPlural(n, this.language));\n if (this.language in this.translations) {\n wrapper.addTranslations(this.translations[this.language]);\n }\n return wrapper;\n }\n}\nfunction getGettextBuilder() {\n return new GettextBuilder();\n}\nexport {\n getGettextBuilder\n};\n//# sourceMappingURL=gettext.mjs.map\n","function getDefaultExportFromCjs (x) {\n\treturn x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;\n}\n\nvar browser = {exports: {}};\n\n// shim for using process in browser\nvar process = browser.exports = {};\n\n// cached from whatever global is present so that test runners that stub it\n// don't break things. But we need to wrap it in a try catch in case it is\n// wrapped in strict mode code which doesn't define any globals. It's inside a\n// function because try/catches deoptimize in certain engines.\n\nvar cachedSetTimeout;\nvar cachedClearTimeout;\n\nfunction defaultSetTimout() {\n throw new Error('setTimeout has not been defined');\n}\nfunction defaultClearTimeout () {\n throw new Error('clearTimeout has not been defined');\n}\n(function () {\n try {\n if (typeof setTimeout === 'function') {\n cachedSetTimeout = setTimeout;\n } else {\n cachedSetTimeout = defaultSetTimout;\n }\n } catch (e) {\n cachedSetTimeout = defaultSetTimout;\n }\n try {\n if (typeof clearTimeout === 'function') {\n cachedClearTimeout = clearTimeout;\n } else {\n cachedClearTimeout = defaultClearTimeout;\n }\n } catch (e) {\n cachedClearTimeout = defaultClearTimeout;\n }\n} ());\nfunction runTimeout(fun) {\n if (cachedSetTimeout === setTimeout) {\n //normal enviroments in sane situations\n return setTimeout(fun, 0);\n }\n // if setTimeout wasn't available but was latter defined\n if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {\n cachedSetTimeout = setTimeout;\n return setTimeout(fun, 0);\n }\n try {\n // when when somebody has screwed with setTimeout but no I.E. maddness\n return cachedSetTimeout(fun, 0);\n } catch(e){\n try {\n // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n return cachedSetTimeout.call(null, fun, 0);\n } catch(e){\n // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error\n return cachedSetTimeout.call(this, fun, 0);\n }\n }\n\n\n}\nfunction runClearTimeout(marker) {\n if (cachedClearTimeout === clearTimeout) {\n //normal enviroments in sane situations\n return clearTimeout(marker);\n }\n // if clearTimeout wasn't available but was latter defined\n if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {\n cachedClearTimeout = clearTimeout;\n return clearTimeout(marker);\n }\n try {\n // when when somebody has screwed with setTimeout but no I.E. maddness\n return cachedClearTimeout(marker);\n } catch (e){\n try {\n // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n return cachedClearTimeout.call(null, marker);\n } catch (e){\n // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.\n // Some versions of I.E. have different rules for clearTimeout vs setTimeout\n return cachedClearTimeout.call(this, marker);\n }\n }\n\n\n\n}\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n if (!draining || !currentQueue) {\n return;\n }\n draining = false;\n if (currentQueue.length) {\n queue = currentQueue.concat(queue);\n } else {\n queueIndex = -1;\n }\n if (queue.length) {\n drainQueue();\n }\n}\n\nfunction drainQueue() {\n if (draining) {\n return;\n }\n var timeout = runTimeout(cleanUpNextTick);\n draining = true;\n\n var len = queue.length;\n while(len) {\n currentQueue = queue;\n queue = [];\n while (++queueIndex < len) {\n if (currentQueue) {\n currentQueue[queueIndex].run();\n }\n }\n queueIndex = -1;\n len = queue.length;\n }\n currentQueue = null;\n draining = false;\n runClearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n var args = new Array(arguments.length - 1);\n if (arguments.length > 1) {\n for (var i = 1; i < arguments.length; i++) {\n args[i - 1] = arguments[i];\n }\n }\n queue.push(new Item(fun, args));\n if (queue.length === 1 && !draining) {\n runTimeout(drainQueue);\n }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n this.fun = fun;\n this.array = array;\n}\nItem.prototype.run = function () {\n this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\nprocess.prependListener = noop;\nprocess.prependOnceListener = noop;\n\nprocess.listeners = function (name) { return [] };\n\nprocess.binding = function (name) {\n throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\nvar browserExports = browser.exports;\nconst process$1 = /*@__PURE__*/getDefaultExportFromCjs(browserExports);\n\nexport { process$1 as default, process$1 as process };\n//# sourceMappingURL=index.js.map\n","'use strict'\n\nconst debug = (\n typeof process === 'object' &&\n process.env &&\n process.env.NODE_DEBUG &&\n /\\bsemver\\b/i.test(process.env.NODE_DEBUG)\n) ? (...args) => console.error('SEMVER', ...args)\n : () => {}\n\nmodule.exports = debug\n","'use strict'\n\n// Note: this is the semver.org version of the spec that it implements\n// Not necessarily the package version of this code.\nconst SEMVER_SPEC_VERSION = '2.0.0'\n\nconst MAX_LENGTH = 256\nconst MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER ||\n/* istanbul ignore next */ 9007199254740991\n\n// Max safe segment length for coercion.\nconst MAX_SAFE_COMPONENT_LENGTH = 16\n\n// Max safe length for a build identifier. The max length minus 6 characters for\n// the shortest version with a build 0.0.0+BUILD.\nconst MAX_SAFE_BUILD_LENGTH = MAX_LENGTH - 6\n\nconst RELEASE_TYPES = [\n 'major',\n 'premajor',\n 'minor',\n 'preminor',\n 'patch',\n 'prepatch',\n 'prerelease',\n]\n\nmodule.exports = {\n MAX_LENGTH,\n MAX_SAFE_COMPONENT_LENGTH,\n MAX_SAFE_BUILD_LENGTH,\n MAX_SAFE_INTEGER,\n RELEASE_TYPES,\n SEMVER_SPEC_VERSION,\n FLAG_INCLUDE_PRERELEASE: 0b001,\n FLAG_LOOSE: 0b010,\n}\n","'use strict'\n\nconst {\n MAX_SAFE_COMPONENT_LENGTH,\n MAX_SAFE_BUILD_LENGTH,\n MAX_LENGTH,\n} = require('./constants')\nconst debug = require('./debug')\nexports = module.exports = {}\n\n// The actual regexps go on exports.re\nconst re = exports.re = []\nconst safeRe = exports.safeRe = []\nconst src = exports.src = []\nconst safeSrc = exports.safeSrc = []\nconst t = exports.t = {}\nlet R = 0\n\nconst LETTERDASHNUMBER = '[a-zA-Z0-9-]'\n\n// Replace some greedy regex tokens to prevent regex dos issues. These regex are\n// used internally via the safeRe object since all inputs in this library get\n// normalized first to trim and collapse all extra whitespace. The original\n// regexes are exported for userland consumption and lower level usage. A\n// future breaking change could export the safer regex only with a note that\n// all input should have extra whitespace removed.\nconst safeRegexReplacements = [\n ['\\\\s', 1],\n ['\\\\d', MAX_LENGTH],\n [LETTERDASHNUMBER, MAX_SAFE_BUILD_LENGTH],\n]\n\nconst makeSafeRegex = (value) => {\n for (const [token, max] of safeRegexReplacements) {\n value = value\n .split(`${token}*`).join(`${token}{0,${max}}`)\n .split(`${token}+`).join(`${token}{1,${max}}`)\n }\n return value\n}\n\nconst createToken = (name, value, isGlobal) => {\n const safe = makeSafeRegex(value)\n const index = R++\n debug(name, index, value)\n t[name] = index\n src[index] = value\n safeSrc[index] = safe\n re[index] = new RegExp(value, isGlobal ? 'g' : undefined)\n safeRe[index] = new RegExp(safe, isGlobal ? 'g' : undefined)\n}\n\n// The following Regular Expressions can be used for tokenizing,\n// validating, and parsing SemVer version strings.\n\n// ## Numeric Identifier\n// A single `0`, or a non-zero digit followed by zero or more digits.\n\ncreateToken('NUMERICIDENTIFIER', '0|[1-9]\\\\d*')\ncreateToken('NUMERICIDENTIFIERLOOSE', '\\\\d+')\n\n// ## Non-numeric Identifier\n// Zero or more digits, followed by a letter or hyphen, and then zero or\n// more letters, digits, or hyphens.\n\ncreateToken('NONNUMERICIDENTIFIER', `\\\\d*[a-zA-Z-]${LETTERDASHNUMBER}*`)\n\n// ## Main Version\n// Three dot-separated numeric identifiers.\n\ncreateToken('MAINVERSION', `(${src[t.NUMERICIDENTIFIER]})\\\\.` +\n `(${src[t.NUMERICIDENTIFIER]})\\\\.` +\n `(${src[t.NUMERICIDENTIFIER]})`)\n\ncreateToken('MAINVERSIONLOOSE', `(${src[t.NUMERICIDENTIFIERLOOSE]})\\\\.` +\n `(${src[t.NUMERICIDENTIFIERLOOSE]})\\\\.` +\n `(${src[t.NUMERICIDENTIFIERLOOSE]})`)\n\n// ## Pre-release Version Identifier\n// A numeric identifier, or a non-numeric identifier.\n// Non-numeric identifiers include numeric identifiers but can be longer.\n// Therefore non-numeric identifiers must go first.\n\ncreateToken('PRERELEASEIDENTIFIER', `(?:${src[t.NONNUMERICIDENTIFIER]\n}|${src[t.NUMERICIDENTIFIER]})`)\n\ncreateToken('PRERELEASEIDENTIFIERLOOSE', `(?:${src[t.NONNUMERICIDENTIFIER]\n}|${src[t.NUMERICIDENTIFIERLOOSE]})`)\n\n// ## Pre-release Version\n// Hyphen, followed by one or more dot-separated pre-release version\n// identifiers.\n\ncreateToken('PRERELEASE', `(?:-(${src[t.PRERELEASEIDENTIFIER]\n}(?:\\\\.${src[t.PRERELEASEIDENTIFIER]})*))`)\n\ncreateToken('PRERELEASELOOSE', `(?:-?(${src[t.PRERELEASEIDENTIFIERLOOSE]\n}(?:\\\\.${src[t.PRERELEASEIDENTIFIERLOOSE]})*))`)\n\n// ## Build Metadata Identifier\n// Any combination of digits, letters, or hyphens.\n\ncreateToken('BUILDIDENTIFIER', `${LETTERDASHNUMBER}+`)\n\n// ## Build Metadata\n// Plus sign, followed by one or more period-separated build metadata\n// identifiers.\n\ncreateToken('BUILD', `(?:\\\\+(${src[t.BUILDIDENTIFIER]\n}(?:\\\\.${src[t.BUILDIDENTIFIER]})*))`)\n\n// ## Full Version String\n// A main version, followed optionally by a pre-release version and\n// build metadata.\n\n// Note that the only major, minor, patch, and pre-release sections of\n// the version string are capturing groups. The build metadata is not a\n// capturing group, because it should not ever be used in version\n// comparison.\n\ncreateToken('FULLPLAIN', `v?${src[t.MAINVERSION]\n}${src[t.PRERELEASE]}?${\n src[t.BUILD]}?`)\n\ncreateToken('FULL', `^${src[t.FULLPLAIN]}$`)\n\n// like full, but allows v1.2.3 and =1.2.3, which people do sometimes.\n// also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty\n// common in the npm registry.\ncreateToken('LOOSEPLAIN', `[v=\\\\s]*${src[t.MAINVERSIONLOOSE]\n}${src[t.PRERELEASELOOSE]}?${\n src[t.BUILD]}?`)\n\ncreateToken('LOOSE', `^${src[t.LOOSEPLAIN]}$`)\n\ncreateToken('GTLT', '((?:<|>)?=?)')\n\n// Something like \"2.*\" or \"1.2.x\".\n// Note that \"x.x\" is a valid xRange identifier, meaning \"any version\"\n// Only the first item is strictly required.\ncreateToken('XRANGEIDENTIFIERLOOSE', `${src[t.NUMERICIDENTIFIERLOOSE]}|x|X|\\\\*`)\ncreateToken('XRANGEIDENTIFIER', `${src[t.NUMERICIDENTIFIER]}|x|X|\\\\*`)\n\ncreateToken('XRANGEPLAIN', `[v=\\\\s]*(${src[t.XRANGEIDENTIFIER]})` +\n `(?:\\\\.(${src[t.XRANGEIDENTIFIER]})` +\n `(?:\\\\.(${src[t.XRANGEIDENTIFIER]})` +\n `(?:${src[t.PRERELEASE]})?${\n src[t.BUILD]}?` +\n `)?)?`)\n\ncreateToken('XRANGEPLAINLOOSE', `[v=\\\\s]*(${src[t.XRANGEIDENTIFIERLOOSE]})` +\n `(?:\\\\.(${src[t.XRANGEIDENTIFIERLOOSE]})` +\n `(?:\\\\.(${src[t.XRANGEIDENTIFIERLOOSE]})` +\n `(?:${src[t.PRERELEASELOOSE]})?${\n src[t.BUILD]}?` +\n `)?)?`)\n\ncreateToken('XRANGE', `^${src[t.GTLT]}\\\\s*${src[t.XRANGEPLAIN]}$`)\ncreateToken('XRANGELOOSE', `^${src[t.GTLT]}\\\\s*${src[t.XRANGEPLAINLOOSE]}$`)\n\n// Coercion.\n// Extract anything that could conceivably be a part of a valid semver\ncreateToken('COERCEPLAIN', `${'(^|[^\\\\d])' +\n '(\\\\d{1,'}${MAX_SAFE_COMPONENT_LENGTH}})` +\n `(?:\\\\.(\\\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?` +\n `(?:\\\\.(\\\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?`)\ncreateToken('COERCE', `${src[t.COERCEPLAIN]}(?:$|[^\\\\d])`)\ncreateToken('COERCEFULL', src[t.COERCEPLAIN] +\n `(?:${src[t.PRERELEASE]})?` +\n `(?:${src[t.BUILD]})?` +\n `(?:$|[^\\\\d])`)\ncreateToken('COERCERTL', src[t.COERCE], true)\ncreateToken('COERCERTLFULL', src[t.COERCEFULL], true)\n\n// Tilde ranges.\n// Meaning is \"reasonably at or greater than\"\ncreateToken('LONETILDE', '(?:~>?)')\n\ncreateToken('TILDETRIM', `(\\\\s*)${src[t.LONETILDE]}\\\\s+`, true)\nexports.tildeTrimReplace = '$1~'\n\ncreateToken('TILDE', `^${src[t.LONETILDE]}${src[t.XRANGEPLAIN]}$`)\ncreateToken('TILDELOOSE', `^${src[t.LONETILDE]}${src[t.XRANGEPLAINLOOSE]}$`)\n\n// Caret ranges.\n// Meaning is \"at least and backwards compatible with\"\ncreateToken('LONECARET', '(?:\\\\^)')\n\ncreateToken('CARETTRIM', `(\\\\s*)${src[t.LONECARET]}\\\\s+`, true)\nexports.caretTrimReplace = '$1^'\n\ncreateToken('CARET', `^${src[t.LONECARET]}${src[t.XRANGEPLAIN]}$`)\ncreateToken('CARETLOOSE', `^${src[t.LONECARET]}${src[t.XRANGEPLAINLOOSE]}$`)\n\n// A simple gt/lt/eq thing, or just \"\" to indicate \"any version\"\ncreateToken('COMPARATORLOOSE', `^${src[t.GTLT]}\\\\s*(${src[t.LOOSEPLAIN]})$|^$`)\ncreateToken('COMPARATOR', `^${src[t.GTLT]}\\\\s*(${src[t.FULLPLAIN]})$|^$`)\n\n// An expression to strip any whitespace between the gtlt and the thing\n// it modifies, so that `> 1.2.3` ==> `>1.2.3`\ncreateToken('COMPARATORTRIM', `(\\\\s*)${src[t.GTLT]\n}\\\\s*(${src[t.LOOSEPLAIN]}|${src[t.XRANGEPLAIN]})`, true)\nexports.comparatorTrimReplace = '$1$2$3'\n\n// Something like `1.2.3 - 1.2.4`\n// Note that these all use the loose form, because they'll be\n// checked against either the strict or loose comparator form\n// later.\ncreateToken('HYPHENRANGE', `^\\\\s*(${src[t.XRANGEPLAIN]})` +\n `\\\\s+-\\\\s+` +\n `(${src[t.XRANGEPLAIN]})` +\n `\\\\s*$`)\n\ncreateToken('HYPHENRANGELOOSE', `^\\\\s*(${src[t.XRANGEPLAINLOOSE]})` +\n `\\\\s+-\\\\s+` +\n `(${src[t.XRANGEPLAINLOOSE]})` +\n `\\\\s*$`)\n\n// Star ranges basically just allow anything at all.\ncreateToken('STAR', '(<|>)?=?\\\\s*\\\\*')\n// >=0.0.0 is like a star\ncreateToken('GTE0', '^\\\\s*>=\\\\s*0\\\\.0\\\\.0\\\\s*$')\ncreateToken('GTE0PRE', '^\\\\s*>=\\\\s*0\\\\.0\\\\.0-0\\\\s*$')\n","'use strict'\n\n// parse out just the options we care about\nconst looseOption = Object.freeze({ loose: true })\nconst emptyOpts = Object.freeze({ })\nconst parseOptions = options => {\n if (!options) {\n return emptyOpts\n }\n\n if (typeof options !== 'object') {\n return looseOption\n }\n\n return options\n}\nmodule.exports = parseOptions\n","'use strict'\n\nconst numeric = /^[0-9]+$/\nconst compareIdentifiers = (a, b) => {\n if (typeof a === 'number' && typeof b === 'number') {\n return a === b ? 0 : a < b ? -1 : 1\n }\n\n const anum = numeric.test(a)\n const bnum = numeric.test(b)\n\n if (anum && bnum) {\n a = +a\n b = +b\n }\n\n return a === b ? 0\n : (anum && !bnum) ? -1\n : (bnum && !anum) ? 1\n : a < b ? -1\n : 1\n}\n\nconst rcompareIdentifiers = (a, b) => compareIdentifiers(b, a)\n\nmodule.exports = {\n compareIdentifiers,\n rcompareIdentifiers,\n}\n","'use strict'\n\nconst debug = require('../internal/debug')\nconst { MAX_LENGTH, MAX_SAFE_INTEGER } = require('../internal/constants')\nconst { safeRe: re, t } = require('../internal/re')\n\nconst parseOptions = require('../internal/parse-options')\nconst { compareIdentifiers } = require('../internal/identifiers')\n\nconst isPrereleaseIdentifier = (prerelease, identifier) => {\n const identifiers = identifier.split('.')\n if (identifiers.length > prerelease.length) {\n return false\n }\n\n for (let i = 0; i < identifiers.length; i++) {\n if (compareIdentifiers(prerelease[i], identifiers[i]) !== 0) {\n return false\n }\n }\n\n return true\n}\n\nclass SemVer {\n constructor (version, options) {\n options = parseOptions(options)\n\n if (version instanceof SemVer) {\n if (version.loose === !!options.loose &&\n version.includePrerelease === !!options.includePrerelease) {\n return version\n } else {\n version = version.version\n }\n } else if (typeof version !== 'string') {\n throw new TypeError(`Invalid version. Must be a string. Got type \"${typeof version}\".`)\n }\n\n if (version.length > MAX_LENGTH) {\n throw new TypeError(\n `version is longer than ${MAX_LENGTH} characters`\n )\n }\n\n debug('SemVer', version, options)\n this.options = options\n this.loose = !!options.loose\n // this isn't actually relevant for versions, but keep it so that we\n // don't run into trouble passing this.options around.\n this.includePrerelease = !!options.includePrerelease\n\n const m = version.trim().match(options.loose ? re[t.LOOSE] : re[t.FULL])\n\n if (!m) {\n throw new TypeError(`Invalid Version: ${version}`)\n }\n\n this.raw = version\n\n // these are actually numbers\n this.major = +m[1]\n this.minor = +m[2]\n this.patch = +m[3]\n\n if (this.major > MAX_SAFE_INTEGER || this.major < 0) {\n throw new TypeError('Invalid major version')\n }\n\n if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) {\n throw new TypeError('Invalid minor version')\n }\n\n if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) {\n throw new TypeError('Invalid patch version')\n }\n\n // numberify any prerelease numeric ids\n if (!m[4]) {\n this.prerelease = []\n } else {\n this.prerelease = m[4].split('.').map((id) => {\n if (/^[0-9]+$/.test(id)) {\n const num = +id\n if (num >= 0 && num < MAX_SAFE_INTEGER) {\n return num\n }\n }\n return id\n })\n }\n\n this.build = m[5] ? m[5].split('.') : []\n this.format()\n }\n\n format () {\n this.version = `${this.major}.${this.minor}.${this.patch}`\n if (this.prerelease.length) {\n this.version += `-${this.prerelease.join('.')}`\n }\n return this.version\n }\n\n toString () {\n return this.version\n }\n\n compare (other) {\n debug('SemVer.compare', this.version, this.options, other)\n if (!(other instanceof SemVer)) {\n if (typeof other === 'string' && other === this.version) {\n return 0\n }\n other = new SemVer(other, this.options)\n }\n\n if (other.version === this.version) {\n return 0\n }\n\n return this.compareMain(other) || this.comparePre(other)\n }\n\n compareMain (other) {\n if (!(other instanceof SemVer)) {\n other = new SemVer(other, this.options)\n }\n\n if (this.major < other.major) {\n return -1\n }\n if (this.major > other.major) {\n return 1\n }\n if (this.minor < other.minor) {\n return -1\n }\n if (this.minor > other.minor) {\n return 1\n }\n if (this.patch < other.patch) {\n return -1\n }\n if (this.patch > other.patch) {\n return 1\n }\n return 0\n }\n\n comparePre (other) {\n if (!(other instanceof SemVer)) {\n other = new SemVer(other, this.options)\n }\n\n // NOT having a prerelease is > having one\n if (this.prerelease.length && !other.prerelease.length) {\n return -1\n } else if (!this.prerelease.length && other.prerelease.length) {\n return 1\n } else if (!this.prerelease.length && !other.prerelease.length) {\n return 0\n }\n\n let i = 0\n do {\n const a = this.prerelease[i]\n const b = other.prerelease[i]\n debug('prerelease compare', i, a, b)\n if (a === undefined && b === undefined) {\n return 0\n } else if (b === undefined) {\n return 1\n } else if (a === undefined) {\n return -1\n } else if (a === b) {\n continue\n } else {\n return compareIdentifiers(a, b)\n }\n } while (++i)\n }\n\n compareBuild (other) {\n if (!(other instanceof SemVer)) {\n other = new SemVer(other, this.options)\n }\n\n let i = 0\n do {\n const a = this.build[i]\n const b = other.build[i]\n debug('build compare', i, a, b)\n if (a === undefined && b === undefined) {\n return 0\n } else if (b === undefined) {\n return 1\n } else if (a === undefined) {\n return -1\n } else if (a === b) {\n continue\n } else {\n return compareIdentifiers(a, b)\n }\n } while (++i)\n }\n\n // preminor will bump the version up to the next minor release, and immediately\n // down to pre-release. premajor and prepatch work the same way.\n inc (release, identifier, identifierBase) {\n if (release.startsWith('pre')) {\n if (!identifier && identifierBase === false) {\n throw new Error('invalid increment argument: identifier is empty')\n }\n // Avoid an invalid semver results\n if (identifier) {\n const match = `-${identifier}`.match(this.options.loose ? re[t.PRERELEASELOOSE] : re[t.PRERELEASE])\n if (!match || match[1] !== identifier) {\n throw new Error(`invalid identifier: ${identifier}`)\n }\n }\n }\n\n switch (release) {\n case 'premajor':\n this.prerelease.length = 0\n this.patch = 0\n this.minor = 0\n this.major++\n this.inc('pre', identifier, identifierBase)\n break\n case 'preminor':\n this.prerelease.length = 0\n this.patch = 0\n this.minor++\n this.inc('pre', identifier, identifierBase)\n break\n case 'prepatch':\n // If this is already a prerelease, it will bump to the next version\n // drop any prereleases that might already exist, since they are not\n // relevant at this point.\n this.prerelease.length = 0\n this.inc('patch', identifier, identifierBase)\n this.inc('pre', identifier, identifierBase)\n break\n // If the input is a non-prerelease version, this acts the same as\n // prepatch.\n case 'prerelease':\n if (this.prerelease.length === 0) {\n this.inc('patch', identifier, identifierBase)\n }\n this.inc('pre', identifier, identifierBase)\n break\n case 'release':\n if (this.prerelease.length === 0) {\n throw new Error(`version ${this.raw} is not a prerelease`)\n }\n this.prerelease.length = 0\n break\n\n case 'major':\n // If this is a pre-major version, bump up to the same major version.\n // Otherwise increment major.\n // 1.0.0-5 bumps to 1.0.0\n // 1.1.0 bumps to 2.0.0\n if (\n this.minor !== 0 ||\n this.patch !== 0 ||\n this.prerelease.length === 0\n ) {\n this.major++\n }\n this.minor = 0\n this.patch = 0\n this.prerelease = []\n break\n case 'minor':\n // If this is a pre-minor version, bump up to the same minor version.\n // Otherwise increment minor.\n // 1.2.0-5 bumps to 1.2.0\n // 1.2.1 bumps to 1.3.0\n if (this.patch !== 0 || this.prerelease.length === 0) {\n this.minor++\n }\n this.patch = 0\n this.prerelease = []\n break\n case 'patch':\n // If this is not a pre-release version, it will increment the patch.\n // If it is a pre-release it will bump up to the same patch version.\n // 1.2.0-5 patches to 1.2.0\n // 1.2.0 patches to 1.2.1\n if (this.prerelease.length === 0) {\n this.patch++\n }\n this.prerelease = []\n break\n // This probably shouldn't be used publicly.\n // 1.0.0 'pre' would become 1.0.0-0 which is the wrong direction.\n case 'pre': {\n const base = Number(identifierBase) ? 1 : 0\n\n if (this.prerelease.length === 0) {\n this.prerelease = [base]\n } else {\n let i = this.prerelease.length\n while (--i >= 0) {\n if (typeof this.prerelease[i] === 'number') {\n this.prerelease[i]++\n i = -2\n }\n }\n if (i === -1) {\n // didn't increment anything\n if (identifier === this.prerelease.join('.') && identifierBase === false) {\n throw new Error('invalid increment argument: identifier already exists')\n }\n this.prerelease.push(base)\n }\n }\n if (identifier) {\n // 1.2.0-beta.1 bumps to 1.2.0-beta.2,\n // 1.2.0-beta.fooblz or 1.2.0-beta bumps to 1.2.0-beta.0\n let prerelease = [identifier, base]\n if (identifierBase === false) {\n prerelease = [identifier]\n }\n if (isPrereleaseIdentifier(this.prerelease, identifier)) {\n const prereleaseBase = this.prerelease[identifier.split('.').length]\n if (isNaN(prereleaseBase)) {\n this.prerelease = prerelease\n }\n } else {\n this.prerelease = prerelease\n }\n }\n break\n }\n default:\n throw new Error(`invalid increment argument: ${release}`)\n }\n this.raw = this.format()\n if (this.build.length) {\n this.raw += `+${this.build.join('.')}`\n }\n return this\n }\n}\n\nmodule.exports = SemVer\n","'use strict'\n\nconst SemVer = require('../classes/semver')\nconst major = (a, loose) => new SemVer(a, loose).major\nmodule.exports = major\n","'use strict'\n\nconst SemVer = require('../classes/semver')\nconst parse = (version, options, throwErrors = false) => {\n if (version instanceof SemVer) {\n return version\n }\n try {\n return new SemVer(version, options)\n } catch (er) {\n if (!throwErrors) {\n return null\n }\n throw er\n }\n}\n\nmodule.exports = parse\n","'use strict'\n\nconst parse = require('./parse')\nconst valid = (version, options) => {\n const v = parse(version, options)\n return v ? v.version : null\n}\nmodule.exports = valid\n","import major from \"semver/functions/major.js\";\nimport valid from \"semver/functions/valid.js\";\n/*!\n * SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: GPL-3.0-or-later\n */\nclass ProxyBus {\n bus;\n constructor(bus2) {\n if (typeof bus2.getVersion !== \"function\" || !valid(bus2.getVersion())) {\n console.warn(\"Proxying an event bus with an unknown or invalid version\");\n } else if (major(bus2.getVersion()) !== major(this.getVersion())) {\n console.warn(\n \"Proxying an event bus of version \" + bus2.getVersion() + \" with \" + this.getVersion()\n );\n }\n this.bus = bus2;\n }\n getVersion() {\n return \"3.3.3\";\n }\n subscribe(name, handler) {\n this.bus.subscribe(name, handler);\n }\n unsubscribe(name, handler) {\n this.bus.unsubscribe(name, handler);\n }\n emit(name, ...event) {\n this.bus.emit(name, ...event);\n }\n}\n/*!\n * SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: GPL-3.0-or-later\n */\nclass SimpleBus {\n handlers = /* @__PURE__ */ new Map();\n getVersion() {\n return \"3.3.3\";\n }\n subscribe(name, handler) {\n this.handlers.set(\n name,\n (this.handlers.get(name) || []).concat(\n handler\n )\n );\n }\n unsubscribe(name, handler) {\n this.handlers.set(\n name,\n (this.handlers.get(name) || []).filter((h) => h !== handler)\n );\n }\n emit(name, ...event) {\n const handlers = this.handlers.get(name) || [];\n handlers.forEach((h) => {\n try {\n ;\n h(event[0]);\n } catch (e) {\n console.error(\"could not invoke event listener\", e);\n }\n });\n }\n}\n/*!\n * SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: GPL-3.0-or-later\n */\nlet bus = null;\nfunction getBus() {\n if (bus !== null) {\n return bus;\n }\n if (typeof window === \"undefined\") {\n return new Proxy({}, {\n get: () => {\n return () => console.error(\n \"Window not available, EventBus can not be established!\"\n );\n }\n });\n }\n if (window.OC?._eventBus && typeof window._nc_event_bus === \"undefined\") {\n console.warn(\n \"found old event bus instance at OC._eventBus. Update your version!\"\n );\n window._nc_event_bus = window.OC._eventBus;\n }\n if (typeof window?._nc_event_bus !== \"undefined\") {\n bus = new ProxyBus(window._nc_event_bus);\n } else {\n bus = window._nc_event_bus = new SimpleBus();\n }\n return bus;\n}\nfunction subscribe(name, handler) {\n getBus().subscribe(name, handler);\n}\nfunction unsubscribe(name, handler) {\n getBus().unsubscribe(name, handler);\n}\nfunction emit(name, ...event) {\n getBus().emit(name, ...event);\n}\nexport {\n ProxyBus,\n SimpleBus,\n emit,\n subscribe,\n unsubscribe\n};\n//# sourceMappingURL=index.mjs.map\n","/*\n * SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: GPL-3.0-or-later\n */\nexport default class ScopedStorage {\n static GLOBAL_SCOPE_VOLATILE = 'nextcloud_vol';\n static GLOBAL_SCOPE_PERSISTENT = 'nextcloud_per';\n scope;\n wrapped;\n constructor(scope, wrapped, persistent) {\n this.scope = `${persistent ? ScopedStorage.GLOBAL_SCOPE_PERSISTENT : ScopedStorage.GLOBAL_SCOPE_VOLATILE}_${btoa(scope)}_`;\n this.wrapped = wrapped;\n }\n scopeKey(key) {\n return `${this.scope}${key}`;\n }\n setItem(key, value) {\n this.wrapped.setItem(this.scopeKey(key), value);\n }\n getItem(key) {\n return this.wrapped.getItem(this.scopeKey(key));\n }\n removeItem(key) {\n this.wrapped.removeItem(this.scopeKey(key));\n }\n clear() {\n Object.keys(this.wrapped)\n .filter((key) => key.startsWith(this.scope))\n .map(this.wrapped.removeItem.bind(this.wrapped));\n }\n}\n","/*\n * SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: GPL-3.0-or-later\n */\nimport ScopedStorage from \"./ScopedStorage.js\";\nexport default class StorageBuilder {\n appId;\n persisted = false;\n clearedOnLogout = false;\n constructor(appId) {\n this.appId = appId;\n }\n persist(persist = true) {\n this.persisted = persist;\n return this;\n }\n clearOnLogout(clear = true) {\n this.clearedOnLogout = clear;\n return this;\n }\n build() {\n return new ScopedStorage(this.appId, this.persisted ? window.localStorage : window.sessionStorage, !this.clearedOnLogout);\n }\n}\n","/*\n * SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: GPL-3.0-or-later\n */\nimport ScopedStorage from \"./ScopedStorage.js\";\nimport StorageBuilder from \"./StorageBuilder.js\";\n/**\n * Get the storage builder for an app\n *\n * @param appId App ID to scope storage\n */\nexport function getBuilder(appId) {\n return new StorageBuilder(appId);\n}\n/**\n * Clear values from storage\n *\n * @param storage The storage to clear\n * @param pred Callback to check if value should be cleared\n */\nfunction clearStorage(storage, pred) {\n Object.keys(storage)\n .filter((k) => pred ? pred(k) : true)\n .map(storage.removeItem.bind(storage));\n}\n/**\n * Clear all values from all storages\n */\nexport function clearAll() {\n const storages = [\n window.sessionStorage,\n window.localStorage,\n ];\n storages.map((s) => clearStorage(s));\n}\n/**\n * Clear ony non persistent values\n */\nexport function clearNonPersistent() {\n const storages = [\n window.sessionStorage,\n window.localStorage,\n ];\n storages.map((s) => clearStorage(s, (k) => !k.startsWith(ScopedStorage.GLOBAL_SCOPE_PERSISTENT)));\n}\n","import { subscribe, emit, unsubscribe } from \"@nextcloud/event-bus\";\nimport { generateUrl } from \"@nextcloud/router\";\nimport { getBuilder } from \"@nextcloud/browser-storage\";\n_subscribeToTokenUpdates();\nfunction getRequestToken() {\n if (globalThis._nc_auth_requestToken) {\n return globalThis._nc_auth_requestToken;\n }\n if (globalThis.document) {\n return document.head.dataset.requesttoken ?? null;\n }\n return null;\n}\nfunction setRequestToken(token) {\n if (!token || typeof token !== \"string\") {\n throw new Error(\"Invalid CSRF token given\", { cause: { token } });\n }\n if (globalThis._nc_auth_requestToken === token) {\n return;\n }\n globalThis._nc_auth_requestToken = token;\n if (globalThis.document) {\n document.head.dataset.requesttoken = token;\n }\n emit(\"csrf-token-update\", { token, _internal: true });\n}\nasync function fetchRequestToken() {\n const url = generateUrl(\"/csrftoken\");\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(\"Could not fetch CSRF token from API\", { cause: response });\n }\n try {\n const { token } = await response.json();\n setRequestToken(token);\n return token;\n } catch (error) {\n throw new Error(\"Could not parse CSRF token from API response\", { cause: error });\n }\n}\nfunction onRequestTokenUpdate(observer) {\n const wrapper = async ({ token }) => {\n try {\n observer(token);\n } catch (error) {\n console.error(\"Error updating CSRF token observer\", error);\n }\n };\n subscribe(\"csrf-token-update\", wrapper);\n return () => unsubscribe(\"csrf-token-update\", wrapper);\n}\nfunction _subscribeToTokenUpdates() {\n subscribe(\"csrf-token-update\", ({ token, _internal }) => {\n if (!_internal) {\n setRequestToken(token);\n }\n });\n}\nfunction getCSPNonce() {\n const meta = document?.querySelector('meta[name=\"csp-nonce\"]');\n if (!meta) {\n const token = getRequestToken();\n return token ? btoa(token) : void 0;\n }\n return meta.nonce;\n}\n/*!\n * SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: GPL-3.0-or-later\n */\nconst browserStorage = getBuilder(\"public\").persist().build();\nclass GuestUser {\n _displayName;\n uid;\n isAdmin;\n constructor() {\n if (!browserStorage.getItem(\"guestUid\")) {\n browserStorage.setItem(\"guestUid\", randomUUID());\n }\n this._displayName = browserStorage.getItem(\"guestNickname\") || \"\";\n this.uid = browserStorage.getItem(\"guestUid\") || randomUUID();\n this.isAdmin = false;\n subscribe(\"user:info:changed\", (guest) => {\n this._displayName = guest.displayName;\n browserStorage.setItem(\"guestNickname\", guest.displayName || \"\");\n });\n }\n get displayName() {\n return this._displayName;\n }\n set displayName(displayName) {\n this._displayName = displayName;\n browserStorage.setItem(\"guestNickname\", displayName);\n emit(\"user:info:changed\", this);\n }\n}\nlet currentUser$1;\nfunction getGuestUser() {\n if (!currentUser$1) {\n currentUser$1 = new GuestUser();\n }\n return currentUser$1;\n}\nfunction getGuestNickname() {\n return getGuestUser()?.displayName || null;\n}\nfunction setGuestNickname(nickname) {\n if (!nickname || nickname.trim().length === 0) {\n throw new Error(\"Nickname cannot be empty\");\n }\n getGuestUser().displayName = nickname;\n}\nfunction randomUUID() {\n if (globalThis.crypto?.randomUUID) {\n return globalThis.crypto.randomUUID();\n }\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, (c) => {\n const r = Math.random() * 16 | 0;\n const v = c === \"x\" ? r : r & 3 | 8;\n return v.toString(16);\n });\n}\nlet currentUser;\nfunction getAttribute(el, attribute) {\n if (el) {\n return el.getAttribute(attribute);\n }\n return null;\n}\nfunction getCurrentUser() {\n if (currentUser !== void 0) {\n return currentUser;\n }\n const head = document?.getElementsByTagName(\"head\")[0];\n if (!head) {\n return null;\n }\n const uid = getAttribute(head, \"data-user\");\n if (uid === null) {\n currentUser = null;\n return currentUser;\n }\n currentUser = {\n uid,\n displayName: getAttribute(head, \"data-user-displayname\"),\n isAdmin: !!window._oc_isadmin\n };\n return currentUser;\n}\nexport {\n fetchRequestToken,\n getCSPNonce,\n getCurrentUser,\n getGuestNickname,\n getGuestUser,\n getRequestToken,\n onRequestTokenUpdate,\n setGuestNickname,\n setRequestToken\n};\n//# sourceMappingURL=index.mjs.map\n","import { getCurrentUser } from \"@nextcloud/auth\";\nvar LogLevel = /* @__PURE__ */ ((LogLevel2) => {\n LogLevel2[LogLevel2[\"Debug\"] = 0] = \"Debug\";\n LogLevel2[LogLevel2[\"Info\"] = 1] = \"Info\";\n LogLevel2[LogLevel2[\"Warn\"] = 2] = \"Warn\";\n LogLevel2[LogLevel2[\"Error\"] = 3] = \"Error\";\n LogLevel2[LogLevel2[\"Fatal\"] = 4] = \"Fatal\";\n return LogLevel2;\n})(LogLevel || {});\nclass ConsoleLogger {\n context;\n constructor(context) {\n this.context = context || {};\n }\n formatMessage(message, level, context) {\n let msg = \"[\" + LogLevel[level].toUpperCase() + \"] \";\n if (context && context.app) {\n msg += context.app + \": \";\n }\n if (typeof message === \"string\") return msg + message;\n msg += `Unexpected ${message.name}`;\n if (message.message) msg += ` \"${message.message}\"`;\n if (level === LogLevel.Debug && message.stack) msg += `\n\nStack trace:\n${message.stack}`;\n return msg;\n }\n log(level, message, context) {\n if (typeof this.context?.level === \"number\" && level < this.context?.level) {\n return;\n }\n if (typeof message === \"object\" && context?.error === void 0) {\n context.error = message;\n }\n switch (level) {\n case LogLevel.Debug:\n console.debug(this.formatMessage(message, LogLevel.Debug, context), context);\n break;\n case LogLevel.Info:\n console.info(this.formatMessage(message, LogLevel.Info, context), context);\n break;\n case LogLevel.Warn:\n console.warn(this.formatMessage(message, LogLevel.Warn, context), context);\n break;\n case LogLevel.Error:\n console.error(this.formatMessage(message, LogLevel.Error, context), context);\n break;\n case LogLevel.Fatal:\n default:\n console.error(this.formatMessage(message, LogLevel.Fatal, context), context);\n break;\n }\n }\n debug(message, context) {\n this.log(LogLevel.Debug, message, Object.assign({}, this.context, context));\n }\n info(message, context) {\n this.log(LogLevel.Info, message, Object.assign({}, this.context, context));\n }\n warn(message, context) {\n this.log(LogLevel.Warn, message, Object.assign({}, this.context, context));\n }\n error(message, context) {\n this.log(LogLevel.Error, message, Object.assign({}, this.context, context));\n }\n fatal(message, context) {\n this.log(LogLevel.Fatal, message, Object.assign({}, this.context, context));\n }\n}\nfunction buildConsoleLogger(context) {\n return new ConsoleLogger(context);\n}\nclass LoggerBuilder {\n context;\n factory;\n constructor(factory) {\n this.context = {};\n this.factory = factory;\n }\n /**\n * Set the app name within the logging context\n *\n * @param appId App name\n */\n setApp(appId) {\n this.context.app = appId;\n return this;\n }\n /**\n * Set the logging level within the logging context\n *\n * @param level Logging level\n */\n setLogLevel(level) {\n this.context.level = level;\n return this;\n }\n /* eslint-disable jsdoc/no-undefined-types */\n /**\n * Set the user id within the logging context\n * @param uid User ID\n * @see {@link detectUser}\n */\n /* eslint-enable jsdoc/no-undefined-types */\n setUid(uid) {\n this.context.uid = uid;\n return this;\n }\n /**\n * Detect the currently logged in user and set the user id within the logging context\n */\n detectUser() {\n const user = getCurrentUser();\n if (user !== null) {\n this.context.uid = user.uid;\n }\n return this;\n }\n /**\n * Detect and use logging level configured in nextcloud config\n */\n detectLogLevel() {\n const self = this;\n const onLoaded = () => {\n if (document.readyState === \"complete\" || document.readyState === \"interactive\") {\n self.context.level = window._oc_config?.loglevel ?? LogLevel.Warn;\n if (window._oc_debug) {\n self.context.level = LogLevel.Debug;\n }\n document.removeEventListener(\"readystatechange\", onLoaded);\n } else {\n document.addEventListener(\"readystatechange\", onLoaded);\n }\n };\n onLoaded();\n return this;\n }\n /** Build a logger using the logging context and factory */\n build() {\n if (this.context.level === void 0) {\n this.detectLogLevel();\n }\n return this.factory(this.context);\n }\n}\nfunction getLoggerBuilder() {\n return new LoggerBuilder(buildConsoleLogger);\n}\nfunction getLogger() {\n return getLoggerBuilder().build();\n}\nexport {\n LogLevel,\n getLogger,\n getLoggerBuilder\n};\n//# sourceMappingURL=index.mjs.map\n","/*!\n * Toastify js 1.12.0\n * https://github.com/apvarun/toastify-js\n * @license MIT licensed\n *\n * Copyright (C) Varun A P\n */\n(function(root, factory) {\n if (typeof module === \"object\" && module.exports) {\n module.exports = factory();\n } else {\n root.Toastify = factory();\n }\n})(this, function(global) {\n // Object initialization\n var Toastify = function(options) {\n // Returning a new init object\n return new Toastify.lib.init(options);\n },\n // Library version\n version = \"1.12.0\";\n\n // Set the default global options\n Toastify.defaults = {\n oldestFirst: true,\n text: \"Toastify is awesome!\",\n node: undefined,\n duration: 3000,\n selector: undefined,\n callback: function () {\n },\n destination: undefined,\n newWindow: false,\n close: false,\n gravity: \"toastify-top\",\n positionLeft: false,\n position: '',\n backgroundColor: '',\n avatar: \"\",\n className: \"\",\n stopOnFocus: true,\n onClick: function () {\n },\n offset: {x: 0, y: 0},\n escapeMarkup: true,\n ariaLive: 'polite',\n style: {background: ''}\n };\n\n // Defining the prototype of the object\n Toastify.lib = Toastify.prototype = {\n toastify: version,\n\n constructor: Toastify,\n\n // Initializing the object with required parameters\n init: function(options) {\n // Verifying and validating the input object\n if (!options) {\n options = {};\n }\n\n // Creating the options object\n this.options = {};\n\n this.toastElement = null;\n\n // Validating the options\n this.options.text = options.text || Toastify.defaults.text; // Display message\n this.options.node = options.node || Toastify.defaults.node; // Display content as node\n this.options.duration = options.duration === 0 ? 0 : options.duration || Toastify.defaults.duration; // Display duration\n this.options.selector = options.selector || Toastify.defaults.selector; // Parent selector\n this.options.callback = options.callback || Toastify.defaults.callback; // Callback after display\n this.options.destination = options.destination || Toastify.defaults.destination; // On-click destination\n this.options.newWindow = options.newWindow || Toastify.defaults.newWindow; // Open destination in new window\n this.options.close = options.close || Toastify.defaults.close; // Show toast close icon\n this.options.gravity = options.gravity === \"bottom\" ? \"toastify-bottom\" : Toastify.defaults.gravity; // toast position - top or bottom\n this.options.positionLeft = options.positionLeft || Toastify.defaults.positionLeft; // toast position - left or right\n this.options.position = options.position || Toastify.defaults.position; // toast position - left or right\n this.options.backgroundColor = options.backgroundColor || Toastify.defaults.backgroundColor; // toast background color\n this.options.avatar = options.avatar || Toastify.defaults.avatar; // img element src - url or a path\n this.options.className = options.className || Toastify.defaults.className; // additional class names for the toast\n this.options.stopOnFocus = options.stopOnFocus === undefined ? Toastify.defaults.stopOnFocus : options.stopOnFocus; // stop timeout on focus\n this.options.onClick = options.onClick || Toastify.defaults.onClick; // Callback after click\n this.options.offset = options.offset || Toastify.defaults.offset; // toast offset\n this.options.escapeMarkup = options.escapeMarkup !== undefined ? options.escapeMarkup : Toastify.defaults.escapeMarkup;\n this.options.ariaLive = options.ariaLive || Toastify.defaults.ariaLive;\n this.options.style = options.style || Toastify.defaults.style;\n if(options.backgroundColor) {\n this.options.style.background = options.backgroundColor;\n }\n\n // Returning the current object for chaining functions\n return this;\n },\n\n // Building the DOM element\n buildToast: function() {\n // Validating if the options are defined\n if (!this.options) {\n throw \"Toastify is not initialized\";\n }\n\n // Creating the DOM object\n var divElement = document.createElement(\"div\");\n divElement.className = \"toastify on \" + this.options.className;\n\n // Positioning toast to left or right or center\n if (!!this.options.position) {\n divElement.className += \" toastify-\" + this.options.position;\n } else {\n // To be depreciated in further versions\n if (this.options.positionLeft === true) {\n divElement.className += \" toastify-left\";\n console.warn('Property `positionLeft` will be depreciated in further versions. Please use `position` instead.')\n } else {\n // Default position\n divElement.className += \" toastify-right\";\n }\n }\n\n // Assigning gravity of element\n divElement.className += \" \" + this.options.gravity;\n\n if (this.options.backgroundColor) {\n // This is being deprecated in favor of using the style HTML DOM property\n console.warn('DEPRECATION NOTICE: \"backgroundColor\" is being deprecated. Please use the \"style.background\" property.');\n }\n\n // Loop through our style object and apply styles to divElement\n for (var property in this.options.style) {\n divElement.style[property] = this.options.style[property];\n }\n\n // Announce the toast to screen readers\n if (this.options.ariaLive) {\n divElement.setAttribute('aria-live', this.options.ariaLive)\n }\n\n // Adding the toast message/node\n if (this.options.node && this.options.node.nodeType === Node.ELEMENT_NODE) {\n // If we have a valid node, we insert it\n divElement.appendChild(this.options.node)\n } else {\n if (this.options.escapeMarkup) {\n divElement.innerText = this.options.text;\n } else {\n divElement.innerHTML = this.options.text;\n }\n\n if (this.options.avatar !== \"\") {\n var avatarElement = document.createElement(\"img\");\n avatarElement.src = this.options.avatar;\n\n avatarElement.className = \"toastify-avatar\";\n\n if (this.options.position == \"left\" || this.options.positionLeft === true) {\n // Adding close icon on the left of content\n divElement.appendChild(avatarElement);\n } else {\n // Adding close icon on the right of content\n divElement.insertAdjacentElement(\"afterbegin\", avatarElement);\n }\n }\n }\n\n // Adding a close icon to the toast\n if (this.options.close === true) {\n // Create a span for close element\n var closeElement = document.createElement(\"button\");\n closeElement.type = \"button\";\n closeElement.setAttribute(\"aria-label\", \"Close\");\n closeElement.className = \"toast-close\";\n closeElement.innerHTML = \"✖\";\n\n // Triggering the removal of toast from DOM on close click\n closeElement.addEventListener(\n \"click\",\n function(event) {\n event.stopPropagation();\n this.removeElement(this.toastElement);\n window.clearTimeout(this.toastElement.timeOutValue);\n }.bind(this)\n );\n\n //Calculating screen width\n var width = window.innerWidth > 0 ? window.innerWidth : screen.width;\n\n // Adding the close icon to the toast element\n // Display on the right if screen width is less than or equal to 360px\n if ((this.options.position == \"left\" || this.options.positionLeft === true) && width > 360) {\n // Adding close icon on the left of content\n divElement.insertAdjacentElement(\"afterbegin\", closeElement);\n } else {\n // Adding close icon on the right of content\n divElement.appendChild(closeElement);\n }\n }\n\n // Clear timeout while toast is focused\n if (this.options.stopOnFocus && this.options.duration > 0) {\n var self = this;\n // stop countdown\n divElement.addEventListener(\n \"mouseover\",\n function(event) {\n window.clearTimeout(divElement.timeOutValue);\n }\n )\n // add back the timeout\n divElement.addEventListener(\n \"mouseleave\",\n function() {\n divElement.timeOutValue = window.setTimeout(\n function() {\n // Remove the toast from DOM\n self.removeElement(divElement);\n },\n self.options.duration\n )\n }\n )\n }\n\n // Adding an on-click destination path\n if (typeof this.options.destination !== \"undefined\") {\n divElement.addEventListener(\n \"click\",\n function(event) {\n event.stopPropagation();\n if (this.options.newWindow === true) {\n window.open(this.options.destination, \"_blank\");\n } else {\n window.location = this.options.destination;\n }\n }.bind(this)\n );\n }\n\n if (typeof this.options.onClick === \"function\" && typeof this.options.destination === \"undefined\") {\n divElement.addEventListener(\n \"click\",\n function(event) {\n event.stopPropagation();\n this.options.onClick();\n }.bind(this)\n );\n }\n\n // Adding offset\n if(typeof this.options.offset === \"object\") {\n\n var x = getAxisOffsetAValue(\"x\", this.options);\n var y = getAxisOffsetAValue(\"y\", this.options);\n\n var xOffset = this.options.position == \"left\" ? x : \"-\" + x;\n var yOffset = this.options.gravity == \"toastify-top\" ? y : \"-\" + y;\n\n divElement.style.transform = \"translate(\" + xOffset + \",\" + yOffset + \")\";\n\n }\n\n // Returning the generated element\n return divElement;\n },\n\n // Displaying the toast\n showToast: functi SPDX-FileCopyrightText: 2026, 2026 Nextcloud GmbH and Nextcloud contributors\r\n * SPDX-License-Identifier: AGPL-3.0-or-later\r\n */\r\n\r\nimport type { RouteRecordRaw } from 'vue-router'\r\n\r\nimport { createRouter, createWebHashHistory } from 'vue-router'\r\nimport Dashboard from './views/Dashboard.vue'\r\n\r\nconst routes: RouteRecordRaw[] = [\r\n\t{ path: '/', name: 'dashboard', component: Dashboard },\r\n]\r\n\r\n// Hash history keeps the SPA from clashing with the surrounding\r\n// admin-settings page's own routing.\r\nexport default createRouter({\r\n\thistory: createWebHashHistory(),\r\n\troutes,\r\n})\r\n","/**\r\n * SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors\r\n * SPDX-License-Identifier: AGPL-3.0-or-later\r\n */\r\n\r\nimport { translate, translatePlural } from '@nextcloud/l10n'\r\nimport { createPinia } from 'pinia'\r\nimport { createApp } from 'vue'\r\nimport App from './App.vue'\r\nimport router from './router'\r\n\r\nimport './styles/tokens.scss'\r\n\r\nconst mount = document.getElementById('dbdoctor-app')\r\nif (mount === null) {\r\n\t// Settings page hasn't rendered the mount node yet — bail out\r\n\t// quietly. Re-running the script on a different page (e.g. when\r\n\t// Nextcloud admin section caches scripts) wouldn't crash.\r\n\t// eslint-disable-next-line no-console\r\n\tconsole.warn('[dbdoctor] mount node #dbdoctor-app not found; skipping app boot.')\r\n} else {\r\n\tconst app = createApp(App)\r\n\r\n\t// Make `t` / `n` available on every component without per-component\r\n\t// imports — matches the convention in the activity / webtrack apps.\r\n\tapp.config.globalProperties.t = translate\r\n\tapp.config.globalProperties.n = translatePlural\r\n\r\n\tapp.use(createPinia())\r\n\tapp.use(router)\r\n\tapp.mount(mount)\r\n}\r\n"],"file":"dbdoctor-main.mjs" SPDX-FileCopyrightText: 2026, 2026, 2026, 2026, 4000, 2026, 2026, 2026, 2026, 2026, 1024, 2026 Nextcloud GmbH and Nextcloud contributors\r\n - SPDX-License-Identifier: AGPL-3.0-or-later\r\n-->\r\n\r\n\r\n\r\n\r\n\r\n","import '../assets/NcEmptyContent-DJMDuGVz.css';\nimport { defineComponent, openBlock, createElementBlock, unref, renderSlot, createCommentVNode, createTextVNode, toDisplayString } from \"vue\";\nimport { c as createElementId } from \"./createElementId-DhjFt1I9.mjs\";\nimport { _ as _export_sfc } from \"./_plugin-vue_export-helper-1tPrXgE0.mjs\";\nconst _hoisted_1 = [\"aria-labelledby\"];\nconst _hoisted_2 = {\n key: 0,\n class: \"empty-content__icon\",\n \"aria-hidden\": \"true\"\n};\nconst _hoisted_3 = [\"id\"];\nconst _hoisted_4 = {\n key: 2,\n class: \"empty-content__description\"\n};\nconst _hoisted_5 = {\n key: 3,\n class: \"empty-content__action\"\n};\nconst _sfc_main = /* @__PURE__ */ defineComponent({\n __name: \"NcEmptyContent\",\n props: {\n description: { default: \"\" },\n name: { default: \"\" }\n },\n setup(__props) {\n const nameId = createElementId();\n return (_ctx, _cache) => {\n return openBlock(), createElementBlock(\"div\", {\n \"aria-labelledby\": unref(nameId),\n class: \"empty-content\",\n role: \"note\"\n }, [\n _ctx.$slots.icon ? (openBlock(), createElementBlock(\"div\", _hoisted_2, [\n renderSlot(_ctx.$slots, \"icon\", {}, void 0, true)\n ])) : createCommentVNode(\"\", true),\n __props.name !== \"\" || _ctx.$slots.name ? (openBlock(), createElementBlock(\"div\", {\n key: 1,\n id: unref(nameId),\n class: \"empty-content__name\"\n }, [\n renderSlot(_ctx.$slots, \"name\", {}, () => [\n createTextVNode(toDisplayString(__props.name), 1)\n ], true)\n ], 8, _hoisted_3)) : createCommentVNode(\"\", true),\n __props.description !== \"\" || _ctx.$slots.description ? (openBlock(), createElementBlock(\"p\", _hoisted_4, [\n renderSlot(_ctx.$slots, \"description\", {}, () => [\n createTextVNode(toDisplayString(__props.description), 1)\n ], true)\n ])) : createCommentVNode(\"\", true),\n _ctx.$slots.action ? (openBlock(), createElementBlock(\"div\", _hoisted_5, [\n renderSlot(_ctx.$slots, \"action\", {}, void 0, true)\n ])) : createCommentVNode(\"\", true)\n ], 8, _hoisted_1);\n };\n }\n});\nconst NcEmptyContent = /* @__PURE__ */ _export_sfc(_sfc_main, [[\"__scopeId\", \"data-v-8609a4c1\"]]);\nexport {\n NcEmptyContent as N\n};\n//# sourceMappingURL=NcEmptyContent-CGAPqk4S.mjs.map\n","\r\n\r\n\r\n\r\n\r\n\r\n","\r\n\r\n\r\n\r\n\r\n\r\n","/**\r\n * SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors\r\n * SPDX-License-Identifier: AGPL-3.0-or-later\r\n */\r\n\r\nimport type {\r\n\tAuditRow,\r\n\tLiveMetrics,\r\n\tRevertedFix,\r\n\tRunResult,\r\n\tScorePoint,\r\n\tSeriesPoint,\r\n\tSettings,\r\n} from './types'\r\n\r\nimport axios from '@nextcloud/axios'\r\nimport { generateOcsUrl } from '@nextcloud/router'\r\n\r\ninterface OcsEnvelope {\r\n\tocs: { meta: unknown, data: T }\r\n}\r\n\r\nfunction url(path: string): string {\r\n\t// Force JSON: OCS endpoints default to XML when no format is set\r\n\t// and @nextcloud/axios doesn't always negotiate it via Accept.\r\n\tconst base = generateOcsUrl('apps/dbdoctor/api/v1' + path)\r\n\treturn base + (base.includes('?') ? '&' : '?') + 'format=json'\r\n}\r\n\r\n// Some installs serve OCS responses with a content type axios doesn't\r\n// auto-parse as JSON. Forcing the Accept header and a manual JSON\r\n// transform on the response side keeps `res.data` an object even when\r\n// the server's Content-Type is text/plain or text/xml.\r\nconst REQUEST_OPTS = {\r\n\theaders: { Accept: 'application/json' },\r\n\tresponseType: 'json' as const,\r\n\ttransformResponse: [\r\n\t\t(data: unknown): unknown => {\r\n\t\t\tif (typeof data === 'string') {\r\n\t\t\t\ttry {\r\n\t\t\t\t\treturn JSON.parse(data)\r\n\t\t\t\t} catch {\r\n\t\t\t\t\treturn data\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\treturn data\r\n\t\t},\r\n\t],\r\n}\r\n\r\n// Surfaces a useful message when the backend returns something that\r\n// isn't an OCS envelope (PHP fatal, HTML 500 page, redirect to login).\r\n// Without this, callers see a cryptic \"undefined is not an object\"\r\n// when they try to read `.ocs.data` on a non-OCS body.\r\nfunction unwrap(body: unknown, label: string): T {\r\n\tif (body === null || typeof body !== 'object') {\r\n\t\tconst preview = typeof body === 'string'\r\n\t\t\t? body.slice(0, 200)\r\n\t\t\t: String(body)\r\n\t\tthrow new Error(`${label}: server returned a non-JSON response (got: ${preview || 'empty body'}). Check the server log.`)\r\n\t}\r\n\tconst ocs = (body as { ocs?: { data?: T } }).ocs\r\n\tif (!ocs || !('data' in ocs)) {\r\n\t\tthrow new Error(`${label}: response is missing the OCS envelope. The endpoint may have errored before reaching the controller.`)\r\n\t}\r\n\treturn ocs.data as T\r\n}\r\n\r\nexport async function getLatest(): Promise {\r\n\tconst res = await axios.get>(url('/check/latest'), REQUEST_OPTS)\r\n\t// 204 No Content gives axios an empty body; treat as \"no run yet\".\r\n\tif (res.status === 204 || res.data === '' || res.data === null) {\r\n\t\treturn null\r\n\t}\r\n\treturn unwrap(res.data, 'getLatest')\r\n}\r\n\r\nexport async function runCheck(): Promise {\r\n\tconst res = await axios.post>(url('/check/run'), null, REQUEST_OPTS)\r\n\treturn unwrap(res.data, 'runCheck')\r\n}\r\n\r\nexport interface PingResult {\r\n\telapsedMs: number\r\n\tok: boolean\r\n\terror?: string\r\n}\r\n\r\n// 1 Hz poll target. We pass a per-request timeout shorter than the\r\n// poll interval so a stalled DB doesn't queue up backed-up requests\r\n// behind each other; the chart shows the timeout as a sentinel point.\r\nconst PING_TIMEOUT_MS = 800\r\n\r\nexport async function pingDatabase(): Promise {\r\n\tconst res = await axios.get>(\r\n\t\turl('/check/ping'),\r\n\t\t{ ...REQUEST_OPTS, timeout: PING_TIMEOUT_MS },\r\n\t)\r\n\treturn unwrap(res.data, 'pingDatabase')\r\n}\r\n\r\nexport async function getHistory(ruleId: string, days: number = 30): Promise {\r\n\tconst res = await axios.get>(\r\n\t\turl('/check/history'),\r\n\t\t{ ...REQUEST_OPTS, params: { ruleId, days } },\r\n\t)\r\n\treturn unwrap<{ series: SeriesPoint[] }>(res.data, 'getHistory').series\r\n}\r\n\r\nexport async function getScoreHistory(days: number = 30): Promise {\r\n\tconst res = await axios.get>(\r\n\t\turl('/check/score-history'),\r\n\t\t{ ...REQUEST_OPTS, params: { days } },\r\n\t)\r\n\treturn unwrap<{ series: ScorePoint[] }>(res.data, 'getScoreHistory').series\r\n}\r\n\r\nexport async function getRevertedFixes(): Promise {\r\n\tconst res = await axios.get>(\r\n\t\turl('/check/reverted-fixes'),\r\n\t\tREQUEST_OPTS,\r\n\t)\r\n\treturn unwrap<{ reverted: RevertedFix[] }>(res.data, 'getRevertedFixes').reverted\r\n}\r\n\r\nexport async function applyChange(ruleId: string, variable: string, value: string): Promise<{\r\n\tsuccess: boolean\r\n\toldValue: string | null\r\n\tnewValue: string | null\r\n\terror?: string\r\n}> {\r\n\ttry {\r\n\t\tconst res = await axios.post>(url('/apply'), { ruleId, variable, value }, REQUEST_OPTS)\r\n\t\treturn unwrap(res.data, 'applyChange')\r\n\t} catch (e) {\r\n\t\t// A non-2xx (bad value → 400, or an unexpected server fault) still\r\n\t\t// carries a useful message in the OCS body. Surface it as a\r\n\t\t// failed result the dialog can render, rather than letting axios's\r\n\t\t// generic \"Request failed with status code NNN\" bubble up.\r\n\t\tconst body = (e as { response?: { data?: unknown } })?.response?.data\r\n\t\tconst data = (body as { ocs?: { data?: { error?: string } } })?.ocs?.data\r\n\t\tconst meta = (body as { ocs?: { meta?: { message?: string } } })?.ocs?.meta\r\n\t\tconst message = data?.error || meta?.message || (e instanceof Error ? e.message : String(e))\r\n\t\treturn { success: false, oldValue: null, newValue: null, error: message }\r\n\t}\r\n}\r\n\r\nexport async function getSettings(): Promise {\r\n\tconst res = await axios.get>(url('/settings'), REQUEST_OPTS)\r\n\treturn unwrap(res.data, 'getSettings')\r\n}\r\n\r\nexport async function updateSettings(patch: Partial<{\r\n\thost: string\r\n\tport: number\r\n\tuser: string\r\n\tdatabase: string\r\n\tdriver: 'pdo_mysql' | 'pdo_pgsql'\r\n\tpassword: string\r\n\tclearPassword: boolean\r\n}>): Promise {\r\n\tconst res = await axios.put>(url('/settings'), patch, REQUEST_OPTS)\r\n\treturn unwrap(res.data, 'updateSettings')\r\n}\r\n\r\nexport async function testConnection(payload: {\r\n\thost: string\r\n\tport: number\r\n\tuser: string\r\n\tpassword: string\r\n\tdatabase: string\r\n\tdriver: 'pdo_mysql' | 'pdo_pgsql'\r\n}): Promise<{ ok: boolean, message: string }> {\r\n\tconst res = await axios.post>(\r\n\t\turl('/settings/test-connection'),\r\n\t\tpayload,\r\n\t\tREQUEST_OPTS,\r\n\t)\r\n\treturn unwrap(res.data, 'testConnection')\r\n}\r\n\r\nexport async function getAudit(limit: number = 50): Promise {\r\n\tconst res = await axios.get>(url('/audit'), { ...REQUEST_OPTS, params: { limit } })\r\n\treturn unwrap<{ entries: AuditRow[] }>(res.data, 'getAudit').entries\r\n}\r\n\r\n// ── Live metrics (dashboard tiles) ──────────────────────────────────\r\n\r\n// Axios reports HTTP failures as a generic \"Request failed with status\r\n// code NNN\". When the body is an OCS error envelope the real cause\r\n// (e.g. the SQL error the controller wrapped) is in ocs.meta.message —\r\n// surface that instead.\r\nfunction toReadableError(e: unknown, label: string): Error {\r\n\tconst body = (e as { response?: { data?: unknown } })?.response?.data\r\n\tconst message = (body as { ocs?: { meta?: { message?: string } } })?.ocs?.meta?.message\r\n\tif (typeof message === 'string' && message !== '') {\r\n\t\treturn new Error(`${label}: ${message}`)\r\n\t}\r\n\treturn e instanceof Error ? e : new Error(String(e))\r\n}\r\n\r\nasync function ocsGet(label: string, path: string, opts: object = {}): Promise {\r\n\ttry {\r\n\t\tconst res = await axios.get>(url(path), { ...REQUEST_OPTS, ...opts })\r\n\t\treturn unwrap(res.data, label)\r\n\t} catch (e) {\r\n\t\tthrow toReadableError(e, label)\r\n\t}\r\n}\r\n\r\nexport async function getLiveMetrics(): Promise {\r\n\treturn ocsGet('getLiveMetrics', '/insights/metrics', { timeout: })\r\n}\r\n","/**\r\n * SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors\r\n * SPDX-License-Identifier: AGPL-3.0-or-later\r\n */\r\n\r\nconst APP = 'dbdoctor'\r\n\r\n// Lightweight logger. We keep this thin (no external deps) so the\r\n// bundle stays small. Output goes through `console` which Nextcloud\r\n// already wires to its log surfaces in dev builds.\r\nexport default {\r\n\tdebug(msg: string, data?: unknown): void {\r\n\t\tif (typeof console !== 'undefined') { console.debug(`[${APP}] ${msg}`, data ?? '') }\r\n\t},\r\n\tinfo(msg: string, data?: unknown): void {\r\n\t\tif (typeof console !== 'undefined') { console.info(`[${APP}] ${msg}`, data ?? '') }\r\n\t},\r\n\twarn(msg: string, data?: unknown): void {\r\n\t\tif (typeof console !== 'undefined') { console.warn(`[${APP}] ${msg}`, data ?? '') }\r\n\t},\r\n\terror(msg: string, data?: unknown): void {\r\n\t\tif (typeof console !== 'undefined') { console.error(`[${APP}] ${msg}`, data ?? '') }\r\n\t},\r\n}\r\n","/**\r\n * SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors\r\n * SPDX-License-Identifier: AGPL-3.0-or-later\r\n */\r\n\r\nimport { defineStore } from 'pinia'\r\nimport { computed, ref } from 'vue'\r\nimport { pingDatabase } from '../api/client'\r\nimport logger from '../utils/logger'\r\n\r\n/**\r\n * Live database-latency telemetry, shared between the LatencyChart and\r\n * the score-card Heartbeat.\r\n *\r\n * Two consumers needed a single source: putting the polling here keeps\r\n * them in lockstep (the heartbeat's BPM matches the chart's last point\r\n * to the millisecond) and lets us refcount subscribers — polling only\r\n * runs when at least one consumer is mounted, and pauses when the tab\r\n * is hidden.\r\n *\r\n * Smoothing: we expose both the raw last reading (`currentMs`) for the\r\n * chart's \"now\" readout and an exponentially-weighted moving average\r\n * (`smoothedMs`) for the heartbeat — a single 200ms spike shouldn't\r\n * make the mascot's heart race for 30 seconds.\r\n */\r\nexport const useLatencyStore = defineStore('dbdoctor/latency', () => {\r\n\tconst MAX_SAMPLES = 60\r\n\tconst POLL_INTERVAL_MS = 1000\r\n\t// EMA weight on the newest sample. 0.25 trades roughly 4 samples\r\n\t// of inertia for a still-responsive smoothed trace.\r\n\tconst EMA_ALPHA = 0.25\r\n\r\n\t// NaN entries denote a failed / timed-out ping; consumers render\r\n\t// them as a gap rather than smoothing them away.\r\n\tconst samples = ref([])\r\n\tconst ema = ref(null)\r\n\r\n\tconst subscribers = ref(0)\r\n\tlet timer: number | null = null\r\n\tlet inflight = false\r\n\tlet visibilityBound = false\r\n\r\n\tconst currentMs = computed(() => {\r\n\t\tconst v = samples.value[samples.value.length - 1]\r\n\t\treturn Number.isFinite(v) ? v : null\r\n\t})\r\n\tconst smoothedMs = computed(() => ema.value)\r\n\r\n\tasync function tick(): Promise {\r\n\t\t// Don't pile up requests if the previous one is still in flight\r\n\t\t// — better to drop a sample than queue them.\r\n\t\tif (inflight) { return }\r\n\t\tinflight = true\r\n\t\ttry {\r\n\t\t\tconst r = await pingDatabase()\r\n\t\t\tconst v = r.ok ? r.elapsedMs : Number.NaN\r\n\t\t\tsamples.value.push(v)\r\n\t\t\tif (Number.isFinite(v)) {\r\n\t\t\t\tema.value = ema.value === null\r\n\t\t\t\t\t? v\r\n\t\t\t\t\t: EMA_ALPHA * v + (1 - EMA_ALPHA) * ema.value\r\n\t\t\t}\r\n\t\t} catch (e) {\r\n\t\t\tsamples.value.push(Number.NaN)\r\n\t\t\tlogger.debug('latency ping failed', e)\r\n\t\t} finally {\r\n\t\t\twhile (samples.value.length > MAX_SAMPLES) { samples.value.shift() }\r\n\t\t\tinflight = false\r\n\t\t}\r\n\t}\r\n\r\n\tfunction start(): void {\r\n\t\tif (timer !== null) { return }\r\n\t\tvoid tick()\r\n\t\ttimer = window.setInterval(() => { void tick() }, POLL_INTERVAL_MS)\r\n\t}\r\n\r\n\tfunction stop(): void {\r\n\t\tif (timer !== null) {\r\n\t\t\twindow.clearInterval(timer)\r\n\t\t\ttimer = null\r\n\t\t}\r\n\t}\r\n\r\n\tfunction onVisibility(): void {\r\n\t\tif (subscribers.value === 0) { return }\r\n\t\tif (document.hidden) {\r\n\t\t\tstop()\r\n\t\t} else {\r\n\t\t\tstart()\r\n\t\t}\r\n\t}\r\n\r\n\tfunction bindVisibility(): void {\r\n\t\tif (visibilityBound) { return }\r\n\t\tdocument.addEventListener('visibilitychange', onVisibility)\r\n\t\tvisibilityBound = true\r\n\t}\r\n\r\n\tfunction unbindVisibility(): void {\r\n\t\tif (!visibilityBound) { return }\r\n\t\tdocument.removeEventListener('visibilitychange', onVisibility)\r\n\t\tvisibilityBound = false\r\n\t}\r\n\r\n\t/**\r\n\t * Refcounted lifecycle. The first subscriber starts polling; the\r\n\t * last unsubscribe stops it. Components should call subscribe()\r\n\t * in onMounted and unsubscribe() in onBeforeUnmount.\r\n\t */\r\n\tfunction subscribe(): void {\r\n\t\tsubscribers.value++\r\n\t\tif (subscribers.value === 1) {\r\n\t\t\tbindVisibility()\r\n\t\t\tif (!document.hidden) { start() }\r\n\t\t}\r\n\t}\r\n\r\n\tfunction unsubscribe(): void {\r\n\t\tsubscribers.value = Math.max(0, subscribers.value - 1)\r\n\t\tif (subscribers.value === 0) {\r\n\t\t\tstop()\r\n\t\t\tunbindVisibility()\r\n\t\t\t// Reset the rolling state so a future mount starts cleanly.\r\n\t\t\tsamples.value = []\r\n\t\t\tema.value = null\r\n\t\t}\r\n\t}\r\n\r\n\treturn {\r\n\t\t// state\r\n\t\tsamples,\r\n\t\t// derived\r\n\t\tcurrentMs,\r\n\t\tsmoothedMs,\r\n\t\t// actions\r\n\t\tsubscribe,\r\n\t\tunsubscribe,\r\n\t}\r\n})\r\n","\r\n\r\n\r\n\r\n\r\n\r\n","/**\r\n * SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors\r\n * SPDX-License-Identifier: AGPL-3.0-or-later\r\n */\r\n\r\nimport type { LiveMetrics } from '../api/types'\r\n\r\nimport { defineStore } from 'pinia'\r\nimport { computed, ref } from 'vue'\r\nimport { getLiveMetrics } from '../api/client'\r\nimport logger from '../utils/logger'\r\n\r\n/**\r\n * Live server metrics for the dashboard tiles: connection saturation,\r\n * cache-hit ratio, and throughput. Throughput is derived from a\r\n * cumulative counter (Questions / transactions) by differencing\r\n * successive polls, so we keep the previous sample to compute a rate.\r\n *\r\n * Refcounted + visibility-aware like the latency store: polling only\r\n * runs while a consumer is mounted and the tab is visible. A slower\r\n * cadence than the 1 Hz latency ping is plenty for these gauges.\r\n */\r\nexport const useMetricsStore = defineStore('dbdoctor/metrics', () => {\r\n\tconst POLL_INTERVAL_MS = 3000\r\n\tconst MAX_QPS_SAMPLES = 40\r\n\r\n\tconst latest = ref(null)\r\n\t// Rolling per-second throughput samples for the mini chart.\r\n\tconst qps = ref([])\r\n\tconst throughputLabel = ref('Queries/s')\r\n\r\n\tconst subscribers = ref(0)\r\n\tlet timer: number | null = null\r\n\tlet inflight = false\r\n\tlet visibilityBound = false\r\n\t// Previous counter + timestamp for rate differencing.\r\n\tlet prevCounter: number | null = null\r\n\tlet prevAt: number | null = null\r\n\r\n\tconst connectionRatio = computed(() => {\r\n\t\tconst m = latest.value\r\n\t\tif (m === null || m.connections.max <= 0) { return null }\r\n\t\treturn Math.min(1, m.connections.used / m.connections.max)\r\n\t})\r\n\tconst cacheHitRatio = computed(() => latest.value?.cacheHitRatio ?? null)\r\n\tconst currentQps = computed(() => (qps.value.length ? qps.value[qps.value.length - 1] : null))\r\n\r\n\tasync function tick(): Promise {\r\n\t\tif (inflight) { return }\r\n\t\tinflight = true\r\n\t\ttry {\r\n\t\t\tconst m = await getLiveMetrics()\r\n\t\t\tlatest.value = m\r\n\t\t\tthroughputLabel.value = m.throughput.label\r\n\r\n\t\t\t// Convert the cumulative counter into a per-second rate.\r\n\t\t\tconst now = Date.now()\r\n\t\t\tif (prevCounter !== null && prevAt !== null) {\r\n\t\t\t\tconst dt = (now - prevAt) / 1000\r\n\t\t\t\tconst dCount = m.throughput.counter - prevCounter\r\n\t\t\t\t// Guard against counter resets (server restart) and gaps.\r\n\t\t\t\tconst rate = dt > 0 && dCount >= 0 ? dCount / dt : 0\r\n\t\t\t\tqps.value.push(Math.round(rate))\r\n\t\t\t\twhile (qps.value.length > MAX_QPS_SAMPLES) { qps.value.shift() }\r\n\t\t\t}\r\n\t\t\tprevCounter = m.throughput.counter\r\n\t\t\tprevAt = now\r\n\t\t} catch (e) {\r\n\t\t\tlogger.debug('metrics poll failed', e)\r\n\t\t} finally {\r\n\t\t\tinflight = false\r\n\t\t}\r\n\t}\r\n\r\n\tfunction start(): void {\r\n\t\tif (timer !== null) { return }\r\n\t\tvoid tick()\r\n\t\ttimer = window.setInterval(() => { void tick() }, POLL_INTERVAL_MS)\r\n\t}\r\n\r\n\tfunction stop(): void {\r\n\t\tif (timer !== null) {\r\n\t\t\twindow.clearInterval(timer)\r\n\t\t\ttimer = null\r\n\t\t}\r\n\t}\r\n\r\n\tfunction onVisibility(): void {\r\n\t\tif (subscribers.value === 0) { return }\r\n\t\tif (document.hidden) { stop() } else { start() }\r\n\t}\r\n\r\n\tfunction subscribe(): void {\r\n\t\tsubscribers.value++\r\n\t\tif (subscribers.value === 1) {\r\n\t\t\tif (!visibilityBound) {\r\n\t\t\t\tdocument.addEventListener('visibilitychange', onVisibility)\r\n\t\t\t\tvisibilityBound = true\r\n\t\t\t}\r\n\t\t\tif (!document.hidden) { start() }\r\n\t\t}\r\n\t}\r\n\r\n\tfunction unsubscribe(): void {\r\n\t\tsubscribers.value = Math.max(0, subscribers.value - 1)\r\n\t\tif (subscribers.value === 0) {\r\n\t\t\tstop()\r\n\t\t\tif (visibilityBound) {\r\n\t\t\t\tdocument.removeEventListener('visibilitychange', onVisibility)\r\n\t\t\t\tvisibilityBound = false\r\n\t\t\t}\r\n\t\t\t// Reset rolling state so a future mount starts clean.\r\n\t\t\tlatest.value = null\r\n\t\t\tqps.value = []\r\n\t\t\tprevCounter = null\r\n\t\t\tprevAt = null\r\n\t\t}\r\n\t}\r\n\r\n\treturn {\r\n\t\tlatest,\r\n\t\tqps,\r\n\t\tthroughputLabel,\r\n\t\tconnectionRatio,\r\n\t\tcacheHitRatio,\r\n\t\tcurrentQps,\r\n\t\tsubscribe,\r\n\t\tunsubscribe,\r\n\t}\r\n})\r\n","/**\r\n * SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors\r\n * SPDX-License-Identifier: AGPL-3.0-or-later\r\n */\r\n\r\nconst SI_BYTE_UNITS = ['B', 'KiB', 'MiB', 'GiB', 'TiB'] as const\r\n\r\n/**\r\n * Render a byte count in IEC units with up to one decimal of\r\n * precision. Used to display sizes in rule justifications when the\r\n * raw `SHOW VARIABLES` value comes back in bytes.\r\n *\r\n * @param bytes\r\n */\r\nexport function formatBytes(bytes: number): string {\r\n\tif (!Number.isFinite(bytes) || bytes < 0) { return '?' }\r\n\tlet n = bytes\r\n\tlet u = 0\r\n\twhile (n >= && u < SI_BYTE_UNITS.length - 1) {\r\n\t\tn /= 1024\r\n\t\tu++\r\n\t}\r\n\treturn (u === 0 ? n.toString() : n.toFixed(1)) + ' ' + SI_BYTE_UNITS[u]\r\n}\r\n\r\n/**\r\n * Render a UNIX timestamp as a relative phrase (e.g. \"2 minutes ago\"),\r\n * falling back to a localized date string for older points.\r\n *\r\n * @param ts\r\n * @param now\r\n */\r\nexport function timeAgo(ts: number, now: number = Date.now() / 1000): string {\r\n\tconst seconds = Math.max(0, Math.floor(now - ts))\r\n\tif (seconds < 5) { return 'just now' }\r\n\tif (seconds < 60) { return `${seconds}s ago` }\r\n\tif (seconds < 3600) { return `${Math.floor(seconds / 60)}m ago` }\r\n\tif (seconds < 86400) { return `${Math.floor(seconds / 3600)}h ago` }\r\n\tif (seconds < 86400 * 14) { return `${Math.floor(seconds / 86400)}d ago` }\r\n\treturn new Date(ts * 1000).toLocaleDateString()\r\n}\r\n\r\n/**\r\n * Pretty-print a percentage with at most one decimal.\r\n *\r\n * @param p\r\n */\r\nexport function formatPercent(p: number): string {\r\n\tif (!Number.isFinite(p)) { return '?' }\r\n\tif (Math.abs(p - Math.round(p)) < 0.05) { return Math.round(p) + '%' }\r\n\treturn p.toFixed(1) + '%'\r\n}\r\n\r\n/**\r\n * Format a rule's primary value for compact display in the overview.\r\n *\r\n * The advisor evaluator collapses everything into a float, but the\r\n * meaningful presentation depends on magnitude:\r\n * - integer-valued numbers print without decimals;\r\n * - small fractional numbers keep up to four decimals (advisor ratios\r\n * like cache_hit_ratio = 0.9842 are common);\r\n * - large integers get thousands separators for readability.\r\n *\r\n * @param v\r\n */\r\nexport function formatValue(v: number | null | undefined): string {\r\n\tif (v === null || v === undefined || !Number.isFinite(v)) { return '—' }\r\n\tif (Number.isInteger(v)) { return v.toLocaleString() }\r\n\tif (Math.abs(v) >= 100) { return Math.round(v).toLocaleString() }\r\n\treturn parseFloat(v.toFixed(4)).toString()\r\n}\r\n","\r\n\r\n\r\n\r\n\r\n\r\n","\n\n","\n\n","\n\n