From d8f9ddc4d51c33be258cc6652bbd6637b556f6ab Mon Sep 17 00:00:00 2001 From: Rodrigo Gomes da Silva Date: Mon, 2 Mar 2026 23:51:42 +0000 Subject: [PATCH 1/3] feat: improve date format detection and resilience MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add support for DD/MM/YY with AM/PM (12-hour European/Brazilian format) - Add support for dot-time format (HH.MM.SS) and Finnish 'klo' marker - Add support for bracketed year-first formats [YYYY/MM/DD] - Implement smart line normalization: - Remove bidirectional marks (LTR/RTL) - Normalize AM/PM variants (a.m., p.m., p. m. → AM/PM) - Convert dot-separated time to colon format - Trim Unicode whitespace - Improve date pattern detection: - Score patterns across file sample (first 200 lines) - Detect day-first vs month-first ambiguity - Prioritize patterns by frequency and context - Graceful fallback to all patterns if no clear match - Ensure proper localization of timestamps in MediaGallery lightbox Resolves #69 --- examples/parser-tests/README.md | 68 ++++++- .../parser-tests/asian-ampm-format-test.txt | 5 + .../bracketed-year-first-test.txt | 3 + .../parser-tests/dot-time-klo-format-test.txt | 3 + .../european-ampm-format-test.txt | 4 + package-lock.json | 27 ++- src/lib/components/MediaGallery.svelte | 6 +- src/lib/parser/chat-parser.ts | 191 +++++++++++++++++- 8 files changed, 279 insertions(+), 28 deletions(-) create mode 100644 examples/parser-tests/asian-ampm-format-test.txt create mode 100644 examples/parser-tests/bracketed-year-first-test.txt create mode 100644 examples/parser-tests/dot-time-klo-format-test.txt create mode 100644 examples/parser-tests/european-ampm-format-test.txt diff --git a/examples/parser-tests/README.md b/examples/parser-tests/README.md index 8d6661e..41328e2 100644 --- a/examples/parser-tests/README.md +++ b/examples/parser-tests/README.md @@ -40,7 +40,43 @@ This directory contains WhatsApp chat export examples in various formats for tes - Japanese media indicators: `<メディアなし>`, `.jpg (ファイル添付)` - Japanese characters in usernames and messages -### 5. `dash-format-test.txt` +### 5. `asian-ampm-format-test.txt` +- **Date Format**: `YYYY/MM/DD, HH:MM am/pm` +- **Example**: `2024/12/01, 10:04 pm` +- **Locale**: Year-first formats with 12-hour clock +- **Features Tested**: + - Asian year-first date format with AM/PM + - Lowercase AM/PM (`am`, `pm`) + - Real-world export style from issue reports + +### 6. `european-ampm-format-test.txt` +- **Date Format**: `DD/MM/YYYY, H:MM AM/PM` +- **Example**: `23/06/2018, 1:55 p.m.` +- **Locale**: Day-first formats with 12-hour clock +- **Features Tested**: + - Day-first date with AM/PM + - AM/PM variants: `p.m.`, `p. m.`, uppercase/lowercase + - Compatibility with parser normalization of AM/PM tokens + +### 7. `dot-time-klo-format-test.txt` +- **Date Format**: `DD.MM.YYYY klo HH.MM.SS` and `DD.MM.YY HH.MM.SS:` +- **Example**: `13.6.2018 klo 21.25.15` +- **Locale**: Finnish and dot-time variants +- **Features Tested**: + - Finnish marker `klo` + - Time using dot separator (`HH.MM` and `HH.MM.SS`) + - Separator after timestamp using `:` + +### 8. `bracketed-year-first-test.txt` +- **Date Format**: `[YYYY/MM/DD, HH:MM:SS]` and `[YYYY/MM/DD H:MM:SS AM/PM]` +- **Example**: `[2018/06/13, 21:25:15]` +- **Locale**: Year-first bracketed variants +- **Features Tested**: + - Bracketed year-first format + - 24-hour and 12-hour variants + - AM/PM normalization inside brackets + +### 9. `dash-format-test.txt` - **Date Format**: `DD-MM-YYYY, HH:MM` - **Example**: `10-12-2024, 14:30` - **Locale**: Alternative European format @@ -76,25 +112,47 @@ The parser supports the following date patterns: - Example: `2024/12/10, 14:30` - Year-first format (Japan, China, Korea) -7. **Bracketed Format**: `[DD/MM/YY, HH:MM:SS]` +7. **Asian Format (12h)**: `YYYY/MM/DD, HH:MM AM/PM` + - Example: `2024/12/01, 10:04 pm` + - Year-first format with 12-hour clock + - Supports uppercase and lowercase AM/PM + +8. **European/Brazilian Format (12h)**: `DD/MM/YY, H:MM AM/PM` + - Example: `23/06/2018, 1:55 p.m.` + - Day-first format with 12-hour clock + - Supports `AM`, `PM`, `a.m.`, `p.m.`, and `p. m.` variants + +9. **Bracketed Format**: `[DD/MM/YY, HH:MM:SS]` - Example: `[10/12/24, 14:30:45]` - Some older WhatsApp versions -8. **iOS Bracketed Format (12h)**: `[DD/MM/YYYY, HH:MM:SS AM/PM]` +10. **iOS Bracketed Format (12h)**: `[DD/MM/YYYY, HH:MM:SS AM/PM]` - Example: `[13/11/2025, 12:25:55 PM]` - iOS WhatsApp exports - Uses 12-hour format with AM/PM - May contain Unicode whitespace (U+202F) before AM/PM - File typically named `_chat.txt` (with underscore prefix) +11. **Bracketed Year-First Format**: `[YYYY/MM/DD, HH:MM:SS]` + - Example: `[2018/06/13, 21:25:15]` + - Supports both 24-hour and AM/PM variants + +12. **Dot-Time + Finnish `klo`**: `DD.MM.YYYY klo HH.MM.SS` + - Example: `13.6.2018 klo 21.25.15` + - Dot-separated time normalized for parsing + ## Test Files ### 1. `german-format-test.txt` (see above) ### 2. `spanish-format-test.txt` (see above) ### 3. `french-format-test.txt` (see above) ### 4. `asian-format-test.txt` (see above) -### 5. `dash-format-test.txt` (see above) -### 6. `ios-format-test.txt` +### 5. `asian-ampm-format-test.txt` (see above) +### 6. `european-ampm-format-test.txt` (see above) +### 7. `dot-time-klo-format-test.txt` (see above) +### 8. `bracketed-year-first-test.txt` (see above) +### 9. `dash-format-test.txt` (see above) +### 10. `ios-format-test.txt` - **Date Format**: `[DD/MM/YYYY, HH:MM:SS AM/PM]` - **Example**: `[13/11/2025, 12:25:55 PM]` - **Locale**: iOS (all locales) diff --git a/examples/parser-tests/asian-ampm-format-test.txt b/examples/parser-tests/asian-ampm-format-test.txt new file mode 100644 index 0000000..0b281a2 --- /dev/null +++ b/examples/parser-tests/asian-ampm-format-test.txt @@ -0,0 +1,5 @@ +2024/12/01, 10:04 pm - Alice: Messages and calls are end-to-end encrypted. Only people in this chat can read, listen to, or share them. Learn more. +2024/12/01, 10:05 pm - Alice: Hello there +2024/12/01, 10:06 pm - Bob: Hi! +2024/12/01, 10:07 pm - Alice: +2024/12/01, 10:08 pm - Bob: Nice diff --git a/examples/parser-tests/bracketed-year-first-test.txt b/examples/parser-tests/bracketed-year-first-test.txt new file mode 100644 index 0000000..bc98604 --- /dev/null +++ b/examples/parser-tests/bracketed-year-first-test.txt @@ -0,0 +1,3 @@ +[2018/06/13, 21:25:15] Ana: mensagem com colchetes +[2018/06/13 1:55:00 p. m.] Bruno: ampm com espaços +[2018/06/13, 01:56:00 AM] Ana: uppercase também funciona diff --git a/examples/parser-tests/dot-time-klo-format-test.txt b/examples/parser-tests/dot-time-klo-format-test.txt new file mode 100644 index 0000000..e51b35d --- /dev/null +++ b/examples/parser-tests/dot-time-klo-format-test.txt @@ -0,0 +1,3 @@ +13.6.2018 klo 21.25.15 - Mika: tämä on testi +13.06.18 21.25.15: Laura: tämä on toinen testi +13.06.2018, 21.25 - Mika: ilman sekunteja diff --git a/examples/parser-tests/european-ampm-format-test.txt b/examples/parser-tests/european-ampm-format-test.txt new file mode 100644 index 0000000..54ccc21 --- /dev/null +++ b/examples/parser-tests/european-ampm-format-test.txt @@ -0,0 +1,4 @@ +23/06/2018, 1:55 p.m. - Loris: one +23/06/2018, 1:56 p. m. - Luke: two +23/06/2018, 1:57 PM - Loris: three +23/06/2018, 1:58 am - Luke: four diff --git a/package-lock.json b/package-lock.json index 4c80228..06dacc0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -709,6 +709,7 @@ "dev": true, "license": "BSD-2-Clause", "optional": true, + "peer": true, "dependencies": { "cross-dirname": "^0.1.0", "debug": "^4.3.4", @@ -2168,7 +2169,6 @@ "integrity": "sha512-DhGl4xMVFGVIyMwswXeyzdL4uXD5OGILGX5N8Y+f6W7LhC1Ze2poSNrkF/fedpVDHEEZ+PHFW0vL14I+mm8K3Q==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@octokit/auth-token": "^6.0.0", "@octokit/graphql": "^9.0.3", @@ -3435,7 +3435,6 @@ "integrity": "sha512-Vp3zX/qlwerQmHMP6x0Ry1oY7eKKRcOWGc2P59srOp4zcqyn+etJyQpELgOi4+ZSUgteX8Y387NuwruLgGXLUQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@standard-schema/spec": "^1.0.0", "@sveltejs/acorn-typescript": "^1.0.5", @@ -3475,7 +3474,6 @@ "integrity": "sha512-YZs/OSKOQAQCnJvM/P+F1URotNnYNeU3P2s4oIpzm1uFaqUEqRxUB0g5ejMjEb5Gjb9/PiBI5Ktrq4rUUF8UVQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@sveltejs/vite-plugin-svelte-inspector": "^5.0.0", "debug": "^4.4.1", @@ -3962,7 +3960,6 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -4013,7 +4010,6 @@ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -5249,7 +5245,8 @@ "integrity": "sha512-+R08/oI0nl3vfPcqftZRpytksBXDzOUveBq/NBVx0sUp1axwzPQrKinNx5yd5sxPu8j1wIy8AfnVQ+5eFdha6Q==", "dev": true, "license": "MIT", - "optional": true + "optional": true, + "peer": true }, "node_modules/cross-env": { "version": "10.1.0", @@ -5824,6 +5821,7 @@ "dev": true, "hasInstallScript": true, "license": "MIT", + "peer": true, "dependencies": { "@electron/asar": "^3.2.1", "debug": "^4.1.1", @@ -5844,6 +5842,7 @@ "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "graceful-fs": "^4.1.2", "jsonfile": "^4.0.0", @@ -5859,6 +5858,7 @@ "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", "dev": true, "license": "MIT", + "peer": true, "optionalDependencies": { "graceful-fs": "^4.1.6" } @@ -5869,6 +5869,7 @@ "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">= 4.0.0" } @@ -7668,7 +7669,6 @@ "integrity": "sha512-FIyV/64EkKhJmjgC0g2hygpBv5RNWVPyNCqSAD7eTCv6eFWNIi4PN1UvdSJGicN/o35bnevgis4Y0UDC0qi8jQ==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=14.0.0" } @@ -8235,7 +8235,6 @@ "integrity": "sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA==", "dev": true, "license": "MIT", - "peer": true, "bin": { "marked": "bin/marked.js" }, @@ -10779,7 +10778,6 @@ "dev": true, "inBundle": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -11527,6 +11525,7 @@ "dev": true, "license": "MIT", "optional": true, + "peer": true, "dependencies": { "commander": "^9.4.0" }, @@ -11544,6 +11543,7 @@ "dev": true, "license": "MIT", "optional": true, + "peer": true, "engines": { "node": "^12.20.0 || >=14" } @@ -12039,7 +12039,6 @@ "integrity": "sha512-6qGjWccl5yoyugHt3jTgztJ9Y0JVzyH8/Voc/D8PlLat9pwxQYXz7W1Dpnq5h0/G5GCYGUaDSlYcyk3AMh5A6g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@semantic-release/commit-analyzer": "^13.0.1", "@semantic-release/error": "^4.0.0", @@ -13198,7 +13197,6 @@ "integrity": "sha512-ynjfCHD3nP2el70kN5Pmg37sSi0EjOm9FgHYQdC4giWG/hzO3AatzXXJJgP305uIhGQxSufJLuYWtkY8uK/8RA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jridgewell/remapping": "^2.3.4", "@jridgewell/sourcemap-codec": "^1.5.0", @@ -13345,6 +13343,7 @@ "integrity": "sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "mkdirp": "^0.5.1", "rimraf": "~2.6.2" @@ -13395,6 +13394,7 @@ "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "minimist": "^1.2.6" }, @@ -13409,6 +13409,7 @@ "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, "license": "ISC", + "peer": true, "dependencies": { "glob": "^7.1.3" }, @@ -13578,7 +13579,6 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -13701,7 +13701,6 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -13945,7 +13944,6 @@ "integrity": "sha512-dZwN5L1VlUBewiP6H9s2+B3e3Jg96D0vzN+Ry73sOefebhYr9f94wwkMNN/9ouoU8pV1BqA1d1zGk8928cx0rg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", @@ -14039,7 +14037,6 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, diff --git a/src/lib/components/MediaGallery.svelte b/src/lib/components/MediaGallery.svelte index 5260dd6..0fd5f8f 100644 --- a/src/lib/components/MediaGallery.svelte +++ b/src/lib/components/MediaGallery.svelte @@ -696,13 +696,13 @@ onDestroy(() => { - + - +
{#each filteredMediaParticipants as participant (participant)} { {/if} · {#if lightboxItem.messageTimestamp} - {new Date(lightboxItem.messageTimestamp).toLocaleString()} + {new Date(lightboxItem.messageTimestamp).toLocaleString(getLocale())} {:else} {m.media_gallery_unknown_date()} {/if} diff --git a/src/lib/parser/chat-parser.ts b/src/lib/parser/chat-parser.ts index 97683e6..f1ac132 100644 --- a/src/lib/parser/chat-parser.ts +++ b/src/lib/parser/chat-parser.ts @@ -189,6 +189,23 @@ const DATE_PATTERNS = [ ); }, }, + // DD/MM/YY, HH:MM AM/PM - European/Brazilian format (12h) + { + regex: + /^(\d{1,2})\/(\d{1,2})\/(\d{2,4}),?\s+(\d{1,2}):(\d{2})(?::(\d{2}))?[\s\u202F\u00A0]*([AP]M)\s*-\s*/i, + parse: (match: RegExpMatchArray) => { + const [, day, month, year, hours, minutes, seconds, ampm] = match; + return parseDateTime( + parseInt(day, 10), + parseInt(month, 10), + normalizeYear(parseInt(year, 10)), + parseInt(hours, 10), + parseInt(minutes, 10), + seconds ? parseInt(seconds, 10) : 0, + ampm, + ); + }, + }, // DD/MM/YY, HH:MM - European/Brazilian format (24h) - No AM/PM means it's not US format { regex: @@ -253,6 +270,39 @@ const DATE_PATTERNS = [ ); }, }, + // DD.MM.YY HH:MM(:SS): - Dot date format with colon separator after time + { + regex: + /^(\d{1,2})\.(\d{1,2})\.(\d{2,4}),?\s+(\d{1,2}):(\d{2})(?::(\d{2}))?\s*:\s*/, + parse: (match: RegExpMatchArray) => { + const [, day, month, year, hours, minutes, seconds] = match; + return parseDateTime( + parseInt(day, 10), + parseInt(month, 10), + normalizeYear(parseInt(year, 10)), + parseInt(hours, 10), + parseInt(minutes, 10), + seconds ? parseInt(seconds, 10) : 0, + ); + }, + }, + // YYYY/MM/DD, HH:MM AM/PM - Asian format with 12-hour time + { + regex: + /^(\d{4})\/(\d{1,2})\/(\d{1,2}),?\s+(\d{1,2}):(\d{2})(?::(\d{2}))?[\s\u202F\u00A0]*([AP]M)\s*-\s*/i, + parse: (match: RegExpMatchArray) => { + const [, year, month, day, hours, minutes, seconds, ampm] = match; + return parseDateTime( + parseInt(day, 10), + parseInt(month, 10), + parseInt(year, 10), + parseInt(hours, 10), + parseInt(minutes, 10), + seconds ? parseInt(seconds, 10) : 0, + ampm, + ); + }, + }, // YYYY/MM/DD, HH:MM - Asian format { regex: @@ -269,6 +319,39 @@ const DATE_PATTERNS = [ ); }, }, + // [YYYY/MM/DD, HH:MM:SS AM/PM] - Bracketed year-first format with 12-hour time + { + regex: + /^\[(\d{4})\/(\d{1,2})\/(\d{1,2}),?\s+(\d{1,2}):(\d{2})(?::(\d{2}))?[\s\u202F\u00A0]*([AP]M)\]\s*/i, + parse: (match: RegExpMatchArray) => { + const [, year, month, day, hours, minutes, seconds, ampm] = match; + return parseDateTime( + parseInt(day, 10), + parseInt(month, 10), + parseInt(year, 10), + parseInt(hours, 10), + parseInt(minutes, 10), + seconds ? parseInt(seconds, 10) : 0, + ampm, + ); + }, + }, + // [YYYY/MM/DD, HH:MM:SS] - Bracketed year-first format (24-hour) + { + regex: + /^\[(\d{4})\/(\d{1,2})\/(\d{1,2}),?\s+(\d{1,2}):(\d{2})(?::(\d{2}))?\]\s*/, + parse: (match: RegExpMatchArray) => { + const [, year, month, day, hours, minutes, seconds] = match; + return parseDateTime( + parseInt(day, 10), + parseInt(month, 10), + parseInt(year, 10), + parseInt(hours, 10), + parseInt(minutes, 10), + seconds ? parseInt(seconds, 10) : 0, + ); + }, + }, // [DD/MM/YYYY, HH:MM:SS AM/PM] - iOS bracketed format with 12-hour time // Note: May contain Unicode whitespace characters (U+202F, U+00A0) before AM/PM // MUST be checked before non-AM/PM bracketed format @@ -306,6 +389,98 @@ const DATE_PATTERNS = [ }, ]; +type DatePattern = (typeof DATE_PATTERNS)[number]; + +const US_AMPM_PATTERN_INDEX = 0; +const DMY_AMPM_PATTERN_INDEX = 1; + +function normalizeLineForParsing(line: string): string { + return line + .replace(/^[\u200E\u200F]+/, '') + .replace(/[\u202F\u00A0]/g, ' ') + .replace(/\s+klo\s+/gi, ' ') + .replace( + /(\s\d{1,2})\.(\d{2})(?:\.(\d{2}))?(?=\s*(?:-|\]|:))/g, + (_, h, m, s) => `${h}:${m}${s ? `:${s}` : ''}`, + ) + .replace( + /\b([ap])\s*\.?\s*m\.?\b/gi, + (_, period: string) => `${period.toUpperCase()}M`, + ); +} + +function detectDatePatternOrder(lines: string[]): DatePattern[] { + const scores = new Array(DATE_PATTERNS.length).fill(0); + const sampleLines = lines.slice(0, 200); + let dayFirstSlashAmPmEvidence = 0; + let monthFirstSlashAmPmEvidence = 0; + + for (const line of sampleLines) { + if (!line.trim()) { + continue; + } + + const normalizedLine = normalizeLineForParsing(line); + + const slashAmPmMatch = normalizedLine.match( + /^(\d{1,2})\/(\d{1,2})\/(\d{2,4}),?\s+\d{1,2}:\d{2}(?::\d{2})?\s*[AP]M\s*-\s*/i, + ); + + if (slashAmPmMatch) { + const first = parseInt(slashAmPmMatch[1], 10); + const second = parseInt(slashAmPmMatch[2], 10); + + if (first > 12 && second <= 12) { + dayFirstSlashAmPmEvidence++; + } else if (second > 12 && first <= 12) { + monthFirstSlashAmPmEvidence++; + } + } + + for (let index = 0; index < DATE_PATTERNS.length; index++) { + const pattern = DATE_PATTERNS[index]; + if (pattern.regex.test(normalizedLine)) { + scores[index]++; + } + } + } + + let bestIndex = -1; + let bestScore = 0; + const tiedBestIndices: number[] = []; + + for (let index = 0; index < scores.length; index++) { + if (scores[index] > bestScore) { + bestScore = scores[index]; + bestIndex = index; + tiedBestIndices.length = 0; + tiedBestIndices.push(index); + } else if (scores[index] === bestScore && bestScore > 0) { + tiedBestIndices.push(index); + } + } + + if ( + tiedBestIndices.includes(US_AMPM_PATTERN_INDEX) && + tiedBestIndices.includes(DMY_AMPM_PATTERN_INDEX) + ) { + if (dayFirstSlashAmPmEvidence > monthFirstSlashAmPmEvidence) { + bestIndex = DMY_AMPM_PATTERN_INDEX; + } else if (monthFirstSlashAmPmEvidence > dayFirstSlashAmPmEvidence) { + bestIndex = US_AMPM_PATTERN_INDEX; + } + } + + if (bestIndex === -1 || bestScore === 0) { + return DATE_PATTERNS; + } + + return [ + DATE_PATTERNS[bestIndex], + ...DATE_PATTERNS.filter((_, index) => index !== bestIndex), + ]; +} + function normalizeYear(year: number): number { if (year < 100) { return year + (year > 50 ? 1900 : 2000); @@ -412,17 +587,22 @@ function isSystemMessage(content: string): boolean { ); } -function parseLine(line: string): { +function parseLine( + line: string, + datePatterns: DatePattern[] = DATE_PATTERNS, +): { timestamp: Date; sender: string; content: string; pattern: RegExp; } | null { - for (const { regex, parse } of DATE_PATTERNS) { - const match = line.match(regex); + const normalizedLine = normalizeLineForParsing(line); + + for (const { regex, parse } of datePatterns) { + const match = normalizedLine.match(regex); if (match) { const timestamp = parse(match); - const remainder = line.substring(match[0].length); + const remainder = normalizedLine.substring(match[0].length); // Try to extract sender and content // Format is usually: "Sender Name: message content" @@ -492,6 +672,7 @@ export function parseChat( filename: string = 'WhatsApp Chat', ): ParsedChat { const lines = content.split(/\r?\n/); + const datePatterns = detectDatePatternOrder(lines); const messages: ChatMessage[] = []; const participantsSet = new Set(); const usedIds = new Set(); // Track used IDs to handle collisions @@ -516,7 +697,7 @@ export function parseChat( for (const line of lines) { if (!line.trim()) continue; - const parsed = parseLine(line); + const parsed = parseLine(line, datePatterns); if (parsed) { // This is a new message - push previous one first From ec7c3daf1640735678a47fff490eb7303afa5eb0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 3 Mar 2026 00:17:54 +0000 Subject: [PATCH 2/3] fix: preserve original line content in parseLine for sender/content Co-authored-by: rodrigogs <2362425+rodrigogs@users.noreply.github.com> --- package-lock.json | 15 ---------- src/lib/parser/chat-parser.ts | 55 ++++++++++++++++++++++++++++++++++- 2 files changed, 54 insertions(+), 16 deletions(-) diff --git a/package-lock.json b/package-lock.json index 06dacc0..a1c325f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13260,21 +13260,6 @@ } } }, - "node_modules/svelte-check/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, "node_modules/tagged-tag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/tagged-tag/-/tagged-tag-1.0.0.tgz", diff --git a/src/lib/parser/chat-parser.ts b/src/lib/parser/chat-parser.ts index f1ac132..54d5291 100644 --- a/src/lib/parser/chat-parser.ts +++ b/src/lib/parser/chat-parser.ts @@ -587,6 +587,54 @@ function isSystemMessage(content: string): boolean { ); } +/** + * Compute the position in `originalLine` that corresponds to the end of the + * timestamp prefix whose normalized form has length `normalizedMatchLength`. + * + * `normalizeLineForParsing` makes five transforms; three of them change length: + * 1. Strips leading U+200E / U+200F directional marks (shortens) + * 2. Collapses `\s+klo\s+` → single space (shortens) + * 3. Rewrites `a.m.`/`p.m.` variants → `AM`/`PM` (shortens) + * The remaining two replace characters 1-for-1 (U+202F/U+00A0 → space; dot + * time separators → colon), so they do not shift positions. + * This function walks both strings in parallel to account for the differences. + */ +function getOriginalRemainderOffset( + originalLine: string, + normalizedMatchLength: number, +): number { + // Step 1: skip leading directional marks that normalization strips + const leadingMarks = originalLine.match(/^[\u200E\u200F]+/); + let origPos = leadingMarks ? leadingMarks[0].length : 0; + let normPos = 0; + + while (normPos < normalizedMatchLength && origPos < originalLine.length) { + const remaining = originalLine.substring(origPos); + + // Step 3: \s+klo\s+ → single space in normalized + const kloMatch = remaining.match(/^\s+klo\s+/i); + if (kloMatch) { + normPos += 1; // one space in normalized + origPos += kloMatch[0].length; + continue; + } + + // Step 5: a.m./p.m. variants → AM/PM in normalized (2 chars) + const ampmMatch = remaining.match(/^([ap])\s*\.?\s*m\.?\b/i); + if (ampmMatch) { + normPos += 2; + origPos += ampmMatch[0].length; + continue; + } + + // Steps 2 and 4 are 1-for-1 character replacements + normPos++; + origPos++; + } + + return origPos; +} + function parseLine( line: string, datePatterns: DatePattern[] = DATE_PATTERNS, @@ -602,7 +650,12 @@ function parseLine( const match = normalizedLine.match(regex); if (match) { const timestamp = parse(match); - const remainder = normalizedLine.substring(match[0].length); + + // Derive remainder from the original line so that sender/content + // preserve the exact exported text (and ID hashes stay stable). + // Normalization is used only for timestamp detection and parsing. + const splitOffset = getOriginalRemainderOffset(line, match[0].length); + const remainder = line.substring(splitOffset); // Try to extract sender and content // Format is usually: "Sender Name: message content" From 432bdb44f04ad9e3850430bc97ed47026385456a Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Wed, 1 Apr 2026 17:26:59 -0300 Subject: [PATCH 3/3] feat: add persistent conversation feature with cross-platform file restoration (#66) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: add persistent conversation feature with cross-platform file restoration Implement "Remember Conversation" toggle that persists chat sessions across app restarts using IndexedDB (idb-keyval). Three platform strategies: Electron file paths, Chromium FileSystemFileHandle, and fallback reselect for Firefox/Safari. New components: RestoreSessionModal, ReselectFileModal, Toast, Modal. Stores metadata, bookmarks, transcriptions, settings (~1MB). Never stores the ZIP file itself. * fix: resolve all 15 type errors in persistent conversations feature - Add File System Access API type declarations (FileSystemHandlePermissionDescriptor, OpenFilePickerOptions, FileSystemFileHandle augmentation, Window.showOpenFilePicker) to the global scope in src/app.d.ts - Register 7 missing icon names (alert-circle, folder, clock, check-all, x, check-circle, message-circle) in the Icon component with SVG path definitions - Add missing isElectronPathReference import in +page.svelte, which also resolves the union type narrowing error for filePath access * fix(electron): harden file:readFromPath IPC handler - Restrict to .zip files only to prevent path traversal attacks - Use async fs.promises.readFile() instead of blocking readFileSync() - Properly slice Buffer to ArrayBuffer using byteOffset/byteLength * fix(i18n): replace hardcoded English strings with Paraglide messages Replace hardcoded strings in RestoreSessionModal ("Select All", "Deselect All") and ReselectFileModal ("Drop WhatsApp ZIP file here", "or click below to browse", "Browse Files") with proper Paraglide i18n message calls. Added translations for all 10 supported languages. * fix(persistence): clean up IndexedDB entries when removing a remembered chat When a user removed a chat via handleRemoveChat(), persisted data in IndexedDB was not cleaned up, leaving orphaned entries that caused the restore modal to show stale chats. Now handleRemoveChat checks if the chat is in rememberedChats and, if so, finds and removes the persisted entry from IndexedDB before removing it from UI state. * fix(persistence): add error logging to silent catch blocks Add console.error/warn logging to five catch blocks in persistence.svelte.ts that were silently swallowing errors, making IndexedDB issues impossible to debug. * fix(ReselectFileModal): eliminate drag-drop flicker with counter pattern Replace boolean isDragging state with dragCounter pattern to fix visual flicker that occurred when dragging files over nested elements. The counter increments on dragenter and decrements on dragleave, preventing the rapid toggling that caused the flicker. * chore: remove AI handoff document * fix: clean up dead code, timer leaks, and unused imports * fix: resolve critical bugs and extract duplicated parse/index logic - Fix C2: restore loop now awaits user reselect via Promise pattern instead of continuing to next chat immediately - Fix C1: add one-time guard to $effect for persistence check - Fix C3: harden Electron file read with path normalization and symlink protection (lstat check) - DRY: extract startIndexWorker() and makeProgressCallback() from ~150 lines of duplicated code between handleFilesSelected and loadChatFromBuffer * fix: address final review items - Replace remaining hardcoded English strings with i18n messages - Filter transcriptions to only include current chat's message IDs when persisting (prevents cross-chat data leakage) - Add translations for new keys to all 9 non-English locales - Document chatFileReferences intentional non-reactive mutation * fix: translate all persistence keys and remove dead isRestoring state * refactor: deduplicate getBookmarksForChatAsExport * fix(electron): use file descriptor to prevent TOCTOU race in file read * refactor(Toast): replace inline SVGs with Icon component Replace inline SVG elements with the reusable Icon component for better code maintainability and consistency. The status icon now uses check-circle for success and alert-circle for error/info types, while the close button uses the x icon. * fix(a11y): add aria-label to drop zone and i18n Modal close label - Add aria-label to drop zone in ReselectFileModal for screen reader accessibility - Replace hardcoded 'Close modal' string with i18n key close_modal in Modal component - Add close_modal translations to all 10 locale files (en, pt, es, fr, de, it, nl, ja, zh, ru) * refactor: address all 13 review items Correctness: - #1: handleRemoveChat now removes from UI first (sync), cleans up IndexedDB in background to avoid stale index issues - #2: Remove redundant double-store of FileSystemFileHandle (savePersistedChat already handles it) - #3: Restored chats now populate chatFileReferences with persistedId to prevent orphaned duplicates on toggle Security: - #4: Use file descriptor with O_NOFOLLOW to prevent TOCTOU race in Electron file read IPC DRY: - #5: Extract LoadingChat interface to shared state.svelte.ts - #6: getBookmarksForChatAsExport delegates to getBookmarksForChat - #7: Extract sanitizeFilename helper to format.ts - #8: formatDate kept local (locale-aware, not extractable) - #9: Add addRemembered/removeRemembered helpers (5 call sites) i18n/Accessibility: - #10: Add aria-label to ReselectFileModal drop zone - #11: i18n Modal close label across 10 locales Clean Code: - #12: Split handleToggleRemember into rememberChat/forgetChat - #13: Toast uses Icon component instead of inline SVGs * fix: address all 9 Copilot review comments 1. Capture Electron file.path from drag-drop for persistence 2. Block metadata restoration when file validation fails 3. Deduplicate savePersistedChat (removes existing entry first) 4. Filter transcriptions by chat message IDs (prevents cross-chat leak) 5. Case-insensitive .zip check in ReselectFileModal 6. Clamp dragCounter to 0 minimum 7. Use isAbsolute + reject .. segments for Electron path validation 8. Guard error.message with instanceof Error check 9. Add keyboard/click handlers to drop zone for accessibility * fix: address 3 new Copilot review comments - Seed rememberedChats from IndexedDB on load so toggle state is correct even when user skips restore modal or clicks Start Fresh - Fix verifyHandlePermission docstring to reflect shouldRequest param - Use chatId+messageId composite key for bookmark import dedup to prevent cross-chat bookmark collisions * fix: capture FileSystemFileHandle during drag-drop for seamless persistence - Use DataTransferItem.getAsFileSystemHandle() during drop event to capture handles without showing a second file picker (Chrome 86+) - Remove promptForFileHandle() call from rememberChat — handles are now captured at drag-drop time, eliminating the confusing double- file-picker UX - Update reselect flow to capture Electron file.path and update the persisted entry so future restores work automatically - Add DataTransferItem.getAsFileSystemHandle type declaration * fix: capture file handles synchronously during drop and fix closure bug - Start all getAsFileSystemHandle() Promises synchronously via Promise.all before any await, preventing DataTransferItem invalidation after first async tick - Capture handleIndex and file path BEFORE the async IIFE to avoid closure-over-loop-variable bug where stale index was read after multiple awaits * fix: pass Electron file path from dialog to persistence layer The Electron file picker (openFile dialog) returns the absolute path but it was discarded when creating the File object from the buffer. This caused all Electron-picked files to be stored as 'reselect-required' instead of 'electron-path', forcing manual reselection on every restore. Now FileDropZone passes the path from Electron's dialog result via a new 'paths' callback parameter. handleFilesSelected prefers this explicit path over file.path (drag-drop fallback). * debug: add persistence flow logging to trace Electron path issue * fix: address 4 Copilot review comments - Toast: reset visibility and restart timer when message prop changes - FileDropZone: use showOpenFilePicker() on Chrome for file input to capture FileSystemFileHandle (drag-drop already captures handles; this fixes the regular "click to browse" flow) - Remove unused isFileSystemAccessSupported import from +page.svelte - Electron dialog path already fixed (result.path passed via paths callback parameter) * fix: address 3 Copilot review comments - Electron IPC: add lstat pre-check for cross-platform symlink rejection (O_NOFOLLOW not supported on Windows), with graceful fallback to O_RDONLY when O_NOFOLLOW unavailable - FileDropZone: enable multi-select in showOpenFilePicker to match the existing behavior - CSS: use :where(button) for low-specificity cursor rule so Tailwind utilities can override it * fix: ReselectFileModal uses Electron dialog to capture file path The reselect modal was using the web file input which doesn't capture the absolute file path in Electron. Now uses the Electron native dialog (electronAPI.openFile) which returns the path, and passes it through to updatePersistedChat so the entry is upgraded from 'reselect-required' to 'electron-path'. After one reselect, future restores work automatically. * fix: move Remember Conversation above Transcription Language in context menu * fix: ReselectFileModal captures FileSystemFileHandle on Chrome and upgrades persisted entries The reselect modal was using plain on Chrome, which doesn't capture a FileSystemFileHandle. This meant even after reselecting, the entry stayed as 'reselect-required' and the user would be prompted again on every restart. Now: - Chrome/Edge: uses showOpenFilePicker() to capture a handle, then upgrades the persisted entry from 'reselect-required' to 'file-handle' via storeFileHandle + updatePersistedChat - Electron: uses native dialog to capture path, upgrades to 'electron-path' - Drag-drop in reselect modal also captures handle via getAsFileSystemHandle() After one reselect, future restores work automatically on all platforms. * fix: removing chat from list no longer deletes persisted data Removing a chat only clears it from the current session. Persisted data in IndexedDB is preserved so the chat reappears in the restore modal on next launch. To permanently forget a chat, user must toggle Remember Conversation off. * chore: remove debug logging from persistence flow * fix: sidebar import uses Electron dialog and captures file path The sidebar "Import chat" button was using a plain which doesn't reliably provide file.path in Electron. Now uses the same platform-aware import as the main drop zone: - Electron: native dialog via electronAPI.openFile() with path capture - Chrome/Edge: showOpenFilePicker() with handle capture - Fallback: regular file input Also fixes Node.js Buffer pool issue in dialog:openFile handler (was sending entire shared ArrayBuffer instead of just the file's portion). * refactor: address all review items - dead code, DRY, a11y, error feedback - Replace dynamic import of storeFileHandle with static import - Remove 6 unused i18n keys from all 10 locale files - Remove dead exports: promptForFileHandle, getPersistedChat, getBookmarksForChatAsExport - Add error toast on restore failure in handleRestoreChats - Extract shared file-picker helpers (openZipFilePicker, openElectronFile, getElectronFilePath) - Add aria-label to FileDropZone drop zone - Rename persistence_close_notification to close_notification in Toast * refactor: centralize modals, fix cross-chat ID collisions, address review feedback - Extract ChatAvatar component replacing 3 inline avatar implementations - Add shared formatRelativeDate helper (label/compact modes) - Add Button size="lg" variant with disabled styles - Vertically center Modal on all breakpoints, not just desktop - RestoreSessionModal: remove description banner, only chat list scrolls, fixed footer with action buttons - Fix message ID collisions across chats by including filename in hash - Fix Toast timer not restarting when message changes while visible - Gate reselect flow: only upgrade persisted entry when validation passes - Add persistence_restore_failed i18n key across all 10 locales - Remove unused isFileSystemAccessSupported import and function --------- Co-authored-by: Rodrigo Gomes da Silva --- electron/main.cjs | 57 +- electron/preload.cjs | 4 + messages/de.json | 26 +- messages/en.json | 25 +- messages/es.json | 26 +- messages/fr.json | 26 +- messages/it.json | 26 +- messages/ja.json | 26 +- messages/nl.json | 26 +- messages/pt.json | 26 +- messages/ru.json | 26 +- messages/zh.json | 26 +- package-lock.json | 1541 +++++++---------- package.json | 1 + src/app.css | 9 + src/app.d.ts | 39 + src/lib/bookmarks.svelte.ts | 8 +- src/lib/components/Button.svelte | 5 +- src/lib/components/ChatAvatar.svelte | 39 + src/lib/components/ChatList.svelte | 80 +- src/lib/components/FileDropZone.svelte | 73 +- src/lib/components/Icon.svelte | 47 +- src/lib/components/Modal.svelte | 13 +- src/lib/components/ModalContent.svelte | 2 +- src/lib/components/ReselectFileModal.svelte | 205 +++ src/lib/components/RestoreSessionModal.svelte | 177 ++ src/lib/components/Toast.svelte | 78 + src/lib/components/index.ts | 3 + src/lib/helpers/file-picker.ts | 66 + src/lib/helpers/format.ts | 67 + src/lib/parser/chat-parser.ts | 8 +- src/lib/persistence.svelte.ts | 562 ++++++ src/lib/state.svelte.ts | 7 + src/lib/transcription.svelte.ts | 30 + src/routes/+page.svelte | 690 ++++++-- 35 files changed, 3005 insertions(+), 1065 deletions(-) create mode 100644 src/lib/components/ChatAvatar.svelte create mode 100644 src/lib/components/ReselectFileModal.svelte create mode 100644 src/lib/components/RestoreSessionModal.svelte create mode 100644 src/lib/components/Toast.svelte create mode 100644 src/lib/helpers/file-picker.ts create mode 100644 src/lib/helpers/format.ts create mode 100644 src/lib/persistence.svelte.ts diff --git a/electron/main.cjs b/electron/main.cjs index fc4c8c1..957bfa4 100644 --- a/electron/main.cjs +++ b/electron/main.cjs @@ -182,7 +182,11 @@ ipcMain.handle('dialog:openFile', async () => { return { path: filePath, name: fileName, - buffer: fileContent.buffer, + // Slice the buffer to avoid sending the entire Node.js Buffer pool + buffer: fileContent.buffer.slice( + fileContent.byteOffset, + fileContent.byteOffset + fileContent.byteLength, + ), }; }); @@ -227,6 +231,57 @@ ipcMain.handle('fs:fileExists', async (_event, filePath) => { return fs.existsSync(filePath); }); +// Read file from absolute path (for persistence) +ipcMain.handle('file:readFromPath', async (_event, filePath) => { + try { + if (typeof filePath !== 'string') { + return { success: false, error: 'Invalid file path' }; + } + const normalized = path.resolve(filePath); + // Require absolute path and reject path traversal segments + if (!path.isAbsolute(filePath)) { + return { success: false, error: 'Invalid file path' }; + } + if (filePath.split(/[/\\]+/).includes('..')) { + return { success: false, error: 'Invalid file path' }; + } + if (path.extname(normalized).toLowerCase() !== '.zip') { + return { success: false, error: 'Only .zip files are allowed' }; + } + + // Pre-check with lstat to reject symlinks (works cross-platform including Windows) + const lst = await fs.promises.lstat(normalized); + if (!lst.isFile() || lst.isSymbolicLink()) { + return { success: false, error: 'Path is not a regular file' }; + } + + // Use O_NOFOLLOW when available to reject symlinks atomically (not supported on Windows) + const openFlags = + typeof fs.constants.O_NOFOLLOW === 'number' + ? fs.constants.O_RDONLY | fs.constants.O_NOFOLLOW + : fs.constants.O_RDONLY; + const fd = await fs.promises.open(normalized, openFlags); + try { + const content = await fd.readFile(); + return { + success: true, + buffer: content.buffer.slice( + content.byteOffset, + content.byteOffset + content.byteLength, + ), + name: path.basename(normalized), + }; + } finally { + await fd.close(); + } + } catch (error) { + return { + success: false, + error: error instanceof Error ? error.message : String(error), + }; + } +}); + ipcMain.handle('shell:openExternal', async (_event, url) => { // Validate URL before opening if (!url.startsWith('https://github.com/rodrigogs/whats-reader')) { diff --git a/electron/preload.cjs b/electron/preload.cjs index 2d42d89..8aa55e7 100644 --- a/electron/preload.cjs +++ b/electron/preload.cjs @@ -12,6 +12,10 @@ contextBridge.exposeInMainWorld('electronAPI', { readDir: (dirPath) => ipcRenderer.invoke('fs:readDir', dirPath), fileExists: (filePath) => ipcRenderer.invoke('fs:fileExists', filePath), + // Persistence file operations + readFileFromPath: (filePath) => + ipcRenderer.invoke('file:readFromPath', filePath), + // External links openExternal: (url) => ipcRenderer.invoke('shell:openExternal', url), diff --git a/messages/de.json b/messages/de.json index fec2c18..11837b1 100644 --- a/messages/de.json +++ b/messages/de.json @@ -181,6 +181,7 @@ "update_never_tooltip": "Nie Update-Benachrichtigungen anzeigen", "version_view_releases": "Versionen auf GitHub anzeigen", "close": "Schließen", + "close_modal": "Modal schließen", "update_ready": "Update bereit", "update_downloading": "Update wird heruntergeladen", "update_close": "Aktualisierungsbenachrichtigung schließen", @@ -241,5 +242,26 @@ "media_gallery_type_other": "Andere", "media_gallery_clear_filter": "Filter löschen", "media_gallery_participant_search_placeholder": "Suche nach Name oder Nummer...", - "media_gallery_participant_no_match": "Kein Teilnehmer entspricht \"{query}\"" -} + "persistence_remember_conversation": "Unterhaltung Merken", + "persistence_conversation_saved": "Die Unterhaltung wird gespeichert", + "persistence_conversation_removed": "Unterhaltung aus gespeicherten Sitzungen entfernt", + "persistence_restore_title": "Gespeicherte Unterhaltungen Wiederherstellen", + "persistence_restore_description": "Sie haben gespeicherte Unterhaltungen aus früheren Sitzungen:", + "persistence_restore_button": "Ausgewählte Wiederherstellen ({count})", + "persistence_start_fresh": "Neu Beginnen", + "persistence_dont_show_again": "Nicht mehr anzeigen", + "persistence_last_opened": "Zuletzt geöffnet: {date}", + "persistence_message_count": "{count} Nachrichten", + "persistence_reselect_title": "Bitte Datei Erneut Auswählen", + "persistence_reselect_description": "Um \"{chatTitle}\" wiederherzustellen, wählen Sie bitte die Originaldatei aus:", + "persistence_skip": "Überspringen", + "persistence_select_all": "Alle auswählen", + "persistence_deselect_all": "Alle abwählen", + "persistence_drop_zip": "WhatsApp-ZIP-Datei hier ablegen", + "persistence_or_browse": "oder klicken Sie unten zum Durchsuchen", + "persistence_browse_files": "Dateien durchsuchen", + "persistence_save_failed": "Fehler beim Speichern der Unterhaltung", + "persistence_restore_failed": "Fehler beim Wiederherstellen der Unterhaltung", + "persistence_remove_failed": "Fehler beim Entfernen der Unterhaltung", + "close_notification": "Benachrichtigung schließen" +} \ No newline at end of file diff --git a/messages/en.json b/messages/en.json index dcc7388..a155142 100644 --- a/messages/en.json +++ b/messages/en.json @@ -231,6 +231,7 @@ "calendar_weekday_fri": "Fr", "calendar_weekday_sat": "Sa", "close": "Close", + "close_modal": "Close modal", "media_gallery_options": "Options", "media_gallery_filter_by_participant": "Filter by participant", "media_gallery_filter_by_type": "Filter by type", @@ -241,5 +242,27 @@ "media_gallery_type_other": "Other", "media_gallery_clear_filter": "Clear filter", "media_gallery_participant_search_placeholder": "Search by name or number...", - "media_gallery_participant_no_match": "No participant matches \"{query}\"" + "media_gallery_participant_no_match": "No participant matches \"{query}\"", + "persistence_remember_conversation": "Remember Conversation", + "persistence_conversation_saved": "Conversation will be remembered", + "persistence_conversation_removed": "Conversation removed from saved sessions", + "persistence_restore_title": "Restore Saved Conversations", + "persistence_restore_description": "You have saved conversations from previous sessions:", + "persistence_restore_button": "Restore Selected ({count})", + "persistence_start_fresh": "Start Fresh", + "persistence_dont_show_again": "Don't show this again", + "persistence_last_opened": "Last opened: {date}", + "persistence_message_count": "{count} messages", + "persistence_reselect_title": "Please Re-select File", + "persistence_reselect_description": "To restore \"{chatTitle}\", please select the original file:", + "persistence_skip": "Skip", + "persistence_select_all": "Select All", + "persistence_deselect_all": "Deselect All", + "persistence_drop_zip": "Drop WhatsApp ZIP file here", + "persistence_or_browse": "or click below to browse", + "persistence_browse_files": "Browse Files", + "persistence_save_failed": "Failed to save conversation", + "persistence_restore_failed": "Failed to restore conversation", + "persistence_remove_failed": "Failed to remove conversation", + "close_notification": "Close notification" } diff --git a/messages/es.json b/messages/es.json index 06862b9..969638b 100644 --- a/messages/es.json +++ b/messages/es.json @@ -181,6 +181,7 @@ "update_never_tooltip": "Nunca mostrar notificaciones de actualización", "version_view_releases": "Ver versiones en GitHub", "close": "Cerrar", + "close_modal": "Cerrar modal", "update_ready": "Actualización lista", "update_downloading": "Descargando actualización", "update_close": "Cerrar notificación de actualización", @@ -241,5 +242,26 @@ "media_gallery_type_other": "Otro", "media_gallery_clear_filter": "Limpiar filtro", "media_gallery_participant_search_placeholder": "Buscar por nombre o número...", - "media_gallery_participant_no_match": "Ningún participante coincide con \"{query}\"" -} + "persistence_remember_conversation": "Recordar Conversación", + "persistence_conversation_saved": "La conversación será recordada", + "persistence_conversation_removed": "Conversación eliminada de las sesiones guardadas", + "persistence_restore_title": "Restaurar Conversaciones Guardadas", + "persistence_restore_description": "Tienes conversaciones guardadas de sesiones anteriores:", + "persistence_restore_button": "Restaurar Seleccionadas ({count})", + "persistence_start_fresh": "Empezar de Nuevo", + "persistence_dont_show_again": "No mostrar de nuevo", + "persistence_last_opened": "Última apertura: {date}", + "persistence_message_count": "{count} mensajes", + "persistence_reselect_title": "Por Favor, Selecciona el Archivo de Nuevo", + "persistence_reselect_description": "Para restaurar \"{chatTitle}\", selecciona el archivo original:", + "persistence_skip": "Omitir", + "persistence_select_all": "Seleccionar Todo", + "persistence_deselect_all": "Deseleccionar Todo", + "persistence_drop_zip": "Suelta el archivo ZIP de WhatsApp aquí", + "persistence_or_browse": "o haz clic abajo para buscar", + "persistence_browse_files": "Buscar Archivos", + "persistence_save_failed": "Error al guardar la conversación", + "persistence_restore_failed": "Error al restaurar la conversación", + "persistence_remove_failed": "Error al eliminar la conversación", + "close_notification": "Cerrar notificación" +} \ No newline at end of file diff --git a/messages/fr.json b/messages/fr.json index 7810134..57915a6 100644 --- a/messages/fr.json +++ b/messages/fr.json @@ -181,6 +181,7 @@ "update_never_tooltip": "Ne jamais afficher les notifications de mise à jour", "version_view_releases": "Voir les versions sur GitHub", "close": "Fermer", + "close_modal": "Fermer la boîte de dialogue", "update_ready": "Prêt pour la mise à jour", "update_downloading": "Téléchargement de la mise à jour", "update_close": "Fermer la notification de mise à jour", @@ -241,5 +242,26 @@ "media_gallery_type_other": "Autre", "media_gallery_clear_filter": "Effacer le filtre", "media_gallery_participant_search_placeholder": "Recherche par nom ou numéro...", - "media_gallery_participant_no_match": "Aucun participant ne correspond à \"{query}\"" -} + "persistence_remember_conversation": "Mémoriser la Conversation", + "persistence_conversation_saved": "La conversation sera mémorisée", + "persistence_conversation_removed": "Conversation supprimée des sessions enregistrées", + "persistence_restore_title": "Restaurer les Conversations Sauvegardées", + "persistence_restore_description": "Vous avez des conversations sauvegardées de sessions précédentes :", + "persistence_restore_button": "Restaurer la Sélection ({count})", + "persistence_start_fresh": "Repartir à Zéro", + "persistence_dont_show_again": "Ne plus afficher", + "persistence_last_opened": "Dernière ouverture : {date}", + "persistence_message_count": "{count} messages", + "persistence_reselect_title": "Veuillez Resélectionner le Fichier", + "persistence_reselect_description": "Pour restaurer \"{chatTitle}\", veuillez sélectionner le fichier original :", + "persistence_skip": "Ignorer", + "persistence_select_all": "Tout sélectionner", + "persistence_deselect_all": "Tout désélectionner", + "persistence_drop_zip": "Déposez le fichier ZIP WhatsApp ici", + "persistence_or_browse": "ou cliquez ci-dessous pour parcourir", + "persistence_browse_files": "Parcourir les fichiers", + "persistence_save_failed": "Échec de l'enregistrement de la conversation", + "persistence_restore_failed": "Échec de la restauration de la conversation", + "persistence_remove_failed": "Échec de la suppression de la conversation", + "close_notification": "Fermer la notification" +} \ No newline at end of file diff --git a/messages/it.json b/messages/it.json index c1d9749..2ffcf1e 100644 --- a/messages/it.json +++ b/messages/it.json @@ -181,6 +181,7 @@ "update_never_tooltip": "Non mostrare mai notifiche di aggiornamento", "version_view_releases": "Visualizza le versioni su GitHub", "close": "Chiudi", + "close_modal": "Chiudi finestra modale", "update_ready": "Aggiornamento pronto", "update_downloading": "Download dell'aggiornamento", "update_close": "Chiudi notifica di aggiornamento", @@ -241,5 +242,26 @@ "media_gallery_type_other": "Altro", "media_gallery_clear_filter": "Cancella filtro", "media_gallery_participant_search_placeholder": "Cerca per nome o numero...", - "media_gallery_participant_no_match": "Nessun partecipante corrisponde a \"{query}\"" -} + "persistence_remember_conversation": "Ricorda Conversazione", + "persistence_conversation_saved": "La conversazione verrà ricordata", + "persistence_conversation_removed": "Conversazione rimossa dalle sessioni salvate", + "persistence_restore_title": "Ripristina Conversazioni Salvate", + "persistence_restore_description": "Hai conversazioni salvate da sessioni precedenti:", + "persistence_restore_button": "Ripristina Selezionate ({count})", + "persistence_start_fresh": "Ricomincia da Zero", + "persistence_dont_show_again": "Non mostrare più", + "persistence_last_opened": "Ultima apertura: {date}", + "persistence_message_count": "{count} messaggi", + "persistence_reselect_title": "Seleziona Nuovamente il File", + "persistence_reselect_description": "Per ripristinare \"{chatTitle}\", seleziona il file originale:", + "persistence_skip": "Salta", + "persistence_select_all": "Seleziona tutto", + "persistence_deselect_all": "Deseleziona tutto", + "persistence_drop_zip": "Trascina qui il file ZIP di WhatsApp", + "persistence_or_browse": "o clicca sotto per sfogliare", + "persistence_browse_files": "Sfoglia file", + "persistence_save_failed": "Impossibile salvare la conversazione", + "persistence_restore_failed": "Impossibile ripristinare la conversazione", + "persistence_remove_failed": "Impossibile rimuovere la conversazione", + "close_notification": "Chiudi notifica" +} \ No newline at end of file diff --git a/messages/ja.json b/messages/ja.json index fed388d..c59d405 100644 --- a/messages/ja.json +++ b/messages/ja.json @@ -181,6 +181,7 @@ "update_never_tooltip": "アップデート通知を表示しない", "version_view_releases": "GitHubでリリースを見る", "close": "閉じる", + "close_modal": "モーダルを閉じる", "update_ready": "アップデート準備完了", "update_downloading": "アップデートをダウンロード中", "update_close": "更新通知を閉じる", @@ -241,5 +242,26 @@ "media_gallery_type_other": "他の", "media_gallery_clear_filter": "フィルターをクリア", "media_gallery_participant_search_placeholder": "名前または番号で検索...", - "media_gallery_participant_no_match": "「{query}」に一致する参加者はいません" -} + "persistence_remember_conversation": "会話を記憶", + "persistence_conversation_saved": "会話が記憶されます", + "persistence_conversation_removed": "保存済みセッションから会話が削除されました", + "persistence_restore_title": "保存済みの会話を復元", + "persistence_restore_description": "以前のセッションから保存された会話があります:", + "persistence_restore_button": "選択した会話を復元 ({count})", + "persistence_start_fresh": "新しく始める", + "persistence_dont_show_again": "今後表示しない", + "persistence_last_opened": "最終オープン: {date}", + "persistence_message_count": "{count} 件のメッセージ", + "persistence_reselect_title": "ファイルを再選択してください", + "persistence_reselect_description": "\"{chatTitle}\" を復元するには、元のファイルを選択してください:", + "persistence_skip": "スキップ", + "persistence_select_all": "すべて選択", + "persistence_deselect_all": "すべて解除", + "persistence_drop_zip": "WhatsAppのZIPファイルをここにドロップ", + "persistence_or_browse": "または下をクリックして参照", + "persistence_browse_files": "ファイルを参照", + "persistence_save_failed": "会話の保存に失敗しました", + "persistence_restore_failed": "会話の復元に失敗しました", + "persistence_remove_failed": "会話の削除に失敗しました", + "close_notification": "通知を閉じる" +} \ No newline at end of file diff --git a/messages/nl.json b/messages/nl.json index 9556db4..8495470 100644 --- a/messages/nl.json +++ b/messages/nl.json @@ -181,6 +181,7 @@ "update_never_tooltip": "Nooit updatemeldingen tonen", "version_view_releases": "Bekijk releases op GitHub", "close": "Sluiten", + "close_modal": "Venster sluiten", "update_ready": "Update gereed", "update_downloading": "Update downloaden", "update_close": "Sluit de updatemelding", @@ -241,5 +242,26 @@ "media_gallery_type_other": "Ander", "media_gallery_clear_filter": "Filter wissen", "media_gallery_participant_search_placeholder": "Zoeken op naam of nummer...", - "media_gallery_participant_no_match": "Geen deelnemer komt overeen met \"{query}\"" -} + "persistence_remember_conversation": "Gesprek Onthouden", + "persistence_conversation_saved": "Het gesprek wordt onthouden", + "persistence_conversation_removed": "Gesprek verwijderd uit opgeslagen sessies", + "persistence_restore_title": "Opgeslagen Gesprekken Herstellen", + "persistence_restore_description": "U heeft opgeslagen gesprekken van eerdere sessies:", + "persistence_restore_button": "Geselecteerde Herstellen ({count})", + "persistence_start_fresh": "Opnieuw Beginnen", + "persistence_dont_show_again": "Niet meer tonen", + "persistence_last_opened": "Laatst geopend: {date}", + "persistence_message_count": "{count} berichten", + "persistence_reselect_title": "Selecteer het Bestand Opnieuw", + "persistence_reselect_description": "Om \"{chatTitle}\" te herstellen, selecteer het originele bestand:", + "persistence_skip": "Overslaan", + "persistence_select_all": "Alles selecteren", + "persistence_deselect_all": "Alles deselecteren", + "persistence_drop_zip": "WhatsApp ZIP-bestand hier neerzetten", + "persistence_or_browse": "of klik hieronder om te bladeren", + "persistence_browse_files": "Bestanden bladeren", + "persistence_save_failed": "Gesprek opslaan mislukt", + "persistence_restore_failed": "Gesprek herstellen mislukt", + "persistence_remove_failed": "Gesprek verwijderen mislukt", + "close_notification": "Melding sluiten" +} \ No newline at end of file diff --git a/messages/pt.json b/messages/pt.json index 18d91b2..c7a9097 100644 --- a/messages/pt.json +++ b/messages/pt.json @@ -181,6 +181,7 @@ "update_never_tooltip": "Nunca mostrar notificações de atualização", "version_view_releases": "Ver versões no GitHub", "close": "Fechar", + "close_modal": "Fechar modal", "update_ready": "Atualização pronta", "update_downloading": "Baixando atualização", "update_close": "Fechar notificação de atualização", @@ -241,5 +242,26 @@ "media_gallery_type_other": "Outro", "media_gallery_clear_filter": "Limpar filtro", "media_gallery_participant_search_placeholder": "Pesquisar por nome ou número...", - "media_gallery_participant_no_match": "Nenhum participante corresponde a \"{query}\"" -} + "persistence_remember_conversation": "Lembrar Conversa", + "persistence_conversation_saved": "A conversa será lembrada", + "persistence_conversation_removed": "Conversa removida das sessões salvas", + "persistence_restore_title": "Restaurar Conversas Salvas", + "persistence_restore_description": "Você tem conversas salvas de sessões anteriores:", + "persistence_restore_button": "Restaurar Selecionadas ({count})", + "persistence_start_fresh": "Começar do Zero", + "persistence_dont_show_again": "Não mostrar novamente", + "persistence_last_opened": "Última abertura: {date}", + "persistence_message_count": "{count} mensagens", + "persistence_reselect_title": "Por Favor, Selecione o Arquivo Novamente", + "persistence_reselect_description": "Para restaurar \"{chatTitle}\", selecione o arquivo original:", + "persistence_skip": "Pular", + "persistence_select_all": "Selecionar Tudo", + "persistence_deselect_all": "Desmarcar Tudo", + "persistence_drop_zip": "Solte o arquivo ZIP do WhatsApp aqui", + "persistence_or_browse": "ou clique abaixo para procurar", + "persistence_browse_files": "Procurar Arquivos", + "persistence_save_failed": "Falha ao salvar conversa", + "persistence_restore_failed": "Falha ao restaurar conversa", + "persistence_remove_failed": "Falha ao remover conversa", + "close_notification": "Fechar notificação" +} \ No newline at end of file diff --git a/messages/ru.json b/messages/ru.json index 7c76d60..08989ad 100644 --- a/messages/ru.json +++ b/messages/ru.json @@ -181,6 +181,7 @@ "update_never_tooltip": "Никогда не показывать уведомления об обновлениях", "version_view_releases": "Посмотреть релизы на GitHub", "close": "Закрыть", + "close_modal": "Закрыть модальное окно", "update_ready": "Обновление готово", "update_downloading": "Загрузка обновления", "update_close": "Закрыть уведомление об обновлении", @@ -241,5 +242,26 @@ "media_gallery_type_other": "Другой", "media_gallery_clear_filter": "Очистить фильтр", "media_gallery_participant_search_placeholder": "Поиск по имени или номеру...", - "media_gallery_participant_no_match": "Ни один участник не соответствует \"{query}\"" -} + "persistence_remember_conversation": "Запомнить Разговор", + "persistence_conversation_saved": "Разговор будет сохранён", + "persistence_conversation_removed": "Разговор удалён из сохранённых сессий", + "persistence_restore_title": "Восстановить Сохранённые Разговоры", + "persistence_restore_description": "У вас есть сохранённые разговоры из предыдущих сессий:", + "persistence_restore_button": "Восстановить Выбранные ({count})", + "persistence_start_fresh": "Начать Заново", + "persistence_dont_show_again": "Больше не показывать", + "persistence_last_opened": "Последнее открытие: {date}", + "persistence_message_count": "{count} сообщений", + "persistence_reselect_title": "Пожалуйста, Выберите Файл Заново", + "persistence_reselect_description": "Чтобы восстановить \"{chatTitle}\", выберите исходный файл:", + "persistence_skip": "Пропустить", + "persistence_select_all": "Выбрать все", + "persistence_deselect_all": "Снять выбор", + "persistence_drop_zip": "Перетащите ZIP-файл WhatsApp сюда", + "persistence_or_browse": "или нажмите ниже для поиска", + "persistence_browse_files": "Обзор файлов", + "persistence_save_failed": "Не удалось сохранить разговор", + "persistence_restore_failed": "Не удалось восстановить разговор", + "persistence_remove_failed": "Не удалось удалить разговор", + "close_notification": "Закрыть уведомление" +} \ No newline at end of file diff --git a/messages/zh.json b/messages/zh.json index 76e59ce..aa73049 100644 --- a/messages/zh.json +++ b/messages/zh.json @@ -181,6 +181,7 @@ "update_never_tooltip": "不再显示更新通知", "version_view_releases": "在 GitHub 上查看版本", "close": "关闭", + "close_modal": "关闭对话框", "update_ready": "更新准备就绪", "update_downloading": "正在下载更新", "update_close": "关闭更新通知", @@ -241,5 +242,26 @@ "media_gallery_type_other": "其他", "media_gallery_clear_filter": "清除过滤器", "media_gallery_participant_search_placeholder": "按名称或编号搜索……", - "media_gallery_participant_no_match": "没有参与者匹配\"{query}\"" -} + "persistence_remember_conversation": "记住对话", + "persistence_conversation_saved": "对话将被记住", + "persistence_conversation_removed": "对话已从保存的会话中移除", + "persistence_restore_title": "恢复已保存的对话", + "persistence_restore_description": "您有来自之前会话的已保存对话:", + "persistence_restore_button": "恢复所选 ({count})", + "persistence_start_fresh": "重新开始", + "persistence_dont_show_again": "不再显示", + "persistence_last_opened": "上次打开: {date}", + "persistence_message_count": "{count} 条消息", + "persistence_reselect_title": "请重新选择文件", + "persistence_reselect_description": "要恢复\"{chatTitle}\",请选择原始文件:", + "persistence_skip": "跳过", + "persistence_select_all": "全选", + "persistence_deselect_all": "取消全选", + "persistence_drop_zip": "将WhatsApp ZIP文件拖放到此处", + "persistence_or_browse": "或点击下方浏览", + "persistence_browse_files": "浏览文件", + "persistence_save_failed": "保存对话失败", + "persistence_restore_failed": "恢复对话失败", + "persistence_remove_failed": "删除对话失败", + "close_notification": "关闭通知" +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index a81bf53..4f065f6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "@floating-ui/dom": "^1.7.4", "@huggingface/transformers": "^3.8.1", "electron-updater": "^6.6.2", + "idb-keyval": "^6.2.2", "jszip": "^3.10.1" }, "devDependencies": { @@ -61,27 +62,24 @@ } }, "node_modules/@actions/http-client": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-3.0.0.tgz", - "integrity": "sha512-1s3tXAfVMSz9a4ZEBkXXRQD4QhY3+GAsWSbaYpeknPOKEeyRiU3lH+bHiLMZdo2x/fIeQ/hscL1wCkDLVM2DZQ==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-3.0.2.tgz", + "integrity": "sha512-JP38FYYpyqvUsz+Igqlc/JG6YO9PaKuvqjM3iGvaLqFnJ7TFmcLyy2IDrY0bI0qCQug8E9K+elv5ZNfw62ZJzA==", "dev": true, "license": "MIT", "dependencies": { "tunnel": "^0.0.6", - "undici": "^5.28.5" + "undici": "^6.23.0" } }, "node_modules/@actions/http-client/node_modules/undici": { - "version": "5.29.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz", - "integrity": "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==", + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.23.0.tgz", + "integrity": "sha512-VfQPToRA5FZs/qJxLIinmU59u0r7LXqoJkCzinq3ckNJp3vKEh7jTWN589YQ5+aoAC/TGRLyJLCPKcLQbM8r9g==", "dev": true, "license": "MIT", - "dependencies": { - "@fastify/busboy": "^2.0.0" - }, "engines": { - "node": ">=14.0" + "node": ">=18.17" } }, "node_modules/@actions/io": { @@ -309,9 +307,9 @@ } }, "node_modules/@electron/asar": { - "version": "3.2.18", - "resolved": "https://registry.npmjs.org/@electron/asar/-/asar-3.2.18.tgz", - "integrity": "sha512-2XyvMe3N3Nrs8cV39IKELRHTYUWFKrmqqSY1U+GMlc0jvqjIVnoxhNd2H4JolWQncbJi1DCvb5TNxZuI2fEjWg==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@electron/asar/-/asar-3.4.1.tgz", + "integrity": "sha512-i4/rNPRS84t0vSRa2HorerGRXWyF4vThfHesw0dmcWHp+cspK743UanA0suA5Q5y8kzY2y6YKrvbIUn69BCAiA==", "dev": true, "license": "MIT", "dependencies": { @@ -437,88 +435,6 @@ "node": ">= 4.0.0" } }, - "node_modules/@electron/node-gyp": { - "version": "10.2.0-electron.1", - "resolved": "git+ssh://git@github.com/electron/node-gyp.git#06b29aafb7708acef8b3669835c8a7857ebc92d2", - "integrity": "sha512-CrYo6TntjpoMO1SHjl5Pa/JoUsECNqNdB7Kx49WLQpWzPw53eEITJ2Hs9fh/ryUYDn4pxZz11StaBYBrLFJdqg==", - "dev": true, - "license": "MIT", - "dependencies": { - "env-paths": "^2.2.0", - "exponential-backoff": "^3.1.1", - "glob": "^8.1.0", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^10.2.1", - "nopt": "^6.0.0", - "proc-log": "^2.0.1", - "semver": "^7.3.5", - "tar": "^6.2.1", - "which": "^2.0.2" - }, - "bin": { - "node-gyp": "bin/node-gyp.js" - }, - "engines": { - "node": ">=12.13.0" - } - }, - "node_modules/@electron/node-gyp/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@electron/node-gyp/node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@electron/node-gyp/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@electron/node-gyp/node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@electron/notarize": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/@electron/notarize/-/notarize-2.5.0.tgz", @@ -551,9 +467,9 @@ } }, "node_modules/@electron/osx-sign": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@electron/osx-sign/-/osx-sign-1.3.1.tgz", - "integrity": "sha512-BAfviURMHpmb1Yb50YbCxnOY0wfwaLXH5KJ4+80zS0gUkzDX3ec23naTlEqKsN+PwYn+a1cCzM7BJ4Wcd3sGzw==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@electron/osx-sign/-/osx-sign-1.3.3.tgz", + "integrity": "sha512-KZ8mhXvWv2rIEgMbWZ4y33bDHyUKMXnx4M0sTyPNK/vcB81ImdeY9Ggdqy0SWbMDgmbqyQ+phgejh6V3R2QuSg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -601,47 +517,31 @@ } }, "node_modules/@electron/rebuild": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@electron/rebuild/-/rebuild-3.7.0.tgz", - "integrity": "sha512-VW++CNSlZwMYP7MyXEbrKjpzEwhB5kDNbzGtiPEjwYysqyTCF+YbNJ210Dj3AjWsGSV4iEEwNkmJN9yGZmVvmw==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@electron/rebuild/-/rebuild-4.0.3.tgz", + "integrity": "sha512-u9vpTHRMkOYCs/1FLiSVAFZ7FbjsXK+bQuzviJZa+lG7BHZl1nz52/IcGvwa3sk80/fc3llutBkbCq10Vh8WQA==", "dev": true, "license": "MIT", "dependencies": { - "@electron/node-gyp": "git+https://github.com/electron/node-gyp.git#06b29aafb7708acef8b3669835c8a7857ebc92d2", "@malept/cross-spawn-promise": "^2.0.0", - "chalk": "^4.0.0", "debug": "^4.1.1", "detect-libc": "^2.0.1", - "fs-extra": "^10.0.0", "got": "^11.7.0", - "node-abi": "^3.45.0", - "node-api-version": "^0.2.0", + "graceful-fs": "^4.2.11", + "node-abi": "^4.2.0", + "node-api-version": "^0.2.1", + "node-gyp": "^11.2.0", "ora": "^5.1.0", "read-binary-file-arch": "^1.0.6", "semver": "^7.3.5", - "tar": "^6.0.5", + "tar": "^7.5.6", "yargs": "^17.0.1" }, "bin": { "electron-rebuild": "lib/cli.js" }, "engines": { - "node": ">=12.13.0" - } - }, - "node_modules/@electron/rebuild/node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" + "node": ">=22.12.0" } }, "node_modules/@electron/rebuild/node_modules/semver": { @@ -658,13 +558,13 @@ } }, "node_modules/@electron/universal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-2.0.1.tgz", - "integrity": "sha512-fKpv9kg4SPmt+hY7SVBnIYULE9QJl8L3sCfcBsnqbJwwBwAeTLokJ9TRt9y7bK0JAzIW2y78TVVjvnQEms/yyA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-2.0.3.tgz", + "integrity": "sha512-Wn9sPYIVFRFl5HmwMJkARCCf7rqK/EurkfQ/rJZ14mHP3iYTjZSIOSVonEAnhWeAXwtw7zOekGRlc6yTtZ0t+g==", "dev": true, "license": "MIT", "dependencies": { - "@electron/asar": "^3.2.7", + "@electron/asar": "^3.3.1", "@malept/cross-spawn-promise": "^2.0.0", "debug": "^4.3.1", "dir-compare": "^4.2.0", @@ -1183,16 +1083,6 @@ "node": ">=18" } }, - "node_modules/@fastify/busboy": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", - "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14" - } - }, "node_modules/@floating-ui/core": { "version": "1.7.3", "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.3.tgz", @@ -1218,13 +1108,6 @@ "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==", "license": "MIT" }, - "node_modules/@gar/promisify": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", - "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", - "dev": true, - "license": "MIT" - }, "node_modules/@hapi/address": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/@hapi/address/-/address-5.1.1.tgz", @@ -1857,9 +1740,9 @@ } }, "node_modules/@isaacs/brace-expansion": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz", - "integrity": "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.1.tgz", + "integrity": "sha512-WMz71T1JS624nWj2n2fnYAuPovhv7EUhk69R6i9dsVyzxt5eM3bjwvgk9L+APE1TRscGysAVMANkB0jh0LQZrQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1971,15 +1854,6 @@ "node": ">=18.0.0" } }, - "node_modules/@isaacs/fs-minipass/node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.13", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", @@ -2111,18 +1985,41 @@ "node": ">=10" } }, + "node_modules/@npmcli/agent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-3.0.0.tgz", + "integrity": "sha512-S79NdEgDQd/NGCay6TCoVzXSj74skRZIKJcpJjC5lOq34SZzyI6MqtiiWoiVWoVrTcGjNeC4ipbh1VIHlpfF5Q==", + "dev": true, + "license": "ISC", + "dependencies": { + "agent-base": "^7.1.0", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.1", + "lru-cache": "^10.0.1", + "socks-proxy-agent": "^8.0.3" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/@npmcli/agent/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, "node_modules/@npmcli/fs": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", - "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-4.0.0.tgz", + "integrity": "sha512-/xGlezI6xfGO9NwuJlnwz/K14qD1kCSAGtacBHnGzeAIuJGazcp45KP5NuyARXoKb7cwulAGWVsbeSxdG/cb0Q==", "dev": true, "license": "ISC", "dependencies": { - "@gar/promisify": "^1.1.3", "semver": "^7.3.5" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/@npmcli/fs/node_modules/semver": { @@ -2138,21 +2035,6 @@ "node": ">=10" } }, - "node_modules/@npmcli/move-file": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", - "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", - "deprecated": "This functionality has been moved to @npmcli/fs", - "dev": true, - "license": "MIT", - "dependencies": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, "node_modules/@octokit/auth-token": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-6.0.0.tgz", @@ -3430,9 +3312,9 @@ } }, "node_modules/@sveltejs/kit": { - "version": "2.49.2", - "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.49.2.tgz", - "integrity": "sha512-Vp3zX/qlwerQmHMP6x0Ry1oY7eKKRcOWGc2P59srOp4zcqyn+etJyQpELgOi4+ZSUgteX8Y387NuwruLgGXLUQ==", + "version": "2.50.2", + "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.50.2.tgz", + "integrity": "sha512-875hTUkEbz+MyJIxWbQjfMaekqdmEKUUfR7JyKcpfMRZqcGyrO9Gd+iS1D/Dx8LpE5FEtutWGOtlAh4ReSAiOA==", "dev": true, "license": "MIT", "dependencies": { @@ -3441,13 +3323,13 @@ "@types/cookie": "^0.6.0", "acorn": "^8.14.1", "cookie": "^0.6.0", - "devalue": "^5.3.2", + "devalue": "^5.6.2", "esm-env": "^1.2.2", "kleur": "^4.1.5", "magic-string": "^0.30.5", "mrmime": "^2.0.0", "sade": "^1.8.1", - "set-cookie-parser": "^2.6.0", + "set-cookie-parser": "^3.0.0", "sirv": "^3.0.0" }, "bin": { @@ -3460,11 +3342,15 @@ "@opentelemetry/api": "^1.0.0", "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0 || ^6.0.0-next.0", "svelte": "^4.0.0 || ^5.0.0-next.0", + "typescript": "^5.3.3", "vite": "^5.0.3 || ^6.0.0 || ^7.0.0-beta.0" }, "peerDependenciesMeta": { "@opentelemetry/api": { "optional": true + }, + "typescript": { + "optional": true } } }, @@ -3792,16 +3678,6 @@ "vite": "^5.2.0 || ^6 || ^7" } }, - "node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10" - } - }, "node_modules/@types/cacheable-request": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", @@ -3948,11 +3824,14 @@ "license": "MIT" }, "node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-3.0.1.tgz", + "integrity": "sha512-AO2ac6pjRB3SJmGJo+v5/aK6Omggp6fsLrs6wN9bd35ulu4cCwaAU9+7ZhXjeqHVkaHThLuzH0nZr0YpCDhygg==", "dev": true, - "license": "ISC" + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } }, "node_modules/acorn": { "version": "8.15.0", @@ -3977,19 +3856,6 @@ "node": ">= 14" } }, - "node_modules/agentkeepalive": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz", - "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "humanize-ms": "^1.2.1" - }, - "engines": { - "node": ">= 8.0.0" - } - }, "node_modules/aggregate-error": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", @@ -4091,52 +3957,152 @@ "license": "MIT" }, "node_modules/app-builder-lib": { - "version": "26.0.12", - "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-26.0.12.tgz", - "integrity": "sha512-+/CEPH1fVKf6HowBUs6LcAIoRcjeqgvAeoSE+cl7Y7LndyQ9ViGPYibNk7wmhMHzNgHIuIbw4nWADPO+4mjgWw==", + "version": "26.7.0", + "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-26.7.0.tgz", + "integrity": "sha512-/UgCD8VrO79Wv8aBNpjMfsS1pIUfIPURoRn0Ik6tMe5avdZF+vQgl/juJgipcMmH3YS0BD573lCdCHyoi84USg==", "dev": true, "license": "MIT", "dependencies": { "@develar/schema-utils": "~2.6.5", - "@electron/asar": "3.2.18", + "@electron/asar": "3.4.1", "@electron/fuses": "^1.8.0", + "@electron/get": "^3.0.0", "@electron/notarize": "2.5.0", - "@electron/osx-sign": "1.3.1", - "@electron/rebuild": "3.7.0", - "@electron/universal": "2.0.1", + "@electron/osx-sign": "1.3.3", + "@electron/rebuild": "^4.0.3", + "@electron/universal": "2.0.3", "@malept/flatpak-bundler": "^0.4.0", "@types/fs-extra": "9.0.13", "async-exit-hook": "^2.0.1", - "builder-util": "26.0.11", - "builder-util-runtime": "9.3.1", + "builder-util": "26.4.1", + "builder-util-runtime": "9.5.1", "chromium-pickle-js": "^0.2.0", - "config-file-ts": "0.2.8-rc1", + "ci-info": "4.3.1", "debug": "^4.3.4", "dotenv": "^16.4.5", "dotenv-expand": "^11.0.6", "ejs": "^3.1.8", - "electron-publish": "26.0.11", + "electron-publish": "26.6.0", "fs-extra": "^10.1.0", "hosted-git-info": "^4.1.0", - "is-ci": "^3.0.0", "isbinaryfile": "^5.0.0", + "jiti": "^2.4.2", "js-yaml": "^4.1.0", "json5": "^2.2.3", "lazy-val": "^1.0.5", - "minimatch": "^10.0.0", + "minimatch": "^10.0.3", "plist": "3.1.0", + "proper-lockfile": "^4.1.2", "resedit": "^1.7.0", - "semver": "^7.3.8", - "tar": "^6.1.12", + "semver": "~7.7.3", + "tar": "^7.5.7", "temp-file": "^3.4.0", - "tiny-async-pool": "1.3.0" + "tiny-async-pool": "1.3.0", + "which": "^5.0.0" }, "engines": { "node": ">=14.0.0" }, "peerDependencies": { - "dmg-builder": "26.0.12", - "electron-builder-squirrel-windows": "26.0.12" + "dmg-builder": "26.7.0", + "electron-builder-squirrel-windows": "26.7.0" + } + }, + "node_modules/app-builder-lib/node_modules/@electron/get": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@electron/get/-/get-3.1.0.tgz", + "integrity": "sha512-F+nKc0xW+kVbBRhFzaMgPy3KwmuNTYX1fx6+FxxoSnNgwYX6LD7AKBTWkU0MQ6IBoe7dz069CNkR673sPAgkCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.1.1", + "env-paths": "^2.2.0", + "fs-extra": "^8.1.0", + "got": "^11.8.5", + "progress": "^2.0.3", + "semver": "^6.2.0", + "sumchecker": "^3.0.1" + }, + "engines": { + "node": ">=14" + }, + "optionalDependencies": { + "global-agent": "^3.0.0" + } + }, + "node_modules/app-builder-lib/node_modules/@electron/get/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/app-builder-lib/node_modules/@electron/get/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/app-builder-lib/node_modules/@electron/get/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/app-builder-lib/node_modules/@electron/get/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/app-builder-lib/node_modules/builder-util-runtime": { + "version": "9.5.1", + "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.5.1.tgz", + "integrity": "sha512-qt41tMfgHTllhResqM5DcnHyDIWNgzHvuY2jDcYP9iaGpkWxTUzV6GQjDeLnlR1/DtdlcsWQbA7sByMpmJFTLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.4", + "sax": "^1.2.4" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/app-builder-lib/node_modules/ci-info": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.1.tgz", + "integrity": "sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" } }, "node_modules/app-builder-lib/node_modules/fs-extra": { @@ -4154,6 +4120,16 @@ "node": ">=12" } }, + "node_modules/app-builder-lib/node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16" + } + }, "node_modules/app-builder-lib/node_modules/semver": { "version": "7.7.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", @@ -4167,6 +4143,22 @@ "node": ">=10" } }, + "node_modules/app-builder-lib/node_modules/which": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz", + "integrity": "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -4425,23 +4417,22 @@ "license": "MIT" }, "node_modules/builder-util": { - "version": "26.0.11", - "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-26.0.11.tgz", - "integrity": "sha512-xNjXfsldUEe153h1DraD0XvDOpqGR0L5eKFkdReB7eFW5HqysDZFfly4rckda6y9dF39N3pkPlOblcfHKGw+uA==", + "version": "26.4.1", + "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-26.4.1.tgz", + "integrity": "sha512-FlgH43XZ50w3UtS1RVGDWOz8v9qMXPC7upMtKMtBEnYdt1OVoS61NYhKm/4x+cIaWqJTXua0+VVPI+fSPGXNIw==", "dev": true, "license": "MIT", "dependencies": { "@types/debug": "^4.1.6", "7zip-bin": "~5.2.0", "app-builder-bin": "5.0.0-alpha.12", - "builder-util-runtime": "9.3.1", + "builder-util-runtime": "9.5.1", "chalk": "^4.1.2", "cross-spawn": "^7.0.6", "debug": "^4.3.4", "fs-extra": "^10.1.0", "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.0", - "is-ci": "^3.0.0", "js-yaml": "^4.1.0", "sanitize-filename": "^1.6.3", "source-map-support": "^0.5.19", @@ -4463,6 +4454,20 @@ "node": ">=12.0.0" } }, + "node_modules/builder-util/node_modules/builder-util-runtime": { + "version": "9.5.1", + "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.5.1.tgz", + "integrity": "sha512-qt41tMfgHTllhResqM5DcnHyDIWNgzHvuY2jDcYP9iaGpkWxTUzV6GQjDeLnlR1/DtdlcsWQbA7sByMpmJFTLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.4", + "sax": "^1.2.4" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/builder-util/node_modules/fs-extra": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", @@ -4479,33 +4484,27 @@ } }, "node_modules/cacache": { - "version": "16.1.3", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", - "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", + "version": "19.0.1", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-19.0.1.tgz", + "integrity": "sha512-hdsUxulXCi5STId78vRVYEtDAjq99ICAUktLTeTYsLoTE6Z8dS0c8pWNCxwdrk9YfJeobDZc2Y186hD/5ZQgFQ==", "dev": true, "license": "ISC", "dependencies": { - "@npmcli/fs": "^2.1.0", - "@npmcli/move-file": "^2.0.0", - "chownr": "^2.0.0", - "fs-minipass": "^2.1.0", - "glob": "^8.0.1", - "infer-owner": "^1.0.4", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", + "@npmcli/fs": "^4.0.0", + "fs-minipass": "^3.0.0", + "glob": "^10.2.2", + "lru-cache": "^10.0.1", + "minipass": "^7.0.3", + "minipass-collect": "^2.0.1", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", - "mkdirp": "^1.0.4", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^9.0.0", - "tar": "^6.1.11", - "unique-filename": "^2.0.0" + "p-map": "^7.0.2", + "ssri": "^12.0.0", + "tar": "^7.4.3", + "unique-filename": "^4.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/cacache/node_modules/brace-expansion": { @@ -4519,47 +4518,48 @@ } }, "node_modules/cacache/node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, "license": "ISC", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" }, - "engines": { - "node": ">=12" + "bin": { + "glob": "dist/esm/bin.mjs" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/cacache/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } + "license": "ISC" }, "node_modules/cacache/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=10" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/cacheable-lookup": { @@ -4688,13 +4688,12 @@ } }, "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true, - "license": "ISC", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "license": "BlueOak-1.0.0", "engines": { - "node": ">=10" + "node": ">=18" } }, "node_modules/chromium-pickle-js": { @@ -4705,9 +4704,9 @@ "license": "MIT" }, "node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.4.0.tgz", + "integrity": "sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==", "dev": true, "funding": [ { @@ -5018,77 +5017,9 @@ "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", "dev": true, "license": "MIT", - "dependencies": { - "ini": "^1.3.4", - "proto-list": "~1.2.1" - } - }, - "node_modules/config-file-ts": { - "version": "0.2.8-rc1", - "resolved": "https://registry.npmjs.org/config-file-ts/-/config-file-ts-0.2.8-rc1.tgz", - "integrity": "sha512-GtNECbVI82bT4RiDIzBSVuTKoSHufnU7Ce7/42bkWZJZFLjmDF2WBpVsvRkhKCfKBnTBb3qZrBwPpFBU/Myvhg==", - "dev": true, - "license": "MIT", - "dependencies": { - "glob": "^10.3.12", - "typescript": "^5.4.3" - } - }, - "node_modules/config-file-ts/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/config-file-ts/node_modules/glob": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", - "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", - "dev": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/config-file-ts/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/config-file-ts/node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" + "dependencies": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" } }, "node_modules/consola": { @@ -5474,9 +5405,9 @@ "license": "MIT" }, "node_modules/devalue": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.6.1.tgz", - "integrity": "sha512-jDwizj+IlEZBunHcOuuFVBnIMPAEHvTsJj0BcIp94xYguLRVBcXO853px/MyIJvbVzWdsGvrRweIUWJw8hBP7A==", + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.6.2.tgz", + "integrity": "sha512-nPRkjWzzDQlsejL1WVifk5rvcFi/y1onBRxjaFMjZeR9mFpqu2gmAZ9xUB9/IEanEP/vBtGeGganC/GO1fmufg==", "dev": true, "license": "MIT" }, @@ -5518,15 +5449,14 @@ } }, "node_modules/dmg-builder": { - "version": "26.0.12", - "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-26.0.12.tgz", - "integrity": "sha512-59CAAjAhTaIMCN8y9kD573vDkxbs1uhDcrFLHSgutYdPcGOU35Rf95725snvzEOy4BFB7+eLJ8djCNPmGwG67w==", + "version": "26.7.0", + "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-26.7.0.tgz", + "integrity": "sha512-uOOBA3f+kW3o4KpSoMQ6SNpdXU7WtxlJRb9vCZgOvqhTz4b3GjcoWKstdisizNZLsylhTMv8TLHFPFW0Uxsj/g==", "dev": true, "license": "MIT", "dependencies": { - "app-builder-lib": "26.0.12", - "builder-util": "26.0.11", - "builder-util-runtime": "9.3.1", + "app-builder-lib": "26.7.0", + "builder-util": "26.4.1", "fs-extra": "^10.1.0", "iconv-lite": "^0.6.2", "js-yaml": "^4.1.0" @@ -5687,19 +5617,19 @@ } }, "node_modules/electron-builder": { - "version": "26.0.12", - "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-26.0.12.tgz", - "integrity": "sha512-cD1kz5g2sgPTMFHjLxfMjUK5JABq3//J4jPswi93tOPFz6btzXYtK5NrDt717NRbukCUDOrrvmYVOWERlqoiXA==", + "version": "26.7.0", + "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-26.7.0.tgz", + "integrity": "sha512-LoXbCvSFxLesPneQ/fM7FB4OheIDA2tjqCdUkKlObV5ZKGhYgi5VHPHO/6UUOUodAlg7SrkPx7BZJPby+Vrtbg==", "dev": true, "license": "MIT", "dependencies": { - "app-builder-lib": "26.0.12", - "builder-util": "26.0.11", - "builder-util-runtime": "9.3.1", + "app-builder-lib": "26.7.0", + "builder-util": "26.4.1", + "builder-util-runtime": "9.5.1", "chalk": "^4.1.2", - "dmg-builder": "26.0.12", + "ci-info": "^4.2.0", + "dmg-builder": "26.7.0", "fs-extra": "^10.1.0", - "is-ci": "^3.0.0", "lazy-val": "^1.0.5", "simple-update-notifier": "2.0.0", "yargs": "^17.6.2" @@ -5713,18 +5643,32 @@ } }, "node_modules/electron-builder-squirrel-windows": { - "version": "26.0.12", - "resolved": "https://registry.npmjs.org/electron-builder-squirrel-windows/-/electron-builder-squirrel-windows-26.0.12.tgz", - "integrity": "sha512-kpwXM7c/ayRUbYVErQbsZ0nQZX4aLHQrPEG9C4h9vuJCXylwFH8a7Jgi2VpKIObzCXO7LKHiCw4KdioFLFOgqA==", + "version": "26.7.0", + "resolved": "https://registry.npmjs.org/electron-builder-squirrel-windows/-/electron-builder-squirrel-windows-26.7.0.tgz", + "integrity": "sha512-3EqkQK+q0kGshdPSKEPb2p5F75TENMKu6Fe5aTdeaPfdzFK4Yjp5L0d6S7K8iyvqIsGQ/ei4bnpyX9wt+kVCKQ==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "app-builder-lib": "26.0.12", - "builder-util": "26.0.11", + "app-builder-lib": "26.7.0", + "builder-util": "26.4.1", "electron-winstaller": "5.4.0" } }, + "node_modules/electron-builder/node_modules/builder-util-runtime": { + "version": "9.5.1", + "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.5.1.tgz", + "integrity": "sha512-qt41tMfgHTllhResqM5DcnHyDIWNgzHvuY2jDcYP9iaGpkWxTUzV6GQjDeLnlR1/DtdlcsWQbA7sByMpmJFTLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.4", + "sax": "^1.2.4" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/electron-builder/node_modules/fs-extra": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", @@ -5741,22 +5685,36 @@ } }, "node_modules/electron-publish": { - "version": "26.0.11", - "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-26.0.11.tgz", - "integrity": "sha512-a8QRH0rAPIWH9WyyS5LbNvW9Ark6qe63/LqDB7vu2JXYpi0Gma5Q60Dh4tmTqhOBQt0xsrzD8qE7C+D7j+B24A==", + "version": "26.6.0", + "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-26.6.0.tgz", + "integrity": "sha512-LsyHMMqbvJ2vsOvuWJ19OezgF2ANdCiHpIucDHNiLhuI+/F3eW98ouzWSRmXXi82ZOPZXC07jnIravY4YYwCLQ==", "dev": true, "license": "MIT", "dependencies": { "@types/fs-extra": "^9.0.11", - "builder-util": "26.0.11", - "builder-util-runtime": "9.3.1", + "builder-util": "26.4.1", + "builder-util-runtime": "9.5.1", "chalk": "^4.1.2", - "form-data": "^4.0.0", + "form-data": "^4.0.5", "fs-extra": "^10.1.0", "lazy-val": "^1.0.5", "mime": "^2.5.2" } }, + "node_modules/electron-publish/node_modules/builder-util-runtime": { + "version": "9.5.1", + "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.5.1.tgz", + "integrity": "sha512-qt41tMfgHTllhResqM5DcnHyDIWNgzHvuY2jDcYP9iaGpkWxTUzV6GQjDeLnlR1/DtdlcsWQbA7sByMpmJFTLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.4", + "sax": "^1.2.4" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/electron-publish/node_modules/fs-extra": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", @@ -6273,9 +6231,9 @@ } }, "node_modules/esrap": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/esrap/-/esrap-2.2.1.tgz", - "integrity": "sha512-GiYWG34AN/4CUyaWAgunGt0Rxvr1PTMlGC0vvEov/uOQYWne2bpN03Um+k8jT+q3op33mKouP2zeJ6OlM+qeUg==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/esrap/-/esrap-2.2.2.tgz", + "integrity": "sha512-zA6497ha+qKvoWIK+WM9NAh5ni17sKZKhbS5B3PoYbBvaYHZWoS33zmFybmyqpn07RLUxSmn+RCls2/XF+d0oQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6634,16 +6592,16 @@ } }, "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", + "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", "dev": true, "license": "ISC", "dependencies": { - "minipass": "^3.0.0" + "minipass": "^7.0.3" }, "engines": { - "node": ">= 8" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/fs.realpath": { @@ -6785,7 +6743,7 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, "license": "ISC", "dependencies": { @@ -7102,16 +7060,6 @@ "node": ">=10.17.0" } }, - "node_modules/humanize-ms": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.0.0" - } - }, "node_modules/iconv-corefoundation": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/iconv-corefoundation/-/iconv-corefoundation-1.1.7.tgz", @@ -7143,6 +7091,12 @@ "node": ">=0.10.0" } }, + "node_modules/idb-keyval": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.2.2.tgz", + "integrity": "sha512-yjD9nARJ/jb1g+CvD0tlhUHOrJ9Sy0P8T9MF3YaLlHnSRpwPfpTX0XIvpmw3gAJUmEu3FiICLBDPXVwyEvrleg==", + "license": "Apache-2.0" + }, "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -7255,13 +7209,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "dev": true, - "license": "ISC" - }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -7321,19 +7268,6 @@ "dev": true, "license": "MIT" }, - "node_modules/is-ci": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", - "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ci-info": "^3.2.0" - }, - "bin": { - "is-ci": "bin.js" - } - }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -7354,13 +7288,6 @@ "node": ">=8" } }, - "node_modules/is-lambda": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", - "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", - "dev": true, - "license": "MIT" - }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -8008,16 +7935,16 @@ } }, "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", "dev": true, "license": "MIT" }, "node_modules/lodash-es": { - "version": "4.17.22", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.22.tgz", - "integrity": "sha512-XEawp1t0gxSi9x01glktRZ5HDy0HXqrM0x5pXQM98EaI0NxO6jVM7omDOxsuEo5UIASAnm2bRp1Jt/e0a2XU8Q==", + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.23.tgz", + "integrity": "sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg==", "dev": true, "license": "MIT" }, @@ -8150,83 +8077,26 @@ } }, "node_modules/make-fetch-happen": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", - "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", - "dev": true, - "license": "ISC", - "dependencies": { - "agentkeepalive": "^4.2.1", - "cacache": "^16.1.0", - "http-cache-semantics": "^4.1.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-fetch": "^2.0.3", + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-14.0.3.tgz", + "integrity": "sha512-QMjGbFTP0blj97EeidG5hk/QhKQ3T4ICckQGLgz38QF7Vgbk6e6FTARN8KhKxyBbWn8R0HU+bnw8aSoFPD4qtQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "@npmcli/agent": "^3.0.0", + "cacache": "^19.0.1", + "http-cache-semantics": "^4.1.1", + "minipass": "^7.0.2", + "minipass-fetch": "^4.0.0", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", + "negotiator": "^1.0.0", + "proc-log": "^5.0.0", "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^9.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/make-fetch-happen/node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/make-fetch-happen/node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/make-fetch-happen/node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "6", - "debug": "4" + "ssri": "^12.0.0" }, "engines": { - "node": ">= 6" - } - }, - "node_modules/make-fetch-happen/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/marked": { @@ -8390,13 +8260,13 @@ } }, "node_modules/minimatch": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz", - "integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==", + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.2.tgz", + "integrity": "sha512-fu656aJ0n2kcXwsnwnv9g24tkU5uSmOlTjd6WyyaKm2Z+h1qmY6bAjrcaIxF/BslFqbZ8UBtbJi7KgQOZD2PTw==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { - "@isaacs/brace-expansion": "^5.0.0" + "@isaacs/brace-expansion": "^5.0.1" }, "engines": { "node": "20 || >=22" @@ -8416,44 +8286,40 @@ } }, "node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.17" } }, "node_modules/minipass-collect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-2.0.1.tgz", + "integrity": "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==", "dev": true, "license": "ISC", "dependencies": { - "minipass": "^3.0.0" + "minipass": "^7.0.3" }, "engines": { - "node": ">= 8" + "node": ">=16 || 14 >=14.17" } }, "node_modules/minipass-fetch": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", - "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-4.0.1.tgz", + "integrity": "sha512-j7U11C5HXigVuutxebFadoYBbd7VSdZWggSe64NVdvWNBqGAiXPL2QVCehjmw7lY1oF9gOllYbORh+hiNgfPgQ==", "dev": true, "license": "MIT", "dependencies": { - "minipass": "^3.1.6", + "minipass": "^7.0.3", "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" + "minizlib": "^3.0.1" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^18.17.0 || >=20.5.0" }, "optionalDependencies": { "encoding": "^0.1.13" @@ -8472,6 +8338,19 @@ "node": ">= 8" } }, + "node_modules/minipass-flush/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/minipass-pipeline": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", @@ -8485,6 +8364,19 @@ "node": ">=8" } }, + "node_modules/minipass-pipeline/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/minipass-sized": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", @@ -8498,31 +8390,43 @@ "node": ">=8" } }, - "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "node_modules/minipass-sized/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "minipass": "^3.0.0", "yallist": "^4.0.0" }, "engines": { - "node": ">= 8" + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz", + "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", + "license": "MIT", + "dependencies": { + "minipass": "^7.1.2" + }, + "engines": { + "node": ">= 18" } }, "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", "dev": true, "license": "MIT", + "peer": true, + "dependencies": { + "minimist": "^1.2.6" + }, "bin": { "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" } }, "node_modules/mri": { @@ -8583,9 +8487,9 @@ } }, "node_modules/negotiator": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", - "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", "dev": true, "license": "MIT", "engines": { @@ -8607,16 +8511,16 @@ "license": "MIT" }, "node_modules/node-abi": { - "version": "3.85.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.85.0.tgz", - "integrity": "sha512-zsFhmbkAzwhTft6nd3VxcG0cvJsT70rL+BIGHWVq5fi6MwGrHwzqKaxXE+Hl2GmnGItnDKPPkO5/LQqjVkIdFg==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-4.26.0.tgz", + "integrity": "sha512-8QwIZqikRvDIkXS2S93LjzhsSPJuIbfaMETWH+Bx8oOT9Sa9UsUtBFQlc3gBNd1+QINjaTloitXr1W3dQLi9Iw==", "dev": true, "license": "MIT", "dependencies": { - "semver": "^7.3.5" + "semver": "^7.6.3" }, "engines": { - "node": ">=10" + "node": ">=22.12.0" } }, "node_modules/node-abi/node_modules/semver": { @@ -8679,20 +8583,84 @@ "node": ">=18" } }, + "node_modules/node-gyp": { + "version": "11.5.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-11.5.0.tgz", + "integrity": "sha512-ra7Kvlhxn5V9Slyus0ygMa2h+UqExPqUIkfk7Pc8QTLT956JLSy51uWFwHtIYy0vI8cB4BDhc/S03+880My/LQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^14.0.3", + "nopt": "^8.0.0", + "proc-log": "^5.0.0", + "semver": "^7.3.5", + "tar": "^7.4.3", + "tinyglobby": "^0.2.12", + "which": "^5.0.0" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/node-gyp/node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16" + } + }, + "node_modules/node-gyp/node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-gyp/node_modules/which": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz", + "integrity": "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, "node_modules/nopt": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", - "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-8.1.0.tgz", + "integrity": "sha512-ieGu42u/Qsa4TFktmaKEwM6MQH0pOWnaB3htzh0JRtx84+Mebc0cbZYN5bC+6WTZ4+77xrL9Pn5m7CV6VIkV7A==", "dev": true, "license": "ISC", "dependencies": { - "abbrev": "^1.0.0" + "abbrev": "^3.0.0" }, "bin": { "nopt": "bin/nopt.js" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/normalize-package-data": { @@ -8760,9 +8728,9 @@ } }, "node_modules/npm": { - "version": "11.7.0", - "resolved": "https://registry.npmjs.org/npm/-/npm-11.7.0.tgz", - "integrity": "sha512-wiCZpv/41bIobCoJ31NStIWKfAxxYyD1iYnWCtiyns8s5v3+l8y0HCP/sScuH6B5+GhIfda4HQKiqeGZwJWhFw==", + "version": "11.9.0", + "resolved": "https://registry.npmjs.org/npm/-/npm-11.9.0.tgz", + "integrity": "sha512-BBZoU926FCypj4b7V7ElinxsWcy4Kss88UG3ejFYmKyq7Uc5XnT34Me2nEhgCOaL5qY4HvGu5aI92C4OYd7NaA==", "bundleDependencies": [ "@isaacs/string-locale-compare", "@npmcli/arborist", @@ -8842,8 +8810,8 @@ ], "dependencies": { "@isaacs/string-locale-compare": "^1.1.0", - "@npmcli/arborist": "^9.1.9", - "@npmcli/config": "^10.4.5", + "@npmcli/arborist": "^9.2.0", + "@npmcli/config": "^10.6.0", "@npmcli/fs": "^5.0.0", "@npmcli/map-workspaces": "^5.0.3", "@npmcli/metavuln-calculator": "^9.0.3", @@ -8851,12 +8819,12 @@ "@npmcli/promise-spawn": "^9.0.1", "@npmcli/redact": "^4.0.0", "@npmcli/run-script": "^10.0.3", - "@sigstore/tuf": "^4.0.0", + "@sigstore/tuf": "^4.0.1", "abbrev": "^4.0.0", "archy": "~1.0.0", "cacache": "^20.0.3", "chalk": "^5.6.2", - "ci-info": "^4.3.1", + "ci-info": "^4.4.0", "cli-columns": "^4.0.0", "fastest-levenshtein": "^1.0.16", "fs-minipass": "^3.0.3", @@ -8868,11 +8836,11 @@ "is-cidr": "^6.0.1", "json-parse-even-better-errors": "^5.0.0", "libnpmaccess": "^10.0.3", - "libnpmdiff": "^8.0.12", - "libnpmexec": "^10.1.11", - "libnpmfund": "^7.0.12", + "libnpmdiff": "^8.1.0", + "libnpmexec": "^10.2.0", + "libnpmfund": "^7.0.14", "libnpmorg": "^8.0.1", - "libnpmpack": "^9.0.12", + "libnpmpack": "^9.1.0", "libnpmpublish": "^11.1.3", "libnpmsearch": "^9.0.1", "libnpmteam": "^8.0.2", @@ -8882,7 +8850,7 @@ "minipass": "^7.1.1", "minipass-pipeline": "^1.2.4", "ms": "^2.1.2", - "node-gyp": "^12.1.0", + "node-gyp": "^12.2.0", "nopt": "^9.0.0", "npm-audit-report": "^7.0.0", "npm-install-checks": "^8.0.0", @@ -8892,7 +8860,7 @@ "npm-registry-fetch": "^19.1.1", "npm-user-validate": "^4.0.0", "p-map": "^7.0.4", - "pacote": "^21.0.4", + "pacote": "^21.1.0", "parse-conflict-json": "^5.0.1", "proc-log": "^6.1.0", "qrcode-terminal": "^0.12.0", @@ -8901,11 +8869,11 @@ "spdx-expression-parse": "^4.0.0", "ssri": "^13.0.0", "supports-color": "^10.2.2", - "tar": "^7.5.2", + "tar": "^7.5.7", "text-table": "~0.2.0", "tiny-relative-date": "^2.0.2", "treeverse": "^3.0.0", - "validate-npm-package-name": "^7.0.0", + "validate-npm-package-name": "^7.0.2", "which": "^6.0.0" }, "bin": { @@ -8939,7 +8907,7 @@ } }, "node_modules/npm/node_modules/@isaacs/brace-expansion": { - "version": "5.0.0", + "version": "5.0.1", "dev": true, "inBundle": true, "license": "MIT", @@ -8985,7 +8953,7 @@ } }, "node_modules/npm/node_modules/@npmcli/arborist": { - "version": "9.1.9", + "version": "9.2.0", "dev": true, "inBundle": true, "license": "ISC", @@ -9003,7 +8971,7 @@ "@npmcli/run-script": "^10.0.0", "bin-links": "^6.0.0", "cacache": "^20.0.1", - "common-ancestor-path": "^1.0.1", + "common-ancestor-path": "^2.0.0", "hosted-git-info": "^9.0.0", "json-stringify-nice": "^1.1.4", "lru-cache": "^11.2.1", @@ -9032,7 +9000,7 @@ } }, "node_modules/npm/node_modules/@npmcli/config": { - "version": "10.4.5", + "version": "10.6.0", "dev": true, "inBundle": true, "license": "ISC", @@ -9227,7 +9195,7 @@ } }, "node_modules/npm/node_modules/@sigstore/core": { - "version": "3.0.0", + "version": "3.1.0", "dev": true, "inBundle": true, "license": "Apache-2.0", @@ -9245,52 +9213,43 @@ } }, "node_modules/npm/node_modules/@sigstore/sign": { - "version": "4.0.1", + "version": "4.1.0", "dev": true, "inBundle": true, "license": "Apache-2.0", "dependencies": { "@sigstore/bundle": "^4.0.0", - "@sigstore/core": "^3.0.0", + "@sigstore/core": "^3.1.0", "@sigstore/protobuf-specs": "^0.5.0", - "make-fetch-happen": "^15.0.2", - "proc-log": "^5.0.0", + "make-fetch-happen": "^15.0.3", + "proc-log": "^6.1.0", "promise-retry": "^2.0.1" }, "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/npm/node_modules/@sigstore/sign/node_modules/proc-log": { - "version": "5.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/npm/node_modules/@sigstore/tuf": { - "version": "4.0.0", + "version": "4.0.1", "dev": true, "inBundle": true, "license": "Apache-2.0", "dependencies": { "@sigstore/protobuf-specs": "^0.5.0", - "tuf-js": "^4.0.0" + "tuf-js": "^4.1.0" }, "engines": { "node": "^20.17.0 || >=22.9.0" } }, "node_modules/npm/node_modules/@sigstore/verify": { - "version": "3.0.0", + "version": "3.1.0", "dev": true, "inBundle": true, "license": "Apache-2.0", "dependencies": { "@sigstore/bundle": "^4.0.0", - "@sigstore/core": "^3.0.0", + "@sigstore/core": "^3.1.0", "@sigstore/protobuf-specs": "^0.5.0" }, "engines": { @@ -9307,33 +9266,18 @@ } }, "node_modules/npm/node_modules/@tufjs/models": { - "version": "4.0.0", + "version": "4.1.0", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "@tufjs/canonical-json": "2.0.0", - "minimatch": "^9.0.5" + "minimatch": "^10.1.1" }, "engines": { "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/npm/node_modules/@tufjs/models/node_modules/minimatch": { - "version": "9.0.5", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/npm/node_modules/abbrev": { "version": "4.0.0", "dev": true, @@ -9373,12 +9317,6 @@ "inBundle": true, "license": "MIT" }, - "node_modules/npm/node_modules/balanced-match": { - "version": "1.0.2", - "dev": true, - "inBundle": true, - "license": "MIT" - }, "node_modules/npm/node_modules/bin-links": { "version": "6.0.0", "dev": true, @@ -9407,15 +9345,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/npm/node_modules/brace-expansion": { - "version": "2.0.2", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, "node_modules/npm/node_modules/cacache": { "version": "20.0.3", "dev": true, @@ -9460,7 +9389,7 @@ } }, "node_modules/npm/node_modules/ci-info": { - "version": "4.3.1", + "version": "4.4.0", "dev": true, "funding": [ { @@ -9509,10 +9438,13 @@ } }, "node_modules/npm/node_modules/common-ancestor-path": { - "version": "1.0.1", + "version": "2.0.0", "dev": true, "inBundle": true, - "license": "ISC" + "license": "BlueOak-1.0.0", + "engines": { + "node": ">= 18" + } }, "node_modules/npm/node_modules/cssesc": { "version": "3.0.0", @@ -9544,7 +9476,7 @@ } }, "node_modules/npm/node_modules/diff": { - "version": "8.0.2", + "version": "8.0.3", "dev": true, "inBundle": true, "license": "BSD-3-Clause", @@ -9611,12 +9543,12 @@ } }, "node_modules/npm/node_modules/glob": { - "version": "13.0.0", + "version": "13.0.1", "dev": true, "inBundle": true, "license": "BlueOak-1.0.0", "dependencies": { - "minimatch": "^10.1.1", + "minimatch": "^10.1.2", "minipass": "^7.1.2", "path-scurry": "^2.0.0" }, @@ -9739,7 +9671,7 @@ } }, "node_modules/npm/node_modules/ip-address": { - "version": "10.0.1", + "version": "10.1.0", "dev": true, "inBundle": true, "license": "MIT", @@ -9760,12 +9692,12 @@ } }, "node_modules/npm/node_modules/is-cidr": { - "version": "6.0.1", + "version": "6.0.2", "dev": true, "inBundle": true, "license": "BSD-2-Clause", "dependencies": { - "cidr-regex": "5.0.1" + "cidr-regex": "^5.0.1" }, "engines": { "node": ">=20" @@ -9842,12 +9774,12 @@ } }, "node_modules/npm/node_modules/libnpmdiff": { - "version": "8.0.12", + "version": "8.1.0", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { - "@npmcli/arborist": "^9.1.9", + "@npmcli/arborist": "^9.2.0", "@npmcli/installed-package-contents": "^4.0.0", "binary-extensions": "^3.0.0", "diff": "^8.0.2", @@ -9861,12 +9793,12 @@ } }, "node_modules/npm/node_modules/libnpmexec": { - "version": "10.1.11", + "version": "10.2.0", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { - "@npmcli/arborist": "^9.1.9", + "@npmcli/arborist": "^9.2.0", "@npmcli/package-json": "^7.0.0", "@npmcli/run-script": "^10.0.0", "ci-info": "^4.0.0", @@ -9884,12 +9816,12 @@ } }, "node_modules/npm/node_modules/libnpmfund": { - "version": "7.0.12", + "version": "7.0.14", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { - "@npmcli/arborist": "^9.1.9" + "@npmcli/arborist": "^9.2.0" }, "engines": { "node": "^20.17.0 || >=22.9.0" @@ -9909,12 +9841,12 @@ } }, "node_modules/npm/node_modules/libnpmpack": { - "version": "9.0.12", + "version": "9.1.0", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { - "@npmcli/arborist": "^9.1.9", + "@npmcli/arborist": "^9.2.0", "@npmcli/run-script": "^10.0.0", "npm-package-arg": "^13.0.0", "pacote": "^21.0.2" @@ -9984,10 +9916,10 @@ } }, "node_modules/npm/node_modules/lru-cache": { - "version": "11.2.2", + "version": "11.2.5", "dev": true, "inBundle": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "engines": { "node": "20 || >=22" } @@ -10015,12 +9947,12 @@ } }, "node_modules/npm/node_modules/minimatch": { - "version": "10.1.1", + "version": "10.1.2", "dev": true, "inBundle": true, "license": "BlueOak-1.0.0", "dependencies": { - "@isaacs/brace-expansion": "^5.0.0" + "@isaacs/brace-expansion": "^5.0.1" }, "engines": { "node": "20 || >=22" @@ -10051,13 +9983,13 @@ } }, "node_modules/npm/node_modules/minipass-fetch": { - "version": "5.0.0", + "version": "5.0.1", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "minipass": "^7.0.3", - "minipass-sized": "^1.0.3", + "minipass-sized": "^2.0.0", "minizlib": "^3.0.1" }, "engines": { @@ -10116,24 +10048,12 @@ } }, "node_modules/npm/node_modules/minipass-sized": { - "version": "1.0.3", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/minipass-sized/node_modules/minipass": { - "version": "3.3.6", + "version": "2.0.0", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { - "yallist": "^4.0.0" + "minipass": "^7.1.2" }, "engines": { "node": ">=8" @@ -10176,7 +10096,7 @@ } }, "node_modules/npm/node_modules/node-gyp": { - "version": "12.1.0", + "version": "12.2.0", "dev": true, "inBundle": true, "license": "MIT", @@ -10188,7 +10108,7 @@ "nopt": "^9.0.0", "proc-log": "^6.0.0", "semver": "^7.3.5", - "tar": "^7.5.2", + "tar": "^7.5.4", "tinyglobby": "^0.2.12", "which": "^6.0.0" }, @@ -10353,7 +10273,7 @@ } }, "node_modules/npm/node_modules/pacote": { - "version": "21.0.4", + "version": "21.1.0", "dev": true, "inBundle": true, "license": "ISC", @@ -10398,7 +10318,7 @@ } }, "node_modules/npm/node_modules/path-scurry": { - "version": "2.0.0", + "version": "2.0.1", "dev": true, "inBundle": true, "license": "BlueOak-1.0.0", @@ -10414,7 +10334,7 @@ } }, "node_modules/npm/node_modules/postcss-selector-parser": { - "version": "7.1.0", + "version": "7.1.1", "dev": true, "inBundle": true, "license": "MIT", @@ -10557,17 +10477,17 @@ } }, "node_modules/npm/node_modules/sigstore": { - "version": "4.0.0", + "version": "4.1.0", "dev": true, "inBundle": true, "license": "Apache-2.0", "dependencies": { "@sigstore/bundle": "^4.0.0", - "@sigstore/core": "^3.0.0", + "@sigstore/core": "^3.1.0", "@sigstore/protobuf-specs": "^0.5.0", - "@sigstore/sign": "^4.0.0", - "@sigstore/tuf": "^4.0.0", - "@sigstore/verify": "^3.0.0" + "@sigstore/sign": "^4.1.0", + "@sigstore/tuf": "^4.0.1", + "@sigstore/verify": "^3.1.0" }, "engines": { "node": "^20.17.0 || >=22.9.0" @@ -10704,7 +10624,7 @@ } }, "node_modules/npm/node_modules/tar": { - "version": "7.5.2", + "version": "7.5.7", "dev": true, "inBundle": true, "license": "BlueOak-1.0.0", @@ -10795,14 +10715,14 @@ } }, "node_modules/npm/node_modules/tuf-js": { - "version": "4.0.0", + "version": "4.1.0", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { - "@tufjs/models": "4.0.0", - "debug": "^4.4.1", - "make-fetch-happen": "^15.0.0" + "@tufjs/models": "4.1.0", + "debug": "^4.4.3", + "make-fetch-happen": "^15.0.1" }, "engines": { "node": "^20.17.0 || >=22.9.0" @@ -10859,7 +10779,7 @@ } }, "node_modules/npm/node_modules/validate-npm-package-name": { - "version": "7.0.0", + "version": "7.0.2", "dev": true, "inBundle": true, "license": "ISC", @@ -10978,61 +10898,6 @@ "tar": "^7.0.1" } }, - "node_modules/onnxruntime-node/node_modules/chownr": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", - "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=18" - } - }, - "node_modules/onnxruntime-node/node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/onnxruntime-node/node_modules/minizlib": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz", - "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", - "license": "MIT", - "dependencies": { - "minipass": "^7.1.2" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/onnxruntime-node/node_modules/tar": { - "version": "7.5.2", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.2.tgz", - "integrity": "sha512-7NyxrTE4Anh8km8iEy7o0QYPs+0JKBTj5ZaqHg6B39erLg0qYXN3BijtShwbsNSvQ+LN75+KV+C4QR/f6Gwnpg==", - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/fs-minipass": "^4.0.0", - "chownr": "^3.0.0", - "minipass": "^7.1.2", - "minizlib": "^3.1.0", - "yallist": "^5.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/onnxruntime-node/node_modules/yallist": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", - "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=18" - } - }, "node_modules/onnxruntime-web": { "version": "1.22.0-dev.20250409-89f8206ba4", "resolved": "https://registry.npmjs.org/onnxruntime-web/-/onnxruntime-web-1.22.0-dev.20250409-89f8206ba4.tgz", @@ -11132,19 +10997,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-filter/node_modules/p-map": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.4.tgz", - "integrity": "sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/p-is-promise": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-3.0.0.tgz", @@ -11198,16 +11050,13 @@ } }, "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.4.tgz", + "integrity": "sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==", "dev": true, "license": "MIT", - "dependencies": { - "aggregate-error": "^3.0.0" - }, "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -11382,16 +11231,6 @@ "dev": true, "license": "ISC" }, - "node_modules/path-scurry/node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -11565,13 +11404,13 @@ } }, "node_modules/proc-log": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-2.0.1.tgz", - "integrity": "sha512-Kcmo2FhfDTXdcbfDH76N7uBYHINxc/8GW7UAVuVP9I+Va3uHSerrnKV6dLooga/gh7GlgzuCCr/eoldnL1muGw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-5.0.0.tgz", + "integrity": "sha512-Azwzvl90HaF0aCz1JrDdXQykFakSSNPaPoiZ9fm5qJIMHioDZEi7OAdRwSm6rSoPtY3Qutnm3L7ogmg3dc+wbQ==", "dev": true, "license": "ISC", "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/process-nextick-args": { @@ -11590,13 +11429,6 @@ "node": ">=0.4.0" } }, - "node_modules/promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", - "dev": true, - "license": "ISC" - }, "node_modules/promise-retry": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", @@ -11611,6 +11443,18 @@ "node": ">=10" } }, + "node_modules/proper-lockfile": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz", + "integrity": "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "retry": "^0.12.0", + "signal-exit": "^3.0.2" + } + }, "node_modules/proto-list": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", @@ -11906,20 +11750,18 @@ } }, "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, "license": "ISC", + "peer": true, "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" } }, "node_modules/roarr": { @@ -12520,9 +12362,9 @@ } }, "node_modules/set-cookie-parser": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz", - "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-3.0.1.tgz", + "integrity": "sha512-n7Z7dXZhJbwuAHhNzkTti6Aw9QDDjZtm3JTpTGATIdNzdQz5GuFs22w90BcvF4INfnrL5xrX3oGsuqO5Dx3A1Q==", "dev": true, "license": "MIT" }, @@ -12834,31 +12676,18 @@ } }, "node_modules/socks-proxy-agent": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", - "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/socks-proxy-agent/node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", + "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", "dev": true, "license": "MIT", "dependencies": { - "debug": "4" + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "socks": "^2.8.3" }, "engines": { - "node": ">= 6.0.0" + "node": ">= 14" } }, "node_modules/source-map": { @@ -12964,16 +12793,16 @@ } }, "node_modules/ssri": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", - "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-12.0.0.tgz", + "integrity": "sha512-S7iGNosepx9RadX82oimUkvr0Ct7IjJbEbs4mJcTxst8um95J3sDYU1RBEOvdu6oL1Wek2ODI5i4MAw+dZ6cAQ==", "dev": true, "license": "ISC", "dependencies": { - "minipass": "^3.1.1" + "minipass": "^7.0.3" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/stat-mode": { @@ -13192,9 +13021,9 @@ } }, "node_modules/svelte": { - "version": "5.46.1", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.46.1.tgz", - "integrity": "sha512-ynjfCHD3nP2el70kN5Pmg37sSi0EjOm9FgHYQdC4giWG/hzO3AatzXXJJgP305uIhGQxSufJLuYWtkY8uK/8RA==", + "version": "5.49.2", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.49.2.tgz", + "integrity": "sha512-PYLwnngYzyhKzqDlGVlCH4z+NVI8mC0/bTv15vw25CcdOhxENsOHIbQ36oj5DIf3oBazM+STbCAvaskpxtBmWA==", "dev": true, "license": "MIT", "dependencies": { @@ -13206,9 +13035,9 @@ "aria-query": "^5.3.1", "axobject-query": "^4.1.0", "clsx": "^2.1.1", - "devalue": "^5.5.0", + "devalue": "^5.6.2", "esm-env": "^1.2.1", - "esrap": "^2.2.1", + "esrap": "^2.2.2", "is-reference": "^3.0.3", "locate-character": "^3.0.0", "magic-string": "^0.30.11", @@ -13295,31 +13124,28 @@ } }, "node_modules/tar": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", - "dev": true, - "license": "ISC", + "version": "7.5.7", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.7.tgz", + "integrity": "sha512-fov56fJiRuThVFXD6o6/Q354S7pnWMJIVlDBYijsTNx6jKSE4pvrDTs6lUnmGvNyfJwFQQwWy3owKz1ucIhveQ==", + "license": "BlueOak-1.0.0", "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.1.0", + "yallist": "^5.0.0" }, "engines": { - "node": ">=10" + "node": ">=18" } }, - "node_modules/tar/node_modules/minipass": { + "node_modules/tar/node_modules/yallist": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true, - "license": "ISC", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "license": "BlueOak-1.0.0", "engines": { - "node": ">=8" + "node": ">=18" } }, "node_modules/temp": { @@ -13373,35 +13199,6 @@ "node": ">=12" } }, - "node_modules/temp/node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/temp/node_modules/rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, "node_modules/tempy": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/tempy/-/tempy-3.1.0.tgz", @@ -13709,9 +13506,9 @@ } }, "node_modules/undici": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.16.0.tgz", - "integrity": "sha512-QEg3HPMll0o3t2ourKwOeUAZ159Kn9mx5pnzHRQO8+Wixmh88YdZRiIwat0iNzNNXn0yoEtXJqFpyW7eM8BV7g==", + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.20.0.tgz", + "integrity": "sha512-MJZrkjyd7DeC+uPZh+5/YaMDxFiiEEaDgbUSVMXayofAkDWF1088CDo+2RPg7B1BuS1qf1vgNE7xqwPxE0DuSQ==", "dev": true, "license": "MIT", "engines": { @@ -13748,29 +13545,29 @@ } }, "node_modules/unique-filename": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", - "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-4.0.0.tgz", + "integrity": "sha512-XSnEewXmQ+veP7xX2dS5Q4yZAvO40cBN2MWkJ7D/6sW4Dg6wYBNwM1Vrnz1FhH5AdeLIlUXRI9e28z1YZi71NQ==", "dev": true, "license": "ISC", "dependencies": { - "unique-slug": "^3.0.0" + "unique-slug": "^5.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/unique-slug": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", - "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-5.0.0.tgz", + "integrity": "sha512-9OdaqO5kwqR+1kVgHAhsp5vPNU0hnxRa26rBFNfNgM7M6pNtgzeBn3s/xbyCQL3dcjzOatcef6UUHpB/6MaETg==", "dev": true, "license": "ISC", "dependencies": { "imurmurhash": "^0.1.4" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/unique-string": { diff --git a/package.json b/package.json index 13c5c95..1fe7e85 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "@floating-ui/dom": "^1.7.4", "@huggingface/transformers": "^3.8.1", "electron-updater": "^6.6.2", + "idb-keyval": "^6.2.2", "jszip": "^3.10.1" }, "overrides": { diff --git a/src/app.css b/src/app.css index 0ea4d3a..c04af3d 100644 --- a/src/app.css +++ b/src/app.css @@ -48,6 +48,15 @@ body { margin: 0; } +/* All buttons should show pointer cursor (low specificity so Tailwind utilities can override) */ +:where(button) { + cursor: pointer; +} + +:where(button:disabled) { + cursor: not-allowed; +} + /* Scrollbar styling */ ::-webkit-scrollbar { width: 12px; diff --git a/src/app.d.ts b/src/app.d.ts index 0d1d16f..73270b7 100644 --- a/src/app.d.ts +++ b/src/app.d.ts @@ -13,6 +13,13 @@ interface ReadResult { error?: string; } +interface FileReadResult { + success: boolean; + buffer?: ArrayBuffer; + name?: string; + error?: string; +} + interface DirEntry { name: string; isDirectory: boolean; @@ -31,6 +38,7 @@ interface ElectronAPI { readFile: (filePath: string) => Promise; readDir: (dirPath: string) => Promise; fileExists: (filePath: string) => Promise; + readFileFromPath: (filePath: string) => Promise; openExternal: (url: string) => Promise; platform: string; isElectron: boolean; @@ -53,8 +61,39 @@ declare global { // interface Platform {} } + // File System Access API types (experimental, not in default TypeScript libs) + // See https://wicg.github.io/file-system-access/ + interface FileSystemHandlePermissionDescriptor { + mode?: 'read' | 'readwrite'; + } + + interface OpenFilePickerOptions { + types?: { + description?: string; + accept: Record; + }[]; + multiple?: boolean; + excludeAcceptAllOption?: boolean; + } + + interface FileSystemFileHandle { + queryPermission( + descriptor?: FileSystemHandlePermissionDescriptor, + ): Promise; + requestPermission( + descriptor?: FileSystemHandlePermissionDescriptor, + ): Promise; + } + + interface DataTransferItem { + getAsFileSystemHandle(): Promise; + } + interface Window { electronAPI?: ElectronAPI; + showOpenFilePicker( + options?: OpenFilePickerOptions, + ): Promise; } } diff --git a/src/lib/bookmarks.svelte.ts b/src/lib/bookmarks.svelte.ts index 93672fe..98dfecb 100644 --- a/src/lib/bookmarks.svelte.ts +++ b/src/lib/bookmarks.svelte.ts @@ -182,10 +182,12 @@ function createBookmarksState() { throw new Error('Invalid bookmark export format'); } - // Merge: add new bookmarks, skip duplicates (by messageId) - const existingIds = new Set(bookmarks.map((b) => b.messageId)); + // Merge: add new bookmarks, skip duplicates (by chatId+messageId to avoid cross-chat collisions) + const existingKeys = new Set( + bookmarks.map((b) => `${b.chatId}:${b.messageId}`), + ); const newBookmarks = data.bookmarks.filter( - (b) => !existingIds.has(b.messageId), + (b) => !existingKeys.has(`${b.chatId}:${b.messageId}`), ); const skipped = data.bookmarks.length - newBookmarks.length; diff --git a/src/lib/components/Button.svelte b/src/lib/components/Button.svelte index 73babda..7cb4d49 100644 --- a/src/lib/components/Button.svelte +++ b/src/lib/components/Button.svelte @@ -4,7 +4,7 @@ import type { HTMLButtonAttributes } from 'svelte/elements'; interface Props extends HTMLButtonAttributes { variant?: 'primary' | 'secondary' | 'ghost' | 'danger'; - size?: 'sm' | 'md'; + size?: 'sm' | 'md' | 'lg'; children?: Snippet; } @@ -17,7 +17,7 @@ let { }: Props = $props(); const baseClasses = - 'cursor-pointer transition-colors inline-flex items-center justify-center gap-1.5 font-medium'; + 'cursor-pointer transition-colors inline-flex items-center justify-center gap-1.5 font-medium disabled:opacity-50 disabled:pointer-events-none'; const variantClasses = { primary: @@ -33,6 +33,7 @@ const variantClasses = { const sizeClasses = { sm: 'px-3 py-1.5 text-xs rounded-md', md: 'px-4 py-1.5 text-sm rounded-lg', + lg: 'px-5 py-2.5 text-sm rounded-lg', }; diff --git a/src/lib/components/ChatAvatar.svelte b/src/lib/components/ChatAvatar.svelte new file mode 100644 index 0000000..5a3ab8e --- /dev/null +++ b/src/lib/components/ChatAvatar.svelte @@ -0,0 +1,39 @@ + + +
+ {getInitials(name)} +
diff --git a/src/lib/components/ChatList.svelte b/src/lib/components/ChatList.svelte index d5da677..905b0a5 100644 --- a/src/lib/components/ChatList.svelte +++ b/src/lib/components/ChatList.svelte @@ -1,20 +1,15 @@
e.key === 'Enter' && openElectronFilePicker()} + aria-label={m.dropzone_title()} + onkeydown={(e) => { + if (e.key === 'Enter' || e.key === ' ') { + e.preventDefault(); + openElectronFilePicker(); + } + }} > import type { Snippet } from 'svelte'; import { browser } from '$app/environment'; +import * as m from '$lib/paraglide/messages'; interface Props { /** @@ -17,7 +18,6 @@ interface Props { class?: string; /** * Accessible label for the close backdrop button - * @default 'Close modal' */ closeAriaLabel?: string; /** @@ -30,7 +30,7 @@ let { open, onClose, class: className = '', - closeAriaLabel = 'Close modal', + closeAriaLabel = m.close_modal(), children, }: Props = $props(); @@ -50,17 +50,18 @@ $effect(() => { {#if open} - + - +