diff --git a/.github/workflows/docs-build-reusable.yaml b/.github/workflows/docs-build-reusable.yaml index 6db7a93267d7..d8788fc74abc 100644 --- a/.github/workflows/docs-build-reusable.yaml +++ b/.github/workflows/docs-build-reusable.yaml @@ -15,15 +15,9 @@ jobs: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 - with: - python-version: '3.x' - - name: Install documentation dependencies - run: pip install --require-hashes -r docs/requirements.txt - env: - PIP_CACHE_DIR: ${{ runner.temp }}/.pip-cache + - uses: astral-sh/setup-uv@f0ec1fc3b38f5e7cd731bb6ce540c5af426746bb # v6.1.0 - name: Build documentation - run: mkdocs build --strict + run: uv run --frozen zensical build --strict working-directory: docs - name: Save PR metadata run: echo "${{ github.event.pull_request.number }}" > docs/site/pr-number.txt diff --git a/docs/.gitignore b/docs/.gitignore index 45ddf0ae3970..9bc5eb2c753f 100644 --- a/docs/.gitignore +++ b/docs/.gitignore @@ -1 +1,5 @@ site/ +site-base/ +site-head/ +compare/output/ +compare/node_modules/ diff --git a/docs/Dockerfile b/docs/Dockerfile deleted file mode 100644 index 77b8e10cd92d..000000000000 --- a/docs/Dockerfile +++ /dev/null @@ -1,15 +0,0 @@ -FROM registry.fedoraproject.org/fedora-minimal:41 - -RUN dnf install -y python-pip \ - && dnf clean all \ - && useradd docs - -WORKDIR /home/docs -USER docs - -COPY requirements.txt . -RUN pip install --no-cache-dir --require-hashes -r requirements.txt \ - && mkdir /home/docs/hypershift - -WORKDIR /home/docs/hypershift -ENTRYPOINT [ "/home/docs/.local/bin/mkdocs" ] diff --git a/docs/Makefile b/docs/Makefile index b3fdc3d4dcba..0e34ff94ef15 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -1,31 +1,74 @@ RUNTIME ?= $(shell sh ../hack/utils.sh get_container_engine) -version := $(shell awk -f image-version.awk requirements.txt) -VERSION ?= $(if $(MKDOCS_TAG),$(MKDOCS_TAG),$(version)) -IMG ?= quay.io/hypershift/mkdocs-material:$(VERSION) +IMG ?= docker.io/zensical/zensical:0.0.51 +BASE ?= main .PHONY: build build: - mkdocs build + uv run --frozen zensical build --strict .PHONY: build-containerized build-containerized: $(RUNTIME) volume create --ignore hypershift-docs-site $(RUNTIME) run --rm -it \ - -v ${PWD}:/home/docs/hypershift:Z \ - -v hypershift-docs-site:/home/docs/hypershift/site \ + -v ${PWD}:/docs:Z \ + -v hypershift-docs-site:/docs/site \ $(IMG) build --strict .PHONY: serve-containerized serve-containerized: $(RUNTIME) run --rm -it -p 8000:8000 \ - -v ${PWD}:/home/docs/hypershift:Z \ - -v hypershift-docs-site:/home/docs/hypershift/site \ - $(IMG) serve --dev-addr 0.0.0.0:8000 + -v ${PWD}:/docs:Z \ + -v hypershift-docs-site:/docs/site \ + $(IMG) -.PHONY: image -image: - $(RUNTIME) build -t $(IMG) . +# Visual comparison between the current working tree and a base ref (default: main). +# +# make compare # compare against main +# make compare BASE=v4.18 # compare against a tag +# +# The report is written to compare/output/ and served on http://127.0.0.1:8883. +.PHONY: compare +compare: compare-build compare-run -.PHONY: push -push: - $(RUNTIME) push $(IMG) +.PHONY: compare-build +compare-build: compare-build-base compare-build-head + +.PHONY: compare-build-base +compare-build-base: + @BASE_SHA=$$(git -C .. rev-parse "$(BASE)"); \ + if [ -f site-base/.commit ] && [ "$$(cat site-base/.commit)" = "$$BASE_SHA" ]; then \ + echo "site-base is up to date ($$BASE_SHA), skipping"; \ + else \ + rm -rf site-base; \ + echo "Building base site from $(BASE) ($$BASE_SHA)..."; \ + WORKTREE=$$(mktemp -d); \ + trap 'git -C .. worktree remove --force "$$WORKTREE" 2>/dev/null' EXIT; \ + git -C .. worktree add --detach "$$WORKTREE" "$(BASE)"; \ + cd "$$WORKTREE/docs" && uv run --frozen zensical build -d "$(CURDIR)/site-base"; \ + echo "$$BASE_SHA" > site-base/.commit; \ + fi + +.PHONY: compare-build-head +compare-build-head: + @rm -rf site-head site; \ + echo "Building head site from working tree..."; \ + uv run --frozen zensical build -f mkdocs.yml; \ + mv site site-head + +.PHONY: compare-run +compare-run: + cd compare && pnpm install --frozen-lockfile + cd compare && pnpm exec playwright install chromium + cd compare && node compare.mjs ../site-base ../site-head --output output + @echo "" + @echo "Report: compare/output/index.html" + @echo "Run 'make compare-serve' to view in a browser." + +.PHONY: compare-serve +compare-serve: + @echo "Serving report at http://127.0.0.1:8883" + @cd compare/output && python3 -m http.server 8883 --bind 127.0.0.1 + +.PHONY: compare-clean +compare-clean: + rm -rf site-base site-head compare/output diff --git a/docs/README.md b/docs/README.md index c9c244921af1..8ee0fea87c6f 100644 --- a/docs/README.md +++ b/docs/README.md @@ -2,49 +2,39 @@ Any changes to the docs in this directory can be tested locally before pushing c steps: 1. cd to this directory -2. Run `make image` to build the image -3. Run `make build-containerized` to build the containerized version of the image -4. Run `make serve-containerized` to serve up the docs website locally +2. Run `make build-containerized` to build the docs inside a container +3. Run `make serve-containerized` to serve the docs website locally Any changes you make while the docs are served locally, will be updated in the local docs website. -## Managing Python dependencies +## Configuration + +The site configuration lives in `mkdocs.yml`. Zensical still uses the MkDocs +configuration format; once Zensical ships a migration tool for its native TOML +config, we will switch over. -`requirements.txt` pins every Python dependency needed to build the docs -(mkdocs and its plugins) to an exact version and includes -`--hash=sha256:...` entries for each published artifact, enabling pip's -hash-checking mode (`pip install --require-hashes`). This is what -`.github/workflows/docs-build-reusable.yaml` installs before running -`mkdocs build --strict`. +## Managing Python dependencies -Because hash-checking mode requires every installed package — including -transitive dependencies of mkdocs-material, mkdocs-mermaid2-plugin, and -mkdocs-glightbox — to be pinned and hashed, the file lists the full resolved -dependency closure, not just the three plugins imported directly. +Dependencies are declared in `pyproject.toml` and locked with +[`uv`](https://docs.astral.sh/uv/) into `uv.lock`, which pins every +direct and transitive package to an exact version with hash verification +for supply chain security. This is what +`.github/workflows/docs-build-reusable.yaml` uses when running +`uv run --frozen zensical build --strict`. ### Adding or updating a dependency -1. Add or update the package's version constraint in `requirements.txt` - (e.g. `newplugin>=1.0.0`, or bump an existing `==` pin). -2. Regenerate the file with [`uv`](https://docs.astral.sh/uv/), compiling to - a new temporary path rather than overwriting `requirements.txt` directly, - then move it into place: +1. Add or update the package in `pyproject.toml` + (e.g. add `"newplugin>=1.0.0"` to `dependencies`, or bump an existing pin). +2. Regenerate the lockfile: ```bash - uv pip compile --generate-hashes docs/requirements.txt -o /tmp/requirements.txt.new - mv /tmp/requirements.txt.new docs/requirements.txt + uv lock ``` - This resolves the full dependency graph, pins every package (direct and - transitive) to an exact version, and adds `--hash=sha256:...` entries for - all of its published wheel/sdist artifacts. Don't edit hashes by hand — - always regenerate so they're guaranteed to match the published artifact. -3. Validate the result, forcing pip to actually verify every package's hash - rather than skipping ones already present locally: +3. Confirm the docs still build: ```bash - pip install --dry-run --ignore-installed --require-hashes -r docs/requirements.txt + uv run --frozen zensical build --strict ``` -4. Confirm the docs still build: `cd docs && mkdocs build --strict` - (after installing the regenerated requirements into your environment). \ No newline at end of file diff --git a/docs/compare/compare.mjs b/docs/compare/compare.mjs new file mode 100644 index 000000000000..235ca44219c8 --- /dev/null +++ b/docs/compare/compare.mjs @@ -0,0 +1,389 @@ +#!/usr/bin/env node +/** + * Visual comparison of two built doc sites. + * + * Usage: + * node compare.mjs [--output ] + * + * Serves both sites locally, screenshots every page with Playwright, + * runs pixel-level diffs, and generates an HTML report. + */ + +import { chromium } from "playwright"; +import { + readFileSync, writeFileSync, mkdirSync, rmSync, existsSync, + readdirSync, statSync, +} from "fs"; +import { join, relative, resolve } from "path"; +import { createServer } from "http"; +import { readFile } from "fs/promises"; +import { extname } from "path"; +import { PNG } from "pngjs"; +import pixelmatch from "pixelmatch"; + +const VIEWPORT = { width: 1280, height: 900 }; +const DIFF_THRESHOLD = 0.1; +const CONCURRENCY = 4; +const MAX_PNG_BYTES = 5 * 1024 * 1024; + +function parseArgs() { + const args = process.argv.slice(2); + let outputDir = null; + const positional = []; + + for (let i = 0; i < args.length; i++) { + if (args[i] === "--output" || args[i] === "-o") { + outputDir = args[++i]; + } else if (!args[i].startsWith("-")) { + positional.push(args[i]); + } + } + + if (positional.length < 2) { + console.error("Usage: node compare.mjs [--output ]"); + process.exit(1); + } + + return { + oldSite: resolve(positional[0]), + newSite: resolve(positional[1]), + outputDir: resolve(outputDir || "compare-output"), + }; +} + +function collectPages(siteDir) { + const pages = []; + function walk(dir) { + for (const entry of readdirSync(dir, { withFileTypes: true })) { + if (entry.isDirectory()) { + walk(join(dir, entry.name)); + } else if (entry.name === "index.html") { + const rel = relative(siteDir, join(dir, entry.name)); + pages.push("/" + rel.replace(/index\.html$/, "")); + } + } + } + walk(siteDir); + return pages.sort(); +} + +function routeToFilename(route) { + if (route === "/") return "_root_.png"; + return route.replace(/^\//, "").replace(/\/$/, "").replace(/\//g, "__") + ".png"; +} + +async function startServer(siteDir, port) { + const mimeTypes = { + ".html": "text/html", ".css": "text/css", + ".js": "application/javascript", ".png": "image/png", + ".jpg": "image/jpeg", ".svg": "image/svg+xml", + ".json": "application/json", ".woff2": "font/woff2", + ".woff": "font/woff", ".ttf": "font/ttf", + }; + + const root = resolve(siteDir); + const server = createServer(async (req, res) => { + let filePath = resolve(root, (req.url === "/" ? "index.html" : req.url).replace(/^\//, "")); + if (!filePath.startsWith(root)) { + res.writeHead(403); + res.end("Forbidden"); + return; + } + if (!filePath.endsWith(".html") && existsSync(join(filePath, "index.html"))) { + filePath = join(filePath, "index.html"); + } + try { + const data = await readFile(filePath); + res.writeHead(200, { "Content-Type": mimeTypes[extname(filePath)] || "application/octet-stream" }); + res.end(data); + } catch { + res.writeHead(404); + res.end("Not found"); + } + }); + + return new Promise((resolve) => { + server.listen(port, "127.0.0.1", () => resolve(server)); + }); +} + +async function screenshotPages(browser, baseUrl, pages, outDir) { + mkdirSync(outDir, { recursive: true }); + const failed = []; + + async function worker(queue) { + const context = await browser.newContext({ viewport: VIEWPORT }); + const page = await context.newPage(); + while (queue.length > 0) { + const route = queue.shift(); + const url = baseUrl + route; + try { + await page.goto(url, { waitUntil: "networkidle", timeout: 30000 }); + await page.waitForTimeout(1000); + await page.evaluate(() => window.scrollTo(0, 0)); + await page.screenshot({ + path: join(outDir, routeToFilename(route)), + fullPage: true, + }); + } catch (err) { + console.error(` FAIL ${route}: ${err.message}`); + failed.push(route); + } + } + await context.close(); + } + + const queue = [...pages]; + await Promise.all(Array.from({ length: CONCURRENCY }, () => worker(queue))); + return failed; +} + +function diffScreenshots(oldDir, newDir, diffDir) { + mkdirSync(diffDir, { recursive: true }); + const results = []; + + const oldFiles = new Set(readdirSync(oldDir)); + const newFiles = new Set(readdirSync(newDir)); + const allFiles = [...new Set([...oldFiles, ...newFiles])].sort(); + + for (const file of allFiles) { + if (!file.endsWith(".png")) continue; + + const pageName = file.replace(/__/g, "/").replace(/\.png$/, "").replace("_root_", "/"); + const oldPath = join(oldDir, file); + const newPath = join(newDir, file); + + if (!oldFiles.has(file)) { + results.push({ page: pageName, status: "new-only", diffPixels: 0, diffPercent: 0 }); + continue; + } + if (!newFiles.has(file)) { + results.push({ page: pageName, status: "old-only", diffPixels: 0, diffPercent: 0 }); + continue; + } + + const oldSize = statSync(oldPath).size; + const newSize = statSync(newPath).size; + if (oldSize > MAX_PNG_BYTES || newSize > MAX_PNG_BYTES) { + console.log(` SKIP ${pageName} (${Math.round(Math.max(oldSize, newSize) / 1024 / 1024)}MB)`); + results.push({ page: pageName, status: "skipped-too-large", diffPixels: 0, diffPercent: 0 }); + continue; + } + + try { + const oldImg = PNG.sync.read(readFileSync(oldPath)); + const newImg = PNG.sync.read(readFileSync(newPath)); + + const width = Math.max(oldImg.width, newImg.width); + const height = Math.max(oldImg.height, newImg.height); + + const padded = (img) => { + if (img.width === width && img.height === height) return img; + const p = new PNG({ width, height }); + PNG.bitblt(img, p, 0, 0, img.width, img.height, 0, 0); + return p; + }; + + const a = padded(oldImg); + const b = padded(newImg); + const diff = new PNG({ width, height }); + + const diffPixels = pixelmatch(a.data, b.data, diff.data, width, height, { + threshold: DIFF_THRESHOLD, + }); + const totalPixels = width * height; + const diffPercent = ((diffPixels / totalPixels) * 100).toFixed(2); + + if (diffPixels > 0) { + writeFileSync(join(diffDir, file), PNG.sync.write(diff)); + } + + a.data = null; + b.data = null; + diff.data = null; + + results.push({ + page: pageName, + status: diffPixels === 0 ? "identical" : "changed", + diffPixels, + diffPercent: parseFloat(diffPercent), + }); + } catch (err) { + console.error(` ERROR ${pageName}: ${err.message}`); + results.push({ page: pageName, status: "error", diffPixels: 0, diffPercent: 0 }); + } + } + + return results; +} + +function generateReport(results, outputDir) { + const changed = results.filter((r) => r.status === "changed").sort((a, b) => b.diffPercent - a.diffPercent); + const identical = results.filter((r) => r.status === "identical"); + const oldOnly = results.filter((r) => r.status === "old-only"); + const newOnly = results.filter((r) => r.status === "new-only"); + const skipped = results.filter((r) => r.status === "skipped-too-large"); + const failed = results.filter((r) => r.status === "failed"); + + console.log(`\n=== Results ===`); + console.log(`Identical: ${identical.length}`); + console.log(`Changed: ${changed.length}`); + console.log(`Old only: ${oldOnly.length}`); + console.log(`New only: ${newOnly.length}`); + console.log(`Skipped: ${skipped.length}`); + if (failed.length) console.log(`Failed: ${failed.length}`); + + if (oldOnly.length) { + console.log(`\nMissing from new site:`); + for (const r of oldOnly) console.log(` ${r.page}`); + } + if (changed.length) { + console.log(`\nChanged (by diff %):`); + for (const r of changed) console.log(` ${r.diffPercent}% ${r.page}`); + } + + writeFileSync(join(outputDir, "results.json"), JSON.stringify(results, null, 2)); + + const pageToFile = (page) => { + if (page === "/") return "_root_.png"; + return page.replace(/^\//, "").replace(/\/$/, "").replace(/\//g, "__") + ".png"; + }; + + let html = ` +Docs Visual Comparison + +

Documentation Visual Comparison

+
+
${identical.length} identical
+
${changed.length} changed
+
${oldOnly.length} missing
+
${newOnly.length} new
+
${skipped.length} skipped
+${failed.length ? `
${failed.length} failed
` : ""} +
`; + + if (failed.length) { + html += `

Failed to screenshot

`; + for (const r of failed) html += `
`; + } + + if (oldOnly.length) { + html += `

Missing from new site

`; + for (const r of oldOnly) html += `
`; + } + if (newOnly.length) { + html += `

Only in new site

`; + for (const r of newOnly) html += `
`; + } + + if (changed.length) { + html += `

Changed pages (${changed.length})

`; + for (const r of changed) { + const file = pageToFile(r.page); + const badge = r.diffPercent > 10 ? "high" : r.diffPercent > 2 ? "medium" : "low"; + html += `
+ +${r.page} +${r.diffPercent}% diff + +
+

Side by side

+
+

Old

+

New

+
+

Diff overlay

+
+
+
`; + } + } + + if (identical.length) { + html += `

Identical pages (${identical.length})

Show all
    `; + for (const r of identical) html += `
  • ${r.page}
  • `; + html += `
`; + } + + html += ``; + + writeFileSync(join(outputDir, "index.html"), html); + console.log(`\nHTML report: ${join(outputDir, "index.html")}`); +} + +async function main() { + const { oldSite, newSite, outputDir } = parseArgs(); + + if (!existsSync(oldSite)) { console.error(`Not found: ${oldSite}`); process.exit(1); } + if (!existsSync(newSite)) { console.error(`Not found: ${newSite}`); process.exit(1); } + + const screenshotsOld = join(outputDir, "screenshots-old"); + const screenshotsNew = join(outputDir, "screenshots-new"); + const screenshotsDiff = join(outputDir, "screenshots-diff"); + for (const d of [screenshotsOld, screenshotsNew, screenshotsDiff]) { + rmSync(d, { recursive: true, force: true }); + } + mkdirSync(outputDir, { recursive: true }); + + const oldPages = collectPages(oldSite); + const newPages = collectPages(newSite); + console.log(`Old site: ${oldPages.length} pages`); + console.log(`New site: ${newPages.length} pages`); + + const onlyInOld = oldPages.filter((p) => !newPages.includes(p)); + const onlyInNew = newPages.filter((p) => !oldPages.includes(p)); + if (onlyInOld.length) console.log(`\nPages only in old:\n ${onlyInOld.join("\n ")}`); + if (onlyInNew.length) console.log(`\nPages only in new:\n ${onlyInNew.join("\n ")}`); + + console.log("\nStarting servers..."); + const serverOld = await startServer(oldSite, 8881); + const serverNew = await startServer(newSite, 8882); + + const browser = await chromium.launch(); + + console.log(`\nScreenshotting old site (${oldPages.length} pages)...`); + const failedOld = await screenshotPages(browser, "http://127.0.0.1:8881", oldPages, screenshotsOld); + + console.log(`Screenshotting new site (${newPages.length} pages)...`); + const failedNew = await screenshotPages(browser, "http://127.0.0.1:8882", newPages, screenshotsNew); + + await browser.close(); + serverOld.close(); + serverNew.close(); + + console.log("\nComparing screenshots..."); + const results = diffScreenshots(screenshotsOld, screenshotsNew, screenshotsDiff); + const allFailed = new Set([...failedOld, ...failedNew]); + for (const route of allFailed) { + results.push({ page: route, status: "failed", diffPixels: 0, diffPercent: 0 }); + } + generateReport(results, outputDir); +} + +main().catch((err) => { + console.error(err); + process.exit(1); +}); diff --git a/docs/compare/package.json b/docs/compare/package.json new file mode 100644 index 000000000000..7bf044a3d54d --- /dev/null +++ b/docs/compare/package.json @@ -0,0 +1,13 @@ +{ + "name": "docs-compare", + "private": true, + "type": "module", + "scripts": { + "compare": "node compare.mjs" + }, + "dependencies": { + "playwright": "1.52.0", + "pixelmatch": "6.0.0", + "pngjs": "7.0.0" + } +} diff --git a/docs/compare/pnpm-lock.yaml b/docs/compare/pnpm-lock.yaml new file mode 100644 index 000000000000..e03f305f1e7f --- /dev/null +++ b/docs/compare/pnpm-lock.yaml @@ -0,0 +1,63 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + pixelmatch: + specifier: 6.0.0 + version: 6.0.0 + playwright: + specifier: 1.52.0 + version: 1.52.0 + pngjs: + specifier: 7.0.0 + version: 7.0.0 + +packages: + + fsevents@2.3.2: + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + pixelmatch@6.0.0: + resolution: {integrity: sha512-FYpL4XiIWakTnIqLqvt3uN4L9B3TsuHIvhLILzTiJZMJUsGvmKNeL4H3b6I99LRyerK9W4IuOXw+N28AtRgK2g==} + hasBin: true + + playwright-core@1.52.0: + resolution: {integrity: sha512-l2osTgLXSMeuLZOML9qYODUQoPPnUsKsb5/P6LJ2e6uPKXUdPK5WYhN4z03G+YNbWmGDY4YENauNu4ZKczreHg==} + engines: {node: '>=18'} + hasBin: true + + playwright@1.52.0: + resolution: {integrity: sha512-JAwMNMBlxJ2oD1kce4KPtMkDeKGHQstdpFPcPH3maElAXon/QZeTvtsfXmTMRyO9TslfoYOXkSsvao2nE1ilTw==} + engines: {node: '>=18'} + hasBin: true + + pngjs@7.0.0: + resolution: {integrity: sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow==} + engines: {node: '>=14.19.0'} + +snapshots: + + fsevents@2.3.2: + optional: true + + pixelmatch@6.0.0: + dependencies: + pngjs: 7.0.0 + + playwright-core@1.52.0: {} + + playwright@1.52.0: + dependencies: + playwright-core: 1.52.0 + optionalDependencies: + fsevents: 2.3.2 + + pngjs@7.0.0: {} diff --git a/docs/content/contribute/branch-process.md b/docs/content/contribute/branch-process.md index e1fd8b428ff7..d3ac79904bcf 100644 --- a/docs/content/contribute/branch-process.md +++ b/docs/content/contribute/branch-process.md @@ -1,3 +1,7 @@ +--- +title: OCP Branching Tasks +--- + ## OCP Branching Tasks for the HyperShift Team These are a set of tasks we need to perform on every OCP branching. We need to: diff --git a/docs/content/contribute/contribute-docs.md b/docs/content/contribute/contribute-docs.md index ffb2bb669422..65cfebd605bb 100644 --- a/docs/content/contribute/contribute-docs.md +++ b/docs/content/contribute/contribute-docs.md @@ -4,10 +4,9 @@ title: Contribute documentation # Contributing documentation -HyperShift's documentation is based on [MkDocs](https://www.mkdocs.org) with the -[Material theme](https://squidfunk.github.io) and roughly follows the -[Diátaxis Framework](https://diataxis.fr) for content organization and stylistic -approach. +HyperShift's documentation is based on [Zensical](https://zensical.org) and +roughly follows the [Diátaxis Framework](https://diataxis.fr) for content +organization and stylistic approach. The documentation site is built and published automatically to [https://hypershift.pages.dev/](https://hypershift.pages.dev/). @@ -17,12 +16,8 @@ All documentation lives in the [`docs` directory](https://github.com/openshift/h All content should be Markdown files placed in the [`docs/content` directory](https://github.com/openshift/hypershift/tree/main/docs/content). The [MkDocs configuration file](https://github.com/openshift/hypershift/blob/main/docs/mkdocs.yml) -contains all the MkDocs and Material theme configuration, including the navigation -structure for the site. - -The `quay.io/hypershift/mkdocs-material:latest` image ([Dockerfile](https://github.com/openshift/hypershift/blob/main/docs/Dockerfile)) -is published to provide an easy and portable way to run `mkdocs` fully configured -to preview the site equivalent to the published site. +contains all the Zensical configuration, including the navigation structure for +the site. !!! note @@ -53,20 +48,77 @@ To start a live preview of the site which automatically rebuilds and refreshes i response to local content and configuration changes, run the following from the `docs` directory: +=== "Native" + + ```shell + uv run --frozen zensical serve + ``` + +=== "Containerized" + + ```shell + make serve-containerized + ``` + +Visit the site at [http://127.0.0.1:8000](http://127.0.0.1:8000). + +## Visual comparison + +When making changes that affect the site's appearance (theme updates, layout +changes, navigation restructuring), you can generate a visual diff against the +current `main` branch: + ```shell -make serve-containerized +cd docs +make compare ``` -Visit the site at [http://0.0.0.0:8000](http://0.0.0.0:8000). +This builds both the base site (from `main`, using mkdocs-material) and the head +site (from your working tree, using Zensical), screenshots every page with +Playwright, and produces a pixel-diff report at `compare/output/index.html`. -!!! note +To view the report locally: + +```shell +make compare-serve +``` + +You can also compare against a different ref: + +```shell +make compare BASE=v4.18 +``` + +To share the report, you can host the `compare/output/` directory on any static +hosting service. For example, using a GitHub Pages repository: + +```shell +# Clone or create a repo with a gh-pages branch +git clone git@github.com:/.git /tmp/compare-site +cd /tmp/compare-site && git checkout gh-pages + +# Copy the report +rm -rf screenshots-* index.html results.json +cp -r /docs/compare/output/* . + +# Commit and push +git add -A && git commit -m "Update comparison report" +git push origin gh-pages +``` + +The report will be available at `https://.github.io//`. + +To start fresh, run: + +```shell +make compare-clean +``` - The `serve-containerized` Make target runs the `quay.io/hypershift/mkdocs-material:latest` - image with the local container runtime. Running `mkdocs` natively is possible - but not supported. +!!! tip - If you need more control over the local preview server, consult [the Makefile](https://github.com/openshift/hypershift/blob/main/docs/Makefile) - as a guide to constructing your own local server command. + The base site is cached in `site-base/` and reused across runs. If you only + changed your working tree, the next `make compare` will only rebuild + `site-head` and regenerate the diffs. ## Generate the API reference diff --git a/docs/content/how-to/ci/docs-preview.md b/docs/content/how-to/ci/docs-preview.md index 0a82bc70de5d..a6a2085096bb 100644 --- a/docs/content/how-to/ci/docs-preview.md +++ b/docs/content/how-to/ci/docs-preview.md @@ -6,7 +6,7 @@ When a pull request modifies files under `docs/`, GitHub Actions workflows autom The preview system uses two separate workflows for security, following the reusable workflow pattern described in [GitHub Actions Workflows](github-actions.md): -1. **Docs Build** (`.github/workflows/docs-build.yaml`) — triggers on `pull_request` for changes under `docs/`. The caller delegates to `docs-build-reusable.yaml@main`, which checks out the PR code, builds with MkDocs in strict mode, and uploads the built site as an artifact. This workflow has no access to secrets. +1. **Docs Build** (`.github/workflows/docs-build.yaml`) — triggers on `pull_request` for changes under `docs/`. The caller delegates to `docs-build-reusable.yaml@main`, which checks out the PR code, builds with Zensical in strict mode, and uploads the built site as an artifact. This workflow has no access to secrets. 2. **Docs Deploy** (`.github/workflows/docs-deploy.yaml`) — triggers via `workflow_run` when the Docs Build workflow completes successfully. It downloads the built artifact and deploys to Cloudflare Pages. This workflow has access to the `docs-preview` environment secrets but never executes PR code. GitHub shows a **View deployment** link in the PR timeline via the `docs-preview` environment. @@ -30,8 +30,7 @@ To preview documentation locally: ```bash cd docs -pip install -r requirements.txt -mkdocs serve +uv run zensical serve ``` Then open [http://127.0.0.1:8000](http://127.0.0.1:8000). diff --git a/docs/content/how-to/ci/github-actions.md b/docs/content/how-to/ci/github-actions.md index 4746e8ea60e7..663074f7880d 100644 --- a/docs/content/how-to/ci/github-actions.md +++ b/docs/content/how-to/ci/github-actions.md @@ -52,7 +52,7 @@ All workflows run on self-hosted ARC runners and target the `main` and `release- | Caller | Reusable | Purpose | |--------|----------|---------| -| `docs-build.yaml` | `docs-build-reusable.yaml` | Build MkDocs site in strict mode | +| `docs-build.yaml` | `docs-build-reusable.yaml` | Build Zensical site in strict mode | !!! info The `docs-deploy.yaml` workflow is not a reusable workflow pair — it triggers via `workflow_run` after the Docs Build completes to deploy the preview. See [Documentation Preview](docs-preview.md) for details. diff --git a/docs/content/how-to/ci/triage/presubmit-failures.md b/docs/content/how-to/ci/triage/presubmit-failures.md index bc61a6a8dc02..2e3889dc3fb1 100644 --- a/docs/content/how-to/ci/triage/presubmit-failures.md +++ b/docs/content/how-to/ci/triage/presubmit-failures.md @@ -105,7 +105,7 @@ These checks only run when relevant files change: |------------|-------------|-----------------| | **Envtest OCP API Validation** | `api/`, `test/envtest/`, CRD test assets | `FAIL` with the test name — see `test/envtest/README.md` for details | | **Envtest Vanilla Kube API Validation** | Same as above | Same as above | -| **Docs Build** | `docs/**` changes | MkDocs build errors — usually a broken link or YAML syntax error | +| **Docs Build** | `docs/**` changes | Zensical build errors — usually a broken link or YAML syntax error | | **Validate CPO Overrides** | `hypershift-operator/controlplaneoperator-overrides/assets/overrides.yaml` changes | Validation error for the CPO overrides file | | **gocacheprog Tests** | `contrib/ci/gocacheprog/**` changes | `FAIL` with the test name | diff --git a/docs/content/how-to/disconnected/idms-icsp-for-management-clusters.md b/docs/content/how-to/disconnected/idms-icsp-for-management-clusters.md index 2976b2389354..e9c70f2e8c48 100644 --- a/docs/content/how-to/disconnected/idms-icsp-for-management-clusters.md +++ b/docs/content/how-to/disconnected/idms-icsp-for-management-clusters.md @@ -1,3 +1,7 @@ +--- +title: IDMS/ICSP Config for Management Cluster +--- + ## Configuring disconnected HostedControlPlanes deployments !!! Note diff --git a/docs/content/how-to/sdn/other-sdn-providers.md b/docs/content/how-to/sdn/other-sdn-providers.md index c05c9ce64480..d2626e8d5660 100644 --- a/docs/content/how-to/sdn/other-sdn-providers.md +++ b/docs/content/how-to/sdn/other-sdn-providers.md @@ -1,3 +1,7 @@ +--- +title: Other SDN providers +--- + This document explains how to create a HostedCluster that runs an SDN provider different from OVNKubernetes. The document assumes that you already have the required infrastructure in place to create HostedClusters. !!! important diff --git a/docs/content/labs/Dual/hostedcluster/baremetalhost.md b/docs/content/labs/Dual/hostedcluster/baremetalhost.md index 5a4fdb82c295..91ceab57a43e 100644 --- a/docs/content/labs/Dual/hostedcluster/baremetalhost.md +++ b/docs/content/labs/Dual/hostedcluster/baremetalhost.md @@ -1,3 +1,7 @@ +--- +title: Bare Metal Hosts +--- + ## Bare Metal Hosts A **BareMetalHost** is an openshift-machine-api object that encompasses both physical and logical details, allowing it to be identified by the Metal3 operator. Subsequently, these details are associated with other Assisted Service objects known as Agents. The structure of this object is as follows: diff --git a/docs/content/labs/Dual/hostedcluster/hostedcluster.md b/docs/content/labs/Dual/hostedcluster/hostedcluster.md index fa826ed0757c..ca93b3666795 100644 --- a/docs/content/labs/Dual/hostedcluster/hostedcluster.md +++ b/docs/content/labs/Dual/hostedcluster/hostedcluster.md @@ -1,3 +1,7 @@ +--- +title: Hosted Cluster Object +--- + In this section, we will focus on all the related objects necessary to achieve a Disconnected Hosted Cluster deployment. **Premises**: diff --git a/docs/content/labs/Dual/hostedcluster/index.md b/docs/content/labs/Dual/hostedcluster/index.md index 4940def03c01..dbd069dd0fe2 100644 --- a/docs/content/labs/Dual/hostedcluster/index.md +++ b/docs/content/labs/Dual/hostedcluster/index.md @@ -1,3 +1,7 @@ +--- +title: Hosted Cluster Creation +--- + A Hosted Cluster, as mentioned in the documentation [here](https://hypershift.pages.dev/reference/concepts-and-personas/), is essentially an OCP API endpoint managed by Hypershift. In this context, we will also include the term HostedControlPlane to enhance readability and comprehension. This terminology is further explained in the same [link](https://hypershift.pages.dev/reference/concepts-and-personas/). The Hosted Cluster comprises two main components: diff --git a/docs/content/labs/Dual/hostedcluster/infraenv.md b/docs/content/labs/Dual/hostedcluster/infraenv.md index 7184b58ea924..d1e127c8deb3 100644 --- a/docs/content/labs/Dual/hostedcluster/infraenv.md +++ b/docs/content/labs/Dual/hostedcluster/infraenv.md @@ -1,3 +1,7 @@ +--- +title: Infra Env +--- + The `InfraEnv` is an Assisted Service object that includes essential details such as the `pullSecretRef` and the `sshAuthorizedKey`. These details are used to create the RHCOS Boot Image customized specifically for the cluster. Below is the structure of this object: ```yaml diff --git a/docs/content/labs/Dual/hostedcluster/nodepool.md b/docs/content/labs/Dual/hostedcluster/nodepool.md index b619f27df407..1e776a390306 100644 --- a/docs/content/labs/Dual/hostedcluster/nodepool.md +++ b/docs/content/labs/Dual/hostedcluster/nodepool.md @@ -1,3 +1,7 @@ +--- +title: Node Pools +--- + A `NodePool` is a scalable set of worker nodes associated with a HostedCluster. NodePool machine architectures remain consistent within a specific pool and are independent of the underlying machine architecture of the control plane. !!! note diff --git a/docs/content/labs/Dual/hostedcluster/worker-nodes.md b/docs/content/labs/Dual/hostedcluster/worker-nodes.md index 49af040fd7d3..0f27bd52ac00 100644 --- a/docs/content/labs/Dual/hostedcluster/worker-nodes.md +++ b/docs/content/labs/Dual/hostedcluster/worker-nodes.md @@ -1,3 +1,7 @@ +--- +title: Worker Nodes +--- + Regarding the worker nodes, if you are working on real bare metal, this step is crucial to ensure that the details set in the `BareMetalHost` are correctly configured. If not, you will need to debug why it's not functioning as expected. However, if you are working with virtual machines, you can follow these steps to create empty ones that will be consumed by the Metal3 operator. To achieve this, we will utilize Kcli. diff --git a/docs/content/labs/Dual/hypervisor/redfish-for-vms.md b/docs/content/labs/Dual/hypervisor/redfish-for-vms.md index a945bbd25edd..8f8316b7d4c9 100644 --- a/docs/content/labs/Dual/hypervisor/redfish-for-vms.md +++ b/docs/content/labs/Dual/hypervisor/redfish-for-vms.md @@ -1,3 +1,7 @@ +--- +title: BMC Access for Metal3 +--- + In a bare metal environment, the preferred approach is to utilize the actual BMC (Baseboard Management Controller) of the nodes used for the management cluster, which can be managed by Metal3 for discovery and provisioning. However, in a virtual environment, this approach is not feasible. As a workaround, we will use `ksushy`, which is an implementation of `sushy-tools`, allowing us to simulate BMCs for the virtual machines. To configure `ksushy`, execute the following commands: diff --git a/docs/content/labs/Dual/mgmt-cluster/compact-dual.md b/docs/content/labs/Dual/mgmt-cluster/compact-dual.md index f872a0f3e512..a9c1bd397e73 100644 --- a/docs/content/labs/Dual/mgmt-cluster/compact-dual.md +++ b/docs/content/labs/Dual/mgmt-cluster/compact-dual.md @@ -1,3 +1,7 @@ +--- +title: OpenShift Compact Dual +--- + In this section, we will discuss how to deploy the Openshift management cluster. To do that, we need to have the following files in place: 1. **Pull Secret** diff --git a/docs/content/labs/Dual/mgmt-cluster/index.md b/docs/content/labs/Dual/mgmt-cluster/index.md index 871521da7d17..d7f0a9a64b6c 100644 --- a/docs/content/labs/Dual/mgmt-cluster/index.md +++ b/docs/content/labs/Dual/mgmt-cluster/index.md @@ -1,3 +1,7 @@ +--- +title: Management Cluster Provisioning +--- + ## Openshift Management Cluster This section contains the necessary artifacts to set up an Openshift management cluster based on virtual machines using kcli as the primary tool. Another option is to use dev-scripts, which uses a different approach. diff --git a/docs/content/labs/Dual/mgmt-cluster/network.md b/docs/content/labs/Dual/mgmt-cluster/network.md index 26ae98cbf1e9..dbe6504fadf3 100644 --- a/docs/content/labs/Dual/mgmt-cluster/network.md +++ b/docs/content/labs/Dual/mgmt-cluster/network.md @@ -1,3 +1,7 @@ +--- +title: Networking +--- + Firstly, we need to ensure that we have the right networks prepared for use in the Hypervisor. These networks will be used to host both the Management and Hosted clusters. To configure these networks, we will use the following `kcli` command: diff --git a/docs/content/labs/IPv4/hostedcluster/baremetalhost.md b/docs/content/labs/IPv4/hostedcluster/baremetalhost.md index f01f4467e72f..c59ddb5e0a78 100644 --- a/docs/content/labs/IPv4/hostedcluster/baremetalhost.md +++ b/docs/content/labs/IPv4/hostedcluster/baremetalhost.md @@ -1,3 +1,7 @@ +--- +title: Bare Metal Hosts +--- + ## Bare Metal Hosts A **BareMetalHost** is an openshift-machine-api object that encompasses both physical and logical details, allowing it to be identified by the Metal3 operator. Subsequently, these details are associated with other Assisted Service objects known as Agents. The structure of this object is as follows: diff --git a/docs/content/labs/IPv4/hostedcluster/hostedcluster.md b/docs/content/labs/IPv4/hostedcluster/hostedcluster.md index 96fcf4028eb7..4722e1819879 100644 --- a/docs/content/labs/IPv4/hostedcluster/hostedcluster.md +++ b/docs/content/labs/IPv4/hostedcluster/hostedcluster.md @@ -1,3 +1,7 @@ +--- +title: Hosted Cluster Object +--- + In this section, we will focus on all the related objects necessary to achieve a Disconnected Hosted Cluster deployment. **Premises**: diff --git a/docs/content/labs/IPv4/hostedcluster/index.md b/docs/content/labs/IPv4/hostedcluster/index.md index 59ca847bcf17..6bc4a41227c8 100644 --- a/docs/content/labs/IPv4/hostedcluster/index.md +++ b/docs/content/labs/IPv4/hostedcluster/index.md @@ -1,3 +1,7 @@ +--- +title: Hosted Cluster Creation +--- + Hosted Cluster, as mentioned in the documentation [here](https://hypershift.pages.dev/reference/concepts-and-personas/), is essentially an OCP API endpoint managed by Hypershift. In this context, we will also include the term HostedControlPlane to enhance readability and comprehension. This terminology is further explained in the same [link](https://hypershift.pages.dev/reference/concepts-and-personas/). The Hosted Cluster consists of two main components: diff --git a/docs/content/labs/IPv4/hostedcluster/infraenv.md b/docs/content/labs/IPv4/hostedcluster/infraenv.md index cd01ff6fb436..781b62373abd 100644 --- a/docs/content/labs/IPv4/hostedcluster/infraenv.md +++ b/docs/content/labs/IPv4/hostedcluster/infraenv.md @@ -1,3 +1,7 @@ +--- +title: Infra Env +--- + The `InfraEnv` is an Assisted Service object that includes essential details such as the `pullSecretRef` and the `sshAuthorizedKey`. These details are used to create the RHCOS Boot Image customized specifically for the cluster. Below is the structure of this object: ```yaml diff --git a/docs/content/labs/IPv4/hostedcluster/nodepool.md b/docs/content/labs/IPv4/hostedcluster/nodepool.md index 4bbdd0f11e53..1ab57dc44f55 100644 --- a/docs/content/labs/IPv4/hostedcluster/nodepool.md +++ b/docs/content/labs/IPv4/hostedcluster/nodepool.md @@ -1,3 +1,7 @@ +--- +title: Node Pools +--- + A `NodePool` is a scalable set of worker nodes associated with a HostedCluster. NodePool machine architectures remain consistent within a specific pool and are independent of the underlying machine architecture of the control plane. !!! note diff --git a/docs/content/labs/IPv4/hostedcluster/worker-nodes.md b/docs/content/labs/IPv4/hostedcluster/worker-nodes.md index 3d37acdf40ff..b811280e362d 100644 --- a/docs/content/labs/IPv4/hostedcluster/worker-nodes.md +++ b/docs/content/labs/IPv4/hostedcluster/worker-nodes.md @@ -1,3 +1,7 @@ +--- +title: Worker Nodes +--- + Regarding the worker nodes, if you are working on real bare metal, this step is crucial to ensure that the details set in the `BareMetalHost` are correctly configured. If not, you will need to debug why it's not functioning as expected. However, if you are working with virtual machines, you can follow these steps to create empty ones that will be consumed by the Metal3 operator. To achieve this, we will utilize Kcli. diff --git a/docs/content/labs/IPv4/hypervisor/redfish-for-vms.md b/docs/content/labs/IPv4/hypervisor/redfish-for-vms.md index 22b7e5f2a61a..417f09b37b04 100644 --- a/docs/content/labs/IPv4/hypervisor/redfish-for-vms.md +++ b/docs/content/labs/IPv4/hypervisor/redfish-for-vms.md @@ -1,3 +1,7 @@ +--- +title: BMC Access for Metal3 +--- + In a bare metal environment, the preferred approach is to utilize the actual BMC (Baseboard Management Controller) of the nodes used for the management cluster, which can be managed by Metal3 for discovery and provisioning. However, in a virtual environment, this approach is not feasible. As a workaround, we will use `ksushy`, which is an implementation of `sushy-tools`, allowing us to simulate BMCs for the virtual machines. To configure `ksushy` we need to execute these commands: diff --git a/docs/content/labs/IPv4/mgmt-cluster/compact-ipv4.md b/docs/content/labs/IPv4/mgmt-cluster/compact-ipv4.md index fc3d1d7c2ebc..1ff09bf04265 100644 --- a/docs/content/labs/IPv4/mgmt-cluster/compact-ipv4.md +++ b/docs/content/labs/IPv4/mgmt-cluster/compact-ipv4.md @@ -1,3 +1,7 @@ +--- +title: OpenShift Compact IPv4 +--- + In this section, we will discuss how to deploy the Openshift management cluster. To do that, we need to have the following files in place: 1. **Pull Secret** diff --git a/docs/content/labs/IPv4/mgmt-cluster/index.md b/docs/content/labs/IPv4/mgmt-cluster/index.md index efe3726dc273..71c45a2a7d5c 100644 --- a/docs/content/labs/IPv4/mgmt-cluster/index.md +++ b/docs/content/labs/IPv4/mgmt-cluster/index.md @@ -1,3 +1,7 @@ +--- +title: Management Cluster Provisioning +--- + ## Openshift Management Cluster This section contains the necessary artifacts to set up an Openshift management cluster based on virtual machines using kcli as the primary tool. Another option is to use dev-scripts, which uses a different approach. diff --git a/docs/content/labs/IPv4/mgmt-cluster/network.md b/docs/content/labs/IPv4/mgmt-cluster/network.md index 40c8ee4c0c6d..140acd5e7b7b 100644 --- a/docs/content/labs/IPv4/mgmt-cluster/network.md +++ b/docs/content/labs/IPv4/mgmt-cluster/network.md @@ -1,3 +1,7 @@ +--- +title: Networking +--- + Firstly, we need to ensure that we have the right networks prepared for use in the Hypervisor. These networks will be used to host both the Management and Hosted clusters. To configure these networks, we will use the following `kcli` command: diff --git a/docs/content/labs/IPv6/hostedcluster/baremetalhost.md b/docs/content/labs/IPv6/hostedcluster/baremetalhost.md index b06d841c054b..11d9c569aaad 100644 --- a/docs/content/labs/IPv6/hostedcluster/baremetalhost.md +++ b/docs/content/labs/IPv6/hostedcluster/baremetalhost.md @@ -1,3 +1,7 @@ +--- +title: Bare Metal Hosts +--- + ## Bare Metal Hosts A **BareMetalHost** is an openshift-machine-api object that encompasses both physical and logical details, allowing it to be identified by the Metal3 operator. Subsequently, these details are associated with other Assisted Service objects known as Agents. The structure of this object is as follows: diff --git a/docs/content/labs/IPv6/hostedcluster/hostedcluster.md b/docs/content/labs/IPv6/hostedcluster/hostedcluster.md index 11e887996350..f3926f600d9f 100644 --- a/docs/content/labs/IPv6/hostedcluster/hostedcluster.md +++ b/docs/content/labs/IPv6/hostedcluster/hostedcluster.md @@ -1,3 +1,7 @@ +--- +title: Hosted Cluster Object +--- + In this section, we will focus on all the related objects necessary to achieve a Disconnected Hosted Cluster deployment. **Premises**: diff --git a/docs/content/labs/IPv6/hostedcluster/index.md b/docs/content/labs/IPv6/hostedcluster/index.md index 80b6deec66e6..e058ace1d10b 100644 --- a/docs/content/labs/IPv6/hostedcluster/index.md +++ b/docs/content/labs/IPv6/hostedcluster/index.md @@ -1,3 +1,7 @@ +--- +title: Hosted Cluster Creation +--- + Hosted Cluster, as mentioned in the documentation [here](https://hypershift.pages.dev/reference/concepts-and-personas/), is essentially an OCP API endpoint managed by Hypershift. In this context, we will also include the term HostedControlPlane to enhance readability and comprehension. This terminology is further explained in the same [link](https://hypershift.pages.dev/reference/concepts-and-personas/). The Hosted Cluster comprises two main components: diff --git a/docs/content/labs/IPv6/hostedcluster/infraenv.md b/docs/content/labs/IPv6/hostedcluster/infraenv.md index c1096a42505c..ea6117cb7e20 100644 --- a/docs/content/labs/IPv6/hostedcluster/infraenv.md +++ b/docs/content/labs/IPv6/hostedcluster/infraenv.md @@ -1,3 +1,7 @@ +--- +title: Infra Env +--- + The `InfraEnv` is an Assisted Service object that includes essential details such as the `pullSecretRef` and the `sshAuthorizedKey`. These details are used to create the RHCOS Boot Image customized specifically for the cluster. Below is the structure of this object: ```yaml diff --git a/docs/content/labs/IPv6/hostedcluster/nodepool.md b/docs/content/labs/IPv6/hostedcluster/nodepool.md index 98d1fe264d28..d1e36464a25a 100644 --- a/docs/content/labs/IPv6/hostedcluster/nodepool.md +++ b/docs/content/labs/IPv6/hostedcluster/nodepool.md @@ -1,3 +1,7 @@ +--- +title: Node Pools +--- + A `NodePool` is a scalable set of worker nodes associated with a HostedCluster. NodePool machine architectures remain consistent within a specific pool and are independent of the underlying machine architecture of the control plane. !!! note diff --git a/docs/content/labs/IPv6/hostedcluster/worker-nodes.md b/docs/content/labs/IPv6/hostedcluster/worker-nodes.md index 4e67f8a6d2de..3ae95e9908aa 100644 --- a/docs/content/labs/IPv6/hostedcluster/worker-nodes.md +++ b/docs/content/labs/IPv6/hostedcluster/worker-nodes.md @@ -1,3 +1,7 @@ +--- +title: Worker Nodes +--- + Regarding the worker nodes, if you are working on real bare metal, this step is crucial to ensure that the details set in the `BareMetalHost` are correctly configured. If not, you will need to debug why it's not functioning as expected. However, if you are working with virtual machines, you can follow these steps to create empty ones that will be consumed by the Metal3 operator. To achieve this, we will utilize Kcli. diff --git a/docs/content/labs/IPv6/hypervisor/redfish-for-vms.md b/docs/content/labs/IPv6/hypervisor/redfish-for-vms.md index fb447d938e71..4f02cd7bd350 100644 --- a/docs/content/labs/IPv6/hypervisor/redfish-for-vms.md +++ b/docs/content/labs/IPv6/hypervisor/redfish-for-vms.md @@ -1,3 +1,7 @@ +--- +title: BMC Access for Metal3 +--- + In a bare metal environment, the preferred approach is to utilize the actual BMC (Baseboard Management Controller) of the nodes used for the management cluster, which can be managed by Metal3 for discovery and provisioning. However, in a virtual environment, this approach is not feasible. As a workaround, we will use `ksushy`, which is an implementation of `sushy-tools`, allowing us to simulate BMCs for the virtual machines. To configure `ksushy` we need to execute these commands: diff --git a/docs/content/labs/IPv6/mgmt-cluster/compact-ipv6.md b/docs/content/labs/IPv6/mgmt-cluster/compact-ipv6.md index 2068574d2064..fb8c75aa1436 100644 --- a/docs/content/labs/IPv6/mgmt-cluster/compact-ipv6.md +++ b/docs/content/labs/IPv6/mgmt-cluster/compact-ipv6.md @@ -1,3 +1,7 @@ +--- +title: OpenShift Compact IPv6 +--- + In this section, we will discuss how to deploy the Openshift management cluster. To do that, we need to have the following files in place: 1. **Pull Secret** diff --git a/docs/content/labs/IPv6/mgmt-cluster/index.md b/docs/content/labs/IPv6/mgmt-cluster/index.md index 1b8e8015bcf5..6c23656c00fe 100644 --- a/docs/content/labs/IPv6/mgmt-cluster/index.md +++ b/docs/content/labs/IPv6/mgmt-cluster/index.md @@ -1,3 +1,7 @@ +--- +title: Management Cluster Provisioning +--- + ## Openshift Management Cluster This section contains the necessary artifacts to set up an Openshift management cluster based on virtual machines using kcli as the primary tool. Another option is to use dev-scripts, which uses a different approach. diff --git a/docs/content/labs/IPv6/mgmt-cluster/network.md b/docs/content/labs/IPv6/mgmt-cluster/network.md index 5e989e5fd38c..bf7163787421 100644 --- a/docs/content/labs/IPv6/mgmt-cluster/network.md +++ b/docs/content/labs/IPv6/mgmt-cluster/network.md @@ -1,3 +1,7 @@ +--- +title: Networking +--- + Firstly, we need to ensure that we have the right networks prepared for use in the Hypervisor. These networks will be used to host both the Management and Hosted clusters. To configure these networks, we will use the following `kcli` command: diff --git a/docs/content/labs/common/hypervisor/network-manager-dispatcher.md b/docs/content/labs/common/hypervisor/network-manager-dispatcher.md index f831cf042946..c2238cb8106d 100644 --- a/docs/content/labs/common/hypervisor/network-manager-dispatcher.md +++ b/docs/content/labs/common/hypervisor/network-manager-dispatcher.md @@ -1,3 +1,7 @@ +--- +title: Network Manager Dispatcher +--- + This script modifies the system DNS resolver to prioritize pointing to the `dnsmasq` service (configured later). This ensures that virtual machines can resolve the various domains, routes, and registries required for the different steps of the process. To enable this, you need to create a script named `forcedns` in `/etc/NetworkManager/dispatcher.d/` with the following content: diff --git a/docs/content/labs/common/mce/agentserviceconfig.md b/docs/content/labs/common/mce/agentserviceconfig.md index 06b9c8d9fec1..83cc04be119a 100644 --- a/docs/content/labs/common/mce/agentserviceconfig.md +++ b/docs/content/labs/common/mce/agentserviceconfig.md @@ -1,3 +1,7 @@ +--- +title: Agent Service Config +--- + The Agent Service Config object is an essential component of the Assisted Service addon included in MCE/ACM, responsible for Baremetal cluster deployment. When the addon is enabled, you must deploy an operand (CRD) named `AgentServiceConfig` to configure it. ## Agent Service Config Objects diff --git a/docs/content/labs/common/mce/index.md b/docs/content/labs/common/mce/index.md index c555898bf0c2..3f3e542fd601 100644 --- a/docs/content/labs/common/mce/index.md +++ b/docs/content/labs/common/mce/index.md @@ -1,3 +1,7 @@ +--- +title: Multicluster Engine +--- + The Multicluster Engine (MCE) is a component of the ACM bundle. It plays a crucial role in deploying clusters across multiple providers. ## Credentials and Authorization diff --git a/docs/content/labs/common/mce/multicluster-engine.md b/docs/content/labs/common/mce/multicluster-engine.md index e86d07f4c960..9b73a5a3a217 100644 --- a/docs/content/labs/common/mce/multicluster-engine.md +++ b/docs/content/labs/common/mce/multicluster-engine.md @@ -1,3 +1,7 @@ +--- +title: ACM/MCE Deployment +--- + The deployment of each component will depend on your needs, follow the next links accordingly: - [ACM Deployment](https://github.com/stolostron/deploy#deploy-using-the-startsh-script-the-easy-way) diff --git a/docs/content/labs/common/mirror/ICSP-IDMS.md b/docs/content/labs/common/mirror/ICSP-IDMS.md index ef2a1ae11add..f31e5d52b1c6 100644 --- a/docs/content/labs/common/mirror/ICSP-IDMS.md +++ b/docs/content/labs/common/mirror/ICSP-IDMS.md @@ -1,3 +1,7 @@ +--- +title: Image Content Policies +--- + Once the mirroring process is complete, you will have two main objects that need to be applied in the Management Cluster: 1. ICSP (Image Content Source Policies) or IDMS (Image Digest Mirror Set). diff --git a/docs/content/labs/common/mirror/mirroring.md b/docs/content/labs/common/mirror/mirroring.md index dcfd4c1edfef..ddb6f855ef3a 100644 --- a/docs/content/labs/common/mirror/mirroring.md +++ b/docs/content/labs/common/mirror/mirroring.md @@ -1,3 +1,7 @@ +--- +title: Mirroring +--- + The mirroring step can take some time to complete, so we recommend starting with this part once the Registry server is up and running. For this purpose, we will use the `oc-mirror` tool, a binary that utilizes an object called `ImageSetConfiguration`. diff --git a/docs/content/labs/common/tls-certificates.md b/docs/content/labs/common/tls-certificates.md index 0c842abca7fe..af4b41e6bc73 100644 --- a/docs/content/labs/common/tls-certificates.md +++ b/docs/content/labs/common/tls-certificates.md @@ -1,3 +1,7 @@ +--- +title: TLS Certificates +--- + !!! important This section is only relevant in disconnected scenarios. If this doesn't apply to your situation, please proceed to the next section. diff --git a/docs/content/labs/common/watching/watching-cp.md b/docs/content/labs/common/watching/watching-cp.md index 8f91c4379557..2ac12b5a8986 100644 --- a/docs/content/labs/common/watching/watching-cp.md +++ b/docs/content/labs/common/watching/watching-cp.md @@ -1,3 +1,7 @@ +--- +title: Watching the Control Plane +--- + Now it's a matter of waiting for the cluster to finish the deployment, so let's take a look at some useful commands on the Management cluster side: ```bash diff --git a/docs/content/labs/common/watching/watching-dp.md b/docs/content/labs/common/watching/watching-dp.md index 6cf865bfeb55..f4af7b64fb7c 100644 --- a/docs/content/labs/common/watching/watching-dp.md +++ b/docs/content/labs/common/watching/watching-dp.md @@ -1,3 +1,7 @@ +--- +title: Watching the Data Plane +--- + If you check the Hosted cluster side you can check how the Operators are progressing and what is the status. To do that we will use these commands ```bash diff --git a/docs/content/recipes/common/control-plane-metrics-forwarding.md b/docs/content/recipes/common/control-plane-metrics-forwarding.md index 2e10ef619e4b..764efda4150b 100644 --- a/docs/content/recipes/common/control-plane-metrics-forwarding.md +++ b/docs/content/recipes/common/control-plane-metrics-forwarding.md @@ -1,3 +1,7 @@ +--- +title: Control Plane Metrics Forwarding +--- + ## Enable Control Plane Metrics Forwarding to Hosted Clusters !!! important diff --git a/docs/content/recipes/common/exposing-dataplane-with-metallb.md b/docs/content/recipes/common/exposing-dataplane-with-metallb.md index 2bbcd586b968..02d42327bf07 100644 --- a/docs/content/recipes/common/exposing-dataplane-with-metallb.md +++ b/docs/content/recipes/common/exposing-dataplane-with-metallb.md @@ -1,3 +1,7 @@ +--- +title: Expose Data Plane Ingress via MetalLB +--- + ## Configure MetalLB for HostedCluster's Data Plane - Deploy the MetalLB Operator using the OLM, applying this manifest or using the UI Console: diff --git a/docs/content/reference/aggregated-docs.md b/docs/content/reference/aggregated-docs.md index 3991b06679b4..7f89a07ddc8a 100644 --- a/docs/content/reference/aggregated-docs.md +++ b/docs/content/reference/aggregated-docs.md @@ -154,6 +154,10 @@ The best PRs to use as a template are the simpler single-capability additions li ## Source: docs/content/contribute/branch-process.md +--- +title: OCP Branching Tasks +--- + ## OCP Branching Tasks for the HyperShift Team These are a set of tasks we need to perform on every OCP branching. We need to: @@ -286,10 +290,9 @@ title: Contribute documentation # Contributing documentation -HyperShift's documentation is based on MkDocs with the -Material theme and roughly follows the -Diátaxis Framework for content organization and stylistic -approach. +HyperShift's documentation is based on Zensical and +roughly follows the Diátaxis Framework for content +organization and stylistic approach. The documentation site is built and published automatically to https://hypershift.pages.dev/. @@ -299,12 +302,8 @@ All documentation lives in the `docs` directory of the Git repository. All content should be Markdown files placed in the `docs/content` directory. The MkDocs configuration file -contains all the MkDocs and Material theme configuration, including the navigation -structure for the site. - -The `quay.io/hypershift/mkdocs-material:latest` image (Dockerfile) -is published to provide an easy and portable way to run `mkdocs` fully configured -to preview the site equivalent to the published site. +contains all the Zensical configuration, including the navigation structure for +the site. !!! note @@ -335,20 +334,77 @@ To start a live preview of the site which automatically rebuilds and refreshes i response to local content and configuration changes, run the following from the `docs` directory: +=== "Native" + + ```shell + uv run --frozen zensical serve + ``` + +=== "Containerized" + + ```shell + make serve-containerized + ``` + +Visit the site at http://127.0.0.1:8000. + +## Visual comparison + +When making changes that affect the site's appearance (theme updates, layout +changes, navigation restructuring), you can generate a visual diff against the +current `main` branch: + ```shell -make serve-containerized +cd docs +make compare ``` -Visit the site at http://0.0.0.0:8000. +This builds both the base site (from `main`, using mkdocs-material) and the head +site (from your working tree, using Zensical), screenshots every page with +Playwright, and produces a pixel-diff report at `compare/output/index.html`. -!!! note +To view the report locally: - The `serve-containerized` Make target runs the `quay.io/hypershift/mkdocs-material:latest` - image with the local container runtime. Running `mkdocs` natively is possible - but not supported. +```shell +make compare-serve +``` + +You can also compare against a different ref: + +```shell +make compare BASE=v4.18 +``` + +To share the report, you can host the `compare/output/` directory on any static +hosting service. For example, using a GitHub Pages repository: + +```shell +# Clone or create a repo with a gh-pages branch +git clone git@github.com:/.git /tmp/compare-site +cd /tmp/compare-site && git checkout gh-pages + +# Copy the report +rm -rf screenshots-* index.html results.json +cp -r /docs/compare/output/* . - If you need more control over the local preview server, consult the Makefile - as a guide to constructing your own local server command. +# Commit and push +git add -A && git commit -m "Update comparison report" +git push origin gh-pages +``` + +The report will be available at `https://.github.io//`. + +To start fresh, run: + +```shell +make compare-clean +``` + +!!! tip + + The base site is cached in `site-base/` and reused across runs. If you only + changed your working tree, the next `make compare` will only rebuild + `site-head` and regenerate the diffs. ## Generate the API reference @@ -4829,6 +4885,10 @@ This implementation provides a secure, autonomous solution that allows HostedClu ## Source: docs/content/how-to/agent/other-sdn-providers.md +--- +title: Other SDN providers +--- + This document explains how to create a HostedCluster that runs an SDN provider different from OVNKubernetes. The document assumes that you already have the required infrastructure in place to create HostedClusters. !!! important @@ -9454,6 +9514,10 @@ This implementation provides a secure, autonomous solution that allows HostedClu ## Source: docs/content/how-to/aws/other-sdn-providers.md +--- +title: Other SDN providers +--- + This document explains how to create a HostedCluster that runs an SDN provider different from OVNKubernetes. The document assumes that you already have the required infrastructure in place to create HostedClusters. !!! important @@ -14360,7 +14424,7 @@ When a pull request modifies files under `docs/`, GitHub Actions workflows autom The preview system uses two separate workflows for security, following the reusable workflow pattern described in GitHub Actions Workflows: -1. **Docs Build** (`.github/workflows/docs-build.yaml`) — triggers on `pull_request` for changes under `docs/`. The caller delegates to `docs-build-reusable.yaml@main`, which checks out the PR code, builds with MkDocs in strict mode, and uploads the built site as an artifact. This workflow has no access to secrets. +1. **Docs Build** (`.github/workflows/docs-build.yaml`) — triggers on `pull_request` for changes under `docs/`. The caller delegates to `docs-build-reusable.yaml@main`, which checks out the PR code, builds with Zensical in strict mode, and uploads the built site as an artifact. This workflow has no access to secrets. 2. **Docs Deploy** (`.github/workflows/docs-deploy.yaml`) — triggers via `workflow_run` when the Docs Build workflow completes successfully. It downloads the built artifact and deploys to Cloudflare Pages. This workflow has access to the `docs-preview` environment secrets but never executes PR code. GitHub shows a **View deployment** link in the PR timeline via the `docs-preview` environment. @@ -14384,8 +14448,7 @@ To preview documentation locally: ```bash cd docs -pip install -r requirements.txt -mkdocs serve +uv run zensical serve ``` Then open http://127.0.0.1:8000. @@ -14449,7 +14512,7 @@ All workflows run on self-hosted ARC runners and target the `main` and `release- | Caller | Reusable | Purpose | |--------|----------|---------| -| `docs-build.yaml` | `docs-build-reusable.yaml` | Build MkDocs site in strict mode | +| `docs-build.yaml` | `docs-build-reusable.yaml` | Build Zensical site in strict mode | !!! info The `docs-deploy.yaml` workflow is not a reusable workflow pair — it triggers via `workflow_run` after the Docs Build completes to deploy the preview. See Documentation Preview for details. @@ -15079,7 +15142,7 @@ These checks only run when relevant files change: |------------|-------------|-----------------| | **Envtest OCP API Validation** | `api/`, `test/envtest/`, CRD test assets | `FAIL` with the test name — see `test/envtest/README.md` for details | | **Envtest Vanilla Kube API Validation** | Same as above | Same as above | -| **Docs Build** | `docs/**` changes | MkDocs build errors — usually a broken link or YAML syntax error | +| **Docs Build** | `docs/**` changes | Zensical build errors — usually a broken link or YAML syntax error | | **Validate CPO Overrides** | `hypershift-operator/controlplaneoperator-overrides/assets/overrides.yaml` changes | Validation error for the CPO overrides file | | **gocacheprog Tests** | `contrib/ci/gocacheprog/**` changes | `FAIL` with the test name | @@ -22538,6 +22601,10 @@ After applying this change, the worker nodes will be able to consume the mirror ## Source: docs/content/how-to/disconnected/idms-icsp-for-management-clusters.md +--- +title: IDMS/ICSP Config for Management Cluster +--- + ## Configuring disconnected HostedControlPlanes deployments !!! Note @@ -30422,6 +30489,10 @@ The list of components restarted are listed below: ## Source: docs/content/how-to/sdn/other-sdn-providers.md +--- +title: Other SDN providers +--- + This document explains how to create a HostedCluster that runs an SDN provider different from OVNKubernetes. The document assumes that you already have the required infrastructure in place to create HostedClusters. !!! important @@ -31224,6 +31295,10 @@ systemctl enable --now dnsmasq-virt ## Source: docs/content/labs/Dual/hostedcluster/baremetalhost.md +--- +title: Bare Metal Hosts +--- + ## Bare Metal Hosts A **BareMetalHost** is an openshift-machine-api object that encompasses both physical and logical details, allowing it to be identified by the Metal3 operator. Subsequently, these details are associated with other Assisted Service objects known as Agents. The structure of this object is as follows: @@ -31358,6 +31433,10 @@ So now, we need to wait until the nodes join the cluster. The Agents will provid ## Source: docs/content/labs/Dual/hostedcluster/hostedcluster.md +--- +title: Hosted Cluster Object +--- + In this section, we will focus on all the related objects necessary to achieve a Disconnected Hosted Cluster deployment. **Premises**: @@ -31617,6 +31696,10 @@ After some time, we will have almost all the pieces in place, and the Control Pl ## Source: docs/content/labs/Dual/hostedcluster/index.md +--- +title: Hosted Cluster Creation +--- + A Hosted Cluster, as mentioned in the documentation here, is essentially an OCP API endpoint managed by Hypershift. In this context, we will also include the term HostedControlPlane to enhance readability and comprehension. This terminology is further explained in the same link. The Hosted Cluster comprises two main components: @@ -31630,6 +31713,10 @@ With this foundational understanding, we can commence our Hosted Cluster deploym ## Source: docs/content/labs/Dual/hostedcluster/infraenv.md +--- +title: Infra Env +--- + The `InfraEnv` is an Assisted Service object that includes essential details such as the `pullSecretRef` and the `sshAuthorizedKey`. These details are used to create the RHCOS Boot Image customized specifically for the cluster. Below is the structure of this object: ```yaml @@ -31667,6 +31754,10 @@ clusters-hosted-dual hosted 2023-09-11T15:14:10Z ## Source: docs/content/labs/Dual/hostedcluster/nodepool.md +--- +title: Node Pools +--- + A `NodePool` is a scalable set of worker nodes associated with a HostedCluster. NodePool machine architectures remain consistent within a specific pool and are independent of the underlying machine architecture of the control plane. !!! note @@ -31733,6 +31824,10 @@ clusters hosted-dual hosted 0 False ## Source: docs/content/labs/Dual/hostedcluster/worker-nodes.md +--- +title: Worker Nodes +--- + Regarding the worker nodes, if you are working on real bare metal, this step is crucial to ensure that the details set in the `BareMetalHost` are correctly configured. If not, you will need to debug why it's not functioning as expected. However, if you are working with virtual machines, you can follow these steps to create empty ones that will be consumed by the Metal3 operator. To achieve this, we will utilize Kcli. @@ -31826,6 +31921,10 @@ This section is primarily focused on Virtual Machines. If you are working with r ## Source: docs/content/labs/Dual/hypervisor/network-manager-dispatcher.md +--- +title: Network Manager Dispatcher +--- + This script modifies the system DNS resolver to prioritize pointing to the `dnsmasq` service (configured later). This ensures that virtual machines can resolve the various domains, routes, and registries required for the different steps of the process. To enable this, you need to create a script named `forcedns` in `/etc/NetworkManager/dispatcher.d/` with the following content: @@ -31945,6 +32044,10 @@ For more info about Kcli please visit the official documentation. ## Source: docs/content/labs/Dual/hypervisor/redfish-for-vms.md +--- +title: BMC Access for Metal3 +--- + In a bare metal environment, the preferred approach is to utilize the actual BMC (Baseboard Management Controller) of the nodes used for the management cluster, which can be managed by Metal3 for discovery and provisioning. However, in a virtual environment, this approach is not feasible. As a workaround, we will use `ksushy`, which is an implementation of `sushy-tools`, allowing us to simulate BMCs for the virtual machines. To configure `ksushy`, execute the following commands: @@ -32020,6 +32123,10 @@ Please note that this documentation is designed to be followed in a specific seq ## Source: docs/content/labs/Dual/mce/agentserviceconfig.md +--- +title: Agent Service Config +--- + The Agent Service Config object is an essential component of the Assisted Service addon included in MCE/ACM, responsible for Baremetal cluster deployment. When the addon is enabled, you must deploy an operand (CRD) named `AgentServiceConfig` to configure it. ## Agent Service Config Objects @@ -32175,6 +32282,10 @@ assisted-service-668b49548-9m7xw 2/2 Running 5 ## Source: docs/content/labs/Dual/mce/index.md +--- +title: Multicluster Engine +--- + The Multicluster Engine (MCE) is a component of the ACM bundle. It plays a crucial role in deploying clusters across multiple providers. ## Credentials and Authorization @@ -32189,6 +32300,10 @@ Agent Service Config{ .md-button } ## Source: docs/content/labs/Dual/mce/multicluster-engine.md +--- +title: ACM/MCE Deployment +--- + The deployment of each component will depend on your needs, follow the next links accordingly: - ACM Deployment @@ -32203,6 +32318,10 @@ The deployment of each component will depend on your needs, follow the next link ## Source: docs/content/labs/Dual/mgmt-cluster/compact-dual.md +--- +title: OpenShift Compact Dual +--- + In this section, we will discuss how to deploy the Openshift management cluster. To do that, we need to have the following files in place: 1. **Pull Secret** @@ -32311,6 +32430,10 @@ kcli create cluster openshift --pf mgmt-compact-hub-dual.yaml ## Source: docs/content/labs/Dual/mgmt-cluster/index.md +--- +title: Management Cluster Provisioning +--- + ## Openshift Management Cluster This section contains the necessary artifacts to set up an Openshift management cluster based on virtual machines using kcli as the primary tool. Another option is to use dev-scripts, which uses a different approach. @@ -32322,6 +32445,10 @@ Openshift Compact Dual{ .md-button } ## Source: docs/content/labs/Dual/mgmt-cluster/network.md +--- +title: Networking +--- + Firstly, we need to ensure that we have the right networks prepared for use in the Hypervisor. These networks will be used to host both the Management and Hosted clusters. To configure these networks, we will use the following `kcli` command: @@ -32370,6 +32497,10 @@ type: routed ## Source: docs/content/labs/Dual/mirror/ICSP-IDMS.md +--- +title: Image Content Policies +--- + Once the mirroring process is complete, you will have two main objects that need to be applied in the Management Cluster: 1. ICSP (Image Content Source Policies) or IDMS (Image Digest Mirror Set). @@ -32418,6 +32549,10 @@ ICSP and IDMS{ .md-button } ## Source: docs/content/labs/Dual/mirror/mirroring.md +--- +title: Mirroring +--- + The mirroring step can take some time to complete, so we recommend starting with this part once the Registry server is up and running. For this purpose, we will use the `oc-mirror` tool, a binary that utilizes an object called `ImageSetConfiguration`. @@ -32596,6 +32731,10 @@ The root folder for the registry is situated at /opt/registry, and it's structur ## Source: docs/content/labs/Dual/tls-certificates.md +--- +title: TLS Certificates +--- + !!! important This section is only relevant in disconnected scenarios. If this doesn't apply to your situation, please proceed to the next section. @@ -32703,6 +32842,10 @@ Data Plane perspective{ .md-button } ## Source: docs/content/labs/Dual/watching/watching-cp.md +--- +title: Watching the Control Plane +--- + Now it's a matter of waiting for the cluster to finish the deployment, so let's take a look at some useful commands on the Management cluster side: ```bash @@ -32728,6 +32871,10 @@ This is how it looks: ## Source: docs/content/labs/Dual/watching/watching-dp.md +--- +title: Watching the Data Plane +--- + If you check the Hosted cluster side you can check how the Operators are progressing and what is the status. To do that we will use these commands ```bash @@ -32900,6 +33047,10 @@ systemctl enable --now dnsmasq-virt ## Source: docs/content/labs/IPv4/hostedcluster/baremetalhost.md +--- +title: Bare Metal Hosts +--- + ## Bare Metal Hosts A **BareMetalHost** is an openshift-machine-api object that encompasses both physical and logical details, allowing it to be identified by the Metal3 operator. Subsequently, these details are associated with other Assisted Service objects known as Agents. The structure of this object is as follows: @@ -33032,6 +33183,10 @@ So now, we need to wait until the nodes join the cluster. The Agents will provid ## Source: docs/content/labs/IPv4/hostedcluster/hostedcluster.md +--- +title: Hosted Cluster Object +--- + In this section, we will focus on all the related objects necessary to achieve a Disconnected Hosted Cluster deployment. **Premises**: @@ -33288,6 +33443,10 @@ After some time, we will have almost all the pieces in place, and the Control Pl ## Source: docs/content/labs/IPv4/hostedcluster/index.md +--- +title: Hosted Cluster Creation +--- + Hosted Cluster, as mentioned in the documentation here, is essentially an OCP API endpoint managed by Hypershift. In this context, we will also include the term HostedControlPlane to enhance readability and comprehension. This terminology is further explained in the same link. The Hosted Cluster consists of two main components: @@ -33301,6 +33460,10 @@ Now, with this foundational understanding, we can proceed with the deployment of ## Source: docs/content/labs/IPv4/hostedcluster/infraenv.md +--- +title: Infra Env +--- + The `InfraEnv` is an Assisted Service object that includes essential details such as the `pullSecretRef` and the `sshAuthorizedKey`. These details are used to create the RHCOS Boot Image customized specifically for the cluster. Below is the structure of this object: ```yaml @@ -33338,6 +33501,10 @@ clusters-hosted-ipv4 hosted 2023-09-11T15:14:10Z ## Source: docs/content/labs/IPv4/hostedcluster/nodepool.md +--- +title: Node Pools +--- + A `NodePool` is a scalable set of worker nodes associated with a HostedCluster. NodePool machine architectures remain consistent within a specific pool and are independent of the underlying machine architecture of the control plane. !!! note @@ -33404,6 +33571,10 @@ clusters hosted-ipv4 hosted 0 False ## Source: docs/content/labs/IPv4/hostedcluster/worker-nodes.md +--- +title: Worker Nodes +--- + Regarding the worker nodes, if you are working on real bare metal, this step is crucial to ensure that the details set in the `BareMetalHost` are correctly configured. If not, you will need to debug why it's not functioning as expected. However, if you are working with virtual machines, you can follow these steps to create empty ones that will be consumed by the Metal3 operator. To achieve this, we will utilize Kcli. @@ -33497,6 +33668,10 @@ This section is entirely dedicated to virtual machine environments. If you are w ## Source: docs/content/labs/IPv4/hypervisor/network-manager-dispatcher.md +--- +title: Network Manager Dispatcher +--- + This script modifies the system DNS resolver to prioritize pointing to the `dnsmasq` service (configured later). This ensures that virtual machines can resolve the various domains, routes, and registries required for the different steps of the process. To enable this, you need to create a script named `forcedns` in `/etc/NetworkManager/dispatcher.d/` with the following content: @@ -33616,6 +33791,10 @@ For more info about Kcli please visit the official documentation. ## Source: docs/content/labs/IPv4/hypervisor/redfish-for-vms.md +--- +title: BMC Access for Metal3 +--- + In a bare metal environment, the preferred approach is to utilize the actual BMC (Baseboard Management Controller) of the nodes used for the management cluster, which can be managed by Metal3 for discovery and provisioning. However, in a virtual environment, this approach is not feasible. As a workaround, we will use `ksushy`, which is an implementation of `sushy-tools`, allowing us to simulate BMCs for the virtual machines. To configure `ksushy` we need to execute these commands: @@ -33689,6 +33868,10 @@ This documentation is structured to be followed in a specific order: ## Source: docs/content/labs/IPv4/mce/agentserviceconfig.md +--- +title: Agent Service Config +--- + The Agent Service Config object is an essential component of the Assisted Service addon included in MCE/ACM, responsible for Baremetal cluster deployment. When the addon is enabled, you must deploy an operand (CRD) named `AgentServiceConfig` to configure it. ## Agent Service Config Objects @@ -33844,6 +34027,10 @@ assisted-service-668b49548-9m7xw 2/2 Running 5 ## Source: docs/content/labs/IPv4/mce/index.md +--- +title: Multicluster Engine +--- + The Multicluster Engine (MCE) is a component of the ACM bundle. It plays a crucial role in deploying clusters across multiple providers. ## Credentials and Authorization @@ -33858,6 +34045,10 @@ Agent Service Config{ .md-button } ## Source: docs/content/labs/IPv4/mce/multicluster-engine.md +--- +title: ACM/MCE Deployment +--- + The deployment of each component will depend on your needs, follow the next links accordingly: - ACM Deployment @@ -33872,6 +34063,10 @@ The deployment of each component will depend on your needs, follow the next link ## Source: docs/content/labs/IPv4/mgmt-cluster/compact-ipv4.md +--- +title: OpenShift Compact IPv4 +--- + In this section, we will discuss how to deploy the Openshift management cluster. To do that, we need to have the following files in place: 1. **Pull Secret** @@ -33969,6 +34164,10 @@ kcli create cluster openshift --pf mgmt-compact-hub-ipv4.yaml ## Source: docs/content/labs/IPv4/mgmt-cluster/index.md +--- +title: Management Cluster Provisioning +--- + ## Openshift Management Cluster This section contains the necessary artifacts to set up an Openshift management cluster based on virtual machines using kcli as the primary tool. Another option is to use dev-scripts, which uses a different approach. @@ -33980,6 +34179,10 @@ Openshift Compact Dual{ .md-button } ## Source: docs/content/labs/IPv4/mgmt-cluster/network.md +--- +title: Networking +--- + Firstly, we need to ensure that we have the right networks prepared for use in the Hypervisor. These networks will be used to host both the Management and Hosted clusters. To configure these networks, we will use the following `kcli` command: @@ -34027,6 +34230,10 @@ type: routed ## Source: docs/content/labs/IPv4/mirror/ICSP-IDMS.md +--- +title: Image Content Policies +--- + Once the mirroring process is complete, you will have two main objects that need to be applied in the Management Cluster: 1. ICSP (Image Content Source Policies) or IDMS (Image Digest Mirror Set). @@ -34075,6 +34282,10 @@ ICSP and IDMS{ .md-button } ## Source: docs/content/labs/IPv4/mirror/mirroring.md +--- +title: Mirroring +--- + The mirroring step can take some time to complete, so we recommend starting with this part once the Registry server is up and running. For this purpose, we will use the `oc-mirror` tool, a binary that utilizes an object called `ImageSetConfiguration`. @@ -34253,6 +34464,10 @@ The root folder for the registry is situated at /opt/registry, and it's structur ## Source: docs/content/labs/IPv4/tls-certificates.md +--- +title: TLS Certificates +--- + !!! important This section is only relevant in disconnected scenarios. If this doesn't apply to your situation, please proceed to the next section. @@ -34360,6 +34575,10 @@ Data Plane perspective{ .md-button } ## Source: docs/content/labs/IPv4/watching/watching-cp.md +--- +title: Watching the Control Plane +--- + Now it's a matter of waiting for the cluster to finish the deployment, so let's take a look at some useful commands on the Management cluster side: ```bash @@ -34385,6 +34604,10 @@ This is how it looks: ## Source: docs/content/labs/IPv4/watching/watching-dp.md +--- +title: Watching the Data Plane +--- + If you check the Hosted cluster side you can check how the Operators are progressing and what is the status. To do that we will use these commands ```bash @@ -34550,6 +34773,10 @@ systemctl enable --now dnsmasq-virt ## Source: docs/content/labs/IPv6/hostedcluster/baremetalhost.md +--- +title: Bare Metal Hosts +--- + ## Bare Metal Hosts A **BareMetalHost** is an openshift-machine-api object that encompasses both physical and logical details, allowing it to be identified by the Metal3 operator. Subsequently, these details are associated with other Assisted Service objects known as Agents. The structure of this object is as follows: @@ -34683,6 +34910,10 @@ So now, we need to wait until the nodes join the cluster. The Agents will provid ## Source: docs/content/labs/IPv6/hostedcluster/hostedcluster.md +--- +title: Hosted Cluster Object +--- + In this section, we will focus on all the related objects necessary to achieve a Disconnected Hosted Cluster deployment. **Premises**: @@ -34942,6 +35173,10 @@ After some time, we will have almost all the pieces in place, and the Control Pl ## Source: docs/content/labs/IPv6/hostedcluster/index.md +--- +title: Hosted Cluster Creation +--- + Hosted Cluster, as mentioned in the documentation here, is essentially an OCP API endpoint managed by Hypershift. In this context, we will also include the term HostedControlPlane to enhance readability and comprehension. This terminology is further explained in the same link. The Hosted Cluster comprises two main components: @@ -34955,6 +35190,10 @@ With this foundational understanding, we can commence our Hosted Cluster deploym ## Source: docs/content/labs/IPv6/hostedcluster/infraenv.md +--- +title: Infra Env +--- + The `InfraEnv` is an Assisted Service object that includes essential details such as the `pullSecretRef` and the `sshAuthorizedKey`. These details are used to create the RHCOS Boot Image customized specifically for the cluster. Below is the structure of this object: ```yaml @@ -34992,6 +35231,10 @@ clusters-hosted-ipv6 hosted 2023-09-11T15:14:10Z ## Source: docs/content/labs/IPv6/hostedcluster/nodepool.md +--- +title: Node Pools +--- + A `NodePool` is a scalable set of worker nodes associated with a HostedCluster. NodePool machine architectures remain consistent within a specific pool and are independent of the underlying machine architecture of the control plane. !!! note @@ -35058,6 +35301,10 @@ clusters hosted-ipv6 hosted 0 False ## Source: docs/content/labs/IPv6/hostedcluster/worker-nodes.md +--- +title: Worker Nodes +--- + Regarding the worker nodes, if you are working on real bare metal, this step is crucial to ensure that the details set in the `BareMetalHost` are correctly configured. If not, you will need to debug why it's not functioning as expected. However, if you are working with virtual machines, you can follow these steps to create empty ones that will be consumed by the Metal3 operator. To achieve this, we will utilize Kcli. @@ -35150,6 +35397,10 @@ This section is primarily focused on Virtual Machines. If you are working with r ## Source: docs/content/labs/IPv6/hypervisor/network-manager-dispatcher.md +--- +title: Network Manager Dispatcher +--- + This script modifies the system DNS resolver to prioritize pointing to the `dnsmasq` service (configured later). This ensures that virtual machines can resolve the various domains, routes, and registries required for the different steps of the process. To enable this, you need to create a script named `forcedns` in `/etc/NetworkManager/dispatcher.d/` with the following content: @@ -35269,6 +35520,10 @@ For more info about Kcli please visit the official documentation. ## Source: docs/content/labs/IPv6/hypervisor/redfish-for-vms.md +--- +title: BMC Access for Metal3 +--- + In a bare metal environment, the preferred approach is to utilize the actual BMC (Baseboard Management Controller) of the nodes used for the management cluster, which can be managed by Metal3 for discovery and provisioning. However, in a virtual environment, this approach is not feasible. As a workaround, we will use `ksushy`, which is an implementation of `sushy-tools`, allowing us to simulate BMCs for the virtual machines. To configure `ksushy` we need to execute these commands: @@ -35343,6 +35598,10 @@ This documentation is prepared to be followed in a concrete order: ## Source: docs/content/labs/IPv6/mce/agentserviceconfig.md +--- +title: Agent Service Config +--- + The Agent Service Config object is an essential component of the Assisted Service addon included in MCE/ACM, responsible for Baremetal cluster deployment. When the addon is enabled, you must deploy an operand (CRD) named `AgentServiceConfig` to configure it. ## Agent Service Config Objects @@ -35498,6 +35757,10 @@ assisted-service-668b49548-9m7xw 2/2 Running 5 ## Source: docs/content/labs/IPv6/mce/index.md +--- +title: Multicluster Engine +--- + The Multicluster Engine (MCE) is a component of the ACM bundle. It plays a crucial role in deploying clusters across multiple providers. ## Credentials and Authorization @@ -35512,6 +35775,10 @@ Agent Service Config{ .md-button } ## Source: docs/content/labs/IPv6/mce/multicluster-engine.md +--- +title: ACM/MCE Deployment +--- + The deployment of each component will depend on your needs, follow the next links accordingly: - ACM Deployment @@ -35526,6 +35793,10 @@ The deployment of each component will depend on your needs, follow the next link ## Source: docs/content/labs/IPv6/mgmt-cluster/compact-ipv6.md +--- +title: OpenShift Compact IPv6 +--- + In this section, we will discuss how to deploy the Openshift management cluster. To do that, we need to have the following files in place: 1. **Pull Secret** @@ -35628,6 +35899,10 @@ kcli create cluster openshift --pf mgmt-compact-hub-ipv6.yaml ## Source: docs/content/labs/IPv6/mgmt-cluster/index.md +--- +title: Management Cluster Provisioning +--- + ## Openshift Management Cluster This section contains the necessary artifacts to set up an Openshift management cluster based on virtual machines using kcli as the primary tool. Another option is to use dev-scripts, which uses a different approach. @@ -35639,6 +35914,10 @@ Openshift Compact Dual{ .md-button } ## Source: docs/content/labs/IPv6/mgmt-cluster/network.md +--- +title: Networking +--- + Firstly, we need to ensure that we have the right networks prepared for use in the Hypervisor. These networks will be used to host both the Management and Hosted clusters. To configure these networks, we will use the following `kcli` command: @@ -35686,6 +35965,10 @@ type: routed ## Source: docs/content/labs/IPv6/mirror/ICSP-IDMS.md +--- +title: Image Content Policies +--- + Once the mirroring process is complete, you will have two main objects that need to be applied in the Management Cluster: 1. ICSP (Image Content Source Policies) or IDMS (Image Digest Mirror Set). @@ -35734,6 +36017,10 @@ ICSP and IDMS{ .md-button } ## Source: docs/content/labs/IPv6/mirror/mirroring.md +--- +title: Mirroring +--- + The mirroring step can take some time to complete, so we recommend starting with this part once the Registry server is up and running. For this purpose, we will use the `oc-mirror` tool, a binary that utilizes an object called `ImageSetConfiguration`. @@ -35912,6 +36199,10 @@ The root folder for the registry is situated at /opt/registry, and it's structur ## Source: docs/content/labs/IPv6/tls-certificates.md +--- +title: TLS Certificates +--- + !!! important This section is only relevant in disconnected scenarios. If this doesn't apply to your situation, please proceed to the next section. @@ -36019,6 +36310,10 @@ Data Plane perspective{ .md-button } ## Source: docs/content/labs/IPv6/watching/watching-cp.md +--- +title: Watching the Control Plane +--- + Now it's a matter of waiting for the cluster to finish the deployment, so let's take a look at some useful commands on the Management cluster side: ```bash @@ -36044,6 +36339,10 @@ This is how it looks: ## Source: docs/content/labs/IPv6/watching/watching-dp.md +--- +title: Watching the Data Plane +--- + If you check the Hosted cluster side you can check how the Operators are progressing and what is the status. To do that we will use these commands ```bash @@ -36126,6 +36425,10 @@ systemctl enable --now libvirtd ## Source: docs/content/labs/common/hypervisor/network-manager-dispatcher.md +--- +title: Network Manager Dispatcher +--- + This script modifies the system DNS resolver to prioritize pointing to the `dnsmasq` service (configured later). This ensures that virtual machines can resolve the various domains, routes, and registries required for the different steps of the process. To enable this, you need to create a script named `forcedns` in `/etc/NetworkManager/dispatcher.d/` with the following content: @@ -36272,6 +36575,10 @@ title: Hypervisor Prerequisites ## Source: docs/content/labs/common/mce/agentserviceconfig.md +--- +title: Agent Service Config +--- + The Agent Service Config object is an essential component of the Assisted Service addon included in MCE/ACM, responsible for Baremetal cluster deployment. When the addon is enabled, you must deploy an operand (CRD) named `AgentServiceConfig` to configure it. ## Agent Service Config Objects @@ -36427,6 +36734,10 @@ assisted-service-668b49548-9m7xw 2/2 Running 5 ## Source: docs/content/labs/common/mce/index.md +--- +title: Multicluster Engine +--- + The Multicluster Engine (MCE) is a component of the ACM bundle. It plays a crucial role in deploying clusters across multiple providers. ## Credentials and Authorization @@ -36441,6 +36752,10 @@ Agent Service Config{ .md-button } ## Source: docs/content/labs/common/mce/multicluster-engine.md +--- +title: ACM/MCE Deployment +--- + The deployment of each component will depend on your needs, follow the next links accordingly: - ACM Deployment @@ -36455,6 +36770,10 @@ The deployment of each component will depend on your needs, follow the next link ## Source: docs/content/labs/common/mirror/ICSP-IDMS.md +--- +title: Image Content Policies +--- + Once the mirroring process is complete, you will have two main objects that need to be applied in the Management Cluster: 1. ICSP (Image Content Source Policies) or IDMS (Image Digest Mirror Set). @@ -36503,6 +36822,10 @@ ICSP and IDMS{ .md-button } ## Source: docs/content/labs/common/mirror/mirroring.md +--- +title: Mirroring +--- + The mirroring step can take some time to complete, so we recommend starting with this part once the Registry server is up and running. For this purpose, we will use the `oc-mirror` tool, a binary that utilizes an object called `ImageSetConfiguration`. @@ -36681,6 +37004,10 @@ The root folder for the registry is situated at /opt/registry, and it's structur ## Source: docs/content/labs/common/tls-certificates.md +--- +title: TLS Certificates +--- + !!! important This section is only relevant in disconnected scenarios. If this doesn't apply to your situation, please proceed to the next section. @@ -36788,6 +37115,10 @@ Data Plane perspective{ .md-button } ## Source: docs/content/labs/common/watching/watching-cp.md +--- +title: Watching the Control Plane +--- + Now it's a matter of waiting for the cluster to finish the deployment, so let's take a look at some useful commands on the Management cluster side: ```bash @@ -36813,6 +37144,10 @@ This is how it looks: ## Source: docs/content/labs/common/watching/watching-dp.md +--- +title: Watching the Data Plane +--- + If you check the Hosted cluster side you can check how the Operators are progressing and what is the status. To do that we will use these commands ```bash @@ -37031,6 +37366,10 @@ The addon will detect the removal and redeploy the HyperShift Operator with the ## Source: docs/content/recipes/common/control-plane-metrics-forwarding.md +--- +title: Control Plane Metrics Forwarding +--- + ## Enable Control Plane Metrics Forwarding to Hosted Clusters !!! important @@ -37353,6 +37692,10 @@ This deletes the `endpoint-resolver` and `metrics-proxy` from the management clu ## Source: docs/content/recipes/common/exposing-dataplane-with-metallb.md +--- +title: Expose Data Plane Ingress via MetalLB +--- + ## Configure MetalLB for HostedCluster's Data Plane - Deploy the MetalLB Operator using the OLM, applying this manifest or using the UI Console: @@ -57615,6 +57958,10 @@ Note: the kube-apiserver will no longer be exposed through a dedicated LB servic ## Source: docs/content/reference/architecture/mce-and-agent.md +--- +title: Multicluster Engine and Agent +--- + **Introduction** This section elucidates the collaboration between Multicluster Engine and Agent to facilitate in-house deployments. Detailed documentation for each of the network stacks can be found in the *Self-Managed Laboratories* section. If you intend to set up a self-managed environment, please proceed to that section and follow the provided steps. @@ -58218,6 +58565,10 @@ This section of the HyperShift documentation contains references. ## Source: docs/content/reference/infrastructure/agent.md +--- +title: Agent +--- + The agent platform does not create any infrastructure but does have two kinds of prerequisites: 1. Agents: An Agent represents a host booted with a discovery image and ready to be provisioned as an OpenShift node. For more information, see here. @@ -58230,6 +58581,10 @@ You can find more details about the prerequisites in the how-to. ## Source: docs/content/reference/infrastructure/aws.md +--- +title: AWS +--- + In this section we want to dissect who creates what and what not. It contains 4 stages: - Infra pre-required and unmanaged for hypershift operator in an arbitrary AWS account @@ -59976,6 +60331,10 @@ services. ## Source: docs/content/reference/manifests/ibmcloud/4.10.md +--- +title: "4.10" +--- + **HostedCluster** ```yaml @@ -60306,6 +60665,10 @@ spec: ## Source: docs/content/reference/manifests/ibmcloud/4.11.md +--- +title: "4.11" +--- + **HostedCluster** ```yaml @@ -60625,6 +60988,10 @@ spec: ## Source: docs/content/reference/manifests/ibmcloud/4.12.md +--- +title: "4.12" +--- + **HostedCluster** ```yaml @@ -60937,6 +61304,10 @@ spec: ## Source: docs/content/reference/manifests/ibmcloud/4.13.md +--- +title: "4.13" +--- + **HostedCluster** ```yaml @@ -61245,6 +61616,10 @@ spec: ## Source: docs/content/reference/manifests/ibmcloud/4.9.md +--- +title: "4.9" +--- + **HostedCluster** ```yaml diff --git a/docs/content/reference/architecture/mce-and-agent.md b/docs/content/reference/architecture/mce-and-agent.md index 2f98bb5e51f4..20597105eae4 100644 --- a/docs/content/reference/architecture/mce-and-agent.md +++ b/docs/content/reference/architecture/mce-and-agent.md @@ -1,3 +1,7 @@ +--- +title: Multicluster Engine and Agent +--- + **Introduction** This section elucidates the collaboration between Multicluster Engine and Agent to facilitate in-house deployments. Detailed documentation for each of the network stacks can be found in the *Self-Managed Laboratories* section. If you intend to set up a self-managed environment, please proceed to that section and follow the provided steps. diff --git a/docs/content/reference/infrastructure/agent.md b/docs/content/reference/infrastructure/agent.md index 508f76594873..be2d72649308 100644 --- a/docs/content/reference/infrastructure/agent.md +++ b/docs/content/reference/infrastructure/agent.md @@ -1,3 +1,7 @@ +--- +title: Agent +--- + The agent platform does not create any infrastructure but does have two kinds of prerequisites: 1. Agents: An Agent represents a host booted with a discovery image and ready to be provisioned as an OpenShift node. For more information, see [here](https://github.com/openshift/assisted-service/blob/master/docs/hive-integration/kube-api-getting-started.md). diff --git a/docs/content/reference/infrastructure/aws.md b/docs/content/reference/infrastructure/aws.md index 2d7757095caa..3f945983072c 100644 --- a/docs/content/reference/infrastructure/aws.md +++ b/docs/content/reference/infrastructure/aws.md @@ -1,3 +1,7 @@ +--- +title: AWS +--- + In this section we want to dissect who creates what and what not. It contains 4 stages: - Infra pre-required and unmanaged for hypershift operator in an arbitrary AWS account diff --git a/docs/content/reference/manifests/ibmcloud/4.10.md b/docs/content/reference/manifests/ibmcloud/4.10.md index 6857f32a57a5..c05db4a3f496 100644 --- a/docs/content/reference/manifests/ibmcloud/4.10.md +++ b/docs/content/reference/manifests/ibmcloud/4.10.md @@ -1,3 +1,7 @@ +--- +title: "4.10" +--- + **HostedCluster** ```yaml diff --git a/docs/content/reference/manifests/ibmcloud/4.11.md b/docs/content/reference/manifests/ibmcloud/4.11.md index 261787f6a339..138e53faf205 100644 --- a/docs/content/reference/manifests/ibmcloud/4.11.md +++ b/docs/content/reference/manifests/ibmcloud/4.11.md @@ -1,3 +1,7 @@ +--- +title: "4.11" +--- + **HostedCluster** ```yaml diff --git a/docs/content/reference/manifests/ibmcloud/4.12.md b/docs/content/reference/manifests/ibmcloud/4.12.md index c4347d18ed1d..bba1941dacec 100644 --- a/docs/content/reference/manifests/ibmcloud/4.12.md +++ b/docs/content/reference/manifests/ibmcloud/4.12.md @@ -1,3 +1,7 @@ +--- +title: "4.12" +--- + **HostedCluster** ```yaml diff --git a/docs/content/reference/manifests/ibmcloud/4.13.md b/docs/content/reference/manifests/ibmcloud/4.13.md index c3f442727c95..f4fef840a45b 100644 --- a/docs/content/reference/manifests/ibmcloud/4.13.md +++ b/docs/content/reference/manifests/ibmcloud/4.13.md @@ -1,3 +1,7 @@ +--- +title: "4.13" +--- + **HostedCluster** ```yaml diff --git a/docs/content/reference/manifests/ibmcloud/4.9.md b/docs/content/reference/manifests/ibmcloud/4.9.md index 7478d14fc663..9bb49c4db063 100644 --- a/docs/content/reference/manifests/ibmcloud/4.9.md +++ b/docs/content/reference/manifests/ibmcloud/4.9.md @@ -1,3 +1,7 @@ +--- +title: "4.9" +--- + **HostedCluster** ```yaml diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 7c3905193947..1b678dcd7b8d 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -7,11 +7,6 @@ theme: - content.code.annotate plugins: - search -- mermaid2: - version: 11.2.0 - javascript: https://unpkg.com/mermaid@11.2.0/dist/mermaid.min.js - arguments: - securityLevel: loose - glightbox: touchNavigation: true loop: false @@ -43,7 +38,7 @@ markdown_extensions: custom_fences: - name: mermaid class: mermaid - format: !!python/name:mermaid2.fence_mermaid + format: !!python/name:pymdownx.superfences.fence_code_format - pymdownx.snippets - admonition - pymdownx.details diff --git a/docs/pyproject.toml b/docs/pyproject.toml new file mode 100644 index 000000000000..96e54c661a4e --- /dev/null +++ b/docs/pyproject.toml @@ -0,0 +1,7 @@ +[project] +name = "hypershift-docs" +version = "0.1.0" +description = "HyperShift documentation" +readme = "README.md" +requires-python = ">=3.12" +dependencies = ["zensical==0.0.51"] diff --git a/docs/requirements.txt b/docs/requirements.txt deleted file mode 100644 index 862859c2ce27..000000000000 --- a/docs/requirements.txt +++ /dev/null @@ -1,451 +0,0 @@ -# This file was autogenerated by uv via the following command: -# uv pip compile --generate-hashes docs/requirements.txt -o /tmp/requirements.txt.new && mv /tmp/requirements.txt.new docs/requirements.txt -babel==2.18.0 \ - --hash=sha256:b80b99a14bd085fcacfa15c9165f651fbb3406e66cc603abf11c5750937c992d \ - --hash=sha256:e2b422b277c2b9a9630c1d7903c2a00d0830c409c59ac8cae9081c92f1aeba35 - # via mkdocs-material -backrefs==5.9 \ - --hash=sha256:6907635edebbe9b2dc3de3a2befff44d74f30a4562adbb8b36f21252ea19c5cf \ - --hash=sha256:7fdf9771f63e6028d7fee7e0c497c81abda597ea45d6b8f89e8ad76994f5befa \ - --hash=sha256:808548cb708d66b82ee231f962cb36faaf4f2baab032f2fbb783e9c2fdddaa59 \ - --hash=sha256:cc37b19fa219e93ff825ed1fed8879e47b4d89aa7a1884860e2db64ccd7c676b \ - --hash=sha256:db8e8ba0e9de81fcd635f440deab5ae5f2591b54ac1ebe0550a2ca063488cd9f \ - --hash=sha256:df5e169836cc8acb5e440ebae9aad4bf9d15e226d3bad049cf3f6a5c20cc8dc9 \ - --hash=sha256:f48ee18f6252b8f5777a22a00a09a85de0ca931658f1dd96d4406a34f3748c60 - # via mkdocs-material -beautifulsoup4==4.15.0 \ - --hash=sha256:288e3ca7d54b06f2ac191970bc275c1939cb46d450b255bf6718b04aa37ab4f7 \ - --hash=sha256:d6f88de62e1d4e38ecb1077eb9724cd0eff29d2a08ca16a401e9b9e93f117cf9 - # via mkdocs-mermaid2-plugin -certifi==2026.7.22 \ - --hash=sha256:62f22742b58a1a33014a2b6b706588a8d7e2a88ae7bd1a6ebe8c992928483775 \ - --hash=sha256:741e2c3b351ddf169a738da9f2c048608ff7f2c5cc02f1ebc6b118bb090d5d55 - # via requests -charset-normalizer==3.4.9 \ - --hash=sha256:0327fcd59a935777d83410750c50600ee9571af2846f71ce40f25b13da1ef380 \ - --hash=sha256:03d07803992c6c7bbc976327f34b18b6160327fc81cb82c9d504720ac0be3b62 \ - --hash=sha256:04ce310cb89c15df659582aee80a0603788732a5e017d5bd5c81158106ce249c \ - --hash=sha256:0d861473f743244d349b50f850d10eb87aeb22bbdcc8e64f79273c94af5a8226 \ - --hash=sha256:0e94703ec9684807f20cfb5eed95c70f67f2a8f21ad620146d7b5a13677b93e5 \ - --hash=sha256:0fa1aec2d32bcc03c8fa0f6f1712caad1adc38509f31142112e5c9daf5b9c833 \ - --hash=sha256:16b65ea0f2465b6fb52aa22de5eca612aa964ddfec00a912e26f4656cbef890b \ - --hash=sha256:16d10d789dd9bcca1173c95af82c58433122564b7bc39385124be735a35cbe99 \ - --hash=sha256:19ac87f93086ce37b86e098888555c4b4bc48102279bae3350098c0ed664b501 \ - --hash=sha256:1d22856ffbe153a602df38e4a5464f0b748a54002e0d69ac6d2ad0a197cc99ec \ - --hash=sha256:21e764fd1e70b6a3e205a0e46f3051701f98a8cb3fad66eeb80e48bb502f8698 \ - --hash=sha256:231ddcbb35e2ff8973e1365db41fe0572662893b99a05deb183b68ad4c0c8bd4 \ - --hash=sha256:253a4a220747e8b5faf57ec320c4f5efb0cef05f647420bf267143ec15dba10a \ - --hash=sha256:280081916dc341820640489a66e4696049401ef1cf6dd672f672e70ad915aca3 \ - --hash=sha256:2a441ea71902098ffe78c5abe6c494f44160b4af614ed16c3d9a3b1d17fd8ee2 \ - --hash=sha256:304b13570067b2547562e308af560b3963857b1fa90bd6afd978130130fe2d6a \ - --hash=sha256:32286a2c8d167e897177b673176c1e3e00d4057caf5d2b64eef9a3666b03018e \ - --hash=sha256:33bdcc2a32c0a0e861f60841a512c8acc658c87c2ac59d89e3a46dacf7d866e4 \ - --hash=sha256:375b83ed0aecfce76c16d198fbc21f3b11b337d68662bea0a995046682a11419 \ - --hash=sha256:3c09a49d6cde137258beb3d551994a2927fd35ad5cf96aed573f61bbd67c5f84 \ - --hash=sha256:3d92613ec25e43b05f042302531ec0f00b8445190e43325880cbd6ab7c2581da \ - --hash=sha256:40a126142a56b2dfc0aacbad1de8310cbf60da7656db0e6b16eebd48e3e93519 \ - --hash=sha256:416c229f77e5ea25b3dfd4b582f8d73d7e43c22320302b9ab128a2d3a0b38efe \ - --hash=sha256:432786d3561e69aeeae6c7e8648964ce0ad05736120135601f87ac26b9c83381 \ - --hash=sha256:43b9e366a31fdd1c87d0eb08f579b4a82b723ea54338f040d6b4e518a026ea29 \ - --hash=sha256:440eede837960000d74978f0eba527be106b5b9aee0daf779d395276ed0b0614 \ - --hash=sha256:45b0cc4e3556cd875e09102988d1ab8356c998b596c9fced84547c8138b487a0 \ - --hash=sha256:476743fe6dfe14a2da12e3ac79125dc84a3b2cf8094369a47a1529b0cd8549fe \ - --hash=sha256:4773092f8019072343a7447203308b176e10199920eb02d6195e81bbb3274c29 \ - --hash=sha256:4b3dac63058cc36820b0dd072f89898604e2d39686fe05321729d00d8ac185a0 \ - --hash=sha256:4d1c96a7a18b9690a4d46df09e3e3382406ae3213727cd1019ebade1c4a81917 \ - --hash=sha256:51307f5c71007673a2bf8232ad973483d281e74cb99c8c5a990af1eefa6277d9 \ - --hash=sha256:51447e9aa2684679af07ca5021c3db526e0284347ebf4ffcec1154c3350cfe32 \ - --hash=sha256:58150c9f9b9a552505912d182ccdf26f6396fb6094816ceebcbb20eecabaed94 \ - --hash=sha256:5b10cd92fc5c498b35a8635df6d5a100207f88b63a4dc1de7ef9a548e1e2cd63 \ - --hash=sha256:5e226f6218febc71f6c1fc2fafb91c226f75bdc1d8fb12d66823716e891608fd \ - --hash=sha256:609b3ba8fcc0fb5ab7af00719d0fb6ad0cb518e48e7712d12fd68f1327951198 \ - --hash=sha256:60f44ade2cf573dad7a277e6f8ca9a51a21dda572b13bd7d8539bb3cd5dbedde \ - --hash=sha256:611057cc5d5c0afc743ba8be6bd828c17e0aaa8643f9d0a9b9bb7dea80eb8012 \ - --hash=sha256:6366a16e1a25018694d6a5d784d09b046edc9eac40ea2b54065c3052672516a1 \ - --hash=sha256:65a7ff3f705e57d392f7261b6d0550fe137c3019477431f1c355e0db0a7d3e15 \ - --hash=sha256:673611bbd43f0810bec0b0f028ddeaaa501190339cac411f347ac76917c3ae7b \ - --hash=sha256:67830fc78e67501f47bb950471b2dcb9b35b140084429318e862895a8e89c993 \ - --hash=sha256:68ce9f4d6b26d5ccbf7fd4459bf75f74a0a146677ebba80597df60cbdb20e6f4 \ - --hash=sha256:68e5f26a1ad57ded6d1cfb85331d1c1a195314756471d97758c48498bb4dcdf5 \ - --hash=sha256:69b157c5d3292bcd443faca052f3096f637f1e074b98212a933c074ae23dc3b8 \ - --hash=sha256:75286256590a6320cf106a0d28970d3560aad9ee09aa7b34fb40524792436d35 \ - --hash=sha256:78841cccf1af7b40f6f716338d50c0902dbe88d9f800b3c973b7a9a0a693a642 \ - --hash=sha256:78fa18e436a1a0e58dbd7e02fc4473f3f32cceb12df9dfca542d075961c307d2 \ - --hash=sha256:79580094b00d1789d1f93ea55bc43cb2f611910c72235b7657f3482ddcc1b22d \ - --hash=sha256:7b86a2b16095d250c6f58b3d9b2eee6f4147754344f3dab0922f7c9bf7d226c9 \ - --hash=sha256:83aed2c10721ddd90f68140685391b50811a880af20654c59af6b6c66c40513c \ - --hash=sha256:84fd18bcc17526fc2b3c1af7d2b9217d32c9c04448c16ec693b9b4f1985c3d33 \ - --hash=sha256:871ff67ea1aad4dfd91736464934d56b32dac49f9fbe16cddba36198a7b3a0db \ - --hash=sha256:898f0e9068ca27d37f8e83a5b962821df851532e6c4a7d615c1c033f9da6eedf \ - --hash=sha256:8a79d9f4d8001473a30c163556b3c3bfebec837495a412dde78b51672f6134f9 \ - --hash=sha256:8c041122946b7ba21bb32c45b1aa57b1be35527690aeb3c5c234521085632eee \ - --hash=sha256:90c44bc373b7687f6948b693cceaea1348ae0975d7474746559494468e3c1d84 \ - --hash=sha256:9104ed0bd76a429d46f9ec0dbc9b08ad1d2dcdf2b00a5a0daa1c145329b35b44 \ - --hash=sha256:920079c3f7456fa213e0829ed2073aaa727fd39d889ead5b4f35d0de5460d04f \ - --hash=sha256:93d59d504b230e83c7a843251681959a0b6a9cd76f6e146ce1b8a80eb8739af9 \ - --hash=sha256:9b2aff1c7b3884512b9512c3eaadd9bab39fb45042ffaaa1dd08ff2b9f8109d9 \ - --hash=sha256:9b8e0f3107e2200b76f6054de99016eac3ee6762713587b36baaa7e4bd2ae177 \ - --hash=sha256:9bb41182d93ea91f60b4bc8fbf4c820c69ef8a12ab2d917f3f1834f1acad07e8 \ - --hash=sha256:9cdef90ae47919cae358d8ab15797a800ed41da7aba5d72419fb510729e2ed4b \ - --hash=sha256:a1786910334ed46ab1dd73222f2cd1e05c2c3bb39f6dddb4f8b36fc382058a39 \ - --hash=sha256:a4cfde78a9f2880208d16a93b795726a3017d5977e08d1e162a7a31322479c41 \ - --hash=sha256:a4fbdde9dd4a9ce5fd52c2b3a347bb50cc89483ef783f1cb00d408c13f7a96c0 \ - --hash=sha256:aa99adc8f081b475a12843953db36831eaf83ec33eb46a90629ca6a5de45a616 \ - --hash=sha256:ac351b3b8014eead140e77e9717e2992c6bbe30b63bc3422422eb84865412e3d \ - --hash=sha256:ad41ba96094304aa090f5a30cb6e4fb3b3f1c264c523394b4c39bbacc4dc92ba \ - --hash=sha256:b5314963fce9b0b12743891de876e724997864ee22aa496f903f426c7e2fa5b2 \ - --hash=sha256:bcf74c1df76758a395bf0af608c04c82257523f55c9868b334f06270d0f2112b \ - --hash=sha256:bd47ba7fc3ca94896759ea0109775132d3e7ab921fbf54038e1bab2e46c313c9 \ - --hash=sha256:c0323c9daef75ef2e5083624b4585018a0c9d5e3b40f607eed81a311270b934b \ - --hash=sha256:c1225416b463483160e4af85d5fc3a9690ccb53fd4b1865a6437825f5ede3209 \ - --hash=sha256:c1c948747b03be832dceed96ca815cef7360de9aa19d37c730f8e3f6101aca48 \ - --hash=sha256:c25fe15c70c59eb7c5ce8c06a1f3fa1da0ecc5ea1e7a5922c40fd2fa9b0d5046 \ - --hash=sha256:cc1b0fff8ead343dae06305f954eb8468ba0ec1a97881f42489d198e4ce3c632 \ - --hash=sha256:cd6280cf040f233bd7d3407b743b4b4c74f70e8e1c4199cb112a62c941c0772a \ - --hash=sha256:cd6c3d4b783c556fa00bf540854e42f135e2f256abd29669fcd0da0f2dec79c2 \ - --hash=sha256:d4d6fcde76f94f5cb9e43e9e9a61f16dacefd228cbbf6f1a09bd9b219a92f1a1 \ - --hash=sha256:ddf4af30b417d9fe16481e9b81c27ab2a7cde1ff7ba3e85653b02db7d145dc7b \ - --hash=sha256:df115d4d83168fdf2cae48ef1ff6d1cb4c466364e30861b37121de0f3bf1b990 \ - --hash=sha256:df7276909358e5635ae203673ab7e509ddd224225a8d6b0790bf13eb2bde1cc5 \ - --hash=sha256:e4fd89cc178bced6ad29cb3e6dd4aa63fa5017c3524dbd0b25998fb64a87cc8b \ - --hash=sha256:e9701d0049d92c16703a42771b98d560b95248949f23f8cf7b4eddd201814fb9 \ - --hash=sha256:ee2f2a527e3c1a6e6411eb4209642e138b544a2d72fe5d0d76daf77b24063534 \ - --hash=sha256:f7fb7d750cfa0a070d2c24e831fd3481019a60dd317ea2b39acbcebc08b6ed81 \ - --hash=sha256:f840ed6d8ecba8255df8c42b87fadeda98ddfc6eeec05e2dc66e26d46dd6f58a \ - --hash=sha256:f86c6358749bd4fda175388691e3ba8c46e24c5347d0afd20f9b7edfc9faf07d \ - --hash=sha256:fa36ec09ef71d158186bc79e359ff5fdd6e7996fe8ab638f00d6b93139ba4fcf \ - --hash=sha256:fe2c7201c642b7c308f1675355ad7ff7b66acfe3541625efe5a3ad38f29d6115 - # via requests -click==8.4.2 \ - --hash=sha256:9a6cea6e60b17ebe0a44c5cc636d94f09bd66142c1cd7d8b4cd731c4917a15f6 \ - --hash=sha256:e6f9f66136c816745b9d65817da91d61d957fb16e02e4dcd0552553c5a197b76 - # via mkdocs -colorama==0.4.6 \ - --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ - --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 - # via mkdocs-material -editorconfig==0.17.1 \ - --hash=sha256:1eda9c2c0db8c16dbd50111b710572a5e6de934e39772de1959d41f64fc17c82 \ - --hash=sha256:23c08b00e8e08cc3adcddb825251c497478df1dada6aefeb01e626ad37303745 - # via jsbeautifier -ghp-import==2.1.0 \ - --hash=sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619 \ - --hash=sha256:9c535c4c61193c2df8871222567d7fd7e5014d835f97dc7b7439069e2413d343 - # via mkdocs -idna==3.18 \ - --hash=sha256:7f952cbe720b688055e3f87de14f5c3e5fdaa8bc3928985c4077ca689de849a2 \ - --hash=sha256:ffb385a7e039654cef1ab9ef32c6fafe283c0c0467bba1d9029738ce4a14a848 - # via requests -jinja2==3.1.6 \ - --hash=sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d \ - --hash=sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67 - # via - # mkdocs - # mkdocs-material -jsbeautifier==2.0.3 \ - --hash=sha256:9579d4e9dbaa00383f3efdff4c98c8140bb85ba319398e8b97cdaba27abd6ba3 \ - --hash=sha256:f0190e279a2cdb827556ada63f41c9c63c11f8116ee06e264b24aa50311cbee3 - # via mkdocs-mermaid2-plugin -markdown==3.10.2 \ - --hash=sha256:994d51325d25ad8aa7ce4ebaec003febcce822c3f8c911e3b17c52f7f589f950 \ - --hash=sha256:e91464b71ae3ee7afd3017d9f358ef0baf158fd9a298db92f1d4761133824c36 - # via - # mkdocs - # mkdocs-material - # pymdown-extensions -markupsafe==3.0.3 \ - --hash=sha256:0303439a41979d9e74d18ff5e2dd8c43ed6c6001fd40e5bf2e43f7bd9bbc523f \ - --hash=sha256:068f375c472b3e7acbe2d5318dea141359e6900156b5b2ba06a30b169086b91a \ - --hash=sha256:0bf2a864d67e76e5c9a34dc26ec616a66b9888e25e7b9460e1c76d3293bd9dbf \ - --hash=sha256:0db14f5dafddbb6d9208827849fad01f1a2609380add406671a26386cdf15a19 \ - --hash=sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf \ - --hash=sha256:0f4b68347f8c5eab4a13419215bdfd7f8c9b19f2b25520968adfad23eb0ce60c \ - --hash=sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175 \ - --hash=sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219 \ - --hash=sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb \ - --hash=sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6 \ - --hash=sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab \ - --hash=sha256:15d939a21d546304880945ca1ecb8a039db6b4dc49b2c5a400387cdae6a62e26 \ - --hash=sha256:177b5253b2834fe3678cb4a5f0059808258584c559193998be2601324fdeafb1 \ - --hash=sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce \ - --hash=sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218 \ - --hash=sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634 \ - --hash=sha256:1ba88449deb3de88bd40044603fafffb7bc2b055d626a330323a9ed736661695 \ - --hash=sha256:1cc7ea17a6824959616c525620e387f6dd30fec8cb44f649e31712db02123dad \ - --hash=sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73 \ - --hash=sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c \ - --hash=sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe \ - --hash=sha256:2a15a08b17dd94c53a1da0438822d70ebcd13f8c3a95abe3a9ef9f11a94830aa \ - --hash=sha256:2f981d352f04553a7171b8e44369f2af4055f888dfb147d55e42d29e29e74559 \ - --hash=sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa \ - --hash=sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37 \ - --hash=sha256:3537e01efc9d4dccdf77221fb1cb3b8e1a38d5428920e0657ce299b20324d758 \ - --hash=sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f \ - --hash=sha256:38664109c14ffc9e7437e86b4dceb442b0096dfe3541d7864d9cbe1da4cf36c8 \ - --hash=sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d \ - --hash=sha256:3b562dd9e9ea93f13d53989d23a7e775fdfd1066c33494ff43f5418bc8c58a5c \ - --hash=sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97 \ - --hash=sha256:4bd4cd07944443f5a265608cc6aab442e4f74dff8088b0dfc8238647b8f6ae9a \ - --hash=sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19 \ - --hash=sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9 \ - --hash=sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9 \ - --hash=sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc \ - --hash=sha256:591ae9f2a647529ca990bc681daebdd52c8791ff06c2bfa05b65163e28102ef2 \ - --hash=sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4 \ - --hash=sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354 \ - --hash=sha256:6b5420a1d9450023228968e7e6a9ce57f65d148ab56d2313fcd589eee96a7a50 \ - --hash=sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698 \ - --hash=sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9 \ - --hash=sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b \ - --hash=sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc \ - --hash=sha256:7be7b61bb172e1ed687f1754f8e7484f1c8019780f6f6b0786e76bb01c2ae115 \ - --hash=sha256:7c3fb7d25180895632e5d3148dbdc29ea38ccb7fd210aa27acbd1201a1902c6e \ - --hash=sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485 \ - --hash=sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f \ - --hash=sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12 \ - --hash=sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025 \ - --hash=sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009 \ - --hash=sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d \ - --hash=sha256:949b8d66bc381ee8b007cd945914c721d9aba8e27f71959d750a46f7c282b20b \ - --hash=sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a \ - --hash=sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5 \ - --hash=sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f \ - --hash=sha256:a320721ab5a1aba0a233739394eb907f8c8da5c98c9181d1161e77a0c8e36f2d \ - --hash=sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1 \ - --hash=sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287 \ - --hash=sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6 \ - --hash=sha256:bc51efed119bc9cfdf792cdeaa4d67e8f6fcccab66ed4bfdd6bde3e59bfcbb2f \ - --hash=sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581 \ - --hash=sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed \ - --hash=sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b \ - --hash=sha256:c0c0b3ade1c0b13b936d7970b1d37a57acde9199dc2aecc4c336773e1d86049c \ - --hash=sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026 \ - --hash=sha256:c4ffb7ebf07cfe8931028e3e4c85f0357459a3f9f9490886198848f4fa002ec8 \ - --hash=sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676 \ - --hash=sha256:d2ee202e79d8ed691ceebae8e0486bd9a2cd4794cec4824e1c99b6f5009502f6 \ - --hash=sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e \ - --hash=sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d \ - --hash=sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d \ - --hash=sha256:de8a88e63464af587c950061a5e6a67d3632e36df62b986892331d4620a35c01 \ - --hash=sha256:df2449253ef108a379b8b5d6b43f4b1a8e81a061d6537becd5582fba5f9196d7 \ - --hash=sha256:e1c1493fb6e50ab01d20a22826e57520f1284df32f2d8601fdd90b6304601419 \ - --hash=sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795 \ - --hash=sha256:e2103a929dfa2fcaf9bb4e7c091983a49c9ac3b19c9061b6d5427dd7d14d81a1 \ - --hash=sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5 \ - --hash=sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d \ - --hash=sha256:e8fc20152abba6b83724d7ff268c249fa196d8259ff481f3b1476383f8f24e42 \ - --hash=sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe \ - --hash=sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda \ - --hash=sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e \ - --hash=sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737 \ - --hash=sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523 \ - --hash=sha256:f42d0984e947b8adf7dd6dde396e720934d12c506ce84eea8476409563607591 \ - --hash=sha256:f71a396b3bf33ecaa1626c255855702aca4d3d9fea5e051b41ac59a9c1c41edc \ - --hash=sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a \ - --hash=sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50 - # via - # jinja2 - # mkdocs -mergedeep==1.3.4 \ - --hash=sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8 \ - --hash=sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307 - # via - # mkdocs - # mkdocs-get-deps -mkdocs==1.6.1 \ - --hash=sha256:7b432f01d928c084353ab39c57282f29f92136665bdd6abf7c1ec8d822ef86f2 \ - --hash=sha256:db91759624d1647f3f34aa0c3f327dd2601beae39a366d6e064c03468d35c20e - # via - # mkdocs-material - # mkdocs-mermaid2-plugin -mkdocs-get-deps==0.2.2 \ - --hash=sha256:8ee8d5f316cdbbb2834bc1df6e69c08fe769a83e040060de26d3c19fad3599a1 \ - --hash=sha256:e7878cbeac04860b8b5e0ca31d3abad3df9411a75a32cde82f8e44b6c16ff650 - # via mkdocs -mkdocs-glightbox==0.4.0 \ - --hash=sha256:392b34207bf95991071a16d5f8916d1d2f2cd5d5bb59ae2997485ccd778c70d9 \ - --hash=sha256:e0107beee75d3eb7380ac06ea2d6eac94c999eaa49f8c3cbab0e7be2ac006ccf - # via -r docs/requirements.txt -mkdocs-material==9.6.8 \ - --hash=sha256:0a51532dd8aa80b232546c073fe3ef60dfaef1b1b12196ac7191ee01702d1cf8 \ - --hash=sha256:8de31bb7566379802532b248bd56d9c4bc834afc4625884bf5769f9412c6a354 - # via -r docs/requirements.txt -mkdocs-material-extensions==1.3.1 \ - --hash=sha256:10c9511cea88f568257f960358a467d12b970e1f7b2c0e5fb2bb48cab1928443 \ - --hash=sha256:adff8b62700b25cb77b53358dad940f3ef973dd6db797907c49e3c2ef3ab4e31 - # via mkdocs-material -mkdocs-mermaid2-plugin==1.2.1 \ - --hash=sha256:22d2cf2c6867d4959a5e0903da2dde78d74581fc0b107b791bc4c7ceb9ce9741 \ - --hash=sha256:9c7694c73a65905ac1578f966e5c193325c4d5a5bc1836727e74ac9f99d0e921 - # via -r docs/requirements.txt -packaging==26.2 \ - --hash=sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e \ - --hash=sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661 - # via mkdocs -paginate==0.5.7 \ - --hash=sha256:22bd083ab41e1a8b4f3690544afb2c60c25e5c9a63a30fa2f483f6c60c8e5945 \ - --hash=sha256:b885e2af73abcf01d9559fd5216b57ef722f8c42affbb63942377668e35c7591 - # via mkdocs-material -pathspec==1.1.1 \ - --hash=sha256:17db5ecd524104a120e173814c90367a96a98d07c45b2e10c2f3919fff91bf5a \ - --hash=sha256:a00ce642f577bf7f473932318056212bc4f8bfdf53128c78bbd5af0b9b20b189 - # via mkdocs -platformdirs==4.11.0 \ - --hash=sha256:0555d18370482847566ffabcaa53ad7c6c1c29f195989ae1ed634a05f76ea1e0 \ - --hash=sha256:360ccded2b7fce0af0ff80cc8f5942a1c5d99b0e856033acb030bfc634709e74 - # via mkdocs-get-deps -pygments==2.20.0 \ - --hash=sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f \ - --hash=sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176 - # via mkdocs-material -pymdown-extensions==10.21.3 \ - --hash=sha256:72cfcf55f07aea0d4af2c4f11dd4e52466ddfb1bb819673146398e0bd3a77354 \ - --hash=sha256:d7a5d08014fc571e80ca21dd6f854e31f94c489800350564d55d15b3c41e76b6 - # via - # mkdocs-material - # mkdocs-mermaid2-plugin -python-dateutil==2.9.0.post0 \ - --hash=sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3 \ - --hash=sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427 - # via ghp-import -pyyaml==6.0.3 \ - --hash=sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c \ - --hash=sha256:0150219816b6a1fa26fb4699fb7daa9caf09eb1999f3b70fb6e786805e80375a \ - --hash=sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3 \ - --hash=sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956 \ - --hash=sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6 \ - --hash=sha256:10892704fc220243f5305762e276552a0395f7beb4dbf9b14ec8fd43b57f126c \ - --hash=sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65 \ - --hash=sha256:1d37d57ad971609cf3c53ba6a7e365e40660e3be0e5175fa9f2365a379d6095a \ - --hash=sha256:1ebe39cb5fc479422b83de611d14e2c0d3bb2a18bbcb01f229ab3cfbd8fee7a0 \ - --hash=sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b \ - --hash=sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1 \ - --hash=sha256:22ba7cfcad58ef3ecddc7ed1db3409af68d023b7f940da23c6c2a1890976eda6 \ - --hash=sha256:27c0abcb4a5dac13684a37f76e701e054692a9b2d3064b70f5e4eb54810553d7 \ - --hash=sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e \ - --hash=sha256:2e71d11abed7344e42a8849600193d15b6def118602c4c176f748e4583246007 \ - --hash=sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310 \ - --hash=sha256:37503bfbfc9d2c40b344d06b2199cf0e96e97957ab1c1b546fd4f87e53e5d3e4 \ - --hash=sha256:3c5677e12444c15717b902a5798264fa7909e41153cdf9ef7ad571b704a63dd9 \ - --hash=sha256:3ff07ec89bae51176c0549bc4c63aa6202991da2d9a6129d7aef7f1407d3f295 \ - --hash=sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea \ - --hash=sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0 \ - --hash=sha256:44edc647873928551a01e7a563d7452ccdebee747728c1080d881d68af7b997e \ - --hash=sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac \ - --hash=sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9 \ - --hash=sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7 \ - --hash=sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35 \ - --hash=sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb \ - --hash=sha256:5cf4e27da7e3fbed4d6c3d8e797387aaad68102272f8f9752883bc32d61cb87b \ - --hash=sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69 \ - --hash=sha256:5ed875a24292240029e4483f9d4a4b8a1ae08843b9c54f43fcc11e404532a8a5 \ - --hash=sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b \ - --hash=sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c \ - --hash=sha256:6344df0d5755a2c9a276d4473ae6b90647e216ab4757f8426893b5dd2ac3f369 \ - --hash=sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd \ - --hash=sha256:652cb6edd41e718550aad172851962662ff2681490a8a711af6a4d288dd96824 \ - --hash=sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198 \ - --hash=sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065 \ - --hash=sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c \ - --hash=sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c \ - --hash=sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764 \ - --hash=sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196 \ - --hash=sha256:8098f252adfa6c80ab48096053f512f2321f0b998f98150cea9bd23d83e1467b \ - --hash=sha256:850774a7879607d3a6f50d36d04f00ee69e7fc816450e5f7e58d7f17f1ae5c00 \ - --hash=sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac \ - --hash=sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8 \ - --hash=sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e \ - --hash=sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28 \ - --hash=sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3 \ - --hash=sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5 \ - --hash=sha256:9c57bb8c96f6d1808c030b1687b9b5fb476abaa47f0db9c0101f5e9f394e97f4 \ - --hash=sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b \ - --hash=sha256:9f3bfb4965eb874431221a3ff3fdcddc7e74e3b07799e0e84ca4a0f867d449bf \ - --hash=sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5 \ - --hash=sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702 \ - --hash=sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8 \ - --hash=sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788 \ - --hash=sha256:b865addae83924361678b652338317d1bd7e79b1f4596f96b96c77a5a34b34da \ - --hash=sha256:b8bb0864c5a28024fac8a632c443c87c5aa6f215c0b126c449ae1a150412f31d \ - --hash=sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc \ - --hash=sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c \ - --hash=sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba \ - --hash=sha256:c2514fceb77bc5e7a2f7adfaa1feb2fb311607c9cb518dbc378688ec73d8292f \ - --hash=sha256:c3355370a2c156cffb25e876646f149d5d68f5e0a3ce86a5084dd0b64a994917 \ - --hash=sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5 \ - --hash=sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26 \ - --hash=sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f \ - --hash=sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b \ - --hash=sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be \ - --hash=sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c \ - --hash=sha256:efd7b85f94a6f21e4932043973a7ba2613b059c4a000551892ac9f1d11f5baf3 \ - --hash=sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6 \ - --hash=sha256:fa160448684b4e94d80416c0fa4aac48967a969efe22931448d853ada8baf926 \ - --hash=sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0 - # via - # mkdocs - # mkdocs-get-deps - # pymdown-extensions - # pyyaml-env-tag -pyyaml-env-tag==1.1 \ - --hash=sha256:17109e1a528561e32f026364712fee1264bc2ea6715120891174ed1b980d2e04 \ - --hash=sha256:2eb38b75a2d21ee0475d6d97ec19c63287a7e140231e4214969d0eac923cd7ff - # via mkdocs -requests==2.34.2 \ - --hash=sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0 \ - --hash=sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed - # via - # mkdocs-material - # mkdocs-mermaid2-plugin -setuptools==83.0.0 \ - --hash=sha256:025bccbbf0fa05b6192bc64ae1e7b16e001fd6d6d4d5de03c97b1c1ade523bef \ - --hash=sha256:29b23c360f22f414dc7336bb39178cc7bcbf6021ed2733cde173f09dba19abb3 - # via mkdocs-mermaid2-plugin -six==1.17.0 \ - --hash=sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274 \ - --hash=sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81 - # via python-dateutil -soupsieve==2.9.1 \ - --hash=sha256:4f4477399246b7a0c720a88ca2454b11cd6bb9ae4c9d170140786e916776c14c \ - --hash=sha256:c33e6605bbc71dd628b00c632d58ae607c22bade247e52553928f83bbb75b4ba - # via beautifulsoup4 -typing-extensions==4.16.0 \ - --hash=sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8 \ - --hash=sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5 - # via beautifulsoup4 -urllib3==2.7.0 \ - --hash=sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c \ - --hash=sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897 - # via requests -watchdog==6.0.0 \ - --hash=sha256:07df1fdd701c5d4c8e55ef6cf55b8f0120fe1aef7ef39a1c6fc6bc2e606d517a \ - --hash=sha256:20ffe5b202af80ab4266dcd3e91aae72bf2da48c0d33bdb15c66658e685e94e2 \ - --hash=sha256:212ac9b8bf1161dc91bd09c048048a95ca3a4c4f5e5d4a7d1b1a7d5752a7f96f \ - --hash=sha256:2cce7cfc2008eb51feb6aab51251fd79b85d9894e98ba847408f662b3395ca3c \ - --hash=sha256:490ab2ef84f11129844c23fb14ecf30ef3d8a6abafd3754a6f75ca1e6654136c \ - --hash=sha256:6eb11feb5a0d452ee41f824e271ca311a09e250441c262ca2fd7ebcf2461a06c \ - --hash=sha256:6f10cb2d5902447c7d0da897e2c6768bca89174d0c6e1e30abec5421af97a5b0 \ - --hash=sha256:7607498efa04a3542ae3e05e64da8202e58159aa1fa4acddf7678d34a35d4f13 \ - --hash=sha256:76aae96b00ae814b181bb25b1b98076d5fc84e8a53cd8885a318b42b6d3a5134 \ - --hash=sha256:7a0e56874cfbc4b9b05c60c8a1926fedf56324bb08cfbc188969777940aef3aa \ - --hash=sha256:82dc3e3143c7e38ec49d61af98d6558288c415eac98486a5c581726e0737c00e \ - --hash=sha256:9041567ee8953024c83343288ccc458fd0a2d811d6a0fd68c4c22609e3490379 \ - --hash=sha256:90c8e78f3b94014f7aaae121e6b909674df5b46ec24d6bebc45c44c56729af2a \ - --hash=sha256:9513f27a1a582d9808cf21a07dae516f0fab1cf2d7683a742c498b93eedabb11 \ - --hash=sha256:9ddf7c82fda3ae8e24decda1338ede66e1c99883db93711d8fb941eaa2d8c282 \ - --hash=sha256:a175f755fc2279e0b7312c0035d52e27211a5bc39719dd529625b1930917345b \ - --hash=sha256:a1914259fa9e1454315171103c6a30961236f508b9b623eae470268bbcc6a22f \ - --hash=sha256:afd0fe1b2270917c5e23c2a65ce50c2a4abb63daafb0d419fde368e272a76b7c \ - --hash=sha256:bc64ab3bdb6a04d69d4023b29422170b74681784ffb9463ed4870cf2f3e66112 \ - --hash=sha256:bdd4e6f14b8b18c334febb9c4425a878a2ac20efd1e0b231978e7b150f92a948 \ - --hash=sha256:c7ac31a19f4545dd92fc25d200694098f42c9a8e391bc00bdd362c5736dbf881 \ - --hash=sha256:c7c15dda13c4eb00d6fb6fc508b3c0ed88b9d5d374056b239c4ad1611125c860 \ - --hash=sha256:c897ac1b55c5a1461e16dae288d22bb2e412ba9807df8397a635d88f671d36c3 \ - --hash=sha256:cbafb470cf848d93b5d013e2ecb245d4aa1c8fd0504e863ccefa32445359d680 \ - --hash=sha256:d1cdb490583ebd691c012b3d6dae011000fe42edb7a82ece80965b42abd61f26 \ - --hash=sha256:e3df4cbb9a450c6d49318f6d14f4bbc80d763fa587ba46ec86f99f9e6876bb26 \ - --hash=sha256:e6439e374fc012255b4ec786ae3c4bc838cd7309a540e5fe0952d03687d8804e \ - --hash=sha256:e6f0e77c9417e7cd62af82529b10563db3423625c5fce018430b249bf977f9e8 \ - --hash=sha256:e7631a77ffb1f7d2eefa4445ebbee491c720a5661ddf6df3498ebecae5ed375c \ - --hash=sha256:ef810fbf7b781a5a593894e4f439773830bdecb885e6880d957d5b9382a960d2 - # via mkdocs diff --git a/docs/uv.lock b/docs/uv.lock new file mode 100644 index 000000000000..cc67e979f910 --- /dev/null +++ b/docs/uv.lock @@ -0,0 +1,271 @@ +version = 1 +revision = 3 +requires-python = ">=3.12" + +[[package]] +name = "click" +version = "8.4.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/76/d4/81420972a676e8ffea40450d8c8c92943e7218a78fe9b64359836cc9876b/click-8.4.2.tar.gz", hash = "sha256:9a6cea6e60b17ebe0a44c5cc636d94f09bd66142c1cd7d8b4cd731c4917a15f6", size = 338000, upload-time = "2026-06-24T17:45:15.148Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fb/e2/79c688af8b210d232694e31e59da9f6ec747bae31c3f5946e4e9b98860d5/click-8.4.2-py3-none-any.whl", hash = "sha256:e6f9f66136c816745b9d65817da91d61d957fb16e02e4dcd0552553c5a197b76", size = 119243, upload-time = "2026-06-24T17:45:13.73Z" }, +] + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, +] + +[[package]] +name = "deepmerge" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/2a/78/6e9e20106224083cfb817d2d3c26e80e72258d617b616721a169b87081e0/deepmerge-2.1.0.tar.gz", hash = "sha256:07ca7a7b8935df596c512fa8161877c0487ac61f691c07766e7d71d2b23bdd2f", size = 21449, upload-time = "2026-06-22T05:46:07.669Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/51/25/2a75b47cb057b1e164c604fb81ab690a6cdb5e2260ce651194eae90f64a3/deepmerge-2.1.0-py3-none-any.whl", hash = "sha256:8f148339a91d680a75ecb74ade235d9e759a93df373a0b04e9d31c8666cfeb75", size = 14345, upload-time = "2026-06-22T05:46:06.742Z" }, +] + +[[package]] +name = "hypershift-docs" +version = "0.1.0" +source = { virtual = "." } +dependencies = [ + { name = "zensical" }, +] + +[package.metadata] +requires-dist = [{ name = "zensical", specifier = ">=0.0.51" }] + +[[package]] +name = "jinja2" +version = "3.1.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markupsafe" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" }, +] + +[[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 = "markupsafe" +version = "3.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7e/99/7690b6d4034fffd95959cbe0c02de8deb3098cc577c67bb6a24fe5d7caa7/markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698", size = 80313, upload-time = "2025-09-27T18:37:40.426Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5a/72/147da192e38635ada20e0a2e1a51cf8823d2119ce8883f7053879c2199b5/markupsafe-3.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e", size = 11615, upload-time = "2025-09-27T18:36:30.854Z" }, + { url = "https://files.pythonhosted.org/packages/9a/81/7e4e08678a1f98521201c3079f77db69fb552acd56067661f8c2f534a718/markupsafe-3.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce", size = 12020, upload-time = "2025-09-27T18:36:31.971Z" }, + { url = "https://files.pythonhosted.org/packages/1e/2c/799f4742efc39633a1b54a92eec4082e4f815314869865d876824c257c1e/markupsafe-3.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d", size = 24332, upload-time = "2025-09-27T18:36:32.813Z" }, + { url = "https://files.pythonhosted.org/packages/3c/2e/8d0c2ab90a8c1d9a24f0399058ab8519a3279d1bd4289511d74e909f060e/markupsafe-3.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d", size = 22947, upload-time = "2025-09-27T18:36:33.86Z" }, + { url = "https://files.pythonhosted.org/packages/2c/54/887f3092a85238093a0b2154bd629c89444f395618842e8b0c41783898ea/markupsafe-3.0.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a", size = 21962, upload-time = "2025-09-27T18:36:35.099Z" }, + { url = "https://files.pythonhosted.org/packages/c9/2f/336b8c7b6f4a4d95e91119dc8521402461b74a485558d8f238a68312f11c/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b", size = 23760, upload-time = "2025-09-27T18:36:36.001Z" }, + { url = "https://files.pythonhosted.org/packages/32/43/67935f2b7e4982ffb50a4d169b724d74b62a3964bc1a9a527f5ac4f1ee2b/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f", size = 21529, upload-time = "2025-09-27T18:36:36.906Z" }, + { url = "https://files.pythonhosted.org/packages/89/e0/4486f11e51bbba8b0c041098859e869e304d1c261e59244baa3d295d47b7/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b", size = 23015, upload-time = "2025-09-27T18:36:37.868Z" }, + { url = "https://files.pythonhosted.org/packages/2f/e1/78ee7a023dac597a5825441ebd17170785a9dab23de95d2c7508ade94e0e/markupsafe-3.0.3-cp312-cp312-win32.whl", hash = "sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d", size = 14540, upload-time = "2025-09-27T18:36:38.761Z" }, + { url = "https://files.pythonhosted.org/packages/aa/5b/bec5aa9bbbb2c946ca2733ef9c4ca91c91b6a24580193e891b5f7dbe8e1e/markupsafe-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c", size = 15105, upload-time = "2025-09-27T18:36:39.701Z" }, + { url = "https://files.pythonhosted.org/packages/e5/f1/216fc1bbfd74011693a4fd837e7026152e89c4bcf3e77b6692fba9923123/markupsafe-3.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f", size = 13906, upload-time = "2025-09-27T18:36:40.689Z" }, + { url = "https://files.pythonhosted.org/packages/38/2f/907b9c7bbba283e68f20259574b13d005c121a0fa4c175f9bed27c4597ff/markupsafe-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795", size = 11622, upload-time = "2025-09-27T18:36:41.777Z" }, + { url = "https://files.pythonhosted.org/packages/9c/d9/5f7756922cdd676869eca1c4e3c0cd0df60ed30199ffd775e319089cb3ed/markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219", size = 12029, upload-time = "2025-09-27T18:36:43.257Z" }, + { url = "https://files.pythonhosted.org/packages/00/07/575a68c754943058c78f30db02ee03a64b3c638586fba6a6dd56830b30a3/markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6", size = 24374, upload-time = "2025-09-27T18:36:44.508Z" }, + { url = "https://files.pythonhosted.org/packages/a9/21/9b05698b46f218fc0e118e1f8168395c65c8a2c750ae2bab54fc4bd4e0e8/markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676", size = 22980, upload-time = "2025-09-27T18:36:45.385Z" }, + { url = "https://files.pythonhosted.org/packages/7f/71/544260864f893f18b6827315b988c146b559391e6e7e8f7252839b1b846a/markupsafe-3.0.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9", size = 21990, upload-time = "2025-09-27T18:36:46.916Z" }, + { url = "https://files.pythonhosted.org/packages/c2/28/b50fc2f74d1ad761af2f5dcce7492648b983d00a65b8c0e0cb457c82ebbe/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1", size = 23784, upload-time = "2025-09-27T18:36:47.884Z" }, + { url = "https://files.pythonhosted.org/packages/ed/76/104b2aa106a208da8b17a2fb72e033a5a9d7073c68f7e508b94916ed47a9/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc", size = 21588, upload-time = "2025-09-27T18:36:48.82Z" }, + { url = "https://files.pythonhosted.org/packages/b5/99/16a5eb2d140087ebd97180d95249b00a03aa87e29cc224056274f2e45fd6/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12", size = 23041, upload-time = "2025-09-27T18:36:49.797Z" }, + { url = "https://files.pythonhosted.org/packages/19/bc/e7140ed90c5d61d77cea142eed9f9c303f4c4806f60a1044c13e3f1471d0/markupsafe-3.0.3-cp313-cp313-win32.whl", hash = "sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed", size = 14543, upload-time = "2025-09-27T18:36:51.584Z" }, + { url = "https://files.pythonhosted.org/packages/05/73/c4abe620b841b6b791f2edc248f556900667a5a1cf023a6646967ae98335/markupsafe-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5", size = 15113, upload-time = "2025-09-27T18:36:52.537Z" }, + { url = "https://files.pythonhosted.org/packages/f0/3a/fa34a0f7cfef23cf9500d68cb7c32dd64ffd58a12b09225fb03dd37d5b80/markupsafe-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485", size = 13911, upload-time = "2025-09-27T18:36:53.513Z" }, + { url = "https://files.pythonhosted.org/packages/e4/d7/e05cd7efe43a88a17a37b3ae96e79a19e846f3f456fe79c57ca61356ef01/markupsafe-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73", size = 11658, upload-time = "2025-09-27T18:36:54.819Z" }, + { url = "https://files.pythonhosted.org/packages/99/9e/e412117548182ce2148bdeacdda3bb494260c0b0184360fe0d56389b523b/markupsafe-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37", size = 12066, upload-time = "2025-09-27T18:36:55.714Z" }, + { url = "https://files.pythonhosted.org/packages/bc/e6/fa0ffcda717ef64a5108eaa7b4f5ed28d56122c9a6d70ab8b72f9f715c80/markupsafe-3.0.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19", size = 25639, upload-time = "2025-09-27T18:36:56.908Z" }, + { url = "https://files.pythonhosted.org/packages/96/ec/2102e881fe9d25fc16cb4b25d5f5cde50970967ffa5dddafdb771237062d/markupsafe-3.0.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025", size = 23569, upload-time = "2025-09-27T18:36:57.913Z" }, + { url = "https://files.pythonhosted.org/packages/4b/30/6f2fce1f1f205fc9323255b216ca8a235b15860c34b6798f810f05828e32/markupsafe-3.0.3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6", size = 23284, upload-time = "2025-09-27T18:36:58.833Z" }, + { url = "https://files.pythonhosted.org/packages/58/47/4a0ccea4ab9f5dcb6f79c0236d954acb382202721e704223a8aafa38b5c8/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f", size = 24801, upload-time = "2025-09-27T18:36:59.739Z" }, + { url = "https://files.pythonhosted.org/packages/6a/70/3780e9b72180b6fecb83a4814d84c3bf4b4ae4bf0b19c27196104149734c/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb", size = 22769, upload-time = "2025-09-27T18:37:00.719Z" }, + { url = "https://files.pythonhosted.org/packages/98/c5/c03c7f4125180fc215220c035beac6b9cb684bc7a067c84fc69414d315f5/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009", size = 23642, upload-time = "2025-09-27T18:37:01.673Z" }, + { url = "https://files.pythonhosted.org/packages/80/d6/2d1b89f6ca4bff1036499b1e29a1d02d282259f3681540e16563f27ebc23/markupsafe-3.0.3-cp313-cp313t-win32.whl", hash = "sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354", size = 14612, upload-time = "2025-09-27T18:37:02.639Z" }, + { url = "https://files.pythonhosted.org/packages/2b/98/e48a4bfba0a0ffcf9925fe2d69240bfaa19c6f7507b8cd09c70684a53c1e/markupsafe-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218", size = 15200, upload-time = "2025-09-27T18:37:03.582Z" }, + { url = "https://files.pythonhosted.org/packages/0e/72/e3cc540f351f316e9ed0f092757459afbc595824ca724cbc5a5d4263713f/markupsafe-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287", size = 13973, upload-time = "2025-09-27T18:37:04.929Z" }, + { url = "https://files.pythonhosted.org/packages/33/8a/8e42d4838cd89b7dde187011e97fe6c3af66d8c044997d2183fbd6d31352/markupsafe-3.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe", size = 11619, upload-time = "2025-09-27T18:37:06.342Z" }, + { url = "https://files.pythonhosted.org/packages/b5/64/7660f8a4a8e53c924d0fa05dc3a55c9cee10bbd82b11c5afb27d44b096ce/markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026", size = 12029, upload-time = "2025-09-27T18:37:07.213Z" }, + { url = "https://files.pythonhosted.org/packages/da/ef/e648bfd021127bef5fa12e1720ffed0c6cbb8310c8d9bea7266337ff06de/markupsafe-3.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737", size = 24408, upload-time = "2025-09-27T18:37:09.572Z" }, + { url = "https://files.pythonhosted.org/packages/41/3c/a36c2450754618e62008bf7435ccb0f88053e07592e6028a34776213d877/markupsafe-3.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97", size = 23005, upload-time = "2025-09-27T18:37:10.58Z" }, + { url = "https://files.pythonhosted.org/packages/bc/20/b7fdf89a8456b099837cd1dc21974632a02a999ec9bf7ca3e490aacd98e7/markupsafe-3.0.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d", size = 22048, upload-time = "2025-09-27T18:37:11.547Z" }, + { url = "https://files.pythonhosted.org/packages/9a/a7/591f592afdc734f47db08a75793a55d7fbcc6902a723ae4cfbab61010cc5/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda", size = 23821, upload-time = "2025-09-27T18:37:12.48Z" }, + { url = "https://files.pythonhosted.org/packages/7d/33/45b24e4f44195b26521bc6f1a82197118f74df348556594bd2262bda1038/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf", size = 21606, upload-time = "2025-09-27T18:37:13.485Z" }, + { url = "https://files.pythonhosted.org/packages/ff/0e/53dfaca23a69fbfbbf17a4b64072090e70717344c52eaaaa9c5ddff1e5f0/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe", size = 23043, upload-time = "2025-09-27T18:37:14.408Z" }, + { url = "https://files.pythonhosted.org/packages/46/11/f333a06fc16236d5238bfe74daccbca41459dcd8d1fa952e8fbd5dccfb70/markupsafe-3.0.3-cp314-cp314-win32.whl", hash = "sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9", size = 14747, upload-time = "2025-09-27T18:37:15.36Z" }, + { url = "https://files.pythonhosted.org/packages/28/52/182836104b33b444e400b14f797212f720cbc9ed6ba34c800639d154e821/markupsafe-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581", size = 15341, upload-time = "2025-09-27T18:37:16.496Z" }, + { url = "https://files.pythonhosted.org/packages/6f/18/acf23e91bd94fd7b3031558b1f013adfa21a8e407a3fdb32745538730382/markupsafe-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4", size = 14073, upload-time = "2025-09-27T18:37:17.476Z" }, + { url = "https://files.pythonhosted.org/packages/3c/f0/57689aa4076e1b43b15fdfa646b04653969d50cf30c32a102762be2485da/markupsafe-3.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab", size = 11661, upload-time = "2025-09-27T18:37:18.453Z" }, + { url = "https://files.pythonhosted.org/packages/89/c3/2e67a7ca217c6912985ec766c6393b636fb0c2344443ff9d91404dc4c79f/markupsafe-3.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175", size = 12069, upload-time = "2025-09-27T18:37:19.332Z" }, + { url = "https://files.pythonhosted.org/packages/f0/00/be561dce4e6ca66b15276e184ce4b8aec61fe83662cce2f7d72bd3249d28/markupsafe-3.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634", size = 25670, upload-time = "2025-09-27T18:37:20.245Z" }, + { url = "https://files.pythonhosted.org/packages/50/09/c419f6f5a92e5fadde27efd190eca90f05e1261b10dbd8cbcb39cd8ea1dc/markupsafe-3.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50", size = 23598, upload-time = "2025-09-27T18:37:21.177Z" }, + { url = "https://files.pythonhosted.org/packages/22/44/a0681611106e0b2921b3033fc19bc53323e0b50bc70cffdd19f7d679bb66/markupsafe-3.0.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e", size = 23261, upload-time = "2025-09-27T18:37:22.167Z" }, + { url = "https://files.pythonhosted.org/packages/5f/57/1b0b3f100259dc9fffe780cfb60d4be71375510e435efec3d116b6436d43/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5", size = 24835, upload-time = "2025-09-27T18:37:23.296Z" }, + { url = "https://files.pythonhosted.org/packages/26/6a/4bf6d0c97c4920f1597cc14dd720705eca0bf7c787aebc6bb4d1bead5388/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523", size = 22733, upload-time = "2025-09-27T18:37:24.237Z" }, + { url = "https://files.pythonhosted.org/packages/14/c7/ca723101509b518797fedc2fdf79ba57f886b4aca8a7d31857ba3ee8281f/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc", size = 23672, upload-time = "2025-09-27T18:37:25.271Z" }, + { url = "https://files.pythonhosted.org/packages/fb/df/5bd7a48c256faecd1d36edc13133e51397e41b73bb77e1a69deab746ebac/markupsafe-3.0.3-cp314-cp314t-win32.whl", hash = "sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d", size = 14819, upload-time = "2025-09-27T18:37:26.285Z" }, + { url = "https://files.pythonhosted.org/packages/1a/8a/0402ba61a2f16038b48b39bccca271134be00c5c9f0f623208399333c448/markupsafe-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9", size = 15426, upload-time = "2025-09-27T18:37:27.316Z" }, + { url = "https://files.pythonhosted.org/packages/70/bc/6f1c2f612465f5fa89b95bead1f44dcb607670fd42891d8fdcd5d039f4f4/markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa", size = 14146, upload-time = "2025-09-27T18:37:28.327Z" }, +] + +[[package]] +name = "pygments" +version = "2.20.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" }, +] + +[[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 = "pyyaml" +version = "6.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/33/422b98d2195232ca1826284a76852ad5a86fe23e31b009c9886b2d0fb8b2/pyyaml-6.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196", size = 182063, upload-time = "2025-09-25T21:32:11.445Z" }, + { url = "https://files.pythonhosted.org/packages/89/a0/6cf41a19a1f2f3feab0e9c0b74134aa2ce6849093d5517a0c550fe37a648/pyyaml-6.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0", size = 173973, upload-time = "2025-09-25T21:32:12.492Z" }, + { url = "https://files.pythonhosted.org/packages/ed/23/7a778b6bd0b9a8039df8b1b1d80e2e2ad78aa04171592c8a5c43a56a6af4/pyyaml-6.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28", size = 775116, upload-time = "2025-09-25T21:32:13.652Z" }, + { url = "https://files.pythonhosted.org/packages/65/30/d7353c338e12baef4ecc1b09e877c1970bd3382789c159b4f89d6a70dc09/pyyaml-6.0.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c", size = 844011, upload-time = "2025-09-25T21:32:15.21Z" }, + { url = "https://files.pythonhosted.org/packages/8b/9d/b3589d3877982d4f2329302ef98a8026e7f4443c765c46cfecc8858c6b4b/pyyaml-6.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc", size = 807870, upload-time = "2025-09-25T21:32:16.431Z" }, + { url = "https://files.pythonhosted.org/packages/05/c0/b3be26a015601b822b97d9149ff8cb5ead58c66f981e04fedf4e762f4bd4/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e", size = 761089, upload-time = "2025-09-25T21:32:17.56Z" }, + { url = "https://files.pythonhosted.org/packages/be/8e/98435a21d1d4b46590d5459a22d88128103f8da4c2d4cb8f14f2a96504e1/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea", size = 790181, upload-time = "2025-09-25T21:32:18.834Z" }, + { url = "https://files.pythonhosted.org/packages/74/93/7baea19427dcfbe1e5a372d81473250b379f04b1bd3c4c5ff825e2327202/pyyaml-6.0.3-cp312-cp312-win32.whl", hash = "sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5", size = 137658, upload-time = "2025-09-25T21:32:20.209Z" }, + { url = "https://files.pythonhosted.org/packages/86/bf/899e81e4cce32febab4fb42bb97dcdf66bc135272882d1987881a4b519e9/pyyaml-6.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b", size = 154003, upload-time = "2025-09-25T21:32:21.167Z" }, + { url = "https://files.pythonhosted.org/packages/1a/08/67bd04656199bbb51dbed1439b7f27601dfb576fb864099c7ef0c3e55531/pyyaml-6.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd", size = 140344, upload-time = "2025-09-25T21:32:22.617Z" }, + { url = "https://files.pythonhosted.org/packages/d1/11/0fd08f8192109f7169db964b5707a2f1e8b745d4e239b784a5a1dd80d1db/pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8", size = 181669, upload-time = "2025-09-25T21:32:23.673Z" }, + { url = "https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1", size = 173252, upload-time = "2025-09-25T21:32:25.149Z" }, + { url = "https://files.pythonhosted.org/packages/50/31/b20f376d3f810b9b2371e72ef5adb33879b25edb7a6d072cb7ca0c486398/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c", size = 767081, upload-time = "2025-09-25T21:32:26.575Z" }, + { url = "https://files.pythonhosted.org/packages/49/1e/a55ca81e949270d5d4432fbbd19dfea5321eda7c41a849d443dc92fd1ff7/pyyaml-6.0.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5", size = 841159, upload-time = "2025-09-25T21:32:27.727Z" }, + { url = "https://files.pythonhosted.org/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6", size = 801626, upload-time = "2025-09-25T21:32:28.878Z" }, + { url = "https://files.pythonhosted.org/packages/f9/11/ba845c23988798f40e52ba45f34849aa8a1f2d4af4b798588010792ebad6/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6", size = 753613, upload-time = "2025-09-25T21:32:30.178Z" }, + { url = "https://files.pythonhosted.org/packages/3d/e0/7966e1a7bfc0a45bf0a7fb6b98ea03fc9b8d84fa7f2229e9659680b69ee3/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be", size = 794115, upload-time = "2025-09-25T21:32:31.353Z" }, + { url = "https://files.pythonhosted.org/packages/de/94/980b50a6531b3019e45ddeada0626d45fa85cbe22300844a7983285bed3b/pyyaml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26", size = 137427, upload-time = "2025-09-25T21:32:32.58Z" }, + { url = "https://files.pythonhosted.org/packages/97/c9/39d5b874e8b28845e4ec2202b5da735d0199dbe5b8fb85f91398814a9a46/pyyaml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c", size = 154090, upload-time = "2025-09-25T21:32:33.659Z" }, + { url = "https://files.pythonhosted.org/packages/73/e8/2bdf3ca2090f68bb3d75b44da7bbc71843b19c9f2b9cb9b0f4ab7a5a4329/pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb", size = 140246, upload-time = "2025-09-25T21:32:34.663Z" }, + { url = "https://files.pythonhosted.org/packages/9d/8c/f4bd7f6465179953d3ac9bc44ac1a8a3e6122cf8ada906b4f96c60172d43/pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac", size = 181814, upload-time = "2025-09-25T21:32:35.712Z" }, + { url = "https://files.pythonhosted.org/packages/bd/9c/4d95bb87eb2063d20db7b60faa3840c1b18025517ae857371c4dd55a6b3a/pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310", size = 173809, upload-time = "2025-09-25T21:32:36.789Z" }, + { url = "https://files.pythonhosted.org/packages/92/b5/47e807c2623074914e29dabd16cbbdd4bf5e9b2db9f8090fa64411fc5382/pyyaml-6.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7", size = 766454, upload-time = "2025-09-25T21:32:37.966Z" }, + { url = "https://files.pythonhosted.org/packages/02/9e/e5e9b168be58564121efb3de6859c452fccde0ab093d8438905899a3a483/pyyaml-6.0.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788", size = 836355, upload-time = "2025-09-25T21:32:39.178Z" }, + { url = "https://files.pythonhosted.org/packages/88/f9/16491d7ed2a919954993e48aa941b200f38040928474c9e85ea9e64222c3/pyyaml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5", size = 794175, upload-time = "2025-09-25T21:32:40.865Z" }, + { url = "https://files.pythonhosted.org/packages/dd/3f/5989debef34dc6397317802b527dbbafb2b4760878a53d4166579111411e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764", size = 755228, upload-time = "2025-09-25T21:32:42.084Z" }, + { url = "https://files.pythonhosted.org/packages/d7/ce/af88a49043cd2e265be63d083fc75b27b6ed062f5f9fd6cdc223ad62f03e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35", size = 789194, upload-time = "2025-09-25T21:32:43.362Z" }, + { url = "https://files.pythonhosted.org/packages/23/20/bb6982b26a40bb43951265ba29d4c246ef0ff59c9fdcdf0ed04e0687de4d/pyyaml-6.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac", size = 156429, upload-time = "2025-09-25T21:32:57.844Z" }, + { url = "https://files.pythonhosted.org/packages/f4/f4/a4541072bb9422c8a883ab55255f918fa378ecf083f5b85e87fc2b4eda1b/pyyaml-6.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3", size = 143912, upload-time = "2025-09-25T21:32:59.247Z" }, + { url = "https://files.pythonhosted.org/packages/7c/f9/07dd09ae774e4616edf6cda684ee78f97777bdd15847253637a6f052a62f/pyyaml-6.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3", size = 189108, upload-time = "2025-09-25T21:32:44.377Z" }, + { url = "https://files.pythonhosted.org/packages/4e/78/8d08c9fb7ce09ad8c38ad533c1191cf27f7ae1effe5bb9400a46d9437fcf/pyyaml-6.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba", size = 183641, upload-time = "2025-09-25T21:32:45.407Z" }, + { url = "https://files.pythonhosted.org/packages/7b/5b/3babb19104a46945cf816d047db2788bcaf8c94527a805610b0289a01c6b/pyyaml-6.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c", size = 831901, upload-time = "2025-09-25T21:32:48.83Z" }, + { url = "https://files.pythonhosted.org/packages/8b/cc/dff0684d8dc44da4d22a13f35f073d558c268780ce3c6ba1b87055bb0b87/pyyaml-6.0.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702", size = 861132, upload-time = "2025-09-25T21:32:50.149Z" }, + { url = "https://files.pythonhosted.org/packages/b1/5e/f77dc6b9036943e285ba76b49e118d9ea929885becb0a29ba8a7c75e29fe/pyyaml-6.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c", size = 839261, upload-time = "2025-09-25T21:32:51.808Z" }, + { url = "https://files.pythonhosted.org/packages/ce/88/a9db1376aa2a228197c58b37302f284b5617f56a5d959fd1763fb1675ce6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065", size = 805272, upload-time = "2025-09-25T21:32:52.941Z" }, + { url = "https://files.pythonhosted.org/packages/da/92/1446574745d74df0c92e6aa4a7b0b3130706a4142b2d1a5869f2eaa423c6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65", size = 829923, upload-time = "2025-09-25T21:32:54.537Z" }, + { url = "https://files.pythonhosted.org/packages/f0/7a/1c7270340330e575b92f397352af856a8c06f230aa3e76f86b39d01b416a/pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9", size = 174062, upload-time = "2025-09-25T21:32:55.767Z" }, + { 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 = "tomli" +version = "2.4.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/22/de/48c59722572767841493b26183a0d1cc411d54fd759c5607c4590b6563a6/tomli-2.4.1.tar.gz", hash = "sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f", size = 17543, upload-time = "2026-03-25T20:22:03.828Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c1/ba/42f134a3fe2b370f555f44b1d72feebb94debcab01676bf918d0cb70e9aa/tomli-2.4.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c742f741d58a28940ce01d58f0ab2ea3ced8b12402f162f4d534dfe18ba1cd6a", size = 155924, upload-time = "2026-03-25T20:21:21.626Z" }, + { url = "https://files.pythonhosted.org/packages/dc/c7/62d7a17c26487ade21c5422b646110f2162f1fcc95980ef7f63e73c68f14/tomli-2.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7f86fd587c4ed9dd76f318225e7d9b29cfc5a9d43de44e5754db8d1128487085", size = 150018, upload-time = "2026-03-25T20:21:23.002Z" }, + { url = "https://files.pythonhosted.org/packages/5c/05/79d13d7c15f13bdef410bdd49a6485b1c37d28968314eabee452c22a7fda/tomli-2.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ff18e6a727ee0ab0388507b89d1bc6a22b138d1e2fa56d1ad494586d61d2eae9", size = 244948, upload-time = "2026-03-25T20:21:24.04Z" }, + { url = "https://files.pythonhosted.org/packages/10/90/d62ce007a1c80d0b2c93e02cab211224756240884751b94ca72df8a875ca/tomli-2.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:136443dbd7e1dee43c68ac2694fde36b2849865fa258d39bf822c10e8068eac5", size = 253341, upload-time = "2026-03-25T20:21:25.177Z" }, + { url = "https://files.pythonhosted.org/packages/1a/7e/caf6496d60152ad4ed09282c1885cca4eea150bfd007da84aea07bcc0a3e/tomli-2.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5e262d41726bc187e69af7825504c933b6794dc3fbd5945e41a79bb14c31f585", size = 248159, upload-time = "2026-03-25T20:21:26.364Z" }, + { url = "https://files.pythonhosted.org/packages/99/e7/c6f69c3120de34bbd882c6fba7975f3d7a746e9218e56ab46a1bc4b42552/tomli-2.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5cb41aa38891e073ee49d55fbc7839cfdb2bc0e600add13874d048c94aadddd1", size = 253290, upload-time = "2026-03-25T20:21:27.46Z" }, + { url = "https://files.pythonhosted.org/packages/d6/2f/4a3c322f22c5c66c4b836ec58211641a4067364f5dcdd7b974b4c5da300c/tomli-2.4.1-cp312-cp312-win32.whl", hash = "sha256:da25dc3563bff5965356133435b757a795a17b17d01dbc0f42fb32447ddfd917", size = 98141, upload-time = "2026-03-25T20:21:28.492Z" }, + { url = "https://files.pythonhosted.org/packages/24/22/4daacd05391b92c55759d55eaee21e1dfaea86ce5c571f10083360adf534/tomli-2.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:52c8ef851d9a240f11a88c003eacb03c31fc1c9c4ec64a99a0f922b93874fda9", size = 108847, upload-time = "2026-03-25T20:21:29.386Z" }, + { url = "https://files.pythonhosted.org/packages/68/fd/70e768887666ddd9e9f5d85129e84910f2db2796f9096aa02b721a53098d/tomli-2.4.1-cp312-cp312-win_arm64.whl", hash = "sha256:f758f1b9299d059cc3f6546ae2af89670cb1c4d48ea29c3cacc4fe7de3058257", size = 95088, upload-time = "2026-03-25T20:21:30.677Z" }, + { url = "https://files.pythonhosted.org/packages/07/06/b823a7e818c756d9a7123ba2cda7d07bc2dd32835648d1a7b7b7a05d848d/tomli-2.4.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:36d2bd2ad5fb9eaddba5226aa02c8ec3fa4f192631e347b3ed28186d43be6b54", size = 155866, upload-time = "2026-03-25T20:21:31.65Z" }, + { url = "https://files.pythonhosted.org/packages/14/6f/12645cf7f08e1a20c7eb8c297c6f11d31c1b50f316a7e7e1e1de6e2e7b7e/tomli-2.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:eb0dc4e38e6a1fd579e5d50369aa2e10acfc9cace504579b2faabb478e76941a", size = 149887, upload-time = "2026-03-25T20:21:33.028Z" }, + { url = "https://files.pythonhosted.org/packages/5c/e0/90637574e5e7212c09099c67ad349b04ec4d6020324539297b634a0192b0/tomli-2.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c7f2c7f2b9ca6bdeef8f0fa897f8e05085923eb091721675170254cbc5b02897", size = 243704, upload-time = "2026-03-25T20:21:34.51Z" }, + { url = "https://files.pythonhosted.org/packages/10/8f/d3ddb16c5a4befdf31a23307f72828686ab2096f068eaf56631e136c1fdd/tomli-2.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f3c6818a1a86dd6dca7ddcaaf76947d5ba31aecc28cb1b67009a5877c9a64f3f", size = 251628, upload-time = "2026-03-25T20:21:36.012Z" }, + { url = "https://files.pythonhosted.org/packages/e3/f1/dbeeb9116715abee2485bf0a12d07a8f31af94d71608c171c45f64c0469d/tomli-2.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d312ef37c91508b0ab2cee7da26ec0b3ed2f03ce12bd87a588d771ae15dcf82d", size = 247180, upload-time = "2026-03-25T20:21:37.136Z" }, + { url = "https://files.pythonhosted.org/packages/d3/74/16336ffd19ed4da28a70959f92f506233bd7cfc2332b20bdb01591e8b1d1/tomli-2.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:51529d40e3ca50046d7606fa99ce3956a617f9b36380da3b7f0dd3dd28e68cb5", size = 251674, upload-time = "2026-03-25T20:21:38.298Z" }, + { url = "https://files.pythonhosted.org/packages/16/f9/229fa3434c590ddf6c0aa9af64d3af4b752540686cace29e6281e3458469/tomli-2.4.1-cp313-cp313-win32.whl", hash = "sha256:2190f2e9dd7508d2a90ded5ed369255980a1bcdd58e52f7fe24b8162bf9fedbd", size = 97976, upload-time = "2026-03-25T20:21:39.316Z" }, + { url = "https://files.pythonhosted.org/packages/6a/1e/71dfd96bcc1c775420cb8befe7a9d35f2e5b1309798f009dca17b7708c1e/tomli-2.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:8d65a2fbf9d2f8352685bc1364177ee3923d6baf5e7f43ea4959d7d8bc326a36", size = 108755, upload-time = "2026-03-25T20:21:40.248Z" }, + { url = "https://files.pythonhosted.org/packages/83/7a/d34f422a021d62420b78f5c538e5b102f62bea616d1d75a13f0a88acb04a/tomli-2.4.1-cp313-cp313-win_arm64.whl", hash = "sha256:4b605484e43cdc43f0954ddae319fb75f04cc10dd80d830540060ee7cd0243cd", size = 95265, upload-time = "2026-03-25T20:21:41.219Z" }, + { url = "https://files.pythonhosted.org/packages/3c/fb/9a5c8d27dbab540869f7c1f8eb0abb3244189ce780ba9cd73f3770662072/tomli-2.4.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:fd0409a3653af6c147209d267a0e4243f0ae46b011aa978b1080359fddc9b6cf", size = 155726, upload-time = "2026-03-25T20:21:42.23Z" }, + { url = "https://files.pythonhosted.org/packages/62/05/d2f816630cc771ad836af54f5001f47a6f611d2d39535364f148b6a92d6b/tomli-2.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a120733b01c45e9a0c34aeef92bf0cf1d56cfe81ed9d47d562f9ed591a9828ac", size = 149859, upload-time = "2026-03-25T20:21:43.386Z" }, + { url = "https://files.pythonhosted.org/packages/ce/48/66341bdb858ad9bd0ceab5a86f90eddab127cf8b046418009f2125630ecb/tomli-2.4.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:559db847dc486944896521f68d8190be1c9e719fced785720d2216fe7022b662", size = 244713, upload-time = "2026-03-25T20:21:44.474Z" }, + { url = "https://files.pythonhosted.org/packages/df/6d/c5fad00d82b3c7a3ab6189bd4b10e60466f22cfe8a08a9394185c8a8111c/tomli-2.4.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:01f520d4f53ef97964a240a035ec2a869fe1a37dde002b57ebc4417a27ccd853", size = 252084, upload-time = "2026-03-25T20:21:45.62Z" }, + { url = "https://files.pythonhosted.org/packages/00/71/3a69e86f3eafe8c7a59d008d245888051005bd657760e96d5fbfb0b740c2/tomli-2.4.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7f94b27a62cfad8496c8d2513e1a222dd446f095fca8987fceef261225538a15", size = 247973, upload-time = "2026-03-25T20:21:46.937Z" }, + { url = "https://files.pythonhosted.org/packages/67/50/361e986652847fec4bd5e4a0208752fbe64689c603c7ae5ea7cb16b1c0ca/tomli-2.4.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ede3e6487c5ef5d28634ba3f31f989030ad6af71edfb0055cbbd14189ff240ba", size = 256223, upload-time = "2026-03-25T20:21:48.467Z" }, + { url = "https://files.pythonhosted.org/packages/8c/9a/b4173689a9203472e5467217e0154b00e260621caa227b6fa01feab16998/tomli-2.4.1-cp314-cp314-win32.whl", hash = "sha256:3d48a93ee1c9b79c04bb38772ee1b64dcf18ff43085896ea460ca8dec96f35f6", size = 98973, upload-time = "2026-03-25T20:21:49.526Z" }, + { url = "https://files.pythonhosted.org/packages/14/58/640ac93bf230cd27d002462c9af0d837779f8773bc03dee06b5835208214/tomli-2.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:88dceee75c2c63af144e456745e10101eb67361050196b0b6af5d717254dddf7", size = 109082, upload-time = "2026-03-25T20:21:50.506Z" }, + { url = "https://files.pythonhosted.org/packages/d5/2f/702d5e05b227401c1068f0d386d79a589bb12bf64c3d2c72ce0631e3bc49/tomli-2.4.1-cp314-cp314-win_arm64.whl", hash = "sha256:b8c198f8c1805dc42708689ed6864951fd2494f924149d3e4bce7710f8eb5232", size = 96490, upload-time = "2026-03-25T20:21:51.474Z" }, + { url = "https://files.pythonhosted.org/packages/45/4b/b877b05c8ba62927d9865dd980e34a755de541eb65fffba52b4cc495d4d2/tomli-2.4.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:d4d8fe59808a54658fcc0160ecfb1b30f9089906c50b23bcb4c69eddc19ec2b4", size = 164263, upload-time = "2026-03-25T20:21:52.543Z" }, + { url = "https://files.pythonhosted.org/packages/24/79/6ab420d37a270b89f7195dec5448f79400d9e9c1826df982f3f8e97b24fd/tomli-2.4.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7008df2e7655c495dd12d2a4ad038ff878d4ca4b81fccaf82b714e07eae4402c", size = 160736, upload-time = "2026-03-25T20:21:53.674Z" }, + { url = "https://files.pythonhosted.org/packages/02/e0/3630057d8eb170310785723ed5adcdfb7d50cb7e6455f85ba8a3deed642b/tomli-2.4.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1d8591993e228b0c930c4bb0db464bdad97b3289fb981255d6c9a41aedc84b2d", size = 270717, upload-time = "2026-03-25T20:21:55.129Z" }, + { url = "https://files.pythonhosted.org/packages/7a/b4/1613716072e544d1a7891f548d8f9ec6ce2faf42ca65acae01d76ea06bb0/tomli-2.4.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:734e20b57ba95624ecf1841e72b53f6e186355e216e5412de414e3c51e5e3c41", size = 278461, upload-time = "2026-03-25T20:21:56.228Z" }, + { url = "https://files.pythonhosted.org/packages/05/38/30f541baf6a3f6df77b3df16b01ba319221389e2da59427e221ef417ac0c/tomli-2.4.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8a650c2dbafa08d42e51ba0b62740dae4ecb9338eefa093aa5c78ceb546fcd5c", size = 274855, upload-time = "2026-03-25T20:21:57.653Z" }, + { url = "https://files.pythonhosted.org/packages/77/a3/ec9dd4fd2c38e98de34223b995a3b34813e6bdadf86c75314c928350ed14/tomli-2.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:504aa796fe0569bb43171066009ead363de03675276d2d121ac1a4572397870f", size = 283144, upload-time = "2026-03-25T20:21:59.089Z" }, + { url = "https://files.pythonhosted.org/packages/ef/be/605a6261cac79fba2ec0c9827e986e00323a1945700969b8ee0b30d85453/tomli-2.4.1-cp314-cp314t-win32.whl", hash = "sha256:b1d22e6e9387bf4739fbe23bfa80e93f6b0373a7f1b96c6227c32bef95a4d7a8", size = 108683, upload-time = "2026-03-25T20:22:00.214Z" }, + { url = "https://files.pythonhosted.org/packages/12/64/da524626d3b9cc40c168a13da8335fe1c51be12c0a63685cc6db7308daae/tomli-2.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:2c1c351919aca02858f740c6d33adea0c5deea37f9ecca1cc1ef9e884a619d26", size = 121196, upload-time = "2026-03-25T20:22:01.169Z" }, + { url = "https://files.pythonhosted.org/packages/5a/cd/e80b62269fc78fc36c9af5a6b89c835baa8af28ff5ad28c7028d60860320/tomli-2.4.1-cp314-cp314t-win_arm64.whl", hash = "sha256:eab21f45c7f66c13f2a9e0e1535309cee140182a9cdae1e041d02e47291e8396", size = 100393, upload-time = "2026-03-25T20:22:02.137Z" }, + { url = "https://files.pythonhosted.org/packages/7b/61/cceae43728b7de99d9b847560c262873a1f6c98202171fd5ed62640b494b/tomli-2.4.1-py3-none-any.whl", hash = "sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe", size = 14583, upload-time = "2026-03-25T20:22:03.012Z" }, +] + +[[package]] +name = "zensical" +version = "0.0.51" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "deepmerge" }, + { name = "jinja2" }, + { name = "markdown" }, + { name = "pygments" }, + { name = "pymdown-extensions" }, + { name = "pyyaml" }, + { name = "tomli" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b8/f7/d07ffb268ca86afb26b7f32dbabe25dec03d3aa63ba4d876720c84681d33/zensical-0.0.51.tar.gz", hash = "sha256:de25de067bedfa18f916d7f366fd64a7fbf09bfcc615b44d1ddbe3b5fe02ab49", size = 3979640, upload-time = "2026-07-17T18:08:03.445Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/48/21/02db3e1fb3904016bfac310037c95b9f1eaaf0ffe7b4a84f14263a7d95df/zensical-0.0.51-cp310-abi3-macosx_10_12_x86_64.whl", hash = "sha256:134d776afa526098e05e34713e2f577c075e57a232e01b97842bb0206716afce", size = 12791154, upload-time = "2026-07-17T18:07:20.748Z" }, + { url = "https://files.pythonhosted.org/packages/a2/35/b0d96f58253514cb3d08f5779020ab01ee5472334fb984b92e3fc9e9c9ac/zensical-0.0.51-cp310-abi3-macosx_11_0_arm64.whl", hash = "sha256:e97ab39668ae3b452c550634e921a0336443743aae5e1fe031c7bb57d049e535", size = 12692190, upload-time = "2026-07-17T18:07:24.553Z" }, + { url = "https://files.pythonhosted.org/packages/2e/90/7a60e126a10c37c6b789938ff17e73fe76bba707fa029cb40ac659aeaa82/zensical-0.0.51-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c9579809f88608e7aa2cff516fff9d267d74a843cf6088a5f4227de2f092bb5", size = 13139337, upload-time = "2026-07-17T18:07:27.885Z" }, + { url = "https://files.pythonhosted.org/packages/ae/c3/9101c97b90d4713ef2816db03366a45ae4762efebffd296737a2dd2df325/zensical-0.0.51-cp310-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:296dc7a14aa28b81a58eb57df2d5c9c9a4b0de7e90c11d99c943354287952925", size = 13069851, upload-time = "2026-07-17T18:07:31.814Z" }, + { url = "https://files.pythonhosted.org/packages/d2/79/0474df9e15a2c18f6281a786e10177c1b6e16feac1c568e7f36ad39b339c/zensical-0.0.51-cp310-abi3-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f779d2d87b4bf228cf2e279bc0ae6bcf3b36a9335ff283a317d01f7c15ae46b2", size = 13451083, upload-time = "2026-07-17T18:07:35.543Z" }, + { url = "https://files.pythonhosted.org/packages/fe/6f/91bbf78f704d5fd4c0c9be27d6bce3b6e4c2c339e4dcd6e7cf19ecda643c/zensical-0.0.51-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67f813a1514a90890ca86248a8d54b81b2164bcbff11a6bcf11b01e1c01a1454", size = 13110446, upload-time = "2026-07-17T18:07:38.783Z" }, + { url = "https://files.pythonhosted.org/packages/d9/89/aa9a95f81771614c37bdc52b8ab21fcdef4c8de7c9cedf34e9bf62674281/zensical-0.0.51-cp310-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:186ef37e0eee0e969e2cfae47b1b97775e3164e2cba95c71faa4dd6ef47ed009", size = 13315871, upload-time = "2026-07-17T18:07:42.43Z" }, + { url = "https://files.pythonhosted.org/packages/08/11/1bf6e9ded29d376f8c12644cc4de04676b010fee8caa17f682606b1f16d5/zensical-0.0.51-cp310-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:f5d91ce246ed930224603083cef02ae8947132fc7c52901d72015ea03526fa58", size = 13344382, upload-time = "2026-07-17T18:07:46.066Z" }, + { url = "https://files.pythonhosted.org/packages/d6/ec/663f16ff82d08b212e7c3236a88bd332f73331f94ddac1c91aaf882bbd1e/zensical-0.0.51-cp310-abi3-musllinux_1_2_i686.whl", hash = "sha256:b1108eae82c6e8ffc33026f60b485c1512647a5333be4f547166b7c8877b98af", size = 13499628, upload-time = "2026-07-17T18:07:49.196Z" }, + { url = "https://files.pythonhosted.org/packages/60/b4/7f1b6c3cf06d9f6ff5216523168a5d6ccc693444d5ceeb911eca97b30d98/zensical-0.0.51-cp310-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:6fa0ecaf14f56841bfc595fa141396350c72aafbec73a016ebe3c824ed21ac72", size = 13451420, upload-time = "2026-07-17T18:07:52.563Z" }, + { url = "https://files.pythonhosted.org/packages/0a/44/be4bc09ec8f69e7be1b07b875887961c4e0e478b03a10d2cc624ef28fbe6/zensical-0.0.51-cp310-abi3-win32.whl", hash = "sha256:fb7ff4946b72168759c6af0a29cf5de4c38aebe633a83292e8cd4145b5213cc2", size = 12375639, upload-time = "2026-07-17T18:07:56.081Z" }, + { url = "https://files.pythonhosted.org/packages/1f/85/aa827c244ed4f404e99a91c3ecf5e5adb62eca806a9e9c8e3333bbad8660/zensical-0.0.51-cp310-abi3-win_amd64.whl", hash = "sha256:12529d3d3991b63820952111dc1d1edc29b2c9b3a3abb16c243bcb649631ebf2", size = 12628965, upload-time = "2026-07-17T18:07:59.741Z" }, +]