enzostvs HF Staff commited on
Commit
1d65062
·
1 Parent(s): 5714aa8

add download project

Browse files
app/api/projects/[repoId]/download/route.ts ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { auth } from "@/lib/auth";
2
+ import { downloadFile, listFiles, RepoDesignation } from "@huggingface/hub";
3
+ import { NextResponse } from "next/server";
4
+ import JSZip from "jszip";
5
+
6
+ export async function GET(
7
+ request: Request,
8
+ { params }: { params: Promise<{ repoId: string }> }
9
+ ) {
10
+ const { repoId }: { repoId: string } = await params;
11
+ const session = await auth();
12
+ if (!session) {
13
+ return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
14
+ }
15
+ const token = session.accessToken;
16
+ const repo: RepoDesignation = {
17
+ type: "space",
18
+ name: session.user?.username + "/" + repoId,
19
+ };
20
+
21
+ try {
22
+ const zip = new JSZip();
23
+ for await (const fileInfo of listFiles({
24
+ repo,
25
+ accessToken: token as string,
26
+ recursive: true,
27
+ })) {
28
+ if (fileInfo.type === "directory" || fileInfo.path.startsWith(".")) {
29
+ continue;
30
+ }
31
+
32
+ try {
33
+ const blob = await downloadFile({
34
+ repo,
35
+ accessToken: token as string,
36
+ path: fileInfo.path,
37
+ raw: true
38
+ }).catch((error) => {
39
+ return null;
40
+ });
41
+ if (!blob) {
42
+ continue;
43
+ }
44
+
45
+ if (blob) {
46
+ const arrayBuffer = await blob.arrayBuffer();
47
+ zip.file(fileInfo.path, arrayBuffer);
48
+ }
49
+ } catch (error) {
50
+ console.error(`Error downloading file ${fileInfo.path}:`, error);
51
+ }
52
+ }
53
+
54
+ const zipBlob = await zip.generateAsync({
55
+ type: "blob",
56
+ compression: "DEFLATE",
57
+ compressionOptions: {
58
+ level: 6
59
+ }
60
+ });
61
+
62
+ const projectName = `${session.user?.username}-${repoId}`.replace(/[^a-zA-Z0-9-_]/g, '_');
63
+ const filename = `${projectName}.zip`;
64
+
65
+ return new NextResponse(zipBlob, {
66
+ headers: {
67
+ "Content-Type": "application/zip",
68
+ "Content-Disposition": `attachment; filename="${filename}"`,
69
+ "Content-Length": zipBlob.size.toString(),
70
+ },
71
+ });
72
+ } catch (error) {
73
+ console.error("Error downloading project:", error);
74
+ return NextResponse.json({ error: "Failed to download project" }, { status: 500 });
75
+ }
76
+ }
components/projects/big-project-card.tsx CHANGED
@@ -3,6 +3,7 @@ import { SpaceEntry } from "@huggingface/hub";
3
  import { format } from "date-fns";
4
  import {
5
  CogIcon,
 
6
  EllipsisVertical,
7
  ExternalLink,
8
  TrashIcon,
@@ -15,6 +16,7 @@ import {
15
  DropdownMenuItem,
16
  DropdownMenuTrigger,
17
  } from "@/components/ui/dropdown-menu";
 
18
 
19
  // from-red-500 to-red-500
20
  // from-yellow-500 to-yellow-500
@@ -32,6 +34,35 @@ export function BigProjectCard({
32
  project: SpaceEntry;
33
  onOpenDeleteDialog: (id: string) => void;
34
  }) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  return (
36
  <a href={`/${project.name}`} className="">
37
  <div className="group/big-card rounded-lg overflow-hidden transition-all border-2 border-background ring-[1px] ring-border relative">
@@ -47,7 +78,7 @@ export function BigProjectCard({
47
  <iframe
48
  src={`https://${project.name.replaceAll(
49
  "/",
50
- "-"
51
  )}.static.hf.space`}
52
  className="w-[700px] h-[350px] border-0 origin-top-left pointer-events-none"
53
  style={{
@@ -84,13 +115,23 @@ export function BigProjectCard({
84
  e.stopPropagation();
85
  window.open(
86
  `https://huggingface.co/spaces/${project.name}/settings`,
87
- "_blank"
88
  );
89
  }}
90
  >
91
  <CogIcon />
92
  Settings
93
  </DropdownMenuItem>
 
 
 
 
 
 
 
 
 
 
94
  <DropdownMenuItem
95
  variant="destructive"
96
  onClick={(e) => {
 
3
  import { format } from "date-fns";
4
  import {
5
  CogIcon,
6
+ Download,
7
  EllipsisVertical,
8
  ExternalLink,
9
  TrashIcon,
 
16
  DropdownMenuItem,
17
  DropdownMenuTrigger,
18
  } from "@/components/ui/dropdown-menu";
19
+ import { toast } from "sonner";
20
 
21
  // from-red-500 to-red-500
22
  // from-yellow-500 to-yellow-500
 
34
  project: SpaceEntry;
35
  onOpenDeleteDialog: (id: string) => void;
36
  }) {
37
+ const handleDownload = async () => {
38
+ try {
39
+ toast.info("Preparing download...");
40
+ const response = await fetch(
41
+ `/api/projects/${project.name.split("/")[1]}/download`,
42
+ {
43
+ headers: {
44
+ Accept: "application/zip",
45
+ },
46
+ },
47
+ );
48
+ if (!response.ok) {
49
+ throw new Error("Failed to download project");
50
+ }
51
+ const blob = await response.blob();
52
+ const url = window.URL.createObjectURL(blob);
53
+ const link = document.createElement("a");
54
+ link.href = url;
55
+ link.download = `${project.name.replaceAll("/", "-")}.zip`;
56
+ document.body.appendChild(link);
57
+ link.click();
58
+ document.body.removeChild(link);
59
+ window.URL.revokeObjectURL(url);
60
+ toast.success("Download started!");
61
+ } catch (error) {
62
+ toast.error("Failed to download project");
63
+ }
64
+ };
65
+
66
  return (
67
  <a href={`/${project.name}`} className="">
68
  <div className="group/big-card rounded-lg overflow-hidden transition-all border-2 border-background ring-[1px] ring-border relative">
 
78
  <iframe
79
  src={`https://${project.name.replaceAll(
80
  "/",
81
+ "-",
82
  )}.static.hf.space`}
83
  className="w-[700px] h-[350px] border-0 origin-top-left pointer-events-none"
84
  style={{
 
115
  e.stopPropagation();
116
  window.open(
117
  `https://huggingface.co/spaces/${project.name}/settings`,
118
+ "_blank",
119
  );
120
  }}
121
  >
122
  <CogIcon />
123
  Settings
124
  </DropdownMenuItem>
125
+ <DropdownMenuItem
126
+ onClick={(e) => {
127
+ handleDownload();
128
+ e.preventDefault();
129
+ e.stopPropagation();
130
+ }}
131
+ >
132
+ <Download />
133
+ Download
134
+ </DropdownMenuItem>
135
  <DropdownMenuItem
136
  variant="destructive"
137
  onClick={(e) => {
package.json CHANGED
@@ -33,6 +33,7 @@
33
  "framer-motion": "^12.23.25",
34
  "huggingface": "link:@auth/core/providers/huggingface",
35
  "i": "^0.3.7",
 
36
  "lucide-react": "^0.554.0",
37
  "monaco-editor": "^0.54.0",
38
  "mongoose": "^9.1.1",
 
33
  "framer-motion": "^12.23.25",
34
  "huggingface": "link:@auth/core/providers/huggingface",
35
  "i": "^0.3.7",
36
+ "jszip": "^3.10.1",
37
  "lucide-react": "^0.554.0",
38
  "monaco-editor": "^0.54.0",
39
  "mongoose": "^9.1.1",
pnpm-lock.yaml CHANGED
@@ -80,6 +80,9 @@ importers:
80
  i:
81
  specifier: ^0.3.7
82
  version: 0.3.7
 
 
 
83
  lucide-react:
84
  specifier: ^0.554.0
85
  version: 0.554.0(react@19.2.0)
@@ -1628,6 +1631,9 @@ packages:
1628
  copy-to-clipboard@3.3.3:
1629
  resolution: {integrity: sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==}
1630
 
 
 
 
1631
  crelt@1.0.6:
1632
  resolution: {integrity: sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==}
1633
 
@@ -2161,6 +2167,9 @@ packages:
2161
  resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==}
2162
  engines: {node: '>= 4'}
2163
 
 
 
 
2164
  import-fresh@3.3.1:
2165
  resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==}
2166
  engines: {node: '>=6'}
@@ -2169,6 +2178,9 @@ packages:
2169
  resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
2170
  engines: {node: '>=0.8.19'}
2171
 
 
 
 
2172
  inline-style-parser@0.2.7:
2173
  resolution: {integrity: sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==}
2174
 
@@ -2306,6 +2318,9 @@ packages:
2306
  resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==}
2307
  engines: {node: '>= 0.4'}
2308
 
 
 
 
2309
  isarray@2.0.5:
2310
  resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==}
2311
 
@@ -2360,6 +2375,9 @@ packages:
2360
  resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==}
2361
  engines: {node: '>=4.0'}
2362
 
 
 
 
2363
  kareem@3.0.0:
2364
  resolution: {integrity: sha512-RKhaOBSPN8L7y4yAgNhDT2602G5FD6QbOIISbjN9D6mjHPeqeg7K+EB5IGSU5o81/X2Gzm3ICnAvQW3x3OP8HA==}
2365
  engines: {node: '>=18.0.0'}
@@ -2378,6 +2396,9 @@ packages:
2378
  resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
2379
  engines: {node: '>= 0.8.0'}
2380
 
 
 
 
2381
  lightningcss-android-arm64@1.30.2:
2382
  resolution: {integrity: sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==}
2383
  engines: {node: '>= 12.0.0'}
@@ -2903,6 +2924,9 @@ packages:
2903
  resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
2904
  engines: {node: '>=10'}
2905
 
 
 
 
2906
  parent-module@1.0.1:
2907
  resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
2908
  engines: {node: '>=6'}
@@ -2963,6 +2987,9 @@ packages:
2963
  resolution: {integrity: sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==}
2964
  engines: {node: '>=6'}
2965
 
 
 
 
2966
  prop-types@15.8.1:
2967
  resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==}
2968
 
@@ -3059,6 +3086,9 @@ packages:
3059
  resolution: {integrity: sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==}
3060
  engines: {node: '>=0.10.0'}
3061
 
 
 
 
3062
  reflect.getprototypeof@1.0.10:
3063
  resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==}
3064
  engines: {node: '>= 0.4'}
@@ -3109,6 +3139,9 @@ packages:
3109
  resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==}
3110
  engines: {node: '>=0.4'}
3111
 
 
 
 
3112
  safe-push-apply@1.0.0:
3113
  resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==}
3114
  engines: {node: '>= 0.4'}
@@ -3149,6 +3182,9 @@ packages:
3149
  resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==}
3150
  engines: {node: '>= 0.4'}
3151
 
 
 
 
3152
  sharp@0.34.5:
3153
  resolution: {integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==}
3154
  engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
@@ -3259,6 +3295,9 @@ packages:
3259
  resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==}
3260
  engines: {node: '>= 0.4'}
3261
 
 
 
 
3262
  stringify-entities@4.0.4:
3263
  resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==}
3264
 
@@ -3484,6 +3523,9 @@ packages:
3484
  peerDependencies:
3485
  react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
3486
 
 
 
 
3487
  uuid@13.0.0:
3488
  resolution: {integrity: sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==}
3489
  hasBin: true
@@ -5042,6 +5084,8 @@ snapshots:
5042
  dependencies:
5043
  toggle-selection: 1.0.6
5044
 
 
 
5045
  crelt@1.0.6: {}
5046
 
5047
  cross-spawn@7.0.6:
@@ -5734,6 +5778,8 @@ snapshots:
5734
 
5735
  ignore@7.0.5: {}
5736
 
 
 
5737
  import-fresh@3.3.1:
5738
  dependencies:
5739
  parent-module: 1.0.1
@@ -5741,6 +5787,8 @@ snapshots:
5741
 
5742
  imurmurhash@0.1.4: {}
5743
 
 
 
5744
  inline-style-parser@0.2.7: {}
5745
 
5746
  inline-style-prefixer@7.0.1:
@@ -5883,6 +5931,8 @@ snapshots:
5883
  call-bound: 1.0.4
5884
  get-intrinsic: 1.3.0
5885
 
 
 
5886
  isarray@2.0.5: {}
5887
 
5888
  isexe@2.0.0: {}
@@ -5929,6 +5979,13 @@ snapshots:
5929
  object.assign: 4.1.7
5930
  object.values: 1.2.1
5931
 
 
 
 
 
 
 
 
5932
  kareem@3.0.0: {}
5933
 
5934
  keyv@4.5.4:
@@ -5946,6 +6003,10 @@ snapshots:
5946
  prelude-ls: 1.2.1
5947
  type-check: 0.4.0
5948
 
 
 
 
 
5949
  lightningcss-android-arm64@1.30.2:
5950
  optional: true
5951
 
@@ -6495,6 +6556,8 @@ snapshots:
6495
  dependencies:
6496
  p-limit: 3.1.0
6497
 
 
 
6498
  parent-module@1.0.1:
6499
  dependencies:
6500
  callsites: 3.1.0
@@ -6548,6 +6611,8 @@ snapshots:
6548
 
6549
  prismjs@1.30.0: {}
6550
 
 
 
6551
  prop-types@15.8.1:
6552
  dependencies:
6553
  loose-envify: 1.4.0
@@ -6667,6 +6732,16 @@ snapshots:
6667
 
6668
  react@19.2.0: {}
6669
 
 
 
 
 
 
 
 
 
 
 
6670
  reflect.getprototypeof@1.0.10:
6671
  dependencies:
6672
  call-bind: 1.0.8
@@ -6747,6 +6822,8 @@ snapshots:
6747
  has-symbols: 1.1.0
6748
  isarray: 2.0.5
6749
 
 
 
6750
  safe-push-apply@1.0.0:
6751
  dependencies:
6752
  es-errors: 1.3.0
@@ -6790,6 +6867,8 @@ snapshots:
6790
  es-errors: 1.3.0
6791
  es-object-atoms: 1.1.1
6792
 
 
 
6793
  sharp@0.34.5:
6794
  dependencies:
6795
  '@img/colour': 1.0.0
@@ -6967,6 +7046,10 @@ snapshots:
6967
  define-properties: 1.2.1
6968
  es-object-atoms: 1.1.1
6969
 
 
 
 
 
6970
  stringify-entities@4.0.4:
6971
  dependencies:
6972
  character-entities-html4: 2.1.0
@@ -7216,6 +7299,8 @@ snapshots:
7216
  dependencies:
7217
  react: 19.2.0
7218
 
 
 
7219
  uuid@13.0.0: {}
7220
 
7221
  uuid@8.3.2: {}
 
80
  i:
81
  specifier: ^0.3.7
82
  version: 0.3.7
83
+ jszip:
84
+ specifier: ^3.10.1
85
+ version: 3.10.1
86
  lucide-react:
87
  specifier: ^0.554.0
88
  version: 0.554.0(react@19.2.0)
 
1631
  copy-to-clipboard@3.3.3:
1632
  resolution: {integrity: sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==}
1633
 
1634
+ core-util-is@1.0.3:
1635
+ resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==}
1636
+
1637
  crelt@1.0.6:
1638
  resolution: {integrity: sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==}
1639
 
 
2167
  resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==}
2168
  engines: {node: '>= 4'}
2169
 
2170
+ immediate@3.0.6:
2171
+ resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==}
2172
+
2173
  import-fresh@3.3.1:
2174
  resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==}
2175
  engines: {node: '>=6'}
 
2178
  resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
2179
  engines: {node: '>=0.8.19'}
2180
 
2181
+ inherits@2.0.4:
2182
+ resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
2183
+
2184
  inline-style-parser@0.2.7:
2185
  resolution: {integrity: sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==}
2186
 
 
2318
  resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==}
2319
  engines: {node: '>= 0.4'}
2320
 
2321
+ isarray@1.0.0:
2322
+ resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==}
2323
+
2324
  isarray@2.0.5:
2325
  resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==}
2326
 
 
2375
  resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==}
2376
  engines: {node: '>=4.0'}
2377
 
2378
+ jszip@3.10.1:
2379
+ resolution: {integrity: sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==}
2380
+
2381
  kareem@3.0.0:
2382
  resolution: {integrity: sha512-RKhaOBSPN8L7y4yAgNhDT2602G5FD6QbOIISbjN9D6mjHPeqeg7K+EB5IGSU5o81/X2Gzm3ICnAvQW3x3OP8HA==}
2383
  engines: {node: '>=18.0.0'}
 
2396
  resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
2397
  engines: {node: '>= 0.8.0'}
2398
 
2399
+ lie@3.3.0:
2400
+ resolution: {integrity: sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==}
2401
+
2402
  lightningcss-android-arm64@1.30.2:
2403
  resolution: {integrity: sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==}
2404
  engines: {node: '>= 12.0.0'}
 
2924
  resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
2925
  engines: {node: '>=10'}
2926
 
2927
+ pako@1.0.11:
2928
+ resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==}
2929
+
2930
  parent-module@1.0.1:
2931
  resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
2932
  engines: {node: '>=6'}
 
2987
  resolution: {integrity: sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==}
2988
  engines: {node: '>=6'}
2989
 
2990
+ process-nextick-args@2.0.1:
2991
+ resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==}
2992
+
2993
  prop-types@15.8.1:
2994
  resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==}
2995
 
 
3086
  resolution: {integrity: sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==}
3087
  engines: {node: '>=0.10.0'}
3088
 
3089
+ readable-stream@2.3.8:
3090
+ resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==}
3091
+
3092
  reflect.getprototypeof@1.0.10:
3093
  resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==}
3094
  engines: {node: '>= 0.4'}
 
3139
  resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==}
3140
  engines: {node: '>=0.4'}
3141
 
3142
+ safe-buffer@5.1.2:
3143
+ resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==}
3144
+
3145
  safe-push-apply@1.0.0:
3146
  resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==}
3147
  engines: {node: '>= 0.4'}
 
3182
  resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==}
3183
  engines: {node: '>= 0.4'}
3184
 
3185
+ setimmediate@1.0.5:
3186
+ resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==}
3187
+
3188
  sharp@0.34.5:
3189
  resolution: {integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==}
3190
  engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
 
3295
  resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==}
3296
  engines: {node: '>= 0.4'}
3297
 
3298
+ string_decoder@1.1.1:
3299
+ resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==}
3300
+
3301
  stringify-entities@4.0.4:
3302
  resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==}
3303
 
 
3523
  peerDependencies:
3524
  react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
3525
 
3526
+ util-deprecate@1.0.2:
3527
+ resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
3528
+
3529
  uuid@13.0.0:
3530
  resolution: {integrity: sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==}
3531
  hasBin: true
 
5084
  dependencies:
5085
  toggle-selection: 1.0.6
5086
 
5087
+ core-util-is@1.0.3: {}
5088
+
5089
  crelt@1.0.6: {}
5090
 
5091
  cross-spawn@7.0.6:
 
5778
 
5779
  ignore@7.0.5: {}
5780
 
5781
+ immediate@3.0.6: {}
5782
+
5783
  import-fresh@3.3.1:
5784
  dependencies:
5785
  parent-module: 1.0.1
 
5787
 
5788
  imurmurhash@0.1.4: {}
5789
 
5790
+ inherits@2.0.4: {}
5791
+
5792
  inline-style-parser@0.2.7: {}
5793
 
5794
  inline-style-prefixer@7.0.1:
 
5931
  call-bound: 1.0.4
5932
  get-intrinsic: 1.3.0
5933
 
5934
+ isarray@1.0.0: {}
5935
+
5936
  isarray@2.0.5: {}
5937
 
5938
  isexe@2.0.0: {}
 
5979
  object.assign: 4.1.7
5980
  object.values: 1.2.1
5981
 
5982
+ jszip@3.10.1:
5983
+ dependencies:
5984
+ lie: 3.3.0
5985
+ pako: 1.0.11
5986
+ readable-stream: 2.3.8
5987
+ setimmediate: 1.0.5
5988
+
5989
  kareem@3.0.0: {}
5990
 
5991
  keyv@4.5.4:
 
6003
  prelude-ls: 1.2.1
6004
  type-check: 0.4.0
6005
 
6006
+ lie@3.3.0:
6007
+ dependencies:
6008
+ immediate: 3.0.6
6009
+
6010
  lightningcss-android-arm64@1.30.2:
6011
  optional: true
6012
 
 
6556
  dependencies:
6557
  p-limit: 3.1.0
6558
 
6559
+ pako@1.0.11: {}
6560
+
6561
  parent-module@1.0.1:
6562
  dependencies:
6563
  callsites: 3.1.0
 
6611
 
6612
  prismjs@1.30.0: {}
6613
 
6614
+ process-nextick-args@2.0.1: {}
6615
+
6616
  prop-types@15.8.1:
6617
  dependencies:
6618
  loose-envify: 1.4.0
 
6732
 
6733
  react@19.2.0: {}
6734
 
6735
+ readable-stream@2.3.8:
6736
+ dependencies:
6737
+ core-util-is: 1.0.3
6738
+ inherits: 2.0.4
6739
+ isarray: 1.0.0
6740
+ process-nextick-args: 2.0.1
6741
+ safe-buffer: 5.1.2
6742
+ string_decoder: 1.1.1
6743
+ util-deprecate: 1.0.2
6744
+
6745
  reflect.getprototypeof@1.0.10:
6746
  dependencies:
6747
  call-bind: 1.0.8
 
6822
  has-symbols: 1.1.0
6823
  isarray: 2.0.5
6824
 
6825
+ safe-buffer@5.1.2: {}
6826
+
6827
  safe-push-apply@1.0.0:
6828
  dependencies:
6829
  es-errors: 1.3.0
 
6867
  es-errors: 1.3.0
6868
  es-object-atoms: 1.1.1
6869
 
6870
+ setimmediate@1.0.5: {}
6871
+
6872
  sharp@0.34.5:
6873
  dependencies:
6874
  '@img/colour': 1.0.0
 
7046
  define-properties: 1.2.1
7047
  es-object-atoms: 1.1.1
7048
 
7049
+ string_decoder@1.1.1:
7050
+ dependencies:
7051
+ safe-buffer: 5.1.2
7052
+
7053
  stringify-entities@4.0.4:
7054
  dependencies:
7055
  character-entities-html4: 2.1.0
 
7299
  dependencies:
7300
  react: 19.2.0
7301
 
7302
+ util-deprecate@1.0.2: {}
7303
+
7304
  uuid@13.0.0: {}
7305
 
7306
  uuid@8.3.2: {}