Step 10C.2: generate optimized map art with sharp
CI / check (push) Successful in 3m26s
Details
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
@ -686,3 +686,12 @@ Implementation decisions not spelled out in `memory-bank/implementation-plan.md`
|
||||||
- **Missing: `badge-cloud-platform`** (the CR marks it optional). It is in the manifest with `file: null`, Jupiter Cloud Platform keeps `badge: "badge-cloud-platform"` in content, and the map simply draws no badge (fallback, decision 0.5.41).
|
- **Missing: `badge-cloud-platform`** (the CR marks it optional). It is in the manifest with `file: null`, Jupiter Cloud Platform keeps `badge: "badge-cloud-platform"` in content, and the map simply draws no badge (fallback, decision 0.5.41).
|
||||||
- **The manifest is JSON** (`apps/web/src/map/art/manifest.json`) with a `kind` per asset (`background`, `body`, `badge`, `ship`), so both the app (typed wrapper `manifest.ts`) and the Node optimization script read the same file.
|
- **The manifest is JSON** (`apps/web/src/map/art/manifest.json`) with a `kind` per asset (`background`, `body`, `badge`, `ship`), so both the app (typed wrapper `manifest.ts`) and the Node optimization script read the same file.
|
||||||
- **The Sun is not a location**, so its sprite key lives only in the manifest; the map style will refer to `sun` directly.
|
- **The Sun is not a location**, so its sprite key lives only in the manifest; the map style will refer to `sun` directly.
|
||||||
|
|
||||||
|
## Step 10C.2
|
||||||
|
|
||||||
|
- **Output naming:** `public/assets/map-gen/<id>@1x.png` and `<id>@2x.png` for sprites, `<id>.webp` for the background. Missing assets (`file: null`) produce nothing and a warning.
|
||||||
|
- **The build runs the script with `--if-available`:** it regenerates when sharp is installed (output is byte-identical, so git sees no change) and otherwise only checks that the committed output exists. Builds therefore never need sharp, as the CR requires.
|
||||||
|
- **The source art is removed from the build output** by a small Vite plugin. Everything in `public/` is copied into `dist` by default, and the sources (about 22 MB) are only script input. The sources stay where the user put them.
|
||||||
|
- **The committed-output test compares decoded pixels, not bytes**, because PNG compression can differ between Windows and Linux (CI). The "twice is identical" test compares bytes within one machine. The source-transparency test reads all four corners of each source sprite.
|
||||||
|
- **Sizes:** the 2x body sprites are about 0.5–0.6 MB each (lossless PNG of detailed art). That is acceptable for now. If the PWA precache (Step 11.1) is too heavy, palette quantization is the lever.
|
||||||
|
- **sharp's install script is not approved** in pnpm; its prebuilt platform binaries load without it.
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,8 @@
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "vite build",
|
"build": "node scripts/map-art.mjs --if-available && vite build",
|
||||||
|
"map-art": "node scripts/map-art.mjs",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"typecheck": "tsc --noEmit"
|
"typecheck": "tsc --noEmit"
|
||||||
},
|
},
|
||||||
|
|
@ -30,6 +31,7 @@
|
||||||
"@types/react-dom": "^19.3.0",
|
"@types/react-dom": "^19.3.0",
|
||||||
"@vitejs/plugin-react": "^6.1.1",
|
"@vitejs/plugin-react": "^6.1.1",
|
||||||
"jsdom": "^30.1.1",
|
"jsdom": "^30.1.1",
|
||||||
|
"sharp": "^0.35.5",
|
||||||
"tailwindcss": "^4.3.3",
|
"tailwindcss": "^4.3.3",
|
||||||
"vite": "^8.3.2"
|
"vite": "^8.3.2"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
After Width: | Height: | Size: 103 KiB |
|
After Width: | Height: | Size: 122 KiB |
|
After Width: | Height: | Size: 474 KiB |
|
After Width: | Height: | Size: 161 KiB |
|
After Width: | Height: | Size: 615 KiB |
|
After Width: | Height: | Size: 161 KiB |
|
After Width: | Height: | Size: 612 KiB |
|
After Width: | Height: | Size: 150 KiB |
|
After Width: | Height: | Size: 570 KiB |
|
After Width: | Height: | Size: 132 KiB |
|
After Width: | Height: | Size: 528 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 86 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 86 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 108 KiB |
|
After Width: | Height: | Size: 152 KiB |
|
After Width: | Height: | Size: 585 KiB |
|
|
@ -0,0 +1,96 @@
|
||||||
|
// Generates optimized map art from the user's source images (CR-003, decision 0.5.37).
|
||||||
|
//
|
||||||
|
// node scripts/map-art.mjs [outDir] regenerate (default public/assets/map-gen)
|
||||||
|
// node scripts/map-art.mjs --if-available as above, but if sharp is not installed,
|
||||||
|
// only check the committed output exists
|
||||||
|
//
|
||||||
|
// Sources in the manifest's `sourceDir` are only ever read.
|
||||||
|
import { existsSync, mkdirSync, readFileSync } from "node:fs";
|
||||||
|
import { dirname, join, resolve } from "node:path";
|
||||||
|
import { fileURLToPath } from "node:url";
|
||||||
|
|
||||||
|
const webRoot = join(dirname(fileURLToPath(import.meta.url)), "..");
|
||||||
|
const manifest = JSON.parse(readFileSync(join(webRoot, "src/map/art/manifest.json"), "utf8"));
|
||||||
|
|
||||||
|
/** Long-side sizes in px for the 1x and 2x variants of each sprite kind. */
|
||||||
|
export const SPRITE_SIZES = { body: [256, 512], badge: [256, 512], ship: [128, 256] };
|
||||||
|
export const BACKGROUND_MAX = 2048;
|
||||||
|
export const DEFAULT_OUT_DIR = join(webRoot, "public/assets/map-gen");
|
||||||
|
|
||||||
|
/** Every file the script writes for the manifest, relative to the output folder. */
|
||||||
|
export function expectedOutputs() {
|
||||||
|
const outputs = [];
|
||||||
|
for (const [id, asset] of Object.entries(manifest.assets)) {
|
||||||
|
if (asset.file === null) continue;
|
||||||
|
if (asset.kind === "background") outputs.push({ id, file: `${id}.webp`, kind: asset.kind });
|
||||||
|
else {
|
||||||
|
const [one, two] = SPRITE_SIZES[asset.kind];
|
||||||
|
outputs.push({ id, file: `${id}@1x.png`, kind: asset.kind, longSide: one });
|
||||||
|
outputs.push({ id, file: `${id}@2x.png`, kind: asset.kind, longSide: two });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return outputs;
|
||||||
|
}
|
||||||
|
|
||||||
|
const png = { compressionLevel: 9, adaptiveFiltering: false, palette: false };
|
||||||
|
|
||||||
|
async function generate(sharp, outDir) {
|
||||||
|
mkdirSync(outDir, { recursive: true });
|
||||||
|
for (const [id, asset] of Object.entries(manifest.assets)) {
|
||||||
|
if (asset.file === null) {
|
||||||
|
console.warn(`map-art: ${id} has no source file; the map will use its placeholder`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const source = join(webRoot, manifest.sourceDir, asset.file);
|
||||||
|
if (asset.kind === "background") {
|
||||||
|
await sharp(source)
|
||||||
|
.resize({
|
||||||
|
width: BACKGROUND_MAX,
|
||||||
|
height: BACKGROUND_MAX,
|
||||||
|
fit: "inside",
|
||||||
|
withoutEnlargement: true,
|
||||||
|
})
|
||||||
|
.webp({ quality: 80, effort: 6 })
|
||||||
|
.toFile(join(outDir, `${id}.webp`));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Trim transparent padding once, then export each size from the trimmed image.
|
||||||
|
const trimmed = await sharp(source).trim().png().toBuffer();
|
||||||
|
const [one, two] = SPRITE_SIZES[asset.kind];
|
||||||
|
for (const [suffix, size] of [
|
||||||
|
["1x", one],
|
||||||
|
["2x", two],
|
||||||
|
]) {
|
||||||
|
await sharp(trimmed)
|
||||||
|
.resize({ width: size, height: size, fit: "inside" })
|
||||||
|
.png(png)
|
||||||
|
.toFile(join(outDir, `${id}@${suffix}.png`));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main(args) {
|
||||||
|
const ifAvailable = args.includes("--if-available");
|
||||||
|
const outDir = resolve(args.find((a) => !a.startsWith("--")) ?? DEFAULT_OUT_DIR);
|
||||||
|
let sharp;
|
||||||
|
try {
|
||||||
|
sharp = (await import("sharp")).default;
|
||||||
|
} catch (error) {
|
||||||
|
if (!ifAvailable) throw error;
|
||||||
|
const missing = expectedOutputs().filter((o) => !existsSync(join(outDir, o.file)));
|
||||||
|
if (missing.length > 0) {
|
||||||
|
throw new Error(
|
||||||
|
`map-art: sharp unavailable and output missing: ${missing.map((o) => o.file)}`,
|
||||||
|
{ cause: error },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
console.warn("map-art: sharp unavailable; using the committed output");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await generate(sharp, outDir);
|
||||||
|
console.log(`map-art: wrote ${expectedOutputs().length} files to ${outDir}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process.argv[1] && resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
|
||||||
|
await main(process.argv.slice(2));
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,102 @@
|
||||||
|
// @vitest-environment node
|
||||||
|
import { execFileSync } from "node:child_process";
|
||||||
|
import { mkdtempSync, readdirSync, readFileSync, rmSync, statSync } from "node:fs";
|
||||||
|
import { tmpdir } from "node:os";
|
||||||
|
import { dirname, join } from "node:path";
|
||||||
|
import { fileURLToPath } from "node:url";
|
||||||
|
import sharp from "sharp";
|
||||||
|
import { afterAll, beforeAll, describe, expect, it } from "vitest";
|
||||||
|
import { artManifest } from "../src/map/art/manifest";
|
||||||
|
|
||||||
|
const webRoot = join(dirname(fileURLToPath(import.meta.url)), "..");
|
||||||
|
const script = join(webRoot, "scripts/map-art.mjs");
|
||||||
|
sharp.cache(false);
|
||||||
|
/** Reads through a buffer so sharp never holds the temp files open (Windows). */
|
||||||
|
const image = (path: string) => sharp(readFileSync(path));
|
||||||
|
const SIZES = { body: [256, 512], badge: [256, 512], ship: [128, 256] } as const;
|
||||||
|
|
||||||
|
const run = (outDir: string) =>
|
||||||
|
execFileSync(process.execPath, [script, outDir], { cwd: webRoot, stdio: "pipe" });
|
||||||
|
|
||||||
|
describe("map art optimization script (CR-003)", () => {
|
||||||
|
let first: string;
|
||||||
|
let second: string;
|
||||||
|
beforeAll(() => {
|
||||||
|
first = mkdtempSync(join(tmpdir(), "map-art-a-"));
|
||||||
|
second = mkdtempSync(join(tmpdir(), "map-art-b-"));
|
||||||
|
run(first);
|
||||||
|
run(second);
|
||||||
|
}, 120_000);
|
||||||
|
afterAll(() => {
|
||||||
|
rmSync(first, { recursive: true, force: true });
|
||||||
|
rmSync(second, { recursive: true, force: true });
|
||||||
|
});
|
||||||
|
|
||||||
|
const present = Object.entries(artManifest.assets).filter(([, a]) => a.file !== null);
|
||||||
|
|
||||||
|
it("writes every expected file at the right size", async () => {
|
||||||
|
for (const [id, asset] of present) {
|
||||||
|
if (asset.kind === "background") {
|
||||||
|
const meta = await image(join(first, `${id}.webp`)).metadata();
|
||||||
|
expect(meta.format).toBe("webp");
|
||||||
|
expect(Math.max(meta.width!, meta.height!)).toBeLessThanOrEqual(2048);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const [one, two] = SIZES[asset.kind];
|
||||||
|
for (const [suffix, longSide] of [
|
||||||
|
["1x", one],
|
||||||
|
["2x", two],
|
||||||
|
] as const) {
|
||||||
|
const meta = await image(join(first, `${id}@${suffix}.png`)).metadata();
|
||||||
|
expect(Math.max(meta.width!, meta.height!), `${id}@${suffix}`).toBe(longSide);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it("produces identical files when run twice", () => {
|
||||||
|
const files = readdirSync(first).sort();
|
||||||
|
expect(readdirSync(second).sort()).toEqual(files);
|
||||||
|
for (const file of files) {
|
||||||
|
expect(readFileSync(join(second, file)).equals(readFileSync(join(first, file))), file).toBe(
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it("matches the committed output pixel for pixel", async () => {
|
||||||
|
// Pixels, not bytes: PNG compression may differ between platforms (CI runs Linux).
|
||||||
|
const committed = join(webRoot, "public/assets/map-gen");
|
||||||
|
for (const file of readdirSync(first).filter((f) => f.endsWith(".png"))) {
|
||||||
|
const [fresh, stored] = await Promise.all([
|
||||||
|
image(join(first, file)).raw().toBuffer(),
|
||||||
|
image(join(committed, file)).raw().toBuffer(),
|
||||||
|
]);
|
||||||
|
expect(stored.equals(fresh), file).toBe(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it("keeps the background under 1 MB", () => {
|
||||||
|
expect(statSync(join(first, "bg.webp")).size).toBeLessThan(1024 * 1024);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("has source sprites with transparent backgrounds", async () => {
|
||||||
|
for (const [id, asset] of present) {
|
||||||
|
if (asset.kind === "background") continue;
|
||||||
|
const { data, info } = await image(join(webRoot, artManifest.sourceDir, asset.file!))
|
||||||
|
.ensureAlpha()
|
||||||
|
.raw()
|
||||||
|
.toBuffer({ resolveWithObject: true });
|
||||||
|
const alpha = (x: number, y: number) => data[(y * info.width + x) * info.channels + 3];
|
||||||
|
const corners = [
|
||||||
|
alpha(0, 0),
|
||||||
|
alpha(info.width - 1, 0),
|
||||||
|
alpha(0, info.height - 1),
|
||||||
|
alpha(info.width - 1, info.height - 1),
|
||||||
|
];
|
||||||
|
expect(
|
||||||
|
corners.every((a) => a === 0),
|
||||||
|
`${asset.file} (${id}): background isn't transparent`,
|
||||||
|
).toBe(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -1,9 +1,30 @@
|
||||||
import tailwindcss from "@tailwindcss/vite";
|
import tailwindcss from "@tailwindcss/vite";
|
||||||
import react from "@vitejs/plugin-react";
|
import react from "@vitejs/plugin-react";
|
||||||
import { defineConfig } from "vite";
|
import { rm } from "node:fs/promises";
|
||||||
|
import { join } from "node:path";
|
||||||
|
import { defineConfig, type Plugin } from "vite";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The user's source map art (public/assets/map) is large and only an input to
|
||||||
|
* scripts/map-art.mjs; the app loads public/assets/map-gen. Drop the sources
|
||||||
|
* from the build output (decision 0.5.37).
|
||||||
|
*/
|
||||||
|
function omitSourceArt(): Plugin {
|
||||||
|
let outDir = "dist";
|
||||||
|
return {
|
||||||
|
name: "omit-source-art",
|
||||||
|
apply: "build",
|
||||||
|
configResolved(config) {
|
||||||
|
outDir = config.build.outDir;
|
||||||
|
},
|
||||||
|
async closeBundle() {
|
||||||
|
await rm(join(outDir, "assets/map"), { recursive: true, force: true });
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [react(), tailwindcss()],
|
plugins: [react(), tailwindcss(), omitSourceArt()],
|
||||||
server: {
|
server: {
|
||||||
// Same-domain API in development too (decision 0.5.20). The server listens on
|
// Same-domain API in development too (decision 0.5.20). The server listens on
|
||||||
// IPv4 only, so target 127.0.0.1 rather than localhost.
|
// IPv4 only, so target 127.0.0.1 rather than localhost.
|
||||||
|
|
|
||||||
|
|
@ -451,6 +451,7 @@ Vite + React 19 + Tailwind 4, React Router 8 (declarative routes). In developmen
|
||||||
| `src/layout/Layout.tsx` | Header (credits, game clock), screen outlet, bottom tab bar |
|
| `src/layout/Layout.tsx` | Header (credits, game clock), screen outlet, bottom tab bar |
|
||||||
| `src/routes.ts` | Screen list shared by router and navigation |
|
| `src/routes.ts` | Screen list shared by router and navigation |
|
||||||
| `src/map/art/manifest.json` | Map art manifest (CR-003): asset id → `{ kind, file }` in `public/assets/map/` (never edited); `null` file = missing, placeholder used |
|
| `src/map/art/manifest.json` | Map art manifest (CR-003): asset id → `{ kind, file }` in `public/assets/map/` (never edited); `null` file = missing, placeholder used |
|
||||||
|
| `scripts/map-art.mjs` | Generates `public/assets/map-gen/` (`<id>@1x.png`, `<id>@2x.png`, `bg.webp`) from the manifest with sharp; output committed |
|
||||||
| `src/screens/*` | HQ, Contracts (TutorialBoard / LocationBoards + DispatchSheet), Fleet, Pilots, Market, Locations, StartScreen |
|
| `src/screens/*` | HQ, Contracts (TutorialBoard / LocationBoards + DispatchSheet), Fleet, Pilots, Market, Locations, StartScreen |
|
||||||
| `src/components/*` | `AwaySummary` dialog, `Countdown` |
|
| `src/components/*` | `AwaySummary` dialog, `Countdown` |
|
||||||
| `src/state/actions.ts` | `useLoadedPlayer`, `useGameAction(route)` (mutation + invalidate state and boards) |
|
| `src/state/actions.ts` | `useLoadedPlayer`, `useGameAction(route)` (mutation + invalidate state and boards) |
|
||||||
|
|
|
||||||
|
|
@ -150,7 +150,7 @@ Spec: `memory-bank/change-requests/CR-002-open-markets.md`. New decisions record
|
||||||
Spec: `memory-bank/change-requests/CR-003-map-art.md`. New decisions recorded as plan §0.5.37–0.5.41.
|
Spec: `memory-bank/change-requests/CR-003-map-art.md`. New decisions recorded as plan §0.5.37–0.5.41.
|
||||||
|
|
||||||
- [x] **Step 10C.1 — Inventory and asset manifest.** `apps/web/src/map/art/manifest.json` maps 12 asset ids to the 11 files in `apps/web/public/assets/map/` (all 1254×1254; sprites RGBA). `badge-cloud-platform` is listed with `file: null` (not provided). Content: `sprite` on every location and ship model, `badge` on Jupiter Cloud Platform. Tests: `art-manifest.test.ts`, content sprite-key tests.
|
- [x] **Step 10C.1 — Inventory and asset manifest.** `apps/web/src/map/art/manifest.json` maps 12 asset ids to the 11 files in `apps/web/public/assets/map/` (all 1254×1254; sprites RGBA). `badge-cloud-platform` is listed with `file: null` (not provided). Content: `sprite` on every location and ship model, `badge` on Jupiter Cloud Platform. Tests: `art-manifest.test.ts`, content sprite-key tests.
|
||||||
- [ ] Step 10C.2 — Asset optimization script
|
- [x] **Step 10C.2 — Asset optimization script.** `apps/web/scripts/map-art.mjs` (sharp; `pnpm --filter @deadhead/web map-art`, and first in `build` with `--if-available`) writes 21 files to `public/assets/map-gen/` (committed): bodies and Sun 256/512 px, ships 128/256 px (trimmed), `bg.webp` 1254 px / 106 KB. The Vite build drops the source art from `dist`. Test: `map-art.test.ts` (sizes, byte-identical reruns, pixels match the committed output, bg < 1 MB, transparent source corners).
|
||||||
- [ ] Step 10C.3 — Map style config
|
- [ ] Step 10C.3 — Map style config
|
||||||
- [ ] Step 10C.4 — Asset loading and fallback
|
- [ ] Step 10C.4 — Asset loading and fallback
|
||||||
- [ ] Step 10C.5 — Background
|
- [ ] Step 10C.5 — Background
|
||||||
|
|
|
||||||
327
pnpm-lock.yaml
|
|
@ -136,6 +136,9 @@ importers:
|
||||||
jsdom:
|
jsdom:
|
||||||
specifier: ^30.1.1
|
specifier: ^30.1.1
|
||||||
version: 30.1.1(@noble/hashes@2.4.0)
|
version: 30.1.1(@noble/hashes@2.4.0)
|
||||||
|
sharp:
|
||||||
|
specifier: ^0.35.5
|
||||||
|
version: 0.35.5(@types/node@24.19.1)
|
||||||
tailwindcss:
|
tailwindcss:
|
||||||
specifier: ^4.3.3
|
specifier: ^4.3.3
|
||||||
version: 4.3.3
|
version: 4.3.3
|
||||||
|
|
@ -337,6 +340,9 @@ packages:
|
||||||
'@drizzle-team/brocli@0.10.2':
|
'@drizzle-team/brocli@0.10.2':
|
||||||
resolution: {integrity: sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w==}
|
resolution: {integrity: sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w==}
|
||||||
|
|
||||||
|
'@emnapi/runtime@1.11.3':
|
||||||
|
resolution: {integrity: sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==}
|
||||||
|
|
||||||
'@esbuild-kit/core-utils@3.3.2':
|
'@esbuild-kit/core-utils@3.3.2':
|
||||||
resolution: {integrity: sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ==}
|
resolution: {integrity: sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ==}
|
||||||
deprecated: 'Merged into tsx: https://tsx.hirok.io'
|
deprecated: 'Merged into tsx: https://tsx.hirok.io'
|
||||||
|
|
@ -875,6 +881,168 @@ packages:
|
||||||
resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==}
|
resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==}
|
||||||
engines: {node: '>=18.18'}
|
engines: {node: '>=18.18'}
|
||||||
|
|
||||||
|
'@img/colour@1.1.0':
|
||||||
|
resolution: {integrity: sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
|
'@img/sharp-darwin-arm64@0.35.5':
|
||||||
|
resolution: {integrity: sha512-QRUlFQ0WxvdWyqqG/WtI3iupfD5rBzmCHXSdPsY91sAtVtTo7Q4cb6zOccZ3gqEqkr0f1As1ehLqmEpDsRf+lg==}
|
||||||
|
engines: {node: '>=20.9.0'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [darwin]
|
||||||
|
|
||||||
|
'@img/sharp-darwin-x64@0.35.5':
|
||||||
|
resolution: {integrity: sha512-+BR255RhDlpygUpOc/Jdt1nT6DQ3XG/ERo5wbcdOf5Q320dKtPCKPLR1LJs9VGXRaMa8l1uUa0tkCNOXiAxZUw==}
|
||||||
|
engines: {node: '>=20.9.0'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [darwin]
|
||||||
|
|
||||||
|
'@img/sharp-freebsd-wasm32@0.35.5':
|
||||||
|
resolution: {integrity: sha512-Y/z91nEZ4uIBX5X3nfTovjU9lHNKFYbL2lpHCLVNmXQK03VIZvXBBt0KxbPGp2SdGSF+2mQU4e+hQaWOt86iAw==}
|
||||||
|
engines: {node: '>=20.9.0'}
|
||||||
|
os: [freebsd]
|
||||||
|
|
||||||
|
'@img/sharp-libvips-darwin-arm64@1.3.4':
|
||||||
|
resolution: {integrity: sha512-5R89nBYiRdUlSWJxPhO+GVtaXzXSxKnRu/xqMn3KTA3L9EB9Oy/P+Nn2f2vlhPuUdy/Zusb2DarbyTpGCfEDuw==}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [darwin]
|
||||||
|
|
||||||
|
'@img/sharp-libvips-darwin-x64@1.3.4':
|
||||||
|
resolution: {integrity: sha512-iR2OKH80yi0U+dUplyh3/xdpFvps6YkCwsXenIJxqxR1v9o+xtKTGbS9H7cps+2Vxjc8B1j96p75NmTGjIhtpQ==}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [darwin]
|
||||||
|
|
||||||
|
'@img/sharp-libvips-linux-arm64@1.3.4':
|
||||||
|
resolution: {integrity: sha512-Y3dgX/6lE2QhQb+Gxy0WZxfg9MEm/JBjamZpS2IklP7xIQoKN4hzAm7KcMVGtaVDt3neE9OKBC7vAfonA/Lr1A==}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [linux]
|
||||||
|
libc: [glibc]
|
||||||
|
|
||||||
|
'@img/sharp-libvips-linux-arm@1.3.4':
|
||||||
|
resolution: {integrity: sha512-LmRtTsOHuvM2+wlO2Db37dx5MiZhB0FvSunciw48YjdOkZz9KAiRbm8ujeMOA1INqmei5NapFxYEK1D1ZSidmw==}
|
||||||
|
cpu: [arm]
|
||||||
|
os: [linux]
|
||||||
|
libc: [glibc]
|
||||||
|
|
||||||
|
'@img/sharp-libvips-linux-ppc64@1.3.4':
|
||||||
|
resolution: {integrity: sha512-Le6boB8Tai0Nis+gIxIpKx68UDVVIqdR8Tin5Yf1z2LJJQLDJvCDRqRu+jC2qCoD+eIomonmOwB4smBRxfVpYQ==}
|
||||||
|
cpu: [ppc64]
|
||||||
|
os: [linux]
|
||||||
|
libc: [glibc]
|
||||||
|
|
||||||
|
'@img/sharp-libvips-linux-riscv64@1.3.4':
|
||||||
|
resolution: {integrity: sha512-aHkkIEHPRdQEegJN20MLmGtxYD9R2wQr3Cwpddnu5+YKMt6Uzax7S9h5gpZTo8wyrGuZSlfQ63OevL5mTyOC7Q==}
|
||||||
|
cpu: [riscv64]
|
||||||
|
os: [linux]
|
||||||
|
libc: [glibc]
|
||||||
|
|
||||||
|
'@img/sharp-libvips-linux-s390x@1.3.4':
|
||||||
|
resolution: {integrity: sha512-ra/mB6MikESDUO7Yg+Mi95bFBb9GsObURuhnOv3OqknjGe9sZrG8tCe9q0xSIGrtLgvgw0gKnFWcK4blSgQOuQ==}
|
||||||
|
cpu: [s390x]
|
||||||
|
os: [linux]
|
||||||
|
libc: [glibc]
|
||||||
|
|
||||||
|
'@img/sharp-libvips-linux-x64@1.3.4':
|
||||||
|
resolution: {integrity: sha512-GJ//SSXbnwSDes02umB3nDJLFcQzw8a18V8fyhqr6tV515tOEMdImjjxj1AoafMRz56F3PHgftnj1QEKSU1zkw==}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [linux]
|
||||||
|
libc: [glibc]
|
||||||
|
|
||||||
|
'@img/sharp-libvips-linuxmusl-arm64@1.3.4':
|
||||||
|
resolution: {integrity: sha512-hvulFwtjUcagsis6BBxHwGFwWoNZjgYmULGVrZcyfNbjA8hKILbRxGg15/7w5HDyXHXUos/j6baAWqnCyQ2DWA==}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [linux]
|
||||||
|
libc: [musl]
|
||||||
|
|
||||||
|
'@img/sharp-libvips-linuxmusl-x64@1.3.4':
|
||||||
|
resolution: {integrity: sha512-6zXKeE/p39I1AmA3cJG35eyBGNqNddLnUXjhwBnsGjFPWqf5VKkDBEqaEkPDoTEtkxwi2vv8Tcr2mDyP4So7Fg==}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [linux]
|
||||||
|
libc: [musl]
|
||||||
|
|
||||||
|
'@img/sharp-linux-arm64@0.35.5':
|
||||||
|
resolution: {integrity: sha512-LYVx5JTsOM2CBzmxreh+nl64/3H6Xb09iSLknqH47z2T2DFFxDeFLP5y4dJwe6H7uGQlHPyEEtIqyo3DYsRwdQ==}
|
||||||
|
engines: {node: '>=20.9.0'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [linux]
|
||||||
|
libc: [glibc]
|
||||||
|
|
||||||
|
'@img/sharp-linux-arm@0.35.5':
|
||||||
|
resolution: {integrity: sha512-LEaXK2WdXVK5ykcw0buWyPMsmLLL2vpHLD6yrNSW+JGEL3BZPA4tpKN6iaMc4AxTTAoaX/sU1rOL51lcIz48ZQ==}
|
||||||
|
engines: {node: '>=20.9.0'}
|
||||||
|
cpu: [arm]
|
||||||
|
os: [linux]
|
||||||
|
libc: [glibc]
|
||||||
|
|
||||||
|
'@img/sharp-linux-ppc64@0.35.5':
|
||||||
|
resolution: {integrity: sha512-QVxAAq8evVRI9ia2vqgwrmWucn5Dfv+JdWzj75pD8omHLPSP7f8p20O8jxzjCcuCEQEOtYOZUmX1hkiZ0kdevA==}
|
||||||
|
engines: {node: '>=20.9.0'}
|
||||||
|
cpu: [ppc64]
|
||||||
|
os: [linux]
|
||||||
|
libc: [glibc]
|
||||||
|
|
||||||
|
'@img/sharp-linux-riscv64@0.35.5':
|
||||||
|
resolution: {integrity: sha512-LtdreXguaavKODPIfzJ4kffx7UNt1omwtK0rch4EBbbSTXPnxWmYSayXdLJw0fJzQ97kHt1gL/yh4tvU+nCyRQ==}
|
||||||
|
engines: {node: '>=20.9.0'}
|
||||||
|
cpu: [riscv64]
|
||||||
|
os: [linux]
|
||||||
|
libc: [glibc]
|
||||||
|
|
||||||
|
'@img/sharp-linux-s390x@0.35.5':
|
||||||
|
resolution: {integrity: sha512-UZasTOFiYzotTsGOCu42BfUzP6Tu6Do/947iRm1RsLKvlllxwGcn4RN27LibGWceix4Y+Pmw3jsnTcCQIgWjqA==}
|
||||||
|
engines: {node: '>=20.9.0'}
|
||||||
|
cpu: [s390x]
|
||||||
|
os: [linux]
|
||||||
|
libc: [glibc]
|
||||||
|
|
||||||
|
'@img/sharp-linux-x64@0.35.5':
|
||||||
|
resolution: {integrity: sha512-SxFtLTeJInhAA9Q836kux2vZNeOBQEx658qvbboZScr0wIARym3IcGmW7KpVD5sbVg0Ojy+udFQdayYIZyoNog==}
|
||||||
|
engines: {node: '>=20.9.0'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [linux]
|
||||||
|
libc: [glibc]
|
||||||
|
|
||||||
|
'@img/sharp-linuxmusl-arm64@0.35.5':
|
||||||
|
resolution: {integrity: sha512-9HbMclmI1zlNkFRs3z9/eBtDjfD0sGlrX1z6b1qwmiFY5ElDLh4BC0LPBdVp7z1DXFiKlIcznf+ZlsuZzLxQqg==}
|
||||||
|
engines: {node: '>=20.9.0'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [linux]
|
||||||
|
libc: [musl]
|
||||||
|
|
||||||
|
'@img/sharp-linuxmusl-x64@0.35.5':
|
||||||
|
resolution: {integrity: sha512-4KOphqB035HrVdqLZfCgMzzERrQkkzOwRhl4OAkRO1YCldbaFjySXMaK534Mo0V+LndnlJk+sbUyLeU0ULyD1A==}
|
||||||
|
engines: {node: '>=20.9.0'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [linux]
|
||||||
|
libc: [musl]
|
||||||
|
|
||||||
|
'@img/sharp-wasm32@0.35.5':
|
||||||
|
resolution: {integrity: sha512-Ptsga1su4tQx+LLF1ECS9U6nz5kmrXKo6XVbtR48Ke3ZRxxgaWBu7IDtEe1quo8hiupwm6WFqxVlXaSf7IINGQ==}
|
||||||
|
engines: {node: '>=20.9.0'}
|
||||||
|
|
||||||
|
'@img/sharp-webcontainers-wasm32@0.35.5':
|
||||||
|
resolution: {integrity: sha512-hfhF/FmoQyTUkA0bIKFOtw536BQSeBMe6BF6QyWlrPxT754+TFLaZ7sKKTfvvM0yJgKgaYTwnFCIZ/GuDw5SUA==}
|
||||||
|
engines: {node: '>=20.9.0'}
|
||||||
|
cpu: [wasm32]
|
||||||
|
|
||||||
|
'@img/sharp-win32-arm64@0.35.5':
|
||||||
|
resolution: {integrity: sha512-X4t7g+7ZA5DKblCBEXGjUqqemj4vczING/5viFwAL8h4N3qYeyjwdCvRLHi4EdOUI+2Z7UFlp1VM+p/AuEtm6Q==}
|
||||||
|
engines: {node: '>=20.9.0'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [win32]
|
||||||
|
|
||||||
|
'@img/sharp-win32-ia32@0.35.5':
|
||||||
|
resolution: {integrity: sha512-5Zm82LoBc43nhwNybZlG7Y1KO//Zhsn306fQl29ZOuStHLGTo3BWL83q3cznX0poxSAMuYL1On/BHBxkBeKr6A==}
|
||||||
|
engines: {node: ^20.9.0}
|
||||||
|
cpu: [ia32]
|
||||||
|
os: [win32]
|
||||||
|
|
||||||
|
'@img/sharp-win32-x64@0.35.5':
|
||||||
|
resolution: {integrity: sha512-x76eH0vEiHlcMQu8Y8IenntaACtddpT6W0wmXtWrnKcnKI7ME5DdgqhAD6SEWOEl1v2zDvkZDhFA9KnURwpfqg==}
|
||||||
|
engines: {node: '>=20.9.0'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [win32]
|
||||||
|
|
||||||
'@jridgewell/gen-mapping@0.3.13':
|
'@jridgewell/gen-mapping@0.3.13':
|
||||||
resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==}
|
resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==}
|
||||||
|
|
||||||
|
|
@ -2332,6 +2500,15 @@ packages:
|
||||||
set-cookie-parser@3.1.2:
|
set-cookie-parser@3.1.2:
|
||||||
resolution: {integrity: sha512-5/r/lTwbJ3zQ+qwdUFZYeRNqda7P5HD8zQKqlSjdGt1/S0cjLAphHusj4Y58ahDtWn/g32xrIS58/ikOvwl0Lw==}
|
resolution: {integrity: sha512-5/r/lTwbJ3zQ+qwdUFZYeRNqda7P5HD8zQKqlSjdGt1/S0cjLAphHusj4Y58ahDtWn/g32xrIS58/ikOvwl0Lw==}
|
||||||
|
|
||||||
|
sharp@0.35.5:
|
||||||
|
resolution: {integrity: sha512-Ywn4OnzGukp7CDMrp08RQ50YKmuwG47brZgIVPTvBaaAfQlRlygrRqSrxdCiL9M+LlzLBiJ68IR1QqvzHyjC7g==}
|
||||||
|
engines: {node: '>=20.9.0'}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/node': '*'
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/node':
|
||||||
|
optional: true
|
||||||
|
|
||||||
shebang-command@2.0.0:
|
shebang-command@2.0.0:
|
||||||
resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
|
resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
|
@ -2428,6 +2605,9 @@ packages:
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
typescript: '>=4.8.4'
|
typescript: '>=4.8.4'
|
||||||
|
|
||||||
|
tslib@2.8.1:
|
||||||
|
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
|
||||||
|
|
||||||
tsx@4.23.15:
|
tsx@4.23.15:
|
||||||
resolution: {integrity: sha512-Yiex1Ovn8z2xPpOWckIiysV1SSyRMY9BkLF++q0yKiDxCqRhosKfMg3janKkiLBwZ5c/YryloKwGZcrEmtwxKw==}
|
resolution: {integrity: sha512-Yiex1Ovn8z2xPpOWckIiysV1SSyRMY9BkLF++q0yKiDxCqRhosKfMg3janKkiLBwZ5c/YryloKwGZcrEmtwxKw==}
|
||||||
engines: {node: '>=18.0.0'}
|
engines: {node: '>=18.0.0'}
|
||||||
|
|
@ -2760,6 +2940,11 @@ snapshots:
|
||||||
|
|
||||||
'@drizzle-team/brocli@0.10.2': {}
|
'@drizzle-team/brocli@0.10.2': {}
|
||||||
|
|
||||||
|
'@emnapi/runtime@1.11.3':
|
||||||
|
dependencies:
|
||||||
|
tslib: 2.8.1
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@esbuild-kit/core-utils@3.3.2':
|
'@esbuild-kit/core-utils@3.3.2':
|
||||||
dependencies:
|
dependencies:
|
||||||
esbuild: 0.18.20
|
esbuild: 0.18.20
|
||||||
|
|
@ -3069,6 +3254,112 @@ snapshots:
|
||||||
|
|
||||||
'@humanwhocodes/retry@0.4.3': {}
|
'@humanwhocodes/retry@0.4.3': {}
|
||||||
|
|
||||||
|
'@img/colour@1.1.0': {}
|
||||||
|
|
||||||
|
'@img/sharp-darwin-arm64@0.35.5':
|
||||||
|
optionalDependencies:
|
||||||
|
'@img/sharp-libvips-darwin-arm64': 1.3.4
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@img/sharp-darwin-x64@0.35.5':
|
||||||
|
optionalDependencies:
|
||||||
|
'@img/sharp-libvips-darwin-x64': 1.3.4
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@img/sharp-freebsd-wasm32@0.35.5':
|
||||||
|
dependencies:
|
||||||
|
'@img/sharp-wasm32': 0.35.5
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@img/sharp-libvips-darwin-arm64@1.3.4':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@img/sharp-libvips-darwin-x64@1.3.4':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@img/sharp-libvips-linux-arm64@1.3.4':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@img/sharp-libvips-linux-arm@1.3.4':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@img/sharp-libvips-linux-ppc64@1.3.4':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@img/sharp-libvips-linux-riscv64@1.3.4':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@img/sharp-libvips-linux-s390x@1.3.4':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@img/sharp-libvips-linux-x64@1.3.4':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@img/sharp-libvips-linuxmusl-arm64@1.3.4':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@img/sharp-libvips-linuxmusl-x64@1.3.4':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@img/sharp-linux-arm64@0.35.5':
|
||||||
|
optionalDependencies:
|
||||||
|
'@img/sharp-libvips-linux-arm64': 1.3.4
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@img/sharp-linux-arm@0.35.5':
|
||||||
|
optionalDependencies:
|
||||||
|
'@img/sharp-libvips-linux-arm': 1.3.4
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@img/sharp-linux-ppc64@0.35.5':
|
||||||
|
optionalDependencies:
|
||||||
|
'@img/sharp-libvips-linux-ppc64': 1.3.4
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@img/sharp-linux-riscv64@0.35.5':
|
||||||
|
optionalDependencies:
|
||||||
|
'@img/sharp-libvips-linux-riscv64': 1.3.4
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@img/sharp-linux-s390x@0.35.5':
|
||||||
|
optionalDependencies:
|
||||||
|
'@img/sharp-libvips-linux-s390x': 1.3.4
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@img/sharp-linux-x64@0.35.5':
|
||||||
|
optionalDependencies:
|
||||||
|
'@img/sharp-libvips-linux-x64': 1.3.4
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@img/sharp-linuxmusl-arm64@0.35.5':
|
||||||
|
optionalDependencies:
|
||||||
|
'@img/sharp-libvips-linuxmusl-arm64': 1.3.4
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@img/sharp-linuxmusl-x64@0.35.5':
|
||||||
|
optionalDependencies:
|
||||||
|
'@img/sharp-libvips-linuxmusl-x64': 1.3.4
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@img/sharp-wasm32@0.35.5':
|
||||||
|
dependencies:
|
||||||
|
'@emnapi/runtime': 1.11.3
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@img/sharp-webcontainers-wasm32@0.35.5':
|
||||||
|
dependencies:
|
||||||
|
'@img/sharp-wasm32': 0.35.5
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@img/sharp-win32-arm64@0.35.5':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@img/sharp-win32-ia32@0.35.5':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@img/sharp-win32-x64@0.35.5':
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@jridgewell/gen-mapping@0.3.13':
|
'@jridgewell/gen-mapping@0.3.13':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@jridgewell/sourcemap-codec': 1.6.0
|
'@jridgewell/sourcemap-codec': 1.6.0
|
||||||
|
|
@ -4354,6 +4645,39 @@ snapshots:
|
||||||
|
|
||||||
set-cookie-parser@3.1.2: {}
|
set-cookie-parser@3.1.2: {}
|
||||||
|
|
||||||
|
sharp@0.35.5(@types/node@24.19.1):
|
||||||
|
dependencies:
|
||||||
|
'@img/colour': 1.1.0
|
||||||
|
detect-libc: 2.1.2
|
||||||
|
semver: 7.8.5
|
||||||
|
optionalDependencies:
|
||||||
|
'@img/sharp-darwin-arm64': 0.35.5
|
||||||
|
'@img/sharp-darwin-x64': 0.35.5
|
||||||
|
'@img/sharp-freebsd-wasm32': 0.35.5
|
||||||
|
'@img/sharp-libvips-darwin-arm64': 1.3.4
|
||||||
|
'@img/sharp-libvips-darwin-x64': 1.3.4
|
||||||
|
'@img/sharp-libvips-linux-arm': 1.3.4
|
||||||
|
'@img/sharp-libvips-linux-arm64': 1.3.4
|
||||||
|
'@img/sharp-libvips-linux-ppc64': 1.3.4
|
||||||
|
'@img/sharp-libvips-linux-riscv64': 1.3.4
|
||||||
|
'@img/sharp-libvips-linux-s390x': 1.3.4
|
||||||
|
'@img/sharp-libvips-linux-x64': 1.3.4
|
||||||
|
'@img/sharp-libvips-linuxmusl-arm64': 1.3.4
|
||||||
|
'@img/sharp-libvips-linuxmusl-x64': 1.3.4
|
||||||
|
'@img/sharp-linux-arm': 0.35.5
|
||||||
|
'@img/sharp-linux-arm64': 0.35.5
|
||||||
|
'@img/sharp-linux-ppc64': 0.35.5
|
||||||
|
'@img/sharp-linux-riscv64': 0.35.5
|
||||||
|
'@img/sharp-linux-s390x': 0.35.5
|
||||||
|
'@img/sharp-linux-x64': 0.35.5
|
||||||
|
'@img/sharp-linuxmusl-arm64': 0.35.5
|
||||||
|
'@img/sharp-linuxmusl-x64': 0.35.5
|
||||||
|
'@img/sharp-webcontainers-wasm32': 0.35.5
|
||||||
|
'@img/sharp-win32-arm64': 0.35.5
|
||||||
|
'@img/sharp-win32-ia32': 0.35.5
|
||||||
|
'@img/sharp-win32-x64': 0.35.5
|
||||||
|
'@types/node': 24.19.1
|
||||||
|
|
||||||
shebang-command@2.0.0:
|
shebang-command@2.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
shebang-regex: 3.0.0
|
shebang-regex: 3.0.0
|
||||||
|
|
@ -4426,6 +4750,9 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
typescript: 6.0.3
|
typescript: 6.0.3
|
||||||
|
|
||||||
|
tslib@2.8.1:
|
||||||
|
optional: true
|
||||||
|
|
||||||
tsx@4.23.15:
|
tsx@4.23.15:
|
||||||
dependencies:
|
dependencies:
|
||||||
esbuild: 0.28.2
|
esbuild: 0.28.2
|
||||||
|
|
|
||||||