From 87258a98b1ff51ba93769133b2e20a6b364a896d Mon Sep 17 00:00:00 2001 From: Panadestein Date: Tue, 6 Oct 2026 15:30:36 +0200 Subject: [PATCH 1/2] =?UTF-8?q?docs:=20=F0=9F=93=9D=20replace=20the=20MkDo?= =?UTF-8?q?cs=20site=20with=20a=20Fumadocs=20site?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Port the Next.js + Fumadocs setup from monoprop to docs/: MDX pages for getting started, concepts, features, benchmarks, references and the developer guide; an API reference generated from the docstrings with griffe; tutorial notebooks executed at build time; KaTeX math and BibTeX citations. The Documentation workflow builds the static export, runs the Python examples in the pages with pytest --markdown-docs, and deploys to GitHub Pages under /src-method. Closes #32 Assisted-by: pi:claude-opus-5.5 --- .devcontainer/devcontainer.json | 5 + .github/workflows/docpages.yml | 54 +- .gitignore | 5 +- AGENTS.md | 17 +- README.md | 30 +- docs/.gitignore | 31 + docs/README.md | 27 + docs/assets/algo_symbol.png | Bin 42089 -> 0 bytes docs/bibliography.bib | 33 + docs/content/docs/benchmarks.mdx | 53 + docs/content/docs/concepts/algorithm.mdx | 56 + docs/content/docs/concepts/conventions.mdx | 69 + docs/content/docs/concepts/index.mdx | 9 + docs/content/docs/concepts/meta.json | 4 + .../docs/contributing/dependencies.mdx | 36 + .../content/docs/contributing/documenting.mdx | 55 + docs/content/docs/contributing/index.mdx | 78 + docs/content/docs/contributing/meta.json | 4 + docs/content/docs/contributing/sonarcloud.mdx | 37 + docs/content/docs/contributing/testing.mdx | 97 + docs/content/docs/contributing/versioning.mdx | 25 + docs/content/docs/features/cutoff.mdx | 33 + docs/content/docs/features/gpu.mdx | 29 + docs/content/docs/features/index.mdx | 12 + docs/content/docs/features/logging.mdx | 20 + docs/content/docs/features/meta.json | 4 + docs/content/docs/features/precision.mdx | 53 + docs/content/docs/features/stacks.mdx | 41 + docs/content/docs/getting-started.mdx | 71 + docs/content/docs/index.mdx | 55 + docs/content/docs/meta.json | 3 + docs/content/docs/references.mdx | 37 + docs/developer-guide/dependencies.md | 35 - docs/developer-guide/sonarcloud.md | 31 - docs/developer-guide/testing.md | 305 - docs/developer-guide/versioning.md | 23 - docs/gen_ref_pages.py | 34 - docs/index.md | 152 - docs/javascripts/config.js | 16 - docs/next.config.mjs | 17 + .../accuracy_vs_bond_dimension.ipynb | 131 + docs/package-lock.json | 7340 +++++++++++++++++ docs/package.json | 38 + docs/postcss.config.mjs | 7 + .../fonts/gt-planar/GT-Planar-Light.woff2 | Bin 0 -> 57456 bytes .../fonts/gt-planar/GT-Planar-Regular.woff2 | Bin 0 -> 58680 bytes .../fonts/gt-planar/GT-Planar-Thin.woff2 | Bin 0 -> 55828 bytes docs/scripts/api-mdx.mjs | 254 + docs/scripts/gen_api_dump.py | 597 ++ docs/scripts/generate-api.mjs | 230 + docs/scripts/notebooks_to_mdx.py | 185 + docs/scripts/remark-xref.mjs | 75 + docs/scripts/xref.mjs | 67 + docs/source.config.ts | 97 + docs/src/app/(docs)/[[...slug]]/page.tsx | 77 + docs/src/app/(docs)/layout.tsx | 11 + docs/src/app/api/search/route.ts | 9 + docs/src/app/global.css | 64 + docs/src/app/icon.svg | 21 + docs/src/app/layout.tsx | 27 + docs/src/app/llms-full.txt/route.ts | 10 + .../app/llms.mdx/docs/[[...slug]]/route.ts | 23 + docs/src/app/llms.txt/route.ts | 8 + docs/src/app/og/docs/[...slug]/route.tsx | 28 + docs/src/components/figure.tsx | 22 + docs/src/components/logo.tsx | 28 + docs/src/components/mdx.tsx | 37 + docs/src/components/py.tsx | 155 + docs/src/lib/cn.ts | 1 + docs/src/lib/fonts.ts | 27 + docs/src/lib/layout.shared.tsx | 13 + docs/src/lib/shared.ts | 18 + docs/src/lib/source.ts | 37 + docs/stylesheets/code_select.css | 5 - docs/stylesheets/extra.css | 10 - docs/tsconfig.json | 45 + flake.nix | 2 + mkdocs.yml | 86 - pyproject.toml | 13 +- uv.lock | 640 +- 80 files changed, 10792 insertions(+), 1342 deletions(-) create mode 100644 docs/.gitignore create mode 100644 docs/README.md delete mode 100644 docs/assets/algo_symbol.png create mode 100644 docs/bibliography.bib create mode 100644 docs/content/docs/benchmarks.mdx create mode 100644 docs/content/docs/concepts/algorithm.mdx create mode 100644 docs/content/docs/concepts/conventions.mdx create mode 100644 docs/content/docs/concepts/index.mdx create mode 100644 docs/content/docs/concepts/meta.json create mode 100644 docs/content/docs/contributing/dependencies.mdx create mode 100644 docs/content/docs/contributing/documenting.mdx create mode 100644 docs/content/docs/contributing/index.mdx create mode 100644 docs/content/docs/contributing/meta.json create mode 100644 docs/content/docs/contributing/sonarcloud.mdx create mode 100644 docs/content/docs/contributing/testing.mdx create mode 100644 docs/content/docs/contributing/versioning.mdx create mode 100644 docs/content/docs/features/cutoff.mdx create mode 100644 docs/content/docs/features/gpu.mdx create mode 100644 docs/content/docs/features/index.mdx create mode 100644 docs/content/docs/features/logging.mdx create mode 100644 docs/content/docs/features/meta.json create mode 100644 docs/content/docs/features/precision.mdx create mode 100644 docs/content/docs/features/stacks.mdx create mode 100644 docs/content/docs/getting-started.mdx create mode 100644 docs/content/docs/index.mdx create mode 100644 docs/content/docs/meta.json create mode 100644 docs/content/docs/references.mdx delete mode 100644 docs/developer-guide/dependencies.md delete mode 100644 docs/developer-guide/sonarcloud.md delete mode 100644 docs/developer-guide/testing.md delete mode 100644 docs/developer-guide/versioning.md delete mode 100644 docs/gen_ref_pages.py delete mode 100644 docs/index.md delete mode 100644 docs/javascripts/config.js create mode 100644 docs/next.config.mjs create mode 100644 docs/notebooks/accuracy_vs_bond_dimension/accuracy_vs_bond_dimension.ipynb create mode 100644 docs/package-lock.json create mode 100644 docs/package.json create mode 100644 docs/postcss.config.mjs create mode 100644 docs/public/fonts/gt-planar/GT-Planar-Light.woff2 create mode 100644 docs/public/fonts/gt-planar/GT-Planar-Regular.woff2 create mode 100644 docs/public/fonts/gt-planar/GT-Planar-Thin.woff2 create mode 100644 docs/scripts/api-mdx.mjs create mode 100755 docs/scripts/gen_api_dump.py create mode 100644 docs/scripts/generate-api.mjs create mode 100755 docs/scripts/notebooks_to_mdx.py create mode 100644 docs/scripts/remark-xref.mjs create mode 100644 docs/scripts/xref.mjs create mode 100644 docs/source.config.ts create mode 100644 docs/src/app/(docs)/[[...slug]]/page.tsx create mode 100644 docs/src/app/(docs)/layout.tsx create mode 100644 docs/src/app/api/search/route.ts create mode 100644 docs/src/app/global.css create mode 100644 docs/src/app/icon.svg create mode 100644 docs/src/app/layout.tsx create mode 100644 docs/src/app/llms-full.txt/route.ts create mode 100644 docs/src/app/llms.mdx/docs/[[...slug]]/route.ts create mode 100644 docs/src/app/llms.txt/route.ts create mode 100644 docs/src/app/og/docs/[...slug]/route.tsx create mode 100644 docs/src/components/figure.tsx create mode 100644 docs/src/components/logo.tsx create mode 100644 docs/src/components/mdx.tsx create mode 100644 docs/src/components/py.tsx create mode 100644 docs/src/lib/cn.ts create mode 100644 docs/src/lib/fonts.ts create mode 100644 docs/src/lib/layout.shared.tsx create mode 100644 docs/src/lib/shared.ts create mode 100644 docs/src/lib/source.ts delete mode 100644 docs/stylesheets/code_select.css delete mode 100644 docs/stylesheets/extra.css create mode 100644 docs/tsconfig.json delete mode 100644 mkdocs.yml diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 4353f5f..eb9cce3 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -4,6 +4,11 @@ "dockerfile": "Dockerfile" }, "remoteUser": "vscode", + "features": { + "ghcr.io/devcontainers/features/node:1": { + "version": "22" + } + }, "customizations": { "vscode": { "settings": { diff --git a/.github/workflows/docpages.yml b/.github/workflows/docpages.yml index edb0ef1..d99dd7d 100644 --- a/.github/workflows/docpages.yml +++ b/.github/workflows/docpages.yml @@ -1,4 +1,4 @@ -# Simple workflow for deploying static content to GitHub Pages +# Build the Fumadocs site under docs/ and deploy it to GitHub Pages name: Documentation # specify which events will trigger this workflow @@ -19,7 +19,7 @@ on: # Allows you to run this workflow manually from the Actions tab workflow_dispatch: - # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages +# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages permissions: contents: read pages: write @@ -37,10 +37,20 @@ env: jobs: build: runs-on: ubuntu-latest + + defaults: + run: + working-directory: docs + + env: + # The site is served from algorithmiq.github.io/src-method. + NEXT_PUBLIC_BASE_PATH: /src-method + steps: - name: Checkout uses: actions/checkout@v7 with: + # grab the history, so hatch-vcs can compute the version number fetch-depth: 0 - name: Install the latest version of uv @@ -49,21 +59,42 @@ jobs: enable-cache: true python-version: "3.14" - - name: Install package - run: | - uv sync --group docs + - name: Set up Node.js + uses: actions/setup-node@v7 + with: + node-version: 22 + cache: npm + cache-dependency-path: docs/package-lock.json - - name: Python environment information + - name: Install dependencies run: | - uv tree + uv sync --no-dev --group docs + npm ci - name: Get src_method version run: | - uv run python -c "import src_method; print(src_method.__version__)" + uv run --no-sync python -c "import src_method; print(src_method.__version__)" + + - name: Generate the API reference + run: | + uv run --no-sync python scripts/gen_api_dump.py src_method -d . + node scripts/generate-api.mjs + + - name: Run the examples in the prose pages + working-directory: . + run: >- + uv run --no-sync python -m pytest --markdown-docs -p no:cacheprovider + docs/content/docs + --ignore=docs/content/docs/api + --ignore=docs/content/docs/tutorials + + - name: Execute the tutorial notebooks + run: | + uv run --no-sync python scripts/notebooks_to_mdx.py - - name: Build docs + - name: Build the static site run: | - uv run mkdocs build + npm run build - name: Setup Pages if: ${{ github.ref == 'refs/heads/main' }} @@ -73,8 +104,7 @@ jobs: if: ${{ github.ref == 'refs/heads/main' }} uses: actions/upload-pages-artifact@v5 with: - # Upload entire repository - path: site + path: docs/out deploy: if: ${{ github.ref == 'refs/heads/main' }} diff --git a/.gitignore b/.gitignore index d00c338..ca75eea 100644 --- a/.gitignore +++ b/.gitignore @@ -51,7 +51,8 @@ dist/ downloads/ eggs/ .eggs/ -lib/ +# using lib/ would exclude the docs/src/lib directory used by next.js +/lib/ lib64/ parts/ sdist/ @@ -172,8 +173,6 @@ venv.bak/ # Rope project settings .ropeproject -# mkdocs documentation -/site # mypy .mypy_cache/ diff --git a/AGENTS.md b/AGENTS.md index 3fd0018..b0c6d35 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -31,8 +31,10 @@ tensor, so there is no wrapper type. skipped lint is a red PR. - Changes to the API or to user-facing behavior -- developers included, e.g. workflows or test layout -- belong in the docs and, when relevant, in - `README.md`. `docs/developer-guide/` covers versioning, dependencies and how - to write tests; read it before changing any of those. + `README.md`. `docs/content/docs/contributing/` covers versioning, + dependencies, tests and the docs site; read it before changing any of those. + Python blocks in the docs pages run in CI: keep them self-contained, or mark + them `python notest`. ## Git and PRs @@ -49,8 +51,9 @@ Package `src/src_method/`: `apply.py` and `compress.py` are the public entry points, `_tensor_train.py` holds the shared train helpers, `utils/_backend.py` the NumPy/CuPy dispatch and `utils/linalg.py` the decompositions. Tests in `tests/`, benchmarks in `benches/` with recorded results in -`baseline-benchmarks/`, MkDocs sources in `docs/`, throwaway scripts in -`sandbox/`. +`baseline-benchmarks/`, the Fumadocs site in `docs/` (MDX pages in +`docs/content/docs/`, tutorial notebooks in `docs/notebooks/`), throwaway +scripts in `sandbox/`. `src/src_method/_version.py` is generated by `hatch-vcs` -- never edit it. @@ -65,9 +68,13 @@ uv run pytest -m "not slow" # fast suite uv run pytest # everything uv run ruff check src/ tests/ uv run ty check src/ -uv run mkdocs serve ``` +Docs site (Node.js 22+), from `docs/`: `npm ci`, then +`uv run python scripts/gen_api_dump.py src_method -d .`, +`node scripts/generate-api.mjs`, `uv run python scripts/notebooks_to_mdx.py` +and `npm run dev`. + ## Notes - `filterwarnings = ["error"]` is on: a stray warning fails the suite. Networks diff --git a/README.md b/README.md index a8862a5..70292b3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Successive Randomized Compression -[![Documentation](https://github.com/Algorithmiq/src-method/actions/workflows/docpages.yml/badge.svg)](https://docs.algorithmiq.fi/src-method) +[![Documentation](https://github.com/Algorithmiq/src-method/actions/workflows/docpages.yml/badge.svg)](https://algorithmiq.github.io/src-method/) [![Test src_method](https://github.com/Algorithmiq/src-method/actions/workflows/test.yml/badge.svg)](https://github.com/Algorithmiq/src-method/actions/workflows/test.yml) [![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](LICENSE) @@ -25,7 +25,7 @@ from src_method import apply, compress, src The `apply` function covers cases 1 and 2 above, the `compress` function cases 3 and 4, and `src` all five: `apply` and `compress` are its two- and one-train special cases. All three functions are pure, meaning no in-place modification ever happens. The user should manage the assignment of the returned objects, possibly overwriting the input variables. -See the [reference documentation](algorithmiq.github.io/src_method/) for details, and the [tests](tests/) or [benchmarks](benches/) folders for usage examples. +See the [reference documentation](https://algorithmiq.github.io/src-method/) for details, and the [tests](tests/) or [benchmarks](benches/) folders for usage examples. Whether a train is an MPS or an MPO is inferred from the rank of its first site tensor, so no wrapper type is needed. @@ -193,18 +193,23 @@ you. Run `prek install --prepare-hooks` once after the first `nix develop`. ## Documentation -We use [MkDocs] to generate our documentation pages. You can find the latest version [at this link]. +The documentation is a [Fumadocs] site under `docs/`, published [at this link]. +It covers concepts, features, tutorials, the API reference generated from the +docstrings, and the developer guide. -We encourage you to build the documentation locally, so you can check that newer -documentation you might have added looks as it should. +To preview it locally you need [Node.js] 22 or later: -To do so, open a terminal in [Visual Studio Code] and run: - -``` -mkdocs serve +```bash +uv sync --group docs +cd docs +npm ci +uv run python scripts/gen_api_dump.py src_method -d . +node scripts/generate-api.mjs +uv run python scripts/notebooks_to_mdx.py +npm run dev ``` -the editor will prompt you to open a new page in your browser, where you can see the rendered documentation. +and open http://localhost:3000. See [`docs/README.md`](docs/README.md) for details. [DevContainer]: https://containers.dev/ [Docker]: https://docs.docker.com/get-docker/ @@ -214,5 +219,6 @@ the editor will prompt you to open a new page in your browser, where you can see [Nix]: https://nixos.org/download/ [direnv]: https://direnv.net/ [uv]: https://docs.astral.sh/uv/ -[MkDocs]: https://www.mkdocs.org/ -[at this link]: https://docs.algorithmiq.fi/src_method +[Fumadocs]: https://fumadocs.dev +[Node.js]: https://nodejs.org +[at this link]: https://algorithmiq.github.io/src-method/ diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 0000000..6e3a091 --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1,31 @@ +# deps +/node_modules + +# generated content +.source +# griffe dump + generated API reference and tutorial MDX (produced by +# docs/scripts/gen_api_dump.py, generate-api.mjs and notebooks_to_mdx.py) +/src_method.json +/content/docs/api/ +/content/docs/tutorials/ + +# test & build +/coverage +/.next/ +/out/ +/build +*.tsbuildinfo + +# misc +.DS_Store +*.pem +/.pnp +.pnp.js +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# others +.env*.local +.vercel +next-env.d.ts diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..41dbe4b --- /dev/null +++ b/docs/README.md @@ -0,0 +1,27 @@ +# src_method documentation site + +A [Fumadocs](https://fumadocs.dev) (Next.js) application, exported as static +files and deployed to GitHub Pages by `.github/workflows/docpages.yml`. + +- `content/docs/` holds the hand-written MDX pages; `meta.json` files order the + sidebar. +- `notebooks//.ipynb` are the tutorials, executed at build time. +- `scripts/` generate the API reference from the docstrings and the tutorial + pages from the notebooks. +- `src/` is the Next.js app: layout, components and routes. + +Build it from the repository root with Node.js 22 or later: + +```bash +uv sync --group docs +cd docs +npm ci +uv run python scripts/gen_api_dump.py src_method -d . +node scripts/generate-api.mjs +uv run python scripts/notebooks_to_mdx.py +npm run dev # live preview on http://localhost:3000 +npm run build # static export in out/ +``` + +The Documenting page of the site (`content/docs/contributing/documenting.mdx`) +covers writing pages, cross-references, citations and tutorials. diff --git a/docs/assets/algo_symbol.png b/docs/assets/algo_symbol.png deleted file mode 100644 index a9de3bd8a070e11cd217e3c6f097875ef0d060e9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 42089 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, U1 acts first +``` + +Each contraction joins the `'d'` leg of a train with the `'u'` leg (or the +physical leg of an MPS) of the train to its right: + +| Stack | Contraction | Result | +|---|---|---| +| `src(A)`, `src(psi)` | none | compressed MPO or MPS | +| `src(A, B, ...)` | `A.d` with `B.u` | MPO | +| `src(A, ..., psi)` | `A.d` with `psi` | MPS on the `'u'` leg of `A` (a ket) | +| `src(phi, A, ...)` | `phi` with `A.u` | MPS on the `'d'` leg of the last MPO (a bra) | + +An MPS may appear only first or last, and not both. `apply(A, B)` and +`compress(A)` are the two- and one-train cases; `apply` accepts only an MPO on the +left. + +## Bras are not conjugated + +A leading MPS is a row vector used **without conjugation**: `src(phi, A, B)` +computes $\phi^T A B$, which equals `src(Bᵀ, Aᵀ, phi)` with $^T$ swapping the `'u'` +and `'d'` legs. For the physical bra $\langle\psi| A B$, conjugate first: + +```python notest +bra = src([t.conj() for t in psi], A, B, chi_out=64) +``` + +The result then pairs with a ket by plain contraction, with no further +conjugation. diff --git a/docs/content/docs/concepts/index.mdx b/docs/content/docs/concepts/index.mdx new file mode 100644 index 0000000..4821f70 --- /dev/null +++ b/docs/content/docs/concepts/index.mdx @@ -0,0 +1,9 @@ +--- +title: Concepts +description: The SRC algorithm and the conventions every function expects. +--- + + + + + diff --git a/docs/content/docs/concepts/meta.json b/docs/content/docs/concepts/meta.json new file mode 100644 index 0000000..e04bd90 --- /dev/null +++ b/docs/content/docs/concepts/meta.json @@ -0,0 +1,4 @@ +{ + "title": "Concepts", + "pages": ["algorithm", "conventions"] +} diff --git a/docs/content/docs/contributing/dependencies.mdx b/docs/content/docs/contributing/dependencies.mdx new file mode 100644 index 0000000..b701fe5 --- /dev/null +++ b/docs/content/docs/contributing/dependencies.mdx @@ -0,0 +1,36 @@ +--- +title: Dependencies +description: Dependency groups and how to change them. +--- + +Dependencies are managed with [uv](https://docs.astral.sh/uv/) and declared in +`pyproject.toml`: + +- **Runtime dependencies** (`[project] dependencies`) are what users install: + NumPy and `opt_einsum`. Keep this list short; every entry is imposed on every + downstream project. +- **Extras** (`[project.optional-dependencies]`) enable optional features in + production: `gpu-nvidia` and `gpu-rocm` add CuPy. +- **Dependency groups** (`[dependency-groups]`) are for development only and are + never installed by users: + - `test`: `pytest`, its plugins, and `quimb` to build reference networks; + - `dev`: the linters, type checker and hooks, plus `test`; + - `interactive`: Jupyter and plotting for notebooks; + - `docs`: what this site's build needs, plus `test` and `interactive`. + +## Why uv? + +- Its lockfile is compact and multi-platform. +- It gives granular control over which index each dependency comes from, which + matters with private indexes. +- It is very fast. + +## Changing dependencies + +1. Edit `pyproject.toml`. +2. Run `uv sync --all-groups` to update the environment and regenerate + `uv.lock`, and commit both files. The `uv-lock` hook fails if they disagree. + +Declare the oldest version that works rather than the one you happen to have +installed: a high floor stops users from installing `src_method` next to anything +that has not caught up yet. diff --git a/docs/content/docs/contributing/documenting.mdx b/docs/content/docs/contributing/documenting.mdx new file mode 100644 index 0000000..c5947df --- /dev/null +++ b/docs/content/docs/contributing/documenting.mdx @@ -0,0 +1,55 @@ +--- +title: Documenting +description: How this site is built, and how to add pages, API docs and tutorials. +--- + +This site is a [Fumadocs](https://fumadocs.dev) application under `docs/`, built +with Next.js into a static export and deployed to GitHub Pages by the +`Documentation` workflow. Pull requests build it too, so a broken page fails CI. + +## Building locally + +You need [Node.js](https://nodejs.org) 22 or later and the `docs` dependency +group. From the repository root: + +```bash +uv sync --group docs +cd docs +npm ci +uv run python scripts/gen_api_dump.py src_method -d . # docstrings -> JSON +node scripts/generate-api.mjs # JSON -> content/docs/api +uv run python scripts/notebooks_to_mdx.py # notebooks -> content/docs/tutorials +npm run dev # http://localhost:3000 +``` + +`npm run build` writes the static export to `docs/out`. The generated API pages, +tutorials and `src_method.json` are ignored by git; regenerate them after +changing a docstring or a notebook. + +## Writing pages + +Hand-written pages are MDX under `docs/content/docs/`; each folder's `meta.json` +orders its sidebar entries. Besides Markdown you can use: + +- math with `$...$` and `$$...$$`, rendered by KaTeX; +- citations with `[@key]`, resolved against `docs/bibliography.bib`; add the + formatted entry to the [References](/references) page too; +- cross-references to the API with `[src][]` or `[text][src_method.stack.src]`; +- Fumadocs components such as `` and ``. + +Python code blocks are executed by the `Documentation` workflow with +`pytest --markdown-docs`, so every example must run on its own. Mark a block that +cannot, for instance one that needs a GPU, with `python notest`. + +## API reference + +The [Python API](/api) pages are generated from the docstrings of the modules +listed in `MODULES` in `docs/scripts/generate-api.mjs`. Write Google-style +docstrings; `Args`, `Returns` and `Raises` sections are rendered as such. + +## Tutorials + +Each tutorial is a notebook at `docs/notebooks//.ipynb`. The build +executes it from top to bottom, failing on any cell error, and renders it to a +page whose title is the notebook's first `#` heading. Keep tutorials quick to +run: they execute on every documentation build. diff --git a/docs/content/docs/contributing/index.mdx b/docs/content/docs/contributing/index.mdx new file mode 100644 index 0000000..3fa6b38 --- /dev/null +++ b/docs/content/docs/contributing/index.mdx @@ -0,0 +1,78 @@ +--- +title: Contributing +description: Workflow, quality gates and code style for working on src_method. +--- + +Bug reports, benchmarks on new hardware and algorithmic improvements are all +welcome. The short version lives in +[`CONTRIBUTING.md`](https://github.com/Algorithmiq/src-method/blob/main/CONTRIBUTING.md); +the pages in this section go into detail. + + + + + + + + + +## Contributor License Agreement + +Before we can merge your contribution, you must sign the [Contributor License +Agreement](https://github.com/Algorithmiq/src-method/blob/main/CLA.md). The CLA +bot posts a one-time comment on your first pull request with instructions. + +## Reporting bugs + +[Open an issue](https://github.com/Algorithmiq/src-method/issues/new/choose) with: + +- the versions of `src_method`, `numpy` and, if relevant, `cupy`; +- a minimal reproducer, ideally with a fixed `seed=`; +- the observed and expected behaviour. + +For numerical-accuracy reports, include the bond dimensions, the number of sites, +the `dtype` and the error metric you used. + +## Development setup + +The repository ships a [Dev Container](https://containers.dev/) configuration and +a Nix flake that install every dependency for you. By hand, you need +[`uv`](https://docs.astral.sh/uv/): + +```bash +uv sync --all-groups --all-extras +uv run prek install --prepare-hooks +``` + +## Quality gates + +All of these must pass before a pull request can be merged; +[`prek`](https://github.com/j178/prek) runs the lint, format and type checks on +every commit, and the `Lint` workflow runs the same hooks in CI. + +```bash +uv run prek run --all-files # lint, format, type check, lockfile +uv run pytest -m "not slow" # fast test suite +uv run pytest # full suite, including slow tests +``` + +New behaviour needs a test. Numerical changes need a test that pins the accuracy, +not just the shapes. + +## Pull requests + +- Keep pull requests focused on a single concern. +- Use [Conventional Commits](https://www.conventionalcommits.org/), optionally + with a [gitmoji](https://gitmoji.dev/) after the colon, e.g. + `fix: 🐛 trim terminal bond on the left-to-right sweep`. +- Update the documentation and the docstrings alongside the code. +- If the change affects performance, include before and after numbers and the + hardware they were measured on. + +## Code style + +The project targets Python 3.11+, is checked with `ruff` under a strict rule set +and type-checked with [`ty`](https://github.com/astral-sh/ty). Public functions +carry type hints and Google-style docstrings without types in the argument list. +The algorithms go through `src_method.utils._backend` rather than importing NumPy +or CuPy directly, so the CPU and GPU paths stay in sync. diff --git a/docs/content/docs/contributing/meta.json b/docs/content/docs/contributing/meta.json new file mode 100644 index 0000000..8508fd7 --- /dev/null +++ b/docs/content/docs/contributing/meta.json @@ -0,0 +1,4 @@ +{ + "title": "Contributing", + "pages": ["testing", "documenting", "dependencies", "versioning", "sonarcloud"] +} diff --git a/docs/content/docs/contributing/sonarcloud.mdx b/docs/content/docs/contributing/sonarcloud.mdx new file mode 100644 index 0000000..28893d7 --- /dev/null +++ b/docs/content/docs/contributing/sonarcloud.mdx @@ -0,0 +1,37 @@ +--- +title: SonarCloud +description: Setting up the SonarCloud analysis. +--- + +Adding SonarCloud analysis for `src_method` takes two steps. + +First, ask a software engineer to enable the SonarCloud app for the repository +in Algorithmiq's GitHub organization settings: + +- Go to [Algorithmiq's GitHub organization settings](https://github.com/organizations/Algorithmiq/settings/profile). +- Click on "GitHub Apps" in the left-hand bar. +- Click "Configure" for SonarCloud. +- In the "Repository Access" menu, add `src-method` to the list. +- Click "Save". + +Then, on the SonarCloud dashboard: + +- Go to the [Algorithmiq organization](https://sonarcloud.io/organizations/algorithmiq/projects). +- Click on the **+** in the top right corner and choose **Analyze new project**. +- Add the `src-method` repository from the list. + + +We run SonarCloud through CI: the analysis method (**Administration > Analysis +method**) must **not** be set to Automatic Analysis. + + +Finally, set the `SONAR_TOKEN` secret for the repository: + +- Copy the token from the [project's GitHub Actions configuration](https://sonarcloud.io/project/configuration/GitHubActions?id=Algorithmiq_src_method). +- Go to the [**Secrets and variables** menu for Actions](https://github.com/Algorithmiq/src-method/settings/secrets/actions). +- Click on **New repository secret**, name it `SONAR_TOKEN` and paste the value. +- Repeat the same steps in the [**Secrets and variables** menu for Dependabot](https://github.com/Algorithmiq/src-method/settings/secrets/dependabot). + +The `Publish Tests Results` job of the test workflow then uploads coverage and +reports, which show up on the SonarCloud dashboard. Without the token, the scan +is skipped rather than failing. diff --git a/docs/content/docs/contributing/testing.mdx b/docs/content/docs/contributing/testing.mdx new file mode 100644 index 0000000..d950202 --- /dev/null +++ b/docs/content/docs/contributing/testing.mdx @@ -0,0 +1,97 @@ +--- +title: Testing +description: Layout of the test suite, markers, warnings and logging in tests. +--- + +The tests live in `tests/` and run with `pytest`: + +```bash +uv run pytest -m "not slow" # what pull requests run +uv run pytest # everything +uv run pytest -k cutoff -x # select by name, stop at the first failure +``` + +Always run tests through `pytest`, never as `python tests/test_.py`. + +| File | Covers | +|---|---| +| `test_package.py` | `apply` and `compress` against `quimb` references, validation, precision | +| `test_stack.py` | `src` over stacks and the sweep behind it | +| `test_tensor_train.py` | the shared train helpers in `_tensor_train` | +| `test_logging.py` | the package leaves the host's logging configuration alone | +| `test_gpu_backend.py` | the CuPy path; skipped without CuPy or a GPU | + +## Writing tests + +- Test one behaviour per test, with a name that says which. +- Build reference networks with `quimb` and compare with `distance` or dense + contractions; numerical changes need a test that pins the accuracy, not just + the shapes. +- Pass a fixed `seed` wherever the result is compared exactly. +- Use `pytest.raises` with `match`, so the test fails if a different error is + raised: + +```python +import pytest + +from src_method import compress + + +def test_rejects_zero_chi_out(): + with pytest.raises(ValueError, match="chi_out"): + compress([], chi_out=0) +``` + +- Parametrize instead of copying a test across inputs: + +```python +import numpy as np +import pytest + + +@pytest.mark.parametrize("dtype", [np.float32, np.complex128]) +def test_dtype(dtype): + assert np.zeros(2, dtype=dtype).dtype == dtype +``` + +## Markers + +`--strict-markers` is on, so only the markers declared in `pyproject.toml` exist: + +- `@pytest.mark.slow` for tests that take a minute or more. Pull requests run + `-m "not slow"`, so mark anything long. +- `@pytest.mark.perf` for `pytest-benchmark` tests, which the benchmark job + compares against `main` and fails on a median slowdown of more than 25 %. + +## Warnings are errors + +`filterwarnings = ["error"]` turns any stray warning into a failure. If a warning +is the behaviour under test, assert it with `pytest.warns`. The exact fallback for +networks with fewer than three sites logs a warning rather than raising one, so +tests of that path assert on the log instead, as below. + +## Logging in tests + +`log_cli` is on, so log records show up live while the tests run. To assert on +them, use the `caplog` [fixture](https://docs.pytest.org/en/stable/how-to/logging.html); +the library logs progress at `DEBUG`, so lower the level of the `src_method` +logger first: + +```python +import logging + +import quimb.tensor as qtn + +from src_method import compress + + +def test_reports_completion(caplog): + caplog.set_level(logging.DEBUG, logger="src_method") + compress(qtn.MPO_rand(4, bond_dim=2, seed=0).arrays, chi_out=2, seed=0) + assert "SRC complete" in caplog.text +``` + +## Coverage + +CI runs the suite with `--cov=src --cov-branch` and reports to SonarCloud. Aim +for every new line to be covered by at least one test. diff --git a/docs/content/docs/contributing/versioning.mdx b/docs/content/docs/contributing/versioning.mdx new file mode 100644 index 0000000..41d0372 --- /dev/null +++ b/docs/content/docs/contributing/versioning.mdx @@ -0,0 +1,25 @@ +--- +title: Versioning +description: How version numbers are computed from git. +--- + +`src_method` follows [semantic versioning](https://semver.org/) and +[PEP 440](https://peps.python.org/pep-0440/). Version numbers are computed from +git by [`hatch-vcs`](https://github.com/ofek/hatch-vcs), which wraps +[`setuptools-scm`](https://setuptools-scm.readthedocs.io) and its [default +scheme](https://setuptools-scm.readthedocs.io/en/latest/usage/#default-versioning-scheme), +so every revision on every branch has an unambiguous version. The build writes it +to `src/src_method/_version.py`, which is generated and never edited by hand. + +The version is available as `src_method.__version__` and looks like +`0.3.3.dev31+gdaa652023.d20261006`: + +- `0.3.3` is the latest tag with its last component increased by one: the + release being worked towards. +- `.dev31` is the number of commits since that tag. +- `+gdaa652023` is the short hash of the current commit. +- `.d20261006` is added only when the working tree has uncommitted changes. + +While in `0.x.y`, breaking changes may occur in minor releases. Commit types +drive the bump: `feat` is a minor change, `fix` a patch, and a `!` marks a +breaking change. diff --git a/docs/content/docs/features/cutoff.mdx b/docs/content/docs/features/cutoff.mdx new file mode 100644 index 0000000..cd8a021 --- /dev/null +++ b/docs/content/docs/features/cutoff.mdx @@ -0,0 +1,33 @@ +--- +title: Adaptive truncation +description: Trim bonds below chi_out with a relative singular-value cutoff. +--- + +By default every inner bond of the output has dimension `chi_out`, even if the +product has lower rank across that cut. Set `cutoff` to trim each bond to its +effective rank: + +```python +import quimb.tensor as qtn + +from src_method import apply + +H = qtn.MPO_identity(8, phys_dim=2) +psi = qtn.MPS_rand_state(8, bond_dim=4, seed=0) + +fixed = apply(H.arrays, psi.arrays, chi_out=32, seed=1) +trimmed = apply(H.arrays, psi.arrays, chi_out=32, cutoff=1e-10, seed=1) + +print([a.shape[0] for a in fixed[1:]]) +print([a.shape[0] for a in trimmed[1:]]) +``` + +During the right-to-left sweep, the QR factorisation at each site is followed by +an SVD of its small `(chi_out, chi_out)` triangular factor, and singular values +below `cutoff * sigma_max` are discarded. The extra cost is negligible next to the +contractions. + +- `cutoff` must lie in `[0.0, 1.0)`; `0.0` (the default) disables trimming. +- `chi_out` remains the upper bound: the cutoff only ever lowers a bond. +- Two-site trains use the exact fallback, which ignores `cutoff` and truncates to + `chi_out`. diff --git a/docs/content/docs/features/gpu.mdx b/docs/content/docs/features/gpu.mdx new file mode 100644 index 0000000..1a4c751 --- /dev/null +++ b/docs/content/docs/features/gpu.mdx @@ -0,0 +1,29 @@ +--- +title: GPU execution +description: Run the sweep on NVIDIA or AMD GPUs through CuPy. +--- + +`src_method` runs on CPU (NumPy) by default and can be accelerated on GPUs +through [CuPy](https://cupy.dev/). Both NVIDIA (CUDA) and AMD (ROCm) GPUs are +supported through optional extras: + +```bash +uv pip install "src_method[gpu-nvidia]" # CUDA 12.x +uv pip install "src_method[gpu-rocm]" # ROCm +``` + +When adding `src_method` to another project's `pyproject.toml`: + +```toml +dependencies = ["src_method[gpu-nvidia]"] +``` + +At runtime, pass `device="gpu"`: + +```python notest +result = apply(H, psi, chi_out=256, device="gpu") +``` + +The inputs can be NumPy or CuPy arrays; they are moved to the device for the +sweep, and the result always comes back as NumPy arrays on the host. Without +CuPy installed, `device="gpu"` raises an `ImportError`. diff --git a/docs/content/docs/features/index.mdx b/docs/content/docs/features/index.mdx new file mode 100644 index 0000000..f5efb3c --- /dev/null +++ b/docs/content/docs/features/index.mdx @@ -0,0 +1,12 @@ +--- +title: Features +description: Stacks, adaptive truncation, precision, GPUs and logging. +--- + + + + + + + + diff --git a/docs/content/docs/features/logging.mdx b/docs/content/docs/features/logging.mdx new file mode 100644 index 0000000..a1b4699 --- /dev/null +++ b/docs/content/docs/features/logging.mdx @@ -0,0 +1,20 @@ +--- +title: Logging +description: Turn on the library's progress and timing messages. +--- + +`src_method` logs through the standard library `logging` module, under the +`src_method` logger, and stays silent by default: it adds only a `NullHandler` +and never touches the root logger or its handlers. + +- Progress and timing of each sweep are logged at `DEBUG`. +- The exact fallback for networks with fewer than three sites logs a `WARNING`. + +To see them, configure logging in your application: + +```python +import logging + +logging.basicConfig(level=logging.INFO) +logging.getLogger("src_method").setLevel(logging.DEBUG) +``` diff --git a/docs/content/docs/features/meta.json b/docs/content/docs/features/meta.json new file mode 100644 index 0000000..b5f5195 --- /dev/null +++ b/docs/content/docs/features/meta.json @@ -0,0 +1,4 @@ +{ + "title": "Features", + "pages": ["stacks", "cutoff", "precision", "gpu", "logging"] +} diff --git a/docs/content/docs/features/precision.mdx b/docs/content/docs/features/precision.mdx new file mode 100644 index 0000000..e6b5efd --- /dev/null +++ b/docs/content/docs/features/precision.mdx @@ -0,0 +1,53 @@ +--- +title: Precision and reproducibility +description: Data types of sketches and results, and seeding. +--- + +## Data types + +The random sketches default to the promoted floating dtype of the inputs, so +single-precision inputs stay single precision and complex inputs get complex +Gaussian sketches. The result has the same dtype as the inputs: + +```python +import numpy as np +import quimb.tensor as qtn + +from src_method import compress + +mps = qtn.MPS_rand_state(6, bond_dim=8, dtype=np.complex64, seed=0) +out = compress(mps.arrays, chi_out=4, seed=1) +assert all(a.dtype == np.complex64 for a in out) +``` + +An explicit `dtype` overrides the sketch dtype, and can promote the result: for +instance, `dtype=np.complex128` on single-precision real inputs returns a +double-precision complex train. + +Complex sketches are circularly symmetric, with real and imaginary parts sharing +the unit variance, and draw from the same random stream as real ones: the same +`seed` gives the same sketches in single and double precision up to rounding. + +## Seeding + +SRC is randomized, so two calls generally return slightly different trains. Pass +an integer `seed` for reproducible results: + +```python +import numpy as np +import quimb.tensor as qtn + +from src_method import compress + +mpo = qtn.MPO_rand(6, bond_dim=8, seed=0) +first = compress(mpo.arrays, chi_out=4, seed=7) +second = compress(mpo.arrays, chi_out=4, seed=7) +assert all(np.array_equal(a, b) for a, b in zip(first, second)) +``` + +## Validation + +`chi_out` must be a positive integer (NumPy integers are accepted, `bool` is +not), and the trains must be open-boundary and agree on their length and the +physical dimensions they join. Invalid input raises a `TypeError` or `ValueError` +naming the culprit before any work is done. diff --git a/docs/content/docs/features/stacks.mdx b/docs/content/docs/features/stacks.mdx new file mode 100644 index 0000000..1806e4e --- /dev/null +++ b/docs/content/docs/features/stacks.mdx @@ -0,0 +1,41 @@ +--- +title: Stacks +description: Contract and compress several trains in a single sweep. +--- + +[`src`](/api/stack#src) accepts any number of trains and compresses their whole +product in one sweep, instead of compressing after every pairwise product: + +```python +import quimb.tensor as qtn + +from src_method import apply, src + +layers = [qtn.MPO_rand(10, bond_dim=2, seed=s) for s in range(3)] +psi = qtn.MPS_rand_state(10, bond_dim=8, seed=3) + +# One sweep over U3 U2 U1 |psi>. +one_shot = src(*(U.arrays for U in layers), psi.arrays, chi_out=32, seed=0) + +# The same product, truncating after every layer. +state = psi.arrays +for U in reversed(layers): + state = apply(U.arrays, state, chi_out=32, seed=0) +``` + +The supported stacks are `MPO^k`, `MPO^k . MPS` and `MPS . MPO^k`; see +[Conventions](/concepts/conventions#contraction-order) for the order and the bra +form. + +## When a single sweep pays off + +The per-site cost of the sweep grows with $\chi_{\text{out}}^2$ times the +*product* of the bond dimensions of all layers, so it grows exponentially with the +depth of the stack. In exchange, a single sweep truncates once instead of once per +layer. In practice that buys at most a moderate gain in accuracy: the error of +the randomized sketch dominates the error compounded across layers. + +Compressing a whole stack at once pays off for shallow stacks of thin layers, such +as two or three Trotter layers; apply anything else pairwise. The [stack +benchmarks](/benchmarks#stacks) measure both accuracy and time against the +pairwise approach. diff --git a/docs/content/docs/getting-started.mdx b/docs/content/docs/getting-started.mdx new file mode 100644 index 0000000..f1a02ac --- /dev/null +++ b/docs/content/docs/getting-started.mdx @@ -0,0 +1,71 @@ +--- +title: Getting Started +description: Install src_method and compress your first product. +--- + +## Installation + +```bash +# CPU only (default) +uv pip install src_method + +# With NVIDIA GPU support (CUDA 12.x) +uv pip install "src_method[gpu-nvidia]" + +# With AMD GPU support (ROCm) +uv pip install "src_method[gpu-rocm]" +``` + +The runtime dependencies are NumPy and `opt_einsum`. The GPU extras add CuPy; +see [GPU execution](/features/gpu). + +## The three entry points + +```python +from src_method import apply, compress, src +``` + +- [`apply`](/api/apply#apply) contracts an MPO with an MPS or another MPO and + compresses the product. +- [`compress`](/api/compress#compress) compresses a single MPS or MPO. +- [`src`](/api/stack#src) contracts a whole stack of trains in one sweep; + `apply` and `compress` are its two- and one-train special cases. + +All three are pure: they never modify their inputs, and return a new list of +site arrays in right-canonical form. Whether a train is an MPS or an MPO is +inferred from the rank of its first site tensor, so there is no wrapper type. + +## A first example + +Apply a random MPO to a random MPS and keep the result at bond dimension 16. +Trains are plain lists of arrays in the [`quimb` layout](/concepts/conventions), +so `quimb` can build the inputs and check the result: + +```python +import quimb.tensor as qtn + +from src_method import apply + +H = qtn.MPO_rand(10, bond_dim=4, phys_dim=2, seed=0) +psi = qtn.MPS_rand_state(10, bond_dim=8, phys_dim=2, seed=1) + +result = apply(H.arrays, psi.arrays, chi_out=32, seed=2) +phi = qtn.MatrixProductState(result) + +exact = H.apply(psi, compress=False) +print(f"max bond: {phi.max_bond()}") +print(f"relative error: {phi.distance(exact) / exact.norm():.2e}") +``` + +The exact product has bond dimension 32, so `chi_out=32` reproduces it +essentially exactly; lower it to trade accuracy for size. Passing `seed` makes the random +sketches, and therefore the result, reproducible. + +Networks with fewer than three sites fall back to an exact SVD-based contraction +and log a warning. + +## Next steps + +- [Concepts](/concepts) explains what SRC does and the index conventions. +- [Features](/features) covers stacks, adaptive truncation and GPUs. +- [Python API](/api) lists every argument. diff --git a/docs/content/docs/index.mdx b/docs/content/docs/index.mdx new file mode 100644 index 0000000..b70d544 --- /dev/null +++ b/docs/content/docs/index.mdx @@ -0,0 +1,55 @@ +--- +title: src_method Documentation +description: Successive Randomized Compression for matrix product states and operators. +--- + +`src_method` is a pure-Python implementation of Successive Randomized +Compression (SRC) [@camano2026src], a randomized algorithm that contracts and +compresses tensor trains in a single sweep. It extends the original MPO-MPS +product to MPO-MPO products, plain compression of an MPS or MPO, and whole +stacks of trains. + +The package has no tensor-network framework dependency: it takes and returns +plain lists of per-site NumPy arrays, in the `quimb` layout [@gray2018quimb], and +runs on GPUs through CuPy. + + +This package is under active development and follows [Semantic +Versioning](https://semver.org/). While in `0.x.y`, breaking changes may occur in +minor releases. Pin your version if you depend on it, and [open an +issue](https://github.com/Algorithmiq/src-method/issues/new/choose) if you have +feedback. + + +New here? Install the package and run the first example in [Getting +Started](/getting-started), then read [Concepts](/concepts) for the algorithm and +the array conventions. + + + + + + + + + +## How the documentation is organised + +**User guide** — use the library. + +- [Getting Started](/getting-started) — installation and a first example. +- [Concepts](/concepts) — how SRC works, and the array layout and contraction + order every function expects. +- [Features](/features) — one-sweep stacks, adaptive truncation, precision and + reproducibility, GPU execution and logging. +- [Tutorials](/tutorials) — runnable notebooks. + +**Reference** — look up details. + +- [Python API](/api) — every public function and argument. +- [Benchmarks](/benchmarks) — accuracy and timing measurements. +- [References](/references) — the papers behind the method. + +**Contributing** — work on `src_method` itself. + +- [Contributing](/contributing) — workflow, quality gates, tests and docs. diff --git a/docs/content/docs/meta.json b/docs/content/docs/meta.json new file mode 100644 index 0000000..a1e7709 --- /dev/null +++ b/docs/content/docs/meta.json @@ -0,0 +1,3 @@ +{ + "pages": ["index", "getting-started", "concepts", "features", "tutorials", "api", "benchmarks", "references", "contributing"] +} diff --git a/docs/content/docs/references.mdx b/docs/content/docs/references.mdx new file mode 100644 index 0000000..3307ca5 --- /dev/null +++ b/docs/content/docs/references.mdx @@ -0,0 +1,37 @@ +--- +title: References +description: The papers behind src_method. +--- + +The SRC algorithm for the compressed MPO-MPS product is introduced in +[@camano2026src]; `src_method` extends it to MPO-MPO products, plain compression +and stacks of trains. It builds on the randomized range finder of +[@halko2011finding]. The array layout follows `quimb` [@gray2018quimb], which the +tests and tutorials also use to build reference networks. + +## Bibliography + +
    +
  1. + C. Camaño, E. N. Epperly, and J. A. Tropp, + "Successive randomized compression: A randomized algorithm for the + compressed MPO-MPS product," + Quantum, vol. 10, p. 2022, 2026. + doi:10.22331/q-2026-03-10-2022, + arXiv:2504.06475 +
  2. +
  3. + N. Halko, P.-G. Martinsson, and J. A. Tropp, + "Finding structure with randomness: Probabilistic algorithms for + constructing approximate matrix decompositions," + SIAM Review, vol. 53, no. 2, pp. 217–288, 2011. + doi:10.1137/090771806 +
  4. +
  5. + J. Gray, + "quimb: A python package for quantum information and many-body + calculations," + Journal of Open Source Software, vol. 3, no. 29, p. 819, 2018. + doi:10.21105/joss.00819 +
  6. +
diff --git a/docs/developer-guide/dependencies.md b/docs/developer-guide/dependencies.md deleted file mode 100644 index e768963..0000000 --- a/docs/developer-guide/dependencies.md +++ /dev/null @@ -1,35 +0,0 @@ -# Managing dependencies - -The dependencies are organized in a hierarchy: - -- system dependencies. If any, these are satisfied through the system package manager. -- run dependencies, _e.g._ those specified in the `dependencies` array in - `pyproject.toml` and which are required to run aurora in production. These - can be satisfied through [uv]. -- development dependencies, _e.g._ those specified in the - `[dependency-groups]` table in `pyproject.toml`. These are **not** - needed in production and can be satisfied through [uv]. -- extra dependencies, _e.g._ those specified in the - `[project.optional-dependencies]` table in `pyproject.toml` and that are - required in production to enable optional features. These can also be satisfied - with [uv]. - -## Why uv? - -There are many command-line tools to interact with public and private Python package indexes. -[uv] is one of the newest around and it's a legitimate question to ask **why not -use simply [pip]?** - -- [uv] has a lockfile format which is compact and multi-platform. -- [uv] allows granular control over _which index_ to use to gather _which - dependency_ from. This is important when interacting with private indexes. -- [uv] is very fast. - -## How do I handle dependencies? - -What you would need to do is: - -* Modify the `pyproject.toml` as needed. -* Run `uv sync` to re-install `src_method` with the modified dependency list and regenerate the lockfile. - -[uv]: https://docs.astral.sh/uv/ diff --git a/docs/developer-guide/sonarcloud.md b/docs/developer-guide/sonarcloud.md deleted file mode 100644 index 893b842..0000000 --- a/docs/developer-guide/sonarcloud.md +++ /dev/null @@ -1,31 +0,0 @@ -# Setting up SonarCloud - -Adding SonarCloud analysis for `src_method` is done in two steps. - -First, ask a software engineer to enable the SonarCloud app for you repository. -This is done through Algorithmiq’s Github organization settings: - -- Go to [Algorithmiq’s Github organization settings](https://github.com/organizations/Algorithmiq/settings/profile) -- Click on "GitHub Apps" on the left-hand vertical bar -- Click "Configure" for Sonarcloud -- In the "Repository Access" menu, add your repo `src_method` to the list, to make it visible to the app. -- Click "Save" - -Then, on the Sonarcloud dashboard: - -- Go to the [Algorithmiq organization](https://sonarcloud.io/organizations/algorithmiq/projects) -- Click on the **+** on the top right corner and choose **Analyze new project** -- Add the `src_method` repo from the list - -!!! warning - We use Sonarcloud through the CI: the analysis method (accessible from **Administration > Analysis method**) must **not** be set to Automatic Analysis. - -Finally, you need to set the `SONAR_TOKEN` for your repository: - -- Copy the token from [here](https://sonarcloud.io/project/configuration/GitHubActions?id=Algorithmiq_src_method) -- Go to [the **Secrets and variables** menu for actions](https://github.com/Algorithmiq/src-method/settings/secrets/actions) -- Click on **New repository secret** -- Type `SONAR_TOKEN` as name and paste the value you copied from the SonarCloud settings. -- Repeat the same steps in [the **Secrets and variables** menu for Dependabot](https://github.com/Algorithmiq/src-method/settings/secrets/dependabot) - -Now the repo is added and reports can be seen from the Sonarcloud dashboard and automatically generated with the Github action. diff --git a/docs/developer-guide/testing.md b/docs/developer-guide/testing.md deleted file mode 100644 index 29ee286..0000000 --- a/docs/developer-guide/testing.md +++ /dev/null @@ -1,305 +0,0 @@ -# Writing Tests - -Unit tests are an important part of writing software. Their usefulness comes in many ways: - -* it allows you to make quick verification of the changes applied -* it makes sure that the code you are using is correct -* it speeds up refactoring and optimization of the code - -Therefore it is important to have many tests, which helps identifying potential issues. -​ -Below we present some technical aspects of testing. The list is by no means -complete and if you're interested, please check the [pytest documentation]. - -## General rules - -There are several simple rules that should be followed in order for unit testing to serve its purpose: - -1. Unit tests should test single functionality in a meaningful way, -2. All public methods should have their own tests, -3. All lines should be tested by at least one test ([code coverage]), and -4. Tests should be as fast as possible (yet meaningful) - -The last point is particularly important as all tests are performed on the -continuous integration (CI) service, on which we have large, yet limited number -of computational resources available. - -Furthermore, having too many slow tests prohibits effective refactoring and -optimization. -On the other hand, speed is not the main factor: if you see that increasing time -is essential for making good tests, feel free to write such a test (but mark it -as slow as explained below). -In any case, a single test should not take more than a few seconds. Ideally one -test case should run in a fraction of a second. - -## Technical aspects - -### Naming convention -​ -All tests should be placed in the `tests` folder. `pytest` test discovery analyzes the -whole repository looking for Python scripts whose names are of -the form `test_.py`. - -???+ warning - - You should always run the test scripts as: - - ```python - pytest test_.py - ``` - and _never_ as: - - ```python - python test_.py - ``` - Running in "isolation" will, in many cases, _not work_ as you'd expect. -​ -All test functions within the files should have names following the pattern -`test_`. Optionally, tests can be grouped inside classes whose name -follows the pattern `Test`. -​ -### Simple tests -​ -Within a test function, checks are performed using the `assert` statement: -​ -```python -def test_addition(): - assert 2*2 == 4 -``` - -The test passes if no error occurred when it was run _and_ all assertions are -satisfied. -​ -If error was the expected behavior, you can use `pytest.raises`: -​ -```python -import pytest -​ -def test_value(): - with pytest.raises(ValueError, match=r'must be \d+$'): - raise ValueError("value must be 42") -``` - -The first argument to `pytest.raises` is the exception type. While it can be -omitted, it is bad practice to do so,[^1] as the test will pass for _any_ other -exception that might be raised by the code you are trying to test. - -The second argument, `match`, is useful to further _narrow down_ the exception -we are trying to test. You should pass is a string or a regular expression -(like in the example) to match against the error message reported by the -exception. When trying to test raised standard library exceptions (like -`ValueError` or `TypeError`) it is good practice to also use the `match` -argument to `pytest.raises`. - -### The `pytest` command line -​ -You can alter the default behavior of the `pytest` invocation with command line -arguments. Some useful options: - -1. `-x` run `pytest` until first error encountered -2. `-m "not slow"` only run tests not marked as slow. -3. `-m "slow"` only run tests marked as slow. -3. `--reruns=[m]` rerun failed tests at most `m` times (useful if there are flaky tests) -4. `--durations=[m]` show `m` slowest test durations -5. `--durations-min=[m]` minimal duration in seconds for inclusion in slowest list, defaults to 0.005 -6. `-v` run in verbose mode. You can add multiple `v`s to increase the verbosity further -7. `-s` to not capture stdout. Useful if you are using `print` for debugging - -### Marking tests -​ -We may organize tests in our test suite more effectively -by adding _marks_ to them. -Below we present a list of marks which may be particularly useful. All the marks -should be placed right before the method. - -1. `@pytest.mark.slow`: indicates that the test function will take a long time -to execute. -1. `@pytest.mark.skip("[Message]")`: skip the test. In place of `[Message]` you -should write the reason why the test is skipped. Please use this mark **only if -absolutely necessary**. -1. `@pytest.mark.parametrize("[varname]", [val1, val2, ...])`: parametrize the -test over different values of the arguments to the test function. See a simple -example below. -​ -```python -import pytest -​ -@pytest.mark.parametrize( - ("test_input", "expected"), - [ - ("3+5", 8), - ("2+4", 6), - ("6*9", 42), - ], -) -def test_eval(test_input, expected): - assert eval(test_input) == expected -``` - -### Collecting test cases with `pytest-cases` - -Test parametrization is a powerful technique to avoid code repetition when -writing tests. However, it can be hard to understand _exactly_ what and how -it's being parameterized. `pytest-cases` (see [documentation]) allows to collect the different -parametrizations into case functions/classes, which can the subsequently be -(re-)used in a parameterization. This leads to tidier test scripts. - -See this example from the `pytest-cases` documentation: - -```python -from pytest_cases import parametrize_with_cases, case - -class Foo: - @case(tags=["one"], id="1") - def case_a_positive_int(self): - return 1 - - @case(tags=["two"], id="2") - def case_another_positive_int(self): - return 2 - -@parametrize_with_cases("a", cases=Foo) -def test_foo(a): - assert a > 0 -``` - -In the parameterization, test cases can be filtered using tags or by globbing -function names. - -???+ info - - By default, `pytest-cases` only considers function names following the pattern - `case_` to be valid test cases. - -### Reusable testing functionality - -#### Reusing data with test fixtures - -Often times you find yourself writing tests that use _the same_ input data to -perform their checks. In order to reduce code duplication, the standard approach -is to use test [fixtures]. -It is very easy to create fixtures with `pytest`: - -```python -import pytest - - -@pytest.fixture -def first_entry(): - return "a" -``` - -and using them is a matter of adding an input argument to your test function: - -```python -def test_string(first_entry): - # Assert - assert first_entry == "a" -``` - -Fixtures can be defined in the same file as the test or placed in `conftest.py` -files in the _same_ or _any parent_ folder of the test file. -`conftest.py` files are special files for `pytest`: they are "evaluated" during -test collection, such that any globally defined data is available to the test -functions when they are executed.[^2] - -Fixtures can be used as arguments to other fixtures. Also, they can be _scoped_, -to decide _when_ the fixture should be executed. -By default, each fixture is function-scoped and is executed _before_ every test -function that needs it. -However, it's better to execute expensive fixtures fewer times and cache their -result. -This is achieved using the `scope` keyword argument to the the `pytest.fixture` -decorator. The available scopes are [documented here]. - -#### Reusing functions with `pytest-helpers-namespace` - -Other times what you want to reuse is not some _data_ produced by a function, but the function itself. -A typical use case is as follows: - -* You're creating a parameterized test. -* The value of the parameter is computed through other parameters. - -`pytest` offers functionality for this in terms of [parameterized fixtures](https://docs.pytest.org/en/stable/how-to/fixtures.html#parametrizing-fixtures) -and [indirect parameterization](https://docs.pytest.org/en/stable/example/parametrize.html#indirect-parametrization), however: - -* The former requires one central place (the fixture definition) where to list -all possible combinations of valid parameters. When running the test using the -parameterized fixture, _all parameter combinations_ will be executed. Excluding -cases to run is cumbersome. -* The latter results in a rather unintuitive way of preparing data for a test. -Especially for those use cases where _multiple arguments_ are needed to -prepare the data for the test. - -While parameterized fixture and indirect parameterization are very useful, -`pytest-helpers-namespace` offers a [lightweight alternative]. -One can define _functions_ in any of the `conftest.py` files -and decorate them appropriately: - -```python -import pytest - - -@pytest.helpers.register -def foo(bar): - return bar -``` - -such that they can be reused in the test files, without having to import -`conftest.py` first: - -```python -def test_helper_namespace(): - assert pytest.helpers.foo(True) is True -``` - -### How to use logging with tests - -Within `aurora`, we adopt a `pytest` configuration that allows to see the output -from the logger when executing tests: - -```toml -[tool.pytest.ini_options] -log_cli = true -log_cli_format = "%(asctime)s %(levelname)s %(message)s" -log_date_format = "%Y-%m-%d %H:%M:%S" -``` - -The default logging level is `logging.WARNING`. - -When writing your tests, you might find useful to obtain output to screen to -check what is going on with the code you are trying to test. Traditionally, one -would reach for the `print` function, but we explicitly discourage such uses and -favour the use of logging instead. -Also, while we don't require it, you might want to test the log messages emitted -by your code, which would require _capturing_ the output from the logger within -the test function. - -The `caplog` [fixture] from `pytest` comes to the rescue in both cases. -The following example shows how to set the log level for the -`aurora.chemistry.eos` submodule to `logging.INFO`: - -```python -def test_foo(caplog): - caplog.set_level(logging.INFO, logger="aurora.chemistry.eos") -``` - -Running the test on the command line will show logging output from the submodule. -The fixture has attributes `records` and `record_tuples`, which store the data -sent to the logger. These can be used if you want to check that specific log -messages have been emitted by your code. - - -[pytest documentation]: https://docs.pytest.org -[code coverage]: https://en.wikipedia.org/wiki/Code_coverage -[documentation]: https://smarie.github.io/python-pytest-cases/ -[fixtures]: https://docs.pytest.org/en/stable/explanation/fixtures.html# -[^1]: luckily, Ruff will flag this bad practice. -[^2]: this is why you should _never_ think of the test scripts as usual Python scripts! Details of how `conftest.py` works can be found [here](https://docs.pytest.org/en/stable/reference/fixtures.html#conftest-py-sharing-fixtures-across-multiple-files). As a corollary to this, never add the boilerplate: -```python -if __name__ == "__main__": -``` -to the bottom of the test file. You can execute any test through `pytest` by simply _selecting_ it with the `-k` flag. -[documented here]: https://docs.pytest.org/en/stable/how-to/fixtures.html#fixture-scopes -[lightweight alternative]: https://pytest-helpers-namespace.readthedocs.io/en/latest/ -[fixture]: https://docs.pytest.org/en/stable/how-to/logging.html diff --git a/docs/developer-guide/versioning.md b/docs/developer-guide/versioning.md deleted file mode 100644 index e2ae1ed..0000000 --- a/docs/developer-guide/versioning.md +++ /dev/null @@ -1,23 +0,0 @@ -# Versioning scheme - -Aurora follows [semantic versioning] and [PEP440] for its version numbers. -We use [setuptools-scm] to compute unambiguous version numbers for any revision -on any branch, either pushed or in local development. -We adopt the default -[convention](https://setuptools-scm.readthedocs.io/en/latest/usage/#default-versioning-scheme) in [setuptools-scm]. - -The version number can be obtained as `aurora.__version__` and it will look -something like `0.2.1.dev1151+g51faf286.d20231003`: - -* The first part `X.Y.Z` is the _current latest tag_ with the rightmost version - number augmented by 1. Thus, `0.2.1` is the _next_ tag that we are working - towards, starting from the currently released tag `0.2.0`. -* The second part `.devN` is the _number of commits since the latest tag_, in - this case 1151 commits. -* The third part `+gXXXXXXXX` is the _current commit short hash_. -* The fourth part `.dYYYYMMDD` is only added in local development, when there - are uncommitted changes in the tree (dirty state). - -[semantic versioning]: https://semver.org/ -[PEP440]: https://peps.python.org/pep-0440/ -[setuptools-scm]: https://setuptools-scm.readthedocs.io diff --git a/docs/gen_ref_pages.py b/docs/gen_ref_pages.py deleted file mode 100644 index b79ff23..0000000 --- a/docs/gen_ref_pages.py +++ /dev/null @@ -1,34 +0,0 @@ -# ruff: noqa: INP001 -"""Generate the code reference pages and navigation.""" -from __future__ import annotations - -from pathlib import Path - -import mkdocs_gen_files - -nav = mkdocs_gen_files.Nav() - -for path in sorted(Path("src").rglob("*.py")): - module_path = path.relative_to("src").with_suffix("") - doc_path = path.relative_to("src").with_suffix(".md") - full_doc_path = Path("reference", doc_path) - - parts = tuple(module_path.parts) - - if parts[-1] == "__init__": - parts = parts[:-1] - doc_path = doc_path.with_name("index.md") - full_doc_path = full_doc_path.with_name("index.md") - elif parts[-1] == "__main__": - continue - - nav[parts] = doc_path.as_posix() - - with mkdocs_gen_files.open(full_doc_path, "w") as fd: - ident = ".".join(parts) - fd.write(f"::: {ident}") - - mkdocs_gen_files.set_edit_path(full_doc_path, path) - -with mkdocs_gen_files.open("reference/SUMMARY.md", "w") as nav_file: - nav_file.writelines(nav.build_literate_nav()) diff --git a/docs/index.md b/docs/index.md deleted file mode 100644 index 913f643..0000000 --- a/docs/index.md +++ /dev/null @@ -1,152 +0,0 @@ -# SRC Method - -## Successive Randomized Compression - -An implementation of the SRC algorithm introduced on [arXiv:2504.06475](https://arxiv.org/abs/2504.06475), but extending the idea to other kinds of tensor networks. - -### Features - -The following primitives are supported: - -1. MPO-MPS randomized contraction-compression. -2. MPO-MPO randomized contraction-compression. -3. MPO randomized compression. -4. MPS randomized compression. -5. Randomized contraction-compression of a whole stack of trains in one sweep: - `MPO^k`, `MPO^k . MPS` and `MPS . MPO^k`. - -`src_method` has no tensor-network framework dependency: it takes and returns plain lists of per-site NumPy arrays, one array per site. - -```python -from src_method import apply, compress, src -``` - -The `apply` function covers cases 1 and 2 above, the `compress` function cases 3 and 4, and `src` all five: `apply` and `compress` are its two- and one-train special cases. All three functions are pure, meaning no in-place modification ever happens. The user should -manage the assignment of the returned objects, possibly overwriting the input variables. -See the [reference documentation](algorithmiq.github.io/src_method/) for details, and the [tests](../tests/) or [benchmarks](../benches/) folders for usage examples. - -Whether a train is an MPS or an MPO is inferred from the rank of its first site tensor, so no wrapper type is needed. - -**NOTE**: the current implementation targets tensor networks with 3 or more sites. For smaller networks, an exact SVD-based fallback is dispatched, with a warning. - -### Tensor Indexing Conventions - -The array layout follows the default `quimb` tensor indexing conventions, so results round-trip through [Quimb](https://quimb.readthedocs.io/en/latest/autoapi/quimb/tensor/index.html) without any permutation: - -```python -import quimb.tensor as qtn - -result = qtn.MatrixProductOperator(apply(H1.arrays, H2.arrays, chi_out=64)) -``` - -- **MPO Tensors:** Bulk tensors have index order `('l', 'r', 'u', 'd')`. - Boundary tensors (at the edges) are rank-3, dropping the outer `'l'` or `'r'` index. - -- **MPS Tensors:** Bulk tensors have index order `('l', 'r', 'u')`. - Boundary tensors are rank-2, dropping the outer bond index. - -Where `'l'`/`'r'` are left/right virtual bonds and `'u'`/`'d'` are the upper/lower physical legs. -Please keep this in mind when constructing or manipulating tensors directly. - -### Contraction Conventions - -`src` contracts a *stack* of trains and compresses the result in a single sweep: - -```python -from src_method import src - -state = src(U3, U2, U1, psi, chi_out=64) # U3 U2 U1 |psi>, U1 acts first -``` - -The stack is written in mathematical order. Each contraction joins the `'d'` leg of a train with the `'u'` leg (or the physical leg of an MPS) of the train to its right: - -| Stack | Contraction | Result | -|---|---|---| -| `src(A)`, `src(psi)` | none | compressed MPO or MPS | -| `src(A, B, ...)` | `A.d` with `B.u` | MPO | -| `src(A, ..., psi)` | `A.d` with `psi` | MPS on the `'u'` leg of `A` (a ket) | -| `src(phi, A, ...)` | `phi` with `A.u` | MPS on the `'d'` leg of the last MPO (a bra) | - -An MPS may appear only first or last, and not both. `apply(A, B)` and `compress(A)` are the two- and one-train cases; `apply` accepts only an MPO on the left. - -A leading MPS is a row vector used **without conjugation**: `src(phi, A, B)` computes `phiᵀ A B`, which equals `src(Bᵀ, Aᵀ, phi)` with `ᵀ` swapping the `'u'` and `'d'` legs. For the physical bra `=1.78 -3. The VSCode [DevContainers extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers). -4. (Optional, but **highly recommended**) The [GitHub CLI] tool. - -You can clone the repository with: - -``` -git clone https://github.com/Algorithmiq/src-method.git -``` - -We recommend using a Git credential manager, such as [GitHub CLI], configured to -use HTTPS as protocol for Git operations. - -Once the code is locally available, you can open its containing folder in -[Visual Studio Code]. The editor will then set up the [DevContainer] for you. -The first time you open the folder the startup will take a few minutes. Once the -process is done, you will have _all_ project dependencies installed, including -the git hooks. -[Visual Studio Code] will be already configured with all the extensions helpful for Python development. - -**Note** that the order in which Visual Studio Code loads the extensions in the -DevContainer is non-deterministic. You might have to execute the *Reload -Window* command to get everything to work as expected after a fresh build of the -container. - -[DevContainer]: https://containers.dev/ -[Docker]: https://docs.docker.com/get-docker/ -[Visual Studio Code]: https://code.visualstudio.com/ -[GitHub CLI]: https://cli.github.com/ -[at this link]: https://docs.algorithmiq.fi/src_method - -### Logging - -`src_method` logs through the standard library `logging` module, under the -`src_method` logger, and stays silent by default: it adds only a `NullHandler` -and never touches the root logger or its handlers. Progress and timing messages -are emitted at `DEBUG`, the small-network fallback at `WARNING`. To see them, -configure logging in your application: - -```python -import logging - -logging.basicConfig(level=logging.INFO) -logging.getLogger("src_method").setLevel(logging.DEBUG) -``` diff --git a/docs/javascripts/config.js b/docs/javascripts/config.js deleted file mode 100644 index fd764a7..0000000 --- a/docs/javascripts/config.js +++ /dev/null @@ -1,16 +0,0 @@ -window.MathJax = { - tex: { - inlineMath: [["\\(", "\\)"]], - displayMath: [["\\[", "\\]"]], - processEscapes: true, - processEnvironments: true - }, - options: { - ignoreHtmlClass: ".*|", - processHtmlClass: "arithmatex" - } -}; - -document$.subscribe(() => { - MathJax.typesetPromise() -}) diff --git a/docs/next.config.mjs b/docs/next.config.mjs new file mode 100644 index 0000000..8996efa --- /dev/null +++ b/docs/next.config.mjs @@ -0,0 +1,17 @@ +import { createMDX } from 'fumadocs-mdx/next'; + +const withMDX = createMDX(); + +/** @type {import('next').NextConfig} */ +const config = { + output: 'export', + // GitHub Pages serves `dir/index.html` for `/dir/` reliably, unlike `dir.html` + // next to a `dir/` folder of the same name. + trailingSlash: true, + // Empty for `npm run dev`; the Pages build sets it to the repository subpath. + basePath: process.env.NEXT_PUBLIC_BASE_PATH ?? '', + reactStrictMode: true, + images: { unoptimized: true }, +}; + +export default withMDX(config); diff --git a/docs/notebooks/accuracy_vs_bond_dimension/accuracy_vs_bond_dimension.ipynb b/docs/notebooks/accuracy_vs_bond_dimension/accuracy_vs_bond_dimension.ipynb new file mode 100644 index 0000000..ebc8a3c --- /dev/null +++ b/docs/notebooks/accuracy_vs_bond_dimension/accuracy_vs_bond_dimension.ipynb @@ -0,0 +1,131 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "9649f8fd", + "metadata": {}, + "source": [ + "# Accuracy versus bond dimension\n", + "\n", + "This tutorial applies a random MPO to a random MPS with `apply` and measures how\n", + "the error of the compressed product falls as the output bond dimension `chi_out`\n", + "grows. As a yardstick it uses `quimb`'s contract-then-truncate, which computes\n", + "the exact product and truncates it with SVDs: close to the best a train of that\n", + "bond dimension can do." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "be003627", + "metadata": {}, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "import quimb.tensor as qtn\n", + "\n", + "from src_method import apply" + ] + }, + { + "cell_type": "markdown", + "id": "6231ca09", + "metadata": {}, + "source": [ + "## The problem\n", + "\n", + "A 16-site MPO with bond dimension 4 applied to an MPS with bond dimension 16: the\n", + "exact product has bond dimension 64, which is still small enough to form and\n", + "use as the reference." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f2f6cbb9", + "metadata": {}, + "outputs": [], + "source": [ + "n_sites = 16\n", + "H = qtn.MPO_rand(n_sites, bond_dim=4, phys_dim=2, seed=0)\n", + "psi = qtn.MPS_rand_state(n_sites, bond_dim=16, phys_dim=2, seed=1)\n", + "\n", + "exact = H.apply(psi, compress=False)\n", + "norm = exact.norm()\n", + "print(f\"exact bond dimension: {exact.max_bond()}\")" + ] + }, + { + "cell_type": "markdown", + "id": "00360359", + "metadata": {}, + "source": [ + "## Sweeping `chi_out`\n", + "\n", + "`apply` takes and returns plain lists of site arrays, so `.arrays` unwraps the\n", + "`quimb` networks and `qtn.MatrixProductState` wraps the result back up. A fixed\n", + "`seed` keeps the random sketches, and the figure, reproducible." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6ecb9224", + "metadata": {}, + "outputs": [], + "source": [ + "chis = [4, 8, 12, 16, 24, 32, 48, 64]\n", + "src_errors, svd_errors = [], []\n", + "for chi in chis:\n", + " phi = qtn.MatrixProductState(apply(H.arrays, psi.arrays, chi_out=chi, seed=2))\n", + " src_errors.append(phi.distance(exact) / norm)\n", + "\n", + " truncated = exact.copy()\n", + " truncated.compress(max_bond=chi)\n", + " svd_errors.append(truncated.distance(exact) / norm)\n", + "\n", + "for chi, e_src, e_svd in zip(chis, src_errors, svd_errors):\n", + " print(f\"chi_out={chi:3d} SRC {e_src:.2e} SVD {e_svd:.2e}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5f171ea7", + "metadata": {}, + "outputs": [], + "source": [ + "fig, ax = plt.subplots(figsize=(6, 4))\n", + "ax.semilogy(chis, np.maximum(src_errors, 1e-16), \"o-\", label=\"SRC (apply)\")\n", + "ax.semilogy(chis, np.maximum(svd_errors, 1e-16), \"s--\", label=\"exact + SVD truncation\")\n", + "ax.set_xlabel(\"chi_out\")\n", + "ax.set_ylabel(\"relative error\")\n", + "ax.legend()\n", + "fig.tight_layout()" + ] + }, + { + "cell_type": "markdown", + "id": "dcd6b6ff", + "metadata": {}, + "source": [ + "Both curves fall together and reach rounding error once `chi_out` matches the\n", + "exact bond dimension of 64. SRC sits somewhat above the SVD truncation: it never\n", + "forms the exact product, and its randomized sketch is not optimal. In exchange,\n", + "its cost grows with `chi_out**2` times the input bond dimensions instead of with\n", + "the cube of the exact bond dimension, which is what makes it pay off once the\n", + "exact product no longer fits." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/package-lock.json b/docs/package-lock.json new file mode 100644 index 0000000..8850ef3 --- /dev/null +++ b/docs/package-lock.json @@ -0,0 +1,7340 @@ +{ + "name": "docs", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "docs", + "version": "0.0.0", + "hasInstallScript": true, + "dependencies": { + "cnfast": "^0.2.0", + "fumadocs-core": "16.15.17", + "fumadocs-mdx": "15.4.5", + "fumadocs-ui": "16.15.17", + "katex": "^0.18.9", + "lucide-react": "^1.49.0", + "next": "16.3.7", + "react": "^19.3.0", + "react-dom": "^19.3.0", + "rehype-citation": "^2.3.2", + "rehype-katex": "^7.0.1", + "rehype-raw": "^7.0.0", + "remark-math": "^6.0.0" + }, + "devDependencies": { + "@tailwindcss/postcss": "^4.3.3", + "@types/mdx": "^2.0.14", + "@types/node": "^26.6.3", + "@types/react": "^19.3.0", + "@types/react-dom": "^19.3.0", + "postcss": "^8.5.28", + "tailwindcss": "^4.3.3", + "typescript": "^7.0.2", + "yaml": "^2.9.1" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@citation-js/core": { + "version": "0.7.21", + "resolved": "https://registry.npmjs.org/@citation-js/core/-/core-0.7.21.tgz", + "integrity": "sha512-Vobv2/Yfnn6C6BVO/pvj7madQ7Mfzl83/jAWwixbemGF6ZThhGMz8++FD9hWHyHXDMYuLGa6fK68c2VsolZmTA==", + "license": "MIT", + "dependencies": { + "@citation-js/date": "^0.5.0", + "@citation-js/name": "^0.4.2", + "fetch-ponyfill": "^7.1.0", + "sync-fetch": "^0.4.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@citation-js/date": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@citation-js/date/-/date-0.5.1.tgz", + "integrity": "sha512-1iDKAZ4ie48PVhovsOXQ+C6o55dWJloXqtznnnKy6CltJBQLIuLLuUqa8zlIvma0ZigjVjgDUhnVaNU1MErtZw==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@citation-js/name": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@citation-js/name/-/name-0.4.2.tgz", + "integrity": "sha512-brSPsjs2fOVzSnARLKu0qncn6suWjHVQtrqSUrnqyaRH95r/Ad4wPF5EsoWr+Dx8HzkCGb/ogmoAzfCsqlTwTQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/@citation-js/plugin-bibjson": { + "version": "0.7.21", + "resolved": "https://registry.npmjs.org/@citation-js/plugin-bibjson/-/plugin-bibjson-0.7.21.tgz", + "integrity": "sha512-Q3eRpeV3pDqX91fvJ8xoYGJk4jB5MQD2woEr6GAoAauAzGVE19J5Lw0SksCHegoAn4z0ZbWMXtOq6rwZPtERbA==", + "license": "MIT", + "dependencies": { + "@citation-js/date": "^0.5.0", + "@citation-js/name": "^0.4.2" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@citation-js/core": "^0.7.0" + } + }, + "node_modules/@citation-js/plugin-bibtex": { + "version": "0.7.21", + "resolved": "https://registry.npmjs.org/@citation-js/plugin-bibtex/-/plugin-bibtex-0.7.21.tgz", + "integrity": "sha512-O008pSsJgiYKn4+7gAWrbNpNdUH++aMeYmZaJ2oFQ8X1tcY5jNBxJcr0zZojNtUi5CVOaXXHQ0yIifoUhuF2Vg==", + "license": "MIT", + "dependencies": { + "@citation-js/date": "^0.5.0", + "@citation-js/name": "^0.4.2", + "moo": "^0.5.1" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@citation-js/core": "^0.7.0" + } + }, + "node_modules/@citation-js/plugin-csl": { + "version": "0.7.22", + "resolved": "https://registry.npmjs.org/@citation-js/plugin-csl/-/plugin-csl-0.7.22.tgz", + "integrity": "sha512-/rGdtbeP3nS4uZDdEbQUHT8PrUcIs0da2t+sWMKYXoOhXQqfw3oJJ7p4tUD+R8lptyIR5Eq20/DFk/kQDdLpYg==", + "license": "MIT", + "dependencies": { + "@citation-js/date": "^0.5.0", + "citeproc": "^2.4.6" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@citation-js/core": "^0.7.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.3.tgz", + "integrity": "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.2.tgz", + "integrity": "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.2.tgz", + "integrity": "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.2.tgz", + "integrity": "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.2.tgz", + "integrity": "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.2.tgz", + "integrity": "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.2.tgz", + "integrity": "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.2.tgz", + "integrity": "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.2.tgz", + "integrity": "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.2.tgz", + "integrity": "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.2.tgz", + "integrity": "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.2.tgz", + "integrity": "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.2.tgz", + "integrity": "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.2.tgz", + "integrity": "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==", + "cpu": [ + "mips64el" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.2.tgz", + "integrity": "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.2.tgz", + "integrity": "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.2.tgz", + "integrity": "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.2.tgz", + "integrity": "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.2.tgz", + "integrity": "sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.2.tgz", + "integrity": "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.2.tgz", + "integrity": "sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.2.tgz", + "integrity": "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.2.tgz", + "integrity": "sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.2.tgz", + "integrity": "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.2.tgz", + "integrity": "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.2.tgz", + "integrity": "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.2.tgz", + "integrity": "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@floating-ui/core": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.8.0.tgz", + "integrity": "sha512-0CIZ5itps/8x7BG8dEIhs53BvCUH2PCoogtakwRTut+Arm58sJooJ0AuZhLw2HJYIR5cMLNPBSS728sPho2khQ==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.12" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.8.0.tgz", + "integrity": "sha512-yXSrzeHZBTZadLOlfyhCkJHNeLJnHRnRInwdZ40L7ZiaAtrBwoYlsDrX3v5zB1Utk7CLfzcOVnVVWoXEky7Ceg==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.8.0", + "@floating-ui/utils": "^0.2.12" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.9.tgz", + "integrity": "sha512-JDjEFGCpImxDCA7JJKviA0M9+RtmJdj0m/NVU5IMgBK+AmZouAQQ7/+2GLH0GXXY0YMw9oXPB8hKdbPYg5QLYg==", + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.8.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.12.tgz", + "integrity": "sha512-HpCo8tmWzLVad5s2d19EhAz5zqrrQ6s69qd6moPMQvkOuSwDT1YgRfWSVuc4ennqrgv3OHppiOGMQ7oC13yIww==", + "license": "MIT" + }, + "node_modules/@fuma-translate/react": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@fuma-translate/react/-/react-1.0.2.tgz", + "integrity": "sha512-uOiOtBx3nRXR8Nu1GzBf1tApgF1FErDBTHxRIAQeyQdyOoZbrNRN6H4kDCWObY4qyGeGbHydG0DHzgeUgFDMIw==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^19.2.0", + "react-dom": "^19.2.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@fumadocs/tailwind": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@fumadocs/tailwind/-/tailwind-0.1.2.tgz", + "integrity": "sha512-VppeXgIRXjZMgpf2qijj1hcfxyeYl1s0ok8k6N3jyjiX64M7sDwnt2zGPd6dbfDybgbBvDw6C6J1e42gB5NzsA==", + "license": "MIT", + "peerDependencies": { + "tailwindcss": "^4.0.0" + }, + "peerDependenciesMeta": { + "tailwindcss": { + "optional": true + } + } + }, + "node_modules/@fumari/image-size": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@fumari/image-size/-/image-size-0.1.1.tgz", + "integrity": "sha512-iaiV2wyzJ4mW358NX4CX3yGit+WjKYzpaQ+rldK9BjL/5jFpeV6ruWnZVq7MEyMn3Gd0DLi8g/79NZAAQaGscw==", + "license": "MIT" + }, + "node_modules/@img/colour": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", + "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.35.4.tgz", + "integrity": "sha512-Uhfl4V4lhP2nbUVF9+hyH1+luj86f1gUFeo8ALYxFoULoU+G87D43BfeMP8XHsk9boxAnCY/bf2EHwhA7MuGsA==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.3.3" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.35.4.tgz", + "integrity": "sha512-hWniXY3bG5qKpkKrAwPe4y+VTPmf086YQAnkxWh7uA1YrlRouWGa0M0Mxj3ZjnXFkv7/TD1bTy9lGUK26vRvWw==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.3.3" + } + }, + "node_modules/@img/sharp-freebsd-wasm32": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-freebsd-wasm32/-/sharp-freebsd-wasm32-0.35.4.tgz", + "integrity": "sha512-lIsKw/BU+kjB4eZjxrYrZmwOJYi3Ajrv66iAlBmUPyKc3HpnloevB1g3wxGD9P/5BbQ1brBGl65VRRrCvQDEqA==", + "license": "Apache-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "dependencies": { + "@img/sharp-wasm32": "0.35.4" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.3.3.tgz", + "integrity": "sha512-suTBPTDGrI9WodccaDdwZItTSaBYASlBk1NSfElSHrUfzu3szG6lvIF58+WiFvnfzuK8ZBFS5zE00PxqxnRiPg==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.3.3.tgz", + "integrity": "sha512-FVJZ5mITMobmXIz/hPDTw0EintTW5H3WfrxwLqEqjiIihlu+hVRyGrFQ60xl0Lxn7Bt3zdpevPaQi0HEzqz9fw==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.3.3.tgz", + "integrity": "sha512-3rbU4vqXXc3hY/OiXdl52xZvT0F1yEngWfvqudtPJg/KkyiaQw2DRsFrNzpmLvfavbwOq3qXn36GP8obHRULQA==", + "cpu": [ + "arm" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.3.3.tgz", + "integrity": "sha512-0DaL0A6Xu6sQSQFwe4iVCrKWU2cCTItnRsYsCdxAMm9NF6twAA9BKnoqy4hqz4+azQ0JHuA26qiUKsf1XJ/v5A==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.3.3.tgz", + "integrity": "sha512-cdn1OvUBwsXhbC0zSzJnNzf5MZ/mTrobawDvNXBTxe8VtqKAm0sRuEY2Evzovb/w9JMk4TvRxqt1mekSuJz64w==", + "cpu": [ + "ppc64" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.3.3.tgz", + "integrity": "sha512-HjPVx7yKz+0lqdhDlTw1tt90wamBoxhiXpvl1XZpJLiHH4RCJ5yDTqH+VlYPv2fwFs89JFw4c1IexYOcQUi4IQ==", + "cpu": [ + "riscv64" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.3.3.tgz", + "integrity": "sha512-neWLh+3yCNThxnfy3c4BbVBeGgt9aftno+XbT56iK28RgeDs3UOFWviLWlUu0bArYVYJaFDK+RRohbicUNCm8Q==", + "cpu": [ + "s390x" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.3.3.tgz", + "integrity": "sha512-4vKmvAst9nrowcqquKFAyZJUDolUaIp8uRiN0mWFguJ1IplC9/pitXtlnnlU4aa/eJw3J7i67V+pwUL+wZGdsA==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.3.3.tgz", + "integrity": "sha512-Y9kQaLMuNoB0bPYOOdcZMaseNrFpPodIWWMrx+CZyydf2xn68j9WYc6sWWRrDwNkzCQjKYfc68L7jKjGlHMibw==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.3.3.tgz", + "integrity": "sha512-fj8Mv0HHfD1Rr+4I68+3agJynxDWtBFgicTbSOb9Bke6pIwzGcJ+RX/yHjmiEGFMCavY/dxvem7MyNaJF+wDiw==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.35.4.tgz", + "integrity": "sha512-7OAS8gI0EReKGVN2HssHlM6umJgxF5VI3xN0p9FA91p/YO+ou5hiNghLdZ5BEHztwaaK5+bLKRf8x/o2L2nk9A==", + "cpu": [ + "arm" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.3.3" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.35.4.tgz", + "integrity": "sha512-De4jpEnAU8Hd5oT0j1G3uL4ZvTuipVMn7YC6vPaJhy6/7EwEae0SVAoBrUMYQbkLGDm85taVWwuPc1a44LTzCQ==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.3.3" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.35.4.tgz", + "integrity": "sha512-2oYZJeIl4kCcMGk4ouZVjnkCtFrpQFlNEtJ6GbxzhHQchwH0NH/qEb9ykmOl29dqwMq+JhFdZn+1ak2FKhI9fQ==", + "cpu": [ + "ppc64" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.3.3" + } + }, + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.35.4.tgz", + "integrity": "sha512-cPbNChoRURAWdebDIHSenxRpgEdy7JkPydSnUxRm9VvKD7m0/xVaR/8Fzlu81pk5nHEvHH87UZUA7cTtwnbJSA==", + "cpu": [ + "riscv64" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-riscv64": "1.3.3" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.35.4.tgz", + "integrity": "sha512-RY0JFY8Fd6RonCBtHz+DvadaPkXDSI1AUn6yWL9TipqkZ1vY8w8evqdgyDFnkm4/K1ve1TvZiaePP5oSd4+WVQ==", + "cpu": [ + "s390x" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.3.3" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.35.4.tgz", + "integrity": "sha512-9qvvEAuk8k89TfWUoX2htWjbAMX8p+NxCppjpcg5k6xMsjhBQPTsoIh36h9Qde4WRuGpJeYnOjdosDn/cnv+OA==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.3.3" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.35.4.tgz", + "integrity": "sha512-KB5jxpfWQTr0nc3xdHtWChdbifHrBGsd2SM62Eyxrl8afikm+f5qGBU75SJIZBT/S1MC8XyacdlXBMSWq6OURA==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.3.3" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.35.4.tgz", + "integrity": "sha512-f+eZJZIQNEEd26RPSW+76chwOf1XtA2Y/O+5ocVyLliHkeih3e+jhLVBdNTd2rS3IbNXK8+ug93Vf5ZXtF5Lxg==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.3.3" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.35.4.tgz", + "integrity": "sha512-zQnl4Kwp7Q6NHsENtU2T/00Zi+w3AQNwz3+UaTyVBy2FpXrzXzGjndpK61onhZjRtRpQXxCTeqw19bVyXOh7jA==", + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.11.3" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-webcontainers-wasm32": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-webcontainers-wasm32/-/sharp-webcontainers-wasm32-0.35.4.tgz", + "integrity": "sha512-ESfNkywmCfPNyaZjxooddJQiQ+l/nTpGEOGthxiLnIHXC/CmcBixnfwUleX9mCz9ovrUUvKMap/pm8RYbzfwaA==", + "cpu": [ + "wasm32" + ], + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@img/sharp-wasm32": "0.35.4" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.35.4.tgz", + "integrity": "sha512-iNdlBX9gLVvqe2I3uIJSIKTq6wckP/DYxZtcqxm09x5Gi24DnFBmPAWZmr60ZyYMG0xlzo6goG3670ar+RXvRw==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.35.4.tgz", + "integrity": "sha512-kqRsbaa5CS6KHlpxnN7WhE6vAAugXyZButpRdvDWetlv6Qv4N9WTcrWzF7tXfB9T7MsoadqdI8hmwLq6UlLvtw==", + "cpu": [ + "ia32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.35.4.tgz", + "integrity": "sha512-XtmnYhBcrORsJ4XJngyzr/EWP0hRZLAZRFaApdKuviyqF78+ylxh2y06ZmtULAMOnObJ3ucpN0AcwSWnMowTRg==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.6.0.tgz", + "integrity": "sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@mdx-js/mdx": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.1.1.tgz", + "integrity": "sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdx": "^2.0.0", + "acorn": "^8.0.0", + "collapse-white-space": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "estree-util-scope": "^1.0.0", + "estree-walker": "^3.0.0", + "hast-util-to-jsx-runtime": "^2.0.0", + "markdown-extensions": "^2.0.0", + "recma-build-jsx": "^1.0.0", + "recma-jsx": "^1.0.0", + "recma-stringify": "^1.0.0", + "rehype-recma": "^1.0.0", + "remark-mdx": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.0.0", + "source-map": "^0.7.0", + "unified": "^11.0.0", + "unist-util-position-from-estree": "^2.0.0", + "unist-util-stringify-position": "^4.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@next/env": { + "version": "16.3.7", + "resolved": "https://registry.npmjs.org/@next/env/-/env-16.3.7.tgz", + "integrity": "sha512-/HuhBN1CorqNTmewTIh81yXOQri6B8Ye/c9D7+830XqwVaf8qMnJNrgNxDn6dLtihq8YzBbI6NSAuMKvpr+DvQ==", + "license": "MIT" + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "16.3.7", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.3.7.tgz", + "integrity": "sha512-MDAd3woxfJOVFtfG2VAuaz5zyyVZTMVUPJAknotCNgeEPrPlRBlcV9YSd8S620P6TiSc2MWpfwO/UAHl9EWRug==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "16.3.7", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.3.7.tgz", + "integrity": "sha512-Usd86QilBWl2G7JxfWskV9NLAxacVRrDDQ3WQIoPKRB0MXiVuVSdyu3wt5EA8SyjQpaVk/7VOzSkRB4LgJltyA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "16.3.7", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.3.7.tgz", + "integrity": "sha512-pVauSs1WomgtBgfJj/Q+846nBix4CdohLUIDafyJGdAvNw5kOusLawoX+rpc2P4U3Kd7tLwqFXsnHeSkLZrqyw==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "16.3.7", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.3.7.tgz", + "integrity": "sha512-vY+iamd6cOfk29bGTgxeS/OXlrlfOfyFgyd34cibC7e25bXRMxuqNUfs2Z9Fxb/VHpV5dopffMSWnCeR2tc8rA==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "16.3.7", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.3.7.tgz", + "integrity": "sha512-NWx0LRZ9IO9rTDXLc+Hi/bNcTKblT86du4OLMRm5Z62C2T5/+mNEhK2XeQxwoSmVFvU2rjMSjJMK4ttZAk88+w==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "16.3.7", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.3.7.tgz", + "integrity": "sha512-v5Dk/iMB4JyQZwQ+UWOZGGAqA4HjkBewKwaCkXi5DqL1Dy1TjXpRmAh8N7VOuID0hLmouICSXozJrMBBG1Xeyw==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "16.3.7", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.3.7.tgz", + "integrity": "sha512-G4BkB7AhfKJnaoIpIkoA66l5pXPGJXD3EF1EsuYj/sgM4rHA41dsa3CIIqjR4FQFZEjU+zGQRbIEPYZIOi5EoA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "16.3.7", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.3.7.tgz", + "integrity": "sha512-DuvRhf50tGU7leT9Ow0cs/9lo81X5lHdNoxSRk4ckSk2Ihn2dsM+BEe5j7ANpEFhD25p//SmV8ajdRtuaBIg3g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@radix-ui/number": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.3.tgz", + "integrity": "sha512-Road2bidD0uu/1BGDOWNdPI06g0lIRy6IF9GZcIrDK2KGItfor8IQwQa+yM2ERgHM1MmHxaxpTzk0/Jp42lNfA==", + "license": "MIT" + }, + "node_modules/@radix-ui/primitive": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.7.tgz", + "integrity": "sha512-rqWnm76nYT8HoNNqEjpgJ7Pw/DrBj5iBTrmEPo6HTX5+VJyBNOqTdv4g89G63HuR5g0AaENoAcH7Is5fF2kZ8Q==", + "license": "MIT" + }, + "node_modules/@radix-ui/react-accordion": { + "version": "1.2.20", + "resolved": "https://registry.npmjs.org/@radix-ui/react-accordion/-/react-accordion-1.2.20.tgz", + "integrity": "sha512-jDhG9FvAEnlhnjrsINbNXcUa4G+L1KqSkJSunkbKEzFRcAb52jvM0PjPxPRvhe1HNc5F5yc0yzzWeeqlH4yBIg==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.7", + "@radix-ui/react-collapsible": "1.1.20", + "@radix-ui/react-collection": "1.1.15", + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.2.2", + "@radix-ui/react-direction": "1.1.4", + "@radix-ui/react-id": "1.1.4", + "@radix-ui/react-primitive": "2.1.10", + "@radix-ui/react-use-controllable-state": "1.2.6" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-arrow": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.15.tgz", + "integrity": "sha512-v4zggRcjadnI+ClKDuijlQEW4tw3NoaeHc/PwpKnLoLLKNUG4InLegkstooLcRIUWCs+8L22dGURCVuFfOKfnA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.10" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-collapsible": { + "version": "1.1.20", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.1.20.tgz", + "integrity": "sha512-mcGesGplBnzN2sbvJETzpCNfSMyPnb29q1GRLU+Ib7bJrpIG2ywmRoh2V5VbA2uNvKikKUlVbAPks7JDjz4A8Q==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.2.2", + "@radix-ui/react-id": "1.1.4", + "@radix-ui/react-presence": "1.1.10", + "@radix-ui/react-primitive": "2.1.10", + "@radix-ui/react-use-controllable-state": "1.2.6", + "@radix-ui/react-use-layout-effect": "1.1.4" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-collection": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.15.tgz", + "integrity": "sha512-9W+B9NPF0NaaPh/1NJd3+KqsnlLqU9H7T2rvww+fp+T/evVXdNAyYcnfRQZFOjkR1ajQp3yORlqnI8soawLvNA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.2.2", + "@radix-ui/react-primitive": "2.1.10", + "@radix-ui/react-slot": "1.3.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.5.tgz", + "integrity": "sha512-+48PbAAbq3didjJxa+OaWY2ZwgAKsNiRGyeHKszblZMQ+kcpd9pAaT11cMkGEie0vsOi3QdeTE6d5Fe3Gn61kA==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-context": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.2.2.tgz", + "integrity": "sha512-RHCUGwKHDr0hDGg4X7ma4JG4/+12qxw8rkh5QKdDldlCvtja6nUx1Ef/8HVrJze81lEsgLQlqjzjGNHantgnQA==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dialog": { + "version": "1.1.23", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.23.tgz", + "integrity": "sha512-Ksw4WeROkO4rC9k/onilX/Ao2Cr1ku1unMNH+XSCcP4jSXYu7HDsg9n4ojMjVb22XpYjAQ9qfrFlVbru1vXDUA==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.2.2", + "@radix-ui/react-dismissable-layer": "1.1.19", + "@radix-ui/react-focus-guards": "1.1.6", + "@radix-ui/react-focus-scope": "1.1.16", + "@radix-ui/react-id": "1.1.4", + "@radix-ui/react-portal": "1.1.17", + "@radix-ui/react-presence": "1.1.10", + "@radix-ui/react-primitive": "2.1.10", + "@radix-ui/react-slot": "1.3.3", + "@radix-ui/react-use-controllable-state": "1.2.6", + "@radix-ui/react-use-layout-effect": "1.1.4", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.7.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-direction": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.4.tgz", + "integrity": "sha512-5pzg4FGQNpExhnhT2zlrP1wZFaYCd1K0nYWoFAdcYoYK868IEigqMX3B3f8yIoRlAhAeDWciLI6ZdCKHF9P4Vg==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.19.tgz", + "integrity": "sha512-8g4pfOL9HoKKLWGiypT+dphVqjFfmcXO5GBnhsG6zI+lxAx/8feQpr+1LSN8Re3hiZ+XkLNS4O9ztK11/LzQ6w==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-primitive": "2.1.10", + "@radix-ui/react-use-callback-ref": "1.1.4", + "@radix-ui/react-use-effect-event": "0.0.5" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-guards": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.6.tgz", + "integrity": "sha512-RNOJjfZMTyBM6xYmV3IVGXkPjIhcBAuv48POevAXwrGJhkWZ9p1rFoIS1JFooPuT193AZmRsCPhpoVJxx6OPoQ==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-scope": { + "version": "1.1.16", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.16.tgz", + "integrity": "sha512-wmRZ2WWLvmt6KHy2rNPOdPUjwq5xOHY02+m+udwJTn0aNIox/rkskAvJTyTLGhPK6KgrUjlJUJpgmx/+wFiFIQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-primitive": "2.1.10", + "@radix-ui/react-use-callback-ref": "1.1.4" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-id": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.4.tgz", + "integrity": "sha512-TMQp2llA+RYn7JcjnrMnz7wN4pcVttPZnRZo52PLQsoLVKzNlVwUeHmfePgTgRluXFvlD3GD5g5MOVVTJCO0qA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.4" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-navigation-menu": { + "version": "1.2.22", + "resolved": "https://registry.npmjs.org/@radix-ui/react-navigation-menu/-/react-navigation-menu-1.2.22.tgz", + "integrity": "sha512-ou7iLEJ+yrhQndkkA4U21XIdS/CS45F4iXIkTZcb6/Ne9EMsOuDudVmCwmDnfFZZ+y1FZqXRNSIgBy+YMvZVZg==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.7", + "@radix-ui/react-collection": "1.1.15", + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.2.2", + "@radix-ui/react-direction": "1.1.4", + "@radix-ui/react-dismissable-layer": "1.1.19", + "@radix-ui/react-id": "1.1.4", + "@radix-ui/react-presence": "1.1.10", + "@radix-ui/react-primitive": "2.1.10", + "@radix-ui/react-use-callback-ref": "1.1.4", + "@radix-ui/react-use-controllable-state": "1.2.6", + "@radix-ui/react-use-layout-effect": "1.1.4", + "@radix-ui/react-use-previous": "1.1.4", + "@radix-ui/react-visually-hidden": "1.2.11" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popover": { + "version": "1.1.23", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.23.tgz", + "integrity": "sha512-mw58MrBlyHWFisTOYignD0vf/3gdcgAR+9of1s9G/38CbFiUwH1nCDkc0AUM9IrXFgN5Ue8n45j9WCgyM1sbiQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.2.2", + "@radix-ui/react-dismissable-layer": "1.1.19", + "@radix-ui/react-focus-guards": "1.1.6", + "@radix-ui/react-focus-scope": "1.1.16", + "@radix-ui/react-id": "1.1.4", + "@radix-ui/react-popper": "1.3.7", + "@radix-ui/react-portal": "1.1.17", + "@radix-ui/react-presence": "1.1.10", + "@radix-ui/react-primitive": "2.1.10", + "@radix-ui/react-slot": "1.3.3", + "@radix-ui/react-use-controllable-state": "1.2.6", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.7.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popper": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.3.7.tgz", + "integrity": "sha512-UsJrrd7w4wuKKTdvd/DNERVlwSlUcyXzjhyDwBk+3aPOsCjOY6ZSbxuw8E6lZTjjfP8Cpd0J8VVkrYUWyGYXyg==", + "license": "MIT", + "dependencies": { + "@floating-ui/react-dom": "^2.0.0", + "@radix-ui/react-arrow": "1.1.15", + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.2.2", + "@radix-ui/react-primitive": "2.1.10", + "@radix-ui/react-use-callback-ref": "1.1.4", + "@radix-ui/react-use-layout-effect": "1.1.4", + "@radix-ui/react-use-rect": "1.1.4", + "@radix-ui/react-use-size": "1.1.4", + "@radix-ui/rect": "1.1.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-portal": { + "version": "1.1.17", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.17.tgz", + "integrity": "sha512-vKQLcWypUnwZVvfV7UkGahH2g6ySe8M8R+zYBwPrv5byZ9QAW6cQVvNKo7GgmD+p8aYb6D9JBuvy8/WhOno2wQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.10", + "@radix-ui/react-use-layout-effect": "1.1.4" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-presence": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.10.tgz", + "integrity": "sha512-3wyzCQ6+ubRA+D4uv9m95JYLXxmOHp05qjrkjeA7uKHHtjpPggQzc6DAb0URl7j67oR0K2foO4ip27TiX037Bw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.4" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-primitive": { + "version": "2.1.10", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.10.tgz", + "integrity": "sha512-MucOnzh6hR5mid6VpkbglRAMYMjKLqRnGBbjXkzjK52fuQDd1qbkx78a5P40mkcnVXJdEVxm26E9OPAiUq7nBg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.3.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-roving-focus": { + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.19.tgz", + "integrity": "sha512-V9jI6hDjT7l3jsCQD9bLNvDLM3tH/gdbOTp7Tefp3hbbgCGQoK7tUvrWiRlcoBHIZ809ElXwNQwVo0B98LuTXQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.7", + "@radix-ui/react-collection": "1.1.15", + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.2.2", + "@radix-ui/react-direction": "1.1.4", + "@radix-ui/react-id": "1.1.4", + "@radix-ui/react-primitive": "2.1.10", + "@radix-ui/react-use-callback-ref": "1.1.4", + "@radix-ui/react-use-controllable-state": "1.2.6", + "@radix-ui/react-use-is-hydrated": "0.1.3", + "@radix-ui/react-use-layout-effect": "1.1.4" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-scroll-area": { + "version": "1.2.18", + "resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.2.18.tgz", + "integrity": "sha512-Zn5Cd171wxsO3Dfg8HaW6RifTb9CYTKQJHs/G4+LN1GfmJpaQMZQyQxMprVPHpaz7QY4l9BxK2JwQuzHsXC8nA==", + "license": "MIT", + "dependencies": { + "@radix-ui/number": "1.1.3", + "@radix-ui/primitive": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.2.2", + "@radix-ui/react-direction": "1.1.4", + "@radix-ui/react-presence": "1.1.10", + "@radix-ui/react-primitive": "2.1.10", + "@radix-ui/react-use-callback-ref": "1.1.4", + "@radix-ui/react-use-layout-effect": "1.1.4" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slot": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.3.3.tgz", + "integrity": "sha512-qx7oqnYbxnK9kYI9m317qmFmEgo6ywqWvbTogdj7cL9p3/yx4M48p7Rnw5z3H890cL/ow/EeWJsuTykeZVXP5Q==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.5" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tabs": { + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.21.tgz", + "integrity": "sha512-UKxJlZid7FVtsk/WTxj4i4uSEgj2Au+KBbS7SQyTlzMhhn+86Cz3tISZdTa87bfEfcuvZezf2ZsxD4xuEKtkog==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.7", + "@radix-ui/react-context": "1.2.2", + "@radix-ui/react-direction": "1.1.4", + "@radix-ui/react-id": "1.1.4", + "@radix-ui/react-presence": "1.1.10", + "@radix-ui/react-primitive": "2.1.10", + "@radix-ui/react-roving-focus": "1.1.19", + "@radix-ui/react-use-controllable-state": "1.2.6" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-callback-ref": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.4.tgz", + "integrity": "sha512-R6OUY2e2fA6Yn6s+VSx5KBV6Nx8LQEhu+cz7LCej18rQ1HLyg9PSC9jP/ZNx0o6FAIK9c0F1kHylzSxKsdlkrQ==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.6.tgz", + "integrity": "sha512-uEQJGT97ZA/TgP/Hydw47lHu+/vQj6z/0jA+WeTbK1o9Rx45GImjpD0tc3W5ad3D6XTSR6e1yEO0FvGq6WQfVQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.7", + "@radix-ui/react-use-effect-event": "0.0.5", + "@radix-ui/react-use-layout-effect": "1.1.4" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-effect-event": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.5.tgz", + "integrity": "sha512-7cshFL8HGS/7HEiHH+9kL9HBwp2sa9yX18Knwek6KYWmXwM7pegMgta2AXMQKI+rq3JnfSj9x8wYqFMTdG1Jgg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.4" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-is-hydrated": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-is-hydrated/-/react-use-is-hydrated-0.1.3.tgz", + "integrity": "sha512-umO/aJ+82CpOnhDZUTbILCQf7kU/g0iv+oGs/Q8jw7IkhWBzaEP4sA268PhFAJTFetbwp3ICc6ktpI4TqtxcIw==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.4.tgz", + "integrity": "sha512-K20DkRkUwDnxEYMBPcg3Y6voLkEy5p5QQmszZgLngKKiC7dzBR/aEuK3w1qlx2JWDUNH6FluahYdgR3BP+QbYw==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-previous": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.4.tgz", + "integrity": "sha512-XoSLhbRbqxFtgJoi2fNHA3C6pDlY34x508vUpUGoFZfvePfHXHbE1lC4FYFMnJWgiCRroSTw6fOsXQoVS9RwZg==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-rect": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.4.tgz", + "integrity": "sha512-cSOCh6JlkmfjLyNcLiu2nB4v+nm+dkZ+Q5KHWk/soo4U7ZLiEQFKHK9/YmtBHjfCEaU43IBKQOc4/uJmCaiCTQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/rect": "1.1.3" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-size": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.4.tgz", + "integrity": "sha512-D3anSY15EJoxrihpsXI6SMrmmonnQtR2ni7arO+Lfdg3O95b9hNXxONk8jA5C8ANdF/h5HMAxejgs8PWJ6rlhw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.4" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-visually-hidden": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.11.tgz", + "integrity": "sha512-NFS86RYYZb4/exihaESBGOpMJFz8MGLAfu3mOBSGByVnVPC9JPASfYubxd/8KbkQK0sYAv8lVQDEQukDX/qXvQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.10" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/rect": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.3.tgz", + "integrity": "sha512-JtyZR+mqgBibTo8xea3B6ZRmzZiM/YeVBtUkas6zMuXjAlfIFIW2FgqeM9eLyvEaYX66vr6DJMK+4U6LV0KhNw==", + "license": "MIT" + }, + "node_modules/@shikijs/core": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-4.4.3.tgz", + "integrity": "sha512-QCR4q2ZO/ILJEuwiBMel4wdcTDb1JGwfjKTxPDF6x8ixOaluPrVqIn06C99AcRPhmYlBR56d/Fb+GN58GzExpg==", + "license": "MIT", + "dependencies": { + "@shikijs/primitive": "4.4.3", + "@shikijs/types": "4.4.3", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.5", + "hast-util-to-html": "^9.0.5" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/engine-javascript": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-4.4.3.tgz", + "integrity": "sha512-FbOjFJp9VLdo1Wevs10BBtVxiTWwNLqZh5Gkhjgda/ioL15YOgeSl9n+6XMa3qRlPQzfhFNe641SrynFHYG0nQ==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "4.4.3", + "@shikijs/vscode-textmate": "^10.0.2", + "oniguruma-to-es": "^4.3.6" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/engine-oniguruma": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-4.4.3.tgz", + "integrity": "sha512-EcOQkxdxGQrc1Row/cC2c96/v1dbZqGnEVu1qTuT/MJmp6+cXCvQussowVmCv5Tqr3KuY3c7IbM6HTW3LJ1k9w==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "4.4.3", + "@shikijs/vscode-textmate": "^10.0.2" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/langs": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-4.4.3.tgz", + "integrity": "sha512-ePic0yfAJGOF83D5wBHK/00EjK65oahBYxFk5epgq33WRv7X9UuxLEV8PtR0szC0z8dl7INIpIodB99JRFlR+A==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "4.4.3" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/primitive": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/@shikijs/primitive/-/primitive-4.4.3.tgz", + "integrity": "sha512-m0wBeLDQDeIxRdUmrCPdQqfuUamDwRL5isCfYbguKD6NiaKpVbsv+3J81DyIKgNW5h4WAIIr8T4EkgQrBBxvaQ==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "4.4.3", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.5" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/themes": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-4.4.3.tgz", + "integrity": "sha512-w8UHjeUnIR965KMWJHUPXOc2mNJUnK3vpVLYLvw5IYU2mnTTJ89E24OrJDBNiJDQ0qzb0tc4l7mrIXx5cFeIyw==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "4.4.3" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/types": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-4.4.3.tgz", + "integrity": "sha512-UEJxmRR++MAGR6hugn0vgVS2W/6lWAts84FFSrnlH9sP0LNol7E5+NQ792pH8liWUhyMyjhTgSUH3k7iD7tc5g==", + "license": "MIT", + "dependencies": { + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.5" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/vscode-textmate": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz", + "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==", + "license": "MIT" + }, + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "license": "MIT" + }, + "node_modules/@swc/helpers": { + "version": "0.5.23", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.23.tgz", + "integrity": "sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@tailwindcss/node": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.3.3.tgz", + "integrity": "sha512-/T8IKEsf9VTU6tLjgC7+sv2mOPtQxzE2jMw7u4Tt40Tx+QSZxpzh95/H6cMKoja9XuW7iMdLJYBB0o9G1CaAgg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/remapping": "^2.3.5", + "enhanced-resolve": "^5.24.1", + "jiti": "^2.7.0", + "lightningcss": "1.32.0", + "magic-string": "^0.30.21", + "source-map-js": "^1.2.1", + "tailwindcss": "4.3.3" + } + }, + "node_modules/@tailwindcss/oxide": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.3.3.tgz", + "integrity": "sha512-krXjAikiaFSPaK/FkAQT5UTx3VormQaiZ5hBFlJZ9UFQGB/rwg1MZIhHAG9smMQRTdyJxP6Qt5MwMtdyU5FWrA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 20" + }, + "optionalDependencies": { + "@tailwindcss/oxide-android-arm64": "4.3.3", + "@tailwindcss/oxide-darwin-arm64": "4.3.3", + "@tailwindcss/oxide-darwin-x64": "4.3.3", + "@tailwindcss/oxide-freebsd-x64": "4.3.3", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.3", + "@tailwindcss/oxide-linux-arm64-gnu": "4.3.3", + "@tailwindcss/oxide-linux-arm64-musl": "4.3.3", + "@tailwindcss/oxide-linux-x64-gnu": "4.3.3", + "@tailwindcss/oxide-linux-x64-musl": "4.3.3", + "@tailwindcss/oxide-wasm32-wasi": "4.3.3", + "@tailwindcss/oxide-win32-arm64-msvc": "4.3.3", + "@tailwindcss/oxide-win32-x64-msvc": "4.3.3" + } + }, + "node_modules/@tailwindcss/oxide-android-arm64": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.3.3.tgz", + "integrity": "sha512-Y85A2gmPSkl5Ve5qR86GL4HT509cFqQh1aes9p3sSkyTPwt0Pppf3GkwGe4JPACcRYjgJIEhQgM6dBClnr0NYw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-darwin-arm64": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.3.3.tgz", + "integrity": "sha512-BiaWatpBcERQFDlOjRDpIVXuFK5PJez5SA4JMg6VYZdBYU+qKfV/vqjcIs+IYmtitf1xYQZTwXvU/8y4lfZUGw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-darwin-x64": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.3.3.tgz", + "integrity": "sha512-fAeUqfV5ndhxRwai8cXGzdLvul9utWOmeTkv69unv4ZXixjn61Z+p9lCWdwOwA3TYboG3BwdVuN/RDjhBRl0mw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-freebsd-x64": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.3.3.tgz", + "integrity": "sha512-iyf5bV6+wnAlflVeEy7R25dupxTNECZN5QMI0qNT6eT+EgaGdZcKhGkr5SdoaWiLJ3spLqIY9VCeSGrwmtg4kw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.3.3.tgz", + "integrity": "sha512-aAYUprJAJQWWbRrPvtjdroZ56Md+JM8pMiopS6xGEwDfLhqj+2ver2p4nU4Mb3CRqcMmNBjo8KkUgcxhkzVQGQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.3.3.tgz", + "integrity": "sha512-nDxldcEENOxZRzC2uu9jrutZdAAQtb+8WWDCSnWL1zvBk1+FN+x6MtDViPB5AJMfttVCUhehGWus3XBPgatM/w==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-musl": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.3.3.tgz", + "integrity": "sha512-Md44bD6veX/PC5iyF8cDVnw4HBIANZepRZZ7a8DQOvkfo5WUBwcp6iAuCUz23u+4SUkhJlD3eL7hNdW8ezd/kA==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.3.3.tgz", + "integrity": "sha512-tx7us1muwOKAKWao2v/GaafFeQboE6aj88vC6ziN2NCGcRm8gWUhwjzg+YdVB1e4boAtdtma4L43onunI6NS4w==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-musl": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.3.3.tgz", + "integrity": "sha512-SJxX60smvHgasZoBy11dX6YRjXJFovwWBoedhbQPOBzgFWBHGB+TVPWB9BxzR7TTxU8FQZAI2AyiNCMzFm8Img==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.3.3.tgz", + "integrity": "sha512-jx1+rPhY/5Ympkktd656HBWEBLxP7dH06losBLjjf5vgCODXvi9KhtftWcMIwTFIDqBr7cRnQkdLnAG+IOlGvQ==", + "bundleDependencies": [ + "@napi-rs/wasm-runtime", + "@emnapi/core", + "@emnapi/runtime", + "@tybys/wasm-util", + "@emnapi/wasi-threads", + "tslib" + ], + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.11.1", + "@emnapi/runtime": "^1.11.1", + "@emnapi/wasi-threads": "^1.2.2", + "@napi-rs/wasm-runtime": "^1.1.4", + "@tybys/wasm-util": "^0.10.2", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/core": { + "version": "1.11.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.2", + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/runtime": { + "version": "1.11.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/wasi-threads": { + "version": "1.2.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": { + "version": "1.1.4", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@tybys/wasm-util": "^0.10.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@tybys/wasm-util": { + "version": "0.10.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/tslib": { + "version": "2.8.1", + "dev": true, + "inBundle": true, + "license": "0BSD", + "optional": true + }, + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.3.3.tgz", + "integrity": "sha512-3rc292Ca2ceK6Ulcc/bAVnTs/3nDtoPhyEKlgPv+yQJQi/JS/AMJlqzxvlDacL1nekbrcf6bTqp/jV4qgnPxNQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.3.3.tgz", + "integrity": "sha512-yJ0pwIVc/nYeGoV02WtsN8KYyLQv7kyI2wDnkezyJlGGjkd4QLwDGAwl47YpPJeuI0M0ObaXGSPjvWDPeTPggw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/postcss": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.3.3.tgz", + "integrity": "sha512-JTSZZGQi1AyKirbLN3azmjVzef92tcX7h+iSqPdaeStyFpGpDlKvvpxeOE8njhbUanbRwr3z8DyzhICWnMtQeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "@tailwindcss/node": "4.3.3", + "@tailwindcss/oxide": "4.3.3", + "postcss": "^8.5.16", + "tailwindcss": "4.3.3" + } + }, + "node_modules/@types/debug": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.13.tgz", + "integrity": "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==", + "license": "MIT", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "license": "MIT" + }, + "node_modules/@types/estree-jsx": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz", + "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==", + "license": "MIT", + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/@types/hast": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.5.tgz", + "integrity": "sha512-rp/ezSWaD1m44dPKICGhiskI13nVr7qTloFwDa/IYkhhf5nzwP+zIQcIJh3WIFSBOy/H1PzB40jPjMDksN4F+g==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/katex": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.16.8.tgz", + "integrity": "sha512-trgaNyfU+Xh2Tc+ABIb44a5AYUpicB3uwirOioeOkNPPbmgRNtcWyDeeFRzjPZENO9Vq8gvVqfhaaXWLlevVwg==", + "license": "MIT" + }, + "node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/mdx": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.14.tgz", + "integrity": "sha512-T48PeuJtvLosNTPVhfnIp3i/n3a4g4Bad7YCq5k64D4u7NwDrAotikQ+5+sjtUvBmxCMlbo3dVL+C2dP0rWHzg==", + "license": "MIT" + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-26.6.3.tgz", + "integrity": "sha512-dsqMQQoeTLqu9wynDD00q573mNzso3IdQOAfHRJqLCcmCFPoGo9A1bDpUcv/9tnKpErQWv9uKeGfl37EIS02Yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~8.9.0" + } + }, + "node_modules/@types/react": { + "version": "19.3.0", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.3.0.tgz", + "integrity": "sha512-N0rFCuH9YoxG9/m61l9MfpJKfmLOVU0em7ipIz6TRgSSkvReLB9vL85GB+yr8Bs5leqpvg96JSwF4ZS1s4viQg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.3.0", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.3.0.tgz", + "integrity": "sha512-ZI7bU42mZXXKHn/qNLEw2IrbiINU7X5+vfgdixBHkCNpYWXjKgfQ/P+uyGb5CjOLB9UcnTeg3rylQtV2hym44Q==", + "devOptional": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.3.0" + } + }, + "node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "license": "MIT" + }, + "node_modules/@typescript/typescript-aix-ppc64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-aix-ppc64/-/typescript-aix-ppc64-7.0.2.tgz", + "integrity": "sha512-MTKKkWB7p/0E9xi1d1tHtZ5PiLkGEMIq88pK2CubZjOsLtYTLqhgIgi6zepFa+9GHZ6h05NMCkQxGKiPXMxXtQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-darwin-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-darwin-arm64/-/typescript-darwin-arm64-7.0.2.tgz", + "integrity": "sha512-gowzar9MwS/aRWp6f3a4KUqzRjAZjOsmGNCM6LcTgXum+dBfgsBVMN+AgvOCCbguXyick6LJhpBszxMebJ8syA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-darwin-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-darwin-x64/-/typescript-darwin-x64-7.0.2.tgz", + "integrity": "sha512-SZ9xZInqApNlNGc9s0W1VSsktYSOe9cFqNOIqmN1Gs8SmkjKZYFt017G4VwPxASInODuAdbTW7sXiFUf893RgA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-freebsd-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-freebsd-arm64/-/typescript-freebsd-arm64-7.0.2.tgz", + "integrity": "sha512-W5NH4y/J0plIIS5b2xvTEkU7JFxyqdMAOgf+Ilhl0vHQXKO5dZoxd+C/jEtq56c4F3wk71RB4BMRQ2XdI+bwYQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-freebsd-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-freebsd-x64/-/typescript-freebsd-x64-7.0.2.tgz", + "integrity": "sha512-UMGDx5sTpzNw3WiPebH7l90IWfJggEd+egHt/q6p7/Cm3zqoV7VxkGXt+3DxPIw8CcmvAB0j3sVVfbhX+M4Tpw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-arm": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-arm/-/typescript-linux-arm-7.0.2.tgz", + "integrity": "sha512-gffT3xPz9sR7j/YJExkyPntrI0P2EP9XbOyWzth2/Gs0RstK+90RBcO0ncXoXy/beYll1SXw846Nf2zdnEz0QQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-arm64/-/typescript-linux-arm64-7.0.2.tgz", + "integrity": "sha512-Qh4eU4/y3yDjnfjjyPYihMj5/ODIlmt+Bzu17OI+fiSRDW57QmU5SiN63exPRNJPKUzcc1INa1NXdrJ+MqHjUQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-loong64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-loong64/-/typescript-linux-loong64-7.0.2.tgz", + "integrity": "sha512-uEHck9i8hoAzXPiYRib1O7miOnz23SxIeVl6F4LXox+qov1K35jHcEW6VHKvZI+pyvl7fZEP4MCU5LYvIq1GuQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-mips64el": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-mips64el/-/typescript-linux-mips64el-7.0.2.tgz", + "integrity": "sha512-R4KvAMnE43W5Qeqb0Ly56O3mWMWIAgsMyz36DCaycd5nbg/9kzm0liw3JocfRqyJY0KPmzFjbswozXyW0DnIYA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-ppc64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-ppc64/-/typescript-linux-ppc64-7.0.2.tgz", + "integrity": "sha512-DORx5b3sd/4S7eayxm4FQv+A7CrkUIGRaHiwI8oiHTAI1fAPWhF4J0vAlkC8biAlHSVVwxMQ3tjZ2/DVbnQiiA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-riscv64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-riscv64/-/typescript-linux-riscv64-7.0.2.tgz", + "integrity": "sha512-wf0jqEDOjrPRnKwYRyyJDRo11KMbvMFrU+q4zqKyChODBzvlkbhNQfKvLxQCcwTpdDaXSHZTVuh0JoCrKCUMHQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-s390x": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-s390x/-/typescript-linux-s390x-7.0.2.tgz", + "integrity": "sha512-IkwJc3L7yhytWd/ewjyxNDfOmswCm9GWMJT/ue/dU4aZNbwZeYAetq42VyLmsmSjvoX7z74X6ZaYCtzAr0EuGw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-x64/-/typescript-linux-x64-7.0.2.tgz", + "integrity": "sha512-EYdf2cNg7rgCWJnxCdJ+F3V39O8ihb37eHAu1LK8oAFizgTQbPOK7zHHXbPt8rX24COqODXeI3sIf0fCXG7H/A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-netbsd-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-netbsd-arm64/-/typescript-netbsd-arm64-7.0.2.tgz", + "integrity": "sha512-+polYF4MF04aPpO5FTkHran9yUQDSXqy5GiSDKpsll5jy3l3+g9QLhpf39T+ePtefhXLOGrLl0QIjkQP6VnelA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-netbsd-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-netbsd-x64/-/typescript-netbsd-x64-7.0.2.tgz", + "integrity": "sha512-8YIT0EHM/3dq10ZOVF/A7pc/YSMtbcecct4rWtexrnSCHOPcpC2KTLXfTCR6vDpnSiY12heNb1GiN/wu+T/FyA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-openbsd-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-openbsd-arm64/-/typescript-openbsd-arm64-7.0.2.tgz", + "integrity": "sha512-APT8+ClYnuYm1u9+kgGXoMj2VzWzcymwh2gNSQVySHfkRDGOTVkoWLjCmOQSaO+PoqQ57B0flRp9SA+7GnnkzQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-openbsd-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-openbsd-x64/-/typescript-openbsd-x64-7.0.2.tgz", + "integrity": "sha512-yX7s+Q0Dln0Dt9tEzZsAjXXR/+ytBM7AlglaqyeMPxQszJ1JhlJdZ6jLA+IzldHtflX81em7lDao1xXu+aRRkg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-sunos-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-sunos-x64/-/typescript-sunos-x64-7.0.2.tgz", + "integrity": "sha512-dLJDGaLZ1D4HPQn62u1n8mBDkJREwMsAkCdkwd4Ieqw+x3TUyTsqY0YiBCtE6H6OzzgGk3iuZ3vFWRS+E8/d1g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-win32-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-win32-arm64/-/typescript-win32-arm64-7.0.2.tgz", + "integrity": "sha512-Gyl1Vy6OsWesLzmq+EP0Fb7b4Nid5232AvcA2SFcdYreldpNtYFFofPjnt62y9hQy7VTaZp65ICJjuAQRaVcIQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-win32-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-win32-x64/-/typescript-win32-x64-7.0.2.tgz", + "integrity": "sha512-0BQ3HkAHHlKLSp1qRvf3SUhGpGsDuhB/jgFw75guyqbxJqEaS0Cw/VFO8i2nHglJUzQCRtMMR/IBAKE3ETMC4g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.3.tgz", + "integrity": "sha512-60YRaenCQcVjYEKOcG824+DRGGIQ3VKErcBoAEDJZz5bKIs2ZG+X/H9Nk+Q6EVkwJk5QNApxbrc5QtBSwtrXAg==", + "license": "ISC" + }, + "node_modules/@yuku-analyzer/binding-android-arm64": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/@yuku-analyzer/binding-android-arm64/-/binding-android-arm64-0.10.2.tgz", + "integrity": "sha512-xt4Vy3RTBw1NfszBlf4A0Rr6ZjA/th2Pj9XlWFLQHW9A1qOCtxNCoIWSzn/INtnZLMB4jO2gWdEtSaHUtK73wA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@yuku-analyzer/binding-darwin-arm64": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/@yuku-analyzer/binding-darwin-arm64/-/binding-darwin-arm64-0.10.2.tgz", + "integrity": "sha512-ftokSqvYXZxfmA/bfIbp8c1BJ8QxNax371kUOQNFyvR5hmtKqQyTqSKtMk+WaixHM3w4tKj/JdyY+ud1bGamXA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@yuku-analyzer/binding-darwin-x64": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/@yuku-analyzer/binding-darwin-x64/-/binding-darwin-x64-0.10.2.tgz", + "integrity": "sha512-yUrmmhmF5R4Xmbfo8gUxJKr3YbvbLcE2JvLhDLzFJkMN29/fGm6K3dZX6YpNecfgBDnQ+VywGp8K9xjRaBFZ3Q==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@yuku-analyzer/binding-freebsd-x64": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/@yuku-analyzer/binding-freebsd-x64/-/binding-freebsd-x64-0.10.2.tgz", + "integrity": "sha512-cy9+KvVoK5Xad3Vs5pLwAeZf3JC/1y0XJElgv1q6g7W7g/n52FRjedpYmQiJeMZdnhJiAshq7Vz/Xj3jC5Ns2Q==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@yuku-analyzer/binding-linux-arm-gnu": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/@yuku-analyzer/binding-linux-arm-gnu/-/binding-linux-arm-gnu-0.10.2.tgz", + "integrity": "sha512-AgVZ6VCV2XP4yHCwyv78KLV76gcu2neiEF2+RBTPQN7sqYY+bLvMxphGPmfG+9qk5Uf1PJAhZYIUnMGVbbRCZw==", + "cpu": [ + "arm" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@yuku-analyzer/binding-linux-arm-musl": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/@yuku-analyzer/binding-linux-arm-musl/-/binding-linux-arm-musl-0.10.2.tgz", + "integrity": "sha512-5qAj2GjoSN6+HuH75+g5r40CFhWmMvH0K8VKWmPfQyOgA/LonoDMr5H5O5feJwzdnfdCytPDAh1RAf7/SSg7dg==", + "cpu": [ + "arm" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@yuku-analyzer/binding-linux-arm64-gnu": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/@yuku-analyzer/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.10.2.tgz", + "integrity": "sha512-eJvQ4Ja5oPf/HOjmBkCLYyhOHUkL7U+iMAN8sX44x8exBBpPRyqnhEgTsuU73HzxPLrGPdRhybFnAE63Omib/Q==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@yuku-analyzer/binding-linux-arm64-musl": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/@yuku-analyzer/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.10.2.tgz", + "integrity": "sha512-TppF2j194mOQ/kBXvNr9u5TYO+eR9r8ieg4lTIEyJIVYHAR9GWeB0oFHLcJiLXVa3qUJGzE4bmzSntCW5ylA7A==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@yuku-analyzer/binding-linux-x64-gnu": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/@yuku-analyzer/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.10.2.tgz", + "integrity": "sha512-03xu6ocJuwhm1a/JKmrHiaJUO1Oj86rABsm4FAl8AvfewfW/9idIUmPiFxZfb6RfiIONegebsTGJhFx0NbBNpA==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@yuku-analyzer/binding-linux-x64-musl": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/@yuku-analyzer/binding-linux-x64-musl/-/binding-linux-x64-musl-0.10.2.tgz", + "integrity": "sha512-f7W2sAWWQN8x8YB0RRxIche7mLImH7lDgzUy9+B69cM2I6VFJ4a5+0pgAuMLROPOqimaxFPdXqLdDE/vpgGltg==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@yuku-analyzer/binding-win32-arm64": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/@yuku-analyzer/binding-win32-arm64/-/binding-win32-arm64-0.10.2.tgz", + "integrity": "sha512-f534qNc5YaJI29e1oryxEnxPkp7WCYJ1j7ChSec8pQNlYqTm8Tao7hij7NxRF+9BuxzeZCZ+WsbaAfLlklR0Eg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@yuku-analyzer/binding-win32-x64": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/@yuku-analyzer/binding-win32-x64/-/binding-win32-x64-0.10.2.tgz", + "integrity": "sha512-sKHkmLK8BsindMfyIThoN0bWC5uqSJEVNaLRD/ifA99mtb0UDin1ZCg4WYSVQAmM4k2iOTl4UZx/p3zcBiBgYw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@yuku-toolchain/types": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/@yuku-toolchain/types/-/types-0.10.2.tgz", + "integrity": "sha512-sSeo4SSSToiS+sSD+bwn/s94EEcaLJ7tG5LCp8gFYC1G5VzxzX7fqB6m9RU1yMD8KTpu6zdU/I1NlQf8hVBJ9Q==", + "license": "MIT" + }, + "node_modules/acorn": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.18.0.tgz", + "integrity": "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, + "node_modules/aria-hidden": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz", + "integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/astring": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/astring/-/astring-1.9.0.tgz", + "integrity": "sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==", + "license": "MIT", + "bin": { + "astring": "bin/astring" + } + }, + "node_modules/bail": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", + "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.11.15", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.15.tgz", + "integrity": "sha512-FwMjJJ7HnyZpWe+oWxegG0fezZyBZUagI5LZEoO3GCbtbKNwRfMH9Ue5d5v01PNePBy1QSfPSDTTeVL0Hb9EzA==", + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001809", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001809.tgz", + "integrity": "sha512-xxWVywk6a6Arlk+hymeycyn/VgqEfLDxupvhH/xiY5SJ/18kmi9o6MiO320DCUzypORHLtvh0I4i04tUhCNHNQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", + "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-reference-invalid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", + "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/chokidar": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", + "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", + "license": "MIT", + "dependencies": { + "readdirp": "^5.0.0" + }, + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/citeproc": { + "version": "2.4.63", + "resolved": "https://registry.npmjs.org/citeproc/-/citeproc-2.4.63.tgz", + "integrity": "sha512-68F95Bp4UbgZU/DBUGQn0qV3HDZLCdI9+Bb2ByrTaNJDL5VEm9LqaiNaxljsvoaExSLEXe1/r6n2Z06SCzW3/Q==", + "license": "CPAL-1.0 OR AGPL-1.0" + }, + "node_modules/class-variance-authority": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz", + "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==", + "license": "Apache-2.0", + "dependencies": { + "clsx": "^2.1.1" + }, + "funding": { + "url": "https://polar.sh/cva" + } + }, + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", + "license": "MIT" + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/cn": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/cn/-/cn-0.3.3.tgz", + "integrity": "sha512-OEiyJkSpYm2kOuNOKQ+c2wmzZRG8orrb9fnObtHTbCGNx/E9KLnGcmcocItOzREKk5KzQN5I2e3BUCj563KEpw==", + "license": "MIT", + "bin": { + "cn": "bin/cn.mjs" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/cnfast": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/cnfast/-/cnfast-0.2.0.tgz", + "integrity": "sha512-US4gOKGIylQWC7Nm+wNj+rOej6hJKyY4HwZYgtfRrduejEIFNNxcGKIWzCcQZxzgx6wKCZCCysWjnzsffiyhrw==", + "license": "MIT", + "bin": { + "cnfast": "bin/cli.js" + }, + "engines": { + "node": ">=22" + } + }, + "node_modules/collapse-white-space": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-2.1.0.tgz", + "integrity": "sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/compute-scroll-into-view": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-3.1.1.tgz", + "integrity": "sha512-VRhuHOLoKYOy4UbilLbUzbYg93XLjv2PncJC50EuTWPA3gaja1UjBsUP/D/9/juV3vQFr6XBEzn9KCAHdUvOHw==", + "license": "MIT" + }, + "node_modules/cross-fetch": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.1.0.tgz", + "integrity": "sha512-uKm5PU+MHTootlWEY+mZ4vvXoCn4fLQxT9dSc1sXVMSFkINTJVN8cAQROpwcKm8bJ/c7rgZVIBWzH5T78sNZZw==", + "license": "MIT", + "dependencies": { + "node-fetch": "^2.7.0" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decode-named-character-reference": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.3.0.tgz", + "integrity": "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==", + "license": "MIT", + "dependencies": { + "character-entities": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "devOptional": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-node-es": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", + "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==", + "license": "MIT" + }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "license": "MIT", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.24.5", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.24.5.tgz", + "integrity": "sha512-L1l8TNvomm6UVW5B253AGxQagSQr+vGwhMlrrfRS2qmhx46AMpMVJKQYLvWYbysTMY8VoicOvzHzoHMbyzB+4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.3.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/entities": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-8.0.0.tgz", + "integrity": "sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/esast-util-from-estree": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/esast-util-from-estree/-/esast-util-from-estree-2.0.0.tgz", + "integrity": "sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "devlop": "^1.0.0", + "estree-util-visit": "^2.0.0", + "unist-util-position-from-estree": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/esast-util-from-js": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/esast-util-from-js/-/esast-util-from-js-2.0.1.tgz", + "integrity": "sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "acorn": "^8.0.0", + "esast-util-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/esbuild": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.2.tgz", + "integrity": "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.28.2", + "@esbuild/android-arm": "0.28.2", + "@esbuild/android-arm64": "0.28.2", + "@esbuild/android-x64": "0.28.2", + "@esbuild/darwin-arm64": "0.28.2", + "@esbuild/darwin-x64": "0.28.2", + "@esbuild/freebsd-arm64": "0.28.2", + "@esbuild/freebsd-x64": "0.28.2", + "@esbuild/linux-arm": "0.28.2", + "@esbuild/linux-arm64": "0.28.2", + "@esbuild/linux-ia32": "0.28.2", + "@esbuild/linux-loong64": "0.28.2", + "@esbuild/linux-mips64el": "0.28.2", + "@esbuild/linux-ppc64": "0.28.2", + "@esbuild/linux-riscv64": "0.28.2", + "@esbuild/linux-s390x": "0.28.2", + "@esbuild/linux-x64": "0.28.2", + "@esbuild/netbsd-arm64": "0.28.2", + "@esbuild/netbsd-x64": "0.28.2", + "@esbuild/openbsd-arm64": "0.28.2", + "@esbuild/openbsd-x64": "0.28.2", + "@esbuild/openharmony-arm64": "0.28.2", + "@esbuild/sunos-x64": "0.28.2", + "@esbuild/win32-arm64": "0.28.2", + "@esbuild/win32-ia32": "0.28.2", + "@esbuild/win32-x64": "0.28.2" + } + }, + "node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/estree-util-attach-comments": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-attach-comments/-/estree-util-attach-comments-3.0.0.tgz", + "integrity": "sha512-cKUwm/HUcTDsYh/9FgnuFqpfquUbwIqwKM26BVCGDPVgvaCl/nDCCjUfiLlx6lsEZ3Z4RFxNbOQ60pkaEwFxGw==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-build-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/estree-util-build-jsx/-/estree-util-build-jsx-3.0.1.tgz", + "integrity": "sha512-8U5eiL6BTrPxp/CHbs2yMgP8ftMhR5ww1eIKoWRMlqvltHF8fZn5LRDvTKuxD3DUn+shRbLGqXemcP51oFCsGQ==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "estree-walker": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-is-identifier-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz", + "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-scope": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/estree-util-scope/-/estree-util-scope-1.0.0.tgz", + "integrity": "sha512-2CAASclonf+JFWBNJPndcOpA8EMJwa0Q8LUFJEKqXLW6+qBvbFZuF5gItbQOs/umBUkjviCSDCbBwU2cXbmrhQ==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-to-js": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/estree-util-to-js/-/estree-util-to-js-2.0.0.tgz", + "integrity": "sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "astring": "^1.8.0", + "source-map": "^0.7.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-value-to-estree": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/estree-util-value-to-estree/-/estree-util-value-to-estree-3.5.0.tgz", + "integrity": "sha512-aMV56R27Gv3QmfmF1MY12GWkGzzeAezAX+UplqHVASfjc9wNzI/X6hC0S9oxq61WT4aQesLGslWP9tKk6ghRZQ==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/remcohaszing" + } + }, + "node_modules/estree-util-visit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/estree-util-visit/-/estree-util-visit-2.0.0.tgz", + "integrity": "sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "license": "MIT" + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/fetch-ponyfill": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/fetch-ponyfill/-/fetch-ponyfill-7.1.0.tgz", + "integrity": "sha512-FhbbL55dj/qdVO3YNK7ZEkshvj3eQ7EuIGV2I6ic/2YiocvyWv+7jg2s4AyS0wdRU75s3tA8ZxI/xPigb0v5Aw==", + "license": "MIT", + "dependencies": { + "node-fetch": "~2.6.1" + } + }, + "node_modules/fetch-ponyfill/node_modules/node-fetch": { + "version": "2.6.13", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.13.tgz", + "integrity": "sha512-StxNAxh15zr77QvvkmveSQ8uCQ4+v5FkvNTj0OESmiHu+VRi/gXArXtkWMElOsOUNLtUEvI4yS+rdtOHZTwlQA==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/framer-motion": { + "version": "13.4.1", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-13.4.1.tgz", + "integrity": "sha512-6DsbU4hsNsokXkwSp3ezdMWMiv5yWzCcdjFgakkeUC6FVIK01Py8ToSzsXvBw8cYA5hff/oXFvZFU7ltbVyUYA==", + "license": "MIT", + "dependencies": { + "motion-dom": "^13.4.1", + "motion-utils": "^13.3.0", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/fumadocs-core": { + "version": "16.15.17", + "resolved": "https://registry.npmjs.org/fumadocs-core/-/fumadocs-core-16.15.17.tgz", + "integrity": "sha512-Pexn60R+S5F33UccW9WoLN+LHAOIraA/VvQt1xAXmfLxitx5rIPR7B9M+5mrqECnuSPltoX843NZ//Z5j/HAOg==", + "license": "MIT", + "dependencies": { + "@fumari/image-size": "^0.1.1", + "estree-util-value-to-estree": "^3.5.0", + "github-slugger": "^2.0.0", + "hast-util-to-estree": "^3.1.3", + "hast-util-to-jsx-runtime": "^2.3.6", + "mdast-util-mdx": "^3.0.0", + "mdast-util-to-markdown": "^2.1.2", + "npm-to-yarn": "3.2.0", + "remark": "^15.0.1", + "remark-gfm": "^4.0.1", + "remark-rehype": "^11.1.2", + "scroll-into-view-if-needed": "^3.1.0", + "shiki": "^4.4.3", + "tinyglobby": "^0.2.17", + "unified": "^11.0.5", + "unist-util-visit": "^5.1.0", + "vfile": "^6.0.3", + "yaml": "^2.9.1", + "zbsearch": "^4.0.0" + }, + "peerDependencies": { + "@mdx-js/mdx": "*", + "@mixedbread/sdk": "0.x.x", + "@modelcontextprotocol/server": "2.x.x", + "@orama/core": "1.x.x", + "@oramacloud/client": "2.x.x", + "@tanstack/react-router": "1.x.x", + "@types/estree-jsx": "*", + "@types/hast": "*", + "@types/mdast": "*", + "@types/react": "*", + "algoliasearch": "5.x.x", + "flexsearch": "*", + "lucide-react": "*", + "next": "16.x.x", + "react": "^19.2.0", + "react-dom": "^19.2.0", + "react-router": "7.x.x || 8.x.x", + "waku": "*", + "zod": "4.x.x" + }, + "peerDependenciesMeta": { + "@mdx-js/mdx": { + "optional": true + }, + "@mixedbread/sdk": { + "optional": true + }, + "@modelcontextprotocol/server": { + "optional": true + }, + "@orama/core": { + "optional": true + }, + "@oramacloud/client": { + "optional": true + }, + "@tanstack/react-router": { + "optional": true + }, + "@types/estree-jsx": { + "optional": true + }, + "@types/hast": { + "optional": true + }, + "@types/mdast": { + "optional": true + }, + "@types/react": { + "optional": true + }, + "algoliasearch": { + "optional": true + }, + "flexsearch": { + "optional": true + }, + "lucide-react": { + "optional": true + }, + "next": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "react-router": { + "optional": true + }, + "waku": { + "optional": true + }, + "zod": { + "optional": true + } + } + }, + "node_modules/fumadocs-mdx": { + "version": "15.4.5", + "resolved": "https://registry.npmjs.org/fumadocs-mdx/-/fumadocs-mdx-15.4.5.tgz", + "integrity": "sha512-r8gzaqleN+YXgPIbkYSZ05zr89dsr67/64Ar/00Uu7dRWTIHzbgmN1nC0lB8RFNeWnrL41bOTJilhLM4PAsrbw==", + "license": "MIT", + "dependencies": { + "@mdx-js/mdx": "^3.1.1", + "@standard-schema/spec": "^1.1.0", + "chokidar": "^5.0.0", + "esbuild": "^0.28.2", + "estree-util-value-to-estree": "^3.5.0", + "github-slugger": "^2.0.0", + "magic-string": "^1.4.1", + "mdast-util-mdx": "^3.0.0", + "picocolors": "^1.1.1", + "picomatch": "^4.0.7", + "tinyexec": "^1.3.1", + "tinyglobby": "^0.2.17", + "unified": "^11.0.5", + "unist-util-remove-position": "^5.0.0", + "unist-util-visit": "^5.1.0", + "vfile": "^6.0.3", + "yaml": "^2.9.1", + "yuku-analyzer": "^0.10.2", + "zod": "^4.6.5" + }, + "bin": { + "fumadocs-mdx": "bin.js" + }, + "peerDependencies": { + "@fumadocs/satteri": "0.x.x", + "@types/mdast": "*", + "@types/mdx": "*", + "@types/react": "*", + "fumadocs-core": "^16.15.3", + "mdast-util-directive": "*", + "next": "^15.3.0 || ^16.0.0", + "react": "^19.2.0", + "rolldown": "*", + "satteri": "^0.10.5", + "vite": "7.x.x || 8.x.x" + }, + "peerDependenciesMeta": { + "@fumadocs/satteri": { + "optional": true + }, + "@types/mdast": { + "optional": true + }, + "@types/mdx": { + "optional": true + }, + "@types/react": { + "optional": true + }, + "mdast-util-directive": { + "optional": true + }, + "next": { + "optional": true + }, + "react": { + "optional": true + }, + "rolldown": { + "optional": true + }, + "satteri": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/fumadocs-mdx/node_modules/magic-string": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-1.4.1.tgz", + "integrity": "sha512-8lyCu36ErXR0J9uaGKlKQoiLZKmtI63YGLE8G2o9jyRPdr4X47LusSOwgOJOzcVtp81fTAAjxR7BwKz682Jhow==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.6.0" + } + }, + "node_modules/fumadocs-ui": { + "version": "16.15.17", + "resolved": "https://registry.npmjs.org/fumadocs-ui/-/fumadocs-ui-16.15.17.tgz", + "integrity": "sha512-Q0Tzfte6Bzz8JCVU0yMISWjEpoTzGKfdeG8WoRxktdv30JblQ+G8n87MG11auMh6Li0CuO5oPqH5otyQ2mQ5Yw==", + "license": "MIT", + "dependencies": { + "@fuma-translate/react": "^1.0.2", + "@fumadocs/tailwind": "0.1.2", + "@radix-ui/react-accordion": "^1.2.20", + "@radix-ui/react-collapsible": "^1.1.20", + "@radix-ui/react-dialog": "^1.1.23", + "@radix-ui/react-direction": "^1.1.4", + "@radix-ui/react-navigation-menu": "^1.2.22", + "@radix-ui/react-popover": "^1.1.23", + "@radix-ui/react-presence": "^1.1.10", + "@radix-ui/react-scroll-area": "^1.2.18", + "@radix-ui/react-slot": "^1.3.3", + "@radix-ui/react-tabs": "^1.1.21", + "class-variance-authority": "^0.7.1", + "cn": "^0.3.0", + "lucide-react": "^1.47.0", + "motion": "^13.4.0", + "next-themes": "^0.4.6", + "react-remove-scroll": "^2.7.2", + "rehype-raw": "^7.0.0", + "scroll-into-view-if-needed": "^3.1.0", + "shiki": "^4.4.3", + "unist-util-visit": "^5.1.0" + }, + "peerDependencies": { + "@types/mdx": "*", + "@types/react": "*", + "fumadocs-core": "16.15.17", + "next": "16.x.x", + "react": "^19.2.0", + "react-dom": "^19.2.0", + "takumi-js": "*" + }, + "peerDependenciesMeta": { + "@types/mdx": { + "optional": true + }, + "@types/react": { + "optional": true + }, + "next": { + "optional": true + }, + "takumi-js": { + "optional": true + } + } + }, + "node_modules/get-nonce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz", + "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/github-slugger": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-2.0.0.tgz", + "integrity": "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==", + "license": "ISC" + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/hast-util-from-dom": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/hast-util-from-dom/-/hast-util-from-dom-5.0.1.tgz", + "integrity": "sha512-N+LqofjR2zuzTjCPzyDUdSshy4Ma6li7p/c3pA78uTwzFgENbgbUrm2ugwsOdcjI1muO+o6Dgzp9p8WHtn/39Q==", + "license": "ISC", + "dependencies": { + "@types/hast": "^3.0.0", + "hastscript": "^9.0.0", + "web-namespaces": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-from-html": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.3.tgz", + "integrity": "sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "devlop": "^1.1.0", + "hast-util-from-parse5": "^8.0.0", + "parse5": "^7.0.0", + "vfile": "^6.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-from-html-isomorphic": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hast-util-from-html-isomorphic/-/hast-util-from-html-isomorphic-2.0.0.tgz", + "integrity": "sha512-zJfpXq44yff2hmE0XmwEOzdWin5xwH+QIhMLOScpX91e/NSGPsAzNCvLQDIEPyO2TXi+lBmU6hjLIhV8MwP2kw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-from-dom": "^5.0.0", + "hast-util-from-html": "^2.0.0", + "unist-util-remove-position": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-from-html/node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/hast-util-from-html/node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "license": "MIT", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/hast-util-from-parse5": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz", + "integrity": "sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "devlop": "^1.0.0", + "hastscript": "^9.0.0", + "property-information": "^7.0.0", + "vfile": "^6.0.0", + "vfile-location": "^5.0.0", + "web-namespaces": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-is-element": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-3.0.0.tgz", + "integrity": "sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-parse-selector": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz", + "integrity": "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-raw": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-9.1.0.tgz", + "integrity": "sha512-Y8/SBAHkZGoNkpzqqfCldijcuUKh7/su31kEBp67cFY09Wy0mTRgtsLYsiIxMJxlu0f6AA5SUTbDR8K0rxnbUw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "@ungap/structured-clone": "^1.0.0", + "hast-util-from-parse5": "^8.0.0", + "hast-util-to-parse5": "^8.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "parse5": "^7.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0", + "web-namespaces": "^2.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-raw/node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/hast-util-raw/node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "license": "MIT", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/hast-util-to-estree": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/hast-util-to-estree/-/hast-util-to-estree-3.1.3.tgz", + "integrity": "sha512-48+B/rJWAp0jamNbAAf9M7Uf//UVqAoMmgXhBdxTDJLGKY+LRnZ99qcG+Qjl5HfMpYNzS5v4EAwVEF34LeAj7w==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-attach-comments": "^3.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-js": "^1.0.0", + "unist-util-position": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-html": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz", + "integrity": "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==", + "license": "MIT", + "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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-jsx-runtime": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz", + "integrity": "sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-js": "^1.0.0", + "unist-util-position": "^5.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-parse5": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-8.0.1.tgz", + "integrity": "sha512-MlWT6Pjt4CG9lFCjiz4BH7l9wmrMkfkJYCxFwKQic8+RTZgWPuWxwAfjJElsXkex7DJjfSJsQIt931ilUgmwdA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "web-namespaces": "^2.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-text": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-4.0.2.tgz", + "integrity": "sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "hast-util-is-element": "^3.0.0", + "unist-util-find-after": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-whitespace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hastscript": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-9.0.1.tgz", + "integrity": "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-parse-selector": "^4.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/html-void-elements": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", + "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/inline-style-parser": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.7.tgz", + "integrity": "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==", + "license": "MIT" + }, + "node_modules/is-alphabetical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", + "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-alphanumerical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", + "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", + "license": "MIT", + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-decimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-decimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", + "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-hexadecimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", + "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jiti": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz", + "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/js-yaml": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.2.tgz", + "integrity": "sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/katex": { + "version": "0.18.9", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.18.9.tgz", + "integrity": "sha512-8ad9RyoKsb/g8/yLFE+KAlP+DhbCTRUNi/V9XGsxn0R+trJJltNwzcDNo0q/DEkOy5fQUQTAQyCXCYSE+OakTQ==", + "funding": [ + "https://opencollective.com/katex", + "https://github.com/sponsors/katex" + ], + "license": "MIT", + "dependencies": { + "commander": "^15.0.0" + }, + "bin": { + "katex": "cli.js" + } + }, + "node_modules/katex/node_modules/commander": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-15.0.0.tgz", + "integrity": "sha512-z67u4ZhzCL/Tydu1lJARtEZYWbWaN7oYLHbsuzocr6y4N6WZAagG3RQ4FW61V1/0+jImpj293XfrcYnd1qxtPg==", + "license": "MIT", + "engines": { + "node": ">=22.12.0" + } + }, + "node_modules/lightningcss": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", + "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.32.0", + "lightningcss-darwin-arm64": "1.32.0", + "lightningcss-darwin-x64": "1.32.0", + "lightningcss-freebsd-x64": "1.32.0", + "lightningcss-linux-arm-gnueabihf": "1.32.0", + "lightningcss-linux-arm64-gnu": "1.32.0", + "lightningcss-linux-arm64-musl": "1.32.0", + "lightningcss-linux-x64-gnu": "1.32.0", + "lightningcss-linux-x64-musl": "1.32.0", + "lightningcss-win32-arm64-msvc": "1.32.0", + "lightningcss-win32-x64-msvc": "1.32.0" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", + "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", + "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", + "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", + "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", + "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", + "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", + "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", + "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", + "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", + "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", + "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/longest-streak": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/lucide-react": { + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-1.49.0.tgz", + "integrity": "sha512-ApfaNM4/7jBrVopqLJ84Jz8TMQ1Q1JeZ1PmKh25aeS3E1FTVcMkSh1bEQB7dfzdIrwXRP8p3z4AJjTIHHb5IIA==", + "license": "ISC", + "peerDependencies": { + "@types/react": "*", + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/markdown-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/markdown-extensions/-/markdown-extensions-2.0.0.tgz", + "integrity": "sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q==", + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/markdown-table": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz", + "integrity": "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/mdast-util-find-and-replace": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz", + "integrity": "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==", + "license": "MIT", + "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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-from-markdown": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.3.tgz", + "integrity": "sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==", + "license": "MIT", + "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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.1.0.tgz", + "integrity": "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==", + "license": "MIT", + "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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-autolink-literal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz", + "integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==", + "license": "MIT", + "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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==", + "license": "MIT", + "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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-strikethrough": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz", + "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-table": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz", + "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==", + "license": "MIT", + "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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-task-list-item": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz", + "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-math": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-math/-/mdast-util-math-3.0.0.tgz", + "integrity": "sha512-Tl9GBNeG/AhJnQM221bJR2HPvLOSnLE/T9cJI9tlc6zwQk2nPk/4f0cHkOdEixQPC/j8UtKDdITswvLAy1OZ1w==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "longest-streak": "^3.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.1.0", + "unist-util-remove-position": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-3.0.0.tgz", + "integrity": "sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w==", + "license": "MIT", + "dependencies": { + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-expression": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz", + "integrity": "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-jsx": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.2.0.tgz", + "integrity": "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "parse-entities": "^4.0.0", + "stringify-entities": "^4.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdxjs-esm": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", + "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-phrasing": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", + "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-hast": { + "version": "13.2.1", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz", + "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==", + "license": "MIT", + "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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-markdown": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz", + "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==", + "license": "MIT", + "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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", + "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "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" + } + }, + "node_modules/micromark-core-commonmark": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz", + "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "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" + } + }, + "node_modules/micromark-extension-gfm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", + "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==", + "license": "MIT", + "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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", + "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", + "license": "MIT", + "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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", + "license": "MIT", + "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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-strikethrough": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz", + "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==", + "license": "MIT", + "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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-table": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz", + "integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==", + "license": "MIT", + "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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-tagfilter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz", + "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==", + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-task-list-item": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz", + "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==", + "license": "MIT", + "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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-math": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-math/-/micromark-extension-math-3.1.0.tgz", + "integrity": "sha512-lvEqd+fHjATVs+2v/8kg9i5Q0AP2k85H0WUOwpIVvUML8BapsMvh1XAogmQjOCsLpoKRCVQqEkQBB3NhVBcsOg==", + "license": "MIT", + "dependencies": { + "@types/katex": "^0.16.0", + "devlop": "^1.0.0", + "katex": "^0.16.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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-math/node_modules/katex": { + "version": "0.16.47", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.47.tgz", + "integrity": "sha512-Eeo8Ys1doU1z+x8AZsPpQu+p/QcZBI5PeOo7QGQdy2x2m0MU/hYagBbGOmXwr5KVbEfVuWv9LpnQWeehogurjg==", + "funding": [ + "https://opencollective.com/katex", + "https://github.com/sponsors/katex" + ], + "license": "MIT", + "dependencies": { + "commander": "^8.3.0" + }, + "bin": { + "katex": "cli.js" + } + }, + "node_modules/micromark-extension-mdx-expression": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-3.0.1.tgz", + "integrity": "sha512-dD/ADLJ1AeMvSAKBwO22zG22N4ybhe7kFIZ3LsDI0GlsNr2A3KYxb0LdC1u5rj4Nw+CHKY0RVdnHX8vj8ejm4Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-mdx-expression": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-mdx-jsx": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-jsx/-/micromark-extension-mdx-jsx-3.0.2.tgz", + "integrity": "sha512-e5+q1DjMh62LZAJOnDraSSbDMvGJ8x3cbjygy2qFEi7HCeUT4BDKCvMozPozcD6WmOt6sVvYDNBKhFSz3kjOVQ==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "micromark-factory-mdx-expression": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdx-md": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-md/-/micromark-extension-mdx-md-2.0.0.tgz", + "integrity": "sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ==", + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdxjs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs/-/micromark-extension-mdxjs-3.0.0.tgz", + "integrity": "sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ==", + "license": "MIT", + "dependencies": { + "acorn": "^8.0.0", + "acorn-jsx": "^5.0.0", + "micromark-extension-mdx-expression": "^3.0.0", + "micromark-extension-mdx-jsx": "^3.0.0", + "micromark-extension-mdx-md": "^2.0.0", + "micromark-extension-mdxjs-esm": "^3.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdxjs-esm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs-esm/-/micromark-extension-mdxjs-esm-3.0.0.tgz", + "integrity": "sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-position-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-factory-destination": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", + "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-label": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", + "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-mdx-expression": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-factory-mdx-expression/-/micromark-factory-mdx-expression-2.0.3.tgz", + "integrity": "sha512-kQnEtA3vzucU2BkrIa8/VaSAsP+EJ3CKOvhMuJgOEGg9KDC6OAY6nSnNDVRiVNRqj7Y4SlSzcStaH/5jge8JdQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-position-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + } + }, + "node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz", + "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "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" + } + }, + "node_modules/micromark-factory-whitespace": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz", + "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "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" + } + }, + "node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-chunked": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz", + "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-classify-character": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz", + "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-combine-extensions": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz", + "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-chunked": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-numeric-character-reference": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz", + "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-string": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz", + "integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "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" + } + }, + "node_modules/micromark-util-encode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", + "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-events-to-acorn": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-util-events-to-acorn/-/micromark-util-events-to-acorn-2.0.3.tgz", + "integrity": "sha512-jmsiEIiZ1n7X1Rr5k8wVExBQCg5jy4UXVADItHmNk1zkwEVhBuIUKRu3fqv+hs4nxLISi2DQGlqIOGiFxgbfHg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/unist": "^3.0.0", + "devlop": "^1.0.0", + "estree-util-visit": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "vfile-message": "^4.0.0" + } + }, + "node_modules/micromark-util-html-tag-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", + "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-normalize-identifier": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz", + "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-resolve-all": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz", + "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", + "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-subtokenize": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz", + "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-types": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", + "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/moo": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.3.tgz", + "integrity": "sha512-m2fmM2dDm7GZQsY7KK2cme8agi+AAljILjQnof7p1ZMDe6dQ4bdnSMx0cPppudoeNv5hEFQirN6u+O4fDE0IWA==", + "license": "BSD-3-Clause" + }, + "node_modules/motion": { + "version": "13.4.1", + "resolved": "https://registry.npmjs.org/motion/-/motion-13.4.1.tgz", + "integrity": "sha512-9YjJ918QN6/4VSigEoqJysNPh33uTruTLbrBdGDI7pM6WTWU4kTPKzmEqJ4bXzLGYyDyZ5ubWX2tv2uTuFQugg==", + "license": "MIT", + "dependencies": { + "framer-motion": "^13.4.1", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/motion-dom": { + "version": "13.4.1", + "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-13.4.1.tgz", + "integrity": "sha512-qw6ILBFHrIPQd3k9Dd1fNlCLHTNzvMXW2zpeTlxn4wZXX02m0Dnsf8ycyvcjtAZtBiBnL4SfbyDIXWg+b1x/Ig==", + "license": "MIT", + "dependencies": { + "motion-utils": "^13.3.0" + } + }, + "node_modules/motion-utils": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-13.3.0.tgz", + "integrity": "sha512-sgSschQp7EseHInIlR7hBbMuvet3RA0bs28KPZAXJcGKGdxHGvh1ogpYDilY3bOMtl73EqPNmp75sAKHYPU5sg==", + "license": "MIT" + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.18", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz", + "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/next": { + "version": "16.3.7", + "resolved": "https://registry.npmjs.org/next/-/next-16.3.7.tgz", + "integrity": "sha512-S4AlB0KMYcvVyEVjfD2Ze/3JsX9PWjpD3hJPcEJTVvkAQsMTYVs9DB1NtaBbs41ZZ18NxYwkmM8ljqtrFrmLsQ==", + "license": "MIT", + "dependencies": { + "@next/env": "16.3.7", + "@swc/helpers": "0.5.23", + "baseline-browser-mapping": "^2.9.19", + "caniuse-lite": "^1.0.30001579", + "postcss": "8.5.23", + "styled-jsx": "5.1.6" + }, + "bin": { + "next": "dist/bin/next" + }, + "engines": { + "node": ">=20.9.0" + }, + "optionalDependencies": { + "@next/swc-darwin-arm64": "16.3.7", + "@next/swc-darwin-x64": "16.3.7", + "@next/swc-linux-arm64-gnu": "16.3.7", + "@next/swc-linux-arm64-musl": "16.3.7", + "@next/swc-linux-x64-gnu": "16.3.7", + "@next/swc-linux-x64-musl": "16.3.7", + "@next/swc-win32-arm64-msvc": "16.3.7", + "@next/swc-win32-x64-msvc": "16.3.7", + "sharp": "^0.35.4" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0", + "@playwright/test": "^1.51.1", + "babel-plugin-react-compiler": "*", + "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "sass": "^1.3.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "@playwright/test": { + "optional": true + }, + "babel-plugin-react-compiler": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "node_modules/next-themes": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.4.6.tgz", + "integrity": "sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc" + } + }, + "node_modules/next/node_modules/postcss": { + "version": "8.5.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.23.tgz", + "integrity": "sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.16", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/npm-to-yarn": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/npm-to-yarn/-/npm-to-yarn-3.2.0.tgz", + "integrity": "sha512-K1HmQeZT2HrjpsR6KgqbN2FAXL2NrJJmNUSD9ck7HGTVu1JKXox8n9SB+tjbU8m8JGLF4OscrroPepew/L7/Xw==", + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/nebrelbug/npm-to-yarn?sponsor=1" + } + }, + "node_modules/oniguruma-parser": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/oniguruma-parser/-/oniguruma-parser-0.12.2.tgz", + "integrity": "sha512-6HVa5oIrgMC6aA6WF6XyyqbhRPJrKR02L20+2+zpDtO5QAzGHAUGw5TKQvwi5vctNnRHkJYmjAhRVQF2EKdTQw==", + "license": "MIT" + }, + "node_modules/oniguruma-to-es": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-4.3.6.tgz", + "integrity": "sha512-csuQ9x3Yr0cEIs/Zgx/OEt9iBw9vqIunAPQkx19R/fiMq2oGVTgcMqO/V3Ybqefr1TBvosI6jU539ksaBULJyA==", + "license": "MIT", + "dependencies": { + "oniguruma-parser": "^0.12.2", + "regex": "^6.1.0", + "regex-recursion": "^6.0.2" + } + }, + "node_modules/parse-entities": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", + "integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^2.0.0", + "character-entities-legacy": "^3.0.0", + "character-reference-invalid": "^2.0.0", + "decode-named-character-reference": "^1.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0", + "is-hexadecimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/parse-entities/node_modules/@types/unist": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", + "license": "MIT" + }, + "node_modules/parse5": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.1.tgz", + "integrity": "sha512-z1e/HMG90obSGeidlli3hj7cbocou0/wa5HacvI3ASx34PecNjNQeaHNo5WIZpWofN9kgkqV1q5YvXe3F0FoPw==", + "license": "MIT", + "dependencies": { + "entities": "^8.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz", + "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.28", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.28.tgz", + "integrity": "sha512-RRuzqDtt5Y9h3quz5hWhK+TPnsmVs6WwSU6LkJMeY4HstUEDuYTG8UJSdawMRzmzAtV+KEoG8N3Qg2qLy5vM/A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.18", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/property-information": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.2.0.tgz", + "integrity": "sha512-IAtzIB6sUiWaJYrX9smp3V46pBGbBeLFRGdh25kg1334VcBlD8HzhPeNIWQH9zhGmo2itIe25EHt9dQP7G5hmg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/react": { + "version": "19.3.0", + "resolved": "https://registry.npmjs.org/react/-/react-19.3.0.tgz", + "integrity": "sha512-E8LUcbtBWt20bbl2YoHfx4ZDBdxVTfOKtCZn9cDSJ4l6/nuoApcpIBcj47t2wZoVX8g2ZHuMHbiShgCR1T5Sog==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.3.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.3.0.tgz", + "integrity": "sha512-JDk8dgif51OjFoDE70+OT9ICyYr+69HlmihNwp1+Nsfbna3t5sIiCa9ZJktDmQ4/1b/rn26hIAR2uYXDMr5r0Q==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.28.0" + }, + "peerDependencies": { + "react": "^19.3.0" + } + }, + "node_modules/react-remove-scroll": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.2.tgz", + "integrity": "sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==", + "license": "MIT", + "dependencies": { + "react-remove-scroll-bar": "^2.3.7", + "react-style-singleton": "^2.2.3", + "tslib": "^2.1.0", + "use-callback-ref": "^1.3.3", + "use-sidecar": "^1.1.3" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-remove-scroll-bar": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz", + "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==", + "license": "MIT", + "dependencies": { + "react-style-singleton": "^2.2.2", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-style-singleton": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz", + "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==", + "license": "MIT", + "dependencies": { + "get-nonce": "^1.0.0", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/readdirp": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.1.1.tgz", + "integrity": "sha512-Kko+Y5XQ6fM+Ce3dq3m9YGxnacYZYl9cA1wZjaF3Vbry2L3i1qVg8+CAgNPsXRArPMUMCaOR7oa9Nqntc43JKA==", + "license": "MIT", + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/recma-build-jsx": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/recma-build-jsx/-/recma-build-jsx-1.0.0.tgz", + "integrity": "sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-util-build-jsx": "^3.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/recma-jsx": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/recma-jsx/-/recma-jsx-1.0.1.tgz", + "integrity": "sha512-huSIy7VU2Z5OLv6oFLosQGGDqPqdO1iq6bWNAdhzMxSJP7RAso4fCZ1cKu8j9YHCZf3TPrq4dw3okhrylgcd7w==", + "license": "MIT", + "dependencies": { + "acorn-jsx": "^5.0.0", + "estree-util-to-js": "^2.0.0", + "recma-parse": "^1.0.0", + "recma-stringify": "^1.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/recma-parse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/recma-parse/-/recma-parse-1.0.0.tgz", + "integrity": "sha512-OYLsIGBB5Y5wjnSnQW6t3Xg7q3fQ7FWbw/vcXtORTnyaSFscOtABg+7Pnz6YZ6c27fG1/aN8CjfwoUEUIdwqWQ==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "esast-util-from-js": "^2.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/recma-stringify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/recma-stringify/-/recma-stringify-1.0.0.tgz", + "integrity": "sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-util-to-js": "^2.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/regex/-/regex-6.1.0.tgz", + "integrity": "sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==", + "license": "MIT", + "dependencies": { + "regex-utilities": "^2.3.0" + } + }, + "node_modules/regex-recursion": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/regex-recursion/-/regex-recursion-6.0.2.tgz", + "integrity": "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==", + "license": "MIT", + "dependencies": { + "regex-utilities": "^2.3.0" + } + }, + "node_modules/regex-utilities": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/regex-utilities/-/regex-utilities-2.3.0.tgz", + "integrity": "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==", + "license": "MIT" + }, + "node_modules/rehype-citation": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/rehype-citation/-/rehype-citation-2.3.2.tgz", + "integrity": "sha512-apeGbeIYrfbirZZMZ0KY9tEZPnMlqomlGbQDNJfMoTV8wBSmLq8XyBywlfHrPLvchFIq9Mrn7g7SmXdQob+5lw==", + "license": "MIT", + "dependencies": { + "@citation-js/core": "^0.7.21", + "@citation-js/date": "^0.5.1", + "@citation-js/name": "^0.4.2", + "@citation-js/plugin-bibjson": "^0.7.21", + "@citation-js/plugin-bibtex": "^0.7.21", + "@citation-js/plugin-csl": "^0.7.22", + "citeproc": "^2.4.63", + "cross-fetch": "^4.1.0", + "hast-util-from-dom": "^5.0.1", + "hast-util-from-parse5": "^8.0.3", + "js-yaml": "^4.1.1", + "parse5": "^8.0.0", + "unified": "^11.0.5", + "unist-util-visit": "^5.1.0" + } + }, + "node_modules/rehype-katex": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/rehype-katex/-/rehype-katex-7.0.1.tgz", + "integrity": "sha512-OiM2wrZ/wuhKkigASodFoo8wimG3H12LWQaH8qSPVJn9apWKFSH3YOCtbKpBorTVw/eI7cuT21XBbvwEswbIOA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/katex": "^0.16.0", + "hast-util-from-html-isomorphic": "^2.0.0", + "hast-util-to-text": "^4.0.0", + "katex": "^0.16.0", + "unist-util-visit-parents": "^6.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-katex/node_modules/katex": { + "version": "0.16.47", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.47.tgz", + "integrity": "sha512-Eeo8Ys1doU1z+x8AZsPpQu+p/QcZBI5PeOo7QGQdy2x2m0MU/hYagBbGOmXwr5KVbEfVuWv9LpnQWeehogurjg==", + "funding": [ + "https://opencollective.com/katex", + "https://github.com/sponsors/katex" + ], + "license": "MIT", + "dependencies": { + "commander": "^8.3.0" + }, + "bin": { + "katex": "cli.js" + } + }, + "node_modules/rehype-raw": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-7.0.0.tgz", + "integrity": "sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-raw": "^9.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-recma": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rehype-recma/-/rehype-recma-1.0.0.tgz", + "integrity": "sha512-lqA4rGUf1JmacCNWWZx0Wv1dHqMwxzsDWYMTowuplHF3xH0N/MmrZ/G3BDZnzAkRmxDadujCjaKM2hqYdCBOGw==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/hast": "^3.0.0", + "hast-util-to-estree": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark": { + "version": "15.0.1", + "resolved": "https://registry.npmjs.org/remark/-/remark-15.0.1.tgz", + "integrity": "sha512-Eht5w30ruCXgFmxVUSlNWQ9iiimq07URKeFS3hNc8cUWy1llX4KDWfyEDZRycMc+znsN9Ux5/tJ/BFdgdOwA3A==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "remark-parse": "^11.0.0", + "remark-stringify": "^11.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-gfm": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.1.tgz", + "integrity": "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==", + "license": "MIT", + "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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-math": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/remark-math/-/remark-math-6.0.0.tgz", + "integrity": "sha512-MMqgnP74Igy+S3WwnhQ7kqGlEerTETXMvJhrUzDikVZ2/uogJCb+WHUg97hK9/jcfc0dkD73s3LN8zU49cTEtA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-math": "^3.0.0", + "micromark-extension-math": "^3.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-mdx": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.1.1.tgz", + "integrity": "sha512-Pjj2IYlUY3+D8x00UJsIOg5BEvfMyeI+2uLPn9VO9Wg4MEtN/VTIq2NEJQfde9PnX15KgtHyl9S0BcTnWrIuWg==", + "license": "MIT", + "dependencies": { + "mdast-util-mdx": "^3.0.0", + "micromark-extension-mdxjs": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-parse": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", + "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-rehype": { + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.2.tgz", + "integrity": "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "mdast-util-to-hast": "^13.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-stringify": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz", + "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-to-markdown": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/scheduler": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.28.0.tgz", + "integrity": "sha512-juorfCmIkIw8tT+p5BXSm6PJjQF/ycEYmKyzURCIt/RaZIhL+PulbQ9Yu2z1HdOJDdqDTlxA1+xKBmHXJsczAw==", + "license": "MIT" + }, + "node_modules/scroll-into-view-if-needed": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-3.1.0.tgz", + "integrity": "sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ==", + "license": "MIT", + "dependencies": { + "compute-scroll-into-view": "^3.0.2" + } + }, + "node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "license": "ISC", + "optional": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/sharp": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.35.4.tgz", + "integrity": "sha512-n++8XWcj+jCOr2IOl7h8LbKnGBDY4aPbmprMONBNFdn0ImXqpGVv5zliDs0V9HbmbCQLpbuo2ej9rAoOQTvMDA==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@img/colour": "^1.1.0", + "detect-libc": "^2.1.2", + "semver": "^7.8.5" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.35.4", + "@img/sharp-darwin-x64": "0.35.4", + "@img/sharp-freebsd-wasm32": "0.35.4", + "@img/sharp-libvips-darwin-arm64": "1.3.3", + "@img/sharp-libvips-darwin-x64": "1.3.3", + "@img/sharp-libvips-linux-arm": "1.3.3", + "@img/sharp-libvips-linux-arm64": "1.3.3", + "@img/sharp-libvips-linux-ppc64": "1.3.3", + "@img/sharp-libvips-linux-riscv64": "1.3.3", + "@img/sharp-libvips-linux-s390x": "1.3.3", + "@img/sharp-libvips-linux-x64": "1.3.3", + "@img/sharp-libvips-linuxmusl-arm64": "1.3.3", + "@img/sharp-libvips-linuxmusl-x64": "1.3.3", + "@img/sharp-linux-arm": "0.35.4", + "@img/sharp-linux-arm64": "0.35.4", + "@img/sharp-linux-ppc64": "0.35.4", + "@img/sharp-linux-riscv64": "0.35.4", + "@img/sharp-linux-s390x": "0.35.4", + "@img/sharp-linux-x64": "0.35.4", + "@img/sharp-linuxmusl-arm64": "0.35.4", + "@img/sharp-linuxmusl-x64": "0.35.4", + "@img/sharp-webcontainers-wasm32": "0.35.4", + "@img/sharp-win32-arm64": "0.35.4", + "@img/sharp-win32-ia32": "0.35.4", + "@img/sharp-win32-x64": "0.35.4" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/shiki": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-4.4.3.tgz", + "integrity": "sha512-Mb/GvXPHBAXdgGIcnfU5L3ldpn1XcxrGkPHwqgRx17/I2XRfqlFKk2vGkHWINn1kdXvzJZeuO3is6I9KLPFm0g==", + "license": "MIT", + "dependencies": { + "@shikijs/core": "4.4.3", + "@shikijs/engine-javascript": "4.4.3", + "@shikijs/engine-oniguruma": "4.4.3", + "@shikijs/langs": "4.4.3", + "@shikijs/themes": "4.4.3", + "@shikijs/types": "4.4.3", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.5" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/source-map": { + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", + "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">= 12" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/stringify-entities": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", + "license": "MIT", + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/style-to-js": { + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.21.tgz", + "integrity": "sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==", + "license": "MIT", + "dependencies": { + "style-to-object": "1.0.14" + } + }, + "node_modules/style-to-object": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.14.tgz", + "integrity": "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==", + "license": "MIT", + "dependencies": { + "inline-style-parser": "0.2.7" + } + }, + "node_modules/styled-jsx": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz", + "integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==", + "license": "MIT", + "dependencies": { + "client-only": "0.0.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "peerDependencies": { + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/sync-fetch": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/sync-fetch/-/sync-fetch-0.4.5.tgz", + "integrity": "sha512-esiWJ7ixSKGpd9DJPBTC4ckChqdOjIwJfYhVHkcQ2Gnm41323p1TRmEI+esTQ9ppD+b5opps2OTEGTCGX5kF+g==", + "license": "MIT", + "dependencies": { + "buffer": "^5.7.1", + "node-fetch": "^2.6.1" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/tailwindcss": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.3.tgz", + "integrity": "sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/tapable": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/tinyexec": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.3.1.tgz", + "integrity": "sha512-GCvB3aoys96IuDFBMcTB46JOR6mdMtAToqwiW8JlWhsoh1mhHi/xn9ss/Dg7N555GiJyEt2qzoG/NHCwM6h1EA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/trough": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", + "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/typescript": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-7.0.2.tgz", + "integrity": "sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc" + }, + "engines": { + "node": ">=16.20.0" + }, + "optionalDependencies": { + "@typescript/typescript-aix-ppc64": "7.0.2", + "@typescript/typescript-darwin-arm64": "7.0.2", + "@typescript/typescript-darwin-x64": "7.0.2", + "@typescript/typescript-freebsd-arm64": "7.0.2", + "@typescript/typescript-freebsd-x64": "7.0.2", + "@typescript/typescript-linux-arm": "7.0.2", + "@typescript/typescript-linux-arm64": "7.0.2", + "@typescript/typescript-linux-loong64": "7.0.2", + "@typescript/typescript-linux-mips64el": "7.0.2", + "@typescript/typescript-linux-ppc64": "7.0.2", + "@typescript/typescript-linux-riscv64": "7.0.2", + "@typescript/typescript-linux-s390x": "7.0.2", + "@typescript/typescript-linux-x64": "7.0.2", + "@typescript/typescript-netbsd-arm64": "7.0.2", + "@typescript/typescript-netbsd-x64": "7.0.2", + "@typescript/typescript-openbsd-arm64": "7.0.2", + "@typescript/typescript-openbsd-x64": "7.0.2", + "@typescript/typescript-sunos-x64": "7.0.2", + "@typescript/typescript-win32-arm64": "7.0.2", + "@typescript/typescript-win32-x64": "7.0.2" + } + }, + "node_modules/undici-types": { + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.9.0.tgz", + "integrity": "sha512-KTDyRTYX8sWmKXAikPHHSyc63CRPETMctyjKFupcC6OBLXT3xsN0e9aF7m+mIXutFWpUXuedtowG7iLOzp0kQg==", + "dev": true, + "license": "MIT" + }, + "node_modules/unified": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", + "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", + "license": "MIT", + "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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-find-after": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-find-after/-/unist-util-find-after-5.0.0.tgz", + "integrity": "sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-is": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position-from-estree": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position-from-estree/-/unist-util-position-from-estree-2.0.0.tgz", + "integrity": "sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-remove-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-5.0.0.tgz", + "integrity": "sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.1.0.tgz", + "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/use-callback-ref": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz", + "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-sidecar": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz", + "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==", + "license": "MIT", + "dependencies": { + "detect-node-es": "^1.1.0", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-location": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-5.0.3.tgz", + "integrity": "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", + "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/web-namespaces": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz", + "integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/yaml": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.1.tgz", + "integrity": "sha512-3NxN8+78OdzbT7C/WjGsyfPAtJaN3FNDsWxv7Y7mcDsT/oOmgW8BpyQQFFBnvZE3j9Y2Sdz1ULFLezL7Eb2yFw==", + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, + "node_modules/yuku-analyzer": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/yuku-analyzer/-/yuku-analyzer-0.10.2.tgz", + "integrity": "sha512-UBRcDcZtIn14g88loZUZ123d6MOkc2hMTawUle5MkuWboowM90KbWHN3Zz+HfuS06sw935ygecBpcJlXHB/pOA==", + "license": "MIT", + "dependencies": { + "@yuku-toolchain/types": "^0.10.2", + "yuku-ast": "^0.10.2" + }, + "optionalDependencies": { + "@yuku-analyzer/binding-android-arm64": "0.10.2", + "@yuku-analyzer/binding-darwin-arm64": "0.10.2", + "@yuku-analyzer/binding-darwin-x64": "0.10.2", + "@yuku-analyzer/binding-freebsd-x64": "0.10.2", + "@yuku-analyzer/binding-linux-arm-gnu": "0.10.2", + "@yuku-analyzer/binding-linux-arm-musl": "0.10.2", + "@yuku-analyzer/binding-linux-arm64-gnu": "0.10.2", + "@yuku-analyzer/binding-linux-arm64-musl": "0.10.2", + "@yuku-analyzer/binding-linux-x64-gnu": "0.10.2", + "@yuku-analyzer/binding-linux-x64-musl": "0.10.2", + "@yuku-analyzer/binding-win32-arm64": "0.10.2", + "@yuku-analyzer/binding-win32-x64": "0.10.2" + } + }, + "node_modules/yuku-ast": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/yuku-ast/-/yuku-ast-0.10.2.tgz", + "integrity": "sha512-UnG9mA6giglCvSErft2/40TVFX750Sj1xgwddPLpG7J7rlr/P1wPADg9G2RK+d/1tNLtRVoLdMMOMVBB9561TQ==", + "license": "MIT", + "dependencies": { + "@yuku-toolchain/types": "^0.10.2" + } + }, + "node_modules/zbsearch": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/zbsearch/-/zbsearch-4.0.0.tgz", + "integrity": "sha512-gm4zfO31n2ZdruTTRQoWVWO4Q2+zrDt2GlrvIc+5JulRQNAm4IanCxER82vQ7Ug96FYkGqWUJBXFe1kGAcDWaQ==", + "license": "Apache-2.0", + "engines": { + "node": ">= 20.0.0" + } + }, + "node_modules/zod": { + "version": "4.6.5", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.6.5.tgz", + "integrity": "sha512-v5l/aFXZQeai4awLbOpSoHecE9UiMrnfx75tEXLjNonXVARxQ5mOeipTjROUchszUNCqnE+hqAMujRsRHsut2Q==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + } + } +} diff --git a/docs/package.json b/docs/package.json new file mode 100644 index 0000000..9f03e1c --- /dev/null +++ b/docs/package.json @@ -0,0 +1,38 @@ +{ + "name": "docs", + "version": "0.0.0", + "private": true, + "scripts": { + "build": "next build", + "dev": "next dev", + "start": "next start", + "types:check": "fumadocs-mdx && next typegen && tsc --noEmit", + "postinstall": "fumadocs-mdx" + }, + "dependencies": { + "cnfast": "^0.2.0", + "fumadocs-core": "16.15.17", + "fumadocs-mdx": "15.4.5", + "fumadocs-ui": "16.15.17", + "katex": "^0.18.9", + "lucide-react": "^1.49.0", + "next": "16.3.7", + "react": "^19.3.0", + "react-dom": "^19.3.0", + "rehype-citation": "^2.3.2", + "rehype-katex": "^7.0.1", + "rehype-raw": "^7.0.0", + "remark-math": "^6.0.0" + }, + "devDependencies": { + "@tailwindcss/postcss": "^4.3.3", + "@types/mdx": "^2.0.14", + "@types/node": "^26.6.3", + "@types/react": "^19.3.0", + "@types/react-dom": "^19.3.0", + "postcss": "^8.5.28", + "tailwindcss": "^4.3.3", + "typescript": "^7.0.2", + "yaml": "^2.9.1" + } +} diff --git a/docs/postcss.config.mjs b/docs/postcss.config.mjs new file mode 100644 index 0000000..297374d --- /dev/null +++ b/docs/postcss.config.mjs @@ -0,0 +1,7 @@ +const config = { + plugins: { + '@tailwindcss/postcss': {}, + }, +}; + +export default config; diff --git a/docs/public/fonts/gt-planar/GT-Planar-Light.woff2 b/docs/public/fonts/gt-planar/GT-Planar-Light.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..9ada00471ed80a7abd0b90bf583ce71ac0de65ee GIT binary patch literal 57456 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 VtecM*BB%puput5i%x@ez0|2V(G%NrB literal 0 HcmV?d00001 diff --git a/docs/public/fonts/gt-planar/GT-Planar-Regular.woff2 b/docs/public/fonts/gt-planar/GT-Planar-Regular.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..29ad899a66689366cee9204b1cec4d52954e621d GIT binary patch literal 58680 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 literal 0 HcmV?d00001 diff --git a/docs/public/fonts/gt-planar/GT-Planar-Thin.woff2 b/docs/public/fonts/gt-planar/GT-Planar-Thin.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..d910c37ac8f6ac2f1bbdafdd5cc2a0844e2557a8 GIT binary patch literal 55828 zcmV(>K-j-`Pew9NR8&s@0NNA)3;+NC0k9|l0NKL;0RR9100000000000000000000 z0000DgN8{Ofhrq<%2*t^I0j$MSOf+Ii7*EsTT-u)0X4_&9|se)s_c|7 zpS{8<-Kag^5Ou5@;4wy>H#|8lrC}Et5H^kh82wh+|NsC0uSg~#SCc7|Y_{4}6h-xp z`-g~J9#BCkS=|ewk8&6)###qc+K@R8$9_8Y{RvrcRvBchp*I z9Zcq89ws78g@>Luw=eoSVQ$S_OJX@CGBZ^ZDq+IZ2vZ7PB~;c#;8u{Aoy7YVW14O6 zRBre-K`He(AeX{fFCk#74rYgadJ> z(o7HJC}f8}nPSvAO(E(Kybl_*sJp0kQ1~x>8L>|tg7o<8U5xAf-ppxtD_3WA*ba}I z`9bd8gdg z*x;BIwRUS=wCk`IRc0=$=Amu=dDI=U{R5-13o+K%#Tuh9vRPwfu_&IO=fhY;v1o&t z1GLSK1CGc85donE1hhfLKup5G$ar(1PFK3Q|3$iV{^oS0i!WE9uH0Py-hJ$QRp%b} z`(v%ww?`pnnT#(9lc-iP*t!}YVLs9U?;b8792K^pRnK0YhrG}jiI50~!I9uBQX&iq z!eAr`*rk}<8MlxEq|~0GelM+O-@iM^`WzNbAxsVmp(u=^d=eIiu{e!Gr#DPz-8)@2 z#(xhdIwfB5^lT$Q2^S=X)W+@M;nQjTXG=3;GGNF-hiUCBAUFM0SCrktKi_`l?8&=t z=Klp?2X(bQQ3XUtLIJa9xtfeC%Gx9g5P+TkO|XvqtbCDu%QJhZm#b@U{O@_&O3MYR zyj8DudG$9yL7Nv-CWPQ9f@Y!#Lu4l7got@k07GnPLW3Z78v}NmXcM5Kg0?h^J)YNd z+jSr}`|tmitI6rz|8>RACNjHMvp(|??VG6>6{JF2%z_63gaApfh!M55{`dRM)0J7d z@yDM85{cG5iH4ZS98f1qcZU)JNMZ>~#BtdytrgcjgEA;`~BZYrmi1=flTG9@Jh<%r;YznhU8 zD?keI?*O>y%s4)v7m-`uZ$DPr_T~QG_Qi(z?Qm~eArzumh@?O%#NrKauzis;kpDeR z^}oMz@0+jv7|nHOtl8ZHphG;JjEk&sti%OY*`*W+!`ALf+7J~XTp&KHf8=)loobfS z`jqhm3`-CgnFzRs+JAa*<|Fuku>HZf5U%~ZKFdvdKc$oOEjMPYZSs7X(zh#ZKA?@I z+piMj^!ev?>!19*oIC5}*W7%IpsFE0h^*f{nfDSSqGk- z%R6yJ{+bFRq8&v;(fykV@X3#%st(^>QUb^?p=yVUz)sJ)`Tx()*~3Wax@)cb<$Pxy z=$Hu|t3h?mq9O*2XgcE+g^pn%KvRMy`J~i?4y0)bQh}x+NNLD^;iNPBj=d>6IrU$Y zw1II_7|n}e={x9`u)2HhUA&~iG>FpfG67%-27kP;>1uUewtwe-6~H63J4pn!$jnhsS){h0uQT%qD(Y-Ef~T%_J;U}0<`15wSIy{YC` zv_n|rdY6QE8NP2ps4Z0F6<$Rmuh0kuJdewo-Jf?gQMscE<>2RP-VAM)HtW!MgR&@t zP{4n6)0-lU<+9xkr$^sUgtz%CH@>=88;<&m{vP5LlKQfNJ78@2$(BhN>!<5-nE+)=ouo~0ozjPN9O$hcaUgN z(KmkeRz;!A0AVN~BVkOj_b=N_{(Cd>lu+CdL?rB;*#G~V^ex+=S6y{f)u@Pw zh%rWtF`{ojZ~5z8h|l*X`PbatwJ!BkRa8YpM66hAtTDz~F~+Fy;NMNCct1sLl_E$G z5fKrQVL6Vix0ve*o`FQ-?bn~QN{a>SNy~#rulZjM9{nd(u7bap@b4A=KV{Va|BvTt{j*WL8Mb8r19PeRhlF@E9{x#e46Aw^^@y}U~MqSo45+QQ0P-?nyjpxRpMYNKwW zn8ftl0SjhQW<1dpbD!@*7P*)uE@SyCTkV>*V9Qprpr zd8ds&<|em|Te7d<;8=_XV|FMYoyeF(>ETPBvBw2j8eohOafasZx?AixZPjZVm}kbq z>)yldEwQ^*wzAHN)If?T#zdY|x1eoTY_8g-kzV%u+)$3<7Qp9Ab3wF%Nmc4yW7!fFa`z zw%uLlrUphAU;iHO)%F%ye7SWtn6$`UUNbvotE_@<4IN`<{Ln9a=Aq|aTXMs?eOYxq z(~}qn&Y~S1=)(kR(FqY0DSVDMIKl;PkpqA#P>jLDKn3T^f+C%mAtqU1ojp#uqM9Z; zLAcQI6D7k(e93d(a7cnI4NzE2QteP`QtLX_g(}shhkA~eaYW^nuHpvW{-p*jQ1{3? zCc(2<{a%E%*qnI6F8vgx1moINvt$encYjKa_nZ_dXF`T_)^4!RtwMe?k*i9pXXCcx z%;riaOiSIoOqGk0IUNDwviZGLQ%zM%42^UdT7RO(!_jb+9X5wvNb0qjC}sNeD8bso z5N`mVsOy&4pvKSS9J4T&!g^<>(iQ&E;dj$7KV~VU3ON@x-N`xKH~; z1$#IA+NXa;Q{*Rd0S2GGty7H4tV2(pn$P!z*( z3bE~X2fMIs8RxtpznzX)>u9;SRQx@^BC=kM`8Q0&o5%`>;Osn=A>_-!0-P}cl=~Y& zq;I)Y-?h|pYP^;!-ib{p&U^bdwnwfE+bDS8H22BOE@rnd+&b+xxy!kNuFvkBK1;jD z!+owEvLPEXfd{^K>~Guiz2oRSW@+2qtK&o}VX+Xed7EdN{w3wYs0?AvF&#UL+c6HF z1JEde?Ng_z(4pl2fq%|PbZD^1I+Om>2kAcYvg7;xq0wwS^82&c!;X__B!47!lIKnw zP_%IeqH{aRYDb5GL8O{>?fTsYRdq}M%8?LnJE>@^Q4?{JokwAnU(;eqiSV71zlQ@USz6U!$JNzxK z)bsJ7cg^P#ASh;wYYA^UlA;;Ccb4M?J9`I5Cph6d_UGveDm<{gwSG`!_X}O! z(k*L<8TIpYl2j?zD-k|GprH&$prUQ|SD6z4fFNWPFl0x6H6Z~*5%tBqL~DvXl1MFF z@U&Wa;eDQ60Hv9p3l9#HRGgzYtpm@071woUu_Tsc3Im`q zKp+svh7i`qvXq=PriMWmlPAd#^GOW)H(GjxDbfBHD;;4~V?9Z=(d{R6==Nv<;V2ij~`RN?Qy=t_3sX@JT%Pyf05~0_T2yWvRBI=41=}Zn{fTT zHY&f>&$js?&H#ds6g|wa!q z92KimpJ|(JNK?i?sAmWTo*2lblx8~UVH_@PitSHR3444ng%a6#yv8K@@S8(QlJewF}v}ev*3#W zE`AUb_Xkl#So)HM0U&FCk9tA?&qy(m!E-v+5u3ifYpl|%eS{11RJ?#m>+jlocCR!3-<9ZI78&t|E}#KuR;M3dpF(kv<9huRg*BQoD9>erneMcDcx} z+JPSyGty2pO(qZ>usH982K>5v00Q!vld-ZwK4P6oilPr)FqYVmoxmI$ORQ_`$cW(+ z8!NTqZaS#MiL;9yW*M~$AI1~GriS*q)hlF&jJKf-sYaj32xr>i_B^9L>T6;Q+mMQM z?8HvKdE5rMRQgYXvC3UKB(~_1MTc!_%2~Veki49J{f*Kt{CencqI|_lD4#_B%Gb2} z_K#=<1N03~fc>&`%J>6{k+jAR`^uprb9WoeQqRCe%D{*_Ac3&q0l*NV>xDb*HjJIU z{oG`i$%W*Eq9g@7v%4~va8yggs7w^^XymnG4yFuQwrR<#`Q~Io)f&rg6<&SutZ0V+ zkY3w5arV^)nX-4yS+2xO6PBlKl!;9-bn%+x@584F=oHo@oNU_|;gC(8eUW$mTS;gn zK*=W}iRAve%m~y8Q05cbzw~E6D$T~}297k0CDz^1T5+WyswDiq%mC1KC^h$q40kup!C(Ql65Bvh^^Eo4JTK=4JD1HA5Z;*UN z=#yXt88EugMIWN|5yo8%ID<9hKK#!@uGdZe21B zr%tlB4x3@C*&*kXahq?=1hq&(V|3vw=vwL;TSBGs>!S6W8CCBC#V2(3NkFf4KB)`M z>Gp#XdDK82>zStr_cP?=l;$e**t;5&YP*=Y=LNdb=x$3@{qk5cz4zo= zxhTQ#W6YZUOUwn4X)zQ@v6Gu`bMWj7&jfiFpRp>YkWA7(hQ(Yg^c!QB&)dPtGm_Sw z0Yw~L>>oR|FRCo;*;b`_n}K-78i{)U(I#^U-5@6&wi4^Ql&E70eZ=m&LhZ&G3}h(1 z(n1ZrB0dHx+<$FG9#4d2j2MHHu&>$%NVEf%SIgAoLt*1PAjm-z)QOAa-;K{#7a@ zp$j8rGS~G7GI>`yqV25418AR%{CP$_R?b66zfbM!hwI3`WdH|fQHt5re|oGch&sCH za_H7b<@)6nSA0BUiSuVCRu6Am@j6 za02jl{$;AdTdwXmfQ3c*jDts&{1L0<62{+AKL*?)0)9c*I2y_xBy&%o=ofG@+YGpO z9s(CgCqn%27Y0b!e-aZy*<;6b-UTic-gS=EIT%VK9HQN_ipl3*``N?7sPQ}HEi8d$ zcbA?{Z@YB#%DGgVa(BS)%LDHk^tOZ|r_YI)qQ$Cw@6oDD0|GtvM}{7mW}X?E4Z0wx zW!19313ii&(mEy1N|=!mA%}$QTJ^BWu*_DtzQoKyC^dWI{WotK2Mrq*5jJ{s#O?R; zqgo2VH@`yw&h}m0iNLVz9?KPMx#RISL|Bwg1Y9|-(~n9W0siVCHJn@IfUTKL&pw1b z^D~aZ-0~UEM}vXM%CA6S8bGKPt-*gtq_M=#(@&B22#6Ho%i~6)!Z?Bg}!E3X5n>N+D~JVohr_G z{;YU@h)m(=4xDZ;mxbo2D7{%4nLYWWBJH6}_7wVw6;uBdkOC|G^oPa?BwKw>#;se9 z#dD12Aj6n06v*PAFvQ%Ttk~)ioTe%mi21O7mAE@8$>+DdXZM|v@#Zj}DY$dL{sq^f z&JG2Wz72a%Q&OYelCL-J*{}hx+qZUqw44$3m9R$*^z9H>6j5ka=}yC#NA`DZzytV> zv+3;`woV_+WX2Ym*aM=X>>J3?humG9cF&MAqYQiiglQDw>g%M_PS`)DEcl<736epB z0Oesm;S2(V7#OU^Ifcr%3Af))l$2FQx`83<(W3jQhO@7K(4ZdllhxYD7=ltPNwC&B%rzYzFIrHSz(P{@EaByCLk#J=$J!B1=Q zQ?kz~3|%vKJOzv4i|-LQKlcnSpiFjm)G?OMcCIkzrYzNsW%C0?TI(W^PSbIBD>Jnv zasBQoIAHC1pUcBMg5~Iy%I1ik35Mh4?3IPT3m|V8$pNB=C2$6D!_NF+d04;h2=}}l z22oLXpLA&SRJ=!X-;L6GULgE!E7e9cj|L+^Wx^{pAibpFdX`##L6IHKWW&YF=@}1w zj)hIl$yggRrby-*B)h{-GpYN11cH2T!{69K0~WU*CDMlYCL8esY&lAh+q6k8;kW@F zZB1V8ENv0vS>gO44YoJGBc8#d#XUWleRzNNnXa5lF0dPVvJr#Qrv!(Uq)(D){!b&3??8r_ zn8&R7j6^u}X1?JPw6+|ampMe1Kx+(#ms#sLYQ0~qihm+s;rd+@SRn7(93LLA1{?3U zh8xe_aqSowmdqI;=c~}tF&goevCxoo*>zgBo;O@NXLnrlxjLor7k}nW1y4_?i)Na_ z5&06BvJpkcc-_O8y!U$o3I`F_UQgtW`;2-kW2!ICjjn$=cCZVd;pDp;lzFWXgD&I9 zqh^kh5o2o@%_sfe_HSW&kv%pC5v3^o8Nt98_>YHh^utO$fkUNpCs!3YfjByFk*A?w zIe;-TXyF|a)qnTuKfYt}Z^9=O0f-Su6OPs!k5*pjJivp`srZWVKeQQDwu7-y3bS^T ziqL@e7o)|o3%OEMC0OznPm`NGBfySI+V|EigxQ23#&%1`96OW=`x2&tKQIXvfo~}A zgt?gc%g=~0ROVCun;ol1Ok^(GIpP7-!F9XFFI&SWAT?11uA(z{@aqFpHen_0n(zr$ zNGjcDFN+tZXYQqGV)v6hG}&Pzza2f6tiZ$VlCe8@He^gCpYPeZO%|h@l>TW%TUr7; zA?9BIJ3EUwgyVK-MaV+U#qrw_!`oT0xW!Ir(D;L{jrb}gA4Y2_D{pEl3+We_8PXk; zS^iiS#;oP!;~fW%DhPMYq4ohG(^rkJlB=G6v*F!P3>{Tv5f-$x6l7Y-Ia!6DT%^rV=T}syIVGhLITI&3ttwLCU6p*vZcknr;fhBbj`&%d zEHpT2dqru(-APw_=q7-U(unsm2~@q36EQ_;a`1qil(aFHk*{CZ*1mo{qPF|kxRFi% zAo`>>T*>;}(l%HKF~w9&U}A2eeYWs0X}{NwEi?}g7^k~DUxEAVJ5r32J^!@hLea@0 z1A_t|Ax)3DDmQVWM_}NpaTL|Tf*uGQu(KOpK9#TCG6=7AA!t2Ya+v*;VIXZ_%{ScV z$yaLJ^37U91)rFTEpF;G6gfH}Zt@Wt@~KauM^(bB5K!U)yj<7wgH&G9oTs9MkfyNp-RRjC52w&EuK6c1^vnXC@Dc6_3Wv{Y=hXzkw8uOh+BpWCxADe$wGIzQg2S}?2~wK~{#vbLb&6`#C%hh2C0fNg6~Ca@GMw`t zH92#ts;1}lnLKl@hzOp?9$A8J$C*_LnWzx1Z~~6n>Au=fJ2Ahf?p*>ocv8U!Jv9Mk zoB2C>g*IVT!~&(vC8C~id_a8^oFOb$R4nJuxL8Vx2qDzx%ayAzqP3KkKP(B?vO;=8 zvY*ROef4p)&5Rv6v-VNu8@+Fol-AakOdUF+R?VNUeqJY2-Q|>Q$ED@-Ea8yd9=?zx z3-m?UUp1NS*q$uRT9hevlk8YgW?fz3!f9%=b0B=aS|XG7!HL+@r%s%3EykYM^y~8F zO9>&?LH~yx&kSa4uG`ax)JT|)K+q8^a|mOpktgLAlw?WU>%nO?LeVP-gT_u`&TH)0 zgv3;|LF%c;-|EaRy;*zQ$a(XXSdsP@we?UKllAUq;QqY1Wk4^(wTNt6#nM z&fGm&C@RsA6vf{7i4|X!{>M=jzmF;0Kj7e!7#XS}pWh;G}a{`slslk zm>%1Wp0bz4t6wkU<<`|!BqWh4g6g%}-N~>!U7B{%VLY}3YM(r@7>m!o82G;|5k`2& zQP5M5ph7pP4(2uq>APr8d1W#_9m}|>o+`AMNOw9LcN=cQN82*vun`DrUr-cbY6b>wYho0Attl50E7>!Be4IuLh!Hybg3422kAn^9_Ll@ zF(!vYGpELv(`!G!j#$%jVC;x;(rO9*|2QpqMBs3G#$j@JEQNAoNft_D=s$mIMlTgK z;4H^Iwi1V^xn?1iT9KF_DE?HgZ%tc7Fshr=Pq;V3%!3P;f;IF2qK zIF7ClLeDvYZo#RLTQCvbfiviCa3;BXg<`T}f$`&b-!P|g@0VewvpM_5vL zf+ah^6D$=>gB4h67y}ca?*it-5EvL{!*Cc3!(ar2gZLmGhy;2;1TfGLJkSRUK@eyK zJ)m2_(11}88PtOgFbcXtu;35!gSt>3O9QQ;CqxMbT_6-RfQ66`6oi)Gz|uh=NCZ~H zGMEKjpg9x(9Rn2u_@Gfh0hS3`K)Zl`Fdyc?5-fA5-~$LiZ}5X_RZXX7uTa6;3llE*Oi(kfCwsTc$-IKG6Gd#9aa%#`PN1bQ-_&teF!L#f+ z@(gL8zf(;Y9z>Es0}EI&lH-5vY=ZZ3OYP%gH~X4H4@8MwF*2sair5&t;y3Zy`Um08g|4ptG3I_L{CW#l`8BH6y-HN8Npg|7$$tLccalB^t$a*4LQIr zJRTf=67JeYcd&tFhgFeGIv%*Q34B0@(eerVa zj@wa+;rK5~F-&Iqog(Qh)e~U7I#XR$xLU5iwI0^j^mO+`9Hc`cth{UBwK9_;S zs`RRM>zuZ!qCp*1BhSxk8Dvk6iruW; zwq1~2rd_RPwiNcM{prEq^HqmT2X07_@QZ!w8|a)3;d4bsRHp(IVxq)HSG z)L3iU7cHR8X;H1N3HmPmp+2p*^w_v<{4+k9d(5GEW-4Z{d0-ZOhkRdsU#vIQ4{O>Q zP;eRApv&}vHc&SW&|Z2mkM3HHQjkPmm= zbsbMjgN?P85$5%;!qestimzF0U#!0hB6fzHt>yiJj6^u0NIRVCLqvR62NQ#!Wv+1 zNF6f)p%Vs=4=aL408_JGkbYyn^*xIToXzzLHTX9ubj&`W%*}wCK%6lSB0T|T&(L8% zH)jmD4>i|z)GR=F{!e2@RspyYlwf2pdO-x{i}tIBivbArvcZi;2WGN%NAn$p_VX(g#v{UKPC(DZk-%N z)j|!#nIbiuRWXgSc+~@`xk$N+J)=#M1P~2QBB+#n+G+3q6RLnOBOm{k zPa1@V$*?On2i_nQqW5AVYhnC&gBb5zyxId_53bUm4sopzw#{gQ{Xbws$pbu0v!r#~ zB!MdUp&vYc*uyi7CmOZ!5HOnBS|YS?4vXxb%No5M<1&BPilOJ{DqdQ|+TN+7YE{B&hu$6UZ7Uzmq!Aly_vm7Dy*ZkHTV8j|;;(ol z&9k+adYtyICK&eE25LO?`X3U$!6O;cMtb##H-~qXe5EukT3_~N@!8tAKHJ+tun<3^ zjsI+L5ZQ>&SjM0I8XmTmU*zS)dtR782-o{Puz6~fU z=rArjy}3ElSK&WILOo0$12;hJZni7!@E5jgzYkL0MRn7COxxayM!MuV!~ z$IkK!!;91B&zR$Lf|l%}-S@Wp=VeU;oTkH)EKsxbpD_7SJM{pwZpnQ2W_1W}t*&lm z=7RugyQpv*hml0b(WUIG=B-#-PYt3~Y>8)m3r6Y)mdl!RMc+j_irT%c^5je?{;vl` z!%pA_Rgb}m{6iu{$L@a~0O?;1Ocnso8Hn7Wtedl%;R%+cnEL9)z(pEeKMR}cF!vlS zE`4Xvv2FfNw;t`B<5}NVWkkiY6t>c$pBhExxhYY|U#;w(I&7ilMDVwVvU9Y_O_5pF zf}7eYccyO8aqT`og#I25A;8LnXCs$`siv$J&qF}1U!;xa0MsnLrw1%dlQ?JEqAMPZ{yd7#WHg3Ri>WymT+h7) zkZq#NlGf@>3t4++BI5WrYJk#8!wH;BxoZ2BX~m(iVTsB)T@FiB?H~1I_T+geC*9N& z?r;FrzGr=nr%?{oY{Zb~=%V&z{$cbKEzL*nInU}Oz1K-ruuQGke+`dnQS@3W%ug9; z0{3UvsSXpRRu?J&U6=_jcXk|b3XD3jH3}gn;kQl zXSTZ?ZhNY3i9__gza(WReZPKCLsXRlo!zq>D#f1(1gN)T(I9dQF<%Rlc|GCt!zSg8L~ssJ zv>U!l36@yGOz!7hjwCbHhFvxHd9pN+&>s5a?(@V}{||p517daF->|8c&5+Ub%B_ginrQG+xCwA21a3-NOdV!)sVpAx!N zh6w@z8p;I;B=?%7&yT0DT61Yh8}{%`t;$?^kza(B@Uae8O9Pb+o=ZAB#ti`0k!K_ z5usP?8ryfb-QNTZjcyC;c{ry=?>2_znrjP2?+CW!9j-Vn3&hi?tJ5|QQ0OgUIBgUX zLrWQo&e&(8qvY>;=8~2Y{yFp;?9cg^=rGtZzN2~2R~goJin%f+jxx*JXlt*9wwo%R zJ8)-S$;-jy0@xJUi#IG}{Dt75mjVBPI7~$EyYA0W+&N;=HV;x?-O-xsUN%KIcjPlT zXtq{*u%EKIyi7$8Blia+R@!}b@4nN@jPO0f#7`-j6Sb3<@3c z$XU%jEz!{sH7+J3et8y%8SRFG(!#flEGblds0pB8{AO&$+3;IES)uZHwIEy_W*u0M z_-yp0^y`bwhRkFXoT8b20Nw)xv5=bPAQ5&ZeTG*3q z%e##pXxji9HN!F0(5Qkg6#7w3)$D74@bJ?IAp7)NLwVwIqf7(B>sC%v8tLCU9s6xx zc>N){sX8QJ}_ za>n>bXe?rmguWYlVzj}uVg+Mx|sp z%pMrZq%2LM?cJ(4gsk?az}oljQySWmVfYR@rtOc4e;?}253_}p555>SKE~+&@vlU~ z(m>>hOV}KWcmzkN_L&{oPJC$K+VY*zpKKM% zh^;}C!0gVpEIyv0nQWw&F(aU?#nVSnzDpIaF3VR+YXJ|-BCuh>1Dh=&T$VeHx5;Es zUC&%%jfG!1{^HXzKeze#M9oYSIYT#VmKGc-pbl{4DEh6lS#<7&S=&}n6w+7m*~~KF zx7Qi^w)XuX6=8Us3LrCD`+`alL`JWia-rKzLM^XEi7@lr%RB8uMdS98>YIDP>G= z-n=p~Jd2Wd(=d?WfJIou$zbpV?%Q*$z)O`fGP3u*r5pqVgQB;@Lcwr0K%rtBy-v~kmP{KvD5~kqx+m7U zd#HLpn$XRzfez7*Yq9_QfZm(3VDu6NKZhsK>K`_N*4sWqqJ3C_dtSgyRXh$o8`Snu z1;6b&w?mKN*nfg>x9<6AL4AOp*&YOdP0yMq=)D7;cLEtJG)!w45jfq2?$$c^ejly5fL3)dyg z%EJJYnv0hUWN@vVOJ1EnZ=|9vK|C0{0lSwds&DtwE#*lJU^8fZ&=U0GI(Z;5uu$*& znuTHxeVLrBti1OiZ{~wZa(VsT2)@dS#)q8%dU9pU=O;x3 ztd){Ws zLHKm!O(qK66_=9R-1=#|vmWBY#X@O)L5N95Plh z#eq?ZR{AB-+964_6YCG-3sz6lnB0`DrHV_@5-Q=AWIp{LUHD5s(%AL>4VeM=zMj~1asewPw0uNb{CBWGWx#9fLY6{cy zT627bM$%8Gddm??)n3qu<;B73TyLplg~N*9hFt!rh?O1s59pnU z*0~y8dG^TK3fp$W-|#mq%`Ba{RV!-GTl#Zqv=7S#f-h5-gGQ&}G+fxVgkbS;Uxnv` zIo@F9VhZEo5j!5lv(7p71N?dnRik=0|$;wKmPq4vu*@g zmMw+^O<@TX{1~gkMHe=w!;x({LVemJiK@Lqyf(;J!^d^<(t&al$_x}vEEQ@CTJ`VW zPg&QLZdi@QLuQ6ipjM1-V?ZRR@utZ3pDJYS+j?-j{MyX$S@VA3WGc2;b8?({@|Oqp z#~(1?u13Ez-%)jZfUO1UhN!G!m(xfz5)G$twpKmbh9%stMoMtW3dbR}!ks({B*N%&7YfV@pvH+wa{ykWd3&0fvP1fg#$m=wM)z51?I z+6!NmyL^|_L-p7YQX>!3;90cChs;G_n9?(4cXoivtix6FUTxE+uV;=kk@anO0@=Gr z)*@u_e8GBWl5IMB!?KLM_<9cC?~g{zh8I(@;bN?cJWodl@U} zrwncts4x=MZFe|qTsd6Z4@lU?OMM;25!&z5=~7NuYm*tDh9Fdc+0z5$6kNYp`M z4@^FgI$_lHK$Rbx|D(P0*)XCb_+1Y~7tGLEttXMvXonIi6c+xjR6TA*=M{xl6kcWX ziW~V!UY+J;KODheudiZBXy1cvSn!q?w1OB<-B z6ggkEoaN9{N`X)R=xOR6$`kD#zr(uK_B#8P^>->kW7TwStEUAJ=%O@Jk6rY2QWR)0 z7^*T2n|Ze@!JgpSSx^@X1EW1NX>e%NyKn0mg{QH`k{?c^X;k-*|InFs%-8iep|oq( zdKs%E3e@uQM5MWetrFh)~AKR&P$2&|6)6HFrjt><9dh+tKi zTOhc$VmTDSKkeSktJNADi*hz;k4LK;ulyjLpyWuJT7 zO(cak7qi1d4FCmW$OyDG6ipUePNXVPO!yDXBKlOcy9H}~8QNy3*ylrROFMz5c-&BC zwN-bIsHk2Hv#?eNrO{@dD4~?xEuu(P`}nS5*cSC#cW0Uu5pLgEiHF13z4XYfG7|tl zK)}C_qt^|6LRY!LEFMW z1K9S2^;0W_98LS(N^yTMMTXx9Ep%8Kv<<%~xHpeVgDiuDk-vy|jT3tZ){m1Z*qiC}vlJl*TFIhxu(kT=5}fu=AV)DsbZBYp{+YSSMZKcXEeMKl#g^mp5BU%%x z78XN0S&z7Z6zN?*?J7g)`uWBdFloQ5(e)sO#N2l{hqr~*G1{4{f?Y4-G0MtB6p zTp3IV>gxFMeVa+(~J7mS8;4j;wq*p=NiRf zS)tlDqd_`8+8-B@Wf%m)ix-uuOvtU;6x(mvW!?d67t@UOXY&+zz%`S*LJkir_kb*% z%Q!mw z#dC_MyeHQlWsA}(7}+^Kac!A(@V7W33MuNno$Cdvf$T}F zmZ=HPPn$b^_8K{q?X{g8-RMQspyCEAsP}HSJHbWO{@7M$;b;1L+pvHob#GL-#F~l1 zv8GyFYxSwE9%CM?qy5ufVev6$jyb__=TobT_@Xqw@>4LQ1rLCQ*T9T|{GAEIQ@>c# z2=kTV_tDEB+Rhv_1r$6!R%a%W0|Qmoa4wiHB3nxqedCz|Nb{t$Qn2Z&^j^HgSZJgC zoemmTqf5`<3Q#?D?b&z*49~w(D`BMv;xy-!{hsBmH1V*|x^D4Qyn3FT`MW(8?bW>2 zJoqzLXe7}$TTuX^+TK<&u_+L$)_Vf>FtrvK?{p|}>CYMXYiE4bneEo?(U?7Kx1z#o z0?v+e>S0xMpl7?}BOw3&5acgWHwW!hD5EklzxsjCz|b}ha?F6|I3&N-cJ8N!*B|%& z!i9?JKc2a#Jo3Qn6FMfPMO6}VfOv1*Ew?>4+Bf-mqTA!BJ4d4zEi4kl$Y|_8p?dWV z$%RiipuzP@-&KQE5O};HZ`Qk~M3FlSIqyve@D;IPb_hUkHxTrL*%B0by8lYFU#%e43Uj5jrmN1zt5&v8U#(uc z=cVbr7AU2pKGkKdGXs6cPbmA87>j%nZH|lc5l&NYI0An48fs{|U*ud_{P|&N3tr(` zem3&yn-a&qcK4&A?=rxQHAVj~wcbnr2Dwk>ZC}qYXy9?0hDks))X3zAmlPX;VWM); z$M-E-RRLyI-9vIgU?QwDv#K(IQ}KMXAu;bD`5eq93v;NfE~nDl{Y5eRf|;fdc7IxF zX#@J}nGqVxgp3#LNC(}R)4-QQWVT^N`+pwWc!Av?q>>T; zLYr+hf$W}Ut3h1|vL&0=6K0}r%MaURD(kopuoQPb(T}>!J2o_&gUHAg12A|WdokW5 z4DF7DN-|JA?b&e)BSKayi(SGCTtYt) zE#pmmxkdgVzg){}63>05t1gmF(NWN18JkPyR5pEG5O{eo`{Uim>+%rKS-O8m7a45N zxcLeG(AjKyxII}XYWP$4SW5hG>9MEk*;fYfgV9|Qt4oBZh85< zvXJ-Y&4bI8JMW;PCvb8<2I$ZmLQcNJF5yI-!?UWG-o*!wc0FSu`+b33Vqc{K789D( ze-a&>w?Y60E2x4<5q+`?PPFUF@s1!s*D!M z9uXOW;0K;(kb6weWV#~`4b0UavC_6}1;5*{QEMY#EX3tzpeIJ7&8CU1Cd23mgFzgc zH8!wn4sT$2$?L!q89h`)Bg?2~B8Cv6t{&K zksW(Z#-BXpvuUWLEWpZ!&GDNz;m~;q&iJ?Ry;v=uR@egS=I9~7b9({tw_G$Uq19%w z{>!&yaQ}l3AWW8!&D==sGh3Fx|L9iC7lHMoEJKgAyvTf(J#`}O7rDmVv5zYjQBlMuWp6*y9-;^6%}hQ}HNv^hw=!mfb5?kH?AW07tTTyDUTj54-J zH#tRf`SZddf=9mCmbi$ zgnc@PK$30b%;l`Syd^196s9SAkYgf_xu){PNKbZ8{}I4@GAUe z?yYHI3XlhWOaI0cUpy^=U7l(x3_e*roWW!yAB<7m@~+zq)nbo;+WV#hOXGNh~h zM&-ln%kzFQDDuX=L}$eyeMYEHF$&VC89}7j?r3~ zjIDJ&wi2{z?L2_IiYBmQ99C|?GE~OA5+V=e`5Y;;l`7&`fZDO@`Vd(t?G@RU==W*$sdt?J zkDl~;LwdbeX-r}a5*N+QH#zdkftd(B>7ZZayyT37z7wc%xi9j>>csz6TlysUfsY)N zhq9M{7R-CSXzS0wrG+}(l0R*H<@!V~2KNi#XcmIO0vJLW>4iU%4xcw0ZvEFYTQ8a2 zgv`^ReD(P=`Ni2mrlM010K7DB|Npk#>dh)9kxC0)!s1Q4H*d(S-N^s#%Nk-3i?~pZ z`FmtJPqV$2w0)P4|CDm7ZpL%-gS%I+pHX&iN!fGx*iU#nZb^3U&9osLQP z^{44^{E4m^6IX#eiQ=z`E8AvRa3FP6 zk(uJh#1-tmlyPMD;oXN6x@t_EWvd}qkhCZRjkzig+FS@KE5}RecwB8(X5M96(*5mK zL7xp;xFTZ7ybS}toi?VY8Xsrnm)JRqkIVWUa>){B_#$ri_H8~3F0Cw(DL!s&QR>Bv z0}5ReH@0lMAy-(n!)aE7e)MxI_E_oZMZft&(-!RF1dhBGiVMT)q1weWx}5-3<}L+Do)K-hRCQ6P%k39(jkOJanK=F z;9xZa9ddRmS8r%@nEz;Wkri(a>)LYhN3I^DDhr*W5S^eh>&@b2gGZ*94c_lk4LgFS z*kLt6t!hK6n7N6bJH%v7^IZwugt9qH6)5u|HQeK}wnt+u%bun4^g=sIswla*{70(v zqM)xl@>{O)5@82rF2#w2)5N3Ym@m@OTrI@4Kl>zkH6* zEVzL8^G;{zSr#N)$Coh?a{?mQUm(`UGBJ6uhOIhy3lAn-bB%*|kZ}tjE;V!z^paae zvNYCKtMf7TP_L@4GpY^Ms5Yum4a1u<_eCRF3zddV8XSR7wbMU51Da&!nJ8uW{}Pid z&^Y>iN)AgXC*FLf;>*|(yl}1=hQVeI2bMZ)|7ulSL!<5imrb>~Lg=fgN2BPi*)9(|gAKZc#@^t72h z6vb}?6ft`=NKE*Gfo+n1Yo0?hiQ3y@8e=w${`j%}CNRK^y4fxuYBa?J-}76BhY5eE z`*Fw~IPAuG5yBIEQCt^&%XPQEew(MhR&*f>QVUgts@jd1cH^O*k*tuNFS%JYEB2IzziR~F!Z8(!! znfjhV2Qj55T3*iWVvM4^VHTq1cQyYufXnr2@ZA^m!c@&S3c#%A5B?z<6k{OPnH|`g z>hVPev4J!^b?fu%s9UXXdU+J%jM)kC!E@Yt^J@iuy_yw>C9 z_Kkw+2ayxIM@1zl)(-6xc<6>F6PC-YU`_KmU;v&mSaBY%Iz0A6e|l+H;ZB-gaSBe% zRZW5Wpet)1k=9cwGz0JVjCdXeIzdx9|3%6&p-uDX)uv_SZ4e)3J7;ex? zyfKNBOyE-pzp3Ei_Xa+F>9~{qDqC;GHd8$iN~PfLp->KE@5{8kIpJkwO@H~l>m7R? z@M-LGAiE)+wxGFh*0KCcjtffuh5VJJ<~vnY4<1ga8Z={e#2SOz)w9n|Gl!-J_J*Dd ze5i0NPUG!}4DNLRUwuvM@+&JHb0!F_CW*v+zgm`OEIG{yc0MovT9wl0*i0fiS@3hm zQt#V}j&;{j7l6q~z5IokLp1rYt#mo8FzXmrsU%HEkh#xt7xi~XGq~SfT=R`hMmIDu zjyc!2oEj_sbMt@7m;V{d`Og^fKSlqaAjfBWz-(P}?pk$GECVR0CEcifw|s&MjU8N5 zNTcryD$+)c=B8DE$6tX z#Q~~{)N|uCW!3A%i6u(qt5EZ~!rvq*&)By_;P&_TWoKd$Gk^I#hBBIz&X*BOuIRAL z=>C1~b7ejh+Iy+Cx(dc7TH2O^soj;&w_!a}-L$>OT$}{CnhJs1Q@I*#!2}h;(cl$3 zNzZVS6_`ypyR9ohAh0Gh?7 z#bmkb0?+)DUdZ=a(9?gx%j~k$SVJGNG5?tFlkX38vb~7i=Q}^+wXM^#$jjz5VDYWx zwE=wb#8;VPv*@69M;_~Fb(uCF?H~IFW`7=ZS_|dzj&1LrC|<~jgdS_5lNt40A4OK| z1p~5HvYA^t)|rmkE|&SqEXo%;nHiq@J8eEXNLAX>=c>A}OCIZ(?P8g~99a};>Mh(C zO%*=cyKR4*+!u-Zr9O+xtFkV)Y{?e~5A8W@wvz%9UT#-wp}b7TY!`BsPuw`Ih4L~T zd+v_#eyxkw(B-XpY{3l>0oRS z=xxzc5scxRu&7{V>v6{W&}jIuqSD85pt9=md1m1GW=k#Hp4I@0(y5=nPB4sAo z>!v0;(YHNVSNbGVp$xyG#@UVZ-WO)}oiBGRdZD=UaGSEyqV{(~u2IH{GFZ!WQ2Ukm zsd@375(4aRzk#go_iOp-@#D2)AqcmoP4Av0wNoEz{6U;Py9SGp0F*{M@|W2sr`d#| z2nj&xwj)0gCbOuKLeD6(b}$klms+TSQfWtiB5W^Wd;HF4US8I`j5iar>Sk&@46J(h z)9JKIbCE4vzFgdNcV1nmI{*TER>3cW1{v1Ks|LTwRcXZep-ETE1$7FM7YnQ zw7qsUS@lyx86su>21TaF6r1uiW_|0Eq}gfU+H@ECx{V*{jmKGDP7{3}i@6^tdeJ8h z+`9ecO>}L$*F#s&Uag=pvbjT`^I0{7JTrePT+v{rR_+WV@a&$Kr=qUfYuBUp z-VyZY&SlDu%vPS+ivwy9;gHSyw*P{J+ZR@+!>zg|-BhWru|?aEQd^U}Ulp(X1SMn! ztTtzSMN){aQ?()4;WjZQ_ER%hq~u@yVFvSXoy17H!T%f>>VpX@-4Sy&U;S z+M9T}QU*?IF0Wr|aWAn0qjl=KQy_eyTQ#{0{RyWgNOzr+uk@ZiCvA%nRP^KszS<04W3m>`w~6Jt&uXTJ z$m4O3rN-N{h~RUORkc;swGCM))E+m&Kiq_Libwyh&%jLO5w%ymmcI5U< zc9T=H@FYIQ)NB*WaTx>FNMsK8Lp1#0DszY|=dNVSJp9np+>t=Lmyh({GWPtBa`|UB=F0-K>{iv(oVCz~*uVS52A57!C2v@{Kk$CyQ18~i z5422`?TbcnOlxMI8}o%&=)Su2QeLvc+kf3{<(6!cz)g{ectC$2SL(5Z)FN4Ksmmnt z_%KqiCK+6XCM_2eF~g+FaRHB~clp4lB|ge8`Y> zX!Y4lpPK9o74EDx^S8^@xnD|U|_y(CtlyU2Hm_Z7HmTqN!;e zabQGb)h9k8??|yuR0>G|A1$k+KRF~;#*03(J&uf~3}iu-$vg2hw=)Jef(|KQN(IKT z62TC`r`Oa&6UZYGJeB~fq90`O3v)lq=^?X|q#@y?^{j&IY`%~Zv$)%N*c~qi)SN8! z^C;f3Ic~W*n+RrvVMSMuqdBGrOgC2fGDQcrifq_74f7qhb2(1ryuMoPT)G_@t+Nbe zVrJTVHtU6c$$qy_FdMv!z;?qXXuQj8Orop{vqXi|gJ+J4vcH5lw~kH|g67ZbPn&nD zbdy|25>8iyJvK8BSIkyga$lCt2P>xz4$Gc8ppz=(NasC83@J`78O(WK4i2td&)|=~ z2PspD?=jo;sBiw~!7V()GfN-bcRC*^7r(6k#*M5UVIB2J5uq692Q{@ndhcN+~&2;hOGM4bLy9LI^?5m#rZELxYrORq(pgng!j+i2K4*M zW6@`yNP0-1s;ji4df-QmC-6^nDIu~URQ=-Vsn6sBNl9P)ScvQKE#w>8Ej5ik4 zDmREJY55|DFD?g>qk(s5!?u_e+_+Z;<^@@+g;20&w7nHKGT0CWhNqc<&D8ip%0e^% z_S7@=w*KwT5sVa6NA6!z>0FrCN!6YAXKgb9 z?7Va$oHs&xjff7UK*;KTsP$2KLF4Ty`F(Y9=>*X*i?F3e+=kyG6Amx4 zY6Y+!_~ZGg@)o+41SXh8&!?R=J7@P}WbSIsycmz#P8~T5-!d>p;MeJ$as3#=L%c3^ z-j8v+@Q8E4s+nvI&c#@kV3Ahe`03Vh*Z)nu^84$6s+Kwiupevs`7yRbqAevehK|V9 zeL8km3lgSTX!^moAX=D%kp!D+;{VT{L9yWMS*%<$2+(iSYd^jlUe_)xGg1~O@VVX9 z1a|RJMo&-n9N&U%p?rOIeu#9hvixyVWypZww}QI@r<6Cz*oQox{XSbmNwjFSDwwYK zEsY(8#!Xt`Pq7^=NFZ=P&Ak5jvHakfLC@!Kgu#rMTjSC=#){o>v^7{0=C{9eD=nxg z00aaQpCe}o5vwBU3Ns|YPbbr$BiqjHP(iYBj`a6Evrm3IW?g;d8BxaT`?}XpeeAhLYO7kmPVJgiV zHh7fgjoWbbBGj24`j>nXV;<@OUyj2he!*aFN9u?5J!gnPJ*M=?c>o7ie@%?>OW%7) zDGkJUy@$xB@I6nq{CsK6{Lnv%@q&z<^>ODdz!ZF(=_mH+!8W<7Y?j;x@;hJv=Csdu zL^R_+VtQbP88bM%mwR!X$1B4;hGR=@Z=u1GoDwek?|I5PFX7o`l|_)j3p`DH*^2A| z1i!`$alcuBF*qi-00X!YiQjY;9}W$8Ha9eM)um9ut-246O&xik<5EWsV$P?*szJbo z?0_-@HvR3z3&&WFCAKuSb$tGBzy^Z-rf1>LSO;}YuaA>39C1p9C%OEX|4EVxX4Q&+ zMY_QZ4f^`BY|6B25*6C_0CgSH8+R1YF`q*>EfW>gbdFBPsXa4jo zn1>w1bT0&becbzX?mA-dhgRf9Kt-k_YD6C9*F`5%bm^?e)fEpK11tKZ&W_kq0O+>- zDgZ@W)-RsSJE#xKNqK4fdqvtg9?o{ID5vJ_WHp_2;UZnaZ(z{_(HcI|4Z5LsO}~H6 zCVu#qe&}F>Kes1@+}Ko;P5A|pHu)ZtGR;aBkE4P7tiVxp9L5k^^v}dSvL=SC4+PQe z#EpkB@>Sphb=`UlV2r7lCtD7+p}rh1OAN-*V0#whC>m_KFTG5{G>$UnEORQ1A+wn- zex^yJe!NNpGP1OQO8y=MVw6P<{K7vZxx@64?zkP>QvLB`QXKw{__;;GxsZ%Bdba;I%cO+1P zhXS*q;`QT^E{+OU6Ic);6?|qY4m!3lM3&qU9y;d-jLXc;I`&Yp{zDdaRCSoC>oL5hS{gcPflSw{V;>c3Mqb0l2*Sv8+8&;d;|*l!ib4EWmDT#lf{hF9+a=(uN0sS3lM<(tY(^8OK<%vYwQMuu`;nq1v z^-Z51!)u&QMrQTYq?9dgv^aa_jXfWHI~j!-anjX^5jJO^;6TY zx$wYh5Z2m`3g#2Q`lY9gO!HfemuW$kd?n!P82bDpG9a zr{%*Z43IycSpvy)EV4=098S#9=2V%nwtN$3l*Vy*n(8j&V2> zd$!`)g)Ow zTH^;SISwZC-%yx{OM~e-H8_3X7!o-I*AL|3c$8^Fx`{)|jx;_5jt`CunNT8!;DsSP z9-krwsX&D@Ge9Ar9AY?|}xK@;AEk30j=ey;bEwOtnW`;&szX}U2 ze4z;O0O&LmTg2`Hij?o8QYbk0Zt*|pYi{@P>vA7%uDK@sD^nF7Or z&t8RIlef@ztpXEF$riW>61pSh_rDj`y5-eLhVA}?EE;>$7o?*wC`FM1PgcP_s zt1T*!?{F^wp#5A7JNi*Gx@B>1h7N1Q((YTZ#&iWb%0CHj3pG`@ee z_eJvf?t7XU71YcBdcDkqzn>wgl&W*MEz>_8SGFJEl5fs5z8;3o)5F6x<2U{>fA-R{ z`C4$-c+(tr>D*nzt-BytH@p;6_lM6e)w@~?-au0^S9AXNFqqPeBNi^geK*QW}9k8}m!vsKTIFlyc*IJRWB?tBi$XC?~c_KB8xzJNy zB}<7TpY~76<8#!>i)jXA8~3s80nRxb9T{W2Vsr^E?#?e$B(v6*as18$$F|quP(lEb ztSGjT0{4yWIv%7GI17e!d8y?T=PWSdZGVx+?Z9<7I+AuC@pgU^7Y~aNN%Hx7L`D^l zmEjB=^BTdBTZ&1H!f*q!YQ}=D1LLDI+#h=t$oiccx3jvecFVmjUA>#3K^G`ZX^(x? z*^6;a*OWr62pO?Y#H(VjJE?cbGpZTh;SeWRr)Qer>)I9vmZ(4Ho2P<4jW7D0K*x&= zmD3Yv;(C-BekH-Yvby>i)jbJvsuO(C3fg-eF?m`-9DId_%&2!JE{Y0Jw2?Ub4V!+L z%9kTXLuVuT2{((L6@DXrM;z%OK$?Aw{uHljrWo|b{5>0zFbB@|^U726Sk(iQpsH_N zQ9nQgchUydIR&Q1IbdYzn((9EX@;ct%i=#0Jx9yFWm6xhReJ7?IyL{CuBwuRfWaWH zjgBy`Ex(4>YG7y@-Drqjy|D}oOC7<-m(qvV*3G?uo)puQ2|#}w$YUX3lrEid5*lQ> zuy48o*q8Txy*1h6_l@j;{|6C2K_VBqW(DcKrkGf~?s!P|>CI^p;IZ=XW}^myUqG5i z7RRAn9(}B3dg&eEx)-Be-e%K16-#>25n94%r+vvtOTpqz=Tg%xG*>QJnv-J921{wIkdU65(=L?;A#85R_lZXLA)upBK9TSTd8^> z@!#0aj+^BZ!a*V_EWtDI__%$mw~ZFWfX7dJo1|F{Pd|Kso`V!FIVunDVo zO)Y(rIQy@&s8nG#6;Ypo%a_duDYE{t_RYO>6pu>wjr$*(XJ_ybN(gt~y!T_$hBo=Y zmbbOsEZd-dwH%D%<C=}b?J!FyyHuKd17-r_)exwQr}B=Twkh0Ze@jKEWd~B% zXinLu^BGkJ<{wH`q8q``Ya_shqbt*K?d?idQe2#E9l(`39@ce#(IE5HHwyUcJMCQ6 zU921qQ^G%ymv;_nIXHG)vCjQ1gnp+TbmZw>;#-*eTkRiv{qx&9&wdrYY#&P)-X)H+ z>G<_?^BKDd4~T$;D5k14(%9}&LJ{C9RYRld=&ke zaVF1E_wFpx+TBIu*mAVF0`e}_+OV^y{i?LW-(V4u|3=Al2ROvQ&uWIRz7w|LSNXR>c zb}~u30^C*A)pe@7>Tl~?uNxd&*6s;u>lHaooK2qIwR)vQebxhxY%Hc9i`FVCY%}~7 zd7_RNb-gPvYc+RkU2ApV4tvIV6pm}n%z)L74bYvlimhfL3Q>L5Y3@gZKXBY8YWG7avPMxg(=+R0$j=m*1DtJy+UixdjaIg_LAeKO{_&vqes!$vTd z*Qu+QT0QbBaMMGbO}%Y56hQ+Il%RxO5Gn;!(H%Z~m@P09%(GXq1{$u?yJ5m&o-GbM zh+u*Re2Qta^x-lsI|o)*2g|G1qImb4x!-w1$~Y3p<5%eGD5EXpLkydx+-q830`EGX zhI`1z1E|skVGTr4}?VbGb`J1gkaqo+ft?;+H=1F7qok@$%l>8?(>W-kUBz)Lx- zvA4HP$vu5=4if1e%PzmQwDFn7jzA2Tz|-yfXjRYYgN7TGl48HVeRa)$yZ2YmmNRes z<98pxI@Zli#_h~&U$t57>24Cwq()*Cn6`!^MqD>0!=4~B%ctHa{B%$vY3_{qYnRTbV~)IeFZQG z9-8Q5g)?q=5h_Zy**4hWfEtb39COJ{kG=8P5C1|)O8W70Ei`M1WtQ9K_SDjeYIPb$ zC8TDq$PCAye4Y!MX>m(g*78@k{nOei$5YB=*m#o2NM2??(WFvMIqeKWMTi_|DyUAK za#x&^l&eD3Xo=#XO zetekrr?hk^Aqz8k){vdbZe@I?Wp;i*-k$%E->*K0`Ehl09i?N~6YcLum-?oo8XP8) z>1L8LY`RH+!l7@^E^l<(GiEQbo;}>*u2x)iy8ErVBxl$Wzw+9gkdp7!I}MKBPFK*4 z^jY*p^!Mpo>HFwE&~GB2kY#5O+y%SAI@kzj!n5Fo@Vjs+ya^tFkHBY%w~4Qb0%B?V zDk(LsO&zJ}POU=H6jrYu>y3_dp?g);&`6?OBkpp)C%x!RAG-O$twzRnobo4rc9)YB zDjrr@YcDJGdpN|!woi!IjxO-n1eOeC2dTu*Y@ndj*T6O2h(&w}qP*}$ zin@4xiYaN^A#If?XGOpR7vi?cThDP&_8U)zz`58!B`5_MBP>N9phST@3WS_Gd3CSR z>|A6wqW?f@Q1cstf-flV4rx=a93r5d*P)%uiyTWT=_g+ervKO=I;0YzVZ-DbL(Bu? z0_x|Uom914A;i*TP^u%pBVPr(I8@%U_#uW^*KA?mPTlIr(O#!Jng zEr+p0l8wer=1+)H^C2rao|1k?QAfL*kGt8MvvxwPq`dU2vgY=9Moc4q_G_O>5xy7j zSyrn{sIztI;UjpcBZjLFdj}9OqiXR0 zJi7PySkg1S^YFB(0VxtI?7~m8`e*xRxR$NT8lrzeN|66E0>CUpSA%ycClW_GTetvB zk`Wb>FT#2fQO1tnTU)oj4c>|r^GAx?nLrGDt{m4LPqzd@;+c>4IBw<%jyTLNBP2~v ztWZiGv2bNc3HY8glFxB68S(lHjjjMkR6yNoDJik~N-nUxI78 z?H5gvBd_U+Yp=-&8kqvLh_?wMkd;WzMvkUbOyy&QK8(@6r0-MzDsMUr4wAT&Ir0F% zcQee7jQZJ>=!{0FkBL%xNG8OW@MMt8!`rHX?k^OGN@;{N!0V9KVjE(kj4@A^06SA2 z8WvAoQT8CuM~L1`%6tI3kf_U)3GpH4^f^}!>@ncv#kY8k+N{D%BaKKw$6wHG^%r>V zQc%8&Aj}JZw5-Q&#gV*3Q@M|#Y6gNl`^^}3#2n7I>pd6?;)Kd$U%yW+ng{b1IQx(M zTKuyM!k}i`{}ftZ7CtSba^}-}blbG=#mV0Ug*{K5l-GxjS>O`_7p2%5a3Y=rM!SB#BePvk6%pZSc65d$K1F%}9-U{VNB=C$7xa;~2JlqAXYsc+3LxH9 za}VeaEo~{c*xzR8nBZ>pliU;;uufpdS08P0WTS=Cr#$=t4ew`CcMFz>F!O7bk%{*1N5S|u+G_empx4JxocfWQ@l@WPD7YDx zPjKU=(KK#3@*~VnvKvMJB$}`lC>YiO`jF)L!yeMUYVdA<^Q5SVy7fvmxpkr}>4w=> z8_vP7=y+X*jtCyu?3xKbprpx0cR_N&JX^kE0?rNUuXuKUf2K_XP0wen3Wj3NaN`O? zWgtz9vm#Yp$gIKX;PXgSsHHzM^1Oq;YF6pD@4*9m$8I~1;Lxo8Z;NTYy%A)@7C}rn zQMqhqma&hyU;hlxbWDS}V1=@j{rSK^l&Uxxt}I~i%f#vH3lH=fE=WCM1&!t zBnu*MlKN9?=EHO~axTogE(?RSNUMsQL3i?EVcjdA13NBnz4RJHO`4?3Yvz~L`PfQI zzW@aO=?PS3P8d}?scK3}h%#^y$ok!?!z&hJ1`cnenDbb#(q(?5n9&g$3;2IB z*c)y3YI5Vd6SAACrO65_rcd@` z=i(U8PjKFvt4g29QvLG6)WH!MQ#y6h>DT3KRK)(ZRZWJR;+nPh%%J3(uEm7im-%yR zh2)m4e(;(5CEsoe$jYQ{@&&&^KE|4ni4#va=E&$%>WTLuK8?udUKgyJ$7{ARMq879 z>O~#X0Icu*@n-1l)}hlDs^b8~ZDsesEk4QW=E>TztvQ;q^+P~dM}GI^@U!MB=aVN@ zQwB$5OzjLzFKv{?p6J3#!z%U4uTC>n+_heuy?ON|nb+~26xr65x_xXs%&-pkB)=a<$YjZ%q8v+8xBBfIon zDsPrq^I?(L&byo(aCr|~uFrlO*Lm{XsdX!qkt+;L>6tDh%-Y(|Pnx8jBPRb*`SJsq zXX67jeGEwh|E0IkLOb~_=Tk7b3u~!;sS5-lYq8ECTKNzlz!d{nNa4`~7$kVqLx=(q zQ?%kkav?!{`HX$uSw25>G27eGyBqyK0Anbxb^T`UGeuu);4lI=dx-U$W zY2H6kst|tp94yfGZsD?!-LM?5M_L@-Sb5h3zkX!P0bwy59dfA(MQlgx>y%qTA(gmm z%8#Rt5wHPK%G=Oy~N+VFBlb&CR2g-y+jR%7XH+W3@WlvPqO zs>bj7gyv(~)Mlie)#B7L5y-?$0%lTX7m@wEAhvJ2*twnY%Q>9#0)#!C&zKOLs;k*c z45pn`fxVt13<8AkCITz^c~YNA+J5u;%p4v7pAQNUh9SX(g}&yH_`7ip$-cXSf_wSK zh^O(Z$?Fh(ZM_T$#=RU;OnP}}VcN?_8?#;k zGR%9`(7~ct9bGJYHPFMVSBO5=zc_1RfDN{7npu5zYofnV#W(fYBl9cuRs1FgJfn&Z zj6OQtGJFK6p@kFS(iN26SsJLr5F&$M!0Er9Gwq8)|;cR&QX7(;pvZ{qtn@*Nl|p~@0+oSl+eyD(t3 zan)%8w4_5Wgs8jLTNB!2)M}vIz!eIR(Gan3_*RnuVmCsxGW199dfE2Ir?*Q9P9uTo zO{;|O;C==t+uQ+xrg6nG1L`Z9qBT0A`^>%=jFA|RshEw0SdO*WjGZ(0<0wuC7rRs* zv6PM|o=CW{kO<~-kQ!ESk$U2-m=+S4K?Jke#vaPz;<^p#a`iTf$D>U!z%UaGny%Q@(ogVeZU9_PhySrdHO$_gV3=e1jX zicpJ|>Kn?b@f#iudu$PxooqfbZ|IDX1Kr)J`@cl8-zNK>wz+wWwi8;`Z%LsS zJ2^}a`FzZ`6z~r>!>&8~uzg)DX+XhS<)eS7mBa&B1jZjG^t{;(pGG_bd_Hbxk@VG zq>3sytGa3~YN&;)mbH*dU$%s|R#(DD>pJ6~6Rkac?be^Wv@Q4jzVEX8aX)tX4L0bC zTi!}n-f+XNKDxtQbH{d~>+bCGZoCV-(9L&kzjVu8-}P?0Tf5cmcV~CH;~wvEcjBqG z(rjfnJ4DX|6j*OMdZ`OAKw7)$>{wfIwyLp`P13AE%JODJ-2q$Uhf{Yks=dqTUBwb4 z0e=x8jlG3F1H$D@LEO)!RnigoyYb)Mbm&s5DR6ROD|Ab2F?R@-I}{Ao0Sh)efQuN% z7ZOPNdApI?OnPmZ4dhnz1Z*B5tlsEWbCHE^izWzpu8Z}1jt8qXVFpjL~cv*UX z!QWpCc=CGcG!-<3+8T64nmRShX1&nT*+kpRSAQLG!7xTQ-d3VlkNb-x|CF53K?i-b za|>*qjMqyeZERh$-_*GD{*Ax?kT+2#8zgp!aj_&zVEuEWpES* z3EFw>rrdPffGkaRaF-It)}h@K?fn28FhlKD?pW9J6oITdF`>9_b-gYPfeZt@4Df1> zH~D?XN9BhN6jhX(ct9vTcGr?GHGh3MfW0 zp?f}vT%mr4AZ38Q*6DkLmgQT4H8gA_74@nkY8|uP@sm$T^GQ&*-SyDE)a;Myi~EG0fXplLXMkUYDhKTsKBhyxG7gfR>deTtF-FAwNr-7eOFvfw-_>;2bm9E z;9{ZjrsNl47TYXwi6nvQxXCgMB6HM$3qVAS98jFsDXC*_KVe?2XPEX}c(<3w> zjJ1l>k9ZPF=!K$0avPI6zIVH!`$oh+-*zW;))wrR6h=?sO_rV$$8XoucDi$=2NBS(Yn*xd zL1;EC2U|!k0u{Smx9ml4D!*CupVdkQv7zL0jV^-7gR4NUD2rEjkYXowO-}P7&uyWz zB3s3_q*Y1xi|hEMkbYUL>G>x-eNzySwFSJ z4{y#dZr)FB!7p#o4=(kS3|r^gIajFbu&JVnah8c(WpIo^*n_BH?+tkLewn{tR=aBf zLYtuQd{YN-Umm%3-6PlGDY(sXdLLJC2 zSI`cW6PB~h)ijPq2f(KWg1Xt*dgjZet$2P4wGMiey>>ns-=wN-O>iTYE3s?a zhTIO6#M=F@pcmu&1!wjM4`I%;b$kPG0mZI{`Mzuk=tI~sl z0@}#w7Mc@LlU;8v&=HTp6GG{Zf#A^$qg+|L6c#T?bXUr%**^B;K}rLBT)56pihY4J zmda;pDeXH|b!02&T3MviKCEdRaMN*&w^M1)a(mdk=`ktMGPiJ%Txckdy8%=isA?o3 zS+hhfMnFxdWF*CNxgF|Zw=m&eYBcmQ)Ir@?*j8-CrxVjju`xGwKCf_1h_|z{TUaP0 zl2i|L9GVoW*|y9f>WAXOn22n1dju)i+aX>76YPz`z7gq)M%<2uZcw-(-enck(`PQe?Xw}j@v!|A=lTS|5n)ywer4yFB2AzQbe zfuQzm`02nkG!~b*++!;FQYWq7iB?BW&9-}*y|e8n+%Z%j=}!F)X_ra2tiDu#mtF6w zH{bCOdmy?;yL#*&!FZFz-$Kv{s_KUC(IRl41~8ecXqg9%vz;8m*LNi6x?SMGuDL@K zR_T5(X+HQ=v@6tYKu{Wc-HU8+J+1ca7waweV0TOa{g21L0cAR%VE#uU7T$p(CM6Gz zZ0YLw#kXzSnX#JEj_r(0XQ3EcJp(39OD0!%W@yjIhIy=193}YS5LS*&4?{Cm7-e!E zSXZC0${VySD|;BrA9t;2utO+LcgsBt#~*{-{O|sH7zUXeu2TaKJoPlIH}+f@fY1Y7 zt|s6g6_zW}miuhSsgWx;rXn>l05EwHx;@EW?C(_^$SM2Wn7CUFA>exz4z1&X9k~${ za!%SyWQBAj#9IA5d6jRNfLqa;f0S*8A%kWb3VdDwh@u4ML=s#<)Uc9L7Aet+U8>;C zdP^@~YZvBmgjZIm`6F<}YG=Z1+QrAkA^~B+&+YO8sWfrrP3X-1%BwV=<3!3v;FD2R ziz+f}$e{z%aZ7aTQ(vk&7m#kXW1YgNUd9kRZoa3o1r4lmkch*iqlo%7V_(a{Tn#A; z4DC>$8(R8I9})h!lBAiK7)(Y^!&=J13@mFqv~JtiGzmJH{c}z?|By-PV9DNS_{h2U z8B`A5!V;!iMZy1Jebh10YhZbx3kd@pl4K~dl zHE#Me5_WdCacO5u-*?zmuSJ{YWE(ST)@j_NDZ3#eu;BYv%u5YQIoxVlS)sw?*G+A}b7!x+YGCksT zk#5&rn91QFJUwVWtuZMllm$Il%g@Va1ws3IGm7j^iQ)zHlpf4k;c|KAMS9g=EG0t> z^Re~Xh)Q=6^HwC9u>uvy(3|R`@jUY`x<(-gr9_{v3Vb3SJ%Qk>TG5!ad|p}DRSJRw zA>$`!({a_K0x@p&(lHU9IS*N|kQzpFyn>4zYOQCa`0#b>-}^3lDPkNHOG8CIiJ(YR zi}Qj`X>m}m@VkhP7l$cnv`klNthmLKrS$%(W3f<_%T~TzL}K{knaNA^5nTTOXi#Vd z&#^~IdjqCo7b@T%u3$63IJElQ77!H_tAbQNH^8aE?P|k)JwWqtOxG{mNEQ<=GeWP9 z08|x<2n}4ZIyT&PC25Ba1yH@-H|3OM;57~XR80>R-dYA#UB4MS$U;;)L@b;ofv*VT z+=i7Pm;I#n<{%_O-6B+JTAao&SkV9d4&ZXyog+N$;=qE^w627;eqYM zFFf!9+C?(7JfkRrH%;d3iA5u{dt(iKD=!9AaeoG1!r3-Y_PmCtSMXp73?lW1`fT;k zK_jyACe?Qo8w(5^Nwj=N17T}7Wd$wMJdBC!Md|{|R_J~M#~K5_I!zc|7ZkWUb#;e1 z2WY7pj+U7<#7t9fw~Q5*LQ}!~#tWDE(MXgY3m?yu=@1LGaRpC;2;AUSheted5Z63Dyl-*v6sK>CsQMi|V-6p1Yq<>+BH&^ap z$-v^80U8~lX{(RINE;V0yH3Av-(Ov4UU}voaKIJ-I9I3IvSdpH3QMjvO`K~c=q7I6 zq_XdexkA?++j_c|F0}xEZdOVYm@$ZA$DGg9o~EwGZ?wClBc!x^)`}ZXCh;EDKg)3DN3&wsEbXLR>+n+WqL84rWLZY(u$RH z2$bR^l6SC}0Vwb880up3sEu*w$w~H*a?qYq!(4ihFtG_@WLb}5#)+z+$!Z%Cw=xsj zfsN7(zf~(PemKAiy56>yR#kSO%iK9^1jdRQ#Q_2!=#Z;+8jg%lV20#gUxY+BT| zX_1LWMsGfx*?D4UlIEnBwAb?kbkQ>6r&o5e2y|y0O>JxFy5fxUq)h1=s_lxdh>^9E z@Mg>KB5$w~IqOPPT8eGsx*2*s@h;h7fCDE}6QiUHnPgUD9KFqtY-Ie2tDn~xt{r0z zx2%vsV<6NV4P94LRig&Q*~G#c86WIl43B7Pj|Ya)B(UVrsS3s?J8gHi$T*6XJH=4N zP|J0)bCsQ3GCVR0XcIdMHcA69_j32&!hTT7?Eh~CCmEWa>sT3ko)6Sb!2}qF95byb zy{arf%TTBoxJEf>18p5q^on_W~9-rsNj!*dBrGlx~5m>qhGX7*^BUdaHJikp=zk1lhT!uu=j}tz7PXb z+;=mxefpR(rsn_cc=HBcUzgC%z#Cf-7itx~-@lJq})(EXn z9$f{)3aDALx)7o;%{;QpjUd-%x^~r-dcq#JUz%SLzFitrI10ryV)n*gI@Xf&WivYV zV;HqsV`9U$R(^z8uGugl;!5Btzzb6cz7hxp5}rACXY5)hm(J`_0x&QueSf1+dchu* zl*mID%|1k{Z-=pLZn@k+{Y+H;f5vHwhbwxi$E}hYOXb6pK=!w43W+|Hz$hcT(!PHW0g zvO!4jX|a#`OY$dJJWo&vu{;keFjJ9|4bf>49c9=^0E)#K!M0QuP1~ngZac>Y!~Jw& zi7KPOABNw^Bh#n}5`%}xW1SRqTw&zIq0#ntOavARW^@6)(oHiDFNUV&g>mUpgW9z- z=em@tp^y0rIXpQPl{SIVp(%r?wUlc2&;(j2W=H=NNanOHl&*o$jT821yVPj_D8Qn4_=<@ zVDsRrg?YHrHo?}4DG%U3EZ5tGUwu*eO8b-r->1Vit;bqeL8$sDo2Z5w8ubx~6c#cNH}6zg3~ zTx-n^9%0)}pZWWT>M?7Dsc2?#H_Pcs@q9IBHdDd$JQejVR3YsoqZ5t|bk=TWr?p;U zsI;`tR*Lr3x1Ulkk1#%+GA}UW^$rw8FB9B_YH{iXD6axvGF1u-Lzz6qHS`LV72oNS zca4%XoAvO5gNiSC;lWs&4nBBF3+m{!E?0KzlKizB%31%`r!_K)@{a`NR78NL%~V2? zk>%HGko27D!Scm?aHfgcW;*HwRwT4mUov5GRTHNl+NPb-m&HIVGXq>V zl2W?Dk*ARnIU(Z;G>mjCA5jpVpk5fTg}|35C}KCe_8Kuk4N6Sn3u_Z0hUll>fT>!H zlodUK(uaNc_nOFvo@4%+2lFr=FQG+mOqDJ z>pe#n=rcd8Mb134P6OrwS`5a>GoQ{F%3BxElzZAJ>%^ubKbu58HY4e6#tO8VDadB7 z;1WbgA!iy2Whx_VQiX=J_ikAfVG}FLCQ^(|PZpbjtRZ1EER7;;Ihm}(Rag-dmH$E%Va_zB5iIKWwW+uo6<}+4@f=I~>#Mf_Q8sQ^l#J7oq^ zZmL#;5}N+YZ?%4(ynv4^!rSy#qbZ-ZDHjkC!Nn~k%@SX+&^%|zQxvcqIM zO|i>NyUnu4RC|{K+2??42UUhus;yCDt-8(YH4D+ARh%{_ggWW02iFfa(*A}ZK9Cr~LlYl~K_oy_IMS9BBbJmLN74sKQG( zs)_4nO?lm}6%^j7r4n3?;TWJn@ zPfbU~4prK@BcvW+1uDjwOE-tymYYr8=7nr2cE-edVN=;xHWOPDvL)SCEnBw=PSl%o zE$?8+03dE>#I}PW8&3rgH$zFlP*5*dOzM#HeDFDja!8)L7nnW+wr6d-vqr8jgynYe zSWYa#OTqGfby^u~%v!WAZRfY~?eWguC&fgfq(X!$sq(6#T56(um8KqApk>O^Ms3$C z%GCwEtB>`qi5u0Dti%TGsY8DHgD5_zC};Vcuk&EIJ@n&C&vvGIhkDezu4*)*z-`L( zF+&}Q9nMdE&~Qn?I;)iFx?y~z7^Cpf1XIkg#}OAog^QOcNs2U?ij3lemp0cDCCZemu*`BR zthCB%Ypk`7zW*rMXp=3r+Ge{QcG_jPJ@z@MO0^nw>NRT7s$GXphaGjyaVK1G(Ph_M zchfDm-SNm{PdxR^3$MNL)_Wg)@y!pv{qfI#K8X+`jx)7kwQjxel+>I~*ZqH`@|N=U@~-mk@|`T+%F^q|t(wrZ3{o&NyJQZ%P^SzRY0Wiq z&&$3B9hD2J91yN!BNd6(Kd7Rx)-A!dI0}zB|)APe&l}PI@V8Wak zIploo0tgvH4wC0aDXf|hdpE`3?4{Wdt~Iub+RF8_9kzZ% zjsoWJ@wTS^cy|INEY@U!{3;BjU^aK61GEq=LK)QcCfZ?vB2}5?Pqb6Cwik4}3p$3H z19nAe_=3;EDl>_+GHTI7{1R1ZY7Td}J7x(iVsNp3KF-ftdEXjXGCPvvDmR!CQuld5oT#Hvil8DVxDsf{39^ObiDE%N+^^Ott_Uj<{FK zRMr~AYGZ$5=a|p5*iJqHD+sy>rLoO>CZ4&TrnIUOQZ{(UxMb{igY{lOQKY zA@qA=eR2UK?54~#5^vc>BkibYM}Xb7?xk3-5WIVV+g32sDMKRj9L{&L!0Gz-H???X z|7s_IUAEdCA7Jn_Tah3po1G&JYe!mZ61=X1;sTCP-I%2})xB%#FiX+UcnM`2e;7Em zpUiF_uF!@97kHKo<$2)L!!LF}it43)ZxKT}^K|E%Es$o0w9dO`IXH}USi&YLV&FN^ zuj$6{FRTC5(gT9!ehm?c12!N#0;)2rTwD7tBT0k*rCTm|PfW}P{HDxV&9 zP=+?S4!dK#F};qMO=k_cnkPA5Zh?pEOKnPFGa`_yFm}Rolqzdxu}`{+j5qr+AV2{K z$q$&b5M&)0nuLQQ}A)+}GNw>i|Y(cL3)Qvfz~8MH_K zBa4702U1&_(jU8+B%LV@IA9#Ff;?=I3M5`6(L1_50ACA1Wa}3|dIIc-jJ>rCZBQ_! z)YffQ%}TL5Ym@vSq%Jtayf9}vi=$jOs0!Q(VRgMUtx_s}8=cTH>|#?$vos0l&Qids z3mUl~n66?5ZL~#FyyyZ_%xawO^Z2B2UxCAXMSiw0(pDnXFio!z)}R=_;duE* z2=S<(xz30y%<+u3{dM8A`@9) zCu>TDyp`e12c-1(@C?$Fj5Hb10x;<_AVyVoS7C0qN77qo=qJ`6a{4J3*9IjJi6iYC z*>Omyk((SXXf5xf>K7QKRKHrOY4S05#=b&GuQY~GT3JthWXrX){Oo$a8OqwLoMhwTZ&}~`##J?+Oo6VZ)W|;mpF<1QV*%6x!%R6e26<}sVz7Kt4_aDK-R4lHYiz3Ka#~i}+SD$30r9*< zZW6m%tCI7pcX_HeYppKID9+Y}s)kTNS);)|zD0@vpr6wYm`}040Hk1{j^%bomw=*l z%M{I)&Fw}@nzeG7gA8T0YR=#xT@77;2XCgfa`R(QjV;vD!fMr~v@6Z~<6O|urfI>R z$aE;EF{mk|B`BinCF`SknbDR)PC{18O>S=W=A||d){yjhGCn&%qvfj+Hd#}S)*Mlj z^p z8PXV_1&ctG_Jnk2prkZZW~M>s1<6eTUaT{kInz?O=x|paosTERa{vSbiDq)R^4Qd> z)g)Bi$JvM$!m}0q9_|)5}i-Xqvp~3Q_egYn7==jH&Lgr z01|>UfJOScExOGEcsqx=n+T0^Tt`hIAq7WPYrWO0Awn#n_%VP9VvI|B_lV3O9FgGp zb=?$=)MaU&h&VTd6=@Z_qz1Ou>mup`r&wX*J&vbsh~Hf%LSsALhnIea>UH215{_vm zH;;XTmsxkCjzvjJn`PpE;Ro6I#4bV+Jb*A3SDzbRZ0*d zo-hci7qb)iWaETB3#Dd72ym1zKo@Fg3=%YZuA$xH!lp3>p~g3)jvY>_$|qw)9ty%c z?401JRt#uBV_^B`30kC38xWfn^>GkR@(Rit0=RXazzvt-zMOA|Rbu=u>}$C9L-k;h zh#q`h1%tH~+1HOJWTj7Oa{{vtIV{9{A>Wo7Y57uA&}MZ_Su7ZVjV|+ojaFF*5abgR zYaF6M?ZTiHnS9IOhHxT?H&fdWpjDYx(~4$poK0(b+B-fW3Z_U3YRWyoHL*?mt8~EQ z)l04R`a1I?V2vhe)G4K51ZdNs$2D}F1DBFqekmg5v^6PuQ;c31Ro62YxyU7ZW3=N(IhW%BH_|du-pGtt%Zx37CPUR&{%pNi^qhDQ}=g-fA|4KB+O)Dzkh7zukNeRss zP!KdjvpPC>i6TJEQ&q3UCd^o3+mlfc5K4^Ks!jzk4F*gP+!iX!`GJ9%;wx>$ARe ze5?DPkN~=+)D>h72dVK3%@^WePz9oXi^jaeJ zCd}dKLD7tYJ)EG zHuP$wXC_3XjD2U=`q?w>gn4~w>986~BCa~36bDNM0D?0o&hR26iae(u@TMZud*4>I zw#CI9imEv?<=fQ|eF(RcD_>YI$^uuHe*1zNMj5YV1H1O65?!BZwUWeBpZnOv@ub}= zkkxmod>l0>QQxU&$zqWtq~2IE<4`^whGhp;-@h}e8*8WP0>&%Uoi%U#J z2R!0!T~sG#v<2O7qpc3^tNbX95d*BdZM+c*vSqzV%b&$SZ4?zmaAL%NjEwAb+mh1hg>qeQBa zVT@(I2^Nz0kcl~xF7jDs-TUPB%~#yugGGMrqO=-elH8Vx`b!aeewfSJ7rRcwl!@sd zzL%KR>a8T(WR(UJ`A{Ml@fd4+F9vQ_G)M1e-&6qluXkq zNVy6)WWUY%g)~pObi9{h4 zYX69g$YYYga$CX1R2dKS%*&Qaf2%1f4mA3-|EF6u3L`<-0xB6)x%YLb4j2NNJ61vU zfW11i4B|Z!cMtd?zovpfQliU(+w* zG`z-PSWg@f|9pOA=)qk|+YK|g2yG*R>x!M%j@|%Bwr4bh(%PFvO`BjcEyH{uii1lT zz(kx0=&}Vew=*yH(zGOuyh@tDvGD{>{t=Z8_mHNrutp_@Xd=K1!_W)IaSc|kJ${oM zKKtQ>Nz5V`IU3+<|#Y zP-(!HsZ*%8cB^T(R9Wc_uXv__eDnESL-Q|VXL#Nkj4nH*OOY;L5Xiwplr)nO`^%yW z=a`<`B@-JUd?&bA?%oa{!@fG}VkyH;sVPdVEyMvqu5J*99pKJVA}!VbAnOM7yFS!rS? zGz}0$74)+Ck%J8{HBmK@3BAz?uM@GkeGksO((M{1j4iZb)h4GL@= zIzd3?Fkq*J-1)7{6t`5XG?7*<88@%BP1N*I@9U-LzNnvuqIa{3!Q$E@g(xP<&LAn} za(U2UvzO-vjY?*D^~yGw*P;T)lj>!=Y%yrf@tS@^GnLe1c~VGR?2cW)KHN6zX6F)PGEh+rBNF)}N5 z7*g`_;W+N`0$3ppQ#CA5hd|65-+qPS74#J80`App1(T+!1X@GY6KPg?T&qrIBw&}h zqWXy7a%D*+I1))Rz$#>QPqVwJGil>h{ea#~%=l$>;X&5qp@ha*(;cUx{Q>pOS&+SC zXp-nj9;iVnp@GXjVDOqNiR;at=qoO-v$T@qX}vh^g~vgs7o6pSopTJ^UfQza*(9w2 z(s_usA+VleRgI`}t7dpd41p@0AE9%Y&<@tJMar(wwZSlsq9wLUE=4P&X(e&q=uRAw z?r)wImw_8~^fcWnuxhYU6omvS(Y38%R9e)KrE1p@|8ijYiNaXAP<&dzr*;UN`|vWM zIXkSwEW;U;Y!h`D8Bl_FN4#f2N?}enI2i?^DStt(&m;Y%}N}kedCd3)aq{bKGZPC8;lALIafJ~`MLxxc5B%D}#q#xUQ_CBM%ha@}tBI#ugd!FT zi#X3>P;X3GU%Y@{8RVzJUItt78|es&#=O(#yqKr7tlKN< zY1Cv=_+~Odz$CZ1UIlW7u_4fGGh-kZ1~>lTT^-47L*$J;dLDcA8YoX1?_J*e!@bd= zFXTD!YKJgxOk8g%<_1@~H%i}kOSDRW3Irb9`4S!oHO7E>@L&}%fXTD7hQtJ$UkK-r zi;Bq2+x0kFH=l~blYLVfRh)r9hQ>jD zGSo0K&>S2}lnzdVwb2mK>(iNJc5{PsI$aZ1sY&@#l7V>^i)HM+gS)S=&`_!XPb@u> z6R%Hnp0dFn8)JnZ))PE2!v}#SMD;@0bTGh>8z#x!%_oRHpRP(;k*q3BC{0CqlFzA^ z+5wTlvV)sN%hB_~kD-voPR7V;n8tXP%J(>CEXF)E3?;srZC-Pia51NqS@ghe-QZl@ zWAD2*L&>ntJDC_{RX?vt~R;;fT za-+21WMiGi(42YG%O7=~)5TP>R=Br8Q84=ak@fFQ2JPPH`O(ypu!^JDN7%W9+NWOD zxd?1Hqh!|#H>ogGVWH4Jr6~lB#lCZ^VgnsAN)|9zQJts{-1?=jZ0*(iwA5ld&o8NB z6g&Mvm0Wu7EHB{lh<9lp{*Nc`9dmW>L1dI1d+oUXxm*5tv_=aHiy3eE+DifU6z@G+ zSiIBtZt2_Ukl6{l8wmxlNAS)A?g|cLwck>DI0d8W#{*5TzJG7@O$2i_Vj<*N!2(5s z;H{1nZM0@XwYsaueGgsr*l@!LytSKNgy430GWWIfNrTJ9Vpb)U6WKnb?2|WXZwJz`sj<4UwzZ_-S^2W1TTFJNemQq5=$i{&=fwCiL^m#*-zqaJh2O}iT+89kypvATsFYf190z*m>fKqYJ@3ul+g(h z34w8e#U@W?-PdQ`N2SxLL-i{L&;Sik01eQ<9*e_^OGrwIp@B1S2510Kz!?BE8rb8p z04FXf1(<9O{2NKOJF1yUh}X2r0vb+dD4vY0F;ivzhDjslV+$&u7CAIal%wZPqn zBy^@wpa_b7^k?hgKfe`G(mZ}ttpp5PyYH?ZUz$!o3UWquT+38UT+GbPn*04|Ik+e( z>Kn-FXgNeYe!BYlAT7LnB2>}X#mCZAT?QdqR`>6bsqWk(Z)|K#L}Q=`ilB%u&6DPF zd0d`DKE0|>50c=-liRIcRcibVkSh^5&mGun`wY4MEScViE z)1h&BuN~tje>R)bS_H1R^9Ip5gF*z^_U&XslOmHbCdDSxP38`;_!rA@6>h+7J$rzS z*L^!i3vd{50&xy;1#t`U0P*Yx-{2?w@ihN;j+lc_R0Bt7rDp}4FUCISOC>+t0_3;= zGUE-%PdHFoGEiNwKPtW#PxYTAI|4xHq>%BF;a~T&WhAu`3MUwVgjScF$Tq$j=3`y zk631T1F-Evshvq+U|?WiU>X#_U_VIqbHci)D{Rh|>`I^6Xt*T&ov3Aq?T2IIUZ9f| z!2RLpz25mg2*=51;rR%rL}5YP52GHrXh%_pMkJeGbj$*+9!^?Ql~HUhXPhXG;$1!_ z&sE?eTt&o$Qj`=HAY&Ee!Ap3RIBT`h73(xKgMRoZpXOJ<1^2gsI6}6SpyANNx7hNE z^K{qHUWqMAUg*y4@6UG#DoJYf=kiQnKn zzTm%ntnj^uf8oFU%~uN>ghPBc7w57+!_7R3`T31hF{@aKIcE(rZ(H` z3_^Gv;GL+*Z`r;ptW=oEy~M%Tf$nLSnhIbZsOxswCUgaVI0@v>2Nj%N0qd;37SdsW zprqBBgSqOU3xuK@KVg^|ca652AWH+REO3^wadAHD(duF_yE#XZ9=s&p;#?LF^IGfk z5vSRa6~Kqz<`13E-R?yNP+I4hu@w*DOLHJDCVS2(t@9{Kd@rZT$C3|(BXaWUQN@sS zKU7n_UF*pS(puw2aE173&KB);iTCmwd@>kzW$Z3^;tO++>*e1BUb$Tt?xdGj0E}l(e^79hX za;@k7N&5VvR2cd5*i}*#l*pthVO?JH8#PA;zu+75jRa^ujl& zd8yp|n(24P;XyAS=X`;X`6l5(yD4-9c>hdJQvAz8KNpot4tD9|$t=xh;VPBFjfkOp zG?eVvDC9H+JTAMQv*HS)Z@#?kk=MW3#%Om1_E`KV9nB+- z#JHl_2+i^(I9x+t2$)H0QRqE)DBkNR;x9Zs+>!62M^awB;VLu^&&$@Nqg={e)dUSs z=5r}sD5Oa|)(}pzY#mwRWG@0^!Ze_9W`0R3XB%IT^5*mo{P3{}uADYGdqZbGR%N{9 z#LW3H;9ef8n`|n4aYw$+oh+=KW`RfKY17FsWJRC7?uIg2_Xc1z>5#}ia(*d7hQbb* zf!kd`pJM6@CzpG}ZKyo> z#m!B#`+Kq%YJA~$_#LnFnPOJQn!AdNll_{~(ZhWKb{UE0u36R87}|Tz<_tPl%*E{V zLFJXrJAIse?o~b$8lAy_2+&0f)7eiQRTR--#~{-2a;O}tlA7ztr4AR)(tVUUdcbSc za;kJSYMATBQf|JXH8k#UXssE?kGA&3oK1lkI{yqpoDpyTgmR|J%hYp)e_@Lo{zU6( zh;e3GYKmGaWciTuOVe0$}FTO1B`H*2qFh-7wKw_oqZI}sWE49up zH9DMe!xJC;Z9C~EN|S#P*~(s=#pj7HJ@#}bh&UPgC^XR=W!BrRR;ROWdg`Np?I69x zxfM`k3FUy!iRp2`onY}Y^;M+UT;(>{qfVD|Zh7XD|Lr9GB)O+As>E_Zr_1y>;z5W6 zS^61nl6fj@v{${u&b#fo&wLUkgQR&BSaeC{fzG7qal(^OiLw1m?Sy+8)=FKmfLKk!PUMrdedA ztqy8-+-3K@_Psnw$s|QS8M2mE5$LR)9tFNcN|kSrF{WE=m2D1bal#c3yz!#~Y2}O<@OrDQ6Lf}U{s)@0Xmvsq6IeE;GzQ*UEt_}k3OO? zfDpsJ3#c|oyk>r*3|QdC+nC$SU1|5Qg{MVN@N&S5w~{ouA#c?{^UTTut>^&zwR~>j zJdd^Eaq-wVX3B7p6&%*~J)7FZPv-wbfon3oW(W zN~^84(Prf;#twaqIm~gKamSnU1QSj)$)uCbW%4Pe?0H&xMrLkaenDYTaY<=elL0J< zX)sMDB0frH&StM{bGKxhws{9uzKSi_x~<=ut=)!g+`%o{{x-F_Ep2Vvs@vX<9p2Ph z*1C?(?Z_6kxYd4sqR<#D4o@J4fFOth(I5uI zf_mfWIwtGf{yNqI+ks^-XKFD!r&(aQAwU2KK?os63`2$t4t@0D;e-M{ z0fZ1zsECviM$%@CF?1+bPM2kt(NhKLRnls}S{oRC4~m(ZJuGy2kSp@wtXX~O+4<|g z90Ex25r%l`Hu&q>5TI!LkqMH20fI9YCbY;*!m}19I$H_i%PU`^rfhL?4Yf*%+ILD; zD=U%H+Lq~6f0g=mqp`6An{Dps*yfGZEtx-#Q&})>^R#ICtkPoD)y#@njBmusIkXz9 za5!rvv*kEl{4gGK#w9o0^TaD3eD}8;sgs0s<0eX;Chzox7Wiv-bE|A# z%PVhF2WskA?S?T)X*oq@D=;CGFxi|YK(fXd*;PD~l65!2G1KlDW;(s&m|i~)0W$+v zFf()qGqa?aSq%rK^AVUXL}I!ah3Qf>rpqyyUS%=8&Stt2i|J|{rfcz-t|wr+k%;Nm za$vf>JecmR0H(Vug6ZB$U?L_2Gq-tRHg8LDHh+s(f~j~bakgwLwhCvAASGOiisqI2a!<0TV zri@vTGBIV%iYa?BNI6KknDQ2jnd8)$In5p63y$dqMm_^~~K z0DefYBw1gyTJp>Ah5#u(VqF-fV{|hF3ysbsEo!QrWzeaiTW}!qe=C?tAANosdSWjZ z01P3fE7Q(XwrwA>9#g}hvq%SQz$(*rF6@XyUzqhQN5;9vYe;c(h!s{pQtJr6)cNj9 zY}uA?=&Dz<+SRRoU#ww`Yub0K#o%IC1+8acal4Xe>31}fgVC7Q;4#LW!&q}1drqtn z@VhSJ?t*RF%8gyi7l^+Ho4*BHxVE*gW8be1gGZS?uqij@rakh{O{|OmCIon{Cxw5` z7e|ZhxOEhF1UVt)+==3`9vMYfWG#PeA-B!DK*(4s8DesBGO1*^!1QSu8}Zse_Zjgt z?@DaUeLbNa%}-c?E@C?w&1D=)j9A`==E8Oma#7+s%c4AyL1_u?L}?{2a;?ckX(p7XbW~Bz_K>-nUes8Dyw9#*M=_4 zi5=k{cDXrofcMi~*To{U4V*r~5d9-l3fkLQOAsUr3{5yVpiD&|MV3JCTeGnG3i*t+ zmfJ0n>)V>y+oE-IwG~^$^Gw)ZwvTPuW`5CQLgI(?#;DgV5o^#(Ff); z7nF6AvT*Lk-MdeVVJKEfpmN4JrXGwmn?Yt>DN-!AT&%QGY_(PF)f~4u%Rz`*Ii&ZaQe7!>G5PfiAdnz}g*2%XDU<+x0ndlG!Bv5nrh&{?ZK+sMib|8Kp%&>@utpt< z9}^E?Br`_lY9Zq|bu&SG>J4hb-G<+Jg?bGdHEAC0pQaowy+ho}O0qZ|20zV!zycK- zoI^zNx=F=DJH|SO5-8SdB$?NlmpIb3@8L>QLo}3tt))%IcO|m|BZA9X%Fqn=T-Ke_ zp9!wH$1hV%tN}#2hLKXu_y1j%FI~V0WZPKq#1GyEN{8GggbP8-OVQ zy0~e;g9G>hU`b0+^*^hiZh%85c>cT0cGG3kMq-rs5G+^kqU_)Iy=t1;>elx>xyj__ zGrwi5VJCNdqf_A2IT0s2(xaToyRY<`cIlq7)FGB^`o|bfahVe)&bj6h9_Kk;+hf2-d}<;9wW@Lge8brQ^X$f+y6+CoHRAI(XH{q29DVMh`Rf5>pOHu8EO(k76}<- zo=Y6DWBw6iJo}M{ImQG0DT6=D6Jcdcwk0AlNlHp8GW_9kj=^s;E%85cU0eTc!;vE3 z_D{e_{{Q%YJ?!az{2qVz*#B|h(Qo>xN4K6&e4YG4?MOg=0z5wV<7dP#(r<6^(IL5m zm1hWw74$8fdcdCMq`9xP+?gwO^eBY8}$(s5YItTzA1G zmpkvZ&)#|Or;q*Td%H=EG)PGLL1aiyH4FB!r-l>tTxp`9nKKQPv~Z)9567rz=gDEd z9M_!=L7W!ANg>V(c1D=f8|88M2$ZkEYTn! zeEI0Hix;O8p&USB)C5R^h671aXCN6G3M5C(fE1&~OUg=xN&%@+Js=Gl38Y1tfOIH3 zkRD|PGW@Bi+P!i`D!+3Flm*CxG6Q+hcpx7d2joW+fC4BNP;k_ID74g$U)MopfV!w5 zP!E*_>Z7(m1Jnp;_^+hEKD}R)(0x!jpf4&0^h4!={-{2%5E~3E8s%IT*AmnPSc-Z8 z%TPC9Icfl`Ky84PC>5{@wE$M5#K0O<5m<*R0P9gpU;|1GY(x`*O{3Av=Gubw0JfrJ zz;@Ic*nx@wJ5dH;7uFrvjgkO+MwOPmwIB5X4yfF~LD{FcE}bLjJW&_8c9FPClwBrm zoTdr>P4aTZRlZ$g>ADCvOo{5Iz;4NET2Z&nkBPGl-AM13tOE0X~2Il6RM{w-3O#{Oa%U5&TeNfuHiDf1xmd-=o0gPyI!~0RK=- z;6Dlg@U3DukQ_*`1!RyA$bq#WKS%-O4_iS2kQyiuc7TE)9Z)dr28BR+pitNY3WGF2 z;jj}F0U3ZI!Cp{g$Ose#_JN{8E}&>|926Zg1I2&?pqP*yC>9(6#fIEKao_|fE@T0U z2M0m%p#V?q^E5L5>hhG(E6Pyam3~T!71=WDRP)%q9ss(?b+RzSE2mV2Ir6Z`G(Dk7Mr~&u@)DYT(8o__4v2+DB z5x;IKT|mvm>E_ZI)IzLV${Lp`Ay(ND4k@29u;&wk72kI{gdIC%Y&4b#Y z=a3)h1)K)GhUTC*@E!UKNrC>sCeVLq3G%^DSZwG776%EixX=wO9`Xk)GmHkyg5rYZ zfcs#zP$IC-@)~T9eCxfaDcEt89P9*233l_Yd$Bv9^kBD9TCh7PBiLP(0_@&N>A<0c zR)J%qwd*+LhcSD5$=IuPl2=N!1>Au! z4BSB|2DpR6)g6MOf;%)^-C-y?xbtBGxCH>;O>RIz}*KY!95M7 zz&!)kz%z&!__;68;u;66j4fcqInf%^r;0rw}20rwY*2cDrF;5leJcz$RPc>bfE z>jhR2HW0jEv>Ut-vZotvCc@bn zm}HV;CY$VpDW*7Os%g%dZo0E(nBlmYW;$t>Sx%d4o=a9)>#B9uxnhH@ZrW~#2X@=z zk)w`z;;wt1`R1Do`vtL!kl6p!0iud(l#)uCq@jkUYO1LzYX-(>G9-zIt%f9D#@1}o zhSd_w1If-{FCp0l>;)wE#+Gi1?$sa53~3@`_u=P0sU!TU2K9vhyS9ee0Cef&aM)t> z?ROAx>a`So<+&dGg2|1{6N0J#78-&O14|JW(0h_nC86bJ)=fV1}og5S!E?Om`z z7pVi^&nMn!aRZx0*H$Z-Z$!>z(f-c3dV066_xiA)+l*}9S%%QNDhR92lgetS&aaDY z+*&O!6VSDT@@5HL=Q}o*C5v-OErF^;;^;Pw7LsAsi&a|$ zefz8RtB-azRpNC$eX~t%!MVRg0WBUC1ck9+)R>dvRvCKlLK|g?P;&;R6#`M~0x~F0 zgm+U-NSqJ{4^DW!-P$+bEPn)YUvHG0)%LLkbIQO~|Yy{QWJMlhrXbDPPMKG8_iBKp4b5ru!b1b;|vW z2$hQMtDL%>%2T#*c`7}2=t5_Qp)KA+q9P~qN z1B6U^*T0T|MR2ubQkzCf$p)%6OXo|majc!KD?G!+8Rb1Y9}3@kCJr7d=e<<+1p_}H z1=A@-X67bi0C{l{Y-o&XKXQ)j#0Qd`RLIdQ2{=P!;vIuj%tAUm6FYcF8~~XY&0F&I zYA;DWY6j&1pRu(OIo*Y6qI7w9?+NGi9tP?D!J@a4YpHP6fv%x44sQF%Q+%&RDIWa~kC9P7Y8xw5-p)1USvVLj=qOSO;$C`VXW&6}@Np-Kd ze|S9hPwW5UnF9aX{6%uO@ky`O(){U`U>v@VCz(9&HP+9XgKCW&KVW%#xEMdhr2;!8 z#A_{Fqj8D?@X;QU^ij{YK-Jd~olZAr>0CRplQ`MKbya&Ixgz%NvlcxuK+*IE)cFLo F1kH2J_s;+T literal 0 HcmV?d00001 diff --git a/docs/scripts/api-mdx.mjs b/docs/scripts/api-mdx.mjs new file mode 100644 index 0000000..9a474e8 --- /dev/null +++ b/docs/scripts/api-mdx.mjs @@ -0,0 +1,254 @@ +// Render the griffe API dump (`gen_api_dump.py`) to Fumadocs MDX. +// +// Derived from the Node half of fumadocs-python (MIT, (c) 2023 Fuma); see +// `gen_api_dump.py` for the full notice. Kept deliberately close to that +// original so the emitted MDX -- and therefore the `/api/...` URL scheme the +// cross-reference index in `xref.mjs` mirrors -- stays unchanged. +// +// Page granularity is the contract: one page per module (`/index.mdx`) +// and one per class (`/.mdx`), with functions and attributes +// rendered inline on their parent's page and addressed by a `#` fragment. +// `xref.mjs` encodes the same rule, so the two must move together. + +import * as fs from 'node:fs/promises'; +import * as path from 'node:path'; +import { stringify } from 'yaml'; + +/** + * Render a module tree to a flat list of `{path, frontmatter, content}` files. + * + * `path` stays package-qualified (`src_method/stack/index.mdx`) -- callers key + * off that leading segment to derive a page's scope and source file -- while + * `write` strips it on the way to disk, matching the hrefs `getHref` mints. + */ +export function convert(mod, options = {}) { + const files = []; + const content = []; + const tabs = []; + const tabContents = []; + + if (mod.description) content.push(encodeText(mod.description)); + const remainder = convertDoc(mod.docstring ?? []); + if (remainder) content.push(remainder); + for (const attr of mod.attributes) content.push(convertAttribute(attr)); + + if (Object.keys(mod.classes).length > 0) { + tabs.push('Class'); + const lines = []; + for (const cls of Object.values(mod.classes)) { + files.push(...convertClass(cls)); + lines.push(element('Card', { title: cls.name, href: getHref(cls, options) })); + } + tabContents.push(element('Cards', undefined, lines.join('\n'))); + } + + if (Object.keys(mod.functions).length > 0) { + tabs.push('Functions'); + const lines = []; + for (const func of Object.values(mod.functions)) lines.push(convertFunction(func)); + tabContents.push(lines.join('\n')); + } + + if (Object.keys(mod.modules).length > 0) { + tabs.push('Modules'); + const lines = []; + for (const submod of Object.values(mod.modules)) { + files.push(...convert(submod, options)); + lines.push(element('Card', { href: getHref(submod, options), title: submod.name })); + } + tabContents.push(element('Cards', undefined, lines.join('\n'))); + } + + if (tabs.length > 0) { + content.push( + element( + 'Tabs', + { items: tabs }, + tabContents.map((tab, i) => element('Tab', { value: tabs[i] }, tab)).join('\n'), + ), + ); + } + + files.push({ + path: [...mod.path.split('.'), 'index.mdx'].join('/'), + frontmatter: { title: mod.name }, + content: content.join('\n\n'), + }); + return files; +} + +function convertClass(cls) { + const content = []; + + if (cls.description) content.push(encodeText(cls.description)); + const remainder = convertDoc(cls.docstring ?? []); + if (remainder) content.push(remainder); + if (cls.attributes.length > 0) content.push(heading(2, 'Attributes')); + for (const attr of cls.attributes) content.push(convertAttribute(attr)); + if (Object.keys(cls.functions).length > 0) { + content.push(heading(2, 'Functions')); + for (const func of Object.values(cls.functions)) content.push(convertFunction(func)); + } + + return [ + { + path: cls.path.replaceAll('.', '/') + '.mdx', + frontmatter: { title: cls.name }, + content: content.join('\n\n'), + }, + ]; +} + +function convertFunction(func) { + return element( + 'PyFunction', + { name: func.name, type: func.signature }, + [ + func.description ? encodeText(func.description) : null, + convertDoc(func.docstring ?? []), + func.source.length > 0 + ? element('PySourceCode', undefined, codeblock('python', func.source)) + : null, + func.parameters.length > 0 + ? element('div', undefined, func.parameters.map(convertParameter).join('\n')) + : null, + element( + 'PyFunctionReturn', + { type: func.returns.annotation }, + [func.returns.description ? encodeText(func.returns.description) : null] + .filter(Boolean) + .join('\n'), + ), + ] + .filter(Boolean) + .join('\n\n'), + ); +} + +function convertParameter(param) { + const lines = []; + if (param.description) { + lines.push( + typeof param.description === 'string' ? param.description : convertDoc(param.description), + ); + } + return element( + 'PyParameter', + { name: param.name, type: param.annotation, value: param.value }, + lines.join('\n'), + ); +} + +function convertAttribute(attribute) { + return element( + 'PyAttribute', + { name: attribute.name, type: attribute.annotation, value: attribute.value }, + [attribute.description ? convertDoc(attribute.description) : null].filter(Boolean).join('\n'), + ); +} + +/** + * Render the docstring sections `simplify_docstring` left in `remainder`. + * + * Anything not handled here is dropped, which is why the default warns: which + * sections griffe splits out is a function of its version, so a docstring can + * stop rendering without anything else changing. + */ +function convertDoc(docstring) { + const lines = []; + for (const item of docstring) { + if (item.kind === 'text') { + lines.push(encodeText(item.value)); + } else if (item.kind === 'admonition') { + lines.push( + element( + 'Callout', + { title: item.title, type: item.value.annotation }, + encodeText(item.value.description), + ), + ); + } else if (item.kind === 'raises') { + lines.push( + ['**Raises**', '', ...item.value.map((exc) => `- \`${exc.annotation}\`: ${encodeText(foldLines(exc.description))}`)].join('\n'), + ); + } else { + console.warn(`api-mdx: dropping unhandled docstring section "${item.kind}"`); + } + } + return lines.join('\n\n'); +} + +// A list item has to stay on one line, but docstring descriptions wrap. +function foldLines(text) { + return String(text).replace(/\s*\n\s*/g, ' ').trim(); +} + +function heading(depth, content) { + return ['#'.repeat(depth), content].join(' '); +} + +function codeblock(meta, code) { + const delimit = '```'; + return `${delimit}${meta}\n${code.replaceAll(delimit, '\\```')}\n${delimit}`; +} + +/** Emit an MDX element, passing every prop as an expression (`name={"x"}`). */ +function element(name, props = {}, children) { + const propsStr = []; + for (const key in props) propsStr.push(`${key}={${JSON.stringify(props[key])}}`); + if (children) { + return `<${name} ${propsStr.join(' ')}>\n\n${children}\n\n`; + } + return `<${name} ${propsStr.join(' ')} />`; +} + +// Mints the URL of the page documenting `ele`, dropping the package's own +// leading segment so it lines up with where `write` puts the file. `pageUrl` in +// `xref.mjs` has to agree with this, since prose links are resolved from there. +function getHref(ele, options) { + const { baseUrl = '/' } = options; + return ( + '/' + + [...baseUrl.split('/'), ...ele.path.split('.').slice(1)].filter((v) => v.length > 0).join('/') + ); +} + +// MDX parses `<` as JSX and `{` as an expression, so docstring prose has to +// escape both -- but not inside code spans, where MDX takes them literally and +// an escape would show up as a stray backslash. +function encodeText(v) { + return v + .split(/(`+[^`]*?`+)/) + .map((part, i) => + i % 2 === 1 + ? part + : part.replaceAll('<', '\\<').replaceAll('{', '\\{').replaceAll('}', '\\}'), + ) + .join(''); +} + +/** + * Write the rendered files under `outDir`, dropping the leading path segment + * (the package name) so `src_method/stack/...` lands at `/stack/...`. + */ +export async function write(output, options = {}) { + await Promise.all( + output.map(async (file) => { + const filePath = path.resolve( + options.outDir ?? './', + file.path.split('/').slice(1).join('/'), + ); + await fs.mkdir(path.dirname(filePath), { recursive: true }); + await fs.writeFile( + filePath, + Object.keys(file.frontmatter).length > 0 + ? `${frontmatter(file.frontmatter)}\n\n${file.content}` + : file.content, + ); + }), + ); +} + +function frontmatter(obj) { + return `---\n${stringify(obj, { compat: 'yaml-1.1', singleQuote: true }).trim()}\n---`; +} diff --git a/docs/scripts/gen_api_dump.py b/docs/scripts/gen_api_dump.py new file mode 100755 index 0000000..9a3409b --- /dev/null +++ b/docs/scripts/gen_api_dump.py @@ -0,0 +1,597 @@ +#!/usr/bin/env python3 +# Copyright 2026 Algorithmiq +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# --------------------------------------------------------------------------- +# Portions of this file are derived from `fumapy`, the Python half of the +# fumadocs-python package (https://github.com/fuma-nama/fumadocs): +# +# MIT License. Copyright (c) 2023 Fuma +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. +# --------------------------------------------------------------------------- +"""Dump a Python package's documented API surface to JSON, via griffe. + +The JSON is the input to two consumers, which is why its schema is a contract +rather than an implementation detail: + +- `scripts/generate-api.mjs`, which renders it to the MDX under + `content/docs/api/`, and +- `scripts/remark-xref.mjs`, which builds the `[Symbol][]` cross-reference index + for prose pages and docstrings from it. + +Run it from `docs/` (see `docs/README.md`); the package has to be importable. +""" + +from __future__ import annotations + +import argparse +import json +import typing as t +from importlib.metadata import version +from pathlib import Path + +import griffe + +# --------------------------------------------------------------------------- +# The JSON schema +# +# These describe the *serialised* shape, which is what the two JS consumers +# read. In flight, the same fields hold griffe model objects (a +# `DocstringParameter` where a `Parameter` is declared, an `Expr` where a `str` +# is); `Encoder` flattens them at dump time. The `t.cast` calls in the `parse_*` +# functions are where that gap is crossed deliberately. +# --------------------------------------------------------------------------- + + +class Module(t.TypedDict): + """A documented module or package.""" + + name: str + path: str + filepath: str + description: str | None + docstring: Docstring + attributes: list[Attribute] + modules: dict[str, Module] + classes: dict[str, Class] + functions: dict[str, Function] + version: str | None + + +class Class(t.TypedDict): + """A documented class.""" + + name: str + path: str + description: str | None + parameters: list[Parameter] + attributes: list[Attribute] + docstring: Docstring + functions: dict[str, Function] + source: str + inherited_members: dict[str, list[dict[str, str]]] + + +class Function(t.TypedDict): + """A documented function or method.""" + + name: str + path: str + signature: str + description: str | None + parameters: list[Parameter] + returns: dict[str, str | None] + docstring: Docstring + source: str + + +class DocstringSection(t.TypedDict): + """A docstring section that `simplify_docstring` did not consume.""" + + kind: str + value: str | list[Parameter] + + +Docstring = list[DocstringSection] + + +class Parameter(t.TypedDict): + """A signature parameter, merged with its docstring entry if it has one.""" + + name: str + annotation: str + description: str + value: str + + +class Attribute(t.TypedDict): + """A module- or class-level attribute.""" + + name: str + annotation: str + description: str + value: str + + +# --------------------------------------------------------------------------- +# Docstring simplification +# --------------------------------------------------------------------------- + + +class SimplifiedDocstring(t.NamedTuple): + """A docstring split into the parts the renderer treats specially. + + Entries are either plain dicts built from the signature or the griffe + docstring elements they were parsed from; `Encoder` serialises both, so the + two are interchangeable downstream. A field is `None` when the parent cannot + have it at all (a module has no parameters), as opposed to an empty list for + a parent that has none. + """ + + description: str | None + parameters: list[object] | None + returns: object | None + attributes: list[object] | None + remainder: list[griffe.DocstringSection] + + +_VARIADIC = (griffe.ParameterKind.var_positional, griffe.ParameterKind.var_keyword) + + +def _parameters_from_signature( + parent: griffe.Class | griffe.Function, +) -> list[object]: + return [ + { + "name": p.name, + "annotation": p.annotation, + "description": None, + "value": None if p.kind in _VARIADIC else p.default, + } + for p in parent.parameters + ] + + +def _returns_from_signature(parent: griffe.Function) -> object: + return { + "name": "", + "annotation": ( + parent.returns + if isinstance(parent.returns, (str, type(None))) + else "".join( + elem if isinstance(elem, str) else elem.canonical_path + for elem in parent.returns.iterate(flat=True) + ) + ), + "description": None, + } + + +def _attributes_from_signature( + parent: griffe.Module | griffe.Class, +) -> list[object]: + return [ + { + "name": attr.name, + "annotation": attr.annotation, + "description": attr.docstring.parsed if attr.docstring else None, + "value": attr.value, + } + for attr in parent.attributes.values() + if (not attr.is_alias and not attr.is_private) + ] + + +def _parse_nested(description: str) -> object: + """Re-parse a docstring entry's description as a Google-style docstring. + + Parameter and attribute descriptions can themselves carry sections; the + renderer expects the parsed form. A description that is already parsed is + returned unchanged -- `AttributeError` is how that shows up. + """ + try: + return griffe.parse_google(griffe.Docstring(description)) + except AttributeError: + return description + + +def _merge_parameters( + documented: list[griffe.DocstringParameter], parent: griffe.Class | griffe.Function +) -> list[object]: + """Order a docstring's parameter entries by the real signature. + + Yields one entry per signature parameter, documented or not, so the renderer + can lay out a full parameter list from a partial docstring. + """ + # Google style documents `*args` as `*args`; the signature names it `args`. + by_name = {entry.name.lstrip("*"): entry for entry in documented} + merged: list[object] = [] + for param in parent.parameters: + entry = by_name.get(param.name) + if entry is not None and param.kind in _VARIADIC: + # griffe reports `()` and `{}` as the defaults of `*args` and + # `**kwargs`, which the renderer would show as `= ()`. + merged.append( + { + "name": param.name, + "annotation": entry.annotation, + "description": _parse_nested(entry.description), + "value": None, + } + ) + elif entry is not None: + # Replaces the raw text with its parsed sections in place, which the + # renderer reads back -- griffe declares `description` as `str`, so + # this widening is deliberate. + entry.description = t.cast("str", _parse_nested(entry.description)) + merged.append(entry) + else: + merged.append( + { + "name": param.name, + "annotation": param.annotation, + "description": None, + "value": None if param.kind in _VARIADIC else param.default, + } + ) + return merged + + +def _merge_attributes( + documented: list[griffe.DocstringAttribute], parent: griffe.Module | griffe.Class +) -> list[object]: + """Order a docstring's attribute entries by the real attributes. + + Yields one entry per non-aliased attribute, documented or not. + """ + by_name = {entry.name: entry for entry in documented} + merged: list[object] = [] + for attr in parent.attributes.values(): + if attr.is_alias: + continue + entry = by_name.get(attr.name) + if entry is not None: + merged.append( + { + "name": entry.name, + "description": _parse_nested(entry.description), + # The declared annotation wins over the inferred one, but + # the value only exists on the real attribute. + "annotation": entry.annotation, + "value": attr.value, + } + ) + else: + merged.append( + { + "name": attr.name, + "annotation": attr.annotation, + "description": (attr.docstring.parsed if attr.docstring else None), + "value": attr.value, + } + ) + return merged + + +def simplify_docstring( + doc: griffe.Docstring | None, + parent: griffe.Module | griffe.Class | griffe.Function | None = None, +) -> SimplifiedDocstring: + """Split a docstring into description, parameters, returns and the rest. + + The `parameters` and `attributes` sections are re-ordered to follow the real + signature, and entries the docstring omits are filled in from it, so the + renderer can lay out every parameter whether or not it is documented. + + Args: + doc: The docstring to simplify; may be `None`. + parent: The object the docstring belongs to, used for the signature. + + Returns: + The docstring's parts, with anything not recognised in `remainder`. + """ + description = None + parameters = ( + _parameters_from_signature(parent) + if isinstance(parent, (griffe.Class, griffe.Function)) + else None + ) + attributes = ( + _attributes_from_signature(parent) + if isinstance(parent, (griffe.Module, griffe.Class)) + else None + ) + returns = ( + _returns_from_signature(parent) if isinstance(parent, griffe.Function) else None + ) + remainder: list[griffe.DocstringSection] = [] + + if not doc: + return SimplifiedDocstring( + description, parameters, returns, attributes, remainder + ) + + for i, sec in enumerate(doc.parsed): + # The leading prose is the summary; later text sections stay in the + # remainder so the renderer can place them after the signature. + if sec.kind == "text" and i == 0: + description = sec.value + continue + + # Each branch is gated on the parent kind that can actually have the + # section, so a misplaced section (`Args:` on a module) lands in the + # remainder instead of failing on a missing signature. + if sec.kind == "parameters" and isinstance( + parent, (griffe.Class, griffe.Function) + ): + parameters = _merge_parameters(sec.value, parent) + continue + + if sec.kind == "returns" and isinstance(parent, griffe.Function): + returns = sec.value[0] + returns.annotation = ( + returns.annotation.canonical_path + if isinstance(returns.annotation, griffe.Expr) + else returns.annotation + ) + continue + + if sec.kind == "attributes" and isinstance( + parent, (griffe.Module, griffe.Class) + ): + attributes = _merge_attributes(sec.value, parent) + continue + + remainder.append(sec) + + return SimplifiedDocstring(description, parameters, returns, attributes, remainder) + + +# --------------------------------------------------------------------------- +# Signatures +# --------------------------------------------------------------------------- + + +def _render_parameter(p: griffe.Parameter) -> str: + """Render one parameter, with its `*`/`**` prefix and default if it has one.""" + if p.kind == griffe.ParameterKind.var_keyword: + return f"**{p.name}" + if p.kind == griffe.ParameterKind.var_positional: + return f"*{p.name}" + if p.default is not None: + return f"{p.name}={p.default}" + return p.name + + +def build_signature(func: griffe.Function) -> str: + """Render a function's signature, including the `/` and `*` separators. + + griffe stores parameter kinds rather than the separators, so the markers are + reconstructed: `/` closes the positional-only run at the first parameter + that is not positional-only, and `*` opens the keyword-only run. + + Args: + func: The function to render. + + Returns: + The signature, from the opening parenthesis to the return annotation. + """ + tokens: list[str] = [] + # `/` closes a run of positional-only parameters, so it is only owed once one + # has been seen; `*` opens the keyword-only run unless `*args` already did. + open_positional_only = False + keyword_only = False + for p in func.parameters: + if p.kind == griffe.ParameterKind.positional_only: + open_positional_only = True + elif open_positional_only: + tokens.append("/") + open_positional_only = False + + if p.kind == griffe.ParameterKind.var_positional: + keyword_only = True + elif p.kind == griffe.ParameterKind.keyword_only and not keyword_only: + tokens.append("*") + keyword_only = True + + tokens.append(_render_parameter(p)) + if open_positional_only: + tokens.append("/") + + signature = f"({', '.join(tokens)})" + if func.returns: + signature += f" -> {func.returns}" + + return signature + + +# --------------------------------------------------------------------------- +# Walking the package +# --------------------------------------------------------------------------- + + +def parse_module(m: griffe.Object | griffe.Alias) -> Module: + """Walk a module recursively, dropping re-exported (aliased) members. + + Aliases are skipped so a symbol is documented once, on the page for the + module that defines it -- which is also what makes the cross-reference index + single-valued. + + Args: + m: The module to walk. + + Returns: + The module's documented surface. + + Raises: + TypeError: If `m` is not a module. + """ + if not isinstance(m, griffe.Module): + raise TypeError("Module must be a module") + + out = simplify_docstring(m.docstring, m) + res: dict[str, object] = { + "name": m.name, + "path": m.path, + "filepath": m.filepath, + "description": out.description, + "docstring": out.remainder, + "attributes": out.attributes, + "modules": { + name: parse_module(value) + for name, value in m.modules.items() + if not value.is_alias + }, + "classes": { + name: parse_class(value) + for name, value in m.classes.items() + if not value.is_alias + }, + "functions": { + name: parse_function(value) + for name, value in m.functions.items() + if not value.is_alias + }, + } + if m.is_package: + try: + res["version"] = version(m.name) + except AttributeError: + res["version"] = "unknown" + + return t.cast("Module", res) + + +def parse_class(c: griffe.Class) -> Class: + """Walk a class. + + Inherited members are recorded by canonical path and grouped by the class + that defines them, so the renderer can point at the base class rather than + duplicating the documentation. + + Args: + c: The class to walk. + + Returns: + The class's documented surface. + """ + out = simplify_docstring(c.docstring, c) + inherited: dict[str, list[dict[str, str]]] = {} + res: dict[str, object] = { + "name": c.name, + "path": c.path, + "description": out.description, + "parameters": out.parameters, + "attributes": out.attributes, + "docstring": out.remainder, + "functions": { + name: parse_function(value) + for name, value in c.functions.items() + if not value.is_alias + }, + "source": c.source, + "inherited_members": inherited, + } + for member in c.inherited_members.values(): + parent_path = ".".join(member.canonical_path.split(".")[:-1]) + entry = {"kind": member.kind, "path": member.canonical_path} + inherited.setdefault(parent_path, []).append(entry) + return t.cast("Class", res) + + +def parse_function(f: griffe.Function) -> Function: + """Walk a function or method.""" + out = simplify_docstring(f.docstring, f) + return t.cast( + "Function", + { + "name": f.name, + "path": f.path, + "signature": build_signature(f), + "description": out.description, + "parameters": out.parameters, + "returns": out.returns, + "docstring": out.remainder, + "source": f.source, + }, + ) + + +# --------------------------------------------------------------------------- +# Serialisation +# --------------------------------------------------------------------------- + + +class Encoder(griffe.JSONEncoder): + """Serialise the griffe objects `simplify_docstring` leaves in the tree. + + The base class already handles every griffe model (via `as_dict`) plus the + `Path`/`set` values they carry; the one thing it gets wrong for us is + `Expr`, which *has* an `as_dict` and so would serialise as a nested tree + where the consumers want the annotation as written. + """ + + def default(self, obj: object) -> object: + """Return a serialisable representation of `obj`.""" + if isinstance(obj, griffe.Expr): + return str(obj) + return super().default(obj) + + +def main() -> None: + """Dump the API surface of the module named on the command line.""" + parser = argparse.ArgumentParser(description="Dump a Python API surface to JSON") + parser.add_argument("module", type=str, help="The module to document") + parser.add_argument( + "--dir", + "-d", + type=Path, + default=Path(), + help="The directory to write `.json` into", + ) + args = parser.parse_args() + + pkg = parse_module( + griffe.load( + args.module, + docstring_parser="auto", + # The renderer shows each function's source in a collapsible block. + store_source=True, + ) + ) + + out_path = args.dir / f"{args.module}.json" + with out_path.open("w") as file: + json.dump(pkg, file, cls=Encoder, indent=2, full=True) + + +if __name__ == "__main__": + main() diff --git a/docs/scripts/generate-api.mjs b/docs/scripts/generate-api.mjs new file mode 100644 index 0000000..14073c7 --- /dev/null +++ b/docs/scripts/generate-api.mjs @@ -0,0 +1,230 @@ +// Generate the Python API reference MDX from the griffe JSON produced by +// `gen_api_dump.py` (see `docs/README.md`). +// +// `api-mdx.mjs`'s `convert`/`write` do the heavy lifting; this script only +// 1. prunes the griffe dump to the public surface (minus private `_`-prefixed members), +// 2. fixes the package-name segment that `convert` puts in cross-links but +// `write` strips from file paths, and +// 3. emits a `meta.json` so the API section is ordered like the old reference. +import * as fs from 'node:fs/promises'; +import * as path from 'node:path'; +import { convert, write } from './api-mdx.mjs'; +import { API_BASE_URL, buildXrefMap, resolve } from './xref.mjs'; + +const JSON_PATH = path.resolve('src_method.json'); +const OUT_DIR = path.resolve('content/docs/api'); + +// Public modules, in sidebar order, with the title shown for each: every module +// defines one entry point, so the page is named after it. +const MODULES = [ + ['stack', 'src'], + ['apply', 'apply'], + ['compress', 'compress'], +]; +const KEEP = new Set(MODULES.map(([name]) => name)); +const MODULE_GITHUB_PATHS = new Map(MODULES.map(([name]) => [name, `src/src_method/${name}.py`])); + +/** Drop single-underscore (non-dunder) members from a {name: node} map. */ +function prunePrivate(map) { + for (const name of Object.keys(map)) { + if (name.startsWith('_') && !name.startsWith('__')) delete map[name]; + } +} + +/** Recursively strip private classes/functions/submodules from a module node. */ +function pruneModule(mod) { + // The documented modules export functions only; their module-level names + // (`logger`, message constants) are implementation details. + mod.attributes = []; + prunePrivate(mod.classes ?? {}); + prunePrivate(mod.functions ?? {}); + for (const cls of Object.values(mod.classes ?? {})) prunePrivate(cls.functions ?? {}); + for (const sub of Object.values(mod.modules ?? {})) pruneModule(sub); +} + +/** + * Derive the fully-qualified scope a rendered page documents, from its file + * path (before `write` strips the leading package segment): + * `src_method/stack/index.mdx` -> `src_method.stack` (module) + * `src_method/index.mdx` -> `src_method` (package) + */ +function scopeFromPath(filePath) { + return filePath + .replace(/\/index\.mdx$/, '') + .replace(/\.mdx$/, '') + .split('/') + .join('.'); +} + +/** + * Resolve cross-references in a rendered MDX page into real links. Targets are + * Python paths, resolved fully-qualified or relative to `scope`, the page's own + * fully-qualified scope (see `scopeFromPath`): + * `[src][src_method.stack.src]` -> `[src](/api/stack#src)` + * `[src][]` (on a page scoped to `src_method.stack`) -> `[src](/api/stack#src)` + * Unresolved targets are collected in `unresolved` (surfaced by the caller) and + * left untouched. + */ +function resolveXrefs(content, xref, unresolved, scope) { + // Avoid double-wrapping a display text the docstring already backticked. + const code = (text) => (/^`.*`$/.test(text) ? text : `\`${text}\``); + + return content.replaceAll(/\[([^\]]+)\]\[([^\]]*)\]/g, (match, display, target) => { + const name = (target || display).trim().replace(/^`|`$/g, ''); + const url = resolve(name, scope, xref); + if (url) return `[${code(display)}](${url})`; + unresolved.add(name); + return match; + }); +} + +function foldToOneLine(text) { + return String(text).replace(/\s*\n\s*/g, ' ').replace(/\s+/g, ' ').trim(); +} + +/** + * Unescape braces within LaTeX/KaTeX math expressions. + * + * Upstream markdown serialization escapes braces (`\{` and `\}`), but KaTeX + * requires unescaped braces for proper grouping (subscripts, superscripts, and + * command arguments). This function selectively unescapes braces only inside + * `$...$` (inline) and `$$...$$` (display) math spans, e.g. `$r_\{12\}$` -> `$r_{12}$`. + */ +function normalizeMathGroupingEscapes(content) { + const normalizeMathSegment = (math) => + math + .replace(/\\\{/g, '{') + .replace(/\\\}/g, '}'); + + return content.replace(/\$\$[\s\S]*?\$\$|\$(?:\\.|[^$\\])+\$/g, (math) => + normalizeMathSegment(math), + ); +} + +/** + * Extract the raw `Returns:` block from a function source docstring. + * We prefer source extraction because some upstream parsed `returns.description` + * values are already truncated to the first wrapped line. + */ +function extractReturnsFromSource(source) { + if (typeof source !== 'string' || source.length === 0) return null; + + // Find a Returns section inside the function source, ending at the next + // section header (e.g. Args:, Raises:, Note:) or the closing docstring. + const match = source.match( + /\n\s+Returns:\n([\s\S]*?)(?=\n\s+[A-Z][A-Za-z_ ]+:\n|\n\s+["']{3})/, + ); + if (!match) return null; + + const text = match[1] + .split('\n') + .map((line) => line.replace(/^\s+/, '')) + .join(' ') + .trim(); + + return text || null; +} + +/** + * Recover a multi-line `Returns:` description that the dump truncated, by + * re-reading it from the function source. + * + * This is a bandaid over the dump, not a fix. griffe's Google parser defaults to + * `returns_multiple_items`, which splits the block one item per physical line + * and distributes a tuple annotation element-wise across them, so the dump's + * `sec.value[0]` keeps only the first line *and* the wrong annotation + * (`graph_size` is documented as `int`, not `tuple[int, int]`). Passing + * `docstring_options={"returns_multiple_items": False}` to `griffe.load` in + * `gen_api_dump.py` fixes both and retires this whole path -- deferred only + * because it changes the generated pages. + */ +function normalizeFunctionReturnsSection(funcNode) { + const fromSource = extractReturnsFromSource(funcNode?.source); + if (fromSource && funcNode?.returns && typeof funcNode.returns === 'object') { + funcNode.returns.description = foldToOneLine(fromSource); + } +} + +function normalizeFunctionReturns(mod) { + if (!mod || typeof mod !== 'object') return; + + for (const fn of Object.values(mod.functions ?? {})) { + normalizeFunctionReturnsSection(fn); + } + + for (const cls of Object.values(mod.classes ?? {})) { + for (const fn of Object.values(cls.functions ?? {})) { + normalizeFunctionReturnsSection(fn); + } + } + + for (const sub of Object.values(mod.modules ?? {})) { + normalizeFunctionReturns(sub); + } +} + +async function main() { + const pkg = JSON.parse(await fs.readFile(JSON_PATH, 'utf8')); + + // Keep only the documented public submodules. + pkg.modules = Object.fromEntries( + Object.entries(pkg.modules ?? {}).filter(([name]) => KEEP.has(name)), + ); + pruneModule(pkg); + normalizeFunctionReturns(pkg); + + const xref = buildXrefMap(pkg); + const unresolved = new Set(); + + const files = convert(pkg, { baseUrl: API_BASE_URL }); + + for (const file of files) { + file.content = resolveXrefs(file.content, xref, unresolved, scopeFromPath(file.path)); + + // Attach source paths to frontmatter so docs can build GitHub links + // without duplicating the module list in app code. + const modulePrefixMatch = file.path.match(/^src_method\/([^/]+)(?:\/|$)/); + const moduleName = modulePrefixMatch?.[1]; + const githubPath = moduleName ? MODULE_GITHUB_PATHS.get(moduleName) : undefined; + if (githubPath) { + file.frontmatter.githubPath = githubPath; + } + file.content = normalizeMathGroupingEscapes(file.content); + + // Add titles to the frontmatter for the modules we documented. The title + // is used in the sidebar and in the page's tag. + const m = file.path.match(/^src_method\/([^/]+)\/index\.mdx$/); + if (m) { + const entry = MODULES.find(([name]) => name === m[1]); + if (entry) file.frontmatter.title = entry[1]; + } + if (file.path === 'src_method/index.mdx') { + file.frontmatter.title = 'Python API'; + file.frontmatter.description = 'Generated reference for the public src_method Python package.'; + file.frontmatter.githubPath = 'src/src_method/__init__.py'; + } + } + + if (unresolved.size > 0) { + console.warn( + `Warning: ${unresolved.size} cross-reference target(s) did not resolve and were left as-is:\n ` + + [...unresolved].sort().join('\n '), + ); + } + + await fs.rm(OUT_DIR, { recursive: true, force: true }); + await write(files, { outDir: OUT_DIR }); + + // Sidebar ordering for the API section. `index.mdx` is intentionally omitted: + // fumadocs treats it as the folder's own index (so the "Python API" title + // links to `/api`); listing it would add a redundant child duplicating + // the section title in the sidebar. + await fs.writeFile( + path.join(OUT_DIR, 'meta.json'), + JSON.stringify({ title: 'Python API', pages: [...MODULES.map(([n]) => n)] }, null, 2), + ); + + console.log(`Wrote ${files.length} API pages to ${OUT_DIR}`); +} + +await main(); diff --git a/docs/scripts/notebooks_to_mdx.py b/docs/scripts/notebooks_to_mdx.py new file mode 100755 index 0000000..5df50ff --- /dev/null +++ b/docs/scripts/notebooks_to_mdx.py @@ -0,0 +1,185 @@ +#!/usr/bin/env python3 +# Copyright 2026 Algorithmiq +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Execute the tutorial notebooks and convert them to Markdown for Fumadocs. + +Each notebook in ``docs/notebooks/<name>/<name>.ipynb`` is executed top to +bottom and rendered to ``docs/content/docs/tutorials/<name>.md``. Execution +fails the build on the first cell error (``allow_errors=False``); this is the +notebook-level "doctest". + +Output images (matplotlib figures, …) and images referenced from markdown cells +are inlined as base64 data URIs so the static export is fully self-contained. +Notebooks are emitted as ``.md`` (not ``.mdx``) so that ``{`` / ``<`` in code +and prose are treated literally and ``$…$`` math is left for ``remark-math``. +""" + +from __future__ import annotations + +import argparse +import base64 +import mimetypes +import re +import sys +from pathlib import Path + +import nbformat +from nbconvert import MarkdownExporter +from nbconvert.preprocessors import ExecutePreprocessor + +DOCS_DIR = Path(__file__).resolve().parent.parent +NB_DIR = DOCS_DIR / "notebooks" +OUT_DIR = DOCS_DIR / "content" / "docs" / "tutorials" +TIMEOUT = 600 # seconds per cell + +_IMG_REF = re.compile(r"!\[([^\]]*)\]\(([^)\s]+)\)") +_H1 = re.compile(r"^\s*#\s+(.+?)\s*$", re.MULTILINE) + + +def discover_notebooks() -> list[str]: + """Return the stems of `docs/notebooks/<stem>/<stem>.ipynb`, alphabetically.""" + return sorted( + p.name + for p in NB_DIR.iterdir() + if p.is_dir() and (p / f"{p.name}.ipynb").is_file() + ) + + +def _notebook_title(nb: nbformat.NotebookNode, stem: str) -> str: + """Extract the page title from the notebook's leading H1 heading.""" + text = "\n".join(cell.source for cell in nb.cells if cell.cell_type == "markdown") + match = _H1.search(text) + return match.group(1).strip() if match else stem.replace("_", " ").title() + + +def title_for(stem: str) -> str: + """Read a notebook's title without executing it.""" + nb = nbformat.read(NB_DIR / stem / f"{stem}.ipynb", as_version=4) + return _notebook_title(nb, stem) + + +def _data_uri(data: bytes, filename: str) -> str: + mime = mimetypes.guess_type(filename)[0] or "image/png" + return f"data:{mime};base64,{base64.b64encode(data).decode('ascii')}" + + +def _inline_images(body: str, resources: dict, nb_dir: Path) -> str: + """Replace image references with self-contained base64 data URIs.""" + outputs: dict[str, bytes] = resources.get("outputs", {}) or {} + + def as_img(alt: str, uri: str) -> str: + # Emit raw HTML rather than markdown image syntax: a `data:` URI looks + # like a relative path to fumadocs' remark-image plugin, which then + # fails trying to read it as a file. Raw <img> bypasses that plugin. + alt = alt.replace('"', """) + return f'<img alt="{alt}" src="{uri}" />' + + def repl(match: re.Match[str]) -> str: + alt, target = match.group(1), match.group(2) + if target.startswith("data:"): + return as_img(alt, target) + name = target.split("/")[-1] + if name in outputs: # image extracted from a cell output + return as_img(alt, _data_uri(outputs[name], name)) + local = (nb_dir / target).resolve() + if local.is_file(): # image committed next to the notebook + return as_img(alt, _data_uri(local.read_bytes(), local.name)) + return match.group(0) + + return _IMG_REF.sub(repl, body) + + +def convert(stem: str) -> Path: + """Execute one notebook and write its Markdown page; return the path.""" + nb_path = NB_DIR / stem / f"{stem}.ipynb" + nb = nbformat.read(nb_path, as_version=4) + title = _notebook_title(nb, stem) + + # Execute with the notebook directory as cwd so relative data loads work. + ExecutePreprocessor(timeout=TIMEOUT, allow_errors=False).preprocess( + nb, {"metadata": {"path": str(nb_path.parent)}} + ) + + exporter = MarkdownExporter() + body, resources = exporter.from_notebook_node(nb) + body = _inline_images(body, resources, nb_path.parent) + + # The frontmatter title becomes the page H1; drop the notebook's own H1. + body = _H1.sub("", body, count=1).lstrip() + + fm = f"---\ntitle: {title}\n---\n\n" + out_path = OUT_DIR / f"{stem}.md" + out_path.write_text(fm + body) + return out_path + + +def write_index(stems: list[str]) -> Path: + """Write the tutorials landing page (index.mdx) listing every notebook.""" + bullets = "\n".join(f"- [{title_for(stem)}](/tutorials/{stem})" for stem in stems) + body = ( + "---\n" + "title: Tutorials\n" + "description: Runnable notebooks applying src_method to concrete " + "problems.\n" + "---\n\n" + "These tutorials work through complete problems end to end. Each one is " + "a notebook executed when the site is built; for the ideas behind the " + "method see [Concepts](/concepts), and for every argument see " + "[Python API](/api).\n\n" + f"{bullets}\n" + ) + out_path = OUT_DIR / "index.mdx" + out_path.write_text(body) + return out_path + + +def main() -> int: + """Convert the selected tutorial notebooks and write the sidebar meta.""" + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument( + "notebooks", + nargs="*", + help="Notebook stems to convert (default: all). E.g. fermi_hubbard", + ) + args = parser.parse_args() + + OUT_DIR.mkdir(parents=True, exist_ok=True) + stems = discover_notebooks() + selected = ( + [s for s in stems if s in set(args.notebooks)] if args.notebooks else stems + ) + + for stem in selected: + print(f"Executing and converting {stem} …", flush=True) # noqa: T201 + out = convert(stem) + print(f" -> {out.relative_to(DOCS_DIR)}", flush=True) # noqa: T201 + + # Landing page for `/tutorials`. fumadocs picks up `index.mdx` as the + # folder's own index automatically, so the "Tutorials" sidebar/nav title + # links here. Always regenerated from the full discovered list (independent + # of the `selected` subset) so every tutorial stays listed. + write_index(stems) + + # Sidebar ordering + section title for the tutorials folder. "index" is + # deliberately *not* listed: fumadocs already treats `index.mdx` as the + # folder index, so the folder title links to `/tutorials`. Listing it + # would add a redundant child entry duplicating the section title. + meta = OUT_DIR / "meta.json" + pages = ", ".join(f'"{s}"' for s in stems) + meta.write_text(f'{{\n "title": "Tutorials",\n "pages": [{pages}]\n}}\n') + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/docs/scripts/remark-xref.mjs b/docs/scripts/remark-xref.mjs new file mode 100644 index 0000000..5dd6958 --- /dev/null +++ b/docs/scripts/remark-xref.mjs @@ -0,0 +1,75 @@ +// Remark plugin: resolve mkdocstrings-style cross-references in prose MDX. +// +// Undefined markdown reference links stay as literal *text* nodes (micromark does +// not emit a `linkReference` without a matching definition), so we operate on +// text nodes via `mdast-util-find-and-replace`. Real `[text](url)` links and +// `[@citation]` nodes do not match the two-bracket pattern and are left untouched. +import * as fs from 'node:fs'; +import * as path from 'node:path'; +import { findAndReplace } from 'mdast-util-find-and-replace'; +import { buildXrefMap, resolve } from './xref.mjs'; + +// Prose is scoped to the package root, so a bare `[src][]` +// resolves via the scope walk in `resolve`. +const SCOPE = 'src_method'; +// Same pattern as `resolveXrefs` in generate-api.mjs. +const XREF_PATTERN = /\[([^\]]+)\]\[([^\]]*)\]/g; + +const JSON_PATH = path.resolve('src_method.json'); + +let xref = null; +let byLeaf = null; +try { + xref = buildXrefMap(JSON.parse(fs.readFileSync(JSON_PATH, 'utf8'))); + // The public classes/functions live in submodules (e.g. + // `src_method.stack.src`) but authors know them by the + // bare name they import, so index every symbol by its leaf name as a fallback -- + // dropping any leaf that maps to more than one URL. + byLeaf = new Map(); + const clashed = new Set(); + for (const [dotted, url] of xref) { + const leaf = dotted.split('.').pop(); + if (clashed.has(leaf)) continue; + if (byLeaf.has(leaf) && byLeaf.get(leaf) !== url) { + byLeaf.delete(leaf); + clashed.add(leaf); + } else { + byLeaf.set(leaf, url); + } + } +} catch (err) { + console.warn( + `remark-xref: could not read ${JSON_PATH} (${err.code ?? err.message}); ` + + 'prose cross-references will be left as-is. Run `docs/scripts/gen_api_dump.py` and `generate-api.mjs` first.', + ); +} + +const unbacktick = (text) => text.replace(/^`(.*)`$/, '$1'); + +export default function remarkXref() { + return (tree, file) => { + if (!xref) return; + findAndReplace(tree, [ + [ + XREF_PATTERN, + (_match, display, target) => { + const name = unbacktick((target || display).trim()); + const url = resolve(name, SCOPE, xref) ?? byLeaf.get(name) ?? null; + if (!url) { + // `return false` leaves the text untouched. `console.warn`, not a + // vfile message -- fumadocs/next does not print those. + const where = file.path ? path.relative(process.cwd(), file.path) : 'prose'; + console.warn(`remark-xref: unresolved cross-reference [${display}][${target}] in ${where}`); + return false; + } + // Symbol names read as code, matching the API pages' styling. + return { + type: 'link', + url, + children: [{ type: 'inlineCode', value: unbacktick(display.trim()) }], + }; + }, + ], + ]); + }; +} diff --git a/docs/scripts/xref.mjs b/docs/scripts/xref.mjs new file mode 100644 index 0000000..c394afb --- /dev/null +++ b/docs/scripts/xref.mjs @@ -0,0 +1,67 @@ +// Shared cross-reference machinery for the docs pipeline: the API-reference +// generator (`generate-api.mjs`) and the prose remark plugin (`remark-xref.mjs`) +// must map a Python symbol path to the same doc URL, so these helpers -- built +// from the griffe dump `src_method.json` -- are the single source of truth for it. + +export const API_BASE_URL = '/api'; + +/** + * Turn a fully-qualified symbol path into the URL of the page that documents + * it. Must agree with `getHref` in `api-mdx.mjs`, which mints the same URLs for + * the links inside the generated pages: both drop the leading package segment, + * because that is what `write` strips from the file paths. + */ +export function pageUrl(dottedPath) { + return ( + '/' + + [...API_BASE_URL.split('/'), ...dottedPath.split('.').slice(1)] + .filter((v) => v.length > 0) + .join('/') + ); +} + +/** + * Build a map from fully-qualified symbol path to the doc URL that documents it. + * + * Classes and modules get their own page. Functions, methods and attributes are + * rendered inline on their parent's page; `PyFunction`/`PyAttribute` (in + * `src/components/py.tsx`) give each card an `id` equal to its member name, so + * those members resolve to their parent page with a `#<name>` fragment that + * jumps to the definition. + */ +export function buildXrefMap(pkg) { + const map = new Map(); + + const addScope = (node, pageUrl) => { + map.set(node.path, pageUrl); + for (const fn of Object.values(node.functions ?? {})) map.set(fn.path, `${pageUrl}#${fn.name}`); + for (const attr of node.attributes ?? []) + map.set(`${node.path}.${attr.name}`, `${pageUrl}#${attr.name}`); + }; + + const visit = (mod) => { + addScope(mod, pageUrl(mod.path)); + for (const cls of Object.values(mod.classes ?? {})) addScope(cls, pageUrl(cls.path)); + for (const sub of Object.values(mod.modules ?? {})) visit(sub); + }; + visit(pkg); + return map; +} + +/** + * Resolve a cross-reference target to a page URL, or `null`. A fully-qualified + * target hits `xref` directly; an unqualified (or class-relative) target is + * resolved against the current page's scope, walking outward from the nearest + * enclosing symbol to the package root. Nearest scope wins, so resolution is + * deterministic -- a bare name only ever binds to something reachable from its + * own scope chain, never to a same-named symbol in an unrelated module. + */ +export function resolve(name, scope, xref) { + if (xref.has(name)) return xref.get(name); + const parts = scope.split('.'); + for (let i = parts.length; i > 0; i--) { + const url = xref.get(`${parts.slice(0, i).join('.')}.${name}`); + if (url) return url; + } + return null; +} diff --git a/docs/source.config.ts b/docs/source.config.ts new file mode 100644 index 0000000..9804c15 --- /dev/null +++ b/docs/source.config.ts @@ -0,0 +1,97 @@ +import { defineConfig, defineDocs } from 'fumadocs-mdx/config'; +import { metaSchema, pageSchema } from 'fumadocs-core/source/schema'; +import { z } from 'zod'; +import remarkMath from 'remark-math'; +import rehypeKatex from 'rehype-katex'; +import rehypeCitation from 'rehype-citation'; +import rehypeRaw from 'rehype-raw'; +import remarkXref from './scripts/remark-xref.mjs'; + +// The tutorial pages are generated as `.md` (not `.mdx`) and embed their +// figures as raw `<img src="data:image/png;base64,…">` tags. In md-format +// MDX leaves `<` literal, so those tags become "raw" HTML nodes — which MDX's +// internal `rehype-remove-raw` strips just after the user rehype plugins run, +// leaving the images blank in the export. `rehype-raw` reparses raw HTML into +// real hast nodes *before* that removal, so the `<img>` survives. We gate it to +// `.md` files: `.mdx` pages carry MDX JSX nodes that rehype-raw would mangle. +function rehypeRawMarkdown() { + // Pass MDX nodes through untouched: fumadocs injects an `mdxjsEsm` export + // (for `includeProcessedMarkdown`) even into md-format trees, and rehype-raw + // cannot compile MDX nodes. + const transform = rehypeRaw({ + passThrough: [ + 'mdxjsEsm', + 'mdxFlowExpression', + 'mdxTextExpression', + 'mdxJsxFlowElement', + 'mdxJsxTextElement', + ], + }); + return (tree: import('hast').Root, file: import('vfile').VFile) => { + if (file.path && !file.path.endsWith('.md')) return tree; + return transform(tree, file); + }; +} + +// `rehypeCitation` links each `[@key]` to a `#bib-key` anchor on the same page, +// but the bibliography is only written out on the references page (see +// `suppressBibliography` below). Point the links there instead. +function rehypeCitationsToReferences() { + const visit = (node: import('hast').Nodes) => { + if (node.type === 'element' && node.tagName === 'a') { + const href = node.properties?.href; + if (typeof href === 'string' && href.startsWith('#bib-')) { + node.properties.href = `/references${href}`; + } + } + if ('children' in node) node.children.forEach(visit); + }; + return (tree: import('hast').Root) => visit(tree); +} + +// You can customize Zod schemas for frontmatter and `meta.json` here +// see https://fumadocs.dev/docs/mdx/collections +export const docs = defineDocs({ + dir: 'content/docs', + docs: { + schema: pageSchema.extend({ + githubPath: z.string().optional(), + }), + postprocess: { + includeProcessedMarkdown: true, + }, + }, + meta: { + schema: metaSchema, + }, +}); + +export default defineConfig({ + mdxOptions: { + // Tutorial pages inline figures as base64 `data:` URIs; keep them as plain + // `<img src>` instead of turning images into static imports. + remarkImageOptions: { useImport: false }, + remarkPlugins: [remarkMath, remarkXref], + // `rehypeCitation` resolves `[@key]` references against bibliography.bib + // (replacing sphinxcontrib-bibtex); `rehypeKatex` renders the math nodes + // produced by `remarkMath`. Both run before the default fumadocs plugins. + rehypePlugins: (plugins) => [ + rehypeRawMarkdown, + rehypeKatex, + [ + rehypeCitation, + { + bibliography: './bibliography.bib', + linkCitations: true, + // The references page hand-writes the formatted bibliography (with + // `id="..."` anchors matching the bib keys), so suppress the + // per-page bibliography that rehype-citation would otherwise append + // to every page that uses an inline `[@key]` citation. + suppressBibliography: true, + }, + ], + rehypeCitationsToReferences, + ...plugins, + ], + }, +}); diff --git a/docs/src/app/(docs)/[[...slug]]/page.tsx b/docs/src/app/(docs)/[[...slug]]/page.tsx new file mode 100644 index 0000000..8790b32 --- /dev/null +++ b/docs/src/app/(docs)/[[...slug]]/page.tsx @@ -0,0 +1,77 @@ +import { getPageImage, getPageMarkdownUrl, source } from '@/lib/source'; +import { + DocsBody, + DocsDescription, + DocsPage, + DocsTitle, + MarkdownCopyButton, + ViewOptionsPopover, +} from 'fumadocs-ui/layouts/docs/page'; +import { notFound } from 'next/navigation'; +import { getMDXComponents } from '@/components/mdx'; +import type { Metadata } from 'next'; +import { createRelativeLink } from 'fumadocs-ui/mdx'; +import { basePath, gitConfig } from '@/lib/shared'; + +function getPageGithubPath(page: (typeof source)['$inferPage']) { + const fromFrontmatter = page.data?.githubPath; + if (typeof fromFrontmatter === 'string' && fromFrontmatter.length > 0) { + return fromFrontmatter; + } + + if (page.slugs[0] !== 'api') { + return `docs/content/docs/${page.path}`; + } + + return 'src/src_method/__init__.py'; +} + +export default async function Page(props: PageProps<'/[[...slug]]'>) { + const params = await props.params; + const page = source.getPage(params.slug); + if (!page) notFound(); + + const MDX = page.data.body; + const markdownUrl = `${basePath}${getPageMarkdownUrl(page).url}`; + + return ( + <DocsPage toc={page.data.toc} full={page.data.full}> + <DocsTitle>{page.data.title}</DocsTitle> + <DocsDescription className="mb-0">{page.data.description}</DocsDescription> + <div className="flex flex-row gap-2 items-center border-b pb-6"> + <MarkdownCopyButton markdownUrl={markdownUrl} /> + <ViewOptionsPopover + markdownUrl={markdownUrl} + githubUrl={`https://github.com/${gitConfig.user}/${gitConfig.repo}/blob/${gitConfig.branch}/${getPageGithubPath(page)}`} + /> + + </div> + <DocsBody> + <MDX + components={getMDXComponents({ + // this allows you to link to other pages with relative file paths + a: createRelativeLink(source, page), + })} + /> + </DocsBody> + </DocsPage> + ); +} + +export async function generateStaticParams() { + return source.generateParams(); +} + +export async function generateMetadata(props: PageProps<'/[[...slug]]'>): Promise<Metadata> { + const params = await props.params; + const page = source.getPage(params.slug); + if (!page) notFound(); + + return { + title: page.data.title, + description: page.data.description, + openGraph: { + images: getPageImage(page).url, + }, + }; +} diff --git a/docs/src/app/(docs)/layout.tsx b/docs/src/app/(docs)/layout.tsx new file mode 100644 index 0000000..0c2bf05 --- /dev/null +++ b/docs/src/app/(docs)/layout.tsx @@ -0,0 +1,11 @@ +import { source } from '@/lib/source'; +import { DocsLayout } from 'fumadocs-ui/layouts/docs'; +import { baseOptions } from '@/lib/layout.shared'; + +export default function Layout({ children }: LayoutProps<'/'>) { + return ( + <DocsLayout tree={source.getPageTree()} {...baseOptions()}> + {children} + </DocsLayout> + ); +} diff --git a/docs/src/app/api/search/route.ts b/docs/src/app/api/search/route.ts new file mode 100644 index 0000000..aaaff7f --- /dev/null +++ b/docs/src/app/api/search/route.ts @@ -0,0 +1,9 @@ +import { source } from '@/lib/source'; +import { createFromSource } from 'fumadocs-core/search/server'; + +export const revalidate = false; + +export const { staticGET: GET } = createFromSource(source, { + // https://docs.orama.com/docs/orama-js/supported-languages + language: 'english', +}); diff --git a/docs/src/app/global.css b/docs/src/app/global.css new file mode 100644 index 0000000..d2b4cf9 --- /dev/null +++ b/docs/src/app/global.css @@ -0,0 +1,64 @@ +@import 'tailwindcss'; +@import 'fumadocs-ui/css/neutral.css'; +@import 'fumadocs-ui/css/preset.css'; + +/* + * Kind badges on the generated Python API reference cards (see + * `src/components/py.tsx`). The `fdpy-` prefix and these two hues are inherited + * from fumadocs-python's stylesheet, which the components used to come from. + */ +@theme inline { + --color-fdpy-func: oklch(79.2% 0.209 151.711); + --color-fdpy-attribute: oklch(74% 0.238 322.16); +} + +/* + * Algorithmiq brand accents (algorithmiq.fi). + * + * The main content keeps the default Fumadocs surfaces; we only brand the + * accent colour (teal #08a89d / #1bb2b2) and tint the left sidebar with the + * brand's pale "green" (mint, oklch(95.61% .0633 170)). Token names mirror the + * Fumadocs preset (see fumadocs-ui/css/lib/default-colors.css). + */ +@theme { + --color-fd-primary: hsl(176, 84%, 34%); /* brand teal #08a89d */ + --color-fd-ring: hsl(176, 84%, 34%); +} + +.dark { + --color-fd-primary: hsl(178, 66%, 56%); /* bright teal, ≈ #1bb2b2 lifted */ + --color-fd-ring: hsl(178, 66%, 56%); +} + +/* + * Left sidebar. Its surface is painted with `bg-fd-card`, so scoping the card + * (and hover/border) tokens here tints only the sidebar, leaving the body's + * cards at their defaults. Active items still pick up the teal `--color-fd-primary`. + */ +#nd-sidebar { + --color-fd-card: oklch(95.61% 0.0633 170); /* brand --color-green (mint) */ + --color-fd-accent: hsl(160, 50%, 84%); /* deeper mint, visible on hover */ + --color-fd-accent-foreground: hsl(180, 56%, 18%); + --color-fd-border: hsla(172, 42%, 70%, 0.6); +} + +.dark #nd-sidebar { + --color-fd-card: hsl(190, 33%, 9%); /* deep teal-tinted surface */ + --color-fd-accent: hsl(188, 32%, 16%); + --color-fd-accent-foreground: hsl(178, 60%, 76%); + --color-fd-border: hsla(180, 35%, 38%, 0.3); +} + +/* Body copy reads better in GT-Planar Light than the default weight. */ +.prose p { + font-weight: 300; +} + +html { + scrollbar-gutter: stable; +} + +html > body[data-scroll-locked] { + margin-right: 0px !important; + --removed-body-scroll-bar-size: 0px !important; +} diff --git a/docs/src/app/icon.svg b/docs/src/app/icon.svg new file mode 100644 index 0000000..c1d4720 --- /dev/null +++ b/docs/src/app/icon.svg @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg id="Symbol_color_black" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 90 90"> + <defs> + <style> + .cls-1 { + fill: url(#linear-gradient); + } + </style> + <linearGradient id="linear-gradient" x1="7.18" y1="45" x2="82.82" y2="45" gradientUnits="userSpaceOnUse"> + <stop offset="0" stop-color="#000"/> + <stop offset=".04" stop-color="#000d0c"/> + <stop offset=".21" stop-color="#003c38"/> + <stop offset=".38" stop-color="#00635c"/> + <stop offset=".54" stop-color="#008178"/> + <stop offset=".7" stop-color="#00978c"/> + <stop offset=".86" stop-color="#00a498"/> + <stop offset="1" stop-color="#00a99d"/> + </linearGradient> + </defs> + <path class="cls-1" d="M64.89,19.97c2.92-3.32,5.58-5.41,7.86-5.41.96,0,1.73.39,2.35,1.19,1.71,2.22,1.98,7.34.64,12.44l-.26.99,2.59.86.31-1.1c1.88-6.75,1.65-12.56-.61-15.53-1.18-1.56-2.92-2.38-5.02-2.38-3.59,0-7.13,2.15-10.74,5.71-5.04-5.14-10.79-8.4-17.02-8.4-10.02,0-19.78,8.18-27.48,23.03-6.18,11.93-10.34,27.18-10.34,37.96,0,10.18,3.52,12.32,6.48,12.32,8.8,0,20.05-16.01,31.16-32.68,10.56,18.46,23.84,32.68,31.53,32.68,4.06,0,6.48-4.6,6.48-12.32,0-13.76-6.94-35.89-17.93-49.37ZM44.19,40.89c-.06.1-.13.19-.19.29-1.19-2.15-2.29-4.3-3.31-6.43l-.48-1-2.47,1.23.43.95c1.23,2.74,2.54,5.44,3.92,8.08-.35.52-.71,1.05-1.06,1.57-10.32,15.35-21,31.21-27.38,31.21-.74,0-1.61-1.62-1.61-6.19,0-10.62,4.65-26.21,9.24-36.12,3.96-8.54,12.3-22.88,23.71-22.88,5.48,0,10.31,3.52,14.27,8.11-4.23,4.9-8.58,11.42-13.23,18.41-.61.92-1.23,1.84-1.85,2.77ZM76.35,76.78c-2.51,0-8.09-3.28-16.19-12.47-4.76-5.4-9.37-11.74-13.36-18.31.2-.31.41-.61.61-.92l.66-1c1.45-2.17,2.87-4.32,4.24-6.42,3.4-5.18,6.72-10.23,9.81-14.28,2.69,3.81,4.84,7.89,6.36,11.14,4.71,10.04,9.47,25.65,9.47,36.08,0,4.57-.86,6.19-1.61,6.19Z"/> +</svg> diff --git a/docs/src/app/layout.tsx b/docs/src/app/layout.tsx new file mode 100644 index 0000000..a59322e --- /dev/null +++ b/docs/src/app/layout.tsx @@ -0,0 +1,27 @@ +import { RootProvider } from 'fumadocs-ui/provider/next'; +import { gtPlanar } from '@/lib/fonts'; +import { basePath, siteUrl } from '@/lib/shared'; +import type { Metadata } from 'next'; +import './global.css'; +// KaTeX styles for math rendered by rehype-katex. +import 'katex/dist/katex.min.css'; + +export const metadata: Metadata = { + metadataBase: new URL(siteUrl), +}; + +export default function Layout({ children }: LayoutProps<'/'>) { + return ( + <html lang="en" className={gtPlanar.className} suppressHydrationWarning> + <body className="flex flex-col min-h-screen"> + <RootProvider + // The docs site is exported as static files, so search must load the + // prebuilt Orama index instead of calling the dynamic query API. + search={{ options: { type: 'static', api: `${basePath}/api/search` } }} + > + {children} + </RootProvider> + </body> + </html> + ); +} diff --git a/docs/src/app/llms-full.txt/route.ts b/docs/src/app/llms-full.txt/route.ts new file mode 100644 index 0000000..d494d2c --- /dev/null +++ b/docs/src/app/llms-full.txt/route.ts @@ -0,0 +1,10 @@ +import { getLLMText, source } from '@/lib/source'; + +export const revalidate = false; + +export async function GET() { + const scan = source.getPages().map(getLLMText); + const scanned = await Promise.all(scan); + + return new Response(scanned.join('\n\n')); +} diff --git a/docs/src/app/llms.mdx/docs/[[...slug]]/route.ts b/docs/src/app/llms.mdx/docs/[[...slug]]/route.ts new file mode 100644 index 0000000..250181a --- /dev/null +++ b/docs/src/app/llms.mdx/docs/[[...slug]]/route.ts @@ -0,0 +1,23 @@ +import { getLLMText, getPageMarkdownUrl, source } from '@/lib/source'; +import { notFound } from 'next/navigation'; + +export const revalidate = false; + +export async function GET(_req: Request, { params }: RouteContext<'/llms.mdx/docs/[[...slug]]'>) { + const { slug } = await params; + const page = source.getPage(slug?.slice(0, -1)); + if (!page) notFound(); + + return new Response(await getLLMText(page), { + headers: { + 'Content-Type': 'text/markdown', + }, + }); +} + +export function generateStaticParams() { + return source.getPages().map((page) => ({ + lang: page.locale, + slug: getPageMarkdownUrl(page).segments, + })); +} diff --git a/docs/src/app/llms.txt/route.ts b/docs/src/app/llms.txt/route.ts new file mode 100644 index 0000000..6ec5475 --- /dev/null +++ b/docs/src/app/llms.txt/route.ts @@ -0,0 +1,8 @@ +import { source } from '@/lib/source'; +import { llms } from 'fumadocs-core/source'; + +export const revalidate = false; + +export async function GET() { + return new Response(await llms(source).index()); +} diff --git a/docs/src/app/og/docs/[...slug]/route.tsx b/docs/src/app/og/docs/[...slug]/route.tsx new file mode 100644 index 0000000..877166d --- /dev/null +++ b/docs/src/app/og/docs/[...slug]/route.tsx @@ -0,0 +1,28 @@ +import { getPageImage, source } from '@/lib/source'; +import { notFound } from 'next/navigation'; +import { ImageResponse } from 'next/og'; +import { generate as DefaultImage } from 'fumadocs-ui/og'; +import { appName } from '@/lib/shared'; + +export const revalidate = false; + +export async function GET(_req: Request, { params }: RouteContext<'/og/docs/[...slug]'>) { + const { slug } = await params; + const page = source.getPage(slug.slice(0, -1)); + if (!page) notFound(); + + return new ImageResponse( + <DefaultImage title={page.data.title} description={page.data.description} site={appName} />, + { + width: 1200, + height: 630, + }, + ); +} + +export function generateStaticParams() { + return source.getPages().map((page) => ({ + lang: page.locale, + slug: getPageImage(page).segments, + })); +} diff --git a/docs/src/components/figure.tsx b/docs/src/components/figure.tsx new file mode 100644 index 0000000..4a5909f --- /dev/null +++ b/docs/src/components/figure.tsx @@ -0,0 +1,22 @@ +// Fumadocs ships no figure/caption pair, so the benchmarks page (and any other +// page with images) rolled its own caption as a plain paragraph after the +// image. This gives that pattern a real `<figure>`/`<figcaption>` and matches +// it visually to the muted, small-text captions already used for API cards. + +import type { ReactNode } from 'react'; + +export function Figure({ children }: { children?: ReactNode }) { + // Markdown wraps a lone image in a `<p>`, and prose typography puts its own + // margin on both: `mb-0` on the `<p>` and `my-0` on the `<img>` (a block + // element with no border/padding around it, so its margin would otherwise + // collapse straight through the `<p>` and swamp `Caption`'s margin-top). + return <figure className="my-6 [&>p]:mb-0 [&_img]:my-0">{children}</figure>; +} + +export function Caption({ children }: { children?: ReactNode }) { + return ( + <figcaption className="text-fd-muted-foreground text-sm mt-4 prose-no-margin"> + {children} + </figcaption> + ); +} diff --git a/docs/src/components/logo.tsx b/docs/src/components/logo.tsx new file mode 100644 index 0000000..88e0ad5 --- /dev/null +++ b/docs/src/components/logo.tsx @@ -0,0 +1,28 @@ +/** + * Algorithmiq's "wave" symbol (from algorithmiq.fi/favicon.svg), redrawn with + * `currentColor` so it inherits the brand teal and stays legible in both light + * and dark mode. The wordmark renders the app name in the inherited GT-Planar. + */ +export function AlgorithmiqMark({ className }: { className?: string }) { + return ( + <svg + viewBox="0 0 90 90" + role="img" + aria-label="Algorithmiq" + fill="currentColor" + className={className} + > + <path d="M64.89,19.97c2.92-3.32,5.58-5.41,7.86-5.41.96,0,1.73.39,2.35,1.19,1.71,2.22,1.98,7.34.64,12.44l-.26.99,2.59.86.31-1.1c1.88-6.75,1.65-12.56-.61-15.53-1.18-1.56-2.92-2.38-5.02-2.38-3.59,0-7.13,2.15-10.74,5.71-5.04-5.14-10.79-8.4-17.02-8.4-10.02,0-19.78,8.18-27.48,23.03-6.18,11.93-10.34,27.18-10.34,37.96,0,10.18,3.52,12.32,6.48,12.32,8.8,0,20.05-16.01,31.16-32.68,10.56,18.46,23.84,32.68,31.53,32.68,4.06,0,6.48-4.6,6.48-12.32,0-13.76-6.94-35.89-17.93-49.37ZM44.19,40.89c-.06.1-.13.19-.19.29-1.19-2.15-2.29-4.3-3.31-6.43l-.48-1-2.47,1.23.43.95c1.23,2.74,2.54,5.44,3.92,8.08-.35.52-.71,1.05-1.06,1.57-10.32,15.35-21,31.21-27.38,31.21-.74,0-1.61-1.62-1.61-6.19,0-10.62,4.65-26.21,9.24-36.12,3.96-8.54,12.3-22.88,23.71-22.88,5.48,0,10.31,3.52,14.27,8.11-4.23,4.9-8.58,11.42-13.23,18.41-.61.92-1.23,1.84-1.85,2.77ZM76.35,76.78c-2.51,0-8.09-3.28-16.19-12.47-4.76-5.4-9.37-11.74-13.36-18.31.2-.31.41-.61.61-.92l.66-1c1.45-2.17,2.87-4.32,4.24-6.42,3.4-5.18,6.72-10.23,9.81-14.28,2.69,3.81,4.84,7.89,6.36,11.14,4.71,10.04,9.47,25.65,9.47,36.08,0,4.57-.86,6.19-1.61,6.19Z" /> + </svg> + ); +} + +/** Nav-bar brand lockup: Algorithmiq mark + package wordmark. */ +export function Logo({ name }: { name: string }) { + return ( + <span className="inline-flex items-center gap-2"> + <AlgorithmiqMark className="size-5 text-fd-primary" /> + <span className="font-medium">{name}</span> + </span> + ); +} diff --git a/docs/src/components/mdx.tsx b/docs/src/components/mdx.tsx new file mode 100644 index 0000000..053f110 --- /dev/null +++ b/docs/src/components/mdx.tsx @@ -0,0 +1,37 @@ +import defaultMdxComponents from 'fumadocs-ui/mdx'; +import * as Py from '@/components/py'; +import { Figure, Caption } from '@/components/figure'; +import type { MDXComponents } from 'mdx/types'; +import type { ImgHTMLAttributes } from 'react'; + +// The tutorial pages embed matplotlib figures as raw `<img src="data:…">` tags +// with no intrinsic dimensions. fumadocs' default `img` wraps Next.js' `Image`, +// which throws ("missing required width property") without width/height. Render +// those as a plain `<img>`; anything that does carry width/height (real image +// files) still goes through the optimized fumadocs component. +function Img({ src, ...props }: ImgHTMLAttributes<HTMLImageElement>) { + const DefaultImg = defaultMdxComponents.img!; + if (props.width == null && props.height == null) { + // eslint-disable-next-line @next/next/no-img-element + return <img src={src} {...props} />; + } + return <DefaultImg src={src} {...props} />; +} + +export function getMDXComponents(components?: MDXComponents) { + return { + ...defaultMdxComponents, + // Py* components (plus Tab/Tabs) used by the generated Python API pages. + ...Py, + Figure, + Caption, + img: Img, + ...components, + } satisfies MDXComponents; +} + +export const useMDXComponents = getMDXComponents; + +declare global { + type MDXProvidedComponents = ReturnType<typeof getMDXComponents>; +} diff --git a/docs/src/components/py.tsx b/docs/src/components/py.tsx new file mode 100644 index 0000000..6a9c86e --- /dev/null +++ b/docs/src/components/py.tsx @@ -0,0 +1,155 @@ +// The component vocabulary of the generated Python API reference: the MDX under +// `content/docs/api/` is written in terms of these, by `scripts/api-mdx.mjs`. +// +// Derived from the React half of fumadocs-python (MIT, (c) 2023 Fuma); see +// `scripts/gen_api_dump.py` for the full notice. +// +// `PyFunction` and `PyAttribute` carry `id={name}`: that is the `#<member>` +// fragment `buildXrefMap` (scripts/xref.mjs) appends for members, which are +// documented inline on their parent's page rather than on one of their own. + +import { + Collapsible, + CollapsibleContent, + CollapsibleTrigger, +} from 'fumadocs-ui/components/ui/collapsible'; +import { buttonVariants } from 'fumadocs-ui/components/ui/button'; +import { highlight } from 'fumadocs-core/highlight'; +import { ChevronRight } from 'lucide-react'; +import { cn } from '@/lib/cn'; +import type { ComponentProps, ReactNode } from 'react'; + +export { Tab, Tabs } from 'fumadocs-ui/components/tabs'; + +// The `scroll-mt` keeps a card clear of the sticky header when an anchor jumps +// to it, so it belongs with the card surface itself, not the anchored members. +const card = 'bg-fd-card rounded-lg text-sm my-6 p-3 border scroll-mt-24'; + +/** The kind badge in a card's header; the colours come from `global.css`. */ +function Badge({ kind }: { kind: 'func' | 'attribute' | 'param' }) { + const color = { + func: 'bg-fdpy-func/10 text-fdpy-func border-fdpy-func/50', + attribute: 'bg-fdpy-attribute/10 text-fdpy-attribute border-fdpy-attribute/50', + param: 'bg-fd-primary/10 text-fd-primary border-fd-primary/10', + }[kind]; + return ( + <code className={cn('text-xs font-medium border p-1 rounded-lg not-prose', color)}>{kind}</code> + ); +} + +/** + * A syntax-highlighted code span. Async (it awaits shiki), so it only ever + * renders on the server -- which is fine, every caller here is a server + * component. Everything rendered here is Python, so the language is not a prop. + */ +async function InlineCode({ code, ...rest }: { code: string } & ComponentProps<'span'>) { + return highlight(code, { + lang: 'python', + components: { + pre: (props) => <span {...props} {...rest} className={cn(rest.className, props.className)} />, + }, + }); +} + +export function PyFunction(props: { name: string; type: string; children?: ReactNode }) { + return ( + <figure id={props.name} className={card}> + <div className="flex gap-2 items-center font-mono flex-wrap mb-4"> + <Badge kind="func" /> + {props.name} + <InlineCode + className="not-prose text-xs text-fd-muted-foreground" + code={props.type} + /> + </div> + <div className="text-fd-muted-foreground prose-no-margin">{props.children}</div> + </figure> + ); +} + +export function PyAttribute(props: { + name: string; + type?: string; + value?: string; + children?: ReactNode; +}) { + return ( + <figure id={props.name} className={card}> + <div className="flex gap-2 items-center flex-wrap font-mono mb-4"> + <Badge kind="attribute" /> + {props.name} + {props.type && ( + <InlineCode + className="not-prose text-fd-muted-foreground text-xs" + code={props.type} + /> + )} + </div> + <div className="text-fd-muted-foreground prose-no-margin"> + {props.value && ( + <InlineCode className="not-prose text-xs" code={`= ${props.value}`} /> + )} + {props.children} + </div> + </figure> + ); +} + +export function PyParameter(props: { + name: string; + type?: string; + value?: string; + children?: ReactNode; +}) { + return ( + // Square middle corners, rounded only at the ends, so the parameters of one + // function stack into a single seamless list. + <div + data-parameter="" + className="bg-fd-secondary text-sm p-3 border shadow-md rounded-none first:rounded-t-lg last:rounded-b-lg" + > + <div className="flex flex-wrap gap-2 items-center font-mono text-fd-foreground"> + <Badge kind="param" /> + {props.name} + {props.type && ( + <InlineCode + className="ms-auto text-fd-muted-foreground not-prose text-xs" + code={props.type} + /> + )} + </div> + <div className="text-fd-muted-foreground prose-no-margin mt-4 empty:hidden"> + {props.value ? ( + <InlineCode code={`= ${props.value}`} className="not-prose text-xs" /> + ) : null} + {props.children} + </div> + </div> + ); +} + +export function PyFunctionReturn({ type, children }: { type?: string; children?: ReactNode }) { + return ( + <div className="border bg-fd-secondary rounded-lg p-3 mt-2"> + <div className="flex flex-wrap gap-2 not-prose"> + <p className="font-medium me-auto">Returns</p> + <InlineCode code={type ?? 'None'} className="text-xs" /> + </div> + {children} + </div> + ); +} + +export function PySourceCode({ children }: { children?: ReactNode }) { + return ( + <Collapsible className="my-6"> + <CollapsibleTrigger + className={cn(buttonVariants({ color: 'secondary', size: 'sm', className: 'group' }))} + > + Source Code + <ChevronRight className="size-3.5 text-fd-muted-foreground group-data-[state=open]:rotate-90" /> + </CollapsibleTrigger> + <CollapsibleContent className="prose-no-margin">{children}</CollapsibleContent> + </Collapsible> + ); +} diff --git a/docs/src/lib/cn.ts b/docs/src/lib/cn.ts new file mode 100644 index 0000000..241ffb3 --- /dev/null +++ b/docs/src/lib/cn.ts @@ -0,0 +1 @@ +export { cn } from 'cnfast'; diff --git a/docs/src/lib/fonts.ts b/docs/src/lib/fonts.ts new file mode 100644 index 0000000..f3a074d --- /dev/null +++ b/docs/src/lib/fonts.ts @@ -0,0 +1,27 @@ +import localFont from 'next/font/local'; + +/** + * Algorithmiq's brand typeface, GT-Planar (self-hosted woff2). + */ +export const gtPlanar = localFont({ + src: [ + { + path: '../../public/fonts/gt-planar/GT-Planar-Thin.woff2', + weight: '100', + style: 'normal', + }, + { + path: '../../public/fonts/gt-planar/GT-Planar-Light.woff2', + weight: '300', + style: 'normal', + }, + { + path: '../../public/fonts/gt-planar/GT-Planar-Regular.woff2', + weight: '400', + style: 'normal', + }, + ], + variable: '--font-gt-planar', + display: 'swap', + fallback: ['ui-sans-serif', 'system-ui', 'sans-serif'], +}); diff --git a/docs/src/lib/layout.shared.tsx b/docs/src/lib/layout.shared.tsx new file mode 100644 index 0000000..b38ec01 --- /dev/null +++ b/docs/src/lib/layout.shared.tsx @@ -0,0 +1,13 @@ +import type { BaseLayoutProps } from 'fumadocs-ui/layouts/shared'; +import { Logo } from '@/components/logo'; +import { appName, gitConfig } from './shared'; + +export function baseOptions(): BaseLayoutProps { + return { + nav: { + // JSX supported + title: <Logo name={appName} />, + }, + githubUrl: `https://github.com/${gitConfig.user}/${gitConfig.repo}`, + }; +} diff --git a/docs/src/lib/shared.ts b/docs/src/lib/shared.ts new file mode 100644 index 0000000..ac1fa5c --- /dev/null +++ b/docs/src/lib/shared.ts @@ -0,0 +1,18 @@ +// The static export is served from a subpath on GitHub Pages +// (algorithmiq.github.io/src-method), which Next.js applies to its own links and +// assets but not to URLs we fetch by hand; prefix those with `basePath`. +export const basePath = process.env.NEXT_PUBLIC_BASE_PATH ?? ''; + +// Absolute URL of the deployed site, for the Open Graph images. +export const siteUrl = `https://algorithmiq.github.io${basePath}`; + +export const appName = 'src_method'; +export const docsRoute = '/'; +export const docsImageRoute = '/og/docs'; +export const docsContentRoute = '/llms.mdx/docs'; + +export const gitConfig = { + user: 'Algorithmiq', + repo: 'src-method', + branch: 'main', +}; diff --git a/docs/src/lib/source.ts b/docs/src/lib/source.ts new file mode 100644 index 0000000..a00a3fc --- /dev/null +++ b/docs/src/lib/source.ts @@ -0,0 +1,37 @@ +import { docs } from 'collections/server'; +import { loader } from 'fumadocs-core/source'; +import { lucideIconsPlugin } from 'fumadocs-core/source/lucide-icons'; +import { docsContentRoute, docsImageRoute, docsRoute } from './shared'; + +// See https://fumadocs.dev/docs/headless/source-api for more info +export const source = loader({ + baseUrl: docsRoute, + source: docs.toFumadocsSource(), + plugins: [lucideIconsPlugin()], +}); + +export function getPageImage(page: (typeof source)['$inferPage']) { + const segments = [...page.slugs, 'image.png']; + + return { + segments, + url: `${docsImageRoute}/${segments.join('/')}`, + }; +} + +export function getPageMarkdownUrl(page: (typeof source)['$inferPage']) { + const segments = [...page.slugs, 'content.md']; + + return { + segments, + url: `${docsContentRoute}/${segments.join('/')}`, + }; +} + +export async function getLLMText(page: (typeof source)['$inferPage']) { + const processed = await page.data.getText('processed'); + + return `# ${page.data.title} (${page.url}) + +${processed}`; +} diff --git a/docs/stylesheets/code_select.css b/docs/stylesheets/code_select.css deleted file mode 100644 index 261023a..0000000 --- a/docs/stylesheets/code_select.css +++ /dev/null @@ -1,5 +0,0 @@ -.highlight .gp, -.highlight .go { - /* Generic.Prompt, Generic.Output */ - user-select: none; -} diff --git a/docs/stylesheets/extra.css b/docs/stylesheets/extra.css deleted file mode 100644 index 2117f39..0000000 --- a/docs/stylesheets/extra.css +++ /dev/null @@ -1,10 +0,0 @@ -[data-md-color-scheme="algorithmiq"] { - --md-primary-fg-color: #3b667d; - --md-accent-fg-color: #54b6b8; -} - -[data-md-color-scheme="slate"] { - --md-primary-fg-color: #3b667d; - --md-accent-fg-color: #54b6b8; - --md-hue: 210; -} diff --git a/docs/tsconfig.json b/docs/tsconfig.json new file mode 100644 index 0000000..4556765 --- /dev/null +++ b/docs/tsconfig.json @@ -0,0 +1,45 @@ +{ + "compilerOptions": { + "target": "ESNext", + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "react-jsx", + "incremental": true, + "paths": { + "@/*": [ + "./src/*" + ], + "collections/*": [ + "./.source/*" + ] + }, + "plugins": [ + { + "name": "next" + } + ] + }, + "include": [ + "next-env.d.ts", + "**/*.ts", + "**/*.tsx", + ".next/types/**/*.ts", + ".next/dev/types/**/*.ts" + ], + "exclude": [ + "node_modules" + ] +} diff --git a/flake.nix b/flake.nix index cc7c8aa..27945b6 100644 --- a/flake.nix +++ b/flake.nix @@ -21,6 +21,8 @@ pkgs.uv pkgs.git pkgs.gh + # Builds the documentation site under docs/. + pkgs.nodejs_22 ]; env = { diff --git a/mkdocs.yml b/mkdocs.yml deleted file mode 100644 index cda7c5b..0000000 --- a/mkdocs.yml +++ /dev/null @@ -1,86 +0,0 @@ -site_name: src_method -repo_url: https://github.com/Algorithmiq/src-method - -watch: - - src/src_method -nav: - - Home: index.md - - 'Developer Guide': - - 'Versioning Scheme': developer-guide/versioning.md - - 'Managing Dependencies': developer-guide/dependencies.md - - 'Writing Tests': developer-guide/testing.md - - Code Reference: reference/ - -plugins: - - search - - mkdocs-jupyter: - include: ["docs/tutorials/*.ipynb"] - execute: true - allow_errors: false - include_requirejs: true - include_source: true - remove_tag_config: - remove_input_tags: - - remove_cell - - gen-files: - scripts: - - docs/gen_ref_pages.py - - literate-nav: - nav_file: SUMMARY.md - - section-index - - mkdocstrings: - handlers: - python: - paths: [src] - options: - docstring_section_style: spacy - show_submodules: false - heading_level: 3 - merge_init_into_class: true - show_category_heading: true - separate_signature: true - show_signature_annotations: true - inherited_members: true - import: - - https://qiskit.org/documentation/objects.inv - - https://numpy.org/doc/stable/objects.inv - - https://docs.python.org/3/objects.inv - - https://docs.scipy.org/doc/scipy/reference/objects.inv -theme: - name: material - font: - text: Open Sans - palette: - # Palette toggle for light mode - - scheme: algorithmiq - toggle: - icon: material/brightness-7 - name: Switch to dark mode - - # Palette toggle for dark mode - - scheme: slate - toggle: - icon: material/brightness-4 - name: Switch to light mode - icon: - repo: fontawesome/brands/github - logo: assets/algo_symbol.png - favicon: assets/algo_symbol.png -extra_css: - - stylesheets/extra.css - - stylesheets/code_select.css -markdown_extensions: - - smarty - - def_list - - admonition - - pymdownx.details - - toc: - permalink: "#" - - pymdownx.arithmatex: - generic: true - - pymdownx.superfences - - pymdownx.magiclink - - footnotes -extra_javascript: - - javascripts/config.js - - https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js diff --git a/pyproject.toml b/pyproject.toml index 161c7c7..ea2e7a9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -86,14 +86,11 @@ interactive = [ "pylatexenc", ] docs = [ - "black[jupyter]>=26.5.1", - "mkdocs-gen-files>=0.5.0", - "mkdocs-jupyter>=0.24.2", - "mkdocs-literate-nav>=0.6.0", - "mkdocs-material>=9", - "mkdocs-section-index>=0.3.5", - "mkdocs>=1.5.1", - "mkdocstrings-python>=1.2.1", + # Builds the Fumadocs site under docs/; see docs/README.md. + "griffelib>=2.2,<3", + "nbconvert", + "pytest-markdown-docs", + { include-group = "test" }, { include-group = "interactive" }, ] diff --git a/uv.lock b/uv.lock index cae5c32..6b66093 100644 --- a/uv.lock +++ b/uv.lock @@ -52,29 +52,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ad/59/3044cc591035b2d2962826a9ae323e02f1dcb07a821d217ae5ccd9b94481/autoray-0.8.10-py3-none-any.whl", hash = "sha256:033f4ba37e2278ece9c50be4a42abe0d91d5c611194d90904c4e6d980300454a", size = 939985, upload-time = "2026-03-06T22:36:38.027Z" }, ] -[[package]] -name = "babel" -version = "2.18.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/7d/b2/51899539b6ceeeb420d40ed3cd4b7a40519404f9baf3d4ac99dc413a834b/babel-2.18.0.tar.gz", hash = "sha256:b80b99a14bd085fcacfa15c9165f651fbb3406e66cc603abf11c5750937c992d", size = 9959554, upload-time = "2026-02-01T12:30:56.078Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/77/f5/21d2de20e8b8b0408f0681956ca2c69f1320a3848ac50e6e7f39c6159675/babel-2.18.0-py3-none-any.whl", hash = "sha256:e2b422b277c2b9a9630c1d7903c2a00d0830c409c59ac8cae9081c92f1aeba35", size = 10196845, upload-time = "2026-02-01T12:30:53.445Z" }, -] - -[[package]] -name = "backrefs" -version = "6.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/4e/a6/e325ec73b638d3ede4421b5445d4a0b8b219481826cc079d510100af356c/backrefs-6.2.tar.gz", hash = "sha256:f44ff4d48808b243b6c0cdc6231e22195c32f77046018141556c66f8bab72a49", size = 7012303, upload-time = "2026-02-16T19:10:15.828Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/1b/39/3765df263e08a4df37f4f43cb5aa3c6c17a4bdd42ecfe841e04c26037171/backrefs-6.2-py310-none-any.whl", hash = "sha256:0fdc7b012420b6b144410342caeb8adc54c6866cf12064abc9bb211302e496f8", size = 381075, upload-time = "2026-02-16T19:10:04.322Z" }, - { url = "https://files.pythonhosted.org/packages/0f/f0/35240571e1b67ffb19dafb29ab34150b6f59f93f717b041082cdb1bfceb1/backrefs-6.2-py311-none-any.whl", hash = "sha256:08aa7fae530c6b2361d7bdcbda1a7c454e330cc9dbcd03f5c23205e430e5c3be", size = 392874, upload-time = "2026-02-16T19:10:06.314Z" }, - { url = "https://files.pythonhosted.org/packages/e3/63/77e8c9745b4d227cce9f5e0a6f68041278c5f9b18588b35905f5f19c1beb/backrefs-6.2-py312-none-any.whl", hash = "sha256:c3f4b9cb2af8cda0d87ab4f57800b57b95428488477be164dd2b47be54db0c90", size = 398787, upload-time = "2026-02-16T19:10:08.274Z" }, - { url = "https://files.pythonhosted.org/packages/c5/71/c754b1737ad99102e03fa3235acb6cb6d3ac9d6f596cbc3e5f236705abd8/backrefs-6.2-py313-none-any.whl", hash = "sha256:12df81596ab511f783b7d87c043ce26bc5b0288cf3bb03610fe76b8189282b2b", size = 400747, upload-time = "2026-02-16T19:10:09.791Z" }, - { url = "https://files.pythonhosted.org/packages/af/75/be12ba31a6eb20dccef2320cd8ccb3f7d9013b68ba4c70156259fee9e409/backrefs-6.2-py314-none-any.whl", hash = "sha256:e5f805ae09819caa1aa0623b4a83790e7028604aa2b8c73ba602c4454e665de7", size = 412602, upload-time = "2026-02-16T19:10:12.317Z" }, - { url = "https://files.pythonhosted.org/packages/21/f8/d02f650c47d05034dcd6f9c8cf94f39598b7a89c00ecda0ecb2911bc27e9/backrefs-6.2-py39-none-any.whl", hash = "sha256:664e33cd88c6840b7625b826ecf2555f32d491800900f5a541f772c485f7cda7", size = 381077, upload-time = "2026-02-16T19:10:13.74Z" }, -] - [[package]] name = "beautifulsoup4" version = "4.14.3" @@ -88,50 +65,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/1a/39/47f9197bdd44df24d67ac8893641e16f386c984a0619ef2ee4c51fbbc019/beautifulsoup4-4.14.3-py3-none-any.whl", hash = "sha256:0918bfe44902e6ad8d57732ba310582e98da931428d231a5ecb9e7c703a735bb", size = 107721, upload-time = "2025-11-30T15:08:24.087Z" }, ] -[[package]] -name = "black" -version = "26.5.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "click" }, - { name = "mypy-extensions" }, - { name = "packaging" }, - { name = "pathspec" }, - { name = "platformdirs" }, - { name = "pytokens" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/c0/37/5628dd55bf2b34257fc7603f0fe97c40e3aaf24265f416a9c85c95ca1436/black-26.5.1.tar.gz", hash = "sha256:dd321f668053961824bcc1be1cc1df748b2d7e4fa28086b08331e577b0100a73", size = 679439, upload-time = "2026-05-18T16:53:36.107Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/4b/96/3c3e09f09f44a37aac36b178a279cd19aa7001bd796187a7b162a294c81f/black-26.5.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:96ae2c733b2aabdd9986e2c5df628ff3473676cd1c5faded1ff496cf6d74083c", size = 1970639, upload-time = "2026-05-18T17:05:11.461Z" }, - { url = "https://files.pythonhosted.org/packages/83/ea/5ad117b9ee3ecd933c712bcbae610006e5b7cc9f41c526cd7ed3b6c4124c/black-26.5.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0e48b87e03bf109288e55cfceadcfa15ff5470aca2851a851950ed2926f450d7", size = 1792130, upload-time = "2026-05-18T17:05:12.983Z" }, - { url = "https://files.pythonhosted.org/packages/06/3a/7c448bc623fcdfa96672531beb5a616ea5e64f6975955254d7731ffb0ad9/black-26.5.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5119fa92ae61f786e8c3662fd60aece1d0a2dd5cca5d0c79417a95e7a4272a59", size = 1846134, upload-time = "2026-05-18T17:05:14.506Z" }, - { url = "https://files.pythonhosted.org/packages/a1/5b/0b39b3a5917f0657ac014ad2edb58c139553a478adfe7f817abf1622ff6e/black-26.5.1-cp311-cp311-win_amd64.whl", hash = "sha256:30d3c14661f2792e9142cce3eeeb1cbc175b3eb5f733be0c8eeb99651e52b0c3", size = 1478883, upload-time = "2026-05-18T17:05:16.542Z" }, - { url = "https://files.pythonhosted.org/packages/4c/48/dc222692e0f95030db1bbfb6c857e76858bad09058221ea7aae815255327/black-26.5.1-cp311-cp311-win_arm64.whl", hash = "sha256:1ef92b76f7733f282fd096ea406200b5a286c42947412b0eaff3a74e3616cefe", size = 1277776, upload-time = "2026-05-18T17:05:18.029Z" }, - { url = "https://files.pythonhosted.org/packages/24/99/7744b906703228264ef73bdd534df88ec1ef3de45c4e78f6d31b9e32d0c9/black-26.5.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4ad6fa01f941920f54f2bbb35f3df7673428a0ef98a0b0840c2eaef3b110efa8", size = 2012518, upload-time = "2026-05-18T17:05:20.108Z" }, - { url = "https://files.pythonhosted.org/packages/b7/c0/c5a3b1636dfd09c42534f2b3cf33506814f6d3e066fb0879ffa16c1ae860/black-26.5.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3915f256e75a2d7cf88d8953d37f780455dc586cc72dee059c528fe77f581217", size = 1816016, upload-time = "2026-05-18T17:05:21.84Z" }, - { url = "https://files.pythonhosted.org/packages/1f/0e/36044316b65ca471d3bb6d3703fd06fb50c6b727c3562f6a5a3153634f88/black-26.5.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d98d4137277c75dfb898ec8d846c4fd68ba1e9cf77f95e2865c203dc18f4c3d", size = 1884150, upload-time = "2026-05-18T17:05:23.546Z" }, - { url = "https://files.pythonhosted.org/packages/b3/33/dafc5808c2af43672912111d7c3354af1615f7e2be3bed7a878461abbe4d/black-26.5.1-cp312-cp312-win_amd64.whl", hash = "sha256:a1dca32d9f1784af512a13410ec204c6f7f0aa9797a111c42e1c03449821c264", size = 1486825, upload-time = "2026-05-18T17:05:25.004Z" }, - { url = "https://files.pythonhosted.org/packages/82/14/b965ee6ad2a311f28bdbf692def3ee9848d2ae289dab28b27657fcee3e78/black-26.5.1-cp312-cp312-win_arm64.whl", hash = "sha256:1037d5ac7b7b310b2632ad867ec8d0e4c4819dcdb0b820f63135da746a24e418", size = 1288646, upload-time = "2026-05-18T17:05:26.477Z" }, - { url = "https://files.pythonhosted.org/packages/3f/5c/c384363980e11e25ca6b93205949bb331fbf35f4e0dbec376dfa6326cec8/black-26.5.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:2b36cf2ddf5566e205f6535f782a62194a184d33e175b64ae8c40b1737522be3", size = 2009020, upload-time = "2026-05-18T17:05:28.132Z" }, - { url = "https://files.pythonhosted.org/packages/0b/df/9f31c5e0babbfed77d505fc5d120beb98b21b33feaeded3924ea941fe360/black-26.5.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1f7ea64ebfa01b50f693508fc39f875e264446d3b097088f84f203b9d09618a0", size = 1813335, upload-time = "2026-05-18T17:05:31.266Z" }, - { url = "https://files.pythonhosted.org/packages/fb/24/8e7b9a2fa61b0afd82209efe937557d180a1fa055bd7f6161eb9defc3719/black-26.5.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ecb3e624844c798144e9bd986954e0adc81d8911a1f30f375e1252fe26e8c294", size = 1881614, upload-time = "2026-05-18T17:05:32.718Z" }, - { url = "https://files.pythonhosted.org/packages/49/ad/b4e0d9365ba8ac34f6bbab62a4b1b2dd5d618fac3fa1b8db968c844201b5/black-26.5.1-cp313-cp313-win_amd64.whl", hash = "sha256:e1a26503279b6b310669fb0b219c39e4820b77e8189fe80f522bb511f247db0a", size = 1488925, upload-time = "2026-05-18T17:05:34.259Z" }, - { url = "https://files.pythonhosted.org/packages/a1/4b/652b859bf5df88a751c30451b09338f7fd26a77d1271c666992f836b7711/black-26.5.1-cp313-cp313-win_arm64.whl", hash = "sha256:5c34b25da232ead53a6f335b76dbea124f4d152ad568b9080d6f944bc2b34b52", size = 1289883, upload-time = "2026-05-18T17:05:36.019Z" }, - { url = "https://files.pythonhosted.org/packages/a6/16/a8da8eb208c51c7f4ce74609a45d0dcc6d8a2141e45e81ee5289d1bb0d59/black-26.5.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:e88976690a64b0af98312ca958415849cb42423423c5f2ee74af4b49a97a2168", size = 2004800, upload-time = "2026-05-18T17:05:38.182Z" }, - { url = "https://files.pythonhosted.org/packages/11/8a/a479296a19e383b70a725882a6cf3d786540601ff03cabbaaf1cce864c5a/black-26.5.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:32d5ea7f6c8bdfa6e648326ebca1f02b0764e2a029edc6f8dce2627e19d468c3", size = 1815576, upload-time = "2026-05-18T17:05:40.309Z" }, - { url = "https://files.pythonhosted.org/packages/81/6b/cfaf3d39f25132c156a068f6b805576c9103a84086019507c70e1911ee7d/black-26.5.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ea8d16dc41655aa113cd64665e7219446cd7e4ff2248d7178eaa905190c86b18", size = 1877927, upload-time = "2026-05-18T17:05:42.463Z" }, - { url = "https://files.pythonhosted.org/packages/66/76/302e313964bcff7e28df329d39f84f5270095730d85ff0acc260610a0d82/black-26.5.1-cp314-cp314-win_amd64.whl", hash = "sha256:577f21094ea469ef92ec1adaf2c9441a226d2144d01a5be2fa823cecf6543e50", size = 1511860, upload-time = "2026-05-18T17:05:43.943Z" }, - { url = "https://files.pythonhosted.org/packages/27/4e/a3827e35e0e567f9f9ee59e2a0ab979267dca98718f25547ca8c6733afd4/black-26.5.1-cp314-cp314-win_arm64.whl", hash = "sha256:ed1a20af114c301a0269bf01163d51dbef72737fd65f850001e7cbe7f3c7abae", size = 1316632, upload-time = "2026-05-18T17:05:45.521Z" }, - { url = "https://files.pythonhosted.org/packages/94/51/f975cae76d44274cc2868dc9040ac5d58d464784610234455b4e7b19c6ef/black-26.5.1-py3-none-any.whl", hash = "sha256:4ed7f7da04046d2e488437170797d3b4a4ad83906683bcb7dfc68b673bbce5e2", size = 213693, upload-time = "2026-05-18T16:53:33.964Z" }, -] - -[package.optional-dependencies] -jupyter = [ - { name = "ipython", version = "9.12.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" }, - { name = "ipython", version = "9.17.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12'" }, - { name = "tokenize-rt" }, -] - [[package]] name = "bleach" version = "6.4.0" @@ -149,15 +82,6 @@ css = [ { name = "tinycss2" }, ] -[[package]] -name = "certifi" -version = "2026.4.22" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/25/ee/6caf7a40c36a1220410afe15a1cc64993a1f864871f698c0f93acb72842a/certifi-2026.4.22.tar.gz", hash = "sha256:8d455352a37b71bf76a79caa83a3d6c25afee4a385d632127b6afb3963f1c580", size = 137077, upload-time = "2026-04-22T11:26:11.191Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/22/30/7cd8fdcdfbc5b869528b079bfb76dcdf6056b1a2097a662e5e8c04f42965/certifi-2026.4.22-py3-none-any.whl", hash = "sha256:3cb2210c8f88ba2318d29b0388d1023c8492ff72ecdde4ebdaddbb13a31b1c4a", size = 135707, upload-time = "2026-04-22T11:26:09.372Z" }, -] - [[package]] name = "cffi" version = "2.0.0" @@ -228,107 +152,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ae/3a/dbeec9d1ee0844c679f6bb5d6ad4e9f198b1224f4e7a32825f47f6192b0c/cffi-2.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0a1527a803f0a659de1af2e1fd700213caba79377e27e4693648c2923da066f9", size = 184195, upload-time = "2025-09-08T23:23:43.004Z" }, ] -[[package]] -name = "charset-normalizer" -version = "3.4.7" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e7/a1/67fe25fac3c7642725500a3f6cfe5821ad557c3abb11c9d20d12c7008d3e/charset_normalizer-3.4.7.tar.gz", hash = "sha256:ae89db9e5f98a11a4bf50407d4363e7b09b31e55bc117b4f7d80aab97ba009e5", size = 144271, upload-time = "2026-04-02T09:28:39.342Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/c2/d7/b5b7020a0565c2e9fa8c09f4b5fa6232feb326b8c20081ccded47ea368fd/charset_normalizer-3.4.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7641bb8895e77f921102f72833904dcd9901df5d6d72a2ab8f31d04b7e51e4e7", size = 309705, upload-time = "2026-04-02T09:26:02.191Z" }, - { url = "https://files.pythonhosted.org/packages/5a/53/58c29116c340e5456724ecd2fff4196d236b98f3da97b404bc5e51ac3493/charset_normalizer-3.4.7-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:202389074300232baeb53ae2569a60901f7efadd4245cf3a3bf0617d60b439d7", size = 206419, upload-time = "2026-04-02T09:26:03.583Z" }, - { url = "https://files.pythonhosted.org/packages/b2/02/e8146dc6591a37a00e5144c63f29fb7c97a734ea8a111190783c0e60ab63/charset_normalizer-3.4.7-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:30b8d1d8c52a48c2c5690e152c169b673487a2a58de1ec7393196753063fcd5e", size = 227901, upload-time = "2026-04-02T09:26:04.738Z" }, - { url = "https://files.pythonhosted.org/packages/fb/73/77486c4cd58f1267bf17db420e930c9afa1b3be3fe8c8b8ebbebc9624359/charset_normalizer-3.4.7-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:532bc9bf33a68613fd7d65e4b1c71a6a38d7d42604ecf239c77392e9b4e8998c", size = 222742, upload-time = "2026-04-02T09:26:06.36Z" }, - { url = "https://files.pythonhosted.org/packages/a1/fa/f74eb381a7d94ded44739e9d94de18dc5edc9c17fb8c11f0a6890696c0a9/charset_normalizer-3.4.7-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2fe249cb4651fd12605b7288b24751d8bfd46d35f12a20b1ba33dea122e690df", size = 214061, upload-time = "2026-04-02T09:26:08.347Z" }, - { url = "https://files.pythonhosted.org/packages/dc/92/42bd3cefcf7687253fb86694b45f37b733c97f59af3724f356fa92b8c344/charset_normalizer-3.4.7-cp311-cp311-manylinux_2_31_armv7l.whl", hash = "sha256:65bcd23054beab4d166035cabbc868a09c1a49d1efe458fe8e4361215df40265", size = 199239, upload-time = "2026-04-02T09:26:09.823Z" }, - { url = "https://files.pythonhosted.org/packages/4c/3d/069e7184e2aa3b3cddc700e3dd267413dc259854adc3380421c805c6a17d/charset_normalizer-3.4.7-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:08e721811161356f97b4059a9ba7bafb23ea5ee2255402c42881c214e173c6b4", size = 210173, upload-time = "2026-04-02T09:26:10.953Z" }, - { url = "https://files.pythonhosted.org/packages/62/51/9d56feb5f2e7074c46f93e0ebdbe61f0848ee246e2f0d89f8e20b89ebb8f/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e060d01aec0a910bdccb8be71faf34e7799ce36950f8294c8bf612cba65a2c9e", size = 209841, upload-time = "2026-04-02T09:26:12.142Z" }, - { url = "https://files.pythonhosted.org/packages/d2/59/893d8f99cc4c837dda1fe2f1139079703deb9f321aabcb032355de13b6c7/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:38c0109396c4cfc574d502df99742a45c72c08eff0a36158b6f04000043dbf38", size = 200304, upload-time = "2026-04-02T09:26:13.711Z" }, - { url = "https://files.pythonhosted.org/packages/7d/1d/ee6f3be3464247578d1ed5c46de545ccc3d3ff933695395c402c21fa6b77/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:1c2a768fdd44ee4a9339a9b0b130049139b8ce3c01d2ce09f67f5a68048d477c", size = 229455, upload-time = "2026-04-02T09:26:14.941Z" }, - { url = "https://files.pythonhosted.org/packages/54/bb/8fb0a946296ea96a488928bdce8ef99023998c48e4713af533e9bb98ef07/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:1a87ca9d5df6fe460483d9a5bbf2b18f620cbed41b432e2bddb686228282d10b", size = 210036, upload-time = "2026-04-02T09:26:16.478Z" }, - { url = "https://files.pythonhosted.org/packages/9a/bc/015b2387f913749f82afd4fcba07846d05b6d784dd16123cb66860e0237d/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:d635aab80466bc95771bb78d5370e74d36d1fe31467b6b29b8b57b2a3cd7d22c", size = 224739, upload-time = "2026-04-02T09:26:17.751Z" }, - { url = "https://files.pythonhosted.org/packages/17/ab/63133691f56baae417493cba6b7c641571a2130eb7bceba6773367ab9ec5/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ae196f021b5e7c78e918242d217db021ed2a6ace2bc6ae94c0fc596221c7f58d", size = 216277, upload-time = "2026-04-02T09:26:18.981Z" }, - { url = "https://files.pythonhosted.org/packages/06/6d/3be70e827977f20db77c12a97e6a9f973631a45b8d186c084527e53e77a4/charset_normalizer-3.4.7-cp311-cp311-win32.whl", hash = "sha256:adb2597b428735679446b46c8badf467b4ca5f5056aae4d51a19f9570301b1ad", size = 147819, upload-time = "2026-04-02T09:26:20.295Z" }, - { url = "https://files.pythonhosted.org/packages/20/d9/5f67790f06b735d7c7637171bbfd89882ad67201891b7275e51116ed8207/charset_normalizer-3.4.7-cp311-cp311-win_amd64.whl", hash = "sha256:8e385e4267ab76874ae30db04c627faaaf0b509e1ccc11a95b3fc3e83f855c00", size = 159281, upload-time = "2026-04-02T09:26:21.74Z" }, - { url = "https://files.pythonhosted.org/packages/ca/83/6413f36c5a34afead88ce6f66684d943d91f233d76dd083798f9602b75ae/charset_normalizer-3.4.7-cp311-cp311-win_arm64.whl", hash = "sha256:d4a48e5b3c2a489fae013b7589308a40146ee081f6f509e047e0e096084ceca1", size = 147843, upload-time = "2026-04-02T09:26:22.901Z" }, - { url = "https://files.pythonhosted.org/packages/0c/eb/4fc8d0a7110eb5fc9cc161723a34a8a6c200ce3b4fbf681bc86feee22308/charset_normalizer-3.4.7-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:eca9705049ad3c7345d574e3510665cb2cf844c2f2dcfe675332677f081cbd46", size = 311328, upload-time = "2026-04-02T09:26:24.331Z" }, - { url = "https://files.pythonhosted.org/packages/f8/e3/0fadc706008ac9d7b9b5be6dc767c05f9d3e5df51744ce4cc9605de7b9f4/charset_normalizer-3.4.7-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6178f72c5508bfc5fd446a5905e698c6212932f25bcdd4b47a757a50605a90e2", size = 208061, upload-time = "2026-04-02T09:26:25.568Z" }, - { url = "https://files.pythonhosted.org/packages/42/f0/3dd1045c47f4a4604df85ec18ad093912ae1344ac706993aff91d38773a2/charset_normalizer-3.4.7-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e1421b502d83040e6d7fb2fb18dff63957f720da3d77b2fbd3187ceb63755d7b", size = 229031, upload-time = "2026-04-02T09:26:26.865Z" }, - { url = "https://files.pythonhosted.org/packages/dc/67/675a46eb016118a2fbde5a277a5d15f4f69d5f3f5f338e5ee2f8948fcf43/charset_normalizer-3.4.7-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:edac0f1ab77644605be2cbba52e6b7f630731fc42b34cb0f634be1a6eface56a", size = 225239, upload-time = "2026-04-02T09:26:28.044Z" }, - { url = "https://files.pythonhosted.org/packages/4b/f8/d0118a2f5f23b02cd166fa385c60f9b0d4f9194f574e2b31cef350ad7223/charset_normalizer-3.4.7-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5649fd1c7bade02f320a462fdefd0b4bd3ce036065836d4f42e0de958038e116", size = 216589, upload-time = "2026-04-02T09:26:29.239Z" }, - { url = "https://files.pythonhosted.org/packages/b1/f1/6d2b0b261b6c4ceef0fcb0d17a01cc5bc53586c2d4796fa04b5c540bc13d/charset_normalizer-3.4.7-cp312-cp312-manylinux_2_31_armv7l.whl", hash = "sha256:203104ed3e428044fd943bc4bf45fa73c0730391f9621e37fe39ecf477b128cb", size = 202733, upload-time = "2026-04-02T09:26:30.5Z" }, - { url = "https://files.pythonhosted.org/packages/6f/c0/7b1f943f7e87cc3db9626ba17807d042c38645f0a1d4415c7a14afb5591f/charset_normalizer-3.4.7-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:298930cec56029e05497a76988377cbd7457ba864beeea92ad7e844fe74cd1f1", size = 212652, upload-time = "2026-04-02T09:26:31.709Z" }, - { url = "https://files.pythonhosted.org/packages/38/dd/5a9ab159fe45c6e72079398f277b7d2b523e7f716acc489726115a910097/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:708838739abf24b2ceb208d0e22403dd018faeef86ddac04319a62ae884c4f15", size = 211229, upload-time = "2026-04-02T09:26:33.282Z" }, - { url = "https://files.pythonhosted.org/packages/d5/ff/531a1cad5ca855d1c1a8b69cb71abfd6d85c0291580146fda7c82857caa1/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:0f7eb884681e3938906ed0434f20c63046eacd0111c4ba96f27b76084cd679f5", size = 203552, upload-time = "2026-04-02T09:26:34.845Z" }, - { url = "https://files.pythonhosted.org/packages/c1/4c/a5fb52d528a8ca41f7598cb619409ece30a169fbdf9cdce592e53b46c3a6/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4dc1e73c36828f982bfe79fadf5919923f8a6f4df2860804db9a98c48824ce8d", size = 230806, upload-time = "2026-04-02T09:26:36.152Z" }, - { url = "https://files.pythonhosted.org/packages/59/7a/071feed8124111a32b316b33ae4de83d36923039ef8cf48120266844285b/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:aed52fea0513bac0ccde438c188c8a471c4e0f457c2dd20cdbf6ea7a450046c7", size = 212316, upload-time = "2026-04-02T09:26:37.672Z" }, - { url = "https://files.pythonhosted.org/packages/fd/35/f7dba3994312d7ba508e041eaac39a36b120f32d4c8662b8814dab876431/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:fea24543955a6a729c45a73fe90e08c743f0b3334bbf3201e6c4bc1b0c7fa464", size = 227274, upload-time = "2026-04-02T09:26:38.93Z" }, - { url = "https://files.pythonhosted.org/packages/8a/2d/a572df5c9204ab7688ec1edc895a73ebded3b023bb07364710b05dd1c9be/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:bb6d88045545b26da47aa879dd4a89a71d1dce0f0e549b1abcb31dfe4a8eac49", size = 218468, upload-time = "2026-04-02T09:26:40.17Z" }, - { url = "https://files.pythonhosted.org/packages/86/eb/890922a8b03a568ca2f336c36585a4713c55d4d67bf0f0c78924be6315ca/charset_normalizer-3.4.7-cp312-cp312-win32.whl", hash = "sha256:2257141f39fe65a3fdf38aeccae4b953e5f3b3324f4ff0daf9f15b8518666a2c", size = 148460, upload-time = "2026-04-02T09:26:41.416Z" }, - { url = "https://files.pythonhosted.org/packages/35/d9/0e7dffa06c5ab081f75b1b786f0aefc88365825dfcd0ac544bdb7b2b6853/charset_normalizer-3.4.7-cp312-cp312-win_amd64.whl", hash = "sha256:5ed6ab538499c8644b8a3e18debabcd7ce684f3fa91cf867521a7a0279cab2d6", size = 159330, upload-time = "2026-04-02T09:26:42.554Z" }, - { url = "https://files.pythonhosted.org/packages/9e/5d/481bcc2a7c88ea6b0878c299547843b2521ccbc40980cb406267088bc701/charset_normalizer-3.4.7-cp312-cp312-win_arm64.whl", hash = "sha256:56be790f86bfb2c98fb742ce566dfb4816e5a83384616ab59c49e0604d49c51d", size = 147828, upload-time = "2026-04-02T09:26:44.075Z" }, - { url = "https://files.pythonhosted.org/packages/c1/3b/66777e39d3ae1ddc77ee606be4ec6d8cbd4c801f65e5a1b6f2b11b8346dd/charset_normalizer-3.4.7-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:f496c9c3cc02230093d8330875c4c3cdfc3b73612a5fd921c65d39cbcef08063", size = 309627, upload-time = "2026-04-02T09:26:45.198Z" }, - { url = "https://files.pythonhosted.org/packages/2e/4e/b7f84e617b4854ade48a1b7915c8ccfadeba444d2a18c291f696e37f0d3b/charset_normalizer-3.4.7-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0ea948db76d31190bf08bd371623927ee1339d5f2a0b4b1b4a4439a65298703c", size = 207008, upload-time = "2026-04-02T09:26:46.824Z" }, - { url = "https://files.pythonhosted.org/packages/c4/bb/ec73c0257c9e11b268f018f068f5d00aa0ef8c8b09f7753ebd5f2880e248/charset_normalizer-3.4.7-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a277ab8928b9f299723bc1a2dabb1265911b1a76341f90a510368ca44ad9ab66", size = 228303, upload-time = "2026-04-02T09:26:48.397Z" }, - { url = "https://files.pythonhosted.org/packages/85/fb/32d1f5033484494619f701e719429c69b766bfc4dbc61aa9e9c8c166528b/charset_normalizer-3.4.7-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3bec022aec2c514d9cf199522a802bd007cd588ab17ab2525f20f9c34d067c18", size = 224282, upload-time = "2026-04-02T09:26:49.684Z" }, - { url = "https://files.pythonhosted.org/packages/fa/07/330e3a0dda4c404d6da83b327270906e9654a24f6c546dc886a0eb0ffb23/charset_normalizer-3.4.7-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e044c39e41b92c845bc815e5ae4230804e8e7bc29e399b0437d64222d92809dd", size = 215595, upload-time = "2026-04-02T09:26:50.915Z" }, - { url = "https://files.pythonhosted.org/packages/e3/7c/fc890655786e423f02556e0216d4b8c6bcb6bdfa890160dc66bf52dee468/charset_normalizer-3.4.7-cp313-cp313-manylinux_2_31_armv7l.whl", hash = "sha256:f495a1652cf3fbab2eb0639776dad966c2fb874d79d87ca07f9d5f059b8bd215", size = 201986, upload-time = "2026-04-02T09:26:52.197Z" }, - { url = "https://files.pythonhosted.org/packages/d8/97/bfb18b3db2aed3b90cf54dc292ad79fdd5ad65c4eae454099475cbeadd0d/charset_normalizer-3.4.7-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e712b419df8ba5e42b226c510472b37bd57b38e897d3eca5e8cfd410a29fa859", size = 211711, upload-time = "2026-04-02T09:26:53.49Z" }, - { url = "https://files.pythonhosted.org/packages/6f/a5/a581c13798546a7fd557c82614a5c65a13df2157e9ad6373166d2a3e645d/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7804338df6fcc08105c7745f1502ba68d900f45fd770d5bdd5288ddccb8a42d8", size = 210036, upload-time = "2026-04-02T09:26:54.975Z" }, - { url = "https://files.pythonhosted.org/packages/8c/bf/b3ab5bcb478e4193d517644b0fb2bf5497fbceeaa7a1bc0f4d5b50953861/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:481551899c856c704d58119b5025793fa6730adda3571971af568f66d2424bb5", size = 202998, upload-time = "2026-04-02T09:26:56.303Z" }, - { url = "https://files.pythonhosted.org/packages/e7/4e/23efd79b65d314fa320ec6017b4b5834d5c12a58ba4610aa353af2e2f577/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f59099f9b66f0d7145115e6f80dd8b1d847176df89b234a5a6b3f00437aa0832", size = 230056, upload-time = "2026-04-02T09:26:57.554Z" }, - { url = "https://files.pythonhosted.org/packages/b9/9f/1e1941bc3f0e01df116e68dc37a55c4d249df5e6fa77f008841aef68264f/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:f59ad4c0e8f6bba240a9bb85504faa1ab438237199d4cce5f622761507b8f6a6", size = 211537, upload-time = "2026-04-02T09:26:58.843Z" }, - { url = "https://files.pythonhosted.org/packages/80/0f/088cbb3020d44428964a6c97fe1edfb1b9550396bf6d278330281e8b709c/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:3dedcc22d73ec993f42055eff4fcfed9318d1eeb9a6606c55892a26964964e48", size = 226176, upload-time = "2026-04-02T09:27:00.437Z" }, - { url = "https://files.pythonhosted.org/packages/6a/9f/130394f9bbe06f4f63e22641d32fc9b202b7e251c9aef4db044324dac493/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:64f02c6841d7d83f832cd97ccf8eb8a906d06eb95d5276069175c696b024b60a", size = 217723, upload-time = "2026-04-02T09:27:02.021Z" }, - { url = "https://files.pythonhosted.org/packages/73/55/c469897448a06e49f8fa03f6caae97074fde823f432a98f979cc42b90e69/charset_normalizer-3.4.7-cp313-cp313-win32.whl", hash = "sha256:4042d5c8f957e15221d423ba781e85d553722fc4113f523f2feb7b188cc34c5e", size = 148085, upload-time = "2026-04-02T09:27:03.192Z" }, - { url = "https://files.pythonhosted.org/packages/5d/78/1b74c5bbb3f99b77a1715c91b3e0b5bdb6fe302d95ace4f5b1bec37b0167/charset_normalizer-3.4.7-cp313-cp313-win_amd64.whl", hash = "sha256:3946fa46a0cf3e4c8cb1cc52f56bb536310d34f25f01ca9b6c16afa767dab110", size = 158819, upload-time = "2026-04-02T09:27:04.454Z" }, - { url = "https://files.pythonhosted.org/packages/68/86/46bd42279d323deb8687c4a5a811fd548cb7d1de10cf6535d099877a9a9f/charset_normalizer-3.4.7-cp313-cp313-win_arm64.whl", hash = "sha256:80d04837f55fc81da168b98de4f4b797ef007fc8a79ab71c6ec9bc4dd662b15b", size = 147915, upload-time = "2026-04-02T09:27:05.971Z" }, - { url = "https://files.pythonhosted.org/packages/97/c8/c67cb8c70e19ef1960b97b22ed2a1567711de46c4ddf19799923adc836c2/charset_normalizer-3.4.7-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:c36c333c39be2dbca264d7803333c896ab8fa7d4d6f0ab7edb7dfd7aea6e98c0", size = 309234, upload-time = "2026-04-02T09:27:07.194Z" }, - { url = "https://files.pythonhosted.org/packages/99/85/c091fdee33f20de70d6c8b522743b6f831a2f1cd3ff86de4c6a827c48a76/charset_normalizer-3.4.7-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1c2aed2e5e41f24ea8ef1590b8e848a79b56f3a5564a65ceec43c9d692dc7d8a", size = 208042, upload-time = "2026-04-02T09:27:08.749Z" }, - { url = "https://files.pythonhosted.org/packages/87/1c/ab2ce611b984d2fd5d86a5a8a19c1ae26acac6bad967da4967562c75114d/charset_normalizer-3.4.7-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:54523e136b8948060c0fa0bc7b1b50c32c186f2fceee897a495406bb6e311d2b", size = 228706, upload-time = "2026-04-02T09:27:09.951Z" }, - { url = "https://files.pythonhosted.org/packages/a8/29/2b1d2cb00bf085f59d29eb773ce58ec2d325430f8c216804a0a5cd83cbca/charset_normalizer-3.4.7-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:715479b9a2802ecac752a3b0efa2b0b60285cf962ee38414211abdfccc233b41", size = 224727, upload-time = "2026-04-02T09:27:11.175Z" }, - { url = "https://files.pythonhosted.org/packages/47/5c/032c2d5a07fe4d4855fea851209cca2b6f03ebeb6d4e3afdb3358386a684/charset_normalizer-3.4.7-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bd6c2a1c7573c64738d716488d2cdd3c00e340e4835707d8fdb8dc1a66ef164e", size = 215882, upload-time = "2026-04-02T09:27:12.446Z" }, - { url = "https://files.pythonhosted.org/packages/2c/c2/356065d5a8b78ed04499cae5f339f091946a6a74f91e03476c33f0ab7100/charset_normalizer-3.4.7-cp314-cp314-manylinux_2_31_armv7l.whl", hash = "sha256:c45e9440fb78f8ddabcf714b68f936737a121355bf59f3907f4e17721b9d1aae", size = 200860, upload-time = "2026-04-02T09:27:13.721Z" }, - { url = "https://files.pythonhosted.org/packages/0c/cd/a32a84217ced5039f53b29f460962abb2d4420def55afabe45b1c3c7483d/charset_normalizer-3.4.7-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3534e7dcbdcf757da6b85a0bbf5b6868786d5982dd959b065e65481644817a18", size = 211564, upload-time = "2026-04-02T09:27:15.272Z" }, - { url = "https://files.pythonhosted.org/packages/44/86/58e6f13ce26cc3b8f4a36b94a0f22ae2f00a72534520f4ae6857c4b81f89/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:e8ac484bf18ce6975760921bb6148041faa8fef0547200386ea0b52b5d27bf7b", size = 211276, upload-time = "2026-04-02T09:27:16.834Z" }, - { url = "https://files.pythonhosted.org/packages/8f/fe/d17c32dc72e17e155e06883efa84514ca375f8a528ba2546bee73fc4df81/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:a5fe03b42827c13cdccd08e6c0247b6a6d4b5e3cdc53fd1749f5896adcdc2356", size = 201238, upload-time = "2026-04-02T09:27:18.229Z" }, - { url = "https://files.pythonhosted.org/packages/6a/29/f33daa50b06525a237451cdb6c69da366c381a3dadcd833fa5676bc468b3/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:2d6eb928e13016cea4f1f21d1e10c1cebd5a421bc57ddf5b1142ae3f86824fab", size = 230189, upload-time = "2026-04-02T09:27:19.445Z" }, - { url = "https://files.pythonhosted.org/packages/b6/6e/52c84015394a6a0bdcd435210a7e944c5f94ea1055f5cc5d56c5fe368e7b/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:e74327fb75de8986940def6e8dee4f127cc9752bee7355bb323cc5b2659b6d46", size = 211352, upload-time = "2026-04-02T09:27:20.79Z" }, - { url = "https://files.pythonhosted.org/packages/8c/d7/4353be581b373033fb9198bf1da3cf8f09c1082561e8e922aa7b39bf9fe8/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:d6038d37043bced98a66e68d3aa2b6a35505dc01328cd65217cefe82f25def44", size = 227024, upload-time = "2026-04-02T09:27:22.063Z" }, - { url = "https://files.pythonhosted.org/packages/30/45/99d18aa925bd1740098ccd3060e238e21115fffbfdcb8f3ece837d0ace6c/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:7579e913a5339fb8fa133f6bbcfd8e6749696206cf05acdbdca71a1b436d8e72", size = 217869, upload-time = "2026-04-02T09:27:23.486Z" }, - { url = "https://files.pythonhosted.org/packages/5c/05/5ee478aa53f4bb7996482153d4bfe1b89e0f087f0ab6b294fcf92d595873/charset_normalizer-3.4.7-cp314-cp314-win32.whl", hash = "sha256:5b77459df20e08151cd6f8b9ef8ef1f961ef73d85c21a555c7eed5b79410ec10", size = 148541, upload-time = "2026-04-02T09:27:25.146Z" }, - { url = "https://files.pythonhosted.org/packages/48/77/72dcb0921b2ce86420b2d79d454c7022bf5be40202a2a07906b9f2a35c97/charset_normalizer-3.4.7-cp314-cp314-win_amd64.whl", hash = "sha256:92a0a01ead5e668468e952e4238cccd7c537364eb7d851ab144ab6627dbbe12f", size = 159634, upload-time = "2026-04-02T09:27:26.642Z" }, - { url = "https://files.pythonhosted.org/packages/c6/a3/c2369911cd72f02386e4e340770f6e158c7980267da16af8f668217abaa0/charset_normalizer-3.4.7-cp314-cp314-win_arm64.whl", hash = "sha256:67f6279d125ca0046a7fd386d01b311c6363844deac3e5b069b514ba3e63c246", size = 148384, upload-time = "2026-04-02T09:27:28.271Z" }, - { url = "https://files.pythonhosted.org/packages/94/09/7e8a7f73d24dba1f0035fbbf014d2c36828fc1bf9c88f84093e57d315935/charset_normalizer-3.4.7-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:effc3f449787117233702311a1b7d8f59cba9ced946ba727bdc329ec69028e24", size = 330133, upload-time = "2026-04-02T09:27:29.474Z" }, - { url = "https://files.pythonhosted.org/packages/8d/da/96975ddb11f8e977f706f45cddd8540fd8242f71ecdb5d18a80723dcf62c/charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fbccdc05410c9ee21bbf16a35f4c1d16123dcdeb8a1d38f33654fa21d0234f79", size = 216257, upload-time = "2026-04-02T09:27:30.793Z" }, - { url = "https://files.pythonhosted.org/packages/e5/e8/1d63bf8ef2d388e95c64b2098f45f84758f6d102a087552da1485912637b/charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:733784b6d6def852c814bce5f318d25da2ee65dd4839a0718641c696e09a2960", size = 234851, upload-time = "2026-04-02T09:27:32.44Z" }, - { url = "https://files.pythonhosted.org/packages/9b/40/e5ff04233e70da2681fa43969ad6f66ca5611d7e669be0246c4c7aaf6dc8/charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a89c23ef8d2c6b27fd200a42aa4ac72786e7c60d40efdc76e6011260b6e949c4", size = 233393, upload-time = "2026-04-02T09:27:34.03Z" }, - { url = "https://files.pythonhosted.org/packages/be/c1/06c6c49d5a5450f76899992f1ee40b41d076aee9279b49cf9974d2f313d5/charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6c114670c45346afedc0d947faf3c7f701051d2518b943679c8ff88befe14f8e", size = 223251, upload-time = "2026-04-02T09:27:35.369Z" }, - { url = "https://files.pythonhosted.org/packages/2b/9f/f2ff16fb050946169e3e1f82134d107e5d4ae72647ec8a1b1446c148480f/charset_normalizer-3.4.7-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:a180c5e59792af262bf263b21a3c49353f25945d8d9f70628e73de370d55e1e1", size = 206609, upload-time = "2026-04-02T09:27:36.661Z" }, - { url = "https://files.pythonhosted.org/packages/69/d5/a527c0cd8d64d2eab7459784fb4169a0ac76e5a6fc5237337982fd61347e/charset_normalizer-3.4.7-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3c9a494bc5ec77d43cea229c4f6db1e4d8fe7e1bbffa8b6f0f0032430ff8ab44", size = 220014, upload-time = "2026-04-02T09:27:38.019Z" }, - { url = "https://files.pythonhosted.org/packages/7e/80/8a7b8104a3e203074dc9aa2c613d4b726c0e136bad1cc734594b02867972/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8d828b6667a32a728a1ad1d93957cdf37489c57b97ae6c4de2860fa749b8fc1e", size = 218979, upload-time = "2026-04-02T09:27:39.37Z" }, - { url = "https://files.pythonhosted.org/packages/02/9a/b759b503d507f375b2b5c153e4d2ee0a75aa215b7f2489cf314f4541f2c0/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:cf1493cd8607bec4d8a7b9b004e699fcf8f9103a9284cc94962cb73d20f9d4a3", size = 209238, upload-time = "2026-04-02T09:27:40.722Z" }, - { url = "https://files.pythonhosted.org/packages/c2/4e/0f3f5d47b86bdb79256e7290b26ac847a2832d9a4033f7eb2cd4bcf4bb5b/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:0c96c3b819b5c3e9e165495db84d41914d6894d55181d2d108cc1a69bfc9cce0", size = 236110, upload-time = "2026-04-02T09:27:42.33Z" }, - { url = "https://files.pythonhosted.org/packages/96/23/bce28734eb3ed2c91dcf93abeb8a5cf393a7b2749725030bb630e554fdd8/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:752a45dc4a6934060b3b0dab47e04edc3326575f82be64bc4fc293914566503e", size = 219824, upload-time = "2026-04-02T09:27:43.924Z" }, - { url = "https://files.pythonhosted.org/packages/2c/6f/6e897c6984cc4d41af319b077f2f600fc8214eb2fe2d6bcb79141b882400/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:8778f0c7a52e56f75d12dae53ae320fae900a8b9b4164b981b9c5ce059cd1fcb", size = 233103, upload-time = "2026-04-02T09:27:45.348Z" }, - { url = "https://files.pythonhosted.org/packages/76/22/ef7bd0fe480a0ae9b656189ec00744b60933f68b4f42a7bb06589f6f576a/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ce3412fbe1e31eb81ea42f4169ed94861c56e643189e1e75f0041f3fe7020abe", size = 225194, upload-time = "2026-04-02T09:27:46.706Z" }, - { url = "https://files.pythonhosted.org/packages/c5/a7/0e0ab3e0b5bc1219bd80a6a0d4d72ca74d9250cb2382b7c699c147e06017/charset_normalizer-3.4.7-cp314-cp314t-win32.whl", hash = "sha256:c03a41a8784091e67a39648f70c5f97b5b6a37f216896d44d2cdcb82615339a0", size = 159827, upload-time = "2026-04-02T09:27:48.053Z" }, - { url = "https://files.pythonhosted.org/packages/7a/1d/29d32e0fb40864b1f878c7f5a0b343ae676c6e2b271a2d55cc3a152391da/charset_normalizer-3.4.7-cp314-cp314t-win_amd64.whl", hash = "sha256:03853ed82eeebbce3c2abfdbc98c96dc205f32a79627688ac9a27370ea61a49c", size = 174168, upload-time = "2026-04-02T09:27:49.795Z" }, - { url = "https://files.pythonhosted.org/packages/de/32/d92444ad05c7a6e41fb2036749777c163baf7a0301a040cb672d6b2b1ae9/charset_normalizer-3.4.7-cp314-cp314t-win_arm64.whl", hash = "sha256:c35abb8bfff0185efac5878da64c45dafd2b37fb0383add1be155a763c1f083d", size = 153018, upload-time = "2026-04-02T09:27:51.116Z" }, - { url = "https://files.pythonhosted.org/packages/db/8f/61959034484a4a7c527811f4721e75d02d653a35afb0b6054474d8185d4c/charset_normalizer-3.4.7-py3-none-any.whl", hash = "sha256:3dce51d0f5e7951f8bb4900c257dad282f49190fdbebecd4ba99bcc41fef404d", size = 61958, upload-time = "2026-04-02T09:28:37.794Z" }, -] - -[[package]] -name = "click" -version = "8.3.3" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "colorama", marker = "sys_platform == 'win32'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/bb/63/f9e1ea081ce35720d8b92acde70daaedace594dc93b693c869e0d5910718/click-8.3.3.tar.gz", hash = "sha256:398329ad4837b2ff7cbe1dd166a4c0f8900c3ca3a218de04466f38f6497f18a2", size = 328061, upload-time = "2026-04-22T15:11:27.506Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ae/44/c1221527f6a71a01ec6fbad7fa78f1d50dfa02217385cf0fa3eec7087d59/click-8.3.3-py3-none-any.whl", hash = "sha256:a2bf429bb3033c89fa4936ffb35d5cb471e3719e1f3c8a7c3fff0b8314305613", size = 110502, upload-time = "2026-04-22T15:11:25.044Z" }, -] - [[package]] name = "cloudpickle" version = "3.1.2" @@ -896,34 +719,13 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/fd/ba/56147c165442cc5ba7e82ecf301c9a68353cede498185869e6e02b4c264f/fonttools-4.62.1-py3-none-any.whl", hash = "sha256:7487782e2113861f4ddcc07c3436450659e3caa5e470b27dc2177cade2d8e7fd", size = 1152647, upload-time = "2026-03-13T13:54:22.735Z" }, ] -[[package]] -name = "ghp-import" -version = "2.1.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "python-dateutil" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/d9/29/d40217cbe2f6b1359e00c6c307bb3fc876ba74068cbab3dde77f03ca0dc4/ghp-import-2.1.0.tar.gz", hash = "sha256:9c535c4c61193c2df8871222567d7fd7e5014d835f97dc7b7439069e2413d343", size = 10943, upload-time = "2022-05-02T15:47:16.11Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl", hash = "sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619", size = 11034, upload-time = "2022-05-02T15:47:14.552Z" }, -] - [[package]] name = "griffelib" -version = "2.0.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/9d/82/74f4a3310cdabfbb10da554c3a672847f1ed33c6f61dd472681ce7f1fe67/griffelib-2.0.2.tar.gz", hash = "sha256:3cf20b3bc470e83763ffbf236e0076b1211bac1bc67de13daf494640f2de707e", size = 166461, upload-time = "2026-03-27T11:34:51.091Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/11/8c/c9138d881c79aa0ea9ed83cbd58d5ca75624378b38cee225dcf5c42cc91f/griffelib-2.0.2-py3-none-any.whl", hash = "sha256:925c857658fb1ba40c0772c37acbc2ab650bd794d9c1b9726922e36ea4117ea1", size = 142357, upload-time = "2026-03-27T11:34:46.275Z" }, -] - -[[package]] -name = "idna" -version = "3.15" +version = "2.3.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/82/77/7b3966d0b9d1d31a36ddf1746926a11dface89a83409bf1483f0237aa758/idna-3.15.tar.gz", hash = "sha256:ca962446ea538f7092a95e057da437618e886f4d349216d2b1e294abfdb65fdc", size = 199245, upload-time = "2026-05-12T22:45:57.011Z" } +sdist = { url = "https://files.pythonhosted.org/packages/2b/27/b55f1a5278918be765fb2fd8b20966bc72bbdd3f789f031937cceea7834a/griffelib-2.3.2.tar.gz", hash = "sha256:df00c7a0dee3d86268d76788997a1859272cb1fb7b865658e043d2c0c3d52e60", size = 234729, upload-time = "2026-10-06T09:54:37.222Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d2/23/408243171aa9aaba178d3e2559159c24c1171a641aa83b67bdd3394ead8e/idna-3.15-py3-none-any.whl", hash = "sha256:048adeaf8c2d788c40fee287673ccaa74c24ffd8dcf09ffa555a2fbb59f10ac8", size = 72340, upload-time = "2026-05-12T22:45:55.733Z" }, + { url = "https://files.pythonhosted.org/packages/04/e5/0ae74c83c1cab2c14daadf28bd0143eb14bb81503834af987b66badc7b61/griffelib-2.3.2-py3-none-any.whl", hash = "sha256:8e710afededd5607f95bf3c8ccc175ee306e7084459faf27b9f9f44ef2a7a274", size = 169420, upload-time = "2026-10-06T09:54:32.038Z" }, ] [[package]] @@ -1112,22 +914,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b1/dd/ead9d8ea85bf202d90cc513b533f9c363121c7792674f78e0d8a854b63b4/jupyterlab_pygments-0.3.0-py3-none-any.whl", hash = "sha256:841a89020971da1d8693f1a99997aefc5dc424bb1b251fd6322462a1b8842780", size = 15884, upload-time = "2023-11-23T09:26:34.325Z" }, ] -[[package]] -name = "jupytext" -version = "1.19.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "markdown-it-py" }, - { name = "mdit-py-plugins" }, - { name = "nbformat" }, - { name = "packaging" }, - { name = "pyyaml" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/13/a5/80c02f307c8ce863cb33e27daf049315e9d96979e14eead700923b5ec9cc/jupytext-1.19.1.tar.gz", hash = "sha256:82587c07e299173c70ed5e8ec7e75183edf1be289ed518bab49ad0d4e3d5f433", size = 4307829, upload-time = "2026-01-25T21:35:13.276Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/16/5a/736dd2f4535dbf3bf26523f9158c011389ef88dd06ec2eef67fd744f1c7b/jupytext-1.19.1-py3-none-any.whl", hash = "sha256:d8975035155d034bdfde5c0c37891425314b7ea8d3a6c4b5d18c294348714cd9", size = 170478, upload-time = "2026-01-25T21:35:11.17Z" }, -] - [[package]] name = "kiwisolver" version = "1.5.0" @@ -1262,25 +1048,16 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/4f/79/d3bbab197e86e0ff4f9c07122895b66a3e0d024247fcff7f12c473cb36d9/llvmlite-0.47.0-cp314-cp314t-win_amd64.whl", hash = "sha256:6842cf6f707ec4be3d985a385ad03f72b2d724439e118fcbe99b2929964f0453", size = 39153839, upload-time = "2026-03-31T18:29:51.004Z" }, ] -[[package]] -name = "markdown" -version = "3.10.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/2b/f4/69fa6ed85ae003c2378ffa8f6d2e3234662abd02c10d216c0ba96081a238/markdown-3.10.2.tar.gz", hash = "sha256:994d51325d25ad8aa7ce4ebaec003febcce822c3f8c911e3b17c52f7f589f950", size = 368805, upload-time = "2026-02-09T14:57:26.942Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl", hash = "sha256:e91464b71ae3ee7afd3017d9f358ef0baf158fd9a298db92f1d4761133824c36", size = 108180, upload-time = "2026-02-09T14:57:25.787Z" }, -] - [[package]] name = "markdown-it-py" -version = "4.0.0" +version = "3.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "mdurl" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/5b/f5/4ec618ed16cc4f8fb3b701563655a69816155e79e24a17b651541804721d/markdown_it_py-4.0.0.tar.gz", hash = "sha256:cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3", size = 73070, upload-time = "2025-08-11T12:57:52.854Z" } +sdist = { url = "https://files.pythonhosted.org/packages/38/71/3b932df36c1a044d397a1f92d1cf91ee0a503d91e470cbd670aa66b07ed0/markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb", size = 74596, upload-time = "2023-06-03T06:41:14.443Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl", hash = "sha256:87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147", size = 87321, upload-time = "2025-08-11T12:57:51.923Z" }, + { url = "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", size = 87528, upload-time = "2023-06-03T06:41:11.019Z" }, ] [[package]] @@ -1433,18 +1210,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/af/33/ee4519fa02ed11a94aef9559552f3b17bb863f2ecfe1a35dc7f548cde231/matplotlib_inline-0.2.1-py3-none-any.whl", hash = "sha256:d56ce5156ba6085e00a9d54fead6ed29a9c47e215cd1bba2e976ef39f5710a76", size = 9516, upload-time = "2025-10-23T09:00:20.675Z" }, ] -[[package]] -name = "mdit-py-plugins" -version = "0.5.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "markdown-it-py" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/b2/fd/a756d36c0bfba5f6e39a1cdbdbfdd448dc02692467d83816dff4592a1ebc/mdit_py_plugins-0.5.0.tar.gz", hash = "sha256:f4918cb50119f50446560513a8e311d574ff6aaed72606ddae6d35716fe809c6", size = 44655, upload-time = "2025-08-11T07:25:49.083Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/fb/86/dd6e5db36df29e76c7a7699123569a4a18c1623ce68d826ed96c62643cae/mdit_py_plugins-0.5.0-py3-none-any.whl", hash = "sha256:07a08422fc1936a5d26d146759e9155ea466e842f5ab2f7d2266dd084c8dab1f", size = 57205, upload-time = "2025-08-11T07:25:47.597Z" }, -] - [[package]] name = "mdurl" version = "0.1.2" @@ -1454,15 +1219,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" }, ] -[[package]] -name = "mergedeep" -version = "1.3.4" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/3a/41/580bb4006e3ed0361b8151a01d324fb03f420815446c7def45d02f74c270/mergedeep-1.3.4.tar.gz", hash = "sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8", size = 4661, upload-time = "2021-02-05T18:55:30.623Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl", hash = "sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307", size = 6354, upload-time = "2021-02-05T18:55:29.583Z" }, -] - [[package]] name = "mistune" version = "3.3.3" @@ -1472,185 +1228,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/89/70/b1e4737b84163db5bb1dfde6f216dbfbf32783330a9989c965e121172830/mistune-3.3.3-py3-none-any.whl", hash = "sha256:99de1585e42dcbd826faa9e11a202727a5e202e4e4722a4c69ac1ff615793dd7", size = 63569, upload-time = "2026-07-09T06:18:03.839Z" }, ] -[[package]] -name = "mkdocs" -version = "1.6.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "click" }, - { name = "colorama", marker = "sys_platform == 'win32'" }, - { name = "ghp-import" }, - { name = "jinja2" }, - { name = "markdown" }, - { name = "markupsafe" }, - { name = "mergedeep" }, - { name = "mkdocs-get-deps" }, - { name = "packaging" }, - { name = "pathspec" }, - { name = "pyyaml" }, - { name = "pyyaml-env-tag" }, - { name = "watchdog" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/bc/c6/bbd4f061bd16b378247f12953ffcb04786a618ce5e904b8c5a01a0309061/mkdocs-1.6.1.tar.gz", hash = "sha256:7b432f01d928c084353ab39c57282f29f92136665bdd6abf7c1ec8d822ef86f2", size = 3889159, upload-time = "2024-08-30T12:24:06.899Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/22/5b/dbc6a8cddc9cfa9c4971d59fb12bb8d42e161b7e7f8cc89e49137c5b279c/mkdocs-1.6.1-py3-none-any.whl", hash = "sha256:db91759624d1647f3f34aa0c3f327dd2601beae39a366d6e064c03468d35c20e", size = 3864451, upload-time = "2024-08-30T12:24:05.054Z" }, -] - -[[package]] -name = "mkdocs-autorefs" -version = "1.4.4" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "markdown" }, - { name = "markupsafe" }, - { name = "mkdocs" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/52/c0/f641843de3f612a6b48253f39244165acff36657a91cc903633d456ae1ac/mkdocs_autorefs-1.4.4.tar.gz", hash = "sha256:d54a284f27a7346b9c38f1f852177940c222da508e66edc816a0fa55fc6da197", size = 56588, upload-time = "2026-02-10T15:23:55.105Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/28/de/a3e710469772c6a89595fc52816da05c1e164b4c866a89e3cb82fb1b67c5/mkdocs_autorefs-1.4.4-py3-none-any.whl", hash = "sha256:834ef5408d827071ad1bc69e0f39704fa34c7fc05bc8e1c72b227dfdc5c76089", size = 25530, upload-time = "2026-02-10T15:23:53.817Z" }, -] - -[[package]] -name = "mkdocs-gen-files" -version = "0.6.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "mkdocs" }, - { name = "properdocs" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/43/43/428f312149c161cae557eecd35f3c4a82b867998b1d47fb29fdfe927be26/mkdocs_gen_files-0.6.1.tar.gz", hash = "sha256:57d7ff2229e23d077e46d14a33db6d37c8823f6ce1a503c874c1764a71679763", size = 8746, upload-time = "2026-03-16T23:26:09.31Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ee/1b/3075eb67fe66e19db059f0a25744c4e56978a309603a20e1d3353d545b5e/mkdocs_gen_files-0.6.1-py3-none-any.whl", hash = "sha256:b3182bfc6219e35b8d26658cb988368659d5d023aac30c2a819247558fc12189", size = 8282, upload-time = "2026-03-16T23:26:08.292Z" }, -] - -[[package]] -name = "mkdocs-get-deps" -version = "0.2.2" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "mergedeep" }, - { name = "platformdirs" }, - { name = "pyyaml" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/ce/25/b3cccb187655b9393572bde9b09261d267c3bf2f2cdabe347673be5976a6/mkdocs_get_deps-0.2.2.tar.gz", hash = "sha256:8ee8d5f316cdbbb2834bc1df6e69c08fe769a83e040060de26d3c19fad3599a1", size = 11047, upload-time = "2026-03-10T02:46:33.632Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/88/29/744136411e785c4b0b744d5413e56555265939ab3a104c6a4b719dad33fd/mkdocs_get_deps-0.2.2-py3-none-any.whl", hash = "sha256:e7878cbeac04860b8b5e0ca31d3abad3df9411a75a32cde82f8e44b6c16ff650", size = 9555, upload-time = "2026-03-10T02:46:32.256Z" }, -] - -[[package]] -name = "mkdocs-jupyter" -version = "0.26.3" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "ipykernel" }, - { name = "jupytext" }, - { name = "mkdocs" }, - { name = "mkdocs-material" }, - { name = "nbconvert" }, - { name = "pygments" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/00/aa/f8d15409a9a3112486994a80d5a975694c7d145c4f8b5b484aeb383420ef/mkdocs_jupyter-0.26.3.tar.gz", hash = "sha256:e1e8bd48a1b96542e84e3028e3066112bac7b94d95ab69f8b91305c84003ca26", size = 1628353, upload-time = "2026-04-17T18:56:31.517Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/13/95/cf3f7fe4910cf0365fa8ea0c731f4b8a624d97cd76ea777913ac8d0868e2/mkdocs_jupyter-0.26.3-py3-none-any.whl", hash = "sha256:cd6644fb578131157194d750fd4d10fc2fd8f1e84e00036ee62df3b5b4b84c82", size = 1459740, upload-time = "2026-04-17T18:56:30.031Z" }, -] - -[[package]] -name = "mkdocs-literate-nav" -version = "0.6.3" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "mkdocs" }, - { name = "properdocs" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/01/af/dd3776a7a713f798f79bec7eb9c661d5cfb83ddc17d9a3667595e53e1559/mkdocs_literate_nav-0.6.3.tar.gz", hash = "sha256:edbaca22343f861fe4e34aac47d55a0c9955c640dbf02eea99fe631e914cf9ee", size = 17526, upload-time = "2026-03-16T23:26:50.688Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/4e/2c/bcf1ae903975ad6f169abb05c1eb0f94395478364deb89270cf034081b29/mkdocs_literate_nav-0.6.3-py3-none-any.whl", hash = "sha256:2c421561280fa9184f88cbf399bebbd4cc17ee507e978a31ce11fd6f3aabf233", size = 13355, upload-time = "2026-03-16T23:26:49.562Z" }, -] - -[[package]] -name = "mkdocs-material" -version = "9.7.7" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "babel" }, - { name = "backrefs" }, - { name = "colorama" }, - { name = "jinja2" }, - { name = "markdown" }, - { name = "mkdocs" }, - { name = "mkdocs-material-extensions" }, - { name = "paginate" }, - { name = "pygments" }, - { name = "pymdown-extensions" }, - { name = "requests" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/f1/cd/c05d3a530ba7934f144fb45f7203cd236adc25c7bdcc34673d202f4b0278/mkdocs_material-9.7.7.tar.gz", hash = "sha256:c0649c065b1b0512d60aad8c10f947f8e455284475239b364b610f2deb4d0855", size = 4097923, upload-time = "2026-07-17T16:21:33.156Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ad/21/17c1bc9e6f47c972ad66fb2ac2568f99f90f1207eeb6fc3b34d094dba7b5/mkdocs_material-9.7.7-py3-none-any.whl", hash = "sha256:8ea9bb1737a5b524a5f9dcf2e1b4ebda8274ae3008aa7845720a97083bef708f", size = 9305438, upload-time = "2026-07-17T16:21:30.017Z" }, -] - -[[package]] -name = "mkdocs-material-extensions" -version = "1.3.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/79/9b/9b4c96d6593b2a541e1cb8b34899a6d021d208bb357042823d4d2cabdbe7/mkdocs_material_extensions-1.3.1.tar.gz", hash = "sha256:10c9511cea88f568257f960358a467d12b970e1f7b2c0e5fb2bb48cab1928443", size = 11847, upload-time = "2023-11-22T19:09:45.208Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/5b/54/662a4743aa81d9582ee9339d4ffa3c8fd40a4965e033d77b9da9774d3960/mkdocs_material_extensions-1.3.1-py3-none-any.whl", hash = "sha256:adff8b62700b25cb77b53358dad940f3ef973dd6db797907c49e3c2ef3ab4e31", size = 8728, upload-time = "2023-11-22T19:09:43.465Z" }, -] - -[[package]] -name = "mkdocs-section-index" -version = "0.3.12" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "mkdocs" }, - { name = "properdocs" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/f1/e2/64d0f3f054ca8efe61e706006ff5f0d49ad99620c62c2e04818573391c33/mkdocs_section_index-0.3.12.tar.gz", hash = "sha256:285635bf86c643b0fc7a343053d7a818049817bff4408f52b80c4367bd5e7268", size = 14946, upload-time = "2026-04-16T19:20:00.953Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b0/4d/a330cab5e055d45e924cec69da54a3d8ed37643964f8d1fa1a772b496273/mkdocs_section_index-0.3.12-py3-none-any.whl", hash = "sha256:a1100039546beb4ebef63ce6fc91f3195fb9c0c3763105d4d3d7cd31e0a046eb", size = 8932, upload-time = "2026-04-16T19:19:59.741Z" }, -] - -[[package]] -name = "mkdocstrings" -version = "1.0.4" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "jinja2" }, - { name = "markdown" }, - { name = "markupsafe" }, - { name = "mkdocs" }, - { name = "mkdocs-autorefs" }, - { name = "pymdown-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/1d/5d/f888d4d3eb31359b327bc9b17a212d6ef03fe0b0682fbb3fc2cb849fb12b/mkdocstrings-1.0.4.tar.gz", hash = "sha256:3969a6515b77db65fd097b53c1b7aa4ae840bd71a2ee62a6a3e89503446d7172", size = 100088, upload-time = "2026-04-15T09:16:53.376Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/6e/94/be70f8ee9c45f2f62b39a1f0e9303bc20e138a8f3b8e50ffd89498e177e1/mkdocstrings-1.0.4-py3-none-any.whl", hash = "sha256:63464b4b29053514f32a1dbbf604e52876d5e638111b0c295ab7ed3cac73ca9b", size = 35560, upload-time = "2026-04-15T09:16:51.436Z" }, -] - -[[package]] -name = "mkdocstrings-python" -version = "2.0.3" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "griffelib" }, - { name = "mkdocs-autorefs" }, - { name = "mkdocstrings" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/29/33/c225eaf898634bdda489a6766fc35d1683c640bffe0e0acd10646b13536d/mkdocstrings_python-2.0.3.tar.gz", hash = "sha256:c518632751cc869439b31c9d3177678ad2bfa5c21b79b863956ad68fc92c13b8", size = 199083, upload-time = "2026-02-20T10:38:36.368Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/32/28/79f0f8de97cce916d5ae88a7bee1ad724855e83e6019c0b4d5b3fabc80f3/mkdocstrings_python-2.0.3-py3-none-any.whl", hash = "sha256:0b83513478bdfd803ff05aa43e9b1fca9dd22bcd9471f09ca6257f009bc5ee12", size = 104779, upload-time = "2026-02-20T10:38:34.517Z" }, -] - -[[package]] -name = "mypy-extensions" -version = "1.1.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a2/6e/371856a3fb9d31ca8dac321cda606860fa4548858c0cc45d9d1d4ca2628b/mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558", size = 6343, upload-time = "2025-04-22T14:54:24.164Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963, upload-time = "2025-04-22T14:54:22.983Z" }, -] - [[package]] name = "nbclient" version = "0.10.4" @@ -1934,15 +1511,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7a/c2/920ef838e2f0028c8262f16101ec09ebd5969864e5a64c4c05fad0617c56/packaging-26.1-py3-none-any.whl", hash = "sha256:5d9c0669c6285e491e0ced2eee587eaf67b670d94a19e94e3984a481aba6802f", size = 95831, upload-time = "2026-04-14T21:12:47.56Z" }, ] -[[package]] -name = "paginate" -version = "0.5.7" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ec/46/68dde5b6bc00c1296ec6466ab27dddede6aec9af1b99090e1107091b3b84/paginate-0.5.7.tar.gz", hash = "sha256:22bd083ab41e1a8b4f3690544afb2c60c25e5c9a63a30fa2f483f6c60c8e5945", size = 19252, upload-time = "2024-08-25T14:17:24.139Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl", hash = "sha256:b885e2af73abcf01d9559fd5216b57ef722f8c42affbb63942377668e35c7591", size = 13746, upload-time = "2024-08-25T14:17:22.55Z" }, -] - [[package]] name = "pandocfilters" version = "1.5.1" @@ -1961,15 +1529,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b6/61/fae042894f4296ec49e3f193aff5d7c18440da9e48102c3315e1bc4519a7/parso-0.8.6-py2.py3-none-any.whl", hash = "sha256:2c549f800b70a5c4952197248825584cb00f033b29c692671d3bf08bf380baff", size = 106894, upload-time = "2026-02-09T15:45:21.391Z" }, ] -[[package]] -name = "pathspec" -version = "1.1.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/2e/17/9c3094b822982b9f1ea666d8580ce59000f61f87c1663556fb72031ad9ec/pathspec-1.1.0.tar.gz", hash = "sha256:f5d7c555da02fd8dde3e4a2354b6aba817a89112fa8f333f7917a2a4834dd080", size = 133918, upload-time = "2026-04-23T01:46:22.298Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/fa/c9/8eed0486f074e9f1ca7f8ce5ad663e65f12fdab344028d658fa1b03d35e0/pathspec-1.1.0-py3-none-any.whl", hash = "sha256:574b128f7456bd899045ccd142dd446af7e6cfd0072d63ad73fbc55fbb4aaa42", size = 56264, upload-time = "2026-04-23T01:46:20.606Z" }, -] - [[package]] name = "pexpect" version = "4.9.0" @@ -2092,29 +1651,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/84/03/0d3ce49e2505ae70cf43bc5bb3033955d2fc9f932163e84dc0779cc47f48/prompt_toolkit-3.0.52-py3-none-any.whl", hash = "sha256:9aac639a3bbd33284347de5ad8d68ecc044b91a762dc39b7c21095fcd6a19955", size = 391431, upload-time = "2025-08-27T15:23:59.498Z" }, ] -[[package]] -name = "properdocs" -version = "1.6.7" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "click" }, - { name = "colorama", marker = "sys_platform == 'win32'" }, - { name = "ghp-import" }, - { name = "jinja2" }, - { name = "markdown" }, - { name = "markupsafe" }, - { name = "packaging" }, - { name = "pathspec" }, - { name = "platformdirs" }, - { name = "pyyaml" }, - { name = "pyyaml-env-tag" }, - { name = "watchdog" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/ec/29/f27a4e1eddf72ed3db6e47818fbafe6debbf09fd7051f9c1a007239b46ef/properdocs-1.6.7.tar.gz", hash = "sha256:adc7b16e562890af0e098a7e5b02e3a81c20894a87d6a28d345c9300de73c26e", size = 276141, upload-time = "2026-03-20T20:07:48.167Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/bd/4d/fc923f5c85318ee8cc903566dc4e0ebe41b2dfc1d2ecf5546db232397ed6/properdocs-1.6.7-py3-none-any.whl", hash = "sha256:6fa0cfa2e01bf338f684892c8a506cf70ea88ae7f3479c933b6fa20168101cbd", size = 225406, upload-time = "2026-03-20T20:07:46.875Z" }, -] - [[package]] name = "psutil" version = "7.2.2" @@ -2326,19 +1862,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e7/06/3d67bd912ef337aa4856b466121d03f304aa1bb4d804f9298b6227cd227e/pylatexenc-2.11-py2.py3-none-any.whl", hash = "sha256:e78e7391d6c104f1ed150e21cfaa58016cdb50aa54406a2eecb793649ffdfdd0", size = 137533, upload-time = "2026-07-25T17:26:30.141Z" }, ] -[[package]] -name = "pymdown-extensions" -version = "11.0.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "markdown" }, - { name = "pyyaml" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/21/a9/5f0c535ba3b08fe09270c16808e053a968868242ecbd5676d4e3a488bf28/pymdown_extensions-11.0.1.tar.gz", hash = "sha256:dd2905ae6fc5b75582fafb139a1266ffc754705efa902aa50067fa7ff4f94ec0", size = 857113, upload-time = "2026-07-02T17:59:22.955Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d6/54/da572c98c0b77626a91b5d3b89f0231d8bff5125c225420908632f8b342d/pymdown_extensions-11.0.1-py3-none-any.whl", hash = "sha256:db3943a62bab7e03af1364f0c4083e64b91fb097675a4b6cceccfbe9a77e5eb2", size = 269455, upload-time = "2026-07-02T17:59:21.271Z" }, -] - [[package]] name = "pyparsing" version = "3.3.2" @@ -2391,6 +1914,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/9d/7a/d968e294073affff457b041c2be9868a40c1c71f4a35fcc1e45e5493067b/pytest_cov-7.1.0-py3-none-any.whl", hash = "sha256:a0461110b7865f9a271aa1b51e516c9a95de9d696734a2f71e3e78f46e1d4678", size = 22876, upload-time = "2026-03-21T20:11:14.438Z" }, ] +[[package]] +name = "pytest-markdown-docs" +version = "0.9.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markdown-it-py" }, + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/59/c7/6953e9e25d90d038600e65b05265693aef7ae2a2b67e0f170d65f4f16c24/pytest_markdown_docs-0.9.2.tar.gz", hash = "sha256:bf7510fdeec90d3e98ac924561c01de8dbaf4c3ad34f2418ed2b0b12e5a3f4f5", size = 10929, upload-time = "2026-03-23T12:35:04.804Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0c/b9/c3df11997d29e69b3f8edae1e903bf44eaf4774ccf4c5b6ddcebde88931c/pytest_markdown_docs-0.9.2-py3-none-any.whl", hash = "sha256:9c05a5bee48214cb36583d4a5131d3a23b327a8d82c92ae860106053fd7d1f9e", size = 13536, upload-time = "2026-03-23T12:35:03.862Z" }, +] + [[package]] name = "python-dateutil" version = "2.9.0.post0" @@ -2403,40 +1939,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, ] -[[package]] -name = "pytokens" -version = "0.4.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b6/34/b4e015b99031667a7b960f888889c5bd34ef585c85e1cb56a594b92836ac/pytokens-0.4.1.tar.gz", hash = "sha256:292052fe80923aae2260c073f822ceba21f3872ced9a68bb7953b348e561179a", size = 23015, upload-time = "2026-01-30T01:03:45.924Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/3d/92/790ebe03f07b57e53b10884c329b9a1a308648fc083a6d4a39a10a28c8fc/pytokens-0.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d70e77c55ae8380c91c0c18dea05951482e263982911fc7410b1ffd1dadd3440", size = 160864, upload-time = "2026-01-30T01:02:57.882Z" }, - { url = "https://files.pythonhosted.org/packages/13/25/a4f555281d975bfdd1eba731450e2fe3a95870274da73fb12c40aeae7625/pytokens-0.4.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4a58d057208cb9075c144950d789511220b07636dd2e4708d5645d24de666bdc", size = 248565, upload-time = "2026-01-30T01:02:59.912Z" }, - { url = "https://files.pythonhosted.org/packages/17/50/bc0394b4ad5b1601be22fa43652173d47e4c9efbf0044c62e9a59b747c56/pytokens-0.4.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b49750419d300e2b5a3813cf229d4e5a4c728dae470bcc89867a9ad6f25a722d", size = 260824, upload-time = "2026-01-30T01:03:01.471Z" }, - { url = "https://files.pythonhosted.org/packages/4e/54/3e04f9d92a4be4fc6c80016bc396b923d2a6933ae94b5f557c939c460ee0/pytokens-0.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d9907d61f15bf7261d7e775bd5d7ee4d2930e04424bab1972591918497623a16", size = 264075, upload-time = "2026-01-30T01:03:04.143Z" }, - { url = "https://files.pythonhosted.org/packages/d1/1b/44b0326cb5470a4375f37988aea5d61b5cc52407143303015ebee94abfd6/pytokens-0.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:ee44d0f85b803321710f9239f335aafe16553b39106384cef8e6de40cb4ef2f6", size = 103323, upload-time = "2026-01-30T01:03:05.412Z" }, - { url = "https://files.pythonhosted.org/packages/41/5d/e44573011401fb82e9d51e97f1290ceb377800fb4eed650b96f4753b499c/pytokens-0.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:140709331e846b728475786df8aeb27d24f48cbcf7bcd449f8de75cae7a45083", size = 160663, upload-time = "2026-01-30T01:03:06.473Z" }, - { url = "https://files.pythonhosted.org/packages/f0/e6/5bbc3019f8e6f21d09c41f8b8654536117e5e211a85d89212d59cbdab381/pytokens-0.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d6c4268598f762bc8e91f5dbf2ab2f61f7b95bdc07953b602db879b3c8c18e1", size = 255626, upload-time = "2026-01-30T01:03:08.177Z" }, - { url = "https://files.pythonhosted.org/packages/bf/3c/2d5297d82286f6f3d92770289fd439956b201c0a4fc7e72efb9b2293758e/pytokens-0.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:24afde1f53d95348b5a0eb19488661147285ca4dd7ed752bbc3e1c6242a304d1", size = 269779, upload-time = "2026-01-30T01:03:09.756Z" }, - { url = "https://files.pythonhosted.org/packages/20/01/7436e9ad693cebda0551203e0bf28f7669976c60ad07d6402098208476de/pytokens-0.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5ad948d085ed6c16413eb5fec6b3e02fa00dc29a2534f088d3302c47eb59adf9", size = 268076, upload-time = "2026-01-30T01:03:10.957Z" }, - { url = "https://files.pythonhosted.org/packages/2e/df/533c82a3c752ba13ae7ef238b7f8cdd272cf1475f03c63ac6cf3fcfb00b6/pytokens-0.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:3f901fe783e06e48e8cbdc82d631fca8f118333798193e026a50ce1b3757ea68", size = 103552, upload-time = "2026-01-30T01:03:12.066Z" }, - { url = "https://files.pythonhosted.org/packages/cb/dc/08b1a080372afda3cceb4f3c0a7ba2bde9d6a5241f1edb02a22a019ee147/pytokens-0.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8bdb9d0ce90cbf99c525e75a2fa415144fd570a1ba987380190e8b786bc6ef9b", size = 160720, upload-time = "2026-01-30T01:03:13.843Z" }, - { url = "https://files.pythonhosted.org/packages/64/0c/41ea22205da480837a700e395507e6a24425151dfb7ead73343d6e2d7ffe/pytokens-0.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5502408cab1cb18e128570f8d598981c68a50d0cbd7c61312a90507cd3a1276f", size = 254204, upload-time = "2026-01-30T01:03:14.886Z" }, - { url = "https://files.pythonhosted.org/packages/e0/d2/afe5c7f8607018beb99971489dbb846508f1b8f351fcefc225fcf4b2adc0/pytokens-0.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:29d1d8fb1030af4d231789959f21821ab6325e463f0503a61d204343c9b355d1", size = 268423, upload-time = "2026-01-30T01:03:15.936Z" }, - { url = "https://files.pythonhosted.org/packages/68/d4/00ffdbd370410c04e9591da9220a68dc1693ef7499173eb3e30d06e05ed1/pytokens-0.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:970b08dd6b86058b6dc07efe9e98414f5102974716232d10f32ff39701e841c4", size = 266859, upload-time = "2026-01-30T01:03:17.458Z" }, - { url = "https://files.pythonhosted.org/packages/a7/c9/c3161313b4ca0c601eeefabd3d3b576edaa9afdefd32da97210700e47652/pytokens-0.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:9bd7d7f544d362576be74f9d5901a22f317efc20046efe2034dced238cbbfe78", size = 103520, upload-time = "2026-01-30T01:03:18.652Z" }, - { url = "https://files.pythonhosted.org/packages/8f/a7/b470f672e6fc5fee0a01d9e75005a0e617e162381974213a945fcd274843/pytokens-0.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:4a14d5f5fc78ce85e426aa159489e2d5961acf0e47575e08f35584009178e321", size = 160821, upload-time = "2026-01-30T01:03:19.684Z" }, - { url = "https://files.pythonhosted.org/packages/80/98/e83a36fe8d170c911f864bfded690d2542bfcfacb9c649d11a9e6eb9dc41/pytokens-0.4.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:97f50fd18543be72da51dd505e2ed20d2228c74e0464e4262e4899797803d7fa", size = 254263, upload-time = "2026-01-30T01:03:20.834Z" }, - { url = "https://files.pythonhosted.org/packages/0f/95/70d7041273890f9f97a24234c00b746e8da86df462620194cef1d411ddeb/pytokens-0.4.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dc74c035f9bfca0255c1af77ddd2d6ae8419012805453e4b0e7513e17904545d", size = 268071, upload-time = "2026-01-30T01:03:21.888Z" }, - { url = "https://files.pythonhosted.org/packages/da/79/76e6d09ae19c99404656d7db9c35dfd20f2086f3eb6ecb496b5b31163bad/pytokens-0.4.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f66a6bbe741bd431f6d741e617e0f39ec7257ca1f89089593479347cc4d13324", size = 271716, upload-time = "2026-01-30T01:03:23.633Z" }, - { url = "https://files.pythonhosted.org/packages/79/37/482e55fa1602e0a7ff012661d8c946bafdc05e480ea5a32f4f7e336d4aa9/pytokens-0.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:b35d7e5ad269804f6697727702da3c517bb8a5228afa450ab0fa787732055fc9", size = 104539, upload-time = "2026-01-30T01:03:24.788Z" }, - { url = "https://files.pythonhosted.org/packages/30/e8/20e7db907c23f3d63b0be3b8a4fd1927f6da2395f5bcc7f72242bb963dfe/pytokens-0.4.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:8fcb9ba3709ff77e77f1c7022ff11d13553f3c30299a9fe246a166903e9091eb", size = 168474, upload-time = "2026-01-30T01:03:26.428Z" }, - { url = "https://files.pythonhosted.org/packages/d6/81/88a95ee9fafdd8f5f3452107748fd04c24930d500b9aba9738f3ade642cc/pytokens-0.4.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:79fc6b8699564e1f9b521582c35435f1bd32dd06822322ec44afdeba666d8cb3", size = 290473, upload-time = "2026-01-30T01:03:27.415Z" }, - { url = "https://files.pythonhosted.org/packages/cf/35/3aa899645e29b6375b4aed9f8d21df219e7c958c4c186b465e42ee0a06bf/pytokens-0.4.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d31b97b3de0f61571a124a00ffe9a81fb9939146c122c11060725bd5aea79975", size = 303485, upload-time = "2026-01-30T01:03:28.558Z" }, - { url = "https://files.pythonhosted.org/packages/52/a0/07907b6ff512674d9b201859f7d212298c44933633c946703a20c25e9d81/pytokens-0.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:967cf6e3fd4adf7de8fc73cd3043754ae79c36475c1c11d514fc72cf5490094a", size = 306698, upload-time = "2026-01-30T01:03:29.653Z" }, - { url = "https://files.pythonhosted.org/packages/39/2a/cbbf9250020a4a8dd53ba83a46c097b69e5eb49dd14e708f496f548c6612/pytokens-0.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:584c80c24b078eec1e227079d56dc22ff755e0ba8654d8383b2c549107528918", size = 116287, upload-time = "2026-01-30T01:03:30.912Z" }, - { url = "https://files.pythonhosted.org/packages/c6/78/397db326746f0a342855b81216ae1f0a32965deccfd7c830a2dbc66d2483/pytokens-0.4.1-py3-none-any.whl", hash = "sha256:26cef14744a8385f35d0e095dc8b3a7583f6c953c2e3d269c7f82484bf5ad2de", size = 13729, upload-time = "2026-01-30T01:03:45.029Z" }, -] - [[package]] name = "pyyaml" version = "6.0.3" @@ -2492,18 +1994,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f1/12/de94a39c2ef588c7e6455cfbe7343d3b2dc9d6b6b2f40c4c6565744c873d/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b", size = 149341, upload-time = "2025-09-25T21:32:56.828Z" }, ] -[[package]] -name = "pyyaml-env-tag" -version = "1.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "pyyaml" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/eb/2e/79c822141bfd05a853236b504869ebc6b70159afc570e1d5a20641782eaa/pyyaml_env_tag-1.1.tar.gz", hash = "sha256:2eb38b75a2d21ee0475d6d97ec19c63287a7e140231e4214969d0eac923cd7ff", size = 5737, upload-time = "2025-05-13T15:24:01.64Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/04/11/432f32f8097b03e3cd5fe57e88efb685d964e2e5178a48ed61e841f7fdce/pyyaml_env_tag-1.1-py3-none-any.whl", hash = "sha256:17109e1a528561e32f026364712fee1264bc2ea6715120891174ed1b980d2e04", size = 4722, upload-time = "2025-05-13T15:23:59.629Z" }, -] - [[package]] name = "pyzmq" version = "27.1.0" @@ -2595,21 +2085,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl", hash = "sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231", size = 26766, upload-time = "2025-10-13T15:30:47.625Z" }, ] -[[package]] -name = "requests" -version = "2.33.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "certifi" }, - { name = "charset-normalizer" }, - { name = "idna" }, - { name = "urllib3" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/5f/a4/98b9c7c6428a668bf7e42ebb7c79d576a1c3c1e3ae2d47e674b468388871/requests-2.33.1.tar.gz", hash = "sha256:18817f8c57c6263968bc123d237e3b8b08ac046f5456bd1e307ee8f4250d3517", size = 134120, upload-time = "2026-03-30T16:09:15.531Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d7/8e/7540e8a2036f79a125c1d2ebadf69ed7901608859186c856fa0388ef4197/requests-2.33.1-py3-none-any.whl", hash = "sha256:4e6d1ef462f3626a1f0a0a9c42dd93c63bad33f9f1c1937509b8c5c8718ab56a", size = 64947, upload-time = "2026-03-30T16:09:13.83Z" }, -] - [[package]] name = "rich" version = "15.0.0" @@ -2931,18 +2406,18 @@ dev = [ { name = "ty" }, ] docs = [ - { name = "black", extra = ["jupyter"] }, + { name = "cmaes" }, + { name = "griffelib" }, { name = "ipykernel" }, { name = "matplotlib" }, - { name = "mkdocs" }, - { name = "mkdocs-gen-files" }, - { name = "mkdocs-jupyter" }, - { name = "mkdocs-literate-nav" }, - { name = "mkdocs-material" }, - { name = "mkdocs-section-index" }, - { name = "mkdocstrings-python" }, + { name = "nbconvert" }, { name = "pydot" }, { name = "pylatexenc" }, + { name = "pytest" }, + { name = "pytest-benchmark" }, + { name = "pytest-cov" }, + { name = "pytest-markdown-docs" }, + { name = "quimb" }, { name = "tqdm" }, ] interactive = [ @@ -2997,18 +2472,18 @@ dev = [ { name = "ty", specifier = "==0.0.82" }, ] docs = [ - { name = "black", extras = ["jupyter"], specifier = ">=26.5.1" }, + { name = "cmaes", specifier = ">=0.12.0" }, + { name = "griffelib", specifier = ">=2.2,<3" }, { name = "ipykernel", specifier = ">=7.2.0" }, { name = "matplotlib", specifier = ">=3.11.0" }, - { name = "mkdocs", specifier = ">=1.5.1" }, - { name = "mkdocs-gen-files", specifier = ">=0.5.0" }, - { name = "mkdocs-jupyter", specifier = ">=0.24.2" }, - { name = "mkdocs-literate-nav", specifier = ">=0.6.0" }, - { name = "mkdocs-material", specifier = ">=9" }, - { name = "mkdocs-section-index", specifier = ">=0.3.5" }, - { name = "mkdocstrings-python", specifier = ">=1.2.1" }, + { name = "nbconvert" }, { name = "pydot", specifier = ">=1.4" }, { name = "pylatexenc" }, + { name = "pytest", specifier = ">=9.1.0,<10.0" }, + { name = "pytest-benchmark", specifier = ">=5.2.3" }, + { name = "pytest-cov", specifier = ">=4.0" }, + { name = "pytest-markdown-docs" }, + { name = "quimb", specifier = ">=1.14.0,<2" }, { name = "tqdm", specifier = ">=4.65.0" }, ] interactive = [ @@ -3052,15 +2527,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e6/34/ebdc18bae6aa14fbee1a08b63c015c72b64868ff7dae68808ab500c492e2/tinycss2-1.4.0-py3-none-any.whl", hash = "sha256:3a49cf47b7675da0b15d0c6e1df8df4ebd96e9394bb905a5775adb0d884c5289", size = 26610, upload-time = "2024-10-24T14:58:28.029Z" }, ] -[[package]] -name = "tokenize-rt" -version = "6.2.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/69/ed/8f07e893132d5051d86a553e749d5c89b2a4776eb3a579b72ed61f8559ca/tokenize_rt-6.2.0.tar.gz", hash = "sha256:8439c042b330c553fdbe1758e4a05c0ed460dbbbb24a606f11f0dee75da4cad6", size = 5476, upload-time = "2025-05-23T23:48:00.035Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/33/f0/3fe8c6e69135a845f4106f2ff8b6805638d4e85c264e70114e8126689587/tokenize_rt-6.2.0-py2.py3-none-any.whl", hash = "sha256:a152bf4f249c847a66497a4a95f63376ed68ac6abf092a2f7cfb29d044ecff44", size = 6004, upload-time = "2025-05-23T23:47:58.812Z" }, -] - [[package]] name = "tomli" version = "2.4.1" @@ -3208,42 +2674,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7", size = 14611, upload-time = "2025-10-01T02:14:40.154Z" }, ] -[[package]] -name = "urllib3" -version = "2.8.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e3/05/b17359e1cefb4f909b5e40b1b90a496d987258916dbbf88e842c729f510e/urllib3-2.8.0.tar.gz", hash = "sha256:63bf2ead4c879426ebf22ef2a781eeb4aa3b4ae798a0435506f8687fd5bb9b63", size = 458972, upload-time = "2026-09-15T19:29:36.253Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/92/9d/c4e665119135114480843e7ab388fa94d8480650450e6f8e26b70d323a4c/urllib3-2.8.0-py3-none-any.whl", hash = "sha256:0cf3cae568d36aa9576b28dfb35f11328f1cb974ca7647d9475ebb86c75ac6e3", size = 135717, upload-time = "2026-09-15T19:29:34.577Z" }, -] - -[[package]] -name = "watchdog" -version = "6.0.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/db/7d/7f3d619e951c88ed75c6037b246ddcf2d322812ee8ea189be89511721d54/watchdog-6.0.0.tar.gz", hash = "sha256:9ddf7c82fda3ae8e24decda1338ede66e1c99883db93711d8fb941eaa2d8c282", size = 131220, upload-time = "2024-11-01T14:07:13.037Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e0/24/d9be5cd6642a6aa68352ded4b4b10fb0d7889cb7f45814fb92cecd35f101/watchdog-6.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6eb11feb5a0d452ee41f824e271ca311a09e250441c262ca2fd7ebcf2461a06c", size = 96393, upload-time = "2024-11-01T14:06:31.756Z" }, - { url = "https://files.pythonhosted.org/packages/63/7a/6013b0d8dbc56adca7fdd4f0beed381c59f6752341b12fa0886fa7afc78b/watchdog-6.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ef810fbf7b781a5a593894e4f439773830bdecb885e6880d957d5b9382a960d2", size = 88392, upload-time = "2024-11-01T14:06:32.99Z" }, - { url = "https://files.pythonhosted.org/packages/d1/40/b75381494851556de56281e053700e46bff5b37bf4c7267e858640af5a7f/watchdog-6.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:afd0fe1b2270917c5e23c2a65ce50c2a4abb63daafb0d419fde368e272a76b7c", size = 89019, upload-time = "2024-11-01T14:06:34.963Z" }, - { url = "https://files.pythonhosted.org/packages/39/ea/3930d07dafc9e286ed356a679aa02d777c06e9bfd1164fa7c19c288a5483/watchdog-6.0.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:bdd4e6f14b8b18c334febb9c4425a878a2ac20efd1e0b231978e7b150f92a948", size = 96471, upload-time = "2024-11-01T14:06:37.745Z" }, - { url = "https://files.pythonhosted.org/packages/12/87/48361531f70b1f87928b045df868a9fd4e253d9ae087fa4cf3f7113be363/watchdog-6.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c7c15dda13c4eb00d6fb6fc508b3c0ed88b9d5d374056b239c4ad1611125c860", size = 88449, upload-time = "2024-11-01T14:06:39.748Z" }, - { url = "https://files.pythonhosted.org/packages/5b/7e/8f322f5e600812e6f9a31b75d242631068ca8f4ef0582dd3ae6e72daecc8/watchdog-6.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6f10cb2d5902447c7d0da897e2c6768bca89174d0c6e1e30abec5421af97a5b0", size = 89054, upload-time = "2024-11-01T14:06:41.009Z" }, - { url = "https://files.pythonhosted.org/packages/68/98/b0345cabdce2041a01293ba483333582891a3bd5769b08eceb0d406056ef/watchdog-6.0.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:490ab2ef84f11129844c23fb14ecf30ef3d8a6abafd3754a6f75ca1e6654136c", size = 96480, upload-time = "2024-11-01T14:06:42.952Z" }, - { url = "https://files.pythonhosted.org/packages/85/83/cdf13902c626b28eedef7ec4f10745c52aad8a8fe7eb04ed7b1f111ca20e/watchdog-6.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:76aae96b00ae814b181bb25b1b98076d5fc84e8a53cd8885a318b42b6d3a5134", size = 88451, upload-time = "2024-11-01T14:06:45.084Z" }, - { url = "https://files.pythonhosted.org/packages/fe/c4/225c87bae08c8b9ec99030cd48ae9c4eca050a59bf5c2255853e18c87b50/watchdog-6.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a175f755fc2279e0b7312c0035d52e27211a5bc39719dd529625b1930917345b", size = 89057, upload-time = "2024-11-01T14:06:47.324Z" }, - { url = "https://files.pythonhosted.org/packages/a9/c7/ca4bf3e518cb57a686b2feb4f55a1892fd9a3dd13f470fca14e00f80ea36/watchdog-6.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:7607498efa04a3542ae3e05e64da8202e58159aa1fa4acddf7678d34a35d4f13", size = 79079, upload-time = "2024-11-01T14:06:59.472Z" }, - { url = "https://files.pythonhosted.org/packages/5c/51/d46dc9332f9a647593c947b4b88e2381c8dfc0942d15b8edc0310fa4abb1/watchdog-6.0.0-py3-none-manylinux2014_armv7l.whl", hash = "sha256:9041567ee8953024c83343288ccc458fd0a2d811d6a0fd68c4c22609e3490379", size = 79078, upload-time = "2024-11-01T14:07:01.431Z" }, - { url = "https://files.pythonhosted.org/packages/d4/57/04edbf5e169cd318d5f07b4766fee38e825d64b6913ca157ca32d1a42267/watchdog-6.0.0-py3-none-manylinux2014_i686.whl", hash = "sha256:82dc3e3143c7e38ec49d61af98d6558288c415eac98486a5c581726e0737c00e", size = 79076, upload-time = "2024-11-01T14:07:02.568Z" }, - { url = "https://files.pythonhosted.org/packages/ab/cc/da8422b300e13cb187d2203f20b9253e91058aaf7db65b74142013478e66/watchdog-6.0.0-py3-none-manylinux2014_ppc64.whl", hash = "sha256:212ac9b8bf1161dc91bd09c048048a95ca3a4c4f5e5d4a7d1b1a7d5752a7f96f", size = 79077, upload-time = "2024-11-01T14:07:03.893Z" }, - { url = "https://files.pythonhosted.org/packages/2c/3b/b8964e04ae1a025c44ba8e4291f86e97fac443bca31de8bd98d3263d2fcf/watchdog-6.0.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:e3df4cbb9a450c6d49318f6d14f4bbc80d763fa587ba46ec86f99f9e6876bb26", size = 79078, upload-time = "2024-11-01T14:07:05.189Z" }, - { url = "https://files.pythonhosted.org/packages/62/ae/a696eb424bedff7407801c257d4b1afda455fe40821a2be430e173660e81/watchdog-6.0.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:2cce7cfc2008eb51feb6aab51251fd79b85d9894e98ba847408f662b3395ca3c", size = 79077, upload-time = "2024-11-01T14:07:06.376Z" }, - { url = "https://files.pythonhosted.org/packages/b5/e8/dbf020b4d98251a9860752a094d09a65e1b436ad181faf929983f697048f/watchdog-6.0.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:20ffe5b202af80ab4266dcd3e91aae72bf2da48c0d33bdb15c66658e685e94e2", size = 79078, upload-time = "2024-11-01T14:07:07.547Z" }, - { url = "https://files.pythonhosted.org/packages/07/f6/d0e5b343768e8bcb4cda79f0f2f55051bf26177ecd5651f84c07567461cf/watchdog-6.0.0-py3-none-win32.whl", hash = "sha256:07df1fdd701c5d4c8e55ef6cf55b8f0120fe1aef7ef39a1c6fc6bc2e606d517a", size = 79065, upload-time = "2024-11-01T14:07:09.525Z" }, - { url = "https://files.pythonhosted.org/packages/db/d9/c495884c6e548fce18a8f40568ff120bc3a4b7b99813081c8ac0c936fa64/watchdog-6.0.0-py3-none-win_amd64.whl", hash = "sha256:cbafb470cf848d93b5d013e2ecb245d4aa1c8fd0504e863ccefa32445359d680", size = 79070, upload-time = "2024-11-01T14:07:10.686Z" }, - { url = "https://files.pythonhosted.org/packages/33/e8/e40370e6d74ddba47f002a32919d91310d6074130fe4e17dabcafc15cbf1/watchdog-6.0.0-py3-none-win_ia64.whl", hash = "sha256:a1914259fa9e1454315171103c6a30961236f508b9b623eae470268bbcc6a22f", size = 79067, upload-time = "2024-11-01T14:07:11.845Z" }, -] - [[package]] name = "wcwidth" version = "0.6.0" From 8a454cc23e66165779de017d8bd3e85750e4654e Mon Sep 17 00:00:00 2001 From: Panadestein <rpana92@gmail.com> Date: Tue, 6 Oct 2026 15:32:37 +0200 Subject: [PATCH 2/2] =?UTF-8?q?docs:=20=F0=9F=93=9D=20list=20the=20bench?= =?UTF-8?q?=20dependency=20group?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Assisted-by: pi:claude-opus-5.5 --- docs/content/docs/contributing/dependencies.mdx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/content/docs/contributing/dependencies.mdx b/docs/content/docs/contributing/dependencies.mdx index b701fe5..890481b 100644 --- a/docs/content/docs/contributing/dependencies.mdx +++ b/docs/content/docs/contributing/dependencies.mdx @@ -14,7 +14,9 @@ Dependencies are managed with [uv](https://docs.astral.sh/uv/) and declared in - **Dependency groups** (`[dependency-groups]`) are for development only and are never installed by users: - `test`: `pytest`, its plugins, and `quimb` to build reference networks; - - `dev`: the linters, type checker and hooks, plus `test`; + - `bench`: what the scripts under `benches/` import (`cyclopts`, `quimb`, + `scipy`); + - `dev`: the linters, type checker and hooks, plus `test` and `bench`; - `interactive`: Jupyter and plotting for notebooks; - `docs`: what this site's build needs, plus `test` and `interactive`.