From ce2051bad59d9143395dd3655bbda9c264103568 Mon Sep 17 00:00:00 2001 From: planshim <100317079+planshim@users.noreply.github.com> Date: Tue, 10 Feb 2026 21:56:55 +0300 Subject: [PATCH] feat: amogus --- .github/workflows/build-docs.yml | 58 ++ .gitignore | 24 + .npmrc | 1 + biome.json | 44 + bun.lock | 895 +++++++++++++++++ commitlint.config.cjs | 3 + .../0_prerequisites.md | 2 + .../1_setup.md | 0 .../README.md | 0 docs/Development/aa.png | Bin 0 -> 29381 bytes .../questions.md | 0 .../troubleshooting.md | 2 +- docs/{revanced-cli => cli} | 0 docs/{revanced-manager => manager} | 0 docs/{revanced-patcher => patcher} | 0 lefthook.yml | 13 + package.json | 53 + scripts/build-llms.ts | 73 ++ scripts/build-sitemap.ts | 3 + scripts/generate-docs-graph.ts | 939 ++++++++++++++++++ site.config.ts | 79 ++ src/_tokens.scss | 23 + src/app.d.ts | 7 + src/app.html | 21 + src/app.scss | 433 ++++++++ src/lib/components/Button.svelte | 111 +++ src/lib/components/CopyCode.svelte | 111 +++ src/lib/components/PageAnchor.svelte | 100 ++ src/lib/components/SearchBar.svelte | 564 +++++++++++ src/lib/components/SearchResult.svelte | 111 +++ src/lib/components/SearchResults.svelte | 66 ++ src/lib/components/SegmentedButton.svelte | 38 + src/lib/components/Separator.svelte | 25 + src/lib/components/Spinner.svelte | 17 + src/lib/config.ts | 45 + src/lib/core/graph.ts | 96 ++ src/lib/core/href-utils.ts | 107 ++ src/lib/core/navigation.ts | 132 +++ src/lib/core/route-data.ts | 29 + src/lib/core/types.ts | 171 ++++ src/lib/layout/DocsHeader.svelte | 82 ++ src/lib/layout/DocsSidebar.svelte | 158 +++ src/lib/layout/Header.svelte | 349 +++++++ src/lib/layout/PageNavigation.svelte | 126 +++ src/lib/layout/SidebarNavList.svelte | 124 +++ src/lib/layout/SidebarPageAnchors.svelte | 40 + src/lib/layout/TableOfContents.svelte | 220 ++++ src/lib/utils/copy.ts | 42 + src/lib/utils/paths.ts | 35 + src/lib/utils/rehype-plugins.ts | 277 ++++++ src/lib/utils/search.ts | 171 ++++ src/routes/+error.svelte | 51 + src/routes/+layout.svelte | 232 +++++ src/routes/+page.svelte | 42 + src/routes/+page.ts | 1 + src/routes/[...slug]/+page.server.ts | 39 + src/routes/[...slug]/+page.svelte | 16 + src/routes/[...slug]/+page.ts | 24 + src/routes/search-index.json/+server.ts | 37 + static/favicon.ico | Bin 0 -> 20239 bytes static/logo.png | Bin 0 -> 7834 bytes static/logo.svg | 1 + static/robots.txt | 3 + svelte.config.js | 152 +++ tsconfig.json | 14 + vite.config.ts | 215 ++++ 66 files changed, 6846 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/build-docs.yml create mode 100644 .gitignore create mode 100644 .npmrc create mode 100644 biome.json create mode 100644 bun.lock create mode 100644 commitlint.config.cjs rename docs/{revanced-development => Development}/0_prerequisites.md (92%) rename docs/{revanced-development => Development}/1_setup.md (100%) rename docs/{revanced-development => Development}/README.md (100%) create mode 100644 docs/Development/aa.png rename docs/{revanced-resources => Resources}/questions.md (100%) rename docs/{revanced-resources => Resources}/troubleshooting.md (96%) rename docs/{revanced-cli => cli} (100%) rename docs/{revanced-manager => manager} (100%) rename docs/{revanced-patcher => patcher} (100%) create mode 100644 lefthook.yml create mode 100644 package.json create mode 100644 scripts/build-llms.ts create mode 100644 scripts/build-sitemap.ts create mode 100644 scripts/generate-docs-graph.ts create mode 100644 site.config.ts create mode 100644 src/_tokens.scss create mode 100644 src/app.d.ts create mode 100644 src/app.html create mode 100644 src/app.scss create mode 100644 src/lib/components/Button.svelte create mode 100644 src/lib/components/CopyCode.svelte create mode 100644 src/lib/components/PageAnchor.svelte create mode 100644 src/lib/components/SearchBar.svelte create mode 100644 src/lib/components/SearchResult.svelte create mode 100644 src/lib/components/SearchResults.svelte create mode 100644 src/lib/components/SegmentedButton.svelte create mode 100644 src/lib/components/Separator.svelte create mode 100644 src/lib/components/Spinner.svelte create mode 100644 src/lib/config.ts create mode 100644 src/lib/core/graph.ts create mode 100644 src/lib/core/href-utils.ts create mode 100644 src/lib/core/navigation.ts create mode 100644 src/lib/core/route-data.ts create mode 100644 src/lib/core/types.ts create mode 100644 src/lib/layout/DocsHeader.svelte create mode 100644 src/lib/layout/DocsSidebar.svelte create mode 100644 src/lib/layout/Header.svelte create mode 100644 src/lib/layout/PageNavigation.svelte create mode 100644 src/lib/layout/SidebarNavList.svelte create mode 100644 src/lib/layout/SidebarPageAnchors.svelte create mode 100644 src/lib/layout/TableOfContents.svelte create mode 100644 src/lib/utils/copy.ts create mode 100644 src/lib/utils/paths.ts create mode 100644 src/lib/utils/rehype-plugins.ts create mode 100644 src/lib/utils/search.ts create mode 100644 src/routes/+error.svelte create mode 100644 src/routes/+layout.svelte create mode 100644 src/routes/+page.svelte create mode 100644 src/routes/+page.ts create mode 100644 src/routes/[...slug]/+page.server.ts create mode 100644 src/routes/[...slug]/+page.svelte create mode 100644 src/routes/[...slug]/+page.ts create mode 100644 src/routes/search-index.json/+server.ts create mode 100644 static/favicon.ico create mode 100644 static/logo.png create mode 100644 static/logo.svg create mode 100644 static/robots.txt create mode 100644 svelte.config.js create mode 100644 tsconfig.json create mode 100644 vite.config.ts diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml new file mode 100644 index 0000000..1114426 --- /dev/null +++ b/.github/workflows/build-docs.yml @@ -0,0 +1,58 @@ +name: Build documentation website + +on: + push: + branches: [main] + pull_request: + branches: [main] + workflow_dispatch: + +permissions: + contents: read + pages: write + id-token: write + +concurrency: + group: pages-${{ github.ref }} + cancel-in-progress: true + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + + - uses: oven-sh/setup-bun@v2 + with: + bun-version: "1.x" + + - name: Install dependencies + run: bun install --frozen-lockfile + + - name: Run lint check + run: bun flint:check + + - name: Build website + env: + SITE_URL_OVERRIDE: ${{ format('https://{0}.github.io/{1}', github.repository_owner, github.event.repository.name) }} + run: bun build:all + + - name: Upload artifact + if: github.ref == 'refs/heads/main' && github.event_name != 'pull_request' + uses: actions/upload-pages-artifact@v3 + with: + path: build + + deploy: + if: github.ref == 'refs/heads/main' && github.event_name != 'pull_request' + needs: build + runs-on: ubuntu-latest + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9aa6fba --- /dev/null +++ b/.gitignore @@ -0,0 +1,24 @@ +node_modules + +# Output +.output +.vercel +.netlify +.wrangler +/.svelte-kit +/build +/generated + +# OS +.DS_Store +Thumbs.db + +# Env +.env +.env.* +!.env.example +!.env.test + +# Vite +vite.config.js.timestamp-* +vite.config.ts.timestamp-* diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..b6f27f1 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +engine-strict=true diff --git a/biome.json b/biome.json new file mode 100644 index 0000000..1150662 --- /dev/null +++ b/biome.json @@ -0,0 +1,44 @@ +{ + "vcs": { + "enabled": true, + "clientKind": "git", + "useIgnoreFile": true + }, + "files": { + "ignoreUnknown": true, + "includes": [ + "**/*.js", + "**/*.cjs", + "**/*.mjs", + "**/*.ts", + "**/*.cts", + "**/*.mts", + "**/*.json", + "**/*.jsonc", + "!node_modules", + "!.claude", + "!.svelte-kit", + "!build", + "!repositories" + ] + }, + "formatter": { + "enabled": true, + "indentStyle": "tab", + "lineWidth": 100 + }, + "linter": { + "enabled": true + }, + "javascript": { + "formatter": { + "quoteStyle": "single", + "semicolons": "always" + } + }, + "json": { + "formatter": { + "indentStyle": "tab" + } + } +} diff --git a/bun.lock b/bun.lock new file mode 100644 index 0000000..e929907 --- /dev/null +++ b/bun.lock @@ -0,0 +1,895 @@ +{ + "lockfileVersion": 1, + "configVersion": 1, + "workspaces": { + "": { + "name": "revanced-documentation", + "dependencies": { + "@sveltejs/adapter-static": "^3.0.10", + "mdsvex": "^0.12.6", + "minisearch": "^7.2.0", + "rehype-autolink-headings": "^7.1.0", + "rehype-sanitize": "^6.0.0", + "rehype-slug": "^6.0.0", + "remark-gfm": "^4.0.1", + "remark-parse": "^11.0.0", + "sass": "^1.97.3", + "sharp": "^0.34.5", + "shiki": "^3.22.0", + "svelte-sitemap": "^2.7.1", + "unified": "^11.0.5", + }, + "devDependencies": { + "@biomejs/biome": "^2.3.14", + "@commitlint/cli": "^20.4.1", + "@commitlint/config-conventional": "^20.4.1", + "@iconify-json/mdi": "^1.2.3", + "@sveltejs/kit": "^2.50.1", + "@sveltejs/vite-plugin-svelte": "^6.2.4", + "fast-glob": "^3.3.3", + "github-slugger": "^2.0.0", + "gray-matter": "^4.0.3", + "lefthook": "^2.1.0", + "mdast-util-to-string": "^4.0.0", + "remark-frontmatter": "^5.0.0", + "svelte": "^5.48.2", + "svelte-check": "^4.3.5", + "typescript": "^5.9.3", + "unist-util-visit": "^5.1.0", + "unplugin-icons": "^23.0.1", + "vite": "^7.3.1", + }, + }, + }, + "packages": { + "@antfu/install-pkg": ["@antfu/install-pkg@1.1.0", "", { "dependencies": { "package-manager-detector": "^1.3.0", "tinyexec": "^1.0.1" } }, "sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ=="], + + "@babel/code-frame": ["@babel/code-frame@7.29.0", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.28.5", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw=="], + + "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.28.5", "", {}, "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q=="], + + "@biomejs/biome": ["@biomejs/biome@2.3.14", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.3.14", "@biomejs/cli-darwin-x64": "2.3.14", "@biomejs/cli-linux-arm64": "2.3.14", "@biomejs/cli-linux-arm64-musl": "2.3.14", "@biomejs/cli-linux-x64": "2.3.14", "@biomejs/cli-linux-x64-musl": "2.3.14", "@biomejs/cli-win32-arm64": "2.3.14", "@biomejs/cli-win32-x64": "2.3.14" }, "bin": { "biome": "bin/biome" } }, "sha512-QMT6QviX0WqXJCaiqVMiBUCr5WRQ1iFSjvOLoTk6auKukJMvnMzWucXpwZB0e8F00/1/BsS9DzcKgWH+CLqVuA=="], + + "@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.3.14", "", { "os": "darwin", "cpu": "arm64" }, "sha512-UJGPpvWJMkLxSRtpCAKfKh41Q4JJXisvxZL8ChN1eNW3m/WlPFJ6EFDCE7YfUb4XS8ZFi3C1dFpxUJ0Ety5n+A=="], + + "@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@2.3.14", "", { "os": "darwin", "cpu": "x64" }, "sha512-PNkLNQG6RLo8lG7QoWe/hhnMxJIt1tEimoXpGQjwS/dkdNiKBLPv4RpeQl8o3s1OKI3ZOR5XPiYtmbGGHAOnLA=="], + + "@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@2.3.14", "", { "os": "linux", "cpu": "arm64" }, "sha512-KT67FKfzIw6DNnUNdYlBg+eU24Go3n75GWK6NwU4+yJmDYFe9i/MjiI+U/iEzKvo0g7G7MZqoyrhIYuND2w8QQ=="], + + "@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@2.3.14", "", { "os": "linux", "cpu": "arm64" }, "sha512-LInRbXhYujtL3sH2TMCH/UBwJZsoGwfQjBrMfl84CD4hL/41C/EU5mldqf1yoFpsI0iPWuU83U+nB2TUUypWeg=="], + + "@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@2.3.14", "", { "os": "linux", "cpu": "x64" }, "sha512-ZsZzQsl9U+wxFrGGS4f6UxREUlgHwmEfu1IrXlgNFrNnd5Th6lIJr8KmSzu/+meSa9f4rzFrbEW9LBBA6ScoMA=="], + + "@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@2.3.14", "", { "os": "linux", "cpu": "x64" }, "sha512-KQU7EkbBBuHPW3/rAcoiVmhlPtDSGOGRPv9js7qJVpYTzjQmVR+C9Rfcz+ti8YCH+zT1J52tuBybtP4IodjxZQ=="], + + "@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@2.3.14", "", { "os": "win32", "cpu": "arm64" }, "sha512-+IKYkj/pUBbnRf1G1+RlyA3LWiDgra1xpS7H2g4BuOzzRbRB+hmlw0yFsLprHhbbt7jUzbzAbAjK/Pn0FDnh1A=="], + + "@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.3.14", "", { "os": "win32", "cpu": "x64" }, "sha512-oizCjdyQ3WJEswpb3Chdngeat56rIdSYK12JI3iI11Mt5T5EXcZ7WLuowzEaFPNJ3zmOQFliMN8QY1Pi+qsfdQ=="], + + "@commitlint/cli": ["@commitlint/cli@20.4.1", "", { "dependencies": { "@commitlint/format": "^20.4.0", "@commitlint/lint": "^20.4.1", "@commitlint/load": "^20.4.0", "@commitlint/read": "^20.4.0", "@commitlint/types": "^20.4.0", "tinyexec": "^1.0.0", "yargs": "^17.0.0" }, "bin": { "commitlint": "./cli.js" } }, "sha512-uuFKKpc7OtQM+6SRqT+a4kV818o1pS+uvv/gsRhyX7g4x495jg+Q7P0+O9VNGyLXBYP0syksS7gMRDJKcekr6A=="], + + "@commitlint/config-conventional": ["@commitlint/config-conventional@20.4.1", "", { "dependencies": { "@commitlint/types": "^20.4.0", "conventional-changelog-conventionalcommits": "^9.1.0" } }, "sha512-0YUvIeBtpi86XriqrR+TCULVFiyYTIOEPjK7tTRMxjcBm1qlzb+kz7IF2WxL6Fq5DaundG8VO37BNgMkMTBwqA=="], + + "@commitlint/config-validator": ["@commitlint/config-validator@20.4.0", "", { "dependencies": { "@commitlint/types": "^20.4.0", "ajv": "^8.11.0" } }, "sha512-zShmKTF+sqyNOfAE0vKcqnpvVpG0YX8F9G/ZIQHI2CoKyK+PSdladXMSns400aZ5/QZs+0fN75B//3Q5CHw++w=="], + + "@commitlint/ensure": ["@commitlint/ensure@20.4.1", "", { "dependencies": { "@commitlint/types": "^20.4.0", "lodash.camelcase": "^4.3.0", "lodash.kebabcase": "^4.1.1", "lodash.snakecase": "^4.1.1", "lodash.startcase": "^4.4.0", "lodash.upperfirst": "^4.3.1" } }, "sha512-WLQqaFx1pBooiVvBrA1YfJNFqZF8wS/YGOtr5RzApDbV9tQ52qT5VkTsY65hFTnXhW8PcDfZLaknfJTmPejmlw=="], + + "@commitlint/execute-rule": ["@commitlint/execute-rule@20.0.0", "", {}, "sha512-xyCoOShoPuPL44gVa+5EdZsBVao/pNzpQhkzq3RdtlFdKZtjWcLlUFQHSWBuhk5utKYykeJPSz2i8ABHQA+ZZw=="], + + "@commitlint/format": ["@commitlint/format@20.4.0", "", { "dependencies": { "@commitlint/types": "^20.4.0", "picocolors": "^1.1.1" } }, "sha512-i3ki3WR0rgolFVX6r64poBHXM1t8qlFel1G1eCBvVgntE3fCJitmzSvH5JD/KVJN/snz6TfaX2CLdON7+s4WVQ=="], + + "@commitlint/is-ignored": ["@commitlint/is-ignored@20.4.1", "", { "dependencies": { "@commitlint/types": "^20.4.0", "semver": "^7.6.0" } }, "sha512-In5EO4JR1lNsAv1oOBBO24V9ND1IqdAJDKZiEpdfjDl2HMasAcT7oA+5BKONv1pRoLG380DGPE2W2RIcUwdgLA=="], + + "@commitlint/lint": ["@commitlint/lint@20.4.1", "", { "dependencies": { "@commitlint/is-ignored": "^20.4.1", "@commitlint/parse": "^20.4.1", "@commitlint/rules": "^20.4.1", "@commitlint/types": "^20.4.0" } }, "sha512-g94LrGl/c6UhuhDQqNqU232aslLEN2vzc7MPfQTHzwzM4GHNnEAwVWWnh0zX8S5YXecuLXDwbCsoGwmpAgPWKA=="], + + "@commitlint/load": ["@commitlint/load@20.4.0", "", { "dependencies": { "@commitlint/config-validator": "^20.4.0", "@commitlint/execute-rule": "^20.0.0", "@commitlint/resolve-extends": "^20.4.0", "@commitlint/types": "^20.4.0", "cosmiconfig": "^9.0.0", "cosmiconfig-typescript-loader": "^6.1.0", "is-plain-obj": "^4.1.0", "lodash.mergewith": "^4.6.2", "picocolors": "^1.1.1" } }, "sha512-Dauup/GfjwffBXRJUdlX/YRKfSVXsXZLnINXKz0VZkXdKDcaEILAi9oflHGbfydonJnJAbXEbF3nXPm9rm3G6A=="], + + "@commitlint/message": ["@commitlint/message@20.4.0", "", {}, "sha512-B5lGtvHgiLAIsK5nLINzVW0bN5hXv+EW35sKhYHE8F7V9Uz1fR4tx3wt7mobA5UNhZKUNgB/+ldVMQE6IHZRyA=="], + + "@commitlint/parse": ["@commitlint/parse@20.4.1", "", { "dependencies": { "@commitlint/types": "^20.4.0", "conventional-changelog-angular": "^8.1.0", "conventional-commits-parser": "^6.2.1" } }, "sha512-XNtZjeRcFuAfUnhYrCY02+mpxwY4OmnvD3ETbVPs25xJFFz1nRo/25nHj+5eM+zTeRFvWFwD4GXWU2JEtoK1/w=="], + + "@commitlint/read": ["@commitlint/read@20.4.0", "", { "dependencies": { "@commitlint/top-level": "^20.4.0", "@commitlint/types": "^20.4.0", "git-raw-commits": "^4.0.0", "minimist": "^1.2.8", "tinyexec": "^1.0.0" } }, "sha512-QfpFn6/I240ySEGv7YWqho4vxqtPpx40FS7kZZDjUJ+eHxu3azfhy7fFb5XzfTqVNp1hNoI3tEmiEPbDB44+cg=="], + + "@commitlint/resolve-extends": ["@commitlint/resolve-extends@20.4.0", "", { "dependencies": { "@commitlint/config-validator": "^20.4.0", "@commitlint/types": "^20.4.0", "global-directory": "^4.0.1", "import-meta-resolve": "^4.0.0", "lodash.mergewith": "^4.6.2", "resolve-from": "^5.0.0" } }, "sha512-ay1KM8q0t+/OnlpqXJ+7gEFQNlUtSU5Gxr8GEwnVf2TPN3+ywc5DzL3JCxmpucqxfHBTFwfRMXxPRRnR5Ki20g=="], + + "@commitlint/rules": ["@commitlint/rules@20.4.1", "", { "dependencies": { "@commitlint/ensure": "^20.4.1", "@commitlint/message": "^20.4.0", "@commitlint/to-lines": "^20.0.0", "@commitlint/types": "^20.4.0" } }, "sha512-WtqypKEPbQEuJwJS4aKs0OoJRBKz1HXPBC9wRtzVNH68FLhPWzxXlF09hpUXM9zdYTpm4vAdoTGkWiBgQ/vL0g=="], + + "@commitlint/to-lines": ["@commitlint/to-lines@20.0.0", "", {}, "sha512-2l9gmwiCRqZNWgV+pX1X7z4yP0b3ex/86UmUFgoRt672Ez6cAM2lOQeHFRUTuE6sPpi8XBCGnd8Kh3bMoyHwJw=="], + + "@commitlint/top-level": ["@commitlint/top-level@20.4.0", "", { "dependencies": { "escalade": "^3.2.0" } }, "sha512-NDzq8Q6jmFaIIBC/GG6n1OQEaHdmaAAYdrZRlMgW6glYWGZ+IeuXmiymDvQNXPc82mVxq2KiE3RVpcs+1OeDeA=="], + + "@commitlint/types": ["@commitlint/types@20.4.0", "", { "dependencies": { "conventional-commits-parser": "^6.2.1", "picocolors": "^1.1.1" } }, "sha512-aO5l99BQJ0X34ft8b0h7QFkQlqxC6e7ZPVmBKz13xM9O8obDaM1Cld4sQlJDXXU/VFuUzQ30mVtHjVz74TuStw=="], + + "@emnapi/runtime": ["@emnapi/runtime@1.8.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg=="], + + "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw=="], + + "@esbuild/android-arm": ["@esbuild/android-arm@0.27.2", "", { "os": "android", "cpu": "arm" }, "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA=="], + + "@esbuild/android-arm64": ["@esbuild/android-arm64@0.27.2", "", { "os": "android", "cpu": "arm64" }, "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA=="], + + "@esbuild/android-x64": ["@esbuild/android-x64@0.27.2", "", { "os": "android", "cpu": "x64" }, "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A=="], + + "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.27.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg=="], + + "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.27.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA=="], + + "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.27.2", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g=="], + + "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.27.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA=="], + + "@esbuild/linux-arm": ["@esbuild/linux-arm@0.27.2", "", { "os": "linux", "cpu": "arm" }, "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw=="], + + "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.27.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw=="], + + "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.27.2", "", { "os": "linux", "cpu": "ia32" }, "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w=="], + + "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.27.2", "", { "os": "linux", "cpu": "none" }, "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg=="], + + "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.27.2", "", { "os": "linux", "cpu": "none" }, "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw=="], + + "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.27.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ=="], + + "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.27.2", "", { "os": "linux", "cpu": "none" }, "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA=="], + + "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.27.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w=="], + + "@esbuild/linux-x64": ["@esbuild/linux-x64@0.27.2", "", { "os": "linux", "cpu": "x64" }, "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA=="], + + "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.27.2", "", { "os": "none", "cpu": "arm64" }, "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw=="], + + "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.27.2", "", { "os": "none", "cpu": "x64" }, "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA=="], + + "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.27.2", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA=="], + + "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.27.2", "", { "os": "openbsd", "cpu": "x64" }, "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg=="], + + "@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.27.2", "", { "os": "none", "cpu": "arm64" }, "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag=="], + + "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.27.2", "", { "os": "sunos", "cpu": "x64" }, "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg=="], + + "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.27.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg=="], + + "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ=="], + + "@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.2", "", { "os": "win32", "cpu": "x64" }, "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ=="], + + "@iconify-json/mdi": ["@iconify-json/mdi@1.2.3", "", { "dependencies": { "@iconify/types": "*" } }, "sha512-O3cLwbDOK7NNDf2ihaQOH5F9JglnulNDFV7WprU2dSoZu3h3cWH//h74uQAB87brHmvFVxIOkuBX2sZSzYhScg=="], + + "@iconify/types": ["@iconify/types@2.0.0", "", {}, "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg=="], + + "@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.0.0", "", {}, "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw=="], + + "@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/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="], + + "@jridgewell/remapping": ["@jridgewell/remapping@2.3.5", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ=="], + + "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="], + + "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="], + + "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="], + + "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], + + "@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="], + + "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="], + + "@oozcitak/dom": ["@oozcitak/dom@1.15.10", "", { "dependencies": { "@oozcitak/infra": "1.0.8", "@oozcitak/url": "1.0.4", "@oozcitak/util": "8.3.8" } }, "sha512-0JT29/LaxVgRcGKvHmSrUTEvZ8BXvZhGl2LASRUgHqDTC1M5g1pLmVv56IYNyt3bG2CUjDkc67wnyZC14pbQrQ=="], + + "@oozcitak/infra": ["@oozcitak/infra@1.0.8", "", { "dependencies": { "@oozcitak/util": "8.3.8" } }, "sha512-JRAUc9VR6IGHOL7OGF+yrvs0LO8SlqGnPAMqyzOuFZPSZSXI7Xf2O9+awQPSMXgIWGtgUf/dA6Hs6X6ySEaWTg=="], + + "@oozcitak/url": ["@oozcitak/url@1.0.4", "", { "dependencies": { "@oozcitak/infra": "1.0.8", "@oozcitak/util": "8.3.8" } }, "sha512-kDcD8y+y3FCSOvnBI6HJgl00viO/nGbQoCINmQ0h98OhnGITrWR3bOGfwYCthgcrV8AnTJz8MzslTQbC3SOAmw=="], + + "@oozcitak/util": ["@oozcitak/util@8.3.8", "", {}, "sha512-T8TbSnGsxo6TDBJx/Sgv/BlVJL3tshxZP7Aq5R1mSnM5OcHY2dQaxLMu2+E8u3gN0MLOzdjurqN4ZRVuzQycOQ=="], + + "@parcel/watcher": ["@parcel/watcher@2.5.6", "", { "dependencies": { "detect-libc": "^2.0.3", "is-glob": "^4.0.3", "node-addon-api": "^7.0.0", "picomatch": "^4.0.3" }, "optionalDependencies": { "@parcel/watcher-android-arm64": "2.5.6", "@parcel/watcher-darwin-arm64": "2.5.6", "@parcel/watcher-darwin-x64": "2.5.6", "@parcel/watcher-freebsd-x64": "2.5.6", "@parcel/watcher-linux-arm-glibc": "2.5.6", "@parcel/watcher-linux-arm-musl": "2.5.6", "@parcel/watcher-linux-arm64-glibc": "2.5.6", "@parcel/watcher-linux-arm64-musl": "2.5.6", "@parcel/watcher-linux-x64-glibc": "2.5.6", "@parcel/watcher-linux-x64-musl": "2.5.6", "@parcel/watcher-win32-arm64": "2.5.6", "@parcel/watcher-win32-ia32": "2.5.6", "@parcel/watcher-win32-x64": "2.5.6" } }, "sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ=="], + + "@parcel/watcher-android-arm64": ["@parcel/watcher-android-arm64@2.5.6", "", { "os": "android", "cpu": "arm64" }, "sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A=="], + + "@parcel/watcher-darwin-arm64": ["@parcel/watcher-darwin-arm64@2.5.6", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA=="], + + "@parcel/watcher-darwin-x64": ["@parcel/watcher-darwin-x64@2.5.6", "", { "os": "darwin", "cpu": "x64" }, "sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg=="], + + "@parcel/watcher-freebsd-x64": ["@parcel/watcher-freebsd-x64@2.5.6", "", { "os": "freebsd", "cpu": "x64" }, "sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng=="], + + "@parcel/watcher-linux-arm-glibc": ["@parcel/watcher-linux-arm-glibc@2.5.6", "", { "os": "linux", "cpu": "arm" }, "sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ=="], + + "@parcel/watcher-linux-arm-musl": ["@parcel/watcher-linux-arm-musl@2.5.6", "", { "os": "linux", "cpu": "arm" }, "sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg=="], + + "@parcel/watcher-linux-arm64-glibc": ["@parcel/watcher-linux-arm64-glibc@2.5.6", "", { "os": "linux", "cpu": "arm64" }, "sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA=="], + + "@parcel/watcher-linux-arm64-musl": ["@parcel/watcher-linux-arm64-musl@2.5.6", "", { "os": "linux", "cpu": "arm64" }, "sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA=="], + + "@parcel/watcher-linux-x64-glibc": ["@parcel/watcher-linux-x64-glibc@2.5.6", "", { "os": "linux", "cpu": "x64" }, "sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ=="], + + "@parcel/watcher-linux-x64-musl": ["@parcel/watcher-linux-x64-musl@2.5.6", "", { "os": "linux", "cpu": "x64" }, "sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg=="], + + "@parcel/watcher-win32-arm64": ["@parcel/watcher-win32-arm64@2.5.6", "", { "os": "win32", "cpu": "arm64" }, "sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q=="], + + "@parcel/watcher-win32-ia32": ["@parcel/watcher-win32-ia32@2.5.6", "", { "os": "win32", "cpu": "ia32" }, "sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g=="], + + "@parcel/watcher-win32-x64": ["@parcel/watcher-win32-x64@2.5.6", "", { "os": "win32", "cpu": "x64" }, "sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw=="], + + "@polka/url": ["@polka/url@1.0.0-next.29", "", {}, "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww=="], + + "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.57.1", "", { "os": "android", "cpu": "arm" }, "sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg=="], + + "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.57.1", "", { "os": "android", "cpu": "arm64" }, "sha512-dQaAddCY9YgkFHZcFNS/606Exo8vcLHwArFZ7vxXq4rigo2bb494/xKMMwRRQW6ug7Js6yXmBZhSBRuBvCCQ3w=="], + + "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.57.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-crNPrwJOrRxagUYeMn/DZwqN88SDmwaJ8Cvi/TN1HnWBU7GwknckyosC2gd0IqYRsHDEnXf328o9/HC6OkPgOg=="], + + "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.57.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-Ji8g8ChVbKrhFtig5QBV7iMaJrGtpHelkB3lsaKzadFBe58gmjfGXAOfI5FV0lYMH8wiqsxKQ1C9B0YTRXVy4w=="], + + "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.57.1", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-R+/WwhsjmwodAcz65guCGFRkMb4gKWTcIeLy60JJQbXrJ97BOXHxnkPFrP+YwFlaS0m+uWJTstrUA9o+UchFug=="], + + "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.57.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-IEQTCHeiTOnAUC3IDQdzRAGj3jOAYNr9kBguI7MQAAZK3caezRrg0GxAb6Hchg4lxdZEI5Oq3iov/w/hnFWY9Q=="], + + "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.57.1", "", { "os": "linux", "cpu": "arm" }, "sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw=="], + + "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.57.1", "", { "os": "linux", "cpu": "arm" }, "sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw=="], + + "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.57.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g=="], + + "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.57.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q=="], + + "@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.57.1", "", { "os": "linux", "cpu": "none" }, "sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA=="], + + "@rollup/rollup-linux-loong64-musl": ["@rollup/rollup-linux-loong64-musl@4.57.1", "", { "os": "linux", "cpu": "none" }, "sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw=="], + + "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.57.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w=="], + + "@rollup/rollup-linux-ppc64-musl": ["@rollup/rollup-linux-ppc64-musl@4.57.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw=="], + + "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.57.1", "", { "os": "linux", "cpu": "none" }, "sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A=="], + + "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.57.1", "", { "os": "linux", "cpu": "none" }, "sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw=="], + + "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.57.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg=="], + + "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.57.1", "", { "os": "linux", "cpu": "x64" }, "sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg=="], + + "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.57.1", "", { "os": "linux", "cpu": "x64" }, "sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw=="], + + "@rollup/rollup-openbsd-x64": ["@rollup/rollup-openbsd-x64@4.57.1", "", { "os": "openbsd", "cpu": "x64" }, "sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw=="], + + "@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.57.1", "", { "os": "none", "cpu": "arm64" }, "sha512-4wYoDpNg6o/oPximyc/NG+mYUejZrCU2q+2w6YZqrAs2UcNUChIZXjtafAiiZSUc7On8v5NyNj34Kzj/Ltk6dQ=="], + + "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.57.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-O54mtsV/6LW3P8qdTcamQmuC990HDfR71lo44oZMZlXU4tzLrbvTii87Ni9opq60ds0YzuAlEr/GNwuNluZyMQ=="], + + "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.57.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-P3dLS+IerxCT/7D2q2FYcRdWRl22dNbrbBEtxdWhXrfIMPP9lQhb5h4Du04mdl5Woq05jVCDPCMF7Ub0NAjIew=="], + + "@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.57.1", "", { "os": "win32", "cpu": "x64" }, "sha512-VMBH2eOOaKGtIJYleXsi2B8CPVADrh+TyNxJ4mWPnKfLB/DBUmzW+5m1xUrcwWoMfSLagIRpjUFeW5CO5hyciQ=="], + + "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.57.1", "", { "os": "win32", "cpu": "x64" }, "sha512-mxRFDdHIWRxg3UfIIAwCm6NzvxG0jDX/wBN6KsQFTvKFqqg9vTrWUE68qEjHt19A5wwx5X5aUi2zuZT7YR0jrA=="], + + "@shikijs/core": ["@shikijs/core@3.22.0", "", { "dependencies": { "@shikijs/types": "3.22.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-iAlTtSDDbJiRpvgL5ugKEATDtHdUVkqgHDm/gbD2ZS9c88mx7G1zSYjjOxp5Qa0eaW0MAQosFRmJSk354PRoQA=="], + + "@shikijs/engine-javascript": ["@shikijs/engine-javascript@3.22.0", "", { "dependencies": { "@shikijs/types": "3.22.0", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.4" } }, "sha512-jdKhfgW9CRtj3Tor0L7+yPwdG3CgP7W+ZEqSsojrMzCjD1e0IxIbwUMDDpYlVBlC08TACg4puwFGkZfLS+56Tw=="], + + "@shikijs/engine-oniguruma": ["@shikijs/engine-oniguruma@3.22.0", "", { "dependencies": { "@shikijs/types": "3.22.0", "@shikijs/vscode-textmate": "^10.0.2" } }, "sha512-DyXsOG0vGtNtl7ygvabHd7Mt5EY8gCNqR9Y7Lpbbd/PbJvgWrqaKzH1JW6H6qFkuUa8aCxoiYVv8/YfFljiQxA=="], + + "@shikijs/langs": ["@shikijs/langs@3.22.0", "", { "dependencies": { "@shikijs/types": "3.22.0" } }, "sha512-x/42TfhWmp6H00T6uwVrdTJGKgNdFbrEdhaDwSR5fd5zhQ1Q46bHq9EO61SCEWJR0HY7z2HNDMaBZp8JRmKiIA=="], + + "@shikijs/themes": ["@shikijs/themes@3.22.0", "", { "dependencies": { "@shikijs/types": "3.22.0" } }, "sha512-o+tlOKqsr6FE4+mYJG08tfCFDS+3CG20HbldXeVoyP+cYSUxDhrFf3GPjE60U55iOkkjbpY2uC3It/eeja35/g=="], + + "@shikijs/types": ["@shikijs/types@3.22.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-491iAekgKDBFE67z70Ok5a8KBMsQ2IJwOWw3us/7ffQkIBCyOQfm/aNwVMBUriP02QshIfgHCBSIYAl3u2eWjg=="], + + "@shikijs/vscode-textmate": ["@shikijs/vscode-textmate@10.0.2", "", {}, "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg=="], + + "@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], + + "@sveltejs/acorn-typescript": ["@sveltejs/acorn-typescript@1.0.8", "", { "peerDependencies": { "acorn": "^8.9.0" } }, "sha512-esgN+54+q0NjB0Y/4BomT9samII7jGwNy/2a3wNZbT2A2RpmXsXwUt24LvLhx6jUq2gVk4cWEvcRO6MFQbOfNA=="], + + "@sveltejs/adapter-static": ["@sveltejs/adapter-static@3.0.10", "", { "peerDependencies": { "@sveltejs/kit": "^2.0.0" } }, "sha512-7D9lYFWJmB7zxZyTE/qxjksvMqzMuYrrsyh1f4AlZqeZeACPRySjbC3aFiY55wb1tWUaKOQG9PVbm74JcN2Iew=="], + + "@sveltejs/kit": ["@sveltejs/kit@2.50.2", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "@sveltejs/acorn-typescript": "^1.0.5", "@types/cookie": "^0.6.0", "acorn": "^8.14.1", "cookie": "^0.6.0", "devalue": "^5.6.2", "esm-env": "^1.2.2", "kleur": "^4.1.5", "magic-string": "^0.30.5", "mrmime": "^2.0.0", "sade": "^1.8.1", "set-cookie-parser": "^3.0.0", "sirv": "^3.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.0.0", "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0 || ^6.0.0-next.0", "svelte": "^4.0.0 || ^5.0.0-next.0", "typescript": "^5.3.3", "vite": "^5.0.3 || ^6.0.0 || ^7.0.0-beta.0" }, "optionalPeers": ["@opentelemetry/api", "typescript"], "bin": { "svelte-kit": "svelte-kit.js" } }, "sha512-875hTUkEbz+MyJIxWbQjfMaekqdmEKUUfR7JyKcpfMRZqcGyrO9Gd+iS1D/Dx8LpE5FEtutWGOtlAh4ReSAiOA=="], + + "@sveltejs/vite-plugin-svelte": ["@sveltejs/vite-plugin-svelte@6.2.4", "", { "dependencies": { "@sveltejs/vite-plugin-svelte-inspector": "^5.0.0", "deepmerge": "^4.3.1", "magic-string": "^0.30.21", "obug": "^2.1.0", "vitefu": "^1.1.1" }, "peerDependencies": { "svelte": "^5.0.0", "vite": "^6.3.0 || ^7.0.0" } }, "sha512-ou/d51QSdTyN26D7h6dSpusAKaZkAiGM55/AKYi+9AGZw7q85hElbjK3kEyzXHhLSnRISHOYzVge6x0jRZ7DXA=="], + + "@sveltejs/vite-plugin-svelte-inspector": ["@sveltejs/vite-plugin-svelte-inspector@5.0.2", "", { "dependencies": { "obug": "^2.1.0" }, "peerDependencies": { "@sveltejs/vite-plugin-svelte": "^6.0.0-next.0", "svelte": "^5.0.0", "vite": "^6.3.0 || ^7.0.0" } }, "sha512-TZzRTcEtZffICSAoZGkPSl6Etsj2torOVrx6Uw0KpXxrec9Gg6jFWQ60Q3+LmNGfZSxHRCZL7vXVZIWmuV50Ig=="], + + "@types/cookie": ["@types/cookie@0.6.0", "", {}, "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA=="], + + "@types/debug": ["@types/debug@4.1.12", "", { "dependencies": { "@types/ms": "*" } }, "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ=="], + + "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], + + "@types/hast": ["@types/hast@3.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ=="], + + "@types/mdast": ["@types/mdast@4.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA=="], + + "@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="], + + "@types/node": ["@types/node@25.2.1", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-CPrnr8voK8vC6eEtyRzvMpgp3VyVRhgclonE7qYi6P9sXwYb59ucfrnmFBTaP0yUi8Gk4yZg/LlTJULGxvTNsg=="], + + "@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="], + + "@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="], + + "acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], + + "ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="], + + "ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], + + "argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="], + + "aria-query": ["aria-query@5.3.2", "", {}, "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw=="], + + "array-ify": ["array-ify@1.0.0", "", {}, "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng=="], + + "axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="], + + "bail": ["bail@2.0.2", "", {}, "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw=="], + + "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], + + "callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="], + + "ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="], + + "character-entities": ["character-entities@2.0.2", "", {}, "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ=="], + + "character-entities-html4": ["character-entities-html4@2.1.0", "", {}, "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA=="], + + "character-entities-legacy": ["character-entities-legacy@3.0.0", "", {}, "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ=="], + + "chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="], + + "cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="], + + "clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="], + + "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], + + "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], + + "comma-separated-tokens": ["comma-separated-tokens@2.0.3", "", {}, "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg=="], + + "compare-func": ["compare-func@2.0.0", "", { "dependencies": { "array-ify": "^1.0.0", "dot-prop": "^5.1.0" } }, "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA=="], + + "confbox": ["confbox@0.2.4", "", {}, "sha512-ysOGlgTFbN2/Y6Cg3Iye8YKulHw+R2fNXHrgSmXISQdMnomY6eNDprVdW9R5xBguEqI954+S6709UyiO7B+6OQ=="], + + "conventional-changelog-angular": ["conventional-changelog-angular@8.1.0", "", { "dependencies": { "compare-func": "^2.0.0" } }, "sha512-GGf2Nipn1RUCAktxuVauVr1e3r8QrLP/B0lEUsFktmGqc3ddbQkhoJZHJctVU829U1c6mTSWftrVOCHaL85Q3w=="], + + "conventional-changelog-conventionalcommits": ["conventional-changelog-conventionalcommits@9.1.0", "", { "dependencies": { "compare-func": "^2.0.0" } }, "sha512-MnbEysR8wWa8dAEvbj5xcBgJKQlX/m0lhS8DsyAAWDHdfs2faDJxTgzRYlRYpXSe7UiKrIIlB4TrBKU9q9DgkA=="], + + "conventional-commits-parser": ["conventional-commits-parser@6.2.1", "", { "dependencies": { "meow": "^13.0.0" }, "bin": { "conventional-commits-parser": "dist/cli/index.js" } }, "sha512-20pyHgnO40rvfI0NGF/xiEoFMkXDtkF8FwHvk5BokoFoCuTQRI8vrNCNFWUOfuolKJMm1tPCHc8GgYEtr1XRNA=="], + + "cookie": ["cookie@0.6.0", "", {}, "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw=="], + + "cosmiconfig": ["cosmiconfig@9.0.0", "", { "dependencies": { "env-paths": "^2.2.1", "import-fresh": "^3.3.0", "js-yaml": "^4.1.0", "parse-json": "^5.2.0" }, "peerDependencies": { "typescript": ">=4.9.5" }, "optionalPeers": ["typescript"] }, "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg=="], + + "cosmiconfig-typescript-loader": ["cosmiconfig-typescript-loader@6.2.0", "", { "dependencies": { "jiti": "^2.6.1" }, "peerDependencies": { "@types/node": "*", "cosmiconfig": ">=9", "typescript": ">=5" } }, "sha512-GEN39v7TgdxgIoNcdkRE3uiAzQt3UXLyHbRHD6YoL048XAeOomyxaP+Hh/+2C6C2wYjxJ2onhJcsQp+L4YEkVQ=="], + + "dargs": ["dargs@8.1.0", "", {}, "sha512-wAV9QHOsNbwnWdNW2FYvE1P56wtgSbM+3SZcdGiWQILwVjACCXDCI3Ai8QlCjMDB8YK5zySiXZYBiwGmNY3lnw=="], + + "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], + + "decode-named-character-reference": ["decode-named-character-reference@1.3.0", "", { "dependencies": { "character-entities": "^2.0.0" } }, "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q=="], + + "deepmerge": ["deepmerge@4.3.1", "", {}, "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A=="], + + "dequal": ["dequal@2.0.3", "", {}, "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="], + + "detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], + + "devalue": ["devalue@5.6.2", "", {}, "sha512-nPRkjWzzDQlsejL1WVifk5rvcFi/y1onBRxjaFMjZeR9mFpqu2gmAZ9xUB9/IEanEP/vBtGeGganC/GO1fmufg=="], + + "devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="], + + "dot-prop": ["dot-prop@5.3.0", "", { "dependencies": { "is-obj": "^2.0.0" } }, "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q=="], + + "emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + + "env-paths": ["env-paths@2.2.1", "", {}, "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A=="], + + "error-ex": ["error-ex@1.3.4", "", { "dependencies": { "is-arrayish": "^0.2.1" } }, "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ=="], + + "esbuild": ["esbuild@0.27.2", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.2", "@esbuild/android-arm": "0.27.2", "@esbuild/android-arm64": "0.27.2", "@esbuild/android-x64": "0.27.2", "@esbuild/darwin-arm64": "0.27.2", "@esbuild/darwin-x64": "0.27.2", "@esbuild/freebsd-arm64": "0.27.2", "@esbuild/freebsd-x64": "0.27.2", "@esbuild/linux-arm": "0.27.2", "@esbuild/linux-arm64": "0.27.2", "@esbuild/linux-ia32": "0.27.2", "@esbuild/linux-loong64": "0.27.2", "@esbuild/linux-mips64el": "0.27.2", "@esbuild/linux-ppc64": "0.27.2", "@esbuild/linux-riscv64": "0.27.2", "@esbuild/linux-s390x": "0.27.2", "@esbuild/linux-x64": "0.27.2", "@esbuild/netbsd-arm64": "0.27.2", "@esbuild/netbsd-x64": "0.27.2", "@esbuild/openbsd-arm64": "0.27.2", "@esbuild/openbsd-x64": "0.27.2", "@esbuild/openharmony-arm64": "0.27.2", "@esbuild/sunos-x64": "0.27.2", "@esbuild/win32-arm64": "0.27.2", "@esbuild/win32-ia32": "0.27.2", "@esbuild/win32-x64": "0.27.2" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw=="], + + "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], + + "escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="], + + "esm-env": ["esm-env@1.2.2", "", {}, "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA=="], + + "esprima": ["esprima@4.0.1", "", { "bin": { "esparse": "./bin/esparse.js", "esvalidate": "./bin/esvalidate.js" } }, "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="], + + "esrap": ["esrap@2.2.2", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" } }, "sha512-zA6497ha+qKvoWIK+WM9NAh5ni17sKZKhbS5B3PoYbBvaYHZWoS33zmFybmyqpn07RLUxSmn+RCls2/XF+d0oQ=="], + + "exsolve": ["exsolve@1.0.8", "", {}, "sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA=="], + + "extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="], + + "extend-shallow": ["extend-shallow@2.0.1", "", { "dependencies": { "is-extendable": "^0.1.0" } }, "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug=="], + + "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], + + "fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="], + + "fast-uri": ["fast-uri@3.1.0", "", {}, "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA=="], + + "fastq": ["fastq@1.20.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw=="], + + "fault": ["fault@2.0.1", "", { "dependencies": { "format": "^0.2.0" } }, "sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ=="], + + "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], + + "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], + + "format": ["format@0.2.2", "", {}, "sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww=="], + + "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], + + "get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="], + + "git-raw-commits": ["git-raw-commits@4.0.0", "", { "dependencies": { "dargs": "^8.0.0", "meow": "^12.0.1", "split2": "^4.0.0" }, "bin": { "git-raw-commits": "cli.mjs" } }, "sha512-ICsMM1Wk8xSGMowkOmPrzo2Fgmfo4bMHLNX6ytHjajRJUqvHOw/TFapQ+QG75c3X/tTDDhOSRPGC52dDbNM8FQ=="], + + "github-slugger": ["github-slugger@2.0.0", "", {}, "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw=="], + + "glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], + + "global-directory": ["global-directory@4.0.1", "", { "dependencies": { "ini": "4.1.1" } }, "sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q=="], + + "gray-matter": ["gray-matter@4.0.3", "", { "dependencies": { "js-yaml": "^3.13.1", "kind-of": "^6.0.2", "section-matter": "^1.0.0", "strip-bom-string": "^1.0.0" } }, "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q=="], + + "hast-util-heading-rank": ["hast-util-heading-rank@3.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-EJKb8oMUXVHcWZTDepnr+WNbfnXKFNf9duMesmr4S8SXTJBJ9M4Yok08pu9vxdJwdlGRhVumk9mEhkEvKGifwA=="], + + "hast-util-is-element": ["hast-util-is-element@3.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g=="], + + "hast-util-sanitize": ["hast-util-sanitize@5.0.2", "", { "dependencies": { "@types/hast": "^3.0.0", "@ungap/structured-clone": "^1.0.0", "unist-util-position": "^5.0.0" } }, "sha512-3yTWghByc50aGS7JlGhk61SPenfE/p1oaFeNwkOOyrscaOkMGrcW9+Cy/QAIOBpZxP1yqDIzFMR0+Np0i0+usg=="], + + "hast-util-to-html": ["hast-util-to-html@9.0.5", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "ccount": "^2.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-whitespace": "^3.0.0", "html-void-elements": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "stringify-entities": "^4.0.0", "zwitch": "^2.0.4" } }, "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw=="], + + "hast-util-to-string": ["hast-util-to-string@3.0.1", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-XelQVTDWvqcl3axRfI0xSeoVKzyIFPwsAGSLIsKdJKQMXDYJS4WYrBNF/8J7RdhIcFI2BOHgAifggsvsxp/3+A=="], + + "hast-util-whitespace": ["hast-util-whitespace@3.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw=="], + + "html-void-elements": ["html-void-elements@3.0.0", "", {}, "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg=="], + + "immutable": ["immutable@5.1.4", "", {}, "sha512-p6u1bG3YSnINT5RQmx/yRZBpenIl30kVxkTLDyHLIMk0gict704Q9n+thfDI7lTRm9vXdDYutVzXhzcThxTnXA=="], + + "import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="], + + "import-meta-resolve": ["import-meta-resolve@4.2.0", "", {}, "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg=="], + + "ini": ["ini@4.1.1", "", {}, "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g=="], + + "is-arrayish": ["is-arrayish@0.2.1", "", {}, "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="], + + "is-extendable": ["is-extendable@0.1.1", "", {}, "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw=="], + + "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], + + "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], + + "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], + + "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], + + "is-obj": ["is-obj@2.0.0", "", {}, "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w=="], + + "is-plain-obj": ["is-plain-obj@4.1.0", "", {}, "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg=="], + + "is-reference": ["is-reference@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.6" } }, "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw=="], + + "jiti": ["jiti@2.6.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="], + + "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], + + "js-yaml": ["js-yaml@3.14.1", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g=="], + + "json-parse-even-better-errors": ["json-parse-even-better-errors@2.3.1", "", {}, "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="], + + "json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], + + "kind-of": ["kind-of@6.0.3", "", {}, "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw=="], + + "kleur": ["kleur@4.1.5", "", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="], + + "lefthook": ["lefthook@2.1.0", "", { "optionalDependencies": { "lefthook-darwin-arm64": "2.1.0", "lefthook-darwin-x64": "2.1.0", "lefthook-freebsd-arm64": "2.1.0", "lefthook-freebsd-x64": "2.1.0", "lefthook-linux-arm64": "2.1.0", "lefthook-linux-x64": "2.1.0", "lefthook-openbsd-arm64": "2.1.0", "lefthook-openbsd-x64": "2.1.0", "lefthook-windows-arm64": "2.1.0", "lefthook-windows-x64": "2.1.0" }, "bin": { "lefthook": "bin/index.js" } }, "sha512-+vS+yywGQW6CN1J1hbGkez//6ixGHIQqfxDN/d3JDm531w9GfGt2lAWTDfZTw/CEl80XsN0raFcnEraR3ldw9g=="], + + "lefthook-darwin-arm64": ["lefthook-darwin-arm64@2.1.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-u2hjHLQXWSFfzO7ln2n/uEydSzfC9sc5cDC7tvKSuOdhvBwaJ0AQ7ZeuqqCQ4YfVIJfYOom1SVE9CBd10FVyig=="], + + "lefthook-darwin-x64": ["lefthook-darwin-x64@2.1.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-zz5rcyrtOZpxon7uE+c0KC/o2ypJeLZql5CL0Y9oaTuECbmhfokm8glsGnyWstW/++PuMpZYYr/qsCJA5elxkQ=="], + + "lefthook-freebsd-arm64": ["lefthook-freebsd-arm64@2.1.0", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-+mXNCNuFHNGYLrDqYWDeHH7kWCLCJFPpspx5PAAm+PD37PRMZJrTqDbaNK9qCghC1tdmT4/Lvilf/ewXHPlaKw=="], + + "lefthook-freebsd-x64": ["lefthook-freebsd-x64@2.1.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-+AU2HD7szuDsUdHue/E3OnF84B2ae/h7CGKpuIUHJntgoJ4kxf89oDvq2/xl8kDCn9cT76UUjgeZUgFYLRj+6Q=="], + + "lefthook-linux-arm64": ["lefthook-linux-arm64@2.1.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-KM70eV1tsEib1/tk+3TFxIdH84EaYlIg5KTQWAg+LB1N23nTQ7lL4Dnh1je6f6KW4tf21nmoMUqsh0xvMkQk8Q=="], + + "lefthook-linux-x64": ["lefthook-linux-x64@2.1.0", "", { "os": "linux", "cpu": "x64" }, "sha512-6Bxmv+l7LiYq9W0IE6v2lmlRtBp6pisnlzhcouMGvH3rDwEGw11NAyRJZA3IPGEMAkIuhnlnVTUwAUzKomfJLg=="], + + "lefthook-openbsd-arm64": ["lefthook-openbsd-arm64@2.1.0", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-ppJNK0bBSPLC8gqksRw5zI/0uLeMA5cK+hmZ4ofcuGNmdrN1dfl2Tx84fdeef0NcQY0ii9Y3j3icIKngIoid/g=="], + + "lefthook-openbsd-x64": ["lefthook-openbsd-x64@2.1.0", "", { "os": "openbsd", "cpu": "x64" }, "sha512-8k9lQsMYqQGu4spaQ8RNSOJidxIcOyfaoF2FPZhthtBfRV3cgVFGrsQ0hbIi5pvQRGUlCqYuCN79qauXHmnL3Q=="], + + "lefthook-windows-arm64": ["lefthook-windows-arm64@2.1.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-0WN+grrxt9zP9NGRcztoPXcz25tteem91rfLWgQFab+50csJ47zldlsB7/eOS/eHG5mUg5g5NPR4XefnXtjOcQ=="], + + "lefthook-windows-x64": ["lefthook-windows-x64@2.1.0", "", { "os": "win32", "cpu": "x64" }, "sha512-XbO/5nAZQLpUn0tPpgCYfFBFJHnymSglQ73jD6wymNrR1j8I5EcXGlP6YcLhnZ83yzsdLC+gup+N6IqUeiyRdw=="], + + "lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="], + + "local-pkg": ["local-pkg@1.1.2", "", { "dependencies": { "mlly": "^1.7.4", "pkg-types": "^2.3.0", "quansync": "^0.2.11" } }, "sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A=="], + + "locate-character": ["locate-character@3.0.0", "", {}, "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA=="], + + "lodash.camelcase": ["lodash.camelcase@4.3.0", "", {}, "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA=="], + + "lodash.kebabcase": ["lodash.kebabcase@4.1.1", "", {}, "sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g=="], + + "lodash.mergewith": ["lodash.mergewith@4.6.2", "", {}, "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ=="], + + "lodash.snakecase": ["lodash.snakecase@4.1.1", "", {}, "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw=="], + + "lodash.startcase": ["lodash.startcase@4.4.0", "", {}, "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg=="], + + "lodash.upperfirst": ["lodash.upperfirst@4.3.1", "", {}, "sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg=="], + + "longest-streak": ["longest-streak@3.1.0", "", {}, "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g=="], + + "magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], + + "markdown-table": ["markdown-table@3.0.4", "", {}, "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw=="], + + "mdast-util-find-and-replace": ["mdast-util-find-and-replace@3.0.2", "", { "dependencies": { "@types/mdast": "^4.0.0", "escape-string-regexp": "^5.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg=="], + + "mdast-util-from-markdown": ["mdast-util-from-markdown@2.0.2", "", { "dependencies": { "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "mdast-util-to-string": "^4.0.0", "micromark": "^4.0.0", "micromark-util-decode-numeric-character-reference": "^2.0.0", "micromark-util-decode-string": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA=="], + + "mdast-util-frontmatter": ["mdast-util-frontmatter@2.0.1", "", { "dependencies": { "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "escape-string-regexp": "^5.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0", "micromark-extension-frontmatter": "^2.0.0" } }, "sha512-LRqI9+wdgC25P0URIJY9vwocIzCcksduHQ9OF2joxQoyTNVduwLAFUzjoopuRJbJAReaKrNQKAZKL3uCMugWJA=="], + + "mdast-util-gfm": ["mdast-util-gfm@3.1.0", "", { "dependencies": { "mdast-util-from-markdown": "^2.0.0", "mdast-util-gfm-autolink-literal": "^2.0.0", "mdast-util-gfm-footnote": "^2.0.0", "mdast-util-gfm-strikethrough": "^2.0.0", "mdast-util-gfm-table": "^2.0.0", "mdast-util-gfm-task-list-item": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ=="], + + "mdast-util-gfm-autolink-literal": ["mdast-util-gfm-autolink-literal@2.0.1", "", { "dependencies": { "@types/mdast": "^4.0.0", "ccount": "^2.0.0", "devlop": "^1.0.0", "mdast-util-find-and-replace": "^3.0.0", "micromark-util-character": "^2.0.0" } }, "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ=="], + + "mdast-util-gfm-footnote": ["mdast-util-gfm-footnote@2.1.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "devlop": "^1.1.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0" } }, "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ=="], + + "mdast-util-gfm-strikethrough": ["mdast-util-gfm-strikethrough@2.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg=="], + + "mdast-util-gfm-table": ["mdast-util-gfm-table@2.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "markdown-table": "^3.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg=="], + + "mdast-util-gfm-task-list-item": ["mdast-util-gfm-task-list-item@2.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ=="], + + "mdast-util-phrasing": ["mdast-util-phrasing@4.1.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "unist-util-is": "^6.0.0" } }, "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w=="], + + "mdast-util-to-hast": ["mdast-util-to-hast@13.2.1", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "@ungap/structured-clone": "^1.0.0", "devlop": "^1.0.0", "micromark-util-sanitize-uri": "^2.0.0", "trim-lines": "^3.0.0", "unist-util-position": "^5.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" } }, "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA=="], + + "mdast-util-to-markdown": ["mdast-util-to-markdown@2.1.2", "", { "dependencies": { "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "longest-streak": "^3.0.0", "mdast-util-phrasing": "^4.0.0", "mdast-util-to-string": "^4.0.0", "micromark-util-classify-character": "^2.0.0", "micromark-util-decode-string": "^2.0.0", "unist-util-visit": "^5.0.0", "zwitch": "^2.0.0" } }, "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA=="], + + "mdast-util-to-string": ["mdast-util-to-string@4.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0" } }, "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg=="], + + "mdsvex": ["mdsvex@0.12.6", "", { "dependencies": { "@types/mdast": "^4.0.4", "@types/unist": "^2.0.3", "prism-svelte": "^0.4.7", "prismjs": "^1.17.1", "unist-util-visit": "^2.0.1", "vfile-message": "^2.0.4" }, "peerDependencies": { "svelte": "^3.56.0 || ^4.0.0 || ^5.0.0-next.120" } }, "sha512-pupx2gzWh3hDtm/iDW4WuCpljmyHbHi34r7ktOqpPGvyiM4MyfNgdJ3qMizXdgCErmvYC9Nn/qyjePy+4ss9Wg=="], + + "meow": ["meow@12.1.1", "", {}, "sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw=="], + + "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="], + + "micromark": ["micromark@4.0.2", "", { "dependencies": { "@types/debug": "^4.0.0", "debug": "^4.0.0", "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "micromark-core-commonmark": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-combine-extensions": "^2.0.0", "micromark-util-decode-numeric-character-reference": "^2.0.0", "micromark-util-encode": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-resolve-all": "^2.0.0", "micromark-util-sanitize-uri": "^2.0.0", "micromark-util-subtokenize": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA=="], + + "micromark-core-commonmark": ["micromark-core-commonmark@2.0.3", "", { "dependencies": { "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "micromark-factory-destination": "^2.0.0", "micromark-factory-label": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-factory-title": "^2.0.0", "micromark-factory-whitespace": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-classify-character": "^2.0.0", "micromark-util-html-tag-name": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-resolve-all": "^2.0.0", "micromark-util-subtokenize": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg=="], + + "micromark-extension-frontmatter": ["micromark-extension-frontmatter@2.0.0", "", { "dependencies": { "fault": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-C4AkuM3dA58cgZha7zVnuVxBhDsbttIMiytjgsM2XbHAB2faRVaHRle40558FBN+DJcrLNCoqG5mlrpdU4cRtg=="], + + "micromark-extension-gfm": ["micromark-extension-gfm@3.0.0", "", { "dependencies": { "micromark-extension-gfm-autolink-literal": "^2.0.0", "micromark-extension-gfm-footnote": "^2.0.0", "micromark-extension-gfm-strikethrough": "^2.0.0", "micromark-extension-gfm-table": "^2.0.0", "micromark-extension-gfm-tagfilter": "^2.0.0", "micromark-extension-gfm-task-list-item": "^2.0.0", "micromark-util-combine-extensions": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w=="], + + "micromark-extension-gfm-autolink-literal": ["micromark-extension-gfm-autolink-literal@2.1.0", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-sanitize-uri": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw=="], + + "micromark-extension-gfm-footnote": ["micromark-extension-gfm-footnote@2.1.0", "", { "dependencies": { "devlop": "^1.0.0", "micromark-core-commonmark": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-sanitize-uri": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw=="], + + "micromark-extension-gfm-strikethrough": ["micromark-extension-gfm-strikethrough@2.1.0", "", { "dependencies": { "devlop": "^1.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-classify-character": "^2.0.0", "micromark-util-resolve-all": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw=="], + + "micromark-extension-gfm-table": ["micromark-extension-gfm-table@2.1.1", "", { "dependencies": { "devlop": "^1.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg=="], + + "micromark-extension-gfm-tagfilter": ["micromark-extension-gfm-tagfilter@2.0.0", "", { "dependencies": { "micromark-util-types": "^2.0.0" } }, "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg=="], + + "micromark-extension-gfm-task-list-item": ["micromark-extension-gfm-task-list-item@2.1.0", "", { "dependencies": { "devlop": "^1.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw=="], + + "micromark-factory-destination": ["micromark-factory-destination@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA=="], + + "micromark-factory-label": ["micromark-factory-label@2.0.1", "", { "dependencies": { "devlop": "^1.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg=="], + + "micromark-factory-space": ["micromark-factory-space@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg=="], + + "micromark-factory-title": ["micromark-factory-title@2.0.1", "", { "dependencies": { "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw=="], + + "micromark-factory-whitespace": ["micromark-factory-whitespace@2.0.1", "", { "dependencies": { "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ=="], + + "micromark-util-character": ["micromark-util-character@2.1.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q=="], + + "micromark-util-chunked": ["micromark-util-chunked@2.0.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0" } }, "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA=="], + + "micromark-util-classify-character": ["micromark-util-classify-character@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q=="], + + "micromark-util-combine-extensions": ["micromark-util-combine-extensions@2.0.1", "", { "dependencies": { "micromark-util-chunked": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg=="], + + "micromark-util-decode-numeric-character-reference": ["micromark-util-decode-numeric-character-reference@2.0.2", "", { "dependencies": { "micromark-util-symbol": "^2.0.0" } }, "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw=="], + + "micromark-util-decode-string": ["micromark-util-decode-string@2.0.1", "", { "dependencies": { "decode-named-character-reference": "^1.0.0", "micromark-util-character": "^2.0.0", "micromark-util-decode-numeric-character-reference": "^2.0.0", "micromark-util-symbol": "^2.0.0" } }, "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ=="], + + "micromark-util-encode": ["micromark-util-encode@2.0.1", "", {}, "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw=="], + + "micromark-util-html-tag-name": ["micromark-util-html-tag-name@2.0.1", "", {}, "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA=="], + + "micromark-util-normalize-identifier": ["micromark-util-normalize-identifier@2.0.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0" } }, "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q=="], + + "micromark-util-resolve-all": ["micromark-util-resolve-all@2.0.1", "", { "dependencies": { "micromark-util-types": "^2.0.0" } }, "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg=="], + + "micromark-util-sanitize-uri": ["micromark-util-sanitize-uri@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-encode": "^2.0.0", "micromark-util-symbol": "^2.0.0" } }, "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ=="], + + "micromark-util-subtokenize": ["micromark-util-subtokenize@2.1.0", "", { "dependencies": { "devlop": "^1.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA=="], + + "micromark-util-symbol": ["micromark-util-symbol@2.0.1", "", {}, "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q=="], + + "micromark-util-types": ["micromark-util-types@2.0.2", "", {}, "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA=="], + + "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], + + "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="], + + "minisearch": ["minisearch@7.2.0", "", {}, "sha512-dqT2XBYUOZOiC5t2HRnwADjhNS2cecp9u+TJRiJ1Qp/f5qjkeT5APcGPjHw+bz89Ms8Jp+cG4AlE+QZ/QnDglg=="], + + "mlly": ["mlly@1.8.0", "", { "dependencies": { "acorn": "^8.15.0", "pathe": "^2.0.3", "pkg-types": "^1.3.1", "ufo": "^1.6.1" } }, "sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g=="], + + "mri": ["mri@1.2.0", "", {}, "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA=="], + + "mrmime": ["mrmime@2.0.1", "", {}, "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ=="], + + "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + + "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], + + "node-addon-api": ["node-addon-api@7.1.1", "", {}, "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ=="], + + "obug": ["obug@2.1.1", "", {}, "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ=="], + + "oniguruma-parser": ["oniguruma-parser@0.12.1", "", {}, "sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w=="], + + "oniguruma-to-es": ["oniguruma-to-es@4.3.4", "", { "dependencies": { "oniguruma-parser": "^0.12.1", "regex": "^6.0.1", "regex-recursion": "^6.0.2" } }, "sha512-3VhUGN3w2eYxnTzHn+ikMI+fp/96KoRSVK9/kMTcFqj1NRDh2IhQCKvYxDnWePKRXY/AqH+Fuiyb7VHSzBjHfA=="], + + "package-manager-detector": ["package-manager-detector@1.6.0", "", {}, "sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA=="], + + "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="], + + "parse-json": ["parse-json@5.2.0", "", { "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", "json-parse-even-better-errors": "^2.3.0", "lines-and-columns": "^1.1.6" } }, "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg=="], + + "pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], + + "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], + + "picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], + + "pkg-types": ["pkg-types@2.3.0", "", { "dependencies": { "confbox": "^0.2.2", "exsolve": "^1.0.7", "pathe": "^2.0.3" } }, "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig=="], + + "postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="], + + "prism-svelte": ["prism-svelte@0.4.7", "", {}, "sha512-yABh19CYbM24V7aS7TuPYRNMqthxwbvx6FF/Rw920YbyBWO3tnyPIqRMgHuSVsLmuHkkBS1Akyof463FVdkeDQ=="], + + "prismjs": ["prismjs@1.30.0", "", {}, "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw=="], + + "property-information": ["property-information@7.1.0", "", {}, "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ=="], + + "quansync": ["quansync@0.2.11", "", {}, "sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA=="], + + "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], + + "readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="], + + "regex": ["regex@6.1.0", "", { "dependencies": { "regex-utilities": "^2.3.0" } }, "sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg=="], + + "regex-recursion": ["regex-recursion@6.0.2", "", { "dependencies": { "regex-utilities": "^2.3.0" } }, "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg=="], + + "regex-utilities": ["regex-utilities@2.3.0", "", {}, "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng=="], + + "rehype-autolink-headings": ["rehype-autolink-headings@7.1.0", "", { "dependencies": { "@types/hast": "^3.0.0", "@ungap/structured-clone": "^1.0.0", "hast-util-heading-rank": "^3.0.0", "hast-util-is-element": "^3.0.0", "unified": "^11.0.0", "unist-util-visit": "^5.0.0" } }, "sha512-rItO/pSdvnvsP4QRB1pmPiNHUskikqtPojZKJPPPAVx9Hj8i8TwMBhofrrAYRhYOOBZH9tgmG5lPqDLuIWPWmw=="], + + "rehype-sanitize": ["rehype-sanitize@6.0.0", "", { "dependencies": { "@types/hast": "^3.0.0", "hast-util-sanitize": "^5.0.0" } }, "sha512-CsnhKNsyI8Tub6L4sm5ZFsme4puGfc6pYylvXo1AeqaGbjOYyzNv3qZPwvs0oMJ39eryyeOdmxwUIo94IpEhqg=="], + + "rehype-slug": ["rehype-slug@6.0.0", "", { "dependencies": { "@types/hast": "^3.0.0", "github-slugger": "^2.0.0", "hast-util-heading-rank": "^3.0.0", "hast-util-to-string": "^3.0.0", "unist-util-visit": "^5.0.0" } }, "sha512-lWyvf/jwu+oS5+hL5eClVd3hNdmwM1kAC0BUvEGD19pajQMIzcNUd/k9GsfQ+FfECvX+JE+e9/btsKH0EjJT6A=="], + + "remark-frontmatter": ["remark-frontmatter@5.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-frontmatter": "^2.0.0", "micromark-extension-frontmatter": "^2.0.0", "unified": "^11.0.0" } }, "sha512-XTFYvNASMe5iPN0719nPrdItC9aU0ssC4v14mH1BCi1u0n1gAocqcujWUrByftZTbLhRtiKRyjYTSIOcr69UVQ=="], + + "remark-gfm": ["remark-gfm@4.0.1", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-gfm": "^3.0.0", "micromark-extension-gfm": "^3.0.0", "remark-parse": "^11.0.0", "remark-stringify": "^11.0.0", "unified": "^11.0.0" } }, "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg=="], + + "remark-parse": ["remark-parse@11.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-from-markdown": "^2.0.0", "micromark-util-types": "^2.0.0", "unified": "^11.0.0" } }, "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA=="], + + "remark-stringify": ["remark-stringify@11.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-to-markdown": "^2.0.0", "unified": "^11.0.0" } }, "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw=="], + + "require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="], + + "require-from-string": ["require-from-string@2.0.2", "", {}, "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="], + + "resolve-from": ["resolve-from@5.0.0", "", {}, "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw=="], + + "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="], + + "rollup": ["rollup@4.57.1", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.57.1", "@rollup/rollup-android-arm64": "4.57.1", "@rollup/rollup-darwin-arm64": "4.57.1", "@rollup/rollup-darwin-x64": "4.57.1", "@rollup/rollup-freebsd-arm64": "4.57.1", "@rollup/rollup-freebsd-x64": "4.57.1", "@rollup/rollup-linux-arm-gnueabihf": "4.57.1", "@rollup/rollup-linux-arm-musleabihf": "4.57.1", "@rollup/rollup-linux-arm64-gnu": "4.57.1", "@rollup/rollup-linux-arm64-musl": "4.57.1", "@rollup/rollup-linux-loong64-gnu": "4.57.1", "@rollup/rollup-linux-loong64-musl": "4.57.1", "@rollup/rollup-linux-ppc64-gnu": "4.57.1", "@rollup/rollup-linux-ppc64-musl": "4.57.1", "@rollup/rollup-linux-riscv64-gnu": "4.57.1", "@rollup/rollup-linux-riscv64-musl": "4.57.1", "@rollup/rollup-linux-s390x-gnu": "4.57.1", "@rollup/rollup-linux-x64-gnu": "4.57.1", "@rollup/rollup-linux-x64-musl": "4.57.1", "@rollup/rollup-openbsd-x64": "4.57.1", "@rollup/rollup-openharmony-arm64": "4.57.1", "@rollup/rollup-win32-arm64-msvc": "4.57.1", "@rollup/rollup-win32-ia32-msvc": "4.57.1", "@rollup/rollup-win32-x64-gnu": "4.57.1", "@rollup/rollup-win32-x64-msvc": "4.57.1", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A=="], + + "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], + + "sade": ["sade@1.8.1", "", { "dependencies": { "mri": "^1.1.0" } }, "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A=="], + + "sass": ["sass@1.97.3", "", { "dependencies": { "chokidar": "^4.0.0", "immutable": "^5.0.2", "source-map-js": ">=0.6.2 <2.0.0" }, "optionalDependencies": { "@parcel/watcher": "^2.4.1" }, "bin": { "sass": "sass.js" } }, "sha512-fDz1zJpd5GycprAbu4Q2PV/RprsRtKC/0z82z0JLgdytmcq0+ujJbJ/09bPGDxCLkKY3Np5cRAOcWiVkLXJURg=="], + + "section-matter": ["section-matter@1.0.0", "", { "dependencies": { "extend-shallow": "^2.0.1", "kind-of": "^6.0.0" } }, "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA=="], + + "semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], + + "set-cookie-parser": ["set-cookie-parser@3.0.1", "", {}, "sha512-n7Z7dXZhJbwuAHhNzkTti6Aw9QDDjZtm3JTpTGATIdNzdQz5GuFs22w90BcvF4INfnrL5xrX3oGsuqO5Dx3A1Q=="], + + "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@3.22.0", "", { "dependencies": { "@shikijs/core": "3.22.0", "@shikijs/engine-javascript": "3.22.0", "@shikijs/engine-oniguruma": "3.22.0", "@shikijs/langs": "3.22.0", "@shikijs/themes": "3.22.0", "@shikijs/types": "3.22.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-LBnhsoYEe0Eou4e1VgJACes+O6S6QC0w71fCSp5Oya79inkwkm15gQ1UF6VtQ8j/taMDh79hAB49WUk8ALQW3g=="], + + "sirv": ["sirv@3.0.2", "", { "dependencies": { "@polka/url": "^1.0.0-next.24", "mrmime": "^2.0.0", "totalist": "^3.0.0" } }, "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g=="], + + "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], + + "space-separated-tokens": ["space-separated-tokens@2.0.2", "", {}, "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q=="], + + "split2": ["split2@4.2.0", "", {}, "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg=="], + + "sprintf-js": ["sprintf-js@1.0.3", "", {}, "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="], + + "string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + + "stringify-entities": ["stringify-entities@4.0.4", "", { "dependencies": { "character-entities-html4": "^2.0.0", "character-entities-legacy": "^3.0.0" } }, "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg=="], + + "strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "strip-bom-string": ["strip-bom-string@1.0.0", "", {}, "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g=="], + + "svelte": ["svelte@5.49.1", "", { "dependencies": { "@jridgewell/remapping": "^2.3.4", "@jridgewell/sourcemap-codec": "^1.5.0", "@sveltejs/acorn-typescript": "^1.0.5", "@types/estree": "^1.0.5", "acorn": "^8.12.1", "aria-query": "^5.3.1", "axobject-query": "^4.1.0", "clsx": "^2.1.1", "devalue": "^5.6.2", "esm-env": "^1.2.1", "esrap": "^2.2.2", "is-reference": "^3.0.3", "locate-character": "^3.0.0", "magic-string": "^0.30.11", "zimmerframe": "^1.1.2" } }, "sha512-jj95WnbKbXsXXngYj28a4zx8jeZx50CN/J4r0CEeax2pbfdsETv/J1K8V9Hbu3DCXnpHz5qAikICuxEooi7eNQ=="], + + "svelte-check": ["svelte-check@4.3.6", "", { "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", "chokidar": "^4.0.1", "fdir": "^6.2.0", "picocolors": "^1.0.0", "sade": "^1.7.4" }, "peerDependencies": { "svelte": "^4.0.0 || ^5.0.0-next.0", "typescript": ">=5.0.0" }, "bin": { "svelte-check": "bin/svelte-check" } }, "sha512-uBkz96ElE3G4pt9E1Tw0xvBfIUQkeH794kDQZdAUk795UVMr+NJZpuFSS62vcmO/DuSalK83LyOwhgWq8YGU1Q=="], + + "svelte-sitemap": ["svelte-sitemap@2.7.1", "", { "dependencies": { "fast-glob": "^3.3.3", "minimist": "^1.2.8", "xmlbuilder2": "^3.1.1" }, "bin": { "svelte-sitemap": "index.js" } }, "sha512-9b6GAoaBZde3CCDvmfoDvRWLPAXeawg8MlcXyMmbf8Iu1HEOvVockagu+PiOhaKmyJE3Q9tnIZLaXlMdkfTxHA=="], + + "tinyexec": ["tinyexec@1.0.2", "", {}, "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg=="], + + "tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="], + + "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], + + "totalist": ["totalist@3.0.1", "", {}, "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ=="], + + "trim-lines": ["trim-lines@3.0.1", "", {}, "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg=="], + + "trough": ["trough@2.2.0", "", {}, "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw=="], + + "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + + "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], + + "ufo": ["ufo@1.6.3", "", {}, "sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q=="], + + "undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], + + "unified": ["unified@11.0.5", "", { "dependencies": { "@types/unist": "^3.0.0", "bail": "^2.0.0", "devlop": "^1.0.0", "extend": "^3.0.0", "is-plain-obj": "^4.0.0", "trough": "^2.0.0", "vfile": "^6.0.0" } }, "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA=="], + + "unist-util-is": ["unist-util-is@6.0.1", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g=="], + + "unist-util-position": ["unist-util-position@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA=="], + + "unist-util-stringify-position": ["unist-util-stringify-position@2.0.3", "", { "dependencies": { "@types/unist": "^2.0.2" } }, "sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g=="], + + "unist-util-visit": ["unist-util-visit@5.1.0", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg=="], + + "unist-util-visit-parents": ["unist-util-visit-parents@6.0.2", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0" } }, "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ=="], + + "unplugin": ["unplugin@2.3.11", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "acorn": "^8.15.0", "picomatch": "^4.0.3", "webpack-virtual-modules": "^0.6.2" } }, "sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww=="], + + "unplugin-icons": ["unplugin-icons@23.0.1", "", { "dependencies": { "@antfu/install-pkg": "^1.1.0", "@iconify/utils": "^3.1.0", "local-pkg": "^1.1.2", "obug": "^2.1.1", "unplugin": "^2.3.11" }, "peerDependencies": { "@svgr/core": ">=7.0.0", "@svgx/core": "^1.0.1", "@vue/compiler-sfc": "^3.0.2", "svelte": "^3.0.0 || ^4.0.0 || ^5.0.0" }, "optionalPeers": ["@svgr/core", "@svgx/core", "@vue/compiler-sfc", "svelte"] }, "sha512-rv0XEJepajKzDLvRUWASM8K+8+/CCfZn2jtogXqg6RIp7kpatRc/aFrVJn8ANQA09e++lPEEv9yX8cC9enc+QQ=="], + + "vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="], + + "vfile-message": ["vfile-message@2.0.4", "", { "dependencies": { "@types/unist": "^2.0.0", "unist-util-stringify-position": "^2.0.0" } }, "sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ=="], + + "vite": ["vite@7.3.1", "", { "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA=="], + + "vitefu": ["vitefu@1.1.1", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0" }, "optionalPeers": ["vite"] }, "sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ=="], + + "webpack-virtual-modules": ["webpack-virtual-modules@0.6.2", "", {}, "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ=="], + + "wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], + + "xmlbuilder2": ["xmlbuilder2@3.1.1", "", { "dependencies": { "@oozcitak/dom": "1.15.10", "@oozcitak/infra": "1.0.8", "@oozcitak/util": "8.3.8", "js-yaml": "3.14.1" } }, "sha512-WCSfbfZnQDdLQLiMdGUQpMxxckeQ4oZNMNhLVkcekTu7xhD4tuUDyAPoY8CwXvBYE6LwBHd6QW2WZXlOWr1vCw=="], + + "y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="], + + "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=="], + + "yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="], + + "zimmerframe": ["zimmerframe@1.1.4", "", {}, "sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ=="], + + "zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="], + + "conventional-commits-parser/meow": ["meow@13.2.0", "", {}, "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA=="], + + "cosmiconfig/js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="], + + "import-fresh/resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], + + "mdast-util-from-markdown/unist-util-stringify-position": ["unist-util-stringify-position@4.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ=="], + + "mdsvex/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="], + + "mdsvex/unist-util-visit": ["unist-util-visit@2.0.3", "", { "dependencies": { "@types/unist": "^2.0.0", "unist-util-is": "^4.0.0", "unist-util-visit-parents": "^3.0.0" } }, "sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q=="], + + "micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + + "mlly/pkg-types": ["pkg-types@1.3.1", "", { "dependencies": { "confbox": "^0.1.8", "mlly": "^1.7.4", "pathe": "^2.0.1" } }, "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ=="], + + "unist-util-stringify-position/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="], + + "vfile/vfile-message": ["vfile-message@4.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw=="], + + "vfile-message/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="], + + "cosmiconfig/js-yaml/argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], + + "mdsvex/unist-util-visit/unist-util-is": ["unist-util-is@4.1.0", "", {}, "sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg=="], + + "mdsvex/unist-util-visit/unist-util-visit-parents": ["unist-util-visit-parents@3.1.1", "", { "dependencies": { "@types/unist": "^2.0.0", "unist-util-is": "^4.0.0" } }, "sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg=="], + + "mlly/pkg-types/confbox": ["confbox@0.1.8", "", {}, "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w=="], + + "vfile/vfile-message/unist-util-stringify-position": ["unist-util-stringify-position@4.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ=="], + } +} diff --git a/commitlint.config.cjs b/commitlint.config.cjs new file mode 100644 index 0000000..4c73b71 --- /dev/null +++ b/commitlint.config.cjs @@ -0,0 +1,3 @@ +module.exports = { + extends: ['@commitlint/config-conventional'], +}; diff --git a/docs/revanced-development/0_prerequisites.md b/docs/Development/0_prerequisites.md similarity index 92% rename from docs/revanced-development/0_prerequisites.md rename to docs/Development/0_prerequisites.md index ef61242..a3a8fdb 100644 --- a/docs/revanced-development/0_prerequisites.md +++ b/docs/Development/0_prerequisites.md @@ -8,6 +8,8 @@ Certain requirements are needed to be able to develop with ReVanced. - Java Development Kit 17 (e.g. [OpenJDK](https://jdk.java.net/archive/)) - Knowledge of Git, Gradle and how to set up and use multi-module Gradle projects +![Prerequisites setup overview screenshot](./aa.png) + ## ⏭️ Whats next The next section explains, how to set up a suitable development environment for ReVanced with [IntelliJ IDEA](https://www.jetbrains.com/idea/) diff --git a/docs/revanced-development/1_setup.md b/docs/Development/1_setup.md similarity index 100% rename from docs/revanced-development/1_setup.md rename to docs/Development/1_setup.md diff --git a/docs/revanced-development/README.md b/docs/Development/README.md similarity index 100% rename from docs/revanced-development/README.md rename to docs/Development/README.md diff --git a/docs/Development/aa.png b/docs/Development/aa.png new file mode 100644 index 0000000000000000000000000000000000000000..54f54b106c958ed0dd3f1f0a8a0be9a05a8c4522 GIT binary patch literal 29381 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 YZ=AyQM!zu-d4Hn#UQHGz{Vm}C0o9YkOaK4? literal 0 HcmV?d00001 diff --git a/docs/revanced-resources/questions.md b/docs/Resources/questions.md similarity index 100% rename from docs/revanced-resources/questions.md rename to docs/Resources/questions.md diff --git a/docs/revanced-resources/troubleshooting.md b/docs/Resources/troubleshooting.md similarity index 96% rename from docs/revanced-resources/troubleshooting.md rename to docs/Resources/troubleshooting.md index fde253a..42622d9 100644 --- a/docs/revanced-resources/troubleshooting.md +++ b/docs/Resources/troubleshooting.md @@ -82,7 +82,7 @@ Enable [Android Auto developer mode](https://developer.android.com/training/cars ## 32 YouTube or YouTube Music playback does not work -First ensure you are using the latest patches. You may be using outdated patches even if the app version has not changed. See [here](https://github.com/ReVanced/revanced-documentation/blob/main/docs/revanced-resources/questions.md#14-how-to-update-patched-apps) for additional information on updating. +First ensure you are using the latest patches. You may be using outdated patches even if the app version has not changed. See [here](questions.md#14-how-to-update-patched-apps) for additional information on updating. Search for existing issues [here](https://github.com/ReVanced/revanced-patches/issues?q=is%3Aissue%20state%3Aopen) as all known issues will have an existing issue. diff --git a/docs/revanced-cli b/docs/cli similarity index 100% rename from docs/revanced-cli rename to docs/cli diff --git a/docs/revanced-manager b/docs/manager similarity index 100% rename from docs/revanced-manager rename to docs/manager diff --git a/docs/revanced-patcher b/docs/patcher similarity index 100% rename from docs/revanced-patcher rename to docs/patcher diff --git a/lefthook.yml b/lefthook.yml new file mode 100644 index 0000000..0848fd2 --- /dev/null +++ b/lefthook.yml @@ -0,0 +1,13 @@ +pre-commit: + parallel: true + commands: + check: + files: git diff --name-only --cached --diff-filter=AM + glob: "*.{js,ts,json}" + run: bunx biome check {files} + +commit-msg: + parallel: false + commands: + commitlint: + run: bunx commitlint --edit diff --git a/package.json b/package.json new file mode 100644 index 0000000..ab2d3d1 --- /dev/null +++ b/package.json @@ -0,0 +1,53 @@ +{ + "name": "revanced-documentation", + "private": true, + "version": "0.0.1", + "type": "module", + "scripts": { + "generate:docs": "bun scripts/generate-docs-graph.ts", + "dev": "bunx --bun svelte-kit sync && bunx --bun vite dev", + "build:all": "bun run generate:docs && bun run build:llms && bun run build && bun run build:sitemap", + "build": "bunx --bun svelte-kit sync && bunx --bun vite build", + "build:llms": "bun scripts/build-llms.ts", + "build:sitemap": "bun scripts/build-sitemap.ts", + "preview": "bunx --bun vite preview", + "flint": "biome check --write .", + "flint:check": "biome check .", + "clint": "commitlint --edit" + }, + "devDependencies": { + "@biomejs/biome": "^2.3.14", + "@commitlint/cli": "^20.4.1", + "@commitlint/config-conventional": "^20.4.1", + "@iconify-json/mdi": "^1.2.3", + "@sveltejs/kit": "^2.50.1", + "@sveltejs/vite-plugin-svelte": "^6.2.4", + "fast-glob": "^3.3.3", + "github-slugger": "^2.0.0", + "gray-matter": "^4.0.3", + "lefthook": "^2.1.0", + "mdast-util-to-string": "^4.0.0", + "remark-frontmatter": "^5.0.0", + "svelte": "^5.48.2", + "svelte-check": "^4.3.5", + "typescript": "^5.9.3", + "unist-util-visit": "^5.1.0", + "unplugin-icons": "^23.0.1", + "vite": "^7.3.1" + }, + "dependencies": { + "@sveltejs/adapter-static": "^3.0.10", + "mdsvex": "^0.12.6", + "minisearch": "^7.2.0", + "rehype-autolink-headings": "^7.1.0", + "rehype-sanitize": "^6.0.0", + "rehype-slug": "^6.0.0", + "remark-gfm": "^4.0.1", + "remark-parse": "^11.0.0", + "sass": "^1.97.3", + "sharp": "^0.34.5", + "shiki": "^3.22.0", + "svelte-sitemap": "^2.7.1", + "unified": "^11.0.5" + } +} diff --git a/scripts/build-llms.ts b/scripts/build-llms.ts new file mode 100644 index 0000000..8ad58ed --- /dev/null +++ b/scripts/build-llms.ts @@ -0,0 +1,73 @@ +import { mkdirSync, readFileSync, writeFileSync } from 'node:fs'; +import { join } from 'node:path'; +import matter from 'gray-matter'; +import { DOCS_DIR, SITE_DESCRIPTION, SITE_TITLE } from '../site.config.js'; +import type { DocsGraph } from '../src/lib/core/types'; + +interface LlmsSourceDocument { + content: string; + includeInLlms: boolean; +} + +function parseLlmsSource(rawMarkdown: string): LlmsSourceDocument { + const parsed = matter(rawMarkdown); + const includeInLlms = parsed.data?.llms !== false; + return { + content: parsed.content.trim(), + includeInLlms, + }; +} + +function buildLlmsDocument( + graph: DocsGraph, + options: { title: string; description: string }, + readSourceMarkdown: (sourcePath: string) => string, +): string { + const docsByRoute = new Map(graph.docs.map((doc) => [doc.routePath, doc])); + const parts: string[] = [`# ${options.title}`, '', options.description, '']; + + for (const section of graph.sections) { + const sectionParts: string[] = []; + + for (const routePath of section.pages) { + const doc = docsByRoute.get(routePath); + if (!doc) { + throw new Error(`Missing docs graph node for route '${routePath}'`); + } + + const source = parseLlmsSource(readSourceMarkdown(doc.sourcePath)); + if (!source.includeInLlms || !source.content) { + continue; + } + + sectionParts.push(`### ${doc.title}`, `Source: ${doc.routePath}`, '', source.content, ''); + } + + if (sectionParts.length === 0) { + continue; + } + + parts.push('---', `## ${section.title}`, '', ...sectionParts); + } + + return `${parts.join('\n').trimEnd()}\n`; +} + +const graphPath = join(process.cwd(), '.svelte-kit/generated/docs-graph.json'); +const graph = JSON.parse(readFileSync(graphPath, 'utf-8')) as DocsGraph; + +const llmsDocument = buildLlmsDocument( + graph, + { + title: SITE_TITLE, + description: SITE_DESCRIPTION, + }, + (sourcePath) => { + const sourceAbsolutePath = join(process.cwd(), DOCS_DIR, sourcePath); + return readFileSync(sourceAbsolutePath, 'utf-8'); + }, +); + +const outDir = join(process.cwd(), 'build'); +mkdirSync(outDir, { recursive: true }); +writeFileSync(join(outDir, 'llms.txt'), llmsDocument); diff --git a/scripts/build-sitemap.ts b/scripts/build-sitemap.ts new file mode 100644 index 0000000..a16cccc --- /dev/null +++ b/scripts/build-sitemap.ts @@ -0,0 +1,3 @@ +import { SITE_URL } from '../site.config.js'; + +await Bun.$`bunx svelte-sitemap --domain ${SITE_URL}`; diff --git a/scripts/generate-docs-graph.ts b/scripts/generate-docs-graph.ts new file mode 100644 index 0000000..61cfca4 --- /dev/null +++ b/scripts/generate-docs-graph.ts @@ -0,0 +1,939 @@ +import { + existsSync, + mkdirSync, + readFileSync, + realpathSync, + statSync, + writeFileSync, +} from 'node:fs'; +import path from 'node:path'; +import fg from 'fast-glob'; +import GithubSlugger from 'github-slugger'; +import matter from 'gray-matter'; +import type { Heading, Image, Link, Root, RootContent } from 'mdast'; +import { toString as mdastToString } from 'mdast-util-to-string'; +import MiniSearch from 'minisearch'; +import remarkFrontmatter from 'remark-frontmatter'; +import remarkGfm from 'remark-gfm'; +import remarkParse from 'remark-parse'; +import sharp from 'sharp'; +import { unified } from 'unified'; +import { visit } from 'unist-util-visit'; +import { + DOCS_DIR, + DOCS_SECTIONS, + GITHUB_EDIT_BASE_URL, + HEADER_BUTTONS, + LOGO_ASSET_PATH, + ORG_NAME, + SITE_DESCRIPTION, + SITE_NAME, + SITE_THEME_COLOR, + SITE_TITLE, + SITE_URL, +} from '../site.config.js'; +import { + type ParsedDocHref, + parseLocalAssetHref, + parseMarkdownDocHref, + resolveDocRelativePath, +} from '../src/lib/core/href-utils'; +import type { + DocNode, + DocsGraph, + SearchSection, + SectionNode, + TableOfContentsHeading, +} from '../src/lib/core/types'; + +const SEARCH_SETTINGS = { + fuzzy: 0.15, + prefix: true, + combineWith: 'AND' as const, + snippetMaxLength: 140, + snippetContextChars: 40, + ellipsis: '...', + highlightTag: 'mark', + maxIndexTextLength: 600, +}; + +const GENERATED_DIR = '.svelte-kit/generated'; +const DOCS_GRAPH_PATH = `${GENERATED_DIR}/docs-graph.json`; +const DOCS_RUNTIME_GRAPH_PATH = `${GENERATED_DIR}/docs-runtime-graph.json`; +const SEARCH_INDEX_PATH = `${GENERATED_DIR}/search-index.json`; +const SITE_PUBLIC_CONFIG_PATH = `${GENERATED_DIR}/site-public.json`; +const ROOT_SECTION_ID = '_root'; + +interface SearchDoc { + id: number; + title: string; + section: string; + sectionId: string; + sectionIcon: string; + url: string; + anchor: string; + text: string; +} + +interface TempDocNode { + doc: DocNode; + parsedLinks: ParsedDocHref[]; + parsedAssets: ParsedDocHref[]; + headingAnchors: Set; +} + +interface ValidationReporter { + report: (message: string) => void; + assertNoIssues: () => void; +} + +interface FrontmatterInput { + title?: unknown; + description?: unknown; + sidebar?: unknown; + sidebar_label?: unknown; + sidebar_position?: unknown; + sidebar_order?: unknown; + slug?: unknown; +} + +function hasOwnSection(sectionId: string): boolean { + return Object.hasOwn(DOCS_SECTIONS, sectionId); +} + +function resolveSectionId(dirName: string): string { + return dirName !== ROOT_SECTION_ID && hasOwnSection(dirName) ? dirName : ROOT_SECTION_ID; +} + +function getSectionConfig(sectionId: string) { + const section = DOCS_SECTIONS[sectionId as keyof typeof DOCS_SECTIONS]; + invariant(Boolean(section), `Missing section definition for '${sectionId}'`); + return section; +} + +function compareSectionOrder(a: string, b: string): number { + return getSectionConfig(a).order - getSectionConfig(b).order; +} + +const parseProcessor = unified().use(remarkParse).use(remarkGfm).use(remarkFrontmatter, ['yaml']); + +function invariant(condition: boolean, message: string): asserts condition { + if (!condition) throw new Error(message); +} + +function isInsideDirectory(root: string, candidate: string): boolean { + const relative = path.relative(root, candidate); + return relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative)); +} + +function resolveAndAssertWorkspacePath(cwd: string, absolutePath: string): string { + const resolvedPath = realpathSync(absolutePath); + invariant( + isInsideDirectory(cwd, resolvedPath), + `Resolved path points outside workspace: ${absolutePath} -> ${resolvedPath}`, + ); + return resolvedPath; +} + +async function readImageMetadata( + absolutePath: string, +): Promise<{ width: number; height: number } | null> { + try { + const metadata = await sharp(absolutePath).metadata(); + if ( + typeof metadata.width === 'number' && + typeof metadata.height === 'number' && + metadata.width > 0 && + metadata.height > 0 + ) { + return { + width: metadata.width, + height: metadata.height, + }; + } + } catch (error) { + if (process.env.DEBUG_DOCS_GRAPH === '1') { + console.warn( + `[docs-graph] Failed to read image metadata for '${absolutePath}':`, + error instanceof Error ? error.message : String(error), + ); + } + } + + return null; +} + +function normalizeToPosix(filePath: string): string { + return filePath.replace(/\\/g, '/'); +} + +function stripMarkdownExtension(filePath: string): string { + return filePath.replace(/\.md$/i, ''); +} + +function slugify(value: string): string { + return value + .normalize('NFKD') + .replace(/[\u0300-\u036f]/g, '') + .replace(/[^\p{L}\p{N}\s_-]/gu, '') + .trim() + .toLowerCase() + .replace(/[_\s]+/g, '-') + .replace(/-{2,}/g, '-') + .replace(/^-|-$/g, ''); +} + +function slugifyPath(value: string, sourcePath: string): string { + const normalized = value.replace(/^\/+|\/+$/g, ''); + invariant(normalized.length > 0, `Invalid empty slug override in '${sourcePath}'`); + + const segments = normalized.split('/').filter(Boolean); + const slugSegments: string[] = []; + for (const segment of segments) { + const slugged = slugify(segment); + invariant( + slugged.length > 0, + `Slug segment '${segment}' in '${sourcePath}' produced an empty slug (contains only special characters or emoji)`, + ); + slugSegments.push(slugged); + } + + const slug = slugSegments.join('/'); + invariant(slug.length > 0, `Invalid slug generated from '${value}' in '${sourcePath}'`); + return slug; +} + +function titleCase(value: string): string { + return value.replace(/[_-]/g, ' ').replace(/\b\w/g, (char) => char.toUpperCase()); +} + +function walkMarkdown(dir: string): string[] { + if (!existsSync(dir)) return []; + return fg + .sync('**/*.md', { + cwd: dir, + absolute: true, + onlyFiles: true, + followSymbolicLinks: true, + }) + .sort((a, b) => a.localeCompare(b)); +} + +function walkAssets(dir: string): string[] { + if (!existsSync(dir)) return []; + return fg + .sync('**/*', { + cwd: dir, + absolute: true, + onlyFiles: true, + followSymbolicLinks: true, + ignore: ['**/*.md'], + }) + .sort((a, b) => a.localeCompare(b)); +} + +function toPlainText(root: Root): string { + return mdastToString(root).replace(/\s+/g, ' ').trim(); +} + +function deriveDocLocation( + sourcePath: string, + slugOverride: string | null, +): { + sectionId: string; + contentSlug: string; + slug: string; + routePath: string; + category: string; +} { + const withoutExt = stripMarkdownExtension(sourcePath); + const parts = withoutExt.split('/').filter(Boolean); + invariant(parts.length > 0, `Invalid docs path: ${sourcePath}`); + + let sectionId = ROOT_SECTION_ID; + let contentSlug: string; + let category = ''; + + if (parts.length === 1) { + contentSlug = parts[0]; + } else { + const topLevelDir = parts[0]; + sectionId = resolveSectionId(topLevelDir); + + if (sectionId === ROOT_SECTION_ID) { + contentSlug = parts.join('/'); + category = topLevelDir; + } else { + contentSlug = parts.slice(1).join('/'); + category = parts.length === 2 ? '' : parts.slice(1, -1).join(' / '); + } + } + + const slugSource = slugOverride ?? contentSlug; + const slug = slugifyPath(slugSource, sourcePath); + const routePath = sectionId === ROOT_SECTION_ID ? `/${slug}` : `/${sectionId}/${slug}`; + + return { + sectionId, + contentSlug, + slug, + routePath, + category, + }; +} + +function extractFrontmatter( + raw: string, + sourcePath: string, +): { + body: string; + title: string | null; + sidebarLabel: string | null; + sidebarOrder: number | null; + description: string | null; + slug: string | null; +} { + const parsed = matter(raw); + const data = (parsed.data ?? {}) as FrontmatterInput; + + const sidebar = + data.sidebar && typeof data.sidebar === 'object' + ? (data.sidebar as Record) + : null; + + const title = typeof data.title === 'string' ? data.title.trim() : null; + const sidebarLabel = + (typeof sidebar?.label === 'string' + ? sidebar.label + : typeof data.sidebar_label === 'string' + ? data.sidebar_label + : null + )?.trim() ?? null; + const description = typeof data.description === 'string' ? data.description.trim() : null; + const slug = typeof data.slug === 'string' ? data.slug.trim() : null; + + let sidebarOrder: number | null = null; + const sidebarOrderRaw = sidebar?.order ?? data.sidebar_position ?? data.sidebar_order; + if (typeof sidebarOrderRaw === 'number' && Number.isFinite(sidebarOrderRaw)) { + sidebarOrder = sidebarOrderRaw; + } else if (typeof sidebarOrderRaw === 'string' && sidebarOrderRaw.trim() !== '') { + const numeric = Number(sidebarOrderRaw); + if (!Number.isFinite(numeric)) { + throw new Error( + `Invalid sidebar order in ${sourcePath}: expected a number, got ${JSON.stringify(sidebarOrderRaw)}`, + ); + } + sidebarOrder = numeric; + } + + return { + body: parsed.content, + title, + sidebarLabel, + sidebarOrder, + description, + slug, + }; +} + +function headingText(heading: Heading): string { + return mdastToString(heading).replace(/\s+/g, ' ').trim(); +} + +function headingSlugText(heading: Heading): string { + return mdastToString(heading); +} + +function extractHeadingsAndSections( + root: Root, + sourcePath: string, +): { + headings: TableOfContentsHeading[]; + searchSections: SearchSection[]; + headingAnchors: string[]; +} { + const slugger = new GithubSlugger(); + const headings: TableOfContentsHeading[] = []; + const headingIds = new Set(); + + const searchSections: SearchSection[] = []; + let currentHeading = ''; + let currentAnchor = ''; + let currentNodes: RootContent[] = []; + + const flush = () => { + if (currentNodes.length === 0 && currentHeading === '') return; + + const sectionRoot: Root = { type: 'root', children: currentNodes }; + const text = toPlainText(sectionRoot); + if (text) { + searchSections.push({ + heading: currentHeading, + anchor: currentAnchor, + text, + }); + } + }; + + for (const node of root.children) { + if (node.type === 'heading') { + flush(); + + const title = headingText(node); + const id = slugger.slug(headingSlugText(node)); + invariant(!headingIds.has(id), `Duplicate heading id '${id}' detected in '${sourcePath}'`); + headingIds.add(id); + + if (node.depth >= 2 && node.depth <= 6) { + headings.push({ + id, + title, + level: node.depth, + }); + } + + currentHeading = title; + currentAnchor = id; + currentNodes = []; + continue; + } + + currentNodes.push(node); + } + + flush(); + + return { headings, searchSections, headingAnchors: [...headingIds] }; +} + +function extractInternalLinks(root: Root): ParsedDocHref[] { + const links: ParsedDocHref[] = []; + visit(root, 'link', (node) => { + const link = node as Link; + if (typeof link.url !== 'string') return; + + const parsed = parseMarkdownDocHref(link.url); + if (parsed) links.push(parsed); + }); + + return links; +} + +function extractInternalAssets(root: Root): ParsedDocHref[] { + const assets: ParsedDocHref[] = []; + visit(root, 'image', (node) => { + const image = node as Image; + if (typeof image.url !== 'string') return; + + const parsed = parseLocalAssetHref(image.url); + if (parsed) assets.push(parsed); + }); + + return assets; +} + +function buildEditUrl(sectionId: string, sourcePath: string): string { + const section = getSectionConfig(sectionId); + const repo = section.repo; + if (sectionId === ROOT_SECTION_ID) { + return `${GITHUB_EDIT_BASE_URL}/${repo.name}/edit/${repo.branch}/${repo.docsPath}/${sourcePath}`; + } + + invariant( + sourcePath.startsWith(`${sectionId}/`), + `Source path '${sourcePath}' does not match section prefix '${sectionId}/'`, + ); + const repoRelativePath = sourcePath.slice(sectionId.length + 1); + return `${GITHUB_EDIT_BASE_URL}/${repo.name}/edit/${repo.branch}/${repo.docsPath}/${repoRelativePath}`; +} + +function extractPrimaryTitle(root: Root): string | null { + for (const node of root.children) { + if (node.type === 'heading' && node.depth === 1) { + const title = headingText(node); + if (title) return title; + } + } + return null; +} + +function decodeAnchor(hash: string): string { + try { + return decodeURIComponent(hash); + } catch { + return hash; + } +} + +async function collectAssets( + cwd: string, + docsDir: string, +): Promise<{ knownAssetPaths: Set; assetMetadata: DocsGraph['assetMetadata'] }> { + const assetFiles = walkAssets(docsDir); + const knownAssetPaths = new Set(); + const assetMetadata: DocsGraph['assetMetadata'] = {}; + + await Promise.all( + assetFiles.map(async (filePath) => { + const workspaceRealPath = resolveAndAssertWorkspacePath(cwd, filePath); + const sourcePath = normalizeToPosix(path.relative(docsDir, filePath)); + knownAssetPaths.add(sourcePath); + const metadata = await readImageMetadata(workspaceRealPath); + if (metadata) { + assetMetadata[sourcePath] = metadata; + } + }), + ); + + return { knownAssetPaths, assetMetadata }; +} + +function parseMarkdownFiles(cwd: string, docsDir: string): TempDocNode[] { + const markdownFiles = walkMarkdown(docsDir); + const temporaryDocs: TempDocNode[] = []; + const routeToSource = new Map(); + const sourceToRoute = new Map(); + + for (const filePath of markdownFiles) { + const workspaceRealFilePath = resolveAndAssertWorkspacePath(cwd, filePath); + const rawFile = readFileSync(filePath, 'utf-8'); + const relativePath = normalizeToPosix(path.relative(docsDir, filePath)); + const workspacePath = normalizeToPosix(path.relative(cwd, filePath)); + const workspaceRealPath = normalizeToPosix(path.relative(cwd, workspaceRealFilePath)); + + const frontmatter = extractFrontmatter(rawFile, relativePath); + const { sectionId, contentSlug, slug, routePath, category } = deriveDocLocation( + relativePath, + frontmatter.slug, + ); + const root = parseProcessor.parse(frontmatter.body) as Root; + const extracted = extractHeadingsAndSections(root, relativePath); + + const sourceWithoutExt = stripMarkdownExtension(relativePath); + const fileName = path.basename(sourceWithoutExt); + const pageTitle = frontmatter.title ?? extractPrimaryTitle(root) ?? titleCase(fileName); + const sidebarLabel = frontmatter.sidebarLabel ?? pageTitle; + + const routeConflict = routeToSource.get(routePath); + invariant( + !routeConflict, + `Duplicate route path '${routePath}' for '${relativePath}' and '${routeConflict}'`, + ); + routeToSource.set(routePath, relativePath); + + const sourceConflict = sourceToRoute.get(relativePath); + invariant(!sourceConflict, `Duplicate source path '${relativePath}'`); + sourceToRoute.set(relativePath, routePath); + + temporaryDocs.push({ + doc: { + sourcePath: relativePath, + workspacePath, + workspaceRealPath, + sectionId, + sectionTitle: getSectionConfig(sectionId).label, + contentSlug, + slug, + routePath, + category, + title: pageTitle, + sidebarLabel, + sidebarOrder: frontmatter.sidebarOrder, + description: frontmatter.description, + headings: extracted.headings, + searchSections: extracted.searchSections, + plainText: toPlainText(root), + editUrl: buildEditUrl(sectionId, relativePath), + }, + parsedLinks: extractInternalLinks(root), + parsedAssets: extractInternalAssets(root), + headingAnchors: new Set(extracted.headingAnchors), + }); + } + + return temporaryDocs; +} + +function createValidationReporter(): ValidationReporter { + const issues: string[] = []; + return { + report(message: string) { + issues.push(message); + }, + assertNoIssues() { + if (issues.length === 0) { + return; + } + throw new Error(issues.join('\n')); + }, + }; +} + +function validateReferences( + temporaryDocs: TempDocNode[], + knownAssetPaths: Set, + reporter: ValidationReporter, +): void { + const docsBySourcePath = new Map( + temporaryDocs.map((tempDoc) => [tempDoc.doc.sourcePath, tempDoc]), + ); + + for (const tempDoc of temporaryDocs) { + for (const link of tempDoc.parsedLinks) { + let resolvedSourcePath: string; + try { + resolvedSourcePath = resolveDocRelativePath(tempDoc.doc.sourcePath, link.targetPath); + } catch (error) { + reporter.report( + `Invalid markdown link in '${tempDoc.doc.sourcePath}': '${link.fullHref}' (${error instanceof Error ? error.message : String(error)})`, + ); + continue; + } + + const targetDoc = docsBySourcePath.get(resolvedSourcePath); + if (!targetDoc) { + reporter.report( + `Unresolved markdown link in '${tempDoc.doc.sourcePath}': '${link.fullHref}' resolves to '${resolvedSourcePath}'`, + ); + continue; + } + + if (link.hash) { + const targetAnchor = decodeAnchor(link.hash); + if (!targetDoc.headingAnchors.has(targetAnchor)) { + reporter.report( + `Unresolved markdown anchor in '${tempDoc.doc.sourcePath}': '${link.fullHref}' points to missing '#${targetAnchor}' in '${resolvedSourcePath}'`, + ); + } + } + } + + for (const asset of tempDoc.parsedAssets) { + let resolvedAssetPath: string; + try { + resolvedAssetPath = resolveDocRelativePath(tempDoc.doc.sourcePath, asset.targetPath); + } catch (error) { + reporter.report( + `Invalid image link in '${tempDoc.doc.sourcePath}': '${asset.fullHref}' (${error instanceof Error ? error.message : String(error)})`, + ); + continue; + } + + if (!knownAssetPaths.has(resolvedAssetPath)) { + reporter.report( + `Unresolved image link in '${tempDoc.doc.sourcePath}': '${asset.fullHref}' resolves to '${resolvedAssetPath}'`, + ); + } + } + } +} + +function organizeSections(temporaryDocs: TempDocNode[]): { + docs: DocNode[]; + sections: SectionNode[]; +} { + const docsBySection = new Map(); + for (const tempDoc of temporaryDocs) { + const sectionDocs = docsBySection.get(tempDoc.doc.sectionId); + if (sectionDocs) { + sectionDocs.push(tempDoc.doc); + continue; + } + docsBySection.set(tempDoc.doc.sectionId, [tempDoc.doc]); + } + + const orderedSectionIds = Object.keys(DOCS_SECTIONS) + .filter((sectionId) => docsBySection.has(sectionId)) + .sort(compareSectionOrder); + + const docs: DocNode[] = []; + const sections: SectionNode[] = []; + + for (const sectionId of orderedSectionIds) { + const sectionDocs = docsBySection.get(sectionId); + invariant(sectionDocs !== undefined, `Missing section docs for '${sectionId}'`); + sectionDocs.sort((a, b) => { + const aOrder = a.sidebarOrder ?? Number.POSITIVE_INFINITY; + const bOrder = b.sidebarOrder ?? Number.POSITIVE_INFINITY; + if (aOrder !== bOrder) return aOrder - bOrder; + return a.routePath.localeCompare(b.routePath); + }); + + docs.push(...sectionDocs); + + const sectionDef = getSectionConfig(sectionId); + sections.push({ + id: sectionId, + title: sectionDef.label, + order: sectionDef.order, + basePath: sectionId === ROOT_SECTION_ID ? '' : sectionId, + isPageAnchor: sectionId !== ROOT_SECTION_ID, + icon: sectionDef.icon, + pages: sectionDocs.map((doc) => doc.routePath), + }); + } + + return { docs, sections }; +} + +async function buildDocsGraph(cwd = process.cwd()): Promise { + const docsDir = path.join(cwd, DOCS_DIR); + + const [{ knownAssetPaths, assetMetadata }, temporaryDocs] = await Promise.all([ + collectAssets(cwd, docsDir), + Promise.resolve(parseMarkdownFiles(cwd, docsDir)), + ]); + + const reporter = createValidationReporter(); + validateReferences(temporaryDocs, knownAssetPaths, reporter); + reporter.assertNoIssues(); + + const { docs, sections } = organizeSections(temporaryDocs); + + return { + generatedAt: new Date().toISOString(), + docs, + sections, + assets: [...knownAssetPaths].sort((a, b) => a.localeCompare(b)), + assetMetadata, + }; +} + +const cwd = process.cwd(); +const graphOutputPath = path.join(cwd, DOCS_GRAPH_PATH); +const runtimeGraphOutputPath = path.join(cwd, DOCS_RUNTIME_GRAPH_PATH); +const searchIndexOutputPath = path.join(cwd, SEARCH_INDEX_PATH); +const sitePublicConfigOutputPath = path.join(cwd, SITE_PUBLIC_CONFIG_PATH); +const docsDir = path.join(cwd, DOCS_DIR); +const repoAssetsDir = path.join(cwd, 'assets'); +const configPath = path.resolve(cwd, 'site.config.ts'); +const force = process.argv.includes('--force'); + +const outputFiles = [ + graphOutputPath, + runtimeGraphOutputPath, + searchIndexOutputPath, + sitePublicConfigOutputPath, +]; + +function assertInsideWorkspace(targetPath: string): void { + const relative = path.relative(cwd, targetPath); + if (relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative))) { + return; + } + throw new Error(`Refusing to write outside workspace: ${targetPath}`); +} + +function writeJsonFile(outputPath: string, value: unknown): void { + assertInsideWorkspace(outputPath); + mkdirSync(path.dirname(outputPath), { recursive: true }); + writeFileSync(outputPath, `${JSON.stringify(value, null, 2)}\n`, 'utf-8'); +} + +function getLatestMtimeMs(paths: string[]): number { + let latest = 0; + for (const filePath of paths) { + if (!existsSync(filePath)) { + continue; + } + const mtimeMs = statSync(filePath).mtimeMs; + if (mtimeMs > latest) { + latest = mtimeMs; + } + } + return latest; +} + +function toWorkspaceRealPath(absolutePath: string): string { + const realPath = realpathSync(absolutePath); + assertInsideWorkspace(realPath); + return realPath; +} + +function collectGenerationInputs(): string[] { + const docsFiles = existsSync(docsDir) + ? fg.sync('**/*', { + cwd: docsDir, + absolute: true, + onlyFiles: true, + followSymbolicLinks: true, + }) + : []; + const docsDirectories = existsSync(docsDir) + ? [ + docsDir, + ...fg.sync('**/*', { + cwd: docsDir, + absolute: true, + onlyDirectories: true, + followSymbolicLinks: true, + }), + ] + : []; + + const repoAssetFiles = existsSync(repoAssetsDir) + ? fg.sync('**/*', { + cwd: repoAssetsDir, + absolute: true, + onlyFiles: true, + followSymbolicLinks: true, + }) + : []; + const repoAssetDirectories = existsSync(repoAssetsDir) + ? [ + repoAssetsDir, + ...fg.sync('**/*', { + cwd: repoAssetsDir, + absolute: true, + onlyDirectories: true, + followSymbolicLinks: true, + }), + ] + : []; + + const scriptFiles = [ + path.resolve(cwd, 'scripts/generate-docs-graph.ts'), + path.resolve(cwd, 'scripts/build-llms.ts'), + path.resolve(cwd, 'src/lib/core/href-utils.ts'), + configPath, + ] + .filter(existsSync) + .map(toWorkspaceRealPath); + + return [ + ...new Set([ + ...docsFiles.map(toWorkspaceRealPath), + ...docsDirectories.map(toWorkspaceRealPath), + ...repoAssetFiles.map(toWorkspaceRealPath), + ...repoAssetDirectories.map(toWorkspaceRealPath), + ...scriptFiles, + ]), + ]; +} + +function isGenerationUpToDate(): boolean { + for (const outputPath of outputFiles) { + if (!existsSync(outputPath)) { + return false; + } + } + + const inputs = collectGenerationInputs(); + if (inputs.length === 0) { + return false; + } + + const newestInput = getLatestMtimeMs(inputs); + if (newestInput === 0) { + return false; + } + + const oldestOutput = Math.min(...outputFiles.map((outputPath) => statSync(outputPath).mtimeMs)); + return oldestOutput >= newestInput; +} + +function buildSearchIndex(currentGraph: DocsGraph): string { + const sectionIconMap = new Map( + currentGraph.sections.map((section) => [section.id, section.icon]), + ); + const docs: SearchDoc[] = []; + let nextId = 1; + + for (const doc of currentGraph.docs) { + const sectionIcon = sectionIconMap.get(doc.sectionId) ?? ''; + + if (doc.searchSections.length === 0) { + if (!doc.plainText) continue; + docs.push({ + id: nextId++, + title: doc.title, + section: doc.sectionTitle, + sectionId: doc.sectionId, + sectionIcon, + url: doc.routePath, + anchor: '', + text: doc.plainText.slice(0, SEARCH_SETTINGS.maxIndexTextLength), + }); + continue; + } + + for (const section of doc.searchSections) { + docs.push({ + id: nextId++, + title: section.heading || doc.title, + section: `${doc.sectionTitle} › ${doc.title}`, + sectionId: doc.sectionId, + sectionIcon, + url: doc.routePath, + anchor: section.anchor, + text: section.text.slice(0, SEARCH_SETTINGS.maxIndexTextLength), + }); + } + } + + const ms = new MiniSearch({ + fields: ['title', 'text', 'section'], + storeFields: ['title', 'section', 'sectionId', 'sectionIcon', 'url', 'anchor', 'text'], + searchOptions: { + boost: { title: 4, section: 2, text: 1 }, + fuzzy: SEARCH_SETTINGS.fuzzy, + prefix: SEARCH_SETTINGS.prefix, + combineWith: SEARCH_SETTINGS.combineWith as 'AND' | 'OR' | 'AND_NOT', + }, + }); + + ms.addAll(docs); + return JSON.stringify(ms); +} + +function buildSitePublicConfig() { + const sectionIcons = Object.fromEntries( + Object.entries(DOCS_SECTIONS).map(([id, section]) => [id, { icon: section.icon }]), + ); + + return { + site: { + name: SITE_NAME, + org: ORG_NAME, + title: SITE_TITLE, + description: SITE_DESCRIPTION, + logoAssetPath: LOGO_ASSET_PATH, + headerButtons: HEADER_BUTTONS, + themeColor: SITE_THEME_COLOR, + }, + sections: sectionIcons, + siteUrl: SITE_URL, + }; +} + +function buildRuntimeDocsGraph(currentGraph: DocsGraph) { + return { + generatedAt: currentGraph.generatedAt, + docs: currentGraph.docs.map((doc) => ({ + sourcePath: doc.sourcePath, + sectionId: doc.sectionId, + sectionTitle: doc.sectionTitle, + contentSlug: doc.contentSlug, + slug: doc.slug, + routePath: doc.routePath, + category: doc.category, + title: doc.title, + sidebarLabel: doc.sidebarLabel, + headings: doc.headings, + editUrl: doc.editUrl, + })), + sections: currentGraph.sections, + }; +} + +if (!force && isGenerationUpToDate()) { + console.log('Docs artifacts are up to date'); + process.exit(0); +} + +const graph = await buildDocsGraph(cwd); + +writeJsonFile(graphOutputPath, graph); +writeJsonFile(runtimeGraphOutputPath, buildRuntimeDocsGraph(graph)); +writeJsonFile(sitePublicConfigOutputPath, buildSitePublicConfig()); +writeFileSync(searchIndexOutputPath, buildSearchIndex(graph), 'utf-8'); diff --git a/site.config.ts b/site.config.ts new file mode 100644 index 0000000..b5161b7 --- /dev/null +++ b/site.config.ts @@ -0,0 +1,79 @@ +export const DOCS_DIR = 'docs'; + +export const SITE_NAME = 'Documentation'; +export const ORG_NAME = 'ReVanced'; +export const SITE_TITLE = `${ORG_NAME} ${SITE_NAME}`; +export const SITE_DESCRIPTION = + 'ReVanced is a modular patcher for Android applications. This documentation covers the ReVanced Patcher, Manager, and CLI.'; +export const LOGO_ASSET_PATH = '/logo.svg'; +export const SITE_THEME_COLOR = '#1a191f'; + +function resolveSiteUrl(): string { + const raw = process.env.SITE_URL_OVERRIDE?.trim() || 'https://docs.revanced.app'; + let parsed: URL; + try { + parsed = new URL(raw); + } catch { + throw new Error(`Invalid SITE_URL_OVERRIDE value '${raw}'`); + } + if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:') { + throw new Error(`SITE_URL_OVERRIDE must use http or https, got '${parsed.protocol}'`); + } + const pathname = parsed.pathname.replace(/\/+$/, ''); + return `${parsed.origin}${pathname === '/' ? '' : pathname}`; +} + +export const SITE_URL = resolveSiteUrl(); + +export const HEADER_BUTTONS = [ + { + href: 'https://github.com/ReVanced/revanced-documentation', + label: 'GitHub', + icon: 'github', + }, +]; + +export const GITHUB_EDIT_BASE_URL = 'https://github.com/ReVanced'; + +export const DOCS_SECTIONS = { + _root: { + label: 'General', + order: 0, + icon: 'home', + repo: { + name: 'revanced-documentation', + branch: 'main', + docsPath: 'docs', + }, + }, + patcher: { + label: 'Patcher', + order: 1, + icon: 'hammer', + repo: { + name: 'revanced-patcher', + branch: 'main', + docsPath: 'docs', + }, + }, + manager: { + label: 'Manager', + order: 2, + icon: 'cellphone', + repo: { + name: 'revanced-manager', + branch: 'main', + docsPath: 'docs', + }, + }, + cli: { + label: 'CLI', + order: 3, + icon: 'console', + repo: { + name: 'revanced-cli', + branch: 'main', + docsPath: 'docs', + }, + }, +} as const; diff --git a/src/_tokens.scss b/src/_tokens.scss new file mode 100644 index 0000000..9e22750 --- /dev/null +++ b/src/_tokens.scss @@ -0,0 +1,23 @@ +$bp-desktop: 1200px; +$bp-mobile: 768px; + +$header-height: 56px; +$toc-row-height: 60px; +$sidebar-width: 280px; +$toc-width: 240px; +$content-max-width: 850px; + +$layout-padding: 24px; +$layout-radius: 24px; + +$z-sidebar: 110; +$z-header: 40; +$z-header-mobile: 100; +$z-dropdown: 200; +$z-modal: 9999; +$z-toc: 50; + +$search-debounce-ms: 60; +$search-max-width: 560px; + +$anchor-offset: calc(#{$header-height} + 24px); diff --git a/src/app.d.ts b/src/app.d.ts new file mode 100644 index 0000000..0e56cd2 --- /dev/null +++ b/src/app.d.ts @@ -0,0 +1,7 @@ +/// + +declare global { + namespace App {} +} + +export {}; diff --git a/src/app.html b/src/app.html new file mode 100644 index 0000000..9955c0b --- /dev/null +++ b/src/app.html @@ -0,0 +1,21 @@ + + + + + + + + + + %sveltekit.head% + + + + + + + + +
%sveltekit.body%
+ + diff --git a/src/app.scss b/src/app.scss new file mode 100644 index 0000000..c898b94 --- /dev/null +++ b/src/app.scss @@ -0,0 +1,433 @@ +* { + box-sizing: inherit; + margin: 0; + padding: 0; + font-family: var(--main-font); + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} + +html { + margin: 0; + padding: 0; + font-size: 100%; + box-sizing: border-box; + overflow-y: scroll; +} + +[id] { + scroll-margin-top: var(--docs-anchor-offset, 80px); +} + +body { + margin: 0; + padding: 0; + min-height: 100vh; + background-color: var(--background-one); +} + +html, +body { + max-width: 100%; +} + +.wrapper { + margin-inline: auto; + width: min(90%, 80rem); + margin-top: 2.6rem; +} + +:root { + --main-font: 'Manrope', sans-serif; + --mono-font: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace; + --docs-anchor-offset: 80px; + + --text-one: hsl(206, 100%, 94%); + --text-ee: hsla(206, 100%, 94%, 60%); + --surface-one: hsl(206, 100%, 94%); + --primary: hsl(206, 100%, 81%); + --secondary: hsl(208, 75%, 82%); + --tertiary: hsla(205, 91%, 69%, 0.15); + + --background-one: hsl(252, 10%, 11%); + --surface-two: hsl(252, 10%, 11%); + --surface-three: hsl(210, 14%, 17%); + --surface-four: hsl(212, 19%, 19%); + --text-two: hsl(212, 19%, 19%); + --border: hsl(221, 17%, 26%); + --surface-five: hsl(221, 17%, 26%); + --text-three: hsl(226, 48%, 18%); + --text-four: hsl(208, 30%, 75%); + --surface-six: hsl(208, 30%, 75%); + --surface-seven: hsl(230, 9%, 13%); + --surface-eight: hsl(240, 9%, 13.5%); + --surface-nine: hsl(230, 9.5%, 17.5%); + + --red-one: hsl(333, 84%, 62%); + --red-two: hsl(357, 74%, 60%); + --red-three: hsl(2, 68%, 83%); + --yellow-one: hsl(59, 100%, 72%); + + --bezier-one: ease-out; + --drop-shadow-one: 0px 4px 5px 0px rgba(0, 0, 0, 0.14), 0px 1px 10px 0px rgba(0, 0, 0, 0.12), + 0px 2px 4px -1px rgba(0, 0, 0, 0.2); +} + +::selection { + background-color: var(--tertiary); +} + +.spinner { + display: inline-block; + width: var(--spinner-size, 18px); + height: var(--spinner-size, 18px); + border: 2px solid rgba(255, 255, 255, 0.2); + border-top-color: var(--primary); + border-radius: 50%; + animation: spinner-rotate 0.9s linear infinite; +} + +@keyframes spinner-rotate { + from { transform: rotate(0deg); } + to { transform: rotate(360deg); } +} + +.img-placeholder-wrapper { + position: relative; + display: inline-block; + overflow: hidden; + border-radius: 8px; + line-height: 0; + max-width: 100%; + border: 1px solid var(--border); + background-color: var(--surface-seven); +} + +.img-placeholder-wrapper .img-spinner { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + z-index: 0; +} + +.img-placeholder-wrapper img { + position: relative; + z-index: 1; + display: block; + width: 100%; + height: auto; + object-fit: cover; +} + +mark { + background-color: var(--secondary); +} + +h1 { + color: var(--text-one); + line-height: 4rem; + font-size: 3.5rem; + font-weight: 700; + letter-spacing: -0.025em; +} + +h2 { + color: var(--text-four); + font-size: 2.5rem; + letter-spacing: -0.04rem; + font-weight: 600; +} + +h3 { + font-size: 1.25rem; + color: var(--secondary); + font-weight: 600; +} + +h4 { + color: var(--secondary); + font-weight: 400; + font-size: 1rem; + letter-spacing: 0.02rem; + line-height: 2rem; +} + +h5 { + color: var(--text-four); + font-weight: 400; + font-size: 0.9rem; + letter-spacing: 0.02rem; +} + +h6 { + color: var(--text-four); + font-weight: 500; + font-size: 0.85rem; +} + +h2, h3, h4, h5, h6 { + position: relative; + + .heading-anchor { + text-decoration: none; + margin-left: 0.35em; + opacity: 0; + } + + &:hover .heading-anchor { + opacity: 1; + } + + .heading-anchor-icon { + color: var(--primary); + font-weight: 400; + + text-decoration: none; + transition: none; + font-size: 0.8em; + } +} + +p { + color: var(--text-four); + font-weight: 400; + font-size: 1rem; + letter-spacing: 0.02rem; + line-height: 1.75rem; +} + +@media (max-width: 768px) { + h1 { + font-size: 2.6rem; + line-height: 3.75rem; + } + + h2 { + font-size: 2rem; + } +} + +::-webkit-scrollbar { + width: 5px; + height: 5px; + background-color: transparent; +} + +::-webkit-scrollbar-thumb { + background-color: var(--primary); + background-clip: content-box; + border-radius: 100px; +} + +::-webkit-scrollbar-thumb:hover { + background-color: var(--surface-five); +} + +hr { + display: block; + height: 1px; + border: 0; + border-top: 1px solid var(--border); +} + +textarea { + resize: vertical; + field-sizing: content; +} + +input, +textarea { + padding: 1rem; + border-radius: 12px; + border: 1px solid var(--border); + background-color: transparent; + color: var(--secondary); +} + +input:focus, +textarea:focus { + outline: 1px solid var(--primary); +} + +.docs-content { + .markdown-content > h1:first-child { + display: none; + } + + .markdown-content > h2:first-of-type { + margin-top: 0; + } + + h1 { + font-size: 2.25rem; + font-weight: 700; + color: var(--text-one); + margin-bottom: 1rem; + line-height: 1.2; + } + + h2 { + font-size: 1.5rem; + font-weight: 600; + color: var(--text-one); + margin-top: 2.5rem; + margin-bottom: 1rem; + padding-bottom: 0.5rem; + border-bottom: 1px solid var(--tertiary); + } + + h3 { + font-size: 1.25rem; + font-weight: 600; + color: var(--text-one); + margin-top: 2rem; + margin-bottom: 0.75rem; + } + + h4, h5, h6 { + font-size: 1rem; + font-weight: 600; + color: var(--text-one); + margin-top: 1.5rem; + margin-bottom: 0.5rem; + } + + p { + color: var(--text-four); + line-height: 1.7; + margin-bottom: 1rem; + } + + a { + color: var(--primary); + text-decoration: none; + + &:hover { + text-decoration: underline; + } + + &.heading-anchor { + text-decoration: none; + } + + &.nav-card { + text-decoration: none; + color: inherit; + + &:hover { + text-decoration: none; + color: inherit; + } + } + } + + ul, ol { + color: var(--text-four); + margin-bottom: 1rem; + padding-left: 1.5rem; + } + + li { + margin-bottom: 0.5rem; + line-height: 1.6; + } + + code { + font-family: var(--mono-font); + background-color: var(--surface-three); + padding: 0.2em 0.4em; + border-radius: 4px; + font-size: 0.875em; + color: var(--primary); + } + + pre { + margin: 1.5rem 0; + border-radius: 8px; + overflow-x: auto; + } + + pre code { + background: transparent; + padding: 0; + font-size: 0.875rem; + color: inherit; + } + + .shiki { + padding: 1rem 1.25rem; + border-radius: 8px; + overflow-x: auto; + } + + table { + width: 100%; + border-collapse: separate; + border-spacing: 0; + margin: 1.5rem 0; + border: 1px solid var(--border); + border-radius: 12px; + overflow: hidden; + } + + th, td { + padding: 0.75rem 1rem; + text-align: left; + border-bottom: 1px solid var(--tertiary); + color: var(--text-four); + } + + tr:last-child td { + border-bottom: none; + } + + th { + font-weight: 600; + color: var(--text-one); + background-color: var(--surface-three); + } + + blockquote { + border-left: 4px solid var(--primary); + margin: 1.5rem 0; + padding: 1rem 1.5rem; + background-color: var(--tertiary); + border-radius: 0 8px 8px 0; + + p { + margin: 0; + color: var(--text-one); + } + } + + hr { + border: none; + border-top: 1px solid var(--tertiary); + margin: 2rem 0; + } + + strong { + font-weight: 600; + color: var(--text-one); + } + + img { + max-width: 100%; + height: auto; + border-radius: 8px; + } + + picture { + display: inline-block; + max-width: 100%; + } + + .img-placeholder-wrapper { + display: inline-block; + position: relative; + overflow: hidden; + border-radius: 8px; + line-height: 0; + max-width: 100%; + } +} diff --git a/src/lib/components/Button.svelte b/src/lib/components/Button.svelte new file mode 100644 index 0000000..07fc86f --- /dev/null +++ b/src/lib/components/Button.svelte @@ -0,0 +1,111 @@ + + +{#if href && !disabled} + + {#if icon} + {@render icon()} + {/if} + {@render children()} + +{:else} + +{/if} + + diff --git a/src/lib/components/CopyCode.svelte b/src/lib/components/CopyCode.svelte new file mode 100644 index 0000000..39a59c3 --- /dev/null +++ b/src/lib/components/CopyCode.svelte @@ -0,0 +1,111 @@ + + +
+ {@render children()} +
+ + diff --git a/src/lib/components/PageAnchor.svelte b/src/lib/components/PageAnchor.svelte new file mode 100644 index 0000000..9339d96 --- /dev/null +++ b/src/lib/components/PageAnchor.svelte @@ -0,0 +1,100 @@ + + + +
+ {@render children()} +
+ {title} +
+ + \ No newline at end of file diff --git a/src/lib/components/SearchBar.svelte b/src/lib/components/SearchBar.svelte new file mode 100644 index 0000000..d5e7ae1 --- /dev/null +++ b/src/lib/components/SearchBar.svelte @@ -0,0 +1,564 @@ + + +{#snippet searchIcon(size: number)} + + {#if !indexReady && !indexError} + + {:else} + + {/if} + +{/snippet} + +{#snippet searchInput(size: number)} + 0 || query.trim().length > 0 || Boolean(indexError))} + /> +{/snippet} + +{#if mode === 'modal'} + +{:else} +
+
+ {@render searchIcon(18)} + {@render searchInput(14)} + {#if query} + + {/if} +
+ + {#if showDropdown && (indexError || (query.trim() && (results.length > 0 || hasSearched)))} +
+ {#if indexError} +
{indexError}
+ {:else} + (selectedIndex = i)} + /> + {/if} +
+ {/if} +
+{/if} + + diff --git a/src/lib/components/SearchResult.svelte b/src/lib/components/SearchResult.svelte new file mode 100644 index 0000000..bb4683d --- /dev/null +++ b/src/lib/components/SearchResult.svelte @@ -0,0 +1,111 @@ + + + + + diff --git a/src/lib/components/SearchResults.svelte b/src/lib/components/SearchResults.svelte new file mode 100644 index 0000000..f4ad3a6 --- /dev/null +++ b/src/lib/components/SearchResults.svelte @@ -0,0 +1,66 @@ + + +{#if results.length > 0} +
+ {#each results as hit, i} + onselect(hit)} + onhover={() => onhover(i)} + /> + {/each} +
+{:else if query.trim() && hasSearched} +
No results found for "{query}"
+{:else if showHint && !query.trim()} +
Start typing to search the documentation
+{/if} + + diff --git a/src/lib/components/SegmentedButton.svelte b/src/lib/components/SegmentedButton.svelte new file mode 100644 index 0000000..bb76585 --- /dev/null +++ b/src/lib/components/SegmentedButton.svelte @@ -0,0 +1,38 @@ + + +
+ {@render children()} +
+ + diff --git a/src/lib/components/Separator.svelte b/src/lib/components/Separator.svelte new file mode 100644 index 0000000..df0197b --- /dev/null +++ b/src/lib/components/Separator.svelte @@ -0,0 +1,25 @@ + + +
+ + \ No newline at end of file diff --git a/src/lib/components/Spinner.svelte b/src/lib/components/Spinner.svelte new file mode 100644 index 0000000..8fc751c --- /dev/null +++ b/src/lib/components/Spinner.svelte @@ -0,0 +1,17 @@ + + + diff --git a/src/lib/config.ts b/src/lib/config.ts new file mode 100644 index 0000000..28f1e0d --- /dev/null +++ b/src/lib/config.ts @@ -0,0 +1,45 @@ +import type { Component } from 'svelte'; +import rawSitePublicConfig from '$generated/site-public.json'; +import type { SitePublicConfig } from '$lib/core/types'; +import IconCellphone from '~icons/mdi/cellphone'; +import IconConsole from '~icons/mdi/console'; +import IconGithub from '~icons/mdi/github'; +import IconHammer from '~icons/mdi/hammer'; +import IconHelpCircleOutline from '~icons/mdi/help-circle-outline'; +import IconHome from '~icons/mdi/home'; + +const config = rawSitePublicConfig as SitePublicConfig; + +export const SITE_URL = config.siteUrl; + +export const SITE_NAME = config.site.name; +export const ORG_NAME = config.site.org; +export const SITE_TITLE = config.site.title; +export const SITE_DESCRIPTION = config.site.description; +export const LOGO_ASSET_PATH = config.site.logoAssetPath; +export const HEADER_BUTTONS = config.site.headerButtons ?? []; +export const SITE_THEME_COLOR = config.site.themeColor; + +type IconComponent = Component<{ width?: number | string; height?: number | string }>; + +const iconComponents: Record = { + home: IconHome, + hammer: IconHammer, + cellphone: IconCellphone, + console: IconConsole, + github: IconGithub, + 'help-circle-outline': IconHelpCircleOutline, +}; + +const fallbackIcon: IconComponent = IconHelpCircleOutline; + +export const sectionIcons: Record = Object.fromEntries( + Object.entries(config.sections).map(([sectionId, section]) => [ + sectionId, + iconComponents[section.icon] ?? fallbackIcon, + ]), +); + +export function getIconComponent(name: string): IconComponent { + return iconComponents[name] ?? fallbackIcon; +} diff --git a/src/lib/core/graph.ts b/src/lib/core/graph.ts new file mode 100644 index 0000000..63f3205 --- /dev/null +++ b/src/lib/core/graph.ts @@ -0,0 +1,96 @@ +import rawGraph from '$generated/docs-runtime-graph.json'; +import type { RuntimeDocNode, RuntimeDocsGraph } from '$lib/core/types'; + +function invariant(condition: boolean, message: string): asserts condition { + if (!condition) { + throw new Error(message); + } +} + +function validateDocsGraph(input: unknown): RuntimeDocsGraph { + invariant(Boolean(input) && typeof input === 'object', 'Invalid docs runtime graph payload'); + + const graph = input as RuntimeDocsGraph; + invariant(Array.isArray(graph.docs), 'docs runtime graph is missing docs[]'); + invariant(Array.isArray(graph.sections), 'docs runtime graph is missing sections[]'); + + const sectionIds = new Set(); + for (const section of graph.sections) { + invariant( + typeof section.id === 'string' && section.id.length > 0, + 'Section id must be a non-empty string', + ); + invariant( + !sectionIds.has(section.id), + `Duplicate section id '${section.id}' in docs runtime graph`, + ); + sectionIds.add(section.id); + } + + const routePaths = new Set(); + for (const doc of graph.docs) { + invariant( + typeof doc.routePath === 'string' && doc.routePath.startsWith('/'), + `Invalid routePath for ${doc.sourcePath}`, + ); + invariant( + typeof doc.sourcePath === 'string' && doc.sourcePath.endsWith('.md'), + `Invalid sourcePath for ${doc.routePath}`, + ); + invariant( + sectionIds.has(doc.sectionId), + `Unknown section id '${doc.sectionId}' in docs runtime graph`, + ); + invariant( + !routePaths.has(doc.routePath), + `Duplicate route path '${doc.routePath}' in docs runtime graph`, + ); + routePaths.add(doc.routePath); + } + + const knownRoutes = new Set(graph.docs.map((doc) => doc.routePath)); + for (const section of graph.sections) { + for (const routePath of section.pages) { + invariant( + knownRoutes.has(routePath), + `Section '${section.id}' references unknown route '${routePath}'`, + ); + } + } + + return graph; +} + +let cached: { + graph: RuntimeDocsGraph; + byRoutePath: Map; + bySourcePath: Map; +} | null = null; + +function ensureLoaded() { + if (cached) return cached; + + const graph = validateDocsGraph(rawGraph); + cached = { + graph, + byRoutePath: new Map(graph.docs.map((doc) => [doc.routePath, doc])), + bySourcePath: new Map(graph.docs.map((doc) => [doc.sourcePath, doc])), + }; + return cached; +} + +export function getDocsGraph(): RuntimeDocsGraph { + return ensureLoaded().graph; +} + +export function getDocBySourcePath(sourcePath: string): RuntimeDocNode | undefined { + return ensureLoaded().bySourcePath.get(sourcePath); +} + +export function getDocByRoutePath(routePath: string): RuntimeDocNode | undefined { + return ensureLoaded().byRoutePath.get(routePath); +} + +export function getAllDocRoutes(): string[] { + return ensureLoaded().graph.docs.map((doc) => doc.routePath); +} diff --git a/src/lib/core/href-utils.ts b/src/lib/core/href-utils.ts new file mode 100644 index 0000000..ea7c598 --- /dev/null +++ b/src/lib/core/href-utils.ts @@ -0,0 +1,107 @@ +import path from 'node:path'; + +export interface ParsedDocHref { + fullHref: string; + targetPath: string; + hash: string; + query: string; +} + +export function normalizePath(value: string): string { + return value.replace(/\\/g, '/'); +} + +export function splitHref(href: string): { pathname: string; query: string; hash: string } { + let pathname = href; + let query = ''; + let hash = ''; + + const hashIndex = pathname.indexOf('#'); + if (hashIndex >= 0) { + hash = pathname.slice(hashIndex + 1); + pathname = pathname.slice(0, hashIndex); + } + + const queryIndex = pathname.indexOf('?'); + if (queryIndex >= 0) { + query = pathname.slice(queryIndex + 1); + pathname = pathname.slice(0, queryIndex); + } + + return { pathname, query, hash }; +} + +export function isExternalHref(href: string): boolean { + if (href.startsWith('//')) return true; + try { + const parsed = new URL(href); + return parsed.protocol.length > 0; + } catch { + return false; + } +} + +export function parseMarkdownDocHref(href: string): ParsedDocHref | null { + if (href.startsWith('#') || isExternalHref(href)) { + return null; + } + + const { pathname, query, hash } = splitHref(href); + if (!pathname) { + return null; + } + + const extension = path.posix.extname(pathname).toLowerCase(); + if (extension && extension !== '.md') { + return null; + } + + let targetPath = pathname; + if (!extension) { + targetPath = pathname.endsWith('/') ? `${pathname}README.md` : `${pathname}.md`; + } + + return { + fullHref: href, + targetPath, + query, + hash, + }; +} + +export function parseLocalAssetHref(href: string): ParsedDocHref | null { + if (href.startsWith('#') || href.startsWith('/') || isExternalHref(href)) { + return null; + } + + const { pathname, query, hash } = splitHref(href); + if (!pathname || pathname.toLowerCase().endsWith('.md')) { + return null; + } + + return { + fullHref: href, + targetPath: pathname, + query, + hash, + }; +} + +export function resolveDocRelativePath(currentSourcePath: string, targetPath: string): string { + const currentDir = path.posix.dirname(currentSourcePath); + const normalized = targetPath.startsWith('/') + ? path.posix.normalize(targetPath.slice(1)) + : path.posix.normalize(path.posix.join(currentDir, targetPath)); + + if (normalized.startsWith('../') || normalized === '..') { + throw new Error(`Relative path escapes docs root: ${targetPath}`); + } + + return normalized; +} + +export function withQueryAndHash(pathname: string, query: string, hash: string): string { + const queryPart = query ? `?${query}` : ''; + const hashPart = hash ? `#${hash}` : ''; + return `${pathname}${queryPart}${hashPart}`; +} diff --git a/src/lib/core/navigation.ts b/src/lib/core/navigation.ts new file mode 100644 index 0000000..e5c5f28 --- /dev/null +++ b/src/lib/core/navigation.ts @@ -0,0 +1,132 @@ +import type { + ClientDocsSection, + DocsPage, + DocsPagination, + DocsPaginationLink, + DocsSection, +} from '$lib/core/types'; +import { getDocByRoutePath, getDocsGraph } from './graph'; + +function routeSlug(routePath: string, basePath: string): string { + if (!basePath) { + return routePath.slice(1); + } + + const prefix = `/${basePath}/`; + if (!routePath.startsWith(prefix)) { + throw new Error(`Route '${routePath}' does not match section base path '${basePath}'`); + } + + return routePath.slice(prefix.length); +} + +function buildSectionPages(section: { basePath: string; pages: string[] }): DocsPage[] { + return section.pages.map((routePath) => { + const doc = getDocByRoutePath(routePath); + if (!doc) { + throw new Error(`Missing doc for route '${routePath}'`); + } + + return { + slug: routeSlug(routePath, section.basePath), + contentSlug: doc.contentSlug, + title: doc.sidebarLabel, + pageTitle: doc.title, + category: doc.category, + routePath: doc.routePath, + sourcePath: doc.sourcePath, + }; + }); +} + +let cached: { + navigation: DocsSection[]; + routeToPageInfo: Map; + paginationByRoute: Map; +} | null = null; + +function ensureBuilt() { + if (cached) return cached; + + const docsGraph = getDocsGraph(); + + const navigation: DocsSection[] = docsGraph.sections.map((section) => ({ + id: section.id, + title: section.title, + basePath: section.basePath, + isPageAnchor: section.isPageAnchor, + icon: section.icon, + order: section.order, + pages: buildSectionPages(section), + })); + + const routeToPageInfo = new Map(); + for (const section of navigation) { + for (const page of section.pages) { + routeToPageInfo.set(page.routePath, { section, page }); + } + } + + const orderedPages: DocsPaginationLink[] = navigation.flatMap((section) => + section.pages.map((page) => ({ + routePath: page.routePath, + title: page.title, + sectionId: section.id, + sectionTitle: section.title, + sectionIcon: section.icon, + })), + ); + + const paginationByRoute = new Map(); + for (let index = 0; index < orderedPages.length; index += 1) { + const current = orderedPages[index]; + if (!current) continue; + + paginationByRoute.set(current.routePath, { + prev: index > 0 ? (orderedPages[index - 1] ?? null) : null, + next: index < orderedPages.length - 1 ? (orderedPages[index + 1] ?? null) : null, + }); + } + + cached = { navigation, routeToPageInfo, paginationByRoute }; + return cached; +} + +function toClientSection(section: DocsSection): ClientDocsSection { + return { + id: section.id, + title: section.title, + basePath: section.basePath, + isPageAnchor: section.isPageAnchor, + icon: section.icon, + order: section.order, + pages: section.pages.map((page) => ({ + title: page.title, + category: page.category, + routePath: page.routePath, + })), + }; +} + +export function getPageInfoByRoutePath( + routePath: string, +): { section: DocsSection; page: DocsPage } | null { + return ensureBuilt().routeToPageInfo.get(routePath) ?? null; +} + +export function getPageInfo(slug: string[]): { section: DocsSection; page: DocsPage } | null { + const routePath = `/${slug.join('/')}`; + return getPageInfoByRoutePath(routePath); +} + +export function getDocsNavigation(): DocsSection[] { + return ensureBuilt().navigation; +} + +export function getClientDocsNavigation(): ClientDocsSection[] { + return ensureBuilt().navigation.map(toClientSection); +} + +export function getPaginationForRoute(routePath: string): DocsPagination { + return ensureBuilt().paginationByRoute.get(routePath) ?? { prev: null, next: null }; +} diff --git a/src/lib/core/route-data.ts b/src/lib/core/route-data.ts new file mode 100644 index 0000000..b54ce3a --- /dev/null +++ b/src/lib/core/route-data.ts @@ -0,0 +1,29 @@ +import { getDocBySourcePath } from '$lib/core/graph'; +import { getPageInfoByRoutePath, getPaginationForRoute } from '$lib/core/navigation'; +import type { DocsRouteData } from '$lib/core/types'; + +export function useDocsRouteData(slug: string[]): DocsRouteData | null { + const routePath = `/${slug.join('/')}`; + const pageInfo = getPageInfoByRoutePath(routePath); + if (!pageInfo) { + return null; + } + + const entry = getDocBySourcePath(pageInfo.page.sourcePath); + if (!entry) { + throw new Error(`Missing docs graph entry for ${pageInfo.page.sourcePath}`); + } + + return { + id: entry.sourcePath, + slug: routePath.slice(1), + routePath, + entry, + section: pageInfo.section, + page: pageInfo.page, + headings: entry.headings, + title: entry.title, + editUrl: entry.editUrl, + pagination: getPaginationForRoute(routePath), + }; +} diff --git a/src/lib/core/types.ts b/src/lib/core/types.ts new file mode 100644 index 0000000..f3bb151 --- /dev/null +++ b/src/lib/core/types.ts @@ -0,0 +1,171 @@ +export type IconName = string; + +export interface SitePublicConfigSite { + name: string; + org: string; + title: string; + description: string; + logoAssetPath: string; + headerButtons?: SitePublicConfigHeaderButton[]; + themeColor: string; +} + +export interface SitePublicConfigHeaderButton { + href: string; + label?: string; + icon?: IconName; +} + +export interface SitePublicConfigSection { + icon: IconName; +} + +export interface SitePublicConfig { + site: SitePublicConfigSite; + sections: Record; + siteUrl: string; +} + +export interface TableOfContentsHeading { + id: string; + title: string; + level: number; +} + +export interface SearchSection { + heading: string; + anchor: string; + text: string; +} + +export interface DocNode { + sourcePath: string; + workspacePath: string; + workspaceRealPath: string; + sectionId: string; + sectionTitle: string; + contentSlug: string; + slug: string; + routePath: string; + category: string; + title: string; + sidebarLabel: string; + sidebarOrder: number | null; + description: string | null; + headings: TableOfContentsHeading[]; + searchSections: SearchSection[]; + plainText: string; + editUrl: string; +} + +export interface RuntimeDocNode { + sourcePath: string; + sectionId: string; + sectionTitle: string; + contentSlug: string; + slug: string; + routePath: string; + category: string; + title: string; + sidebarLabel: string; + headings: TableOfContentsHeading[]; + editUrl: string; +} + +export interface SectionNode { + id: string; + title: string; + order: number; + basePath: string; + isPageAnchor: boolean; + icon: IconName; + pages: string[]; +} + +export interface AssetMetadataEntry { + width: number; + height: number; +} + +export interface DocsGraph { + generatedAt: string; + docs: DocNode[]; + sections: SectionNode[]; + assets: string[]; + assetMetadata: Record; +} + +export interface RuntimeDocsGraph { + generatedAt: string; + docs: RuntimeDocNode[]; + sections: SectionNode[]; +} + +export interface TableOfContentsItem { + id: string; + title: string; + level: number; + children?: TableOfContentsItem[]; +} + +export interface DocsPage { + slug: string; + contentSlug: string; + title: string; + pageTitle: string; + category: string; + routePath: string; + sourcePath: string; +} + +export interface DocsSection { + id: string; + title: string; + basePath: string; + isPageAnchor: boolean; + icon: IconName; + order: number; + pages: DocsPage[]; +} + +export interface ClientDocsPage { + title: string; + category: string; + routePath: string; +} + +export interface ClientDocsSection { + id: string; + title: string; + basePath: string; + isPageAnchor: boolean; + icon: IconName; + order: number; + pages: ClientDocsPage[]; +} + +export interface DocsPaginationLink { + routePath: string; + title: string; + sectionId: string; + sectionTitle: string; + sectionIcon: IconName; +} + +export interface DocsPagination { + prev: DocsPaginationLink | null; + next: DocsPaginationLink | null; +} + +export interface DocsRouteData { + id: string; + slug: string; + routePath: string; + entry: RuntimeDocNode; + section: DocsSection; + page: DocsPage; + headings: TableOfContentsHeading[]; + title: string; + editUrl: string; + pagination: DocsPagination; +} diff --git a/src/lib/layout/DocsHeader.svelte b/src/lib/layout/DocsHeader.svelte new file mode 100644 index 0000000..f4446cd --- /dev/null +++ b/src/lib/layout/DocsHeader.svelte @@ -0,0 +1,82 @@ + + +
+

{title}

+ + {#if showCopyButton} +
+ + + + +
+ {/if} +
+ + diff --git a/src/lib/layout/DocsSidebar.svelte b/src/lib/layout/DocsSidebar.svelte new file mode 100644 index 0000000..f0af00c --- /dev/null +++ b/src/lib/layout/DocsSidebar.svelte @@ -0,0 +1,158 @@ + + + + + diff --git a/src/lib/layout/Header.svelte b/src/lib/layout/Header.svelte new file mode 100644 index 0000000..459f1ef --- /dev/null +++ b/src/lib/layout/Header.svelte @@ -0,0 +1,349 @@ + + + + +{#if mobileSearchOpen} + mobileSearchOpen = false} /> +{/if} + + diff --git a/src/lib/layout/PageNavigation.svelte b/src/lib/layout/PageNavigation.svelte new file mode 100644 index 0000000..cf29fdc --- /dev/null +++ b/src/lib/layout/PageNavigation.svelte @@ -0,0 +1,126 @@ + + +{#if prevPage || nextPage} + +{/if} + + diff --git a/src/lib/layout/SidebarNavList.svelte b/src/lib/layout/SidebarNavList.svelte new file mode 100644 index 0000000..0ac651f --- /dev/null +++ b/src/lib/layout/SidebarNavList.svelte @@ -0,0 +1,124 @@ + + +{#snippet sectionGroups(groups: { category: string; pages: ClientDocsPage[] }[], fallbackLabel?: string)} + {#each groups as group (group.category)} + + {/each} +{/snippet} + + + + diff --git a/src/lib/layout/SidebarPageAnchors.svelte b/src/lib/layout/SidebarPageAnchors.svelte new file mode 100644 index 0000000..e6b6a78 --- /dev/null +++ b/src/lib/layout/SidebarPageAnchors.svelte @@ -0,0 +1,40 @@ + + +
+ {#each sections as section (section.id)} + {@const SectionIcon = sectionIcons[section.id]} + + {#if SectionIcon}{/if} + + {/each} +
+ + diff --git a/src/lib/layout/TableOfContents.svelte b/src/lib/layout/TableOfContents.svelte new file mode 100644 index 0000000..91d224a --- /dev/null +++ b/src/lib/layout/TableOfContents.svelte @@ -0,0 +1,220 @@ + + +{#if items.length > 0} + +{/if} + + diff --git a/src/lib/utils/copy.ts b/src/lib/utils/copy.ts new file mode 100644 index 0000000..8068eaf --- /dev/null +++ b/src/lib/utils/copy.ts @@ -0,0 +1,42 @@ +export async function copyToClipboard(text: string): Promise { + if (navigator.clipboard?.writeText) { + try { + await navigator.clipboard.writeText(text); + return true; + } catch (_error) {} + } + + const ta = Object.assign(document.createElement('textarea'), { + value: text, + style: 'position:fixed;top:0;left:0;opacity:0;pointer-events:none', + }); + document.body.appendChild(ta); + try { + ta.select(); + return document.execCommand('copy'); + } finally { + ta.remove(); + } +} + +export function createCopyStatus(setStatus: (message: string | null) => void, resetMs = 2000) { + let timer: ReturnType | null = null; + + function set(message: string) { + setStatus(message); + if (timer) clearTimeout(timer); + timer = setTimeout(() => { + setStatus(null); + timer = null; + }, resetMs); + } + + function clear() { + if (timer) { + clearTimeout(timer); + timer = null; + } + } + + return { set, clear }; +} diff --git a/src/lib/utils/paths.ts b/src/lib/utils/paths.ts new file mode 100644 index 0000000..424fd8b --- /dev/null +++ b/src/lib/utils/paths.ts @@ -0,0 +1,35 @@ +import { base, resolve } from '$app/paths'; + +function stripTrailingSlash(pathname: string): string { + if (pathname.length <= 1) { + return pathname || '/'; + } + return pathname.replace(/\/+$/, ''); +} + +function normalizedBasePath(): string { + const rawBase = base || '/'; + const basePath = rawBase.startsWith('/') ? rawBase : `/${rawBase}`; + return stripTrailingSlash(basePath); +} + +export function normalizePathname(pathname: string): string { + const normalizedPathname = stripTrailingSlash(pathname || '/'); + const normalizedRootHref = normalizedBasePath(); + + if (normalizedRootHref === '/') { + return normalizedPathname; + } + if (normalizedPathname === normalizedRootHref) { + return '/'; + } + if (normalizedPathname.startsWith(`${normalizedRootHref}/`)) { + return normalizedPathname.slice(normalizedRootHref.length) || '/'; + } + + return normalizedPathname; +} + +export function resolveRoutePath(routePath: string): string { + return resolve(routePath as `/${string}`); +} diff --git a/src/lib/utils/rehype-plugins.ts b/src/lib/utils/rehype-plugins.ts new file mode 100644 index 0000000..841d52d --- /dev/null +++ b/src/lib/utils/rehype-plugins.ts @@ -0,0 +1,277 @@ +import { existsSync, readFileSync, statSync } from 'node:fs'; +import path from 'node:path'; +import type { Element, Root as HastRoot, Parent } from 'hast'; +import { visit } from 'unist-util-visit'; +import type { VFile } from 'vfile'; +import { + normalizePath, + parseLocalAssetHref, + parseMarkdownDocHref, + resolveDocRelativePath, + withQueryAndHash, +} from '../core/href-utils.js'; + +type NodeProperties = Record; + +interface DocsGraphConfig { + docs: Array<{ + sourcePath: string; + routePath: string; + workspacePath: string; + workspaceRealPath: string; + }>; + assets: string[]; + assetMetadata: Record; +} + +interface DocsGraphContext { + sourceToRoute: Record; + filePathToSourcePath: Record; + assetPathSet: Set; + assetMetadataByPath: Record; +} + +function withBasePath(pathname: string, siteBasePath: string): string { + if (!siteBasePath || siteBasePath === '/') { + return pathname; + } + const normalizedBase = siteBasePath.endsWith('/') ? siteBasePath.slice(0, -1) : siteBasePath; + return `${normalizedBase}${pathname}`; +} + +function inferSourcePath( + filePath: string, + filePathToSourcePath: Record, +): string | null { + const normalized = normalizePath(filePath); + const cwdRelative = normalizePath(path.relative(process.cwd(), normalized)); + const candidates = [ + normalized, + normalized.replace(/^\.\//, ''), + cwdRelative, + cwdRelative.replace(/^\.\//, ''), + ]; + + const docsIndex = normalized.lastIndexOf('/docs/'); + if (docsIndex !== -1) { + candidates.push(normalized.slice(docsIndex + '/docs/'.length)); + } + + for (const candidate of candidates) { + const sourcePath = filePathToSourcePath[candidate]; + if (sourcePath) { + return sourcePath; + } + } + + return null; +} + +function getProperties(node: Element): NodeProperties { + if (!node.properties) { + node.properties = {}; + } + return node.properties as NodeProperties; +} + +function parseNumericDimension(value: unknown): number | null { + if (typeof value === 'number' && Number.isFinite(value) && value > 0) { + return value; + } + + if (typeof value !== 'string') { + return null; + } + + const normalized = value.trim().toLowerCase(); + if (!normalized || normalized.endsWith('%')) { + return null; + } + + const numericPart = normalized.endsWith('px') ? normalized.slice(0, -2).trim() : normalized; + const parsed = Number.parseFloat(numericPart); + return Number.isFinite(parsed) && parsed > 0 ? parsed : null; +} + +function createPlaceholderStyle(width: number | null, height: number | null): string | undefined { + if (!width || !height) { + return undefined; + } + + return [ + `width:min(100%,${width}px)`, + `max-width:${width}px`, + `aspect-ratio:${width}/${height}`, + ].join(';'); +} + +function wrapWithImagePlaceholder(node: Element): Element { + const properties = getProperties(node); + const width = parseNumericDimension(properties.width); + const height = parseNumericDimension(properties.height); + const style = createPlaceholderStyle(width, height); + + return { + type: 'element', + tagName: 'span', + properties: { + className: ['img-placeholder-wrapper'], + ...(style ? { style } : {}), + }, + children: [ + { + type: 'element', + tagName: 'span', + properties: { className: ['spinner', 'img-spinner'], 'aria-hidden': 'true' }, + children: [], + }, + node, + ], + }; +} + +interface RehypeDocLinksOptions { + docsGraphPath: string; + siteBasePath: string; + assetsPublicPath: string; +} + +let cachedGraphContext: DocsGraphContext | null = null; +let cachedGraphMtimeMs = -1; + +function loadGraphContext(docsGraphPath: string): DocsGraphContext { + if (!existsSync(docsGraphPath)) { + throw new Error( + `Missing docs graph at ${docsGraphPath}. Start dev/build so docs generation plugin can run.`, + ); + } + + const mtimeMs = statSync(docsGraphPath).mtimeMs; + if (cachedGraphContext && mtimeMs === cachedGraphMtimeMs) { + return cachedGraphContext; + } + + const docsGraph = JSON.parse(readFileSync(docsGraphPath, 'utf-8')) as DocsGraphConfig; + const sourceToRoute = Object.fromEntries( + docsGraph.docs.map((doc) => [doc.sourcePath, doc.routePath]), + ); + const filePathToSourcePath = Object.fromEntries( + docsGraph.docs.flatMap((doc) => [ + [doc.sourcePath, doc.sourcePath], + [`docs/${doc.sourcePath}`, doc.sourcePath], + [doc.workspacePath, doc.sourcePath], + [doc.workspaceRealPath, doc.sourcePath], + ]), + ); + const context: DocsGraphContext = { + sourceToRoute, + filePathToSourcePath, + assetPathSet: new Set(docsGraph.assets), + assetMetadataByPath: docsGraph.assetMetadata ?? {}, + }; + + cachedGraphContext = context; + cachedGraphMtimeMs = mtimeMs; + return context; +} + +export function rehypeDocLinks({ + docsGraphPath, + siteBasePath, + assetsPublicPath, +}: RehypeDocLinksOptions): (tree: HastRoot, vfile: VFile) => void { + return (tree: HastRoot, vfile: VFile) => { + const { sourceToRoute, filePathToSourcePath, assetPathSet, assetMetadataByPath } = + loadGraphContext(docsGraphPath); + const fileMeta = vfile as VFile & { filename?: string; path?: string }; + const filePath = fileMeta.filename || fileMeta.path || fileMeta.history?.[0]; + if (!filePath) { + return; + } + + const sourcePath = inferSourcePath(filePath, filePathToSourcePath); + if (!sourcePath || !sourceToRoute[sourcePath]) { + return; + } + + visit(tree, 'element', (node: Element, index, parent) => { + if (node.tagName === 'a') { + const properties = getProperties(node); + const href = properties.href; + if (typeof href === 'string') { + const parsed = parseMarkdownDocHref(href); + if (parsed) { + const resolvedSourcePath = resolveDocRelativePath(sourcePath, parsed.targetPath); + const routePath = sourceToRoute[resolvedSourcePath]; + if (!routePath) { + throw new Error( + `Unresolved markdown link '${href}' in '${sourcePath}' (resolved '${resolvedSourcePath}')`, + ); + } + + const routeWithBase = withBasePath(routePath, siteBasePath); + properties.href = withQueryAndHash(routeWithBase, parsed.query, parsed.hash); + } + } + return; + } + + if (node.tagName !== 'img') { + return; + } + + const properties = getProperties(node); + const src = properties.src; + if (typeof src !== 'string') { + return; + } + + let metadataAssetPath: string | null = null; + const parsedAsset = parseLocalAssetHref(src); + if (parsedAsset) { + const resolvedAssetPath = resolveDocRelativePath(sourcePath, parsedAsset.targetPath); + if (assetPathSet.has(resolvedAssetPath)) { + metadataAssetPath = resolvedAssetPath; + const normalizedAssetsPath = assetsPublicPath.replace(/\/+$/, ''); + const assetUrl = `${normalizedAssetsPath}/${resolvedAssetPath}`; + const assetWithBase = withBasePath(assetUrl, siteBasePath); + properties.src = withQueryAndHash(assetWithBase, parsedAsset.query, parsedAsset.hash); + } else if (resolvedAssetPath.startsWith('assets/')) { + const staticAssetPath = withBasePath(`/${resolvedAssetPath}`, siteBasePath); + properties.src = withQueryAndHash(staticAssetPath, parsedAsset.query, parsedAsset.hash); + } else { + throw new Error( + `Unresolved image link '${src}' in '${sourcePath}' (resolved '${resolvedAssetPath}')`, + ); + } + } + + if (metadataAssetPath) { + const metadata = assetMetadataByPath[metadataAssetPath]; + if (metadata) { + properties.width ??= metadata.width; + properties.height ??= metadata.height; + } + } + + properties.loading ??= 'lazy'; + properties.decoding ??= 'async'; + + const parentNode = parent as Parent | undefined; + if (!parentNode || typeof index !== 'number') { + return; + } + + const parentElement = parentNode as Element; + if (parentElement.type === 'element' && parentElement.tagName === 'picture') { + return; + } + + if (!Array.isArray(parentNode.children)) { + return; + } + + parentNode.children[index] = wrapWithImagePlaceholder(node); + }); + }; +} diff --git a/src/lib/utils/search.ts b/src/lib/utils/search.ts new file mode 100644 index 0000000..972d9f1 --- /dev/null +++ b/src/lib/utils/search.ts @@ -0,0 +1,171 @@ +import MiniSearch from 'minisearch'; +import { resolve } from '$app/paths'; + +const SEARCH_FUZZY = 0.15; +const SEARCH_PREFIX = true; +const SEARCH_COMBINE_WITH = 'AND' as const; +const SNIPPET_MAX_LENGTH = 140; +const SNIPPET_CONTEXT_CHARS = 40; +const SNIPPET_ELLIPSIS = '...'; +const HIGHLIGHT_TAG = 'mark'; + +const MINISEARCH_OPTIONS = { + fields: ['title', 'text', 'section'], + storeFields: ['title', 'section', 'sectionId', 'sectionIcon', 'url', 'anchor', 'text'], + searchOptions: { + boost: { title: 4, section: 2, text: 1 }, + fuzzy: SEARCH_FUZZY, + prefix: SEARCH_PREFIX, + combineWith: SEARCH_COMBINE_WITH, + }, +}; + +let instance: MiniSearch | null = null; +let loadPromise: Promise | null = null; + +export function getIndex(): MiniSearch | null { + return instance; +} + +export function isReady(): boolean { + return instance !== null; +} + +export async function ensureIndex(): Promise { + if (instance) return instance; + if (loadPromise) return loadPromise; + + loadPromise = (async () => { + try { + const res = await fetch(resolve('/search-index.json')); + if (!res.ok) throw new Error(`Failed to fetch search index: ${res.status}`); + const json = await res.text(); + instance = MiniSearch.loadJSON(json, MINISEARCH_OPTIONS); + return instance; + } catch (e) { + loadPromise = null; + console.error('Failed to load search index:', e); + throw e; + } + })(); + + return loadPromise; +} + +export interface SearchHit { + id: string; + title: string; + section: string; + sectionId: string; + sectionIcon: string; + url: string; + anchor: string; + text: string; + score: number; +} + +interface SearchIndexResult { + id: string | number; + title: string; + section: string; + sectionId: string; + sectionIcon?: string; + url: string; + anchor: string; + text: string; + score: number; +} + +export function search(query: string): SearchHit[] { + const ms = getIndex(); + if (!ms || !query.trim()) return []; + + const raw = ms.search(query, { + combineWith: SEARCH_COMBINE_WITH, + }); + + return raw.map((result) => { + const entry = result as unknown as SearchIndexResult; + return { + id: String(entry.id), + title: entry.title, + section: entry.section, + sectionId: entry.sectionId, + sectionIcon: entry.sectionIcon ?? '', + url: entry.url, + anchor: entry.anchor, + text: entry.text, + score: entry.score, + }; + }); +} + +function escapeHtml(str: string): string { + return str.replaceAll('&', '&').replaceAll('<', '<').replaceAll('>', '>'); +} + +function escapeRegex(text: string): string { + return text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); +} + +function queryTerms(query: string): string[] { + return query.trim().toLowerCase().split(/\s+/).filter(Boolean); +} + +function matchRegex(query: string): RegExp | null { + const terms = query.trim().split(/\s+/).filter(Boolean); + if (terms.length === 0) return null; + + return new RegExp(`(${terms.map(escapeRegex).join('|')})`, 'gi'); +} + +export function highlightMatch(text: string, query: string): string { + const escaped = escapeHtml(text); + const regex = matchRegex(query); + if (!regex) return escaped; + return escaped.replace(regex, `<${HIGHLIGHT_TAG}>$1`); +} + +export function getSnippet(text: string, query: string, maxLen = SNIPPET_MAX_LENGTH): string { + const normalizedText = text.replace(/\s+/g, ' ').trim(); + if (!normalizedText) { + return ''; + } + + const snippetLength = maxLen > 0 ? maxLen : 1; + if (normalizedText.length <= snippetLength) { + return normalizedText; + } + + const lowerText = normalizedText.toLowerCase(); + const terms = queryTerms(query); + let matchIndex = 0; + + for (const term of terms) { + const index = lowerText.indexOf(term); + if (index >= 0) { + matchIndex = index; + break; + } + } + + let snippetStart = matchIndex - SNIPPET_CONTEXT_CHARS; + if (snippetStart < 0) { + snippetStart = 0; + } + + let snippetEnd = snippetStart + snippetLength; + if (snippetEnd > normalizedText.length) { + snippetEnd = normalizedText.length; + } + + let snippet = normalizedText.slice(snippetStart, snippetEnd).trim(); + if (snippetStart > 0) { + snippet = `${SNIPPET_ELLIPSIS}${snippet}`; + } + if (snippetEnd < normalizedText.length) { + snippet += SNIPPET_ELLIPSIS; + } + + return snippet; +} diff --git a/src/routes/+error.svelte b/src/routes/+error.svelte new file mode 100644 index 0000000..d2a27fb --- /dev/null +++ b/src/routes/+error.svelte @@ -0,0 +1,51 @@ + + + + Error {page.status} | {SITE_TITLE} + + +
+ {page.status} +

{page.error?.message || 'Something went wrong'}

+ Back to home +
+ + diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte new file mode 100644 index 0000000..fa7834e --- /dev/null +++ b/src/routes/+layout.svelte @@ -0,0 +1,232 @@ + + + + + + + + + + +
+ +
+ + +
+ +
+ {#if isDocPage} + + {/if} +
+ {@render children()} +
+ {#if isDocPage} + + {/if} +
+
+
+ + {#if hasToc} + + {/if} +
+ + diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte new file mode 100644 index 0000000..11dee91 --- /dev/null +++ b/src/routes/+page.svelte @@ -0,0 +1,42 @@ + + + + {SITE_TITLE} + + + +
+

Welcome to {SITE_TITLE}

+
+ + diff --git a/src/routes/+page.ts b/src/routes/+page.ts new file mode 100644 index 0000000..189f71e --- /dev/null +++ b/src/routes/+page.ts @@ -0,0 +1 @@ +export const prerender = true; diff --git a/src/routes/[...slug]/+page.server.ts b/src/routes/[...slug]/+page.server.ts new file mode 100644 index 0000000..4feb2e7 --- /dev/null +++ b/src/routes/[...slug]/+page.server.ts @@ -0,0 +1,39 @@ +import { error } from '@sveltejs/kit'; +import { getAllDocRoutes } from '$lib/core/graph'; +import { useDocsRouteData } from '$lib/core/route-data'; +import type { PageServerLoad } from './$types'; + +export const prerender = true; + +export function entries() { + return getAllDocRoutes().map((route) => { + const slug = route.slice(1); + return { slug }; + }); +} + +export const load: PageServerLoad = ({ params }) => { + if (!params.slug) { + throw error(404, 'Page not found'); + } + + const slug = params.slug.split('/'); + const routeData = useDocsRouteData(slug); + if (!routeData) { + throw error(404, 'Page not found'); + } + + const sourcePath = routeData.page.sourcePath; + if (!sourcePath.endsWith('.md') || sourcePath.includes('..')) { + throw error(500, 'Invalid source path for docs page'); + } + + return { + sourcePath, + title: routeData.title, + section: routeData.section.title, + headings: routeData.headings, + editUrl: routeData.editUrl, + pagination: routeData.pagination, + }; +}; diff --git a/src/routes/[...slug]/+page.svelte b/src/routes/[...slug]/+page.svelte new file mode 100644 index 0000000..8bd02a7 --- /dev/null +++ b/src/routes/[...slug]/+page.svelte @@ -0,0 +1,16 @@ + + + + {data.title} - {data.section} | {SITE_TITLE} + + + + diff --git a/src/routes/[...slug]/+page.ts b/src/routes/[...slug]/+page.ts new file mode 100644 index 0000000..95d1b5c --- /dev/null +++ b/src/routes/[...slug]/+page.ts @@ -0,0 +1,24 @@ +import { error } from '@sveltejs/kit'; +import type { Component } from 'svelte'; +import type { PageLoad } from './$types'; + +const components = import.meta.glob('/docs/**/*.md'); + +export const load: PageLoad = async ({ data }) => { + const sourcePath = data.sourcePath; + if (typeof sourcePath !== 'string' || !sourcePath.endsWith('.md')) { + throw error(500, 'Missing source path for docs page'); + } + + const componentPath = `/docs/${sourcePath}`; + const loader = components[componentPath]; + if (!loader) { + throw error(404, 'Page content not found'); + } + + const component = (await loader()) as { default: Component }; + return { + ...data, + component: component.default, + }; +}; diff --git a/src/routes/search-index.json/+server.ts b/src/routes/search-index.json/+server.ts new file mode 100644 index 0000000..22f3d68 --- /dev/null +++ b/src/routes/search-index.json/+server.ts @@ -0,0 +1,37 @@ +import { readFileSync } from 'node:fs'; +import { join } from 'node:path'; +import type { RequestHandler } from './$types'; + +export const prerender = true; + +let cachedSearchIndex: string | null = null; + +function getSearchIndex(): string | null { + if (cachedSearchIndex !== null) { + return cachedSearchIndex; + } + + try { + cachedSearchIndex = readFileSync( + join(process.cwd(), '.svelte-kit/generated/search-index.json'), + 'utf-8', + ); + return cachedSearchIndex; + } catch { + return null; + } +} + +export const GET: RequestHandler = () => { + const searchIndex = getSearchIndex(); + if (searchIndex === null) { + return new Response(JSON.stringify({ error: 'Search index is not available yet.' }), { + status: 503, + headers: { 'Content-Type': 'application/json; charset=utf-8' }, + }); + } + + return new Response(searchIndex, { + headers: { 'Content-Type': 'application/json; charset=utf-8' }, + }); +}; diff --git a/static/favicon.ico b/static/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..0a4ba62047862221c80b95a793c80a4acb67a6c3 GIT binary patch literal 20239 zcmYhi1yq||6D}H{xVuAfcXucSiWPTv_u^V;p)Kz2?(V_eDef*sL$Tnw>Gz*|)`7($ zkj%{9GqcC`^8x@c(C>d=Fo5@f$Ik!&0rd4x)z5P1C?qJ*m+11JKC1tF_umf^0`!-m zdztmWzg*luYr@PFcxM0rpBv>rN@@D6U1TF_YU!-Kf&WZeT6J?g&P*yS(K4s3;CB9G z`-L9wh1#Xl8H(Pit6EP@{XW!4^SleZP;12mrlA_g+a z59v4IqSUou!-PS$<9G49L@Z@D==IyqZT7m!nokzOc9b+V?X*8U(8iVDd{t6eDNag% zxkU2}60E}ncN~g728Nf zi(A>VEi7z^OWjm*8M)gdf^9$HA2j0~1%qnX+n3-16?UWp75ZtUPcK=e?di`}Ee3e~ zGQV-xU%C^6UG;F=C#A?Zaya_Q8YOsq_ICNGygasw3CGu+ER zW8*)i;Xl_(9rOnM(Ky{)EWPh?No%?LYUZ~DH+7)E?H5UUShsbPkZv*}2B5$O>LdqFy2T1r?M{M+WAgvIis*A#R(TQ^zT0!{O`0=_(-G z5*9M6qYxhzI35F^=o?v`Tc$5dbn!8QpNou~RX-$7)G6b)WJ3-H@%gaDK8eEScqh z{>@wJON;J+^@)m)e5_kR8hv=&iX~3@gqx&|l53FT&LB>aYqZ#-TwUmEq2}kEhyC`r z2!$-dgL3p^wziV6l;zcyu4Z7aoBZ7Pb%P!qgo=Q*7l4VZd$o) zhWYCyXQ%K_#3{(sZx6qUw17iq*iQw<%m^NxT4qW ztfYz6mQoL8$q&563fbC~F$UP-gD* zG*|*$3hQ}yau^3>WcFW(!^L~>PO4TL(%07;aZO)#T~$LAa6f(LnV9Pt+ag11!l~pT zmsxlLu0zBSVfghRi;WVs7sua1PV>ZvgjIT1Zm!UHNjH5`%GYU`)&5d(c1~GS4|5|e zV7R*BY&UqECq0eK+bR=$sx}j*uVp8xH6C>B0QyPgsrKDSnL+%SD&t74pRA^XhS zIWovlAhB8agHitUb*0z?nMA?V%&A7EveQ!IJ0NG1nn=A~H72mj&MWe5FUzb%a8SC3 zb;fG%o3nj!H6*9t--0w0#y$t_nq-zPSvIkgj=xo4ZupCh zrvIAL$blP057y6kA72~8iL-g48hL8!>aX>eO?8*#jZoNZ`O-QTJxho2&uniV_U0xG zM1@E7EI%6Y9huHn*JNr(Fto9oEI9-<5d(X3{xpm*y}f#z$KPRC3}GNWZIPRzx=m)rN|D z_W?X@M?8h9%*wP|3EN}TmdkE{j?(voGgrfIfeIQI##n~f*ZR!XE$6k8%)jg+_dnK` zTeR9?#1Ud{NlXVJ>PxU1T=7SRUelcQ=L) zJLe0_Fl;T`Z_*BHn=ZBUjO8Dl;QubSlibDrlQPE!RAnb3>v;IP*CscxB##-z&U~I? zFLYhBUPVCW`MFHI`A%!LcE=b&&a?%H=l}H29NDIyKMJsX2%=nHl@QXeSsdFwo#Qp^wAI*ndBY?iJkqff|M~f@9Ph@8&|baV zc$&`vKIk{nyW(bk(jlkT*mW!?U-s0TkezCan#Phohmp;>j{!HI;+-WFzUmU$WorO+ z4+Ygk(Knd9&NMPzu~xhhqLWzI@;n?<3TqmF$`M%VR3j&k`R>T}Y2CuYtWDS0<2p}t z>t_}?{T^<=8*^K3fA&7p$Os^8QmpzCh3~LfGX$U75xmRcMOqR$C5lP9-Q+(O7*5>B zuyM30G=-i?n(d}is`26x|7v?(aUyx>G+r+BX3!uT(sEm|s_n3@A>@>8(9`Sjj5Z%O z!i&z){=+T`FueImxat?Tf#Jp@ATXH3+Q)QN~Ax0?Dr<+ zRHZJGcXOqOmG&%?C^@a53YfK)WkMKzgTg75!*_v-@Su7`ixiQ;?w&9)-wE$7qD4(H z%_ND)z-k24zuj1fhR46qr+@Mz8XXtqx|&?=(Fzn43lGr?p7O`y7@)mhXGRYSyflKj zx!;llvxNtFVe!`zGtVluYk6hlYCn{8Tl4t2Qjn|v9A~h0 zxvzg%I`4-11vdJ!{>PFKgQ~63^0}O=R;@`@3B0XGlb9%gqZgOJm+6>6v^~Acci5r) zlWFaA3uSrlRAf`H8Ss;Xh-?6~ zz{~y(z`>>nA>2Xsp%K^;J`e}Niaz1{d$Rj`b+5(odfU}oWa)lG7p6>DaZcMEyRxAe zs@wcP4mMOG_0%Xg62q*>^9wA_djD@ZR|ujBq_KU4>u5Z{tFE}KOY=L;{Kpd$$WyBB zDQ`MHN9ZYuqNBj{sn4v~>lk*-Y|0VvJ_B zA^zeSOP3ojAQsJbL+u6)Xi*N@(ev?caso+kcziZhVPLAWno}@pAOMs!QQR+I)OZwN zv~j%rjTAJL| zc+J8Oo_q&7PJ7Vzk=;AbbKectq*G2~ zB{PCwS|rX1M560Ljw9_lawpf0!#F1#f8TQp`=1Bo^!oWLH zia^wvMsSyNI63~lz6=+pbR^@PUvH}WhbjUVBb(N(qjp*k2Av=6YeV?Cwv^JI zEKAx~EcgmoAz+-9u&V+(ig2(FiA^g4>K=rPbjq)5^C}_``+W?&BO&Pq;jiNG^yXF{ zcJZFD2(=^o(q)ui4m_duf$GxGRg_5qD83Qy$}0lV5K@S3mbP~4Rmm_nsD$~Df+Ai1 zdMaB?;h#L&@so-XfVPJ5O=DUdl3PN}FJx7xP;!|blB*7kzs{^A{>~6+%{;L~Vh#Cu zI5~{6?CZkt;^C<`*k-V$j|&x#$H-=B=OlRNasNqOe5pZb#W?0mmim zXZoaUhgnD3P0J=*+8-ho>kitVeN)d#hWquL){V>8ga$ramN6~9wFUC`g^P72V-=-v zSByaWnx4KvlGxj{uTwON)27-9WDMQpS8}Z}I5hg`1cU=IKk+Y7Lk0ZUAVEBG@*Yi# zHhgqK!xiun#nknjNVWZqM^9vqA@QhYazjW*24}e!J+kG|*)e?mVqfBXt;TE)wfcAOT{Dlso^U-F9#cd#{IR41QN77I z6k1h?OsbdT!G=Ji2ZGfN(HpCSv7P-5v0^k$4U*K0M4a>+v?cCCEY z$PjwbR@!^fWY*Df!}Kv&g<(viXGrQpk2z5{33+udx~`}7*@0C{^$$D?^=^n4<>FSf z#RaTT+2N(j>3w}`ju@9A`G=Ep_PL7%L9b6sm=NB9FI=(5?2S>4koJCuAp#5p%b2C7 zs^YI~h^p|SGqrxf#jU1z0O;wzYH1e@$=4g!gD6>)sHd}4ex_NEBKXO!(X^fF!%p5! zq85cpRoUEq#<=809jL#n(VQMJXV6@ZB#Q1buz$n}6W*KPB@wNdKx9T~(FJ2F-K$-{ z;otlTth?d&9eg@cDY#d?_hHnQPiInT-_hQ%`KSJ^h93(d{4O+j8K)k?qJ1qUD;Y$9 zR4*Y1SDcZ>ALX!Hx0eLAP5Lk9BxkwlRbT7LMT(}z=f|k^)!u3&!a&I)j;G8lnRwt^ zdUY$BjY!CxXQYDzEAF4EYw-tCY3v`z?X&M29p+t~M69jwid*%r1c7e`pa~?UuWXzt zd5YKr=W=?#OLDd<2dS4tXXunupQ?PDvQX(O@qWu$z_b0WY~ zX7G+*>t(iB_>QWmhdgE^a0hUfo4|yRRmMGd#K{ZpH6bU?b_=?jC#9MjOK>YU^P5L@ zXlVmzL~stK&I#hhuDhUB_q;!|MTsj|O>&c9<5l0EppM+shZ+WAHY>JUJ!#|I=W_hu zVsl?Bz!oB$B3=5}QpfR4m$nyz$3?~$JTZL?#=-9r;P2)&%kEt39`eQC#T|GEJP@p! z7hGuWT*RWrE6-jPhQ2TZKw&U-rWhio=#yW&G%1kr6iALZrD)ry@#Cu_lF~q3^g;0; zgoH(NcGm!NHR-WXN7WF>lFfVRP!wTDov zoNOOIIj;!i@`$Q@SOu+rf{7L>laZh+)`@!8J1mOs=v&hJURUYPkbU^f<|r7jvb^7| zi&dvQd96p9anyPu6lux39gG_7E?>ZWSXmCpE4m#g{Z_$6qrt0f*$x|Kimh~c;VTfl z8|z{6UcF1_Cmtx7a{BMOk8RDib%GknjFa_472WfiAK$Hxy5Btehe;$|7@mfJuQJxx zaCOAT{1On@-q&5)BWMob30U^d*zb8HBp734Gi8x!A(lUM9Ip)5R`(0*{l8=l`@r6d zJ$Jmr`HgMQoV3%fjONn;y`apP$s@C0QAc$Nz!Z)B)0PUbj(S47a+{w=M*rkwyd@fJ z;@BiT5jiLYbDO=X#MwVBRP@L{E5O=zr<2t&Zm1lni8Mdw~;SBQ_t4d$X2`)!K6dJtOXrfB(?&g zWy4zP37tYnlOg1sv=gK&O6IbqoR$06*CGfSLKRBjZD#cVfv2mPT^VTtTKGU;#&6rQz z8N=xqwj}vAk1R}wM@R3i|4|{z_A#fyceeN3gSr%=+%t8!SA!?c@x;GIsl&C-3+D7J zR2Z7vy(uWP6T@>#n<6WXU5`{vlN<`yS{gc2;*fxv)oGucteq<2$?7h)G-Ez;Da_OwY$*|<#3qmHBx&^KeNixSn;P%^COhOFCtw5M$T_K8RC1xkhEBxr0?8G2~{E*ciM)nF>s2eD2`+9 zNY)IGP7eUI*lR<_AVAum8EHuGg}HmLcI#j-`Ah=rV;+5TBK=cM=`i2 z#>QaQj~TAzt&;GXGW~>=3*6VNDTgrMn6)ZqH`+Z;RvT?@J8o}JG)}j=I+q%|YL07d zHF8S$Pd;JZX`GM_+)`J|86qUXTlsB%0(gFf&h>%p`Jds^OVB9$-B~IwZ5x6v_-1>d$#kok-zBpqb@; zpGAw8WvE%5=v>xNZxTkS%!gSDY{EJ*>YQV8ZiSsuyhHxj3eAVA72{_Upbytr(eX^K z#&V63iQPf4n{>qT?|Ha=r4E~{zuJGqQ{kmThxYr;X@qo zLX6dQs+o-Dl#7-2Svv-<@T~ID7*WS>N3a3oF~X8Yqx1`IZrxl+QD6D=*!N+*oM9*S zU--xSC@&iIm5?^r>EAilQW7?uxsl0{5=Y-}O6Kag7&~&j<};vTVy0%m0u52GZf^q) z8S_Gwg)+?6BQM*g^D}E2Bb!wJGm=(zKE@U=7_yHC@H8YV1#oa62ff*OME@tvTPz2w zuA1V8wV+EU0|OB3r}IO;?^y`x{9GU&^L?RwpFdN-P`)nv+iQzJrBNq;wwV7?)z;+j z@KN%OSSK_3Ntz;#k$1M@GEqSR;{myqq@Hmz`?rQn9{UfQ1u>B~0`gzE>JW}BAG5I9 z3QYn=gW9osZ6R#tP1{F3%19f{d?^x+`uCRBQkPRESzxmh%AZ&+p-UwouXLDkwdk1aduiE$c7Nwyxm}44u>5soy_99c?bAx&0xYoq9+3q2?2GzS;E$`ik=yoMo z9)0bANHKNecwQ#FoDtbqc1tZh)})^O8+YM(1G49@4z^1e0MtaBi1(I6@Drvaj+pm; z1H7h=jF_)sU^lE4e6G*Wd3MT3TPoya^l{4R4W~;}WK&r}8fz=593~}CcV|7qNUj#% zRcErL#AP063qq~b)YB~2QNSL1%^wW~lZ>5?AF`QU4wbUg{vRo^m?971@RB{s=4qg( zo+#wCE^}5nLZOR%ev=0e>EI#~1{*WQ()r)ZCc$i0=Y$-_s*tx=llHn|qbDYV_@g!S z(nbo@lcwiTYN`W#=&npWwUDf2($&1uzjb`fCRiTofm{-an;*gQ-dhU6&zp)od3wWR z-0CsN{>A!wH|CNT2uCPK;9@k;#HwVraW)|;W&!wqRNhe^&-wE@FsC%N#K9~D}a z_v1rsw|P%9`t#z;t6xIKbRGc&W> zU_6(U4aXQg6?w3!ajeLotTc*`JJeblqUJ;n0W%i?(LawY*l zx5Qd&DpG$#$2IFe#gg-ixxyZf;20ciIothO_>foP84~{BR3f~XS-uN#@auqqLpWF! zCG>V>T}ZgYUdTUvH4#Gx_?u#}j&q7|`)mgty>yucZ*VsC zKoqz{T?HI;sa{9ITL=y^)mInE9KtW#qce|cd&nf7;h zUD84OA?ZkXXx_N?uxZ^RT?^S)VIN2p>(W6^W|gE2oyeQH_1uE(ljopyrKwuDULE>y z-xFYaTa-$0Hn{Q!hWPt%#0&H&452IYkE1Z$#qs$OqlJf(%_pTl--n0+u21y^!WYFo zjqFgtEh0pM4mj7}fL+diT*kz3%0&2XgKrvPDA*9~pqrV9f)sF30CUqJQ_51Wf+Vyu z8@L0ZU^=v8feai(WD){kYQ~a>&P^~bOz-q`425_=8iRLdejiK9>o@cDsG^IlO54h1 zluE4YP*EzE+B2-lE=3&A@D7bGNaivOwBn3P+3{){zUclo_(SP8xYhq1+JO+vS#Sgb zXqzW00=I-$^Z@Jb&PXMu)vYEfhb+=!%bDLbu@l3^F&K>+^ZE(lw)>yCX1BJG$ z@wvFeO*%4+a3Ck2)>Mj4+Dl48n8OdIks!yO-1o4<~CA!E@ox z-_4gR>k1-CW-*ZB`!;Bvmzqi#2;TIbQvsTJX9=(ctR~gxcelhh_1U0T-xwP~1;r5_ zoG5#SaF2;I{p|RVT|Ol7Ga}4qVNpuL$U;5b$Xe9Hb@p=H)L79-j4+Zh2Nw-v?O2rd zV5gCaOkT;3F?SOGCYVnmaf`uqB!+yhYrDp%v&{W)+=UE&q1G_hn%L$y$#!#71{EvX z?gq3+Z3Y6%!E$=4^sC=Gm}{OPdV3tpDPg?yRx9xPrsR{}UM7qm9l?}?vvn5cs#kAs zYA*=H=osRXQ>V{mk3H%B@S~T0H?QFB#M)XAslVi8a~Ns(97=BUcjkj#Wz;@KxbaZ# zvC9Qj)ZA9H*TOGWdgDvIDx#S~WG{mZ_P8vRFmyt9N)6R-Sp>N$u6MXsN-NPT@Y0Fu!9 zVD%gH3afm}B#1oEy19fT(NrVctd7Dw?XA>!g|19x2V-d(j2KQPD*6M{R3U62M%^ZM z=oVQ3*zxAF#b|mk8b9~m(#k5ntLv52{{vcQ_8F0#_{Kj;zY3-VEdQ1cWCH)_tPnh9b-X3 zffB~gi6nOEi&X%$t(jwmust$o6$ajXy2vUS{{@7`dE`@BbO@UP(mSXrQY@^+(at0L z$T@zD#z}JpO2;P1yL~$$ZpyR|TvLw*xYz6SX7D)_^$B{N69qno`I;=M+AMQ+x*D zdL=29yL9d^ta_7c)#w^j&mEcLVd3CVzlw@><5WsVV9@)^ru8k5D zH(TtJm4r%M{}SyvVVQe-n3OpEc=wiKVg;LMiW@avhjtVe<)QGy8D@R^jNH#sg;owj z<8=P=9lQsoYK^0eC;WTD=8f_A%?g$SR@j zC()4DXb<2?1LgG(AoUE?0Dn8knn#@@Kg=_tqF@JLs9My`v-JoT{F2xu7M7{>f>sTY{bAyT#rLrQ+?| zD9bhLGjtCh?%vvaaCUa_{>L~tewBlUIuyKoLF{!dRa>`jsnE5aO+Atlw)i4}$&PHU zv!R&EE)Pz4STYMx0hU{&HZ#eQUsy~&Ju#-&1`cpdtR*FKniI3tLRWs(VHBS{X@CgG zG}R2Z;+#2O#@_8iB=h@5?!Ojh!dsjp3bfs7!_8HaIRhfW9-T)9gSN!%w}9>Ps;1xk z7BkhFW=MXauVvmGVz>V`zRRm~XMrwAudZ{E=<~7O-+o;vQ!S_rQOYXg=6Zd&(SadJk8W~ss!34(=;)_%c%G(sqpH8XIn1cbH^t-qCtr>}l09FJ&}*Mii3#}1 zgmSn3F`0QuE!E-rD!~-mY1pl|IL&n(bq79|DI_!FIE5(FuxR)jp`c@mu{Ik_g1iFv z{vlk#%N4svQK5Nxj6R9jO2>G7Adn$VnG;3ZDh=Vez+ZYc7w~TpGY&NHqZHWa$wyVcOe~kkWa+5D!;~5T=@6&^m z^zPn#fr^}s#5>Ij7FywU*1?f~@Vs7Z3Eu{iI$9(Yw=Pdk>GJ~CSauf5HRigG$CFvg z4TaiWEcyxM{nlbjq|D@+8Tu^0f%kYCOdfs#->WnrTWQU_9FI&%;-~-qPEyIO6c+fq ze)Fed_Ihr~w5X#`V#gOjMdx8XON+wG<>^>8$uD1;cqLVGM5*ND&T;Y;8SO z>jn~#g&-&-l-{fpA|!2xc1#+KExGw2R`uhwRo*trKX6m*xs|a;DLW(Scv(2)u@wXG ze|UXs7I_4czj5Z@2dIj4#-CDzylm`u84Bq)+b8p?GN|Mfk?`4n`V8Md_;ce+`9kvg zO%I{(j4dS5=wL|5&G|rzKi{z-GF2gkjWJBEj(LE0g)sj@r3dNEHASi1Xasek;f@m@ zaP5nSg@>2qk~-fMO=B;tZhIA!1DEqS6>t@GPx5B-8RT+#sFPQAHpx^nLU{;<>Qw6|--EVuT?7_P^UIozc)>WwK@33p&R&NxbR|aI@e=me zLl*#`&=l%#&}7j5SDF@Y?JqT-PAn|pC}W<>cK4%?q7xIdNq)zYhR>7pEEEcwasCuT z*UDL_Q~{oW0A_)UrqNo&C4Jol086}n#AYp+JV|!srAnPxZf@@DzxgB~#^KBX*Xbp5 zYY4g5VvX&XT=}ewi5<785SZQ+IDl^QVFp~U9?GT9bkPUlzestDSoi=GMx?>v;fy<7 zr?aJMHb7OqjWNm6X*;gtYYNtisV ziIgvpw?Mm5=xj*yecUdYU@FwdR0*J*ZP7!B|EI8bA;;=4c^(MOjywwRA+Vj5m1tAB z5+)=~6R8~Y&^{oiHg9)D5OJC=Qxze-dNS$y4|B*XW3<*7;L7lwm*}&RD#P2rx6sGD zYVzT7(yu74T(g^-*>A6)U`3aj)t+ETfRXJ0H2YXY&DNAUPpovjvuy^oos57T44*V--R%c0j4+5 zPbWFjR9#ci+&PQNBEF*d;LWys*g(^NZc&dZ4KFXRiJu`E?nuh(2iyZHe40ipe|R^Tj#s~D)~>#|UWz1ij_P12ptV{_yy z?y9u<4VvFi=S=z#0CmX!ow&(2f_EX`p<;P_5Vfi_b zgtX2JZ6zh89C!d3i$n{H#`wBFpqCzcmP&jOZcI%cyv2FqOnl6q;D`^FPiOVk2Eg140kSX- zZLbms5gGF)d@F9g$D#nf^P==FtxLRIh2i~>fV}W{LesmB7}tN$L~dkXR3s$Tu3#$o zkPhfvJlTwRlINL<4Dea#omb}-Zyjlmtvc~Sot^;HkL_Y?E>m63*P0`lb!r@cGXiq^ zY}}%NkU5;<7bF0B=68pv@%n&Wrp9gUtGIl2$Y04LX{p`R^7g@oIkaO@a%d|^svGgvzJ*yVX}G!AwvSAW}tUs*~k_^&GauXqX&Ci9Dhtk94G zZo4NIrzF1zm_Wt%WhW=g+~40@-%a{(K;<8e=%lh7&L~Uz^&B3(3)$S7?4EsQXTzSo z2m}z0PhPu)Nx53 zm;h*z>khN?0-Fskz@aYkF1Z4EiPOIiHQ_B+JeYqJ)T*^Bg*vfsZAeoSubpJAQKu|A z32z)M9;gorbccFknavxj_ZudCpm6T&f3^q8=0jO(gCN1y+pyXD#*CD{Np`QLOSk+p!yx|fk!I>93+BquZ>LwIoJI3*bHJdHr z_~ENqjp{tVy@#s93XAD{iSk??g@{*_`0MSwz-Ra?2_PaUS$Q-J>RDHE08<>taZa?Q z*N$u_n0w+k9@XNIOX76s4w+Xwl{Iu=t4#4`>n-F?x?pp}{7bqZ%3^mD7JFR{GcTFK zCF(FnFs`{J^-TDHG*1(2igVOl_7OdXEpTj`&nK^Urf6GvIVeq`(3GDWC_55MIg_}x zmY@bd9W7e6)pL~#`!2D81^{hC`?{}AeIx~+*;6xz-Q6%U?C?OjMU(0342=nISCp)w@^wrDoVwoEdRGi8)+QgLsIgbh zI(7)3Z76%2UOH`5yJV&8sb*2wk@+20;%ZEKa?bGmJ!)BZvIJW@Zf)REL!zM#_u*sL z3gx8tFM2ApzB8DftFxfK)t-?VpXbb7qmGm=%|773#?eak#$p!g(_3 zp&<4z!k9Zl@%R)V;RxJOurft9=2gJX_p7t?_?>Okkjy#!>oec@Q{Gz*C@*f5D=;{9i)F_O zD~-z{oZe$+1lp!9J{yd@P@;v(umL{Rp$>~+K=dr$mJb#$+IHZOdMF6t9*-l>!@Bff zx@r@vJ)->Rdli;ouFl_}F2mS^J8gDC0jJq^K}Ya82hBC_x3xGyD8f@~Vz_7MKhiP*H6rVOtaqNsfX&T_~4^-ZRX! z0z#mjWd*o3<}tWAqna0?ufP(pG85H(k_Pca5dCrP2k9M6&RcKbnXCUbQHiq#ynjE`ylaUzU z%)O4^+h(&2x0gIt`OLIS9CXgn9iOW6a0j!4^9%UlF4I$W9>AiH#!C`yy*bZug9Z~* zP5`O0dB8mC&0#GyT`OF#@9~kz!l_jj&BA&MtVP`(Rm5&Uya)M*t@%vtQ2p%S8r0X! z{{X+%=4SCPv7wG=dOENTKpGZ?{lkZI0sw7zFfFe%E4!J&+sf`px@8m?4Gn6&JAGju%;iHA67{`bPK>}e^V`v$tPgI--wa=TM$8Zf_X7CpQcf!d;(H7klkL-3X1 zCSSvIHv$Tw&yVzDw%lg7*j0^jrjrBMBf<`McDF|n0pK44{hc#(+OmA&pGsVU#nZk8 zJQ?NtP4zFB=Osgn3fEoeRkx&{Ux(k(_FBuEc?C1}WIVPo4b=LJr~32u&W_(0^K z@@BIiGwI!gH3MiAwZ9d@rv$h0U^)|kcqOHLir_1gQ#fgmN4pH-DPF?ct4zXrt8xCM1)ru499!u;(xb4l=zwa_dMf7$}j6$9ID5mS2cRuT?pOCgJ8Ayl#7YF-h{-1ZVtKtZYBb$S%} z0uT&)j(OrRS*fz5i~`O$Bwvy1-2NppMESa7bli5l?SA zpDbCC!s#Pa!iL!W1lm_RN*-8%?xOdm9?toZu=*6B_IecZa-k zRz!Iv4D_B|_Z3mvR6aw*8m}r;uP*bf=nSamb1TFmO0Dub<-gO6-a!19JW8z>CdSmh z5sQv)!Ve;Ac^)KbA)g|`c{=?c5yP0xtml&QF5k{Cf!u@A^B=TS(+{Z~*!FmNMV3+^ zOs@chZF;+{v?(&#^koO?nFOwY+N*PaW1m|wFeXT98T^Qbuz~ZdL%Bu_Q{!+Zqe3kt zAwg*7h36j@Z0s6=zpu=u=cXU4TjjvcUf}CDmj&`&zAFV0@zt4z^y@>|m5w2GyXM@i zgoLa#e9nCbgcoR05&FCCFYUD`G4(x4Y|t9xj&uyK9I#Mu@6#y5DM33}NM`Z0MavtJ znMr=*PA6N>4dkJ3A(z6#i42uSWu7~l%KHU57B+kfHwUiv%UO3&9nO3`;QS9WAw*vI_X$AQIxj#8_(I#y$)B=($~a5 zSut`bAe}NJ!uBT1L7BVR;oTIGaA!E~HwAW(o-#~lVy?VP# z;M?u4f*MfLjBN{vFuLYE)G>6>Af#NRN7wHVHlK2yI{kZi`is{w)ZUMAJbm3sykXpF zAeGCbEaDNp#b}qMD6DAKFP{iiQ0Qqt*J<`*iALu%mjywj`NLYjaq#GwjBOae)g91dnsEA>4pRr9pEUoGZgHRChhdF?XoLfwv({q3 zjMjzmD@9yG(dVO4G?-*KJs}Bvr8EZ?&b!3YRQG=2f-{9tN*jo?Sy+^3112hjNIlmL z6{sdSVAHZ4s0 zH`pFMW8A+_Z(1J z6n5f;V#GYs{*w6xcID5+gL|_)1~JU=$7oI~u87=~+t52!7Ccs}<&NOL`deqn`g_!3GhE|IB~k-Abhs?i;f+ z%15oCZ%hNySZ8-A`*0|1Pn&nEefNT2vG5y+9-BGvj>w(V&x$C`J!*wsKVlMBJKN9? zL>T_Y@V#bcH@E|{vwIcT-ypkHeDub&+KN&sBL#(1{>FsjF?XFjd;$NULtm?@;|2Ho z16TOW$iB3EmAkE8&!K^70gB3Ql*m5i+pDRbRO{Y`rS94_3YmKK#y!_n_VYZ&l$rEE zpU41Ay(Y+1#tBjLCi^hEmg8btlrR zSup4Rtml9T^wZy@A7s^N6T2bEN^lRy^>dfM1@7f_Bx8W)mx(nXvkGk$C&miRCheD9 zJs&~}{$;Q!{G?^0#|OOCTi^AZ{@^)}UF<*&BE(#$J+8eaC&kbZjTv&yc55C!993o# zm4|wrT|LDeL>klYVSvV)#Ip60M#i~vnJd;MCG1HL;{DmkK8nK201);7JfCz(@fdy5H`KL+ZmEM}E;+9ZR98 z>}KFDwnywFHgl8maq_MF;?q9{bT3!*q8aEtzHbP)riJC8g9IoCpw?LVjClT8FxuCh zz}7!!C)PTupRsH=?U=O6^mX82=*~KRM~ET2=)aRdRT8{kd+b((6!y2z1pU>fmtOE) z658e7DT`ho&FmDD_1K+SB*K6tPc3_&XK8fhZCK?ykE7BV4Xj@;hG3J{nf>T^zqNMz z{RXg02uXB}?54jB`@HBy>3aqok_sujU|3xEB3T|6@p>-h^IQF)51_F|T?Xu(ZJru~D0mrTp#-yxlBK(JUHi zi#Q-^kE~eoR-K0_h9$lqaJV7^+F-vF^5ixgi)>kd*5w?roI0wphq#4qH<-!%KzPj; z!YP~|O=7-~dVuA?^@dW`DCoPQS4e?NgNkAzc}cb4`vHq95>cC*hNz(-2D#(J4MFBkU8 z=8M%s=@IcKrEnogdb07^qH<4FMV86~iSI5zLTnf9#!RAVYGPa|{Xq<1H_TDT=-`jT zY64~XXRZxQCTdOsHAxKX-UEtPctH4AJ?LcuFL1MBey>OPPJ)r_`9fo-M+u6Q!A?B@gFw91!d*)W*(npO}&O()%N zIud$F5T5&Mq|TZU2&4Z?8tmp5EJ130PrVnNfl(GU=l#pqKjIXsnH;gmdIvb3S@x~= zrAzQhMaR!qD57xChul)0Ft@%(7qI%@za${T^xE}G{br@Tn=$;_)lQvjEoX*G zV%|@~J-m@OytQ9uSUj_kBzY1o{pOA@Q8;Y8&pXpAlF|pkx{~0FY9m`^wLQ&+BG~om z#%}+=05J{D@~?mWOE~u5&)O&Iv}#{MKjLx+*KzlrxJ}@SwMdV&pRFTS^RUi7XK_%C z29#c^l;#O|qjmV|-+9Io!K>`qj&)jfEP=&7`1pelK2TtreV;(zJ;I^SE^(bm=tg9C zx{kYh$MPV+BZ%0?2|6!yKhDuDAM*>zthT6CN*+~d9$F2l~$Hjcf$+btF_ zTPmL0P0S*vsAE*OZMYf@6w6+}BGuuxhX>#Vcp^8Rf+yikk4ayP<{jo~o>eIiQ_Iea zv?r#FV{QtksN*)qF}Kn=>b}TsILqWd@iDoMze_DTEuboO?Xs^Ds4E3;_Z@vKv^Cls zZ4VFR#zXKRyy!Fpp1i3&>Dr>>0tIY-q-Md%!h7lqp&M~gIP~B5zG2LbQLeEMzH^(% z4Pmje$UW`}xkR6%FIx@LtoPq>|1m^jx|qwEaNecifSwX7j z+)HqS3&*IVA|Rco1TmKz7-R2l)}r>LtlSGd2#X^>n`<;xtoh|{dK(2_;rIBZwcy;) zD@JRhm+h4&ZOx-0Ok?xvx>J4EwN3xpwiO7Ks^_}jyb zaStEoi4lGq2%=9@BfnUxT&I<`QG~i`P&ljlsQb!wT5?-V(AvZ`{&C)c&w_W@L&Keh zon$ZF5zRZNi#GjsDA26>QenGkf*VgbkIdd*T{q@hE91m_yIm(eqPz?QZj+x74+W`d z*fgr%*qD7Y5lpG>Bgoh5_^4ytx?8=Gf$Kh1YXh`JUV;y=7-R44Vehnthu|e12?#!) z0<5SchapFW{eV5f825l1@Z5)n33rAYCp~}Chn@>Obc9e3ioUa8f&Tf$db8{}o1vPT}lEAR}D05lId4m~RB*RQXj zDsp!ZhA$N!$v+5}(U%1g3H`VmUm7RgU*{U1^*m1lL40-~VDpee)FEo*J6^l|^m0_7 z)(R|}+rRAXtA6f44SmOHb&EPiU1v|n^0E!Hp0hXBvqzf3J1(Oy36GTj6D_(dQXm!e zwUqpq;fin?prbG25NFY7fw+6-QRC!9x|dEXFwPqZDhPdE-cp}={YQj72<#U2Tai1n+ z5AQYTxlSt9Y(ljix{)o{mD8vT*#Q-G$aR@7ZNzP_kGmJ|GVWR>FL)v*L-R<>@MQ{^ zxAsZ_j|4tA^DNmMZ{97r|(Bq z>bIe?pH%&I&EV~SG&y_YjhBn1Wh+$C>Y$#!FEtNes?`nZC>#2G>g_dU{lIO$oZG(H zm+fYh(2c(-8u*MA_EGANzG9J@geD8;(HX)q`jjxl-4{-y&c3UUyX$6%f3(w>@c6mb z1142>0s*rQjR5tM0+iT-`J<8fB za1xh&JJ-SW>;Q>6;kwD!y63h<8|x?Dbwit@?H!^|3JyHt%itshMzLEY?6FelC*Bdx zV=fCehj1Bt_3!$)`yqzOj}GzQzvQnO{}T)#HYPcbzDTY5Y@|j3aa5~K2dZ4JwYHC8 z8Jn^>L*;+{3X^q>6#mn*Yk4g7k(OuVy>i`FT3Jx0R*@UIm%pf$^<}y9A9@Y^U(lvJ z+z)jbd*$zFYv(bSw6<^AbBzK)O$+u4x8(1!E+AZ|{9EY8-}t~V>3&DUtr#>B@z6_{~<7ZASw z4?GN#F7`G#jyywl1GbZG*L3b#Cu(zO46Ca((ov;4%^AkewcghTL85H=>@CrM+f)Cl zk8jEt=$dfMi*6(0P-U}4?U-kGW zw3#9Pemk_G7St!)6hW&kR-8C|6}CpNQae}Dr)EC+%q-{9vzI1qTVsWz~|o@Se@ zFpT|GHc$XdgX~*P_}hTs5ONzegDoA0KBEKC`}H@Yd@Y>RzAlC<<-S zHu`u;t&Jw$68t{~U-kGZ<-;0*F7A$So^V}oZzJ5MJrlY~cR$c4JapA3KAvYtdUD4w zh0Upye@c3i$#p%S>)eg&{zJFvKWS~jQy<~NZDT+DurjJj1u!ZYcSYDm?Lz<%JOmYv zW6qV-O}<}MpO_VHNP4`{Fy+Z(1#Di4>oV!_Ca&8E-Q)+=9LJn5i8@E!w;6IkYYUZB zDx7tK(dXHSnZh~thSn1qr+$lJ=)2rQ)nmi<Z_bZmuLRt~0JX?(O?=UDkJr zyY(*WR-f=dt7~2SJ>f9soHC$FR&@1X>;>UIi?pFAn^qW8o(h*qnSawKKB}WndK}I@ z*$OuHO+)h6&sn7OJ3ZIxhUs&HmGj=7-qaOml{Hx#}LNjS&f{vVgb2bFb6kDPQQ~e<=4rEUbaT(@uS^9ICoKZIC_&fjWzm&8xzwG6m#$OT66K`^$ zRC9Wjidk}wW%EzEB^>cHo<|6Y4+KLa4AZ_7E&8na69e(3&JV(nsAI$tM@9Y^k1p+e$c1yz!p%7@hTU=eB@w)fgx#>cs$s1#{eO6>t&hMX4`BcR002ov JPDHLkV1l{h5JLa} literal 0 HcmV?d00001 diff --git a/static/logo.png b/static/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..ba76d105fba27357ec7f768b4e0d91fe41acabe0 GIT binary patch literal 7834 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 literal 0 HcmV?d00001 diff --git a/static/logo.svg b/static/logo.svg new file mode 100644 index 0000000..20b2a31 --- /dev/null +++ b/static/logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/static/robots.txt b/static/robots.txt new file mode 100644 index 0000000..b6dd667 --- /dev/null +++ b/static/robots.txt @@ -0,0 +1,3 @@ +# allow crawling everything by default +User-agent: * +Disallow: diff --git a/svelte.config.js b/svelte.config.js new file mode 100644 index 0000000..0708309 --- /dev/null +++ b/svelte.config.js @@ -0,0 +1,152 @@ +import adapter from '@sveltejs/adapter-static'; +import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'; +import { mdsvex } from 'mdsvex'; +import rehypeAutolinkHeadings from 'rehype-autolink-headings'; +import rehypeSanitize from 'rehype-sanitize'; +import rehypeSlug from 'rehype-slug'; +import { createHighlighter } from 'shiki'; +import { SITE_URL } from './site.config.js'; +import { rehypeDocLinks } from './src/lib/utils/rehype-plugins.js'; + +const SHIKI_THEME = 'github-dark'; +const DOCS_ASSETS_PATH = '/assets/docs'; +const DOCS_GRAPH_PATH = '.svelte-kit/generated/docs-graph.json'; +const SVELTEKIT_OUT_DIR = '.svelte-kit'; +const SHIKI_LANGUAGES = [ + 'javascript', + 'typescript', + 'kotlin', + 'java', + 'bash', + 'json', + 'groovy', + 'svelte', + 'html', + 'css', + 'properties', + 'xml', + 'yaml', + 'shell', + 'markdown', +]; + +let highlighterPromise = null; + +function getSiteBasePath(siteUrl) { + const pathname = new URL(siteUrl).pathname.replace(/\/+$/, ''); + return pathname === '/' ? '' : pathname; +} + +const SITE_BASE_PATH = getSiteBasePath(SITE_URL); + +function getHighlighter() { + if (!highlighterPromise) { + highlighterPromise = createHighlighter({ + themes: [SHIKI_THEME], + langs: SHIKI_LANGUAGES, + }); + } + return highlighterPromise; +} + +function resolveLang(highlighter, lang) { + if (!lang) return 'text'; + try { + highlighter.getLanguage(lang); + return lang; + } catch { + return 'text'; + } +} + +function withBase(pathname) { + return `${SITE_BASE_PATH}${pathname}`; +} + +const config = { + extensions: ['.svelte', '.md'], + preprocess: [ + vitePreprocess(), + mdsvex({ + extensions: ['.md'], + rehypePlugins: [ + rehypeSanitize, + rehypeSlug, + [ + rehypeAutolinkHeadings, + { + behavior: 'append', + properties: { + className: ['heading-anchor'], + 'aria-label': 'Link to this section', + }, + content: [ + { + type: 'element', + tagName: 'span', + properties: { className: ['heading-anchor-icon'], 'aria-hidden': 'true' }, + children: [{ type: 'text', value: '#' }], + }, + ], + }, + ], + [ + rehypeDocLinks, + { + docsGraphPath: DOCS_GRAPH_PATH, + siteBasePath: SITE_BASE_PATH, + assetsPublicPath: DOCS_ASSETS_PATH, + }, + ], + ], + highlight: { + highlighter: async (code, lang) => { + const highlighter = await getHighlighter(); + const highlighted = highlighter.codeToHtml(code, { + lang: resolveLang(highlighter, lang), + theme: SHIKI_THEME, + }); + const wrapped = [ + '
', + '', + highlighted, + '
', + ].join(''); + const escaped = wrapped.replace(/\\/g, '\\\\').replace(/`/g, '\\`').replace(/\$/g, '\\$'); + return `{@html \`${escaped}\`}`; + }, + }, + }), + ], + kit: { + outDir: SVELTEKIT_OUT_DIR, + alias: { + $generated: `${SVELTEKIT_OUT_DIR}/generated`, + }, + paths: { + base: SITE_BASE_PATH, + }, + inlineStyleThreshold: 0, + adapter: adapter({ + pages: 'build', + assets: 'build', + fallback: null, + precompress: true, + strict: true, + }), + prerender: { + handleHttpError: ({ path: prerenderPath, message }) => { + if (prerenderPath === withBase('/favicon.ico') || prerenderPath === withBase('/logo.png')) { + return; + } + if (prerenderPath.startsWith(withBase('/assets/'))) { + return; + } + throw new Error(message); + }, + handleMissingId: 'fail', + }, + }, +}; + +export default config; diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..845a586 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,14 @@ +{ + "extends": "./.svelte-kit/tsconfig.json", + "compilerOptions": { + "rewriteRelativeImportExtensions": true, + "allowJs": false, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "sourceMap": true, + "strict": true, + "moduleResolution": "bundler" + } +} diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..a6dc9a2 --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,215 @@ +import { spawn } from 'node:child_process'; +import { existsSync, readFileSync, statSync } from 'node:fs'; +import path from 'node:path'; +import { sveltekit } from '@sveltejs/kit/vite'; +import fg from 'fast-glob'; +import Icons from 'unplugin-icons/vite'; +import { defineConfig, type Plugin } from 'vite'; +import { DOCS_DIR } from './site.config.js'; + +const DOCS_ASSETS_PUBLIC_PATH = '/assets/docs'; +const DOCS_GRAPH_PATH = '.svelte-kit/generated/docs-graph.json'; +const SVELTEKIT_OUT_DIR = '.svelte-kit'; + +function docsArtifactsPlugin(): Plugin { + const normalizedOutDir = SVELTEKIT_OUT_DIR.split('/') + .join(path.sep) + .replace(/[/\\]+$/, ''); + const generatedDirSegment = `${path.sep}${normalizedOutDir}${path.sep}generated${path.sep}`; + let root = process.cwd(); + let generatedInitially = false; + let generationInProgress = false; + let pendingForceRun = false; + let debounceTimer: ReturnType | null = null; + + function shouldRegenerate(filePath: string): boolean { + const normalized = path.normalize(filePath); + if (normalized.includes(generatedDirSegment)) { + return false; + } + + const relative = path.relative(root, normalized); + if (relative.startsWith('..')) { + return false; + } + + return ( + relative === 'site.config.ts' || + relative.startsWith(`docs${path.sep}`) || + relative.startsWith(`assets${path.sep}`) || + relative.startsWith(`src${path.sep}lib${path.sep}core${path.sep}`) || + relative.startsWith(`scripts${path.sep}`) + ); + } + + function runGeneration(force: boolean): Promise { + const args = ['scripts/generate-docs-graph.ts']; + if (force) { + args.push('--force'); + } + + return new Promise((resolve, reject) => { + const child = spawn('bun', args, { + cwd: root, + stdio: 'inherit', + env: process.env, + }); + + child.on('error', reject); + child.on('close', (code) => { + if (code === 0) { + resolve(); + return; + } + reject(new Error(`Docs generation failed with exit code ${code ?? 1}`)); + }); + }); + } + + async function triggerGeneration( + force: boolean, + onSuccess: () => void, + onError: (error: unknown) => void, + ): Promise { + if (force) { + pendingForceRun = true; + } + if (generationInProgress) { + return; + } + + generationInProgress = true; + let shouldForce = force; + while (true) { + try { + await runGeneration(shouldForce); + } catch (error) { + generationInProgress = false; + onError(error); + return; + } + if (!pendingForceRun) { + break; + } + pendingForceRun = false; + shouldForce = true; + } + + generationInProgress = false; + onSuccess(); + } + + /** Serve a file from `sourceDir` for requests under the given URL prefix (dev only). */ + function serveFromDir(sourceDir: string) { + return (req: { url?: string }, res: { end: (data: Buffer) => void }, next: () => void) => { + const url = req.url?.split('?')[0]; + if (!url) return next(); + const relativePath = decodeURIComponent(url).replace(/^\/+/, ''); + const filePath = path.join(sourceDir, relativePath); + if ( + !filePath.startsWith(sourceDir) || + !existsSync(filePath) || + !statSync(filePath).isFile() + ) { + return next(); + } + res.end(readFileSync(filePath)); + }; + } + + return { + name: 'docs-artifacts', + configResolved(config) { + root = config.root; + }, + async buildStart() { + if (generatedInitially) { + return; + } + generatedInitially = true; + await runGeneration(false); + }, + configureServer(server) { + root = server.config.root; + + const docsDir = path.resolve(root, DOCS_DIR); + const repoAssetsDir = path.resolve(root, 'assets'); + + server.middlewares.use(DOCS_ASSETS_PUBLIC_PATH, serveFromDir(docsDir)); + + server.middlewares.use('/assets', serveFromDir(repoAssetsDir)); + + const onFileChange = (filePath: string) => { + if (!shouldRegenerate(filePath)) { + return; + } + if (debounceTimer) { + clearTimeout(debounceTimer); + } + debounceTimer = setTimeout(() => { + void triggerGeneration( + true, + () => server.ws.send({ type: 'full-reload' }), + (error) => + server.config.logger.error(error instanceof Error ? error.message : String(error)), + ); + }, 120); + }; + + server.watcher.on('add', onFileChange); + server.watcher.on('change', onFileChange); + server.watcher.on('unlink', onFileChange); + }, + generateBundle() { + const docsDir = path.resolve(root, DOCS_DIR); + const repoAssetsDir = path.resolve(root, 'assets'); + const graphPath = path.resolve(root, DOCS_GRAPH_PATH); + + if (existsSync(graphPath)) { + const graph = JSON.parse(readFileSync(graphPath, 'utf-8')); + const assets: string[] = graph.assets ?? []; + for (const assetPath of assets) { + const filePath = path.join(docsDir, assetPath); + if (!existsSync(filePath)) { + this.warn(`Doc asset not found: ${filePath} (referenced as '${assetPath}')`); + continue; + } + this.emitFile({ + type: 'asset', + fileName: `${DOCS_ASSETS_PUBLIC_PATH.replace(/^\//, '')}/${assetPath}`, + source: readFileSync(filePath), + }); + } + } + + if (existsSync(repoAssetsDir)) { + const repoAssets = fg.sync('**/*', { + cwd: repoAssetsDir, + onlyFiles: true, + followSymbolicLinks: true, + }); + for (const assetPath of repoAssets) { + const filePath = path.join(repoAssetsDir, assetPath); + this.emitFile({ + type: 'asset', + fileName: `assets/${assetPath.replace(/\\/g, '/')}`, + source: readFileSync(filePath), + }); + } + } + }, + }; +} + +const workspaceRoot = path.resolve(process.cwd()); +const docsRoot = path.resolve(workspaceRoot, 'docs'); +const repoAssetsRoot = path.resolve(workspaceRoot, 'assets'); + +export default defineConfig({ + server: { + fs: { + allow: [workspaceRoot, docsRoot, repoAssetsRoot], + }, + }, + plugins: [docsArtifactsPlugin(), Icons({ compiler: 'svelte' }), sveltekit()], +});