diff --git a/.gitignore b/.gitignore index ecc2b67d3..d5f692eb9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ # Node, Bun, and Deno Related -package-lock.json node_modules/ # IDE Related @@ -74,3 +73,5 @@ website/.docusaurus/ # Added by cargo /target + +.claude/ \ No newline at end of file diff --git a/substrate.json b/substrate.json new file mode 100644 index 000000000..101725d8d --- /dev/null +++ b/substrate.json @@ -0,0 +1,8 @@ +{ + "package": { + "name": "language", + "kind": "library", + "version": "0.1.0", + "subdir": "substrate/specs/language" + } +} \ No newline at end of file diff --git a/substrate/.agents/skills/grill-me/SKILL.md b/substrate/.agents/skills/grill-me/SKILL.md new file mode 100644 index 000000000..bd04394c6 --- /dev/null +++ b/substrate/.agents/skills/grill-me/SKILL.md @@ -0,0 +1,10 @@ +--- +name: grill-me +description: Interview the user relentlessly about a plan or design until reaching shared understanding, resolving each branch of the decision tree. Use when user wants to stress-test a plan, get grilled on their design, or mentions "grill me". +--- + +Interview me relentlessly about every aspect of this plan until we reach a shared understanding. Walk down each branch of the design tree, resolving dependencies between decisions one-by-one. For each question, provide your recommended answer. + +Ask the questions one at a time. + +If a question can be answered by exploring the codebase, explore the codebase instead. diff --git a/substrate/.agents/skills/grill-with-docs/ADR-FORMAT.md b/substrate/.agents/skills/grill-with-docs/ADR-FORMAT.md new file mode 100644 index 000000000..da7e78ec1 --- /dev/null +++ b/substrate/.agents/skills/grill-with-docs/ADR-FORMAT.md @@ -0,0 +1,47 @@ +# ADR Format + +ADRs live in `docs/adr/` and use sequential numbering: `0001-slug.md`, `0002-slug.md`, etc. + +Create the `docs/adr/` directory lazily — only when the first ADR is needed. + +## Template + +```md +# {Short title of the decision} + +{1-3 sentences: what's the context, what did we decide, and why.} +``` + +That's it. An ADR can be a single paragraph. The value is in recording *that* a decision was made and *why* — not in filling out sections. + +## Optional sections + +Only include these when they add genuine value. Most ADRs won't need them. + +- **Status** frontmatter (`proposed | accepted | deprecated | superseded by ADR-NNNN`) — useful when decisions are revisited +- **Considered Options** — only when the rejected alternatives are worth remembering +- **Consequences** — only when non-obvious downstream effects need to be called out + +## Numbering + +Scan `docs/adr/` for the highest existing number and increment by one. + +## When to offer an ADR + +All three of these must be true: + +1. **Hard to reverse** — the cost of changing your mind later is meaningful +2. **Surprising without context** — a future reader will look at the code and wonder "why on earth did they do it this way?" +3. **The result of a real trade-off** — there were genuine alternatives and you picked one for specific reasons + +If a decision is easy to reverse, skip it — you'll just reverse it. If it's not surprising, nobody will wonder why. If there was no real alternative, there's nothing to record beyond "we did the obvious thing." + +### What qualifies + +- **Architectural shape.** "We're using a monorepo." "The write model is event-sourced, the read model is projected into Postgres." +- **Integration patterns between contexts.** "Ordering and Billing communicate via domain events, not synchronous HTTP." +- **Technology choices that carry lock-in.** Database, message bus, auth provider, deployment target. Not every library — just the ones that would take a quarter to swap out. +- **Boundary and scope decisions.** "Customer data is owned by the Customer context; other contexts reference it by ID only." The explicit no-s are as valuable as the yes-s. +- **Deliberate deviations from the obvious path.** "We're using manual SQL instead of an ORM because X." Anything where a reasonable reader would assume the opposite. These stop the next engineer from "fixing" something that was deliberate. +- **Constraints not visible in the code.** "We can't use AWS because of compliance requirements." "Response times must be under 200ms because of the partner API contract." +- **Rejected alternatives when the rejection is non-obvious.** If you considered GraphQL and picked REST for subtle reasons, record it — otherwise someone will suggest GraphQL again in six months. diff --git a/substrate/.agents/skills/grill-with-docs/CONTEXT-FORMAT.md b/substrate/.agents/skills/grill-with-docs/CONTEXT-FORMAT.md new file mode 100644 index 000000000..ddfa247ca --- /dev/null +++ b/substrate/.agents/skills/grill-with-docs/CONTEXT-FORMAT.md @@ -0,0 +1,77 @@ +# CONTEXT.md Format + +## Structure + +```md +# {Context Name} + +{One or two sentence description of what this context is and why it exists.} + +## Language + +**Order**: +{A concise description of the term} +_Avoid_: Purchase, transaction + +**Invoice**: +A request for payment sent to a customer after delivery. +_Avoid_: Bill, payment request + +**Customer**: +A person or organization that places orders. +_Avoid_: Client, buyer, account + +## Relationships + +- An **Order** produces one or more **Invoices** +- An **Invoice** belongs to exactly one **Customer** + +## Example dialogue + +> **Dev:** "When a **Customer** places an **Order**, do we create the **Invoice** immediately?" +> **Domain expert:** "No — an **Invoice** is only generated once a **Fulfillment** is confirmed." + +## Flagged ambiguities + +- "account" was used to mean both **Customer** and **User** — resolved: these are distinct concepts. +``` + +## Rules + +- **Be opinionated.** When multiple words exist for the same concept, pick the best one and list the others as aliases to avoid. +- **Flag conflicts explicitly.** If a term is used ambiguously, call it out in "Flagged ambiguities" with a clear resolution. +- **Keep definitions tight.** One sentence max. Define what it IS, not what it does. +- **Show relationships.** Use bold term names and express cardinality where obvious. +- **Only include terms specific to this project's context.** General programming concepts (timeouts, error types, utility patterns) don't belong even if the project uses them extensively. Before adding a term, ask: is this a concept unique to this context, or a general programming concept? Only the former belongs. +- **Group terms under subheadings** when natural clusters emerge. If all terms belong to a single cohesive area, a flat list is fine. +- **Write an example dialogue.** A conversation between a dev and a domain expert that demonstrates how the terms interact naturally and clarifies boundaries between related concepts. + +## Single vs multi-context repos + +**Single context (most repos):** One `CONTEXT.md` at the repo root. + +**Multiple contexts:** A `CONTEXT-MAP.md` at the repo root lists the contexts, where they live, and how they relate to each other: + +```md +# Context Map + +## Contexts + +- [Ordering](./src/ordering/CONTEXT.md) — receives and tracks customer orders +- [Billing](./src/billing/CONTEXT.md) — generates invoices and processes payments +- [Fulfillment](./src/fulfillment/CONTEXT.md) — manages warehouse picking and shipping + +## Relationships + +- **Ordering → Fulfillment**: Ordering emits `OrderPlaced` events; Fulfillment consumes them to start picking +- **Fulfillment → Billing**: Fulfillment emits `ShipmentDispatched` events; Billing consumes them to generate invoices +- **Ordering ↔ Billing**: Shared types for `CustomerId` and `Money` +``` + +The skill infers which structure applies: + +- If `CONTEXT-MAP.md` exists, read it to find contexts +- If only a root `CONTEXT.md` exists, single context +- If neither exists, create a root `CONTEXT.md` lazily when the first term is resolved + +When multiple contexts exist, infer which one the current topic relates to. If unclear, ask. diff --git a/substrate/.agents/skills/grill-with-docs/SKILL.md b/substrate/.agents/skills/grill-with-docs/SKILL.md new file mode 100644 index 000000000..5ea0aa913 --- /dev/null +++ b/substrate/.agents/skills/grill-with-docs/SKILL.md @@ -0,0 +1,88 @@ +--- +name: grill-with-docs +description: Grilling session that challenges your plan against the existing domain model, sharpens terminology, and updates documentation (CONTEXT.md, ADRs) inline as decisions crystallise. Use when user wants to stress-test a plan against their project's language and documented decisions. +--- + + + +Interview me relentlessly about every aspect of this plan until we reach a shared understanding. Walk down each branch of the design tree, resolving dependencies between decisions one-by-one. For each question, provide your recommended answer. + +Ask the questions one at a time, waiting for feedback on each question before continuing. + +If a question can be answered by exploring the codebase, explore the codebase instead. + + + + + +## Domain awareness + +During codebase exploration, also look for existing documentation: + +### File structure + +Most repos have a single context: + +``` +/ +├── CONTEXT.md +├── docs/ +│ └── adr/ +│ ├── 0001-event-sourced-orders.md +│ └── 0002-postgres-for-write-model.md +└── src/ +``` + +If a `CONTEXT-MAP.md` exists at the root, the repo has multiple contexts. The map points to where each one lives: + +``` +/ +├── CONTEXT-MAP.md +├── docs/ +│ └── adr/ ← system-wide decisions +├── src/ +│ ├── ordering/ +│ │ ├── CONTEXT.md +│ │ └── docs/adr/ ← context-specific decisions +│ └── billing/ +│ ├── CONTEXT.md +│ └── docs/adr/ +``` + +Create files lazily — only when you have something to write. If no `CONTEXT.md` exists, create one when the first term is resolved. If no `docs/adr/` exists, create it when the first ADR is needed. + +## During the session + +### Challenge against the glossary + +When the user uses a term that conflicts with the existing language in `CONTEXT.md`, call it out immediately. "Your glossary defines 'cancellation' as X, but you seem to mean Y — which is it?" + +### Sharpen fuzzy language + +When the user uses vague or overloaded terms, propose a precise canonical term. "You're saying 'account' — do you mean the Customer or the User? Those are different things." + +### Discuss concrete scenarios + +When domain relationships are being discussed, stress-test them with specific scenarios. Invent scenarios that probe edge cases and force the user to be precise about the boundaries between concepts. + +### Cross-reference with code + +When the user states how something works, check whether the code agrees. If you find a contradiction, surface it: "Your code cancels entire Orders, but you just said partial cancellation is possible — which is right?" + +### Update CONTEXT.md inline + +When a term is resolved, update `CONTEXT.md` right there. Don't batch these up — capture them as they happen. Use the format in [CONTEXT-FORMAT.md](./CONTEXT-FORMAT.md). + +`CONTEXT.md` should be totally devoid of implementation details. Do not treat `CONTEXT.md` as a spec, a scratch pad, or a repository for implementation decisions. It is a glossary and nothing else. + +### Offer ADRs sparingly + +Only offer to create an ADR when all three are true: + +1. **Hard to reverse** — the cost of changing your mind later is meaningful +2. **Surprising without context** — a future reader will wonder "why did they do it this way?" +3. **The result of a real trade-off** — there were genuine alternatives and you picked one for specific reasons + +If any of the three is missing, skip the ADR. Use the format in [ADR-FORMAT.md](./ADR-FORMAT.md). + + diff --git a/substrate/.gitignore b/substrate/.gitignore new file mode 100644 index 000000000..9349c6ac2 --- /dev/null +++ b/substrate/.gitignore @@ -0,0 +1,11 @@ +node_modules/ +dist/ +.claude/ +.obsidian/ +*.code-workspace +*.log +*.tsbuildinfo +assets/web/assets/ +assets/web/index.html +examples/.github/ +examples/substrate/ \ No newline at end of file diff --git a/substrate/.markdownlint-cli2.jsonc b/substrate/.markdownlint-cli2.jsonc new file mode 100644 index 000000000..9e241eb30 --- /dev/null +++ b/substrate/.markdownlint-cli2.jsonc @@ -0,0 +1,14 @@ +{ + "config": { + // Heading levels should increment one at a time + "MD001": true, + // Line length: disabled (spec tables and links can be long) + "MD013": false, + // Allow duplicate headings in different sections (operations reuse names) + "MD024": false, + // Ordered list items should use incrementing numbers + "MD029": true, + // Inline HTML: disabled (none expected, but don't block on it) + "MD033": false + } +} \ No newline at end of file diff --git a/substrate/.remarkignore b/substrate/.remarkignore new file mode 100644 index 000000000..e06c8944c --- /dev/null +++ b/substrate/.remarkignore @@ -0,0 +1,2 @@ +examples/broken.md +docs/src/content/ diff --git a/substrate/.remarkrc.yml b/substrate/.remarkrc.yml new file mode 100644 index 000000000..7112009bf --- /dev/null +++ b/substrate/.remarkrc.yml @@ -0,0 +1,2 @@ +plugins: + - remark-validate-links diff --git a/substrate/CLAUDE.md b/substrate/CLAUDE.md new file mode 100644 index 000000000..ca8aced61 --- /dev/null +++ b/substrate/CLAUDE.md @@ -0,0 +1,85 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Important Instructions + +- When presenting multiple options for the user to choose between (e.g. during grilling sessions, design discussions, or any enumerated choice), label them with latin letters or short descriptive tags — never Greek letters. +- When implementing a new feature or changing an existing one always update the `specs/` folder to reflect the requirements and design. +- **Minimum 7-day package age (transitive too).** Never add or upgrade an + npm dependency — direct *or transitive* — to a version published less + than seven days ago. Brand-new releases get yanked or get + supply-chain-compromised; the seven-day soak is our line of defence. + Workflow when adding/bumping a dep: + 1. Before installing, check `npm view time --json` for the + candidate version; pick an older patch or wait if it's too young. + 2. After installing, run **`node scripts/check-ages-deep.mjs`** — it + walks every package in `node_modules/` and `web/node_modules/` + (730+ entries) and exits non-zero if anything is younger than 7 days. + This is the script that matters; it catches transitive deps that + direct-only audits miss (e.g. `rollup` arriving via `vite`). + 3. If a direct dep's `^` / `~` range would resolve to a too-young + version, pin it to an exact version (no caret/tilde). + 4. If a *transitive* dep is too young, pin it via the `overrides` field + in the relevant `package.json` (`web/package.json` for the SPA tree, + root `package.json` for the CLI tree). Document the rationale in a + `comment_overrides` sibling so the next person knows why and when to + revisit. Re-run the deep audit after `npm install`. + + `scripts/check-ages.mjs` (direct-only) and + `scripts/check-range-risk.mjs` (latest-satisfying probe) exist as + faster sanity checks but **are not sufficient on their own**; + `check-ages-deep.mjs` is the source of truth. +- **Keep the bundled AI-assistant instructions in sync with the CLI.** Whenever you add, rename, remove, or change the behavior of a `substrate` command (especially the `refactor` subcommands), update *both* of these files in the same change so users who consume substrate via `substrate install` get an accurate skill: + - `assets/ai-instructions/claude/substrate-cli/SKILL.md` — the Claude skill. + - `assets/ai-instructions/copilot/substrate-cli.instructions.md` — the GitHub Copilot path-scoped instructions. + These are shipped with the npm package and copied into the consumer's project by `substrate init` and `substrate install`. If the spec under `specs/tools/cli/` changes but these files do not, the change is incomplete. + +## Commands + +```bash +npm run build # Build CLI (tsc → dist/) and web UI (vite → assets/web/) +npm run build:cli # CLI only +npm run build:web # Web UI only (Vite production build) +npm run dev:web # Live dev: substrate dev :5173 + Vite HMR on :5174 +npm run web:install # Install web/ dependencies +npm run test # Run all tests (vitest) +npm run test:watch # Watch mode +npm run lint # Markdown lint + link validation +npm run lint:md # Markdown structure only +npm run lint:links # Internal link resolution only +``` + +Run a single test file: +```bash +npx vitest run test/stages/typecheck.test.ts +``` + +## Project Overview + +This is **substrate**: an LLM-native executable specification language. The project is part of an umbrella +project called Morphir so it's sometimes referred to as **morphir-substrate**. The project lives under the +morphir repo, but it should treated as a standalne project. + +### Specs (`specs/`) + +The language specification itself lives in `specs/language/concepts/` and `specs/language/expressions/` as markdown files — they are both the source of truth and test input for the pipeline. + +### Web UI (`web/`) + +The `substrate dev` development UI is a Vite + React + TypeScript SPA +under `web/`. `vite build` emits a self-contained bundle into +`assets/web/`, which `src/commands/dev.ts` serves as static files in +production. + +Layout and conventions (one folder per component, CSS modules, brand +tokens via `branding/tokens.css`) are documented in `web/README.md`. +Keep `web/src/types.ts` in sync with the JSON shapes served by +`src/commands/dev.ts`. + +## Important Notes + +- TypeScript strict mode, ES modules (`"type": "module"` in package.json) +- Tests live in `test/**/*.test.ts` with 10-second timeout (vitest) +- Compiled output goes to `dist/`; the CLI binary is `dist/cli.js` +- No AI co-authors in commits (see root `CLAUDE.md` at the parent repo level for EasyCLA requirements) diff --git a/substrate/LICENSE b/substrate/LICENSE new file mode 100644 index 000000000..e2d14cff9 --- /dev/null +++ b/substrate/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Attila Mihaly + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/substrate/README.md b/substrate/README.md new file mode 100644 index 000000000..4cb1f8fcb --- /dev/null +++ b/substrate/README.md @@ -0,0 +1,109 @@ +# Substrate + +**Verifiable knowledge for human–LLM collaboration.** + +Substrate turns the documents your organization already writes — +specifications, regulations, domain models, runbooks — into a structured, +link-typed, mechanically verifiable corpus that both humans and language +models can read, edit, and act on. + +## Why + +Most institutional knowledge lives in unverifiable documents. Nothing +checks that a definition on page 12 matches the rule on page 47, that +an example still produces the stated output, or that the implementation +actually does what the document says. As specifications evolve, the gap +between document and reality widens silently. + +LLMs amplify this. They are powerful readers and writers of prose, but +their answers are only as trustworthy as the context they are given. +Feed a model the wrong slice of a sprawling document set, or one that +quietly contradicts itself, and you get confident output that is wrong +in ways no one catches. + +The same structure that makes a corpus mechanically verifiable also +makes it the ideal context source for an LLM. A document set that tools +can check, an LLM can be trusted to act on. + +## What it is + +Substrate is **plain markdown**, written by humans assisted by LLMs, +rendered by GitHub, no custom syntax. Structure is carried by the things +markdown already gives you — headings, tables, lists, footnotes, and +especially **links** between documents. + +Those links are the trick. As authors describe a business problem in +their own words, every reference to a concept, type, or operation is a +link to the place that defines it. The corpus quietly accumulates a +**semantic knowledge graph** that tools can traverse, type-check, and +slice for an LLM — without constraining how the prose is written. The +freedom to describe the domain naturally and the ability to interpret +it mechanically come from the same structure. + +Around that medium, Substrate adds: + +- A **package model** — versioned libraries of reusable concepts, and + domain corpora that compose them, with cross-repository links resolved + through a vendored `substrate/` tree. +- A **CLI** — `substrate` — that extracts focused context for LLMs, + validates the corpus for consistency and type compatibility, refactors + safely across files, runs embedded test cases, and binds + specifications to live data. + +## Verifiable knowledge + +Every claim the corpus makes is mechanically checkable: that this term +has that type, that this operation produces that output for this input, +that this rule depends on that definition. Verification is layered — +structural validity, link resolution, type compatibility, embedded test +cases — and findings are reported against the originating prose, not an +opaque intermediate representation. + +## What this changes for engineers + +Engineers contribute most when they can spot patterns and translate +them into efficient technology. With unstructured prose as the only +context, that skill has nowhere to land — engineers either build a +mental model in their head and hand-hold an LLM through implementation, +or they let the LLM interpret the prose directly and improvise a +solution from prose plus training data. + +Substrate externalizes the mental model. Engineers describe recurring +patterns using the corpus's own identifiers and attach **technology +mappings** to them — how each pattern is realized in TypeScript, SQL, +or whatever target fits. Where a pattern matches and a mapping exists, +the tooling produces the implementation directly: no LLM improvisation, +no per-task prompt engineering. Where a case is novel, the LLM still +helps, but its work is checked against the corpus and the result can +be promoted to a reusable pattern. Engineering judgment accumulates +in the corpus rather than evaporating into chat transcripts. + +## What you can do with it today + +```bash +substrate context spec.md#section # tree-shaken slice for an LLM +substrate validate # structure, links, types +substrate test spec.md # run embedded test cases +substrate refactor rename a.md#x b.md#y # safe corpus-wide rename +substrate install / update / publish # versioned packages +``` + +Run `substrate --help` for the full command set. + +## Status + +Substrate is part of the [Morphir](https://github.com/finos/morphir) +project. It is in active development; the language and tooling are +evolving together. + +## Learn more + +- [Vision](specs/vision.md) — goals, principles, and where this is + headed. +- [Language Specification](specs/language/README.md) — the conventions the + corpus follows. +- [CLI](specs/tools/cli/) — command reference and design decisions. + +## License + +See [LICENSE](LICENSE). diff --git a/substrate/assets/ai-instructions/claude/substrate-cli/SKILL.md b/substrate/assets/ai-instructions/claude/substrate-cli/SKILL.md new file mode 100644 index 000000000..30e8e0d57 --- /dev/null +++ b/substrate/assets/ai-instructions/claude/substrate-cli/SKILL.md @@ -0,0 +1,291 @@ +--- +name: substrate-cli +description: Use the substrate CLI to manage, refactor, validate, and slice the markdown corpus in a Substrate package. Trigger whenever the user wants to rename a markdown file, rename or move a heading/section, update cross-document links, validate links, install or update vendored packages, or extract a tree-shaken markdown slice for LLM context. +--- + +# Substrate CLI + +Substrate is a CLI for working with a corpus of plain markdown files that are +linked together as a semantic knowledge graph. The corpus root is the +directory that contains `substrate.json`. Vendored dependencies live under +`substrate/` next to that manifest. + +The CLI exists so that **you never edit markdown links by hand** when a file +or heading moves: every operation that could break a link is implemented as a +single subcommand that updates the disk *and* every reference in the project +atomically. Prefer these commands over hand-edits, multi-step bash, or +search-and-replace. + +## When to reach for this skill + +Reach for `substrate` whenever the user asks you to: + +- Rename a markdown file in a Substrate project. +- Rename a heading (and have inbound `#anchor` links keep working). +- Move a section from one document to another. +- Check that every link in the corpus resolves. +- Install, update, or publish a Substrate package. +- Produce a focused, self-contained markdown slice from a large corpus + ("give me just the part of these docs an LLM needs to answer X"). +- Count words, links, or sections in a markdown file. + +Detect whether the project is a Substrate corpus by looking for +`substrate.json` walking up from the current directory. If none is found, +this CLI doesn't apply. + +## Refactoring — `substrate refactor rename` + +**This is the most important command in this skill.** Whenever a file or +heading moves, use it instead of editing files manually. It rewrites every +inline link `[text](path)` and every reference-style definition +`[id]: path` in every `.md` file in the project — you do not have to find +them yourself. + +The operation performed is determined by the **shape** of the two +arguments. There is only one command; three different operations: + +### Rename a file + +```bash +substrate refactor rename specs/old-name.md specs/new-name.md +``` + +Both arguments are plain file paths. Renames the file on disk and rewrites +every link that pointed at the old path. Use whenever a `.md` file moves +or is renamed. + +### Rename a section (same file) + +```bash +substrate refactor rename specs/foo.md#old-anchor specs/foo.md#new-anchor +``` + +Both arguments are in the same file but with different anchors. Changes the +heading text in the file, then rewrites every inbound `#anchor` reference. + +The new heading text is **derived from the anchor slug**: hyphens become +spaces and the first letter is capitalised. `my-new-section` becomes the +heading `# My new section`. If the user gives you the *heading text they +want* rather than a slug, convert it to a slug first +(`Decision Table` → `decision-table`). + +### Move a section between files + +```bash +# Interactive — opens a TTY picker for the insertion point in b.md. +substrate refactor rename specs/a.md#section specs/b.md + +# Non-interactive — appends the section after #parent in b.md. +substrate refactor rename specs/a.md#section specs/b.md#parent +``` + +`from` has an anchor; `to` is a different file. Removes the section and +all its sub-sections from the source file, then appends them in the +target file. Every reference to any of the moved anchors is rewritten to +point at the target file. Heading depth is **not** adjusted. + +When you are running unattended (no TTY), always specify the parent +anchor in the `to` argument — the interactive picker will refuse to run +and the command will fail. + +### Failure modes worth anticipating + +- **Anchor collision when moving.** If any moved heading slug already + exists in the target file the command errors before making changes. + Tell the user to rename the conflicting section first (with the + section-rename form above), then retry the move. +- **Same anchor on both sides of a section rename.** If the new heading + slugifies to the existing anchor (e.g. only capitalisation changed), + the command errors with "nothing to do." Pick a textually different + heading. +- **File rename with anchors.** Mixing file and anchor shapes — e.g. + `rename a.md b.md#x` — is rejected. Decide whether you are renaming a + file or moving a section. + +### What does *not* count as a refactor + +These do not have dedicated commands; do them manually and then run +`substrate validate`: + +- Splitting one large `.md` into several files. +- Merging several files into one. +- Renaming a directory (rename each file individually, or `git mv` plus + hand-fixups + `substrate validate`). + +`substrate validate` after any manual change is the safety net. + +## Markdown management commands + +### `substrate validate` + +Walks every `.md` file in the corpus and reports unresolved links. Exits +non-zero on any broken link. Run it after any hand-edit that could move +content or change a heading; run it before publishing. + +```bash +substrate validate +``` + +### `substrate context [#section] ...` + +Produces a single self-contained markdown document on stdout, tree-shaken +to the sections actually reachable from the supplied roots and rewritten +so cross-file links become in-document anchors. Use this whenever the +user wants to feed a slice of the corpus to an LLM as compact context. + +```bash +# Default — tree-shake to just the sections needed. +substrate context specs/spec.md#decision-table > context.md + +# Include the full file (still rewrites links). +substrate context --no-tree-shaking specs/spec.md > context.md + +# Only the explicitly named roots; do not follow links. +substrate context --no-inline specs/a.md specs/b.md > context.md + +# Pull in matching sections from a horizontal package via reverse traversal. +substrate context spec.md --horizontal horizontals/examples +``` + +If a file has a section whose anchor is `summary`, asking for the whole +file is silently rewritten to just that summary — author the `summary` +section deliberately when you want a compact synopsis. + +### `substrate stats [file]` + +Prints word count, line count, rough token estimate, link breakdown, +section count, and heading depth statistics. Reads stdin when no file is +supplied — useful for piping `substrate context` output: + +```bash +substrate context spec.md | substrate stats +``` + +Use this to size a slice before sending it to an LLM. + +### `substrate verify ` + +Runs the full pipeline (parse → include → lint → references → typecheck +→ test) on a single file. Heavier than `validate`; reach for it when the +user wants the *language* checks, not just link resolution. + +### `substrate dev` + +Starts a local development web UI that browses every `.md` file under a +directory and auto-reloads when files change on disk. Use it when the +user wants to "see" the corpus in a browser while editing. + +```bash +substrate dev # serve the current working directory +substrate dev --dir specs # serve a specific directory +substrate dev --port 4000 # pin the port (default: OS-assigned) +``` + +The URL is printed on standard out so the user can ctrl/cmd-click to +open it. The server binds to `127.0.0.1` by default and is +unauthenticated — do not pass `--host 0.0.0.0` on an untrusted network. + +The current implementation is a plain markdown viewer; substrate-specific +rendering (link resolution, type info, test overlays) is intentionally +out of scope for now. + +## Writing interpretations — `substrate write interpretation` + +Use this whenever you produce or update a substrate YAML snippet for a +markdown section. It writes the snippet *into* the document for you, +rather than asking the user to copy-paste a fenced block. + +```bash +substrate write interpretation < snippet.yaml +# or, piping inline: +printf 'substrate:\n values:\n foo:\n add: [a, b]\n' \ + | substrate write interpretation specs/foo.md overview +``` + +What it does: + +- Reads pure substrate YAML from **stdin** (no temp file required). +- Validates it through the same parser the dev UI uses. Both YAML + syntax errors and substrate language errors (`unknown expression + shape`, wrong arity, missing required key, …) abort the write with + exit code 1 and print every diagnostic to stderr. Warnings are + printed but do not abort. +- Stamps a fresh `last-interpreted-at` ISO-8601 timestamp under the + `substrate:` mapping in the YAML text. If the input already contains + a `last-interpreted-at`, it is overwritten — never carry one through + from a previous snippet, the CLI owns that field. +- Aligns the markdown file's mtime with the stamped timestamp so the + dev viewer's freshness check reads "up to date" immediately after the + write. +- Locates `` by slugifying every ATX heading in the file (GFM + rules) and matching against the argument. A leading `#` is + tolerated. +- Within that section, replaces an existing ` ```yaml ` fenced block + whose first content line begins with `substrate:`. If no such block + exists, appends a new fenced block as the section's last piece of + content. + +The command touches only ``; cross-document links and vendored +packages are untouched. Pair it with the dev viewer (`substrate dev`) +to see the rendered interpretation immediately after writing. + +## Package commands + +### `substrate init` + +Scaffolds a new Substrate package in the current directory. Prompts for +name, kind (`corpus` / `library` / `horizontal`), and version. Writes +`substrate.json` and creates `substrate/`. Pass `-y` / `--yes` to +accept all defaults. + +Aborts without writing anything if `substrate.json` already exists. + +`substrate init` also drops AI-assistant instructions into the project — +this skill at `.claude/skills/substrate-cli/SKILL.md` and a GitHub Copilot +equivalent at `.github/instructions/substrate-cli.instructions.md` — so +that any LLM working in the project knows about the CLI. + +### `substrate install` + +Resolves every dependency in `substrate.json` and vendors it under +`substrate/`. Writes (or honours) `substrate-lock.json`. Idempotent. + +Pass `-f` / `--force` to reinstall every dependency even when the +lockfile says it is already present and intact — useful after local +edits to vendored content or an interrupted install. + +Running `substrate install` also refreshes the bundled AI-assistant +instructions in the project (`.claude/skills/substrate-cli/SKILL.md` and +`.github/instructions/substrate-cli.instructions.md`). Treat those files +as **managed by the CLI** — they are overwritten on every install. If a +user has hand-edited them, save their changes elsewhere or rename the +file before running `install`. + +### `substrate update [package]` + +Re-resolves one dependency (or every dependency) against the latest +matching git tag, updates `substrate-lock.json`, and refreshes the vendored +tree. + +### `substrate publish` + +Tags the current `package.version` and pushes the tag. Refuses to +publish a `corpus`. Refuses to publish a dirty working tree. Runs +`validate` first and aborts on any failure. + +## Conventions when you generate substrate commands + +- Always use **forward slashes** in paths, even on Windows — the CLI is + cross-platform and accepts them everywhere. +- Anchors use **GFM slug rules**: lowercase, alphanumerics and hyphens + only, sequences of other characters collapsed to a single hyphen, + duplicates within a file get `-2`, `-3`, … suffixes. +- The CLI mutates the working tree. Confirm with the user before + running anything that mutates more than one file (refactors, install, + update, publish) unless the user has already approved it. +- When a refactor errors, **do not fall back to a manual fix**. + Surface the error to the user — the precondition (collision, identical + anchor, missing section) is something the user should resolve, and + hand-editing risks leaving the corpus in a half-renamed state. +- After any hand-edit you make to markdown, run `substrate validate` + before reporting the task complete. diff --git a/substrate/assets/ai-instructions/claude/substrate-interpretation/SKILL.md b/substrate/assets/ai-instructions/claude/substrate-interpretation/SKILL.md new file mode 100644 index 000000000..3d7fb1796 --- /dev/null +++ b/substrate/assets/ai-instructions/claude/substrate-interpretation/SKILL.md @@ -0,0 +1,325 @@ +--- +name: substrate-interpretation +description: Annotate a Substrate markdown document with executable `substrate:` YAML blocks so the Substrate dev UI's interpretation view can render it. Trigger whenever the user wants to interpret, annotate, or "add YAML" to a markdown file, asks for a substrate AST from prose, or says things like "make this interpretable", "fill in the YAML", "produce the substrate interpretation". +--- + +# Substrate interpretation + +Substrate documents are plain markdown. The **interpretation view** in +the `substrate dev` UI renders a typed AST (types and values) side-by-side +with the prose, but only if the document carries fenced `substrate:` YAML +blocks. This skill is how you produce those blocks from prose. + +## When to reach for this skill + +Use it when the user: + +- Hands you a markdown file (or section) and asks you to **interpret**, + **annotate**, **add YAML**, **make it executable**, or **make it show + up in the interpretation view**. +- Wants the prose-driven substrate AST (types + values) reverse-engineered + from a narrative description. +- Asks for a "substrate YAML" block, a "one-of", a `match`, an `if/then/else`, + or any operator expression derived from English. + +Do **not** invent prose. Only emit YAML that is grounded in what the +markdown already says. The whole point of the `src:` keys is to prove +every node in the AST traces back to a literal phrase in the prose. + +## The output contract + +For each markdown section that contains domain meaning (a type +enumeration, a rule, a formula, a piece of decision logic), append a +fenced YAML block of the form: + +````markdown +```yaml +substrate: + types: { ... } + values: { ... } +``` +```` + +Rules: + +1. **One file, possibly many blocks.** Put each block in the section + whose prose it interprets. The dev UI concatenates blocks per file. +2. **Don't restate the prose.** Leave the markdown text intact. The YAML + block is added *after* the prose it interprets. +3. **Cover what makes sense.** Sections that are pure narrative, history, + or motivation typically have no YAML. Sections that enumerate cases, + define a calculation, or describe a decision rule do. +4. **Every node carries `src:`.** Extract as much `src` information as + possible. The `src` value is an **exact substring of the prose** — + not a paraphrase. Prefer the shortest phrase that uniquely supports + the node. A node may have a single string `src:` or a YAML sequence + of strings when more than one phrase supports it. +5. **Names are kebab-case identifiers.** Type names, value names, and + variant tags use `^[A-Za-z_][A-Za-z0-9_-]*$`. Variable references + (parameters, fields the prose mentions) are bare identifiers; string + data is quoted. + +## Canonical example + +The following short document exercises every construct in one piece — +a `one-of` type, a `match` over its variants, nested `if` / operator +expressions, numeric literals, variable references, and `src:` anchors +at every level. Study it before writing your first block. + +````markdown +# Trade Auto-Approval Risk Logic + +## Overview + +We need to build some basic logic for auto-approving trades based on +the type of asset being traded. For now, we're dealing with equities, +bonds, and derivatives. Each type has a different risk profile, so the +approval logic should reflect that. Equities should be auto-approved +if their risk score is under 0.5. Bonds are more conservative, so only +auto-approve if the risk score is under 0.3. For derivatives, we want +to auto-approve only if the notional is under one million and the +leverage is less than 2. + +```yaml +substrate: + types: + asset: + one-of: + - tag: equity + src: "equities" + - tag: bond + src: "bonds" + - tag: derivative + src: "derivatives" + src: "type of asset" + values: + auto-approve: + match: + on: asset + cases: + - when: equity + then: + - if: + less-than: + - risk_score + - 0.5 + src: "risk score is under 0.5." + then: true + else: false + src: "Equities should be auto-approved if their risk score is under 0.5." + - when: bond + then: + - if: + less-than: + - risk_score + - 0.3 + src: "risk score is under 0.3." + then: true + else: false + src: "Bonds are more conservative, so only auto-approve if the risk score is under 0.3." + - when: derivative + then: + - if: + all-of: + - less-than: + - notional + - 1,000,000 + - less-than: + - leverage + - 2 + src: "notional is under one million and the leverage is less than 2" + then: true + else: false + src: "For derivatives, we want to auto-approve only if the notional is under one million and the leverage is less than 2." + src: "Each type has a different risk profile" +``` +```` + +Notice how every variant, every comparison, and every case carries its +own `src:` quoting the exact phrase from the prose above. + +## The YAML shape + +### Module skeleton + +```yaml +substrate: + types: + : + values: + : + src: "phrase that justifies the module / section as a whole" +``` + +`src:` is optional at every level but should be filled in wherever a +phrase in the prose justifies the node. + +### Type definitions — `one-of` + +The only supported type kind is `one-of` (a tagged union / enum): + +```yaml +types: + asset: + one-of: + - tag: equity + src: "equities" + - tag: bond + src: "bonds" + - tag: derivative + src: "derivatives" + src: "type of asset" +``` + +A bare-string variant (`- equity`) is shorthand for `{ tag: equity }`. +Prefer the mapping form so each variant carries its own `src:`. + +### Value definitions + +A zero-parameter value is just an expression: + +```yaml +values: + auto-approve: + match: + on: asset + cases: + - when: equity + then: true +``` + +A value with parameters uses the explicit form: + +```yaml +values: + area: + params: [width, height] + body: + multiply: [width, height] + src: "area is width times height" +``` + +### Expressions + +A `ValueExpression` is one of: + +- **Literal**: a bare scalar (`true`, `0.5`, `"hello"`, `null`). Numbers + with thousands separators are accepted (`1,000,000`). For ambiguity-free + intent, use the explicit `lit:` form: `lit: 0.5`. +- **Variable**: an unquoted identifier matching + `^[A-Za-z_][A-Za-z0-9_-]*$` is a variable reference (e.g. a parameter + or a field name the prose mentions like `risk_score`, `notional`, + `leverage`). Quoted strings are **always** string literals. The + explicit form is `var: name`. +- **If**: a mapping with `if`, `then`, `else`. + ```yaml + if: + less-than: [risk_score, 0.5] + src: "risk score is under 0.5" + then: true + else: false + ``` +- **Match**: a mapping with `match: { on, cases: [{ when, then }] }`. +- **Apply**: one operator key per expression. + +### Operators + +Operators are a closed, discriminated set. Use only these keys: + +- **Binary** (sequence of two operands, or `{ left, right }`): + `equals`, `not-equals`, `less-than`, `less-than-or-equal`, + `greater-than`, `greater-than-or-equal`, `add`, `subtract`, + `multiply`, `divide`, `contains`, `starts-with`, `ends-with`. +- **Unary** (single operand): `not`. +- **N-ary** (sequence of operands): `and`, `or`, `concat`. + +Aliases the parser also accepts: `all-of` → `and`, `any-of` → `or`, +`eq`, `neq`, `lt`, `lte`, `gt`, `gte`. Prefer the long, English forms +(`and`, `less-than`) — they read better next to the prose. + +Examples: + +```yaml +equals: [status, "approved"] + +all-of: + - less-than: [notional, 1,000,000] + - less-than: [leverage, 2] + +not: + equals: [side, "sell"] +``` + +## Extracting `src` — the heart of the skill + +`src` is what makes interpretation valuable. The viewer renders each +`src` entry as a hover-linked anchor between the visual element and the +prose span, so every node should point to the prose that justifies it. + +When deciding what `src` to attach: + +- **Use a literal substring of the prose.** Do not rephrase. If the + prose says "risk score is under 0.5.", the `src` is + `"risk score is under 0.5."` — keep the trailing period or omit it + consistently, but never invent words. +- **Anchor at the right level.** The `src` on a `match` case is the + full sentence describing that case. The `src` on the inner condition + is just the predicate clause inside that sentence. +- **Attach multiple anchors when prose supports a node from several + places.** Use a sequence: + ```yaml + src: + - "first supporting phrase" + - "second supporting phrase" + ``` +- **Anchor variants too.** Each `one-of` variant should carry the + noun the prose used: `equities`, `bonds`, `derivatives`. +- **Anchor literal thresholds.** When the prose says "under one million", + attach that phrase to the `less-than` apply, not just to the + enclosing case. + +If a node has no supporting prose, omit `src:` for that node rather than +faking one. A missing `src` is honest; a wrong `src` is misleading. + +## Workflow + +When the user points you at a markdown file: + +1. **Read the file end to end first.** Build a mental model of what + types and values it implies before writing any YAML. +2. **Identify the type enumerations.** Phrases like "we deal with X, Y, + and Z", "there are three kinds of …", "the status can be …" become + `one-of` types. +3. **Identify the rules / formulas / decisions.** Each becomes a value + definition. Decision-by-case (per type variant) becomes a `match`. + Threshold rules become `if` / operator chains. +4. **Pick names that match the prose.** If the prose says + "auto-approve", the value is `auto-approve`. If a field is referred + to as "risk score", use `risk_score` (or `risk-score`) consistently. +5. **Draft the YAML block(s).** One block per markdown section that + carries meaning. Place each block at the end of its section. +6. **Walk back over every node and attach `src:` from the prose.** This + is not an afterthought — it is the deliverable. If you can't find a + phrase to support a node, ask whether the node should exist. +7. **Sanity-check operator arity.** Binary ops want exactly two + operands; `not` wants one; `and` / `or` / `concat` want a sequence. +8. **Verify in the dev UI when possible.** The `substrate dev` command + boots the interpretation view; its diagnostics panel will surface any + structural mistakes. The parser never throws — broken blocks degrade + gracefully, but you should still resolve diagnostics before declaring + done. + +## Anti-patterns + +- Inventing fields or variants the prose doesn't mention. +- Using `src:` to *describe* the node ("the equity case") instead of + quoting the prose. +- Wrapping everything in a single giant `and:` instead of letting the + `match` / `if` structure mirror the prose. +- Quoting bare identifiers (`"risk_score"`) — that makes them string + literals, not variable references. +- Using operators not in the closed set above. There is no `between`, + no `in`, no `length`. Express them with the primitives (`and` of two + comparisons; `or` of `equals`; etc.). +- Skipping `src:` because "the structure is obvious". The whole point + of interpretation is the anchored link back to prose. diff --git a/substrate/assets/ai-instructions/claude/ts-horizontal-regen/SKILL.md b/substrate/assets/ai-instructions/claude/ts-horizontal-regen/SKILL.md new file mode 100644 index 000000000..668d1bd8f --- /dev/null +++ b/substrate/assets/ai-instructions/claude/ts-horizontal-regen/SKILL.md @@ -0,0 +1,131 @@ +--- +name: ts-horizontal-regen +description: Regenerate src/language/expressions/*.ts from the TypeScript horizontal package at horizontals/typescript/. Run when a spec operation is added, renamed, or its signature changes. Trigger on "regenerate the TypeScript evaluators", "regen from horizontal", or any mention of re-running the TS horizontal. +--- + +# TypeScript Horizontal Regeneration + +This skill regenerates the TypeScript evaluator modules under +`src/language/expressions/` from the horizontal package at +`horizontals/typescript/`. Every generated file is gated by +`substrate verify` — if verification fails, the skill stops and +surfaces the failures for you to resolve. + +## When to use + +- A new operation has been added to a spec file and a corresponding + lambda has been added to `horizontals/typescript/expressions/.md`. +- An existing lambda has been corrected in the horizontal. +- You want to cut `src/language/expressions/` over to generated output + for the first time. + +Do **not** edit `src/language/expressions/*.ts` by hand after cutover — +those files are generated artifacts. Edit the horizontal instead, then +re-run this skill. + +## Workflow + +### 1. Compose the spec + horizontal for each module + +For each expression module that has a horizontal counterpart, run: + +```bash +node dist/cli.js context specs/language/expressions/.md \ + --horizontal horizontals/typescript/ +``` + +This produces a self-contained markdown document that interleaves the +spec's operation signatures with the horizontal's TypeScript snippets, +with all cross-file links rewritten as in-document anchors. + +### 2. Extract operations and lambdas + +Read the composed output. For each operation: + +- **Anchor** (registry key): derived from the spec heading slug, + e.g. `not-operation`, `and-operation`. +- **Inputs**: the parameter names and count from the `#### Inputs` list + in the spec — these determine `arity` and the lambda's argument names. +- **Lambda**: the TypeScript snippet from the horizontal, a typed + arrow function whose parameters match the spec's input names exactly. + +### 3. Regenerate the TypeScript module + +Write `src/language/expressions/.ts` with this shape: + +```typescript +/** + * expressions — generated from horizontals/typescript/expressions/.md + * DO NOT EDIT — regenerate with the ts-horizontal-regen skill. + */ +import type { Value } from "../ast.js"; +import type { OperationEvaluator } from "./index.js"; + +export const modulePath = "expressions/.md"; + +export const operations: ReadonlyMap = new Map([ + [ + "", + { + arity: , + evaluate: (args) => { + const lambda = ; + return lambda(args[0] as , args[1] as , ...) as Value; + }, + }, + ], + // … one entry per operation +]); +``` + +Keep the lambda on a single line when it fits; use a block body when the +lambda spans multiple lines (e.g. the `date` module). + +Also regenerate `src/language/expressions/index.ts` to import every +module that exposes `operations` and call `registerModule` for each. + +### 4. Verify + +```bash +npm run build && node dist/cli.js verify specs/language/expressions/ --quiet +``` + +If any file reports errors in the `test` stage, the regenerated lambdas +do not match the spec's truth tables. Stop, report the failures, and do +not commit. The developer must correct either the horizontal lambda or +the spec test case before proceeding. + +If all files pass, the regeneration is complete. + +### 5. Per-operation targeting (optional) + +To regenerate a single operation during horizontal development: + +```bash +node dist/cli.js context \ + specs/language/expressions/boolean.md#not-operation \ + --horizontal horizontals/typescript/ +``` + +Read the composed output for just that operation and update only its +entry in the corresponding `.ts` file, then re-verify. + +## Files involved + +| Path | Role | +| ---- | ---- | +| `horizontals/typescript/substrate.json` | Horizontal package manifest | +| `horizontals/typescript/expressions/*.md` | One file per expression module; carries TypeScript lambdas | +| `specs/language/expressions/*.md` | Spec source of truth; carries signatures and test cases | +| `src/language/expressions/*.ts` | Generated output — do not edit by hand | +| `src/language/expressions/index.ts` | Generated registry assembly — do not edit by hand | + +## Failure handling + +When `substrate verify` rejects the regenerated output: + +1. Show the failing test diagnostics to the developer. +2. Ask whether to correct the **horizontal** (wrong lambda) or the + **spec** (wrong test case). +3. After the correction, re-run from step 1 of this workflow. +4. Do not auto-retry — each attempt is a deliberate act. diff --git a/substrate/assets/ai-instructions/copilot/substrate-cli.instructions.md b/substrate/assets/ai-instructions/copilot/substrate-cli.instructions.md new file mode 100644 index 000000000..45e9aebac --- /dev/null +++ b/substrate/assets/ai-instructions/copilot/substrate-cli.instructions.md @@ -0,0 +1,135 @@ +--- +applyTo: "**/*.md,**/substrate.json,**/substrate-lock.json" +description: "How to use the substrate CLI to manage and refactor the markdown corpus in a Substrate package." +--- + +# Substrate CLI — instructions for GitHub Copilot + +This project is a [Substrate](https://github.com/AttilaMihaly/morphir/tree/substrate) +corpus: a directory of plain markdown files linked together as a semantic +knowledge graph, rooted at the nearest `substrate.json`. The `substrate` +CLI manages, validates, and refactors that corpus. + +**Never edit cross-document links by hand.** Whenever a file or heading +moves, use `substrate refactor rename` so every reference in the project is +updated atomically. + +## Refactoring (most important) + +`substrate refactor rename ` performs one of three operations +based on the shape of its arguments. Use this command in place of `mv`, +`git mv`, or hand-edits whenever a `.md` file or heading moves. + +| From shape | To shape | Operation | +| --- | --- | --- | +| `path/file.md` | `path/file.md` | Rename a file on disk and rewrite every link to it. | +| `file.md#old` | `file.md#new` | Rename a heading and rewrite every `#anchor` reference. | +| `a.md#section` | `b.md` | Move section to `b.md`; opens an interactive picker for insertion point. | +| `a.md#section` | `b.md#parent` | Move section to `b.md`, inserted after the `#parent` subtree. | + +Examples: + +```bash +substrate refactor rename specs/old-name.md specs/new-name.md +substrate refactor rename specs/foo.md#old-anchor specs/foo.md#new-anchor +substrate refactor rename specs/a.md#my-section specs/b.md#parent +``` + +The new heading text for a rename is derived from the anchor slug — +hyphens become spaces and the first letter is capitalised +(`my-new-section` becomes the heading `My new section`). If the user +gives you the heading text, slugify it first. + +**Anchor collisions and identical-slug renames error before any change +is made**; surface the error rather than retrying with hand-edits. + +**The interactive picker requires a TTY.** When invoking from automation +or CI, always pass an explicit `#parent` anchor in the destination. + +There are no commands for splitting, merging, or renaming directories; +do those manually and then run `substrate validate`. + +## Validation and context + +| Command | Purpose | +| --- | --- | +| `substrate validate` | Walk every `.md` in the corpus and report unresolved links. Run after any hand-edit. | +| `substrate verify ` | Full pipeline: parse → include → lint → references → typecheck → test. Heavier than `validate`. | +| `substrate context [#section] ...` | Emit a tree-shaken, self-contained markdown slice to stdout — for feeding into an LLM. | +| `substrate stats [file]` | Word count, line count, token estimate, link breakdown, heading depths. Reads stdin when no file. | + +Useful `substrate context` flags: + +- `--no-tree-shaking` — include each referenced file in full, but still rewrite cross-file links to in-document anchors. +- `--no-inline` — do not follow links at all; emit only the explicit roots. +- `--horizontal ` — pull in matching sections from a horizontal package via reverse traversal. Repeatable. + +If a file has a `#summary` section, asking for the whole file is silently +rewritten to that summary. Author `#summary` deliberately for compact +slices. + +## Packages + +| Command | Purpose | +| --- | --- | +| `substrate init` | Scaffold a new package: prompts for name, kind, version. Pass `-y` for defaults. Also drops these AI instructions into the project. | +| `substrate install` | Resolve and vendor every dependency under `substrate/`. Writes `substrate-lock.json`. Also refreshes these AI instructions. Idempotent. Pass `-f` / `--force` to reinstall everything even if already present per the lockfile. | +| `substrate update [pkg]` | Re-resolve one or every dependency against the latest matching git tag. | +| `substrate publish` | Tag and push a library/horizontal release. Refuses on dirty trees or `kind: corpus`. | + +The contents of `.github/instructions/substrate-cli.instructions.md` and +`.claude/skills/substrate-cli/SKILL.md` are **managed by `substrate +install`** — they are overwritten on every install. Do not hand-edit +them; if you need a customisation, copy them to a different filename. + +## Writing substrate interpretations into markdown + +`substrate write interpretation ` reads pure substrate +YAML from stdin and splices it into the named section of ``. Use +this instead of hand-editing fenced code blocks whenever an LLM +produces a new or updated interpretation for a section. + +```bash +substrate write interpretation specs/foo.md overview < snippet.yaml +``` + +Behaviour: + +- The YAML is validated through the same parser the dev viewer uses; + YAML syntax errors and substrate language errors both abort the + write with a non-zero exit code. +- A fresh `last-interpreted-at` ISO-8601 timestamp is stamped under + `substrate:` (overwriting any value the caller supplied), and the + file's mtime is aligned with it so the dev viewer reads "up to date". +- If the target section already contains a ` ```yaml ` block whose + first content line is `substrate:`, it is replaced in place; + otherwise a new fenced block is appended as the section's last + piece of content. +- `` is a GFM heading slug — the same form used in cross-document + link fragments. A leading `#` is tolerated. + +## Local dev UI + +`substrate dev` starts a local web UI that browses every `.md` file under +a directory and auto-reloads on disk changes. Run it from the corpus root +when the user wants to "see" their markdown in a browser. + +```bash +substrate dev # serve the current directory +substrate dev --dir specs # serve a specific directory +substrate dev --port 4000 # pin the port +``` + +The command prints the URL on standard out so it is ctrl/cmd-clickable. +It binds to `127.0.0.1` by default; do not bind elsewhere on untrusted +networks — the server is unauthenticated. + +## Conventions for generated commands + +- Always use forward slashes in paths, even on Windows. +- Anchors follow GFM slug rules: lowercase, alphanumerics and hyphens, + duplicates within one file get `-2`, `-3`, … suffixes. +- The CLI mutates the working tree. Confirm before running a refactor, + install, update, or publish unless the user has pre-approved it. +- After any hand-edit you make to a markdown file, run `substrate + validate` before reporting the task complete. diff --git a/substrate/assets/ai-instructions/copilot/substrate-interpretation.instructions.md b/substrate/assets/ai-instructions/copilot/substrate-interpretation.instructions.md new file mode 100644 index 000000000..b1d836e63 --- /dev/null +++ b/substrate/assets/ai-instructions/copilot/substrate-interpretation.instructions.md @@ -0,0 +1,195 @@ +--- +applyTo: "**/*.md" +description: "How to annotate Substrate markdown documents with `substrate:` YAML blocks so the interpretation view can render them." +--- + +# Substrate interpretation — instructions for GitHub Copilot + +Substrate markdown documents become executable when each meaningful +section carries a fenced `substrate:` YAML block describing its types +and values. This file tells you how to produce those blocks from prose. + +## When to add YAML + +Add a `substrate:` YAML block to a markdown section when the prose +contains domain meaning the interpretation view should render: + +- type enumerations ("we handle equities, bonds, and derivatives"), +- rules / formulas ("approve if the risk score is under 0.5"), +- decision logic that branches on a type variant or a predicate. + +Skip narrative, history, motivation, and meta sections. One markdown +file may carry several `substrate:` blocks — one per meaningful section. + +Never edit or rephrase the prose to fit the YAML. The prose is the +source of truth; the YAML is its interpretation. + +## Block shape + +````markdown +```yaml +substrate: + types: + : + one-of: + - tag: + src: "" + src: "" + values: + : + # either an inline expression… + match: + on: + cases: + - when: + then: + src: "" + # …or the explicit form with params + body + params: [a, b] + body: + multiply: [a, b] + src: "" + src: "" +``` +```` + +### Expressions + +- **Literal**: a bare scalar (`true`, `0.5`, `"hello"`, `null`). Use + `lit: ` when you need to be explicit. Numbers may use thousands + separators (`1,000,000`). +- **Variable**: unquoted identifier (`risk_score`, `notional`). Quoted + strings are always string literals — never quote a variable. Explicit + form: `var: name`. +- **If**: `{ if: , then: , else: }`. +- **Match**: `{ match: { on: , cases: [{ when, then }] } }`. + +### Operators (closed set) + +- Binary (`[left, right]` or `{ left, right }`): `equals`, `not-equals`, + `less-than`, `less-than-or-equal`, `greater-than`, + `greater-than-or-equal`, `add`, `subtract`, `multiply`, `divide`, + `contains`, `starts-with`, `ends-with`. +- Unary (single operand): `not`. +- N-ary (sequence of operands): `and`, `or`, `concat`. + +Aliases also accepted: `all-of` → `and`, `any-of` → `or`, `eq`, `neq`, +`lt`, `lte`, `gt`, `gte`. Prefer the long forms; they read better. + +There is no `between`, `in`, `length`, etc. Compose with the primitives. + +## `src:` — extract every phrase you can + +The `src` field is the deliverable, not an afterthought. The interpretation +viewer renders each `src` entry as a hover-linked anchor between the AST +node and the prose. Every node should have one when prose supports it. + +- The value of `src` must be an **exact substring of the prose** — never + a paraphrase. Either a single string or a YAML sequence of strings. +- Anchor at the right level: the `match` case carries the full sentence + for that case; the inner predicate carries just the predicate clause. +- Variants carry the noun the prose used (`"equities"`, `"bonds"`). +- Literal thresholds carry the phrase that names them + (`"under one million"`). +- If no phrase supports a node, omit `src:`. Do not invent one. + +## Names + +Type names, value names, and variant tags use kebab-case identifiers +matching `^[A-Za-z_][A-Za-z0-9_-]*$`. Pick names that mirror the prose +(`auto-approve`, `risk_score`, `asset`). + +## Anti-patterns + +- Inventing variants or fields the prose doesn't mention. +- Using `src:` to describe the node instead of quoting the prose. +- Quoting a variable reference (turns it into a string literal). +- Replacing `match` / `if` structure with one giant `and:`. +- Using operators outside the closed set. +- Omitting `src:` because "the structure is obvious". + +## Canonical example + +The following short document exercises every construct in one piece — +a `one-of` type, a `match` over its variants, nested `if` / operator +expressions, numeric literals, variable references, and `src:` anchors +at every level. + +````markdown +# Trade Auto-Approval Risk Logic + +## Overview + +We need to build some basic logic for auto-approving trades based on +the type of asset being traded. For now, we're dealing with equities, +bonds, and derivatives. Each type has a different risk profile, so the +approval logic should reflect that. Equities should be auto-approved +if their risk score is under 0.5. Bonds are more conservative, so only +auto-approve if the risk score is under 0.3. For derivatives, we want +to auto-approve only if the notional is under one million and the +leverage is less than 2. + +```yaml +substrate: + types: + asset: + one-of: + - tag: equity + src: "equities" + - tag: bond + src: "bonds" + - tag: derivative + src: "derivatives" + src: "type of asset" + values: + auto-approve: + match: + on: asset + cases: + - when: equity + then: + - if: + less-than: + - risk_score + - 0.5 + src: "risk score is under 0.5." + then: true + else: false + src: "Equities should be auto-approved if their risk score is under 0.5." + - when: bond + then: + - if: + less-than: + - risk_score + - 0.3 + src: "risk score is under 0.3." + then: true + else: false + src: "Bonds are more conservative, so only auto-approve if the risk score is under 0.3." + - when: derivative + then: + - if: + all-of: + - less-than: + - notional + - 1,000,000 + - less-than: + - leverage + - 2 + src: "notional is under one million and the leverage is less than 2" + then: true + else: false + src: "For derivatives, we want to auto-approve only if the notional is under one million and the leverage is less than 2." + src: "Each type has a different risk profile" +``` +```` + +Notice how every variant, every comparison, and every case carries its +own `src:` quoting the exact phrase from the prose above. + +## Validating + +The `substrate dev` command boots the interpretation view; its +diagnostics panel flags structural problems. The parser never throws — +a broken block degrades gracefully — but resolve every diagnostic +before declaring the file done. diff --git a/substrate/assets/ai-instructions/copilot/ts-horizontal-regen.instructions.md b/substrate/assets/ai-instructions/copilot/ts-horizontal-regen.instructions.md new file mode 100644 index 000000000..f8438de13 --- /dev/null +++ b/substrate/assets/ai-instructions/copilot/ts-horizontal-regen.instructions.md @@ -0,0 +1,21 @@ +--- +applyTo: "horizontals/typescript/**,src/language/expressions/**" +--- + +# TypeScript Horizontal Regeneration + +The files under `src/language/expressions/` are **generated** from the horizontal +package at `horizontals/typescript/`. Do not edit them directly. + +To regenerate after changing a horizontal lambda or adding a new operation: + +1. `node dist/cli.js context specs/language/expressions/.md --horizontal horizontals/typescript/` +2. Read the composed output; extract each operation's anchor, arity, and TypeScript lambda. +3. Rewrite `src/language/expressions/.ts` using the template in + `assets/ai-instructions/claude/ts-horizontal-regen/SKILL.md`. +4. `npm run build && node dist/cli.js verify specs/language/expressions/ --quiet` +5. If any test-stage errors appear, fix the lambda or the spec before committing. + +The horizontal file format: each `## [OperationName](spec-anchor)` section contains +a fenced `ts` block with a typed arrow function whose parameters match the spec's +`#### Inputs` parameter names exactly. diff --git a/substrate/assets/web/logo.svg b/substrate/assets/web/logo.svg new file mode 100644 index 000000000..27ae7d89e --- /dev/null +++ b/substrate/assets/web/logo.svg @@ -0,0 +1,16 @@ + + Morphir Substrate + + + + + diff --git a/substrate/branding/design-system.md b/substrate/branding/design-system.md new file mode 100644 index 000000000..fe7dcb4e5 --- /dev/null +++ b/substrate/branding/design-system.md @@ -0,0 +1,149 @@ +# Morphir Substrate Design System + +This is the canonical design system for Morphir Substrate. It is the source of truth for the docs site, the spec editor, and any other surface that needs to look and feel like Substrate. + +For geometric construction details (lattice math, logo coordinates), see [`style.md`](./style.md). This document focuses on tokens, usage, and rationale. + +--- + +## Brand palette + +Substrate uses a three-color brand palette: two bright signal colors inherited from the Morphir / FINOS family, plus one deep neutral used for type and UI chrome. + +| Token | Role | Hex | Notes | +| ------------------ | ---------------------------- | ---------- | ----------------------------------------------------------- | +| `--brand-blue` | Primary signal | `#16A2DC` | Logo stroke. Links, primary actions, focus rings. | +| `--brand-orange` | Secondary signal | `#F26A21` | Logo stroke. Accents, highlights, callouts. | +| `--brand-slate` | Tertiary (ink / neutral) | `#2C4A5A` | Body text, headings, UI chrome, dark surfaces. | + +### Why Deep Slate `#2C4A5A` as the third color + +The brand signals are a complementary pair — orange (≈20°) and cyan-blue (≈197°) sit almost opposite on the color wheel, which makes them loud together. A saturated third hue would fight them. Deep Slate is chosen for three reasons: + +1. **Analogous to the brand blue, but muted.** `#2C4A5A` sits near hue 204°, within a few degrees of `#16A2DC`, so it reads as part of the same family. But its saturation is ~35% (vs. 82% for the brand blue) and its lightness is ~26% (vs. ~48%), so it recedes to a neutral. +2. **It stays out of the way.** Because it is desaturated and dark, it reads as "ink" rather than as a third accent, which keeps the orange ↔ blue brand signals doing the visual work. +3. **It replaces a pine green.** The earlier tertiary was `#2F4738` (pine). The green cast clashed with the orange signal (orange + green = muddy). A cool slate keeps the palette in the blue–orange complementary axis and feels crisper. + +Alternatives considered: navy (too blue, competes with the brand blue), teal (too close to brand blue in hue and saturation), graphite (too neutral, loses warmth). + +### Supporting neutrals and surfaces + +| Token | Value | Use | +| ------------------ | ---------------------------------- | --------------------------------------------- | +| `--surface-1` | `#F7F9FB` | Page background (light mode). | +| `--surface-2` | `#EEF2F6` | Cards, elevated panels. | +| `--surface-inverse`| `#1A2A34` | Dark-mode page background (slate, deepened). | +| `--ink` | `#2C4A5A` | Default text on light surfaces. | +| `--ink-muted` | `rgba(44, 74, 90, 0.70)` | Secondary text, captions. | +| `--ink-subtle` | `rgba(44, 74, 90, 0.45)` | Tertiary text, placeholders. | +| `--rule` | `rgba(44, 74, 90, 0.14)` | Hairlines, dividers, input borders. | + +### Functional tints + +Derived from the tertiary, used sparingly. + +| Token | Value | Use | +| ------------------ | ---------------------------------- | --------------------------------------------- | +| `--link` | `#16A2DC` | Links on light surfaces. | +| `--link-hover` | `#0E87B8` | Hover / active link. | +| `--accent` | `#F26A21` | Highlights, badges, focus accents. | +| `--accent-hover` | `#D9571A` | Hover state on orange accents. | + +--- + +## Typography + +Substrate is an **LLM-native executable specification language** — the product is text. Type choices favor long-form reading and code legibility. + +| Role | Family | Notes | +| ----------- | ---------------------------------------------------------------------------------------- | ---------------------------------------------------- | +| UI / body | `"Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif` | Primary UI and prose font. | +| Display | Same as body, heavier weights (600–700) | No separate display face — one family, many weights. | +| Mono / code | `"JetBrains Mono", "Fira Code", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace`| Code blocks, spec editor. | + +### Type scale (1.250 – major third) + +| Token | Size | Line-height | Use | +| ------------- | --------- | ----------- | --------------------------- | +| `--step--1` | `0.833rem`| `1.5` | Captions, fine print. | +| `--step-0` | `1rem` | `1.6` | Body. | +| `--step-1` | `1.25rem` | `1.5` | Lead, subheads. | +| `--step-2` | `1.563rem`| `1.35` | H3. | +| `--step-3` | `1.953rem`| `1.25` | H2. | +| `--step-4` | `2.441rem`| `1.2` | H1. | +| `--step-5` | `3.052rem`| `1.1` | Hero display. | + +--- + +## Spacing + +8-pt base with a T-shirt scale. + +| Token | Value | +| ----------- | ------ | +| `--space-1` | `4px` | +| `--space-2` | `8px` | +| `--space-3` | `12px` | +| `--space-4` | `16px` | +| `--space-5` | `24px` | +| `--space-6` | `32px` | +| `--space-7` | `48px` | +| `--space-8` | `64px` | +| `--space-9` | `96px` | + +## Radii + +| Token | Value | Use | +| --------------- | ------- | -------------------- | +| `--radius-sm` | `4px` | Inputs, small chips. | +| `--radius-md` | `8px` | Cards, buttons. | +| `--radius-lg` | `12px` | Panels, modals. | +| `--radius-pill` | `999px` | Pills, tags. | + +## Elevation + +Elevation is kept minimal — rely on the rule color and surface shifts rather than drop shadows. + +| Token | Value | +| --------------- | --------------------------------------------- | +| `--shadow-1` | `0 1px 2px rgba(44, 74, 90, 0.06)` | +| `--shadow-2` | `0 4px 12px rgba(44, 74, 90, 0.08)` | +| `--shadow-focus`| `0 0 0 3px rgba(22, 162, 220, 0.35)` | + +--- + +## Logo + +The canonical mark is defined in [`style.md` § Logo](./style.md#logo) and rendered in [`logo.html`](./logo.html). See [`logo.svg`](./logo.svg) for the production asset, and [`wordmark.svg`](./wordmark.svg) for the horizontal lockup used in the docs site header. + +### Alignment rules + +- The mark's **geometric bounding box is centered on its own origin** in `logo.svg` (the polylines are shifted so the bbox midpoint is `(0, 0)`). Any container that centers the SVG will visually center the mark — no manual nudging required. +- In horizontal lockups, the wordmark **"substrate"** sits to the right of the mark with its **cap-height midline aligned to the mark's vertical center**. Use `display: flex; align-items: center;` with the wordmark rendered as SVG text with `dominant-baseline="central"` anchored at the mark's y-midpoint. +- Minimum clear space around the mark is `0.5 · s` on all sides (where `s` is the lattice spacing at the logo's render size). + +### Wordmark + +| Property | Value | +| --------------- | ------------------------------------------------ | +| Family | `Inter` | +| Weight | `600` (Semibold) | +| Tracking | `-0.01em` | +| Case | lowercase "substrate" | +| Color | `--brand-slate` (`#2C4A5A`) on light surfaces | + +--- + +## Background — triangular lattice + +See [`style.md` § Triangular Lattice](./style.md#triangular-lattice-background-pattern) for geometry. Implementation notes for the docs site: + +- The lattice is rendered as a tinted overlay at **8–12% opacity** on hero sections only; body pages use plain `--surface-1` to maximize reading comfort. +- Dot and line colors use the slate tertiary: `rgba(44, 74, 90, 0.50)` (dots) and `rgba(44, 74, 90, 0.25)` (lines). +- Spacing `s = 40px` on screen; `s = 24px` for dense hero compositions. + +--- + +## Tokens file + +All of the tokens above are exported as CSS custom properties in [`tokens.css`](./tokens.css). Consumers (docs site, spec editor) should `@import` that file and reference the variables — never hard-code hex values outside of `tokens.css`. diff --git a/substrate/branding/logo.html b/substrate/branding/logo.html new file mode 100644 index 000000000..89b23d771 --- /dev/null +++ b/substrate/branding/logo.html @@ -0,0 +1,105 @@ + + + + + + + Morphir Substrate — Logo Construction Grid + + + + + + + +
4×4 triangular lattice — 25 nodes
+ + + + + \ No newline at end of file diff --git a/substrate/branding/logo.svg b/substrate/branding/logo.svg new file mode 100644 index 000000000..da07b4421 --- /dev/null +++ b/substrate/branding/logo.svg @@ -0,0 +1,25 @@ + + Morphir Substrate + + + + + + + + diff --git a/substrate/branding/style.html b/substrate/branding/style.html new file mode 100644 index 000000000..91a2adb4b --- /dev/null +++ b/substrate/branding/style.html @@ -0,0 +1,164 @@ + + + + + + + Morphir Substrate - Triangular Dot Background + + + + + + + +
Triangular tiling — dots at vertices
+ + + + + \ No newline at end of file diff --git a/substrate/branding/style.md b/substrate/branding/style.md new file mode 100644 index 000000000..83b7f14f5 --- /dev/null +++ b/substrate/branding/style.md @@ -0,0 +1,144 @@ +# Morphir Substrate Style Guide + +## Triangular Lattice Background Pattern + +### Overview + +The primary background texture is a **triangular tiling** (also called a _deltille_ or _A₂ lattice_). It is one of the three regular tilings of the Euclidean plane. Every interior vertex of the tiling is shared by exactly six equilateral triangles, giving each dot six equidistant neighbours at 60° intervals. + +This pattern is used as the structural background for pages, documentation, and presentation materials. It communicates geometric precision, regularity, and the crystalline structure that underlies the Morphir Substrate language model. + +--- + +### Geometry + +#### Lattice vectors + +The lattice is generated by two basis vectors of equal length **s** (the side length, or _spacing_) separated by 60°: + +```text +a₁ = s · (√3/2, ½) +a₂ = s · (0, 1) +``` + +Every vertex position **p** is an integer linear combination of these vectors: + +```text +p(m, n) = m·a₁ + n·a₂ where m, n ∈ ℤ +``` + +#### Column-based equivalent + +In screen coordinates the lattice is organised in vertical columns. Odd-numbered columns are shifted down by half a spacing: + +| Column parity | x position | y position | +| ---------------- | ---------------- | --------------- | +| Even (0, 2, 4 …) | `col · (s·√3/2)` | `row · s` | +| Odd (1, 3, 5 …) | `col · (s·√3/2)` | `row · s + s/2` | + +- **Horizontal spacing** between adjacent columns: `s · √3/2 ≈ 0.866 · s` +- **Vertical spacing** between adjacent dots in the same column: `s` +- **Distance between any two nearest-neighbour dots**: exactly `s` (equal for all six neighbours) + +This orientation places vertical lattice edges and produces hexagonal Voronoi cells that are pointy-top (vertex at top and bottom, flat sides left and right), matching the logo geometry. + +The current implementation uses **s = 40 px** at screen resolution. + +--- + +### Visual style + +| Property | Value | +| --------------- | ------------------------ | +| Dot radius | `2.5 px` | +| Dot colour | `rgba(47, 71, 56, 0.50)` | +| Line width | `0.8 px` | +| Line colour | `rgba(47, 71, 56, 0.25)` | +| Lattice spacing | `40 px` | + +- Lines are drawn **beneath** dots so that dot circles are never obscured at intersections. +- Line width is kept below dot diameter so the nodes read as primary and the edges as secondary. +- Opacity values ensure the pattern recedes behind foreground content without disappearing. + +--- + +### Usage guidance + +- Use the pattern as a **full-bleed background** on landing pages, section dividers, and cover slides. +- The pattern can be **tinted** by changing the dot and line colours to match a page's colour theme, while keeping the same opacity ratio (dots at 2× the opacity of lines). +- The lattice spacing (`s`) may be scaled to suit the medium: + - Screen backgrounds: `s = 40 px` + - Print / large-format: scale proportionally so the pattern remains perceptible but not dominant. +- The pattern tiles seamlessly; there is no minimum canvas size. + +--- + +## Logo + +### Overview + +The logo mark is composed of two thick, rounded polylines — one blue, one orange — each tracing four consecutive edges of a regular hexagon that is embedded in the triangular lattice. The two partial hexagons are offset from each other by one lattice step and together form an interlocking mark that reads as a single cohesive symbol. + +### Relationship to the triangular lattice + +The hexagons in the logo are the **Voronoi cells** of the A₂ lattice described in the background pattern section. Each hexagon has a **vertex at the top and bottom** and **flat vertical sides** — the pointy-top orientation. The logo traces two of those hexagons, one centred slightly above and one below, overlapping at the centre of the composition. + +Each edge of the polyline follows a lattice edge of length **s** (the same spacing constant used in the background pattern), so the logo scales uniformly with the pattern. + +### Colours + +| Element | Role | Hex | +| ------------- | ---------------------- | --------- | +| Blue stroke | First partial hexagon | `#16A2DC` | +| Orange stroke | Second partial hexagon | `#F26A21` | + +These are the official Morphir / FINOS project colours. + +### Stroke properties + +| Property | Value | +| ----------------- | -------------------------------------------- | +| Stroke width | `2.4 · s` (where `s` is the lattice spacing) | +| `stroke-linecap` | `round` | +| `stroke-linejoin` | `round` | + +At the reference size of `s = 16 px` the stroke width is `38.4 px`. + +### Geometry (reference coordinates) + +Coordinates are expressed relative to the logo's own centre `(0, 0)` in a coordinate system where the lattice spacing is `s = 80 px` and the column width is `w = s · √3/2 ≈ 69.282 px`. + +**Blue polyline** — nodes 4 → 3 → 2 → 7 → 13: + +```text +69.282,-140 0,-180 -69.282,-140 -69.282,-60 0,-20 +``` + +**Orange polyline** — nodes 8 → 9 → 14 → 18 → 12: + +```text +0,-100 69.282,-60 69.282,20 0,60 -69.282,20 +``` + +### Minimal SVG + +The following self-contained SVG is the canonical reference rendering of the logo mark. + +```svg + + + + + + +``` + +To scale the logo to a different size, multiply all coordinate values and `stroke-width` by the same factor. diff --git a/substrate/branding/tokens.css b/substrate/branding/tokens.css new file mode 100644 index 000000000..5b7ea02e5 --- /dev/null +++ b/substrate/branding/tokens.css @@ -0,0 +1,92 @@ +/* + * Morphir Substrate — design tokens + * + * Canonical source: branding/design-system.md + * Geometry source: branding/style.md + * + * Import this file wherever brand styling is needed. Never hard-code + * hex values outside of this file. + */ + +:root { + /* Brand palette */ + --brand-blue: #16a2dc; + --brand-orange: #f26a21; + --brand-slate: #2c4a5a; + + /* Surfaces */ + --surface-1: #f7f9fb; + --surface-2: #eef2f6; + --surface-inverse: #1a2a34; + + /* Ink */ + --ink: #2c4a5a; + --ink-muted: rgba(44, 74, 90, 0.7); + --ink-subtle: rgba(44, 74, 90, 0.45); + --rule: rgba(44, 74, 90, 0.14); + + /* Functional */ + --link: var(--brand-blue); + --link-hover: #0e87b8; + --accent: var(--brand-orange); + --accent-hover: #d9571a; + + /* Lattice */ + --lattice-dot: rgba(44, 74, 90, 0.5); + --lattice-line: rgba(44, 74, 90, 0.25); + + /* Typography */ + --font-sans: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; + --font-mono: "JetBrains Mono", "Fira Code", ui-monospace, SFMono-Regular, + Menlo, Consolas, monospace; + + /* Type scale (major third, 1.250) */ + --step--1: 0.833rem; + --step-0: 1rem; + --step-1: 1.25rem; + --step-2: 1.563rem; + --step-3: 1.953rem; + --step-4: 2.441rem; + --step-5: 3.052rem; + + /* Spacing (8-pt scale) */ + --space-1: 4px; + --space-2: 8px; + --space-3: 12px; + --space-4: 16px; + --space-5: 24px; + --space-6: 32px; + --space-7: 48px; + --space-8: 64px; + --space-9: 96px; + + /* Radii */ + --radius-sm: 4px; + --radius-md: 8px; + --radius-lg: 12px; + --radius-pill: 999px; + + /* Elevation */ + --shadow-1: 0 1px 2px rgba(44, 74, 90, 0.06); + --shadow-2: 0 4px 12px rgba(44, 74, 90, 0.08); + --shadow-focus: 0 0 0 3px rgba(22, 162, 220, 0.35); +} + +/* Dark mode: invert surfaces and ink, keep brand signals saturated */ +:root[data-theme="dark"], +:root.theme-dark { + --surface-1: #1a2a34; + --surface-2: #22333f; + --surface-inverse: #f7f9fb; + + --ink: #e6edf3; + --ink-muted: rgba(230, 237, 243, 0.7); + --ink-subtle: rgba(230, 237, 243, 0.45); + --rule: rgba(230, 237, 243, 0.12); + + --lattice-dot: rgba(230, 237, 243, 0.45); + --lattice-line: rgba(230, 237, 243, 0.2); + + --link: #4ebbe8; + --link-hover: #86d0ef; +} diff --git a/substrate/branding/wordmark.svg b/substrate/branding/wordmark.svg new file mode 100644 index 000000000..068f9b61f --- /dev/null +++ b/substrate/branding/wordmark.svg @@ -0,0 +1,31 @@ + + Morphir Substrate + + + + + + + + substrate + diff --git a/substrate/docs/.gitignore b/substrate/docs/.gitignore new file mode 100644 index 000000000..d54377cad --- /dev/null +++ b/substrate/docs/.gitignore @@ -0,0 +1,19 @@ +# build output +dist/ +.astro/ + +# dependencies +node_modules/ + +# generated content synced from ../specs +src/content/docs/specs/ + +# logs +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + +# env +.env +.env.production diff --git a/substrate/docs/astro.config.mjs b/substrate/docs/astro.config.mjs new file mode 100644 index 000000000..6fa277f63 --- /dev/null +++ b/substrate/docs/astro.config.mjs @@ -0,0 +1,13 @@ +import { defineConfig } from "astro/config"; +import mdx from "@astrojs/mdx"; + +export default defineConfig({ + site: "https://morphir.org/substrate", + integrations: [mdx()], + markdown: { + shikiConfig: { + theme: "github-light", + wrap: true, + }, + }, +}); diff --git a/substrate/docs/package-lock.json b/substrate/docs/package-lock.json new file mode 100644 index 000000000..d7eb0345a --- /dev/null +++ b/substrate/docs/package-lock.json @@ -0,0 +1,5495 @@ +{ + "name": "@substrate/docs", + "version": "0.0.1", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@substrate/docs", + "version": "0.0.1", + "dependencies": { + "@astrojs/mdx": "^5.0.0", + "astro": "^6.0.0" + } + }, + "node_modules/@astrojs/compiler": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@astrojs/compiler/-/compiler-3.0.1.tgz", + "integrity": "sha512-z97oYbdebO5aoWzuJ/8q5hLK232+17KcLZ7cJ8BCWk6+qNzVxn/gftC0KzMBUTD8WAaBkPpNSQK6PXLnNrZ0CA==", + "license": "MIT" + }, + "node_modules/@astrojs/internal-helpers": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@astrojs/internal-helpers/-/internal-helpers-0.8.0.tgz", + "integrity": "sha512-J56GrhEiV+4dmrGLPNOl2pZjpHXAndWVyiVDYGDuw6MWKpBSEMLdFxHzeM/6sqaknw9M+HFfHZAcvi3OfT3D/w==", + "license": "MIT", + "dependencies": { + "picomatch": "^4.0.3" + } + }, + "node_modules/@astrojs/markdown-remark": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@astrojs/markdown-remark/-/markdown-remark-7.1.0.tgz", + "integrity": "sha512-P+HnCsu2js3BoTc8kFmu+E9gOcFeMdPris75g+Zl4sY8+bBRbSQV6xzcBDbZ27eE7yBGEGQoqjpChx+KJYIPYQ==", + "license": "MIT", + "dependencies": { + "@astrojs/internal-helpers": "0.8.0", + "@astrojs/prism": "4.0.1", + "github-slugger": "^2.0.0", + "hast-util-from-html": "^2.0.3", + "hast-util-to-text": "^4.0.2", + "js-yaml": "^4.1.1", + "mdast-util-definitions": "^6.0.0", + "rehype-raw": "^7.0.0", + "rehype-stringify": "^10.0.1", + "remark-gfm": "^4.0.1", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.1.2", + "remark-smartypants": "^3.0.2", + "retext-smartypants": "^6.2.0", + "shiki": "^4.0.0", + "smol-toml": "^1.6.0", + "unified": "^11.0.5", + "unist-util-remove-position": "^5.0.0", + "unist-util-visit": "^5.1.0", + "unist-util-visit-parents": "^6.0.2", + "vfile": "^6.0.3" + } + }, + "node_modules/@astrojs/mdx": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@astrojs/mdx/-/mdx-5.0.3.tgz", + "integrity": "sha512-zv/OlM5sZZvyjHqJjR3FjJvoCgbxdqj3t4jO/gSEUNcck3BjdtMgNQw8UgPfAGe4yySdG4vjZ3OC5wUxhu7ckg==", + "license": "MIT", + "dependencies": { + "@astrojs/markdown-remark": "7.1.0", + "@mdx-js/mdx": "^3.1.1", + "acorn": "^8.16.0", + "es-module-lexer": "^2.0.0", + "estree-util-visit": "^2.0.0", + "hast-util-to-html": "^9.0.5", + "piccolore": "^0.1.3", + "rehype-raw": "^7.0.0", + "remark-gfm": "^4.0.1", + "remark-smartypants": "^3.0.2", + "source-map": "^0.7.6", + "unist-util-visit": "^5.1.0", + "vfile": "^6.0.3" + }, + "engines": { + "node": ">=22.12.0" + }, + "peerDependencies": { + "astro": "^6.0.0" + } + }, + "node_modules/@astrojs/prism": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@astrojs/prism/-/prism-4.0.1.tgz", + "integrity": "sha512-nksZQVjlferuWzhPsBpQ1JE5XuKAf1id1/9Hj4a9KG4+ofrlzxUUwX4YGQF/SuDiuiGKEnzopGOt38F3AnVWsQ==", + "license": "MIT", + "dependencies": { + "prismjs": "^1.30.0" + }, + "engines": { + "node": ">=22.12.0" + } + }, + "node_modules/@astrojs/telemetry": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@astrojs/telemetry/-/telemetry-3.3.1.tgz", + "integrity": "sha512-7fcIxXS9J4ls5tr8b3ww9rbAIz2+HrhNJYZdkAhhB4za/I5IZ/60g+Bs8q7zwG0tOIZfNB4JWhVJ1Qkl/OrNCw==", + "license": "MIT", + "dependencies": { + "ci-info": "^4.4.0", + "dlv": "^1.1.3", + "dset": "^3.1.4", + "is-docker": "^4.0.0", + "is-wsl": "^3.1.1", + "which-pm-runs": "^1.1.0" + }, + "engines": { + "node": "18.20.8 || ^20.3.0 || >=22.0.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz", + "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@capsizecss/unpack": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@capsizecss/unpack/-/unpack-4.0.0.tgz", + "integrity": "sha512-VERIM64vtTP1C4mxQ5thVT9fK0apjPFobqybMtA1UdUujWka24ERHbRHFGmpbbhp73MhV+KSsHQH9C6uOTdEQA==", + "license": "MIT", + "dependencies": { + "fontkitten": "^1.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@clack/core": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@clack/core/-/core-1.2.0.tgz", + "integrity": "sha512-qfxof/3T3t9DPU/Rj3OmcFyZInceqj/NVtO9rwIuJqCUgh32gwPjpFQQp/ben07qKlhpwq7GzfWpST4qdJ5Drg==", + "license": "MIT", + "dependencies": { + "fast-wrap-ansi": "^0.1.3", + "sisteransi": "^1.0.5" + } + }, + "node_modules/@clack/prompts": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@clack/prompts/-/prompts-1.2.0.tgz", + "integrity": "sha512-4jmztR9fMqPMjz6H/UZXj0zEmE43ha1euENwkckKKel4XpSfokExPo5AiVStdHSAlHekz4d0CA/r45Ok1E4D3w==", + "license": "MIT", + "dependencies": { + "@clack/core": "1.2.0", + "fast-string-width": "^1.1.0", + "fast-wrap-ansi": "^0.1.3", + "sisteransi": "^1.0.5" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", + "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz", + "integrity": "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.7.tgz", + "integrity": "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.7.tgz", + "integrity": "sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.7.tgz", + "integrity": "sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.7.tgz", + "integrity": "sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.7.tgz", + "integrity": "sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.7.tgz", + "integrity": "sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.7.tgz", + "integrity": "sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.7.tgz", + "integrity": "sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.7.tgz", + "integrity": "sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.7.tgz", + "integrity": "sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.7.tgz", + "integrity": "sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.7.tgz", + "integrity": "sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==", + "cpu": [ + "mips64el" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.7.tgz", + "integrity": "sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.7.tgz", + "integrity": "sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.7.tgz", + "integrity": "sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.7.tgz", + "integrity": "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.7.tgz", + "integrity": "sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.7.tgz", + "integrity": "sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.7.tgz", + "integrity": "sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.7.tgz", + "integrity": "sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.7.tgz", + "integrity": "sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.7.tgz", + "integrity": "sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.7.tgz", + "integrity": "sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.7.tgz", + "integrity": "sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.7.tgz", + "integrity": "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/colour": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", + "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz", + "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz", + "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz", + "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz", + "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz", + "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==", + "cpu": [ + "arm" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz", + "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz", + "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==", + "cpu": [ + "ppc64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz", + "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==", + "cpu": [ + "riscv64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz", + "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==", + "cpu": [ + "s390x" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz", + "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz", + "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz", + "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz", + "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==", + "cpu": [ + "arm" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz", + "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz", + "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==", + "cpu": [ + "ppc64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz", + "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==", + "cpu": [ + "riscv64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-riscv64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz", + "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==", + "cpu": [ + "s390x" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz", + "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz", + "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz", + "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz", + "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==", + "cpu": [ + "wasm32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.7.0" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz", + "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz", + "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==", + "cpu": [ + "ia32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz", + "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT" + }, + "node_modules/@mdx-js/mdx": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.1.1.tgz", + "integrity": "sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdx": "^2.0.0", + "acorn": "^8.0.0", + "collapse-white-space": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "estree-util-scope": "^1.0.0", + "estree-walker": "^3.0.0", + "hast-util-to-jsx-runtime": "^2.0.0", + "markdown-extensions": "^2.0.0", + "recma-build-jsx": "^1.0.0", + "recma-jsx": "^1.0.0", + "recma-stringify": "^1.0.0", + "rehype-recma": "^1.0.0", + "remark-mdx": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.0.0", + "source-map": "^0.7.0", + "unified": "^11.0.0", + "unist-util-position-from-estree": "^2.0.0", + "unist-util-stringify-position": "^4.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@oslojs/encoding": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@oslojs/encoding/-/encoding-1.1.0.tgz", + "integrity": "sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==", + "license": "MIT" + }, + "node_modules/@rollup/pluginutils": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.3.0.tgz", + "integrity": "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/pluginutils/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.2.tgz", + "integrity": "sha512-dnlp69efPPg6Uaw2dVqzWRfAWRnYVb1XJ8CyyhIbZeaq4CA5/mLeZ1IEt9QqQxmbdvagjLIm2ZL8BxXv5lH4Yw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.2.tgz", + "integrity": "sha512-OqZTwDRDchGRHHm/hwLOL7uVPB9aUvI0am/eQuWMNyFHf5PSEQmyEeYYheA0EPPKUO/l0uigCp+iaTjoLjVoHg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.2.tgz", + "integrity": "sha512-UwRE7CGpvSVEQS8gUMBe1uADWjNnVgP3Iusyda1nSRwNDCsRjnGc7w6El6WLQsXmZTbLZx9cecegumcitNfpmA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.2.tgz", + "integrity": "sha512-gjEtURKLCC5VXm1I+2i1u9OhxFsKAQJKTVB8WvDAHF+oZlq0GTVFOlTlO1q3AlCTE/DF32c16ESvfgqR7343/g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.2.tgz", + "integrity": "sha512-Bcl6CYDeAgE70cqZaMojOi/eK63h5Me97ZqAQoh77VPjMysA/4ORQBRGo3rRy45x4MzVlU9uZxs8Uwy7ZaKnBw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.2.tgz", + "integrity": "sha512-LU+TPda3mAE2QB0/Hp5VyeKJivpC6+tlOXd1VMoXV/YFMvk/MNk5iXeBfB4MQGRWyOYVJ01625vjkr0Az98OJQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.2.tgz", + "integrity": "sha512-2QxQrM+KQ7DAW4o22j+XZ6RKdxjLD7BOWTP0Bv0tmjdyhXSsr2Ul1oJDQqh9Zf5qOwTuTc7Ek83mOFaKnodPjg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.2.tgz", + "integrity": "sha512-TbziEu2DVsTEOPif2mKWkMeDMLoYjx95oESa9fkQQK7r/Orta0gnkcDpzwufEcAO2BLBsD7mZkXGFqEdMRRwfw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.2.tgz", + "integrity": "sha512-bO/rVDiDUuM2YfuCUwZ1t1cP+/yqjqz+Xf2VtkdppefuOFS2OSeAfgafaHNkFn0t02hEyXngZkxtGqXcXwO8Rg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.2.tgz", + "integrity": "sha512-hr26p7e93Rl0Za+JwW7EAnwAvKkehh12BU1Llm9Ykiibg4uIr2rbpxG9WCf56GuvidlTG9KiiQT/TXT1yAWxTA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.2.tgz", + "integrity": "sha512-pOjB/uSIyDt+ow3k/RcLvUAOGpysT2phDn7TTUB3n75SlIgZzM6NKAqlErPhoFU+npgY3/n+2HYIQVbF70P9/A==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.2.tgz", + "integrity": "sha512-2/w+q8jszv9Ww1c+6uJT3OwqhdmGP2/4T17cu8WuwyUuuaCDDJ2ojdyYwZzCxx0GcsZBhzi3HmH+J5pZNXnd+Q==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.2.tgz", + "integrity": "sha512-11+aL5vKheYgczxtPVVRhdptAM2H7fcDR5Gw4/bTcteuZBlH4oP9f5s9zYO9aGZvoGeBpqXI/9TZZihZ609wKw==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.2.tgz", + "integrity": "sha512-i16fokAGK46IVZuV8LIIwMdtqhin9hfYkCh8pf8iC3QU3LpwL+1FSFGej+O7l3E/AoknL6Dclh2oTdnRMpTzFQ==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.2.tgz", + "integrity": "sha512-49FkKS6RGQoriDSK/6E2GkAsAuU5kETFCh7pG4yD/ylj9rKhTmO3elsnmBvRD4PgJPds5W2PkhC82aVwmUcJ7A==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.2.tgz", + "integrity": "sha512-mjYNkHPfGpUR00DuM1ZZIgs64Hpf4bWcz9Z41+4Q+pgDx73UwWdAYyf6EG/lRFldmdHHzgrYyge5akFUW0D3mQ==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.2.tgz", + "integrity": "sha512-ALyvJz965BQk8E9Al/JDKKDLH2kfKFLTGMlgkAbbYtZuJt9LU8DW3ZoDMCtQpXAltZxwBHevXz5u+gf0yA0YoA==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.2.tgz", + "integrity": "sha512-UQjrkIdWrKI626Du8lCQ6MJp/6V1LAo2bOK9OTu4mSn8GGXIkPXk/Vsp4bLHCd9Z9Iz2OTEaokUE90VweJgIYQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.2.tgz", + "integrity": "sha512-bTsRGj6VlSdn/XD4CGyzMnzaBs9bsRxy79eTqTCBsA8TMIEky7qg48aPkvJvFe1HyzQ5oMZdg7AnVlWQSKLTnw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.2.tgz", + "integrity": "sha512-6d4Z3534xitaA1FcMWP7mQPq5zGwBmGbhphh2DwaA1aNIXUu3KTOfwrWpbwI4/Gr0uANo7NTtaykFyO2hPuFLg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.2.tgz", + "integrity": "sha512-NetAg5iO2uN7eB8zE5qrZ3CSil+7IJt4WDFLcC75Ymywq1VZVD6qJ6EvNLjZ3rEm6gB7XW5JdT60c6MN35Z85Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.2.tgz", + "integrity": "sha512-NCYhOotpgWZ5kdxCZsv6Iudx0wX8980Q/oW4pNFNihpBKsDbEA1zpkfxJGC0yugsUuyDZ7gL37dbzwhR0VI7pQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.2.tgz", + "integrity": "sha512-RXsaOqXxfoUBQoOgvmmijVxJnW2IGB0eoMO7F8FAjaj0UTywUO/luSqimWBJn04WNgUkeNhh7fs7pESXajWmkg==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.2.tgz", + "integrity": "sha512-qdAzEULD+/hzObedtmV6iBpdL5TIbKVztGiK7O3/KYSf+HIzU257+MX1EXJcyIiDbMAqmbwaufcYPvyRryeZtA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.2.tgz", + "integrity": "sha512-Nd/SgG27WoA9e+/TdK74KnHz852TLa94ovOYySo/yMPuTmpckK/jIF2jSwS3g7ELSKXK13/cVdmg1Z/DaCWKxA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@shikijs/core": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-4.0.2.tgz", + "integrity": "sha512-hxT0YF4ExEqB8G/qFdtJvpmHXBYJ2lWW7qTHDarVkIudPFE6iCIrqdgWxGn5s+ppkGXI0aEGlibI0PAyzP3zlw==", + "license": "MIT", + "dependencies": { + "@shikijs/primitive": "4.0.2", + "@shikijs/types": "4.0.2", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4", + "hast-util-to-html": "^9.0.5" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/engine-javascript": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-4.0.2.tgz", + "integrity": "sha512-7PW0Nm49DcoUIQEXlJhNNBHyoGMjalRETTCcjMqEaMoJRLljy1Bi/EGV3/qLBgLKQejdspiiYuHGQW6dX94Nag==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "4.0.2", + "@shikijs/vscode-textmate": "^10.0.2", + "oniguruma-to-es": "^4.3.4" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/engine-oniguruma": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-4.0.2.tgz", + "integrity": "sha512-UpCB9Y2sUKlS9z8juFSKz7ZtysmeXCgnRF0dlhXBkmQnek7lAToPte8DkxmEYGNTMii72zU/lyXiCB6StuZeJg==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "4.0.2", + "@shikijs/vscode-textmate": "^10.0.2" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/langs": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-4.0.2.tgz", + "integrity": "sha512-KaXby5dvoeuZzN0rYQiPMjFoUrz4hgwIE+D6Du9owcHcl6/g16/yT5BQxSW5cGt2MZBz6Hl0YuRqf12omRfUUg==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "4.0.2" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/primitive": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@shikijs/primitive/-/primitive-4.0.2.tgz", + "integrity": "sha512-M6UMPrSa3fN5ayeJwFVl9qWofl273wtK1VG8ySDZ1mQBfhCpdd8nEx7nPZ/tk7k+TYcpqBZzj/AnwxT9lO+HJw==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "4.0.2", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/themes": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-4.0.2.tgz", + "integrity": "sha512-mjCafwt8lJJaVSsQvNVrJumbnnj1RI8jbUKrPKgE6E3OvQKxnuRoBaYC51H4IGHePsGN/QtALglWBU7DoKDFnA==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "4.0.2" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/types": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-4.0.2.tgz", + "integrity": "sha512-qzbeRooUTPnLE+sHD/Z8DStmaDgnbbc/pMrU203950aRqjX/6AFHeDYT+j00y2lPdz0ywJKx7o/7qnqTivtlXg==", + "license": "MIT", + "dependencies": { + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/vscode-textmate": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz", + "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==", + "license": "MIT" + }, + "node_modules/@types/debug": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.13.tgz", + "integrity": "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==", + "license": "MIT", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "license": "MIT" + }, + "node_modules/@types/estree-jsx": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz", + "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==", + "license": "MIT", + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/mdx": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.13.tgz", + "integrity": "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==", + "license": "MIT" + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "license": "MIT" + }, + "node_modules/@types/nlcst": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/nlcst/-/nlcst-2.0.3.tgz", + "integrity": "sha512-vSYNSDe6Ix3q+6Z7ri9lyWqgGhJTmzRjZRqyq15N0Z/1/UnVsno9G/N40NBijoYx2seFDIl0+B2mgAb9mezUCA==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "license": "MIT" + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "license": "ISC" + }, + "node_modules/acorn": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/anymatch/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, + "node_modules/aria-query": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/array-iterate": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/array-iterate/-/array-iterate-2.0.1.tgz", + "integrity": "sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/astring": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/astring/-/astring-1.9.0.tgz", + "integrity": "sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==", + "license": "MIT", + "bin": { + "astring": "bin/astring" + } + }, + "node_modules/astro": { + "version": "6.1.8", + "resolved": "https://registry.npmjs.org/astro/-/astro-6.1.8.tgz", + "integrity": "sha512-6fT9M12U3fpi13DiPavNKDIoBflASTSxmKTEe+zXhWtlebQuOqfOnIrMWyRmlXp+mgDsojmw+fVFG9LUTzKSog==", + "license": "MIT", + "dependencies": { + "@astrojs/compiler": "^3.0.1", + "@astrojs/internal-helpers": "0.8.0", + "@astrojs/markdown-remark": "7.1.0", + "@astrojs/telemetry": "3.3.1", + "@capsizecss/unpack": "^4.0.0", + "@clack/prompts": "^1.1.0", + "@oslojs/encoding": "^1.1.0", + "@rollup/pluginutils": "^5.3.0", + "aria-query": "^5.3.2", + "axobject-query": "^4.1.0", + "ci-info": "^4.4.0", + "clsx": "^2.1.1", + "common-ancestor-path": "^2.0.0", + "cookie": "^1.1.1", + "devalue": "^5.6.3", + "diff": "^8.0.3", + "dset": "^3.1.4", + "es-module-lexer": "^2.0.0", + "esbuild": "^0.27.3", + "flattie": "^1.1.1", + "fontace": "~0.4.1", + "github-slugger": "^2.0.0", + "html-escaper": "3.0.3", + "http-cache-semantics": "^4.2.0", + "js-yaml": "^4.1.1", + "magic-string": "^0.30.21", + "magicast": "^0.5.2", + "mrmime": "^2.0.1", + "neotraverse": "^0.6.18", + "obug": "^2.1.1", + "p-limit": "^7.3.0", + "p-queue": "^9.1.0", + "package-manager-detector": "^1.6.0", + "piccolore": "^0.1.3", + "picomatch": "^4.0.3", + "rehype": "^13.0.2", + "semver": "^7.7.4", + "shiki": "^4.0.2", + "smol-toml": "^1.6.0", + "svgo": "^4.0.1", + "tinyclip": "^0.1.12", + "tinyexec": "^1.0.4", + "tinyglobby": "^0.2.15", + "tsconfck": "^3.1.6", + "ultrahtml": "^1.6.0", + "unifont": "~0.7.4", + "unist-util-visit": "^5.1.0", + "unstorage": "^1.17.4", + "vfile": "^6.0.3", + "vite": "^7.3.1", + "vitefu": "^1.1.2", + "xxhash-wasm": "^1.1.0", + "yargs-parser": "^22.0.0", + "zod": "^4.3.6" + }, + "bin": { + "astro": "bin/astro.mjs" + }, + "engines": { + "node": ">=22.12.0", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/astrodotbuild" + }, + "optionalDependencies": { + "sharp": "^0.34.0" + } + }, + "node_modules/axobject-query": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", + "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/bail": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", + "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "license": "ISC" + }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", + "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-reference-invalid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", + "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/chokidar": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", + "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", + "license": "MIT", + "dependencies": { + "readdirp": "^5.0.0" + }, + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/ci-info": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.4.0.tgz", + "integrity": "sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/collapse-white-space": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-2.1.0.tgz", + "integrity": "sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/commander": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "license": "MIT", + "engines": { + "node": ">=16" + } + }, + "node_modules/common-ancestor-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-2.0.0.tgz", + "integrity": "sha512-dnN3ibLeoRf2HNC+OlCiNc5d2zxbLJXOtiZUudNFSXZrNSydxcCsSpRzXwfu7BBWCIfHPw+xTayeBvJCP/D8Ng==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">= 18" + } + }, + "node_modules/cookie": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", + "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/cookie-es": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/cookie-es/-/cookie-es-1.2.3.tgz", + "integrity": "sha512-lXVyvUvrNXblMqzIRrxHb57UUVmqsSWlxqt3XIjCkUP0wDAf6uicO6KMbEgYrMNtEvWgWHwe42CKxPu9MYAnWw==", + "license": "MIT" + }, + "node_modules/crossws": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/crossws/-/crossws-0.3.5.tgz", + "integrity": "sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA==", + "license": "MIT", + "dependencies": { + "uncrypto": "^0.1.3" + } + }, + "node_modules/css-select": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz", + "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-tree": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.2.1.tgz", + "integrity": "sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==", + "license": "MIT", + "dependencies": { + "mdn-data": "2.27.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/css-what": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", + "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/csso": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", + "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", + "license": "MIT", + "dependencies": { + "css-tree": "~2.2.0" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/css-tree": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", + "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", + "license": "MIT", + "dependencies": { + "mdn-data": "2.0.28", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/mdn-data": { + "version": "2.0.28", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", + "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", + "license": "CC0-1.0" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decode-named-character-reference": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.3.0.tgz", + "integrity": "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==", + "license": "MIT", + "dependencies": { + "character-entities": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/defu": { + "version": "6.1.7", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.7.tgz", + "integrity": "sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==", + "license": "MIT" + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/destr": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz", + "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==", + "license": "MIT" + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/devalue": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.7.1.tgz", + "integrity": "sha512-MUbZ586EgQqdRnC4yDrlod3BEdyvE4TapGYHMW2CiaW+KkkFmWEFqBUaLltEZCGi0iFXCEjRF0OjF0DV2QHjOA==", + "license": "MIT" + }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "license": "MIT", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/diff": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.4.tgz", + "integrity": "sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "license": "MIT" + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/dom-serializer/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dset": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/dset/-/dset-3.1.4.tgz", + "integrity": "sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/es-module-lexer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", + "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", + "license": "MIT" + }, + "node_modules/esast-util-from-estree": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/esast-util-from-estree/-/esast-util-from-estree-2.0.0.tgz", + "integrity": "sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "devlop": "^1.0.0", + "estree-util-visit": "^2.0.0", + "unist-util-position-from-estree": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/esast-util-from-js": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/esast-util-from-js/-/esast-util-from-js-2.0.1.tgz", + "integrity": "sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "acorn": "^8.0.0", + "esast-util-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/esbuild": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz", + "integrity": "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.7", + "@esbuild/android-arm": "0.27.7", + "@esbuild/android-arm64": "0.27.7", + "@esbuild/android-x64": "0.27.7", + "@esbuild/darwin-arm64": "0.27.7", + "@esbuild/darwin-x64": "0.27.7", + "@esbuild/freebsd-arm64": "0.27.7", + "@esbuild/freebsd-x64": "0.27.7", + "@esbuild/linux-arm": "0.27.7", + "@esbuild/linux-arm64": "0.27.7", + "@esbuild/linux-ia32": "0.27.7", + "@esbuild/linux-loong64": "0.27.7", + "@esbuild/linux-mips64el": "0.27.7", + "@esbuild/linux-ppc64": "0.27.7", + "@esbuild/linux-riscv64": "0.27.7", + "@esbuild/linux-s390x": "0.27.7", + "@esbuild/linux-x64": "0.27.7", + "@esbuild/netbsd-arm64": "0.27.7", + "@esbuild/netbsd-x64": "0.27.7", + "@esbuild/openbsd-arm64": "0.27.7", + "@esbuild/openbsd-x64": "0.27.7", + "@esbuild/openharmony-arm64": "0.27.7", + "@esbuild/sunos-x64": "0.27.7", + "@esbuild/win32-arm64": "0.27.7", + "@esbuild/win32-ia32": "0.27.7", + "@esbuild/win32-x64": "0.27.7" + } + }, + "node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/estree-util-attach-comments": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-attach-comments/-/estree-util-attach-comments-3.0.0.tgz", + "integrity": "sha512-cKUwm/HUcTDsYh/9FgnuFqpfquUbwIqwKM26BVCGDPVgvaCl/nDCCjUfiLlx6lsEZ3Z4RFxNbOQ60pkaEwFxGw==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-build-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/estree-util-build-jsx/-/estree-util-build-jsx-3.0.1.tgz", + "integrity": "sha512-8U5eiL6BTrPxp/CHbs2yMgP8ftMhR5ww1eIKoWRMlqvltHF8fZn5LRDvTKuxD3DUn+shRbLGqXemcP51oFCsGQ==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "estree-walker": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-is-identifier-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz", + "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-scope": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/estree-util-scope/-/estree-util-scope-1.0.0.tgz", + "integrity": "sha512-2CAASclonf+JFWBNJPndcOpA8EMJwa0Q8LUFJEKqXLW6+qBvbFZuF5gItbQOs/umBUkjviCSDCbBwU2cXbmrhQ==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-to-js": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/estree-util-to-js/-/estree-util-to-js-2.0.0.tgz", + "integrity": "sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "astring": "^1.8.0", + "source-map": "^0.7.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-visit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/estree-util-visit/-/estree-util-visit-2.0.0.tgz", + "integrity": "sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/eventemitter3": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", + "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", + "license": "MIT" + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "license": "MIT" + }, + "node_modules/fast-string-truncated-width": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/fast-string-truncated-width/-/fast-string-truncated-width-1.2.1.tgz", + "integrity": "sha512-Q9acT/+Uu3GwGj+5w/zsGuQjh9O1TyywhIwAxHudtWrgF09nHOPrvTLhQevPbttcxjr/SNN7mJmfOw/B1bXgow==", + "license": "MIT" + }, + "node_modules/fast-string-width": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-string-width/-/fast-string-width-1.1.0.tgz", + "integrity": "sha512-O3fwIVIH5gKB38QNbdg+3760ZmGz0SZMgvwJbA1b2TGXceKE6A2cOlfogh1iw8lr049zPyd7YADHy+B7U4W9bQ==", + "license": "MIT", + "dependencies": { + "fast-string-truncated-width": "^1.2.0" + } + }, + "node_modules/fast-wrap-ansi": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/fast-wrap-ansi/-/fast-wrap-ansi-0.1.6.tgz", + "integrity": "sha512-HlUwET7a5gqjURj70D5jl7aC3Zmy4weA1SHUfM0JFI0Ptq987NH2TwbBFLoERhfwk+E+eaq4EK3jXoT+R3yp3w==", + "license": "MIT", + "dependencies": { + "fast-string-width": "^1.1.0" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/flattie": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flattie/-/flattie-1.1.1.tgz", + "integrity": "sha512-9UbaD6XdAL97+k/n+N7JwX46K/M6Zc6KcFYskrYL8wbBV/Uyk0CTAMY0VT+qiK5PM7AIc9aTWYtq65U7T+aCNQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/fontace": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/fontace/-/fontace-0.4.1.tgz", + "integrity": "sha512-lDMvbAzSnHmbYMTEld5qdtvNH2/pWpICOqpean9IgC7vUbUJc3k+k5Dokp85CegamqQpFbXf0rAVkbzpyTA8aw==", + "license": "MIT", + "dependencies": { + "fontkitten": "^1.0.2" + } + }, + "node_modules/fontkitten": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/fontkitten/-/fontkitten-1.0.3.tgz", + "integrity": "sha512-Wp1zXWPVUPBmfoa3Cqc9ctaKuzKAV6uLstRqlR56kSjplf5uAce+qeyYym7F+PHbGTk+tCEdkCW6RD7DX/gBZw==", + "license": "MIT", + "dependencies": { + "tiny-inflate": "^1.0.3" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/github-slugger": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-2.0.0.tgz", + "integrity": "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==", + "license": "ISC" + }, + "node_modules/h3": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/h3/-/h3-1.15.11.tgz", + "integrity": "sha512-L3THSe2MPeBwgIZVSH5zLdBBU90TOxarvhK9d04IDY2AmVS8j2Jz2LIWtwsGOU3lu2I5jCN7FNvVfY2+XyF+mg==", + "license": "MIT", + "dependencies": { + "cookie-es": "^1.2.3", + "crossws": "^0.3.5", + "defu": "^6.1.6", + "destr": "^2.0.5", + "iron-webcrypto": "^1.2.1", + "node-mock-http": "^1.0.4", + "radix3": "^1.1.2", + "ufo": "^1.6.3", + "uncrypto": "^0.1.3" + } + }, + "node_modules/hast-util-from-html": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.3.tgz", + "integrity": "sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "devlop": "^1.1.0", + "hast-util-from-parse5": "^8.0.0", + "parse5": "^7.0.0", + "vfile": "^6.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-from-parse5": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz", + "integrity": "sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "devlop": "^1.0.0", + "hastscript": "^9.0.0", + "property-information": "^7.0.0", + "vfile": "^6.0.0", + "vfile-location": "^5.0.0", + "web-namespaces": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-is-element": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-3.0.0.tgz", + "integrity": "sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-parse-selector": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz", + "integrity": "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-raw": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-9.1.0.tgz", + "integrity": "sha512-Y8/SBAHkZGoNkpzqqfCldijcuUKh7/su31kEBp67cFY09Wy0mTRgtsLYsiIxMJxlu0f6AA5SUTbDR8K0rxnbUw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "@ungap/structured-clone": "^1.0.0", + "hast-util-from-parse5": "^8.0.0", + "hast-util-to-parse5": "^8.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "parse5": "^7.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0", + "web-namespaces": "^2.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-estree": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/hast-util-to-estree/-/hast-util-to-estree-3.1.3.tgz", + "integrity": "sha512-48+B/rJWAp0jamNbAAf9M7Uf//UVqAoMmgXhBdxTDJLGKY+LRnZ99qcG+Qjl5HfMpYNzS5v4EAwVEF34LeAj7w==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-attach-comments": "^3.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-js": "^1.0.0", + "unist-util-position": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-html": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz", + "integrity": "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-whitespace": "^3.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "stringify-entities": "^4.0.0", + "zwitch": "^2.0.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-jsx-runtime": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz", + "integrity": "sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-js": "^1.0.0", + "unist-util-position": "^5.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-parse5": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-8.0.1.tgz", + "integrity": "sha512-MlWT6Pjt4CG9lFCjiz4BH7l9wmrMkfkJYCxFwKQic8+RTZgWPuWxwAfjJElsXkex7DJjfSJsQIt931ilUgmwdA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "web-namespaces": "^2.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-text": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-4.0.2.tgz", + "integrity": "sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "hast-util-is-element": "^3.0.0", + "unist-util-find-after": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-whitespace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hastscript": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-9.0.1.tgz", + "integrity": "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-parse-selector": "^4.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/html-escaper": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-3.0.3.tgz", + "integrity": "sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==", + "license": "MIT" + }, + "node_modules/html-void-elements": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", + "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", + "license": "BSD-2-Clause" + }, + "node_modules/inline-style-parser": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.7.tgz", + "integrity": "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==", + "license": "MIT" + }, + "node_modules/iron-webcrypto": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/iron-webcrypto/-/iron-webcrypto-1.2.1.tgz", + "integrity": "sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/brc-dd" + } + }, + "node_modules/is-alphabetical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", + "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-alphanumerical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", + "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", + "license": "MIT", + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-decimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-decimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", + "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-docker": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-4.0.0.tgz", + "integrity": "sha512-LHE+wROyG/Y/0ZnbktRCoTix2c1RhgWaZraMZ8o1Q7zCh0VSrICJQO5oqIIISrcSBtrXv0o233w1IYwsWCjTzA==", + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-hexadecimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", + "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "license": "MIT", + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-inside-container/node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-wsl": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.1.tgz", + "integrity": "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==", + "license": "MIT", + "dependencies": { + "is-inside-container": "^1.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/longest-streak": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/lru-cache": { + "version": "11.3.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.3.5.tgz", + "integrity": "sha512-NxVFwLAnrd9i7KUBxC4DrUhmgjzOs+1Qm50D3oF1/oL+r1NpZ4gA7xvG0/zJ8evR7zIKn4vLf7qTNduWFtCrRw==", + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/magicast": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.2.tgz", + "integrity": "sha512-E3ZJh4J3S9KfwdjZhe2afj6R9lGIN5Pher1pF39UGrXRqq/VDaGVIGN13BjHd2u8B61hArAGOnso7nBOouW3TQ==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", + "source-map-js": "^1.2.1" + } + }, + "node_modules/markdown-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/markdown-extensions/-/markdown-extensions-2.0.0.tgz", + "integrity": "sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q==", + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/markdown-table": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz", + "integrity": "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/mdast-util-definitions": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-6.0.0.tgz", + "integrity": "sha512-scTllyX6pnYNZH/AIp/0ePz6s4cZtARxImwoPJ7kS42n+MnVsI4XbnG6d4ibehRIldYMWM2LD7ImQblVhUejVQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-find-and-replace": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz", + "integrity": "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "escape-string-regexp": "^5.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-from-markdown": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.3.tgz", + "integrity": "sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark": "^4.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.1.0.tgz", + "integrity": "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==", + "license": "MIT", + "dependencies": { + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-gfm-autolink-literal": "^2.0.0", + "mdast-util-gfm-footnote": "^2.0.0", + "mdast-util-gfm-strikethrough": "^2.0.0", + "mdast-util-gfm-table": "^2.0.0", + "mdast-util-gfm-task-list-item": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-autolink-literal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz", + "integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "ccount": "^2.0.0", + "devlop": "^1.0.0", + "mdast-util-find-and-replace": "^3.0.0", + "micromark-util-character": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-strikethrough": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz", + "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-table": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz", + "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "markdown-table": "^3.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-task-list-item": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz", + "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-3.0.0.tgz", + "integrity": "sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w==", + "license": "MIT", + "dependencies": { + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-expression": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz", + "integrity": "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-jsx": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.2.0.tgz", + "integrity": "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "parse-entities": "^4.0.0", + "stringify-entities": "^4.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdxjs-esm": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", + "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-phrasing": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", + "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-hast": { + "version": "13.2.1", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz", + "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-markdown": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz", + "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "longest-streak": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdn-data": { + "version": "2.27.1", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.27.1.tgz", + "integrity": "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==", + "license": "CC0-1.0" + }, + "node_modules/micromark": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", + "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz", + "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-destination": "^2.0.0", + "micromark-factory-label": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-title": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-html-tag-name": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", + "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==", + "license": "MIT", + "dependencies": { + "micromark-extension-gfm-autolink-literal": "^2.0.0", + "micromark-extension-gfm-footnote": "^2.0.0", + "micromark-extension-gfm-strikethrough": "^2.0.0", + "micromark-extension-gfm-table": "^2.0.0", + "micromark-extension-gfm-tagfilter": "^2.0.0", + "micromark-extension-gfm-task-list-item": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", + "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-strikethrough": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz", + "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-table": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz", + "integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-tagfilter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz", + "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==", + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-task-list-item": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz", + "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdx-expression": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-3.0.1.tgz", + "integrity": "sha512-dD/ADLJ1AeMvSAKBwO22zG22N4ybhe7kFIZ3LsDI0GlsNr2A3KYxb0LdC1u5rj4Nw+CHKY0RVdnHX8vj8ejm4Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-mdx-expression": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-mdx-jsx": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-jsx/-/micromark-extension-mdx-jsx-3.0.2.tgz", + "integrity": "sha512-e5+q1DjMh62LZAJOnDraSSbDMvGJ8x3cbjygy2qFEi7HCeUT4BDKCvMozPozcD6WmOt6sVvYDNBKhFSz3kjOVQ==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "micromark-factory-mdx-expression": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdx-md": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-md/-/micromark-extension-mdx-md-2.0.0.tgz", + "integrity": "sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ==", + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdxjs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs/-/micromark-extension-mdxjs-3.0.0.tgz", + "integrity": "sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ==", + "license": "MIT", + "dependencies": { + "acorn": "^8.0.0", + "acorn-jsx": "^5.0.0", + "micromark-extension-mdx-expression": "^3.0.0", + "micromark-extension-mdx-jsx": "^3.0.0", + "micromark-extension-mdx-md": "^2.0.0", + "micromark-extension-mdxjs-esm": "^3.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdxjs-esm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs-esm/-/micromark-extension-mdxjs-esm-3.0.0.tgz", + "integrity": "sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-position-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-factory-destination": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", + "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-label": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", + "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-mdx-expression": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-factory-mdx-expression/-/micromark-factory-mdx-expression-2.0.3.tgz", + "integrity": "sha512-kQnEtA3vzucU2BkrIa8/VaSAsP+EJ3CKOvhMuJgOEGg9KDC6OAY6nSnNDVRiVNRqj7Y4SlSzcStaH/5jge8JdQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-position-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + } + }, + "node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz", + "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz", + "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-chunked": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz", + "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-classify-character": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz", + "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-combine-extensions": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz", + "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-chunked": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-numeric-character-reference": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz", + "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-string": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz", + "integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-encode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", + "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-events-to-acorn": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-util-events-to-acorn/-/micromark-util-events-to-acorn-2.0.3.tgz", + "integrity": "sha512-jmsiEIiZ1n7X1Rr5k8wVExBQCg5jy4UXVADItHmNk1zkwEVhBuIUKRu3fqv+hs4nxLISi2DQGlqIOGiFxgbfHg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/unist": "^3.0.0", + "devlop": "^1.0.0", + "estree-util-visit": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "vfile-message": "^4.0.0" + } + }, + "node_modules/micromark-util-html-tag-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", + "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-normalize-identifier": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz", + "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-resolve-all": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz", + "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", + "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-subtokenize": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz", + "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-types": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", + "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/mrmime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", + "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/neotraverse": { + "version": "0.6.18", + "resolved": "https://registry.npmjs.org/neotraverse/-/neotraverse-0.6.18.tgz", + "integrity": "sha512-Z4SmBUweYa09+o6pG+eASabEpP6QkQ70yHj351pQoEXIs8uHbaU2DWVmzBANKgflPa47A50PtB2+NgRpQvr7vA==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/nlcst-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/nlcst-to-string/-/nlcst-to-string-4.0.0.tgz", + "integrity": "sha512-YKLBCcUYKAg0FNlOBT6aI91qFmSiFKiluk655WzPF+DDMA02qIyy8uiRqI8QXtcFpEvll12LpL5MXqEmAZ+dcA==", + "license": "MIT", + "dependencies": { + "@types/nlcst": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/node-fetch-native": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz", + "integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==", + "license": "MIT" + }, + "node_modules/node-mock-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/node-mock-http/-/node-mock-http-1.0.4.tgz", + "integrity": "sha512-8DY+kFsDkNXy1sJglUfuODx1/opAGJGyrTuFqEoN90oRc2Vk0ZbD4K2qmKXBBEhZQzdKHIVfEJpDU8Ak2NJEvQ==", + "license": "MIT" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/obug": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", + "integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==", + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], + "license": "MIT" + }, + "node_modules/ofetch": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/ofetch/-/ofetch-1.5.1.tgz", + "integrity": "sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA==", + "license": "MIT", + "dependencies": { + "destr": "^2.0.5", + "node-fetch-native": "^1.6.7", + "ufo": "^1.6.1" + } + }, + "node_modules/ohash": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", + "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", + "license": "MIT" + }, + "node_modules/oniguruma-parser": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/oniguruma-parser/-/oniguruma-parser-0.12.1.tgz", + "integrity": "sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w==", + "license": "MIT" + }, + "node_modules/oniguruma-to-es": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-4.3.5.tgz", + "integrity": "sha512-Zjygswjpsewa0NLTsiizVuMQZbp0MDyM6lIt66OxsF21npUDlzpHi1Mgb/qhQdkb+dWFTzJmFbEWdvZgRho8eQ==", + "license": "MIT", + "dependencies": { + "oniguruma-parser": "^0.12.1", + "regex": "^6.1.0", + "regex-recursion": "^6.0.2" + } + }, + "node_modules/p-limit": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-7.3.0.tgz", + "integrity": "sha512-7cIXg/Z0M5WZRblrsOla88S4wAK+zOQQWeBYfV3qJuJXMr+LnbYjaadrFaS0JILfEDPVqHyKnZ1Z/1d6J9VVUw==", + "license": "MIT", + "dependencies": { + "yocto-queue": "^1.2.1" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-queue": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-9.1.2.tgz", + "integrity": "sha512-ktsDOALzTYTWWF1PbkNVg2rOt+HaOaMWJMUnt7T3qf5tvZ1L8dBW3tObzprBcXNMKkwj+yFSLqHso0x+UFcJXw==", + "license": "MIT", + "dependencies": { + "eventemitter3": "^5.0.1", + "p-timeout": "^7.0.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-timeout": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-7.0.1.tgz", + "integrity": "sha512-AxTM2wDGORHGEkPCt8yqxOTMgpfbEHqF51f/5fJCmwFC3C/zNcGT63SymH2ttOAaiIws2zVg4+izQCjrakcwHg==", + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-manager-detector": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.6.0.tgz", + "integrity": "sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==", + "license": "MIT" + }, + "node_modules/parse-entities": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", + "integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^2.0.0", + "character-entities-legacy": "^3.0.0", + "character-reference-invalid": "^2.0.0", + "decode-named-character-reference": "^1.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0", + "is-hexadecimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/parse-entities/node_modules/@types/unist": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", + "license": "MIT" + }, + "node_modules/parse-latin": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse-latin/-/parse-latin-7.0.0.tgz", + "integrity": "sha512-mhHgobPPua5kZ98EF4HWiH167JWBfl4pvAIXXdbaVohtK7a6YBOy56kvhCqduqyo/f3yrHFWmqmiMg/BkBkYYQ==", + "license": "MIT", + "dependencies": { + "@types/nlcst": "^2.0.0", + "@types/unist": "^3.0.0", + "nlcst-to-string": "^4.0.0", + "unist-util-modify-children": "^4.0.0", + "unist-util-visit-children": "^3.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "license": "MIT", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/piccolore": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/piccolore/-/piccolore-0.1.3.tgz", + "integrity": "sha512-o8bTeDWjE086iwKrROaDf31K0qC/BENdm15/uH9usSC/uZjJOKb2YGiVHfLY4GhwsERiPI1jmwI2XrA7ACOxVw==", + "license": "ISC" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.10", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.10.tgz", + "integrity": "sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/prismjs": { + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz", + "integrity": "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/property-information": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", + "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/radix3": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/radix3/-/radix3-1.1.2.tgz", + "integrity": "sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==", + "license": "MIT" + }, + "node_modules/readdirp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz", + "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==", + "license": "MIT", + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/recma-build-jsx": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/recma-build-jsx/-/recma-build-jsx-1.0.0.tgz", + "integrity": "sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-util-build-jsx": "^3.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/recma-jsx": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/recma-jsx/-/recma-jsx-1.0.1.tgz", + "integrity": "sha512-huSIy7VU2Z5OLv6oFLosQGGDqPqdO1iq6bWNAdhzMxSJP7RAso4fCZ1cKu8j9YHCZf3TPrq4dw3okhrylgcd7w==", + "license": "MIT", + "dependencies": { + "acorn-jsx": "^5.0.0", + "estree-util-to-js": "^2.0.0", + "recma-parse": "^1.0.0", + "recma-stringify": "^1.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/recma-parse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/recma-parse/-/recma-parse-1.0.0.tgz", + "integrity": "sha512-OYLsIGBB5Y5wjnSnQW6t3Xg7q3fQ7FWbw/vcXtORTnyaSFscOtABg+7Pnz6YZ6c27fG1/aN8CjfwoUEUIdwqWQ==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "esast-util-from-js": "^2.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/recma-stringify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/recma-stringify/-/recma-stringify-1.0.0.tgz", + "integrity": "sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-util-to-js": "^2.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/regex/-/regex-6.1.0.tgz", + "integrity": "sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==", + "license": "MIT", + "dependencies": { + "regex-utilities": "^2.3.0" + } + }, + "node_modules/regex-recursion": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/regex-recursion/-/regex-recursion-6.0.2.tgz", + "integrity": "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==", + "license": "MIT", + "dependencies": { + "regex-utilities": "^2.3.0" + } + }, + "node_modules/regex-utilities": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/regex-utilities/-/regex-utilities-2.3.0.tgz", + "integrity": "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==", + "license": "MIT" + }, + "node_modules/rehype": { + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/rehype/-/rehype-13.0.2.tgz", + "integrity": "sha512-j31mdaRFrwFRUIlxGeuPXXKWQxet52RBQRvCmzl5eCefn/KGbomK5GMHNMsOJf55fgo3qw5tST5neDuarDYR2A==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "rehype-parse": "^9.0.0", + "rehype-stringify": "^10.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-parse": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-9.0.1.tgz", + "integrity": "sha512-ksCzCD0Fgfh7trPDxr2rSylbwq9iYDkSn8TCDmEJ49ljEUBxDVCzCHv7QNzZOfODanX4+bWQ4WZqLCRWYLfhag==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-from-html": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-raw": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-7.0.0.tgz", + "integrity": "sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-raw": "^9.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-recma": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rehype-recma/-/rehype-recma-1.0.0.tgz", + "integrity": "sha512-lqA4rGUf1JmacCNWWZx0Wv1dHqMwxzsDWYMTowuplHF3xH0N/MmrZ/G3BDZnzAkRmxDadujCjaKM2hqYdCBOGw==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/hast": "^3.0.0", + "hast-util-to-estree": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-stringify": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/rehype-stringify/-/rehype-stringify-10.0.1.tgz", + "integrity": "sha512-k9ecfXHmIPuFVI61B9DeLPN0qFHfawM6RsuX48hoqlaKSF61RskNjSm1lI8PhBEM0MRdLxVVm4WmTqJQccH9mA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-to-html": "^9.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-gfm": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.1.tgz", + "integrity": "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-gfm": "^3.0.0", + "micromark-extension-gfm": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-stringify": "^11.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-mdx": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.1.1.tgz", + "integrity": "sha512-Pjj2IYlUY3+D8x00UJsIOg5BEvfMyeI+2uLPn9VO9Wg4MEtN/VTIq2NEJQfde9PnX15KgtHyl9S0BcTnWrIuWg==", + "license": "MIT", + "dependencies": { + "mdast-util-mdx": "^3.0.0", + "micromark-extension-mdxjs": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-parse": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", + "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-rehype": { + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.2.tgz", + "integrity": "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "mdast-util-to-hast": "^13.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-smartypants": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/remark-smartypants/-/remark-smartypants-3.0.2.tgz", + "integrity": "sha512-ILTWeOriIluwEvPjv67v7Blgrcx+LZOkAUVtKI3putuhlZm84FnqDORNXPPm+HY3NdZOMhyDwZ1E+eZB/Df5dA==", + "license": "MIT", + "dependencies": { + "retext": "^9.0.0", + "retext-smartypants": "^6.0.0", + "unified": "^11.0.4", + "unist-util-visit": "^5.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/remark-stringify": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz", + "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-to-markdown": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/retext": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/retext/-/retext-9.0.0.tgz", + "integrity": "sha512-sbMDcpHCNjvlheSgMfEcVrZko3cDzdbe1x/e7G66dFp0Ff7Mldvi2uv6JkJQzdRcvLYE8CA8Oe8siQx8ZOgTcA==", + "license": "MIT", + "dependencies": { + "@types/nlcst": "^2.0.0", + "retext-latin": "^4.0.0", + "retext-stringify": "^4.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/retext-latin": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/retext-latin/-/retext-latin-4.0.0.tgz", + "integrity": "sha512-hv9woG7Fy0M9IlRQloq/N6atV82NxLGveq+3H2WOi79dtIYWN8OaxogDm77f8YnVXJL2VD3bbqowu5E3EMhBYA==", + "license": "MIT", + "dependencies": { + "@types/nlcst": "^2.0.0", + "parse-latin": "^7.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/retext-smartypants": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/retext-smartypants/-/retext-smartypants-6.2.0.tgz", + "integrity": "sha512-kk0jOU7+zGv//kfjXEBjdIryL1Acl4i9XNkHxtM7Tm5lFiCog576fjNC9hjoR7LTKQ0DsPWy09JummSsH1uqfQ==", + "license": "MIT", + "dependencies": { + "@types/nlcst": "^2.0.0", + "nlcst-to-string": "^4.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/retext-stringify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/retext-stringify/-/retext-stringify-4.0.0.tgz", + "integrity": "sha512-rtfN/0o8kL1e+78+uxPTqu1Klt0yPzKuQ2BfWwwfgIUSayyzxpM1PJzkKt4V8803uB9qSy32MvI7Xep9khTpiA==", + "license": "MIT", + "dependencies": { + "@types/nlcst": "^2.0.0", + "nlcst-to-string": "^4.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rollup": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.2.tgz", + "integrity": "sha512-J9qZyW++QK/09NyN/zeO0dG/1GdGfyp9lV8ajHnRVLfo/uFsbji5mHnDgn/qYdUHyCkM2N+8VyspgZclfAh0eQ==", + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.60.2", + "@rollup/rollup-android-arm64": "4.60.2", + "@rollup/rollup-darwin-arm64": "4.60.2", + "@rollup/rollup-darwin-x64": "4.60.2", + "@rollup/rollup-freebsd-arm64": "4.60.2", + "@rollup/rollup-freebsd-x64": "4.60.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.60.2", + "@rollup/rollup-linux-arm-musleabihf": "4.60.2", + "@rollup/rollup-linux-arm64-gnu": "4.60.2", + "@rollup/rollup-linux-arm64-musl": "4.60.2", + "@rollup/rollup-linux-loong64-gnu": "4.60.2", + "@rollup/rollup-linux-loong64-musl": "4.60.2", + "@rollup/rollup-linux-ppc64-gnu": "4.60.2", + "@rollup/rollup-linux-ppc64-musl": "4.60.2", + "@rollup/rollup-linux-riscv64-gnu": "4.60.2", + "@rollup/rollup-linux-riscv64-musl": "4.60.2", + "@rollup/rollup-linux-s390x-gnu": "4.60.2", + "@rollup/rollup-linux-x64-gnu": "4.60.2", + "@rollup/rollup-linux-x64-musl": "4.60.2", + "@rollup/rollup-openbsd-x64": "4.60.2", + "@rollup/rollup-openharmony-arm64": "4.60.2", + "@rollup/rollup-win32-arm64-msvc": "4.60.2", + "@rollup/rollup-win32-ia32-msvc": "4.60.2", + "@rollup/rollup-win32-x64-gnu": "4.60.2", + "@rollup/rollup-win32-x64-msvc": "4.60.2", + "fsevents": "~2.3.2" + } + }, + "node_modules/sax": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.0.tgz", + "integrity": "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=11.0.0" + } + }, + "node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/sharp": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", + "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", + "hasInstallScript": true, + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@img/colour": "^1.0.0", + "detect-libc": "^2.1.2", + "semver": "^7.7.3" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.34.5", + "@img/sharp-darwin-x64": "0.34.5", + "@img/sharp-libvips-darwin-arm64": "1.2.4", + "@img/sharp-libvips-darwin-x64": "1.2.4", + "@img/sharp-libvips-linux-arm": "1.2.4", + "@img/sharp-libvips-linux-arm64": "1.2.4", + "@img/sharp-libvips-linux-ppc64": "1.2.4", + "@img/sharp-libvips-linux-riscv64": "1.2.4", + "@img/sharp-libvips-linux-s390x": "1.2.4", + "@img/sharp-libvips-linux-x64": "1.2.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", + "@img/sharp-libvips-linuxmusl-x64": "1.2.4", + "@img/sharp-linux-arm": "0.34.5", + "@img/sharp-linux-arm64": "0.34.5", + "@img/sharp-linux-ppc64": "0.34.5", + "@img/sharp-linux-riscv64": "0.34.5", + "@img/sharp-linux-s390x": "0.34.5", + "@img/sharp-linux-x64": "0.34.5", + "@img/sharp-linuxmusl-arm64": "0.34.5", + "@img/sharp-linuxmusl-x64": "0.34.5", + "@img/sharp-wasm32": "0.34.5", + "@img/sharp-win32-arm64": "0.34.5", + "@img/sharp-win32-ia32": "0.34.5", + "@img/sharp-win32-x64": "0.34.5" + } + }, + "node_modules/shiki": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-4.0.2.tgz", + "integrity": "sha512-eAVKTMedR5ckPo4xne/PjYQYrU3qx78gtJZ+sHlXEg5IHhhoQhMfZVzetTYuaJS0L2Ef3AcCRzCHV8T0WI6nIQ==", + "license": "MIT", + "dependencies": { + "@shikijs/core": "4.0.2", + "@shikijs/engine-javascript": "4.0.2", + "@shikijs/engine-oniguruma": "4.0.2", + "@shikijs/langs": "4.0.2", + "@shikijs/themes": "4.0.2", + "@shikijs/types": "4.0.2", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "license": "MIT" + }, + "node_modules/smol-toml": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.6.1.tgz", + "integrity": "sha512-dWUG8F5sIIARXih1DTaQAX4SsiTXhInKf1buxdY9DIg4ZYPZK5nGM1VRIYmEbDbsHt7USo99xSLFu5Q1IqTmsg==", + "license": "BSD-3-Clause", + "engines": { + "node": ">= 18" + }, + "funding": { + "url": "https://github.com/sponsors/cyyynthia" + } + }, + "node_modules/source-map": { + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", + "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">= 12" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/stringify-entities": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", + "license": "MIT", + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/style-to-js": { + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.21.tgz", + "integrity": "sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==", + "license": "MIT", + "dependencies": { + "style-to-object": "1.0.14" + } + }, + "node_modules/style-to-object": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.14.tgz", + "integrity": "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==", + "license": "MIT", + "dependencies": { + "inline-style-parser": "0.2.7" + } + }, + "node_modules/svgo": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-4.0.1.tgz", + "integrity": "sha512-XDpWUOPC6FEibaLzjfe0ucaV0YrOjYotGJO1WpF0Zd+n6ZGEQUsSugaoLq9QkEZtAfQIxT42UChcssDVPP3+/w==", + "license": "MIT", + "dependencies": { + "commander": "^11.1.0", + "css-select": "^5.1.0", + "css-tree": "^3.0.1", + "css-what": "^6.1.0", + "csso": "^5.0.5", + "picocolors": "^1.1.1", + "sax": "^1.5.0" + }, + "bin": { + "svgo": "bin/svgo.js" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/svgo" + } + }, + "node_modules/tiny-inflate": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", + "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==", + "license": "MIT" + }, + "node_modules/tinyclip": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/tinyclip/-/tinyclip-0.1.12.tgz", + "integrity": "sha512-Ae3OVUqifDw0wBriIBS7yVaW44Dp6eSHQcyq4Igc7eN2TJH/2YsicswaW+J/OuMvhpDPOKEgpAZCjkb4hpoyeA==", + "license": "MIT", + "engines": { + "node": "^16.14.0 || >= 17.3.0" + } + }, + "node_modules/tinyexec": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.1.1.tgz", + "integrity": "sha512-VKS/ZaQhhkKFMANmAOhhXVoIfBXblQxGX1myCQ2faQrfmobMftXeJPcZGp0gS07ocvGJWDLZGyOZDadDBqYIJg==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.16", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", + "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/trough": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", + "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/tsconfck": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/tsconfck/-/tsconfck-3.1.6.tgz", + "integrity": "sha512-ks6Vjr/jEw0P1gmOVwutM3B7fWxoWBL2KRDb1JfqGVawBmO5UsvmWOQFGHBPl5yxYz4eERr19E6L7NMv+Fej4w==", + "license": "MIT", + "bin": { + "tsconfck": "bin/tsconfck.js" + }, + "engines": { + "node": "^18 || >=20" + }, + "peerDependencies": { + "typescript": "^5.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/ufo": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.3.tgz", + "integrity": "sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==", + "license": "MIT" + }, + "node_modules/ultrahtml": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ultrahtml/-/ultrahtml-1.6.0.tgz", + "integrity": "sha512-R9fBn90VTJrqqLDwyMph+HGne8eqY1iPfYhPzZrvKpIfwkWZbcYlfpsb8B9dTvBfpy1/hqAD7Wi8EKfP9e8zdw==", + "license": "MIT" + }, + "node_modules/uncrypto": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/uncrypto/-/uncrypto-0.1.3.tgz", + "integrity": "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==", + "license": "MIT" + }, + "node_modules/unified": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", + "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unifont": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/unifont/-/unifont-0.7.4.tgz", + "integrity": "sha512-oHeis4/xl42HUIeHuNZRGEvxj5AaIKR+bHPNegRq5LV1gdc3jundpONbjglKpihmJf+dswygdMJn3eftGIMemg==", + "license": "MIT", + "dependencies": { + "css-tree": "^3.1.0", + "ofetch": "^1.5.1", + "ohash": "^2.0.11" + } + }, + "node_modules/unist-util-find-after": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-find-after/-/unist-util-find-after-5.0.0.tgz", + "integrity": "sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-is": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-modify-children": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-modify-children/-/unist-util-modify-children-4.0.0.tgz", + "integrity": "sha512-+tdN5fGNddvsQdIzUF3Xx82CU9sMM+fA0dLgR9vOmT0oPT2jH+P1nd5lSqfCfXAw+93NhcXNY2qqvTUtE4cQkw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "array-iterate": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position-from-estree": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position-from-estree/-/unist-util-position-from-estree-2.0.0.tgz", + "integrity": "sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-remove-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-5.0.0.tgz", + "integrity": "sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.1.0.tgz", + "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-children": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit-children/-/unist-util-visit-children-3.0.0.tgz", + "integrity": "sha512-RgmdTfSBOg04sdPcpTSD1jzoNBjt9a80/ZCzp5cI9n1qPzLZWF9YdvWGN2zmTumP1HWhXKdUWexjy/Wy/lJ7tA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unstorage": { + "version": "1.17.5", + "resolved": "https://registry.npmjs.org/unstorage/-/unstorage-1.17.5.tgz", + "integrity": "sha512-0i3iqvRfx29hkNntHyQvJTpf5W9dQ9ZadSoRU8+xVlhVtT7jAX57fazYO9EHvcRCfBCyi5YRya7XCDOsbTgkPg==", + "license": "MIT", + "dependencies": { + "anymatch": "^3.1.3", + "chokidar": "^5.0.0", + "destr": "^2.0.5", + "h3": "^1.15.10", + "lru-cache": "^11.2.7", + "node-fetch-native": "^1.6.7", + "ofetch": "^1.5.1", + "ufo": "^1.6.3" + }, + "peerDependencies": { + "@azure/app-configuration": "^1.8.0", + "@azure/cosmos": "^4.2.0", + "@azure/data-tables": "^13.3.0", + "@azure/identity": "^4.6.0", + "@azure/keyvault-secrets": "^4.9.0", + "@azure/storage-blob": "^12.26.0", + "@capacitor/preferences": "^6 || ^7 || ^8", + "@deno/kv": ">=0.9.0", + "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0", + "@planetscale/database": "^1.19.0", + "@upstash/redis": "^1.34.3", + "@vercel/blob": ">=0.27.1", + "@vercel/functions": "^2.2.12 || ^3.0.0", + "@vercel/kv": "^1 || ^2 || ^3", + "aws4fetch": "^1.0.20", + "db0": ">=0.2.1", + "idb-keyval": "^6.2.1", + "ioredis": "^5.4.2", + "uploadthing": "^7.4.4" + }, + "peerDependenciesMeta": { + "@azure/app-configuration": { + "optional": true + }, + "@azure/cosmos": { + "optional": true + }, + "@azure/data-tables": { + "optional": true + }, + "@azure/identity": { + "optional": true + }, + "@azure/keyvault-secrets": { + "optional": true + }, + "@azure/storage-blob": { + "optional": true + }, + "@capacitor/preferences": { + "optional": true + }, + "@deno/kv": { + "optional": true + }, + "@netlify/blobs": { + "optional": true + }, + "@planetscale/database": { + "optional": true + }, + "@upstash/redis": { + "optional": true + }, + "@vercel/blob": { + "optional": true + }, + "@vercel/functions": { + "optional": true + }, + "@vercel/kv": { + "optional": true + }, + "aws4fetch": { + "optional": true + }, + "db0": { + "optional": true + }, + "idb-keyval": { + "optional": true + }, + "ioredis": { + "optional": true + }, + "uploadthing": { + "optional": true + } + } + }, + "node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-location": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-5.0.3.tgz", + "integrity": "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", + "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vite": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.2.tgz", + "integrity": "sha512-Bby3NOsna2jsjfLVOHKes8sGwgl4TT0E6vvpYgnAYDIF/tie7MRaFthmKuHx1NSXjiTueXH3do80FMQgvEktRg==", + "license": "MIT", + "dependencies": { + "esbuild": "^0.27.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vitefu": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.1.3.tgz", + "integrity": "sha512-ub4okH7Z5KLjb6hDyjqrGXqWtWvoYdU3IGm/NorpgHncKoLTCfRIbvlhBm7r0YstIaQRYlp4yEbFqDcKSzXSSg==", + "license": "MIT", + "workspaces": [ + "tests/deps/*", + "tests/projects/*", + "tests/projects/workspace/packages/*" + ], + "peerDependencies": { + "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "vite": { + "optional": true + } + } + }, + "node_modules/web-namespaces": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz", + "integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/which-pm-runs": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.1.0.tgz", + "integrity": "sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/xxhash-wasm": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-1.1.0.tgz", + "integrity": "sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA==", + "license": "MIT" + }, + "node_modules/yargs-parser": { + "version": "22.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz", + "integrity": "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==", + "license": "ISC", + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=23" + } + }, + "node_modules/yocto-queue": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.2.tgz", + "integrity": "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==", + "license": "MIT", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zod": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz", + "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + } + } +} diff --git a/substrate/docs/package.json b/substrate/docs/package.json new file mode 100644 index 000000000..46fe69954 --- /dev/null +++ b/substrate/docs/package.json @@ -0,0 +1,17 @@ +{ + "name": "@substrate/docs", + "version": "0.0.1", + "private": true, + "type": "module", + "scripts": { + "sync": "node scripts/sync-specs.mjs", + "dev": "npm run sync && astro dev", + "build": "npm run sync && astro build", + "preview": "astro preview", + "astro": "astro" + }, + "dependencies": { + "@astrojs/mdx": "^5.0.0", + "astro": "^6.0.0" + } +} diff --git a/substrate/docs/scripts/sync-specs.mjs b/substrate/docs/scripts/sync-specs.mjs new file mode 100644 index 000000000..c092977d7 --- /dev/null +++ b/substrate/docs/scripts/sync-specs.mjs @@ -0,0 +1,111 @@ +#!/usr/bin/env node +/* + * Copy ../specs/**\/*.md into src/content/docs/specs/ so Starlight + * can render them as doc pages. We inject minimal frontmatter + * (title + description) derived from the first H1 and first + * paragraph of each file. + * + * Run via `npm run sync`. Output is gitignored (see .gitignore). + */ +import { mkdir, readdir, readFile, writeFile, rm, stat } from "node:fs/promises"; +import { existsSync } from "node:fs"; +import { dirname, join, relative, resolve } from "node:path"; +import { fileURLToPath } from "node:url"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const SPEC_SRC = resolve(__dirname, "../../specs"); +const SPEC_DST = resolve(__dirname, "../src/content/docs/specs"); + +async function walk(dir) { + const entries = await readdir(dir, { withFileTypes: true }); + const files = []; + for (const entry of entries) { + const full = join(dir, entry.name); + if (entry.isDirectory()) { + files.push(...(await walk(full))); + } else if (entry.isFile() && entry.name.endsWith(".md")) { + files.push(full); + } + } + return files; +} + +function extractTitleAndLede(md) { + const lines = md.split(/\r?\n/); + let title = null; + let lede = null; + for (let i = 0; i < lines.length; i++) { + const line = lines[i]; + if (!title && line.startsWith("# ")) { + title = line.replace(/^#\s+/, "").trim(); + continue; + } + if (title && !lede) { + const t = line.trim(); + if (t === "" || t.startsWith("#")) continue; + lede = t.replace(/[`*_]/g, ""); + break; + } + } + return { title, lede }; +} + +function toFrontmatter({ title, lede, source }) { + const safe = (s) => + (s || "") + .replace(/\\/g, "\\\\") + .replace(/"/g, '\\"') + .slice(0, 220); + const lines = ["---"]; + lines.push(`title: "${safe(title)}"`); + if (lede) lines.push(`description: "${safe(lede)}"`); + lines.push(`editUrl: false`); + lines.push(`# synced from ${source}`); + lines.push("---", ""); + return lines.join("\n"); +} + +async function main() { + if (!existsSync(SPEC_SRC)) { + console.error(`sync-specs: source not found: ${SPEC_SRC}`); + process.exit(1); + } + if (existsSync(SPEC_DST)) await rm(SPEC_DST, { recursive: true, force: true }); + await mkdir(SPEC_DST, { recursive: true }); + + const files = await walk(SPEC_SRC); + let count = 0; + for (const file of files) { + const rel = relative(SPEC_SRC, file); + const dst = join(SPEC_DST, rel); + await mkdir(dirname(dst), { recursive: true }); + + const raw = await readFile(file, "utf8"); + // If the file already has frontmatter (starts with ---), preserve it. + let out; + if (raw.startsWith("---\n") || raw.startsWith("---\r\n")) { + out = raw; + } else { + const { title, lede } = extractTitleAndLede(raw); + const fmTitle = title || rel.replace(/\.md$/, "").split(/[\\/]/).pop(); + const fm = toFrontmatter({ + title: fmTitle, + lede, + source: `specs/${rel.replace(/\\/g, "/")}`, + }); + // Strip the first H1 since Starlight renders title from frontmatter. + const stripped = title + ? raw.replace(/^#\s+.*\r?\n/, "") + : raw; + out = fm + stripped; + } + await writeFile(dst, out, "utf8"); + count++; + } + console.log(`sync-specs: copied ${count} file(s) into ${relative(process.cwd(), SPEC_DST)}`); +} + +main().catch((err) => { + console.error(err); + process.exit(1); +}); diff --git a/substrate/docs/src/assets/logo.svg b/substrate/docs/src/assets/logo.svg new file mode 100644 index 000000000..a24b14fad --- /dev/null +++ b/substrate/docs/src/assets/logo.svg @@ -0,0 +1,13 @@ + + Morphir Substrate + + + diff --git a/substrate/docs/src/assets/wordmark.svg b/substrate/docs/src/assets/wordmark.svg new file mode 100644 index 000000000..48032844a --- /dev/null +++ b/substrate/docs/src/assets/wordmark.svg @@ -0,0 +1,22 @@ + + Morphir Substrate + + + + + substrate + diff --git a/substrate/docs/src/components/CliDemo.astro b/substrate/docs/src/components/CliDemo.astro new file mode 100644 index 000000000..27cc09dae --- /dev/null +++ b/substrate/docs/src/components/CliDemo.astro @@ -0,0 +1,99 @@ +--- +// Animated substrate CLI demo. The animation runs client-side once +// hydrated; if JS is disabled the full transcript is shown statically. +--- + +
+
+ + + + substrate — order-total +
+
+ +
$ substrate test examples/order-total.md
+
✓ 24/24 tests passed
+
+
+ + diff --git a/substrate/docs/src/components/Footer.astro b/substrate/docs/src/components/Footer.astro new file mode 100644 index 000000000..bc3d6b2b7 --- /dev/null +++ b/substrate/docs/src/components/Footer.astro @@ -0,0 +1,19 @@ +--- +import logo from "../assets/logo.svg"; +--- + + diff --git a/substrate/docs/src/components/Lattice.astro b/substrate/docs/src/components/Lattice.astro new file mode 100644 index 000000000..8b8dc207f --- /dev/null +++ b/substrate/docs/src/components/Lattice.astro @@ -0,0 +1,143 @@ +--- +// Triangular lattice (deltille / A2) background pattern, rendered to a +// canvas that fills its host element. Ported from the Substrate design +// system reference lattice-background.js. +interface Props { + spacing?: number; + dotRadius?: number; + lineWidth?: number; + class?: string; + id?: string; +} +const { + spacing = 26, + dotRadius = 1.4, + lineWidth = 0.55, + class: className = "lattice-host", + id, +} = Astro.props; +--- + +
+ + diff --git a/substrate/docs/src/components/Sidebar.astro b/substrate/docs/src/components/Sidebar.astro new file mode 100644 index 000000000..4fb6ad532 --- /dev/null +++ b/substrate/docs/src/components/Sidebar.astro @@ -0,0 +1,33 @@ +--- +import { NAV } from "../nav"; +interface Props { + activeSlug?: string; +} +const { activeSlug } = Astro.props; + +function href(slug: string) { + return `/docs/${slug}/`; +} +--- + + diff --git a/substrate/docs/src/components/TopBar.astro b/substrate/docs/src/components/TopBar.astro new file mode 100644 index 000000000..3623ecee8 --- /dev/null +++ b/substrate/docs/src/components/TopBar.astro @@ -0,0 +1,30 @@ +--- +interface Props { + active?: "overview" | "docs" | "examples" | "blog"; +} +const { active = "overview" } = Astro.props; +import logo from "../assets/logo.svg"; +--- + +
+ + + Substrate + + +
+ + GitHub +
+
diff --git a/substrate/docs/src/content.config.ts b/substrate/docs/src/content.config.ts new file mode 100644 index 000000000..2530f3ed4 --- /dev/null +++ b/substrate/docs/src/content.config.ts @@ -0,0 +1,14 @@ +import { defineCollection, z } from "astro:content"; +import { glob } from "astro/loaders"; + +const docs = defineCollection({ + loader: glob({ pattern: "**/*.{md,mdx}", base: "./src/content/docs" }), + schema: z.object({ + title: z.string(), + description: z.string().optional(), + eyebrow: z.string().optional(), + breadcrumb: z.array(z.string()).optional(), + }), +}); + +export const collections = { docs }; diff --git a/substrate/docs/src/content/docs/brand/design-system.md b/substrate/docs/src/content/docs/brand/design-system.md new file mode 100644 index 000000000..4cc87a46e --- /dev/null +++ b/substrate/docs/src/content/docs/brand/design-system.md @@ -0,0 +1,43 @@ +--- +title: Design system +description: Colors, typography, spacing, and brand usage for Morphir Substrate. +breadcrumb: ["Brand", "Design system"] +--- + +Substrate's full design system reference lives in the [`branding/` folder](https://github.com/AttilaMihaly/morphir-substrate/tree/main/branding). The canonical source of truth is [`branding/design-system.md`](https://github.com/AttilaMihaly/morphir-substrate/blob/main/branding/design-system.md). + +## At a glance + +| Token | Value | Role | +| ---------------- | ---------- | --------------------------------- | +| Brand blue | `#16A2DC` | Primary signal — logo, links. | +| Brand orange | `#F26A21` | Secondary signal — accents. | +| Deep Slate | `#2C4A5A` | Tertiary — ink, chrome, surfaces. | + +### Why Deep Slate + +The two brand signals (orange and blue) are a complementary pair and already do the visual work. The third color is a **neutral ink**, not a third accent. Deep Slate `#2C4A5A`: + +- sits in the same hue family as the brand blue (≈204°) so it reads as part of the palette, +- is desaturated (~35%) and dark (~26% lightness) so it recedes to a neutral, and +- replaces the earlier pine green `#2F4738`, whose green cast muddled the orange signal. + +## Logo + +The mark's geometric bounding box is centered on its own origin — any container that centers the SVG visually centers the mark. In horizontal lockups (mark + "substrate" wordmark), the wordmark's cap-height midline aligns to the mark's vertical center. + +See [`branding/logo.svg`](https://github.com/AttilaMihaly/morphir-substrate/blob/main/branding/logo.svg) and [`branding/wordmark.svg`](https://github.com/AttilaMihaly/morphir-substrate/blob/main/branding/wordmark.svg). + +## Typography + +- **Display:** Fraunces (serif, weight 500) — section headings and hero. +- **UI / body:** Inter. +- **Code:** JetBrains Mono. + +## Spacing + +4-pt base scale, `--s-1` (4px) through `--s-24` (96px). + +## Background lattice + +Substrate uses a triangular (A₂) lattice as its signature background texture. Geometry and rendering parameters are in [`branding/style.md`](https://github.com/AttilaMihaly/morphir-substrate/blob/main/branding/style.md). diff --git a/substrate/docs/src/content/docs/getting-started.md b/substrate/docs/src/content/docs/getting-started.md new file mode 100644 index 000000000..474af933c --- /dev/null +++ b/substrate/docs/src/content/docs/getting-started.md @@ -0,0 +1,69 @@ +--- +title: Install & quickstart +description: Install the substrate CLI and run your first spec. +breadcrumb: ["Start here", "Install & quickstart"] +--- + +## Install + +Substrate ships as a Node.js CLI. You will need **Node 20+** and **npm 10+**. + +```bash +npm install -g substrate +``` + +Verify the install: + +```bash +substrate --version +``` + +## Your first spec + +Substrate specs are plain Markdown. Create `hello.md`: + +````markdown +# Hello + +A substrate spec that greets the world. + +```substrate +function greet(name: String) -> String = + "Hello, " + name + "!" +``` + +## Example + +`greet("world")` should return `"Hello, world!"`. +```` + +Run it: + +```bash +substrate run hello.md +``` + +## Validate a project + +To check that every spec in a directory is well-formed: + +```bash +substrate validate ./specs +``` + +## Install / update packages + +Substrate specs can depend on other specs. Use the package commands to +manage those dependencies: + +```bash +substrate install # install dependencies declared in substrate.toml +substrate update # refresh locked versions +substrate publish # publish the current package to the registry +``` + +## Next steps + +- Read the [language specification](/docs/specs/language/) for syntax and semantics. +- Browse the [examples](https://github.com/AttilaMihaly/morphir-substrate/tree/main/examples) for fully-worked specs. +- See the [CLI reference](/docs/specs/tools/cli/readme/) for every command and flag. diff --git a/substrate/docs/src/content/docs/introduction.md b/substrate/docs/src/content/docs/introduction.md new file mode 100644 index 000000000..6e0524ab2 --- /dev/null +++ b/substrate/docs/src/content/docs/introduction.md @@ -0,0 +1,85 @@ +--- +title: Introduction +description: "Substrate turns the documents an organization already writes into verifiable knowledge — a structured, link-typed corpus that humans, engineers, and LLMs can collaborate on." +breadcrumb: ["Start here", "Introduction"] +--- + +Substrate is a **specification substrate**: a structured, link-typed, +human-readable corpus of Markdown documents that captures what a system +*should* do — its concepts, rules, operations, and examples — in a form +that both humans and LLMs can read, edit, and reason about. + +Its purpose is to turn the documents an organization already writes — +specifications, regulations, domain models, runbooks — into **verifiable +knowledge**: a corpus whose internal consistency, type compatibility, +and behavioural claims can be checked by tooling rather than taken on +faith. + +## Why this matters + +Most institutional knowledge lives in unverifiable documents. Nothing +checks that a definition on page 12 matches the rule on page 47, that +an example still produces the stated output, or that the implementation +actually does what the document says. + +LLMs amplify this. They are powerful readers and writers of prose, but +their answers are only as trustworthy as the context they are given. +Feed a model the wrong slice of a sprawling document set, or one that +quietly contradicts itself, and you get confident output that is wrong +in ways no one catches. + +The same structure that makes a corpus mechanically verifiable also +makes it the ideal context source for an LLM. A document set that tools +can check, an LLM can be trusted to act on. + +## A knowledge graph hidden in plain Markdown + +Substrate is **plain Markdown**, written by humans assisted by LLMs, +rendered by GitHub, no custom syntax. Structure is carried by the +things Markdown already gives you — headings, tables, lists, footnotes, +and especially **links** between documents. + +As authors describe a business problem in their own words, every +reference to a concept, type, or operation is a link to the place that +defines it. The corpus quietly accumulates a **semantic knowledge +graph** that tools can traverse, type-check, and slice for an LLM — +without constraining how the prose is written. The freedom to describe +the domain naturally and the ability to interpret it mechanically come +from the same structure. + +## What this changes for engineers + +Engineers contribute most when they can spot patterns and translate +them into efficient technology. With unstructured prose as the only +context, that skill has nowhere to land — engineers either build a +mental model in their head and hand-hold an LLM through implementation, +or they let the LLM interpret the prose directly and improvise. + +Substrate externalizes the mental model. Engineers describe recurring +patterns using the corpus's own identifiers and attach **technology +mappings** to them — how each pattern is realized in TypeScript, SQL, +or whatever target fits. Where a pattern matches and a mapping exists, +the tooling produces the implementation directly: no LLM improvisation, +no per-task prompt engineering. Where a case is novel, the LLM still +helps, but its work is checked against the corpus and the result can be +promoted to a reusable pattern. Engineering judgment accumulates in the +corpus rather than evaporating into chat transcripts. + +## How to read these docs + +- **[Vision](/docs/specs/vision/)** — goals, principles, and where this + is headed. +- **[Language](/docs/specs/language/)** — the conventions a Substrate + corpus follows: Markdown structure, link semantics, types, concepts, + and expressions. +- **[Tools](/docs/specs/tools/cli/)** — the `substrate` CLI: context + extraction, validation, refactoring, packaging, and test execution. +- **[Install & quickstart](/docs/getting-started/)** — set up a corpus + and run your first commands in about five minutes. + +## Conventions + +Inline `code` denotes Substrate identifiers, command names, or other +literal tokens. Block quotes are direct quotations from the primary +sources a corpus cites (regulations, contracts, papers). Decision +tables render as ordinary Markdown tables and are authoritative. diff --git a/substrate/docs/src/layouts/Base.astro b/substrate/docs/src/layouts/Base.astro new file mode 100644 index 000000000..a5d54022d --- /dev/null +++ b/substrate/docs/src/layouts/Base.astro @@ -0,0 +1,30 @@ +--- +import TopBar from "../components/TopBar.astro"; +import Footer from "../components/Footer.astro"; +import "../styles/tokens.css"; +import "../styles/app.css"; +interface Props { + title: string; + description?: string; + activeNav?: "overview" | "docs" | "examples" | "blog"; +} +const { title, description, activeNav = "overview" } = Astro.props; +--- + + + + + + + {title} + {description && } + + + +
+ + +
+
+ + diff --git a/substrate/docs/src/layouts/Docs.astro b/substrate/docs/src/layouts/Docs.astro new file mode 100644 index 000000000..e3a930502 --- /dev/null +++ b/substrate/docs/src/layouts/Docs.astro @@ -0,0 +1,91 @@ +--- +import Base from "./Base.astro"; +import Sidebar from "../components/Sidebar.astro"; +import { NAV } from "../nav"; + +interface Props { + title: string; + description?: string; + activeSlug: string; + breadcrumb?: string[]; + headings?: { depth: number; slug: string; text: string }[]; +} +const { + title, + description, + activeSlug, + breadcrumb = [], + headings = [], +} = Astro.props; + +// Flatten nav for prev/next calculation. +const flat = NAV.flatMap((s) => s.items); +const idx = flat.findIndex((i) => i.slug === activeSlug); +const prev = idx > 0 ? flat[idx - 1] : null; +const next = idx >= 0 && idx < flat.length - 1 ? flat[idx + 1] : null; + +const tocItems = headings.filter((h) => h.depth === 2 || h.depth === 3); +--- + + +
+ +
+
+ { + breadcrumb.length > 0 && ( + + ) + } +

{title}

+ {description &&

{description}

} + + { + (prev || next) && ( + + ) + } +
+
+ { + tocItems.length > 0 && ( + + ) + } +
+ diff --git a/substrate/docs/src/nav.ts b/substrate/docs/src/nav.ts new file mode 100644 index 000000000..c265b70ba --- /dev/null +++ b/substrate/docs/src/nav.ts @@ -0,0 +1,69 @@ +/** + * Docs sidebar navigation. Entries reference content-collection slugs + * under `src/content/docs/` (without the leading slash). Sections with + * `indent: 1` render with the indented treatment used for nested groups. + */ +export interface NavItem { + slug: string; + label: string; +} +export interface NavSection { + name: string; + items: NavItem[]; + indent?: 0 | 1; +} + +export const NAV: NavSection[] = [ + { + name: "Getting started", + items: [ + { slug: "introduction", label: "Introduction" }, + { slug: "specs/vision", label: "Vision" }, + { slug: "getting-started", label: "Install & quickstart" }, + ], + }, + { + name: "Language", + items: [{ slug: "specs/language", label: "Overview" }], + }, + { + name: "Concepts", + indent: 1, + items: [ + { slug: "specs/language/concepts/record", label: "Record" }, + { slug: "specs/language/concepts/choice", label: "Choice" }, + { + slug: "specs/language/concepts/decision-table", + label: "Decision Table", + }, + { slug: "specs/language/concepts/operation", label: "Operation" }, + { slug: "specs/language/concepts/provenance", label: "Provenance" }, + { slug: "specs/language/concepts/type-class", label: "Type Class" }, + ], + }, + { + name: "Expressions", + indent: 1, + items: [ + { slug: "specs/language/expressions/boolean", label: "Boolean" }, + { slug: "specs/language/expressions/number", label: "Number" }, + { slug: "specs/language/expressions/ordering", label: "Ordering" }, + { slug: "specs/language/expressions/collection", label: "Collection" }, + { slug: "specs/language/expressions/string", label: "String" }, + { slug: "specs/language/expressions/date", label: "Date" }, + ], + }, + { + name: "Tools", + items: [ + { slug: "specs/tools/cli/readme", label: "CLI" }, + { slug: "specs/tools/cli/commands", label: "Commands" }, + { slug: "specs/tools/cli/packages", label: "Packages" }, + { slug: "specs/tools/cli/design-decisions", label: "Design Decisions" }, + ], + }, + { + name: "Brand", + items: [{ slug: "brand/design-system", label: "Design system" }], + }, +]; diff --git a/substrate/docs/src/pages/docs/[...slug].astro b/substrate/docs/src/pages/docs/[...slug].astro new file mode 100644 index 000000000..eeacbde4d --- /dev/null +++ b/substrate/docs/src/pages/docs/[...slug].astro @@ -0,0 +1,50 @@ +--- +import { getCollection, render } from "astro:content"; +import Docs from "../../layouts/Docs.astro"; +import { NAV } from "../../nav"; + +export async function getStaticPaths() { + const entries = await getCollection("docs"); + return entries.map((entry) => ({ + params: { slug: entry.id }, + props: { entry }, + })); +} + +const { entry } = Astro.props; +const { Content, headings } = await render(entry); + +function labelFor(slug: string): string | undefined { + for (const s of NAV) { + const it = s.items.find((i) => i.slug === slug); + if (it) return it.label; + } + return undefined; +} + +// Compute breadcrumb from slug segments or explicit frontmatter. +const segments = entry.id.split("/"); +const defaultCrumb = segments + .slice(0, -1) + .map( + (s) => + s.replace(/[-_]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase()), + ); +const breadcrumb = entry.data.breadcrumb ?? [ + ...defaultCrumb, + labelFor(entry.id) ?? entry.data.title, +]; + +const title = entry.data.title; +const description = entry.data.description; +--- + + + + diff --git a/substrate/docs/src/pages/docs/index.astro b/substrate/docs/src/pages/docs/index.astro new file mode 100644 index 000000000..20ff8d41c --- /dev/null +++ b/substrate/docs/src/pages/docs/index.astro @@ -0,0 +1,4 @@ +--- +// Redirect /docs/ to the first sidebar entry. +return Astro.redirect("/docs/introduction/"); +--- diff --git a/substrate/docs/src/pages/index.astro b/substrate/docs/src/pages/index.astro new file mode 100644 index 000000000..4a9e56392 --- /dev/null +++ b/substrate/docs/src/pages/index.astro @@ -0,0 +1,85 @@ +--- +import Base from "../layouts/Base.astro"; +import Lattice from "../components/Lattice.astro"; +import CliDemo from "../components/CliDemo.astro"; +--- + + +
+ +
+
+
A FINOS project · v0.1.0
+

Verifiable knowledge for human–LLM collaboration.

+

+ Substrate turns the documents your organization already writes — + specifications, regulations, domain models — into a structured, + link-typed corpus that humans and LLMs can read, edit, and + reason about. The same structure that tools can check is the + context an LLM can be trusted to act on. +

+ +
+ +
+
+
Verifiable knowledge
+

+ Every claim a corpus makes — types, dependencies, examples, + test cases — is mechanically checkable. Findings are reported + against the originating prose, not an opaque intermediate + form. +

+
+
+
A graph in plain markdown
+

+ Authors describe the domain in their own words. Links between + documents quietly accumulate a semantic knowledge graph that + tools can traverse, type-check, and slice for an LLM. +

+
+
+
Engineer leverage
+

+ Externalize the mental model. Register patterns and + technology mappings against the corpus and let the tooling + generate implementations directly — instead of re-prompting + an LLM for every change. +

+
+
+ +
+
+
Command line
+

The corpus is a runnable artifact.

+

+ The substrate CLI extracts focused context for an + LLM, validates the corpus for consistency and type + compatibility, refactors safely across files, and runs the + test cases embedded in the prose. Exits non-zero on failure — + the same shape as any other check in a CI pipeline. +

+
    +
  • context — extract a tree-shaken slice for an LLM
  • +
  • validate — check structure, links, and types
  • +
  • test — run every embedded case
  • +
  • refactor — rename and move with references intact
  • +
+
+ +
+
+
+ diff --git a/substrate/docs/src/styles/app.css b/substrate/docs/src/styles/app.css new file mode 100644 index 000000000..33f42e403 --- /dev/null +++ b/substrate/docs/src/styles/app.css @@ -0,0 +1,689 @@ +/* Application chrome — topbar, hero, docs layout, footer. + Ported from the Substrate design system reference docs-site, + with pine palette replaced by the slate scale. */ + +/* ─── App shell ─────────────────────────────────────────────── */ +.docs-app { + display: flex; + flex-direction: column; + min-height: 100vh; +} + +/* ─── Topbar ────────────────────────────────────────────────── */ +.docs-top { + display: grid; + grid-template-columns: auto 1fr auto; + align-items: center; + gap: 28px; + padding: 12px 28px; + border-bottom: 1px solid var(--slate-200); + background: rgba(253, 254, 254, 0.88); + backdrop-filter: blur(6px); + position: sticky; + top: 0; + z-index: 10; +} + +.docs-brand { + display: flex; + align-items: center; + gap: 10px; + text-decoration: none; +} + +.docs-brand img { + width: 26px; + height: 26px; + display: block; +} + +.docs-brand span { + font-family: var(--font-display); + font-weight: 500; + font-size: 18px; + color: var(--slate-900); + letter-spacing: -0.01em; + line-height: 1; + /* align wordmark midline to mark center */ +} + +.docs-topnav { + display: flex; + gap: 22px; +} + +.docs-topnav a { + font-size: 13px; + color: var(--fg-2); + text-decoration: none; + padding: 4px 0; + border-bottom: 1.5px solid transparent; +} + +.docs-topnav a:hover { + color: var(--fg-1); +} + +.docs-topnav a.active { + color: var(--slate-900); + border-bottom-color: var(--brand-orange); +} + +.docs-top-right { + display: flex; + gap: 12px; + align-items: center; +} + +.search { + font-family: var(--font-mono); + font-size: 12px; + color: var(--fg-3); + background: var(--bg-elev); + border: 1px solid var(--slate-200); + padding: 6px 12px; + border-radius: 6px; + display: flex; + gap: 8px; + align-items: center; +} + +.search span { + background: var(--slate-100); + padding: 1px 6px; + border-radius: 4px; + font-size: 10px; + color: var(--fg-2); +} + +/* ─── Landing hero ──────────────────────────────────────────── */ +.landing { + position: relative; + overflow: hidden; + background: var(--bg-radial); +} + +.lattice-host { + position: absolute; + inset: 0; + opacity: 0.85; + pointer-events: none; +} + +.landing-inner { + position: relative; + max-width: 1100px; + margin: 0 auto; + padding: 72px 32px 96px; +} + +.lead { + max-width: 780px; +} + +.landing h1 { + font-family: var(--font-display); + font-weight: 500; + font-size: 60px; + line-height: 1.05; + letter-spacing: -0.02em; + color: var(--slate-900); + margin: 0 0 18px; + text-wrap: balance; +} + +.landing .s-lede { + font-size: 19px; + line-height: 1.55; + max-width: 620px; + margin: 0; +} + +.cta-row { + display: flex; + gap: 10px; + margin-top: 28px; +} + +.three-up { + display: grid; + grid-template-columns: 1fr 1fr 1fr; + gap: 32px; + margin-top: 80px; + padding-top: 40px; +} + +.three-up>div { + display: flex; + flex-direction: column; + gap: 6px; + background: radial-gradient(ellipse farthest-side at 30% 30%, var(--paper) 50%, #eef2f600 100%); + padding: 8px; +} + +.three-up p { + font-size: 14px; + color: var(--fg-2); + line-height: 1.6; + margin: 0; +} + +.threeup-eyebrow { + font-family: var(--font-display); + font-weight: 500; + font-size: 18px; + color: var(--slate-900); + margin-bottom: 4px; + letter-spacing: -0.005em; +} + +.threeup-eyebrow::before { + content: ""; + display: inline-block; + width: 8px; + height: 8px; + margin-right: 10px; + vertical-align: middle; + border-radius: 999px; + background: var(--brand-blue); +} + +.three-up>div:nth-child(2) .threeup-eyebrow::before { + background: var(--brand-orange); +} + +.three-up>div:nth-child(3) .threeup-eyebrow::before { + background: var(--slate-700); +} + +.demo-slab { + display: grid; + grid-template-columns: 1.1fr 1fr; + gap: 56px; + margin-top: 96px; + align-items: center; +} + +.demo-copy h2 { + font-family: var(--font-display); + font-weight: 500; + font-size: 34px; + letter-spacing: -0.012em; + line-height: 1.15; + margin: 0 0 12px; + color: var(--slate-900); + text-wrap: balance; +} + +.demo-copy p { + font-size: 15px; + color: var(--fg-2); + line-height: 1.6; + max-width: 500px; +} + +.cli-flags { + list-style: none; + padding: 0; + margin: 14px 0 0; + display: flex; + flex-direction: column; + gap: 6px; +} + +.cli-flags li { + font-size: 13.5px; + color: var(--fg-2); +} + +.cli-flags code { + font-family: var(--font-mono); + font-size: 12.5px; + background: var(--bg-sunk); + border: 1px solid var(--slate-200); + padding: 1px 7px; + border-radius: 4px; + color: var(--slate-900); + margin-right: 6px; +} + +/* ─── CLI window ────────────────────────────────────────────── */ +.cli-window { + background: var(--slate-900); + border-radius: 12px; + box-shadow: + 0 20px 50px rgba(26, 42, 52, 0.2), + 0 4px 12px rgba(26, 42, 52, 0.12); + overflow: hidden; + border: 1px solid var(--slate-800); +} + +.cli-titlebar { + display: flex; + align-items: center; + gap: 7px; + padding: 10px 14px; + background: var(--slate-800); + border-bottom: 1px solid rgba(255, 255, 255, 0.05); +} + +.cli-titlebar .dot { + width: 11px; + height: 11px; + border-radius: 999px; +} + +.cli-title { + margin-left: 10px; + font-family: var(--font-mono); + font-size: 11px; + color: var(--slate-400); + letter-spacing: 0.04em; +} + +.cli-body { + padding: 18px 20px; + font-family: var(--font-mono); + font-size: 12.5px; + line-height: 1.7; + color: #d4dde4; + min-height: 340px; + max-height: 380px; + overflow: auto; +} + +.cli-line { + white-space: pre; +} + +.cli-prompt { + color: #fdfefe; +} + +.cli-prompt::first-letter { + color: #869cab; +} + +.cli-ok { + color: #6bc289; +} + +.cli-dim { + color: #5a7586; +} + +.cli-num { + color: #f9b57a; + font-size: 16px; + padding: 4px 0; +} + +.cli-hdr { + color: #f9b57a; + font-weight: 600; + padding-top: 4px; +} + +.cli-def { + color: #8dcde8; +} + +.caret { + color: #f9b57a; + animation: blink 1s steps(1) infinite; +} + +@keyframes blink { + 50% { + opacity: 0; + } +} + +/* ─── Docs work area ────────────────────────────────────────── */ +.docs-work { + display: grid; + grid-template-columns: 240px 1fr 200px; + max-width: 1280px; + width: 100%; + margin: 0 auto; + padding: 32px; + gap: 40px; + flex: 1; +} + +.docs-sidebar { + position: sticky; + top: 80px; + align-self: flex-start; + max-height: calc(100vh - 100px); + overflow-y: auto; +} + +.docs-toc { + position: sticky; + top: 80px; + align-self: flex-start; +} + +.docs-main { + min-width: 0; +} + +/* Sidebar nav */ +.docs-nav { + display: flex; + flex-direction: column; + gap: 18px; + font-size: 13.5px; +} + +.nav-section.indent-1 { + padding-left: 10px; + border-left: 1px solid var(--slate-200); + margin-left: 2px; +} + +.nav-eyebrow { + font-family: var(--font-mono); + font-size: 10px; + text-transform: uppercase; + letter-spacing: 0.1em; + color: var(--fg-3); + margin-bottom: 6px; +} + +.docs-nav ul { + list-style: none; + padding: 0; + margin: 0; + display: flex; + flex-direction: column; + gap: 2px; +} + +.docs-nav li a { + display: block; + padding: 4px 8px; + border-radius: 5px; + color: var(--fg-2); + text-decoration: none; + font-size: 13px; +} + +.docs-nav li a:hover { + background: var(--slate-100); + color: var(--slate-900); +} + +.docs-nav li a.active { + background: var(--brand-blue-soft); + color: var(--brand-blue-ink); + font-weight: 500; +} + +/* ─── Docs page body ────────────────────────────────────────── */ +.docs-page { + max-width: 760px; +} + +.page-breadcrumb { + font-family: var(--font-mono); + font-size: 11px; + color: var(--fg-3); + text-transform: uppercase; + letter-spacing: 0.08em; + margin-bottom: 10px; +} + +.page-breadcrumb b { + color: var(--fg-1); + font-weight: 500; +} + +.docs-page h1 { + font-family: var(--font-display); + font-weight: 500; + font-size: 44px; + line-height: 1.1; + letter-spacing: -0.015em; + margin: 0 0 12px; + color: var(--slate-900); +} + +.docs-page .s-lede { + margin: 0 0 24px; +} + +.docs-page p { + font-size: 15px; + line-height: 1.7; + color: var(--fg-1); +} + +.docs-page h2 { + font-family: var(--font-display); + font-weight: 500; + font-size: 26px; + margin: 32px 0 10px; + color: var(--slate-900); + scroll-margin-top: 90px; +} + +.docs-page h3 { + font-family: var(--font-display); + font-weight: 500; + font-size: 20px; + margin: 24px 0 8px; + color: var(--slate-900); +} + +.docs-page h4 { + font-family: var(--font-body); + font-weight: 600; + font-size: 14px; + margin: 18px 0 6px; + color: var(--fg-2); + text-transform: uppercase; + letter-spacing: 0.06em; +} + +.docs-page ul { + padding-left: 22px; +} + +.docs-page li { + font-size: 15px; + line-height: 1.7; + margin-bottom: 4px; +} + +.docs-page pre { + background: var(--bg-sunk); + border: 1px solid var(--slate-200); + border-radius: 8px; + padding: 12px 16px; + font-size: 13px; + overflow-x: auto; + font-family: var(--font-mono); +} + +.docs-page pre code { + background: transparent; + border: 0; + padding: 0; + font-family: var(--font-mono); +} + +.docs-page code { + font-family: var(--font-mono); + background: var(--bg-sunk); + border: 1px solid var(--slate-100); + padding: 0.08em 0.38em; + border-radius: var(--radius-xs); + color: var(--slate-900); + font-size: 0.88em; +} + +.docs-page blockquote { + font-size: 13.5px; + margin: var(--s-5) 0; + padding: var(--s-3) var(--s-5); + border-left: 3px solid var(--brand-blue); + background: var(--brand-blue-soft); + color: var(--slate-800); + border-radius: 0 var(--radius-sm) var(--radius-sm) 0; + font-style: italic; +} + +.docs-page table { + width: 100%; + border-collapse: collapse; + margin: 10px 0 20px; + font-size: 13px; +} + +.docs-page th, +.docs-page td { + padding: 7px 10px; + text-align: left; + border-bottom: 1px solid var(--slate-200); + vertical-align: top; +} + +.docs-page th { + font-weight: 600; + color: var(--fg-2); + border-bottom: 1px solid var(--slate-300); +} + +.page-pager { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 12px; + margin-top: 40px; + padding-top: 20px; + border-top: 1px solid var(--slate-200); +} + +.page-pager a { + display: flex; + flex-direction: column; + gap: 2px; + padding: 12px 14px; + border: 1px solid var(--slate-200); + border-radius: 8px; + text-decoration: none; + color: var(--fg-2); +} + +.page-pager a.next { + text-align: right; + align-items: flex-end; +} + +.page-pager span { + font-size: 11px; + font-family: var(--font-mono); + text-transform: uppercase; + letter-spacing: 0.06em; + color: var(--fg-3); +} + +.page-pager b { + color: var(--slate-900); + font-family: var(--font-display); + font-weight: 500; + font-size: 16px; +} + +.page-pager a:hover { + border-color: var(--brand-blue); + background: var(--bg-elev); +} + +/* TOC */ +.toc-eyebrow { + font-family: var(--font-mono); + font-size: 10px; + text-transform: uppercase; + letter-spacing: 0.1em; + color: var(--fg-3); + margin-bottom: 8px; +} + +.docs-toc ul { + list-style: none; + padding: 0; + margin: 0; + border-left: 1px solid var(--slate-200); +} + +.docs-toc li a { + display: block; + padding: 4px 10px; + color: var(--fg-3); + text-decoration: none; + font-size: 12.5px; +} + +.docs-toc li a:hover { + color: var(--slate-900); +} + +/* ─── Footer ────────────────────────────────────────────────── */ +.docs-footer { + padding: 20px 28px; + border-top: 1px solid var(--slate-200); + background: var(--slate-50); + display: flex; + justify-content: space-between; + align-items: center; + font-size: 12.5px; +} + +.foot-brand { + display: flex; + align-items: center; + gap: 10px; + color: var(--fg-2); +} + +.foot-brand img { + width: 22px; + height: 22px; + opacity: 0.7; +} + +.foot-links { + display: flex; + gap: 18px; +} + +.foot-links a { + color: var(--fg-2); + text-decoration: none; +} + +.foot-links a:hover { + color: var(--brand-blue); +} + +/* ─── Responsive ────────────────────────────────────────────── */ +@media (max-width: 1040px) { + .docs-work { + grid-template-columns: 220px 1fr; + } + + .docs-toc { + display: none; + } + + .demo-slab { + grid-template-columns: 1fr; + gap: 32px; + } + + .landing h1 { + font-size: 44px; + } +} \ No newline at end of file diff --git a/substrate/docs/src/styles/tokens.css b/substrate/docs/src/styles/tokens.css new file mode 100644 index 000000000..c09a805c5 --- /dev/null +++ b/substrate/docs/src/styles/tokens.css @@ -0,0 +1,284 @@ +/* ============================================================= + Substrate · Colors, Type & Foundations + ----------------------------------------------------------------- + The palette is anchored by a slate surface system centered on + #2C4A5A (the tertiary ink — see branding/design-system.md), + paired with the canonical blue (#16A2DC) and orange (#F26A21) + as the two "signal" accents — mirroring the two polylines in + the logo. + ============================================================= */ + +@import url("https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,400;9..144,500;9..144,600&family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap"); + +:root { + /* ─── Brand colours ─────────────────────────────────────────── */ + --brand-blue: #16a2dc; + --brand-blue-ink: #0e7ca9; + --brand-blue-soft: #d7eef8; + + --brand-orange: #f26a21; + --brand-orange-ink: #c4531a; + --brand-orange-soft: #fce4d5; + + /* ─── Slate surface / ink scale (tertiary, anchored on #2C4A5A) ─ */ + --slate-900: #0e1e28; + --slate-800: #1a2a34; + --slate-700: #2c4a5a; + /* ← anchor: dot/line colour & ink on light */ + --slate-600: #3e5c6c; + --slate-500: #5a7586; + --slate-400: #869cab; + --slate-300: #b6c5d0; + --slate-200: #d4dde4; + --slate-100: #e6ebf0; + --slate-50: #eef2f6; + --paper: #f7f9fb; + --paper-pure: #fdfefe; + + /* ─── Semantic surface / text ───────────────────────────────── */ + --bg: var(--paper); + --bg-elev: var(--paper-pure); + --bg-sunk: var(--slate-50); + --bg-tint: var(--slate-100); + --bg-radial: radial-gradient(circle at 20% 10%, var(--paper), var(--slate-50)); + + --fg-1: var(--slate-800); + --fg-2: var(--slate-600); + --fg-3: var(--slate-500); + --fg-4: var(--slate-400); + --fg-inverse: var(--paper-pure); + + --link: var(--brand-blue); + --link-hover: var(--brand-blue-ink); + --link-visited: var(--brand-blue-ink); + + /* ─── Lattice tokens (read by the Lattice component) ──────── */ + --dot-color: rgba(44, 74, 90, 0.26); + --line-color: rgba(44, 74, 90, 0.11); + + /* ─── Status / verification ─────────────────────────────────── */ + --ok: #3b8e5a; + --ok-soft: #e1f1e6; + --warn: #c47a0e; + --warn-soft: #fbefd4; + --fail: #c0392b; + --fail-soft: #f8e1dd; + --info: var(--brand-blue); + --info-soft: var(--brand-blue-soft); + + /* ─── Borders, radii, shadow ────────────────────────────────── */ + --border: 1px solid var(--slate-200); + --border-strong: 1px solid var(--slate-300); + --border-faint: 1px solid var(--slate-100); + + --radius-xs: 3px; + --radius-sm: 6px; + --radius-md: 10px; + --radius-lg: 14px; + --radius-xl: 20px; + --radius-pill: 999px; + + /* soft, slate-tinted shadows — never pure black */ + --shadow-1: 0 1px 2px rgba(26, 42, 52, 0.06), + 0 1px 1px rgba(26, 42, 52, 0.04); + --shadow-2: 0 2px 6px rgba(26, 42, 52, 0.07), + 0 1px 2px rgba(26, 42, 52, 0.05); + --shadow-3: 0 8px 24px rgba(26, 42, 52, 0.09), + 0 2px 6px rgba(26, 42, 52, 0.06); + --shadow-ink: inset 0 0 0 1px rgba(26, 42, 52, 0.08); + + /* ─── Spacing scale (4px base) ──────────────────────────────── */ + --s-0: 0; + --s-1: 4px; + --s-2: 8px; + --s-3: 12px; + --s-4: 16px; + --s-5: 20px; + --s-6: 24px; + --s-8: 32px; + --s-10: 40px; + --s-12: 48px; + --s-16: 64px; + --s-20: 80px; + --s-24: 96px; + + /* ─── Typography ────────────────────────────────────────────── */ + --font-display: + "Fraunces", "Source Serif Pro", "Iowan Old Style", "Apple Garamond", + Georgia, "Times New Roman", serif; + --font-body: + "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, + sans-serif; + --font-mono: + "JetBrains Mono", "SF Mono", ui-monospace, Menlo, Consolas, monospace; + + /* Type scale */ + --fs-xs: 12px; + --fs-sm: 13px; + --fs-base: 15px; + --fs-md: 17px; + --fs-lg: 20px; + --fs-xl: 24px; + --fs-2xl: 32px; + --fs-3xl: 44px; + --fs-4xl: 60px; + + --lh-tight: 1.15; + --lh-snug: 1.3; + --lh-body: 1.55; + --lh-loose: 1.7; + + --tracking-tight: -0.01em; + --tracking-normal: 0; + --tracking-wide: 0.04em; + --tracking-caps: 0.08em; + + /* Motion */ + --ease-standard: cubic-bezier(0.2, 0.6, 0.2, 1); + --ease-exit: cubic-bezier(0.4, 0, 1, 1); + --dur-1: 120ms; + --dur-2: 180ms; + --dur-3: 260ms; +} + +/* ============================================================= + Base element styles (scoped to .substrate — applied at the + top-level app shell so it covers the whole page). + ============================================================= */ + +*, +*::before, +*::after { + box-sizing: border-box; +} + +html, +body { + margin: 0; + min-height: 100%; +} + +.substrate { + font-family: var(--font-body); + color: var(--fg-1); + background: var(--bg); + font-size: var(--fs-base); + line-height: var(--lh-body); + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.substrate a { + color: var(--link); + text-decoration-line: underline; + text-decoration-thickness: 1px; + text-decoration-color: color-mix(in oklab, var(--link) 40%, transparent); + text-underline-offset: 2px; + transition: + color var(--dur-1) var(--ease-standard), + text-decoration-color var(--dur-1) var(--ease-standard); +} + +.substrate a:hover { + color: var(--link-hover); + text-decoration-color: currentColor; +} + +/* Buttons */ +.s-btn { + --_bg: var(--slate-800); + --_fg: var(--paper-pure); + --_bd: var(--slate-800); + display: inline-flex; + align-items: center; + gap: var(--s-2); + font-family: var(--font-body); + font-size: var(--fs-sm); + font-weight: 500; + line-height: 1; + padding: 10px 14px; + border-radius: var(--radius-sm); + background: var(--_bg); + color: var(--_fg); + border: 1px solid var(--_bd); + cursor: pointer; + transition: + transform var(--dur-1) var(--ease-standard), + background var(--dur-1) var(--ease-standard), + box-shadow var(--dur-1) var(--ease-standard); + text-decoration: none; +} + +.s-btn:hover { + background: var(--slate-900); + border-color: var(--slate-900); +} + +.s-btn:active { + transform: translateY(1px); +} + +.s-btn.secondary { + --_bg: var(--paper-pure); + --_fg: var(--slate-800); + --_bd: var(--slate-300); +} + +.s-btn.secondary:hover { + background: var(--slate-50); + border-color: var(--slate-400); +} + +.s-btn.ghost { + --_bg: transparent; + --_fg: var(--slate-800); + --_bd: transparent; +} + +.s-btn.ghost:hover { + background: var(--slate-100); +} + +.s-btn.primary-blue { + --_bg: var(--brand-blue); + --_bd: var(--brand-blue); +} + +.s-btn.primary-blue:hover { + background: var(--brand-blue-ink); + border-color: var(--brand-blue-ink); +} + +.s-btn.primary-orange { + --_bg: var(--brand-orange); + --_bd: var(--brand-orange); +} + +.s-btn.primary-orange:hover { + background: var(--brand-orange-ink); + border-color: var(--brand-orange-ink); +} + +/* Lede / eyebrow */ +.s-lede { + font-family: var(--font-display); + font-weight: 400; + font-size: var(--fs-lg); + line-height: var(--lh-body); + color: var(--fg-2); + font-style: italic; +} + +.s-eyebrow, +.eyebrow { + font-family: var(--font-mono); + font-size: 11px; + text-transform: uppercase; + letter-spacing: 0.12em; + color: var(--fg-3); +} + +/* Selection */ +.substrate ::selection { + background: color-mix(in oklab, var(--brand-orange) 30%, transparent); +} \ No newline at end of file diff --git a/substrate/docs/tsconfig.json b/substrate/docs/tsconfig.json new file mode 100644 index 000000000..8bf91d3bb --- /dev/null +++ b/substrate/docs/tsconfig.json @@ -0,0 +1,5 @@ +{ + "extends": "astro/tsconfigs/strict", + "include": [".astro/types.d.ts", "**/*"], + "exclude": ["dist"] +} diff --git a/substrate/examples/assessment-grading-pipeline.md b/substrate/examples/assessment-grading-pipeline.md new file mode 100644 index 000000000..aa39ce98e --- /dev/null +++ b/substrate/examples/assessment-grading-pipeline.md @@ -0,0 +1,82 @@ +# Assessment Grading [Pipeline](../substrate/language/dataflow/pipeline.md) + +Routes candidate names and test scores through two transformation steps: +the first step assigns a pass/fail status and assembles the full name; +the second step formats a one-line summary message. + +## Input + +- `first name`: [text][str-t] +- `last name`: [text][str-t] +- `score`: [number][num-t] + +## Steps + +1. [Select][select] + - `full name` : [text][str-t] + - [concat][cat] + - [first name][var] + - [last name][var] + - `status` : [text][str-t] + - [if][if] [score][var] [>][gt] [59][num] + - [then][then] ["pass"][str] + - [else][else] ["fail"][str] + +2. [Select][select] + - `summary` : [text][str-t] + - [concat][cat] + - [concat][cat] + - [full name][var] + - [": "][str] + - [status][var] + +## Output + +- `summary`: [text][str-t] + +## [Test cases][tc] + +### Pass, fail, and boundary score + +#### Inputs + +| `first name` | `last name` | `score` | +| ------------ | ----------- | ------- | +| `"Alice"` | `"Smith"` | 85 | +| `"Bob"` | `"Jones"` | 45 | +| `"Carol"` | `"White"` | 60 | + +#### Expected outputs + +| `summary` | +| ---------------------- | +| `"AliceSmith: pass"` | +| `"BobJones: fail"` | +| `"CarolWhite: pass"` | + +### Single row + +#### Inputs + +| `first name` | `last name` | `score` | +| ------------ | ----------- | ------- | +| `"David"` | `"Lee"` | 0 | + +#### Expected outputs + +| `summary` | +| ------------------- | +| `"DavidLee: fail"` | + +[cat]: ../substrate/language/expressions/string.md#concatenate-operation +[else]: ../substrate/language/expressions/decision-tree.md#else +[gt]: ../substrate/language/expressions/ordering.md#greater-than-operation +[if]: ../substrate/language/expressions/decision-tree.md#if +[num]: ../substrate/language/expressions/number.md#literals +[num-t]: ../substrate/language/expressions/number.md +[select]: ../substrate/language/dataflow/select.md +[str]: ../substrate/language/expressions/string.md#literals +[str-t]: ../substrate/language/expressions/string.md +[tc]: ../substrate/language/concepts/test-case.md +[then]: ../substrate/language/expressions/decision-tree.md#then +[var]: ../substrate/language/expressions/README.md#variables diff --git a/substrate/examples/broken.md b/substrate/examples/broken.md new file mode 100644 index 000000000..0782afdb3 --- /dev/null +++ b/substrate/examples/broken.md @@ -0,0 +1,40 @@ +# Broken Example + +An intentionally malformed document for testing CLI error reporting. + +## Inputs + +- `price` — a price value +- `rate` — a rate value + +## Definitions + +### `computed_tax` + +Computes tax with a [broken link to nowhere](../substrate/language/expressions/nonexistent.md#fake-operation). + +- [Multiply](../substrate/language/expressions/nonexistent.md#fake-operation) + - `price` + - `rate` + +#### Test cases + +| `price` | `rate` | `computed_tax` | +| ------- | ------ | -------------- | +| 100 | 0.1 | 999 | + +### `always_true` + +Returns [true][bool] unconditionally but the test table expects the wrong result. + +- [Equal](../substrate/language/expressions/equality.md#equal-operation) + - `price` + - `price` + +#### Test cases + +| `price` | `always_true` | +| ------- | ------------- | +| 42 | false | + +[bool]: ../substrate/language/expressions/boolean.md diff --git a/substrate/examples/fr2052a-lcr/knowledge/README.md b/substrate/examples/fr2052a-lcr/knowledge/README.md new file mode 100644 index 000000000..a7e9a915d --- /dev/null +++ b/substrate/examples/fr2052a-lcr/knowledge/README.md @@ -0,0 +1,89 @@ +# FR 2052a / LCR Example + +This example demonstrates how to codify a banking regulation as an +executable substrate specification. It covers a narrow but complete slice +of two related artifacts: + +- **FR 2052a** — the Federal Reserve's _Complex Institution Liquidity + Monitoring Report_, a data-collection form that large U.S. banks + submit daily or monthly. FR 2052a defines a schema: what counts as a + deposit row, what fields it carries, what categorical values are + allowed. +- **The Liquidity Coverage Ratio (LCR) rule** — codified at + [12 CFR Part 249][part-249], which specifies the runoff rates applied + to each category of liability and the calculation that produces the + LCR itself. The two are inseparable in practice: FR 2052a is the data + feed; 12 CFR §249 is the calculation. + +## Scope + +The example covers one FR 2052a section, one LCR rate assignment, and +the computation that combines them: + +- **FR 2052a §O.D.1 Transactional Accounts** — a [Record][rec] + describing one deposit row. +- **Supporting categorical types** — [Counterparty](counterparty.md), + [Account Type](account-type.md), [Relationship](relationship.md), and + [Maturity Bucket](maturity-bucket.md), each declared as a + [Choice][choice]. Maturity Bucket is the data-carrying case; the rest + are pure enumerations. +- **Retail outflow rate** — a [Decision Table][dt] encoding the rate + assignment from [12 CFR §249.32(a)][cfr-32a]. +- **Total retail outflow** — a user module computing the dollar outflow + from a collection of deposit rows, combining classification and + rates. + +Deliberately out of scope in this MVP slice: + +- Other FR 2052a sections (O.D.2 through O.D.13, outflows other than + deposits, all inflows, HQLA composition, supplemental reporting). +- The full LCR ratio: numerator (HQLA), denominator (net cash + outflows), and the 75% inflow cap. +- Transition-window amendments and historical version selection — + the example targets a single authoritative corpus version. + +Extending to those cases is copy-paste of the patterns shown here. + +## How to read + +Start at the data schema, work up to the rule, then the calculation: + +1. [Counterparty](counterparty.md), [Account Type](account-type.md), + [Relationship](relationship.md) — categorical dimensions used by + every retail deposit row. +2. [Maturity Bucket](maturity-bucket.md) — demonstrates a + data-carrying [Choice][choice] (variants parameterised by day + ranges). +3. [Transactional Accounts](transactional-accounts.md) — the FR 2052a + §O.D.1 record schema. +4. [Retail Outflow Rate](retail-outflow-rate.md) — the + [Decision Table][dt] assigning a rate to each classification. +5. [Retail Outflow](retail-outflow.md) — the user module computing + dollar outflow over a collection of deposits. + +## Conventions + +- Every artifact derived from an external document carries a + [Provenance][prov] section citing the form or regulation. + Normative passages are quoted verbatim as blockquotes. +- Categorical values use [Choice][choice] rather than [String][str]: + the allowed set is fixed by the regulation and enforced statically. +- Rate assignments use [Decision Tables][dt] rather than nested + [If-Then-Else][ite]: the rule is tabular in the regulation and + should remain tabular in the specification. +- Optional fields use the [Optionality][opt] convention: the slot is + marked optional and consumers coalesce explicitly with + [Default][opt-default]. +- Cross-references to substrate concepts use reference-style link + definitions to keep inline prose readable. + +[choice]: ../../substrate/language/concepts/choice.md +[cfr-32a]: https://www.ecfr.gov/current/title-12/part-249/section-249.32#p-249.32(a) +[dt]: ../../substrate/language/concepts/decision-table.md +[ite]: ../../substrate/language/expressions/boolean.md#if-then-else-operation +[opt]: ../../substrate/language/concepts/optionality.md +[opt-default]: ../../substrate/language/concepts/optionality.md#default-operation +[part-249]: https://www.ecfr.gov/current/title-12/part-249 +[prov]: ../../substrate/language/concepts/provenance.md +[rec]: ../../substrate/language/concepts/record.md +[str]: ../../substrate/language/expressions/string.md diff --git a/substrate/examples/fr2052a-lcr/knowledge/account-type.md b/substrate/examples/fr2052a-lcr/knowledge/account-type.md new file mode 100644 index 000000000..38c584890 --- /dev/null +++ b/substrate/examples/fr2052a-lcr/knowledge/account-type.md @@ -0,0 +1,37 @@ +# Account Type [Choice](../../substrate/language/concepts/choice.md) + +The Account Type classifies whether a deposit is held in a transactional +account. The distinction is material for LCR: transactional accounts are +presumed to be operational and receive a lower outflow rate. + +## [Provenance](../../substrate/language/concepts/provenance.md) + +- [FR 2052a instructions, Product classifications for §O.D Outflows — Deposits][fr2052a-form] + + > The distinction between transactional and non-transactional accounts + > follows Regulation D. Transactional accounts are deposits from which + > the depositor is permitted to make transfers or withdrawals by + > negotiable instrument, payment order, debit card, or similar means. + +- [12 CFR §249.3 — Transactional account definition][cfr-3] + + > For purposes of this part, a transactional account has the meaning + > given to "transaction account" in Regulation D (12 CFR part 204), + > §204.2(e). + +## Variants + +- **Transactional** — a deposit account from which withdrawals or + transfers may be made by negotiable instrument, payment order, debit + card, or similar means (per Regulation D §204.2(e)). +- **Non-Transactional** — a deposit account from which such withdrawals + are limited or not permitted (savings accounts, time deposits, etc.). + +## Type Class Instances + +- **[Equality](../../substrate/language/expressions/equality.md)** — + inherited automatically from the [Choice][choice] concept. + +[choice]: ../../substrate/language/concepts/choice.md +[cfr-3]: https://www.ecfr.gov/current/title-12/part-249/section-249.3 +[fr2052a-form]: https://www.federalreserve.gov/reportforms/forms/FR_2052a20220429_f.pdf diff --git a/substrate/examples/fr2052a-lcr/knowledge/counterparty.md b/substrate/examples/fr2052a-lcr/knowledge/counterparty.md new file mode 100644 index 000000000..fef588c96 --- /dev/null +++ b/substrate/examples/fr2052a-lcr/knowledge/counterparty.md @@ -0,0 +1,56 @@ +# Counterparty [Choice](../../substrate/language/concepts/choice.md) + +The Counterparty type classifies the party on the other side of a +position for FR 2052a reporting. The set of counterparty categories is +fixed by the form instructions; each row of the report is labelled with +exactly one counterparty. + +This example declares a subset of the full counterparty enumeration +sufficient to demonstrate retail outflow classification. The full set +published in the FR 2052a instructions additionally includes Sovereign, +Central Bank, GSE, PSE, MDB, Other Supranational, Pension Fund, +Broker-Dealer, Investment Company or Advisor, Financial Market Utility, +Other Supervised Non-Bank Financial Entity, Non-Regulated Fund, and +Internal. + +## [Provenance](../../substrate/language/concepts/provenance.md) + +- [FR 2052a instructions, Field Definitions — Counterparty (version 2025-02-26)][fr2052a-form] + + > Counterparty refers to the entity that is the other party to the + > transaction. The table below indicates the appropriate counterparty + > classification for each reported row. + +- [12 CFR §249.3 — Definition of retail customer or counterparty][cfr-3] + + > _Retail customer or counterparty_ means a customer or counterparty + > that is: (1) An individual; (2) A business customer that meets the + > definition of a retail customer or counterparty under §249.3; or + > (3) A living or testamentary trust that: (i) Is solely for the + > benefit of natural persons; (ii) Does not have a corporate trustee; + > and (iii) Terminates within 21 years and 10 months after the death + > of grantors or beneficiaries of the trust living on the effective + > date of the trust or within 25 years after the effective date of + > the trust. + +## Variants + +- **Retail** — a natural-person customer. +- **Small Business** — a business customer meeting the FR 2052a + definition of a small business counterparty (treated as retail-like + for outflow classification). +- **Non-Financial Corporate** — a non-financial business entity that + is not a small business. +- **Bank** — a depository institution counterparty. + +## Type Class Instances + +- **[Equality](../../substrate/language/expressions/equality.md)** — + inherited automatically from the [Choice][choice] concept: two values + are equal when they name the same variant. +- **[Ordering](../../substrate/language/expressions/ordering.md)** — not + implemented. Counterparty categories have no canonical order. + +[choice]: ../../substrate/language/concepts/choice.md +[cfr-3]: https://www.ecfr.gov/current/title-12/part-249/section-249.3 +[fr2052a-form]: https://www.federalreserve.gov/reportforms/forms/FR_2052a20220429_f.pdf diff --git a/substrate/examples/fr2052a-lcr/knowledge/maturity-bucket.md b/substrate/examples/fr2052a-lcr/knowledge/maturity-bucket.md new file mode 100644 index 000000000..e90319f4a --- /dev/null +++ b/substrate/examples/fr2052a-lcr/knowledge/maturity-bucket.md @@ -0,0 +1,56 @@ +# Maturity Bucket [Choice](../../substrate/language/concepts/choice.md) + +The Maturity Bucket type classifies a position by the number of days +remaining to contractual maturity. FR 2052a reports maturity as a +bucketed value rather than a raw date so that positions with comparable +runoff horizons aggregate naturally. + +Unlike the other categorical dimensions in this example, Maturity +Bucket carries data: a bucket is either _Open_ (no contractual +maturity), a contiguous day _Range_, or _Beyond_ a threshold. The +bounds are parameters of the variant rather than names of distinct +variants, because the LCR rule references the numeric thresholds +directly (e.g. "within 30 days"). + +## [Provenance](../../substrate/language/concepts/provenance.md) + +- [FR 2052a instructions, Field Definitions — Maturity Bucket][fr2052a-form] + + > Maturity Bucket reflects the remaining contractual maturity of the + > reported position, measured in calendar days from the reporting + > date. Positions without a contractual maturity are reported as + > Open. + +- [12 CFR §249.32 — Outflow horizon][cfr-32] + + > Outflow amounts are calculated over a prospective 30 calendar-day + > period beginning on the calculation date. + +## Variants + +- **Open** — no contractual maturity (e.g. demand deposits). +- **Range** — a contiguous, inclusive range of days to maturity. + - `from_days` — [Integer](../../substrate/language/expressions/integer.md), + required. Lower bound, inclusive. + - `to_days` — [Integer](../../substrate/language/expressions/integer.md), + required. Upper bound, inclusive. +- **Beyond** — longer than a threshold number of days. + - `from_days` — [Integer](../../substrate/language/expressions/integer.md), + required. Lower bound, exclusive. + +## Type Class Instances + +- **[Equality](../../substrate/language/expressions/equality.md)** — + inherited automatically from the [Choice][choice] concept: two values + are equal when they are the same variant and their `from_days` and + `to_days` fields are equal. +- **[Ordering](../../substrate/language/expressions/ordering.md)** — not + implemented. A meaningful order would require comparing open-ended + and bounded variants against each other, which the LCR rule does not + require. Consumers that need to ask "does this bucket intersect the + next 30 days?" should use [Match][match] on the variants directly. + +[choice]: ../../substrate/language/concepts/choice.md +[match]: ../../substrate/language/concepts/choice.md#match-operation +[cfr-32]: https://www.ecfr.gov/current/title-12/part-249/section-249.32 +[fr2052a-form]: https://www.federalreserve.gov/reportforms/forms/FR_2052a20220429_f.pdf diff --git a/substrate/examples/fr2052a-lcr/knowledge/relationship.md b/substrate/examples/fr2052a-lcr/knowledge/relationship.md new file mode 100644 index 000000000..97d2d76cc --- /dev/null +++ b/substrate/examples/fr2052a-lcr/knowledge/relationship.md @@ -0,0 +1,41 @@ +# Relationship [Choice](../../substrate/language/concepts/choice.md) + +The Relationship type classifies whether a deposit counterparty has an +established banking relationship with the reporting institution. LCR +outflow rates distinguish deposits from established-relationship +customers (lower presumed runoff) from deposits without such a +relationship (higher presumed runoff). + +## [Provenance](../../substrate/language/concepts/provenance.md) + +- [12 CFR §249.3 — Established relationship definition][cfr-3] + + > _Established relationship_ means a relationship between a retail + > customer or counterparty and a covered company that is evidenced by + > the retail customer or counterparty: (1) Actively using the covered + > company to perform banking services; (2) Having at least one + > additional banking relationship with the covered company at the + > time the retail customer or counterparty opens a new account with + > the covered company; or (3) Having any other relationship that is + > documented by the covered company. + +- [FR 2052a instructions, Product classifications for §O.D Outflows — Deposits][fr2052a-form] + + > Deposits are further classified by whether the counterparty has an + > established relationship with the reporting institution, as defined + > in 12 CFR §249.3. + +## Variants + +- **Established** — the counterparty has an established relationship + with the reporting institution under 12 CFR §249.3. +- **None** — no established relationship. + +## Type Class Instances + +- **[Equality](../../substrate/language/expressions/equality.md)** — + inherited automatically from the [Choice][choice] concept. + +[choice]: ../../substrate/language/concepts/choice.md +[cfr-3]: https://www.ecfr.gov/current/title-12/part-249/section-249.3 +[fr2052a-form]: https://www.federalreserve.gov/reportforms/forms/FR_2052a20220429_f.pdf diff --git a/substrate/examples/fr2052a-lcr/knowledge/retail-outflow-rate.md b/substrate/examples/fr2052a-lcr/knowledge/retail-outflow-rate.md new file mode 100644 index 000000000..826452ca2 --- /dev/null +++ b/substrate/examples/fr2052a-lcr/knowledge/retail-outflow-rate.md @@ -0,0 +1,77 @@ +# Retail Outflow Rate [Decision Table](../../substrate/language/concepts/decision-table.md) + +The Retail Outflow Rate decision table assigns an LCR runoff rate to a +retail deposit position based on its classification. The rates and +conditions are fixed by [12 CFR §249.32(a)][cfr-32a]. + +Two concepts from the rule drive the rates: + +- **Stable** retail deposits are deposits entirely covered by deposit + insurance AND either held in a transactional account OR from a + depositor with an established relationship. Stable deposits receive + the lowest runoff rate (3%). +- **Less stable** retail deposits are insured retail deposits that do + not qualify as stable, plus uninsured retail deposits. Less stable + deposits receive a 10% runoff rate. + +Small Business counterparties are treated identically to natural-person +Retail counterparties for this rate, per [§249.32(a)(5)][cfr-32a-5]. +Non-retail counterparties fall outside §249.32(a) and are not in scope +for this table. + +## [Provenance](../../substrate/language/concepts/provenance.md) + +- [12 CFR §249.32(a) — Retail deposit outflow amount][cfr-32a] + + > A covered company shall calculate its retail deposit outflow amount + > as follows: (1) 3 percent of all stable retail deposits; (2) 10 + > percent of all other retail deposits that are not brokered deposits; + > ... + +- [12 CFR §249.3 — Stable retail deposit definition][cfr-3] + + > _Stable retail deposit_ means a retail deposit that is entirely + > covered by deposit insurance and: (1) Is held by the depositor in + > a transactional account; or (2) The depositor that holds the + > account has another established relationship with the covered + > company such as another deposit account, a loan, bill payment + > services, or any similar service or product provided to the + > depositor that the covered company demonstrates to the satisfaction + > of the Board would make deposit withdrawal highly unlikely during + > a liquidity stress event. + +## Inputs + +- `counterparty` — [Counterparty](counterparty.md) +- `insured` — [Boolean](../../substrate/language/expressions/boolean.md) +- `account_type` — [Account Type](account-type.md) +- `relationship` — [Relationship](relationship.md) + +## Outputs + +- `outflow_rate` — [Decimal](../../substrate/language/expressions/decimal.md) + +## Rules + +| counterparty | insured | account_type | relationship | → outflow_rate | +| -------------- | ------- | ----------------- | ------------ | -------------- | +| Retail | true | Transactional | | 0.03 | +| Retail | true | Non-Transactional | Established | 0.03 | +| Retail | true | Non-Transactional | None | 0.10 | +| Retail | false | | | 0.10 | +| Small Business | true | Transactional | | 0.03 | +| Small Business | true | Non-Transactional | Established | 0.03 | +| Small Business | true | Non-Transactional | None | 0.10 | +| Small Business | false | | | 0.10 | + +The table is exhaustive over the in-scope counterparties: the four +Retail rows and four Small Business rows cover every combination of +`insured`, `account_type`, and `relationship`. Positions whose +counterparty is Non-Financial Corporate or Bank are out of scope for +this table and are routed to a different rate table (not modelled in +this MVP slice); evaluating this table for such a row is a +specification error at the call site, not a runtime fallthrough. + +[cfr-3]: https://www.ecfr.gov/current/title-12/part-249/section-249.3 +[cfr-32a]: https://www.ecfr.gov/current/title-12/part-249/section-249.32#p-249.32(a) +[cfr-32a-5]: https://www.ecfr.gov/current/title-12/part-249/section-249.32#p-249.32(a)(5) diff --git a/substrate/examples/fr2052a-lcr/knowledge/retail-outflow.md b/substrate/examples/fr2052a-lcr/knowledge/retail-outflow.md new file mode 100644 index 000000000..a962133fc --- /dev/null +++ b/substrate/examples/fr2052a-lcr/knowledge/retail-outflow.md @@ -0,0 +1,88 @@ +# Retail Outflow + +Computes the total retail deposit outflow in dollars from a collection +of FR 2052a §O.D.1 [Transactional Accounts](transactional-accounts.md) +rows. This is the retail-deposit contribution to the LCR denominator; +the full LCR ratio composes this with other outflow categories and +with inflows and HQLA, which are out of scope for this example. + +The calculation has two steps: + +1. For each row, look up the applicable outflow rate using the + [Retail Outflow Rate](retail-outflow-rate.md) decision table, then + multiply by the row's `amount` to produce a per-row outflow. +2. Sum the per-row outflows across the collection. + +## [Provenance](../../substrate/language/concepts/provenance.md) + +- [12 CFR §249.32(a) — Retail deposit outflow amount][cfr-32a] + + > A covered company shall calculate its retail deposit outflow amount + > as the sum of the outflow amounts for each category of retail + > deposit, each calculated by multiplying the outstanding balance by + > the applicable outflow rate. + +## Inputs + +- `deposits` — a [Collection][col] of + [Transactional Accounts](transactional-accounts.md) rows representing + the retail-deposit population for one reporting date. + +## Definitions + +### `row_outflow` + +The dollar outflow for a single deposit row. Defined as a +[per-row](transactional-accounts.md) function applied by +[Map][map]: the rate is looked up via the +[Retail Outflow Rate][rate] decision table using the row's +classification fields, then multiplied by the row's `amount`. + +- [Multiply][mul] + - [Retail Outflow Rate][rate] + - `row.counterparty` + - `row.insured` + - `row.account_type` + - `row.relationship` + - `row.amount` + +#### Test cases + +| `row` | `row_outflow` | +| ------------------------------------------------------------------------------------------------------------------------------- | ------------- | +| `{ amount: 1000, counterparty: Retail, insured: true, account_type: Transactional, relationship: Established, ... }` | 30 | +| `{ amount: 1000, counterparty: Retail, insured: true, account_type: Non-Transactional, relationship: None, ... }` | 100 | +| `{ amount: 2500, counterparty: Retail, insured: false, account_type: Transactional, relationship: Established, ... }` | 250 | +| `{ amount: 500, counterparty: Small Business, insured: true, account_type: Non-Transactional, relationship: Established, ... }` | 15 | + +### `per_row_outflows` + +The collection of per-row outflows, one element per input row. + +- [Map][map] + - `deposits` + - `row_outflow` + +### `total_outflow` + +The total retail outflow for the reporting date: the sum of per-row +outflows. + +- [Sum][sum] + - `per_row_outflows` + +#### Test cases + +| `deposits` | `total_outflow` | +| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- | +| `[]` | 0 | +| `[{ amount: 1000, Retail, insured, Transactional, Established }]` | 30 | +| `[{ amount: 1000, Retail, insured, Transactional, Established }, { amount: 1000, Retail, insured, Non-Transactional, None }]` | 130 | +| `[{ amount: 2500, Retail, uninsured, Transactional, Established }, { amount: 500, Small Business, insured, Non-Transactional, Established }]` | 265 | + +[col]: ../../substrate/language/expressions/collection.md +[cfr-32a]: https://www.ecfr.gov/current/title-12/part-249/section-249.32#p-249.32(a) +[map]: ../../substrate/language/expressions/collection.md#map-operation +[mul]: ../../substrate/language/expressions/number.md#multiplication-operation +[rate]: retail-outflow-rate.md +[sum]: ../../substrate/language/expressions/collection.md#sum-operation diff --git a/substrate/examples/fr2052a-lcr/knowledge/substrate.toml b/substrate/examples/fr2052a-lcr/knowledge/substrate.toml new file mode 100644 index 000000000..edda25bd6 --- /dev/null +++ b/substrate/examples/fr2052a-lcr/knowledge/substrate.toml @@ -0,0 +1,6 @@ +[package] +name = "@AttilaMihaly/fr2052a-lcr-example" +kind = "corpus" + +[dependencies] +"@AttilaMihaly/morphir-substrate" = "^0.1.0" diff --git a/substrate/examples/fr2052a-lcr/knowledge/transactional-accounts.md b/substrate/examples/fr2052a-lcr/knowledge/transactional-accounts.md new file mode 100644 index 000000000..42467c124 --- /dev/null +++ b/substrate/examples/fr2052a-lcr/knowledge/transactional-accounts.md @@ -0,0 +1,53 @@ +# Transactional Accounts [Record](../../substrate/language/concepts/record.md) + +The Transactional Accounts record captures one row of FR 2052a section +**§O.D.1 Outflows — Deposits — Transactional Accounts**. Each row +represents an aggregated deposit position classified by counterparty, +account type, relationship, maturity, and insurance status. A single +submission contains many such rows. + +The fields here are a minimal subset sufficient to drive the retail +outflow calculation. The full FR 2052a schema additionally carries +currency, collateral class, encumbrance flags, and reporting-entity +identifiers; those are orthogonal to the classification logic and are +omitted in this MVP slice. + +## [Provenance](../../substrate/language/concepts/provenance.md) + +- [FR 2052a instructions, §O.D.1 Transactional Accounts][fr2052a-form] + + > Transactional Accounts captures deposit balances held in + > transactional accounts, classified by counterparty type, insurance + > status, established relationship, and remaining maturity. The + > reported amount is the unpaid principal balance as of the reporting + > date. + +- [12 CFR §249.32(a) — Retail funding outflow amount][cfr-32a] + + > A covered company shall calculate its retail funding outflow amount + > as the sum of outflow amounts for each category of retail deposit, + > applying the applicable outflow rate to the outstanding balance. + +## Fields + +| Name | Type | Optionality | Description | +| ----------------- | ------------------------------------------------------ | ----------- | ---------------------------------------------------------------------- | +| `report_date` | [Date](../../substrate/language/expressions/date.md) | required | The FR 2052a reporting date as of which balances are measured. | +| `amount` | [Decimal](../../substrate/language/expressions/decimal.md) | required | Unpaid principal balance, in reporting currency units. | +| `counterparty` | [Counterparty](counterparty.md) | required | The party on the other side of the deposit position. | +| `account_type` | [Account Type](account-type.md) | required | Whether the deposit is held in a transactional account. | +| `relationship` | [Relationship](relationship.md) | required | Whether the counterparty has an established relationship. | +| `maturity_bucket` | [Maturity Bucket](maturity-bucket.md) | required | Remaining contractual maturity, bucketed. | +| `insured` | [Boolean](../../substrate/language/expressions/boolean.md) | required | `true` when the deposit is covered by deposit insurance up to limit. | + +## Type Class Instances + +Transactional Accounts does not declare an [Equality][eq] instance. +Rows are identified by the submission they belong to and their +position within it, not by structural equality of their fields; two +rows with identical field values may represent distinct aggregated +populations. + +[eq]: ../../substrate/language/expressions/equality.md +[cfr-32a]: https://www.ecfr.gov/current/title-12/part-249/section-249.32#p-249.32(a) +[fr2052a-form]: https://www.federalreserve.gov/reportforms/forms/FR_2052a20220429_f.pdf diff --git a/substrate/examples/fr2052a-lcr/raw/FR_2052a20250226_f.pdf b/substrate/examples/fr2052a-lcr/raw/FR_2052a20250226_f.pdf new file mode 100644 index 000000000..21f04bfcf Binary files /dev/null and b/substrate/examples/fr2052a-lcr/raw/FR_2052a20250226_f.pdf differ diff --git a/substrate/examples/fr2052a-lcr/structured/EXTRACTION.md b/substrate/examples/fr2052a-lcr/structured/EXTRACTION.md new file mode 100644 index 000000000..d0d7630b5 --- /dev/null +++ b/substrate/examples/fr2052a-lcr/structured/EXTRACTION.md @@ -0,0 +1,341 @@ +# FR 2052a PDF → Markdown Extraction + +This folder contains the FR 2052a Complex Institution Liquidity Monitoring +Report instructions, extracted from the source PDF and split into a set of +Markdown files that mirror the document's original section structure. + +The Markdown here is **not yet the substrate knowledge corpus**. It is a +faithful reformatting of the source document, intended as the input for a +later restructuring pass. + +## Source + +- `../raw/FR_2052a20250226_f.pdf` — FR 2052a Instructions, dated 2025-02-26 + (revision approved through Feb 2028). 106 pages of instructions plus + three appended mapping documents (Appendices VI, VII, VIII) with their + own page numbering. + +## Status — where we are right now + +| Section | State | +| -------------------------------------------------- | -------------------- | +| 01 General Instructions | ✅ auto-generated | +| 02 Field Definitions | ✅ auto-generated | +| 03 Product Definitions (all 13 group files) | ✅ auto-generated | +| Appendix I — Data Format, Tables, and Fields | ✅ hand-curated | +| Appendix II-a — Product/Sub-Product Requirements | ✅ hand-curated | +| Appendix II-b — Counterparty Requirements | ✅ hand-curated | +| Appendix II-c — Collateral Class Requirements | ✅ hand-curated | +| Appendix II-d — Forward Start Exclusions | ✅ hand-curated | +| Appendix III — Asset Category Table | ✅ hand-curated | +| Appendix IV-a — Maturity Bucket Value List | ✅ hand-curated | +| Appendix IV-b — Maturity Bucket Tailoring | ✅ hand-curated | +| Appendix V — Double Counting of Certain Exposures | ✅ hand-curated (fenced verbatim; trailing VI/VII/VIII pointers removed) | +| Appendix VI — LCR to FR 2052a Mapping | ✅ hand-curated | +| Appendix VII — STWF to FR 2052a Mapping | ✅ hand-curated | +| Appendix VIII — NSFR to FR 2052a Mapping | ✅ hand-curated | + +All product / appendix sections are now curated. Appendix V +is kept as fenced verbatim (prose-heavy, no tabular data); the only +hand edit was stripping the trailing pointers to Appendices VI/VII/VIII, +which live in their own files. Appendices VI and VIII required special +handling because the LCR/NSFR formulas use Cambria Math font subsets +with a broken ToUnicode CMap; formulas were transcribed from 12 CFR 249 +and the visible document structure. The mapping tables (140 provisions +in VI, 114 provisions in VIII) were extracted via +`pdfplumber.extract_text()`. + +## Why this approach + +The source PDF is born-digital — text is stored as real Unicode, not +pixels — so OCR is unnecessary. Heading conventions in the document are +regular, which makes a deterministic splitter feasible for the bulk of +the content. We chose this over an ML extractor (Docling, Marker) for +three reasons: + +1. **Reproducibility.** No model weights, no nondeterminism. The same + PDF produces byte-identical Markdown for the auto-generated portions. +2. **Transparency.** Every transformation is visible in + [`scripts/extract.py`](scripts/extract.py). When something looks + wrong in the output we can trace it to a specific rule. +3. **Footprint.** `pdftotext` plus a few hundred lines of Python beats a + multi-GB model download for a document this regular. + +For the appendix tables, where positional graphics matter (check-mark +columns, cross-page table merging, custom-positioned glyphs), we drop +into per-appendix curation backed by `pdfplumber`. See *Curation +workflow* below. + +## Pipeline + +``` +raw/FR_2052a20250226_f.pdf + │ + │ ── extract.py ─────────────────────────────────────────────────────── + │ pdftotext -layout -enc UTF-8 (column alignment) + │ ▼ + │ structured/scripts/_full.txt (intermediate) + │ ▼ + │ strip page chrome, locate section anchors, + │ slice into per-section bodies, format prose / fenced appendices + │ ▼ + │ structured/output/**/*.md (auto-generated files) + │ (skipped if listed in MANUAL_CURATION) + │ + │ ── per-appendix curation (where the auto output isn't enough) ────── + │ pdftotext -raw OR pdfplumber (recovers structure) + │ ▼ + │ scripts/despace.py (de-glyph-spacing) + │ ▼ + │ hand-edit, guided by structured/human-annotations.md + │ ▼ + │ structured/output/04-appendices/*.md (curated overwrites) +``` + +## Output layout + +``` +output/ + 01-general-instructions.md + 02-field-definitions.md (one ## per field term) + 03-product-definitions/ + 00-overview.md + I.A-inflows-assets.md (one ### per product) + I.U-inflows-unsecured.md + I.S-inflows-secured.md + I.O-inflows-other.md + O.W-outflows-wholesale.md + O.S-outflows-secured.md + O.D-outflows-deposits.md + O.O-outflows-other.md + S.DC-supplemental-derivatives-collateral.md + S.L-supplemental-lrm.md + S.B-supplemental-balance-sheet.md + S.I-supplemental-informational.md + S.FX-supplemental-foreign-exchange.md + 04-appendices/ + I-data-format.md (curated — bullet list, MD tables) + II-a-product-subproduct-requirements.md (curated — 4-col MD table) + II-b-counterparty-requirements.md (curated — 3-col MD table, HTML