From 9a66e8b2a9df141830f7fa19e6b14a7c4f4502cb Mon Sep 17 00:00:00 2001 From: lovestaco Date: Tue, 28 Oct 2025 19:46:04 +0530 Subject: [PATCH 1/8] fix: clean _svgastro --- frontend/src/pages/svg_icons/_SvgIcons.astro | 140 +++++++++---------- 1 file changed, 63 insertions(+), 77 deletions(-) diff --git a/frontend/src/pages/svg_icons/_SvgIcons.astro b/frontend/src/pages/svg_icons/_SvgIcons.astro index 6699f694aa..ca4cce955d 100644 --- a/frontend/src/pages/svg_icons/_SvgIcons.astro +++ b/frontend/src/pages/svg_icons/_SvgIcons.astro @@ -1,57 +1,16 @@ --- -import CreditsButton from "@/components/buttons/CreditsButton"; -import Pagination from "@/components/PaginationComponent.astro"; -import ToolContainer from "@/components/tool/ToolContainer"; -import ToolContentCardWrapper from "@/components/tool/ToolContentCardWrapper"; -import ToolHead from "@/components/tool/ToolHead"; -import { Card } from "@/components/ui/card"; -import { formatNumber } from "@/lib/utils"; -import { Download, Filter, Star } from "lucide-react"; -import AdBanner from "../../components/banner/AdBanner.astro"; - -// Helper function to get category emoji -const getCategoryEmoji = (categoryName: string): string => { - const emojiMap: Record = { - 'general': '🔧', - 'animals': '🐾', - 'nature': '🌿', - 'technology': '💻', - 'business': '💼', - 'social': '👥', - 'shapes': '🔷', - '18': '🔞', - 'account': '👤', - 'ad': '📢', - 'automation': '🤖', - 'banking': '🏦', - 'bitcoin': '₿', - 'browser': '🌐', - 'cloud': '☁️', - 'communication': '💬', - 'database': '🗄️', - 'design': '🎨', - 'development': '⚡', - 'education': '📚', - 'entertainment': '🎬', - 'finance': '💰', - 'food': '🍕', - 'gaming': '🎮', - 'health': '🏥', - 'home': '🏠', - 'music': '🎵', - 'navigation': '🧭', - 'news': '📰', - 'shopping': '🛒', - 'sports': '⚽', - 'travel': '✈️', - 'weather': '🌤️', - }; - - return emojiMap[categoryName.toLowerCase()] || '🔧'; -}; +import CreditsButton from '@/components/buttons/CreditsButton'; +import Pagination from '@/components/PaginationComponent.astro'; +import ToolContainer from '@/components/tool/ToolContainer'; +import ToolContentCardWrapper from '@/components/tool/ToolContentCardWrapper'; +import ToolHead from '@/components/tool/ToolHead'; +import { Card } from '@/components/ui/card'; +import { formatNumber } from '@/lib/utils'; +import { Download, Filter, Star } from 'lucide-react'; +import AdBanner from '../../components/banner/AdBanner.astro'; // Helper function to render SVG icon preview -function renderIconPreview(categoryName: string, iconName: string, index: number) { +function renderIconPreview(categoryName: string, iconName: string) { return `
@@ -74,19 +33,28 @@ function renderIconPreview(categoryName: string, iconName: string, index: number // Helper function to render category card function renderCategoryCard(category: any): string { - const iconPreviews = category.fileNames?.slice(0, 6).map((fileObj: any, i: number) => { - const iconName = typeof fileObj === 'string' - ? fileObj.replace('.svg', '') - : fileObj.fileName?.replace('.svg', '') || `icon-${i}`; - - return renderIconPreview(category.name, iconName, i); - }).join('') || ''; + const iconPreviews = + category.fileNames + ?.slice(0, 6) + .map((fileObj: any, i: number) => { + const iconName = + typeof fileObj === 'string' + ? fileObj.replace('.svg', '') + : fileObj.fileName?.replace('.svg', '') || `icon-${i}`; + + return renderIconPreview(category.name, iconName); + }) + .join('') || ''; // Fill remaining slots with empty placeholders const remainingSlots = Math.max(0, 6 - (category.fileNames?.length || 0)); - const emptySlots = Array(remainingSlots).fill(0).map(() => - '
' - ).join(''); + const emptySlots = Array(remainingSlots) + .fill(0) + .map( + () => + '
' + ) + .join(''); return ` @@ -129,31 +104,37 @@ const { categories, currentPage, totalPages, totalCategories, totalSvgIcons, bre
{totalCategories}
Categories
-
-
{formatNumber(totalSvgIcons)}
-
SVG Icons
-
+
+
+ {formatNumber(totalSvgIcons)} +
+
SVG Icons
+
- Showing {categories.length} of {totalCategories} categories (Page {currentPage} of {totalPages}) + Showing {categories.length} of {totalCategories} categories (Page { + currentPage + } of {totalPages})
- {categories.map((category: any) => ( - - ))} + { + categories.map((category: any) => ( + + )) + }
- -

Why Use Our SVG Icons?

+

+ Why Use Our SVG Icons? +

Instant Download

- Download SVG icons instantly without registration or signup required. + Download SVG icons instantly without registration or signup + required.

Easy Customization

- Edit colors, add backgrounds, and customize vector graphics for your projects. + Edit colors, add backgrounds, and customize vector graphics for + your projects.

High Quality

- Professional vector graphics that scale perfectly for any screen size. + Professional vector graphics that scale perfectly for any screen + size.

@@ -198,7 +184,7 @@ const { categories, currentPage, totalPages, totalCategories, totalSvgIcons, bre href="/freedevtools/" class="inline-flex items-center px-4 py-2 text-sm font-medium text-blue-600 dark:text-blue-400 bg-blue-50 dark:bg-blue-900/20 rounded-lg hover:bg-blue-100 dark:hover:bg-blue-900/30 transition-colors" > - ← Back to Free DevTools + ← Back to Free DevTools
@@ -214,7 +200,7 @@ const { categories, currentPage, totalPages, totalCategories, totalSvgIcons, bre display: block; object-fit: contain; } - + .icon-preview { overflow: hidden; display: flex; From 3555bbf6caba161f2f54f084a7ab95a40ae0e687 Mon Sep 17 00:00:00 2001 From: lovestaco Date: Wed, 29 Oct 2025 21:36:44 +0530 Subject: [PATCH 2/8] script and code changes for sqlite3 --- frontend/db/svg_icons/svg-icons-schema.ts | 55 + frontend/db/svg_icons/svg-icons-utils.ts | 149 ++ frontend/package-lock.json | 1337 +++++++++-------- .../build_sqlite_from_json.py | 265 ++++ .../scripts/svg_icons_to_base64/svg_to_db.py | 206 +++ frontend/src/content.config.ts | 47 - frontend/src/lib/svg-icons-utils.ts | 83 - frontend/src/pages/svg_icons/[category].astro | 164 +- .../pages/svg_icons/[category]/[icon].astro | 352 +++-- frontend/src/pages/svg_icons/[page].astro | 79 +- frontend/src/pages/svg_icons/_SvgIcons.astro | 128 +- frontend/src/pages/svg_icons/credits.astro | 240 ++- frontend/src/pages/svg_icons/index.astro | 109 +- .../src/pages/svg_icons_pages/sitemap.xml.ts | 16 +- frontend/tsconfig.json | 3 +- 15 files changed, 1960 insertions(+), 1273 deletions(-) create mode 100644 frontend/db/svg_icons/svg-icons-schema.ts create mode 100644 frontend/db/svg_icons/svg-icons-utils.ts create mode 100644 frontend/scripts/svg_icons_to_base64/build_sqlite_from_json.py create mode 100644 frontend/scripts/svg_icons_to_base64/svg_to_db.py delete mode 100644 frontend/src/lib/svg-icons-utils.ts diff --git a/frontend/db/svg_icons/svg-icons-schema.ts b/frontend/db/svg_icons/svg-icons-schema.ts new file mode 100644 index 0000000000..c65c66c415 --- /dev/null +++ b/frontend/db/svg_icons/svg-icons-schema.ts @@ -0,0 +1,55 @@ +export interface Icon { + id: number; + cluster: string; + name: string; + base64: string; + description: string; + usecases: string; + synonyms: string[]; // JSON array stored as TEXT, SQLite can query with json_each() + tags: string[]; // JSON array stored as TEXT, SQLite can query with json_each() + industry: string; + emotional_cues: string; + enhanced: number; // 0 or 1, convert to boolean +} + +export interface Cluster { + name: string; + count: number; + source_folder: string; + path: string; + keywords: string[]; // JSON array stored as TEXT, SQLite can query with json_each() + features: string[]; // JSON array stored as TEXT, SQLite can query with json_each() + title: string; + description: string; +} + +export interface Overview { + id: number; + total_count: number; +} + +// Raw database row types (before JSON parsing) +export interface RawIconRow { + id: number; + cluster: string; + name: string; + base64: string; + description: string; + usecases: string; + synonyms: string; // JSON string before parsing + tags: string; // JSON string before parsing + industry: string; + emotional_cues: string; + enhanced: number; +} + +export interface RawClusterRow { + name: string; + count: number; + source_folder: string; + path: string; + keywords: string; // JSON string before parsing + features: string; // JSON string before parsing + title: string; + description: string; +} diff --git a/frontend/db/svg_icons/svg-icons-utils.ts b/frontend/db/svg_icons/svg-icons-utils.ts new file mode 100644 index 0000000000..4d8179a760 --- /dev/null +++ b/frontend/db/svg_icons/svg-icons-utils.ts @@ -0,0 +1,149 @@ +import Database from 'better-sqlite3'; +import path from 'path'; +import type { + Cluster, + Icon, + Overview, + RawClusterRow, + RawIconRow, +} from './svg-icons-schema'; + +let dbInstance: Database.Database | null = null; + +function getDbPath(): string { + return path.resolve(process.cwd(), 'db/svg_icons/svg-icons-db.db'); +} + +export function getDb(): Database.Database { + if (dbInstance) return dbInstance; + const dbPath = getDbPath(); + dbInstance = new Database(dbPath, { readonly: true }); + // Improve read performance for build-time queries + dbInstance.pragma('journal_mode = OFF'); + dbInstance.pragma('synchronous = OFF'); + return dbInstance; +} + +export function getClusterIcons(cluster: string, limit = 10): Icon[] { + const db = getDb(); + const stmt = db.prepare( + `SELECT id, cluster, name, base64, description, usecases, + json(synonyms) as synonyms, json(tags) as tags, + industry, emotional_cues, enhanced + FROM icon WHERE cluster = ? ORDER BY name LIMIT ?` + ); + const results = stmt.all(cluster, limit) as RawIconRow[]; + return results.map((row) => ({ + ...row, + synonyms: JSON.parse(row.synonyms || '[]') as string[], + tags: JSON.parse(row.tags || '[]') as string[], + })) as Icon[]; +} + +export function getClusters(): Cluster[] { + const db = getDb(); + const stmt = db.prepare( + `SELECT name, count, source_folder, path, + json(keywords) as keywords, json(features) as features, + title, description + FROM cluster ORDER BY name` + ); + const results = stmt.all() as RawClusterRow[]; + return results.map((row) => ({ + ...row, + keywords: JSON.parse(row.keywords || '[]') as string[], + features: JSON.parse(row.features || '[]') as string[], + })) as Cluster[]; +} + +export function getTotalIcons(): number { + const db = getDb(); + const row = db + .prepare('SELECT total_count FROM overview WHERE id = 1') + .get() as Overview | undefined; + return row?.total_count ?? 0; +} + +export function getIconsByCluster(cluster: string): Icon[] { + const db = getDb(); + const stmt = db.prepare( + `SELECT id, cluster, name, base64, description, usecases, + json(synonyms) as synonyms, json(tags) as tags, + industry, emotional_cues, enhanced + FROM icon WHERE cluster = ? ORDER BY name` + ); + const results = stmt.all(cluster) as RawIconRow[]; + return results.map((row) => ({ + ...row, + synonyms: JSON.parse(row.synonyms || '[]') as string[], + tags: JSON.parse(row.tags || '[]') as string[], + })) as Icon[]; +} + +export function getClusterByName(name: string): Cluster | null { + const db = getDb(); + const stmt = db.prepare( + `SELECT name, count, source_folder, path, + json(keywords) as keywords, json(features) as features, + title, description + FROM cluster WHERE name = ?` + ); + const result = stmt.get(name) as RawClusterRow | undefined; + if (!result) return null; + return { + ...result, + keywords: JSON.parse(result.keywords || '[]') as string[], + features: JSON.parse(result.features || '[]') as string[], + } as Cluster; +} + +// Get icon by category (cluster display name) and icon name (without .svg extension) +export function getIconByCategoryAndName( + category: string, + iconName: string +): Icon | null { + const db = getDb(); + // First, get the cluster to find the source_folder (actual cluster key) + const clusterData = getClusterByName(category); + if (!clusterData) return null; + + // Build the filename with .svg extension + const filename = iconName.includes('.svg') ? iconName : `${iconName}.svg`; + + // Query icon using source_folder (cluster key) and filename + const stmt = db.prepare( + `SELECT id, cluster, name, base64, description, usecases, + json(synonyms) as synonyms, json(tags) as tags, + industry, emotional_cues, enhanced + FROM icon WHERE cluster = ? AND name = ?` + ); + const result = stmt.get(clusterData.source_folder || category, filename) as + | RawIconRow + | undefined; + if (!result) return null; + + return { + ...result, + synonyms: JSON.parse(result.synonyms || '[]') as string[], + tags: JSON.parse(result.tags || '[]') as string[], + } as Icon; +} + +// Example helper function to query icons by tag using json_each +export function getIconsByTag(tag: string): Icon[] { + const db = getDb(); + const stmt = db.prepare( + `SELECT DISTINCT i.id, i.cluster, i.name, i.base64, i.description, i.usecases, + json(i.synonyms) as synonyms, json(i.tags) as tags, + i.industry, i.emotional_cues, i.enhanced + FROM icon i, json_each(i.tags) + WHERE json_each.value = ? + ORDER BY i.cluster, i.name` + ); + const results = stmt.all(tag) as RawIconRow[]; + return results.map((row) => ({ + ...row, + synonyms: JSON.parse(row.synonyms || '[]') as string[], + tags: JSON.parse(row.tags || '[]') as string[], + })) as Icon[]; +} diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 763338fa2f..e4814021c0 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -176,9 +176,9 @@ } }, "node_modules/@astrojs/mdx": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/@astrojs/mdx/-/mdx-4.3.7.tgz", - "integrity": "sha512-5SRmvMyT/UMWaU2eoD+htnXtE2mUZZEH2K/nEzhuEy+iCsOSuS/DUry59WuKUJRQETi1mgJFdNR4dZLJHYVuRA==", + "version": "4.3.9", + "resolved": "https://registry.npmjs.org/@astrojs/mdx/-/mdx-4.3.9.tgz", + "integrity": "sha512-80LHiM4z3FxAjATHNgFpa8nlTNSprAWB4UUKnr/QG56Pwk7uRnJWrXlok4wSCi/3fg8kTZ98A408Q91M+iqJdw==", "license": "MIT", "dependencies": { "@astrojs/markdown-remark": "6.3.8", @@ -187,7 +187,7 @@ "es-module-lexer": "^1.7.0", "estree-util-visit": "^2.0.0", "hast-util-to-html": "^9.0.5", - "kleur": "^4.1.5", + "picocolors": "^1.1.1", "rehype-raw": "^7.0.0", "remark-gfm": "^4.0.1", "remark-smartypants": "^3.0.2", @@ -215,14 +215,14 @@ } }, "node_modules/@astrojs/react": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@astrojs/react/-/react-4.4.0.tgz", - "integrity": "sha512-RzblkVImAFdV1C0AWsSWzS70Z0FMtW2p0XXkNYu3QePfyVJta3JIy8m8jY8271etaCZtpFjsE2UaiHGZIBm6nw==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@astrojs/react/-/react-4.4.1.tgz", + "integrity": "sha512-3M3RE+KYlbvov+uvn7SzgcO/zoMiK16Glwo9Ic0ZOJ0B+4PSULMeniwtyQg1m1Eq5k4BbqpIuC18lA2uzQSflQ==", "license": "MIT", "dependencies": { "@vitejs/plugin-react": "^4.7.0", "ultrahtml": "^1.6.0", - "vite": "^6.3.6" + "vite": "^6.4.1" }, "engines": { "node": "18.20.8 || ^20.3.0 || >=22.0.0" @@ -260,10 +260,19 @@ "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, + "node_modules/@astrojs/react/node_modules/react-refresh": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", + "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/@astrojs/react/node_modules/vite": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.0.tgz", - "integrity": "sha512-oLnWs9Hak/LOlKjeSpOwD6JMks8BeICEdYMJBf6P4Lac/pO9tKiv/XhXnAM7nNfSkZahjlCZu9sS50zL8fSnsw==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz", + "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", "license": "MIT", "dependencies": { "esbuild": "^0.25.0", @@ -431,29 +440,29 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.4.tgz", - "integrity": "sha512-YsmSKC29MJwf0gF8Rjjrg5LQCmyh+j/nD8/eP7f+BeoQTKYqs9RoWbjGOdy0+1Ekr68RJZMUOPVQaQisnIo4Rw==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.5.tgz", + "integrity": "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.4.tgz", - "integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz", + "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.3", + "@babel/generator": "^7.28.5", "@babel/helper-compilation-targets": "^7.27.2", "@babel/helper-module-transforms": "^7.28.3", "@babel/helpers": "^7.28.4", - "@babel/parser": "^7.28.4", + "@babel/parser": "^7.28.5", "@babel/template": "^7.27.2", - "@babel/traverse": "^7.28.4", - "@babel/types": "^7.28.4", + "@babel/traverse": "^7.28.5", + "@babel/types": "^7.28.5", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", @@ -469,14 +478,23 @@ "url": "https://opencollective.com/babel" } }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/@babel/generator": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz", - "integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz", + "integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==", "license": "MIT", "dependencies": { - "@babel/parser": "^7.28.3", - "@babel/types": "^7.28.2", + "@babel/parser": "^7.28.5", + "@babel/types": "^7.28.5", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" @@ -501,6 +519,15 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/@babel/helper-globals": { "version": "7.28.0", "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", @@ -559,9 +586,9 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", - "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -590,12 +617,12 @@ } }, "node_modules/@babel/parser": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.4.tgz", - "integrity": "sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", + "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", "license": "MIT", "dependencies": { - "@babel/types": "^7.28.4" + "@babel/types": "^7.28.5" }, "bin": { "parser": "bin/babel-parser.js" @@ -658,17 +685,17 @@ } }, "node_modules/@babel/traverse": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.4.tgz", - "integrity": "sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz", + "integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==", "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.3", + "@babel/generator": "^7.28.5", "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.28.4", + "@babel/parser": "^7.28.5", "@babel/template": "^7.27.2", - "@babel/types": "^7.28.4", + "@babel/types": "^7.28.5", "debug": "^4.3.1" }, "engines": { @@ -676,13 +703,13 @@ } }, "node_modules/@babel/types": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.4.tgz", - "integrity": "sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", + "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" + "@babel/helper-validator-identifier": "^7.28.5" }, "engines": { "node": ">=6.9.0" @@ -831,9 +858,9 @@ "license": "MIT" }, "node_modules/@emnapi/runtime": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.5.0.tgz", - "integrity": "sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.6.0.tgz", + "integrity": "sha512-obtUmAHTMjll499P+D9A3axeJFlhdjOWdKUNs/U6QIGT7V5RjcUW1xToAzjvmgTSQhDbYn/NwfTRoJcQ2rNBxA==", "license": "MIT", "optional": true, "dependencies": { @@ -1275,23 +1302,10 @@ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, "node_modules/@eslint-community/regexpp": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", - "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", "dev": true, "license": "MIT", "engines": { @@ -1338,13 +1352,26 @@ } }, "node_modules/@eslint/config-helpers": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.1.tgz", - "integrity": "sha512-csZAzkNhsgwb0I/UAV6/RGFTbiakPCf0ZrGmrIxQpYvGZ00PhTkSnyKNolphgIvmnJeGw6rcGVEXfTzUnFuEvw==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-helpers/node_modules/@eslint/core": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.16.0" + "@types/json-schema": "^7.0.15" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1411,6 +1438,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@eslint/eslintrc/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, "node_modules/@eslint/eslintrc/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -1424,19 +1461,6 @@ "node": "*" } }, - "node_modules/@eslint/eslintrc/node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@eslint/js": { "version": "9.38.0", "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.38.0.tgz", @@ -1461,19 +1485,32 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.0.tgz", - "integrity": "sha512-sB5uyeq+dwCWyPi31B2gQlVlo+j5brPlWx4yZBrEaRo/nhdDE8Xke1gsGgtiBdaBTxuTkceLVuVt/pclrasb0A==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.16.0", + "@eslint/core": "^0.17.0", "levn": "^0.4.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@eslint/plugin-kit/node_modules/@eslint/core": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@expressive-code/core": { "version": "0.41.3", "resolved": "https://registry.npmjs.org/@expressive-code/core/-/core-0.41.3.tgz", @@ -1567,9 +1604,9 @@ } }, "node_modules/@huggingface/transformers": { - "version": "3.7.5", - "resolved": "https://registry.npmjs.org/@huggingface/transformers/-/transformers-3.7.5.tgz", - "integrity": "sha512-5jvrIwHyRXfOKVaGKYvUZM6ZjJKQXWeKzIOdKBE5pdzPSNzTwBNx5NdWcGElf4Ddv7Dl2mWsvJh+G5RnCUxMmA==", + "version": "3.7.6", + "resolved": "https://registry.npmjs.org/@huggingface/transformers/-/transformers-3.7.6.tgz", + "integrity": "sha512-OYlIRY8vj8r/pNx2CdXcDHz4KqpEC+bUMKzdVW5Dx//gp4XRmK+/g8as0h3cssRQYT0vG1A6VCfZy8SV0F4RDQ==", "license": "Apache-2.0", "dependencies": { "@huggingface/jinja": "^0.5.1", @@ -2116,12 +2153,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "license": "MIT" - }, "node_modules/@isaacs/cliui/node_modules/string-width": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", @@ -3380,9 +3411,9 @@ "license": "MIT" }, "node_modules/@rolldown/pluginutils": { - "version": "1.0.0-beta.38", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.38.tgz", - "integrity": "sha512-N/ICGKleNhA5nc9XXQG/kkKHJ7S55u0x0XUJbbkmdCnFuoRkM1Il12q9q0eX19+M7KKUEPw/daUPIRnxhcxAIw==", + "version": "1.0.0-beta.43", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.43.tgz", + "integrity": "sha512-5Uxg7fQUCmfhax7FJke2+8B6cqgeUJUD9o2uXIKXhD+mG0mL6NObmVoi9wXEU1tY89mZKgAYA6fTbftx3q2ZPQ==", "dev": true, "license": "MIT" }, @@ -3415,9 +3446,9 @@ "license": "MIT" }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.52.4.tgz", - "integrity": "sha512-BTm2qKNnWIQ5auf4deoetINJm2JzvihvGb9R6K/ETwKLql/Bb3Eg2H1FBp1gUb4YGbydMA3jcmQTR73q7J+GAA==", + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.52.5.tgz", + "integrity": "sha512-8c1vW4ocv3UOMp9K+gToY5zL2XiiVw3k7f1ksf4yO1FlDFQ1C2u72iACFnSOceJFsWskc2WZNqeRhFRPzv+wtQ==", "cpu": [ "arm" ], @@ -3428,9 +3459,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.52.4.tgz", - "integrity": "sha512-P9LDQiC5vpgGFgz7GSM6dKPCiqR3XYN1WwJKA4/BUVDjHpYsf3iBEmVz62uyq20NGYbiGPR5cNHI7T1HqxNs2w==", + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.52.5.tgz", + "integrity": "sha512-mQGfsIEFcu21mvqkEKKu2dYmtuSZOBMmAl5CFlPGLY94Vlcm+zWApK7F/eocsNzp8tKmbeBP8yXyAbx0XHsFNA==", "cpu": [ "arm64" ], @@ -3441,9 +3472,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.52.4.tgz", - "integrity": "sha512-QRWSW+bVccAvZF6cbNZBJwAehmvG9NwfWHwMy4GbWi/BQIA/laTIktebT2ipVjNncqE6GLPxOok5hsECgAxGZg==", + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.52.5.tgz", + "integrity": "sha512-takF3CR71mCAGA+v794QUZ0b6ZSrgJkArC+gUiG6LB6TQty9T0Mqh3m2ImRBOxS2IeYBo4lKWIieSvnEk2OQWA==", "cpu": [ "arm64" ], @@ -3454,9 +3485,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.52.4.tgz", - "integrity": "sha512-hZgP05pResAkRJxL1b+7yxCnXPGsXU0fG9Yfd6dUaoGk+FhdPKCJ5L1Sumyxn8kvw8Qi5PvQ8ulenUbRjzeCTw==", + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.52.5.tgz", + "integrity": "sha512-W901Pla8Ya95WpxDn//VF9K9u2JbocwV/v75TE0YIHNTbhqUTv9w4VuQ9MaWlNOkkEfFwkdNhXgcLqPSmHy0fA==", "cpu": [ "x64" ], @@ -3467,9 +3498,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.52.4.tgz", - "integrity": "sha512-xmc30VshuBNUd58Xk4TKAEcRZHaXlV+tCxIXELiE9sQuK3kG8ZFgSPi57UBJt8/ogfhAF5Oz4ZSUBN77weM+mQ==", + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.52.5.tgz", + "integrity": "sha512-QofO7i7JycsYOWxe0GFqhLmF6l1TqBswJMvICnRUjqCx8b47MTo46W8AoeQwiokAx3zVryVnxtBMcGcnX12LvA==", "cpu": [ "arm64" ], @@ -3480,9 +3511,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.52.4.tgz", - "integrity": "sha512-WdSLpZFjOEqNZGmHflxyifolwAiZmDQzuOzIq9L27ButpCVpD7KzTRtEG1I0wMPFyiyUdOO+4t8GvrnBLQSwpw==", + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.52.5.tgz", + "integrity": "sha512-jr21b/99ew8ujZubPo9skbrItHEIE50WdV86cdSoRkKtmWa+DDr6fu2c/xyRT0F/WazZpam6kk7IHBerSL7LDQ==", "cpu": [ "x64" ], @@ -3493,9 +3524,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.52.4.tgz", - "integrity": "sha512-xRiOu9Of1FZ4SxVbB0iEDXc4ddIcjCv2aj03dmW8UrZIW7aIQ9jVJdLBIhxBI+MaTnGAKyvMwPwQnoOEvP7FgQ==", + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.52.5.tgz", + "integrity": "sha512-PsNAbcyv9CcecAUagQefwX8fQn9LQ4nZkpDboBOttmyffnInRy8R8dSg6hxxl2Re5QhHBf6FYIDhIj5v982ATQ==", "cpu": [ "arm" ], @@ -3506,9 +3537,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.52.4.tgz", - "integrity": "sha512-FbhM2p9TJAmEIEhIgzR4soUcsW49e9veAQCziwbR+XWB2zqJ12b4i/+hel9yLiD8pLncDH4fKIPIbt5238341Q==", + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.52.5.tgz", + "integrity": "sha512-Fw4tysRutyQc/wwkmcyoqFtJhh0u31K+Q6jYjeicsGJJ7bbEq8LwPWV/w0cnzOqR2m694/Af6hpFayLJZkG2VQ==", "cpu": [ "arm" ], @@ -3519,9 +3550,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.52.4.tgz", - "integrity": "sha512-4n4gVwhPHR9q/g8lKCyz0yuaD0MvDf7dV4f9tHt0C73Mp8h38UCtSCSE6R9iBlTbXlmA8CjpsZoujhszefqueg==", + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.52.5.tgz", + "integrity": "sha512-a+3wVnAYdQClOTlyapKmyI6BLPAFYs0JM8HRpgYZQO02rMR09ZcV9LbQB+NL6sljzG38869YqThrRnfPMCDtZg==", "cpu": [ "arm64" ], @@ -3532,9 +3563,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.52.4.tgz", - "integrity": "sha512-u0n17nGA0nvi/11gcZKsjkLj1QIpAuPFQbR48Subo7SmZJnGxDpspyw2kbpuoQnyK+9pwf3pAoEXerJs/8Mi9g==", + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.52.5.tgz", + "integrity": "sha512-AvttBOMwO9Pcuuf7m9PkC1PUIKsfaAJ4AYhy944qeTJgQOqJYJ9oVl2nYgY7Rk0mkbsuOpCAYSs6wLYB2Xiw0Q==", "cpu": [ "arm64" ], @@ -3545,9 +3576,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.52.4.tgz", - "integrity": "sha512-0G2c2lpYtbTuXo8KEJkDkClE/+/2AFPdPAbmaHoE870foRFs4pBrDehilMcrSScrN/fB/1HTaWO4bqw+ewBzMQ==", + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.52.5.tgz", + "integrity": "sha512-DkDk8pmXQV2wVrF6oq5tONK6UHLz/XcEVow4JTTerdeV1uqPeHxwcg7aFsfnSm9L+OO8WJsWotKM2JJPMWrQtA==", "cpu": [ "loong64" ], @@ -3558,9 +3589,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.52.4.tgz", - "integrity": "sha512-teSACug1GyZHmPDv14VNbvZFX779UqWTsd7KtTM9JIZRDI5NUwYSIS30kzI8m06gOPB//jtpqlhmraQ68b5X2g==", + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.52.5.tgz", + "integrity": "sha512-W/b9ZN/U9+hPQVvlGwjzi+Wy4xdoH2I8EjaCkMvzpI7wJUs8sWJ03Rq96jRnHkSrcHTpQe8h5Tg3ZzUPGauvAw==", "cpu": [ "ppc64" ], @@ -3571,9 +3602,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.52.4.tgz", - "integrity": "sha512-/MOEW3aHjjs1p4Pw1Xk4+3egRevx8Ji9N6HUIA1Ifh8Q+cg9dremvFCUbOX2Zebz80BwJIgCBUemjqhU5XI5Eg==", + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.52.5.tgz", + "integrity": "sha512-sjQLr9BW7R/ZiXnQiWPkErNfLMkkWIoCz7YMn27HldKsADEKa5WYdobaa1hmN6slu9oWQbB6/jFpJ+P2IkVrmw==", "cpu": [ "riscv64" ], @@ -3584,9 +3615,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.52.4.tgz", - "integrity": "sha512-1HHmsRyh845QDpEWzOFtMCph5Ts+9+yllCrREuBR/vg2RogAQGGBRC8lDPrPOMnrdOJ+mt1WLMOC2Kao/UwcvA==", + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.52.5.tgz", + "integrity": "sha512-hq3jU/kGyjXWTvAh2awn8oHroCbrPm8JqM7RUpKjalIRWWXE01CQOf/tUNWNHjmbMHg/hmNCwc/Pz3k1T/j/Lg==", "cpu": [ "riscv64" ], @@ -3597,9 +3628,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.52.4.tgz", - "integrity": "sha512-seoeZp4L/6D1MUyjWkOMRU6/iLmCU2EjbMTyAG4oIOs1/I82Y5lTeaxW0KBfkUdHAWN7j25bpkt0rjnOgAcQcA==", + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.52.5.tgz", + "integrity": "sha512-gn8kHOrku8D4NGHMK1Y7NA7INQTRdVOntt1OCYypZPRt6skGbddska44K8iocdpxHTMMNui5oH4elPH4QOLrFQ==", "cpu": [ "s390x" ], @@ -3610,9 +3641,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.52.4.tgz", - "integrity": "sha512-Wi6AXf0k0L7E2gteNsNHUs7UMwCIhsCTs6+tqQ5GPwVRWMaflqGec4Sd8n6+FNFDw9vGcReqk2KzBDhCa1DLYg==", + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.52.5.tgz", + "integrity": "sha512-hXGLYpdhiNElzN770+H2nlx+jRog8TyynpTVzdlc6bndktjKWyZyiCsuDAlpd+j+W+WNqfcyAWz9HxxIGfZm1Q==", "cpu": [ "x64" ], @@ -3623,9 +3654,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.52.4.tgz", - "integrity": "sha512-dtBZYjDmCQ9hW+WgEkaffvRRCKm767wWhxsFW3Lw86VXz/uJRuD438/XvbZT//B96Vs8oTA8Q4A0AfHbrxP9zw==", + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.52.5.tgz", + "integrity": "sha512-arCGIcuNKjBoKAXD+y7XomR9gY6Mw7HnFBv5Rw7wQRvwYLR7gBAgV7Mb2QTyjXfTveBNFAtPt46/36vV9STLNg==", "cpu": [ "x64" ], @@ -3636,9 +3667,9 @@ ] }, "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.52.4.tgz", - "integrity": "sha512-1ox+GqgRWqaB1RnyZXL8PD6E5f7YyRUJYnCqKpNzxzP0TkaUh112NDrR9Tt+C8rJ4x5G9Mk8PQR3o7Ku2RKqKA==", + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.52.5.tgz", + "integrity": "sha512-QoFqB6+/9Rly/RiPjaomPLmR/13cgkIGfA40LHly9zcH1S0bN2HVFYk3a1eAyHQyjs3ZJYlXvIGtcCs5tko9Cw==", "cpu": [ "arm64" ], @@ -3649,9 +3680,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.52.4.tgz", - "integrity": "sha512-8GKr640PdFNXwzIE0IrkMWUNUomILLkfeHjXBi/nUvFlpZP+FA8BKGKpacjW6OUUHaNI6sUURxR2U2g78FOHWQ==", + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.52.5.tgz", + "integrity": "sha512-w0cDWVR6MlTstla1cIfOGyl8+qb93FlAVutcor14Gf5Md5ap5ySfQ7R9S/NjNaMLSFdUnKGEasmVnu3lCMqB7w==", "cpu": [ "arm64" ], @@ -3662,9 +3693,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.52.4.tgz", - "integrity": "sha512-AIy/jdJ7WtJ/F6EcfOb2GjR9UweO0n43jNObQMb6oGxkYTfLcnN7vYYpG+CN3lLxrQkzWnMOoNSHTW54pgbVxw==", + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.52.5.tgz", + "integrity": "sha512-Aufdpzp7DpOTULJCuvzqcItSGDH73pF3ko/f+ckJhxQyHtp67rHw3HMNxoIdDMUITJESNE6a8uh4Lo4SLouOUg==", "cpu": [ "ia32" ], @@ -3675,9 +3706,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.52.4.tgz", - "integrity": "sha512-UF9KfsH9yEam0UjTwAgdK0anlQ7c8/pWPU2yVjyWcF1I1thABt6WXE47cI71pGiZ8wGvxohBoLnxM04L/wj8mQ==", + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.52.5.tgz", + "integrity": "sha512-UGBUGPFp1vkj6p8wCRraqNhqwX/4kNQPS57BCFc8wYh0g94iVIW33wJtQAx3G7vrjjNtRaxiMUylM0ktp/TRSQ==", "cpu": [ "x64" ], @@ -3688,9 +3719,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.52.4.tgz", - "integrity": "sha512-bf9PtUa0u8IXDVxzRToFQKsNCRz9qLYfR/MpECxl4mRoWYjAeFjgxj1XdZr2M/GNVpT05p+LgQOHopYDlUu6/w==", + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.52.5.tgz", + "integrity": "sha512-TAcgQh2sSkykPRWLrdyy2AiceMckNf5loITqXxFI5VuQjS5tSuw3WlwdN8qv8vzjLAUTvYaH/mVjSFpbkFbpTg==", "cpu": [ "x64" ], @@ -3701,60 +3732,60 @@ ] }, "node_modules/@shikijs/core": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-3.13.0.tgz", - "integrity": "sha512-3P8rGsg2Eh2qIHekwuQjzWhKI4jV97PhvYjYUzGqjvJfqdQPz+nMlfWahU24GZAyW1FxFI1sYjyhfh5CoLmIUA==", + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-3.14.0.tgz", + "integrity": "sha512-qRSeuP5vlYHCNUIrpEBQFO7vSkR7jn7Kv+5X3FO/zBKVDGQbcnlScD3XhkrHi/R8Ltz0kEjvFR9Szp/XMRbFMw==", "license": "MIT", "dependencies": { - "@shikijs/types": "3.13.0", + "@shikijs/types": "3.14.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "node_modules/@shikijs/engine-javascript": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-3.13.0.tgz", - "integrity": "sha512-Ty7xv32XCp8u0eQt8rItpMs6rU9Ki6LJ1dQOW3V/56PKDcpvfHPnYFbsx5FFUP2Yim34m/UkazidamMNVR4vKg==", + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-3.14.0.tgz", + "integrity": "sha512-3v1kAXI2TsWQuwv86cREH/+FK9Pjw3dorVEykzQDhwrZj0lwsHYlfyARaKmn6vr5Gasf8aeVpb8JkzeWspxOLQ==", "license": "MIT", "dependencies": { - "@shikijs/types": "3.13.0", + "@shikijs/types": "3.14.0", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.3" } }, "node_modules/@shikijs/engine-oniguruma": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.13.0.tgz", - "integrity": "sha512-O42rBGr4UDSlhT2ZFMxqM7QzIU+IcpoTMzb3W7AlziI1ZF7R8eS2M0yt5Ry35nnnTX/LTLXFPUjRFCIW+Operg==", + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.14.0.tgz", + "integrity": "sha512-TNcYTYMbJyy+ZjzWtt0bG5y4YyMIWC2nyePz+CFMWqm+HnZZyy9SWMgo8Z6KBJVIZnx8XUXS8U2afO6Y0g1Oug==", "license": "MIT", "dependencies": { - "@shikijs/types": "3.13.0", + "@shikijs/types": "3.14.0", "@shikijs/vscode-textmate": "^10.0.2" } }, "node_modules/@shikijs/langs": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.13.0.tgz", - "integrity": "sha512-672c3WAETDYHwrRP0yLy3W1QYB89Hbpj+pO4KhxK6FzIrDI2FoEXNiNCut6BQmEApYLfuYfpgOZaqbY+E9b8wQ==", + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.14.0.tgz", + "integrity": "sha512-DIB2EQY7yPX1/ZH7lMcwrK5pl+ZkP/xoSpUzg9YC8R+evRCCiSQ7yyrvEyBsMnfZq4eBzLzBlugMyTAf13+pzg==", "license": "MIT", "dependencies": { - "@shikijs/types": "3.13.0" + "@shikijs/types": "3.14.0" } }, "node_modules/@shikijs/themes": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.13.0.tgz", - "integrity": "sha512-Vxw1Nm1/Od8jyA7QuAenaV78BG2nSr3/gCGdBkLpfLscddCkzkL36Q5b67SrLLfvAJTOUzW39x4FHVCFriPVgg==", + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.14.0.tgz", + "integrity": "sha512-fAo/OnfWckNmv4uBoUu6dSlkcBc+SA1xzj5oUSaz5z3KqHtEbUypg/9xxgJARtM6+7RVm0Q6Xnty41xA1ma1IA==", "license": "MIT", "dependencies": { - "@shikijs/types": "3.13.0" + "@shikijs/types": "3.14.0" } }, "node_modules/@shikijs/types": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.13.0.tgz", - "integrity": "sha512-oM9P+NCFri/mmQ8LoFGVfVyemm5Hi27330zuOBp0annwJdKH1kOLndw3zCtAVDehPLg9fKqoEx3Ht/wNZxolfw==", + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.14.0.tgz", + "integrity": "sha512-bQGgC6vrY8U/9ObG1Z/vTro+uclbjjD/uG58RvfxKZVD5p9Yc1ka3tVyEFy7BNJLzxuWyHH5NWynP9zZZS59eQ==", "license": "MIT", "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", @@ -3941,13 +3972,14 @@ } }, "node_modules/@types/chai": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.2.tgz", - "integrity": "sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", "dev": true, "license": "MIT", "dependencies": { - "@types/deep-eql": "*" + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" } }, "node_modules/@types/debug": { @@ -3967,9 +3999,9 @@ "license": "MIT" }, "node_modules/@types/emscripten": { - "version": "1.41.4", - "resolved": "https://registry.npmjs.org/@types/emscripten/-/emscripten-1.41.4.tgz", - "integrity": "sha512-ECf0qTibhAi2Z0K6FIY96CvBTVkVIuVunOfbTUgbaAmGmbwsc33dbK9KZPROWsmzHotddy6C5pIqYqOmsBoJEw==", + "version": "1.41.5", + "resolved": "https://registry.npmjs.org/@types/emscripten/-/emscripten-1.41.5.tgz", + "integrity": "sha512-cMQm7pxu6BxtHyqJ7mQZ2kXWV5SLmugybFdHCBbJ5eHzOo6VhBckEgAT3//rP5FwPHNPeEiq4SmQ5ucBwsOo4Q==", "license": "MIT" }, "node_modules/@types/estree": { @@ -4075,12 +4107,12 @@ } }, "node_modules/@types/node": { - "version": "24.8.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.8.0.tgz", - "integrity": "sha512-5x08bUtU8hfboMTrJ7mEO4CpepS9yBwAqcL52y86SWNmbPX8LVbNs3EP4cNrIZgdjk2NAlP2ahNihozpoZIxSg==", + "version": "24.9.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.9.2.tgz", + "integrity": "sha512-uWN8YqxXxqFMX2RqGOrumsKeti4LlmIMIyV0lgut4jx7KQBcBiW6vkDtIBvHnHIquwNfJhk8v2OtmO8zXWHfPA==", "license": "MIT", "dependencies": { - "undici-types": "~7.14.0" + "undici-types": "~7.16.0" } }, "node_modules/@types/react": { @@ -4182,16 +4214,6 @@ "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", - "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, "node_modules/@typescript-eslint/parser": { "version": "8.46.2", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.46.2.tgz", @@ -4342,35 +4364,6 @@ "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/@typescript-eslint/typescript-estree/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/@typescript-eslint/typescript-estree/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/@typescript-eslint/utils": { "version": "8.46.2", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.46.2.tgz", @@ -4413,6 +4406,19 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/@ungap/structured-clone": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", @@ -4420,18 +4426,18 @@ "license": "ISC" }, "node_modules/@vitejs/plugin-react": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.0.4.tgz", - "integrity": "sha512-La0KD0vGkVkSk6K+piWDKRUyg8Rl5iAIKRMH0vMJI0Eg47bq1eOxmoObAaQG37WMW9MSyk7Cs8EIWwJC1PtzKA==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.1.0.tgz", + "integrity": "sha512-4LuWrg7EKWgQaMJfnN+wcmbAW+VSsCmqGohftWjuct47bv8uE4n/nPpq4XjJPsxgq00GGG5J8dvBczp8uxScew==", "dev": true, "license": "MIT", "dependencies": { "@babel/core": "^7.28.4", "@babel/plugin-transform-react-jsx-self": "^7.27.1", "@babel/plugin-transform-react-jsx-source": "^7.27.1", - "@rolldown/pluginutils": "1.0.0-beta.38", + "@rolldown/pluginutils": "1.0.0-beta.43", "@types/babel__core": "^7.20.5", - "react-refresh": "^0.17.0" + "react-refresh": "^0.18.0" }, "engines": { "node": "^20.19.0 || >=22.12.0" @@ -4556,9 +4562,9 @@ } }, "node_modules/ace-builds": { - "version": "1.43.3", - "resolved": "https://registry.npmjs.org/ace-builds/-/ace-builds-1.43.3.tgz", - "integrity": "sha512-MCl9rALmXwIty/4Qboijo/yNysx1r6hBTzG+6n/TiOm5LFhZpEvEIcIITPFiEOEFDfgBOEmxu+a4f54LEFM6Sg==", + "version": "1.43.4", + "resolved": "https://registry.npmjs.org/ace-builds/-/ace-builds-1.43.4.tgz", + "integrity": "sha512-8hAxVfo2ImICd69BWlZwZlxe9rxDGDjuUhh+WeWgGDvfBCE+r3lkynkQvIovDz4jcMi8O7bsEaFygaDT+h9sBA==", "license": "BSD-3-Clause" }, "node_modules/acorn": { @@ -4623,6 +4629,15 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "license": "MIT" }, + "node_modules/ansi-align/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", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/ansi-align/node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -4928,9 +4943,9 @@ } }, "node_modules/astro": { - "version": "5.14.5", - "resolved": "https://registry.npmjs.org/astro/-/astro-5.14.5.tgz", - "integrity": "sha512-EHt7y3+nHYyKzBats1AL3N4Pyrvqyr+zXBC7njUa9Tfe+gsiHlunaw+lXitTT/DDVwO2R/f/qVG7Xc6rl0b2KQ==", + "version": "5.15.2", + "resolved": "https://registry.npmjs.org/astro/-/astro-5.15.2.tgz", + "integrity": "sha512-xQQ+PiYJ7WpUJrHJpAb52TQAUCFmSR8lAtQr3tFfSIZoTQiEMFx3HITJ01t3eDUpHjja8J6JcYqgAhr9xygKQg==", "license": "MIT", "dependencies": { "@astrojs/compiler": "^2.12.2", @@ -4965,7 +4980,6 @@ "http-cache-semantics": "^4.2.0", "import-meta-resolve": "^4.2.0", "js-yaml": "^4.1.0", - "kleur": "^4.1.5", "magic-string": "^0.30.18", "magicast": "^0.3.5", "mrmime": "^2.0.1", @@ -4973,6 +4987,7 @@ "p-limit": "^6.2.0", "p-queue": "^8.1.0", "package-manager-detector": "^1.3.0", + "picocolors": "^1.1.1", "picomatch": "^4.0.3", "prompts": "^2.4.2", "rehype": "^13.0.2", @@ -4987,7 +5002,7 @@ "unist-util-visit": "^5.0.0", "unstorage": "^1.17.0", "vfile": "^6.0.3", - "vite": "^6.3.6", + "vite": "^6.4.1", "vitefu": "^1.1.1", "xxhash-wasm": "^1.1.0", "yargs-parser": "^21.1.1", @@ -5062,17 +5077,17 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/astro-eslint-parser/node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "node_modules/astro-eslint-parser/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, + "license": "Apache-2.0", "engines": { - "node": ">=10" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/astro-expressive-code": { @@ -5120,22 +5135,10 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/astro/node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/astro/node_modules/vite": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.0.tgz", - "integrity": "sha512-oLnWs9Hak/LOlKjeSpOwD6JMks8BeICEdYMJBf6P4Lac/pO9tKiv/XhXnAM7nNfSkZahjlCZu9sS50zL8fSnsw==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz", + "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", "license": "MIT", "dependencies": { "esbuild": "^0.25.0", @@ -5327,9 +5330,9 @@ } }, "node_modules/axios": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.12.2.tgz", - "integrity": "sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.1.tgz", + "integrity": "sha512-hU4EGxxt+j7TQijx1oYdAjw4xuIp1wRQSsbMFwSthCWeBQur1eF+qJ5iQ5sN3Tw8YRzQNKb8jszgBdMDVqwJcw==", "dev": true, "license": "MIT", "dependencies": { @@ -5390,9 +5393,9 @@ "license": "MIT" }, "node_modules/baseline-browser-mapping": { - "version": "2.8.17", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.17.tgz", - "integrity": "sha512-j5zJcx6golJYTG6c05LUZ3Z8Gi+M62zRT/ycz4Xq4iCOdpcxwg7ngEYD4KA0eWZC7U17qh/Smq8bYbACJ0ipBA==", + "version": "2.8.21", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.21.tgz", + "integrity": "sha512-JU0h5APyQNsHOlAM7HnQnPToSDQoEBZqzu/YBlqDnEeymPnZDREeXJA3KBMQee+dKteAxZ2AtvQEvVYdZf241Q==", "license": "Apache-2.0", "bin": { "baseline-browser-mapping": "dist/cli.js" @@ -5513,9 +5516,9 @@ } }, "node_modules/browserslist": { - "version": "4.26.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.26.3.tgz", - "integrity": "sha512-lAUU+02RFBuCKQPj/P6NgjlbCnLBMp4UtgTx7vNHd3XSIJF87s9a5rA3aH2yw3GS9DqZAUbOtZdCCiZeVRqt0w==", + "version": "4.27.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.27.0.tgz", + "integrity": "sha512-AXVQwdhot1eqLihwasPElhX2tAZiBjWdJ9i/Zcj2S6QYIjkx62OKSfnobkriB81C3l4w0rVy3Nt4jaTBltYEpw==", "funding": [ { "type": "opencollective", @@ -5532,11 +5535,11 @@ ], "license": "MIT", "dependencies": { - "baseline-browser-mapping": "^2.8.9", - "caniuse-lite": "^1.0.30001746", - "electron-to-chromium": "^1.5.227", - "node-releases": "^2.0.21", - "update-browserslist-db": "^1.1.3" + "baseline-browser-mapping": "^2.8.19", + "caniuse-lite": "^1.0.30001751", + "electron-to-chromium": "^1.5.238", + "node-releases": "^2.0.26", + "update-browserslist-db": "^1.1.4" }, "bin": { "browserslist": "cli.js" @@ -5930,9 +5933,9 @@ } }, "node_modules/cli-truncate": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-5.1.0.tgz", - "integrity": "sha512-7JDGG+4Zp0CsknDCedl0DYdaeOhc46QNpXi3NLQblkZpXXgA6LncLDUUyvrjSvZeF3VRQa+KiMGomazQrC1V8g==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-5.1.1.tgz", + "integrity": "sha512-SroPvNHxUnk+vIW/dOSfNqdy1sPEFkrTk6TUtqLCnBlo3N7TNYYkzzN7uSD6+jVjrdO4+p8nH7JzH6cIvUem6A==", "dev": true, "license": "MIT", "dependencies": { @@ -5995,6 +5998,15 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "license": "MIT" }, + "node_modules/cliui/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", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/cliui/node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -6112,12 +6124,13 @@ } }, "node_modules/commander": { - "version": "12.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", - "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "version": "14.0.2", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.2.tgz", + "integrity": "sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ==", + "dev": true, "license": "MIT", "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/common-ancestor-path": { @@ -6155,9 +6168,9 @@ "license": "MIT" }, "node_modules/cronstrue": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/cronstrue/-/cronstrue-3.3.0.tgz", - "integrity": "sha512-iwJytzJph1hosXC09zY8F5ACDJKerr0h3/2mOxg9+5uuFObYlgK0m35uUPk4GCvhHc2abK7NfnR9oMqY0qZFAg==", + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/cronstrue/-/cronstrue-3.9.0.tgz", + "integrity": "sha512-T3S35zmD0Ai2B4ko6+mEM+k9C6tipe2nB9RLiGT6QL2Wn0Vsn2cCZAC8Oeuf4CaE00GZWVdpYitbpWCNlIWqdA==", "license": "MIT", "bin": { "cronstrue": "bin/cli.js" @@ -6570,9 +6583,9 @@ } }, "node_modules/devalue": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.4.1.tgz", - "integrity": "sha512-YtoaOfsqjbZQKGIMRYDWKjUmSB4VJ/RElB+bXZawQAQYAo4xu08GKTMVlsZDTF6R2MbAgjcAQRPI5eIyRAT2OQ==", + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.4.2.tgz", + "integrity": "sha512-MwPZTKEPK2k8Qgfmqrd48ZKVvzSQjgW0lXLxiIBA8dQjtf/6mw6pggHNLcyDKyf+fI6eXxlQwPsfaCMTU5U+Bw==", "license": "MIT" }, "node_modules/devlop": { @@ -6758,15 +6771,15 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.237", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.237.tgz", - "integrity": "sha512-icUt1NvfhGLar5lSWH3tHNzablaA5js3HVHacQimfP8ViEBOQv+L7DKEuHdbTZ0SKCO1ogTJTIL1Gwk9S6Qvcg==", + "version": "1.5.243", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.243.tgz", + "integrity": "sha512-ZCphxFW3Q1TVhcgS9blfut1PX8lusVi2SvXQgmEEnK4TCmE1JhH2JkjJN+DNt0pJJwfBri5AROBnz2b/C+YU9g==", "license": "ISC" }, "node_modules/emoji-regex": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", - "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "license": "MIT" }, "node_modules/encoding-sniffer": { @@ -7176,19 +7189,6 @@ "eslint": ">=6.0.0" } }, - "node_modules/eslint-compat-utils/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/eslint-config-prettier": { "version": "10.1.8", "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz", @@ -7206,9 +7206,9 @@ } }, "node_modules/eslint-plugin-astro": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-astro/-/eslint-plugin-astro-1.3.1.tgz", - "integrity": "sha512-2XaLCMQm8htW1UvJvy1Zcmg8l0ziskitiUfJTn/w1Mk7r4Mxj0fZeNpN6UTNrm64XBIXSa5h8UCGrg8mdu47+g==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-astro/-/eslint-plugin-astro-1.4.0.tgz", + "integrity": "sha512-BCHPj3gORh1RYFR3sZXY0/9N9lOOw4mQYUkMWFFoFqhZtYnytuzxlyCIr8tqMmSNdZ9P4SQNq5h4v8Amr2EE5Q==", "dev": true, "license": "MIT", "dependencies": { @@ -7217,7 +7217,7 @@ "@typescript-eslint/types": "^7.7.1 || ^8", "astro-eslint-parser": "^1.0.2", "eslint-compat-utils": "^0.6.0", - "globals": "^15.0.0", + "globals": "^16.0.0", "postcss": "^8.4.14", "postcss-selector-parser": "^7.0.0" }, @@ -7231,19 +7231,6 @@ "eslint": ">=8.57.0" } }, - "node_modules/eslint-plugin-astro/node_modules/globals": { - "version": "15.15.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz", - "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/eslint-plugin-astro/node_modules/postcss-selector-parser": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", @@ -7309,13 +7296,6 @@ "concat-map": "0.0.1" } }, - "node_modules/eslint-plugin-jsx-a11y/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true, - "license": "MIT" - }, "node_modules/eslint-plugin-jsx-a11y/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -7363,17 +7343,17 @@ } }, "node_modules/eslint-plugin-react-hooks": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.0.0.tgz", - "integrity": "sha512-fNXaOwvKwq2+pXiRpXc825Vd63+KM4DLL40Rtlycb8m7fYpp6efrTp1sa6ZbP/Ap58K2bEKFXRmhURE+CJAQWw==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.0.1.tgz", + "integrity": "sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA==", "dev": true, "license": "MIT", "dependencies": { "@babel/core": "^7.24.4", "@babel/parser": "^7.24.4", "hermes-parser": "^0.25.1", - "zod": "^3.22.4 || ^4.0.0", - "zod-validation-error": "^3.0.3 || ^4.0.0" + "zod": "^3.25.0 || ^4.0.0", + "zod-validation-error": "^3.5.0 || ^4.0.0" }, "engines": { "node": ">=18" @@ -7406,22 +7386,14 @@ "node": "*" } }, - "node_modules/eslint-plugin-react/node_modules/resolve": { - "version": "2.0.0-next.5", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", - "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "node_modules/eslint-plugin-react/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": "MIT", - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, + "license": "ISC", "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "semver": "bin/semver.js" } }, "node_modules/eslint-scope": { @@ -7442,13 +7414,13 @@ } }, "node_modules/eslint-visitor-keys": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", - "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, "license": "Apache-2.0", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -7498,37 +7470,27 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/eslint/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, + "license": "Apache-2.0", "engines": { - "node": ">=10" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "node_modules/eslint/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 4" } }, "node_modules/eslint/node_modules/minimatch": { @@ -7544,22 +7506,6 @@ "node": "*" } }, - "node_modules/eslint/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/espree": { "version": "10.4.0", "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", @@ -7578,6 +7524,19 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/esquery": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", @@ -7870,16 +7829,20 @@ } }, "node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, "license": "MIT", "dependencies": { - "locate-path": "^5.0.0", + "locate-path": "^6.0.0", "path-exists": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/flat-cache": { @@ -8249,6 +8212,21 @@ "node": ">=10.13.0" } }, + "node_modules/glob/node_modules/minimatch": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz", + "integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/brace-expansion": "^5.0.0" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/global-agent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", @@ -8266,18 +8244,6 @@ "node": ">=10.0" } }, - "node_modules/global-agent/node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/globals": { "version": "16.4.0", "resolved": "https://registry.npmjs.org/globals/-/globals-16.4.0.tgz", @@ -9013,9 +8979,9 @@ "license": "BSD-3-Clause" }, "node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", "dev": true, "license": "MIT", "engines": { @@ -9334,12 +9300,19 @@ } }, "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", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", + "integrity": "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==", + "dev": true, "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.3.1" + }, "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/is-generator-function": { @@ -9906,9 +9879,9 @@ } }, "node_modules/kleur": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", - "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", "license": "MIT", "engines": { "node": ">=6" @@ -9924,9 +9897,9 @@ } }, "node_modules/konva": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/konva/-/konva-10.0.2.tgz", - "integrity": "sha512-NrZED6YG5BX5h3Xu8EZgLqhQ/+ZhxANYXmlIhMOfpBf+0ToExcdwE+Y46LyJOO/JR7FVeR3YTqon3eirnuo44A==", + "version": "10.0.8", + "resolved": "https://registry.npmjs.org/konva/-/konva-10.0.8.tgz", + "integrity": "sha512-kQqErBIj2mR/srYDheRD2hq5v0gkwqoJZvbPz3DhCcyRNJfMEnd/AzLhWz2f567BB9vtL2p2EqKwI6n+MyM9Hw==", "funding": [ { "type": "patreon", @@ -10017,14 +9990,14 @@ "license": "MIT" }, "node_modules/lint-staged": { - "version": "16.2.5", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-16.2.5.tgz", - "integrity": "sha512-o36wH3OX0jRWqDw5dOa8a8x6GXTKaLM+LvhRaucZxez0IxA+KNDUCiyjBfNgsMNmchwSX6urLSL7wShcUqAang==", + "version": "16.2.6", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-16.2.6.tgz", + "integrity": "sha512-s1gphtDbV4bmW1eylXpVMk2u7is7YsrLl8hzrtvC70h4ByhcMLZFY01Fx05ZUDNuv1H8HO4E+e2zgejV1jVwNw==", "dev": true, "license": "MIT", "dependencies": { "commander": "^14.0.1", - "listr2": "^9.0.4", + "listr2": "^9.0.5", "micromatch": "^4.0.8", "nano-spawn": "^2.0.0", "pidtree": "^0.6.0", @@ -10041,16 +10014,6 @@ "url": "https://opencollective.com/lint-staged" } }, - "node_modules/lint-staged/node_modules/commander": { - "version": "14.0.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.1.tgz", - "integrity": "sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=20" - } - }, "node_modules/listr2": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/listr2/-/listr2-9.0.5.tgz", @@ -10070,15 +10033,19 @@ } }, "node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, "license": "MIT", "dependencies": { - "p-locate": "^4.1.0" + "p-locate": "^5.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/lodash": { @@ -10185,9 +10152,9 @@ } }, "node_modules/magic-string": { - "version": "0.30.19", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.19.tgz", - "integrity": "sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==", + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" @@ -10227,9 +10194,9 @@ } }, "node_modules/marked": { - "version": "16.4.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-16.4.0.tgz", - "integrity": "sha512-CTPAcRBq57cn3R8n3hwc2REddc28hjR7RzDXQ+lXLmMJYqn20BaI2cGw6QjgZGIgVfp2Wdfw4aMzgNteQ6qJgQ==", + "version": "16.4.1", + "resolved": "https://registry.npmjs.org/marked/-/marked-16.4.1.tgz", + "integrity": "sha512-ntROs7RaN3EvWfy3EZi14H4YxmT6A5YvywfhO+0pm+cH/dnSQRmdAmoFIc3B9aiwTehyk7pESH4ofyBY+V5hZg==", "license": "MIT", "bin": { "marked": "bin/marked.js" @@ -11437,15 +11404,15 @@ } }, "node_modules/minimatch": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.3.tgz", - "integrity": "sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "license": "ISC", "dependencies": { - "@isaacs/brace-expansion": "^5.0.0" + "brace-expansion": "^2.0.1" }, "engines": { - "node": "20 || >=22" + "node": ">=16 || 14 >=14.17" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -11583,10 +11550,9 @@ } }, "node_modules/node-abi": { - "version": "3.78.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.78.0.tgz", - "integrity": "sha512-E2wEyrgX/CqvicaQYU3Ze1PFGjc4QYPGsjUrlYkqAE0WjHEZwgOsGMPMzkMse4LjJbDmaEuDX3CM036j5K2DSQ==", - "dev": true, + "version": "3.79.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.79.0.tgz", + "integrity": "sha512-Pr/5KdBQGG8TirdkS0qN3B+f3eo8zTOfZQWAxHoJqopMz2/uvRnG+S4fWu/6AZxKei2CP2p/psdQ5HFC2Ap5BA==", "license": "MIT", "dependencies": { "semver": "^7.3.5" @@ -11601,20 +11567,6 @@ "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", "dev": true, "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/node-addon-api": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", - "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", - "dev": true, - "license": "MIT" - }, "node_modules/node-fetch-native": { "version": "1.6.7", "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz", @@ -11628,9 +11580,9 @@ "license": "MIT" }, "node_modules/node-releases": { - "version": "2.0.25", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.25.tgz", - "integrity": "sha512-4auku8B/vw5psvTiiN9j1dAOsXvMoGqJuKJcR+dTdqiXEK20mMTk1UEo3HS16LeGQsVG6+qKTPM9u/qQ2LqATA==", + "version": "2.0.26", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.26.tgz", + "integrity": "sha512-S2M9YimhSjBSvYnlr5/+umAnPHE++ODwt5e2Ij6FoX45HA/s4vHdkDx1eax2pAPeAOqu4s9b7ppahsyEFdVqQA==", "license": "MIT" }, "node_modules/normalize-path": { @@ -11786,14 +11738,14 @@ } }, "node_modules/ofetch": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/ofetch/-/ofetch-1.4.1.tgz", - "integrity": "sha512-QZj2DfGplQAr2oj9KzceK9Hwz6Whxazmn85yYeVuS3u9XTMOGMRx0kO95MQ+vLsj/S/NwBDMMLU5hpxvI6Tklw==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/ofetch/-/ofetch-1.5.0.tgz", + "integrity": "sha512-A7llJ7eZyziA5xq9//3ZurA8OhFqtS99K5/V1sLBJ5j137CM/OAjlbA/TEJXBuOWwOfLqih+oH5U3ran4za1FQ==", "license": "MIT", "dependencies": { - "destr": "^2.0.3", - "node-fetch-native": "^1.6.4", - "ufo": "^1.5.4" + "destr": "^2.0.5", + "node-fetch-native": "^1.6.7", + "ufo": "^1.6.1" } }, "node_modules/ohash": { @@ -11941,27 +11893,16 @@ } }, "node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-locate/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, "license": "MIT", "dependencies": { - "p-try": "^2.0.0" + "p-limit": "^3.0.2" }, "engines": { - "node": ">=6" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -12011,9 +11952,9 @@ "license": "BlueOak-1.0.0" }, "node_modules/package-manager-detector": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.4.1.tgz", - "integrity": "sha512-dSMiVLBEA4XaNJ0PRb4N5cV/SEP4BWrWZKBmfF+OUm2pQTiZ6DDkKeWaltwu3JRhLoy59ayIkJ00cx9K9CaYTg==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.5.0.tgz", + "integrity": "sha512-uBj69dVlYe/+wxj8JOpr97XfsxH/eumMt6HqjNTmJDf/6NO9s+0uxeOneIz3AsPt2m6y9PqzDzd3ATcU17MNfw==", "license": "MIT" }, "node_modules/pagefind": { @@ -12357,6 +12298,26 @@ "postcss": "^8.0.0" } }, + "node_modules/postcss-import/node_modules/resolve": { + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/postcss-js": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.1.0.tgz", @@ -12581,15 +12542,6 @@ "node": ">= 6" } }, - "node_modules/prompts/node_modules/kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", @@ -12683,6 +12635,15 @@ "purgecss": "bin/purgecss.js" } }, + "node_modules/purgecss/node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/purgecss/node_modules/postcss-selector-parser": { "version": "6.1.2", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", @@ -12755,6 +12716,15 @@ "rc": "cli.js" } }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/react": { "version": "19.2.0", "resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz", @@ -12853,9 +12823,9 @@ "peer": true }, "node_modules/react-konva": { - "version": "19.0.10", - "resolved": "https://registry.npmjs.org/react-konva/-/react-konva-19.0.10.tgz", - "integrity": "sha512-tJID7bungYs8ri5McjjlHWCniQMAasiNkTgATd8OJEnLrz3B7S5JN7nFkNfWETIHPx9rEN3gc+kQg32RhdZJcw==", + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/react-konva/-/react-konva-19.2.0.tgz", + "integrity": "sha512-Ofifq/rdNvff50+Lj8x86WSfoeQDvdysOlsXMMrpD2uWmDxUPrEYSRLt27iCfdovQZL6xinKRpX9VaL9xDwXDQ==", "funding": [ { "type": "patreon", @@ -12872,48 +12842,37 @@ ], "license": "MIT", "dependencies": { - "@types/react-reconciler": "^0.32.1", + "@types/react-reconciler": "^0.32.2", "its-fine": "^2.0.0", - "react-reconciler": "0.32.0", - "scheduler": "0.26.0" + "react-reconciler": "0.33.0", + "scheduler": "0.27.0" }, "peerDependencies": { "konva": "^8.0.1 || ^7.2.5 || ^9.0.0 || ^10.0.0", - "react": "^18.3.1 || ^19.0.0", - "react-dom": "^18.3.1 || ^19.0.0" + "react": "^19.2.0", + "react-dom": "^19.2.0" } }, - "node_modules/react-konva/node_modules/scheduler": { - "version": "0.26.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", - "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==", - "license": "MIT" - }, "node_modules/react-reconciler": { - "version": "0.32.0", - "resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.32.0.tgz", - "integrity": "sha512-2NPMOzgTlG0ZWdIf3qG+dcbLSoAc/uLfOwckc3ofy5sSK0pLJqnQLpUFxvGcN2rlXSjnVtGeeFLNimCQEj5gOQ==", + "version": "0.33.0", + "resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.33.0.tgz", + "integrity": "sha512-KetWRytFv1epdpJc3J4G75I4WrplZE5jOL7Yq0p34+OVOKF4Se7WrdIdVC45XsSSmUTlht2FM/fM1FZb1mfQeA==", "license": "MIT", "dependencies": { - "scheduler": "^0.26.0" + "scheduler": "^0.27.0" }, "engines": { "node": ">=0.10.0" }, "peerDependencies": { - "react": "^19.1.0" + "react": "^19.2.0" } }, - "node_modules/react-reconciler/node_modules/scheduler": { - "version": "0.26.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", - "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==", - "license": "MIT" - }, "node_modules/react-refresh": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", - "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.18.0.tgz", + "integrity": "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -13433,21 +13392,19 @@ "license": "ISC" }, "node_modules/resolve": { - "version": "1.22.10", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", - "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "version": "2.0.0-next.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "dev": true, "license": "MIT", "dependencies": { - "is-core-module": "^2.16.0", + "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" }, - "engines": { - "node": ">= 0.4" - }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -13581,9 +13538,9 @@ } }, "node_modules/rollup": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.52.4.tgz", - "integrity": "sha512-CLEVl+MnPAiKh5pl4dEWSyMTpuflgNQiLGhMv8ezD5W/qP8AKvmYpCOKRRNOh7oRKnauBZ4SyeYkMS+1VSyKwQ==", + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.52.5.tgz", + "integrity": "sha512-3GuObel8h7Kqdjt0gxkEzaifHTqLVW56Y/bjN7PSQtkKr0w3V/QYSdt6QWYtd7A1xUtYQigtdUfgj1RvWVtorw==", "license": "MIT", "dependencies": { "@types/estree": "1.0.8" @@ -13596,28 +13553,28 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.52.4", - "@rollup/rollup-android-arm64": "4.52.4", - "@rollup/rollup-darwin-arm64": "4.52.4", - "@rollup/rollup-darwin-x64": "4.52.4", - "@rollup/rollup-freebsd-arm64": "4.52.4", - "@rollup/rollup-freebsd-x64": "4.52.4", - "@rollup/rollup-linux-arm-gnueabihf": "4.52.4", - "@rollup/rollup-linux-arm-musleabihf": "4.52.4", - "@rollup/rollup-linux-arm64-gnu": "4.52.4", - "@rollup/rollup-linux-arm64-musl": "4.52.4", - "@rollup/rollup-linux-loong64-gnu": "4.52.4", - "@rollup/rollup-linux-ppc64-gnu": "4.52.4", - "@rollup/rollup-linux-riscv64-gnu": "4.52.4", - "@rollup/rollup-linux-riscv64-musl": "4.52.4", - "@rollup/rollup-linux-s390x-gnu": "4.52.4", - "@rollup/rollup-linux-x64-gnu": "4.52.4", - "@rollup/rollup-linux-x64-musl": "4.52.4", - "@rollup/rollup-openharmony-arm64": "4.52.4", - "@rollup/rollup-win32-arm64-msvc": "4.52.4", - "@rollup/rollup-win32-ia32-msvc": "4.52.4", - "@rollup/rollup-win32-x64-gnu": "4.52.4", - "@rollup/rollup-win32-x64-msvc": "4.52.4", + "@rollup/rollup-android-arm-eabi": "4.52.5", + "@rollup/rollup-android-arm64": "4.52.5", + "@rollup/rollup-darwin-arm64": "4.52.5", + "@rollup/rollup-darwin-x64": "4.52.5", + "@rollup/rollup-freebsd-arm64": "4.52.5", + "@rollup/rollup-freebsd-x64": "4.52.5", + "@rollup/rollup-linux-arm-gnueabihf": "4.52.5", + "@rollup/rollup-linux-arm-musleabihf": "4.52.5", + "@rollup/rollup-linux-arm64-gnu": "4.52.5", + "@rollup/rollup-linux-arm64-musl": "4.52.5", + "@rollup/rollup-linux-loong64-gnu": "4.52.5", + "@rollup/rollup-linux-ppc64-gnu": "4.52.5", + "@rollup/rollup-linux-riscv64-gnu": "4.52.5", + "@rollup/rollup-linux-riscv64-musl": "4.52.5", + "@rollup/rollup-linux-s390x-gnu": "4.52.5", + "@rollup/rollup-linux-x64-gnu": "4.52.5", + "@rollup/rollup-linux-x64-musl": "4.52.5", + "@rollup/rollup-openharmony-arm64": "4.52.5", + "@rollup/rollup-win32-arm64-msvc": "4.52.5", + "@rollup/rollup-win32-ia32-msvc": "4.52.5", + "@rollup/rollup-win32-x64-gnu": "4.52.5", + "@rollup/rollup-win32-x64-msvc": "4.52.5", "fsevents": "~2.3.2" } }, @@ -13777,12 +13734,15 @@ "license": "MIT" }, "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", "license": "ISC", "bin": { "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, "node_modules/semver-compare": { @@ -13915,18 +13875,6 @@ "@img/sharp-win32-x64": "0.34.4" } }, - "node_modules/sharp/node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -13949,17 +13897,17 @@ } }, "node_modules/shiki": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-3.13.0.tgz", - "integrity": "sha512-aZW4l8Og16CokuCLf8CF8kq+KK2yOygapU5m3+hoGw0Mdosc6fPitjM+ujYarppj5ZIKGyPDPP1vqmQhr+5/0g==", + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-3.14.0.tgz", + "integrity": "sha512-J0yvpLI7LSig3Z3acIuDLouV5UCKQqu8qOArwMx+/yPVC3WRMgrP67beaG8F+j4xfEWE0eVC4GeBCIXeOPra1g==", "license": "MIT", "dependencies": { - "@shikijs/core": "3.13.0", - "@shikijs/engine-javascript": "3.13.0", - "@shikijs/engine-oniguruma": "3.13.0", - "@shikijs/langs": "3.13.0", - "@shikijs/themes": "3.13.0", - "@shikijs/types": "3.13.0", + "@shikijs/core": "3.14.0", + "@shikijs/engine-javascript": "3.14.0", + "@shikijs/engine-oniguruma": "3.14.0", + "@shikijs/langs": "3.14.0", + "@shikijs/themes": "3.14.0", + "@shikijs/types": "3.14.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } @@ -14138,15 +14086,15 @@ "license": "MIT" }, "node_modules/sitemap": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/sitemap/-/sitemap-8.0.0.tgz", - "integrity": "sha512-+AbdxhM9kJsHtruUF39bwS/B0Fytw6Fr1o4ZAIAEqA6cke2xcoO2GleBw9Zw7nRzILVEgz7zBM5GiTJjie1G9A==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/sitemap/-/sitemap-8.0.2.tgz", + "integrity": "sha512-LwktpJcyZDoa0IL6KT++lQ53pbSrx2c9ge41/SeLTyqy2XUNA6uR4+P9u5IVo5lPeL2arAcOKn1aZAxoYbCKlQ==", "license": "MIT", "dependencies": { "@types/node": "^17.0.5", "@types/sax": "^1.2.1", "arg": "^5.0.0", - "sax": "^1.2.4" + "sax": "^1.4.1" }, "bin": { "sitemap": "dist/cli.js" @@ -14192,22 +14140,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", - "integrity": "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "get-east-asian-width": "^1.3.1" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/smol-toml": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.4.2.tgz", @@ -14346,6 +14278,15 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "license": "MIT" }, + "node_modules/string-width-cjs/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", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/string-width-cjs/node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -14358,6 +14299,12 @@ "node": ">=8" } }, + "node_modules/string-width/node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "license": "MIT" + }, "node_modules/string.prototype.includes": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz", @@ -14539,13 +14486,16 @@ } }, "node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/strip-literal": { @@ -14658,21 +14608,6 @@ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "license": "ISC" }, - "node_modules/sucrase/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/sucrase/node_modules/path-scurry": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", @@ -14807,6 +14742,26 @@ "node": ">=4" } }, + "node_modules/tailwindcss/node_modules/resolve": { + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/tar": { "version": "7.5.1", "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.1.tgz", @@ -15271,9 +15226,9 @@ } }, "node_modules/undici-types": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.14.0.tgz", - "integrity": "sha512-QQiYxHuyZ9gQUIrmPo3IA+hUl4KYk8uSA7cHrcKd/l3p1OTpZcM0Tbp9x7FAtXdAYhlasd60ncPpgu6ihG6TOA==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", "license": "MIT" }, "node_modules/unicode-properties": { @@ -15341,9 +15296,9 @@ } }, "node_modules/unist-util-is": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", - "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0" @@ -15449,9 +15404,9 @@ } }, "node_modules/unist-util-visit-parents": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", - "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", @@ -15593,9 +15548,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", - "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.4.tgz", + "integrity": "sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==", "funding": [ { "type": "opencollective", @@ -15732,9 +15687,9 @@ } }, "node_modules/vite": { - "version": "7.1.10", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.10.tgz", - "integrity": "sha512-CmuvUBzVJ/e3HGxhg6cYk88NGgTnBoOo7ogtfJJ0fefUWAxN/WDSUa50o+oVBxuIhO8FoEZW0j2eW7sfjs5EtA==", + "version": "7.1.12", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.12.tgz", + "integrity": "sha512-ZWyE8YXEXqJrrSLvYgrRP7p62OziLW7xI5HYGWFzOvupfAlrLvURSzv/FyGyy0eidogEM3ujU+kUG1zuHgb6Ug==", "devOptional": true, "license": "MIT", "dependencies": { @@ -16215,6 +16170,15 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "license": "MIT" }, + "node_modules/wrap-ansi-cjs/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", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/wrap-ansi-cjs/node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -16399,6 +16363,67 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "license": "MIT" }, + "node_modules/yargs/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/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", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yargs/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/yargs/node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", diff --git a/frontend/scripts/svg_icons_to_base64/build_sqlite_from_json.py b/frontend/scripts/svg_icons_to_base64/build_sqlite_from_json.py new file mode 100644 index 0000000000..1c5ae64328 --- /dev/null +++ b/frontend/scripts/svg_icons_to_base64/build_sqlite_from_json.py @@ -0,0 +1,265 @@ +#!/usr/bin/env python3 +""" +Build a SQLite database from base64 SVG JSON files and verify contents. + +- Scans scripts/svg_icons_to_base64/base64_svg_icons/*.json +- Reads data/cluster_svg.json for metadata +- Creates SQLite DB at db/svg_icons/svg-icons-db.db +- Table: icon(id INTEGER PRIMARY KEY AUTOINCREMENT, cluster TEXT, name TEXT, base64 TEXT, ...) +- Table: cluster(name TEXT PRIMARY KEY, count INTEGER, source_folder TEXT, ...) +- Table: overview(id INTEGER PRIMARY KEY CHECK(id = 1), total_count INTEGER) +- Indexes on (cluster) and (cluster, name) +- Verifies by printing counts and sample rows +""" + +import json +import sqlite3 +from pathlib import Path + +BASE_DIR = Path(__file__).parent +JSON_DIR = BASE_DIR / "base64_svg_icons" +CLUSTER_SVG_PATH = BASE_DIR.parent.parent / "data" / "cluster_svg.json" +DB_PATH = Path(__file__).parent.parent.parent / "db" / "svg_icons" / "svg-icons-db.db" + + +def ensure_schema(conn: sqlite3.Connection) -> None: + cur = conn.cursor() + cur.execute( + """ + CREATE TABLE IF NOT EXISTS icon ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + cluster TEXT NOT NULL, + name TEXT NOT NULL, + base64 TEXT NOT NULL, + description TEXT DEFAULT '', + usecases TEXT DEFAULT '', + synonyms TEXT DEFAULT '[]', + tags TEXT DEFAULT '[]', + industry TEXT DEFAULT '', + emotional_cues TEXT DEFAULT '', + enhanced INTEGER DEFAULT 0 + ); + """ + ) + cur.execute("CREATE INDEX IF NOT EXISTS idx_icon_cluster ON icon(cluster);") + cur.execute( + "CREATE UNIQUE INDEX IF NOT EXISTS idx_icon_cluster_name ON icon(cluster, name);" + ) + + # Create cluster table + cur.execute( + """ + CREATE TABLE IF NOT EXISTS cluster ( + name TEXT PRIMARY KEY, + count INTEGER NOT NULL, + source_folder TEXT DEFAULT '', + path TEXT DEFAULT '', + keywords TEXT DEFAULT '[]', + features TEXT DEFAULT '[]', + title TEXT DEFAULT '', + description TEXT DEFAULT '' + ); + """ + ) + + # Create overview table + cur.execute( + """ + CREATE TABLE IF NOT EXISTS overview ( + id INTEGER PRIMARY KEY CHECK(id = 1), + total_count INTEGER NOT NULL + ); + """ + ) + conn.commit() + + +essql = "INSERT OR IGNORE INTO icon(cluster, name, base64, description, usecases, synonyms, tags, industry, emotional_cues, enhanced) VALUES(?, ?, ?, ?, ?, json(?), json(?), ?, ?, ?)" + + +def load_cluster_svg_data() -> dict: + """Load cluster_svg.json metadata.""" + if not CLUSTER_SVG_PATH.exists(): + print( + f"⚠ cluster_svg.json not found at {CLUSTER_SVG_PATH}, using empty metadata" + ) + return {} + + try: + with open(CLUSTER_SVG_PATH, "r", encoding="utf-8") as f: + data = json.load(f) + return data.get("clusters", {}) + except Exception as e: + print(f"⚠ Failed to read cluster_svg.json: {e}, using empty metadata") + return {} + + +def load_json_files(conn: sqlite3.Connection) -> tuple[int, int]: + if not JSON_DIR.exists(): + raise SystemExit(f"JSON directory not found: {JSON_DIR}") + + cluster_metadata = load_cluster_svg_data() + cur = conn.cursor() + inserted = 0 + files = list(JSON_DIR.glob("*.json")) + + for json_file in files: + cluster = json_file.stem + cluster_data = cluster_metadata.get(cluster, {}) + file_names_data = { + item.get("fileName", ""): item for item in cluster_data.get("fileNames", []) + } + + try: + data = json.loads(json_file.read_text("utf-8")) + except Exception as e: + print(f"✗ Failed to read {json_file}: {e}") + continue + icons = data.get("icons") + if not isinstance(icons, list): + print(f"⚠ Skipping {json_file.name}: no 'icons' array") + continue + + batch = [] + for item in icons: + filename = item.get("filename", "") + if not filename or not item.get("base64"): + continue + + # Get metadata from cluster_svg.json for this specific file + file_meta = file_names_data.get(filename, {}) + + # Prepare data with defaults + description = file_meta.get("description", "") + usecases = file_meta.get("usecases", "") + synonyms = json.dumps(file_meta.get("synonyms", [])) + tags = json.dumps(file_meta.get("tags", [])) + industry = file_meta.get("industry", "") + emotional_cues = file_meta.get("emotional_cues", "") + enhanced = 1 if file_meta.get("enhanced", False) else 0 + + batch.append( + ( + cluster, + filename, + item.get("base64", ""), + description, + usecases, + synonyms, + tags, + industry, + emotional_cues, + enhanced, + ) + ) + + cur.executemany(essql, batch) + conn.commit() + print(f"✓ {json_file.name}: inserted {len(batch)} rows") + inserted += len(batch) + return inserted, len(files) + + +def populate_cluster_and_overview(conn: sqlite3.Connection) -> None: + """Populate cluster and overview tables from icon table and cluster_svg.json.""" + cur = conn.cursor() + cluster_metadata = load_cluster_svg_data() + + # Populate cluster table + cur.execute("DELETE FROM cluster;") + + # Get all clusters from icon table + cur.execute("SELECT DISTINCT cluster FROM icon ORDER BY cluster;") + clusters = [row[0] for row in cur.fetchall()] + + for cluster_name in clusters: + # Count icons for this cluster + cur.execute("SELECT COUNT(*) FROM icon WHERE cluster = ?;", (cluster_name,)) + count = cur.fetchone()[0] + + # Get metadata from cluster_svg.json + cluster_data = cluster_metadata.get(cluster_name, {}) + + # Use display name from cluster_svg.json, fallback to folder name + display_name = cluster_data.get("name", cluster_name) + source_folder = cluster_data.get("source_folder", cluster_name) + path = cluster_data.get("path", "") + keywords = json.dumps(cluster_data.get("keywords", [])) + features = json.dumps(cluster_data.get("features", [])) + title = cluster_data.get("title", "") + description = cluster_data.get("description", "") + + cur.execute( + """ + INSERT INTO cluster (name, count, source_folder, path, keywords, features, title, description) + VALUES (?, ?, ?, ?, json(?), json(?), ?, ?); + """, + ( + display_name, + count, + source_folder, + path, + keywords, + features, + title, + description, + ), + ) + + # Get total count and populate overview table + cur.execute("SELECT COUNT(*) FROM icon;") + total_count = cur.fetchone()[0] + + cur.execute("DELETE FROM overview;") + cur.execute("INSERT INTO overview (id, total_count) VALUES (1, ?);", (total_count,)) + + conn.commit() + print(f"✓ Populated cluster and overview tables") + + +def verify(conn: sqlite3.Connection) -> None: + cur = conn.cursor() + cur.execute("SELECT COUNT(*) FROM icon;") + total = cur.fetchone()[0] + print(f"Total rows: {total}") + + cur.execute( + "SELECT cluster, COUNT(*) FROM icon GROUP BY cluster ORDER BY cluster LIMIT 10;" + ) + for cluster, count in cur.fetchall(): + print(f" {cluster}: {count}") + + cur.execute( + "SELECT cluster, name, length(base64) FROM icon ORDER BY cluster, name LIMIT 5;" + ) + print("Sample rows:") + for row in cur.fetchall(): + print(" ", row) + + # Verify cluster table + cur.execute( + "SELECT name, count, source_folder FROM cluster ORDER BY name LIMIT 10;" + ) + print("\nCluster table:") + for row in cur.fetchall(): + print(f" {row[0]}: {row[1]} icons, source_folder: {row[2]}") + + # Verify overview table + cur.execute("SELECT total_count FROM overview WHERE id = 1;") + overview_row = cur.fetchone() + if overview_row: + print(f"\nOverview table: total_count = {overview_row[0]}") + + +def main() -> None: + DB_PATH.unlink(missing_ok=True) + with sqlite3.connect(DB_PATH) as conn: + ensure_schema(conn) + inserted, files = load_json_files(conn) + print(f"Inserted {inserted} rows from {files} files into {DB_PATH}") + populate_cluster_and_overview(conn) + verify(conn) + + +if __name__ == "__main__": + main() diff --git a/frontend/scripts/svg_icons_to_base64/svg_to_db.py b/frontend/scripts/svg_icons_to_base64/svg_to_db.py new file mode 100644 index 0000000000..2b3e9da09d --- /dev/null +++ b/frontend/scripts/svg_icons_to_base64/svg_to_db.py @@ -0,0 +1,206 @@ +#!/usr/bin/env python3 +""" +SVG to Base64 Converter +Converts SVG files to base64 encoded strings and stores them in a JSON file. +""" + +import base64 +import io +import json +import os +import shutil +import xml.etree.ElementTree as ET +from concurrent.futures import ProcessPoolExecutor, as_completed +from multiprocessing import Pool, cpu_count +from pathlib import Path + +# Import build_sqlite_from_json to call it after processing +import build_sqlite_from_json +import cairosvg +from PIL import Image + + +def svg_to_base64(svg_path): + """ + Convert SVG file to high-quality WebP and then to base64 encoded string. + Uses cairosvg with high DPI (600) for maximum quality rendering. + + Args: + svg_path (str): Path to the SVG file + + Returns: + str: Base64 encoded string of the WebP + """ + try: + # Always render at 80x80 for consistent high quality output + # This matches the test script behavior + final_width = 80 + final_height = 80 + + # Render SVG to PNG with very high DPI for maximum quality + png_bytes = cairosvg.svg2png( + url=str(svg_path), + output_width=final_width, + output_height=final_height, + dpi=600, + ) + + # Open with PIL and convert to WebP + img = Image.open(io.BytesIO(png_bytes)) + + # Preserve transparency - convert to RGBA if needed (WebP supports RGBA with transparency) + if img.mode != "RGBA": + img = img.convert("RGBA") + + # Save to bytes as WebP with high quality + img_bytes = io.BytesIO() + img.save(img_bytes, format="WebP", quality=80, method=6) + img_bytes.seek(0) + + # Convert to base64 + base64_string = base64.b64encode(img_bytes.getvalue()).decode("utf-8") + return base64_string + + except Exception as e: + print(f"Error converting {svg_path}: {e}") + return None + + +def process_single_svg(svg_file): + """ + Process a single SVG file and return base64 encoded data. + + Args: + svg_file (Path): Path to the SVG file + + Returns: + tuple: (filename, base64_string) or (filename, None) if failed + """ + try: + base64_string = svg_to_base64(svg_file) + return svg_file.name, base64_string + except Exception as e: + print(f"Error processing {svg_file.name}: {e}") + return svg_file.name, None + + +def process_svg_directory(svg_dir): + """ + Process SVG files in a directory and return base64 encoded data. + Uses parallel processing for faster conversion. + Processes all SVG files in the directory. + + Args: + svg_dir (str): Path to directory containing SVG files + + Returns: + list: List of base64 encoded WebP strings + """ + svg_path = Path(svg_dir) + + if not svg_path.exists(): + print(f"Directory {svg_dir} does not exist") + return [] + + # Find all SVG files in the directory + svg_files = list(svg_path.glob("*.svg")) + + if not svg_files: + print(f"No SVG files found in {svg_dir}") + return [] + + print(f"Processing {len(svg_files)} SVG files") + + # Use parallel processing + base64_data = [] + max_workers = min(7, cpu_count()) # Use 7 threads or available CPUs + + with ProcessPoolExecutor(max_workers=max_workers) as executor: + # Submit all tasks + future_to_file = { + executor.submit(process_single_svg, svg_file): svg_file + for svg_file in svg_files + } + + # Collect results as they complete + for future in as_completed(future_to_file): + svg_file = future_to_file[future] + try: + filename, base64_string = future.result() + if base64_string: + base64_data.append({"filename": filename, "base64": base64_string}) + print(f"✓ Processed: {filename}") + else: + print(f"✗ Failed: {filename}") + except Exception as e: + print(f"✗ Error processing {svg_file.name}: {e}") + + return base64_data + + +def main(): + """ + Main function to process SVG directories and generate multiple JSON files. + Uses parallel processing for faster execution. + """ + # Base directory containing SVG icon folders + base_dir = Path("../../public/svg_icons") + output_dir = Path("base64_svg_icons") + + if not base_dir.exists(): + print(f"Base directory {base_dir} does not exist") + return + + # Create output directory if it doesn't exist + output_dir.mkdir(exist_ok=True) + print(f"Output directory: {output_dir}") + print(f"Using {min(7, cpu_count())} CPU threads for parallel processing") + + processed_clusters = 0 + total_clusters = len([d for d in base_dir.iterdir() if d.is_dir()]) + + print(f"Found {total_clusters} clusters to process") + + # Process each subdirectory in svg_icons + for i, cluster_dir in enumerate(base_dir.iterdir(), 1): + if cluster_dir.is_dir(): + cluster_name = cluster_dir.name + print(f"\n[{i}/{total_clusters}] Processing cluster: {cluster_name}") + + # Get base64 data for all SVG files in this cluster + base64_data = process_svg_directory(cluster_dir) + + if base64_data: + # Create JSON data for this cluster + cluster_data = {"icons": base64_data} + + # Write individual JSON file for this cluster + output_file = output_dir / f"{cluster_name}.json" + try: + with open(output_file, "w", encoding="utf-8") as f: + json.dump(cluster_data, f, indent=2, ensure_ascii=False) + print(f"✓ Created {output_file} with {len(base64_data)} images") + processed_clusters += 1 + except Exception as e: + print(f"✗ Error writing {output_file}: {e}") + else: + print(f"✗ No valid SVG files found in cluster '{cluster_name}'") + + print(f"\n🎉 Successfully processed {processed_clusters}/{total_clusters} clusters") + print(f"📁 JSON files created in: {output_dir}") + + # Build SQLite database from JSON files + print(f"\n🔨 Building SQLite database from JSON files...") + try: + build_sqlite_from_json.main() + # Delete base64_svg_icons directory after successful database build + if output_dir.exists(): + print(f"\n🗑️ Deleting {output_dir} directory...") + shutil.rmtree(output_dir) + print(f"✓ Deleted {output_dir}") + except Exception as e: + print(f"✗ Error building SQLite database: {e}") + + +if __name__ == "__main__": + main() diff --git a/frontend/src/content.config.ts b/frontend/src/content.config.ts index ae0c001129..d10aefa8ed 100644 --- a/frontend/src/content.config.ts +++ b/frontend/src/content.config.ts @@ -105,52 +105,6 @@ const mcpCategoryData = defineCollection({ }), }); -// Define the SVG icons metadata collection -const svgIconsMetadata = defineCollection({ - loader: file('data/cluster_svg.json', { - parser: (fileContent) => { - const data = JSON.parse(fileContent); - return { - 'svg-icons-metadata': data, - }; - }, - }), - schema: z.object({ - clusters: z.record( - z.string(), - z.object({ - name: z.string(), - source_folder: z.string(), - path: z.string(), - keywords: z.array(z.string()), - features: z.array(z.string()), - title: z.string(), - description: z.string(), - fileNames: z.array( - z.union([ - z.string(), // Simple filename - z - .object({ - fileName: z.string(), - description: z.string().optional(), - usecases: z.string().optional(), - synonyms: z.array(z.string()).optional(), - tags: z.array(z.string()).optional(), - industry: z.string().optional(), - emotional_cues: z.string().optional(), - enhanced: z.boolean().optional(), - author: z.string().optional(), - license: z.string().optional(), - }) - .passthrough(), // Allow additional properties - ]) - ), - enhanced: z.boolean().optional(), - }) - ), - }), -}); - // Define the PNG icons metadata collection const pngIconsMetadata = defineCollection({ loader: file('data/cluster_png.json', { @@ -201,6 +155,5 @@ export const collections = { tldr, mcpMetadata, mcpCategoryData, - svgIconsMetadata, pngIconsMetadata, }; diff --git a/frontend/src/lib/svg-icons-utils.ts b/frontend/src/lib/svg-icons-utils.ts deleted file mode 100644 index f685c46f74..0000000000 --- a/frontend/src/lib/svg-icons-utils.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { getCollection } from 'astro:content'; - -/** - * Generate paginated paths for SVG icons categories - */ -export async function generateSvgIconsStaticPaths() { - const svgIconsEntries = await getCollection('svgIconsMetadata'); - const iconsData = svgIconsEntries[0]?.data; - - if (!iconsData) { - throw new Error('SVG icons metadata not found'); - } - - // Get all categories with their data - const categories = Object.entries(iconsData.clusters).map( - ([key, clusterData]) => ({ - id: key, - name: clusterData.name, - description: clusterData.description, - icon: `/freedevtools/svg_icons/${clusterData.name}/`, - iconCount: clusterData.fileNames.length, - url: `/freedevtools/svg_icons/${clusterData.name}/`, - keywords: clusterData.keywords, - features: clusterData.features, - fileNames: clusterData.fileNames, // Include fileNames for icon previews - }) - ); - - const itemsPerPage = 30; - const totalPages = Math.ceil(categories.length / itemsPerPage); - const paths: any[] = []; - - // Generate pagination pages (2, 3, 4, etc. - page 1 is handled by index.astro) - for (let i = 2; i <= totalPages; i++) { - paths.push({ - params: { page: i.toString() }, - props: { - type: 'pagination', - page: i, - itemsPerPage, - totalPages, - categories, - }, - }); - } - - return paths; -} - -/** - * Create a category-to-icons mapping for efficient lookups - */ -export async function createCategoryIconsMap() { - const svgIconsEntries = await getCollection('svgIconsMetadata'); - const iconsData = svgIconsEntries[0]?.data; - - if (!iconsData) { - throw new Error('SVG icons metadata not found'); - } - - const categoryMap = new Map(); - - for (const [key, clusterData] of Object.entries(iconsData.clusters)) { - const icons = clusterData.fileNames.map((fileObj: any) => { - const iconName = - typeof fileObj === 'string' - ? fileObj.replace('.svg', '') - : fileObj.fileName.replace('.svg', ''); - - return { - name: iconName, - url: `/freedevtools/svg_icons/${clusterData.name}/${iconName}/`, - description: - typeof fileObj === 'object' ? fileObj.description || '' : '', - category: clusterData.name, - }; - }); - - categoryMap.set(clusterData.name, icons); - } - - return categoryMap; -} diff --git a/frontend/src/pages/svg_icons/[category].astro b/frontend/src/pages/svg_icons/[category].astro index ae664b29b9..797b815bcb 100644 --- a/frontend/src/pages/svg_icons/[category].astro +++ b/frontend/src/pages/svg_icons/[category].astro @@ -1,61 +1,57 @@ --- -import BaseLayout from '../../layouts/BaseLayout.astro'; +import { + getClusterByName, + getClusters, + getIconsByCluster, +} from 'db/svg_icons/svg-icons-utils'; +import AdBanner from '../../components/banner/AdBanner.astro'; import CreditsButton from '../../components/buttons/CreditsButton'; import ToolContainer from '../../components/tool/ToolContainer'; import ToolHead from '../../components/tool/ToolHead'; -import { getCollection } from 'astro:content'; -import AdBanner from '../../components/banner/AdBanner.astro'; +import BaseLayout from '../../layouts/BaseLayout.astro'; export async function getStaticPaths() { - const svgIconsEntries = await getCollection('svgIconsMetadata'); - const iconsData = svgIconsEntries[0]?.data; + const clusters = getClusters(); - if (!iconsData) { - throw new Error('SVG icons metadata not found'); - } + // Use cluster names for URLs (these match cluster_svg.json cluster.name) + const categories = clusters.map((cluster) => cluster.name); - const categories = Object.values(iconsData.clusters).map((cluster: any) => cluster.name); - - return categories.map(category => ({ + return categories.map((category) => ({ params: { category }, - props: { category } + props: { category }, })); } const { category } = Astro.params; async function getCategoryIcons() { - const svgIconsEntries = await getCollection('svgIconsMetadata'); - const iconsData = svgIconsEntries[0]?.data; + // Get icons from SQLite database + // The category parameter is the cluster display name (from cluster.name in cluster_svg.json) + // Look up cluster by display name to get the source_folder (actual folder name used in icon table) + const clusterData = getClusterByName(category); - if (!iconsData) { + if (!clusterData) { return []; } - // Find the cluster by name - const cluster = Object.values(iconsData.clusters).find((c: any) => c.name === category) as any; - if (!cluster) { - return []; - } - - const icons = []; + // The icon table uses cluster key (folder name = source_folder), not display name + // Use source_folder to query icons + const dbIcons = getIconsByCluster(clusterData.source_folder || category); - // Process each file object in the cluster - NO SVG loading at build time - for (const fileObj of cluster.fileNames) { - const iconName = typeof fileObj === 'string' - ? fileObj.replace('.svg', '') - : fileObj.fileName?.replace('.svg', '') || ''; + const icons = dbIcons.map((icon) => { + const iconName = icon.name.replace('.svg', ''); - icons.push({ + return { name: iconName, - description: typeof fileObj === 'object' ? fileObj.description || `Free ${iconName} icon` : `Free ${iconName} icon`, + description: icon.description || `Free ${iconName} icon`, category: category, - tags: typeof fileObj === 'object' ? fileObj.tags || cluster.keywords || [] : cluster.keywords || [], - author: typeof fileObj === 'object' ? fileObj.author || 'Free DevTools' : 'Free DevTools', - license: typeof fileObj === 'object' ? fileObj.license || 'MIT' : 'MIT', - url: `/freedevtools/svg_icons/${category}/${iconName}/` - }); - } + tags: icon.tags || [], + author: 'Free DevTools', + license: 'MIT', + url: `/freedevtools/svg_icons/${category}/${iconName}/`, + base64: icon.base64, + }; + }); return icons; } @@ -63,43 +59,27 @@ async function getCategoryIcons() { const categoryIcons = await getCategoryIcons(); const totalIcons = categoryIcons.length; -const categoryIconMap = { - "general": "https://cdn-icons-png.flaticon.com/512/5515/5515389.png", - "animals": "https://cdn-icons-png.flaticon.com/512/1998/1998619.png", - "nature": "https://cdn-icons-png.flaticon.com/512/1998/1998619.png", - "technology": "https://cdn-icons-png.flaticon.com/512/2103/2103633.png", - "business": "https://cdn-icons-png.flaticon.com/512/2103/2103633.png", - "social": "https://cdn-icons-png.flaticon.com/512/2103/2103633.png", - "shapes": "https://cdn-icons-png.flaticon.com/512/2103/2103633.png", -}; - -const categoryIcon = categoryIconMap[category as keyof typeof categoryIconMap] || categoryIconMap.general; - // Breadcrumb data const breadcrumbItems = [ { label: 'Free DevTools', href: '/freedevtools/' }, { label: 'SVG Icons', href: '/freedevtools/svg_icons/' }, - { label: category } + { label: category }, ]; --- - - -
@@ -109,46 +89,53 @@ const breadcrumbItems = [ description={`Discover ${totalIcons} scalable ${category} icons ready in vector SVG format`} breadcrumbItems={breadcrumbItems} /> -
-
- {categoryIcons.map((icon) => { - const iconName = icon.name.replace(/_/g, ' ').replace(/\b\w/g, (l: string) => l.toUpperCase()); - - return ( - - -
+
@@ -166,4 +153,3 @@ const breadcrumbItems = [ object-fit: contain; } - diff --git a/frontend/src/pages/svg_icons/[category]/[icon].astro b/frontend/src/pages/svg_icons/[category]/[icon].astro index 08331360f1..b7311a7c5a 100644 --- a/frontend/src/pages/svg_icons/[category]/[icon].astro +++ b/frontend/src/pages/svg_icons/[category]/[icon].astro @@ -1,4 +1,8 @@ --- +import { + getClusters, + getIconByCategoryAndName, +} from 'db/svg_icons/svg-icons-utils'; import AdBanner from '../../../components/banner/AdBanner.astro'; import CopyPngButton from '../../../components/buttons/CopyPngButton.tsx'; import CopySvgButton from '../../../components/buttons/CopySvgButton.tsx'; @@ -9,72 +13,55 @@ import ToastProvider from '../../../components/ToastProvider'; import ToolContainer from '../../../components/tool/ToolContainer'; import ToolHead from '../../../components/tool/ToolHead'; import BaseLayout from '../../../layouts/BaseLayout.astro'; -// SVG processing moved to client-side for better performance - export async function getStaticPaths() { - const { getCollection } = await import('astro:content'); - - const svgIconsEntries = await getCollection('svgIconsMetadata'); - const iconsData = svgIconsEntries[0]?.data; + const clusters = getClusters(); + const paths = []; - if (!iconsData) { - throw new Error('SVG icons metadata not found'); - } + // Process each cluster (category) + for (const cluster of clusters) { + // Get all icons for this cluster using source_folder (cluster key) + const { getIconsByCluster } = await import('db/svg_icons/svg-icons-utils'); + const icons = getIconsByCluster(cluster.source_folder || cluster.name); + + // Process each icon + for (const iconRecord of icons) { + const iconName = iconRecord.name.replace('.svg', ''); - const paths = []; - - // Process each cluster (category) - NO SVG loading at build time - for (const [clusterKey, clusterData] of Object.entries(iconsData.clusters)) { - const cluster = clusterData as any; - const categoryName = cluster.name; // Use the name from the cluster data - - // Process each file object in the cluster - NO SVG loading at build time - for (const fileObj of cluster.fileNames) { - const iconName = typeof fileObj === 'string' - ? fileObj.replace('.svg', '') - : fileObj.fileName?.replace('.svg', '') || ''; - paths.push({ - params: { category: categoryName, icon: iconName }, - props: { - iconData: { - name: iconName, - description: typeof fileObj === 'object' ? fileObj.description || `Free ${iconName} icon` : `Free ${iconName} icon`, - category: categoryName, - tags: typeof fileObj === 'object' ? fileObj.tags || cluster.keywords || [] : cluster.keywords || [], - author: typeof fileObj === 'object' ? fileObj.author || 'Free DevTools by Hexmos' : 'Free DevTools by Hexmos', - license: typeof fileObj === 'object' ? fileObj.license || 'MIT' : 'MIT', - usecases: typeof fileObj === 'object' ? fileObj.usecases || '' : '', - synonyms: typeof fileObj === 'object' ? fileObj.synonyms || [] : [], - industry: typeof fileObj === 'object' ? fileObj.industry || '' : '', - emotional_cues: typeof fileObj === 'object' ? fileObj.emotional_cues || '' : '' - } - } + params: { category: cluster.name, icon: iconName }, }); } } - + return paths; } - const { category, icon } = Astro.params; -const { iconData } = Astro.props as { - iconData: { - name: string; - category: string; - svgContent: string; - originalSvgContent: string; - tags: string[]; - author: string; - license: string; - description: string; - usecases: string; - synonyms: string[]; - industry: string; - emotional_cues: string; - }; + +// Get icon data from SQLite database +const iconRecord = getIconByCategoryAndName(category || '', icon || ''); + +if (!iconRecord) { + return Astro.redirect('/freedevtools/svg_icons/'); +} + +// Prepare icon data for the component +const iconName = iconRecord.name.replace('.svg', ''); +const iconData = { + name: iconName, + description: iconRecord.description || `Free ${iconName} icon`, + category: category || '', + tags: iconRecord.tags || [], + author: 'Free DevTools by Hexmos', + license: 'MIT', + usecases: iconRecord.usecases || '', + synonyms: iconRecord.synonyms || [], + industry: iconRecord.industry || '', + emotional_cues: iconRecord.emotional_cues || '', + // SVG content will be fetched client-side if needed, empty for now since we use file paths + svgContent: '', + originalSvgContent: '', }; // Breadcrumb data @@ -82,53 +69,51 @@ const breadcrumbItems = [ { label: 'Free DevTools', href: '/freedevtools/' }, { label: 'SVG Icons', href: '/freedevtools/svg_icons/' }, { label: category, href: `/freedevtools/svg_icons/${category}/` }, - { label: iconData.name } + { label: iconData.name }, ]; - // Generate SEO-friendly title and description const seoTitle = `Free ${iconData.name} SVG Icon Download | Online Free DevTools by Hexmos`; const seoDescription = `Download ${iconData.name} SVG icon for free. High-quality vector icon in ${iconData.category} category. No registration required. Unlimited Downloads.`; - // Generate better alt text for the icon const altText = `${iconData.name} ${iconData.category} icon - Free SVG download`; - const canonical = `https://hexmos.com/freedevtools/svg_icons/${category}/${icon}/`; - // Static SVG dimensions for structured data -const svgDimensions = { width: 128, height: 128, viewBox: "0 0 128 128", aspectRatio: 1 }; - +const svgDimensions = { + width: 128, + height: 128, + viewBox: '0 0 128 128', + aspectRatio: 1, +}; // Generate thumbnail URL (points to the actual SVG image in public folder) // For brand-oauth icon, use PNG thumbnail for better Google search preview -const thumbnailUrl = icon === 'brand-oauth' && category === 'factory' - ? `https://hexmos.com/freedevtools/emoji_data/abacus/abacus_3d.png` - : `https://hexmos.com/freedevtools/svg_icons/${category}/${icon}.svg`; - +const thumbnailUrl = + icon === 'brand-oauth' && category === 'factory' + ? `https://hexmos.com/freedevtools/emoji_data/abacus/abacus_3d.png` + : `https://hexmos.com/freedevtools/svg_icons/${category}/${icon}.svg`; // Set encoding format based on the same condition -const encodingFormat = icon === 'brand-oauth' && category === 'factory' - ? "image/png" - : "image/svg+xml"; - +const encodingFormat = + icon === 'brand-oauth' && category === 'factory' + ? 'image/png' + : 'image/svg+xml'; --- - - - -
- -
- - - - {/* Main Section: Icon + Buttons (left) + Metadata (right) */} -
- - {/* Left Block: Icon + Buttons */} -
- - {/* Icon Canvas (Wider + Taller) */} -
- - - {altText} - + + +
+
+ + + {/* Main Section: Icon + Buttons (left) + Metadata (right) */} +
+ {/* Left Block: Icon + Buttons */} +
+ {/* Icon Canvas (Wider + Taller) */} +
+ + + {altText} + +
- - {/* Copy & Download Buttons */} -
- - - - + {/* Copy & Download Buttons */} +
+ + + + +
-
- - {/* Right Block: Metadata */} -
- -

- {iconData.description} -

- - {/* Sections */} - {[ - { title: "Practical Applications", content: iconData.usecases }, - { - title: "Alternative Terms", - content: iconData.synonyms.length ? ( -
- {iconData.synonyms.map((synonym) => ( - - {synonym} - - ))} + {/* Right Block: Metadata */} +
+

+ {iconData.description} +

+ + {/* Sections */} + { + [ + { title: 'Practical Applications', content: iconData.usecases }, + { + title: 'Alternative Terms', + content: iconData.synonyms.length ? ( +
+ {iconData.synonyms.map((synonym) => ( + + {synonym} + + ))} +
+ ) : ( + 'No synonyms available.' + ), + }, + { title: 'Business Domains', content: iconData.industry }, + { + title: 'Psychological Impact', + content: iconData.emotional_cues, + }, + ].map((section) => ( +
+

+ {section.title} +

+

{section.content}

- ) : "No synonyms available." - }, - { title: "Business Domains", content: iconData.industry }, - { title: "Psychological Impact", content: iconData.emotional_cues } - ].map((section) => ( + )) + } + + {/* Tags */}
-

{section.title}

-

{section.content}

+

+ Tags +

+ { + iconData.tags.length > 0 ? ( +
+ {iconData.tags.map((tag) => ( +

+ {tag} +

+ ))} +
+ ) : ( +

No tags available.

+ ) + }
- ))} - - {/* Tags */} -
-

Tags

- {iconData.tags.length > 0 ? ( -
- {iconData.tags.map((tag) => ( -

- {tag} -

- ))} -
- ) : ( -

No tags available.

- )}
-
- {/* Footer / Navigation */} - - - - - - - + + ← Back to SVG Icons + + +
+ + -