From cf0455a52125daee059c989501febfb8cf3908e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20HOUZ=C3=89?= Date: Tue, 10 Mar 2026 09:58:27 +0100 Subject: [PATCH 1/3] Add full Windows support (install.ps1, new targets, build flags, ICO, metadata) - build.ts: remove bytecode (breaks Windows), add Windows-specific flags (icon, hideConsole, title, publisher, version, description, copyright), support bun-windows-x64-baseline / bun-windows-x64-modern / bun-windows-arm64 - build.test.ts: unit tests for parseTarget, isWindowsTarget, getOutfile, getBuildCompileOptions (35 cases) - install.ps1: detect ARM64, prefer x64-modern with auto-fallback to x64-baseline when asset is absent in the release - cd.yaml: add bun-windows-x64-baseline, bun-windows-x64-modern, bun-windows-arm64 to the build matrix - scripts/generate-ico.ts: generate multi-resolution ICO (16/32/48/256) from docs/public/logo.svg via sharp - docs/public/icons/favicon.ico: generated Windows icon asset - README.md: add Windows PowerShell quick-start block - package.json: add generate-ico script, add sharp dev dependency --- .github/workflows/cd.yaml | 9 + README.md | 10 + build.test.ts | 248 +++++++++++++++++++++++ build.ts | 144 ++++++++++--- bun.lock | 63 +++++- docs/.vitepress/theme/InstallSection.vue | 92 ++++++++- docs/getting-started/installation.md | 31 ++- docs/public/icons/favicon.ico | Bin 0 -> 15600 bytes install.ps1 | 248 +++++++++++++++++++++++ package.json | 2 + scripts/generate-ico.ts | 56 +++++ 11 files changed, 858 insertions(+), 45 deletions(-) create mode 100644 build.test.ts create mode 100644 docs/public/icons/favicon.ico create mode 100644 install.ps1 create mode 100644 scripts/generate-ico.ts diff --git a/.github/workflows/cd.yaml b/.github/workflows/cd.yaml index 8a9c537..eb912c6 100644 --- a/.github/workflows/cd.yaml +++ b/.github/workflows/cd.yaml @@ -30,6 +30,15 @@ jobs: - runner: ubuntu-latest target: bun-windows-x64 artifact: github-code-search-windows-x64.exe + - runner: ubuntu-latest + target: bun-windows-x64-baseline + artifact: github-code-search-windows-x64-baseline.exe + - runner: ubuntu-latest + target: bun-windows-x64-modern + artifact: github-code-search-windows-x64-modern.exe + - runner: ubuntu-latest + target: bun-windows-arm64 + artifact: github-code-search-windows-arm64.exe # macOS — must run on macOS for ad-hoc codesigning - runner: macos-latest target: bun-darwin-x64 diff --git a/README.md b/README.md index e46c830..3f8320c 100644 --- a/README.md +++ b/README.md @@ -14,12 +14,22 @@ keyboard-driven TUI, fine-grained extract selection, markdown/JSON output. ## Quick start +**macOS / Linux** + ```bash export GITHUB_TOKEN=ghp_xxxxxxxxxxxxxxxxxxxx curl -fsSL https://raw.githubusercontent.com/fulll/github-code-search/main/install.sh | bash github-code-search query "TODO" --org my-org ``` +**Windows** (PowerShell) + +```powershell +$env:GITHUB_TOKEN = "ghp_xxxxxxxxxxxxxxxxxxxx" +powershell -c "irm https://raw.githubusercontent.com/fulll/github-code-search/main/install.ps1 | iex" +github-code-search query "TODO" --org my-org +``` + ## Features - **Org-wide search** — queries all repositories in a GitHub organization in one command, with automatic pagination up to 1 000 results diff --git a/build.test.ts b/build.test.ts new file mode 100644 index 0000000..819f500 --- /dev/null +++ b/build.test.ts @@ -0,0 +1,248 @@ +import { describe, it, expect } from "bun:test"; +import { + parseTarget, + isWindowsTarget, + getOutfile, + getBuildCompileOptions, + type WindowsMeta, +} from "./build"; + +// ─── parseTarget ───────────────────────────────────────────────────────────── + +describe("parseTarget", () => { + it("parses bun-linux-x64", () => { + expect(parseTarget("bun-linux-x64")).toEqual({ os: "linux", arch: "x64" }); + }); + + it("parses bun-linux-x64-baseline", () => { + expect(parseTarget("bun-linux-x64-baseline")).toEqual({ + os: "linux", + arch: "x64-baseline", + }); + }); + + it("parses bun-linux-arm64", () => { + expect(parseTarget("bun-linux-arm64")).toEqual({ + os: "linux", + arch: "arm64", + }); + }); + + it("parses bun-linux-arm64-musl", () => { + expect(parseTarget("bun-linux-arm64-musl")).toEqual({ + os: "linux", + arch: "arm64-musl", + }); + }); + + it("parses bun-darwin-x64", () => { + expect(parseTarget("bun-darwin-x64")).toEqual({ + os: "darwin", + arch: "x64", + }); + }); + + it("parses bun-darwin-arm64", () => { + expect(parseTarget("bun-darwin-arm64")).toEqual({ + os: "darwin", + arch: "arm64", + }); + }); + + it("parses bun-windows-x64", () => { + expect(parseTarget("bun-windows-x64")).toEqual({ + os: "windows", + arch: "x64", + }); + }); + + it("parses bun-windows-x64-baseline", () => { + expect(parseTarget("bun-windows-x64-baseline")).toEqual({ + os: "windows", + arch: "x64-baseline", + }); + }); + + it("parses bun-windows-x64-modern", () => { + expect(parseTarget("bun-windows-x64-modern")).toEqual({ + os: "windows", + arch: "x64-modern", + }); + }); + + it("parses bun-windows-arm64", () => { + expect(parseTarget("bun-windows-arm64")).toEqual({ + os: "windows", + arch: "arm64", + }); + }); + + it("returns native platform when target is null", () => { + const result = parseTarget(null); + // We can only assert the shape, not the exact values (depends on the runner) + expect(typeof result.os).toBe("string"); + expect(typeof result.arch).toBe("string"); + expect(result.os.length).toBeGreaterThan(0); + }); + + it("returns native platform when target is undefined", () => { + const result = parseTarget(undefined); + expect(typeof result.os).toBe("string"); + expect(typeof result.arch).toBe("string"); + }); + + // baseline must be parsed before plain x64 (order matters in the if-chain) + it("does not confuse windows-x64-baseline with windows-x64", () => { + expect(parseTarget("bun-windows-x64-baseline").arch).toBe("x64-baseline"); + expect(parseTarget("bun-windows-x64").arch).toBe("x64"); + }); + + it("does not confuse linux-x64-baseline with linux-x64", () => { + expect(parseTarget("bun-linux-x64-baseline").arch).toBe("x64-baseline"); + expect(parseTarget("bun-linux-x64").arch).toBe("x64"); + }); +}); + +// ─── isWindowsTarget ───────────────────────────────────────────────────────── + +describe("isWindowsTarget", () => { + it("returns true for windows", () => { + expect(isWindowsTarget("windows")).toBe(true); + }); + + it("returns false for linux", () => { + expect(isWindowsTarget("linux")).toBe(false); + }); + + it("returns false for darwin", () => { + expect(isWindowsTarget("darwin")).toBe(false); + }); +}); + +// ─── getOutfile ─────────────────────────────────────────────────────────────── + +describe("getOutfile", () => { + it("adds .exe suffix for windows targets", () => { + expect(getOutfile("windows", "bun-windows-x64")).toBe( + "./dist/github-code-search-windows-x64.exe", + ); + }); + + it("adds .exe suffix for windows-x64-modern", () => { + expect(getOutfile("windows", "bun-windows-x64-modern")).toBe( + "./dist/github-code-search-windows-x64-modern.exe", + ); + }); + + it("adds .exe suffix for windows-x64-baseline", () => { + expect(getOutfile("windows", "bun-windows-x64-baseline")).toBe( + "./dist/github-code-search-windows-x64-baseline.exe", + ); + }); + + it("adds .exe suffix for windows-arm64", () => { + expect(getOutfile("windows", "bun-windows-arm64")).toBe( + "./dist/github-code-search-windows-arm64.exe", + ); + }); + + it("does not add .exe for linux targets", () => { + expect(getOutfile("linux", "bun-linux-x64")).toBe("./dist/github-code-search-linux-x64"); + }); + + it("does not add .exe for darwin targets", () => { + expect(getOutfile("darwin", "bun-darwin-arm64")).toBe("./dist/github-code-search-darwin-arm64"); + }); + + it("omits suffix for native (no target)", () => { + const outfile = getOutfile("linux", null); + expect(outfile).toBe("./dist/github-code-search"); + }); + + it("strips the bun- prefix from the suffix", () => { + expect(getOutfile("linux", "bun-linux-arm64")).toBe("./dist/github-code-search-linux-arm64"); + }); +}); + +// ─── getBuildCompileOptions ─────────────────────────────────────────────────── + +const FULL_META: WindowsMeta = { + iconPath: "/abs/path/favicon.ico", + title: "github-code-search", + publisher: "fulll", + appVersion: "1.2.3", + description: "Interactive GitHub code search", + copyright: "Copyright © 2026 fulll — MIT", +}; + +describe("getBuildCompileOptions", () => { + it("returns only outfile for non-windows targets", () => { + const opts = getBuildCompileOptions("linux", "./dist/foo", FULL_META); + expect(opts).toEqual({ outfile: "./dist/foo" }); + }); + + it("returns only outfile for darwin", () => { + const opts = getBuildCompileOptions("darwin", "./dist/foo", FULL_META); + expect(opts).toEqual({ outfile: "./dist/foo" }); + }); + + it("includes hideConsole for windows target", () => { + const opts = getBuildCompileOptions("windows", "./dist/foo.exe", FULL_META); + expect(opts).toMatchObject({ + outfile: "./dist/foo.exe", + windows: { hideConsole: true }, + }); + }); + + it("sets icon from iconPath", () => { + const opts = getBuildCompileOptions("windows", "./dist/foo.exe", FULL_META) as { + windows: WindowsMeta & { icon: string; hideConsole: boolean }; + }; + expect(opts.windows.icon).toBe("/abs/path/favicon.ico"); + }); + + it("sets title", () => { + const opts = getBuildCompileOptions("windows", "./dist/foo.exe", FULL_META) as { + windows: { title: string }; + }; + expect(opts.windows.title).toBe("github-code-search"); + }); + + it("sets publisher", () => { + const opts = getBuildCompileOptions("windows", "./dist/foo.exe", FULL_META) as { + windows: { publisher: string }; + }; + expect(opts.windows.publisher).toBe("fulll"); + }); + + it("sets version from appVersion", () => { + const opts = getBuildCompileOptions("windows", "./dist/foo.exe", FULL_META) as { + windows: { version: string }; + }; + expect(opts.windows.version).toBe("1.2.3"); + }); + + it("sets description", () => { + const opts = getBuildCompileOptions("windows", "./dist/foo.exe", FULL_META) as { + windows: { description: string }; + }; + expect(opts.windows.description).toBe("Interactive GitHub code search"); + }); + + it("sets copyright", () => { + const opts = getBuildCompileOptions("windows", "./dist/foo.exe", FULL_META) as { + windows: { copyright: string }; + }; + expect(opts.windows.copyright).toBe("Copyright © 2026 fulll — MIT"); + }); + + it("works with empty meta (all windows fields undefined)", () => { + const opts = getBuildCompileOptions("windows", "./dist/foo.exe") as { + outfile: string; + windows: Record; + }; + expect(opts.outfile).toBe("./dist/foo.exe"); + expect(opts.windows.icon).toBeUndefined(); + expect(opts.windows.title).toBeUndefined(); + }); +}); diff --git a/build.ts b/build.ts index 326cc03..cac476b 100644 --- a/build.ts +++ b/build.ts @@ -3,50 +3,133 @@ * Build script – compiles github-code-search.ts into a standalone binary. * * Usage: - * bun run build.ts.ts # current platform - * bun run build.ts.ts --target=bun-linux-x64 # cross-compile + * bun run build.ts # current platform + * bun run build.ts --target=bun-linux-x64 # cross-compile * * Supported targets (Bun executables): * bun-linux-x64 bun-linux-x64-baseline bun-linux-arm64 * bun-darwin-x64 bun-darwin-arm64 - * bun-windows-x64 + * bun-windows-x64 bun-windows-x64-baseline bun-windows-x64-modern + * bun-windows-arm64 */ -import { version } from "./package.json" with { type: "json" }; +import { version, description, author, license } from "./package.json" with { type: "json" }; -// ─── CLI args ────────────────────────────────────────────────────────────────── +// ─── Pure helpers (exported for unit tests) ─────────────────────────────────── -const targetArg = process.argv.find((a) => a.startsWith("--target=")); -const target = targetArg?.slice("--target=".length) ?? null; +export type ParsedTarget = { + os: string; + arch: string; +}; -// ─── Derive OS / arch from target ───────────────────────────────────────────── +/** + * Derive a canonical { os, arch } pair from a Bun target string such as + * "bun-windows-x64-modern" or "bun-linux-arm64". + * Returns { os: process.platform, arch: process.arch } when `t` is null/undefined. + */ +export function parseTarget(t: string | null | undefined): ParsedTarget { + if (!t) + return { + os: process.platform, + arch: process.arch === "x64" ? "x64" : process.arch, + }; -function parseTarget(t: string): { os: string; arch: string } { const s = t.replace(/^bun-/, ""); + if (s.startsWith("linux-x64-baseline")) return { os: "linux", arch: "x64-baseline" }; if (s.startsWith("linux-x64")) return { os: "linux", arch: "x64" }; if (s.startsWith("linux-arm64-musl")) return { os: "linux", arch: "arm64-musl" }; if (s.startsWith("linux-arm64")) return { os: "linux", arch: "arm64" }; if (s.startsWith("darwin-x64")) return { os: "darwin", arch: "x64" }; if (s.startsWith("darwin-arm64")) return { os: "darwin", arch: "arm64" }; + if (s.startsWith("windows-x64-baseline")) return { os: "windows", arch: "x64-baseline" }; + if (s.startsWith("windows-x64-modern")) return { os: "windows", arch: "x64-modern" }; if (s.startsWith("windows-x64")) return { os: "windows", arch: "x64" }; + if (s.startsWith("windows-arm64")) return { os: "windows", arch: "arm64" }; + return { os: process.platform, arch: process.arch }; } -const { os: targetOs, arch: targetArch } = target - ? parseTarget(target) - : { - os: process.platform, - arch: process.arch === "x64" ? "x64" : process.arch, +/** + * Returns true when the given os value targets Windows. + */ +export function isWindowsTarget(targetOs: string): boolean { + return targetOs === "windows"; +} + +/** + * Compute the output filename for the binary. + * + * target=bun-linux-x64 → dist/github-code-search-linux-x64 + * target=bun-windows-x64 → dist/github-code-search-windows-x64.exe + * target=bun-windows-x64-modern → dist/github-code-search-windows-x64-modern.exe + * target=null (native) → dist/github-code-search + */ +export function getOutfile(targetOs: string, target: string | null): string { + const ext = isWindowsTarget(targetOs) ? ".exe" : ""; + const suffix = target ? `-${target.replace(/^bun-/, "")}` : ""; + return `./dist/github-code-search${suffix}${ext}`; +} + +export type WindowsMeta = { + iconPath?: string; + title?: string; + publisher?: string; + appVersion?: string; + description?: string; + copyright?: string; +}; + +/** + * Build the `compile` options forwarded to Bun.build(). + * Windows binaries receive metadata-enriching flags so the resulting .exe + * is not misidentified as "bun" by the OS and shows correct file properties. + * See: https://bun.sh/docs/bundler/executables#windows-specific-flags + * + * @param meta.iconPath Absolute path to .ico — must be absolute so Bun + * resolves it correctly regardless of the caller's CWD. + */ +export function getBuildCompileOptions( + targetOs: string, + outfile: string, + meta: WindowsMeta = {}, +): NonNullable[0]["compile"]> { + if (isWindowsTarget(targetOs)) { + return { + outfile, + windows: { + // iconPath must be absolute — relative paths are resolved from the + // process CWD which may differ from the script location. + icon: meta.iconPath, + // hideConsole: true — prevents Windows from spawning a detached console + // window when the binary is launched from a GUI context (e.g. Explorer). + // The binary still runs correctly in any terminal emulator / cmd / pwsh. + hideConsole: true, + title: meta.title, + publisher: meta.publisher, + version: meta.appVersion, + description: meta.description, + copyright: meta.copyright, + }, }; + } + return { outfile }; +} -// ─── Output path ─────────────────────────────────────────────────────────────── +// ─── CLI args ───────────────────────────────────────────────────────────────── -const ext = targetOs === "windows" ? ".exe" : ""; -const suffix = target ? `-${target.replace(/^bun-/, "")}` : ""; -const outfile = `./dist/github-code-search${suffix}${ext}`; +const targetArg = process.argv.find((a) => a.startsWith("--target=")); +const target = targetArg?.slice("--target=".length) ?? null; + +// ─── Derive OS / arch from target ──────────────────────────────────────────── + +const { os: targetOs, arch: targetArch } = parseTarget(target); + +// ─── Output path ───────────────────────────────────────────────────────────── -// ─── Git commit hash ────────────────────────────────────────────────────────── +const outfile = getOutfile(targetOs, target); + +// ─── Git commit hash ───────────────────────────────────────────────────────── let commit = "dev"; try { @@ -66,26 +149,37 @@ const label = `${version} (${commit} · ${targetOs}/${targetArch})`; console.log(`Building github-code-search v${label}… outfile=${outfile}`); if (target) console.log(` Target: ${target}`); +// Absolute path to the Windows icon — must be absolute so Bun resolves it +// correctly when the script is invoked from any working directory. +const icoPath = `${import.meta.dir}/docs/public/icons/favicon.ico`; + +const currentYear = new Date().getFullYear(); + await Bun.$`mkdir -p dist`; await Bun.build({ entrypoints: ["./github-code-search.ts"], minify: true, - bytecode: true, - compile: { - outfile, - }, + // Fix: bytecode: true causes the binary to fail on Windows — removed. + compile: getBuildCompileOptions(targetOs, outfile, { + iconPath: icoPath, + title: "github-code-search", + publisher: typeof author === "string" ? author : author.name, + appVersion: version, + description, + copyright: `Copyright © ${currentYear} ${typeof author === "string" ? author : author.name} — ${license}`, + }), define: { BUILD_VERSION: JSON.stringify(version), BUILD_COMMIT: JSON.stringify(commit), BUILD_TARGET_OS: JSON.stringify(targetOs), BUILD_TARGET_ARCH: JSON.stringify(targetArch), }, - target: target ? target : undefined, + target: target ? (target as Parameters[0]["target"]) : undefined, }); console.log(` Built ${outfile}`); -// ─── Ad-hoc codesign (macOS only) ──────────────────────────────────────────── +// ─── Ad-hoc codesign (macOS only) ───────────────────────────────────────────── if (targetOs === "darwin" && process.platform === "darwin") { const sign = Bun.spawn( diff --git a/bun.lock b/bun.lock index d27446f..758c50c 100644 --- a/bun.lock +++ b/bun.lock @@ -17,6 +17,7 @@ "oxfmt": "^0.36.0", "oxlint": "^1.51.0", "pa11y-ci": "^4.1.0", + "sharp": "^0.34.5", "vitepress": "^1.6.3", "vitepress-mermaid-renderer": "^1.1.18", }, @@ -157,6 +158,56 @@ "@iconify/utils": ["@iconify/utils@3.1.0", "", { "dependencies": { "@antfu/install-pkg": "^1.1.0", "@iconify/types": "^2.0.0", "mlly": "^1.8.0" } }, "sha512-Zlzem1ZXhI1iHeeERabLNzBHdOa4VhQbqAcOQaMKuTuyZCpwKbC2R4Dd0Zo3g9EAc+Y4fiarO8HIHRAth7+skw=="], + "@img/colour": ["@img/colour@1.1.0", "", {}, "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ=="], + + "@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.2.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w=="], + + "@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.2.4" }, "os": "darwin", "cpu": "x64" }, "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw=="], + + "@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.2.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g=="], + + "@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.2.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg=="], + + "@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.2.4", "", { "os": "linux", "cpu": "arm" }, "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A=="], + + "@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw=="], + + "@img/sharp-libvips-linux-ppc64": ["@img/sharp-libvips-linux-ppc64@1.2.4", "", { "os": "linux", "cpu": "ppc64" }, "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA=="], + + "@img/sharp-libvips-linux-riscv64": ["@img/sharp-libvips-linux-riscv64@1.2.4", "", { "os": "linux", "cpu": "none" }, "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA=="], + + "@img/sharp-libvips-linux-s390x": ["@img/sharp-libvips-linux-s390x@1.2.4", "", { "os": "linux", "cpu": "s390x" }, "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ=="], + + "@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw=="], + + "@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw=="], + + "@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg=="], + + "@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.2.4" }, "os": "linux", "cpu": "arm" }, "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw=="], + + "@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.2.4" }, "os": "linux", "cpu": "arm64" }, "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg=="], + + "@img/sharp-linux-ppc64": ["@img/sharp-linux-ppc64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-ppc64": "1.2.4" }, "os": "linux", "cpu": "ppc64" }, "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA=="], + + "@img/sharp-linux-riscv64": ["@img/sharp-linux-riscv64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-riscv64": "1.2.4" }, "os": "linux", "cpu": "none" }, "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw=="], + + "@img/sharp-linux-s390x": ["@img/sharp-linux-s390x@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-s390x": "1.2.4" }, "os": "linux", "cpu": "s390x" }, "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg=="], + + "@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.2.4" }, "os": "linux", "cpu": "x64" }, "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ=="], + + "@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" }, "os": "linux", "cpu": "arm64" }, "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg=="], + + "@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.2.4" }, "os": "linux", "cpu": "x64" }, "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q=="], + + "@img/sharp-wasm32": ["@img/sharp-wasm32@0.34.5", "", { "dependencies": { "@emnapi/runtime": "^1.7.0" }, "cpu": "none" }, "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw=="], + + "@img/sharp-win32-arm64": ["@img/sharp-win32-arm64@0.34.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g=="], + + "@img/sharp-win32-ia32": ["@img/sharp-win32-ia32@0.34.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg=="], + + "@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.34.5", "", { "os": "win32", "cpu": "x64" }, "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw=="], + "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="], "@lhci/cli": ["@lhci/cli@0.15.1", "", { "dependencies": { "@lhci/utils": "0.15.1", "chrome-launcher": "^0.13.4", "compression": "^1.7.4", "debug": "^4.3.1", "express": "^4.17.1", "inquirer": "^6.3.1", "isomorphic-fetch": "^3.0.0", "lighthouse": "12.6.1", "lighthouse-logger": "1.2.0", "open": "^7.1.0", "proxy-agent": "^6.4.0", "tmp": "^0.1.0", "uuid": "^8.3.1", "yargs": "^15.4.1", "yargs-parser": "^13.1.2" }, "bin": { "lhci": "./src/cli.js" } }, "sha512-yhC0oXnXqGHYy1xl4D8YqaydMZ/khFAnXGY/o2m/J3PqPa/D0nj3V6TLoH02oVMFeEF2AQim7UbmdXMiXx2tOw=="], @@ -767,6 +818,8 @@ "destroy": ["destroy@1.2.0", "", {}, "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg=="], + "detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], + "devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="], "devtools-protocol": ["devtools-protocol@0.0.1467305", "", {}, "sha512-LxwMLqBoPPGpMdRL4NkLFRNy3QLp6Uqa7GNp1v6JaBheop2QrB9Q7q0A/q/CYYP9sBfZdHOyszVx4gc9zyk7ow=="], @@ -1257,7 +1310,7 @@ "search-insights": ["search-insights@2.17.3", "", {}, "sha512-RQPdCYTa8A68uM2jwxoY842xDhvx3E5LFL1LxvxCNMev4o5mLuokczhzjAgGwUZBAmOKZknArSxLKmXtIi2AxQ=="], - "semver": ["semver@5.7.2", "", { "bin": { "semver": "bin/semver" } }, "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="], + "semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], "send": ["send@0.19.2", "", { "dependencies": { "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "~0.5.2", "http-errors": "~2.0.1", "mime": "1.6.0", "ms": "2.1.3", "on-finished": "~2.4.1", "range-parser": "~1.2.1", "statuses": "~2.0.2" } }, "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg=="], @@ -1267,6 +1320,8 @@ "setprototypeof": ["setprototypeof@1.2.0", "", {}, "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="], + "sharp": ["sharp@0.34.5", "", { "dependencies": { "@img/colour": "^1.0.0", "detect-libc": "^2.1.2", "semver": "^7.7.3" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.34.5", "@img/sharp-darwin-x64": "0.34.5", "@img/sharp-libvips-darwin-arm64": "1.2.4", "@img/sharp-libvips-darwin-x64": "1.2.4", "@img/sharp-libvips-linux-arm": "1.2.4", "@img/sharp-libvips-linux-arm64": "1.2.4", "@img/sharp-libvips-linux-ppc64": "1.2.4", "@img/sharp-libvips-linux-riscv64": "1.2.4", "@img/sharp-libvips-linux-s390x": "1.2.4", "@img/sharp-libvips-linux-x64": "1.2.4", "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", "@img/sharp-libvips-linuxmusl-x64": "1.2.4", "@img/sharp-linux-arm": "0.34.5", "@img/sharp-linux-arm64": "0.34.5", "@img/sharp-linux-ppc64": "0.34.5", "@img/sharp-linux-riscv64": "0.34.5", "@img/sharp-linux-s390x": "0.34.5", "@img/sharp-linux-x64": "0.34.5", "@img/sharp-linuxmusl-arm64": "0.34.5", "@img/sharp-linuxmusl-x64": "0.34.5", "@img/sharp-wasm32": "0.34.5", "@img/sharp-win32-arm64": "0.34.5", "@img/sharp-win32-ia32": "0.34.5", "@img/sharp-win32-x64": "0.34.5" } }, "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg=="], + "shiki": ["shiki@2.5.0", "", { "dependencies": { "@shikijs/core": "2.5.0", "@shikijs/engine-javascript": "2.5.0", "@shikijs/engine-oniguruma": "2.5.0", "@shikijs/langs": "2.5.0", "@shikijs/themes": "2.5.0", "@shikijs/types": "2.5.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-mI//trrsaiCIPsja5CNfsyNOqgAZUb6VpJA+340toL42UpzQlXpwRV9nch69X6gaUxrr9kaOOa6e3y3uAkGFxQ=="], "side-channel": ["side-channel@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", "side-channel-list": "^1.0.0", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw=="], @@ -1477,8 +1532,6 @@ "@paulirish/trace_engine/third-party-web": ["third-party-web@0.29.0", "", {}, "sha512-nBDSJw5B7Sl1YfsATG2XkW5qgUPODbJhXw++BKygi9w6O/NKS98/uY/nR/DxDq2axEjL6halHW1v+jhm/j1DBQ=="], - "@puppeteer/browsers/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], - "@puppeteer/browsers/yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="], "@tybys/wasm-util/tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], @@ -1531,6 +1584,8 @@ "lighthouse/open": ["open@8.4.2", "", { "dependencies": { "define-lazy-prop": "^2.0.0", "is-docker": "^2.1.1", "is-wsl": "^2.2.0" } }, "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ=="], + "lighthouse/semver": ["semver@5.7.2", "", { "bin": { "semver": "bin/semver" } }, "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="], + "lighthouse/yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="], "lighthouse/yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="], @@ -1545,8 +1600,6 @@ "mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], - "pa11y/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], - "parse5/entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="], "puppeteer/devtools-protocol": ["devtools-protocol@0.0.1581282", "", {}, "sha512-nv7iKtNZQshSW2hKzYNr46nM/Cfh5SEvE2oV0/SEGgc9XupIY5ggf84Cz8eJIkBce7S3bmTAauFD6aysMpnqsQ=="], diff --git a/docs/.vitepress/theme/InstallSection.vue b/docs/.vitepress/theme/InstallSection.vue index 118a988..0708910 100644 --- a/docs/.vitepress/theme/InstallSection.vue +++ b/docs/.vitepress/theme/InstallSection.vue @@ -1,15 +1,27 @@